Fixed a couple of HWND type mismatches.
[wine/multimedia.git] / dlls / dplayx / dplaysp.c
blobe38d2b6aa01cf062e9ad56b099a1ea6138b72308
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>
5 */
7 #include <string.h>
8 #include "winerror.h"
9 #include "debugtools.h"
11 #include "dpinit.h"
12 #include "dplaysp.h"
13 #include "dplay_global.h"
14 #include "name_server.h"
15 #include "dplayx_messages.h"
17 #include "dplayx_global.h" /* FIXME: For global hack */
19 /* FIXME: Need to add interface locking inside procedures */
21 DEFAULT_DEBUG_CHANNEL(dplay);
23 /* Prototypes */
24 static BOOL DPSP_CreateIUnknown( LPVOID lpSP );
25 static BOOL DPSP_DestroyIUnknown( LPVOID lpSP );
26 static BOOL DPSP_CreateDirectPlaySP( LPVOID lpSP, IDirectPlay2Impl* dp );
27 static BOOL DPSP_DestroyDirectPlaySP( LPVOID lpSP );
29 /* Predefine the interface */
30 typedef struct IDirectPlaySPImpl IDirectPlaySPImpl;
32 typedef struct tagDirectPlaySPIUnknownData
34 ULONG ulObjRef;
35 CRITICAL_SECTION DPSP_lock;
36 } DirectPlaySPIUnknownData;
38 typedef struct tagDirectPlaySPData
40 LPVOID lpSpRemoteData;
41 DWORD dwSpRemoteDataSize; /* Size of data pointed to by lpSpRemoteData */
43 LPVOID lpSpLocalData;
44 DWORD dwSpLocalDataSize; /* Size of data pointed to by lpSpLocalData */
46 IDirectPlay2Impl* dplay; /* FIXME: This should perhaps be iface not impl */
48 } DirectPlaySPData;
50 #define DPSP_IMPL_FIELDS \
51 ULONG ulInterfaceRef; \
52 DirectPlaySPIUnknownData* unk; \
53 DirectPlaySPData* sp;
55 struct IDirectPlaySPImpl
57 ICOM_VFIELD(IDirectPlaySP);
58 DPSP_IMPL_FIELDS
61 /* Forward declaration of virtual tables */
62 static ICOM_VTABLE(IDirectPlaySP) directPlaySPVT;
64 /* This structure is passed to the DP object for safe keeping */
65 typedef struct tagDP_SPPLAYERDATA
67 LPVOID lpPlayerLocalData;
68 DWORD dwPlayerLocalDataSize;
70 LPVOID lpPlayerRemoteData;
71 DWORD dwPlayerRemoteDataSize;
72 } DP_SPPLAYERDATA, *LPDP_SPPLAYERDATA;
74 /* Create the SP interface */
75 extern
76 HRESULT DPSP_CreateInterface( REFIID riid, LPVOID* ppvObj, IDirectPlay2Impl* dp )
78 TRACE( " for %s\n", debugstr_guid( riid ) );
80 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
81 sizeof( IDirectPlaySPImpl ) );
83 if( *ppvObj == NULL )
85 return DPERR_OUTOFMEMORY;
88 if( IsEqualGUID( &IID_IDirectPlaySP, riid ) )
90 ICOM_THIS(IDirectPlaySPImpl,*ppvObj);
91 ICOM_VTBL(This) = &directPlaySPVT;
93 else
95 /* Unsupported interface */
96 HeapFree( GetProcessHeap(), 0, *ppvObj );
97 *ppvObj = NULL;
99 return E_NOINTERFACE;
102 /* Initialize it */
103 if( DPSP_CreateIUnknown( *ppvObj ) &&
104 DPSP_CreateDirectPlaySP( *ppvObj, dp )
107 IDirectPlaySP_AddRef( (LPDIRECTPLAYSP)*ppvObj );
108 return S_OK;
111 /* Initialize failed, destroy it */
112 DPSP_DestroyDirectPlaySP( *ppvObj );
113 DPSP_DestroyIUnknown( *ppvObj );
115 HeapFree( GetProcessHeap(), 0, *ppvObj );
116 *ppvObj = NULL;
118 return DPERR_NOMEMORY;
121 static BOOL DPSP_CreateIUnknown( LPVOID lpSP )
123 ICOM_THIS(IDirectPlaySPImpl,lpSP);
125 This->unk = (DirectPlaySPIUnknownData*)HeapAlloc( GetProcessHeap(),
126 HEAP_ZERO_MEMORY,
127 sizeof( *(This->unk) ) );
129 if ( This->unk == NULL )
131 return FALSE;
134 InitializeCriticalSection( &This->unk->DPSP_lock );
136 return TRUE;
139 static BOOL DPSP_DestroyIUnknown( LPVOID lpSP )
141 ICOM_THIS(IDirectPlaySPImpl,lpSP);
143 DeleteCriticalSection( &This->unk->DPSP_lock );
144 HeapFree( GetProcessHeap(), 0, This->unk );
146 return TRUE;
150 static BOOL DPSP_CreateDirectPlaySP( LPVOID lpSP, IDirectPlay2Impl* dp )
152 ICOM_THIS(IDirectPlaySPImpl,lpSP);
154 This->sp = (DirectPlaySPData*)HeapAlloc( GetProcessHeap(),
155 HEAP_ZERO_MEMORY,
156 sizeof( *(This->sp) ) );
158 if ( This->sp == NULL )
160 return FALSE;
163 This->sp->dplay = dp;
165 /* Normally we should be keeping a reference, but since only the dplay
166 * interface that created us can destroy us, we do not keep a reference
167 * to it (ie we'd be stuck with always having one reference to the dplay
168 * object, and hence us, around).
169 * NOTE: The dp object does reference count us.
171 * FIXME: This is a kludge to get around a problem where a queryinterface
172 * is used to get a new interface and then is closed. We will then
173 * reference garbage. However, with this we will never deallocate
174 * the interface we store. The correct fix is to require all
175 * DP internal interfaces to use the This->dp2 interface which
176 * should be changed to This->dp
178 IDirectPlayX_AddRef( (LPDIRECTPLAY2)dp );
180 return TRUE;
183 static BOOL DPSP_DestroyDirectPlaySP( LPVOID lpSP )
185 ICOM_THIS(IDirectPlaySPImpl,lpSP);
187 /* Normally we should be keeping a reference, but since only the dplay
188 * interface that created us can destroy us, we do not keep a reference
189 * to it (ie we'd be stuck with always having one reference to the dplay
190 * object, and hence us, around).
191 * NOTE: The dp object does reference count us.
193 /*IDirectPlayX_Release( (LPDIRECTPLAY2)This->sp->dplay ); */
195 HeapFree( GetProcessHeap(), 0, This->sp->lpSpRemoteData );
196 HeapFree( GetProcessHeap(), 0, This->sp->lpSpLocalData );
198 /* FIXME: Need to delete player queue */
200 HeapFree( GetProcessHeap(), 0, This->sp );
201 return TRUE;
204 /* Interface implementation */
206 static HRESULT WINAPI DPSP_QueryInterface
207 ( LPDIRECTPLAYSP iface,
208 REFIID riid,
209 LPVOID* ppvObj )
211 ICOM_THIS(IDirectPlaySPImpl,iface);
212 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
214 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
215 sizeof( *This ) );
217 if( *ppvObj == NULL )
219 return DPERR_OUTOFMEMORY;
222 CopyMemory( *ppvObj, This, sizeof( *This ) );
223 (*(IDirectPlaySPImpl**)ppvObj)->ulInterfaceRef = 0;
225 if( IsEqualGUID( &IID_IDirectPlaySP, riid ) )
227 ICOM_THIS(IDirectPlaySPImpl,*ppvObj);
228 ICOM_VTBL(This) = &directPlaySPVT;
230 else
232 /* Unsupported interface */
233 HeapFree( GetProcessHeap(), 0, *ppvObj );
234 *ppvObj = NULL;
236 return E_NOINTERFACE;
239 IDirectPlaySP_AddRef( (LPDIRECTPLAYSP)*ppvObj );
241 return S_OK;
244 static ULONG WINAPI DPSP_AddRef
245 ( LPDIRECTPLAYSP iface )
247 ULONG ulInterfaceRefCount, ulObjRefCount;
248 ICOM_THIS(IDirectPlaySPImpl,iface);
250 ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
251 ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
253 TRACE( "ref count incremented to %lu:%lu for %p\n",
254 ulInterfaceRefCount, ulObjRefCount, This );
256 return ulObjRefCount;
259 static ULONG WINAPI DPSP_Release
260 ( LPDIRECTPLAYSP iface )
262 ULONG ulInterfaceRefCount, ulObjRefCount;
263 ICOM_THIS(IDirectPlaySPImpl,iface);
265 ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
266 ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
268 TRACE( "ref count decremented to %lu:%lu for %p\n",
269 ulInterfaceRefCount, ulObjRefCount, This );
271 /* Deallocate if this is the last reference to the object */
272 if( ulObjRefCount == 0 )
274 DPSP_DestroyDirectPlaySP( This );
275 DPSP_DestroyIUnknown( This );
278 if( ulInterfaceRefCount == 0 )
280 HeapFree( GetProcessHeap(), 0, This );
283 return ulInterfaceRefCount;
286 static HRESULT WINAPI IDirectPlaySPImpl_AddMRUEntry
287 ( LPDIRECTPLAYSP iface,
288 LPCWSTR lpSection,
289 LPCWSTR lpKey,
290 LPCVOID lpData,
291 DWORD dwDataSize,
292 DWORD dwMaxEntries
295 ICOM_THIS(IDirectPlaySPImpl,iface);
297 /* Should be able to call the comctl32 undocumented MRU routines.
298 I suspect that the interface works appropriately */
299 FIXME( "(%p)->(%p,%p%p,0x%08lx,0x%08lx): stub\n",
300 This, lpSection, lpKey, lpData, dwDataSize, dwMaxEntries );
302 return DP_OK;
305 static HRESULT WINAPI IDirectPlaySPImpl_CreateAddress
306 ( LPDIRECTPLAYSP iface,
307 REFGUID guidSP,
308 REFGUID guidDataType,
309 LPCVOID lpData,
310 DWORD dwDataSize,
311 LPVOID lpAddress,
312 LPDWORD lpdwAddressSize
315 ICOM_THIS(IDirectPlaySPImpl,iface);
317 FIXME( "(%p)->(%s,%s,%p,0x%08lx,%p,%p): stub\n",
318 This, debugstr_guid(guidSP), debugstr_guid(guidDataType),
319 lpData, dwDataSize, lpAddress, lpdwAddressSize );
321 return DP_OK;
324 static HRESULT WINAPI IDirectPlaySPImpl_EnumAddress
325 ( LPDIRECTPLAYSP iface,
326 LPDPENUMADDRESSCALLBACK lpEnumAddressCallback,
327 LPCVOID lpAddress,
328 DWORD dwAddressSize,
329 LPVOID lpContext
332 ICOM_THIS(IDirectPlaySPImpl,iface);
334 TRACE( "(%p)->(%p,%p,0x%08lx,%p)\n",
335 This, lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
337 DPL_EnumAddress( lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
339 return DP_OK;
342 static HRESULT WINAPI IDirectPlaySPImpl_EnumMRUEntries
343 ( LPDIRECTPLAYSP iface,
344 LPCWSTR lpSection,
345 LPCWSTR lpKey,
346 LPENUMMRUCALLBACK lpEnumMRUCallback,
347 LPVOID lpContext
350 ICOM_THIS(IDirectPlaySPImpl,iface);
352 /* Should be able to call the comctl32 undocumented MRU routines.
353 I suspect that the interface works appropriately */
354 FIXME( "(%p)->(%p,%p,%p,%p,): stub\n",
355 This, lpSection, lpKey, lpEnumMRUCallback, lpContext );
357 return DP_OK;
360 static HRESULT WINAPI IDirectPlaySPImpl_GetPlayerFlags
361 ( LPDIRECTPLAYSP iface,
362 DPID idPlayer,
363 LPDWORD lpdwPlayerFlags
366 ICOM_THIS(IDirectPlaySPImpl,iface);
368 FIXME( "(%p)->(0x%08lx,%p): stub\n",
369 This, idPlayer, lpdwPlayerFlags );
371 return DP_OK;
374 static HRESULT WINAPI IDirectPlaySPImpl_GetSPPlayerData
375 ( LPDIRECTPLAYSP iface,
376 DPID idPlayer,
377 LPVOID* lplpData,
378 LPDWORD lpdwDataSize,
379 DWORD dwFlags
382 HRESULT hr;
383 LPDP_SPPLAYERDATA lpPlayerData;
384 ICOM_THIS(IDirectPlaySPImpl,iface);
386 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx)\n",
387 This, idPlayer, lplpData, lpdwDataSize, dwFlags );
389 hr = DP_GetSPPlayerData( This->sp->dplay, idPlayer, (LPVOID*)&lpPlayerData );
391 if( FAILED(hr) )
393 TRACE( "Couldn't get player data: %s\n", DPLAYX_HresultToString(hr) );
394 return DPERR_INVALIDPLAYER;
397 /* What to do in the case where there is nothing set yet? */
398 if( dwFlags == DPSET_LOCAL )
400 if( lpPlayerData->lpPlayerLocalData )
402 HeapFree( GetProcessHeap(), 0, lpPlayerData->lpPlayerLocalData );
405 *lplpData = lpPlayerData->lpPlayerLocalData;
406 *lpdwDataSize = lpPlayerData->dwPlayerLocalDataSize;
408 else if( dwFlags == DPSET_REMOTE )
410 if( lpPlayerData->lpPlayerRemoteData )
412 HeapFree( GetProcessHeap(), 0, lpPlayerData->lpPlayerRemoteData );
415 *lplpData = lpPlayerData->lpPlayerRemoteData;
416 *lpdwDataSize = lpPlayerData->dwPlayerRemoteDataSize;
419 if( *lplpData == NULL )
421 hr = DPERR_GENERIC;
424 return hr;
427 static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage
428 ( LPDIRECTPLAYSP iface,
429 LPVOID lpMessageBody,
430 DWORD dwMessageBodySize,
431 LPVOID lpMessageHeader
434 LPDPMSG_SENDENVELOPE lpMsg = (LPDPMSG_SENDENVELOPE)lpMessageBody;
435 HRESULT hr = DPERR_GENERIC;
436 WORD wCommandId;
437 WORD wVersion;
438 DPSP_REPLYDATA data;
440 ICOM_THIS(IDirectPlaySPImpl,iface);
442 FIXME( "(%p)->(%p,0x%08lx,%p): mostly stub\n",
443 This, lpMessageBody, dwMessageBodySize, lpMessageHeader );
445 wCommandId = lpMsg->wCommandId;
446 wVersion = lpMsg->wVersion;
448 TRACE( "Incomming message has envelope of 0x%08lx, %u, %u\n",
449 lpMsg->dwMagic, wCommandId, wVersion );
451 if( lpMsg->dwMagic != DPMSGMAGIC_DPLAYMSG )
453 ERR( "Unknown magic 0x%08lx!\n", lpMsg->dwMagic );
454 return DPERR_GENERIC;
457 #if 0
459 const LPDWORD lpcHeader = (LPDWORD)lpMessageHeader;
461 TRACE( "lpMessageHeader = [0x%08lx] [0x%08lx] [0x%08lx] [0x%08lx] [0x%08lx]\n",
462 lpcHeader[0], lpcHeader[1], lpcHeader[2], lpcHeader[3], lpcHeader[4] );
464 #endif
466 /* Pass everything else to Direct Play */
467 data.lpMessage = NULL;
468 data.dwMessageSize = 0;
470 /* Pass this message to the dplay interface to handle */
471 hr = DP_HandleMessage( This->sp->dplay, lpMessageBody, dwMessageBodySize,
472 lpMessageHeader, wCommandId, wVersion,
473 &data.lpMessage, &data.dwMessageSize );
475 if( FAILED(hr) )
477 ERR( "Command processing failed %s\n", DPLAYX_HresultToString(hr) );
480 /* Do we want a reply? */
481 if( data.lpMessage != NULL )
483 data.lpSPMessageHeader = lpMessageHeader;
484 data.idNameServer = 0;
485 data.lpISP = iface;
487 hr = (This->sp->dplay->dp2->spData.lpCB->Reply)( &data );
489 if( FAILED(hr) )
491 ERR( "Reply failed %s\n", DPLAYX_HresultToString(hr) );
495 return hr;
497 #if 0
498 HRESULT hr = DP_OK;
499 HANDLE hReceiveEvent = 0;
500 /* FIXME: Aquire some sort of interface lock */
501 /* FIXME: Need some sort of context for this callback. Need to determine
502 * how this is actually done with the SP
504 /* FIXME: Who needs to delete the message when done? */
505 switch( lpMsg->dwType )
507 case DPSYS_CREATEPLAYERORGROUP:
509 LPDPMSG_CREATEPLAYERORGROUP msg = (LPDPMSG_CREATEPLAYERORGROUP)lpMsg;
511 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
513 hr = DP_IF_CreatePlayer( This, lpMessageHeader, msg->dpId,
514 &msg->dpnName, 0, msg->lpData,
515 msg->dwDataSize, msg->dwFlags, ... );
517 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
519 /* Group in group situation? */
520 if( msg->dpIdParent == DPID_NOPARENT_GROUP )
522 hr = DP_IF_CreateGroup( This, lpMessageHeader, msg->dpId,
523 &msg->dpnName, 0, msg->lpData,
524 msg->dwDataSize, msg->dwFlags, ... );
526 else /* Group in Group */
528 hr = DP_IF_CreateGroupInGroup( This, lpMessageHeader, msg->dpIdParent,
529 &msg->dpnName, 0, msg->lpData,
530 msg->dwDataSize, msg->dwFlags, ... );
533 else /* Hmmm? */
535 ERR( "Corrupt msg->dwPlayerType for DPSYS_CREATEPLAYERORGROUP\n" );
536 return;
539 break;
542 case DPSYS_DESTROYPLAYERORGROUP:
544 LPDPMSG_DESTROYPLAYERORGROUP msg = (LPDPMSG_DESTROYPLAYERORGROUP)lpMsg;
546 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
548 hr = DP_IF_DestroyPlayer( This, msg->dpId, ... );
550 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
552 hr = DP_IF_DestroyGroup( This, msg->dpId, ... );
554 else /* Hmmm? */
556 ERR( "Corrupt msg->dwPlayerType for DPSYS_DESTROYPLAYERORGROUP\n" );
557 return;
560 break;
563 case DPSYS_ADDPLAYERTOGROUP:
565 LPDPMSG_ADDPLAYERTOGROUP msg = (LPDPMSG_ADDPLAYERTOGROUP)lpMsg;
567 hr = DP_IF_AddPlayerToGroup( This, msg->dpIdGroup, msg->dpIdPlayer, ... );
568 break;
571 case DPSYS_DELETEPLAYERFROMGROUP:
573 LPDPMSG_DELETEPLAYERFROMGROUP msg = (LPDPMSG_DELETEPLAYERFROMGROUP)lpMsg;
575 hr = DP_IF_DeletePlayerFromGroup( This, msg->dpIdGroup, msg->dpIdPlayer,
576 ... );
578 break;
581 case DPSYS_SESSIONLOST:
583 LPDPMSG_SESSIONLOST msg = (LPDPMSG_SESSIONLOST)lpMsg;
585 FIXME( "DPSYS_SESSIONLOST not handled\n" );
587 break;
590 case DPSYS_HOST:
592 LPDPMSG_HOST msg = (LPDPMSG_HOST)lpMsg;
594 FIXME( "DPSYS_HOST not handled\n" );
596 break;
599 case DPSYS_SETPLAYERORGROUPDATA:
601 LPDPMSG_SETPLAYERORGROUPDATA msg = (LPDPMSG_SETPLAYERORGROUPDATA)lpMsg;
603 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
605 hr = DP_IF_SetPlayerData( This, msg->dpId, msg->lpData, msg->dwDataSize, DPSET_REMOTE, ... );
607 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
609 hr = DP_IF_SetGroupData( This, msg->dpId, msg->lpData, msg->dwDataSize,
610 DPSET_REMOTE, ... );
612 else /* Hmmm? */
614 ERR( "Corrupt msg->dwPlayerType for LPDPMSG_SETPLAYERORGROUPDATA\n" );
615 return;
618 break;
621 case DPSYS_SETPLAYERORGROUPNAME:
623 LPDPMSG_SETPLAYERORGROUPNAME msg = (LPDPMSG_SETPLAYERORGROUPNAME)lpMsg;
625 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
627 hr = DP_IF_SetPlayerName( This, msg->dpId, msg->dpnName, ... );
629 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
631 hr = DP_IF_SetGroupName( This, msg->dpId, msg->dpnName, ... );
633 else /* Hmmm? */
635 ERR( "Corrupt msg->dwPlayerType for LPDPMSG_SETPLAYERORGROUPDATA\n" );
636 return;
639 break;
642 case DPSYS_SETSESSIONDESC;
644 LPDPMSG_SETSESSIONDESC msg = (LPDPMSG_SETSESSIONDESC)lpMsg;
646 hr = DP_IF_SetSessionDesc( This, &msg->dpDesc );
648 break;
651 case DPSYS_ADDGROUPTOGROUP:
653 LPDPMSG_ADDGROUPTOGROUP msg = (LPDPMSG_ADDGROUPTOGROUP)lpMsg;
655 hr = DP_IF_AddGroupToGroup( This, msg->dpIdParentGroup, msg->dpIdGroup,
656 ... );
658 break;
661 case DPSYS_DELETEGROUPFROMGROUP:
663 LPDPMSG_DELETEGROUPFROMGROUP msg = (LPDPMSG_DELETEGROUPFROMGROUP)lpMsg;
665 hr = DP_IF_DeleteGroupFromGroup( This, msg->dpIdParentGroup,
666 msg->dpIdGroup, ... );
668 break;
671 case DPSYS_SECUREMESSAGE:
673 LPDPMSG_SECUREMESSAGE msg = (LPDPMSG_SECUREMESSAGE)lpMsg;
675 FIXME( "DPSYS_SECUREMESSAGE not implemented\n" );
677 break;
680 case DPSYS_STARTSESSION:
682 LPDPMSG_STARTSESSION msg = (LPDPMSG_STARTSESSION)lpMsg;
684 FIXME( "DPSYS_STARTSESSION not implemented\n" );
686 break;
689 case DPSYS_CHAT:
691 LPDPMSG_CHAT msg = (LPDPMSG_CHAT)lpMsg;
693 FIXME( "DPSYS_CHAT not implemeneted\n" );
695 break;
698 case DPSYS_SETGROUPOWNER:
700 LPDPMSG_SETGROUPOWNER msg = (LPDPMSG_SETGROUPOWNER)lpMsg;
702 FIXME( "DPSYS_SETGROUPOWNER not implemented\n" );
704 break;
707 case DPSYS_SENDCOMPLETE:
709 LPDPMSG_SENDCOMPLETE msg = (LPDPMSG_SENDCOMPLETE)lpMsg;
711 FIXME( "DPSYS_SENDCOMPLETE not implemented\n" );
713 break;
716 default:
718 /* NOTE: This should be a user defined type. There is nothing that we
719 * need to do with it except queue it.
721 TRACE( "Received user message type(?) 0x%08lx through SP.\n",
722 lpMsg->dwType );
723 break;
727 FIXME( "Queue message in the receive queue. Need some context data!\n" );
729 if( FAILED(hr) )
731 ERR( "Unable to perform action for msg type 0x%08lx\n", lpMsg->dwType );
733 /* If a receive event was registered for this player, invoke it */
734 if( hReceiveEvent )
736 SetEvent( hReceiveEvent );
738 #endif
741 static HRESULT WINAPI IDirectPlaySPImpl_SetSPPlayerData
742 ( LPDIRECTPLAYSP iface,
743 DPID idPlayer,
744 LPVOID lpData,
745 DWORD dwDataSize,
746 DWORD dwFlags
749 HRESULT hr;
750 LPDP_SPPLAYERDATA lpPlayerEntry;
751 LPVOID lpPlayerData;
753 ICOM_THIS(IDirectPlaySPImpl,iface);
755 /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
756 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx)\n",
757 This, idPlayer, lpData, dwDataSize, dwFlags );
759 hr = DP_GetSPPlayerData( This->sp->dplay, idPlayer, (LPVOID*)&lpPlayerEntry );
760 if( FAILED(hr) )
762 /* Player must not exist */
763 return DPERR_INVALIDPLAYER;
766 lpPlayerData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
767 CopyMemory( lpPlayerData, lpData, dwDataSize );
769 if( dwFlags == DPSET_LOCAL )
771 lpPlayerEntry->lpPlayerLocalData = lpPlayerData;
772 lpPlayerEntry->dwPlayerLocalDataSize = dwDataSize;
774 else if( dwFlags == DPSET_REMOTE )
776 lpPlayerEntry->lpPlayerRemoteData = lpPlayerData;
777 lpPlayerEntry->dwPlayerRemoteDataSize = dwDataSize;
780 hr = DP_SetSPPlayerData( This->sp->dplay, idPlayer, lpPlayerEntry );
782 return hr;
785 static HRESULT WINAPI IDirectPlaySPImpl_CreateCompoundAddress
786 ( LPDIRECTPLAYSP iface,
787 LPCDPCOMPOUNDADDRESSELEMENT lpElements,
788 DWORD dwElementCount,
789 LPVOID lpAddress,
790 LPDWORD lpdwAddressSize
793 ICOM_THIS(IDirectPlaySPImpl,iface);
795 FIXME( "(%p)->(%p,0x%08lx,%p,%p): stub\n",
796 This, lpElements, dwElementCount, lpAddress, lpdwAddressSize );
798 return DP_OK;
801 static HRESULT WINAPI IDirectPlaySPImpl_GetSPData
802 ( LPDIRECTPLAYSP iface,
803 LPVOID* lplpData,
804 LPDWORD lpdwDataSize,
805 DWORD dwFlags
808 HRESULT hr = DP_OK;
809 ICOM_THIS(IDirectPlaySPImpl,iface);
811 /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
812 TRACE( "(%p)->(%p,%p,0x%08lx)\n",
813 This, lplpData, lpdwDataSize, dwFlags );
815 #if 0
816 /* This is what the documentation says... */
817 if( dwFlags != DPSET_REMOTE )
819 return DPERR_INVALIDPARAMS;
821 #else
822 /* ... but most service providers call this with 1 */
823 /* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
824 * thing?
826 if( dwFlags != DPSET_REMOTE )
828 TRACE( "Undocumented dwFlags 0x%08lx used\n", dwFlags );
830 #endif
832 /* FIXME: What to do in the case where this isn't initialized yet? */
834 /* Yes, we're supposed to return a pointer to the memory we have stored! */
835 if( dwFlags == DPSET_REMOTE )
837 *lpdwDataSize = This->sp->dwSpRemoteDataSize;
838 *lplpData = This->sp->lpSpRemoteData;
840 if( This->sp->lpSpRemoteData == NULL )
842 hr = DPERR_GENERIC;
845 else if( dwFlags == DPSET_LOCAL )
847 *lpdwDataSize = This->sp->dwSpLocalDataSize;
848 *lplpData = This->sp->lpSpLocalData;
850 if( This->sp->lpSpLocalData == NULL )
852 hr = DPERR_GENERIC;
856 return hr;
859 static HRESULT WINAPI IDirectPlaySPImpl_SetSPData
860 ( LPDIRECTPLAYSP iface,
861 LPVOID lpData,
862 DWORD dwDataSize,
863 DWORD dwFlags
866 LPVOID lpSpData;
868 ICOM_THIS(IDirectPlaySPImpl,iface);
870 /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
871 TRACE( "(%p)->(%p,0x%08lx,0x%08lx)\n",
872 This, lpData, dwDataSize, dwFlags );
874 #if 0
875 /* This is what the documentation says... */
876 if( dwFlags != DPSET_REMOTE )
878 return DPERR_INVALIDPARAMS;
880 #else
881 /* ... but most service providers call this with 1 */
882 /* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
883 * thing?
885 if( dwFlags != DPSET_REMOTE )
887 TRACE( "Undocumented dwFlags 0x%08lx used\n", dwFlags );
889 #endif
891 lpSpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
892 CopyMemory( lpSpData, lpData, dwDataSize );
894 /* If we have data already allocated, free it and replace it */
895 if( dwFlags == DPSET_REMOTE )
897 if( This->sp->lpSpRemoteData )
899 HeapFree( GetProcessHeap(), 0, This->sp->lpSpRemoteData );
902 This->sp->dwSpRemoteDataSize = dwDataSize;
903 This->sp->lpSpRemoteData = lpSpData;
905 else if ( dwFlags == DPSET_LOCAL )
907 if( This->sp->lpSpLocalData )
909 HeapFree( GetProcessHeap(), 0, This->sp->lpSpLocalData );
912 This->sp->lpSpLocalData = lpSpData;
913 This->sp->dwSpLocalDataSize = dwDataSize;
916 return DP_OK;
919 static VOID WINAPI IDirectPlaySPImpl_SendComplete
920 ( LPDIRECTPLAYSP iface,
921 LPVOID unknownA,
922 DWORD unknownB
925 ICOM_THIS(IDirectPlaySPImpl,iface);
927 FIXME( "(%p)->(%p,0x%08lx): stub\n",
928 This, unknownA, unknownB );
932 static struct ICOM_VTABLE(IDirectPlaySP) directPlaySPVT =
934 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
936 DPSP_QueryInterface,
937 DPSP_AddRef,
938 DPSP_Release,
940 IDirectPlaySPImpl_AddMRUEntry,
941 IDirectPlaySPImpl_CreateAddress,
942 IDirectPlaySPImpl_EnumAddress,
943 IDirectPlaySPImpl_EnumMRUEntries,
944 IDirectPlaySPImpl_GetPlayerFlags,
945 IDirectPlaySPImpl_GetSPPlayerData,
946 IDirectPlaySPImpl_HandleMessage,
947 IDirectPlaySPImpl_SetSPPlayerData,
948 IDirectPlaySPImpl_CreateCompoundAddress,
949 IDirectPlaySPImpl_GetSPData,
950 IDirectPlaySPImpl_SetSPData,
951 IDirectPlaySPImpl_SendComplete
955 /* DP external interfaces to call into DPSP interface */
957 /* Allocate the structure */
958 extern LPVOID DPSP_CreateSPPlayerData(void)
960 TRACE( "Creating SPPlayer data struct\n" );
961 return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
962 sizeof( DP_SPPLAYERDATA ) );