Fixed callback parameters (bogus hWave); added acm conversion for
[wine.git] / dlls / dplayx / dplaysp.c
bloba66198110695cfc473467ed9f9ef1908330e6e4b
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 "heap.h"
9 #include "winerror.h"
10 #include "debugtools.h"
12 #include "dpinit.h"
13 #include "dplaysp.h"
14 #include "dplay_global.h"
15 #include "name_server.h"
16 #include "dplayx_messages.h"
18 #include "dplayx_global.h" /* FIXME: For global hack */
20 /* FIXME: Need to add interface locking inside procedures */
22 DEFAULT_DEBUG_CHANNEL(dplay);
24 /* Prototypes */
25 static BOOL DPSP_CreateIUnknown( LPVOID lpSP );
26 static BOOL DPSP_DestroyIUnknown( LPVOID lpSP );
27 static BOOL DPSP_CreateDirectPlaySP( LPVOID lpSP, IDirectPlay2Impl* dp );
28 static BOOL DPSP_DestroyDirectPlaySP( LPVOID lpSP );
30 /* Predefine the interface */
31 typedef struct IDirectPlaySPImpl IDirectPlaySPImpl;
33 typedef struct tagDirectPlaySPIUnknownData
35 ULONG ulObjRef;
36 CRITICAL_SECTION DPSP_lock;
37 } DirectPlaySPIUnknownData;
39 typedef struct tagDirectPlaySPData
41 LPVOID lpSpRemoteData;
42 DWORD dwSpRemoteDataSize; /* Size of data pointed to by lpSpRemoteData */
44 LPVOID lpSpLocalData;
45 DWORD dwSpLocalDataSize; /* Size of data pointed to by lpSpLocalData */
47 IDirectPlay2Impl* dplay; /* FIXME: This should perhaps be iface not impl */
49 } DirectPlaySPData;
51 #define DPSP_IMPL_FIELDS \
52 ULONG ulInterfaceRef; \
53 DirectPlaySPIUnknownData* unk; \
54 DirectPlaySPData* sp;
56 struct IDirectPlaySPImpl
58 ICOM_VFIELD(IDirectPlaySP);
59 DPSP_IMPL_FIELDS
62 /* Forward declaration of virtual tables */
63 static ICOM_VTABLE(IDirectPlaySP) directPlaySPVT;
65 /* This structure is passed to the DP object for safe keeping */
66 typedef struct tagDP_SPPLAYERDATA
68 LPVOID lpPlayerLocalData;
69 DWORD dwPlayerLocalDataSize;
71 LPVOID lpPlayerRemoteData;
72 DWORD dwPlayerRemoteDataSize;
73 } DP_SPPLAYERDATA, *LPDP_SPPLAYERDATA;
75 /* Create the SP interface */
76 extern
77 HRESULT DPSP_CreateInterface( REFIID riid, LPVOID* ppvObj, IDirectPlay2Impl* dp )
79 TRACE( " for %s\n", debugstr_guid( riid ) );
81 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
82 sizeof( IDirectPlaySPImpl ) );
84 if( *ppvObj == NULL )
86 return DPERR_OUTOFMEMORY;
89 if( IsEqualGUID( &IID_IDirectPlaySP, riid ) )
91 ICOM_THIS(IDirectPlaySPImpl,*ppvObj);
92 ICOM_VTBL(This) = &directPlaySPVT;
94 else
96 /* Unsupported interface */
97 HeapFree( GetProcessHeap(), 0, *ppvObj );
98 *ppvObj = NULL;
100 return E_NOINTERFACE;
103 /* Initialize it */
104 if( DPSP_CreateIUnknown( *ppvObj ) &&
105 DPSP_CreateDirectPlaySP( *ppvObj, dp )
108 IDirectPlaySP_AddRef( (LPDIRECTPLAYSP)*ppvObj );
109 return S_OK;
112 /* Initialize failed, destroy it */
113 DPSP_DestroyDirectPlaySP( *ppvObj );
114 DPSP_DestroyIUnknown( *ppvObj );
116 HeapFree( GetProcessHeap(), 0, *ppvObj );
117 *ppvObj = NULL;
119 return DPERR_NOMEMORY;
122 static BOOL DPSP_CreateIUnknown( LPVOID lpSP )
124 ICOM_THIS(IDirectPlaySPImpl,lpSP);
126 This->unk = (DirectPlaySPIUnknownData*)HeapAlloc( GetProcessHeap(),
127 HEAP_ZERO_MEMORY,
128 sizeof( *(This->unk) ) );
130 if ( This->unk == NULL )
132 return FALSE;
135 InitializeCriticalSection( &This->unk->DPSP_lock );
137 return TRUE;
140 static BOOL DPSP_DestroyIUnknown( LPVOID lpSP )
142 ICOM_THIS(IDirectPlaySPImpl,lpSP);
144 DeleteCriticalSection( &This->unk->DPSP_lock );
145 HeapFree( GetProcessHeap(), 0, This->unk );
147 return TRUE;
151 static BOOL DPSP_CreateDirectPlaySP( LPVOID lpSP, IDirectPlay2Impl* dp )
153 ICOM_THIS(IDirectPlaySPImpl,lpSP);
155 This->sp = (DirectPlaySPData*)HeapAlloc( GetProcessHeap(),
156 HEAP_ZERO_MEMORY,
157 sizeof( *(This->sp) ) );
159 if ( This->sp == NULL )
161 return FALSE;
164 This->sp->dplay = dp;
166 /* Normally we should be keeping a reference, but since only the dplay
167 * interface that created us can destroy us, we do not keep a reference
168 * to it (ie we'd be stuck with always having one reference to the dplay
169 * object, and hence us, around).
170 * NOTE: The dp object does reference count us.
172 * FIXME: This is a kludge to get around a problem where a queryinterface
173 * is used to get a new interface and then is closed. We will then
174 * reference garbage. However, with this we will never deallocate
175 * the interface we store. The correct fix is to require all
176 * DP internal interfaces to use the This->dp2 interface which
177 * should be changed to This->dp
179 IDirectPlayX_AddRef( (LPDIRECTPLAY2)dp );
181 return TRUE;
184 static BOOL DPSP_DestroyDirectPlaySP( LPVOID lpSP )
186 ICOM_THIS(IDirectPlaySPImpl,lpSP);
188 /* Normally we should be keeping a reference, but since only the dplay
189 * interface that created us can destroy us, we do not keep a reference
190 * to it (ie we'd be stuck with always having one reference to the dplay
191 * object, and hence us, around).
192 * NOTE: The dp object does reference count us.
194 /*IDirectPlayX_Release( (LPDIRECTPLAY2)This->sp->dplay ); */
196 HeapFree( GetProcessHeap(), 0, This->sp->lpSpRemoteData );
197 HeapFree( GetProcessHeap(), 0, This->sp->lpSpLocalData );
199 /* FIXME: Need to delete player queue */
201 HeapFree( GetProcessHeap(), 0, This->sp );
202 return TRUE;
205 /* Interface implementation */
207 static HRESULT WINAPI DPSP_QueryInterface
208 ( LPDIRECTPLAYSP iface,
209 REFIID riid,
210 LPVOID* ppvObj )
212 ICOM_THIS(IDirectPlaySPImpl,iface);
213 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
215 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
216 sizeof( *This ) );
218 if( *ppvObj == NULL )
220 return DPERR_OUTOFMEMORY;
223 CopyMemory( *ppvObj, This, sizeof( *This ) );
224 (*(IDirectPlaySPImpl**)ppvObj)->ulInterfaceRef = 0;
226 if( IsEqualGUID( &IID_IDirectPlaySP, riid ) )
228 ICOM_THIS(IDirectPlaySPImpl,*ppvObj);
229 ICOM_VTBL(This) = &directPlaySPVT;
231 else
233 /* Unsupported interface */
234 HeapFree( GetProcessHeap(), 0, *ppvObj );
235 *ppvObj = NULL;
237 return E_NOINTERFACE;
240 IDirectPlaySP_AddRef( (LPDIRECTPLAYSP)*ppvObj );
242 return S_OK;
245 static ULONG WINAPI DPSP_AddRef
246 ( LPDIRECTPLAYSP iface )
248 ULONG ulInterfaceRefCount, ulObjRefCount;
249 ICOM_THIS(IDirectPlaySPImpl,iface);
251 ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
252 ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
254 TRACE( "ref count incremented to %lu:%lu for %p\n",
255 ulInterfaceRefCount, ulObjRefCount, This );
257 return ulObjRefCount;
260 static ULONG WINAPI DPSP_Release
261 ( LPDIRECTPLAYSP iface )
263 ULONG ulInterfaceRefCount, ulObjRefCount;
264 ICOM_THIS(IDirectPlaySPImpl,iface);
266 ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
267 ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
269 TRACE( "ref count decremented to %lu:%lu for %p\n",
270 ulInterfaceRefCount, ulObjRefCount, This );
272 /* Deallocate if this is the last reference to the object */
273 if( ulObjRefCount == 0 )
275 DPSP_DestroyDirectPlaySP( This );
276 DPSP_DestroyIUnknown( This );
279 if( ulInterfaceRefCount == 0 )
281 HeapFree( GetProcessHeap(), 0, This );
284 return ulInterfaceRefCount;
287 static HRESULT WINAPI IDirectPlaySPImpl_AddMRUEntry
288 ( LPDIRECTPLAYSP iface,
289 LPCWSTR lpSection,
290 LPCWSTR lpKey,
291 LPCVOID lpData,
292 DWORD dwDataSize,
293 DWORD dwMaxEntries
296 ICOM_THIS(IDirectPlaySPImpl,iface);
298 /* Should be able to call the comctl32 undocumented MRU routines.
299 I suspect that the interface works appropriately */
300 FIXME( "(%p)->(%p,%p%p,0x%08lx,0x%08lx): stub\n",
301 This, lpSection, lpKey, lpData, dwDataSize, dwMaxEntries );
303 return DP_OK;
306 static HRESULT WINAPI IDirectPlaySPImpl_CreateAddress
307 ( LPDIRECTPLAYSP iface,
308 REFGUID guidSP,
309 REFGUID guidDataType,
310 LPCVOID lpData,
311 DWORD dwDataSize,
312 LPVOID lpAddress,
313 LPDWORD lpdwAddressSize
316 ICOM_THIS(IDirectPlaySPImpl,iface);
318 FIXME( "(%p)->(%s,%s,%p,0x%08lx,%p,%p): stub\n",
319 This, debugstr_guid(guidSP), debugstr_guid(guidDataType),
320 lpData, dwDataSize, lpAddress, lpdwAddressSize );
322 return DP_OK;
325 static HRESULT WINAPI IDirectPlaySPImpl_EnumAddress
326 ( LPDIRECTPLAYSP iface,
327 LPDPENUMADDRESSCALLBACK lpEnumAddressCallback,
328 LPCVOID lpAddress,
329 DWORD dwAddressSize,
330 LPVOID lpContext
333 ICOM_THIS(IDirectPlaySPImpl,iface);
335 TRACE( "(%p)->(%p,%p,0x%08lx,%p)\n",
336 This, lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
338 DPL_EnumAddress( lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
340 return DP_OK;
343 static HRESULT WINAPI IDirectPlaySPImpl_EnumMRUEntries
344 ( LPDIRECTPLAYSP iface,
345 LPCWSTR lpSection,
346 LPCWSTR lpKey,
347 LPENUMMRUCALLBACK lpEnumMRUCallback,
348 LPVOID lpContext
351 ICOM_THIS(IDirectPlaySPImpl,iface);
353 /* Should be able to call the comctl32 undocumented MRU routines.
354 I suspect that the interface works appropriately */
355 FIXME( "(%p)->(%p,%p,%p,%p,): stub\n",
356 This, lpSection, lpKey, lpEnumMRUCallback, lpContext );
358 return DP_OK;
361 static HRESULT WINAPI IDirectPlaySPImpl_GetPlayerFlags
362 ( LPDIRECTPLAYSP iface,
363 DPID idPlayer,
364 LPDWORD lpdwPlayerFlags
367 ICOM_THIS(IDirectPlaySPImpl,iface);
369 FIXME( "(%p)->(0x%08lx,%p): stub\n",
370 This, idPlayer, lpdwPlayerFlags );
372 return DP_OK;
375 static HRESULT WINAPI IDirectPlaySPImpl_GetSPPlayerData
376 ( LPDIRECTPLAYSP iface,
377 DPID idPlayer,
378 LPVOID* lplpData,
379 LPDWORD lpdwDataSize,
380 DWORD dwFlags
383 HRESULT hr;
384 LPDP_SPPLAYERDATA lpPlayerData;
385 ICOM_THIS(IDirectPlaySPImpl,iface);
387 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx)\n",
388 This, idPlayer, lplpData, lpdwDataSize, dwFlags );
390 hr = DP_GetSPPlayerData( This->sp->dplay, idPlayer, (LPVOID*)&lpPlayerData );
392 if( FAILED(hr) )
394 TRACE( "Couldn't get player data: %s\n", DPLAYX_HresultToString(hr) );
395 return DPERR_INVALIDPLAYER;
398 /* What to do in the case where there is nothing set yet? */
399 if( dwFlags == DPSET_LOCAL )
401 if( lpPlayerData->lpPlayerLocalData )
403 HeapFree( GetProcessHeap(), 0, lpPlayerData->lpPlayerLocalData );
406 *lplpData = lpPlayerData->lpPlayerLocalData;
407 *lpdwDataSize = lpPlayerData->dwPlayerLocalDataSize;
409 else if( dwFlags == DPSET_REMOTE )
411 if( lpPlayerData->lpPlayerRemoteData )
413 HeapFree( GetProcessHeap(), 0, lpPlayerData->lpPlayerRemoteData );
416 *lplpData = lpPlayerData->lpPlayerRemoteData;
417 *lpdwDataSize = lpPlayerData->dwPlayerRemoteDataSize;
420 if( *lplpData == NULL )
422 hr = DPERR_GENERIC;
425 return hr;
428 static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage
429 ( LPDIRECTPLAYSP iface,
430 LPVOID lpMessageBody,
431 DWORD dwMessageBodySize,
432 LPVOID lpMessageHeader
435 LPDPMSG_SENDENVELOPE lpMsg = (LPDPMSG_SENDENVELOPE)lpMessageBody;
436 HRESULT hr = DPERR_GENERIC;
437 WORD wCommandId;
438 WORD wVersion;
439 DPSP_REPLYDATA data;
441 ICOM_THIS(IDirectPlaySPImpl,iface);
443 FIXME( "(%p)->(%p,0x%08lx,%p): mostly stub\n",
444 This, lpMessageBody, dwMessageBodySize, lpMessageHeader );
446 wCommandId = lpMsg->wCommandId;
447 wVersion = lpMsg->wVersion;
449 TRACE( "Incomming message has envelope of 0x%08lx, %u, %u\n",
450 lpMsg->dwMagic, wCommandId, wVersion );
452 if( lpMsg->dwMagic != DPMSGMAGIC_DPLAYMSG )
454 ERR( "Unknown magic 0x%08lx!\n", lpMsg->dwMagic );
455 return DPERR_GENERIC;
458 #if 0
460 const LPDWORD lpcHeader = (LPDWORD)lpMessageHeader;
462 TRACE( "lpMessageHeader = [0x%08lx] [0x%08lx] [0x%08lx] [0x%08lx] [0x%08lx]\n",
463 lpcHeader[0], lpcHeader[1], lpcHeader[2], lpcHeader[3], lpcHeader[4] );
465 #endif
467 /* Pass everything else to Direct Play */
468 data.lpMessage = NULL;
469 data.dwMessageSize = 0;
471 /* Pass this message to the dplay interface to handle */
472 hr = DP_HandleMessage( This->sp->dplay, lpMessageBody, dwMessageBodySize,
473 lpMessageHeader, wCommandId, wVersion,
474 &data.lpMessage, &data.dwMessageSize );
476 if( FAILED(hr) )
478 ERR( "Command processing failed %s\n", DPLAYX_HresultToString(hr) );
481 /* Do we want a reply? */
482 if( data.lpMessage != NULL )
484 data.lpSPMessageHeader = lpMessageHeader;
485 data.idNameServer = 0;
486 data.lpISP = iface;
488 hr = (This->sp->dplay->dp2->spData.lpCB->Reply)( &data );
490 if( FAILED(hr) )
492 ERR( "Reply failed %s\n", DPLAYX_HresultToString(hr) );
496 return hr;
498 #if 0
499 HRESULT hr = DP_OK;
500 HANDLE hReceiveEvent = 0;
501 /* FIXME: Aquire some sort of interface lock */
502 /* FIXME: Need some sort of context for this callback. Need to determine
503 * how this is actually done with the SP
505 /* FIXME: Who needs to delete the message when done? */
506 switch( lpMsg->dwType )
508 case DPSYS_CREATEPLAYERORGROUP:
510 LPDPMSG_CREATEPLAYERORGROUP msg = (LPDPMSG_CREATEPLAYERORGROUP)lpMsg;
512 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
514 hr = DP_IF_CreatePlayer( This, lpMessageHeader, msg->dpId,
515 &msg->dpnName, 0, msg->lpData,
516 msg->dwDataSize, msg->dwFlags, ... );
518 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
520 /* Group in group situation? */
521 if( msg->dpIdParent == DPID_NOPARENT_GROUP )
523 hr = DP_IF_CreateGroup( This, lpMessageHeader, msg->dpId,
524 &msg->dpnName, 0, msg->lpData,
525 msg->dwDataSize, msg->dwFlags, ... );
527 else /* Group in Group */
529 hr = DP_IF_CreateGroupInGroup( This, lpMessageHeader, msg->dpIdParent,
530 &msg->dpnName, 0, msg->lpData,
531 msg->dwDataSize, msg->dwFlags, ... );
534 else /* Hmmm? */
536 ERR( "Corrupt msg->dwPlayerType for DPSYS_CREATEPLAYERORGROUP\n" );
537 return;
540 break;
543 case DPSYS_DESTROYPLAYERORGROUP:
545 LPDPMSG_DESTROYPLAYERORGROUP msg = (LPDPMSG_DESTROYPLAYERORGROUP)lpMsg;
547 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
549 hr = DP_IF_DestroyPlayer( This, msg->dpId, ... );
551 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
553 hr = DP_IF_DestroyGroup( This, msg->dpId, ... );
555 else /* Hmmm? */
557 ERR( "Corrupt msg->dwPlayerType for DPSYS_DESTROYPLAYERORGROUP\n" );
558 return;
561 break;
564 case DPSYS_ADDPLAYERTOGROUP:
566 LPDPMSG_ADDPLAYERTOGROUP msg = (LPDPMSG_ADDPLAYERTOGROUP)lpMsg;
568 hr = DP_IF_AddPlayerToGroup( This, msg->dpIdGroup, msg->dpIdPlayer, ... );
569 break;
572 case DPSYS_DELETEPLAYERFROMGROUP:
574 LPDPMSG_DELETEPLAYERFROMGROUP msg = (LPDPMSG_DELETEPLAYERFROMGROUP)lpMsg;
576 hr = DP_IF_DeletePlayerFromGroup( This, msg->dpIdGroup, msg->dpIdPlayer,
577 ... );
579 break;
582 case DPSYS_SESSIONLOST:
584 LPDPMSG_SESSIONLOST msg = (LPDPMSG_SESSIONLOST)lpMsg;
586 FIXME( "DPSYS_SESSIONLOST not handled\n" );
588 break;
591 case DPSYS_HOST:
593 LPDPMSG_HOST msg = (LPDPMSG_HOST)lpMsg;
595 FIXME( "DPSYS_HOST not handled\n" );
597 break;
600 case DPSYS_SETPLAYERORGROUPDATA:
602 LPDPMSG_SETPLAYERORGROUPDATA msg = (LPDPMSG_SETPLAYERORGROUPDATA)lpMsg;
604 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
606 hr = DP_IF_SetPlayerData( This, msg->dpId, msg->lpData, msg->dwDataSize, DPSET_REMOTE, ... );
608 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
610 hr = DP_IF_SetGroupData( This, msg->dpId, msg->lpData, msg->dwDataSize,
611 DPSET_REMOTE, ... );
613 else /* Hmmm? */
615 ERR( "Corrupt msg->dwPlayerType for LPDPMSG_SETPLAYERORGROUPDATA\n" );
616 return;
619 break;
622 case DPSYS_SETPLAYERORGROUPNAME:
624 LPDPMSG_SETPLAYERORGROUPNAME msg = (LPDPMSG_SETPLAYERORGROUPNAME)lpMsg;
626 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
628 hr = DP_IF_SetPlayerName( This, msg->dpId, msg->dpnName, ... );
630 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
632 hr = DP_IF_SetGroupName( This, msg->dpId, msg->dpnName, ... );
634 else /* Hmmm? */
636 ERR( "Corrupt msg->dwPlayerType for LPDPMSG_SETPLAYERORGROUPDATA\n" );
637 return;
640 break;
643 case DPSYS_SETSESSIONDESC;
645 LPDPMSG_SETSESSIONDESC msg = (LPDPMSG_SETSESSIONDESC)lpMsg;
647 hr = DP_IF_SetSessionDesc( This, &msg->dpDesc );
649 break;
652 case DPSYS_ADDGROUPTOGROUP:
654 LPDPMSG_ADDGROUPTOGROUP msg = (LPDPMSG_ADDGROUPTOGROUP)lpMsg;
656 hr = DP_IF_AddGroupToGroup( This, msg->dpIdParentGroup, msg->dpIdGroup,
657 ... );
659 break;
662 case DPSYS_DELETEGROUPFROMGROUP:
664 LPDPMSG_DELETEGROUPFROMGROUP msg = (LPDPMSG_DELETEGROUPFROMGROUP)lpMsg;
666 hr = DP_IF_DeleteGroupFromGroup( This, msg->dpIdParentGroup,
667 msg->dpIdGroup, ... );
669 break;
672 case DPSYS_SECUREMESSAGE:
674 LPDPMSG_SECUREMESSAGE msg = (LPDPMSG_SECUREMESSAGE)lpMsg;
676 FIXME( "DPSYS_SECUREMESSAGE not implemented\n" );
678 break;
681 case DPSYS_STARTSESSION:
683 LPDPMSG_STARTSESSION msg = (LPDPMSG_STARTSESSION)lpMsg;
685 FIXME( "DPSYS_STARTSESSION not implemented\n" );
687 break;
690 case DPSYS_CHAT:
692 LPDPMSG_CHAT msg = (LPDPMSG_CHAT)lpMsg;
694 FIXME( "DPSYS_CHAT not implemeneted\n" );
696 break;
699 case DPSYS_SETGROUPOWNER:
701 LPDPMSG_SETGROUPOWNER msg = (LPDPMSG_SETGROUPOWNER)lpMsg;
703 FIXME( "DPSYS_SETGROUPOWNER not implemented\n" );
705 break;
708 case DPSYS_SENDCOMPLETE:
710 LPDPMSG_SENDCOMPLETE msg = (LPDPMSG_SENDCOMPLETE)lpMsg;
712 FIXME( "DPSYS_SENDCOMPLETE not implemented\n" );
714 break;
717 default:
719 /* NOTE: This should be a user defined type. There is nothing that we
720 * need to do with it except queue it.
722 TRACE( "Received user message type(?) 0x%08lx through SP.\n",
723 lpMsg->dwType );
724 break;
728 FIXME( "Queue message in the receive queue. Need some context data!\n" );
730 if( FAILED(hr) )
732 ERR( "Unable to perform action for msg type 0x%08lx\n", lpMsg->dwType );
734 /* If a receieve event was registered for this player, invoke it */
735 if( hReceiveEvent )
737 SetEvent( hReceiveEvent );
739 #endif
742 static HRESULT WINAPI IDirectPlaySPImpl_SetSPPlayerData
743 ( LPDIRECTPLAYSP iface,
744 DPID idPlayer,
745 LPVOID lpData,
746 DWORD dwDataSize,
747 DWORD dwFlags
750 HRESULT hr;
751 LPDP_SPPLAYERDATA lpPlayerEntry;
752 LPVOID lpPlayerData;
754 ICOM_THIS(IDirectPlaySPImpl,iface);
756 /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
757 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx)\n",
758 This, idPlayer, lpData, dwDataSize, dwFlags );
760 hr = DP_GetSPPlayerData( This->sp->dplay, idPlayer, (LPVOID*)&lpPlayerEntry );
761 if( FAILED(hr) )
763 /* Player must not exist */
764 return DPERR_INVALIDPLAYER;
767 lpPlayerData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
768 CopyMemory( lpPlayerData, lpData, dwDataSize );
770 if( dwFlags == DPSET_LOCAL )
772 lpPlayerEntry->lpPlayerLocalData = lpPlayerData;
773 lpPlayerEntry->dwPlayerLocalDataSize = dwDataSize;
775 else if( dwFlags == DPSET_REMOTE )
777 lpPlayerEntry->lpPlayerRemoteData = lpPlayerData;
778 lpPlayerEntry->dwPlayerRemoteDataSize = dwDataSize;
781 hr = DP_SetSPPlayerData( This->sp->dplay, idPlayer, lpPlayerEntry );
783 return hr;
786 static HRESULT WINAPI IDirectPlaySPImpl_CreateCompoundAddress
787 ( LPDIRECTPLAYSP iface,
788 LPCDPCOMPOUNDADDRESSELEMENT lpElements,
789 DWORD dwElementCount,
790 LPVOID lpAddress,
791 LPDWORD lpdwAddressSize
794 ICOM_THIS(IDirectPlaySPImpl,iface);
796 FIXME( "(%p)->(%p,0x%08lx,%p,%p): stub\n",
797 This, lpElements, dwElementCount, lpAddress, lpdwAddressSize );
799 return DP_OK;
802 static HRESULT WINAPI IDirectPlaySPImpl_GetSPData
803 ( LPDIRECTPLAYSP iface,
804 LPVOID* lplpData,
805 LPDWORD lpdwDataSize,
806 DWORD dwFlags
809 HRESULT hr = DP_OK;
810 ICOM_THIS(IDirectPlaySPImpl,iface);
812 /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
813 TRACE( "(%p)->(%p,%p,0x%08lx)\n",
814 This, lplpData, lpdwDataSize, dwFlags );
816 #if 0
817 /* This is what the documentation says... */
818 if( dwFlags != DPSET_REMOTE )
820 return DPERR_INVALIDPARAMS;
822 #else
823 /* ... but most service providers call this with 1 */
824 /* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
825 * thing?
827 if( dwFlags != DPSET_REMOTE )
829 TRACE( "Undocumented dwFlags 0x%08lx used\n", dwFlags );
831 #endif
833 /* FIXME: What to do in the case where this isn't initialized yet? */
835 /* Yes, we're supposed to return a pointer to the memory we have stored! */
836 if( dwFlags == DPSET_REMOTE )
838 *lpdwDataSize = This->sp->dwSpRemoteDataSize;
839 *lplpData = This->sp->lpSpRemoteData;
841 if( This->sp->lpSpRemoteData == NULL )
843 hr = DPERR_GENERIC;
846 else if( dwFlags == DPSET_LOCAL )
848 *lpdwDataSize = This->sp->dwSpLocalDataSize;
849 *lplpData = This->sp->lpSpLocalData;
851 if( This->sp->lpSpLocalData == NULL )
853 hr = DPERR_GENERIC;
857 return hr;
860 static HRESULT WINAPI IDirectPlaySPImpl_SetSPData
861 ( LPDIRECTPLAYSP iface,
862 LPVOID lpData,
863 DWORD dwDataSize,
864 DWORD dwFlags
867 LPVOID lpSpData;
869 ICOM_THIS(IDirectPlaySPImpl,iface);
871 /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
872 TRACE( "(%p)->(%p,0x%08lx,0x%08lx)\n",
873 This, lpData, dwDataSize, dwFlags );
875 #if 0
876 /* This is what the documentation says... */
877 if( dwFlags != DPSET_REMOTE )
879 return DPERR_INVALIDPARAMS;
881 #else
882 /* ... but most service providers call this with 1 */
883 /* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
884 * thing?
886 if( dwFlags != DPSET_REMOTE )
888 TRACE( "Undocumented dwFlags 0x%08lx used\n", dwFlags );
890 #endif
892 lpSpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
893 CopyMemory( lpSpData, lpData, dwDataSize );
895 /* If we have data already allocated, free it and replace it */
896 if( dwFlags == DPSET_REMOTE )
898 if( This->sp->lpSpRemoteData )
900 HeapFree( GetProcessHeap(), 0, This->sp->lpSpRemoteData );
903 This->sp->dwSpRemoteDataSize = dwDataSize;
904 This->sp->lpSpRemoteData = lpSpData;
906 else if ( dwFlags == DPSET_LOCAL )
908 if( This->sp->lpSpLocalData )
910 HeapFree( GetProcessHeap(), 0, This->sp->lpSpLocalData );
913 This->sp->lpSpLocalData = lpSpData;
914 This->sp->dwSpLocalDataSize = dwDataSize;
917 return DP_OK;
920 static VOID WINAPI IDirectPlaySPImpl_SendComplete
921 ( LPDIRECTPLAYSP iface,
922 LPVOID unknownA,
923 DWORD unknownB
926 ICOM_THIS(IDirectPlaySPImpl,iface);
928 FIXME( "(%p)->(%p,0x%08lx): stub\n",
929 This, unknownA, unknownB );
933 static struct ICOM_VTABLE(IDirectPlaySP) directPlaySPVT =
935 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
937 DPSP_QueryInterface,
938 DPSP_AddRef,
939 DPSP_Release,
941 IDirectPlaySPImpl_AddMRUEntry,
942 IDirectPlaySPImpl_CreateAddress,
943 IDirectPlaySPImpl_EnumAddress,
944 IDirectPlaySPImpl_EnumMRUEntries,
945 IDirectPlaySPImpl_GetPlayerFlags,
946 IDirectPlaySPImpl_GetSPPlayerData,
947 IDirectPlaySPImpl_HandleMessage,
948 IDirectPlaySPImpl_SetSPPlayerData,
949 IDirectPlaySPImpl_CreateCompoundAddress,
950 IDirectPlaySPImpl_GetSPData,
951 IDirectPlaySPImpl_SetSPData,
952 IDirectPlaySPImpl_SendComplete
956 /* DP external interfaces to call into DPSP interface */
958 /* Allocate the structure */
959 extern LPVOID DPSP_CreateSPPlayerData(void)
961 TRACE( "Creating SPPlayer data struct\n" );
962 return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
963 sizeof( DP_SPPLAYERDATA ) );