d3drm: Implement IDirect3DRMFrameX_AddTransform.
[wine/multimedia.git] / dlls / dplayx / dplaysp.c
blobbd3e2c18dc53a699c9daf70454010fab6eb72bf2
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
21 #include <string.h>
22 #include "winerror.h"
23 #include "wine/debug.h"
25 #include "dpinit.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);
37 /* Prototypes */
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
48 LONG ulObjRef;
49 CRITICAL_SECTION DPSP_lock;
50 } DirectPlaySPIUnknownData;
52 typedef struct tagDirectPlaySPData
54 LPVOID lpSpRemoteData;
55 DWORD dwSpRemoteDataSize; /* Size of data pointed to by lpSpRemoteData */
57 LPVOID lpSpLocalData;
58 DWORD dwSpLocalDataSize; /* Size of data pointed to by lpSpLocalData */
60 IDirectPlay2Impl* dplay; /* FIXME: This should perhaps be iface not impl */
62 } DirectPlaySPData;
64 #define DPSP_IMPL_FIELDS \
65 LONG ulInterfaceRef; \
66 DirectPlaySPIUnknownData* unk; \
67 DirectPlaySPData* sp;
69 struct IDirectPlaySPImpl
71 const IDirectPlaySPVtbl *lpVtbl;
72 DPSP_IMPL_FIELDS
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 ) );
96 if( *ppvObj == NULL )
98 return DPERR_OUTOFMEMORY;
101 if( IsEqualGUID( &IID_IDirectPlaySP, riid ) )
103 IDirectPlaySPImpl *This = *ppvObj;
104 This->lpVtbl = &directPlaySPVT;
106 else
108 /* Unsupported interface */
109 HeapFree( GetProcessHeap(), 0, *ppvObj );
110 *ppvObj = NULL;
112 return E_NOINTERFACE;
115 /* Initialize it */
116 if( DPSP_CreateIUnknown( *ppvObj ) &&
117 DPSP_CreateDirectPlaySP( *ppvObj, dp )
120 IDirectPlaySP_AddRef( (LPDIRECTPLAYSP)*ppvObj );
121 return S_OK;
124 /* Initialize failed, destroy it */
125 DPSP_DestroyDirectPlaySP( *ppvObj );
126 DPSP_DestroyIUnknown( *ppvObj );
128 HeapFree( GetProcessHeap(), 0, *ppvObj );
129 *ppvObj = NULL;
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 )
142 return FALSE;
145 InitializeCriticalSection( &This->unk->DPSP_lock );
146 This->unk->DPSP_lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectPlaySPImpl*->DirectPlaySPIUnknownData*->DPSP_lock");
148 return TRUE;
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 );
159 return TRUE;
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 )
171 return FALSE;
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 );
191 return TRUE;
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 );
212 return TRUE;
215 /* Interface implementation */
217 static HRESULT WINAPI DPSP_QueryInterface
218 ( LPDIRECTPLAYSP iface,
219 REFIID riid,
220 LPVOID* ppvObj )
222 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
223 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
225 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
226 sizeof( *This ) );
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;
241 else
243 /* Unsupported interface */
244 HeapFree( GetProcessHeap(), 0, *ppvObj );
245 *ppvObj = NULL;
247 return E_NOINTERFACE;
250 IDirectPlaySP_AddRef( (LPDIRECTPLAYSP)*ppvObj );
252 return S_OK;
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,
299 LPCWSTR lpSection,
300 LPCWSTR lpKey,
301 LPCVOID lpData,
302 DWORD dwDataSize,
303 DWORD dwMaxEntries
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 );
313 return DP_OK;
316 static HRESULT WINAPI IDirectPlaySPImpl_CreateAddress
317 ( LPDIRECTPLAYSP iface,
318 REFGUID guidSP,
319 REFGUID guidDataType,
320 LPCVOID lpData,
321 DWORD dwDataSize,
322 LPVOID lpAddress,
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 );
332 return DP_OK;
335 static HRESULT WINAPI IDirectPlaySPImpl_EnumAddress
336 ( LPDIRECTPLAYSP iface,
337 LPDPENUMADDRESSCALLBACK lpEnumAddressCallback,
338 LPCVOID lpAddress,
339 DWORD dwAddressSize,
340 LPVOID lpContext
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 );
350 return DP_OK;
353 static HRESULT WINAPI IDirectPlaySPImpl_EnumMRUEntries
354 ( LPDIRECTPLAYSP iface,
355 LPCWSTR lpSection,
356 LPCWSTR lpKey,
357 LPENUMMRUCALLBACK lpEnumMRUCallback,
358 LPVOID lpContext
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 );
368 return DP_OK;
371 static HRESULT WINAPI IDirectPlaySPImpl_GetPlayerFlags
372 ( LPDIRECTPLAYSP iface,
373 DPID idPlayer,
374 LPDWORD lpdwPlayerFlags
377 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
379 FIXME( "(%p)->(0x%08x,%p): stub\n",
380 This, idPlayer, lpdwPlayerFlags );
382 return DP_OK;
385 static HRESULT WINAPI IDirectPlaySPImpl_GetSPPlayerData
386 ( LPDIRECTPLAYSP iface,
387 DPID idPlayer,
388 LPVOID* lplpData,
389 LPDWORD lpdwDataSize,
390 DWORD dwFlags
393 HRESULT hr;
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 );
402 if( FAILED(hr) )
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 )
424 hr = DPERR_GENERIC;
427 return hr;
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;
439 WORD wCommandId;
440 WORD wVersion;
441 DPSP_REPLYDATA data;
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;
460 #if 0
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] );
467 #endif
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 );
478 if( FAILED(hr) )
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;
488 data.lpISP = iface;
490 hr = (This->sp->dplay->dp2->spData.lpCB->Reply)( &data );
492 if( FAILED(hr) )
494 ERR( "Reply failed %s\n", DPLAYX_HresultToString(hr) );
498 return hr;
500 #if 0
501 HRESULT hr = DP_OK;
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, ... );
536 else /* Hmmm? */
538 ERR( "Corrupt msg->dwPlayerType for DPSYS_CREATEPLAYERORGROUP\n" );
539 return;
542 break;
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, ... );
557 else /* Hmmm? */
559 ERR( "Corrupt msg->dwPlayerType for DPSYS_DESTROYPLAYERORGROUP\n" );
560 return;
563 break;
566 case DPSYS_ADDPLAYERTOGROUP:
568 LPDPMSG_ADDPLAYERTOGROUP msg = lpMsg;
570 hr = DP_IF_AddPlayerToGroup( This, msg->dpIdGroup, msg->dpIdPlayer, ... );
571 break;
574 case DPSYS_DELETEPLAYERFROMGROUP:
576 LPDPMSG_DELETEPLAYERFROMGROUP msg = lpMsg;
578 hr = DP_IF_DeletePlayerFromGroup( This, msg->dpIdGroup, msg->dpIdPlayer,
579 ... );
581 break;
584 case DPSYS_SESSIONLOST:
586 LPDPMSG_SESSIONLOST msg = lpMsg;
588 FIXME( "DPSYS_SESSIONLOST not handled\n" );
590 break;
593 case DPSYS_HOST:
595 LPDPMSG_HOST msg = lpMsg;
597 FIXME( "DPSYS_HOST not handled\n" );
599 break;
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,
613 DPSET_REMOTE, ... );
615 else /* Hmmm? */
617 ERR( "Corrupt msg->dwPlayerType for LPDPMSG_SETPLAYERORGROUPDATA\n" );
618 return;
621 break;
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, ... );
636 else /* Hmmm? */
638 ERR( "Corrupt msg->dwPlayerType for LPDPMSG_SETPLAYERORGROUPDATA\n" );
639 return;
642 break;
645 case DPSYS_SETSESSIONDESC;
647 LPDPMSG_SETSESSIONDESC msg = lpMsg;
649 hr = DP_IF_SetSessionDesc( This, &msg->dpDesc );
651 break;
654 case DPSYS_ADDGROUPTOGROUP:
656 LPDPMSG_ADDGROUPTOGROUP msg = lpMsg;
658 hr = DP_IF_AddGroupToGroup( This, msg->dpIdParentGroup, msg->dpIdGroup,
659 ... );
661 break;
664 case DPSYS_DELETEGROUPFROMGROUP:
666 LPDPMSG_DELETEGROUPFROMGROUP msg = lpMsg;
668 hr = DP_IF_DeleteGroupFromGroup( This, msg->dpIdParentGroup,
669 msg->dpIdGroup, ... );
671 break;
674 case DPSYS_SECUREMESSAGE:
676 LPDPMSG_SECUREMESSAGE msg = lpMsg;
678 FIXME( "DPSYS_SECUREMESSAGE not implemented\n" );
680 break;
683 case DPSYS_STARTSESSION:
685 LPDPMSG_STARTSESSION msg = lpMsg;
687 FIXME( "DPSYS_STARTSESSION not implemented\n" );
689 break;
692 case DPSYS_CHAT:
694 LPDPMSG_CHAT msg = lpMsg;
696 FIXME( "DPSYS_CHAT not implemeneted\n" );
698 break;
701 case DPSYS_SETGROUPOWNER:
703 LPDPMSG_SETGROUPOWNER msg = lpMsg;
705 FIXME( "DPSYS_SETGROUPOWNER not implemented\n" );
707 break;
710 case DPSYS_SENDCOMPLETE:
712 LPDPMSG_SENDCOMPLETE msg = lpMsg;
714 FIXME( "DPSYS_SENDCOMPLETE not implemented\n" );
716 break;
719 default:
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",
725 lpMsg->dwType );
726 break;
730 FIXME( "Queue message in the receive queue. Need some context data!\n" );
732 if( FAILED(hr) )
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 */
737 if( hReceiveEvent )
739 SetEvent( hReceiveEvent );
741 #endif
744 static HRESULT WINAPI IDirectPlaySPImpl_SetSPPlayerData
745 ( LPDIRECTPLAYSP iface,
746 DPID idPlayer,
747 LPVOID lpData,
748 DWORD dwDataSize,
749 DWORD dwFlags
752 HRESULT hr;
753 LPDP_SPPLAYERDATA lpPlayerEntry;
754 LPVOID lpPlayerData;
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 );
763 if( FAILED(hr) )
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 );
785 return hr;
788 static HRESULT WINAPI IDirectPlaySPImpl_CreateCompoundAddress
789 ( LPDIRECTPLAYSP iface,
790 LPCDPCOMPOUNDADDRESSELEMENT lpElements,
791 DWORD dwElementCount,
792 LPVOID lpAddress,
793 LPDWORD lpdwAddressSize
796 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
798 FIXME( "(%p)->(%p,0x%08x,%p,%p): stub\n",
799 This, lpElements, dwElementCount, lpAddress, lpdwAddressSize );
801 return DP_OK;
804 static HRESULT WINAPI IDirectPlaySPImpl_GetSPData
805 ( LPDIRECTPLAYSP iface,
806 LPVOID* lplpData,
807 LPDWORD lpdwDataSize,
808 DWORD dwFlags
811 HRESULT hr = DP_OK;
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 );
818 #if 0
819 /* This is what the documentation says... */
820 if( dwFlags != DPSET_REMOTE )
822 return DPERR_INVALIDPARAMS;
824 #else
825 /* ... but most service providers call this with 1 */
826 /* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
827 * thing?
829 if( dwFlags != DPSET_REMOTE )
831 TRACE( "Undocumented dwFlags 0x%08x used\n", dwFlags );
833 #endif
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 )
845 hr = DPERR_GENERIC;
848 else if( dwFlags == DPSET_LOCAL )
850 *lpdwDataSize = This->sp->dwSpLocalDataSize;
851 *lplpData = This->sp->lpSpLocalData;
853 if( This->sp->lpSpLocalData == NULL )
855 hr = DPERR_GENERIC;
859 return hr;
862 static HRESULT WINAPI IDirectPlaySPImpl_SetSPData
863 ( LPDIRECTPLAYSP iface,
864 LPVOID lpData,
865 DWORD dwDataSize,
866 DWORD dwFlags
869 LPVOID lpSpData;
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 );
877 #if 0
878 /* This is what the documentation says... */
879 if( dwFlags != DPSET_REMOTE )
881 return DPERR_INVALIDPARAMS;
883 #else
884 /* ... but most service providers call this with 1 */
885 /* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
886 * thing?
888 if( dwFlags != DPSET_REMOTE )
890 TRACE( "Undocumented dwFlags 0x%08x used\n", dwFlags );
892 #endif
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;
911 return DP_OK;
914 static VOID WINAPI IDirectPlaySPImpl_SendComplete
915 ( LPDIRECTPLAYSP iface,
916 LPVOID unknownA,
917 DWORD unknownB
920 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
922 FIXME( "(%p)->(%p,0x%08x): stub\n",
923 This, unknownA, unknownB );
926 static const IDirectPlaySPVtbl directPlaySPVT =
929 DPSP_QueryInterface,
930 DPSP_AddRef,
931 DPSP_Release,
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 ) );