explorerframe: A spelling fix in a comment.
[wine.git] / dlls / dplayx / dplaysp.c
blob43938e8511ce07a370d770d1a584dfc8454f083f
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 typedef struct IDirectPlaySPImpl
38 IDirectPlaySP IDirectPlaySP_iface;
39 LONG ref;
40 void *remote_data;
41 DWORD remote_data_size;
42 void *local_data;
43 DWORD local_data_size;
44 IDirectPlayImpl *dplay; /* FIXME: This should perhaps be iface not impl */
45 } IDirectPlaySPImpl;
47 /* This structure is passed to the DP object for safe keeping */
48 typedef struct tagDP_SPPLAYERDATA
50 LPVOID lpPlayerLocalData;
51 DWORD dwPlayerLocalDataSize;
53 LPVOID lpPlayerRemoteData;
54 DWORD dwPlayerRemoteDataSize;
55 } DP_SPPLAYERDATA, *LPDP_SPPLAYERDATA;
58 static inline IDirectPlaySPImpl *impl_from_IDirectPlaySP( IDirectPlaySP *iface )
60 return CONTAINING_RECORD( iface, IDirectPlaySPImpl, IDirectPlaySP_iface );
63 static HRESULT WINAPI IDirectPlaySPImpl_QueryInterface( IDirectPlaySP *iface, REFIID riid,
64 void **ppv )
66 TRACE("(%p)->(%s,%p)\n", iface, debugstr_guid( riid ), ppv );
68 if ( IsEqualGUID( &IID_IUnknown, riid ) || IsEqualGUID( &IID_IDirectPlaySP, riid ) )
70 *ppv = iface;
71 IDirectPlaySP_AddRef( iface );
72 return S_OK;
75 FIXME( "Unsupported interface %s\n", debugstr_guid( riid ) );
76 *ppv = NULL;
77 return E_NOINTERFACE;
80 static ULONG WINAPI IDirectPlaySPImpl_AddRef( IDirectPlaySP *iface )
82 IDirectPlaySPImpl *This = impl_from_IDirectPlaySP( iface );
83 ULONG ref = InterlockedIncrement( &This->ref );
85 TRACE( "(%p) ref=%d\n", This, ref );
87 return ref;
90 static ULONG WINAPI IDirectPlaySPImpl_Release( IDirectPlaySP *iface )
92 IDirectPlaySPImpl *This = impl_from_IDirectPlaySP( iface );
93 ULONG ref = InterlockedDecrement( &This->ref );
95 TRACE( "(%p) ref=%d\n", This, ref );
97 if( !ref )
99 HeapFree( GetProcessHeap(), 0, This->remote_data );
100 HeapFree( GetProcessHeap(), 0, This->local_data );
101 HeapFree( GetProcessHeap(), 0, This );
104 return ref;
107 static HRESULT WINAPI IDirectPlaySPImpl_AddMRUEntry( IDirectPlaySP *iface, LPCWSTR lpSection,
108 LPCWSTR lpKey, const void *lpData, DWORD dwDataSize, DWORD dwMaxEntries )
110 IDirectPlaySPImpl *This = impl_from_IDirectPlaySP( iface );
112 /* Should be able to call the comctl32 undocumented MRU routines.
113 I suspect that the interface works appropriately */
114 FIXME( "(%p)->(%p,%p%p,0x%08x,0x%08x): stub\n",
115 This, lpSection, lpKey, lpData, dwDataSize, dwMaxEntries );
117 return DP_OK;
120 static HRESULT WINAPI IDirectPlaySPImpl_CreateAddress( IDirectPlaySP *iface, REFGUID guidSP,
121 REFGUID guidDataType, const void *lpData, DWORD dwDataSize, void *lpAddress,
122 DWORD *lpdwAddressSize )
124 IDirectPlaySPImpl *This = impl_from_IDirectPlaySP( iface );
126 FIXME( "(%p)->(%s,%s,%p,0x%08x,%p,%p): stub\n",
127 This, debugstr_guid(guidSP), debugstr_guid(guidDataType),
128 lpData, dwDataSize, lpAddress, lpdwAddressSize );
130 return DP_OK;
133 static HRESULT WINAPI IDirectPlaySPImpl_EnumAddress( IDirectPlaySP *iface,
134 LPDPENUMADDRESSCALLBACK lpEnumAddressCallback, const void *lpAddress, DWORD dwAddressSize,
135 void *lpContext )
137 IDirectPlaySPImpl *This = impl_from_IDirectPlaySP( iface );
139 TRACE( "(%p)->(%p,%p,0x%08x,%p)\n",
140 This, lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
142 DPL_EnumAddress( lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
144 return DP_OK;
147 static HRESULT WINAPI IDirectPlaySPImpl_EnumMRUEntries( IDirectPlaySP *iface, LPCWSTR lpSection,
148 LPCWSTR lpKey, LPENUMMRUCALLBACK lpEnumMRUCallback, void *lpContext )
150 IDirectPlaySPImpl *This = impl_from_IDirectPlaySP( iface );
152 /* Should be able to call the comctl32 undocumented MRU routines.
153 I suspect that the interface works appropriately */
154 FIXME( "(%p)->(%p,%p,%p,%p): stub\n",
155 This, lpSection, lpKey, lpEnumMRUCallback, lpContext );
157 return DP_OK;
160 static HRESULT WINAPI IDirectPlaySPImpl_GetPlayerFlags( IDirectPlaySP *iface, DPID idPlayer,
161 DWORD *lpdwPlayerFlags )
163 IDirectPlaySPImpl *This = impl_from_IDirectPlaySP( iface );
165 FIXME( "(%p)->(0x%08x,%p): stub\n",
166 This, idPlayer, lpdwPlayerFlags );
168 return DP_OK;
171 static HRESULT WINAPI IDirectPlaySPImpl_GetSPPlayerData( IDirectPlaySP *iface, DPID idPlayer,
172 void **lplpData, DWORD *lpdwDataSize, DWORD dwFlags )
174 IDirectPlaySPImpl *This = impl_from_IDirectPlaySP( iface );
175 HRESULT hr;
176 LPDP_SPPLAYERDATA lpPlayerData;
178 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x)\n",
179 This, idPlayer, lplpData, lpdwDataSize, dwFlags );
181 hr = DP_GetSPPlayerData( This->dplay, idPlayer, (void**)&lpPlayerData );
183 if( FAILED(hr) )
185 TRACE( "Couldn't get player data: %s\n", DPLAYX_HresultToString(hr) );
186 return DPERR_INVALIDPLAYER;
189 /* What to do in the case where there is nothing set yet? */
190 if( dwFlags == DPSET_LOCAL )
192 *lplpData = lpPlayerData->lpPlayerLocalData;
193 *lpdwDataSize = lpPlayerData->dwPlayerLocalDataSize;
195 else if( dwFlags == DPSET_REMOTE )
197 *lplpData = lpPlayerData->lpPlayerRemoteData;
198 *lpdwDataSize = lpPlayerData->dwPlayerRemoteDataSize;
201 if( *lplpData == NULL )
203 hr = DPERR_GENERIC;
206 return hr;
209 static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage( IDirectPlaySP *iface, void *lpMessageBody,
210 DWORD dwMessageBodySize, void *lpMessageHeader )
212 IDirectPlaySPImpl *This = impl_from_IDirectPlaySP( iface );
213 LPDPMSG_SENDENVELOPE lpMsg = lpMessageBody;
214 HRESULT hr = DPERR_GENERIC;
215 WORD wCommandId;
216 WORD wVersion;
217 DPSP_REPLYDATA data;
219 FIXME( "(%p)->(%p,0x%08x,%p): mostly stub\n",
220 This, lpMessageBody, dwMessageBodySize, lpMessageHeader );
222 wCommandId = lpMsg->wCommandId;
223 wVersion = lpMsg->wVersion;
225 TRACE( "Incoming message has envelope of 0x%08x, %u, %u\n",
226 lpMsg->dwMagic, wCommandId, wVersion );
228 if( lpMsg->dwMagic != DPMSGMAGIC_DPLAYMSG )
230 ERR( "Unknown magic 0x%08x!\n", lpMsg->dwMagic );
231 return DPERR_GENERIC;
234 #if 0
236 const LPDWORD lpcHeader = lpMessageHeader;
238 TRACE( "lpMessageHeader = [0x%08lx] [0x%08lx] [0x%08lx] [0x%08lx] [0x%08lx]\n",
239 lpcHeader[0], lpcHeader[1], lpcHeader[2], lpcHeader[3], lpcHeader[4] );
241 #endif
243 /* Pass everything else to Direct Play */
244 data.lpMessage = NULL;
245 data.dwMessageSize = 0;
247 /* Pass this message to the dplay interface to handle */
248 hr = DP_HandleMessage( This->dplay, lpMessageBody, dwMessageBodySize, lpMessageHeader,
249 wCommandId, wVersion, &data.lpMessage, &data.dwMessageSize );
251 if( FAILED(hr) )
253 ERR( "Command processing failed %s\n", DPLAYX_HresultToString(hr) );
256 /* Do we want a reply? */
257 if( data.lpMessage != NULL )
259 data.lpSPMessageHeader = lpMessageHeader;
260 data.idNameServer = 0;
261 data.lpISP = iface;
263 hr = This->dplay->dp2->spData.lpCB->Reply( &data );
265 if( FAILED(hr) )
267 ERR( "Reply failed %s\n", DPLAYX_HresultToString(hr) );
271 return hr;
273 #if 0
274 HRESULT hr = DP_OK;
275 HANDLE hReceiveEvent = 0;
276 /* FIXME: Acquire some sort of interface lock */
277 /* FIXME: Need some sort of context for this callback. Need to determine
278 * how this is actually done with the SP
280 /* FIXME: Who needs to delete the message when done? */
281 switch( lpMsg->dwType )
283 case DPSYS_CREATEPLAYERORGROUP:
285 LPDPMSG_CREATEPLAYERORGROUP msg = lpMsg;
287 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
289 hr = DP_IF_CreatePlayer( This, lpMessageHeader, msg->dpId,
290 &msg->dpnName, 0, msg->lpData,
291 msg->dwDataSize, msg->dwFlags, ... );
293 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
295 /* Group in group situation? */
296 if( msg->dpIdParent == DPID_NOPARENT_GROUP )
298 hr = DP_IF_CreateGroup( This, lpMessageHeader, msg->dpId,
299 &msg->dpnName, 0, msg->lpData,
300 msg->dwDataSize, msg->dwFlags, ... );
302 else /* Group in Group */
304 hr = DP_IF_CreateGroupInGroup( This, lpMessageHeader, msg->dpIdParent,
305 &msg->dpnName, 0, msg->lpData,
306 msg->dwDataSize, msg->dwFlags, ... );
309 else /* Hmmm? */
311 ERR( "Corrupt msg->dwPlayerType for DPSYS_CREATEPLAYERORGROUP\n" );
312 return;
315 break;
318 case DPSYS_DESTROYPLAYERORGROUP:
320 LPDPMSG_DESTROYPLAYERORGROUP msg = lpMsg;
322 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
324 hr = DP_IF_DestroyPlayer( This, msg->dpId, ... );
326 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
328 hr = DP_IF_DestroyGroup( This, msg->dpId, ... );
330 else /* Hmmm? */
332 ERR( "Corrupt msg->dwPlayerType for DPSYS_DESTROYPLAYERORGROUP\n" );
333 return;
336 break;
339 case DPSYS_ADDPLAYERTOGROUP:
341 LPDPMSG_ADDPLAYERTOGROUP msg = lpMsg;
343 hr = DP_IF_AddPlayerToGroup( This, msg->dpIdGroup, msg->dpIdPlayer, ... );
344 break;
347 case DPSYS_DELETEPLAYERFROMGROUP:
349 LPDPMSG_DELETEPLAYERFROMGROUP msg = lpMsg;
351 hr = DP_IF_DeletePlayerFromGroup( This, msg->dpIdGroup, msg->dpIdPlayer,
352 ... );
354 break;
357 case DPSYS_SESSIONLOST:
359 LPDPMSG_SESSIONLOST msg = lpMsg;
361 FIXME( "DPSYS_SESSIONLOST not handled\n" );
363 break;
366 case DPSYS_HOST:
368 LPDPMSG_HOST msg = lpMsg;
370 FIXME( "DPSYS_HOST not handled\n" );
372 break;
375 case DPSYS_SETPLAYERORGROUPDATA:
377 LPDPMSG_SETPLAYERORGROUPDATA msg = lpMsg;
379 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
381 hr = DP_IF_SetPlayerData( This, msg->dpId, msg->lpData, msg->dwDataSize, DPSET_REMOTE, ... );
383 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
385 hr = DP_IF_SetGroupData( This, msg->dpId, msg->lpData, msg->dwDataSize,
386 DPSET_REMOTE, ... );
388 else /* Hmmm? */
390 ERR( "Corrupt msg->dwPlayerType for LPDPMSG_SETPLAYERORGROUPDATA\n" );
391 return;
394 break;
397 case DPSYS_SETPLAYERORGROUPNAME:
399 LPDPMSG_SETPLAYERORGROUPNAME msg = lpMsg;
401 if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
403 hr = DP_IF_SetPlayerName( This, msg->dpId, msg->dpnName, ... );
405 else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
407 hr = DP_IF_SetGroupName( This, msg->dpId, msg->dpnName, ... );
409 else /* Hmmm? */
411 ERR( "Corrupt msg->dwPlayerType for LPDPMSG_SETPLAYERORGROUPDATA\n" );
412 return;
415 break;
418 case DPSYS_SETSESSIONDESC;
420 LPDPMSG_SETSESSIONDESC msg = lpMsg;
422 hr = DP_IF_SetSessionDesc( This, &msg->dpDesc );
424 break;
427 case DPSYS_ADDGROUPTOGROUP:
429 LPDPMSG_ADDGROUPTOGROUP msg = lpMsg;
431 hr = DP_IF_AddGroupToGroup( This, msg->dpIdParentGroup, msg->dpIdGroup,
432 ... );
434 break;
437 case DPSYS_DELETEGROUPFROMGROUP:
439 LPDPMSG_DELETEGROUPFROMGROUP msg = lpMsg;
441 hr = DP_IF_DeleteGroupFromGroup( This, msg->dpIdParentGroup,
442 msg->dpIdGroup, ... );
444 break;
447 case DPSYS_SECUREMESSAGE:
449 LPDPMSG_SECUREMESSAGE msg = lpMsg;
451 FIXME( "DPSYS_SECUREMESSAGE not implemented\n" );
453 break;
456 case DPSYS_STARTSESSION:
458 LPDPMSG_STARTSESSION msg = lpMsg;
460 FIXME( "DPSYS_STARTSESSION not implemented\n" );
462 break;
465 case DPSYS_CHAT:
467 LPDPMSG_CHAT msg = lpMsg;
469 FIXME( "DPSYS_CHAT not implemeneted\n" );
471 break;
474 case DPSYS_SETGROUPOWNER:
476 LPDPMSG_SETGROUPOWNER msg = lpMsg;
478 FIXME( "DPSYS_SETGROUPOWNER not implemented\n" );
480 break;
483 case DPSYS_SENDCOMPLETE:
485 LPDPMSG_SENDCOMPLETE msg = lpMsg;
487 FIXME( "DPSYS_SENDCOMPLETE not implemented\n" );
489 break;
492 default:
494 /* NOTE: This should be a user defined type. There is nothing that we
495 * need to do with it except queue it.
497 TRACE( "Received user message type(?) 0x%08lx through SP.\n",
498 lpMsg->dwType );
499 break;
503 FIXME( "Queue message in the receive queue. Need some context data!\n" );
505 if( FAILED(hr) )
507 ERR( "Unable to perform action for msg type 0x%08lx\n", lpMsg->dwType );
509 /* If a receive event was registered for this player, invoke it */
510 if( hReceiveEvent )
512 SetEvent( hReceiveEvent );
514 #endif
517 static HRESULT WINAPI IDirectPlaySPImpl_SetSPPlayerData( IDirectPlaySP *iface, DPID idPlayer,
518 void *lpData, DWORD dwDataSize, DWORD dwFlags )
520 IDirectPlaySPImpl *This = impl_from_IDirectPlaySP( iface );
521 HRESULT hr;
522 LPDP_SPPLAYERDATA lpPlayerEntry;
523 LPVOID lpPlayerData;
525 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x)\n", This, idPlayer, lpData, dwDataSize, dwFlags );
527 hr = DP_GetSPPlayerData( This->dplay, idPlayer, (void**)&lpPlayerEntry );
528 if( FAILED(hr) )
530 /* Player must not exist */
531 return DPERR_INVALIDPLAYER;
534 lpPlayerData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
535 CopyMemory( lpPlayerData, lpData, dwDataSize );
537 if( dwFlags == DPSET_LOCAL )
539 lpPlayerEntry->lpPlayerLocalData = lpPlayerData;
540 lpPlayerEntry->dwPlayerLocalDataSize = dwDataSize;
542 else if( dwFlags == DPSET_REMOTE )
544 lpPlayerEntry->lpPlayerRemoteData = lpPlayerData;
545 lpPlayerEntry->dwPlayerRemoteDataSize = dwDataSize;
548 hr = DP_SetSPPlayerData( This->dplay, idPlayer, lpPlayerEntry );
550 return hr;
553 static HRESULT WINAPI IDirectPlaySPImpl_CreateCompoundAddress( IDirectPlaySP *iface,
554 const DPCOMPOUNDADDRESSELEMENT *lpElements, DWORD dwElementCount, void *lpAddress,
555 DWORD *lpdwAddressSize )
557 IDirectPlaySPImpl *This = impl_from_IDirectPlaySP( iface );
559 FIXME( "(%p)->(%p,0x%08x,%p,%p): stub\n",
560 This, lpElements, dwElementCount, lpAddress, lpdwAddressSize );
562 return DP_OK;
565 static HRESULT WINAPI IDirectPlaySPImpl_GetSPData( IDirectPlaySP *iface, void **lplpData,
566 DWORD *lpdwDataSize, DWORD dwFlags )
568 IDirectPlaySPImpl *This = impl_from_IDirectPlaySP( iface );
569 HRESULT hr = DP_OK;
571 TRACE( "(%p)->(%p,%p,0x%08x)\n", This, lplpData, lpdwDataSize, dwFlags );
573 #if 0
574 /* This is what the documentation says... */
575 if( dwFlags != DPSET_REMOTE )
577 return DPERR_INVALIDPARAMS;
579 #else
580 /* ... but most service providers call this with 1 */
581 /* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
582 * thing?
584 if( dwFlags != DPSET_REMOTE )
586 TRACE( "Undocumented dwFlags 0x%08x used\n", dwFlags );
588 #endif
590 /* FIXME: What to do in the case where this isn't initialized yet? */
592 /* Yes, we're supposed to return a pointer to the memory we have stored! */
593 if( dwFlags == DPSET_REMOTE )
595 *lpdwDataSize = This->remote_data_size;
596 *lplpData = This->remote_data;
598 if( !This->remote_data )
599 hr = DPERR_GENERIC;
601 else if( dwFlags == DPSET_LOCAL )
603 *lpdwDataSize = This->local_data_size;
604 *lplpData = This->local_data;
606 if( !This->local_data )
607 hr = DPERR_GENERIC;
610 return hr;
613 static HRESULT WINAPI IDirectPlaySPImpl_SetSPData( IDirectPlaySP *iface, void *lpData,
614 DWORD dwDataSize, DWORD dwFlags )
616 IDirectPlaySPImpl *This = impl_from_IDirectPlaySP( iface );
617 LPVOID lpSpData;
619 TRACE( "(%p)->(%p,0x%08x,0x%08x)\n", This, lpData, dwDataSize, dwFlags );
621 #if 0
622 /* This is what the documentation says... */
623 if( dwFlags != DPSET_REMOTE )
625 return DPERR_INVALIDPARAMS;
627 #else
628 /* ... but most service providers call this with 1 */
629 /* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
630 * thing?
632 if( dwFlags != DPSET_REMOTE )
634 TRACE( "Undocumented dwFlags 0x%08x used\n", dwFlags );
636 #endif
638 lpSpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
639 CopyMemory( lpSpData, lpData, dwDataSize );
641 /* If we have data already allocated, free it and replace it */
642 if( dwFlags == DPSET_REMOTE )
644 HeapFree( GetProcessHeap(), 0, This->remote_data );
645 This->remote_data_size = dwDataSize;
646 This->remote_data = lpSpData;
648 else if ( dwFlags == DPSET_LOCAL )
650 HeapFree( GetProcessHeap(), 0, This->local_data );
651 This->local_data = lpSpData;
652 This->local_data_size = dwDataSize;
655 return DP_OK;
658 static void WINAPI IDirectPlaySPImpl_SendComplete( IDirectPlaySP *iface, void *unknownA,
659 DWORD unknownB )
661 IDirectPlaySPImpl *This = impl_from_IDirectPlaySP( iface );
663 FIXME( "(%p)->(%p,0x%08x): stub\n",
664 This, unknownA, unknownB );
667 static const IDirectPlaySPVtbl directPlaySPVT =
669 IDirectPlaySPImpl_QueryInterface,
670 IDirectPlaySPImpl_AddRef,
671 IDirectPlaySPImpl_Release,
672 IDirectPlaySPImpl_AddMRUEntry,
673 IDirectPlaySPImpl_CreateAddress,
674 IDirectPlaySPImpl_EnumAddress,
675 IDirectPlaySPImpl_EnumMRUEntries,
676 IDirectPlaySPImpl_GetPlayerFlags,
677 IDirectPlaySPImpl_GetSPPlayerData,
678 IDirectPlaySPImpl_HandleMessage,
679 IDirectPlaySPImpl_SetSPPlayerData,
680 IDirectPlaySPImpl_CreateCompoundAddress,
681 IDirectPlaySPImpl_GetSPData,
682 IDirectPlaySPImpl_SetSPData,
683 IDirectPlaySPImpl_SendComplete
686 HRESULT dplaysp_create( REFIID riid, void **ppv, IDirectPlayImpl *dp )
688 IDirectPlaySPImpl *obj;
689 HRESULT hr;
691 TRACE( "(%s, %p)\n", debugstr_guid( riid ), ppv );
693 *ppv = NULL;
694 obj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *obj ) );
695 if ( !obj )
696 return DPERR_OUTOFMEMORY;
698 obj->IDirectPlaySP_iface.lpVtbl = &directPlaySPVT;
699 obj->ref = 1;
700 obj->dplay = dp;
702 hr = IDirectPlaySP_QueryInterface( &obj->IDirectPlaySP_iface, riid, ppv );
703 IDirectPlaySP_Release( &obj->IDirectPlaySP_iface );
705 return hr;
708 /* DP external interfaces to call into DPSP interface */
710 /* Allocate the structure */
711 LPVOID DPSP_CreateSPPlayerData(void)
713 TRACE( "Creating SPPlayer data struct\n" );
714 return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
715 sizeof( DP_SPPLAYERDATA ) );