Specify the proper call convention in the PropSysFreeString()
[wine] / dlls / dplayx / lobbysp.c
1 /* This contains the implementation of the Lobby Service
2  * Providers interface required to communicate with Direct Play
3  *
4  * Copyright 2001 Peter Hunnisett
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "winerror.h"
22 #include "wine/debug.h"
23
24 #include "lobbysp.h"
25 #include "dplay_global.h"
26 #include "dpinit.h"
27
28 WINE_DEFAULT_DEBUG_CHANNEL(dplay);
29
30 /* Prototypes */
31 static BOOL DPLSP_CreateIUnknown( LPVOID lpSP );
32 static BOOL DPLSP_DestroyIUnknown( LPVOID lpSP );
33 static BOOL DPLSP_CreateDPLobbySP( LPVOID lpSP, IDirectPlay2Impl* dp );
34 static BOOL DPLSP_DestroyDPLobbySP( LPVOID lpSP );
35
36
37 /* Predefine the interface */
38 typedef struct IDPLobbySPImpl IDPLobbySPImpl;
39
40 typedef struct tagDPLobbySPIUnknownData
41 {
42   ULONG             ulObjRef;
43   CRITICAL_SECTION  DPLSP_lock;
44 } DPLobbySPIUnknownData;
45
46 typedef struct tagDPLobbySPData
47 {
48   IDirectPlay2Impl* dplay;
49 } DPLobbySPData;
50
51 #define DPLSP_IMPL_FIELDS \
52    ULONG ulInterfaceRef; \
53    DPLobbySPIUnknownData* unk; \
54    DPLobbySPData* sp;
55
56 struct IDPLobbySPImpl
57 {
58   IDPLobbySPVtbl *lpVtbl;
59   DPLSP_IMPL_FIELDS
60 };
61
62 /* Forward declaration of virtual tables */
63 static IDPLobbySPVtbl dpLobbySPVT;
64
65 extern
66 HRESULT DPLSP_CreateInterface( REFIID riid, LPVOID* ppvObj, IDirectPlay2Impl* dp )
67 {
68   TRACE( " for %s\n", debugstr_guid( riid ) );
69
70   *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
71                        sizeof( IDPLobbySPImpl ) );
72
73   if( *ppvObj == NULL )
74   {
75     return DPERR_OUTOFMEMORY;
76   }
77
78   if( IsEqualGUID( &IID_IDPLobbySP, riid ) )
79   {
80     IDPLobbySPImpl *This = (IDPLobbySPImpl *)*ppvObj;
81     This->lpVtbl = &dpLobbySPVT;
82   }
83   else
84   {
85     /* Unsupported interface */
86     HeapFree( GetProcessHeap(), 0, *ppvObj );
87     *ppvObj = NULL;
88
89     return E_NOINTERFACE;
90   }
91
92   /* Initialize it */
93   if( DPLSP_CreateIUnknown( *ppvObj ) &&
94       DPLSP_CreateDPLobbySP( *ppvObj, dp )
95     )
96   {
97     IDPLobbySP_AddRef( (LPDPLOBBYSP)*ppvObj );
98     return S_OK;
99   }
100
101   /* Initialize failed, destroy it */
102   DPLSP_DestroyDPLobbySP( *ppvObj );
103   DPLSP_DestroyIUnknown( *ppvObj );
104
105   HeapFree( GetProcessHeap(), 0, *ppvObj );
106   *ppvObj = NULL;
107
108   return DPERR_NOMEMORY;
109 }
110
111 static BOOL DPLSP_CreateIUnknown( LPVOID lpSP )
112 {
113   IDPLobbySPImpl *This = (IDPLobbySPImpl *)lpSP;
114
115   This->unk = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->unk) ) );
116
117   if ( This->unk == NULL )
118   {
119     return FALSE;
120   }
121
122   InitializeCriticalSection( &This->unk->DPLSP_lock );
123
124   return TRUE;
125 }
126
127 static BOOL DPLSP_DestroyIUnknown( LPVOID lpSP )
128 {
129   IDPLobbySPImpl *This = (IDPLobbySPImpl *)lpSP;
130
131   DeleteCriticalSection( &This->unk->DPLSP_lock );
132   HeapFree( GetProcessHeap(), 0, This->unk );
133
134   return TRUE;
135 }
136
137 static BOOL DPLSP_CreateDPLobbySP( LPVOID lpSP, IDirectPlay2Impl* dp )
138 {
139   IDPLobbySPImpl *This = (IDPLobbySPImpl *)lpSP;
140
141   This->sp = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->sp) ) );
142
143   if ( This->sp == NULL )
144   {
145     return FALSE;
146   }
147
148   This->sp->dplay = dp;
149
150   /* Normally we should be keeping a reference, but since only the dplay
151    * interface that created us can destroy us, we do not keep a reference
152    * to it (ie we'd be stuck with always having one reference to the dplay
153    * object, and hence us, around).
154    * NOTE: The dp object does reference count us.
155    *
156    * FIXME: This is a kludge to get around a problem where a queryinterface
157    *        is used to get a new interface and then is closed. We will then
158    *        reference garbage. However, with this we will never deallocate
159    *        the interface we store. The correct fix is to require all
160    *        DP internal interfaces to use the This->dp2 interface which
161    *        should be changed to This->dp
162    */
163   IDirectPlayX_AddRef( (LPDIRECTPLAY2)dp );
164
165
166   return TRUE;
167 }
168
169 static BOOL DPLSP_DestroyDPLobbySP( LPVOID lpSP )
170 {
171   IDPLobbySPImpl *This = (IDPLobbySPImpl *)lpSP;
172
173   HeapFree( GetProcessHeap(), 0, This->sp );
174
175   return TRUE;
176 }
177
178 static
179 HRESULT WINAPI DPLSP_QueryInterface
180 ( LPDPLOBBYSP iface,
181   REFIID riid,
182   LPVOID* ppvObj
183 )
184 {
185   IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
186   TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
187
188   *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
189                        sizeof( *This ) );
190
191   if( *ppvObj == NULL )
192   {
193     return DPERR_OUTOFMEMORY;
194   }
195
196   CopyMemory( *ppvObj, This, sizeof( *This )  );
197   (*(IDPLobbySPImpl**)ppvObj)->ulInterfaceRef = 0;
198
199   if( IsEqualGUID( &IID_IDPLobbySP, riid ) )
200   {
201     IDPLobbySPImpl *This = (IDPLobbySPImpl *)*ppvObj;
202     This->lpVtbl = &dpLobbySPVT;
203   }
204   else
205   {
206     /* Unsupported interface */
207     HeapFree( GetProcessHeap(), 0, *ppvObj );
208     *ppvObj = NULL;
209
210     return E_NOINTERFACE;
211   }
212
213   IDPLobbySP_AddRef( (LPDPLOBBYSP)*ppvObj );
214
215   return S_OK;
216 }
217
218 static
219 ULONG WINAPI DPLSP_AddRef
220 ( LPDPLOBBYSP iface )
221 {
222   ULONG ulInterfaceRefCount, ulObjRefCount;
223   IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
224
225   ulObjRefCount       = InterlockedIncrement( &This->unk->ulObjRef );
226   ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
227
228   TRACE( "ref count incremented to %lu:%lu for %p\n",
229          ulInterfaceRefCount, ulObjRefCount, This );
230
231   return ulObjRefCount;
232 }
233
234 static
235 ULONG WINAPI DPLSP_Release
236 ( LPDPLOBBYSP iface )
237 {
238   ULONG ulInterfaceRefCount, ulObjRefCount;
239   IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
240
241   ulObjRefCount       = InterlockedDecrement( &This->unk->ulObjRef );
242   ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
243
244   TRACE( "ref count decremented to %lu:%lu for %p\n",
245          ulInterfaceRefCount, ulObjRefCount, This );
246
247   /* Deallocate if this is the last reference to the object */
248   if( ulObjRefCount == 0 )
249   {
250      DPLSP_DestroyDPLobbySP( This );
251      DPLSP_DestroyIUnknown( This );
252   }
253
254   if( ulInterfaceRefCount == 0 )
255   {
256     HeapFree( GetProcessHeap(), 0, This );
257   }
258
259   return ulInterfaceRefCount;
260 }
261
262 static
263 HRESULT WINAPI IDPLobbySPImpl_AddGroupToGroup
264 ( LPDPLOBBYSP iface,
265   LPSPDATA_ADDREMOTEGROUPTOGROUP argtg
266 )
267 {
268   IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
269   FIXME( "(%p)->(%p):stub\n", This, argtg );
270   return DP_OK;
271 }
272
273 static
274 HRESULT WINAPI IDPLobbySPImpl_AddPlayerToGroup
275 ( LPDPLOBBYSP iface,
276   LPSPDATA_ADDREMOTEPLAYERTOGROUP arptg
277 )
278 {
279   IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
280   FIXME( "(%p)->(%p):stub\n", This, arptg );
281   return DP_OK;
282 }
283
284 static
285 HRESULT WINAPI IDPLobbySPImpl_CreateGroup
286 ( LPDPLOBBYSP iface,
287   LPSPDATA_CREATEREMOTEGROUP crg
288 )
289 {
290   IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
291   FIXME( "(%p)->(%p):stub\n", This, crg );
292   return DP_OK;
293 }
294
295 static
296 HRESULT WINAPI IDPLobbySPImpl_CreateGroupInGroup
297 ( LPDPLOBBYSP iface,
298   LPSPDATA_CREATEREMOTEGROUPINGROUP crgig
299 )
300 {
301   IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
302   FIXME( "(%p)->(%p):stub\n", This, crgig );
303   return DP_OK;
304 }
305
306 static
307 HRESULT WINAPI IDPLobbySPImpl_DeleteGroupFromGroup
308 ( LPDPLOBBYSP iface,
309   LPSPDATA_DELETEREMOTEGROUPFROMGROUP drgfg
310 )
311 {
312   IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
313   FIXME( "(%p)->(%p):stub\n", This, drgfg );
314   return DP_OK;
315 }
316
317 static
318 HRESULT WINAPI IDPLobbySPImpl_DeletePlayerFromGroup
319 ( LPDPLOBBYSP iface,
320   LPSPDATA_DELETEREMOTEPLAYERFROMGROUP drpfg
321 )
322 {
323   IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
324   FIXME( "(%p)->(%p):stub\n", This, drpfg );
325   return DP_OK;
326 }
327
328 static
329 HRESULT WINAPI IDPLobbySPImpl_DestroyGroup
330 ( LPDPLOBBYSP iface,
331   LPSPDATA_DESTROYREMOTEGROUP drg
332 )
333 {
334   IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
335   FIXME( "(%p)->(%p):stub\n", This, drg );
336   return DP_OK;
337 }
338
339 static
340 HRESULT WINAPI IDPLobbySPImpl_EnumSessionsResponse
341 ( LPDPLOBBYSP iface,
342   LPSPDATA_ENUMSESSIONSRESPONSE er
343 )
344 {
345   IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
346   FIXME( "(%p)->(%p):stub\n", This, er );
347   return DP_OK;
348 }
349
350 static
351 HRESULT WINAPI IDPLobbySPImpl_GetSPDataPointer
352 ( LPDPLOBBYSP iface,
353   LPVOID* lplpData
354 )
355 {
356   IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
357   FIXME( "(%p)->(%p):stub\n", This, lplpData );
358   return DP_OK;
359 }
360
361 static
362 HRESULT WINAPI IDPLobbySPImpl_HandleMessage
363 ( LPDPLOBBYSP iface,
364   LPSPDATA_HANDLEMESSAGE hm
365 )
366 {
367   IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
368   FIXME( "(%p)->(%p):stub\n", This, hm );
369   return DP_OK;
370 }
371
372 static
373 HRESULT WINAPI IDPLobbySPImpl_SendChatMessage
374 ( LPDPLOBBYSP iface,
375   LPSPDATA_CHATMESSAGE cm
376 )
377 {
378   IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
379   FIXME( "(%p)->(%p):stub\n", This, cm );
380   return DP_OK;
381 }
382
383 static
384 HRESULT WINAPI IDPLobbySPImpl_SetGroupName
385 ( LPDPLOBBYSP iface,
386   LPSPDATA_SETREMOTEGROUPNAME srgn
387 )
388 {
389   IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
390   FIXME( "(%p)->(%p):stub\n", This, srgn );
391   return DP_OK;
392 }
393
394 static
395 HRESULT WINAPI IDPLobbySPImpl_SetPlayerName
396 ( LPDPLOBBYSP iface,
397   LPSPDATA_SETREMOTEPLAYERNAME srpn
398 )
399 {
400   IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
401   FIXME( "(%p)->(%p):stub\n", This, srpn );
402   return DP_OK;
403 }
404
405 static
406 HRESULT WINAPI IDPLobbySPImpl_SetSessionDesc
407 ( LPDPLOBBYSP iface,
408   LPSPDATA_SETSESSIONDESC ssd
409 )
410 {
411   IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
412   FIXME( "(%p)->(%p):stub\n", This, ssd );
413   return DP_OK;
414 }
415
416 static
417 HRESULT WINAPI IDPLobbySPImpl_SetSPDataPointer
418 ( LPDPLOBBYSP iface,
419   LPVOID lpData
420 )
421 {
422   IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
423   FIXME( "(%p)->(%p):stub\n", This, lpData );
424   return DP_OK;
425 }
426
427 static
428 HRESULT WINAPI IDPLobbySPImpl_StartSession
429 ( LPDPLOBBYSP iface,
430   LPSPDATA_STARTSESSIONCOMMAND ssc
431 )
432 {
433   IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
434   FIXME( "(%p)->(%p):stub\n", This, ssc );
435   return DP_OK;
436 }
437
438
439 static struct IDPLobbySPVtbl dpLobbySPVT =
440 {
441
442   DPLSP_QueryInterface,
443   DPLSP_AddRef,
444   DPLSP_Release,
445
446   IDPLobbySPImpl_AddGroupToGroup,
447   IDPLobbySPImpl_AddPlayerToGroup,
448   IDPLobbySPImpl_CreateGroup,
449   IDPLobbySPImpl_CreateGroupInGroup,
450   IDPLobbySPImpl_DeleteGroupFromGroup,
451   IDPLobbySPImpl_DeletePlayerFromGroup,
452   IDPLobbySPImpl_DestroyGroup,
453   IDPLobbySPImpl_EnumSessionsResponse,
454   IDPLobbySPImpl_GetSPDataPointer,
455   IDPLobbySPImpl_HandleMessage,
456   IDPLobbySPImpl_SendChatMessage,
457   IDPLobbySPImpl_SetGroupName,
458   IDPLobbySPImpl_SetPlayerName,
459   IDPLobbySPImpl_SetSessionDesc,
460   IDPLobbySPImpl_SetSPDataPointer,
461   IDPLobbySPImpl_StartSession
462
463 };