dplayx: GetSPPlayerData was releasing the memory we were going to use
[wine/gsoc_dplay.git] / dlls / dplayx / dplaysp.c
blobd8cb6787a1473dabb3e4c31308029118baef4b9b
1 /* This contains the implementation of the interface Service
2 * Providers require to communicate with Direct Play
4 * Copyright 2000 Peter Hunnisett
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.
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.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <string.h>
22 #include "winerror.h"
23 #include "wine/debug.h"
25 #include "dpinit.h"
26 #include "wine/dplaysp.h"
27 #include "dplay_global.h"
28 #include "name_server.h"
29 #include "dplayx_messages.h"
31 #include "dplayx_global.h" /* FIXME: For global hack */
33 /* FIXME: Need to add interface locking inside procedures */
35 WINE_DEFAULT_DEBUG_CHANNEL(dplay);
37 /* Prototypes */
38 static BOOL DPSP_CreateIUnknown( LPVOID lpSP );
39 static BOOL DPSP_DestroyIUnknown( LPVOID lpSP );
40 static BOOL DPSP_CreateDirectPlaySP( LPVOID lpSP, IDirectPlay2Impl* dp );
41 static BOOL DPSP_DestroyDirectPlaySP( LPVOID lpSP );
43 /* Predefine the interface */
44 typedef struct IDirectPlaySPImpl IDirectPlaySPImpl;
46 typedef struct tagDirectPlaySPIUnknownData
48 LONG ulObjRef;
49 CRITICAL_SECTION DPSP_lock;
50 } DirectPlaySPIUnknownData;
52 typedef struct tagDirectPlaySPData
54 LPVOID lpSpRemoteData;
55 DWORD dwSpRemoteDataSize; /* Size of data pointed to by lpSpRemoteData */
57 LPVOID lpSpLocalData;
58 DWORD dwSpLocalDataSize; /* Size of data pointed to by lpSpLocalData */
60 IDirectPlay2Impl* dplay; /* FIXME: This should perhaps be iface not impl */
62 } DirectPlaySPData;
64 #define DPSP_IMPL_FIELDS \
65 LONG ulInterfaceRef; \
66 DirectPlaySPIUnknownData* unk; \
67 DirectPlaySPData* sp;
69 struct IDirectPlaySPImpl
71 const IDirectPlaySPVtbl *lpVtbl;
72 DPSP_IMPL_FIELDS
75 /* Forward declaration of virtual tables */
76 static const IDirectPlaySPVtbl directPlaySPVT;
78 /* This structure is passed to the DP object for safe keeping */
79 typedef struct tagDP_SPPLAYERDATA
81 LPVOID lpPlayerLocalData;
82 DWORD dwPlayerLocalDataSize;
84 LPVOID lpPlayerRemoteData;
85 DWORD dwPlayerRemoteDataSize;
86 } DP_SPPLAYERDATA, *LPDP_SPPLAYERDATA;
88 /* Create the SP interface */
89 HRESULT DPSP_CreateInterface( REFIID riid, LPVOID* ppvObj, IDirectPlay2Impl* dp )
91 TRACE( " for %s\n", debugstr_guid( riid ) );
93 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
94 sizeof( IDirectPlaySPImpl ) );
96 if( *ppvObj == NULL )
98 return DPERR_OUTOFMEMORY;
101 if( IsEqualGUID( &IID_IDirectPlaySP, riid ) )
103 IDirectPlaySPImpl *This = *ppvObj;
104 This->lpVtbl = &directPlaySPVT;
106 else
108 /* Unsupported interface */
109 HeapFree( GetProcessHeap(), 0, *ppvObj );
110 *ppvObj = NULL;
112 return E_NOINTERFACE;
115 /* Initialize it */
116 if( DPSP_CreateIUnknown( *ppvObj ) &&
117 DPSP_CreateDirectPlaySP( *ppvObj, dp )
120 IDirectPlaySP_AddRef( (LPDIRECTPLAYSP)*ppvObj );
121 return S_OK;
124 /* Initialize failed, destroy it */
125 DPSP_DestroyDirectPlaySP( *ppvObj );
126 DPSP_DestroyIUnknown( *ppvObj );
128 HeapFree( GetProcessHeap(), 0, *ppvObj );
129 *ppvObj = NULL;
131 return DPERR_NOMEMORY;
134 static BOOL DPSP_CreateIUnknown( LPVOID lpSP )
136 IDirectPlaySPImpl *This = lpSP;
138 This->unk = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->unk) ) );
140 if ( This->unk == NULL )
142 return FALSE;
145 InitializeCriticalSection( &This->unk->DPSP_lock );
146 This->unk->DPSP_lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectPlaySPImpl*->DirectPlaySPIUnknownData*->DPSP_lock");
148 return TRUE;
151 static BOOL DPSP_DestroyIUnknown( LPVOID lpSP )
153 IDirectPlaySPImpl *This = lpSP;
155 This->unk->DPSP_lock.DebugInfo->Spare[0] = 0;
156 DeleteCriticalSection( &This->unk->DPSP_lock );
157 HeapFree( GetProcessHeap(), 0, This->unk );
159 return TRUE;
163 static BOOL DPSP_CreateDirectPlaySP( LPVOID lpSP, IDirectPlay2Impl* dp )
165 IDirectPlaySPImpl *This = lpSP;
167 This->sp = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->sp) ) );
169 if ( This->sp == NULL )
171 return FALSE;
174 This->sp->dplay = dp;
176 /* Normally we should be keeping a reference, but since only the dplay
177 * interface that created us can destroy us, we do not keep a reference
178 * to it (ie we'd be stuck with always having one reference to the dplay
179 * object, and hence us, around).
180 * NOTE: The dp object does reference count us.
182 * FIXME: This is a kludge to get around a problem where a queryinterface
183 * is used to get a new interface and then is closed. We will then
184 * reference garbage. However, with this we will never deallocate
185 * the interface we store. The correct fix is to require all
186 * DP internal interfaces to use the This->dp2 interface which
187 * should be changed to This->dp
189 IDirectPlayX_AddRef( (LPDIRECTPLAY2)dp );
191 return TRUE;
194 static BOOL DPSP_DestroyDirectPlaySP( LPVOID lpSP )
196 IDirectPlaySPImpl *This = lpSP;
198 /* Normally we should be keeping a reference, but since only the dplay
199 * interface that created us can destroy us, we do not keep a reference
200 * to it (ie we'd be stuck with always having one reference to the dplay
201 * object, and hence us, around).
202 * NOTE: The dp object does reference count us.
204 /*IDirectPlayX_Release( (LPDIRECTPLAY2)This->sp->dplay ); */
206 HeapFree( GetProcessHeap(), 0, This->sp->lpSpRemoteData );
207 HeapFree( GetProcessHeap(), 0, This->sp->lpSpLocalData );
209 /* FIXME: Need to delete player queue */
211 HeapFree( GetProcessHeap(), 0, This->sp );
212 return TRUE;
215 /* Interface implementation */
217 static HRESULT WINAPI DPSP_QueryInterface
218 ( LPDIRECTPLAYSP iface,
219 REFIID riid,
220 LPVOID* ppvObj )
222 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
223 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
225 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
226 sizeof( *This ) );
228 if( *ppvObj == NULL )
230 return DPERR_OUTOFMEMORY;
233 CopyMemory( *ppvObj, This, sizeof( *This ) );
234 (*(IDirectPlaySPImpl**)ppvObj)->ulInterfaceRef = 0;
236 if( IsEqualGUID( &IID_IDirectPlaySP, riid ) )
238 IDirectPlaySPImpl *This = *ppvObj;
239 This->lpVtbl = &directPlaySPVT;
241 else
243 /* Unsupported interface */
244 HeapFree( GetProcessHeap(), 0, *ppvObj );
245 *ppvObj = NULL;
247 return E_NOINTERFACE;
250 IDirectPlaySP_AddRef( (LPDIRECTPLAYSP)*ppvObj );
252 return S_OK;
255 static ULONG WINAPI DPSP_AddRef
256 ( LPDIRECTPLAYSP iface )
258 ULONG ulInterfaceRefCount, ulObjRefCount;
259 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
261 ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
262 ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
264 TRACE( "ref count incremented to %u:%u for %p\n",
265 ulInterfaceRefCount, ulObjRefCount, This );
267 return ulObjRefCount;
270 static ULONG WINAPI DPSP_Release
271 ( LPDIRECTPLAYSP iface )
273 ULONG ulInterfaceRefCount, ulObjRefCount;
274 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
276 ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
277 ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
279 TRACE( "ref count decremented to %u:%u for %p\n",
280 ulInterfaceRefCount, ulObjRefCount, This );
282 /* Deallocate if this is the last reference to the object */
283 if( ulObjRefCount == 0 )
285 DPSP_DestroyDirectPlaySP( This );
286 DPSP_DestroyIUnknown( This );
289 if( ulInterfaceRefCount == 0 )
291 HeapFree( GetProcessHeap(), 0, This );
294 return ulInterfaceRefCount;
297 static HRESULT WINAPI IDirectPlaySPImpl_AddMRUEntry
298 ( LPDIRECTPLAYSP iface,
299 LPCWSTR lpSection,
300 LPCWSTR lpKey,
301 LPCVOID lpData,
302 DWORD dwDataSize,
303 DWORD dwMaxEntries
306 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
308 /* Should be able to call the comctl32 undocumented MRU routines.
309 I suspect that the interface works appropriately */
310 FIXME( "(%p)->(%p,%p%p,0x%08x,0x%08x): stub\n",
311 This, lpSection, lpKey, lpData, dwDataSize, dwMaxEntries );
313 return DP_OK;
316 static HRESULT WINAPI IDirectPlaySPImpl_CreateAddress
317 ( LPDIRECTPLAYSP iface,
318 REFGUID guidSP,
319 REFGUID guidDataType,
320 LPCVOID lpData,
321 DWORD dwDataSize,
322 LPVOID lpAddress,
323 LPDWORD lpdwAddressSize
326 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
328 FIXME( "(%p)->(%s,%s,%p,0x%08x,%p,%p): stub\n",
329 This, debugstr_guid(guidSP), debugstr_guid(guidDataType),
330 lpData, dwDataSize, lpAddress, lpdwAddressSize );
332 return DP_OK;
335 static HRESULT WINAPI IDirectPlaySPImpl_EnumAddress
336 ( LPDIRECTPLAYSP iface,
337 LPDPENUMADDRESSCALLBACK lpEnumAddressCallback,
338 LPCVOID lpAddress,
339 DWORD dwAddressSize,
340 LPVOID lpContext
343 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
345 TRACE( "(%p)->(%p,%p,0x%08x,%p)\n",
346 This, lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
348 DPL_EnumAddress( lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
350 return DP_OK;
353 static HRESULT WINAPI IDirectPlaySPImpl_EnumMRUEntries
354 ( LPDIRECTPLAYSP iface,
355 LPCWSTR lpSection,
356 LPCWSTR lpKey,
357 LPENUMMRUCALLBACK lpEnumMRUCallback,
358 LPVOID lpContext
361 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
363 /* Should be able to call the comctl32 undocumented MRU routines.
364 I suspect that the interface works appropriately */
365 FIXME( "(%p)->(%p,%p,%p,%p,): stub\n",
366 This, lpSection, lpKey, lpEnumMRUCallback, lpContext );
368 return DP_OK;
371 static HRESULT WINAPI IDirectPlaySPImpl_GetPlayerFlags
372 ( LPDIRECTPLAYSP iface,
373 DPID idPlayer,
374 LPDWORD lpdwPlayerFlags
377 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
379 FIXME( "(%p)->(0x%08x,%p): stub\n",
380 This, idPlayer, lpdwPlayerFlags );
382 return DP_OK;
385 static HRESULT WINAPI IDirectPlaySPImpl_GetSPPlayerData
386 ( LPDIRECTPLAYSP iface,
387 DPID idPlayer,
388 LPVOID* lplpData,
389 LPDWORD lpdwDataSize,
390 DWORD dwFlags
393 HRESULT hr;
394 LPDP_SPPLAYERDATA lpPlayerData;
395 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
397 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x)\n",
398 This, idPlayer, lplpData, lpdwDataSize, dwFlags );
400 hr = DP_GetSPPlayerData( This->sp->dplay, idPlayer, (LPVOID*)&lpPlayerData );
402 if( FAILED(hr) )
404 ERR( "Couldn't get player data: %s\n", DPLAYX_HresultToString(hr) );
405 return hr;
408 if( dwFlags == DPSET_LOCAL )
410 *lplpData = lpPlayerData->lpPlayerLocalData;
411 *lpdwDataSize = lpPlayerData->dwPlayerLocalDataSize;
413 else if( dwFlags == DPSET_REMOTE )
415 *lplpData = lpPlayerData->lpPlayerRemoteData;
416 *lpdwDataSize = lpPlayerData->dwPlayerRemoteDataSize;
419 return DP_OK;
422 static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage
423 ( LPDIRECTPLAYSP iface,
424 LPVOID lpMessageBody,
425 DWORD dwMessageBodySize,
426 LPVOID lpMessageHeader
429 LPDPSP_MSG_ENVELOPE lpMsg = lpMessageBody;
430 DPSP_REPLYDATA data;
431 HRESULT hr;
433 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
435 TRACE( "(%p)->(%p,0x%08x,%p)\n",
436 This, lpMessageBody, dwMessageBodySize, lpMessageHeader );
438 TRACE( "Incoming message has envelope of 0x%08x, 0x%x, %u\n",
439 lpMsg->dwMagic, lpMsg->wCommandId, lpMsg->wVersion );
441 if( lpMsg->dwMagic != DPMSG_SIGNATURE )
443 ERR( "Unknown magic 0x%08x!\n", lpMsg->dwMagic );
444 return DPERR_GENERIC;
447 /* Pass everything else to Direct Play */
448 data.lpMessage = NULL;
449 data.dwMessageSize = 0;
451 /* Pass this message to the dplay interface to handle */
452 hr = DP_HandleMessage( This->sp->dplay, lpMessageBody, dwMessageBodySize,
453 lpMessageHeader, lpMsg->wCommandId, lpMsg->wVersion,
454 &data.lpMessage, &data.dwMessageSize );
455 if( FAILED(hr) )
457 ERR( "Command processing failed %s\n", DPLAYX_HresultToString(hr) );
460 /* Do we want a reply? */
461 if( data.lpMessage != NULL )
463 data.lpSPMessageHeader = lpMessageHeader;
464 data.idNameServer = 0;
465 data.lpISP = iface;
467 hr = (This->sp->dplay->dp2->spData.lpCB->Reply)( &data );
469 if( FAILED(hr) )
471 ERR( "Reply failed %s\n", DPLAYX_HresultToString(hr) );
475 return hr;
478 static HRESULT WINAPI IDirectPlaySPImpl_SetSPPlayerData
479 ( LPDIRECTPLAYSP iface,
480 DPID idPlayer,
481 LPVOID lpData,
482 DWORD dwDataSize,
483 DWORD dwFlags
486 HRESULT hr;
487 LPDP_SPPLAYERDATA lpPlayerEntry;
488 LPVOID lpPlayerData;
490 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
492 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x)\n",
493 This, idPlayer, lpData, dwDataSize, dwFlags );
495 hr = DP_GetSPPlayerData( This->sp->dplay, idPlayer, (LPVOID*)&lpPlayerEntry );
496 if( FAILED(hr) )
498 /* Player must not exist */
499 return DPERR_INVALIDPLAYER;
502 lpPlayerData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
503 CopyMemory( lpPlayerData, lpData, dwDataSize );
505 /* If we have data already allocated, free it and replace it */
506 if( dwFlags == DPSET_LOCAL )
508 HeapFree( GetProcessHeap(), 0, lpPlayerEntry->lpPlayerLocalData );
509 lpPlayerEntry->lpPlayerLocalData = lpPlayerData;
510 lpPlayerEntry->dwPlayerLocalDataSize = dwDataSize;
512 else if( dwFlags == DPSET_REMOTE )
514 HeapFree( GetProcessHeap(), 0, lpPlayerEntry->lpPlayerRemoteData );
515 lpPlayerEntry->lpPlayerRemoteData = lpPlayerData;
516 lpPlayerEntry->dwPlayerRemoteDataSize = dwDataSize;
519 hr = DP_SetSPPlayerData( This->sp->dplay, idPlayer, lpPlayerEntry );
521 return hr;
524 static HRESULT WINAPI IDirectPlaySPImpl_CreateCompoundAddress
525 ( LPDIRECTPLAYSP iface,
526 LPCDPCOMPOUNDADDRESSELEMENT lpElements,
527 DWORD dwElementCount,
528 LPVOID lpAddress,
529 LPDWORD lpdwAddressSize
532 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
534 FIXME( "(%p)->(%p,0x%08x,%p,%p): stub\n",
535 This, lpElements, dwElementCount, lpAddress, lpdwAddressSize );
537 return DP_OK;
540 static HRESULT WINAPI IDirectPlaySPImpl_GetSPData
541 ( LPDIRECTPLAYSP iface,
542 LPVOID* lplpData,
543 LPDWORD lpdwDataSize,
544 DWORD dwFlags
547 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
549 TRACE( "(%p)->(%p,%p,0x%08x)\n",
550 This, lplpData, lpdwDataSize, dwFlags );
552 if( dwFlags == DPSET_REMOTE )
554 *lpdwDataSize = This->sp->dwSpRemoteDataSize;
555 *lplpData = This->sp->lpSpRemoteData;
557 else if( dwFlags == DPSET_LOCAL )
559 *lpdwDataSize = This->sp->dwSpLocalDataSize;
560 *lplpData = This->sp->lpSpLocalData;
563 return DP_OK;
566 static HRESULT WINAPI IDirectPlaySPImpl_SetSPData
567 ( LPDIRECTPLAYSP iface,
568 LPVOID lpData,
569 DWORD dwDataSize,
570 DWORD dwFlags
573 LPVOID lpSpData;
575 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
577 TRACE( "(%p)->(%p,%d,0x%08x)\n",
578 This, lpData, dwDataSize, dwFlags );
580 lpSpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
581 CopyMemory( lpSpData, lpData, dwDataSize );
583 /* If we have data already allocated, free it and replace it */
584 if( dwFlags == DPSET_REMOTE )
586 HeapFree( GetProcessHeap(), 0, This->sp->lpSpRemoteData );
587 This->sp->dwSpRemoteDataSize = dwDataSize;
588 This->sp->lpSpRemoteData = lpSpData;
590 else if ( dwFlags == DPSET_LOCAL )
592 HeapFree( GetProcessHeap(), 0, This->sp->lpSpLocalData );
593 This->sp->lpSpLocalData = lpSpData;
594 This->sp->dwSpLocalDataSize = dwDataSize;
597 return DP_OK;
600 static VOID WINAPI IDirectPlaySPImpl_SendComplete
601 ( LPDIRECTPLAYSP iface,
602 LPVOID unknownA,
603 DWORD unknownB
606 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
608 FIXME( "(%p)->(%p,0x%08x): stub\n",
609 This, unknownA, unknownB );
612 static const IDirectPlaySPVtbl directPlaySPVT =
615 DPSP_QueryInterface,
616 DPSP_AddRef,
617 DPSP_Release,
619 IDirectPlaySPImpl_AddMRUEntry,
620 IDirectPlaySPImpl_CreateAddress,
621 IDirectPlaySPImpl_EnumAddress,
622 IDirectPlaySPImpl_EnumMRUEntries,
623 IDirectPlaySPImpl_GetPlayerFlags,
624 IDirectPlaySPImpl_GetSPPlayerData,
625 IDirectPlaySPImpl_HandleMessage,
626 IDirectPlaySPImpl_SetSPPlayerData,
627 IDirectPlaySPImpl_CreateCompoundAddress,
628 IDirectPlaySPImpl_GetSPData,
629 IDirectPlaySPImpl_SetSPData,
630 IDirectPlaySPImpl_SendComplete
634 /* DP external interfaces to call into DPSP interface */
636 /* Allocate the structure */
637 LPVOID DPSP_CreateSPPlayerData(void)
639 TRACE( "Creating SPPlayer data struct\n" );
640 return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
641 sizeof( DP_SPPLAYERDATA ) );