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
23 #include "wine/debug.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
);
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
49 CRITICAL_SECTION DPSP_lock
;
50 } DirectPlaySPIUnknownData
;
52 typedef struct tagDirectPlaySPData
54 LPVOID lpSpRemoteData
;
55 DWORD dwSpRemoteDataSize
; /* Size of data pointed to by lpSpRemoteData */
58 DWORD dwSpLocalDataSize
; /* Size of data pointed to by lpSpLocalData */
60 IDirectPlay2Impl
* dplay
; /* FIXME: This should perhaps be iface not impl */
64 #define DPSP_IMPL_FIELDS \
65 LONG ulInterfaceRef; \
66 DirectPlaySPIUnknownData* unk; \
69 struct IDirectPlaySPImpl
71 const IDirectPlaySPVtbl
*lpVtbl
;
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
) );
98 return DPERR_OUTOFMEMORY
;
101 if( IsEqualGUID( &IID_IDirectPlaySP
, riid
) )
103 IDirectPlaySPImpl
*This
= *ppvObj
;
104 This
->lpVtbl
= &directPlaySPVT
;
108 /* Unsupported interface */
109 HeapFree( GetProcessHeap(), 0, *ppvObj
);
112 return E_NOINTERFACE
;
116 if( DPSP_CreateIUnknown( *ppvObj
) &&
117 DPSP_CreateDirectPlaySP( *ppvObj
, dp
)
120 IDirectPlaySP_AddRef( (LPDIRECTPLAYSP
)*ppvObj
);
124 /* Initialize failed, destroy it */
125 DPSP_DestroyDirectPlaySP( *ppvObj
);
126 DPSP_DestroyIUnknown( *ppvObj
);
128 HeapFree( GetProcessHeap(), 0, *ppvObj
);
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
)
145 InitializeCriticalSection( &This
->unk
->DPSP_lock
);
146 This
->unk
->DPSP_lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": IDirectPlaySPImpl*->DirectPlaySPIUnknownData*->DPSP_lock");
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
);
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
)
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
);
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
);
215 /* Interface implementation */
217 static HRESULT WINAPI DPSP_QueryInterface
218 ( LPDIRECTPLAYSP iface
,
222 IDirectPlaySPImpl
*This
= (IDirectPlaySPImpl
*)iface
;
223 TRACE("(%p)->(%s,%p)\n", This
, debugstr_guid( riid
), ppvObj
);
225 *ppvObj
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
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
;
243 /* Unsupported interface */
244 HeapFree( GetProcessHeap(), 0, *ppvObj
);
247 return E_NOINTERFACE
;
250 IDirectPlaySP_AddRef( (LPDIRECTPLAYSP
)*ppvObj
);
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
,
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
);
316 static HRESULT WINAPI IDirectPlaySPImpl_CreateAddress
317 ( LPDIRECTPLAYSP iface
,
319 REFGUID guidDataType
,
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
);
335 static HRESULT WINAPI IDirectPlaySPImpl_EnumAddress
336 ( LPDIRECTPLAYSP iface
,
337 LPDPENUMADDRESSCALLBACK lpEnumAddressCallback
,
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
);
353 static HRESULT WINAPI IDirectPlaySPImpl_EnumMRUEntries
354 ( LPDIRECTPLAYSP iface
,
357 LPENUMMRUCALLBACK lpEnumMRUCallback
,
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
);
371 static HRESULT WINAPI IDirectPlaySPImpl_GetPlayerFlags
372 ( LPDIRECTPLAYSP iface
,
374 LPDWORD lpdwPlayerFlags
377 IDirectPlaySPImpl
*This
= (IDirectPlaySPImpl
*)iface
;
379 FIXME( "(%p)->(0x%08x,%p): stub\n",
380 This
, idPlayer
, lpdwPlayerFlags
);
385 static HRESULT WINAPI IDirectPlaySPImpl_GetSPPlayerData
386 ( LPDIRECTPLAYSP iface
,
389 LPDWORD lpdwDataSize
,
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
);
404 ERR( "Couldn't get player data: %s\n", DPLAYX_HresultToString(hr
) );
408 if( dwFlags
== DPSET_LOCAL
)
410 *lplpData
= lpPlayerData
->lpPlayerLocalData
;
411 *lpdwDataSize
= lpPlayerData
->dwPlayerLocalDataSize
;
413 else if( dwFlags
== DPSET_REMOTE
)
415 *lplpData
= lpPlayerData
->lpPlayerRemoteData
;
416 *lpdwDataSize
= lpPlayerData
->dwPlayerRemoteDataSize
;
422 static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage
423 ( LPDIRECTPLAYSP iface
,
424 LPVOID lpMessageBody
,
425 DWORD dwMessageBodySize
,
426 LPVOID lpMessageHeader
429 LPDPSP_MSG_ENVELOPE lpMsg
= lpMessageBody
;
433 IDirectPlaySPImpl
*This
= (IDirectPlaySPImpl
*)iface
;
435 TRACE( "(%p)->(%p,0x%08x,%p)\n",
436 This
, lpMessageBody
, dwMessageBodySize
, lpMessageHeader
);
438 TRACE( "Incoming message has envelope of 0x%08x, 0x%x, %u\n",
439 lpMsg
->dwMagic
, lpMsg
->wCommandId
, lpMsg
->wVersion
);
441 if( lpMsg
->dwMagic
!= DPMSG_SIGNATURE
)
443 ERR( "Unknown magic 0x%08x!\n", lpMsg
->dwMagic
);
444 return DPERR_GENERIC
;
447 /* Pass everything else to Direct Play */
448 data
.lpMessage
= NULL
;
449 data
.dwMessageSize
= 0;
451 /* Pass this message to the dplay interface to handle */
452 hr
= DP_HandleMessage( This
->sp
->dplay
, lpMessageBody
, dwMessageBodySize
,
453 lpMessageHeader
, lpMsg
->wCommandId
, lpMsg
->wVersion
,
454 &data
.lpMessage
, &data
.dwMessageSize
);
457 ERR( "Command processing failed %s\n", DPLAYX_HresultToString(hr
) );
460 /* Do we want a reply? */
461 if( data
.lpMessage
!= NULL
)
463 data
.lpSPMessageHeader
= lpMessageHeader
;
464 data
.idNameServer
= 0;
467 hr
= (This
->sp
->dplay
->dp2
->spData
.lpCB
->Reply
)( &data
);
471 ERR( "Reply failed %s\n", DPLAYX_HresultToString(hr
) );
478 static HRESULT WINAPI IDirectPlaySPImpl_SetSPPlayerData
479 ( LPDIRECTPLAYSP iface
,
487 LPDP_SPPLAYERDATA lpPlayerEntry
;
490 IDirectPlaySPImpl
*This
= (IDirectPlaySPImpl
*)iface
;
492 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x)\n",
493 This
, idPlayer
, lpData
, dwDataSize
, dwFlags
);
495 hr
= DP_GetSPPlayerData( This
->sp
->dplay
, idPlayer
, (LPVOID
*)&lpPlayerEntry
);
498 /* Player must not exist */
499 return DPERR_INVALIDPLAYER
;
502 lpPlayerData
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, dwDataSize
);
503 CopyMemory( lpPlayerData
, lpData
, dwDataSize
);
505 /* If we have data already allocated, free it and replace it */
506 if( dwFlags
== DPSET_LOCAL
)
508 HeapFree( GetProcessHeap(), 0, lpPlayerEntry
->lpPlayerLocalData
);
509 lpPlayerEntry
->lpPlayerLocalData
= lpPlayerData
;
510 lpPlayerEntry
->dwPlayerLocalDataSize
= dwDataSize
;
512 else if( dwFlags
== DPSET_REMOTE
)
514 HeapFree( GetProcessHeap(), 0, lpPlayerEntry
->lpPlayerRemoteData
);
515 lpPlayerEntry
->lpPlayerRemoteData
= lpPlayerData
;
516 lpPlayerEntry
->dwPlayerRemoteDataSize
= dwDataSize
;
519 hr
= DP_SetSPPlayerData( This
->sp
->dplay
, idPlayer
, lpPlayerEntry
);
524 static HRESULT WINAPI IDirectPlaySPImpl_CreateCompoundAddress
525 ( LPDIRECTPLAYSP iface
,
526 LPCDPCOMPOUNDADDRESSELEMENT lpElements
,
527 DWORD dwElementCount
,
529 LPDWORD lpdwAddressSize
532 IDirectPlaySPImpl
*This
= (IDirectPlaySPImpl
*)iface
;
534 FIXME( "(%p)->(%p,0x%08x,%p,%p): stub\n",
535 This
, lpElements
, dwElementCount
, lpAddress
, lpdwAddressSize
);
540 static HRESULT WINAPI IDirectPlaySPImpl_GetSPData
541 ( LPDIRECTPLAYSP iface
,
543 LPDWORD lpdwDataSize
,
547 IDirectPlaySPImpl
*This
= (IDirectPlaySPImpl
*)iface
;
549 TRACE( "(%p)->(%p,%p,0x%08x)\n",
550 This
, lplpData
, lpdwDataSize
, dwFlags
);
552 if( dwFlags
== DPSET_REMOTE
)
554 *lpdwDataSize
= This
->sp
->dwSpRemoteDataSize
;
555 *lplpData
= This
->sp
->lpSpRemoteData
;
557 else if( dwFlags
== DPSET_LOCAL
)
559 *lpdwDataSize
= This
->sp
->dwSpLocalDataSize
;
560 *lplpData
= This
->sp
->lpSpLocalData
;
566 static HRESULT WINAPI IDirectPlaySPImpl_SetSPData
567 ( LPDIRECTPLAYSP iface
,
575 IDirectPlaySPImpl
*This
= (IDirectPlaySPImpl
*)iface
;
577 TRACE( "(%p)->(%p,%d,0x%08x)\n",
578 This
, lpData
, dwDataSize
, dwFlags
);
580 lpSpData
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, dwDataSize
);
581 CopyMemory( lpSpData
, lpData
, dwDataSize
);
583 /* If we have data already allocated, free it and replace it */
584 if( dwFlags
== DPSET_REMOTE
)
586 HeapFree( GetProcessHeap(), 0, This
->sp
->lpSpRemoteData
);
587 This
->sp
->dwSpRemoteDataSize
= dwDataSize
;
588 This
->sp
->lpSpRemoteData
= lpSpData
;
590 else if ( dwFlags
== DPSET_LOCAL
)
592 HeapFree( GetProcessHeap(), 0, This
->sp
->lpSpLocalData
);
593 This
->sp
->lpSpLocalData
= lpSpData
;
594 This
->sp
->dwSpLocalDataSize
= dwDataSize
;
600 static VOID WINAPI IDirectPlaySPImpl_SendComplete
601 ( LPDIRECTPLAYSP iface
,
606 IDirectPlaySPImpl
*This
= (IDirectPlaySPImpl
*)iface
;
608 FIXME( "(%p)->(%p,0x%08x): stub\n",
609 This
, unknownA
, unknownB
);
612 static const IDirectPlaySPVtbl directPlaySPVT
=
619 IDirectPlaySPImpl_AddMRUEntry
,
620 IDirectPlaySPImpl_CreateAddress
,
621 IDirectPlaySPImpl_EnumAddress
,
622 IDirectPlaySPImpl_EnumMRUEntries
,
623 IDirectPlaySPImpl_GetPlayerFlags
,
624 IDirectPlaySPImpl_GetSPPlayerData
,
625 IDirectPlaySPImpl_HandleMessage
,
626 IDirectPlaySPImpl_SetSPPlayerData
,
627 IDirectPlaySPImpl_CreateCompoundAddress
,
628 IDirectPlaySPImpl_GetSPData
,
629 IDirectPlaySPImpl_SetSPData
,
630 IDirectPlaySPImpl_SendComplete
634 /* DP external interfaces to call into DPSP interface */
636 /* Allocate the structure */
637 LPVOID
DPSP_CreateSPPlayerData(void)
639 TRACE( "Creating SPPlayer data struct\n" );
640 return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
641 sizeof( DP_SPPLAYERDATA
) );