- Generate machine-local IPIDs.
[wine.git] / dlls / dplayx / dplaysp.c
blob548b281c792b8152d56401634eb87489c2904fa2
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <string.h>
22 #include "winerror.h"
23 #include "wine/debug.h"
25 #include "dpinit.h"
26 #include "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 ULONG 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 ULONG ulInterfaceRef; \
66 DirectPlaySPIUnknownData* unk; \
67 DirectPlaySPData* sp;
69 struct IDirectPlaySPImpl
71 IDirectPlaySPVtbl *lpVtbl;
72 DPSP_IMPL_FIELDS
75 /* Forward declaration of virtual tables */
76 static 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 extern
90 HRESULT DPSP_CreateInterface( REFIID riid, LPVOID* ppvObj, IDirectPlay2Impl* dp )
92 TRACE( " for %s\n", debugstr_guid( riid ) );
94 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
95 sizeof( IDirectPlaySPImpl ) );
97 if( *ppvObj == NULL )
99 return DPERR_OUTOFMEMORY;
102 if( IsEqualGUID( &IID_IDirectPlaySP, riid ) )
104 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)*ppvObj;
105 This->lpVtbl = &directPlaySPVT;
107 else
109 /* Unsupported interface */
110 HeapFree( GetProcessHeap(), 0, *ppvObj );
111 *ppvObj = NULL;
113 return E_NOINTERFACE;
116 /* Initialize it */
117 if( DPSP_CreateIUnknown( *ppvObj ) &&
118 DPSP_CreateDirectPlaySP( *ppvObj, dp )
121 IDirectPlaySP_AddRef( (LPDIRECTPLAYSP)*ppvObj );
122 return S_OK;
125 /* Initialize failed, destroy it */
126 DPSP_DestroyDirectPlaySP( *ppvObj );
127 DPSP_DestroyIUnknown( *ppvObj );
129 HeapFree( GetProcessHeap(), 0, *ppvObj );
130 *ppvObj = NULL;
132 return DPERR_NOMEMORY;
135 static BOOL DPSP_CreateIUnknown( LPVOID lpSP )
137 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)lpSP;
139 This->unk = (DirectPlaySPIUnknownData*)HeapAlloc( GetProcessHeap(),
140 HEAP_ZERO_MEMORY,
141 sizeof( *(This->unk) ) );
143 if ( This->unk == NULL )
145 return FALSE;
148 InitializeCriticalSection( &This->unk->DPSP_lock );
150 return TRUE;
153 static BOOL DPSP_DestroyIUnknown( LPVOID lpSP )
155 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)lpSP;
157 DeleteCriticalSection( &This->unk->DPSP_lock );
158 HeapFree( GetProcessHeap(), 0, This->unk );
160 return TRUE;
164 static BOOL DPSP_CreateDirectPlaySP( LPVOID lpSP, IDirectPlay2Impl* dp )
166 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)lpSP;
168 This->sp = (DirectPlaySPData*)HeapAlloc( GetProcessHeap(),
169 HEAP_ZERO_MEMORY,
170 sizeof( *(This->sp) ) );
172 if ( This->sp == NULL )
174 return FALSE;
177 This->sp->dplay = dp;
179 /* Normally we should be keeping a reference, but since only the dplay
180 * interface that created us can destroy us, we do not keep a reference
181 * to it (ie we'd be stuck with always having one reference to the dplay
182 * object, and hence us, around).
183 * NOTE: The dp object does reference count us.
185 * FIXME: This is a kludge to get around a problem where a queryinterface
186 * is used to get a new interface and then is closed. We will then
187 * reference garbage. However, with this we will never deallocate
188 * the interface we store. The correct fix is to require all
189 * DP internal interfaces to use the This->dp2 interface which
190 * should be changed to This->dp
192 IDirectPlayX_AddRef( (LPDIRECTPLAY2)dp );
194 return TRUE;
197 static BOOL DPSP_DestroyDirectPlaySP( LPVOID lpSP )
199 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)lpSP;
201 /* Normally we should be keeping a reference, but since only the dplay
202 * interface that created us can destroy us, we do not keep a reference
203 * to it (ie we'd be stuck with always having one reference to the dplay
204 * object, and hence us, around).
205 * NOTE: The dp object does reference count us.
207 /*IDirectPlayX_Release( (LPDIRECTPLAY2)This->sp->dplay ); */
209 HeapFree( GetProcessHeap(), 0, This->sp->lpSpRemoteData );
210 HeapFree( GetProcessHeap(), 0, This->sp->lpSpLocalData );
212 /* FIXME: Need to delete player queue */
214 HeapFree( GetProcessHeap(), 0, This->sp );
215 return TRUE;
218 /* Interface implementation */
220 static HRESULT WINAPI DPSP_QueryInterface
221 ( LPDIRECTPLAYSP iface,
222 REFIID riid,
223 LPVOID* ppvObj )
225 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
226 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
228 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
229 sizeof( *This ) );
231 if( *ppvObj == NULL )
233 return DPERR_OUTOFMEMORY;
236 CopyMemory( *ppvObj, This, sizeof( *This ) );
237 (*(IDirectPlaySPImpl**)ppvObj)->ulInterfaceRef = 0;
239 if( IsEqualGUID( &IID_IDirectPlaySP, riid ) )
241 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)*ppvObj;
242 This->lpVtbl = &directPlaySPVT;
244 else
246 /* Unsupported interface */
247 HeapFree( GetProcessHeap(), 0, *ppvObj );
248 *ppvObj = NULL;
250 return E_NOINTERFACE;
253 IDirectPlaySP_AddRef( (LPDIRECTPLAYSP)*ppvObj );
255 return S_OK;
258 static ULONG WINAPI DPSP_AddRef
259 ( LPDIRECTPLAYSP iface )
261 ULONG ulInterfaceRefCount, ulObjRefCount;
262 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
264 ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
265 ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
267 TRACE( "ref count incremented to %lu:%lu for %p\n",
268 ulInterfaceRefCount, ulObjRefCount, This );
270 return ulObjRefCount;
273 static ULONG WINAPI DPSP_Release
274 ( LPDIRECTPLAYSP iface )
276 ULONG ulInterfaceRefCount, ulObjRefCount;
277 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
279 ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
280 ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
282 TRACE( "ref count decremented to %lu:%lu for %p\n",
283 ulInterfaceRefCount, ulObjRefCount, This );
285 /* Deallocate if this is the last reference to the object */
286 if( ulObjRefCount == 0 )
288 DPSP_DestroyDirectPlaySP( This );
289 DPSP_DestroyIUnknown( This );
292 if( ulInterfaceRefCount == 0 )
294 HeapFree( GetProcessHeap(), 0, This );
297 return ulInterfaceRefCount;
300 static HRESULT WINAPI IDirectPlaySPImpl_AddMRUEntry
301 ( LPDIRECTPLAYSP iface,
302 LPCWSTR lpSection,
303 LPCWSTR lpKey,
304 LPCVOID lpData,
305 DWORD dwDataSize,
306 DWORD dwMaxEntries
309 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
311 /* Should be able to call the comctl32 undocumented MRU routines.
312 I suspect that the interface works appropriately */
313 FIXME( "(%p)->(%p,%p%p,0x%08lx,0x%08lx): stub\n",
314 This, lpSection, lpKey, lpData, dwDataSize, dwMaxEntries );
316 return DP_OK;
319 static HRESULT WINAPI IDirectPlaySPImpl_CreateAddress
320 ( LPDIRECTPLAYSP iface,
321 REFGUID guidSP,
322 REFGUID guidDataType,
323 LPCVOID lpData,
324 DWORD dwDataSize,
325 LPVOID lpAddress,
326 LPDWORD lpdwAddressSize
329 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
331 FIXME( "(%p)->(%s,%s,%p,0x%08lx,%p,%p): stub\n",
332 This, debugstr_guid(guidSP), debugstr_guid(guidDataType),
333 lpData, dwDataSize, lpAddress, lpdwAddressSize );
335 return DP_OK;
338 static HRESULT WINAPI IDirectPlaySPImpl_EnumAddress
339 ( LPDIRECTPLAYSP iface,
340 LPDPENUMADDRESSCALLBACK lpEnumAddressCallback,
341 LPCVOID lpAddress,
342 DWORD dwAddressSize,
343 LPVOID lpContext
346 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
348 TRACE( "(%p)->(%p,%p,0x%08lx,%p)\n",
349 This, lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
351 DPL_EnumAddress( lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
353 return DP_OK;
356 static HRESULT WINAPI IDirectPlaySPImpl_EnumMRUEntries
357 ( LPDIRECTPLAYSP iface,
358 LPCWSTR lpSection,
359 LPCWSTR lpKey,
360 LPENUMMRUCALLBACK lpEnumMRUCallback,
361 LPVOID lpContext
364 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
366 /* Should be able to call the comctl32 undocumented MRU routines.
367 I suspect that the interface works appropriately */
368 FIXME( "(%p)->(%p,%p,%p,%p,): stub\n",
369 This, lpSection, lpKey, lpEnumMRUCallback, lpContext );
371 return DP_OK;
374 static HRESULT WINAPI IDirectPlaySPImpl_GetPlayerFlags
375 ( LPDIRECTPLAYSP iface,
376 DPID idPlayer,
377 LPDWORD lpdwPlayerFlags
380 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
382 FIXME( "(%p)->(0x%08lx,%p): stub\n",
383 This, idPlayer, lpdwPlayerFlags );
385 return DP_OK;
388 static HRESULT WINAPI IDirectPlaySPImpl_GetSPPlayerData
389 ( LPDIRECTPLAYSP iface,
390 DPID idPlayer,
391 LPVOID* lplpData,
392 LPDWORD lpdwDataSize,
393 DWORD dwFlags
396 HRESULT hr;
397 LPDP_SPPLAYERDATA lpPlayerData;
398 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
400 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx)\n",
401 This, idPlayer, lplpData, lpdwDataSize, dwFlags );
403 hr = DP_GetSPPlayerData( This->sp->dplay, idPlayer, (LPVOID*)&lpPlayerData );
405 if( FAILED(hr) )
407 TRACE( "Couldn't get player data: %s\n", DPLAYX_HresultToString(hr) );
408 return DPERR_INVALIDPLAYER;
411 /* What to do in the case where there is nothing set yet? */
412 if( dwFlags == DPSET_LOCAL )
414 HeapFree( GetProcessHeap(), 0, lpPlayerData->lpPlayerLocalData );
415 *lplpData = lpPlayerData->lpPlayerLocalData;
416 *lpdwDataSize = lpPlayerData->dwPlayerLocalDataSize;
418 else if( dwFlags == DPSET_REMOTE )
420 HeapFree( GetProcessHeap(), 0, lpPlayerData->lpPlayerRemoteData );
421 *lplpData = lpPlayerData->lpPlayerRemoteData;
422 *lpdwDataSize = lpPlayerData->dwPlayerRemoteDataSize;
425 if( *lplpData == NULL )
427 hr = DPERR_GENERIC;
430 return hr;
433 static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage
434 ( LPDIRECTPLAYSP iface,
435 LPVOID lpMessageBody,
436 DWORD dwMessageBodySize,
437 LPVOID lpMessageHeader
440 LPDPMSG_SENDENVELOPE lpMsg = (LPDPMSG_SENDENVELOPE)lpMessageBody;
441 HRESULT hr = DPERR_GENERIC;
442 WORD wCommandId;
443 WORD wVersion;
444 DPSP_REPLYDATA data;
446 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
448 FIXME( "(%p)->(%p,0x%08lx,%p): mostly stub\n",
449 This, lpMessageBody, dwMessageBodySize, lpMessageHeader );
451 wCommandId = lpMsg->wCommandId;
452 wVersion = lpMsg->wVersion;
454 TRACE( "Incoming message has envelope of 0x%08lx, %u, %u\n",
455 lpMsg->dwMagic, wCommandId, wVersion );
457 if( lpMsg->dwMagic != DPMSGMAGIC_DPLAYMSG )
459 ERR( "Unknown magic 0x%08lx!\n", lpMsg->dwMagic );
460 return DPERR_GENERIC;
463 #if 0
465 const LPDWORD lpcHeader = (LPDWORD)lpMessageHeader;
467 TRACE( "lpMessageHeader = [0x%08lx] [0x%08lx] [0x%08lx] [0x%08lx] [0x%08lx]\n",
468 lpcHeader[0], lpcHeader[1], lpcHeader[2], lpcHeader[3], lpcHeader[4] );
470 #endif
472 /* Pass everything else to Direct Play */
473 data.lpMessage = NULL;
474 data.dwMessageSize = 0;
476 /* Pass this message to the dplay interface to handle */
477 hr = DP_HandleMessage( This->sp->dplay, lpMessageBody, dwMessageBodySize,
478 lpMessageHeader, wCommandId, wVersion,
479 &data.lpMessage, &data.dwMessageSize );
481 if( FAILED(hr) )
483 ERR( "Command processing failed %s\n", DPLAYX_HresultToString(hr) );
486 /* Do we want a reply? */
487 if( data.lpMessage != NULL )
489 data.lpSPMessageHeader = lpMessageHeader;
490 data.idNameServer = 0;
491 data.lpISP = iface;
493 hr = (This->sp->dplay->dp2->spData.lpCB->Reply)( &data );
495 if( FAILED(hr) )
497 ERR( "Reply failed %s\n", DPLAYX_HresultToString(hr) );
501 return hr;
503 #if 0
504 HRESULT hr = DP_OK;
505 HANDLE hReceiveEvent = 0;
506 /* FIXME: Aquire some sort of interface lock */
507 /* FIXME: Need some sort of context for this callback. Need to determine
508 * how this is actually done with the SP
510 /* FIXME: Who needs to delete the message when done? */
511 switch( lpMsg->dwType )
513 case DPSYS_CREATEPLAYERORGROUP:
515 LPDPMSG_CREATEPLAYERORGROUP msg = (LPDPMSG_CREATEPLAYERORGROUP)lpMsg;
517 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
519 hr = DP_IF_CreatePlayer( This, lpMessageHeader, msg->dpId,
520 &msg->dpnName, 0, msg->lpData,
521 msg->dwDataSize, msg->dwFlags, ... );
523 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
525 /* Group in group situation? */
526 if( msg->dpIdParent == DPID_NOPARENT_GROUP )
528 hr = DP_IF_CreateGroup( This, lpMessageHeader, msg->dpId,
529 &msg->dpnName, 0, msg->lpData,
530 msg->dwDataSize, msg->dwFlags, ... );
532 else /* Group in Group */
534 hr = DP_IF_CreateGroupInGroup( This, lpMessageHeader, msg->dpIdParent,
535 &msg->dpnName, 0, msg->lpData,
536 msg->dwDataSize, msg->dwFlags, ... );
539 else /* Hmmm? */
541 ERR( "Corrupt msg->dwPlayerType for DPSYS_CREATEPLAYERORGROUP\n" );
542 return;
545 break;
548 case DPSYS_DESTROYPLAYERORGROUP:
550 LPDPMSG_DESTROYPLAYERORGROUP msg = (LPDPMSG_DESTROYPLAYERORGROUP)lpMsg;
552 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
554 hr = DP_IF_DestroyPlayer( This, msg->dpId, ... );
556 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
558 hr = DP_IF_DestroyGroup( This, msg->dpId, ... );
560 else /* Hmmm? */
562 ERR( "Corrupt msg->dwPlayerType for DPSYS_DESTROYPLAYERORGROUP\n" );
563 return;
566 break;
569 case DPSYS_ADDPLAYERTOGROUP:
571 LPDPMSG_ADDPLAYERTOGROUP msg = (LPDPMSG_ADDPLAYERTOGROUP)lpMsg;
573 hr = DP_IF_AddPlayerToGroup( This, msg->dpIdGroup, msg->dpIdPlayer, ... );
574 break;
577 case DPSYS_DELETEPLAYERFROMGROUP:
579 LPDPMSG_DELETEPLAYERFROMGROUP msg = (LPDPMSG_DELETEPLAYERFROMGROUP)lpMsg;
581 hr = DP_IF_DeletePlayerFromGroup( This, msg->dpIdGroup, msg->dpIdPlayer,
582 ... );
584 break;
587 case DPSYS_SESSIONLOST:
589 LPDPMSG_SESSIONLOST msg = (LPDPMSG_SESSIONLOST)lpMsg;
591 FIXME( "DPSYS_SESSIONLOST not handled\n" );
593 break;
596 case DPSYS_HOST:
598 LPDPMSG_HOST msg = (LPDPMSG_HOST)lpMsg;
600 FIXME( "DPSYS_HOST not handled\n" );
602 break;
605 case DPSYS_SETPLAYERORGROUPDATA:
607 LPDPMSG_SETPLAYERORGROUPDATA msg = (LPDPMSG_SETPLAYERORGROUPDATA)lpMsg;
609 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
611 hr = DP_IF_SetPlayerData( This, msg->dpId, msg->lpData, msg->dwDataSize, DPSET_REMOTE, ... );
613 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
615 hr = DP_IF_SetGroupData( This, msg->dpId, msg->lpData, msg->dwDataSize,
616 DPSET_REMOTE, ... );
618 else /* Hmmm? */
620 ERR( "Corrupt msg->dwPlayerType for LPDPMSG_SETPLAYERORGROUPDATA\n" );
621 return;
624 break;
627 case DPSYS_SETPLAYERORGROUPNAME:
629 LPDPMSG_SETPLAYERORGROUPNAME msg = (LPDPMSG_SETPLAYERORGROUPNAME)lpMsg;
631 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
633 hr = DP_IF_SetPlayerName( This, msg->dpId, msg->dpnName, ... );
635 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
637 hr = DP_IF_SetGroupName( This, msg->dpId, msg->dpnName, ... );
639 else /* Hmmm? */
641 ERR( "Corrupt msg->dwPlayerType for LPDPMSG_SETPLAYERORGROUPDATA\n" );
642 return;
645 break;
648 case DPSYS_SETSESSIONDESC;
650 LPDPMSG_SETSESSIONDESC msg = (LPDPMSG_SETSESSIONDESC)lpMsg;
652 hr = DP_IF_SetSessionDesc( This, &msg->dpDesc );
654 break;
657 case DPSYS_ADDGROUPTOGROUP:
659 LPDPMSG_ADDGROUPTOGROUP msg = (LPDPMSG_ADDGROUPTOGROUP)lpMsg;
661 hr = DP_IF_AddGroupToGroup( This, msg->dpIdParentGroup, msg->dpIdGroup,
662 ... );
664 break;
667 case DPSYS_DELETEGROUPFROMGROUP:
669 LPDPMSG_DELETEGROUPFROMGROUP msg = (LPDPMSG_DELETEGROUPFROMGROUP)lpMsg;
671 hr = DP_IF_DeleteGroupFromGroup( This, msg->dpIdParentGroup,
672 msg->dpIdGroup, ... );
674 break;
677 case DPSYS_SECUREMESSAGE:
679 LPDPMSG_SECUREMESSAGE msg = (LPDPMSG_SECUREMESSAGE)lpMsg;
681 FIXME( "DPSYS_SECUREMESSAGE not implemented\n" );
683 break;
686 case DPSYS_STARTSESSION:
688 LPDPMSG_STARTSESSION msg = (LPDPMSG_STARTSESSION)lpMsg;
690 FIXME( "DPSYS_STARTSESSION not implemented\n" );
692 break;
695 case DPSYS_CHAT:
697 LPDPMSG_CHAT msg = (LPDPMSG_CHAT)lpMsg;
699 FIXME( "DPSYS_CHAT not implemeneted\n" );
701 break;
704 case DPSYS_SETGROUPOWNER:
706 LPDPMSG_SETGROUPOWNER msg = (LPDPMSG_SETGROUPOWNER)lpMsg;
708 FIXME( "DPSYS_SETGROUPOWNER not implemented\n" );
710 break;
713 case DPSYS_SENDCOMPLETE:
715 LPDPMSG_SENDCOMPLETE msg = (LPDPMSG_SENDCOMPLETE)lpMsg;
717 FIXME( "DPSYS_SENDCOMPLETE not implemented\n" );
719 break;
722 default:
724 /* NOTE: This should be a user defined type. There is nothing that we
725 * need to do with it except queue it.
727 TRACE( "Received user message type(?) 0x%08lx through SP.\n",
728 lpMsg->dwType );
729 break;
733 FIXME( "Queue message in the receive queue. Need some context data!\n" );
735 if( FAILED(hr) )
737 ERR( "Unable to perform action for msg type 0x%08lx\n", lpMsg->dwType );
739 /* If a receive event was registered for this player, invoke it */
740 if( hReceiveEvent )
742 SetEvent( hReceiveEvent );
744 #endif
747 static HRESULT WINAPI IDirectPlaySPImpl_SetSPPlayerData
748 ( LPDIRECTPLAYSP iface,
749 DPID idPlayer,
750 LPVOID lpData,
751 DWORD dwDataSize,
752 DWORD dwFlags
755 HRESULT hr;
756 LPDP_SPPLAYERDATA lpPlayerEntry;
757 LPVOID lpPlayerData;
759 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
761 /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
762 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx)\n",
763 This, idPlayer, lpData, dwDataSize, dwFlags );
765 hr = DP_GetSPPlayerData( This->sp->dplay, idPlayer, (LPVOID*)&lpPlayerEntry );
766 if( FAILED(hr) )
768 /* Player must not exist */
769 return DPERR_INVALIDPLAYER;
772 lpPlayerData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
773 CopyMemory( lpPlayerData, lpData, dwDataSize );
775 if( dwFlags == DPSET_LOCAL )
777 lpPlayerEntry->lpPlayerLocalData = lpPlayerData;
778 lpPlayerEntry->dwPlayerLocalDataSize = dwDataSize;
780 else if( dwFlags == DPSET_REMOTE )
782 lpPlayerEntry->lpPlayerRemoteData = lpPlayerData;
783 lpPlayerEntry->dwPlayerRemoteDataSize = dwDataSize;
786 hr = DP_SetSPPlayerData( This->sp->dplay, idPlayer, lpPlayerEntry );
788 return hr;
791 static HRESULT WINAPI IDirectPlaySPImpl_CreateCompoundAddress
792 ( LPDIRECTPLAYSP iface,
793 LPCDPCOMPOUNDADDRESSELEMENT lpElements,
794 DWORD dwElementCount,
795 LPVOID lpAddress,
796 LPDWORD lpdwAddressSize
799 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
801 FIXME( "(%p)->(%p,0x%08lx,%p,%p): stub\n",
802 This, lpElements, dwElementCount, lpAddress, lpdwAddressSize );
804 return DP_OK;
807 static HRESULT WINAPI IDirectPlaySPImpl_GetSPData
808 ( LPDIRECTPLAYSP iface,
809 LPVOID* lplpData,
810 LPDWORD lpdwDataSize,
811 DWORD dwFlags
814 HRESULT hr = DP_OK;
815 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
817 /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
818 TRACE( "(%p)->(%p,%p,0x%08lx)\n",
819 This, lplpData, lpdwDataSize, dwFlags );
821 #if 0
822 /* This is what the documentation says... */
823 if( dwFlags != DPSET_REMOTE )
825 return DPERR_INVALIDPARAMS;
827 #else
828 /* ... but most service providers call this with 1 */
829 /* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
830 * thing?
832 if( dwFlags != DPSET_REMOTE )
834 TRACE( "Undocumented dwFlags 0x%08lx used\n", dwFlags );
836 #endif
838 /* FIXME: What to do in the case where this isn't initialized yet? */
840 /* Yes, we're supposed to return a pointer to the memory we have stored! */
841 if( dwFlags == DPSET_REMOTE )
843 *lpdwDataSize = This->sp->dwSpRemoteDataSize;
844 *lplpData = This->sp->lpSpRemoteData;
846 if( This->sp->lpSpRemoteData == NULL )
848 hr = DPERR_GENERIC;
851 else if( dwFlags == DPSET_LOCAL )
853 *lpdwDataSize = This->sp->dwSpLocalDataSize;
854 *lplpData = This->sp->lpSpLocalData;
856 if( This->sp->lpSpLocalData == NULL )
858 hr = DPERR_GENERIC;
862 return hr;
865 static HRESULT WINAPI IDirectPlaySPImpl_SetSPData
866 ( LPDIRECTPLAYSP iface,
867 LPVOID lpData,
868 DWORD dwDataSize,
869 DWORD dwFlags
872 LPVOID lpSpData;
874 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
876 /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
877 TRACE( "(%p)->(%p,0x%08lx,0x%08lx)\n",
878 This, lpData, dwDataSize, dwFlags );
880 #if 0
881 /* This is what the documentation says... */
882 if( dwFlags != DPSET_REMOTE )
884 return DPERR_INVALIDPARAMS;
886 #else
887 /* ... but most service providers call this with 1 */
888 /* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
889 * thing?
891 if( dwFlags != DPSET_REMOTE )
893 TRACE( "Undocumented dwFlags 0x%08lx used\n", dwFlags );
895 #endif
897 lpSpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
898 CopyMemory( lpSpData, lpData, dwDataSize );
900 /* If we have data already allocated, free it and replace it */
901 if( dwFlags == DPSET_REMOTE )
903 HeapFree( GetProcessHeap(), 0, This->sp->lpSpRemoteData );
904 This->sp->dwSpRemoteDataSize = dwDataSize;
905 This->sp->lpSpRemoteData = lpSpData;
907 else if ( dwFlags == DPSET_LOCAL )
909 HeapFree( GetProcessHeap(), 0, This->sp->lpSpLocalData );
910 This->sp->lpSpLocalData = lpSpData;
911 This->sp->dwSpLocalDataSize = dwDataSize;
914 return DP_OK;
917 static VOID WINAPI IDirectPlaySPImpl_SendComplete
918 ( LPDIRECTPLAYSP iface,
919 LPVOID unknownA,
920 DWORD unknownB
923 IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
925 FIXME( "(%p)->(%p,0x%08lx): stub\n",
926 This, unknownA, unknownB );
930 static struct IDirectPlaySPVtbl directPlaySPVT =
933 DPSP_QueryInterface,
934 DPSP_AddRef,
935 DPSP_Release,
937 IDirectPlaySPImpl_AddMRUEntry,
938 IDirectPlaySPImpl_CreateAddress,
939 IDirectPlaySPImpl_EnumAddress,
940 IDirectPlaySPImpl_EnumMRUEntries,
941 IDirectPlaySPImpl_GetPlayerFlags,
942 IDirectPlaySPImpl_GetSPPlayerData,
943 IDirectPlaySPImpl_HandleMessage,
944 IDirectPlaySPImpl_SetSPPlayerData,
945 IDirectPlaySPImpl_CreateCompoundAddress,
946 IDirectPlaySPImpl_GetSPData,
947 IDirectPlaySPImpl_SetSPData,
948 IDirectPlaySPImpl_SendComplete
952 /* DP external interfaces to call into DPSP interface */
954 /* Allocate the structure */
955 extern LPVOID DPSP_CreateSPPlayerData(void)
957 TRACE( "Creating SPPlayer data struct\n" );
958 return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
959 sizeof( DP_SPPLAYERDATA ) );