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"
26 #include "wine/dplaysp.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 */
89 HRESULT
DPSP_CreateInterface( REFIID riid
, LPVOID
* ppvObj
, IDirectPlay2Impl
* dp
)
91 TRACE( " for %s\n", debugstr_guid( riid
) );
93 *ppvObj
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
94 sizeof( IDirectPlaySPImpl
) );
98 return DPERR_OUTOFMEMORY
;
101 if( IsEqualGUID( &IID_IDirectPlaySP
, riid
) )
103 IDirectPlaySPImpl
*This
= *ppvObj
;
104 This
->lpVtbl
= &directPlaySPVT
;
108 /* Unsupported interface */
109 HeapFree( GetProcessHeap(), 0, *ppvObj
);
112 return E_NOINTERFACE
;
116 if( DPSP_CreateIUnknown( *ppvObj
) &&
117 DPSP_CreateDirectPlaySP( *ppvObj
, dp
)
120 IDirectPlaySP_AddRef( (LPDIRECTPLAYSP
)*ppvObj
);
124 /* Initialize failed, destroy it */
125 DPSP_DestroyDirectPlaySP( *ppvObj
);
126 DPSP_DestroyIUnknown( *ppvObj
);
128 HeapFree( GetProcessHeap(), 0, *ppvObj
);
131 return DPERR_NOMEMORY
;
134 static BOOL
DPSP_CreateIUnknown( LPVOID lpSP
)
136 IDirectPlaySPImpl
*This
= lpSP
;
138 This
->unk
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *(This
->unk
) ) );
140 if ( This
->unk
== NULL
)
145 InitializeCriticalSection( &This
->unk
->DPSP_lock
);
146 This
->unk
->DPSP_lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": IDirectPlaySPImpl*->DirectPlaySPIUnknownData*->DPSP_lock");
151 static BOOL
DPSP_DestroyIUnknown( LPVOID lpSP
)
153 IDirectPlaySPImpl
*This
= lpSP
;
155 This
->unk
->DPSP_lock
.DebugInfo
->Spare
[0] = 0;
156 DeleteCriticalSection( &This
->unk
->DPSP_lock
);
157 HeapFree( GetProcessHeap(), 0, This
->unk
);
163 static BOOL
DPSP_CreateDirectPlaySP( LPVOID lpSP
, IDirectPlay2Impl
* dp
)
165 IDirectPlaySPImpl
*This
= lpSP
;
167 This
->sp
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *(This
->sp
) ) );
169 if ( This
->sp
== NULL
)
174 This
->sp
->dplay
= dp
;
176 /* Normally we should be keeping a reference, but since only the dplay
177 * interface that created us can destroy us, we do not keep a reference
178 * to it (ie we'd be stuck with always having one reference to the dplay
179 * object, and hence us, around).
180 * NOTE: The dp object does reference count us.
182 * FIXME: This is a kludge to get around a problem where a queryinterface
183 * is used to get a new interface and then is closed. We will then
184 * reference garbage. However, with this we will never deallocate
185 * the interface we store. The correct fix is to require all
186 * DP internal interfaces to use the This->dp2 interface which
187 * should be changed to This->dp
189 IDirectPlayX_AddRef( (LPDIRECTPLAY2
)dp
);
194 static BOOL
DPSP_DestroyDirectPlaySP( LPVOID lpSP
)
196 IDirectPlaySPImpl
*This
= lpSP
;
198 /* Normally we should be keeping a reference, but since only the dplay
199 * interface that created us can destroy us, we do not keep a reference
200 * to it (ie we'd be stuck with always having one reference to the dplay
201 * object, and hence us, around).
202 * NOTE: The dp object does reference count us.
204 /*IDirectPlayX_Release( (LPDIRECTPLAY2)This->sp->dplay ); */
206 HeapFree( GetProcessHeap(), 0, This
->sp
->lpSpRemoteData
);
207 HeapFree( GetProcessHeap(), 0, This
->sp
->lpSpLocalData
);
209 /* FIXME: Need to delete player queue */
211 HeapFree( GetProcessHeap(), 0, This
->sp
);
215 /* Interface implementation */
217 static HRESULT WINAPI DPSP_QueryInterface
218 ( LPDIRECTPLAYSP iface
,
222 IDirectPlaySPImpl
*This
= (IDirectPlaySPImpl
*)iface
;
223 TRACE("(%p)->(%s,%p)\n", This
, debugstr_guid( riid
), ppvObj
);
225 *ppvObj
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
228 if( *ppvObj
== NULL
)
230 return DPERR_OUTOFMEMORY
;
233 CopyMemory( *ppvObj
, This
, sizeof( *This
) );
234 (*(IDirectPlaySPImpl
**)ppvObj
)->ulInterfaceRef
= 0;
236 if( IsEqualGUID( &IID_IDirectPlaySP
, riid
) )
238 IDirectPlaySPImpl
*This
= *ppvObj
;
239 This
->lpVtbl
= &directPlaySPVT
;
243 /* Unsupported interface */
244 HeapFree( GetProcessHeap(), 0, *ppvObj
);
247 return E_NOINTERFACE
;
250 IDirectPlaySP_AddRef( (LPDIRECTPLAYSP
)*ppvObj
);
255 static ULONG WINAPI DPSP_AddRef
256 ( LPDIRECTPLAYSP iface
)
258 ULONG ulInterfaceRefCount
, ulObjRefCount
;
259 IDirectPlaySPImpl
*This
= (IDirectPlaySPImpl
*)iface
;
261 ulObjRefCount
= InterlockedIncrement( &This
->unk
->ulObjRef
);
262 ulInterfaceRefCount
= InterlockedIncrement( &This
->ulInterfaceRef
);
264 TRACE( "ref count incremented to %u:%u for %p\n",
265 ulInterfaceRefCount
, ulObjRefCount
, This
);
267 return ulObjRefCount
;
270 static ULONG WINAPI DPSP_Release
271 ( LPDIRECTPLAYSP iface
)
273 ULONG ulInterfaceRefCount
, ulObjRefCount
;
274 IDirectPlaySPImpl
*This
= (IDirectPlaySPImpl
*)iface
;
276 ulObjRefCount
= InterlockedDecrement( &This
->unk
->ulObjRef
);
277 ulInterfaceRefCount
= InterlockedDecrement( &This
->ulInterfaceRef
);
279 TRACE( "ref count decremented to %u:%u for %p\n",
280 ulInterfaceRefCount
, ulObjRefCount
, This
);
282 /* Deallocate if this is the last reference to the object */
283 if( ulObjRefCount
== 0 )
285 DPSP_DestroyDirectPlaySP( This
);
286 DPSP_DestroyIUnknown( This
);
289 if( ulInterfaceRefCount
== 0 )
291 HeapFree( GetProcessHeap(), 0, This
);
294 return ulInterfaceRefCount
;
297 static HRESULT WINAPI IDirectPlaySPImpl_AddMRUEntry
298 ( LPDIRECTPLAYSP iface
,
306 IDirectPlaySPImpl
*This
= (IDirectPlaySPImpl
*)iface
;
308 /* Should be able to call the comctl32 undocumented MRU routines.
309 I suspect that the interface works appropriately */
310 FIXME( "(%p)->(%p,%p%p,0x%08x,0x%08x): stub\n",
311 This
, lpSection
, lpKey
, lpData
, dwDataSize
, dwMaxEntries
);
316 static HRESULT WINAPI IDirectPlaySPImpl_CreateAddress
317 ( LPDIRECTPLAYSP iface
,
319 REFGUID guidDataType
,
323 LPDWORD lpdwAddressSize
326 IDirectPlaySPImpl
*This
= (IDirectPlaySPImpl
*)iface
;
328 FIXME( "(%p)->(%s,%s,%p,0x%08x,%p,%p): stub\n",
329 This
, debugstr_guid(guidSP
), debugstr_guid(guidDataType
),
330 lpData
, dwDataSize
, lpAddress
, lpdwAddressSize
);
335 static HRESULT WINAPI IDirectPlaySPImpl_EnumAddress
336 ( LPDIRECTPLAYSP iface
,
337 LPDPENUMADDRESSCALLBACK lpEnumAddressCallback
,
343 IDirectPlaySPImpl
*This
= (IDirectPlaySPImpl
*)iface
;
345 TRACE( "(%p)->(%p,%p,0x%08x,%p)\n",
346 This
, lpEnumAddressCallback
, lpAddress
, dwAddressSize
, lpContext
);
348 DPL_EnumAddress( lpEnumAddressCallback
, lpAddress
, dwAddressSize
, lpContext
);
353 static HRESULT WINAPI IDirectPlaySPImpl_EnumMRUEntries
354 ( LPDIRECTPLAYSP iface
,
357 LPENUMMRUCALLBACK lpEnumMRUCallback
,
361 IDirectPlaySPImpl
*This
= (IDirectPlaySPImpl
*)iface
;
363 /* Should be able to call the comctl32 undocumented MRU routines.
364 I suspect that the interface works appropriately */
365 FIXME( "(%p)->(%p,%p,%p,%p,): stub\n",
366 This
, lpSection
, lpKey
, lpEnumMRUCallback
, lpContext
);
371 static HRESULT WINAPI IDirectPlaySPImpl_GetPlayerFlags
372 ( LPDIRECTPLAYSP iface
,
374 LPDWORD lpdwPlayerFlags
377 IDirectPlaySPImpl
*This
= (IDirectPlaySPImpl
*)iface
;
379 FIXME( "(%p)->(0x%08x,%p): stub\n",
380 This
, idPlayer
, lpdwPlayerFlags
);
385 static HRESULT WINAPI IDirectPlaySPImpl_GetSPPlayerData
386 ( LPDIRECTPLAYSP iface
,
389 LPDWORD lpdwDataSize
,
394 LPDP_SPPLAYERDATA lpPlayerData
;
395 IDirectPlaySPImpl
*This
= (IDirectPlaySPImpl
*)iface
;
397 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x)\n",
398 This
, idPlayer
, lplpData
, lpdwDataSize
, dwFlags
);
400 hr
= DP_GetSPPlayerData( This
->sp
->dplay
, idPlayer
, (LPVOID
*)&lpPlayerData
);
404 TRACE( "Couldn't get player data: %s\n", DPLAYX_HresultToString(hr
) );
405 return DPERR_INVALIDPLAYER
;
408 /* What to do in the case where there is nothing set yet? */
409 if( dwFlags
== DPSET_LOCAL
)
411 HeapFree( GetProcessHeap(), 0, lpPlayerData
->lpPlayerLocalData
);
412 *lplpData
= lpPlayerData
->lpPlayerLocalData
;
413 *lpdwDataSize
= lpPlayerData
->dwPlayerLocalDataSize
;
415 else if( dwFlags
== DPSET_REMOTE
)
417 HeapFree( GetProcessHeap(), 0, lpPlayerData
->lpPlayerRemoteData
);
418 *lplpData
= lpPlayerData
->lpPlayerRemoteData
;
419 *lpdwDataSize
= lpPlayerData
->dwPlayerRemoteDataSize
;
422 if( *lplpData
== NULL
)
430 static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage
431 ( LPDIRECTPLAYSP iface
,
432 LPVOID lpMessageBody
,
433 DWORD dwMessageBodySize
,
434 LPVOID lpMessageHeader
437 LPDPMSG_SENDENVELOPE lpMsg
= lpMessageBody
;
438 HRESULT hr
= DPERR_GENERIC
;
443 IDirectPlaySPImpl
*This
= (IDirectPlaySPImpl
*)iface
;
445 FIXME( "(%p)->(%p,0x%08x,%p): mostly stub\n",
446 This
, lpMessageBody
, dwMessageBodySize
, lpMessageHeader
);
448 wCommandId
= lpMsg
->wCommandId
;
449 wVersion
= lpMsg
->wVersion
;
451 TRACE( "Incoming message has envelope of 0x%08x, %u, %u\n",
452 lpMsg
->dwMagic
, wCommandId
, wVersion
);
454 if( lpMsg
->dwMagic
!= DPMSGMAGIC_DPLAYMSG
)
456 ERR( "Unknown magic 0x%08x!\n", lpMsg
->dwMagic
);
457 return DPERR_GENERIC
;
462 const LPDWORD lpcHeader
= lpMessageHeader
;
464 TRACE( "lpMessageHeader = [0x%08lx] [0x%08lx] [0x%08lx] [0x%08lx] [0x%08lx]\n",
465 lpcHeader
[0], lpcHeader
[1], lpcHeader
[2], lpcHeader
[3], lpcHeader
[4] );
469 /* Pass everything else to Direct Play */
470 data
.lpMessage
= NULL
;
471 data
.dwMessageSize
= 0;
473 /* Pass this message to the dplay interface to handle */
474 hr
= DP_HandleMessage( This
->sp
->dplay
, lpMessageBody
, dwMessageBodySize
,
475 lpMessageHeader
, wCommandId
, wVersion
,
476 &data
.lpMessage
, &data
.dwMessageSize
);
480 ERR( "Command processing failed %s\n", DPLAYX_HresultToString(hr
) );
483 /* Do we want a reply? */
484 if( data
.lpMessage
!= NULL
)
486 data
.lpSPMessageHeader
= lpMessageHeader
;
487 data
.idNameServer
= 0;
490 hr
= (This
->sp
->dplay
->dp2
->spData
.lpCB
->Reply
)( &data
);
494 ERR( "Reply failed %s\n", DPLAYX_HresultToString(hr
) );
502 HANDLE hReceiveEvent
= 0;
503 /* FIXME: Acquire some sort of interface lock */
504 /* FIXME: Need some sort of context for this callback. Need to determine
505 * how this is actually done with the SP
507 /* FIXME: Who needs to delete the message when done? */
508 switch( lpMsg
->dwType
)
510 case DPSYS_CREATEPLAYERORGROUP
:
512 LPDPMSG_CREATEPLAYERORGROUP msg
= lpMsg
;
514 if( msg
->dwPlayerType
== DPPLAYERTYPE_PLAYER
)
516 hr
= DP_IF_CreatePlayer( This
, lpMessageHeader
, msg
->dpId
,
517 &msg
->dpnName
, 0, msg
->lpData
,
518 msg
->dwDataSize
, msg
->dwFlags
, ... );
520 else if( msg
->dwPlayerType
== DPPLAYERTYPE_GROUP
)
522 /* Group in group situation? */
523 if( msg
->dpIdParent
== DPID_NOPARENT_GROUP
)
525 hr
= DP_IF_CreateGroup( This
, lpMessageHeader
, msg
->dpId
,
526 &msg
->dpnName
, 0, msg
->lpData
,
527 msg
->dwDataSize
, msg
->dwFlags
, ... );
529 else /* Group in Group */
531 hr
= DP_IF_CreateGroupInGroup( This
, lpMessageHeader
, msg
->dpIdParent
,
532 &msg
->dpnName
, 0, msg
->lpData
,
533 msg
->dwDataSize
, msg
->dwFlags
, ... );
538 ERR( "Corrupt msg->dwPlayerType for DPSYS_CREATEPLAYERORGROUP\n" );
545 case DPSYS_DESTROYPLAYERORGROUP
:
547 LPDPMSG_DESTROYPLAYERORGROUP msg
= lpMsg
;
549 if( msg
->dwPlayerType
== DPPLAYERTYPE_PLAYER
)
551 hr
= DP_IF_DestroyPlayer( This
, msg
->dpId
, ... );
553 else if( msg
->dwPlayerType
== DPPLAYERTYPE_GROUP
)
555 hr
= DP_IF_DestroyGroup( This
, msg
->dpId
, ... );
559 ERR( "Corrupt msg->dwPlayerType for DPSYS_DESTROYPLAYERORGROUP\n" );
566 case DPSYS_ADDPLAYERTOGROUP
:
568 LPDPMSG_ADDPLAYERTOGROUP msg
= lpMsg
;
570 hr
= DP_IF_AddPlayerToGroup( This
, msg
->dpIdGroup
, msg
->dpIdPlayer
, ... );
574 case DPSYS_DELETEPLAYERFROMGROUP
:
576 LPDPMSG_DELETEPLAYERFROMGROUP msg
= lpMsg
;
578 hr
= DP_IF_DeletePlayerFromGroup( This
, msg
->dpIdGroup
, msg
->dpIdPlayer
,
584 case DPSYS_SESSIONLOST
:
586 LPDPMSG_SESSIONLOST msg
= lpMsg
;
588 FIXME( "DPSYS_SESSIONLOST not handled\n" );
595 LPDPMSG_HOST msg
= lpMsg
;
597 FIXME( "DPSYS_HOST not handled\n" );
602 case DPSYS_SETPLAYERORGROUPDATA
:
604 LPDPMSG_SETPLAYERORGROUPDATA msg
= lpMsg
;
606 if( msg
->dwPlayerType
== DPPLAYERTYPE_PLAYER
)
608 hr
= DP_IF_SetPlayerData( This
, msg
->dpId
, msg
->lpData
, msg
->dwDataSize
, DPSET_REMOTE
, ... );
610 else if( msg
->dwPlayerType
== DPPLAYERTYPE_GROUP
)
612 hr
= DP_IF_SetGroupData( This
, msg
->dpId
, msg
->lpData
, msg
->dwDataSize
,
617 ERR( "Corrupt msg->dwPlayerType for LPDPMSG_SETPLAYERORGROUPDATA\n" );
624 case DPSYS_SETPLAYERORGROUPNAME
:
626 LPDPMSG_SETPLAYERORGROUPNAME msg
= lpMsg
;
628 if( msg
->dwPlayerType
== DPPLAYERTYPE_PLAYER
)
630 hr
= DP_IF_SetPlayerName( This
, msg
->dpId
, msg
->dpnName
, ... );
632 else if( msg
->dwPlayerType
== DPPLAYERTYPE_GROUP
)
634 hr
= DP_IF_SetGroupName( This
, msg
->dpId
, msg
->dpnName
, ... );
638 ERR( "Corrupt msg->dwPlayerType for LPDPMSG_SETPLAYERORGROUPDATA\n" );
645 case DPSYS_SETSESSIONDESC
;
647 LPDPMSG_SETSESSIONDESC msg
= lpMsg
;
649 hr
= DP_IF_SetSessionDesc( This
, &msg
->dpDesc
);
654 case DPSYS_ADDGROUPTOGROUP
:
656 LPDPMSG_ADDGROUPTOGROUP msg
= lpMsg
;
658 hr
= DP_IF_AddGroupToGroup( This
, msg
->dpIdParentGroup
, msg
->dpIdGroup
,
664 case DPSYS_DELETEGROUPFROMGROUP
:
666 LPDPMSG_DELETEGROUPFROMGROUP msg
= lpMsg
;
668 hr
= DP_IF_DeleteGroupFromGroup( This
, msg
->dpIdParentGroup
,
669 msg
->dpIdGroup
, ... );
674 case DPSYS_SECUREMESSAGE
:
676 LPDPMSG_SECUREMESSAGE msg
= lpMsg
;
678 FIXME( "DPSYS_SECUREMESSAGE not implemented\n" );
683 case DPSYS_STARTSESSION
:
685 LPDPMSG_STARTSESSION msg
= lpMsg
;
687 FIXME( "DPSYS_STARTSESSION not implemented\n" );
694 LPDPMSG_CHAT msg
= lpMsg
;
696 FIXME( "DPSYS_CHAT not implemeneted\n" );
701 case DPSYS_SETGROUPOWNER
:
703 LPDPMSG_SETGROUPOWNER msg
= lpMsg
;
705 FIXME( "DPSYS_SETGROUPOWNER not implemented\n" );
710 case DPSYS_SENDCOMPLETE
:
712 LPDPMSG_SENDCOMPLETE msg
= lpMsg
;
714 FIXME( "DPSYS_SENDCOMPLETE not implemented\n" );
721 /* NOTE: This should be a user defined type. There is nothing that we
722 * need to do with it except queue it.
724 TRACE( "Received user message type(?) 0x%08lx through SP.\n",
730 FIXME( "Queue message in the receive queue. Need some context data!\n" );
734 ERR( "Unable to perform action for msg type 0x%08lx\n", lpMsg
->dwType
);
736 /* If a receive event was registered for this player, invoke it */
739 SetEvent( hReceiveEvent
);
744 static HRESULT WINAPI IDirectPlaySPImpl_SetSPPlayerData
745 ( LPDIRECTPLAYSP iface
,
753 LPDP_SPPLAYERDATA lpPlayerEntry
;
756 IDirectPlaySPImpl
*This
= (IDirectPlaySPImpl
*)iface
;
758 /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
759 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x)\n",
760 This
, idPlayer
, lpData
, dwDataSize
, dwFlags
);
762 hr
= DP_GetSPPlayerData( This
->sp
->dplay
, idPlayer
, (LPVOID
*)&lpPlayerEntry
);
765 /* Player must not exist */
766 return DPERR_INVALIDPLAYER
;
769 lpPlayerData
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, dwDataSize
);
770 CopyMemory( lpPlayerData
, lpData
, dwDataSize
);
772 if( dwFlags
== DPSET_LOCAL
)
774 lpPlayerEntry
->lpPlayerLocalData
= lpPlayerData
;
775 lpPlayerEntry
->dwPlayerLocalDataSize
= dwDataSize
;
777 else if( dwFlags
== DPSET_REMOTE
)
779 lpPlayerEntry
->lpPlayerRemoteData
= lpPlayerData
;
780 lpPlayerEntry
->dwPlayerRemoteDataSize
= dwDataSize
;
783 hr
= DP_SetSPPlayerData( This
->sp
->dplay
, idPlayer
, lpPlayerEntry
);
788 static HRESULT WINAPI IDirectPlaySPImpl_CreateCompoundAddress
789 ( LPDIRECTPLAYSP iface
,
790 LPCDPCOMPOUNDADDRESSELEMENT lpElements
,
791 DWORD dwElementCount
,
793 LPDWORD lpdwAddressSize
796 IDirectPlaySPImpl
*This
= (IDirectPlaySPImpl
*)iface
;
798 FIXME( "(%p)->(%p,0x%08x,%p,%p): stub\n",
799 This
, lpElements
, dwElementCount
, lpAddress
, lpdwAddressSize
);
804 static HRESULT WINAPI IDirectPlaySPImpl_GetSPData
805 ( LPDIRECTPLAYSP iface
,
807 LPDWORD lpdwDataSize
,
812 IDirectPlaySPImpl
*This
= (IDirectPlaySPImpl
*)iface
;
814 /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
815 TRACE( "(%p)->(%p,%p,0x%08x)\n",
816 This
, lplpData
, lpdwDataSize
, dwFlags
);
819 /* This is what the documentation says... */
820 if( dwFlags
!= DPSET_REMOTE
)
822 return DPERR_INVALIDPARAMS
;
825 /* ... but most service providers call this with 1 */
826 /* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
829 if( dwFlags
!= DPSET_REMOTE
)
831 TRACE( "Undocumented dwFlags 0x%08x used\n", dwFlags
);
835 /* FIXME: What to do in the case where this isn't initialized yet? */
837 /* Yes, we're supposed to return a pointer to the memory we have stored! */
838 if( dwFlags
== DPSET_REMOTE
)
840 *lpdwDataSize
= This
->sp
->dwSpRemoteDataSize
;
841 *lplpData
= This
->sp
->lpSpRemoteData
;
843 if( This
->sp
->lpSpRemoteData
== NULL
)
848 else if( dwFlags
== DPSET_LOCAL
)
850 *lpdwDataSize
= This
->sp
->dwSpLocalDataSize
;
851 *lplpData
= This
->sp
->lpSpLocalData
;
853 if( This
->sp
->lpSpLocalData
== NULL
)
862 static HRESULT WINAPI IDirectPlaySPImpl_SetSPData
863 ( LPDIRECTPLAYSP iface
,
871 IDirectPlaySPImpl
*This
= (IDirectPlaySPImpl
*)iface
;
873 /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
874 TRACE( "(%p)->(%p,0x%08x,0x%08x)\n",
875 This
, lpData
, dwDataSize
, dwFlags
);
878 /* This is what the documentation says... */
879 if( dwFlags
!= DPSET_REMOTE
)
881 return DPERR_INVALIDPARAMS
;
884 /* ... but most service providers call this with 1 */
885 /* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
888 if( dwFlags
!= DPSET_REMOTE
)
890 TRACE( "Undocumented dwFlags 0x%08x used\n", dwFlags
);
894 lpSpData
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, dwDataSize
);
895 CopyMemory( lpSpData
, lpData
, dwDataSize
);
897 /* If we have data already allocated, free it and replace it */
898 if( dwFlags
== DPSET_REMOTE
)
900 HeapFree( GetProcessHeap(), 0, This
->sp
->lpSpRemoteData
);
901 This
->sp
->dwSpRemoteDataSize
= dwDataSize
;
902 This
->sp
->lpSpRemoteData
= lpSpData
;
904 else if ( dwFlags
== DPSET_LOCAL
)
906 HeapFree( GetProcessHeap(), 0, This
->sp
->lpSpLocalData
);
907 This
->sp
->lpSpLocalData
= lpSpData
;
908 This
->sp
->dwSpLocalDataSize
= dwDataSize
;
914 static VOID WINAPI IDirectPlaySPImpl_SendComplete
915 ( LPDIRECTPLAYSP iface
,
920 IDirectPlaySPImpl
*This
= (IDirectPlaySPImpl
*)iface
;
922 FIXME( "(%p)->(%p,0x%08x): stub\n",
923 This
, unknownA
, unknownB
);
926 static const IDirectPlaySPVtbl directPlaySPVT
=
933 IDirectPlaySPImpl_AddMRUEntry
,
934 IDirectPlaySPImpl_CreateAddress
,
935 IDirectPlaySPImpl_EnumAddress
,
936 IDirectPlaySPImpl_EnumMRUEntries
,
937 IDirectPlaySPImpl_GetPlayerFlags
,
938 IDirectPlaySPImpl_GetSPPlayerData
,
939 IDirectPlaySPImpl_HandleMessage
,
940 IDirectPlaySPImpl_SetSPPlayerData
,
941 IDirectPlaySPImpl_CreateCompoundAddress
,
942 IDirectPlaySPImpl_GetSPData
,
943 IDirectPlaySPImpl_SetSPData
,
944 IDirectPlaySPImpl_SendComplete
948 /* DP external interfaces to call into DPSP interface */
950 /* Allocate the structure */
951 LPVOID
DPSP_CreateSPPlayerData(void)
953 TRACE( "Creating SPPlayer data struct\n" );
954 return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
955 sizeof( DP_SPPLAYERDATA
) );