1 /* This contains the implementation of the interface Service
2 * Providers require to communicate with Direct Play
4 * Copyright 2000 Peter Hunnisett <hunnise@nortelnetworks.com>
9 #include "debugtools.h"
13 #include "dplay_global.h"
14 #include "name_server.h"
15 #include "dplayx_messages.h"
17 #include "dplayx_global.h" /* FIXME: For global hack */
19 /* FIXME: Need to add interface locking inside procedures */
21 DEFAULT_DEBUG_CHANNEL(dplay)
24 static BOOL DPSP_CreateIUnknown( LPVOID lpSP );
25 static BOOL DPSP_DestroyIUnknown( LPVOID lpSP );
26 static BOOL DPSP_CreateDirectPlaySP( LPVOID lpSP, IDirectPlay2Impl* dp );
27 static BOOL DPSP_DestroyDirectPlaySP( LPVOID lpSP );
29 /* Predefine the interface */
30 typedef struct IDirectPlaySPImpl IDirectPlaySPImpl;
32 typedef struct tagDirectPlaySPIUnknownData
35 CRITICAL_SECTION DPSP_lock;
36 } DirectPlaySPIUnknownData;
38 typedef struct tagDirectPlaySPData
40 LPVOID lpSpRemoteData;
41 DWORD dwSpRemoteDataSize; /* Size of data pointed to by lpSpRemoteData */
44 DWORD dwSpLocalDataSize; /* Size of data pointed to by lpSpLocalData */
46 IDirectPlay2Impl* dplay; /* FIXME: This should perhaps be iface not impl */
50 #define DPSP_IMPL_FIELDS \
51 ULONG ulInterfaceRef; \
52 DirectPlaySPIUnknownData* unk; \
55 struct IDirectPlaySPImpl
57 ICOM_VFIELD(IDirectPlaySP);
61 /* Forward declaration of virtual tables */
62 static ICOM_VTABLE(IDirectPlaySP) directPlaySPVT;
64 /* This structure is passed to the DP object for safe keeping */
65 typedef struct tagDP_SPPLAYERDATA
67 LPVOID lpPlayerLocalData;
68 DWORD dwPlayerLocalDataSize;
70 LPVOID lpPlayerRemoteData;
71 DWORD dwPlayerRemoteDataSize;
72 } DP_SPPLAYERDATA, *LPDP_SPPLAYERDATA;
74 /* Create the SP interface */
76 HRESULT DPSP_CreateInterface( REFIID riid, LPVOID* ppvObj, IDirectPlay2Impl* dp )
78 TRACE( " for %s\n", debugstr_guid( riid ) );
80 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
81 sizeof( IDirectPlaySPImpl ) );
85 return DPERR_OUTOFMEMORY;
88 if( IsEqualGUID( &IID_IDirectPlaySP, riid ) )
90 ICOM_THIS(IDirectPlaySPImpl,*ppvObj);
91 ICOM_VTBL(This) = &directPlaySPVT;
95 /* Unsupported interface */
96 HeapFree( GetProcessHeap(), 0, *ppvObj );
103 if( DPSP_CreateIUnknown( *ppvObj ) &&
104 DPSP_CreateDirectPlaySP( *ppvObj, dp )
107 IDirectPlaySP_AddRef( (LPDIRECTPLAYSP)*ppvObj );
111 /* Initialize failed, destroy it */
112 DPSP_DestroyDirectPlaySP( *ppvObj );
113 DPSP_DestroyIUnknown( *ppvObj );
115 HeapFree( GetProcessHeap(), 0, *ppvObj );
118 return DPERR_NOMEMORY;
121 static BOOL DPSP_CreateIUnknown( LPVOID lpSP )
123 ICOM_THIS(IDirectPlaySPImpl,lpSP);
125 This->unk = (DirectPlaySPIUnknownData*)HeapAlloc( GetProcessHeap(),
127 sizeof( *(This->unk) ) );
129 if ( This->unk == NULL )
134 InitializeCriticalSection( &This->unk->DPSP_lock );
139 static BOOL DPSP_DestroyIUnknown( LPVOID lpSP )
141 ICOM_THIS(IDirectPlaySPImpl,lpSP);
143 DeleteCriticalSection( &This->unk->DPSP_lock );
144 HeapFree( GetProcessHeap(), 0, This->unk );
150 static BOOL DPSP_CreateDirectPlaySP( LPVOID lpSP, IDirectPlay2Impl* dp )
152 ICOM_THIS(IDirectPlaySPImpl,lpSP);
154 This->sp = (DirectPlaySPData*)HeapAlloc( GetProcessHeap(),
156 sizeof( *(This->sp) ) );
158 if ( This->sp == NULL )
163 This->sp->dplay = dp;
165 /* Normally we should be keeping a reference, but since only the dplay
166 * interface that created us can destroy us, we do not keep a reference
167 * to it (ie we'd be stuck with always having one reference to the dplay
168 * object, and hence us, around).
169 * NOTE: The dp object does reference count us.
171 /* IDirectPlayX_AddRef( (LPDIRECTPLAY2)dp ); */
173 /* FIXME: This is a kludge to get around a problem where a queryinterface
174 * is used to get a new interface and then is closed. We will then
175 * reference garbage. However, with this we will never deallocate
176 * the interface we store. The correct fix is to require all
177 * DP internal interfaces to use the This->dp2 interface which
178 * should be changed to This->dp
180 IDirectPlayX_AddRef( (LPDIRECTPLAY2)dp );
185 static BOOL DPSP_DestroyDirectPlaySP( LPVOID lpSP )
187 ICOM_THIS(IDirectPlaySPImpl,lpSP);
189 /* Normally we should be keeping a reference, but since only the dplay
190 * interface that created us can destroy us, we do not keep a reference
191 * to it (ie we'd be stuck with always having one reference to the dplay
192 * object, and hence us, around).
193 * NOTE: The dp object does reference count us.
195 /*IDirectPlayX_Release( (LPDIRECTPLAY2)This->sp->dplay ); */
197 HeapFree( GetProcessHeap(), 0, This->sp->lpSpRemoteData );
198 HeapFree( GetProcessHeap(), 0, This->sp->lpSpLocalData );
200 /* FIXME: Need to delete player queue */
202 HeapFree( GetProcessHeap(), 0, This->sp );
206 /* Interface implementation */
208 static HRESULT WINAPI DPSP_QueryInterface
209 ( LPDIRECTPLAYSP iface,
213 ICOM_THIS(IDirectPlaySPImpl,iface);
214 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
216 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
219 if( *ppvObj == NULL )
221 return DPERR_OUTOFMEMORY;
224 CopyMemory( *ppvObj, This, sizeof( *This ) );
225 (*(IDirectPlaySPImpl**)ppvObj)->ulInterfaceRef = 0;
227 if( IsEqualGUID( &IID_IDirectPlaySP, riid ) )
229 ICOM_THIS(IDirectPlaySPImpl,*ppvObj);
230 ICOM_VTBL(This) = &directPlaySPVT;
234 /* Unsupported interface */
235 HeapFree( GetProcessHeap(), 0, *ppvObj );
238 return E_NOINTERFACE;
241 IDirectPlaySP_AddRef( (LPDIRECTPLAYSP)*ppvObj );
246 static ULONG WINAPI DPSP_AddRef
247 ( LPDIRECTPLAYSP iface )
249 ULONG ulInterfaceRefCount, ulObjRefCount;
250 ICOM_THIS(IDirectPlaySPImpl,iface);
252 ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
253 ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
255 TRACE( "ref count incremented to %lu:%lu for %p\n",
256 ulInterfaceRefCount, ulObjRefCount, This );
258 return ulObjRefCount;
261 static ULONG WINAPI DPSP_Release
262 ( LPDIRECTPLAYSP iface )
264 ULONG ulInterfaceRefCount, ulObjRefCount;
265 ICOM_THIS(IDirectPlaySPImpl,iface);
267 ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
268 ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
270 TRACE( "ref count decremented to %lu:%lu for %p\n",
271 ulInterfaceRefCount, ulObjRefCount, This );
273 /* Deallocate if this is the last reference to the object */
274 if( ulObjRefCount == 0 )
276 DPSP_DestroyDirectPlaySP( This );
277 DPSP_DestroyIUnknown( This );
280 if( ulInterfaceRefCount == 0 )
282 HeapFree( GetProcessHeap(), 0, This );
285 return ulInterfaceRefCount;
288 static HRESULT WINAPI IDirectPlaySPImpl_AddMRUEntry
289 ( LPDIRECTPLAYSP iface,
297 ICOM_THIS(IDirectPlaySPImpl,iface);
299 FIXME( "(%p)->(%p,%p%p,0x%08lx,0x%08lx): stub\n",
300 This, lpSection, lpKey, lpData, dwDataSize, dwMaxEntries );
305 static HRESULT WINAPI IDirectPlaySPImpl_CreateAddress
306 ( LPDIRECTPLAYSP iface,
308 REFGUID guidDataType,
312 LPDWORD lpdwAddressSize
315 ICOM_THIS(IDirectPlaySPImpl,iface);
317 FIXME( "(%p)->(%s,%s,%p,0x%08lx,%p,%p): stub\n",
318 This, debugstr_guid(guidSP), debugstr_guid(guidDataType),
319 lpData, dwDataSize, lpAddress, lpdwAddressSize );
324 static HRESULT WINAPI IDirectPlaySPImpl_EnumAddress
325 ( LPDIRECTPLAYSP iface,
326 LPDPENUMADDRESSCALLBACK lpEnumAddressCallback,
332 ICOM_THIS(IDirectPlaySPImpl,iface);
334 TRACE( "(%p)->(%p,%p,0x%08lx,%p)\n",
335 This, lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
337 DPL_EnumAddress( lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
342 static HRESULT WINAPI IDirectPlaySPImpl_EnumMRUEntries
343 ( LPDIRECTPLAYSP iface,
346 LPENUMMRUCALLBACK lpEnumMRUCallback,
350 ICOM_THIS(IDirectPlaySPImpl,iface);
352 FIXME( "(%p)->(%p,%p,%p,%p,): stub\n",
353 This, lpSection, lpKey, lpEnumMRUCallback, lpContext );
358 static HRESULT WINAPI IDirectPlaySPImpl_GetPlayerFlags
359 ( LPDIRECTPLAYSP iface,
361 LPDWORD lpdwPlayerFlags
364 ICOM_THIS(IDirectPlaySPImpl,iface);
366 FIXME( "(%p)->(0x%08lx,%p): stub\n",
367 This, idPlayer, lpdwPlayerFlags );
372 static HRESULT WINAPI IDirectPlaySPImpl_GetSPPlayerData
373 ( LPDIRECTPLAYSP iface,
376 LPDWORD lpdwDataSize,
381 LPDP_SPPLAYERDATA lpPlayerData;
382 ICOM_THIS(IDirectPlaySPImpl,iface);
384 /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
385 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx)\n",
386 This, idPlayer, lplpData, lpdwDataSize, dwFlags );
388 hr = DP_GetSPPlayerData( This->sp->dplay, idPlayer, (LPVOID*)&lpPlayerData );
392 TRACE( "Couldn't get player data: %s\n", DPLAYX_HresultToString(hr) );
393 return DPERR_INVALIDPLAYER;
396 /* What to do in the case where there is nothing set yet? */
397 if( dwFlags == DPSET_LOCAL )
399 if( lpPlayerData->lpPlayerLocalData )
401 HeapFree( GetProcessHeap(), 0, lpPlayerData->lpPlayerLocalData );
404 *lplpData = lpPlayerData->lpPlayerLocalData;
405 *lpdwDataSize = lpPlayerData->dwPlayerLocalDataSize;
407 else if( dwFlags == DPSET_REMOTE )
409 if( lpPlayerData->lpPlayerRemoteData )
411 HeapFree( GetProcessHeap(), 0, lpPlayerData->lpPlayerRemoteData );
414 *lplpData = lpPlayerData->lpPlayerRemoteData;
415 *lpdwDataSize = lpPlayerData->dwPlayerRemoteDataSize;
418 if( *lplpData == NULL )
426 static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage
427 ( LPDIRECTPLAYSP iface,
428 LPVOID lpMessageBody,
429 DWORD dwMessageBodySize,
430 LPVOID lpMessageHeader
433 LPDPMSG_SENDENVELOPE lpMsg = (LPDPMSG_SENDENVELOPE)lpMessageBody;
434 HRESULT hr = DPERR_GENERIC;
438 ICOM_THIS(IDirectPlaySPImpl,iface);
440 /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
441 FIXME( "(%p)->(%p,0x%08lx,%p): mostly stub\n",
442 This, lpMessageBody, dwMessageBodySize, lpMessageHeader );
444 wCommandId = lpMsg->wCommandId;
445 wVersion = lpMsg->wVersion;
447 TRACE( "Incomming message has envelope of 0x%08lx, %u, %u\n",
448 lpMsg->dwMagic, wCommandId, wVersion );
450 if( lpMsg->dwMagic != DPMSGMAGIC_DPLAYMSG )
452 ERR( "Unknown magic 0x%08lx!\n", lpMsg->dwMagic );
455 switch( lpMsg->wCommandId )
457 /* Name server needs to handle this request */
458 /* FIXME: This should be done in direct play handler */
459 case DPMSGCMD_ENUMSESSIONSREQUEST:
463 data.lpSPMessageHeader = lpMessageHeader;
464 data.idNameServer = 0;
467 NS_ReplyToEnumSessionsRequest( lpMessageBody, &data, This->sp->dplay );
469 hr = (This->sp->dplay->dp2->spData.lpCB->Reply)( &data );
473 ERR( "Reply failed 0x%08lx\n", hr );
479 /* Name server needs to handle this request */
480 /* FIXME: This should be done in direct play handler */
481 case DPMSGCMD_ENUMSESSIONSREPLY:
483 NS_SetRemoteComputerAsNameServer( lpMessageHeader,
484 This->sp->dplay->dp2->spData.dwSPHeaderSize,
485 (LPDPMSG_ENUMSESSIONSREPLY)lpMessageBody,
486 This->sp->dplay->dp2->lpNameServerData );
488 /* No reply expected */
494 /* Pass everything else to Direct Play */
499 data.lpMessage = NULL;
500 data.dwMessageSize = 0;
502 /* Pass this message to the dplay interface to handle */
503 hr = DP_HandleMessage( This->sp->dplay, lpMessageBody, dwMessageBodySize,
504 lpMessageHeader, wCommandId, wVersion,
505 &data.lpMessage, &data.dwMessageSize );
507 /* Do we want a reply? */
508 if( data.lpMessage != NULL )
512 data.lpSPMessageHeader = lpMessageHeader;
513 data.idNameServer = 0;
516 hr = (This->sp->dplay->dp2->spData.lpCB->Reply)( &data );
520 ERR( "Reply failed %s\n", DPLAYX_HresultToString(hr) );
530 HANDLE hReceiveEvent = 0;
531 /* FIXME: Aquire some sort of interface lock */
532 /* FIXME: Need some sort of context for this callback. Need to determine
533 * how this is actually done with the SP
535 /* FIXME: Who needs to delete the message when done? */
536 switch( lpMsg->dwType )
538 case DPSYS_CREATEPLAYERORGROUP:
540 LPDPMSG_CREATEPLAYERORGROUP msg = (LPDPMSG_CREATEPLAYERORGROUP)lpMsg;
542 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
544 hr = DP_IF_CreatePlayer( This, lpMessageHeader, msg->dpId,
545 &msg->dpnName, 0, msg->lpData,
546 msg->dwDataSize, msg->dwFlags, ... );
548 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
550 /* Group in group situation? */
551 if( msg->dpIdParent == DPID_NOPARENT_GROUP )
553 hr = DP_IF_CreateGroup( This, lpMessageHeader, msg->dpId,
554 &msg->dpnName, 0, msg->lpData,
555 msg->dwDataSize, msg->dwFlags, ... );
557 else /* Group in Group */
559 hr = DP_IF_CreateGroupInGroup( This, lpMessageHeader, msg->dpIdParent,
560 &msg->dpnName, 0, msg->lpData,
561 msg->dwDataSize, msg->dwFlags, ... );
566 ERR( "Corrupt msg->dwPlayerType for DPSYS_CREATEPLAYERORGROUP\n" );
573 case DPSYS_DESTROYPLAYERORGROUP:
575 LPDPMSG_DESTROYPLAYERORGROUP msg = (LPDPMSG_DESTROYPLAYERORGROUP)lpMsg;
577 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
579 hr = DP_IF_DestroyPlayer( This, msg->dpId, ... );
581 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
583 hr = DP_IF_DestroyGroup( This, msg->dpId, ... );
587 ERR( "Corrupt msg->dwPlayerType for DPSYS_DESTROYPLAYERORGROUP\n" );
594 case DPSYS_ADDPLAYERTOGROUP:
596 LPDPMSG_ADDPLAYERTOGROUP msg = (LPDPMSG_ADDPLAYERTOGROUP)lpMsg;
598 hr = DP_IF_AddPlayerToGroup( This, msg->dpIdGroup, msg->dpIdPlayer, ... );
602 case DPSYS_DELETEPLAYERFROMGROUP:
604 LPDPMSG_DELETEPLAYERFROMGROUP msg = (LPDPMSG_DELETEPLAYERFROMGROUP)lpMsg;
606 hr = DP_IF_DeletePlayerFromGroup( This, msg->dpIdGroup, msg->dpIdPlayer,
612 case DPSYS_SESSIONLOST:
614 LPDPMSG_SESSIONLOST msg = (LPDPMSG_SESSIONLOST)lpMsg;
616 FIXME( "DPSYS_SESSIONLOST not handled\n" );
623 LPDPMSG_HOST msg = (LPDPMSG_HOST)lpMsg;
625 FIXME( "DPSYS_HOST not handled\n" );
630 case DPSYS_SETPLAYERORGROUPDATA:
632 LPDPMSG_SETPLAYERORGROUPDATA msg = (LPDPMSG_SETPLAYERORGROUPDATA)lpMsg;
634 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
636 hr = DP_IF_SetPlayerData( This, msg->dpId, msg->lpData, msg->dwDataSize, DPSET_REMOTE, ... );
638 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
640 hr = DP_IF_SetGroupData( This, msg->dpId, msg->lpData, msg->dwDataSize,
645 ERR( "Corrupt msg->dwPlayerType for LPDPMSG_SETPLAYERORGROUPDATA\n" );
652 case DPSYS_SETPLAYERORGROUPNAME:
654 LPDPMSG_SETPLAYERORGROUPNAME msg = (LPDPMSG_SETPLAYERORGROUPNAME)lpMsg;
656 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
658 hr = DP_IF_SetPlayerName( This, msg->dpId, msg->dpnName, ... );
660 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
662 hr = DP_IF_SetGroupName( This, msg->dpId, msg->dpnName, ... );
666 ERR( "Corrupt msg->dwPlayerType for LPDPMSG_SETPLAYERORGROUPDATA\n" );
673 case DPSYS_SETSESSIONDESC;
675 LPDPMSG_SETSESSIONDESC msg = (LPDPMSG_SETSESSIONDESC)lpMsg;
677 hr = DP_IF_SetSessionDesc( This, &msg->dpDesc );
682 case DPSYS_ADDGROUPTOGROUP:
684 LPDPMSG_ADDGROUPTOGROUP msg = (LPDPMSG_ADDGROUPTOGROUP)lpMsg;
686 hr = DP_IF_AddGroupToGroup( This, msg->dpIdParentGroup, msg->dpIdGroup,
692 case DPSYS_DELETEGROUPFROMGROUP:
694 LPDPMSG_DELETEGROUPFROMGROUP msg = (LPDPMSG_DELETEGROUPFROMGROUP)lpMsg;
696 hr = DP_IF_DeleteGroupFromGroup( This, msg->dpIdParentGroup,
697 msg->dpIdGroup, ... );
702 case DPSYS_SECUREMESSAGE:
704 LPDPMSG_SECUREMESSAGE msg = (LPDPMSG_SECUREMESSAGE)lpMsg;
706 FIXME( "DPSYS_SECUREMESSAGE not implemented\n" );
711 case DPSYS_STARTSESSION:
713 LPDPMSG_STARTSESSION msg = (LPDPMSG_STARTSESSION)lpMsg;
715 FIXME( "DPSYS_STARTSESSION not implemented\n" );
722 LPDPMSG_CHAT msg = (LPDPMSG_CHAT)lpMsg;
724 FIXME( "DPSYS_CHAT not implemeneted\n" );
729 case DPSYS_SETGROUPOWNER:
731 LPDPMSG_SETGROUPOWNER msg = (LPDPMSG_SETGROUPOWNER)lpMsg;
733 FIXME( "DPSYS_SETGROUPOWNER not implemented\n" );
738 case DPSYS_SENDCOMPLETE:
740 LPDPMSG_SENDCOMPLETE msg = (LPDPMSG_SENDCOMPLETE)lpMsg;
742 FIXME( "DPSYS_SENDCOMPLETE not implemented\n" );
749 /* NOTE: This should be a user defined type. There is nothing that we
750 * need to do with it except queue it.
752 TRACE( "Received user message type(?) 0x%08lx through SP.\n",
758 FIXME( "Queue message in the receive queue. Need some context data!\n" );
762 ERR( "Unable to perform action for msg type 0x%08lx\n", lpMsg->dwType );
764 /* If a receieve event was registered for this player, invoke it */
767 SetEvent( hReceiveEvent );
774 static HRESULT WINAPI IDirectPlaySPImpl_SetSPPlayerData
775 ( LPDIRECTPLAYSP iface,
783 LPDP_SPPLAYERDATA lpPlayerEntry;
786 ICOM_THIS(IDirectPlaySPImpl,iface);
788 /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
789 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx)\n",
790 This, idPlayer, lpData, dwDataSize, dwFlags );
792 hr = DP_GetSPPlayerData( This->sp->dplay, idPlayer, (LPVOID*)&lpPlayerEntry );
795 /* Player must not exist */
796 return DPERR_INVALIDPLAYER;
799 lpPlayerData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
800 CopyMemory( lpPlayerData, lpData, dwDataSize );
802 if( dwFlags == DPSET_LOCAL )
804 lpPlayerEntry->lpPlayerLocalData = lpPlayerData;
805 lpPlayerEntry->dwPlayerLocalDataSize = dwDataSize;
807 else if( dwFlags == DPSET_REMOTE )
809 lpPlayerEntry->lpPlayerRemoteData = lpPlayerData;
810 lpPlayerEntry->dwPlayerRemoteDataSize = dwDataSize;
813 hr = DP_SetSPPlayerData( This->sp->dplay, idPlayer, lpPlayerEntry );
818 static HRESULT WINAPI IDirectPlaySPImpl_CreateCompoundAddress
819 ( LPDIRECTPLAYSP iface,
820 LPCDPCOMPOUNDADDRESSELEMENT lpElements,
821 DWORD dwElementCount,
823 LPDWORD lpdwAddressSize
826 ICOM_THIS(IDirectPlaySPImpl,iface);
828 FIXME( "(%p)->(%p,0x%08lx,%p,%p): stub\n",
829 This, lpElements, dwElementCount, lpAddress, lpdwAddressSize );
834 static HRESULT WINAPI IDirectPlaySPImpl_GetSPData
835 ( LPDIRECTPLAYSP iface,
837 LPDWORD lpdwDataSize,
842 ICOM_THIS(IDirectPlaySPImpl,iface);
844 /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
845 TRACE( "(%p)->(%p,%p,0x%08lx)\n",
846 This, lplpData, lpdwDataSize, dwFlags );
849 /* This is what the documentation says... */
850 if( dwFlags != DPSET_REMOTE )
852 return DPERR_INVALIDPARAMS;
855 /* ... but most service providers call this with 1 */
856 /* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
859 if( dwFlags != DPSET_REMOTE )
861 FIXME( "Undocumented dwFlags 0x%08lx used\n", dwFlags );
865 /* FIXME: What to do in the case where this isn't initialized yet? */
867 /* Yes, we're supposed to return a pointer to the memory we have stored! */
868 if( dwFlags == DPSET_REMOTE )
870 *lpdwDataSize = This->sp->dwSpRemoteDataSize;
871 *lplpData = This->sp->lpSpRemoteData;
873 if( This->sp->lpSpRemoteData == NULL )
878 else if( dwFlags == DPSET_LOCAL )
880 *lpdwDataSize = This->sp->dwSpLocalDataSize;
881 *lplpData = This->sp->lpSpLocalData;
883 if( This->sp->lpSpLocalData == NULL )
892 static HRESULT WINAPI IDirectPlaySPImpl_SetSPData
893 ( LPDIRECTPLAYSP iface,
901 ICOM_THIS(IDirectPlaySPImpl,iface);
903 /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
904 TRACE( "(%p)->(%p,0x%08lx,0x%08lx)\n",
905 This, lpData, dwDataSize, dwFlags );
908 /* This is what the documentation says... */
909 if( dwFlags != DPSET_REMOTE )
911 return DPERR_INVALIDPARAMS;
914 /* ... but most service providers call this with 1 */
915 /* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
918 if( dwFlags != DPSET_REMOTE )
920 FIXME( "Undocumented dwFlags 0x%08lx used\n", dwFlags );
924 lpSpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
925 CopyMemory( lpSpData, lpData, dwDataSize );
927 /* If we have data already allocated, free it and replace it */
928 if( dwFlags == DPSET_REMOTE )
930 if( This->sp->lpSpRemoteData )
932 HeapFree( GetProcessHeap(), 0, This->sp->lpSpRemoteData );
935 This->sp->dwSpRemoteDataSize = dwDataSize;
936 This->sp->lpSpRemoteData = lpSpData;
938 else if ( dwFlags == DPSET_LOCAL )
940 if( This->sp->lpSpLocalData )
942 HeapFree( GetProcessHeap(), 0, This->sp->lpSpLocalData );
945 This->sp->lpSpLocalData = lpSpData;
946 This->sp->dwSpLocalDataSize = dwDataSize;
952 static VOID WINAPI IDirectPlaySPImpl_SendComplete
953 ( LPDIRECTPLAYSP iface,
958 ICOM_THIS(IDirectPlaySPImpl,iface);
960 FIXME( "(%p)->(%p,0x%08lx): stub\n",
961 This, unknownA, unknownB );
965 static struct ICOM_VTABLE(IDirectPlaySP) directPlaySPVT =
967 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
973 IDirectPlaySPImpl_AddMRUEntry,
974 IDirectPlaySPImpl_CreateAddress,
975 IDirectPlaySPImpl_EnumAddress,
976 IDirectPlaySPImpl_EnumMRUEntries,
977 IDirectPlaySPImpl_GetPlayerFlags,
978 IDirectPlaySPImpl_GetSPPlayerData,
979 IDirectPlaySPImpl_HandleMessage,
980 IDirectPlaySPImpl_SetSPPlayerData,
981 IDirectPlaySPImpl_CreateCompoundAddress,
982 IDirectPlaySPImpl_GetSPData,
983 IDirectPlaySPImpl_SetSPData,
984 IDirectPlaySPImpl_SendComplete
988 /* DP external interfaces to call into DPSP interface */
990 /* Allocate the structure */
991 extern LPVOID DPSP_CreateSPPlayerData(void)
993 TRACE( "Creating SPPlayer data struct\n" );
994 return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
995 sizeof( DP_SPPLAYERDATA ) );