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
) );