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
23 #include "wine/debug.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);
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
49 CRITICAL_SECTION DPSP_lock;
50 } DirectPlaySPIUnknownData;
52 typedef struct tagDirectPlaySPData
54 LPVOID lpSpRemoteData;
55 DWORD dwSpRemoteDataSize; /* Size of data pointed to by lpSpRemoteData */
58 DWORD dwSpLocalDataSize; /* Size of data pointed to by lpSpLocalData */
60 IDirectPlay2Impl* dplay; /* FIXME: This should perhaps be iface not impl */
64 #define DPSP_IMPL_FIELDS \
65 LONG ulInterfaceRef; \
66 DirectPlaySPIUnknownData* unk; \
69 struct IDirectPlaySPImpl
71 const IDirectPlaySPVtbl *lpVtbl;
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 */
90 HRESULT DPSP_CreateInterface( REFIID riid, LPVOID* ppvObj, IDirectPlay2Impl* dp )
92 TRACE( " for %s\n", debugstr_guid( riid ) );
94 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
95 sizeof( IDirectPlaySPImpl ) );
99 return DPERR_OUTOFMEMORY;
102 if( IsEqualGUID( &IID_IDirectPlaySP, riid ) )
104 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)*ppvObj;
105 This->lpVtbl = &directPlaySPVT;
109 /* Unsupported interface */
110 HeapFree( GetProcessHeap(), 0, *ppvObj );
113 return E_NOINTERFACE;
117 if( DPSP_CreateIUnknown( *ppvObj ) &&
118 DPSP_CreateDirectPlaySP( *ppvObj, dp )
121 IDirectPlaySP_AddRef( (LPDIRECTPLAYSP)*ppvObj );
125 /* Initialize failed, destroy it */
126 DPSP_DestroyDirectPlaySP( *ppvObj );
127 DPSP_DestroyIUnknown( *ppvObj );
129 HeapFree( GetProcessHeap(), 0, *ppvObj );
132 return DPERR_NOMEMORY;
135 static BOOL DPSP_CreateIUnknown( LPVOID lpSP )
137 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)lpSP;
139 This->unk = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->unk) ) );
141 if ( This->unk == NULL )
146 InitializeCriticalSection( &This->unk->DPSP_lock );
147 This->unk->DPSP_lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectPlaySPImpl*->DirectPlaySPIUnknownData*->DPSP_lock");
152 static BOOL DPSP_DestroyIUnknown( LPVOID lpSP )
154 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)lpSP;
156 This->unk->DPSP_lock.DebugInfo->Spare[0] = 0;
157 DeleteCriticalSection( &This->unk->DPSP_lock );
158 HeapFree( GetProcessHeap(), 0, This->unk );
164 static BOOL DPSP_CreateDirectPlaySP( LPVOID lpSP, IDirectPlay2Impl* dp )
166 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)lpSP;
168 This->sp = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->sp) ) );
170 if ( This->sp == NULL )
175 This->sp->dplay = dp;
177 /* Normally we should be keeping a reference, but since only the dplay
178 * interface that created us can destroy us, we do not keep a reference
179 * to it (ie we'd be stuck with always having one reference to the dplay
180 * object, and hence us, around).
181 * NOTE: The dp object does reference count us.
183 * FIXME: This is a kludge to get around a problem where a queryinterface
184 * is used to get a new interface and then is closed. We will then
185 * reference garbage. However, with this we will never deallocate
186 * the interface we store. The correct fix is to require all
187 * DP internal interfaces to use the This->dp2 interface which
188 * should be changed to This->dp
190 IDirectPlayX_AddRef( (LPDIRECTPLAY2)dp );
195 static BOOL DPSP_DestroyDirectPlaySP( LPVOID lpSP )
197 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)lpSP;
199 /* Normally we should be keeping a reference, but since only the dplay
200 * interface that created us can destroy us, we do not keep a reference
201 * to it (ie we'd be stuck with always having one reference to the dplay
202 * object, and hence us, around).
203 * NOTE: The dp object does reference count us.
205 /*IDirectPlayX_Release( (LPDIRECTPLAY2)This->sp->dplay ); */
207 HeapFree( GetProcessHeap(), 0, This->sp->lpSpRemoteData );
208 HeapFree( GetProcessHeap(), 0, This->sp->lpSpLocalData );
210 /* FIXME: Need to delete player queue */
212 HeapFree( GetProcessHeap(), 0, This->sp );
216 /* Interface implementation */
218 static HRESULT WINAPI DPSP_QueryInterface
219 ( LPDIRECTPLAYSP iface,
223 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
224 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
226 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
229 if( *ppvObj == NULL )
231 return DPERR_OUTOFMEMORY;
234 CopyMemory( *ppvObj, This, sizeof( *This ) );
235 (*(IDirectPlaySPImpl**)ppvObj)->ulInterfaceRef = 0;
237 if( IsEqualGUID( &IID_IDirectPlaySP, riid ) )
239 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)*ppvObj;
240 This->lpVtbl = &directPlaySPVT;
244 /* Unsupported interface */
245 HeapFree( GetProcessHeap(), 0, *ppvObj );
248 return E_NOINTERFACE;
251 IDirectPlaySP_AddRef( (LPDIRECTPLAYSP)*ppvObj );
256 static ULONG WINAPI DPSP_AddRef
257 ( LPDIRECTPLAYSP iface )
259 ULONG ulInterfaceRefCount, ulObjRefCount;
260 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
262 ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
263 ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
265 TRACE( "ref count incremented to %u:%u for %p\n",
266 ulInterfaceRefCount, ulObjRefCount, This );
268 return ulObjRefCount;
271 static ULONG WINAPI DPSP_Release
272 ( LPDIRECTPLAYSP iface )
274 ULONG ulInterfaceRefCount, ulObjRefCount;
275 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
277 ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
278 ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
280 TRACE( "ref count decremented to %u:%u for %p\n",
281 ulInterfaceRefCount, ulObjRefCount, This );
283 /* Deallocate if this is the last reference to the object */
284 if( ulObjRefCount == 0 )
286 DPSP_DestroyDirectPlaySP( This );
287 DPSP_DestroyIUnknown( This );
290 if( ulInterfaceRefCount == 0 )
292 HeapFree( GetProcessHeap(), 0, This );
295 return ulInterfaceRefCount;
298 static HRESULT WINAPI IDirectPlaySPImpl_AddMRUEntry
299 ( LPDIRECTPLAYSP iface,
307 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
309 /* Should be able to call the comctl32 undocumented MRU routines.
310 I suspect that the interface works appropriately */
311 FIXME( "(%p)->(%p,%p%p,0x%08x,0x%08x): stub\n",
312 This, lpSection, lpKey, lpData, dwDataSize, dwMaxEntries );
317 static HRESULT WINAPI IDirectPlaySPImpl_CreateAddress
318 ( LPDIRECTPLAYSP iface,
320 REFGUID guidDataType,
324 LPDWORD lpdwAddressSize
327 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
329 FIXME( "(%p)->(%s,%s,%p,0x%08x,%p,%p): stub\n",
330 This, debugstr_guid(guidSP), debugstr_guid(guidDataType),
331 lpData, dwDataSize, lpAddress, lpdwAddressSize );
336 static HRESULT WINAPI IDirectPlaySPImpl_EnumAddress
337 ( LPDIRECTPLAYSP iface,
338 LPDPENUMADDRESSCALLBACK lpEnumAddressCallback,
344 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
346 TRACE( "(%p)->(%p,%p,0x%08x,%p)\n",
347 This, lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
349 DPL_EnumAddress( lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
354 static HRESULT WINAPI IDirectPlaySPImpl_EnumMRUEntries
355 ( LPDIRECTPLAYSP iface,
358 LPENUMMRUCALLBACK lpEnumMRUCallback,
362 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
364 /* Should be able to call the comctl32 undocumented MRU routines.
365 I suspect that the interface works appropriately */
366 FIXME( "(%p)->(%p,%p,%p,%p,): stub\n",
367 This, lpSection, lpKey, lpEnumMRUCallback, lpContext );
372 static HRESULT WINAPI IDirectPlaySPImpl_GetPlayerFlags
373 ( LPDIRECTPLAYSP iface,
375 LPDWORD lpdwPlayerFlags
378 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
380 FIXME( "(%p)->(0x%08x,%p): stub\n",
381 This, idPlayer, lpdwPlayerFlags );
386 static HRESULT WINAPI IDirectPlaySPImpl_GetSPPlayerData
387 ( LPDIRECTPLAYSP iface,
390 LPDWORD lpdwDataSize,
395 LPDP_SPPLAYERDATA lpPlayerData;
396 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
398 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x)\n",
399 This, idPlayer, lplpData, lpdwDataSize, dwFlags );
401 hr = DP_GetSPPlayerData( This->sp->dplay, idPlayer, (LPVOID*)&lpPlayerData );
405 TRACE( "Couldn't get player data: %s\n", DPLAYX_HresultToString(hr) );
406 return DPERR_INVALIDPLAYER;
409 /* What to do in the case where there is nothing set yet? */
410 if( dwFlags == DPSET_LOCAL )
412 HeapFree( GetProcessHeap(), 0, lpPlayerData->lpPlayerLocalData );
413 *lplpData = lpPlayerData->lpPlayerLocalData;
414 *lpdwDataSize = lpPlayerData->dwPlayerLocalDataSize;
416 else if( dwFlags == DPSET_REMOTE )
418 HeapFree( GetProcessHeap(), 0, lpPlayerData->lpPlayerRemoteData );
419 *lplpData = lpPlayerData->lpPlayerRemoteData;
420 *lpdwDataSize = lpPlayerData->dwPlayerRemoteDataSize;
423 if( *lplpData == NULL )
431 static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage
432 ( LPDIRECTPLAYSP iface,
433 LPVOID lpMessageBody,
434 DWORD dwMessageBodySize,
435 LPVOID lpMessageHeader
438 LPDPMSG_SENDENVELOPE lpMsg = (LPDPMSG_SENDENVELOPE)lpMessageBody;
439 HRESULT hr = DPERR_GENERIC;
444 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
446 FIXME( "(%p)->(%p,0x%08x,%p): mostly stub\n",
447 This, lpMessageBody, dwMessageBodySize, lpMessageHeader );
449 wCommandId = lpMsg->wCommandId;
450 wVersion = lpMsg->wVersion;
452 TRACE( "Incoming message has envelope of 0x%08x, %u, %u\n",
453 lpMsg->dwMagic, wCommandId, wVersion );
455 if( lpMsg->dwMagic != DPMSGMAGIC_DPLAYMSG )
457 ERR( "Unknown magic 0x%08x!\n", lpMsg->dwMagic );
458 return DPERR_GENERIC;
463 const LPDWORD lpcHeader = (LPDWORD)lpMessageHeader;
465 TRACE( "lpMessageHeader = [0x%08lx] [0x%08lx] [0x%08lx] [0x%08lx] [0x%08lx]\n",
466 lpcHeader[0], lpcHeader[1], lpcHeader[2], lpcHeader[3], lpcHeader[4] );
470 /* Pass everything else to Direct Play */
471 data.lpMessage = NULL;
472 data.dwMessageSize = 0;
474 /* Pass this message to the dplay interface to handle */
475 hr = DP_HandleMessage( This->sp->dplay, lpMessageBody, dwMessageBodySize,
476 lpMessageHeader, wCommandId, wVersion,
477 &data.lpMessage, &data.dwMessageSize );
481 ERR( "Command processing failed %s\n", DPLAYX_HresultToString(hr) );
484 /* Do we want a reply? */
485 if( data.lpMessage != NULL )
487 data.lpSPMessageHeader = lpMessageHeader;
488 data.idNameServer = 0;
491 hr = (This->sp->dplay->dp2->spData.lpCB->Reply)( &data );
495 ERR( "Reply failed %s\n", DPLAYX_HresultToString(hr) );
503 HANDLE hReceiveEvent = 0;
504 /* FIXME: Acquire some sort of interface lock */
505 /* FIXME: Need some sort of context for this callback. Need to determine
506 * how this is actually done with the SP
508 /* FIXME: Who needs to delete the message when done? */
509 switch( lpMsg->dwType )
511 case DPSYS_CREATEPLAYERORGROUP:
513 LPDPMSG_CREATEPLAYERORGROUP msg = (LPDPMSG_CREATEPLAYERORGROUP)lpMsg;
515 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
517 hr = DP_IF_CreatePlayer( This, lpMessageHeader, msg->dpId,
518 &msg->dpnName, 0, msg->lpData,
519 msg->dwDataSize, msg->dwFlags, ... );
521 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
523 /* Group in group situation? */
524 if( msg->dpIdParent == DPID_NOPARENT_GROUP )
526 hr = DP_IF_CreateGroup( This, lpMessageHeader, msg->dpId,
527 &msg->dpnName, 0, msg->lpData,
528 msg->dwDataSize, msg->dwFlags, ... );
530 else /* Group in Group */
532 hr = DP_IF_CreateGroupInGroup( This, lpMessageHeader, msg->dpIdParent,
533 &msg->dpnName, 0, msg->lpData,
534 msg->dwDataSize, msg->dwFlags, ... );
539 ERR( "Corrupt msg->dwPlayerType for DPSYS_CREATEPLAYERORGROUP\n" );
546 case DPSYS_DESTROYPLAYERORGROUP:
548 LPDPMSG_DESTROYPLAYERORGROUP msg = (LPDPMSG_DESTROYPLAYERORGROUP)lpMsg;
550 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
552 hr = DP_IF_DestroyPlayer( This, msg->dpId, ... );
554 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
556 hr = DP_IF_DestroyGroup( This, msg->dpId, ... );
560 ERR( "Corrupt msg->dwPlayerType for DPSYS_DESTROYPLAYERORGROUP\n" );
567 case DPSYS_ADDPLAYERTOGROUP:
569 LPDPMSG_ADDPLAYERTOGROUP msg = (LPDPMSG_ADDPLAYERTOGROUP)lpMsg;
571 hr = DP_IF_AddPlayerToGroup( This, msg->dpIdGroup, msg->dpIdPlayer, ... );
575 case DPSYS_DELETEPLAYERFROMGROUP:
577 LPDPMSG_DELETEPLAYERFROMGROUP msg = (LPDPMSG_DELETEPLAYERFROMGROUP)lpMsg;
579 hr = DP_IF_DeletePlayerFromGroup( This, msg->dpIdGroup, msg->dpIdPlayer,
585 case DPSYS_SESSIONLOST:
587 LPDPMSG_SESSIONLOST msg = (LPDPMSG_SESSIONLOST)lpMsg;
589 FIXME( "DPSYS_SESSIONLOST not handled\n" );
596 LPDPMSG_HOST msg = (LPDPMSG_HOST)lpMsg;
598 FIXME( "DPSYS_HOST not handled\n" );
603 case DPSYS_SETPLAYERORGROUPDATA:
605 LPDPMSG_SETPLAYERORGROUPDATA msg = (LPDPMSG_SETPLAYERORGROUPDATA)lpMsg;
607 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
609 hr = DP_IF_SetPlayerData( This, msg->dpId, msg->lpData, msg->dwDataSize, DPSET_REMOTE, ... );
611 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
613 hr = DP_IF_SetGroupData( This, msg->dpId, msg->lpData, msg->dwDataSize,
618 ERR( "Corrupt msg->dwPlayerType for LPDPMSG_SETPLAYERORGROUPDATA\n" );
625 case DPSYS_SETPLAYERORGROUPNAME:
627 LPDPMSG_SETPLAYERORGROUPNAME msg = (LPDPMSG_SETPLAYERORGROUPNAME)lpMsg;
629 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
631 hr = DP_IF_SetPlayerName( This, msg->dpId, msg->dpnName, ... );
633 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
635 hr = DP_IF_SetGroupName( This, msg->dpId, msg->dpnName, ... );
639 ERR( "Corrupt msg->dwPlayerType for LPDPMSG_SETPLAYERORGROUPDATA\n" );
646 case DPSYS_SETSESSIONDESC;
648 LPDPMSG_SETSESSIONDESC msg = (LPDPMSG_SETSESSIONDESC)lpMsg;
650 hr = DP_IF_SetSessionDesc( This, &msg->dpDesc );
655 case DPSYS_ADDGROUPTOGROUP:
657 LPDPMSG_ADDGROUPTOGROUP msg = (LPDPMSG_ADDGROUPTOGROUP)lpMsg;
659 hr = DP_IF_AddGroupToGroup( This, msg->dpIdParentGroup, msg->dpIdGroup,
665 case DPSYS_DELETEGROUPFROMGROUP:
667 LPDPMSG_DELETEGROUPFROMGROUP msg = (LPDPMSG_DELETEGROUPFROMGROUP)lpMsg;
669 hr = DP_IF_DeleteGroupFromGroup( This, msg->dpIdParentGroup,
670 msg->dpIdGroup, ... );
675 case DPSYS_SECUREMESSAGE:
677 LPDPMSG_SECUREMESSAGE msg = (LPDPMSG_SECUREMESSAGE)lpMsg;
679 FIXME( "DPSYS_SECUREMESSAGE not implemented\n" );
684 case DPSYS_STARTSESSION:
686 LPDPMSG_STARTSESSION msg = (LPDPMSG_STARTSESSION)lpMsg;
688 FIXME( "DPSYS_STARTSESSION not implemented\n" );
695 LPDPMSG_CHAT msg = (LPDPMSG_CHAT)lpMsg;
697 FIXME( "DPSYS_CHAT not implemeneted\n" );
702 case DPSYS_SETGROUPOWNER:
704 LPDPMSG_SETGROUPOWNER msg = (LPDPMSG_SETGROUPOWNER)lpMsg;
706 FIXME( "DPSYS_SETGROUPOWNER not implemented\n" );
711 case DPSYS_SENDCOMPLETE:
713 LPDPMSG_SENDCOMPLETE msg = (LPDPMSG_SENDCOMPLETE)lpMsg;
715 FIXME( "DPSYS_SENDCOMPLETE not implemented\n" );
722 /* NOTE: This should be a user defined type. There is nothing that we
723 * need to do with it except queue it.
725 TRACE( "Received user message type(?) 0x%08lx through SP.\n",
731 FIXME( "Queue message in the receive queue. Need some context data!\n" );
735 ERR( "Unable to perform action for msg type 0x%08lx\n", lpMsg->dwType );
737 /* If a receive event was registered for this player, invoke it */
740 SetEvent( hReceiveEvent );
745 static HRESULT WINAPI IDirectPlaySPImpl_SetSPPlayerData
746 ( LPDIRECTPLAYSP iface,
754 LPDP_SPPLAYERDATA lpPlayerEntry;
757 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
759 /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
760 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x)\n",
761 This, idPlayer, lpData, dwDataSize, dwFlags );
763 hr = DP_GetSPPlayerData( This->sp->dplay, idPlayer, (LPVOID*)&lpPlayerEntry );
766 /* Player must not exist */
767 return DPERR_INVALIDPLAYER;
770 lpPlayerData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
771 CopyMemory( lpPlayerData, lpData, dwDataSize );
773 if( dwFlags == DPSET_LOCAL )
775 lpPlayerEntry->lpPlayerLocalData = lpPlayerData;
776 lpPlayerEntry->dwPlayerLocalDataSize = dwDataSize;
778 else if( dwFlags == DPSET_REMOTE )
780 lpPlayerEntry->lpPlayerRemoteData = lpPlayerData;
781 lpPlayerEntry->dwPlayerRemoteDataSize = dwDataSize;
784 hr = DP_SetSPPlayerData( This->sp->dplay, idPlayer, lpPlayerEntry );
789 static HRESULT WINAPI IDirectPlaySPImpl_CreateCompoundAddress
790 ( LPDIRECTPLAYSP iface,
791 LPCDPCOMPOUNDADDRESSELEMENT lpElements,
792 DWORD dwElementCount,
794 LPDWORD lpdwAddressSize
797 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
799 FIXME( "(%p)->(%p,0x%08x,%p,%p): stub\n",
800 This, lpElements, dwElementCount, lpAddress, lpdwAddressSize );
805 static HRESULT WINAPI IDirectPlaySPImpl_GetSPData
806 ( LPDIRECTPLAYSP iface,
808 LPDWORD lpdwDataSize,
813 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
815 /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
816 TRACE( "(%p)->(%p,%p,0x%08x)\n",
817 This, lplpData, lpdwDataSize, dwFlags );
820 /* This is what the documentation says... */
821 if( dwFlags != DPSET_REMOTE )
823 return DPERR_INVALIDPARAMS;
826 /* ... but most service providers call this with 1 */
827 /* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
830 if( dwFlags != DPSET_REMOTE )
832 TRACE( "Undocumented dwFlags 0x%08x used\n", dwFlags );
836 /* FIXME: What to do in the case where this isn't initialized yet? */
838 /* Yes, we're supposed to return a pointer to the memory we have stored! */
839 if( dwFlags == DPSET_REMOTE )
841 *lpdwDataSize = This->sp->dwSpRemoteDataSize;
842 *lplpData = This->sp->lpSpRemoteData;
844 if( This->sp->lpSpRemoteData == NULL )
849 else if( dwFlags == DPSET_LOCAL )
851 *lpdwDataSize = This->sp->dwSpLocalDataSize;
852 *lplpData = This->sp->lpSpLocalData;
854 if( This->sp->lpSpLocalData == NULL )
863 static HRESULT WINAPI IDirectPlaySPImpl_SetSPData
864 ( LPDIRECTPLAYSP iface,
872 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
874 /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
875 TRACE( "(%p)->(%p,0x%08x,0x%08x)\n",
876 This, lpData, dwDataSize, dwFlags );
879 /* This is what the documentation says... */
880 if( dwFlags != DPSET_REMOTE )
882 return DPERR_INVALIDPARAMS;
885 /* ... but most service providers call this with 1 */
886 /* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
889 if( dwFlags != DPSET_REMOTE )
891 TRACE( "Undocumented dwFlags 0x%08x used\n", dwFlags );
895 lpSpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
896 CopyMemory( lpSpData, lpData, dwDataSize );
898 /* If we have data already allocated, free it and replace it */
899 if( dwFlags == DPSET_REMOTE )
901 HeapFree( GetProcessHeap(), 0, This->sp->lpSpRemoteData );
902 This->sp->dwSpRemoteDataSize = dwDataSize;
903 This->sp->lpSpRemoteData = lpSpData;
905 else if ( dwFlags == DPSET_LOCAL )
907 HeapFree( GetProcessHeap(), 0, This->sp->lpSpLocalData );
908 This->sp->lpSpLocalData = lpSpData;
909 This->sp->dwSpLocalDataSize = dwDataSize;
915 static VOID WINAPI IDirectPlaySPImpl_SendComplete
916 ( LPDIRECTPLAYSP iface,
921 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
923 FIXME( "(%p)->(%p,0x%08x): stub\n",
924 This, unknownA, unknownB );
927 static const IDirectPlaySPVtbl directPlaySPVT =
934 IDirectPlaySPImpl_AddMRUEntry,
935 IDirectPlaySPImpl_CreateAddress,
936 IDirectPlaySPImpl_EnumAddress,
937 IDirectPlaySPImpl_EnumMRUEntries,
938 IDirectPlaySPImpl_GetPlayerFlags,
939 IDirectPlaySPImpl_GetSPPlayerData,
940 IDirectPlaySPImpl_HandleMessage,
941 IDirectPlaySPImpl_SetSPPlayerData,
942 IDirectPlaySPImpl_CreateCompoundAddress,
943 IDirectPlaySPImpl_GetSPData,
944 IDirectPlaySPImpl_SetSPData,
945 IDirectPlaySPImpl_SendComplete
949 /* DP external interfaces to call into DPSP interface */
951 /* Allocate the structure */
952 extern LPVOID DPSP_CreateSPPlayerData(void)
954 TRACE( "Creating SPPlayer data struct\n" );
955 return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
956 sizeof( DP_SPPLAYERDATA ) );