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 */
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 = (IDirectPlaySPImpl *)*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 = (IDirectPlaySPImpl *)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 = (IDirectPlaySPImpl *)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 = (IDirectPlaySPImpl *)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 = (IDirectPlaySPImpl *)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 = (IDirectPlaySPImpl *)*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 = (LPDPMSG_SENDENVELOPE)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 = (LPDWORD)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 = (LPDPMSG_CREATEPLAYERORGROUP)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 = (LPDPMSG_DESTROYPLAYERORGROUP)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 = (LPDPMSG_ADDPLAYERTOGROUP)lpMsg;
570 hr = DP_IF_AddPlayerToGroup( This, msg->dpIdGroup, msg->dpIdPlayer, ... );
574 case DPSYS_DELETEPLAYERFROMGROUP:
576 LPDPMSG_DELETEPLAYERFROMGROUP msg = (LPDPMSG_DELETEPLAYERFROMGROUP)lpMsg;
578 hr = DP_IF_DeletePlayerFromGroup( This, msg->dpIdGroup, msg->dpIdPlayer,
584 case DPSYS_SESSIONLOST:
586 LPDPMSG_SESSIONLOST msg = (LPDPMSG_SESSIONLOST)lpMsg;
588 FIXME( "DPSYS_SESSIONLOST not handled\n" );
595 LPDPMSG_HOST msg = (LPDPMSG_HOST)lpMsg;
597 FIXME( "DPSYS_HOST not handled\n" );
602 case DPSYS_SETPLAYERORGROUPDATA:
604 LPDPMSG_SETPLAYERORGROUPDATA msg = (LPDPMSG_SETPLAYERORGROUPDATA)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 = (LPDPMSG_SETPLAYERORGROUPNAME)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 = (LPDPMSG_SETSESSIONDESC)lpMsg;
649 hr = DP_IF_SetSessionDesc( This, &msg->dpDesc );
654 case DPSYS_ADDGROUPTOGROUP:
656 LPDPMSG_ADDGROUPTOGROUP msg = (LPDPMSG_ADDGROUPTOGROUP)lpMsg;
658 hr = DP_IF_AddGroupToGroup( This, msg->dpIdParentGroup, msg->dpIdGroup,
664 case DPSYS_DELETEGROUPFROMGROUP:
666 LPDPMSG_DELETEGROUPFROMGROUP msg = (LPDPMSG_DELETEGROUPFROMGROUP)lpMsg;
668 hr = DP_IF_DeleteGroupFromGroup( This, msg->dpIdParentGroup,
669 msg->dpIdGroup, ... );
674 case DPSYS_SECUREMESSAGE:
676 LPDPMSG_SECUREMESSAGE msg = (LPDPMSG_SECUREMESSAGE)lpMsg;
678 FIXME( "DPSYS_SECUREMESSAGE not implemented\n" );
683 case DPSYS_STARTSESSION:
685 LPDPMSG_STARTSESSION msg = (LPDPMSG_STARTSESSION)lpMsg;
687 FIXME( "DPSYS_STARTSESSION not implemented\n" );
694 LPDPMSG_CHAT msg = (LPDPMSG_CHAT)lpMsg;
696 FIXME( "DPSYS_CHAT not implemeneted\n" );
701 case DPSYS_SETGROUPOWNER:
703 LPDPMSG_SETGROUPOWNER msg = (LPDPMSG_SETGROUPOWNER)lpMsg;
705 FIXME( "DPSYS_SETGROUPOWNER not implemented\n" );
710 case DPSYS_SENDCOMPLETE:
712 LPDPMSG_SENDCOMPLETE msg = (LPDPMSG_SENDCOMPLETE)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 ) );