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"
25 #include "wine/dplaysp.h"
26 #include "dplay_global.h"
27 #include "name_server.h"
28 #include "dplayx_messages.h"
30 #include "dplayx_global.h" /* FIXME: For global hack */
32 /* FIXME: Need to add interface locking inside procedures */
34 WINE_DEFAULT_DEBUG_CHANNEL(dplay);
37 static BOOL DPSP_CreateIUnknown( LPVOID lpSP );
38 static BOOL DPSP_DestroyIUnknown( LPVOID lpSP );
39 static BOOL DPSP_CreateDirectPlaySP( void *lpSP, IDirectPlayImpl *dp );
40 static BOOL DPSP_DestroyDirectPlaySP( LPVOID lpSP );
42 /* Predefine the interface */
43 typedef struct IDirectPlaySPImpl IDirectPlaySPImpl;
45 typedef struct tagDirectPlaySPIUnknownData
48 CRITICAL_SECTION DPSP_lock;
49 } DirectPlaySPIUnknownData;
51 typedef struct tagDirectPlaySPData
53 LPVOID lpSpRemoteData;
54 DWORD dwSpRemoteDataSize; /* Size of data pointed to by lpSpRemoteData */
57 DWORD dwSpLocalDataSize; /* Size of data pointed to by lpSpLocalData */
59 IDirectPlayImpl *dplay; /* FIXME: This should perhaps be iface not impl */
63 #define DPSP_IMPL_FIELDS \
64 LONG ulInterfaceRef; \
65 DirectPlaySPIUnknownData* unk; \
68 struct IDirectPlaySPImpl
70 const IDirectPlaySPVtbl *lpVtbl;
74 /* Forward declaration of virtual tables */
75 static const IDirectPlaySPVtbl directPlaySPVT;
77 /* This structure is passed to the DP object for safe keeping */
78 typedef struct tagDP_SPPLAYERDATA
80 LPVOID lpPlayerLocalData;
81 DWORD dwPlayerLocalDataSize;
83 LPVOID lpPlayerRemoteData;
84 DWORD dwPlayerRemoteDataSize;
85 } DP_SPPLAYERDATA, *LPDP_SPPLAYERDATA;
87 /* Create the SP interface */
88 HRESULT DPSP_CreateInterface( REFIID riid, void **ppvObj, IDirectPlayImpl *dp )
90 TRACE( " for %s\n", debugstr_guid( riid ) );
92 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
93 sizeof( IDirectPlaySPImpl ) );
97 return DPERR_OUTOFMEMORY;
100 if( IsEqualGUID( &IID_IDirectPlaySP, riid ) )
102 IDirectPlaySPImpl *This = *ppvObj;
103 This->lpVtbl = &directPlaySPVT;
107 /* Unsupported interface */
108 HeapFree( GetProcessHeap(), 0, *ppvObj );
111 return E_NOINTERFACE;
115 if( DPSP_CreateIUnknown( *ppvObj ) &&
116 DPSP_CreateDirectPlaySP( *ppvObj, dp )
119 IDirectPlaySP_AddRef( (LPDIRECTPLAYSP)*ppvObj );
123 /* Initialize failed, destroy it */
124 DPSP_DestroyDirectPlaySP( *ppvObj );
125 DPSP_DestroyIUnknown( *ppvObj );
127 HeapFree( GetProcessHeap(), 0, *ppvObj );
130 return DPERR_NOMEMORY;
133 static BOOL DPSP_CreateIUnknown( LPVOID lpSP )
135 IDirectPlaySPImpl *This = lpSP;
137 This->unk = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->unk) ) );
139 if ( This->unk == NULL )
144 InitializeCriticalSection( &This->unk->DPSP_lock );
145 This->unk->DPSP_lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectPlaySPImpl*->DirectPlaySPIUnknownData*->DPSP_lock");
150 static BOOL DPSP_DestroyIUnknown( LPVOID lpSP )
152 IDirectPlaySPImpl *This = lpSP;
154 This->unk->DPSP_lock.DebugInfo->Spare[0] = 0;
155 DeleteCriticalSection( &This->unk->DPSP_lock );
156 HeapFree( GetProcessHeap(), 0, This->unk );
162 static BOOL DPSP_CreateDirectPlaySP( void *lpSP, IDirectPlayImpl *dp )
164 IDirectPlaySPImpl *This = lpSP;
166 This->sp = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->sp) ) );
168 if ( This->sp == NULL )
173 This->sp->dplay = dp;
178 static BOOL DPSP_DestroyDirectPlaySP( LPVOID lpSP )
180 IDirectPlaySPImpl *This = lpSP;
182 HeapFree( GetProcessHeap(), 0, This->sp->lpSpRemoteData );
183 HeapFree( GetProcessHeap(), 0, This->sp->lpSpLocalData );
185 /* FIXME: Need to delete player queue */
187 HeapFree( GetProcessHeap(), 0, This->sp );
191 /* Interface implementation */
193 static HRESULT WINAPI DPSP_QueryInterface
194 ( LPDIRECTPLAYSP iface,
198 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
199 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
201 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
204 if( *ppvObj == NULL )
206 return DPERR_OUTOFMEMORY;
209 CopyMemory( *ppvObj, This, sizeof( *This ) );
210 (*(IDirectPlaySPImpl**)ppvObj)->ulInterfaceRef = 0;
212 if( IsEqualGUID( &IID_IDirectPlaySP, riid ) )
214 IDirectPlaySPImpl *This = *ppvObj;
215 This->lpVtbl = &directPlaySPVT;
219 /* Unsupported interface */
220 HeapFree( GetProcessHeap(), 0, *ppvObj );
223 return E_NOINTERFACE;
226 IDirectPlaySP_AddRef( (LPDIRECTPLAYSP)*ppvObj );
231 static ULONG WINAPI DPSP_AddRef
232 ( LPDIRECTPLAYSP iface )
234 ULONG ulInterfaceRefCount, ulObjRefCount;
235 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
237 ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
238 ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
240 TRACE( "ref count incremented to %u:%u for %p\n",
241 ulInterfaceRefCount, ulObjRefCount, This );
243 return ulObjRefCount;
246 static ULONG WINAPI DPSP_Release
247 ( LPDIRECTPLAYSP iface )
249 ULONG ulInterfaceRefCount, ulObjRefCount;
250 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
252 ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
253 ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
255 TRACE( "ref count decremented to %u:%u for %p\n",
256 ulInterfaceRefCount, ulObjRefCount, This );
258 /* Deallocate if this is the last reference to the object */
259 if( ulObjRefCount == 0 )
261 DPSP_DestroyDirectPlaySP( This );
262 DPSP_DestroyIUnknown( This );
265 if( ulInterfaceRefCount == 0 )
267 HeapFree( GetProcessHeap(), 0, This );
270 return ulInterfaceRefCount;
273 static HRESULT WINAPI IDirectPlaySPImpl_AddMRUEntry
274 ( LPDIRECTPLAYSP iface,
282 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
284 /* Should be able to call the comctl32 undocumented MRU routines.
285 I suspect that the interface works appropriately */
286 FIXME( "(%p)->(%p,%p%p,0x%08x,0x%08x): stub\n",
287 This, lpSection, lpKey, lpData, dwDataSize, dwMaxEntries );
292 static HRESULT WINAPI IDirectPlaySPImpl_CreateAddress
293 ( LPDIRECTPLAYSP iface,
295 REFGUID guidDataType,
299 LPDWORD lpdwAddressSize
302 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
304 FIXME( "(%p)->(%s,%s,%p,0x%08x,%p,%p): stub\n",
305 This, debugstr_guid(guidSP), debugstr_guid(guidDataType),
306 lpData, dwDataSize, lpAddress, lpdwAddressSize );
311 static HRESULT WINAPI IDirectPlaySPImpl_EnumAddress
312 ( LPDIRECTPLAYSP iface,
313 LPDPENUMADDRESSCALLBACK lpEnumAddressCallback,
319 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
321 TRACE( "(%p)->(%p,%p,0x%08x,%p)\n",
322 This, lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
324 DPL_EnumAddress( lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
329 static HRESULT WINAPI IDirectPlaySPImpl_EnumMRUEntries
330 ( LPDIRECTPLAYSP iface,
333 LPENUMMRUCALLBACK lpEnumMRUCallback,
337 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
339 /* Should be able to call the comctl32 undocumented MRU routines.
340 I suspect that the interface works appropriately */
341 FIXME( "(%p)->(%p,%p,%p,%p,): stub\n",
342 This, lpSection, lpKey, lpEnumMRUCallback, lpContext );
347 static HRESULT WINAPI IDirectPlaySPImpl_GetPlayerFlags
348 ( LPDIRECTPLAYSP iface,
350 LPDWORD lpdwPlayerFlags
353 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
355 FIXME( "(%p)->(0x%08x,%p): stub\n",
356 This, idPlayer, lpdwPlayerFlags );
361 static HRESULT WINAPI IDirectPlaySPImpl_GetSPPlayerData
362 ( LPDIRECTPLAYSP iface,
365 LPDWORD lpdwDataSize,
370 LPDP_SPPLAYERDATA lpPlayerData;
371 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
373 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x)\n",
374 This, idPlayer, lplpData, lpdwDataSize, dwFlags );
376 hr = DP_GetSPPlayerData( This->sp->dplay, idPlayer, (LPVOID*)&lpPlayerData );
380 TRACE( "Couldn't get player data: %s\n", DPLAYX_HresultToString(hr) );
381 return DPERR_INVALIDPLAYER;
384 /* What to do in the case where there is nothing set yet? */
385 if( dwFlags == DPSET_LOCAL )
387 HeapFree( GetProcessHeap(), 0, lpPlayerData->lpPlayerLocalData );
388 *lplpData = lpPlayerData->lpPlayerLocalData;
389 *lpdwDataSize = lpPlayerData->dwPlayerLocalDataSize;
391 else if( dwFlags == DPSET_REMOTE )
393 HeapFree( GetProcessHeap(), 0, lpPlayerData->lpPlayerRemoteData );
394 *lplpData = lpPlayerData->lpPlayerRemoteData;
395 *lpdwDataSize = lpPlayerData->dwPlayerRemoteDataSize;
398 if( *lplpData == NULL )
406 static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage
407 ( LPDIRECTPLAYSP iface,
408 LPVOID lpMessageBody,
409 DWORD dwMessageBodySize,
410 LPVOID lpMessageHeader
413 LPDPMSG_SENDENVELOPE lpMsg = lpMessageBody;
414 HRESULT hr = DPERR_GENERIC;
419 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
421 FIXME( "(%p)->(%p,0x%08x,%p): mostly stub\n",
422 This, lpMessageBody, dwMessageBodySize, lpMessageHeader );
424 wCommandId = lpMsg->wCommandId;
425 wVersion = lpMsg->wVersion;
427 TRACE( "Incoming message has envelope of 0x%08x, %u, %u\n",
428 lpMsg->dwMagic, wCommandId, wVersion );
430 if( lpMsg->dwMagic != DPMSGMAGIC_DPLAYMSG )
432 ERR( "Unknown magic 0x%08x!\n", lpMsg->dwMagic );
433 return DPERR_GENERIC;
438 const LPDWORD lpcHeader = lpMessageHeader;
440 TRACE( "lpMessageHeader = [0x%08lx] [0x%08lx] [0x%08lx] [0x%08lx] [0x%08lx]\n",
441 lpcHeader[0], lpcHeader[1], lpcHeader[2], lpcHeader[3], lpcHeader[4] );
445 /* Pass everything else to Direct Play */
446 data.lpMessage = NULL;
447 data.dwMessageSize = 0;
449 /* Pass this message to the dplay interface to handle */
450 hr = DP_HandleMessage( This->sp->dplay, lpMessageBody, dwMessageBodySize,
451 lpMessageHeader, wCommandId, wVersion,
452 &data.lpMessage, &data.dwMessageSize );
456 ERR( "Command processing failed %s\n", DPLAYX_HresultToString(hr) );
459 /* Do we want a reply? */
460 if( data.lpMessage != NULL )
462 data.lpSPMessageHeader = lpMessageHeader;
463 data.idNameServer = 0;
466 hr = (This->sp->dplay->dp2->spData.lpCB->Reply)( &data );
470 ERR( "Reply failed %s\n", DPLAYX_HresultToString(hr) );
478 HANDLE hReceiveEvent = 0;
479 /* FIXME: Acquire some sort of interface lock */
480 /* FIXME: Need some sort of context for this callback. Need to determine
481 * how this is actually done with the SP
483 /* FIXME: Who needs to delete the message when done? */
484 switch( lpMsg->dwType )
486 case DPSYS_CREATEPLAYERORGROUP:
488 LPDPMSG_CREATEPLAYERORGROUP msg = lpMsg;
490 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
492 hr = DP_IF_CreatePlayer( This, lpMessageHeader, msg->dpId,
493 &msg->dpnName, 0, msg->lpData,
494 msg->dwDataSize, msg->dwFlags, ... );
496 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
498 /* Group in group situation? */
499 if( msg->dpIdParent == DPID_NOPARENT_GROUP )
501 hr = DP_IF_CreateGroup( This, lpMessageHeader, msg->dpId,
502 &msg->dpnName, 0, msg->lpData,
503 msg->dwDataSize, msg->dwFlags, ... );
505 else /* Group in Group */
507 hr = DP_IF_CreateGroupInGroup( This, lpMessageHeader, msg->dpIdParent,
508 &msg->dpnName, 0, msg->lpData,
509 msg->dwDataSize, msg->dwFlags, ... );
514 ERR( "Corrupt msg->dwPlayerType for DPSYS_CREATEPLAYERORGROUP\n" );
521 case DPSYS_DESTROYPLAYERORGROUP:
523 LPDPMSG_DESTROYPLAYERORGROUP msg = lpMsg;
525 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
527 hr = DP_IF_DestroyPlayer( This, msg->dpId, ... );
529 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
531 hr = DP_IF_DestroyGroup( This, msg->dpId, ... );
535 ERR( "Corrupt msg->dwPlayerType for DPSYS_DESTROYPLAYERORGROUP\n" );
542 case DPSYS_ADDPLAYERTOGROUP:
544 LPDPMSG_ADDPLAYERTOGROUP msg = lpMsg;
546 hr = DP_IF_AddPlayerToGroup( This, msg->dpIdGroup, msg->dpIdPlayer, ... );
550 case DPSYS_DELETEPLAYERFROMGROUP:
552 LPDPMSG_DELETEPLAYERFROMGROUP msg = lpMsg;
554 hr = DP_IF_DeletePlayerFromGroup( This, msg->dpIdGroup, msg->dpIdPlayer,
560 case DPSYS_SESSIONLOST:
562 LPDPMSG_SESSIONLOST msg = lpMsg;
564 FIXME( "DPSYS_SESSIONLOST not handled\n" );
571 LPDPMSG_HOST msg = lpMsg;
573 FIXME( "DPSYS_HOST not handled\n" );
578 case DPSYS_SETPLAYERORGROUPDATA:
580 LPDPMSG_SETPLAYERORGROUPDATA msg = lpMsg;
582 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
584 hr = DP_IF_SetPlayerData( This, msg->dpId, msg->lpData, msg->dwDataSize, DPSET_REMOTE, ... );
586 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
588 hr = DP_IF_SetGroupData( This, msg->dpId, msg->lpData, msg->dwDataSize,
593 ERR( "Corrupt msg->dwPlayerType for LPDPMSG_SETPLAYERORGROUPDATA\n" );
600 case DPSYS_SETPLAYERORGROUPNAME:
602 LPDPMSG_SETPLAYERORGROUPNAME msg = lpMsg;
604 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
606 hr = DP_IF_SetPlayerName( This, msg->dpId, msg->dpnName, ... );
608 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
610 hr = DP_IF_SetGroupName( This, msg->dpId, msg->dpnName, ... );
614 ERR( "Corrupt msg->dwPlayerType for LPDPMSG_SETPLAYERORGROUPDATA\n" );
621 case DPSYS_SETSESSIONDESC;
623 LPDPMSG_SETSESSIONDESC msg = lpMsg;
625 hr = DP_IF_SetSessionDesc( This, &msg->dpDesc );
630 case DPSYS_ADDGROUPTOGROUP:
632 LPDPMSG_ADDGROUPTOGROUP msg = lpMsg;
634 hr = DP_IF_AddGroupToGroup( This, msg->dpIdParentGroup, msg->dpIdGroup,
640 case DPSYS_DELETEGROUPFROMGROUP:
642 LPDPMSG_DELETEGROUPFROMGROUP msg = lpMsg;
644 hr = DP_IF_DeleteGroupFromGroup( This, msg->dpIdParentGroup,
645 msg->dpIdGroup, ... );
650 case DPSYS_SECUREMESSAGE:
652 LPDPMSG_SECUREMESSAGE msg = lpMsg;
654 FIXME( "DPSYS_SECUREMESSAGE not implemented\n" );
659 case DPSYS_STARTSESSION:
661 LPDPMSG_STARTSESSION msg = lpMsg;
663 FIXME( "DPSYS_STARTSESSION not implemented\n" );
670 LPDPMSG_CHAT msg = lpMsg;
672 FIXME( "DPSYS_CHAT not implemeneted\n" );
677 case DPSYS_SETGROUPOWNER:
679 LPDPMSG_SETGROUPOWNER msg = lpMsg;
681 FIXME( "DPSYS_SETGROUPOWNER not implemented\n" );
686 case DPSYS_SENDCOMPLETE:
688 LPDPMSG_SENDCOMPLETE msg = lpMsg;
690 FIXME( "DPSYS_SENDCOMPLETE not implemented\n" );
697 /* NOTE: This should be a user defined type. There is nothing that we
698 * need to do with it except queue it.
700 TRACE( "Received user message type(?) 0x%08lx through SP.\n",
706 FIXME( "Queue message in the receive queue. Need some context data!\n" );
710 ERR( "Unable to perform action for msg type 0x%08lx\n", lpMsg->dwType );
712 /* If a receive event was registered for this player, invoke it */
715 SetEvent( hReceiveEvent );
720 static HRESULT WINAPI IDirectPlaySPImpl_SetSPPlayerData
721 ( LPDIRECTPLAYSP iface,
729 LPDP_SPPLAYERDATA lpPlayerEntry;
732 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
734 /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
735 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x)\n",
736 This, idPlayer, lpData, dwDataSize, dwFlags );
738 hr = DP_GetSPPlayerData( This->sp->dplay, idPlayer, (LPVOID*)&lpPlayerEntry );
741 /* Player must not exist */
742 return DPERR_INVALIDPLAYER;
745 lpPlayerData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
746 CopyMemory( lpPlayerData, lpData, dwDataSize );
748 if( dwFlags == DPSET_LOCAL )
750 lpPlayerEntry->lpPlayerLocalData = lpPlayerData;
751 lpPlayerEntry->dwPlayerLocalDataSize = dwDataSize;
753 else if( dwFlags == DPSET_REMOTE )
755 lpPlayerEntry->lpPlayerRemoteData = lpPlayerData;
756 lpPlayerEntry->dwPlayerRemoteDataSize = dwDataSize;
759 hr = DP_SetSPPlayerData( This->sp->dplay, idPlayer, lpPlayerEntry );
764 static HRESULT WINAPI IDirectPlaySPImpl_CreateCompoundAddress
765 ( LPDIRECTPLAYSP iface,
766 LPCDPCOMPOUNDADDRESSELEMENT lpElements,
767 DWORD dwElementCount,
769 LPDWORD lpdwAddressSize
772 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
774 FIXME( "(%p)->(%p,0x%08x,%p,%p): stub\n",
775 This, lpElements, dwElementCount, lpAddress, lpdwAddressSize );
780 static HRESULT WINAPI IDirectPlaySPImpl_GetSPData
781 ( LPDIRECTPLAYSP iface,
783 LPDWORD lpdwDataSize,
788 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
790 /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
791 TRACE( "(%p)->(%p,%p,0x%08x)\n",
792 This, lplpData, lpdwDataSize, dwFlags );
795 /* This is what the documentation says... */
796 if( dwFlags != DPSET_REMOTE )
798 return DPERR_INVALIDPARAMS;
801 /* ... but most service providers call this with 1 */
802 /* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
805 if( dwFlags != DPSET_REMOTE )
807 TRACE( "Undocumented dwFlags 0x%08x used\n", dwFlags );
811 /* FIXME: What to do in the case where this isn't initialized yet? */
813 /* Yes, we're supposed to return a pointer to the memory we have stored! */
814 if( dwFlags == DPSET_REMOTE )
816 *lpdwDataSize = This->sp->dwSpRemoteDataSize;
817 *lplpData = This->sp->lpSpRemoteData;
819 if( This->sp->lpSpRemoteData == NULL )
824 else if( dwFlags == DPSET_LOCAL )
826 *lpdwDataSize = This->sp->dwSpLocalDataSize;
827 *lplpData = This->sp->lpSpLocalData;
829 if( This->sp->lpSpLocalData == NULL )
838 static HRESULT WINAPI IDirectPlaySPImpl_SetSPData
839 ( LPDIRECTPLAYSP iface,
847 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
849 /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
850 TRACE( "(%p)->(%p,0x%08x,0x%08x)\n",
851 This, lpData, dwDataSize, dwFlags );
854 /* This is what the documentation says... */
855 if( dwFlags != DPSET_REMOTE )
857 return DPERR_INVALIDPARAMS;
860 /* ... but most service providers call this with 1 */
861 /* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
864 if( dwFlags != DPSET_REMOTE )
866 TRACE( "Undocumented dwFlags 0x%08x used\n", dwFlags );
870 lpSpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
871 CopyMemory( lpSpData, lpData, dwDataSize );
873 /* If we have data already allocated, free it and replace it */
874 if( dwFlags == DPSET_REMOTE )
876 HeapFree( GetProcessHeap(), 0, This->sp->lpSpRemoteData );
877 This->sp->dwSpRemoteDataSize = dwDataSize;
878 This->sp->lpSpRemoteData = lpSpData;
880 else if ( dwFlags == DPSET_LOCAL )
882 HeapFree( GetProcessHeap(), 0, This->sp->lpSpLocalData );
883 This->sp->lpSpLocalData = lpSpData;
884 This->sp->dwSpLocalDataSize = dwDataSize;
890 static VOID WINAPI IDirectPlaySPImpl_SendComplete
891 ( LPDIRECTPLAYSP iface,
896 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
898 FIXME( "(%p)->(%p,0x%08x): stub\n",
899 This, unknownA, unknownB );
902 static const IDirectPlaySPVtbl directPlaySPVT =
909 IDirectPlaySPImpl_AddMRUEntry,
910 IDirectPlaySPImpl_CreateAddress,
911 IDirectPlaySPImpl_EnumAddress,
912 IDirectPlaySPImpl_EnumMRUEntries,
913 IDirectPlaySPImpl_GetPlayerFlags,
914 IDirectPlaySPImpl_GetSPPlayerData,
915 IDirectPlaySPImpl_HandleMessage,
916 IDirectPlaySPImpl_SetSPPlayerData,
917 IDirectPlaySPImpl_CreateCompoundAddress,
918 IDirectPlaySPImpl_GetSPData,
919 IDirectPlaySPImpl_SetSPData,
920 IDirectPlaySPImpl_SendComplete
924 /* DP external interfaces to call into DPSP interface */
926 /* Allocate the structure */
927 LPVOID DPSP_CreateSPPlayerData(void)
929 TRACE( "Creating SPPlayer data struct\n" );
930 return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
931 sizeof( DP_SPPLAYERDATA ) );