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>
10 #include "debugtools.h"
14 #include "dplay_global.h"
15 #include "name_server.h"
16 #include "dplayx_messages.h"
18 #include "dplayx_global.h" /* FIXME: For global hack */
20 /* FIXME: Need to add interface locking inside procedures */
22 DEFAULT_DEBUG_CHANNEL(dplay
);
25 static BOOL
DPSP_CreateIUnknown( LPVOID lpSP
);
26 static BOOL
DPSP_DestroyIUnknown( LPVOID lpSP
);
27 static BOOL
DPSP_CreateDirectPlaySP( LPVOID lpSP
, IDirectPlay2Impl
* dp
);
28 static BOOL
DPSP_DestroyDirectPlaySP( LPVOID lpSP
);
30 /* Predefine the interface */
31 typedef struct IDirectPlaySPImpl IDirectPlaySPImpl
;
33 typedef struct tagDirectPlaySPIUnknownData
36 CRITICAL_SECTION DPSP_lock
;
37 } DirectPlaySPIUnknownData
;
39 typedef struct tagDirectPlaySPData
41 LPVOID lpSpRemoteData
;
42 DWORD dwSpRemoteDataSize
; /* Size of data pointed to by lpSpRemoteData */
45 DWORD dwSpLocalDataSize
; /* Size of data pointed to by lpSpLocalData */
47 IDirectPlay2Impl
* dplay
; /* FIXME: This should perhaps be iface not impl */
51 #define DPSP_IMPL_FIELDS \
52 ULONG ulInterfaceRef; \
53 DirectPlaySPIUnknownData* unk; \
56 struct IDirectPlaySPImpl
58 ICOM_VFIELD(IDirectPlaySP
);
62 /* Forward declaration of virtual tables */
63 static ICOM_VTABLE(IDirectPlaySP
) directPlaySPVT
;
65 /* This structure is passed to the DP object for safe keeping */
66 typedef struct tagDP_SPPLAYERDATA
68 LPVOID lpPlayerLocalData
;
69 DWORD dwPlayerLocalDataSize
;
71 LPVOID lpPlayerRemoteData
;
72 DWORD dwPlayerRemoteDataSize
;
73 } DP_SPPLAYERDATA
, *LPDP_SPPLAYERDATA
;
75 /* Create the SP interface */
77 HRESULT
DPSP_CreateInterface( REFIID riid
, LPVOID
* ppvObj
, IDirectPlay2Impl
* dp
)
79 TRACE( " for %s\n", debugstr_guid( riid
) );
81 *ppvObj
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
82 sizeof( IDirectPlaySPImpl
) );
86 return DPERR_OUTOFMEMORY
;
89 if( IsEqualGUID( &IID_IDirectPlaySP
, riid
) )
91 ICOM_THIS(IDirectPlaySPImpl
,*ppvObj
);
92 ICOM_VTBL(This
) = &directPlaySPVT
;
96 /* Unsupported interface */
97 HeapFree( GetProcessHeap(), 0, *ppvObj
);
100 return E_NOINTERFACE
;
104 if( DPSP_CreateIUnknown( *ppvObj
) &&
105 DPSP_CreateDirectPlaySP( *ppvObj
, dp
)
108 IDirectPlaySP_AddRef( (LPDIRECTPLAYSP
)*ppvObj
);
112 /* Initialize failed, destroy it */
113 DPSP_DestroyDirectPlaySP( *ppvObj
);
114 DPSP_DestroyIUnknown( *ppvObj
);
116 HeapFree( GetProcessHeap(), 0, *ppvObj
);
119 return DPERR_NOMEMORY
;
122 static BOOL
DPSP_CreateIUnknown( LPVOID lpSP
)
124 ICOM_THIS(IDirectPlaySPImpl
,lpSP
);
126 This
->unk
= (DirectPlaySPIUnknownData
*)HeapAlloc( GetProcessHeap(),
128 sizeof( *(This
->unk
) ) );
130 if ( This
->unk
== NULL
)
135 InitializeCriticalSection( &This
->unk
->DPSP_lock
);
140 static BOOL
DPSP_DestroyIUnknown( LPVOID lpSP
)
142 ICOM_THIS(IDirectPlaySPImpl
,lpSP
);
144 DeleteCriticalSection( &This
->unk
->DPSP_lock
);
145 HeapFree( GetProcessHeap(), 0, This
->unk
);
151 static BOOL
DPSP_CreateDirectPlaySP( LPVOID lpSP
, IDirectPlay2Impl
* dp
)
153 ICOM_THIS(IDirectPlaySPImpl
,lpSP
);
155 This
->sp
= (DirectPlaySPData
*)HeapAlloc( GetProcessHeap(),
157 sizeof( *(This
->sp
) ) );
159 if ( This
->sp
== NULL
)
164 This
->sp
->dplay
= dp
;
166 /* Normally we should be keeping a reference, but since only the dplay
167 * interface that created us can destroy us, we do not keep a reference
168 * to it (ie we'd be stuck with always having one reference to the dplay
169 * object, and hence us, around).
170 * NOTE: The dp object does reference count us.
172 * FIXME: This is a kludge to get around a problem where a queryinterface
173 * is used to get a new interface and then is closed. We will then
174 * reference garbage. However, with this we will never deallocate
175 * the interface we store. The correct fix is to require all
176 * DP internal interfaces to use the This->dp2 interface which
177 * should be changed to This->dp
179 IDirectPlayX_AddRef( (LPDIRECTPLAY2
)dp
);
184 static BOOL
DPSP_DestroyDirectPlaySP( LPVOID lpSP
)
186 ICOM_THIS(IDirectPlaySPImpl
,lpSP
);
188 /* Normally we should be keeping a reference, but since only the dplay
189 * interface that created us can destroy us, we do not keep a reference
190 * to it (ie we'd be stuck with always having one reference to the dplay
191 * object, and hence us, around).
192 * NOTE: The dp object does reference count us.
194 /*IDirectPlayX_Release( (LPDIRECTPLAY2)This->sp->dplay ); */
196 HeapFree( GetProcessHeap(), 0, This
->sp
->lpSpRemoteData
);
197 HeapFree( GetProcessHeap(), 0, This
->sp
->lpSpLocalData
);
199 /* FIXME: Need to delete player queue */
201 HeapFree( GetProcessHeap(), 0, This
->sp
);
205 /* Interface implementation */
207 static HRESULT WINAPI DPSP_QueryInterface
208 ( LPDIRECTPLAYSP iface
,
212 ICOM_THIS(IDirectPlaySPImpl
,iface
);
213 TRACE("(%p)->(%s,%p)\n", This
, debugstr_guid( riid
), ppvObj
);
215 *ppvObj
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
218 if( *ppvObj
== NULL
)
220 return DPERR_OUTOFMEMORY
;
223 CopyMemory( *ppvObj
, This
, sizeof( *This
) );
224 (*(IDirectPlaySPImpl
**)ppvObj
)->ulInterfaceRef
= 0;
226 if( IsEqualGUID( &IID_IDirectPlaySP
, riid
) )
228 ICOM_THIS(IDirectPlaySPImpl
,*ppvObj
);
229 ICOM_VTBL(This
) = &directPlaySPVT
;
233 /* Unsupported interface */
234 HeapFree( GetProcessHeap(), 0, *ppvObj
);
237 return E_NOINTERFACE
;
240 IDirectPlaySP_AddRef( (LPDIRECTPLAYSP
)*ppvObj
);
245 static ULONG WINAPI DPSP_AddRef
246 ( LPDIRECTPLAYSP iface
)
248 ULONG ulInterfaceRefCount
, ulObjRefCount
;
249 ICOM_THIS(IDirectPlaySPImpl
,iface
);
251 ulObjRefCount
= InterlockedIncrement( &This
->unk
->ulObjRef
);
252 ulInterfaceRefCount
= InterlockedIncrement( &This
->ulInterfaceRef
);
254 TRACE( "ref count incremented to %lu:%lu for %p\n",
255 ulInterfaceRefCount
, ulObjRefCount
, This
);
257 return ulObjRefCount
;
260 static ULONG WINAPI DPSP_Release
261 ( LPDIRECTPLAYSP iface
)
263 ULONG ulInterfaceRefCount
, ulObjRefCount
;
264 ICOM_THIS(IDirectPlaySPImpl
,iface
);
266 ulObjRefCount
= InterlockedDecrement( &This
->unk
->ulObjRef
);
267 ulInterfaceRefCount
= InterlockedDecrement( &This
->ulInterfaceRef
);
269 TRACE( "ref count decremented to %lu:%lu for %p\n",
270 ulInterfaceRefCount
, ulObjRefCount
, This
);
272 /* Deallocate if this is the last reference to the object */
273 if( ulObjRefCount
== 0 )
275 DPSP_DestroyDirectPlaySP( This
);
276 DPSP_DestroyIUnknown( This
);
279 if( ulInterfaceRefCount
== 0 )
281 HeapFree( GetProcessHeap(), 0, This
);
284 return ulInterfaceRefCount
;
287 static HRESULT WINAPI IDirectPlaySPImpl_AddMRUEntry
288 ( LPDIRECTPLAYSP iface
,
296 ICOM_THIS(IDirectPlaySPImpl
,iface
);
298 /* Should be able to call the comctl32 undocumented MRU routines.
299 I suspect that the interface works appropriately */
300 FIXME( "(%p)->(%p,%p%p,0x%08lx,0x%08lx): stub\n",
301 This
, lpSection
, lpKey
, lpData
, dwDataSize
, dwMaxEntries
);
306 static HRESULT WINAPI IDirectPlaySPImpl_CreateAddress
307 ( LPDIRECTPLAYSP iface
,
309 REFGUID guidDataType
,
313 LPDWORD lpdwAddressSize
316 ICOM_THIS(IDirectPlaySPImpl
,iface
);
318 FIXME( "(%p)->(%s,%s,%p,0x%08lx,%p,%p): stub\n",
319 This
, debugstr_guid(guidSP
), debugstr_guid(guidDataType
),
320 lpData
, dwDataSize
, lpAddress
, lpdwAddressSize
);
325 static HRESULT WINAPI IDirectPlaySPImpl_EnumAddress
326 ( LPDIRECTPLAYSP iface
,
327 LPDPENUMADDRESSCALLBACK lpEnumAddressCallback
,
333 ICOM_THIS(IDirectPlaySPImpl
,iface
);
335 TRACE( "(%p)->(%p,%p,0x%08lx,%p)\n",
336 This
, lpEnumAddressCallback
, lpAddress
, dwAddressSize
, lpContext
);
338 DPL_EnumAddress( lpEnumAddressCallback
, lpAddress
, dwAddressSize
, lpContext
);
343 static HRESULT WINAPI IDirectPlaySPImpl_EnumMRUEntries
344 ( LPDIRECTPLAYSP iface
,
347 LPENUMMRUCALLBACK lpEnumMRUCallback
,
351 ICOM_THIS(IDirectPlaySPImpl
,iface
);
353 /* Should be able to call the comctl32 undocumented MRU routines.
354 I suspect that the interface works appropriately */
355 FIXME( "(%p)->(%p,%p,%p,%p,): stub\n",
356 This
, lpSection
, lpKey
, lpEnumMRUCallback
, lpContext
);
361 static HRESULT WINAPI IDirectPlaySPImpl_GetPlayerFlags
362 ( LPDIRECTPLAYSP iface
,
364 LPDWORD lpdwPlayerFlags
367 ICOM_THIS(IDirectPlaySPImpl
,iface
);
369 FIXME( "(%p)->(0x%08lx,%p): stub\n",
370 This
, idPlayer
, lpdwPlayerFlags
);
375 static HRESULT WINAPI IDirectPlaySPImpl_GetSPPlayerData
376 ( LPDIRECTPLAYSP iface
,
379 LPDWORD lpdwDataSize
,
384 LPDP_SPPLAYERDATA lpPlayerData
;
385 ICOM_THIS(IDirectPlaySPImpl
,iface
);
387 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx)\n",
388 This
, idPlayer
, lplpData
, lpdwDataSize
, dwFlags
);
390 hr
= DP_GetSPPlayerData( This
->sp
->dplay
, idPlayer
, (LPVOID
*)&lpPlayerData
);
394 TRACE( "Couldn't get player data: %s\n", DPLAYX_HresultToString(hr
) );
395 return DPERR_INVALIDPLAYER
;
398 /* What to do in the case where there is nothing set yet? */
399 if( dwFlags
== DPSET_LOCAL
)
401 if( lpPlayerData
->lpPlayerLocalData
)
403 HeapFree( GetProcessHeap(), 0, lpPlayerData
->lpPlayerLocalData
);
406 *lplpData
= lpPlayerData
->lpPlayerLocalData
;
407 *lpdwDataSize
= lpPlayerData
->dwPlayerLocalDataSize
;
409 else if( dwFlags
== DPSET_REMOTE
)
411 if( lpPlayerData
->lpPlayerRemoteData
)
413 HeapFree( GetProcessHeap(), 0, lpPlayerData
->lpPlayerRemoteData
);
416 *lplpData
= lpPlayerData
->lpPlayerRemoteData
;
417 *lpdwDataSize
= lpPlayerData
->dwPlayerRemoteDataSize
;
420 if( *lplpData
== NULL
)
428 static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage
429 ( LPDIRECTPLAYSP iface
,
430 LPVOID lpMessageBody
,
431 DWORD dwMessageBodySize
,
432 LPVOID lpMessageHeader
435 LPDPMSG_SENDENVELOPE lpMsg
= (LPDPMSG_SENDENVELOPE
)lpMessageBody
;
436 HRESULT hr
= DPERR_GENERIC
;
441 ICOM_THIS(IDirectPlaySPImpl
,iface
);
443 FIXME( "(%p)->(%p,0x%08lx,%p): mostly stub\n",
444 This
, lpMessageBody
, dwMessageBodySize
, lpMessageHeader
);
446 wCommandId
= lpMsg
->wCommandId
;
447 wVersion
= lpMsg
->wVersion
;
449 TRACE( "Incomming message has envelope of 0x%08lx, %u, %u\n",
450 lpMsg
->dwMagic
, wCommandId
, wVersion
);
452 if( lpMsg
->dwMagic
!= DPMSGMAGIC_DPLAYMSG
)
454 ERR( "Unknown magic 0x%08lx!\n", lpMsg
->dwMagic
);
455 return DPERR_GENERIC
;
460 const LPDWORD lpcHeader
= (LPDWORD
)lpMessageHeader
;
462 TRACE( "lpMessageHeader = [0x%08lx] [0x%08lx] [0x%08lx] [0x%08lx] [0x%08lx]\n",
463 lpcHeader
[0], lpcHeader
[1], lpcHeader
[2], lpcHeader
[3], lpcHeader
[4] );
467 /* Pass everything else to Direct Play */
468 data
.lpMessage
= NULL
;
469 data
.dwMessageSize
= 0;
471 /* Pass this message to the dplay interface to handle */
472 hr
= DP_HandleMessage( This
->sp
->dplay
, lpMessageBody
, dwMessageBodySize
,
473 lpMessageHeader
, wCommandId
, wVersion
,
474 &data
.lpMessage
, &data
.dwMessageSize
);
478 ERR( "Command processing failed %s\n", DPLAYX_HresultToString(hr
) );
481 /* Do we want a reply? */
482 if( data
.lpMessage
!= NULL
)
484 data
.lpSPMessageHeader
= lpMessageHeader
;
485 data
.idNameServer
= 0;
488 hr
= (This
->sp
->dplay
->dp2
->spData
.lpCB
->Reply
)( &data
);
492 ERR( "Reply failed %s\n", DPLAYX_HresultToString(hr
) );
500 HANDLE hReceiveEvent
= 0;
501 /* FIXME: Aquire some sort of interface lock */
502 /* FIXME: Need some sort of context for this callback. Need to determine
503 * how this is actually done with the SP
505 /* FIXME: Who needs to delete the message when done? */
506 switch( lpMsg
->dwType
)
508 case DPSYS_CREATEPLAYERORGROUP
:
510 LPDPMSG_CREATEPLAYERORGROUP msg
= (LPDPMSG_CREATEPLAYERORGROUP
)lpMsg
;
512 if( msg
->dwPlayerType
== DPPLAYERTYPE_PLAYER
)
514 hr
= DP_IF_CreatePlayer( This
, lpMessageHeader
, msg
->dpId
,
515 &msg
->dpnName
, 0, msg
->lpData
,
516 msg
->dwDataSize
, msg
->dwFlags
, ... );
518 else if( msg
->dwPlayerType
== DPPLAYERTYPE_GROUP
)
520 /* Group in group situation? */
521 if( msg
->dpIdParent
== DPID_NOPARENT_GROUP
)
523 hr
= DP_IF_CreateGroup( This
, lpMessageHeader
, msg
->dpId
,
524 &msg
->dpnName
, 0, msg
->lpData
,
525 msg
->dwDataSize
, msg
->dwFlags
, ... );
527 else /* Group in Group */
529 hr
= DP_IF_CreateGroupInGroup( This
, lpMessageHeader
, msg
->dpIdParent
,
530 &msg
->dpnName
, 0, msg
->lpData
,
531 msg
->dwDataSize
, msg
->dwFlags
, ... );
536 ERR( "Corrupt msg->dwPlayerType for DPSYS_CREATEPLAYERORGROUP\n" );
543 case DPSYS_DESTROYPLAYERORGROUP
:
545 LPDPMSG_DESTROYPLAYERORGROUP msg
= (LPDPMSG_DESTROYPLAYERORGROUP
)lpMsg
;
547 if( msg
->dwPlayerType
== DPPLAYERTYPE_PLAYER
)
549 hr
= DP_IF_DestroyPlayer( This
, msg
->dpId
, ... );
551 else if( msg
->dwPlayerType
== DPPLAYERTYPE_GROUP
)
553 hr
= DP_IF_DestroyGroup( This
, msg
->dpId
, ... );
557 ERR( "Corrupt msg->dwPlayerType for DPSYS_DESTROYPLAYERORGROUP\n" );
564 case DPSYS_ADDPLAYERTOGROUP
:
566 LPDPMSG_ADDPLAYERTOGROUP msg
= (LPDPMSG_ADDPLAYERTOGROUP
)lpMsg
;
568 hr
= DP_IF_AddPlayerToGroup( This
, msg
->dpIdGroup
, msg
->dpIdPlayer
, ... );
572 case DPSYS_DELETEPLAYERFROMGROUP
:
574 LPDPMSG_DELETEPLAYERFROMGROUP msg
= (LPDPMSG_DELETEPLAYERFROMGROUP
)lpMsg
;
576 hr
= DP_IF_DeletePlayerFromGroup( This
, msg
->dpIdGroup
, msg
->dpIdPlayer
,
582 case DPSYS_SESSIONLOST
:
584 LPDPMSG_SESSIONLOST msg
= (LPDPMSG_SESSIONLOST
)lpMsg
;
586 FIXME( "DPSYS_SESSIONLOST not handled\n" );
593 LPDPMSG_HOST msg
= (LPDPMSG_HOST
)lpMsg
;
595 FIXME( "DPSYS_HOST not handled\n" );
600 case DPSYS_SETPLAYERORGROUPDATA
:
602 LPDPMSG_SETPLAYERORGROUPDATA msg
= (LPDPMSG_SETPLAYERORGROUPDATA
)lpMsg
;
604 if( msg
->dwPlayerType
== DPPLAYERTYPE_PLAYER
)
606 hr
= DP_IF_SetPlayerData( This
, msg
->dpId
, msg
->lpData
, msg
->dwDataSize
, DPSET_REMOTE
, ... );
608 else if( msg
->dwPlayerType
== DPPLAYERTYPE_GROUP
)
610 hr
= DP_IF_SetGroupData( This
, msg
->dpId
, msg
->lpData
, msg
->dwDataSize
,
615 ERR( "Corrupt msg->dwPlayerType for LPDPMSG_SETPLAYERORGROUPDATA\n" );
622 case DPSYS_SETPLAYERORGROUPNAME
:
624 LPDPMSG_SETPLAYERORGROUPNAME msg
= (LPDPMSG_SETPLAYERORGROUPNAME
)lpMsg
;
626 if( msg
->dwPlayerType
== DPPLAYERTYPE_PLAYER
)
628 hr
= DP_IF_SetPlayerName( This
, msg
->dpId
, msg
->dpnName
, ... );
630 else if( msg
->dwPlayerType
== DPPLAYERTYPE_GROUP
)
632 hr
= DP_IF_SetGroupName( This
, msg
->dpId
, msg
->dpnName
, ... );
636 ERR( "Corrupt msg->dwPlayerType for LPDPMSG_SETPLAYERORGROUPDATA\n" );
643 case DPSYS_SETSESSIONDESC
;
645 LPDPMSG_SETSESSIONDESC msg
= (LPDPMSG_SETSESSIONDESC
)lpMsg
;
647 hr
= DP_IF_SetSessionDesc( This
, &msg
->dpDesc
);
652 case DPSYS_ADDGROUPTOGROUP
:
654 LPDPMSG_ADDGROUPTOGROUP msg
= (LPDPMSG_ADDGROUPTOGROUP
)lpMsg
;
656 hr
= DP_IF_AddGroupToGroup( This
, msg
->dpIdParentGroup
, msg
->dpIdGroup
,
662 case DPSYS_DELETEGROUPFROMGROUP
:
664 LPDPMSG_DELETEGROUPFROMGROUP msg
= (LPDPMSG_DELETEGROUPFROMGROUP
)lpMsg
;
666 hr
= DP_IF_DeleteGroupFromGroup( This
, msg
->dpIdParentGroup
,
667 msg
->dpIdGroup
, ... );
672 case DPSYS_SECUREMESSAGE
:
674 LPDPMSG_SECUREMESSAGE msg
= (LPDPMSG_SECUREMESSAGE
)lpMsg
;
676 FIXME( "DPSYS_SECUREMESSAGE not implemented\n" );
681 case DPSYS_STARTSESSION
:
683 LPDPMSG_STARTSESSION msg
= (LPDPMSG_STARTSESSION
)lpMsg
;
685 FIXME( "DPSYS_STARTSESSION not implemented\n" );
692 LPDPMSG_CHAT msg
= (LPDPMSG_CHAT
)lpMsg
;
694 FIXME( "DPSYS_CHAT not implemeneted\n" );
699 case DPSYS_SETGROUPOWNER
:
701 LPDPMSG_SETGROUPOWNER msg
= (LPDPMSG_SETGROUPOWNER
)lpMsg
;
703 FIXME( "DPSYS_SETGROUPOWNER not implemented\n" );
708 case DPSYS_SENDCOMPLETE
:
710 LPDPMSG_SENDCOMPLETE msg
= (LPDPMSG_SENDCOMPLETE
)lpMsg
;
712 FIXME( "DPSYS_SENDCOMPLETE not implemented\n" );
719 /* NOTE: This should be a user defined type. There is nothing that we
720 * need to do with it except queue it.
722 TRACE( "Received user message type(?) 0x%08lx through SP.\n",
728 FIXME( "Queue message in the receive queue. Need some context data!\n" );
732 ERR( "Unable to perform action for msg type 0x%08lx\n", lpMsg
->dwType
);
734 /* If a receieve event was registered for this player, invoke it */
737 SetEvent( hReceiveEvent
);
742 static HRESULT WINAPI IDirectPlaySPImpl_SetSPPlayerData
743 ( LPDIRECTPLAYSP iface
,
751 LPDP_SPPLAYERDATA lpPlayerEntry
;
754 ICOM_THIS(IDirectPlaySPImpl
,iface
);
756 /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
757 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx)\n",
758 This
, idPlayer
, lpData
, dwDataSize
, dwFlags
);
760 hr
= DP_GetSPPlayerData( This
->sp
->dplay
, idPlayer
, (LPVOID
*)&lpPlayerEntry
);
763 /* Player must not exist */
764 return DPERR_INVALIDPLAYER
;
767 lpPlayerData
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, dwDataSize
);
768 CopyMemory( lpPlayerData
, lpData
, dwDataSize
);
770 if( dwFlags
== DPSET_LOCAL
)
772 lpPlayerEntry
->lpPlayerLocalData
= lpPlayerData
;
773 lpPlayerEntry
->dwPlayerLocalDataSize
= dwDataSize
;
775 else if( dwFlags
== DPSET_REMOTE
)
777 lpPlayerEntry
->lpPlayerRemoteData
= lpPlayerData
;
778 lpPlayerEntry
->dwPlayerRemoteDataSize
= dwDataSize
;
781 hr
= DP_SetSPPlayerData( This
->sp
->dplay
, idPlayer
, lpPlayerEntry
);
786 static HRESULT WINAPI IDirectPlaySPImpl_CreateCompoundAddress
787 ( LPDIRECTPLAYSP iface
,
788 LPCDPCOMPOUNDADDRESSELEMENT lpElements
,
789 DWORD dwElementCount
,
791 LPDWORD lpdwAddressSize
794 ICOM_THIS(IDirectPlaySPImpl
,iface
);
796 FIXME( "(%p)->(%p,0x%08lx,%p,%p): stub\n",
797 This
, lpElements
, dwElementCount
, lpAddress
, lpdwAddressSize
);
802 static HRESULT WINAPI IDirectPlaySPImpl_GetSPData
803 ( LPDIRECTPLAYSP iface
,
805 LPDWORD lpdwDataSize
,
810 ICOM_THIS(IDirectPlaySPImpl
,iface
);
812 /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
813 TRACE( "(%p)->(%p,%p,0x%08lx)\n",
814 This
, lplpData
, lpdwDataSize
, dwFlags
);
817 /* This is what the documentation says... */
818 if( dwFlags
!= DPSET_REMOTE
)
820 return DPERR_INVALIDPARAMS
;
823 /* ... but most service providers call this with 1 */
824 /* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
827 if( dwFlags
!= DPSET_REMOTE
)
829 TRACE( "Undocumented dwFlags 0x%08lx used\n", dwFlags
);
833 /* FIXME: What to do in the case where this isn't initialized yet? */
835 /* Yes, we're supposed to return a pointer to the memory we have stored! */
836 if( dwFlags
== DPSET_REMOTE
)
838 *lpdwDataSize
= This
->sp
->dwSpRemoteDataSize
;
839 *lplpData
= This
->sp
->lpSpRemoteData
;
841 if( This
->sp
->lpSpRemoteData
== NULL
)
846 else if( dwFlags
== DPSET_LOCAL
)
848 *lpdwDataSize
= This
->sp
->dwSpLocalDataSize
;
849 *lplpData
= This
->sp
->lpSpLocalData
;
851 if( This
->sp
->lpSpLocalData
== NULL
)
860 static HRESULT WINAPI IDirectPlaySPImpl_SetSPData
861 ( LPDIRECTPLAYSP iface
,
869 ICOM_THIS(IDirectPlaySPImpl
,iface
);
871 /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
872 TRACE( "(%p)->(%p,0x%08lx,0x%08lx)\n",
873 This
, lpData
, dwDataSize
, dwFlags
);
876 /* This is what the documentation says... */
877 if( dwFlags
!= DPSET_REMOTE
)
879 return DPERR_INVALIDPARAMS
;
882 /* ... but most service providers call this with 1 */
883 /* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
886 if( dwFlags
!= DPSET_REMOTE
)
888 TRACE( "Undocumented dwFlags 0x%08lx used\n", dwFlags
);
892 lpSpData
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, dwDataSize
);
893 CopyMemory( lpSpData
, lpData
, dwDataSize
);
895 /* If we have data already allocated, free it and replace it */
896 if( dwFlags
== DPSET_REMOTE
)
898 if( This
->sp
->lpSpRemoteData
)
900 HeapFree( GetProcessHeap(), 0, This
->sp
->lpSpRemoteData
);
903 This
->sp
->dwSpRemoteDataSize
= dwDataSize
;
904 This
->sp
->lpSpRemoteData
= lpSpData
;
906 else if ( dwFlags
== DPSET_LOCAL
)
908 if( This
->sp
->lpSpLocalData
)
910 HeapFree( GetProcessHeap(), 0, This
->sp
->lpSpLocalData
);
913 This
->sp
->lpSpLocalData
= lpSpData
;
914 This
->sp
->dwSpLocalDataSize
= dwDataSize
;
920 static VOID WINAPI IDirectPlaySPImpl_SendComplete
921 ( LPDIRECTPLAYSP iface
,
926 ICOM_THIS(IDirectPlaySPImpl
,iface
);
928 FIXME( "(%p)->(%p,0x%08lx): stub\n",
929 This
, unknownA
, unknownB
);
933 static struct ICOM_VTABLE(IDirectPlaySP
) directPlaySPVT
=
935 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
941 IDirectPlaySPImpl_AddMRUEntry
,
942 IDirectPlaySPImpl_CreateAddress
,
943 IDirectPlaySPImpl_EnumAddress
,
944 IDirectPlaySPImpl_EnumMRUEntries
,
945 IDirectPlaySPImpl_GetPlayerFlags
,
946 IDirectPlaySPImpl_GetSPPlayerData
,
947 IDirectPlaySPImpl_HandleMessage
,
948 IDirectPlaySPImpl_SetSPPlayerData
,
949 IDirectPlaySPImpl_CreateCompoundAddress
,
950 IDirectPlaySPImpl_GetSPData
,
951 IDirectPlaySPImpl_SetSPData
,
952 IDirectPlaySPImpl_SendComplete
956 /* DP external interfaces to call into DPSP interface */
958 /* Allocate the structure */
959 extern LPVOID
DPSP_CreateSPPlayerData(void)
961 TRACE( "Creating SPPlayer data struct\n" );
962 return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
963 sizeof( DP_SPPLAYERDATA
) );