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