user32/tests: Test MDI child order changing caused by WM_MDINEXT.
[wine/multimedia.git] / dlls / dplayx / dplaysp.c
blob899348e24acdda0a2a86a39e3ebe375c6019a603
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 "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);
36 /* Prototypes */
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
47 LONG ulObjRef;
48 CRITICAL_SECTION DPSP_lock;
49 } DirectPlaySPIUnknownData;
51 typedef struct tagDirectPlaySPData
53 LPVOID lpSpRemoteData;
54 DWORD dwSpRemoteDataSize; /* Size of data pointed to by lpSpRemoteData */
56 LPVOID lpSpLocalData;
57 DWORD dwSpLocalDataSize; /* Size of data pointed to by lpSpLocalData */
59 IDirectPlayImpl *dplay; /* FIXME: This should perhaps be iface not impl */
61 } DirectPlaySPData;
63 #define DPSP_IMPL_FIELDS \
64 LONG ulInterfaceRef; \
65 DirectPlaySPIUnknownData* unk; \
66 DirectPlaySPData* sp;
68 struct IDirectPlaySPImpl
70 const IDirectPlaySPVtbl *lpVtbl;
71 DPSP_IMPL_FIELDS
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 ) );
95 if( *ppvObj == NULL )
97 return DPERR_OUTOFMEMORY;
100 if( IsEqualGUID( &IID_IDirectPlaySP, riid ) )
102 IDirectPlaySPImpl *This = *ppvObj;
103 This->lpVtbl = &directPlaySPVT;
105 else
107 /* Unsupported interface */
108 HeapFree( GetProcessHeap(), 0, *ppvObj );
109 *ppvObj = NULL;
111 return E_NOINTERFACE;
114 /* Initialize it */
115 if( DPSP_CreateIUnknown( *ppvObj ) &&
116 DPSP_CreateDirectPlaySP( *ppvObj, dp )
119 IDirectPlaySP_AddRef( (LPDIRECTPLAYSP)*ppvObj );
120 return S_OK;
123 /* Initialize failed, destroy it */
124 DPSP_DestroyDirectPlaySP( *ppvObj );
125 DPSP_DestroyIUnknown( *ppvObj );
127 HeapFree( GetProcessHeap(), 0, *ppvObj );
128 *ppvObj = NULL;
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 )
141 return FALSE;
144 InitializeCriticalSection( &This->unk->DPSP_lock );
145 This->unk->DPSP_lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectPlaySPImpl*->DirectPlaySPIUnknownData*->DPSP_lock");
147 return TRUE;
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 );
158 return TRUE;
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 )
170 return FALSE;
173 This->sp->dplay = dp;
175 return TRUE;
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 );
188 return TRUE;
191 /* Interface implementation */
193 static HRESULT WINAPI DPSP_QueryInterface
194 ( LPDIRECTPLAYSP iface,
195 REFIID riid,
196 LPVOID* ppvObj )
198 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
199 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
201 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
202 sizeof( *This ) );
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;
217 else
219 /* Unsupported interface */
220 HeapFree( GetProcessHeap(), 0, *ppvObj );
221 *ppvObj = NULL;
223 return E_NOINTERFACE;
226 IDirectPlaySP_AddRef( (LPDIRECTPLAYSP)*ppvObj );
228 return S_OK;
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,
275 LPCWSTR lpSection,
276 LPCWSTR lpKey,
277 LPCVOID lpData,
278 DWORD dwDataSize,
279 DWORD dwMaxEntries
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 );
289 return DP_OK;
292 static HRESULT WINAPI IDirectPlaySPImpl_CreateAddress
293 ( LPDIRECTPLAYSP iface,
294 REFGUID guidSP,
295 REFGUID guidDataType,
296 LPCVOID lpData,
297 DWORD dwDataSize,
298 LPVOID lpAddress,
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 );
308 return DP_OK;
311 static HRESULT WINAPI IDirectPlaySPImpl_EnumAddress
312 ( LPDIRECTPLAYSP iface,
313 LPDPENUMADDRESSCALLBACK lpEnumAddressCallback,
314 LPCVOID lpAddress,
315 DWORD dwAddressSize,
316 LPVOID lpContext
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 );
326 return DP_OK;
329 static HRESULT WINAPI IDirectPlaySPImpl_EnumMRUEntries
330 ( LPDIRECTPLAYSP iface,
331 LPCWSTR lpSection,
332 LPCWSTR lpKey,
333 LPENUMMRUCALLBACK lpEnumMRUCallback,
334 LPVOID lpContext
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 );
344 return DP_OK;
347 static HRESULT WINAPI IDirectPlaySPImpl_GetPlayerFlags
348 ( LPDIRECTPLAYSP iface,
349 DPID idPlayer,
350 LPDWORD lpdwPlayerFlags
353 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
355 FIXME( "(%p)->(0x%08x,%p): stub\n",
356 This, idPlayer, lpdwPlayerFlags );
358 return DP_OK;
361 static HRESULT WINAPI IDirectPlaySPImpl_GetSPPlayerData
362 ( LPDIRECTPLAYSP iface,
363 DPID idPlayer,
364 LPVOID* lplpData,
365 LPDWORD lpdwDataSize,
366 DWORD dwFlags
369 HRESULT hr;
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 );
378 if( FAILED(hr) )
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 *lplpData = lpPlayerData->lpPlayerLocalData;
388 *lpdwDataSize = lpPlayerData->dwPlayerLocalDataSize;
390 else if( dwFlags == DPSET_REMOTE )
392 *lplpData = lpPlayerData->lpPlayerRemoteData;
393 *lpdwDataSize = lpPlayerData->dwPlayerRemoteDataSize;
396 if( *lplpData == NULL )
398 hr = DPERR_GENERIC;
401 return hr;
404 static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage
405 ( LPDIRECTPLAYSP iface,
406 LPVOID lpMessageBody,
407 DWORD dwMessageBodySize,
408 LPVOID lpMessageHeader
411 LPDPMSG_SENDENVELOPE lpMsg = lpMessageBody;
412 HRESULT hr = DPERR_GENERIC;
413 WORD wCommandId;
414 WORD wVersion;
415 DPSP_REPLYDATA data;
417 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
419 FIXME( "(%p)->(%p,0x%08x,%p): mostly stub\n",
420 This, lpMessageBody, dwMessageBodySize, lpMessageHeader );
422 wCommandId = lpMsg->wCommandId;
423 wVersion = lpMsg->wVersion;
425 TRACE( "Incoming message has envelope of 0x%08x, %u, %u\n",
426 lpMsg->dwMagic, wCommandId, wVersion );
428 if( lpMsg->dwMagic != DPMSGMAGIC_DPLAYMSG )
430 ERR( "Unknown magic 0x%08x!\n", lpMsg->dwMagic );
431 return DPERR_GENERIC;
434 #if 0
436 const LPDWORD lpcHeader = lpMessageHeader;
438 TRACE( "lpMessageHeader = [0x%08lx] [0x%08lx] [0x%08lx] [0x%08lx] [0x%08lx]\n",
439 lpcHeader[0], lpcHeader[1], lpcHeader[2], lpcHeader[3], lpcHeader[4] );
441 #endif
443 /* Pass everything else to Direct Play */
444 data.lpMessage = NULL;
445 data.dwMessageSize = 0;
447 /* Pass this message to the dplay interface to handle */
448 hr = DP_HandleMessage( This->sp->dplay, lpMessageBody, dwMessageBodySize,
449 lpMessageHeader, wCommandId, wVersion,
450 &data.lpMessage, &data.dwMessageSize );
452 if( FAILED(hr) )
454 ERR( "Command processing failed %s\n", DPLAYX_HresultToString(hr) );
457 /* Do we want a reply? */
458 if( data.lpMessage != NULL )
460 data.lpSPMessageHeader = lpMessageHeader;
461 data.idNameServer = 0;
462 data.lpISP = iface;
464 hr = (This->sp->dplay->dp2->spData.lpCB->Reply)( &data );
466 if( FAILED(hr) )
468 ERR( "Reply failed %s\n", DPLAYX_HresultToString(hr) );
472 return hr;
474 #if 0
475 HRESULT hr = DP_OK;
476 HANDLE hReceiveEvent = 0;
477 /* FIXME: Acquire some sort of interface lock */
478 /* FIXME: Need some sort of context for this callback. Need to determine
479 * how this is actually done with the SP
481 /* FIXME: Who needs to delete the message when done? */
482 switch( lpMsg->dwType )
484 case DPSYS_CREATEPLAYERORGROUP:
486 LPDPMSG_CREATEPLAYERORGROUP msg = lpMsg;
488 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
490 hr = DP_IF_CreatePlayer( This, lpMessageHeader, msg->dpId,
491 &msg->dpnName, 0, msg->lpData,
492 msg->dwDataSize, msg->dwFlags, ... );
494 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
496 /* Group in group situation? */
497 if( msg->dpIdParent == DPID_NOPARENT_GROUP )
499 hr = DP_IF_CreateGroup( This, lpMessageHeader, msg->dpId,
500 &msg->dpnName, 0, msg->lpData,
501 msg->dwDataSize, msg->dwFlags, ... );
503 else /* Group in Group */
505 hr = DP_IF_CreateGroupInGroup( This, lpMessageHeader, msg->dpIdParent,
506 &msg->dpnName, 0, msg->lpData,
507 msg->dwDataSize, msg->dwFlags, ... );
510 else /* Hmmm? */
512 ERR( "Corrupt msg->dwPlayerType for DPSYS_CREATEPLAYERORGROUP\n" );
513 return;
516 break;
519 case DPSYS_DESTROYPLAYERORGROUP:
521 LPDPMSG_DESTROYPLAYERORGROUP msg = lpMsg;
523 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
525 hr = DP_IF_DestroyPlayer( This, msg->dpId, ... );
527 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
529 hr = DP_IF_DestroyGroup( This, msg->dpId, ... );
531 else /* Hmmm? */
533 ERR( "Corrupt msg->dwPlayerType for DPSYS_DESTROYPLAYERORGROUP\n" );
534 return;
537 break;
540 case DPSYS_ADDPLAYERTOGROUP:
542 LPDPMSG_ADDPLAYERTOGROUP msg = lpMsg;
544 hr = DP_IF_AddPlayerToGroup( This, msg->dpIdGroup, msg->dpIdPlayer, ... );
545 break;
548 case DPSYS_DELETEPLAYERFROMGROUP:
550 LPDPMSG_DELETEPLAYERFROMGROUP msg = lpMsg;
552 hr = DP_IF_DeletePlayerFromGroup( This, msg->dpIdGroup, msg->dpIdPlayer,
553 ... );
555 break;
558 case DPSYS_SESSIONLOST:
560 LPDPMSG_SESSIONLOST msg = lpMsg;
562 FIXME( "DPSYS_SESSIONLOST not handled\n" );
564 break;
567 case DPSYS_HOST:
569 LPDPMSG_HOST msg = lpMsg;
571 FIXME( "DPSYS_HOST not handled\n" );
573 break;
576 case DPSYS_SETPLAYERORGROUPDATA:
578 LPDPMSG_SETPLAYERORGROUPDATA msg = lpMsg;
580 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
582 hr = DP_IF_SetPlayerData( This, msg->dpId, msg->lpData, msg->dwDataSize, DPSET_REMOTE, ... );
584 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
586 hr = DP_IF_SetGroupData( This, msg->dpId, msg->lpData, msg->dwDataSize,
587 DPSET_REMOTE, ... );
589 else /* Hmmm? */
591 ERR( "Corrupt msg->dwPlayerType for LPDPMSG_SETPLAYERORGROUPDATA\n" );
592 return;
595 break;
598 case DPSYS_SETPLAYERORGROUPNAME:
600 LPDPMSG_SETPLAYERORGROUPNAME msg = lpMsg;
602 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
604 hr = DP_IF_SetPlayerName( This, msg->dpId, msg->dpnName, ... );
606 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
608 hr = DP_IF_SetGroupName( This, msg->dpId, msg->dpnName, ... );
610 else /* Hmmm? */
612 ERR( "Corrupt msg->dwPlayerType for LPDPMSG_SETPLAYERORGROUPDATA\n" );
613 return;
616 break;
619 case DPSYS_SETSESSIONDESC;
621 LPDPMSG_SETSESSIONDESC msg = lpMsg;
623 hr = DP_IF_SetSessionDesc( This, &msg->dpDesc );
625 break;
628 case DPSYS_ADDGROUPTOGROUP:
630 LPDPMSG_ADDGROUPTOGROUP msg = lpMsg;
632 hr = DP_IF_AddGroupToGroup( This, msg->dpIdParentGroup, msg->dpIdGroup,
633 ... );
635 break;
638 case DPSYS_DELETEGROUPFROMGROUP:
640 LPDPMSG_DELETEGROUPFROMGROUP msg = lpMsg;
642 hr = DP_IF_DeleteGroupFromGroup( This, msg->dpIdParentGroup,
643 msg->dpIdGroup, ... );
645 break;
648 case DPSYS_SECUREMESSAGE:
650 LPDPMSG_SECUREMESSAGE msg = lpMsg;
652 FIXME( "DPSYS_SECUREMESSAGE not implemented\n" );
654 break;
657 case DPSYS_STARTSESSION:
659 LPDPMSG_STARTSESSION msg = lpMsg;
661 FIXME( "DPSYS_STARTSESSION not implemented\n" );
663 break;
666 case DPSYS_CHAT:
668 LPDPMSG_CHAT msg = lpMsg;
670 FIXME( "DPSYS_CHAT not implemeneted\n" );
672 break;
675 case DPSYS_SETGROUPOWNER:
677 LPDPMSG_SETGROUPOWNER msg = lpMsg;
679 FIXME( "DPSYS_SETGROUPOWNER not implemented\n" );
681 break;
684 case DPSYS_SENDCOMPLETE:
686 LPDPMSG_SENDCOMPLETE msg = lpMsg;
688 FIXME( "DPSYS_SENDCOMPLETE not implemented\n" );
690 break;
693 default:
695 /* NOTE: This should be a user defined type. There is nothing that we
696 * need to do with it except queue it.
698 TRACE( "Received user message type(?) 0x%08lx through SP.\n",
699 lpMsg->dwType );
700 break;
704 FIXME( "Queue message in the receive queue. Need some context data!\n" );
706 if( FAILED(hr) )
708 ERR( "Unable to perform action for msg type 0x%08lx\n", lpMsg->dwType );
710 /* If a receive event was registered for this player, invoke it */
711 if( hReceiveEvent )
713 SetEvent( hReceiveEvent );
715 #endif
718 static HRESULT WINAPI IDirectPlaySPImpl_SetSPPlayerData
719 ( LPDIRECTPLAYSP iface,
720 DPID idPlayer,
721 LPVOID lpData,
722 DWORD dwDataSize,
723 DWORD dwFlags
726 HRESULT hr;
727 LPDP_SPPLAYERDATA lpPlayerEntry;
728 LPVOID lpPlayerData;
730 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
732 /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
733 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x)\n",
734 This, idPlayer, lpData, dwDataSize, dwFlags );
736 hr = DP_GetSPPlayerData( This->sp->dplay, idPlayer, (LPVOID*)&lpPlayerEntry );
737 if( FAILED(hr) )
739 /* Player must not exist */
740 return DPERR_INVALIDPLAYER;
743 lpPlayerData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
744 CopyMemory( lpPlayerData, lpData, dwDataSize );
746 if( dwFlags == DPSET_LOCAL )
748 lpPlayerEntry->lpPlayerLocalData = lpPlayerData;
749 lpPlayerEntry->dwPlayerLocalDataSize = dwDataSize;
751 else if( dwFlags == DPSET_REMOTE )
753 lpPlayerEntry->lpPlayerRemoteData = lpPlayerData;
754 lpPlayerEntry->dwPlayerRemoteDataSize = dwDataSize;
757 hr = DP_SetSPPlayerData( This->sp->dplay, idPlayer, lpPlayerEntry );
759 return hr;
762 static HRESULT WINAPI IDirectPlaySPImpl_CreateCompoundAddress
763 ( LPDIRECTPLAYSP iface,
764 LPCDPCOMPOUNDADDRESSELEMENT lpElements,
765 DWORD dwElementCount,
766 LPVOID lpAddress,
767 LPDWORD lpdwAddressSize
770 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
772 FIXME( "(%p)->(%p,0x%08x,%p,%p): stub\n",
773 This, lpElements, dwElementCount, lpAddress, lpdwAddressSize );
775 return DP_OK;
778 static HRESULT WINAPI IDirectPlaySPImpl_GetSPData
779 ( LPDIRECTPLAYSP iface,
780 LPVOID* lplpData,
781 LPDWORD lpdwDataSize,
782 DWORD dwFlags
785 HRESULT hr = DP_OK;
786 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
788 /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
789 TRACE( "(%p)->(%p,%p,0x%08x)\n",
790 This, lplpData, lpdwDataSize, dwFlags );
792 #if 0
793 /* This is what the documentation says... */
794 if( dwFlags != DPSET_REMOTE )
796 return DPERR_INVALIDPARAMS;
798 #else
799 /* ... but most service providers call this with 1 */
800 /* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
801 * thing?
803 if( dwFlags != DPSET_REMOTE )
805 TRACE( "Undocumented dwFlags 0x%08x used\n", dwFlags );
807 #endif
809 /* FIXME: What to do in the case where this isn't initialized yet? */
811 /* Yes, we're supposed to return a pointer to the memory we have stored! */
812 if( dwFlags == DPSET_REMOTE )
814 *lpdwDataSize = This->sp->dwSpRemoteDataSize;
815 *lplpData = This->sp->lpSpRemoteData;
817 if( This->sp->lpSpRemoteData == NULL )
819 hr = DPERR_GENERIC;
822 else if( dwFlags == DPSET_LOCAL )
824 *lpdwDataSize = This->sp->dwSpLocalDataSize;
825 *lplpData = This->sp->lpSpLocalData;
827 if( This->sp->lpSpLocalData == NULL )
829 hr = DPERR_GENERIC;
833 return hr;
836 static HRESULT WINAPI IDirectPlaySPImpl_SetSPData
837 ( LPDIRECTPLAYSP iface,
838 LPVOID lpData,
839 DWORD dwDataSize,
840 DWORD dwFlags
843 LPVOID lpSpData;
845 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
847 /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
848 TRACE( "(%p)->(%p,0x%08x,0x%08x)\n",
849 This, lpData, dwDataSize, dwFlags );
851 #if 0
852 /* This is what the documentation says... */
853 if( dwFlags != DPSET_REMOTE )
855 return DPERR_INVALIDPARAMS;
857 #else
858 /* ... but most service providers call this with 1 */
859 /* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
860 * thing?
862 if( dwFlags != DPSET_REMOTE )
864 TRACE( "Undocumented dwFlags 0x%08x used\n", dwFlags );
866 #endif
868 lpSpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
869 CopyMemory( lpSpData, lpData, dwDataSize );
871 /* If we have data already allocated, free it and replace it */
872 if( dwFlags == DPSET_REMOTE )
874 HeapFree( GetProcessHeap(), 0, This->sp->lpSpRemoteData );
875 This->sp->dwSpRemoteDataSize = dwDataSize;
876 This->sp->lpSpRemoteData = lpSpData;
878 else if ( dwFlags == DPSET_LOCAL )
880 HeapFree( GetProcessHeap(), 0, This->sp->lpSpLocalData );
881 This->sp->lpSpLocalData = lpSpData;
882 This->sp->dwSpLocalDataSize = dwDataSize;
885 return DP_OK;
888 static VOID WINAPI IDirectPlaySPImpl_SendComplete
889 ( LPDIRECTPLAYSP iface,
890 LPVOID unknownA,
891 DWORD unknownB
894 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
896 FIXME( "(%p)->(%p,0x%08x): stub\n",
897 This, unknownA, unknownB );
900 static const IDirectPlaySPVtbl directPlaySPVT =
903 DPSP_QueryInterface,
904 DPSP_AddRef,
905 DPSP_Release,
907 IDirectPlaySPImpl_AddMRUEntry,
908 IDirectPlaySPImpl_CreateAddress,
909 IDirectPlaySPImpl_EnumAddress,
910 IDirectPlaySPImpl_EnumMRUEntries,
911 IDirectPlaySPImpl_GetPlayerFlags,
912 IDirectPlaySPImpl_GetSPPlayerData,
913 IDirectPlaySPImpl_HandleMessage,
914 IDirectPlaySPImpl_SetSPPlayerData,
915 IDirectPlaySPImpl_CreateCompoundAddress,
916 IDirectPlaySPImpl_GetSPData,
917 IDirectPlaySPImpl_SetSPData,
918 IDirectPlaySPImpl_SendComplete
922 /* DP external interfaces to call into DPSP interface */
924 /* Allocate the structure */
925 LPVOID DPSP_CreateSPPlayerData(void)
927 TRACE( "Creating SPPlayer data struct\n" );
928 return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
929 sizeof( DP_SPPLAYERDATA ) );