msi: Don't defer custom actions in the UI sequence if they match the currently runnin...
[wine/multimedia.git] / dlls / dplayx / dplay.c
blob4529c5e95c1ad5207f6a6e69fb644e23c5c731d8
1 /* Direct Play 2,3,4 Implementation
3 * Copyright 1998,1999,2000,2001 - Peter Hunnisett
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #define COBJMACROS
21 #include "config.h"
22 #include "wine/port.h"
24 #include <stdarg.h>
25 #include <string.h>
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
29 #include "windef.h"
30 #include "winerror.h"
31 #include "winbase.h"
32 #include "winnt.h"
33 #include "winreg.h"
34 #include "winnls.h"
35 #include "wine/unicode.h"
36 #include "wine/debug.h"
38 #include "dplayx_global.h"
39 #include "name_server.h"
40 #include "dplayx_queue.h"
41 #include "wine/dplaysp.h"
42 #include "dplay_global.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(dplay);
46 /* FIXME: Should this be externed? */
47 extern HRESULT DPL_CreateCompoundAddress
48 ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
49 LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
52 /* Local function prototypes */
53 static lpPlayerList DP_FindPlayer( IDirectPlayImpl *This, DPID dpid );
54 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, const DPNAME *lpSrc, BOOL bAnsi );
55 static void DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
56 LPVOID lpData, DWORD dwDataSize );
57 static void DP_DeleteDPNameStruct( LPDPNAME lpDPName );
58 static BOOL CALLBACK cbDeletePlayerFromAllGroups( DPID dpId,
59 DWORD dwPlayerType,
60 LPCDPNAME lpName,
61 DWORD dwFlags,
62 LPVOID lpContext );
63 static lpGroupData DP_FindAnyGroup( IDirectPlayImpl *This, DPID dpid );
65 /* Helper methods for player/group interfaces */
66 static HRESULT DP_SetSessionDesc( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpSessDesc,
67 DWORD dwFlags, BOOL bInitial, BOOL bAnsi );
68 static HRESULT DP_SP_SendEx( IDirectPlayImpl *This, DWORD dwFlags, void *lpData, DWORD dwDataSize,
69 DWORD dwPriority, DWORD dwTimeout, void *lpContext, DWORD *lpdwMsgID );
70 static BOOL DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
71 LPDWORD lpdwBufSize );
73 static DPID DP_GetRemoteNextObjectId(void);
75 static DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi );
76 static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc,
77 LPCDPSESSIONDESC2 srcSessDesc, BOOL bAnsi );
80 #define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */
81 #define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported
82 we don't have to change much */
83 #define DPID_NAME_SERVER 0x19a9d65b /* Don't ask me why */
85 /* Strip out dwFlag values which cannot be sent in the CREATEGROUP msg */
86 #define DPMSG_CREATEGROUP_DWFLAGS(x) ( (x) & DPGROUP_HIDDEN )
88 /* Strip out all dwFlags values for CREATEPLAYER msg */
89 #define DPMSG_CREATEPLAYER_DWFLAGS(x) 0
91 static LONG kludgePlayerGroupId = 1000;
94 static inline IDirectPlayImpl *impl_from_IDirectPlay( IDirectPlay *iface )
96 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay_iface );
99 static inline IDirectPlayImpl *impl_from_IDirectPlay2( IDirectPlay2 *iface )
101 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay2_iface );
104 static inline IDirectPlayImpl *impl_from_IDirectPlay2A( IDirectPlay2A *iface )
106 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay2A_iface );
109 static inline IDirectPlayImpl *impl_from_IDirectPlay3A( IDirectPlay3A *iface )
111 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay3A_iface );
114 static inline IDirectPlayImpl *impl_from_IDirectPlay3( IDirectPlay3 *iface )
116 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay3_iface );
119 static inline IDirectPlayImpl *impl_from_IDirectPlay4A( IDirectPlay4A *iface )
121 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay4A_iface );
124 static inline IDirectPlayImpl *impl_from_IDirectPlay4( IDirectPlay4 *iface )
126 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay4_iface );
129 static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
131 IDirectPlayImpl *This = lpDP;
133 This->dp2 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp2) ) );
134 if ( This->dp2 == NULL )
136 return FALSE;
139 This->dp2->bConnectionOpen = FALSE;
141 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
142 This->dp2->dwEnumSessionLock = 0;
144 This->dp2->bHostInterface = FALSE;
146 DPQ_INIT(This->dp2->receiveMsgs);
147 DPQ_INIT(This->dp2->sendMsgs);
148 DPQ_INIT(This->dp2->repliesExpected);
150 if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
152 /* FIXME: Memory leak */
153 return FALSE;
156 /* Provide an initial session desc with nothing in it */
157 This->dp2->lpSessionDesc = HeapAlloc( GetProcessHeap(),
158 HEAP_ZERO_MEMORY,
159 sizeof( *This->dp2->lpSessionDesc ) );
160 if( This->dp2->lpSessionDesc == NULL )
162 /* FIXME: Memory leak */
163 return FALSE;
165 This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc );
167 /* We are emulating a dp 6 implementation */
168 This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION;
170 This->dp2->spData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
171 sizeof( *This->dp2->spData.lpCB ) );
172 This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB );
173 This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION;
175 /* This is the pointer to the service provider */
176 if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP,
177 (LPVOID*)&This->dp2->spData.lpISP, This ) )
180 /* FIXME: Memory leak */
181 return FALSE;
184 /* Setup lobby provider information */
185 This->dp2->dplspData.dwSPVersion = DPSP_MAJORVERSION;
186 This->dp2->dplspData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
187 sizeof( *This->dp2->dplspData.lpCB ) );
188 This->dp2->dplspData.lpCB->dwSize = sizeof( *This->dp2->dplspData.lpCB );
190 if( FAILED( DPLSP_CreateInterface( &IID_IDPLobbySP,
191 (LPVOID*)&This->dp2->dplspData.lpISP, This ) )
194 /* FIXME: Memory leak */
195 return FALSE;
198 return TRUE;
201 /* Definition of the global function in dplayx_queue.h. #
202 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
203 DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
205 HeapFree( GetProcessHeap(), 0, elem );
208 static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
210 IDirectPlayImpl *This = lpDP;
212 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
214 TerminateThread( This->dp2->hEnumSessionThread, 0 );
215 CloseHandle( This->dp2->hEnumSessionThread );
218 /* Finish with the SP - have it shutdown */
219 if( This->dp2->spData.lpCB->ShutdownEx )
221 DPSP_SHUTDOWNDATA data;
223 TRACE( "Calling SP ShutdownEx\n" );
225 data.lpISP = This->dp2->spData.lpISP;
227 (*This->dp2->spData.lpCB->ShutdownEx)( &data );
229 else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
231 TRACE( "Calling obsolete SP Shutdown\n" );
232 (*This->dp2->spData.lpCB->Shutdown)();
235 /* Unload the SP (if it exists) */
236 if( This->dp2->hServiceProvider != 0 )
238 FreeLibrary( This->dp2->hServiceProvider );
241 /* Unload the Lobby Provider (if it exists) */
242 if( This->dp2->hDPLobbyProvider != 0 )
244 FreeLibrary( This->dp2->hDPLobbyProvider );
247 /* FIXME: Need to delete receive and send msgs queue contents */
249 NS_DeleteSessionCache( This->dp2->lpNameServerData );
251 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
253 IDirectPlaySP_Release( This->dp2->spData.lpISP );
255 /* Delete the contents */
256 HeapFree( GetProcessHeap(), 0, This->dp2 );
258 return TRUE;
261 static void dplay_destroy(IDirectPlayImpl *obj)
263 DP_DestroyDirectPlay2( obj );
264 obj->lock.DebugInfo->Spare[0] = 0;
265 DeleteCriticalSection( &obj->lock );
266 HeapFree( GetProcessHeap(), 0, obj );
269 static inline DPID DP_NextObjectId(void)
271 return (DPID)InterlockedIncrement( &kludgePlayerGroupId );
274 /* *lplpReply will be non NULL iff there is something to reply */
275 HRESULT DP_HandleMessage( IDirectPlayImpl *This, const void *lpcMessageBody,
276 DWORD dwMessageBodySize, const void *lpcMessageHeader, WORD wCommandId, WORD wVersion,
277 void **lplpReply, DWORD *lpdwMsgSize )
279 TRACE( "(%p)->(%p,0x%08x,%p,%u,%u)\n",
280 This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId,
281 wVersion );
283 switch( wCommandId )
285 /* Name server needs to handle this request */
286 case DPMSGCMD_ENUMSESSIONSREQUEST:
287 /* Reply expected */
288 NS_ReplyToEnumSessionsRequest( lpcMessageBody, lplpReply, lpdwMsgSize, This );
289 break;
291 /* Name server needs to handle this request */
292 case DPMSGCMD_ENUMSESSIONSREPLY:
293 /* No reply expected */
294 NS_AddRemoteComputerAsNameServer( lpcMessageHeader,
295 This->dp2->spData.dwSPHeaderSize,
296 lpcMessageBody,
297 This->dp2->lpNameServerData );
298 break;
300 case DPMSGCMD_REQUESTNEWPLAYERID:
302 LPCDPMSG_REQUESTNEWPLAYERID lpcMsg = lpcMessageBody;
304 LPDPMSG_NEWPLAYERIDREPLY lpReply;
306 *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
308 *lplpReply = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, *lpdwMsgSize );
310 FIXME( "Ignoring dwFlags 0x%08x in request msg\n",
311 lpcMsg->dwFlags );
313 /* Setup the reply */
314 lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) +
315 This->dp2->spData.dwSPHeaderSize );
317 lpReply->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
318 lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY;
319 lpReply->envelope.wVersion = DPMSGVER_DP6;
321 lpReply->dpidNewPlayerId = DP_NextObjectId();
323 TRACE( "Allocating new playerid 0x%08x from remote request\n",
324 lpReply->dpidNewPlayerId );
325 break;
328 case DPMSGCMD_GETNAMETABLEREPLY:
329 case DPMSGCMD_NEWPLAYERIDREPLY:
330 #if 0
331 if( wCommandId == DPMSGCMD_NEWPLAYERIDREPLY )
332 DebugBreak();
333 #endif
334 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
335 break;
337 #if 1
338 case DPMSGCMD_JUSTENVELOPE:
339 TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08x\n", lpcMessageHeader, ((const DWORD *)lpcMessageHeader)[1] );
340 NS_SetLocalAddr( This->dp2->lpNameServerData, lpcMessageHeader, 20 );
341 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
342 #endif
344 case DPMSGCMD_FORWARDADDPLAYER:
345 #if 0
346 DebugBreak();
347 #endif
348 #if 1
349 TRACE( "Sending message to self to get my addr\n" );
350 DP_MSG_ToSelf( This, 1 ); /* This is a hack right now */
351 #endif
352 break;
354 case DPMSGCMD_FORWARDADDPLAYERNACK:
355 DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
356 break;
358 default:
359 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
360 DebugBreak();
361 break;
364 /* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */
366 return DP_OK;
370 static HRESULT WINAPI IDirectPlayImpl_QueryInterface( IDirectPlay *iface, REFIID riid, void **ppv )
372 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
373 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
376 static ULONG WINAPI IDirectPlayImpl_AddRef( IDirectPlay *iface )
378 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
379 ULONG ref = InterlockedIncrement( &This->ref );
381 TRACE( "(%p) ref=%d\n", This, ref );
383 if ( ref == 1 )
384 InterlockedIncrement( &This->numIfaces );
386 return ref;
389 static ULONG WINAPI IDirectPlayImpl_Release( IDirectPlay *iface )
391 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
392 ULONG ref = InterlockedDecrement( &This->ref );
394 TRACE( "(%p) ref=%d\n", This, ref );
396 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
397 dplay_destroy( This );
399 return ref;
402 static HRESULT WINAPI IDirectPlayImpl_AddPlayerToGroup( IDirectPlay *iface, DPID group,
403 DPID player )
405 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
406 FIXME( "(%p)->(0x%08x,0x%08x): stub\n", This, group, player );
407 return E_NOTIMPL;
410 static HRESULT WINAPI IDirectPlayImpl_Close( IDirectPlay *iface )
412 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
413 FIXME( "(%p): stub\n", This );
414 return E_NOTIMPL;
417 static HRESULT WINAPI IDirectPlayImpl_CreatePlayer( IDirectPlay *iface, DPID *player,
418 LPSTR name, LPSTR fullname, HANDLE *event )
420 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
421 FIXME( "(%p)->(%p,%s,%s,%p): stub\n", This, player, debugstr_a( name ), debugstr_a( fullname ),
422 event );
423 return E_NOTIMPL;
426 static HRESULT WINAPI IDirectPlayImpl_CreateGroup( IDirectPlay *iface, DPID *group, LPSTR name,
427 LPSTR fullname )
429 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
430 FIXME( "(%p)->(%p,%s,%s): stub\n", This, group, debugstr_a( name ), debugstr_a( fullname ) );
431 return E_NOTIMPL;
434 static HRESULT WINAPI IDirectPlayImpl_DeletePlayerFromGroup( IDirectPlay *iface, DPID group,
435 DPID player )
437 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
438 FIXME( "(%p)->(0x%08x,0x%08x): stub\n", This, group, player );
439 return E_NOTIMPL;
442 static HRESULT WINAPI IDirectPlayImpl_DestroyPlayer( IDirectPlay *iface, DPID player )
444 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
445 FIXME( "(%p)->(0x%08x): stub\n", This, player );
446 return E_NOTIMPL;
449 static HRESULT WINAPI IDirectPlayImpl_DestroyGroup( IDirectPlay *iface, DPID group )
451 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
452 FIXME( "(%p)->(0x%08x): stub\n", This, group );
453 return E_NOTIMPL;
456 static HRESULT WINAPI IDirectPlayImpl_EnableNewPlayers( IDirectPlay *iface, BOOL enable )
458 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
459 FIXME( "(%p)->(%d): stub\n", This, enable );
460 return E_NOTIMPL;
463 static HRESULT WINAPI IDirectPlayImpl_EnumGroupPlayers( IDirectPlay *iface, DPID group,
464 LPDPENUMPLAYERSCALLBACK enumplayercb, void *context, DWORD flags )
466 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
467 FIXME( "(%p)->(0x%08x,%p,%p,0x%08x): stub\n", This, group, enumplayercb, context, flags );
468 return E_NOTIMPL;
471 static HRESULT WINAPI IDirectPlayImpl_EnumGroups( IDirectPlay *iface, DWORD session,
472 LPDPENUMPLAYERSCALLBACK enumplayercb, void *context, DWORD flags )
474 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
475 FIXME( "(%p)->(0x%08x,%p,%p,0x%08x): stub\n", This, session, enumplayercb, context, flags );
476 return E_NOTIMPL;
479 static HRESULT WINAPI IDirectPlayImpl_EnumPlayers( IDirectPlay *iface, DWORD session,
480 LPDPENUMPLAYERSCALLBACK enumplayercb, void *context, DWORD flags )
482 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
483 FIXME( "(%p)->(0x%08x,%p,%p,0x%08x): stub\n", This, session, enumplayercb, context, flags );
484 return E_NOTIMPL;
487 static HRESULT WINAPI IDirectPlayImpl_EnumSessions( IDirectPlay *iface, DPSESSIONDESC *sdesc,
488 DWORD timeout, LPDPENUMSESSIONSCALLBACK enumsessioncb, void *context, DWORD flags )
490 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
491 FIXME( "(%p)->(%p,%u,%p,%p,0x%08x): stub\n", This, sdesc, timeout, enumsessioncb, context,
492 flags );
493 return E_NOTIMPL;
496 static HRESULT WINAPI IDirectPlayImpl_GetCaps( IDirectPlay *iface, DPCAPS *caps )
498 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
499 FIXME( "(%p)->(%p): stub\n", This, caps );
500 return E_NOTIMPL;
503 static HRESULT WINAPI IDirectPlayImpl_GetMessageCount( IDirectPlay *iface, DPID player,
504 DWORD *count )
506 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
507 FIXME( "(%p)->(0x%08x,%p): stub\n", This, player, count );
508 return E_NOTIMPL;
511 static HRESULT WINAPI IDirectPlayImpl_GetPlayerCaps( IDirectPlay *iface, DPID player, DPCAPS *caps )
513 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
514 FIXME( "(%p)->(0x%08x,%p): stub\n", This, player, caps );
515 return E_NOTIMPL;
518 static HRESULT WINAPI IDirectPlayImpl_GetPlayerName( IDirectPlay *iface, DPID player, LPSTR name,
519 DWORD *size_name, LPSTR fullname, DWORD *size_fullname )
521 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
522 FIXME( "(%p)->(0x%08x,%p,%p,%p,%p): stub\n", This, player, name, size_name, fullname,
523 size_fullname );
524 return E_NOTIMPL;
527 static HRESULT WINAPI IDirectPlayImpl_Initialize( IDirectPlay *iface, GUID *guid )
529 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
530 FIXME( "(%p)->(%p): stub\n", This, guid );
531 return E_NOTIMPL;
534 static HRESULT WINAPI IDirectPlayImpl_Open( IDirectPlay *iface, DPSESSIONDESC *sdesc )
536 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
537 FIXME( "(%p)->(%p): stub\n", This, sdesc );
538 return E_NOTIMPL;
541 static HRESULT WINAPI IDirectPlayImpl_Receive( IDirectPlay *iface, DPID *from, DPID *to,
542 DWORD flags, void *data, DWORD *size )
544 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
545 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p): stub\n", This, from, to, flags, data, size );
546 return E_NOTIMPL;
549 static HRESULT WINAPI IDirectPlayImpl_SaveSession( IDirectPlay *iface, LPSTR reserved )
551 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
552 FIXME( "(%p)->(%p): stub\n", This, reserved );
553 return E_NOTIMPL;
556 static HRESULT WINAPI IDirectPlayImpl_Send( IDirectPlay *iface, DPID from, DPID to, DWORD flags,
557 void *data, DWORD size )
559 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
560 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%u): stub\n", This, from, to, flags, data, size );
561 return E_NOTIMPL;
564 static HRESULT WINAPI IDirectPlayImpl_SetPlayerName( IDirectPlay *iface, DPID player, LPSTR name,
565 LPSTR fullname )
567 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
568 FIXME( "(%p)->(0x%08x,%s,%s): stub\n", This, player, debugstr_a( name ),
569 debugstr_a ( fullname ) );
570 return E_NOTIMPL;
573 static const IDirectPlayVtbl dp_vt =
575 IDirectPlayImpl_QueryInterface,
576 IDirectPlayImpl_AddRef,
577 IDirectPlayImpl_Release,
578 IDirectPlayImpl_AddPlayerToGroup,
579 IDirectPlayImpl_Close,
580 IDirectPlayImpl_CreatePlayer,
581 IDirectPlayImpl_CreateGroup,
582 IDirectPlayImpl_DeletePlayerFromGroup,
583 IDirectPlayImpl_DestroyPlayer,
584 IDirectPlayImpl_DestroyGroup,
585 IDirectPlayImpl_EnableNewPlayers,
586 IDirectPlayImpl_EnumGroupPlayers,
587 IDirectPlayImpl_EnumGroups,
588 IDirectPlayImpl_EnumPlayers,
589 IDirectPlayImpl_EnumSessions,
590 IDirectPlayImpl_GetCaps,
591 IDirectPlayImpl_GetMessageCount,
592 IDirectPlayImpl_GetPlayerCaps,
593 IDirectPlayImpl_GetPlayerName,
594 IDirectPlayImpl_Initialize,
595 IDirectPlayImpl_Open,
596 IDirectPlayImpl_Receive,
597 IDirectPlayImpl_SaveSession,
598 IDirectPlayImpl_Send,
599 IDirectPlayImpl_SetPlayerName,
603 static HRESULT WINAPI IDirectPlay2AImpl_QueryInterface( IDirectPlay2A *iface, REFIID riid,
604 void **ppv )
606 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
607 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
610 static HRESULT WINAPI IDirectPlay2Impl_QueryInterface( IDirectPlay2 *iface, REFIID riid,
611 void **ppv )
613 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
614 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
617 static HRESULT WINAPI IDirectPlay3AImpl_QueryInterface( IDirectPlay3A *iface, REFIID riid,
618 void **ppv )
620 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
621 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
624 static HRESULT WINAPI IDirectPlay3Impl_QueryInterface( IDirectPlay3 *iface, REFIID riid,
625 void **ppv )
627 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
628 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
631 static HRESULT WINAPI IDirectPlay4AImpl_QueryInterface( IDirectPlay4A *iface, REFIID riid,
632 void **ppv )
634 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
635 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
638 static HRESULT WINAPI IDirectPlay4Impl_QueryInterface( IDirectPlay4 *iface, REFIID riid,
639 void **ppv )
641 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
643 if ( IsEqualGUID( &IID_IUnknown, riid ) )
645 TRACE( "(%p)->(IID_IUnknown %p)\n", This, ppv );
646 *ppv = &This->IDirectPlay_iface;
648 else if ( IsEqualGUID( &IID_IDirectPlay, riid ) )
650 TRACE( "(%p)->(IID_IDirectPlay %p)\n", This, ppv );
651 *ppv = &This->IDirectPlay_iface;
653 else if ( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
655 TRACE( "(%p)->(IID_IDirectPlay2A %p)\n", This, ppv );
656 *ppv = &This->IDirectPlay2A_iface;
658 else if ( IsEqualGUID( &IID_IDirectPlay2, riid ) )
660 TRACE( "(%p)->(IID_IDirectPlay2 %p)\n", This, ppv );
661 *ppv = &This->IDirectPlay2_iface;
663 else if ( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
665 TRACE( "(%p)->(IID_IDirectPlay3A %p)\n", This, ppv );
666 *ppv = &This->IDirectPlay3A_iface;
668 else if ( IsEqualGUID( &IID_IDirectPlay3, riid ) )
670 TRACE( "(%p)->(IID_IDirectPlay3 %p)\n", This, ppv );
671 *ppv = &This->IDirectPlay3_iface;
673 else if ( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
675 TRACE( "(%p)->(IID_IDirectPlay4A %p)\n", This, ppv );
676 *ppv = &This->IDirectPlay4A_iface;
678 else if ( IsEqualGUID( &IID_IDirectPlay4, riid ) )
680 TRACE( "(%p)->(IID_IDirectPlay4 %p)\n", This, ppv );
681 *ppv = &This->IDirectPlay4_iface;
683 else
685 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
686 *ppv = NULL;
687 return E_NOINTERFACE;
690 IUnknown_AddRef((IUnknown*)*ppv);
691 return S_OK;
694 static ULONG WINAPI IDirectPlay2AImpl_AddRef( IDirectPlay2A *iface )
696 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
697 ULONG ref = InterlockedIncrement( &This->ref2A );
699 TRACE( "(%p) ref2A=%d\n", This, ref );
701 if ( ref == 1 )
702 InterlockedIncrement( &This->numIfaces );
704 return ref;
707 static ULONG WINAPI IDirectPlay2Impl_AddRef( IDirectPlay2 *iface )
709 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
710 ULONG ref = InterlockedIncrement( &This->ref2 );
712 TRACE( "(%p) ref2=%d\n", This, ref );
714 if ( ref == 1 )
715 InterlockedIncrement( &This->numIfaces );
717 return ref;
720 static ULONG WINAPI IDirectPlay3AImpl_AddRef( IDirectPlay3A *iface )
722 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
723 ULONG ref = InterlockedIncrement( &This->ref3A );
725 TRACE( "(%p) ref3A=%d\n", This, ref );
727 if ( ref == 1 )
728 InterlockedIncrement( &This->numIfaces );
730 return ref;
733 static ULONG WINAPI IDirectPlay3Impl_AddRef( IDirectPlay3 *iface )
735 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
736 ULONG ref = InterlockedIncrement( &This->ref3 );
738 TRACE( "(%p) ref3=%d\n", This, ref );
740 if ( ref == 1 )
741 InterlockedIncrement( &This->numIfaces );
743 return ref;
746 static ULONG WINAPI IDirectPlay4AImpl_AddRef(IDirectPlay4A *iface)
748 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
749 ULONG ref = InterlockedIncrement( &This->ref4A );
751 TRACE( "(%p) ref4A=%d\n", This, ref );
753 if ( ref == 1 )
754 InterlockedIncrement( &This->numIfaces );
756 return ref;
759 static ULONG WINAPI IDirectPlay4Impl_AddRef(IDirectPlay4 *iface)
761 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
762 ULONG ref = InterlockedIncrement( &This->ref4 );
764 TRACE( "(%p) ref4=%d\n", This, ref );
766 if ( ref == 1 )
767 InterlockedIncrement( &This->numIfaces );
769 return ref;
772 static ULONG WINAPI IDirectPlay2AImpl_Release( IDirectPlay2A *iface )
774 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
775 ULONG ref = InterlockedDecrement( &This->ref2A );
777 TRACE( "(%p) ref2A=%d\n", This, ref );
779 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
780 dplay_destroy( This );
782 return ref;
785 static ULONG WINAPI IDirectPlay2Impl_Release( IDirectPlay2 *iface )
787 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
788 ULONG ref = InterlockedDecrement( &This->ref2 );
790 TRACE( "(%p) ref2=%d\n", This, ref );
792 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
793 dplay_destroy( This );
795 return ref;
798 static ULONG WINAPI IDirectPlay3AImpl_Release( IDirectPlay3A *iface )
800 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
801 ULONG ref = InterlockedDecrement( &This->ref3A );
803 TRACE( "(%p) ref3A=%d\n", This, ref );
805 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
806 dplay_destroy( This );
808 return ref;
811 static ULONG WINAPI IDirectPlay3Impl_Release( IDirectPlay3 *iface )
813 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
814 ULONG ref = InterlockedDecrement( &This->ref3 );
816 TRACE( "(%p) ref3=%d\n", This, ref );
818 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
819 dplay_destroy( This );
821 return ref;
824 static ULONG WINAPI IDirectPlay4AImpl_Release(IDirectPlay4A *iface)
826 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
827 ULONG ref = InterlockedDecrement( &This->ref4A );
829 TRACE( "(%p) ref4A=%d\n", This, ref );
831 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
832 dplay_destroy( This );
834 return ref;
837 static ULONG WINAPI IDirectPlay4Impl_Release(IDirectPlay4 *iface)
839 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
840 ULONG ref = InterlockedDecrement( &This->ref4 );
842 TRACE( "(%p) ref4=%d\n", This, ref );
844 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
845 dplay_destroy( This );
847 return ref;
850 static HRESULT WINAPI IDirectPlay2AImpl_AddPlayerToGroup( IDirectPlay2A *iface, DPID group,
851 DPID player )
853 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
854 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4A_iface, group, player );
857 static HRESULT WINAPI IDirectPlay2Impl_AddPlayerToGroup( IDirectPlay2 *iface, DPID group,
858 DPID player )
860 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
861 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
864 static HRESULT WINAPI IDirectPlay3AImpl_AddPlayerToGroup( IDirectPlay3A *iface, DPID group,
865 DPID player )
867 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
868 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
871 static HRESULT WINAPI IDirectPlay3Impl_AddPlayerToGroup( IDirectPlay3 *iface, DPID group,
872 DPID player )
874 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
875 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
878 static HRESULT WINAPI IDirectPlay4AImpl_AddPlayerToGroup( IDirectPlay4A *iface, DPID group,
879 DPID player )
881 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
882 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
885 static HRESULT WINAPI IDirectPlay4Impl_AddPlayerToGroup( IDirectPlay4 *iface, DPID group,
886 DPID player )
888 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
889 lpGroupData gdata;
890 lpPlayerList plist;
891 lpPlayerList newplist;
893 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, group, player );
895 if ( This->dp2->connectionInitialized == NO_PROVIDER )
896 return DPERR_UNINITIALIZED;
898 /* Find the group */
899 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
900 return DPERR_INVALIDGROUP;
902 /* Find the player */
903 if ( ( plist = DP_FindPlayer( This, player ) ) == NULL )
904 return DPERR_INVALIDPLAYER;
906 /* Create a player list (ie "shortcut" ) */
907 newplist = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *newplist ) );
908 if ( !newplist )
909 return DPERR_CANTADDPLAYER;
911 /* Add the shortcut */
912 plist->lpPData->uRef++;
913 newplist->lpPData = plist->lpPData;
915 /* Add the player to the list of players for this group */
916 DPQ_INSERT(gdata->players, newplist, players);
918 /* Let the SP know that we've added a player to the group */
919 if ( This->dp2->spData.lpCB->AddPlayerToGroup )
921 DPSP_ADDPLAYERTOGROUPDATA data;
923 TRACE( "Calling SP AddPlayerToGroup\n" );
925 data.idPlayer = player;
926 data.idGroup = group;
927 data.lpISP = This->dp2->spData.lpISP;
929 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
932 /* Inform all other peers of the addition of player to the group. If there are
933 * no peers keep this event quiet.
934 * Also, if this event was the result of another machine sending it to us,
935 * don't bother rebroadcasting it.
937 if ( This->dp2->lpSessionDesc &&
938 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
940 DPMSG_ADDPLAYERTOGROUP msg;
941 msg.dwType = DPSYS_ADDPLAYERTOGROUP;
943 msg.dpIdGroup = group;
944 msg.dpIdPlayer = player;
946 /* FIXME: Correct to just use send effectively? */
947 /* FIXME: Should size include data w/ message or just message "header" */
948 /* FIXME: Check return code */
949 IDirectPlayX_SendEx( iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
950 0, 0, NULL, NULL );
953 return DP_OK;
956 static HRESULT WINAPI IDirectPlay2AImpl_Close( IDirectPlay2A *iface )
958 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
959 return IDirectPlayX_Close( &This->IDirectPlay4A_iface );
962 static HRESULT WINAPI IDirectPlay2Impl_Close( IDirectPlay2 *iface )
964 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
965 return IDirectPlayX_Close( &This->IDirectPlay4_iface );
968 static HRESULT WINAPI IDirectPlay3AImpl_Close( IDirectPlay3A *iface )
970 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
971 return IDirectPlayX_Close( &This->IDirectPlay4_iface );
974 static HRESULT WINAPI IDirectPlay3Impl_Close( IDirectPlay3 *iface )
976 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
977 return IDirectPlayX_Close( &This->IDirectPlay4_iface );
980 static HRESULT WINAPI IDirectPlay4AImpl_Close( IDirectPlay4A *iface )
982 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
983 return IDirectPlayX_Close( &This->IDirectPlay4_iface);
986 static HRESULT WINAPI IDirectPlay4Impl_Close( IDirectPlay4 *iface )
988 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
989 HRESULT hr = DP_OK;
991 TRACE( "(%p)\n", This );
993 /* FIXME: Need to find a new host I assume (how?) */
994 /* FIXME: Need to destroy all local groups */
995 /* FIXME: Need to migrate all remotely visible players to the new host */
997 /* Invoke the SP callback to inform of session close */
998 if( This->dp2->spData.lpCB->CloseEx )
1000 DPSP_CLOSEDATA data;
1002 TRACE( "Calling SP CloseEx\n" );
1003 data.lpISP = This->dp2->spData.lpISP;
1004 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
1006 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
1008 TRACE( "Calling SP Close (obsolete interface)\n" );
1009 hr = (*This->dp2->spData.lpCB->Close)();
1012 return hr;
1015 static lpGroupData DP_CreateGroup( IDirectPlayImpl *This, const DPID *lpid, const DPNAME *lpName,
1016 DWORD dwFlags, DPID idParent, BOOL bAnsi )
1018 lpGroupData lpGData;
1020 /* Allocate the new space and add to end of high level group list */
1021 lpGData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGData ) );
1023 if( lpGData == NULL )
1025 return NULL;
1028 DPQ_INIT(lpGData->groups);
1029 DPQ_INIT(lpGData->players);
1031 /* Set the desired player ID - no sanity checking to see if it exists */
1032 lpGData->dpid = *lpid;
1034 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
1036 /* FIXME: Should we check that the parent exists? */
1037 lpGData->parent = idParent;
1039 /* FIXME: Should we validate the dwFlags? */
1040 lpGData->dwFlags = dwFlags;
1042 TRACE( "Created group id 0x%08x\n", *lpid );
1044 return lpGData;
1047 /* This method assumes that all links to it are already deleted */
1048 static void DP_DeleteGroup( IDirectPlayImpl *This, DPID dpid )
1050 lpGroupList lpGList;
1052 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1054 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
1056 if( lpGList == NULL )
1058 ERR( "DPID 0x%08x not found\n", dpid );
1059 return;
1062 if( --(lpGList->lpGData->uRef) )
1064 FIXME( "Why is this not the last reference to group?\n" );
1065 DebugBreak();
1068 /* Delete player */
1069 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
1070 HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
1072 /* Remove and Delete Player List object */
1073 HeapFree( GetProcessHeap(), 0, lpGList );
1077 static lpGroupData DP_FindAnyGroup( IDirectPlayImpl *This, DPID dpid )
1079 lpGroupList lpGroups;
1081 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1083 if( dpid == DPID_SYSTEM_GROUP )
1085 return This->dp2->lpSysGroup;
1087 else
1089 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
1092 if( lpGroups == NULL )
1094 return NULL;
1097 return lpGroups->lpGData;
1100 static HRESULT DP_IF_CreateGroup( IDirectPlayImpl *This, void *lpMsgHdr, DPID *lpidGroup,
1101 DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
1103 lpGroupData lpGData;
1105 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1106 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
1107 dwFlags, bAnsi );
1109 if( This->dp2->connectionInitialized == NO_PROVIDER )
1111 return DPERR_UNINITIALIZED;
1114 /* If the name is not specified, we must provide one */
1115 if( DPID_UNKNOWN == *lpidGroup )
1117 /* If we are the name server, we decide on the group ids. If not, we
1118 * must ask for one before attempting a creation.
1120 if( This->dp2->bHostInterface )
1122 *lpidGroup = DP_NextObjectId();
1124 else
1126 *lpidGroup = DP_GetRemoteNextObjectId();
1130 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
1131 DPID_NOPARENT_GROUP, bAnsi );
1133 if( lpGData == NULL )
1135 return DPERR_CANTADDPLAYER; /* yes player not group */
1138 if( DPID_SYSTEM_GROUP == *lpidGroup )
1140 This->dp2->lpSysGroup = lpGData;
1141 TRACE( "Inserting system group\n" );
1143 else
1145 /* Insert into the system group */
1146 lpGroupList lpGroup = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGroup ) );
1147 lpGroup->lpGData = lpGData;
1149 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
1152 /* Something is now referencing this data */
1153 lpGData->uRef++;
1155 /* Set all the important stuff for the group */
1156 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
1158 /* FIXME: We should only create the system group if GetCaps returns
1159 * DPCAPS_GROUPOPTIMIZED.
1162 /* Let the SP know that we've created this group */
1163 if( This->dp2->spData.lpCB->CreateGroup )
1165 DPSP_CREATEGROUPDATA data;
1166 DWORD dwCreateFlags = 0;
1168 TRACE( "Calling SP CreateGroup\n" );
1170 if( *lpidGroup == DPID_NOPARENT_GROUP )
1171 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
1173 if( lpMsgHdr == NULL )
1174 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1176 if( dwFlags & DPGROUP_HIDDEN )
1177 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
1179 data.idGroup = *lpidGroup;
1180 data.dwFlags = dwCreateFlags;
1181 data.lpSPMessageHeader = lpMsgHdr;
1182 data.lpISP = This->dp2->spData.lpISP;
1184 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1187 /* Inform all other peers of the creation of a new group. If there are
1188 * no peers keep this event quiet.
1189 * Also if this message was sent to us, don't rebroadcast.
1191 if( ( lpMsgHdr == NULL ) &&
1192 This->dp2->lpSessionDesc &&
1193 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1195 DPMSG_CREATEPLAYERORGROUP msg;
1196 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1198 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1199 msg.dpId = *lpidGroup;
1200 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1201 msg.lpData = lpData;
1202 msg.dwDataSize = dwDataSize;
1203 msg.dpnName = *lpGroupName;
1204 msg.dpIdParent = DPID_NOPARENT_GROUP;
1205 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
1207 /* FIXME: Correct to just use send effectively? */
1208 /* FIXME: Should size include data w/ message or just message "header" */
1209 /* FIXME: Check return code */
1210 IDirectPlayX_SendEx( &This->IDirectPlay4_iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
1211 sizeof( msg ), 0, 0, NULL, NULL );
1214 return DP_OK;
1217 static HRESULT WINAPI IDirectPlay2AImpl_CreateGroup( IDirectPlay2A *iface, DPID *lpidGroup,
1218 DPNAME *name, void *data, DWORD size, DWORD flags )
1220 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
1221 return IDirectPlayX_CreateGroup( &This->IDirectPlay4A_iface, lpidGroup, name, data, size,
1222 flags );
1225 static HRESULT WINAPI IDirectPlay2Impl_CreateGroup( IDirectPlay2 *iface, DPID *lpidGroup,
1226 DPNAME *name, void *data, DWORD size, DWORD flags )
1228 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
1229 return IDirectPlayX_CreateGroup( &This->IDirectPlay4_iface, lpidGroup, name, data, size,
1230 flags );
1233 static HRESULT WINAPI IDirectPlay3AImpl_CreateGroup( IDirectPlay3A *iface, DPID *group,
1234 DPNAME *name, void *data, DWORD size, DWORD flags )
1236 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
1237 return IDirectPlayX_CreateGroup( &This->IDirectPlay4_iface, group, name, data, size,
1238 flags );
1241 static HRESULT WINAPI IDirectPlay3Impl_CreateGroup( IDirectPlay3 *iface, DPID *lpidGroup,
1242 DPNAME *name, void *data, DWORD size, DWORD flags )
1244 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
1245 return IDirectPlayX_CreateGroup( &This->IDirectPlay4_iface, lpidGroup, name, data, size,
1246 flags );
1249 static HRESULT WINAPI IDirectPlay4AImpl_CreateGroup( IDirectPlay4A *iface, DPID *lpidGroup,
1250 DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1252 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
1254 *lpidGroup = DPID_UNKNOWN;
1256 return DP_IF_CreateGroup( This, NULL, lpidGroup, lpGroupName, lpData, dwDataSize, dwFlags,
1257 TRUE );
1260 static HRESULT WINAPI IDirectPlay4Impl_CreateGroup( IDirectPlay4 *iface, DPID *lpidGroup,
1261 DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1263 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
1265 *lpidGroup = DPID_UNKNOWN;
1267 return DP_IF_CreateGroup( This, NULL, lpidGroup, lpGroupName, lpData, dwDataSize, dwFlags,
1268 FALSE );
1272 static void
1273 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
1274 LPVOID lpData, DWORD dwDataSize )
1276 /* Clear out the data with this player */
1277 if( dwFlags & DPSET_LOCAL )
1279 if ( lpGData->dwLocalDataSize != 0 )
1281 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
1282 lpGData->lpLocalData = NULL;
1283 lpGData->dwLocalDataSize = 0;
1286 else
1288 if( lpGData->dwRemoteDataSize != 0 )
1290 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
1291 lpGData->lpRemoteData = NULL;
1292 lpGData->dwRemoteDataSize = 0;
1296 /* Reallocate for new data */
1297 if( lpData != NULL )
1299 if( dwFlags & DPSET_LOCAL )
1301 lpGData->lpLocalData = lpData;
1302 lpGData->dwLocalDataSize = dwDataSize;
1304 else
1306 lpGData->lpRemoteData = HeapAlloc( GetProcessHeap(), 0, dwDataSize );
1307 CopyMemory( lpGData->lpRemoteData, lpData, dwDataSize );
1308 lpGData->dwRemoteDataSize = dwDataSize;
1314 /* This function will just create the storage for the new player. */
1315 static lpPlayerData DP_CreatePlayer( IDirectPlayImpl *This, DPID *lpid, DPNAME *lpName,
1316 DWORD dwFlags, HANDLE hEvent, BOOL bAnsi )
1318 lpPlayerData lpPData;
1320 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
1322 /* Allocate the storage for the player and associate it with list element */
1323 lpPData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPData ) );
1324 if( lpPData == NULL )
1326 return NULL;
1329 /* Set the desired player ID */
1330 lpPData->dpid = *lpid;
1332 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
1334 lpPData->dwFlags = dwFlags;
1336 /* If we were given an event handle, duplicate it */
1337 if( hEvent != 0 )
1339 if( !DuplicateHandle( GetCurrentProcess(), hEvent,
1340 GetCurrentProcess(), &lpPData->hEvent,
1341 0, FALSE, DUPLICATE_SAME_ACCESS )
1344 /* FIXME: Memory leak */
1345 ERR( "Can't duplicate player msg handle %p\n", hEvent );
1349 /* Initialize the SP data section */
1350 lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData();
1352 TRACE( "Created player id 0x%08x\n", *lpid );
1354 if( ~dwFlags & DPLAYI_PLAYER_SYSPLAYER )
1355 This->dp2->lpSessionDesc->dwCurrentPlayers++;
1357 return lpPData;
1360 /* Delete the contents of the DPNAME struct */
1361 static void
1362 DP_DeleteDPNameStruct( LPDPNAME lpDPName )
1364 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u1.lpszShortNameA );
1365 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u2.lpszLongNameA );
1368 /* This method assumes that all links to it are already deleted */
1369 static void DP_DeletePlayer( IDirectPlayImpl *This, DPID dpid )
1371 lpPlayerList lpPList;
1373 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1375 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1377 if( lpPList == NULL )
1379 ERR( "DPID 0x%08x not found\n", dpid );
1380 return;
1383 /* Verify that this is the last reference to the data */
1384 if( --(lpPList->lpPData->uRef) )
1386 FIXME( "Why is this not the last reference to player?\n" );
1387 DebugBreak();
1390 /* Delete player */
1391 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1393 CloseHandle( lpPList->lpPData->hEvent );
1394 HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
1396 /* Delete Player List object */
1397 HeapFree( GetProcessHeap(), 0, lpPList );
1400 static lpPlayerList DP_FindPlayer( IDirectPlayImpl *This, DPID dpid )
1402 lpPlayerList lpPlayers;
1404 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1406 if(This->dp2->lpSysGroup == NULL)
1407 return NULL;
1409 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1411 return lpPlayers;
1414 /* Basic area for Dst must already be allocated */
1415 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, const DPNAME *lpSrc, BOOL bAnsi )
1417 if( lpSrc == NULL )
1419 ZeroMemory( lpDst, sizeof( *lpDst ) );
1420 lpDst->dwSize = sizeof( *lpDst );
1421 return TRUE;
1424 if( lpSrc->dwSize != sizeof( *lpSrc) )
1426 return FALSE;
1429 /* Delete any existing pointers */
1430 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1431 HeapFree( GetProcessHeap(), 0, lpDst->u2.lpszLongNameA );
1433 /* Copy as required */
1434 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1436 if( bAnsi )
1438 if( lpSrc->u1.lpszShortNameA )
1440 lpDst->u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), 0,
1441 strlen(lpSrc->u1.lpszShortNameA)+1 );
1442 strcpy( lpDst->u1.lpszShortNameA, lpSrc->u1.lpszShortNameA );
1444 if( lpSrc->u2.lpszLongNameA )
1446 lpDst->u2.lpszLongNameA = HeapAlloc( GetProcessHeap(), 0,
1447 strlen(lpSrc->u2.lpszLongNameA)+1 );
1448 strcpy( lpDst->u2.lpszLongNameA, lpSrc->u2.lpszLongNameA );
1451 else
1453 if( lpSrc->u1.lpszShortNameA )
1455 lpDst->u1.lpszShortName = HeapAlloc( GetProcessHeap(), 0,
1456 (strlenW(lpSrc->u1.lpszShortName)+1)*sizeof(WCHAR) );
1457 strcpyW( lpDst->u1.lpszShortName, lpSrc->u1.lpszShortName );
1459 if( lpSrc->u2.lpszLongNameA )
1461 lpDst->u2.lpszLongName = HeapAlloc( GetProcessHeap(), 0,
1462 (strlenW(lpSrc->u2.lpszLongName)+1)*sizeof(WCHAR) );
1463 strcpyW( lpDst->u2.lpszLongName, lpSrc->u2.lpszLongName );
1467 return TRUE;
1470 static void
1471 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
1472 LPVOID lpData, DWORD dwDataSize )
1474 /* Clear out the data with this player */
1475 if( dwFlags & DPSET_LOCAL )
1477 if ( lpPData->dwLocalDataSize != 0 )
1479 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
1480 lpPData->lpLocalData = NULL;
1481 lpPData->dwLocalDataSize = 0;
1484 else
1486 if( lpPData->dwRemoteDataSize != 0 )
1488 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
1489 lpPData->lpRemoteData = NULL;
1490 lpPData->dwRemoteDataSize = 0;
1494 /* Reallocate for new data */
1495 if( lpData != NULL )
1498 if( dwFlags & DPSET_LOCAL )
1500 lpPData->lpLocalData = lpData;
1501 lpPData->dwLocalDataSize = dwDataSize;
1503 else
1505 lpPData->lpRemoteData = HeapAlloc( GetProcessHeap(), 0, dwDataSize );
1506 CopyMemory( lpPData->lpRemoteData, lpData, dwDataSize );
1507 lpPData->dwRemoteDataSize = dwDataSize;
1513 /* Note: lpMsgHdr is NULL for local creation, non NULL for remote creation */
1514 static HRESULT DP_IF_CreatePlayer( IDirectPlayImpl *This, void *lpMsgHdr, DPID *lpidPlayer,
1515 DPNAME *lpPlayerName, HANDLE hEvent, void *lpData, DWORD dwDataSize, DWORD dwFlags,
1516 BOOL bAnsi )
1518 HRESULT hr = DP_OK;
1519 lpPlayerData lpPData;
1520 lpPlayerList lpPList;
1521 DWORD dwCreateFlags = 0;
1523 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1524 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1525 dwDataSize, dwFlags, bAnsi );
1526 if( This->dp2->connectionInitialized == NO_PROVIDER )
1528 return DPERR_UNINITIALIZED;
1531 if( dwFlags == 0 )
1533 dwFlags = DPPLAYER_SPECTATOR;
1536 if( lpidPlayer == NULL )
1538 return DPERR_INVALIDPARAMS;
1542 /* Determine the creation flags for the player. These will be passed
1543 * to the name server if requesting a player id and to the SP when
1544 * informing it of the player creation
1547 if( dwFlags & DPPLAYER_SERVERPLAYER )
1549 if( *lpidPlayer == DPID_SERVERPLAYER )
1551 /* Server player for the host interface */
1552 dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
1554 else if( *lpidPlayer == DPID_NAME_SERVER )
1556 /* Name server - master of everything */
1557 dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
1559 else
1561 /* Server player for a non host interface */
1562 dwCreateFlags |= DPLAYI_PLAYER_SYSPLAYER;
1566 if( lpMsgHdr == NULL )
1567 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1570 /* Verify we know how to handle all the flags */
1571 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1572 ( dwFlags & DPPLAYER_SPECTATOR )
1576 /* Assume non fatal failure */
1577 ERR( "unknown dwFlags = 0x%08x\n", dwFlags );
1580 /* If the name is not specified, we must provide one */
1581 if( *lpidPlayer == DPID_UNKNOWN )
1583 /* If we are the session master, we dish out the group/player ids */
1584 if( This->dp2->bHostInterface )
1586 *lpidPlayer = DP_NextObjectId();
1588 else
1590 hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer );
1592 if( FAILED(hr) )
1594 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1595 return hr;
1599 else
1601 /* FIXME: Would be nice to perhaps verify that we don't already have
1602 * this player.
1606 /* We pass creation flags, so we can distinguish sysplayers and not count them in the current
1607 player total */
1608 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwCreateFlags,
1609 hEvent, bAnsi );
1611 if( lpPData == NULL )
1613 return DPERR_CANTADDPLAYER;
1616 /* Create the list object and link it in */
1617 lpPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPList ) );
1618 if( lpPList == NULL )
1620 FIXME( "Memory leak\n" );
1621 return DPERR_CANTADDPLAYER;
1624 lpPData->uRef = 1;
1625 lpPList->lpPData = lpPData;
1627 /* Add the player to the system group */
1628 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1630 /* Update the information and send it to all players in the session */
1631 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
1633 /* Let the SP know that we've created this player */
1634 if( This->dp2->spData.lpCB->CreatePlayer )
1636 DPSP_CREATEPLAYERDATA data;
1638 data.idPlayer = *lpidPlayer;
1639 data.dwFlags = dwCreateFlags;
1640 data.lpSPMessageHeader = lpMsgHdr;
1641 data.lpISP = This->dp2->spData.lpISP;
1643 TRACE( "Calling SP CreatePlayer 0x%08x: dwFlags: 0x%08x lpMsgHdr: %p\n",
1644 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
1646 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1649 if( FAILED(hr) )
1651 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1652 return hr;
1655 /* Now let the SP know that this player is a member of the system group */
1656 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1658 DPSP_ADDPLAYERTOGROUPDATA data;
1660 data.idPlayer = *lpidPlayer;
1661 data.idGroup = DPID_SYSTEM_GROUP;
1662 data.lpISP = This->dp2->spData.lpISP;
1664 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1666 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1669 if( FAILED(hr) )
1671 ERR( "Failed to add player to sys group with sp: %s\n",
1672 DPLAYX_HresultToString(hr) );
1673 return hr;
1676 #if 1
1677 if( This->dp2->bHostInterface == FALSE )
1679 /* Let the name server know about the creation of this player */
1680 /* FIXME: Is this only to be done for the creation of a server player or
1681 * is this used for regular players? If only for server players, move
1682 * this call to DP_SecureOpen(...);
1684 #if 0
1685 TRACE( "Sending message to self to get my addr\n" );
1686 DP_MSG_ToSelf( This, *lpidPlayer ); /* This is a hack right now */
1687 #endif
1689 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
1691 #else
1692 /* Inform all other peers of the creation of a new player. If there are
1693 * no peers keep this quiet.
1694 * Also, if this was a remote event, no need to rebroadcast it.
1696 if( ( lpMsgHdr == NULL ) &&
1697 This->dp2->lpSessionDesc &&
1698 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1700 DPMSG_CREATEPLAYERORGROUP msg;
1701 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1703 msg.dwPlayerType = DPPLAYERTYPE_PLAYER;
1704 msg.dpId = *lpidPlayer;
1705 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */
1706 msg.lpData = lpData;
1707 msg.dwDataSize = dwDataSize;
1708 msg.dpnName = *lpPlayerName;
1709 msg.dpIdParent = DPID_NOPARENT_GROUP;
1710 msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
1712 /* FIXME: Correct to just use send effectively? */
1713 /* FIXME: Should size include data w/ message or just message "header" */
1714 /* FIXME: Check return code */
1715 hr = IDirectPlayX_SendEx( &This->IDirectPlay4_iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0,
1716 &msg, sizeof( msg ), 0, 0, NULL, NULL );
1718 #endif
1720 return hr;
1723 static HRESULT WINAPI IDirectPlay2AImpl_CreatePlayer( IDirectPlay2A *iface, DPID *lpidPlayer,
1724 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags )
1726 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
1727 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4A_iface, lpidPlayer, name, event, data,
1728 size, flags );
1731 static HRESULT WINAPI IDirectPlay2Impl_CreatePlayer( IDirectPlay2 *iface, DPID *lpidPlayer,
1732 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags )
1734 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
1735 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4_iface, lpidPlayer, name, event, data,
1736 size, flags );
1739 static HRESULT WINAPI IDirectPlay3AImpl_CreatePlayer( IDirectPlay3A *iface, DPID *lpidPlayer,
1740 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags )
1742 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
1743 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4_iface, lpidPlayer, name, event, data,
1744 size, flags );
1747 static HRESULT WINAPI IDirectPlay3Impl_CreatePlayer( IDirectPlay3 *iface, DPID *lpidPlayer,
1748 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags )
1750 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
1751 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4_iface, lpidPlayer, name, event, data,
1752 size, flags );
1755 static HRESULT WINAPI IDirectPlay4AImpl_CreatePlayer( IDirectPlay4A *iface, DPID *lpidPlayer,
1756 DPNAME *lpPlayerName, HANDLE hEvent, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1758 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
1760 if( lpidPlayer == NULL )
1762 return DPERR_INVALIDPARAMS;
1765 if( dwFlags & DPPLAYER_SERVERPLAYER )
1767 *lpidPlayer = DPID_SERVERPLAYER;
1769 else
1771 *lpidPlayer = DPID_UNKNOWN;
1774 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1775 lpData, dwDataSize, dwFlags, TRUE );
1778 static HRESULT WINAPI IDirectPlay4Impl_CreatePlayer( IDirectPlay4 *iface, DPID *lpidPlayer,
1779 DPNAME *lpPlayerName, HANDLE hEvent, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1781 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
1783 if( lpidPlayer == NULL )
1785 return DPERR_INVALIDPARAMS;
1788 if( dwFlags & DPPLAYER_SERVERPLAYER )
1790 *lpidPlayer = DPID_SERVERPLAYER;
1792 else
1794 *lpidPlayer = DPID_UNKNOWN;
1797 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1798 lpData, dwDataSize, dwFlags, FALSE );
1801 static DPID DP_GetRemoteNextObjectId(void)
1803 FIXME( ":stub\n" );
1805 /* Hack solution */
1806 return DP_NextObjectId();
1809 static HRESULT WINAPI IDirectPlay2AImpl_DeletePlayerFromGroup( IDirectPlay2A *iface, DPID group,
1810 DPID player )
1812 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
1813 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4A_iface, group, player );
1816 static HRESULT WINAPI IDirectPlay2Impl_DeletePlayerFromGroup( IDirectPlay2 *iface, DPID group,
1817 DPID player )
1819 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
1820 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1823 static HRESULT WINAPI IDirectPlay3AImpl_DeletePlayerFromGroup( IDirectPlay3A *iface, DPID group,
1824 DPID player )
1826 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
1827 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1830 static HRESULT WINAPI IDirectPlay3Impl_DeletePlayerFromGroup( IDirectPlay3 *iface, DPID group,
1831 DPID player )
1833 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
1834 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1837 static HRESULT WINAPI IDirectPlay4AImpl_DeletePlayerFromGroup( IDirectPlay4A *iface, DPID group,
1838 DPID player )
1840 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
1841 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1844 static HRESULT WINAPI IDirectPlay4Impl_DeletePlayerFromGroup( IDirectPlay4 *iface, DPID group,
1845 DPID player )
1847 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
1848 HRESULT hr = DP_OK;
1850 lpGroupData gdata;
1851 lpPlayerList plist;
1853 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, group, player );
1855 /* Find the group */
1856 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
1857 return DPERR_INVALIDGROUP;
1859 /* Find the player */
1860 if ( DP_FindPlayer( This, player ) == NULL )
1861 return DPERR_INVALIDPLAYER;
1863 /* Remove the player shortcut from the group */
1864 DPQ_REMOVE_ENTRY( gdata->players, players, lpPData->dpid, ==, player, plist );
1866 if ( !plist )
1867 return DPERR_INVALIDPLAYER;
1869 /* One less reference */
1870 plist->lpPData->uRef--;
1872 /* Delete the Player List element */
1873 HeapFree( GetProcessHeap(), 0, plist );
1875 /* Inform the SP if they care */
1876 if ( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1878 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1880 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1881 data.idPlayer = player;
1882 data.idGroup = group;
1883 data.lpISP = This->dp2->spData.lpISP;
1884 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1887 /* Need to send a DELETEPLAYERFROMGROUP message */
1888 FIXME( "Need to send a message\n" );
1890 return hr;
1893 typedef struct _DPRGOPContext
1895 IDirectPlayImpl *This;
1896 BOOL bAnsi;
1897 DPID idGroup;
1898 } DPRGOPContext, *lpDPRGOPContext;
1900 static BOOL CALLBACK
1901 cbRemoveGroupOrPlayer(
1902 DPID dpId,
1903 DWORD dwPlayerType,
1904 LPCDPNAME lpName,
1905 DWORD dwFlags,
1906 LPVOID lpContext )
1908 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1910 TRACE( "Removing element:0x%08x (type:0x%08x) from element:0x%08x\n",
1911 dpId, dwPlayerType, lpCtxt->idGroup );
1913 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1915 if ( FAILED( IDirectPlayX_DeleteGroupFromGroup( &lpCtxt->This->IDirectPlay4_iface,
1916 lpCtxt->idGroup, dpId ) ) )
1917 ERR( "Unable to delete group 0x%08x from group 0x%08x\n", dpId, lpCtxt->idGroup );
1919 else if ( FAILED( IDirectPlayX_DeletePlayerFromGroup( &lpCtxt->This->IDirectPlay4_iface,
1920 lpCtxt->idGroup, dpId ) ) )
1921 ERR( "Unable to delete player 0x%08x from grp 0x%08x\n", dpId, lpCtxt->idGroup );
1923 return TRUE; /* Continue enumeration */
1926 static HRESULT DP_IF_DestroyGroup( IDirectPlayImpl *This, void *lpMsgHdr, DPID idGroup, BOOL bAnsi )
1928 lpGroupData lpGData;
1929 DPRGOPContext context;
1931 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1932 This, lpMsgHdr, idGroup, bAnsi );
1934 /* Find the group */
1935 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1937 return DPERR_INVALIDPLAYER; /* yes player */
1940 context.This = This;
1941 context.bAnsi = bAnsi;
1942 context.idGroup = idGroup;
1944 /* Remove all players that this group has */
1945 IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, idGroup, NULL, cbRemoveGroupOrPlayer,
1946 &context, 0 );
1948 /* Remove all links to groups that this group has since this is dp3 */
1949 IDirectPlayX_EnumGroupsInGroup( &This->IDirectPlay4_iface, idGroup, NULL, cbRemoveGroupOrPlayer,
1950 (void*)&context, 0 );
1952 /* Remove this group from the parent group - if it has one */
1953 if( ( idGroup != DPID_SYSTEM_GROUP ) && ( lpGData->parent != DPID_SYSTEM_GROUP ) )
1954 IDirectPlayX_DeleteGroupFromGroup( &This->IDirectPlay4_iface, lpGData->parent, idGroup );
1956 /* Now delete this group data and list from the system group */
1957 DP_DeleteGroup( This, idGroup );
1959 /* Let the SP know that we've destroyed this group */
1960 if( This->dp2->spData.lpCB->DeleteGroup )
1962 DPSP_DELETEGROUPDATA data;
1964 FIXME( "data.dwFlags is incorrect\n" );
1966 data.idGroup = idGroup;
1967 data.dwFlags = 0;
1968 data.lpISP = This->dp2->spData.lpISP;
1970 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1973 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1975 return DP_OK;
1978 static HRESULT WINAPI IDirectPlay2AImpl_DestroyGroup( IDirectPlay2A *iface, DPID group )
1980 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
1981 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4A_iface, group );
1984 static HRESULT WINAPI IDirectPlay2Impl_DestroyGroup( IDirectPlay2 *iface, DPID group )
1986 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
1987 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4_iface, group );
1990 static HRESULT WINAPI IDirectPlay3AImpl_DestroyGroup( IDirectPlay3A *iface, DPID group )
1992 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
1993 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4_iface, group );
1996 static HRESULT WINAPI IDirectPlay3Impl_DestroyGroup( IDirectPlay3 *iface, DPID group )
1998 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
1999 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4_iface, group );
2002 static HRESULT WINAPI IDirectPlay4AImpl_DestroyGroup( IDirectPlay4A *iface, DPID idGroup )
2004 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2005 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
2008 static HRESULT WINAPI IDirectPlay4Impl_DestroyGroup( IDirectPlay4 *iface, DPID idGroup )
2010 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2011 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
2014 typedef struct _DPFAGContext
2016 IDirectPlayImpl *This;
2017 DPID idPlayer;
2018 BOOL bAnsi;
2019 } DPFAGContext, *lpDPFAGContext;
2021 static HRESULT DP_IF_DestroyPlayer( IDirectPlayImpl *This, void *lpMsgHdr, DPID idPlayer,
2022 BOOL bAnsi )
2024 DPFAGContext cbContext;
2026 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
2027 This, lpMsgHdr, idPlayer, bAnsi );
2029 if( This->dp2->connectionInitialized == NO_PROVIDER )
2031 return DPERR_UNINITIALIZED;
2034 if( DP_FindPlayer( This, idPlayer ) == NULL )
2036 return DPERR_INVALIDPLAYER;
2039 /* FIXME: If the player is remote, we must be the host to delete this */
2041 cbContext.This = This;
2042 cbContext.idPlayer = idPlayer;
2043 cbContext.bAnsi = bAnsi;
2045 /* Find each group and call DeletePlayerFromGroup if the player is a
2046 member of the group */
2047 IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, NULL, cbDeletePlayerFromAllGroups, &cbContext,
2048 DPENUMGROUPS_ALL );
2050 /* Now delete player and player list from the sys group */
2051 DP_DeletePlayer( This, idPlayer );
2053 /* Let the SP know that we've destroyed this group */
2054 if( This->dp2->spData.lpCB->DeletePlayer )
2056 DPSP_DELETEPLAYERDATA data;
2058 FIXME( "data.dwFlags is incorrect\n" );
2060 data.idPlayer = idPlayer;
2061 data.dwFlags = 0;
2062 data.lpISP = This->dp2->spData.lpISP;
2064 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
2067 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
2069 return DP_OK;
2072 static BOOL CALLBACK
2073 cbDeletePlayerFromAllGroups(
2074 DPID dpId,
2075 DWORD dwPlayerType,
2076 LPCDPNAME lpName,
2077 DWORD dwFlags,
2078 LPVOID lpContext )
2080 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
2082 if( dwPlayerType == DPPLAYERTYPE_GROUP )
2084 IDirectPlayX_DeletePlayerFromGroup( &lpCtxt->This->IDirectPlay4_iface, dpId, lpCtxt->idPlayer );
2086 /* Enumerate all groups in this group since this will normally only
2087 * be called for top level groups
2089 IDirectPlayX_EnumGroupsInGroup( &lpCtxt->This->IDirectPlay4_iface, dpId, NULL,
2090 cbDeletePlayerFromAllGroups, lpContext, DPENUMGROUPS_ALL);
2093 else
2095 ERR( "Group callback has dwPlayerType = 0x%08x\n", dwPlayerType );
2098 return TRUE;
2101 static HRESULT WINAPI IDirectPlay2AImpl_DestroyPlayer( IDirectPlay2A *iface, DPID player )
2103 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2104 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4A_iface, player );
2107 static HRESULT WINAPI IDirectPlay2Impl_DestroyPlayer( IDirectPlay2 *iface, DPID player )
2109 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2110 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4_iface, player );
2113 static HRESULT WINAPI IDirectPlay3AImpl_DestroyPlayer( IDirectPlay3A *iface, DPID player )
2115 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2116 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4_iface, player );
2119 static HRESULT WINAPI IDirectPlay3Impl_DestroyPlayer( IDirectPlay3 *iface, DPID player )
2121 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2122 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4_iface, player );
2125 static HRESULT WINAPI IDirectPlay4AImpl_DestroyPlayer( IDirectPlay4A *iface, DPID idPlayer )
2127 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2128 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
2131 static HRESULT WINAPI IDirectPlay4Impl_DestroyPlayer( IDirectPlay4 *iface, DPID idPlayer )
2133 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2134 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
2137 static HRESULT WINAPI IDirectPlay2AImpl_EnumGroupPlayers( IDirectPlay2A *iface, DPID group,
2138 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2140 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2141 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4A_iface, group, instance,
2142 enumplayercb, context, flags );
2145 static HRESULT WINAPI IDirectPlay2Impl_EnumGroupPlayers( IDirectPlay2 *iface, DPID group,
2146 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2148 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2149 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance,
2150 enumplayercb, context, flags );
2153 static HRESULT WINAPI IDirectPlay3AImpl_EnumGroupPlayers( IDirectPlay3A *iface, DPID group,
2154 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2156 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2157 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance,
2158 enumplayercb, context, flags );
2161 static HRESULT WINAPI IDirectPlay3Impl_EnumGroupPlayers( IDirectPlay3 *iface, DPID group,
2162 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2164 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2165 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance,
2166 enumplayercb, context, flags );
2169 static HRESULT WINAPI IDirectPlay4AImpl_EnumGroupPlayers( IDirectPlay4A *iface, DPID group,
2170 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2172 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2173 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance, enumplayercb,
2174 context, flags );
2177 static HRESULT WINAPI IDirectPlay4Impl_EnumGroupPlayers( IDirectPlay4 *iface, DPID group,
2178 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2180 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2181 lpGroupData gdata;
2182 lpPlayerList plist;
2184 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x): semi stub\n", This, group, instance, enumplayercb,
2185 context, flags );
2187 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2188 return DPERR_UNINITIALIZED;
2190 /* Find the group */
2191 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
2192 return DPERR_INVALIDGROUP;
2194 if ( DPQ_IS_EMPTY( gdata->players ) )
2195 return DP_OK;
2197 /* Walk the players in this group */
2198 for( plist = DPQ_FIRST( gdata->players ); ; plist = DPQ_NEXT( plist->players ) )
2200 /* We do not enum the name server or app server as they are of no
2201 * consequence to the end user.
2203 if ( ( plist->lpPData->dpid != DPID_NAME_SERVER ) &&
2204 ( plist->lpPData->dpid != DPID_SERVERPLAYER ) )
2206 /* FIXME: Need to add stuff for flags checking */
2207 if ( !enumplayercb( plist->lpPData->dpid, DPPLAYERTYPE_PLAYER,
2208 &plist->lpPData->name, plist->lpPData->dwFlags, context ) )
2209 /* User requested break */
2210 return DP_OK;
2213 if ( DPQ_IS_ENDOFLIST( plist->players ) )
2214 break;
2216 return DP_OK;
2219 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2220 static HRESULT WINAPI IDirectPlay2AImpl_EnumGroups( IDirectPlay2A *iface, GUID *instance,
2221 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2223 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2224 return IDirectPlayX_EnumGroups( &This->IDirectPlay4A_iface, instance, enumplayercb, context,
2225 flags );
2228 static HRESULT WINAPI IDirectPlay2Impl_EnumGroups( IDirectPlay2 *iface, GUID *instance,
2229 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2231 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2232 return IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2233 flags );
2236 static HRESULT WINAPI IDirectPlay3AImpl_EnumGroups( IDirectPlay3A *iface, GUID *instance,
2237 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2239 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2240 return IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2241 flags );
2244 static HRESULT WINAPI IDirectPlay3Impl_EnumGroups( IDirectPlay3 *iface, GUID *instance,
2245 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2247 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2248 return IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2249 flags );
2252 static HRESULT WINAPI IDirectPlay4AImpl_EnumGroups( IDirectPlay4A *iface, GUID *instance,
2253 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2255 return IDirectPlayX_EnumGroupsInGroup( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2256 context, flags );
2259 static HRESULT WINAPI IDirectPlay4Impl_EnumGroups ( IDirectPlay4 *iface, GUID *instance,
2260 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2262 return IDirectPlayX_EnumGroupsInGroup( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2263 context, flags );
2266 static HRESULT WINAPI IDirectPlay2AImpl_EnumPlayers( IDirectPlay2A *iface, GUID *instance,
2267 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2269 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2270 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4A_iface, instance, enumplayercb, context,
2271 flags );
2274 static HRESULT WINAPI IDirectPlay2Impl_EnumPlayers( IDirectPlay2 *iface, GUID *instance,
2275 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2277 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2278 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2279 flags );
2282 static HRESULT WINAPI IDirectPlay3AImpl_EnumPlayers( IDirectPlay3A *iface, GUID *instance,
2283 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2285 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2286 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2287 flags );
2290 static HRESULT WINAPI IDirectPlay3Impl_EnumPlayers( IDirectPlay3 *iface, GUID *instance,
2291 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2293 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2294 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2295 flags );
2298 static HRESULT WINAPI IDirectPlay4AImpl_EnumPlayers( IDirectPlay4A *iface, GUID *instance,
2299 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2301 return IDirectPlayX_EnumGroupPlayers( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2302 context, flags );
2305 static HRESULT WINAPI IDirectPlay4Impl_EnumPlayers( IDirectPlay4 *iface, GUID *instance,
2306 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2308 return IDirectPlayX_EnumGroupPlayers( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2309 context, flags );
2312 /* This function should call the registered callback function that the user
2313 passed into EnumSessions for each entry available.
2315 static void DP_InvokeEnumSessionCallbacks
2316 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2317 LPVOID lpNSInfo,
2318 DWORD dwTimeout,
2319 LPVOID lpContext )
2321 LPDPSESSIONDESC2 lpSessionDesc;
2323 FIXME( ": not checking for conditions\n" );
2325 /* Not sure if this should be pruning but it's convenient */
2326 NS_PruneSessionCache( lpNSInfo );
2328 NS_ResetSessionEnumeration( lpNSInfo );
2330 /* Enumerate all sessions */
2331 /* FIXME: Need to indicate ANSI */
2332 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2334 TRACE( "EnumSessionsCallback2 invoked\n" );
2335 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2337 return;
2341 /* Invoke one last time to indicate that there is no more to come */
2342 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2345 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2347 EnumSessionAsyncCallbackData* data = lpContext;
2348 HANDLE hSuicideRequest = data->hSuicideRequest;
2349 DWORD dwTimeout = data->dwTimeout;
2351 TRACE( "Thread started with timeout = 0x%08x\n", dwTimeout );
2353 for( ;; )
2355 HRESULT hr;
2357 /* Sleep up to dwTimeout waiting for request to terminate thread */
2358 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2360 TRACE( "Thread terminating on terminate request\n" );
2361 break;
2364 /* Now resend the enum request */
2365 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2366 data->dwEnumSessionFlags,
2367 data->lpSpData );
2369 if( FAILED(hr) )
2371 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2372 /* FIXME: Should we kill this thread? How to inform the main thread? */
2377 TRACE( "Thread terminating\n" );
2379 /* Clean up the thread data */
2380 CloseHandle( hSuicideRequest );
2381 HeapFree( GetProcessHeap(), 0, lpContext );
2383 /* FIXME: Need to have some notification to main app thread that this is
2384 * dead. It would serve two purposes. 1) allow sync on termination
2385 * so that we don't actually send something to ourselves when we
2386 * become name server (race condition) and 2) so that if we die
2387 * abnormally something else will be able to tell.
2390 return 1;
2393 static void DP_KillEnumSessionThread( IDirectPlayImpl *This )
2395 /* Does a thread exist? If so we were doing an async enum session */
2396 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2398 TRACE( "Killing EnumSession thread %p\n",
2399 This->dp2->hEnumSessionThread );
2401 /* Request that the thread kill itself nicely */
2402 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2403 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2405 /* We no longer need to know about the thread */
2406 CloseHandle( This->dp2->hEnumSessionThread );
2408 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2412 static HRESULT WINAPI IDirectPlay2AImpl_EnumSessions( IDirectPlay2A *iface, DPSESSIONDESC2 *sdesc,
2413 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2415 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2416 return IDirectPlayX_EnumSessions( &This->IDirectPlay4A_iface, sdesc, timeout, enumsessioncb,
2417 context, flags );
2420 static HRESULT WINAPI IDirectPlay2Impl_EnumSessions( IDirectPlay2 *iface, DPSESSIONDESC2 *sdesc,
2421 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2423 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2424 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2425 context, flags );
2428 static HRESULT WINAPI IDirectPlay3AImpl_EnumSessions( IDirectPlay3A *iface, DPSESSIONDESC2 *sdesc,
2429 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2431 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2432 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2433 context, flags );
2436 static HRESULT WINAPI IDirectPlay3Impl_EnumSessions( IDirectPlay3 *iface, DPSESSIONDESC2 *sdesc,
2437 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2439 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2440 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2441 context, flags );
2444 static HRESULT WINAPI IDirectPlay4AImpl_EnumSessions( IDirectPlay4A *iface, DPSESSIONDESC2 *sdesc,
2445 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2447 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2448 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2449 context, flags );
2452 static HRESULT WINAPI IDirectPlay4Impl_EnumSessions( IDirectPlay4 *iface, DPSESSIONDESC2 *sdesc,
2453 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2455 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2456 void *connection;
2457 DWORD size;
2458 HRESULT hr = DP_OK;
2460 TRACE( "(%p)->(%p,0x%08x,%p,%p,0x%08x)\n", This, sdesc, timeout, enumsessioncb,
2461 context, flags );
2463 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2464 return DPERR_UNINITIALIZED;
2466 /* Can't enumerate if the interface is already open */
2467 if ( This->dp2->bConnectionOpen )
2468 return DPERR_GENERIC;
2470 /* The loading of a lobby provider _seems_ to require a backdoor loading
2471 * of the service provider to also associate with this DP object. This is
2472 * because the app doesn't seem to have to call EnumConnections and
2473 * InitializeConnection for the SP before calling this method. As such
2474 * we'll do their dirty work for them with a quick hack so as to always
2475 * load the TCP/IP service provider.
2477 * The correct solution would seem to involve creating a dialog box which
2478 * contains the possible SPs. These dialog boxes most likely follow SDK
2479 * examples.
2481 if ( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
2483 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2485 if ( !DP_BuildSPCompoundAddr( (GUID*)&DPSPGUID_TCPIP, &connection, &size ) )
2487 ERR( "Can't build compound addr\n" );
2488 return DPERR_GENERIC;
2491 hr = IDirectPlayX_InitializeConnection( &This->IDirectPlay4_iface, connection, 0 );
2492 if ( FAILED(hr) )
2493 return hr;
2495 HeapFree( GetProcessHeap(), 0, connection );
2496 This->dp2->bSPInitialized = TRUE;
2500 /* Use the service provider default? */
2501 if ( !timeout )
2503 DPCAPS caps;
2504 caps.dwSize = sizeof( caps );
2506 IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, &caps, 0 );
2507 timeout = caps.dwTimeout;
2508 if ( !timeout )
2509 timeout = DPMSG_WAIT_5_SECS; /* Provide the TCP/IP default */
2512 if ( flags & DPENUMSESSIONS_STOPASYNC )
2514 DP_KillEnumSessionThread( This );
2515 return hr;
2518 if ( flags & DPENUMSESSIONS_ASYNC )
2520 /* Enumerate everything presently in the local session cache */
2521 DP_InvokeEnumSessionCallbacks( enumsessioncb, This->dp2->lpNameServerData, timeout,
2522 context );
2524 if ( This->dp2->dwEnumSessionLock )
2525 return DPERR_CONNECTING;
2527 /* See if we've already created a thread to service this interface */
2528 if ( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2530 DWORD tid;
2531 This->dp2->dwEnumSessionLock++;
2533 /* Send the first enum request inline since the user may cancel a dialog
2534 * if one is presented. Also, may also have a connecting return code.
2536 hr = NS_SendSessionRequestBroadcast( &sdesc->guidApplication, flags,
2537 &This->dp2->spData );
2539 if ( SUCCEEDED(hr) )
2541 EnumSessionAsyncCallbackData* data = HeapAlloc( GetProcessHeap(),
2542 HEAP_ZERO_MEMORY, sizeof( *data ) );
2543 /* FIXME: need to kill the thread on object deletion */
2544 data->lpSpData = &This->dp2->spData;
2545 data->requestGuid = sdesc->guidApplication;
2546 data->dwEnumSessionFlags = flags;
2547 data->dwTimeout = timeout;
2549 This->dp2->hKillEnumSessionThreadEvent = CreateEventW( NULL, TRUE, FALSE, NULL );
2550 if ( !DuplicateHandle( GetCurrentProcess(), This->dp2->hKillEnumSessionThreadEvent,
2551 GetCurrentProcess(), &data->hSuicideRequest, 0, FALSE,
2552 DUPLICATE_SAME_ACCESS ) )
2553 ERR( "Can't duplicate thread killing handle\n" );
2555 TRACE( ": creating EnumSessionsRequest thread\n" );
2556 This->dp2->hEnumSessionThread = CreateThread( NULL, 0,
2557 DP_EnumSessionsSendAsyncRequestThread, data, 0, &tid );
2559 This->dp2->dwEnumSessionLock--;
2562 else
2564 /* Invalidate the session cache for the interface */
2565 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2566 /* Send the broadcast for session enumeration */
2567 hr = NS_SendSessionRequestBroadcast( &sdesc->guidApplication, flags, &This->dp2->spData );
2568 SleepEx( timeout, FALSE );
2569 DP_InvokeEnumSessionCallbacks( enumsessioncb, This->dp2->lpNameServerData, timeout,
2570 context );
2573 return hr;
2576 static HRESULT WINAPI IDirectPlay2AImpl_GetCaps( IDirectPlay2A *iface, DPCAPS *caps, DWORD flags )
2578 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2579 return IDirectPlayX_GetCaps( &This->IDirectPlay4A_iface, caps, flags );
2582 static HRESULT WINAPI IDirectPlay2Impl_GetCaps( IDirectPlay2 *iface, DPCAPS *caps, DWORD flags )
2584 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2585 return IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, caps, flags );
2588 static HRESULT WINAPI IDirectPlay3AImpl_GetCaps( IDirectPlay3A *iface, DPCAPS *caps, DWORD flags )
2590 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2591 return IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, caps, flags );
2594 static HRESULT WINAPI IDirectPlay3Impl_GetCaps( IDirectPlay3 *iface, DPCAPS *caps, DWORD flags )
2596 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2597 return IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, caps, flags );
2600 static HRESULT WINAPI IDirectPlay4AImpl_GetCaps( IDirectPlay4A *iface, DPCAPS *caps, DWORD flags )
2602 return IDirectPlayX_GetPlayerCaps( iface, DPID_ALLPLAYERS, caps, flags );
2605 static HRESULT WINAPI IDirectPlay4Impl_GetCaps( IDirectPlay4 *iface, DPCAPS *caps, DWORD flags )
2607 return IDirectPlayX_GetPlayerCaps( iface, DPID_ALLPLAYERS, caps, flags );
2610 static HRESULT WINAPI IDirectPlay2AImpl_GetGroupData( IDirectPlay2A *iface, DPID group, void *data,
2611 DWORD *size, DWORD flags )
2613 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2614 return IDirectPlayX_GetGroupData( &This->IDirectPlay4A_iface, group, data, size, flags );
2617 static HRESULT WINAPI IDirectPlay2Impl_GetGroupData( IDirectPlay2 *iface, DPID group, void *data,
2618 DWORD *size, DWORD flags )
2620 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2621 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2624 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupData( IDirectPlay3A *iface, DPID group, void *data,
2625 DWORD *size, DWORD flags )
2627 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2628 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2631 static HRESULT WINAPI IDirectPlay3Impl_GetGroupData( IDirectPlay3 *iface, DPID group, void *data,
2632 DWORD *size, DWORD flags )
2634 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2635 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2638 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupData( IDirectPlay4A *iface, DPID group,
2639 void *data, DWORD *size, DWORD flags )
2641 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2642 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2645 static HRESULT WINAPI IDirectPlay4Impl_GetGroupData( IDirectPlay4 *iface, DPID group,
2646 void *data, DWORD *size, DWORD flags )
2648 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2649 lpGroupData gdata;
2650 DWORD bufsize;
2651 void *src;
2653 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x)\n", This, group, data, size, flags );
2655 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
2656 return DPERR_INVALIDGROUP;
2658 /* How much buffer is required? */
2659 if ( flags & DPSET_LOCAL )
2661 bufsize = gdata->dwLocalDataSize;
2662 src = gdata->lpLocalData;
2664 else
2666 bufsize = gdata->dwRemoteDataSize;
2667 src = gdata->lpRemoteData;
2670 /* Is the user requesting to know how big a buffer is required? */
2671 if ( !data || *size < bufsize )
2673 *size = bufsize;
2674 return DPERR_BUFFERTOOSMALL;
2677 CopyMemory( data, src, bufsize );
2679 return DP_OK;
2682 static HRESULT DP_IF_GetGroupName( IDirectPlayImpl *This, DPID idGroup, void *lpData,
2683 DWORD *lpdwDataSize, BOOL bAnsi )
2685 lpGroupData lpGData;
2686 LPDPNAME lpName = lpData;
2687 DWORD dwRequiredDataSize;
2689 FIXME("(%p)->(0x%08x,%p,%p,%u) ANSI ignored\n",
2690 This, idGroup, lpData, lpdwDataSize, bAnsi );
2692 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2694 return DPERR_INVALIDGROUP;
2697 dwRequiredDataSize = lpGData->name.dwSize;
2699 if( lpGData->name.u1.lpszShortNameA )
2701 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
2704 if( lpGData->name.u2.lpszLongNameA )
2706 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
2709 if( ( lpData == NULL ) ||
2710 ( *lpdwDataSize < dwRequiredDataSize )
2713 *lpdwDataSize = dwRequiredDataSize;
2714 return DPERR_BUFFERTOOSMALL;
2717 /* Copy the structure */
2718 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2720 if( lpGData->name.u1.lpszShortNameA )
2722 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2723 lpGData->name.u1.lpszShortNameA );
2725 else
2727 lpName->u1.lpszShortNameA = NULL;
2730 if( lpGData->name.u1.lpszShortNameA )
2732 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2733 lpGData->name.u2.lpszLongNameA );
2735 else
2737 lpName->u2.lpszLongNameA = NULL;
2740 return DP_OK;
2743 static HRESULT WINAPI IDirectPlay2AImpl_GetGroupName( IDirectPlay2A *iface, DPID group, void *data,
2744 DWORD *size )
2746 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2747 return IDirectPlayX_GetGroupName( &This->IDirectPlay4A_iface, group, data, size );
2750 static HRESULT WINAPI IDirectPlay2Impl_GetGroupName( IDirectPlay2 *iface, DPID group, void *data,
2751 DWORD *size )
2753 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2754 return IDirectPlayX_GetGroupName( &This->IDirectPlay4_iface, group, data, size );
2757 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupName( IDirectPlay3A *iface, DPID group, void *data,
2758 DWORD *size )
2760 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2761 return IDirectPlayX_GetGroupName( &This->IDirectPlay4_iface, group, data, size );
2764 static HRESULT WINAPI IDirectPlay3Impl_GetGroupName( IDirectPlay3 *iface, DPID group, void *data,
2765 DWORD *size )
2767 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2768 return IDirectPlayX_GetGroupName( &This->IDirectPlay4_iface, group, data, size );
2771 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupName( IDirectPlay4A *iface, DPID idGroup,
2772 void *lpData, DWORD *lpdwDataSize )
2774 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2775 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2778 static HRESULT WINAPI IDirectPlay4Impl_GetGroupName( IDirectPlay4 *iface, DPID idGroup,
2779 void *lpData, DWORD *lpdwDataSize )
2781 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2782 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2785 static HRESULT WINAPI IDirectPlay2AImpl_GetMessageCount( IDirectPlay2A *iface, DPID player,
2786 DWORD *count )
2788 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2789 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4A_iface, player, count );
2792 static HRESULT WINAPI IDirectPlay2Impl_GetMessageCount( IDirectPlay2 *iface, DPID player,
2793 DWORD *count )
2795 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2796 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4_iface, player, count );
2799 static HRESULT WINAPI IDirectPlay3AImpl_GetMessageCount( IDirectPlay3A *iface, DPID player,
2800 DWORD *count )
2802 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2803 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4_iface, player, count );
2806 static HRESULT WINAPI IDirectPlay3Impl_GetMessageCount( IDirectPlay3 *iface, DPID player,
2807 DWORD *count )
2809 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2810 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4_iface, player, count );
2813 static HRESULT WINAPI IDirectPlay4AImpl_GetMessageCount( IDirectPlay4A *iface, DPID player,
2814 DWORD *count )
2816 return IDirectPlayX_GetMessageQueue( iface, 0, player, DPMESSAGEQUEUE_RECEIVE, count, NULL );
2819 static HRESULT WINAPI IDirectPlay4Impl_GetMessageCount( IDirectPlay4 *iface, DPID player,
2820 DWORD *count )
2822 return IDirectPlayX_GetMessageQueue( iface, 0, player, DPMESSAGEQUEUE_RECEIVE, count, NULL );
2825 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerAddress( IDirectPlay2A *iface, DPID player,
2826 void *data, DWORD *size )
2828 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2829 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4A_iface, player, data, size );
2832 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerAddress( IDirectPlay2 *iface, DPID player,
2833 void *data, DWORD *size )
2835 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2836 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4_iface, player, data, size );
2839 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerAddress( IDirectPlay3A *iface, DPID player,
2840 void *data, DWORD *size )
2842 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2843 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4_iface, player, data, size );
2846 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerAddress( IDirectPlay3 *iface, DPID player,
2847 void *data, DWORD *size )
2849 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2850 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4_iface, player, data, size );
2853 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerAddress( IDirectPlay4A *iface, DPID player,
2854 void *data, DWORD *size )
2856 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2857 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, player, data, size );
2858 return DP_OK;
2861 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerAddress( IDirectPlay4 *iface, DPID player,
2862 void *data, DWORD *size )
2864 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2865 FIXME( "(%p)->(0x%08x,%p,%p): stub\n", This, player, data, size );
2866 return DP_OK;
2869 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerCaps( IDirectPlay2A *iface, DPID player,
2870 DPCAPS *caps, DWORD flags )
2872 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2873 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4A_iface, player, caps, flags );
2876 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerCaps( IDirectPlay2 *iface, DPID player,
2877 DPCAPS *caps, DWORD flags )
2879 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2880 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2883 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerCaps( IDirectPlay3A *iface, DPID player,
2884 DPCAPS *caps, DWORD flags )
2886 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2887 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2890 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerCaps( IDirectPlay3 *iface, DPID player,
2891 DPCAPS *caps, DWORD flags )
2893 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2894 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2897 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerCaps( IDirectPlay4A *iface, DPID player,
2898 DPCAPS *caps, DWORD flags )
2900 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2901 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2904 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerCaps( IDirectPlay4 *iface, DPID player,
2905 DPCAPS *caps, DWORD flags )
2907 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2908 DPSP_GETCAPSDATA data;
2910 TRACE( "(%p)->(0x%08x,%p,0x%08x)\n", This, player, caps, flags);
2912 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2913 return DPERR_UNINITIALIZED;
2915 /* Query the service provider */
2916 data.idPlayer = player;
2917 data.dwFlags = flags;
2918 data.lpCaps = caps;
2919 data.lpISP = This->dp2->spData.lpISP;
2921 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2924 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerData( IDirectPlay2A *iface, DPID player,
2925 void *data, DWORD *size, DWORD flags )
2927 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2928 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4A_iface, player, data, size, flags );
2931 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerData( IDirectPlay2 *iface, DPID player,
2932 void *data, DWORD *size, DWORD flags )
2934 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2935 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2938 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerData( IDirectPlay3A *iface, DPID player,
2939 void *data, DWORD *size, DWORD flags )
2941 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2942 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2945 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerData( IDirectPlay3 *iface, DPID player,
2946 void *data, DWORD *size, DWORD flags )
2948 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2949 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2952 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerData( IDirectPlay4A *iface, DPID player,
2953 void *data, DWORD *size, DWORD flags )
2955 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2956 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2959 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerData( IDirectPlay4 *iface, DPID player,
2960 void *data, DWORD *size, DWORD flags )
2962 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2963 lpPlayerList plist;
2964 DWORD bufsize;
2965 void *src;
2967 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x)\n", This, player, data, size, flags );
2969 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2970 return DPERR_UNINITIALIZED;
2972 if ( ( plist = DP_FindPlayer( This, player ) ) == NULL )
2973 return DPERR_INVALIDPLAYER;
2975 if ( flags & DPSET_LOCAL )
2977 bufsize = plist->lpPData->dwLocalDataSize;
2978 src = plist->lpPData->lpLocalData;
2980 else
2982 bufsize = plist->lpPData->dwRemoteDataSize;
2983 src = plist->lpPData->lpRemoteData;
2986 /* Is the user requesting to know how big a buffer is required? */
2987 if ( !data || *size < bufsize )
2989 *size = bufsize;
2990 return DPERR_BUFFERTOOSMALL;
2993 CopyMemory( data, src, bufsize );
2995 return DP_OK;
2998 static HRESULT DP_IF_GetPlayerName( IDirectPlayImpl *This, DPID idPlayer, void *lpData,
2999 DWORD *lpdwDataSize, BOOL bAnsi )
3001 lpPlayerList lpPList;
3002 LPDPNAME lpName = lpData;
3003 DWORD dwRequiredDataSize;
3005 FIXME( "(%p)->(0x%08x,%p,%p,%u): ANSI\n",
3006 This, idPlayer, lpData, lpdwDataSize, bAnsi );
3008 if( This->dp2->connectionInitialized == NO_PROVIDER )
3010 return DPERR_UNINITIALIZED;
3013 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3015 return DPERR_INVALIDPLAYER;
3018 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
3020 if( lpPList->lpPData->name.u1.lpszShortNameA )
3022 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
3025 if( lpPList->lpPData->name.u2.lpszLongNameA )
3027 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
3030 if( ( lpData == NULL ) ||
3031 ( *lpdwDataSize < dwRequiredDataSize )
3034 *lpdwDataSize = dwRequiredDataSize;
3035 return DPERR_BUFFERTOOSMALL;
3038 /* Copy the structure */
3039 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
3041 if( lpPList->lpPData->name.u1.lpszShortNameA )
3043 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
3044 lpPList->lpPData->name.u1.lpszShortNameA );
3046 else
3048 lpName->u1.lpszShortNameA = NULL;
3051 if( lpPList->lpPData->name.u1.lpszShortNameA )
3053 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
3054 lpPList->lpPData->name.u2.lpszLongNameA );
3056 else
3058 lpName->u2.lpszLongNameA = NULL;
3061 return DP_OK;
3064 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerName( IDirectPlay2A *iface, DPID player,
3065 void *data, DWORD *size )
3067 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3068 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4A_iface, player, data, size );
3071 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerName( IDirectPlay2 *iface, DPID player,
3072 void *data, DWORD *size )
3074 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3075 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4_iface, player, data, size );
3078 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerName( IDirectPlay3A *iface, DPID player,
3079 void *data, DWORD *size )
3081 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3082 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4_iface, player, data, size );
3085 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerName( IDirectPlay3 *iface, DPID player,
3086 void *data, DWORD *size )
3088 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3089 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4_iface, player, data, size );
3092 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerName( IDirectPlay4A *iface, DPID idPlayer,
3093 void *lpData, DWORD *lpdwDataSize )
3095 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3096 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
3099 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerName( IDirectPlay4 *iface, DPID idPlayer,
3100 void *lpData, DWORD *lpdwDataSize )
3102 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3103 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
3106 static HRESULT DP_GetSessionDesc( IDirectPlayImpl *This, void *lpData, DWORD *lpdwDataSize,
3107 BOOL bAnsi )
3109 DWORD dwRequiredSize;
3111 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
3113 if( This->dp2->connectionInitialized == NO_PROVIDER )
3115 return DPERR_UNINITIALIZED;
3118 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
3120 return DPERR_INVALIDPARAMS;
3123 /* FIXME: Get from This->dp2->lpSessionDesc */
3124 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
3126 if ( ( lpData == NULL ) ||
3127 ( *lpdwDataSize < dwRequiredSize )
3130 *lpdwDataSize = dwRequiredSize;
3131 return DPERR_BUFFERTOOSMALL;
3134 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
3136 return DP_OK;
3139 static HRESULT WINAPI IDirectPlay2AImpl_GetSessionDesc( IDirectPlay2A *iface, void *data,
3140 DWORD *size )
3142 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3143 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4A_iface, data, size );
3146 static HRESULT WINAPI IDirectPlay2Impl_GetSessionDesc( IDirectPlay2 *iface, void *data,
3147 DWORD *size )
3149 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3150 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4_iface, data, size );
3153 static HRESULT WINAPI IDirectPlay3AImpl_GetSessionDesc( IDirectPlay3A *iface, void *data,
3154 DWORD *size )
3156 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3157 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4_iface, data, size );
3160 static HRESULT WINAPI IDirectPlay3Impl_GetSessionDesc( IDirectPlay3 *iface, void *data,
3161 DWORD *size )
3163 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3164 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4_iface, data, size );
3167 static HRESULT WINAPI IDirectPlay4AImpl_GetSessionDesc( IDirectPlay4A *iface, void *lpData,
3168 DWORD *lpdwDataSize )
3170 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3171 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
3174 static HRESULT WINAPI IDirectPlay4Impl_GetSessionDesc( IDirectPlay4 *iface, void *lpData,
3175 DWORD *lpdwDataSize )
3177 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3178 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
3181 static HRESULT WINAPI IDirectPlay2AImpl_Initialize( IDirectPlay2A *iface, GUID *guid )
3183 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3184 return IDirectPlayX_Initialize( &This->IDirectPlay4A_iface, guid );
3187 static HRESULT WINAPI IDirectPlay2Impl_Initialize( IDirectPlay2 *iface, GUID *guid )
3189 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3190 return IDirectPlayX_Initialize( &This->IDirectPlay4_iface, guid );
3193 static HRESULT WINAPI IDirectPlay3AImpl_Initialize( IDirectPlay3A *iface, GUID *guid )
3195 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3196 return IDirectPlayX_Initialize( &This->IDirectPlay4_iface, guid );
3199 static HRESULT WINAPI IDirectPlay3Impl_Initialize( IDirectPlay3 *iface, GUID *guid )
3201 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3202 return IDirectPlayX_Initialize( &This->IDirectPlay4_iface, guid );
3205 /* Intended only for COM compatibility. Always returns an error. */
3206 static HRESULT WINAPI IDirectPlay4AImpl_Initialize( IDirectPlay4A *iface, GUID *guid )
3208 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3209 TRACE("(%p)->(%p): no-op\n", This, guid );
3210 return DPERR_ALREADYINITIALIZED;
3213 static HRESULT WINAPI IDirectPlay4Impl_Initialize( IDirectPlay4 *iface, GUID *guid )
3215 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3216 TRACE( "(%p)->(%p): no-op\n", This, guid );
3217 return DPERR_ALREADYINITIALIZED;
3221 static HRESULT DP_SecureOpen( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpsd, DWORD dwFlags,
3222 const DPSECURITYDESC *lpSecurity, const DPCREDENTIALS *lpCredentials, BOOL bAnsi )
3224 HRESULT hr = DP_OK;
3226 FIXME( "(%p)->(%p,0x%08x,%p,%p): partial stub\n",
3227 This, lpsd, dwFlags, lpSecurity, lpCredentials );
3229 if( This->dp2->connectionInitialized == NO_PROVIDER )
3231 return DPERR_UNINITIALIZED;
3234 if( lpsd->dwSize != sizeof(DPSESSIONDESC2) )
3236 TRACE( ": rejecting invalid dpsd size (%d).\n", lpsd->dwSize );
3237 return DPERR_INVALIDPARAMS;
3240 if( This->dp2->bConnectionOpen )
3242 TRACE( ": rejecting already open connection.\n" );
3243 return DPERR_ALREADYINITIALIZED;
3246 /* If we're enumerating, kill the thread */
3247 DP_KillEnumSessionThread( This );
3249 if( dwFlags & DPOPEN_CREATE )
3251 /* Rightoo - this computer is the host and the local computer needs to be
3252 the name server so that others can join this session */
3253 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
3255 This->dp2->bHostInterface = TRUE;
3257 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
3258 if( FAILED( hr ) )
3260 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
3261 return hr;
3265 /* Invoke the conditional callback for the service provider */
3266 if( This->dp2->spData.lpCB->Open )
3268 DPSP_OPENDATA data;
3270 FIXME( "Not all data fields are correct. Need new parameter\n" );
3272 data.bCreate = (dwFlags & DPOPEN_CREATE ) != 0;
3273 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
3274 : NS_GetNSAddr( This->dp2->lpNameServerData );
3275 data.lpISP = This->dp2->spData.lpISP;
3276 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) != 0;
3277 data.dwOpenFlags = dwFlags;
3278 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
3280 hr = (*This->dp2->spData.lpCB->Open)(&data);
3281 if( FAILED( hr ) )
3283 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
3284 return hr;
3289 /* Create the system group of which everything is a part of */
3290 DPID systemGroup = DPID_SYSTEM_GROUP;
3292 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
3293 NULL, 0, 0, TRUE );
3297 if( dwFlags & DPOPEN_JOIN )
3299 DPID dpidServerId = DPID_UNKNOWN;
3301 /* Create the server player for this interface. This way we can receive
3302 * messages for this session.
3304 /* FIXME: I suppose that we should be setting an event for a receive
3305 * type of thing. That way the messaging thread could know to wake
3306 * up. DPlay would then trigger the hEvent for the player the
3307 * message is directed to.
3309 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
3311 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
3314 else if( dwFlags & DPOPEN_CREATE )
3316 DPID dpidNameServerId = DPID_NAME_SERVER;
3318 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
3319 0, DPPLAYER_SERVERPLAYER, bAnsi );
3322 if( FAILED(hr) )
3324 ERR( "Couldn't create name server/system player: %s\n",
3325 DPLAYX_HresultToString(hr) );
3328 return hr;
3331 static HRESULT WINAPI IDirectPlay2AImpl_Open( IDirectPlay2A *iface, DPSESSIONDESC2 *sdesc,
3332 DWORD flags )
3334 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3335 return IDirectPlayX_Open( &This->IDirectPlay4A_iface, sdesc, flags );
3338 static HRESULT WINAPI IDirectPlay2Impl_Open( IDirectPlay2 *iface, DPSESSIONDESC2 *sdesc,
3339 DWORD flags )
3341 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3342 return IDirectPlayX_Open( &This->IDirectPlay4_iface, sdesc, flags );
3345 static HRESULT WINAPI IDirectPlay3AImpl_Open( IDirectPlay3A *iface, DPSESSIONDESC2 *sdesc,
3346 DWORD flags )
3348 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3349 return IDirectPlayX_Open( &This->IDirectPlay4_iface, sdesc, flags );
3352 static HRESULT WINAPI IDirectPlay3Impl_Open( IDirectPlay3 *iface, DPSESSIONDESC2 *sdesc,
3353 DWORD flags )
3355 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3356 return IDirectPlayX_Open( &This->IDirectPlay4_iface, sdesc, flags );
3359 static HRESULT WINAPI IDirectPlay4AImpl_Open( IDirectPlay4A *iface, DPSESSIONDESC2 *sdesc,
3360 DWORD flags )
3362 return IDirectPlayX_SecureOpen( iface, sdesc, flags, NULL, NULL );
3365 static HRESULT WINAPI IDirectPlay4Impl_Open( IDirectPlay4 *iface, DPSESSIONDESC2 *sdesc,
3366 DWORD flags )
3368 return IDirectPlayX_SecureOpen( iface, sdesc, flags, NULL, NULL );
3371 static HRESULT DP_IF_Receive( IDirectPlayImpl *This, DPID *lpidFrom, DPID *lpidTo, DWORD dwFlags,
3372 void *lpData, DWORD *lpdwDataSize, BOOL bAnsi )
3374 LPDPMSG lpMsg = NULL;
3376 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p,%u): stub\n",
3377 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
3379 if( This->dp2->connectionInitialized == NO_PROVIDER )
3381 return DPERR_UNINITIALIZED;
3384 if( dwFlags == 0 )
3386 dwFlags = DPRECEIVE_ALL;
3389 /* If the lpData is NULL, we must be peeking the message */
3390 if( ( lpData == NULL ) &&
3391 !( dwFlags & DPRECEIVE_PEEK )
3394 return DPERR_INVALIDPARAMS;
3397 if( dwFlags & DPRECEIVE_ALL )
3399 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
3401 if( !( dwFlags & DPRECEIVE_PEEK ) )
3403 FIXME( "Remove from queue\n" );
3406 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
3407 ( dwFlags & DPRECEIVE_FROMPLAYER )
3410 FIXME( "Find matching message 0x%08x\n", dwFlags );
3412 else
3414 ERR( "Hmmm..dwFlags 0x%08x\n", dwFlags );
3417 if( lpMsg == NULL )
3419 return DPERR_NOMESSAGES;
3422 /* Copy into the provided buffer */
3423 if (lpData) CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
3425 return DP_OK;
3428 static HRESULT WINAPI IDirectPlay2AImpl_Receive( IDirectPlay2A *iface, DPID *from, DPID *to,
3429 DWORD flags, void *data, DWORD *size )
3431 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3432 return IDirectPlayX_Receive( &This->IDirectPlay4A_iface, from, to, flags, data, size );
3435 static HRESULT WINAPI IDirectPlay2Impl_Receive( IDirectPlay2 *iface, DPID *from, DPID *to,
3436 DWORD flags, void *data, DWORD *size )
3438 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3439 return IDirectPlayX_Receive( &This->IDirectPlay4_iface, from, to, flags, data, size );
3442 static HRESULT WINAPI IDirectPlay3AImpl_Receive( IDirectPlay3A *iface, DPID *from, DPID *to,
3443 DWORD flags, void *data, DWORD *size )
3445 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3446 return IDirectPlayX_Receive( &This->IDirectPlay4_iface, from, to, flags, data, size );
3449 static HRESULT WINAPI IDirectPlay3Impl_Receive( IDirectPlay3 *iface, DPID *from, DPID *to,
3450 DWORD flags, void *data, DWORD *size )
3452 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3453 return IDirectPlayX_Receive( &This->IDirectPlay4_iface, from, to, flags, data, size );
3456 static HRESULT WINAPI IDirectPlay4AImpl_Receive( IDirectPlay4A *iface, DPID *lpidFrom,
3457 DPID *lpidTo, DWORD dwFlags, void *lpData, DWORD *lpdwDataSize )
3459 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3460 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, TRUE );
3463 static HRESULT WINAPI IDirectPlay4Impl_Receive( IDirectPlay4 *iface, DPID *lpidFrom,
3464 DPID *lpidTo, DWORD dwFlags, void *lpData, DWORD *lpdwDataSize )
3466 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3467 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, FALSE );
3470 static HRESULT WINAPI IDirectPlay2AImpl_Send( IDirectPlay2A *iface, DPID from, DPID to,
3471 DWORD flags, void *data, DWORD size )
3473 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3474 return IDirectPlayX_Send( &This->IDirectPlay4A_iface, from, to, flags, data, size );
3477 static HRESULT WINAPI IDirectPlay2Impl_Send( IDirectPlay2 *iface, DPID from, DPID to,
3478 DWORD flags, void *data, DWORD size )
3480 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3481 return IDirectPlayX_Send( &This->IDirectPlay4_iface, from, to, flags, data, size );
3484 static HRESULT WINAPI IDirectPlay3AImpl_Send( IDirectPlay3A *iface, DPID from, DPID to,
3485 DWORD flags, void *data, DWORD size )
3487 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3488 return IDirectPlayX_Send( &This->IDirectPlay4_iface, from, to, flags, data, size );
3491 static HRESULT WINAPI IDirectPlay3Impl_Send( IDirectPlay3 *iface, DPID from, DPID to,
3492 DWORD flags, void *data, DWORD size )
3494 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3495 return IDirectPlayX_Send( &This->IDirectPlay4_iface, from, to, flags, data, size );
3498 static HRESULT WINAPI IDirectPlay4AImpl_Send( IDirectPlay4A *iface, DPID from, DPID to,
3499 DWORD flags, void *data, DWORD size )
3501 return IDirectPlayX_SendEx( iface, from, to, flags, data, size, 0, 0, NULL, NULL );
3504 static HRESULT WINAPI IDirectPlay4Impl_Send( IDirectPlay4 *iface, DPID from, DPID to,
3505 DWORD flags, void *data, DWORD size )
3507 return IDirectPlayX_SendEx( iface, from, to, flags, data, size, 0, 0, NULL, NULL );
3510 static HRESULT WINAPI IDirectPlay2AImpl_SetGroupData( IDirectPlay2A *iface, DPID group, void *data,
3511 DWORD size, DWORD flags )
3513 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3514 return IDirectPlayX_SetGroupData( &This->IDirectPlay4A_iface, group, data, size, flags );
3517 static HRESULT WINAPI IDirectPlay2Impl_SetGroupData( IDirectPlay2 *iface, DPID group, void *data,
3518 DWORD size, DWORD flags )
3520 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3521 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3524 static HRESULT WINAPI IDirectPlay3AImpl_SetGroupData( IDirectPlay3A *iface, DPID group, void *data,
3525 DWORD size, DWORD flags )
3527 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3528 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3531 static HRESULT WINAPI IDirectPlay3Impl_SetGroupData( IDirectPlay3 *iface, DPID group, void *data,
3532 DWORD size, DWORD flags )
3534 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3535 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3538 static HRESULT WINAPI IDirectPlay4AImpl_SetGroupData( IDirectPlay4A *iface, DPID group, void *data,
3539 DWORD size, DWORD flags )
3541 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3542 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3545 static HRESULT WINAPI IDirectPlay4Impl_SetGroupData( IDirectPlay4 *iface, DPID group, void *data,
3546 DWORD size, DWORD flags )
3548 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3549 lpGroupData gdata;
3551 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x)\n", This, group, data, size, flags );
3553 /* Parameter check */
3554 if ( !data && size )
3555 return DPERR_INVALIDPARAMS;
3557 /* Find the pointer to the data for this player */
3558 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
3559 return DPERR_INVALIDOBJECT;
3561 if ( !(flags & DPSET_LOCAL) )
3563 FIXME( "Was this group created by this interface?\n" );
3564 /* FIXME: If this is a remote update need to allow it but not
3565 * send a message.
3569 DP_SetGroupData( gdata, flags, data, size );
3571 /* FIXME: Only send a message if this group is local to the session otherwise
3572 * it will have been rejected above
3574 if ( !(flags & DPSET_LOCAL) )
3575 FIXME( "Send msg?\n" );
3577 return DP_OK;
3580 static HRESULT DP_IF_SetGroupName( IDirectPlayImpl *This, DPID idGroup, DPNAME *lpGroupName,
3581 DWORD dwFlags, BOOL bAnsi )
3583 lpGroupData lpGData;
3585 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n", This, idGroup,
3586 lpGroupName, dwFlags, bAnsi );
3588 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3590 return DPERR_INVALIDGROUP;
3593 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
3595 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3596 FIXME( "Message not sent and dwFlags ignored\n" );
3598 return DP_OK;
3601 static HRESULT WINAPI IDirectPlay2AImpl_SetGroupName( IDirectPlay2A *iface, DPID group,
3602 DPNAME *name, DWORD flags )
3604 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3605 return IDirectPlayX_SetGroupName( &This->IDirectPlay4A_iface, group, name, flags );
3608 static HRESULT WINAPI IDirectPlay2Impl_SetGroupName( IDirectPlay2 *iface, DPID group,
3609 DPNAME *name, DWORD flags )
3611 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3612 return IDirectPlayX_SetGroupName( &This->IDirectPlay4_iface, group, name, flags );
3615 static HRESULT WINAPI IDirectPlay3AImpl_SetGroupName( IDirectPlay3A *iface, DPID group,
3616 DPNAME *name, DWORD flags )
3618 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3619 return IDirectPlayX_SetGroupName( &This->IDirectPlay4_iface, group, name, flags );
3622 static HRESULT WINAPI IDirectPlay3Impl_SetGroupName( IDirectPlay3 *iface, DPID group,
3623 DPNAME *name, DWORD flags )
3625 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3626 return IDirectPlayX_SetGroupName( &This->IDirectPlay4_iface, group, name, flags );
3629 static HRESULT WINAPI IDirectPlay4AImpl_SetGroupName( IDirectPlay4A *iface, DPID idGroup,
3630 DPNAME *lpGroupName, DWORD dwFlags )
3632 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3633 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
3636 static HRESULT WINAPI IDirectPlay4Impl_SetGroupName( IDirectPlay4 *iface, DPID idGroup,
3637 DPNAME *lpGroupName, DWORD dwFlags )
3639 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3640 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
3643 static HRESULT WINAPI IDirectPlay2AImpl_SetPlayerData( IDirectPlay2A *iface, DPID player,
3644 void *data, DWORD size, DWORD flags )
3646 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3647 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4A_iface, player, data, size, flags );
3650 static HRESULT WINAPI IDirectPlay2Impl_SetPlayerData( IDirectPlay2 *iface, DPID player,
3651 void *data, DWORD size, DWORD flags )
3653 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3654 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
3657 static HRESULT WINAPI IDirectPlay3AImpl_SetPlayerData( IDirectPlay3A *iface, DPID player,
3658 void *data, DWORD size, DWORD flags )
3660 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3661 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
3664 static HRESULT WINAPI IDirectPlay3Impl_SetPlayerData( IDirectPlay3 *iface, DPID player,
3665 void *data, DWORD size, DWORD flags )
3667 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3668 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
3671 static HRESULT WINAPI IDirectPlay4AImpl_SetPlayerData( IDirectPlay4A *iface, DPID player,
3672 void *data, DWORD size, DWORD flags )
3674 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3675 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
3678 static HRESULT WINAPI IDirectPlay4Impl_SetPlayerData( IDirectPlay4 *iface, DPID player,
3679 void *data, DWORD size, DWORD flags )
3681 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3682 lpPlayerList plist;
3684 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x)\n", This, player, data, size, flags );
3686 if ( This->dp2->connectionInitialized == NO_PROVIDER )
3687 return DPERR_UNINITIALIZED;
3689 /* Parameter check */
3690 if ( !data && size )
3691 return DPERR_INVALIDPARAMS;
3693 /* Find the pointer to the data for this player */
3694 if ( (plist = DP_FindPlayer( This, player )) == NULL )
3695 return DPERR_INVALIDPLAYER;
3697 if ( !(flags & DPSET_LOCAL) )
3699 FIXME( "Was this group created by this interface?\n" );
3700 /* FIXME: If this is a remote update need to allow it but not
3701 * send a message.
3705 DP_SetPlayerData( plist->lpPData, flags, data, size );
3707 if ( !(flags & DPSET_LOCAL) )
3708 FIXME( "Send msg?\n" );
3710 return DP_OK;
3713 static HRESULT DP_IF_SetPlayerName( IDirectPlayImpl *This, DPID idPlayer, DPNAME *lpPlayerName,
3714 DWORD dwFlags, BOOL bAnsi )
3716 lpPlayerList lpPList;
3718 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n",
3719 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3721 if( This->dp2->connectionInitialized == NO_PROVIDER )
3723 return DPERR_UNINITIALIZED;
3726 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3728 return DPERR_INVALIDGROUP;
3731 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3733 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3734 FIXME( "Message not sent and dwFlags ignored\n" );
3736 return DP_OK;
3739 static HRESULT WINAPI IDirectPlay2AImpl_SetPlayerName( IDirectPlay2A *iface, DPID player,
3740 DPNAME *name, DWORD flags )
3742 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3743 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4A_iface, player, name, flags );
3746 static HRESULT WINAPI IDirectPlay2Impl_SetPlayerName( IDirectPlay2 *iface, DPID player,
3747 DPNAME *name, DWORD flags )
3749 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3750 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4_iface, player, name, flags );
3753 static HRESULT WINAPI IDirectPlay3AImpl_SetPlayerName( IDirectPlay3A *iface, DPID player,
3754 DPNAME *name, DWORD flags )
3756 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3757 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4_iface, player, name, flags );
3760 static HRESULT WINAPI IDirectPlay3Impl_SetPlayerName( IDirectPlay3 *iface, DPID player,
3761 DPNAME *name, DWORD flags )
3763 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3764 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4_iface, player, name, flags );
3767 static HRESULT WINAPI IDirectPlay4AImpl_SetPlayerName( IDirectPlay4A *iface, DPID idPlayer,
3768 DPNAME *lpPlayerName, DWORD dwFlags )
3770 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3771 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3774 static HRESULT WINAPI IDirectPlay4Impl_SetPlayerName( IDirectPlay4 *iface, DPID idPlayer,
3775 DPNAME *lpPlayerName, DWORD dwFlags )
3777 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3778 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3781 static HRESULT DP_SetSessionDesc( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpSessDesc,
3782 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3784 DWORD dwRequiredSize;
3785 LPDPSESSIONDESC2 lpTempSessDesc;
3787 TRACE( "(%p)->(%p,0x%08x,%u,%u)\n",
3788 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3790 if( This->dp2->connectionInitialized == NO_PROVIDER )
3792 return DPERR_UNINITIALIZED;
3795 if( dwFlags )
3797 return DPERR_INVALIDPARAMS;
3800 /* Only the host is allowed to update the session desc */
3801 if( !This->dp2->bHostInterface )
3803 return DPERR_ACCESSDENIED;
3806 /* FIXME: Copy into This->dp2->lpSessionDesc */
3807 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3808 lpTempSessDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize );
3810 if( lpTempSessDesc == NULL )
3812 return DPERR_OUTOFMEMORY;
3815 /* Free the old */
3816 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3818 This->dp2->lpSessionDesc = lpTempSessDesc;
3819 /* Set the new */
3820 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3821 if( bInitial )
3823 /*Initializing session GUID*/
3824 CoCreateGuid( &(This->dp2->lpSessionDesc->guidInstance) );
3826 /* If this is an external invocation of the interface, we should be
3827 * letting everyone know that things have changed. Otherwise this is
3828 * just an initialization and it doesn't need to be propagated.
3830 if( !bInitial )
3832 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3835 return DP_OK;
3838 static HRESULT WINAPI IDirectPlay2AImpl_SetSessionDesc( IDirectPlay2A *iface, DPSESSIONDESC2 *sdesc,
3839 DWORD flags )
3841 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3842 return IDirectPlayX_SetSessionDesc( &This->IDirectPlay4A_iface, sdesc, flags );
3845 static HRESULT WINAPI IDirectPlay2Impl_SetSessionDesc( IDirectPlay2 *iface, DPSESSIONDESC2 *sdesc,
3846 DWORD flags )
3848 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3849 return IDirectPlayX_SetSessionDesc( &This->IDirectPlay4_iface, sdesc, flags );
3852 static HRESULT WINAPI IDirectPlay3AImpl_SetSessionDesc( IDirectPlay3A *iface, DPSESSIONDESC2 *sdesc,
3853 DWORD flags )
3855 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3856 return IDirectPlayX_SetSessionDesc( &This->IDirectPlay4_iface, sdesc, flags );
3859 static HRESULT WINAPI IDirectPlay3Impl_SetSessionDesc( IDirectPlay3 *iface, DPSESSIONDESC2 *sdesc,
3860 DWORD flags )
3862 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3863 return IDirectPlayX_SetSessionDesc( &This->IDirectPlay4_iface, sdesc, flags );
3866 static HRESULT WINAPI IDirectPlay4AImpl_SetSessionDesc( IDirectPlay4A *iface,
3867 DPSESSIONDESC2 *lpSessDesc, DWORD dwFlags )
3869 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3870 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3873 static HRESULT WINAPI IDirectPlay4Impl_SetSessionDesc( IDirectPlay4 *iface,
3874 DPSESSIONDESC2 *lpSessDesc, DWORD dwFlags )
3876 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3877 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3880 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3881 static DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3883 DWORD dwSize = 0;
3885 if( lpSessDesc == NULL )
3887 /* Hmmm..don't need any size? */
3888 ERR( "NULL lpSessDesc\n" );
3889 return dwSize;
3892 dwSize += sizeof( *lpSessDesc );
3894 if( bAnsi )
3896 if( lpSessDesc->u1.lpszSessionNameA )
3898 dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1;
3901 if( lpSessDesc->u2.lpszPasswordA )
3903 dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1;
3906 else /* UNICODE */
3908 if( lpSessDesc->u1.lpszSessionName )
3910 dwSize += sizeof( WCHAR ) *
3911 ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 );
3914 if( lpSessDesc->u2.lpszPassword )
3916 dwSize += sizeof( WCHAR ) *
3917 ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 );
3921 return dwSize;
3924 /* Assumes that contiguous buffers are already allocated. */
3925 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3926 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3928 BYTE* lpStartOfFreeSpace;
3930 if( lpSessionDest == NULL )
3932 ERR( "NULL lpSessionDest\n" );
3933 return;
3936 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3938 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3940 if( bAnsi )
3942 if( lpSessionSrc->u1.lpszSessionNameA )
3944 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3945 lpSessionDest->u1.lpszSessionNameA );
3946 lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3947 lpStartOfFreeSpace +=
3948 lstrlenA( lpSessionDest->u1.lpszSessionNameA ) + 1;
3951 if( lpSessionSrc->u2.lpszPasswordA )
3953 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3954 lpSessionDest->u2.lpszPasswordA );
3955 lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3958 else /* UNICODE */
3960 if( lpSessionSrc->u1.lpszSessionName )
3962 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3963 lpSessionDest->u1.lpszSessionName );
3964 lpSessionDest->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3965 lpStartOfFreeSpace += sizeof(WCHAR) *
3966 ( lstrlenW( lpSessionDest->u1.lpszSessionName ) + 1 );
3969 if( lpSessionSrc->u2.lpszPassword )
3971 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3972 lpSessionDest->u2.lpszPassword );
3973 lpSessionDest->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3978 static HRESULT WINAPI IDirectPlay3AImpl_AddGroupToGroup( IDirectPlay3A *iface, DPID parent,
3979 DPID group )
3981 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3982 return IDirectPlayX_AddGroupToGroup( &This->IDirectPlay4A_iface, parent, group );
3985 static HRESULT WINAPI IDirectPlay3Impl_AddGroupToGroup( IDirectPlay3 *iface, DPID parent,
3986 DPID group )
3988 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3989 return IDirectPlayX_AddGroupToGroup( &This->IDirectPlay4_iface, parent, group );
3992 static HRESULT WINAPI IDirectPlay4AImpl_AddGroupToGroup( IDirectPlay4A *iface, DPID parent,
3993 DPID group )
3995 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3996 return IDirectPlayX_AddGroupToGroup( &This->IDirectPlay4_iface, parent, group );
3999 static HRESULT WINAPI IDirectPlay4Impl_AddGroupToGroup( IDirectPlay4 *iface, DPID parent,
4000 DPID group )
4002 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4003 lpGroupData gdata;
4004 lpGroupList glist;
4006 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, parent, group );
4008 if ( This->dp2->connectionInitialized == NO_PROVIDER )
4009 return DPERR_UNINITIALIZED;
4011 if ( !DP_FindAnyGroup(This, parent ) )
4012 return DPERR_INVALIDGROUP;
4014 if ( ( gdata = DP_FindAnyGroup(This, group ) ) == NULL )
4015 return DPERR_INVALIDGROUP;
4017 /* Create a player list (ie "shortcut" ) */
4018 glist = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *glist ) );
4019 if ( !glist )
4020 return DPERR_CANTADDPLAYER;
4022 /* Add the shortcut */
4023 gdata->uRef++;
4024 glist->lpGData = gdata;
4026 /* Add the player to the list of players for this group */
4027 DPQ_INSERT( gdata->groups, glist, groups );
4029 /* Send a ADDGROUPTOGROUP message */
4030 FIXME( "Not sending message\n" );
4032 return DP_OK;
4035 static HRESULT DP_IF_CreateGroupInGroup( IDirectPlayImpl *This, void *lpMsgHdr, DPID idParentGroup,
4036 DPID *lpidGroup, DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags,
4037 BOOL bAnsi )
4039 lpGroupData lpGParentData;
4040 lpGroupList lpGList;
4041 lpGroupData lpGData;
4043 TRACE( "(%p)->(0x%08x,%p,%p,%p,0x%08x,0x%08x,%u)\n",
4044 This, idParentGroup, lpidGroup, lpGroupName, lpData,
4045 dwDataSize, dwFlags, bAnsi );
4047 if( This->dp2->connectionInitialized == NO_PROVIDER )
4049 return DPERR_UNINITIALIZED;
4052 /* Verify that the specified parent is valid */
4053 if( ( lpGParentData = DP_FindAnyGroup(This, idParentGroup ) ) == NULL )
4054 return DPERR_INVALIDGROUP;
4056 lpGData = DP_CreateGroup(This, lpidGroup, lpGroupName, dwFlags, idParentGroup, bAnsi );
4058 if( lpGData == NULL )
4060 return DPERR_CANTADDPLAYER; /* yes player not group */
4063 /* Something else is referencing this data */
4064 lpGData->uRef++;
4066 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
4068 /* The list has now been inserted into the interface group list. We now
4069 need to put a "shortcut" to this group in the parent group */
4070 lpGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGList ) );
4071 if( lpGList == NULL )
4073 FIXME( "Memory leak\n" );
4074 return DPERR_CANTADDPLAYER; /* yes player not group */
4077 lpGList->lpGData = lpGData;
4079 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
4081 /* Let the SP know that we've created this group */
4082 if( This->dp2->spData.lpCB->CreateGroup )
4084 DPSP_CREATEGROUPDATA data;
4086 TRACE( "Calling SP CreateGroup\n" );
4088 data.idGroup = *lpidGroup;
4089 data.dwFlags = dwFlags;
4090 data.lpSPMessageHeader = lpMsgHdr;
4091 data.lpISP = This->dp2->spData.lpISP;
4093 (*This->dp2->spData.lpCB->CreateGroup)( &data );
4096 /* Inform all other peers of the creation of a new group. If there are
4097 * no peers keep this quiet.
4099 if( This->dp2->lpSessionDesc &&
4100 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
4102 DPMSG_CREATEPLAYERORGROUP msg;
4104 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
4105 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
4106 msg.dpId = *lpidGroup;
4107 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
4108 msg.lpData = lpData;
4109 msg.dwDataSize = dwDataSize;
4110 msg.dpnName = *lpGroupName;
4112 /* FIXME: Correct to just use send effectively? */
4113 /* FIXME: Should size include data w/ message or just message "header" */
4114 /* FIXME: Check return code */
4115 IDirectPlayX_SendEx( &This->IDirectPlay4_iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
4116 sizeof( msg ), 0, 0, NULL, NULL );
4119 return DP_OK;
4122 static HRESULT WINAPI IDirectPlay3AImpl_CreateGroupInGroup( IDirectPlay3A *iface, DPID parent,
4123 DPID *group, DPNAME *name, void *data, DWORD size, DWORD flags )
4125 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4126 return IDirectPlayX_CreateGroupInGroup( &This->IDirectPlay4A_iface, parent, group, name,
4127 data, size, flags );
4130 static HRESULT WINAPI IDirectPlay3Impl_CreateGroupInGroup( IDirectPlay3 *iface, DPID parent,
4131 DPID *group, DPNAME *name, void *data, DWORD size, DWORD flags )
4133 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4134 return IDirectPlayX_CreateGroupInGroup( &This->IDirectPlay4_iface, parent, group, name,
4135 data, size, flags );
4138 static HRESULT WINAPI IDirectPlay4AImpl_CreateGroupInGroup( IDirectPlay4A *iface,
4139 DPID idParentGroup, DPID *lpidGroup, DPNAME *lpGroupName, void *lpData, DWORD dwDataSize,
4140 DWORD dwFlags )
4142 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4144 *lpidGroup = DPID_UNKNOWN;
4146 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup, lpGroupName, lpData,
4147 dwDataSize, dwFlags, TRUE );
4150 static HRESULT WINAPI IDirectPlay4Impl_CreateGroupInGroup( IDirectPlay4 *iface, DPID idParentGroup,
4151 DPID *lpidGroup, DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags )
4153 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4155 *lpidGroup = DPID_UNKNOWN;
4157 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup, lpGroupName, lpData,
4158 dwDataSize, dwFlags, FALSE );
4161 static HRESULT WINAPI IDirectPlay3AImpl_DeleteGroupFromGroup( IDirectPlay3A *iface, DPID parent,
4162 DPID group )
4164 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4165 return IDirectPlayX_DeleteGroupFromGroup( &This->IDirectPlay4A_iface, parent, group );
4168 static HRESULT WINAPI IDirectPlay3Impl_DeleteGroupFromGroup( IDirectPlay3 *iface, DPID parent,
4169 DPID group )
4171 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4172 return IDirectPlayX_DeleteGroupFromGroup( &This->IDirectPlay4_iface, parent, group );
4175 static HRESULT WINAPI IDirectPlay4AImpl_DeleteGroupFromGroup( IDirectPlay4A *iface, DPID parent,
4176 DPID group )
4178 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4179 return IDirectPlayX_DeleteGroupFromGroup( &This->IDirectPlay4_iface, parent, group );
4182 static HRESULT WINAPI IDirectPlay4Impl_DeleteGroupFromGroup( IDirectPlay4 *iface, DPID parent,
4183 DPID group )
4185 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4186 lpGroupList glist;
4187 lpGroupData parentdata;
4189 TRACE("(%p)->(0x%08x,0x%08x)\n", This, parent, group );
4191 /* Is the parent group valid? */
4192 if ( ( parentdata = DP_FindAnyGroup(This, parent ) ) == NULL )
4193 return DPERR_INVALIDGROUP;
4195 /* Remove the group from the parent group queue */
4196 DPQ_REMOVE_ENTRY( parentdata->groups, groups, lpGData->dpid, ==, group, glist );
4198 if ( glist == NULL )
4199 return DPERR_INVALIDGROUP;
4201 /* Decrement the ref count */
4202 glist->lpGData->uRef--;
4204 /* Free up the list item */
4205 HeapFree( GetProcessHeap(), 0, glist );
4207 /* Should send a DELETEGROUPFROMGROUP message */
4208 FIXME( "message not sent\n" );
4210 return DP_OK;
4213 static BOOL DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
4214 LPDWORD lpdwBufSize )
4216 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
4217 HRESULT hr;
4219 dpCompoundAddress.dwDataSize = sizeof( GUID );
4220 dpCompoundAddress.guidDataType = DPAID_ServiceProvider;
4221 dpCompoundAddress.lpData = lpcSpGuid;
4223 *lplpAddrBuf = NULL;
4224 *lpdwBufSize = 0;
4226 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
4227 lpdwBufSize, TRUE );
4229 if( hr != DPERR_BUFFERTOOSMALL )
4231 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
4232 return FALSE;
4235 /* Now allocate the buffer */
4236 *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4237 *lpdwBufSize );
4239 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
4240 lpdwBufSize, TRUE );
4241 if( FAILED(hr) )
4243 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
4244 return FALSE;
4247 return TRUE;
4250 static HRESULT WINAPI IDirectPlay3AImpl_EnumConnections( IDirectPlay3A *iface,
4251 const GUID *application, LPDPENUMCONNECTIONSCALLBACK enumcb, void *context, DWORD flags )
4253 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4254 return IDirectPlayX_EnumConnections( &This->IDirectPlay4A_iface, application, enumcb, context,
4255 flags );
4258 static HRESULT WINAPI IDirectPlay3Impl_EnumConnections( IDirectPlay3 *iface,
4259 const GUID *application, LPDPENUMCONNECTIONSCALLBACK enumcb, void *context, DWORD flags )
4261 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4262 return IDirectPlayX_EnumConnections( &This->IDirectPlay4_iface, application, enumcb, context,
4263 flags );
4266 static HRESULT WINAPI IDirectPlay4AImpl_EnumConnections( IDirectPlay4A *iface,
4267 const GUID *lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, void *lpContext,
4268 DWORD dwFlags )
4270 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4271 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
4273 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
4274 if( dwFlags == 0 )
4276 dwFlags = DPCONNECTION_DIRECTPLAY;
4279 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
4280 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) )
4283 return DPERR_INVALIDFLAGS;
4286 if( !lpEnumCallback )
4288 return DPERR_INVALIDPARAMS;
4291 /* Enumerate DirectPlay service providers */
4292 if( dwFlags & DPCONNECTION_DIRECTPLAY )
4294 HKEY hkResult;
4295 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4296 LPCSTR guidDataSubKey = "Guid";
4297 char subKeyName[51];
4298 DWORD dwIndex, sizeOfSubKeyName=50;
4299 FILETIME filetime;
4301 /* Need to loop over the service providers in the registry */
4302 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4303 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4305 /* Hmmm. Does this mean that there are no service providers? */
4306 ERR(": no service providers?\n");
4307 return DP_OK;
4311 /* Traverse all the service providers we have available */
4312 for( dwIndex=0;
4313 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4314 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4315 ++dwIndex, sizeOfSubKeyName=51 )
4318 HKEY hkServiceProvider;
4319 GUID serviceProviderGUID;
4320 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
4321 char returnBuffer[51];
4322 WCHAR buff[51];
4323 DPNAME dpName;
4324 BOOL bBuildPass;
4326 LPVOID lpAddressBuffer = NULL;
4327 DWORD dwAddressBufferSize = 0;
4329 TRACE(" this time through: %s\n", subKeyName );
4331 /* Get a handle for this particular service provider */
4332 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4333 &hkServiceProvider ) != ERROR_SUCCESS )
4335 ERR(": what the heck is going on?\n" );
4336 continue;
4339 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4340 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
4341 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4343 ERR(": missing GUID registry data members\n" );
4344 RegCloseKey(hkServiceProvider);
4345 continue;
4347 RegCloseKey(hkServiceProvider);
4349 /* FIXME: Check return types to ensure we're interpreting data right */
4350 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4351 CLSIDFromString( buff, &serviceProviderGUID );
4352 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4354 /* Fill in the DPNAME struct for the service provider */
4355 dpName.dwSize = sizeof( dpName );
4356 dpName.dwFlags = 0;
4357 dpName.u1.lpszShortNameA = subKeyName;
4358 dpName.u2.lpszLongNameA = NULL;
4360 /* Create the compound address for the service provider.
4361 * NOTE: This is a gruesome architectural scar right now. DP
4362 * uses DPL and DPL uses DP. Nasty stuff. This may be why the
4363 * native dll just gets around this little bit by allocating an
4364 * 80 byte buffer which isn't even filled with a valid compound
4365 * address. Oh well. Creating a proper compound address is the
4366 * way to go anyways despite this method taking slightly more
4367 * heap space and realtime :) */
4369 bBuildPass = DP_BuildSPCompoundAddr( &serviceProviderGUID,
4370 &lpAddressBuffer,
4371 &dwAddressBufferSize );
4372 if( !bBuildPass )
4374 ERR( "Can't build compound addr\n" );
4375 return DPERR_GENERIC;
4378 /* The enumeration will return FALSE if we are not to continue */
4379 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
4380 &dpName, dwFlags, lpContext ) )
4382 return DP_OK;
4387 /* Enumerate DirectPlayLobby service providers */
4388 if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY )
4390 HKEY hkResult;
4391 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
4392 LPCSTR guidDataSubKey = "Guid";
4393 char subKeyName[51];
4394 DWORD dwIndex, sizeOfSubKeyName=50;
4395 FILETIME filetime;
4397 /* Need to loop over the service providers in the registry */
4398 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4399 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4401 /* Hmmm. Does this mean that there are no service providers? */
4402 ERR(": no service providers?\n");
4403 return DP_OK;
4407 /* Traverse all the lobby providers we have available */
4408 for( dwIndex=0;
4409 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4410 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4411 ++dwIndex, sizeOfSubKeyName=51 )
4414 HKEY hkServiceProvider;
4415 GUID serviceProviderGUID;
4416 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
4417 char returnBuffer[51];
4418 WCHAR buff[51];
4419 DPNAME dpName;
4420 HRESULT hr;
4422 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
4423 LPVOID lpAddressBuffer = NULL;
4424 DWORD dwAddressBufferSize = 0;
4426 TRACE(" this time through: %s\n", subKeyName );
4428 /* Get a handle for this particular service provider */
4429 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4430 &hkServiceProvider ) != ERROR_SUCCESS )
4432 ERR(": what the heck is going on?\n" );
4433 continue;
4436 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4437 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
4438 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4440 ERR(": missing GUID registry data members\n" );
4441 RegCloseKey(hkServiceProvider);
4442 continue;
4444 RegCloseKey(hkServiceProvider);
4446 /* FIXME: Check return types to ensure we're interpreting data right */
4447 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4448 CLSIDFromString( buff, &serviceProviderGUID );
4449 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4451 /* Fill in the DPNAME struct for the service provider */
4452 dpName.dwSize = sizeof( dpName );
4453 dpName.dwFlags = 0;
4454 dpName.u1.lpszShortNameA = subKeyName;
4455 dpName.u2.lpszLongNameA = NULL;
4457 /* Create the compound address for the service provider.
4458 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
4459 nast stuff. This may be why the native dll just gets around this little bit by
4460 allocating an 80 byte buffer which isn't even a filled with a valid compound
4461 address. Oh well. Creating a proper compound address is the way to go anyways
4462 despite this method taking slightly more heap space and realtime :) */
4464 dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
4465 dpCompoundAddress.dwDataSize = sizeof( GUID );
4466 dpCompoundAddress.lpData = &serviceProviderGUID;
4468 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
4469 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
4471 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
4472 return hr;
4475 /* Now allocate the buffer */
4476 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
4478 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
4479 &dwAddressBufferSize, TRUE ) ) != DP_OK )
4481 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
4482 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
4483 return hr;
4486 /* The enumeration will return FALSE if we are not to continue */
4487 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
4488 &dpName, dwFlags, lpContext ) )
4490 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
4491 return DP_OK;
4493 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
4497 return DP_OK;
4500 static HRESULT WINAPI IDirectPlay4Impl_EnumConnections( IDirectPlay4 *iface,
4501 const GUID *application, LPDPENUMCONNECTIONSCALLBACK enumcb, void *context, DWORD flags )
4503 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4504 FIXME( "(%p)->(%p,%p,%p,0x%08x): stub\n", This, application, enumcb, context, flags );
4505 return DP_OK;
4508 static HRESULT WINAPI IDirectPlay3AImpl_EnumGroupsInGroup( IDirectPlay3A *iface, DPID group,
4509 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
4511 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4512 return IDirectPlayX_EnumGroupsInGroup( &This->IDirectPlay4A_iface, group, instance,
4513 enumplayercb, context, flags );
4516 static HRESULT WINAPI IDirectPlay3Impl_EnumGroupsInGroup( IDirectPlay3 *iface, DPID group,
4517 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
4519 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4520 return IDirectPlayX_EnumGroupsInGroup( &This->IDirectPlay4_iface, group, instance,
4521 enumplayercb, context, flags );
4524 static HRESULT WINAPI IDirectPlay4AImpl_EnumGroupsInGroup( IDirectPlay4A *iface, DPID group,
4525 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
4527 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4528 return IDirectPlayX_EnumGroupsInGroup( &This->IDirectPlay4_iface, group, instance,
4529 enumplayercb, context, flags );
4532 static HRESULT WINAPI IDirectPlay4Impl_EnumGroupsInGroup( IDirectPlay4 *iface, DPID group,
4533 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
4535 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4536 lpGroupList glist;
4537 lpGroupData gdata;
4539 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x): semi stub\n", This, group, instance, enumplayercb,
4540 context, flags );
4542 if ( This->dp2->connectionInitialized == NO_PROVIDER )
4543 return DPERR_UNINITIALIZED;
4545 if ( ( gdata = DP_FindAnyGroup(This, group ) ) == NULL )
4546 return DPERR_INVALIDGROUP;
4548 if ( DPQ_IS_EMPTY( gdata->groups ) )
4549 return DP_OK;
4552 for( glist = DPQ_FIRST( gdata->groups ); ; glist = DPQ_NEXT( glist->groups ) )
4554 /* FIXME: Should check flags for match here */
4555 if ( !(*enumplayercb)( glist->lpGData->dpid, DPPLAYERTYPE_GROUP, &glist->lpGData->name,
4556 flags, context ) )
4557 return DP_OK; /* User requested break */
4559 if ( DPQ_IS_ENDOFLIST( glist->groups ) )
4560 break;
4563 return DP_OK;
4566 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupConnectionSettings( IDirectPlay3A *iface,
4567 DWORD flags, DPID group, void *data, DWORD *size )
4569 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4570 return IDirectPlayX_GetGroupConnectionSettings( &This->IDirectPlay4A_iface, flags, group,
4571 data, size );
4574 static HRESULT WINAPI IDirectPlay3Impl_GetGroupConnectionSettings( IDirectPlay3 *iface,
4575 DWORD flags, DPID group, void *data, DWORD *size )
4577 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4578 return IDirectPlayX_GetGroupConnectionSettings( &This->IDirectPlay4_iface, flags, group,
4579 data, size );
4582 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupConnectionSettings( IDirectPlay4A *iface,
4583 DWORD flags, DPID group, void *data, DWORD *size )
4585 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4586 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, flags, group, data, size );
4587 return DP_OK;
4590 static HRESULT WINAPI IDirectPlay4Impl_GetGroupConnectionSettings( IDirectPlay4 *iface, DWORD flags,
4591 DPID group, void *data, DWORD *size )
4593 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4594 FIXME( "(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, flags, group, data, size );
4595 return DP_OK;
4598 static BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
4599 REFGUID guidDataType,
4600 DWORD dwDataSize,
4601 LPCVOID lpData,
4602 LPVOID lpContext )
4604 /* Looking for the GUID of the provider to load */
4605 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
4606 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
4609 TRACE( "Found SP/LP (%s) %s (data size = 0x%08x)\n",
4610 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
4612 if( dwDataSize != sizeof( GUID ) )
4614 ERR( "Invalid sp/lp guid size 0x%08x\n", dwDataSize );
4617 memcpy( lpContext, lpData, dwDataSize );
4619 /* There shouldn't be more than 1 GUID/compound address */
4620 return FALSE;
4623 /* Still waiting for what we want */
4624 return TRUE;
4628 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
4629 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
4631 UINT i;
4632 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4633 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
4634 LPCSTR guidDataSubKey = "Guid";
4635 LPCSTR majVerDataSubKey = "dwReserved1";
4636 LPCSTR minVerDataSubKey = "dwReserved2";
4637 LPCSTR pathSubKey = "Path";
4639 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
4641 /* FIXME: Cloned code with a quick hack. */
4642 for( i=0; i<2; i++ )
4644 HKEY hkResult;
4645 LPCSTR searchSubKey;
4646 char subKeyName[51];
4647 DWORD dwIndex, sizeOfSubKeyName=50;
4648 FILETIME filetime;
4650 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
4651 *lpbIsDpSp = (i == 0) ? TRUE : FALSE;
4654 /* Need to loop over the service providers in the registry */
4655 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4656 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4658 /* Hmmm. Does this mean that there are no service providers? */
4659 ERR(": no service providers?\n");
4660 return 0;
4663 /* Traverse all the service providers we have available */
4664 for( dwIndex=0;
4665 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4666 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4667 ++dwIndex, sizeOfSubKeyName=51 )
4670 HKEY hkServiceProvider;
4671 GUID serviceProviderGUID;
4672 DWORD returnType, sizeOfReturnBuffer = 255;
4673 char returnBuffer[256];
4674 WCHAR buff[51];
4675 DWORD dwTemp, len;
4677 TRACE(" this time through: %s\n", subKeyName );
4679 /* Get a handle for this particular service provider */
4680 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4681 &hkServiceProvider ) != ERROR_SUCCESS )
4683 ERR(": what the heck is going on?\n" );
4684 continue;
4687 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4688 NULL, &returnType, (LPBYTE)returnBuffer,
4689 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4691 ERR(": missing GUID registry data members\n" );
4692 continue;
4695 /* FIXME: Check return types to ensure we're interpreting data right */
4696 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4697 CLSIDFromString( buff, &serviceProviderGUID );
4698 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4700 /* Determine if this is the Service Provider that the user asked for */
4701 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
4703 continue;
4706 if( i == 0 ) /* DP SP */
4708 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
4709 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
4710 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
4713 sizeOfReturnBuffer = 255;
4715 /* Get dwReserved1 */
4716 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
4717 NULL, &returnType, (LPBYTE)returnBuffer,
4718 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4720 ERR(": missing dwReserved1 registry data members\n") ;
4721 continue;
4724 if( i == 0 )
4725 memcpy( &lpSpData->dwReserved1, returnBuffer, sizeof(lpSpData->dwReserved1) );
4727 sizeOfReturnBuffer = 255;
4729 /* Get dwReserved2 */
4730 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4731 NULL, &returnType, (LPBYTE)returnBuffer,
4732 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4734 ERR(": missing dwReserved1 registry data members\n") ;
4735 continue;
4738 if( i == 0 )
4739 memcpy( &lpSpData->dwReserved2, returnBuffer, sizeof(lpSpData->dwReserved2) );
4741 sizeOfReturnBuffer = 255;
4743 /* Get the path for this service provider */
4744 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
4745 NULL, NULL, (LPBYTE)returnBuffer,
4746 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
4748 ERR(": missing PATH registry data members: 0x%08x\n", dwTemp );
4749 continue;
4752 TRACE( "Loading %s\n", returnBuffer );
4753 return LoadLibraryA( returnBuffer );
4757 return 0;
4760 static HRESULT DP_InitializeDPSP( IDirectPlayImpl *This, HMODULE hServiceProvider )
4762 HRESULT hr;
4763 LPDPSP_SPINIT SPInit;
4765 /* Initialize the service provider by calling SPInit */
4766 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4768 if( SPInit == NULL )
4770 ERR( "Service provider doesn't provide SPInit interface?\n" );
4771 FreeLibrary( hServiceProvider );
4772 return DPERR_UNAVAILABLE;
4775 TRACE( "Calling SPInit (DP SP entry point)\n" );
4777 hr = (*SPInit)( &This->dp2->spData );
4779 if( FAILED(hr) )
4781 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4782 FreeLibrary( hServiceProvider );
4783 return hr;
4786 /* FIXME: Need to verify the sanity of the returned callback table
4787 * using IsBadCodePtr */
4788 This->dp2->bSPInitialized = TRUE;
4790 /* This interface is now initialized as a DP object */
4791 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
4793 /* Store the handle of the module so that we can unload it later */
4794 This->dp2->hServiceProvider = hServiceProvider;
4796 return hr;
4799 static HRESULT DP_InitializeDPLSP( IDirectPlayImpl *This, HMODULE hLobbyProvider )
4801 HRESULT hr;
4802 LPSP_INIT DPLSPInit;
4804 /* Initialize the service provider by calling SPInit */
4805 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
4807 if( DPLSPInit == NULL )
4809 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4810 FreeLibrary( hLobbyProvider );
4811 return DPERR_UNAVAILABLE;
4814 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4816 hr = (*DPLSPInit)( &This->dp2->dplspData );
4818 if( FAILED(hr) )
4820 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4821 FreeLibrary( hLobbyProvider );
4822 return hr;
4825 /* FIXME: Need to verify the sanity of the returned callback table
4826 * using IsBadCodePtr */
4828 This->dp2->bDPLSPInitialized = TRUE;
4830 /* This interface is now initialized as a lobby object */
4831 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
4833 /* Store the handle of the module so that we can unload it later */
4834 This->dp2->hDPLobbyProvider = hLobbyProvider;
4836 return hr;
4839 static HRESULT WINAPI IDirectPlay3AImpl_InitializeConnection( IDirectPlay3A *iface,
4840 void *connection, DWORD flags )
4842 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4843 return IDirectPlayX_InitializeConnection( &This->IDirectPlay4A_iface, connection, flags );
4846 static HRESULT WINAPI IDirectPlay3Impl_InitializeConnection( IDirectPlay3 *iface,
4847 void *connection, DWORD flags )
4849 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4850 return IDirectPlayX_InitializeConnection( &This->IDirectPlay4_iface, connection, flags );
4853 static HRESULT WINAPI IDirectPlay4AImpl_InitializeConnection( IDirectPlay4A *iface,
4854 void *connection, DWORD flags )
4856 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4857 return IDirectPlayX_InitializeConnection( &This->IDirectPlay4_iface, connection, flags );
4860 static HRESULT WINAPI IDirectPlay4Impl_InitializeConnection( IDirectPlay4 *iface,
4861 void *connection, DWORD flags )
4863 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4864 HMODULE servprov;
4865 GUID sp;
4866 const DWORD size = 80; /* FIXME: Need to calculate it correctly */
4867 BOOL is_dp_sp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4868 HRESULT hr;
4870 TRACE( "(%p)->(%p,0x%08x)\n", This, connection, flags );
4872 if ( !connection )
4873 return DPERR_INVALIDPARAMS;
4875 if ( flags )
4876 return DPERR_INVALIDFLAGS;
4878 if ( This->dp2->connectionInitialized != NO_PROVIDER )
4879 return DPERR_ALREADYINITIALIZED;
4881 /* Find out what the requested SP is and how large this buffer is */
4882 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, connection, size, &sp );
4884 if ( FAILED(hr) )
4886 ERR( "Invalid compound address?\n" );
4887 return DPERR_UNAVAILABLE;
4890 /* Load the service provider */
4891 servprov = DP_LoadSP( &sp, &This->dp2->spData, &is_dp_sp );
4893 if ( !servprov )
4895 ERR( "Unable to load service provider %s\n", debugstr_guid(&sp) );
4896 return DPERR_UNAVAILABLE;
4899 if ( is_dp_sp )
4901 /* Fill in what we can of the Service Provider required information.
4902 * The rest was be done in DP_LoadSP
4904 This->dp2->spData.lpAddress = connection;
4905 This->dp2->spData.dwAddressSize = size;
4906 This->dp2->spData.lpGuid = &sp;
4907 hr = DP_InitializeDPSP( This, servprov );
4909 else
4911 This->dp2->dplspData.lpAddress = connection;
4912 hr = DP_InitializeDPLSP( This, servprov );
4915 if ( FAILED(hr) )
4916 return hr;
4918 return DP_OK;
4921 static HRESULT WINAPI IDirectPlay3AImpl_SecureOpen( IDirectPlay3A *iface,
4922 const DPSESSIONDESC2 *sdesc, DWORD flags, const DPSECURITYDESC *security,
4923 const DPCREDENTIALS *credentials )
4925 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4926 return IDirectPlayX_SecureOpen( &This->IDirectPlay4A_iface, sdesc, flags, security,
4927 credentials );
4930 static HRESULT WINAPI IDirectPlay3Impl_SecureOpen( IDirectPlay3 *iface,
4931 const DPSESSIONDESC2 *sdesc, DWORD flags, const DPSECURITYDESC *security,
4932 const DPCREDENTIALS *credentials )
4934 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4935 return IDirectPlayX_SecureOpen( &This->IDirectPlay4_iface, sdesc, flags, security,
4936 credentials );
4939 static HRESULT WINAPI IDirectPlay4AImpl_SecureOpen( IDirectPlay4A *iface,
4940 const DPSESSIONDESC2 *lpsd, DWORD dwFlags, const DPSECURITYDESC *lpSecurity,
4941 const DPCREDENTIALS *lpCredentials )
4943 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4944 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4947 static HRESULT WINAPI IDirectPlay4Impl_SecureOpen( IDirectPlay4 *iface,
4948 const DPSESSIONDESC2 *lpsd, DWORD dwFlags, const DPSECURITYDESC *lpSecurity,
4949 const DPCREDENTIALS *lpCredentials )
4951 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4952 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4955 static HRESULT WINAPI IDirectPlay3AImpl_SendChatMessage( IDirectPlay3A *iface, DPID from, DPID to,
4956 DWORD flags, DPCHAT *chatmsg )
4958 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4959 return IDirectPlayX_SendChatMessage( &This->IDirectPlay4A_iface, from, to, flags, chatmsg );
4962 static HRESULT WINAPI IDirectPlay3Impl_SendChatMessage( IDirectPlay3 *iface, DPID from, DPID to,
4963 DWORD flags, DPCHAT *chatmsg )
4965 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4966 return IDirectPlayX_SendChatMessage( &This->IDirectPlay4_iface, from, to, flags, chatmsg );
4969 static HRESULT WINAPI IDirectPlay4AImpl_SendChatMessage( IDirectPlay4A *iface, DPID from,
4970 DPID to, DWORD flags, DPCHAT *chatmsg )
4972 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4973 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, from, to, flags, chatmsg );
4974 return DP_OK;
4977 static HRESULT WINAPI IDirectPlay4Impl_SendChatMessage( IDirectPlay4 *iface, DPID from, DPID to,
4978 DWORD flags, DPCHAT *chatmsg )
4980 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4981 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, from, to, flags, chatmsg );
4982 return DP_OK;
4985 static HRESULT WINAPI IDirectPlay3AImpl_SetGroupConnectionSettings( IDirectPlay3A *iface,
4986 DWORD flags, DPID group, DPLCONNECTION *connection )
4988 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4989 return IDirectPlayX_SetGroupConnectionSettings( &This->IDirectPlay4A_iface, flags, group,
4990 connection );
4993 static HRESULT WINAPI IDirectPlay3Impl_SetGroupConnectionSettings( IDirectPlay3 *iface,
4994 DWORD flags, DPID group, DPLCONNECTION *connection )
4996 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4997 return IDirectPlayX_SetGroupConnectionSettings( &This->IDirectPlay4_iface, flags, group,
4998 connection );
5001 static HRESULT WINAPI IDirectPlay4AImpl_SetGroupConnectionSettings( IDirectPlay4A *iface,
5002 DWORD flags, DPID group, DPLCONNECTION *connection )
5004 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5005 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, flags, group, connection );
5006 return DP_OK;
5009 static HRESULT WINAPI IDirectPlay4Impl_SetGroupConnectionSettings( IDirectPlay4 *iface, DWORD flags,
5010 DPID group, DPLCONNECTION *connection )
5012 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5013 FIXME( "(%p)->(0x%08x,0x%08x,%p): stub\n", This, flags, group, connection );
5014 return DP_OK;
5017 static HRESULT WINAPI IDirectPlay3AImpl_StartSession( IDirectPlay3A *iface, DWORD flags,
5018 DPID group )
5020 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
5021 return IDirectPlayX_StartSession( &This->IDirectPlay4A_iface, flags, group );
5024 static HRESULT WINAPI IDirectPlay3Impl_StartSession( IDirectPlay3 *iface, DWORD flags,
5025 DPID group )
5027 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
5028 return IDirectPlayX_StartSession( &This->IDirectPlay4_iface, flags, group );
5031 static HRESULT WINAPI IDirectPlay4AImpl_StartSession( IDirectPlay4A *iface, DWORD flags,
5032 DPID group )
5034 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5035 return IDirectPlayX_StartSession( &This->IDirectPlay4_iface, flags, group );
5038 static HRESULT WINAPI IDirectPlay4Impl_StartSession( IDirectPlay4 *iface, DWORD flags, DPID group )
5040 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5041 FIXME( "(%p)->(0x%08x,0x%08x): stub\n", This, flags, group );
5042 return DP_OK;
5045 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupFlags( IDirectPlay3A *iface, DPID group,
5046 DWORD *flags )
5048 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
5049 return IDirectPlayX_GetGroupFlags( &This->IDirectPlay4A_iface, group, flags );
5052 static HRESULT WINAPI IDirectPlay3Impl_GetGroupFlags( IDirectPlay3 *iface, DPID group,
5053 DWORD *flags )
5055 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
5056 return IDirectPlayX_GetGroupFlags( &This->IDirectPlay4_iface, group, flags );
5059 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupFlags( IDirectPlay4A *iface, DPID group,
5060 DWORD *flags )
5062 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5063 return IDirectPlayX_GetGroupFlags( &This->IDirectPlay4_iface, group, flags );
5066 static HRESULT WINAPI IDirectPlay4Impl_GetGroupFlags( IDirectPlay4 *iface, DPID group,
5067 DWORD *flags )
5069 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5070 FIXME( "(%p)->(0x%08x,%p): stub\n", This, group, flags );
5071 return DP_OK;
5074 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupParent( IDirectPlay3A *iface, DPID group,
5075 DPID *parent )
5077 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
5078 return IDirectPlayX_GetGroupParent( &This->IDirectPlay4A_iface, group, parent );
5081 static HRESULT WINAPI IDirectPlay3Impl_GetGroupParent( IDirectPlay3 *iface, DPID group,
5082 DPID *parent )
5084 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
5085 return IDirectPlayX_GetGroupParent( &This->IDirectPlay4_iface, group, parent );
5088 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupParent( IDirectPlay4A *iface, DPID group,
5089 DPID *parent )
5091 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5092 return IDirectPlayX_GetGroupParent( &This->IDirectPlay4_iface, group, parent );
5095 static HRESULT WINAPI IDirectPlay4Impl_GetGroupParent( IDirectPlay4 *iface, DPID group,
5096 DPID *parent )
5098 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5099 lpGroupData gdata;
5101 TRACE( "(%p)->(0x%08x,%p)\n", This, group, parent );
5103 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
5104 return DPERR_INVALIDGROUP;
5106 *parent = gdata->dpid;
5108 return DP_OK;
5111 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerAccount( IDirectPlay3A *iface, DPID player,
5112 DWORD flags, void *data, DWORD *size )
5114 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
5115 return IDirectPlayX_GetPlayerAccount( &This->IDirectPlay4A_iface, player, flags, data, size );
5118 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerAccount( IDirectPlay3 *iface, DPID player,
5119 DWORD flags, void *data, DWORD *size )
5121 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
5122 return IDirectPlayX_GetPlayerAccount( &This->IDirectPlay4_iface, player, flags, data, size );
5125 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerAccount( IDirectPlay4A *iface, DPID player,
5126 DWORD flags, void *data, DWORD *size )
5128 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5129 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, player, flags, data, size );
5130 return DP_OK;
5133 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerAccount( IDirectPlay4 *iface, DPID player,
5134 DWORD flags, void *data, DWORD *size )
5136 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5137 FIXME( "(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, player, flags, data, size );
5138 return DP_OK;
5141 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerFlags( IDirectPlay3A *iface, DPID player,
5142 DWORD *flags )
5144 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
5145 return IDirectPlayX_GetPlayerFlags( &This->IDirectPlay4A_iface, player, flags );
5148 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerFlags( IDirectPlay3 *iface, DPID player,
5149 DWORD *flags )
5151 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
5152 return IDirectPlayX_GetPlayerFlags( &This->IDirectPlay4_iface, player, flags );
5155 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerFlags( IDirectPlay4A *iface, DPID player,
5156 DWORD *flags )
5158 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5159 return IDirectPlayX_GetPlayerFlags( &This->IDirectPlay4_iface, player, flags );
5162 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerFlags( IDirectPlay4 *iface, DPID player,
5163 DWORD *flags )
5165 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5166 FIXME( "(%p)->(0x%08x,%p): stub\n", This, player, flags );
5167 return DP_OK;
5170 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupOwner( IDirectPlay4A *iface, DPID group,
5171 DPID *owner )
5173 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5174 return IDirectPlayX_GetGroupOwner( &This->IDirectPlay4_iface, group, owner );
5177 static HRESULT WINAPI IDirectPlay4Impl_GetGroupOwner( IDirectPlay4 *iface, DPID group,
5178 DPID *owner )
5180 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5181 FIXME( "(%p)->(0x%08x,%p): stub\n", This, group, owner );
5182 return DP_OK;
5185 static HRESULT WINAPI IDirectPlay4AImpl_SetGroupOwner( IDirectPlay4A *iface, DPID group,
5186 DPID owner )
5188 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5189 return IDirectPlayX_SetGroupOwner( &This->IDirectPlay4_iface, group, owner );
5192 static HRESULT WINAPI IDirectPlay4Impl_SetGroupOwner( IDirectPlay4 *iface, DPID group ,
5193 DPID owner )
5195 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5196 FIXME( "(%p)->(0x%08x,0x%08x): stub\n", This, group, owner );
5197 return DP_OK;
5200 static HRESULT WINAPI IDirectPlay4AImpl_SendEx( IDirectPlay4A *iface, DPID from, DPID to,
5201 DWORD flags, void *data, DWORD size, DWORD priority, DWORD timeout, void *context,
5202 DWORD *msgid )
5204 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5205 return IDirectPlayX_SendEx( &This->IDirectPlay4_iface, from, to, flags, data, size, priority,
5206 timeout, context, msgid );
5209 static HRESULT WINAPI IDirectPlay4Impl_SendEx( IDirectPlay4 *iface, DPID from, DPID to,
5210 DWORD flags, void *data, DWORD size, DWORD priority, DWORD timeout, void *context,
5211 DWORD *msgid )
5213 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5215 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,0x%08x,0x%08x,0x%08x,%p,%p): semi-stub\n",
5216 This, from, to, flags, data, size, priority, timeout, context, msgid );
5218 if ( This->dp2->connectionInitialized == NO_PROVIDER )
5219 return DPERR_UNINITIALIZED;
5221 /* FIXME: Add parameter checking */
5222 /* FIXME: First call to this needs to acquire a message id which will be
5223 * used for multiple sends
5226 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
5228 /* Verify that the message is being sent from a valid local player. The
5229 * from player may be anonymous DPID_UNKNOWN
5231 if ( from != DPID_UNKNOWN && !DP_FindPlayer( This, from ) )
5233 WARN( "INFO: Invalid from player 0x%08x\n", from );
5234 return DPERR_INVALIDPLAYER;
5237 /* Verify that the message is being sent to a valid player, group or to
5238 * everyone. If it's valid, send it to those players.
5240 if ( to == DPID_ALLPLAYERS )
5242 /* See if SP has the ability to multicast. If so, use it */
5243 if ( This->dp2->spData.lpCB->SendToGroupEx )
5244 FIXME( "Use group sendex to group 0\n" );
5245 else if ( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
5246 FIXME( "Use obsolete group send to group 0\n" );
5247 else /* No multicast, multiplicate */
5248 FIXME( "Send to all players using EnumPlayersInGroup\n" );
5250 else if ( DP_FindPlayer( This, to ) )
5252 /* Have the service provider send this message */
5253 /* FIXME: Could optimize for local interface sends */
5254 return DP_SP_SendEx( This, flags, data, size, priority, timeout, context, msgid );
5256 else if ( DP_FindAnyGroup( This, to ) )
5258 /* See if SP has the ability to multicast. If so, use it */
5259 if ( This->dp2->spData.lpCB->SendToGroupEx )
5260 FIXME( "Use group sendex\n" );
5261 else if ( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
5262 FIXME( "Use obsolete group send to group\n" );
5263 else /* No multicast, multiplicate */
5264 FIXME( "Send to all players using EnumPlayersInGroup\n" );
5267 else
5268 return DPERR_INVALIDPLAYER;
5270 /* FIXME: Should return what the send returned */
5271 return DP_OK;
5274 static HRESULT DP_SP_SendEx( IDirectPlayImpl *This, DWORD dwFlags, void *lpData, DWORD dwDataSize,
5275 DWORD dwPriority, DWORD dwTimeout, void *lpContext, DWORD *lpdwMsgID )
5277 LPDPMSG lpMElem;
5279 FIXME( ": stub\n" );
5281 /* FIXME: This queuing should only be for async messages */
5283 lpMElem = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpMElem ) );
5284 lpMElem->msg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
5286 CopyMemory( lpMElem->msg, lpData, dwDataSize );
5288 /* FIXME: Need to queue based on priority */
5289 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
5291 return DP_OK;
5294 static HRESULT WINAPI IDirectPlay4AImpl_GetMessageQueue( IDirectPlay4A *iface, DPID from, DPID to,
5295 DWORD flags, DWORD *msgs, DWORD *bytes )
5297 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5298 return IDirectPlayX_GetMessageQueue( &This->IDirectPlay4_iface, from, to, flags, msgs, bytes );
5301 static HRESULT WINAPI IDirectPlay4Impl_GetMessageQueue( IDirectPlay4 *iface, DPID from, DPID to,
5302 DWORD flags, DWORD *msgs, DWORD *bytes )
5304 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5305 HRESULT hr = DP_OK;
5307 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%p): semi-stub\n", This, from, to, flags, msgs, bytes );
5309 /* FIXME: Do we need to do from and to sanity checking here? */
5310 /* FIXME: What about sends which are not immediate? */
5312 if ( This->dp2->spData.lpCB->GetMessageQueue )
5314 DPSP_GETMESSAGEQUEUEDATA data;
5316 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
5318 /* FIXME: None of this is documented :( */
5319 data.lpISP = This->dp2->spData.lpISP;
5320 data.dwFlags = flags;
5321 data.idFrom = from;
5322 data.idTo = to;
5323 data.lpdwNumMsgs = msgs;
5324 data.lpdwNumBytes = bytes;
5326 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
5328 else
5329 FIXME( "No SP for GetMessageQueue - fake some data\n" );
5331 return hr;
5334 static HRESULT dplay_cancelmsg ( IDirectPlayImpl* This, DWORD msgid, DWORD flags, DWORD minprio,
5335 DWORD maxprio )
5337 HRESULT hr = DP_OK;
5339 FIXME( "(%p)->(0x%08x,0x%08x): semi stub\n", This, msgid, flags );
5341 if ( This->dp2->spData.lpCB->Cancel )
5343 DPSP_CANCELDATA data;
5345 TRACE( "Calling SP Cancel\n" );
5347 /* FIXME: Undocumented callback */
5349 data.lpISP = This->dp2->spData.lpISP;
5350 data.dwFlags = flags;
5351 data.lprglpvSPMsgID = NULL;
5352 data.cSPMsgID = msgid;
5353 data.dwMinPriority = minprio;
5354 data.dwMaxPriority = maxprio;
5356 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
5358 else
5359 FIXME( "SP doesn't implement Cancel\n" );
5361 return hr;
5364 static HRESULT WINAPI IDirectPlay4AImpl_CancelMessage( IDirectPlay4A *iface, DWORD msgid,
5365 DWORD flags )
5367 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5368 return IDirectPlayX_CancelMessage( &This->IDirectPlay4_iface, msgid, flags );
5371 static HRESULT WINAPI IDirectPlay4Impl_CancelMessage( IDirectPlay4 *iface, DWORD msgid,
5372 DWORD flags )
5374 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5376 if ( flags != 0 )
5377 return DPERR_INVALIDFLAGS;
5379 if ( msgid == 0 )
5380 flags |= DPCANCELSEND_ALL;
5382 return dplay_cancelmsg( This, msgid, flags, 0, 0 );
5385 static HRESULT WINAPI IDirectPlay4AImpl_CancelPriority( IDirectPlay4A *iface, DWORD minprio,
5386 DWORD maxprio, DWORD flags )
5388 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5389 return IDirectPlayX_CancelPriority( &This->IDirectPlay4_iface, minprio, maxprio, flags );
5392 static HRESULT WINAPI IDirectPlay4Impl_CancelPriority( IDirectPlay4 *iface, DWORD minprio,
5393 DWORD maxprio, DWORD flags )
5395 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5397 if ( flags != 0 )
5398 return DPERR_INVALIDFLAGS;
5400 return dplay_cancelmsg( This, 0, DPCANCELSEND_PRIORITY, minprio, maxprio );
5403 static const IDirectPlay2Vtbl dp2_vt =
5405 IDirectPlay2Impl_QueryInterface,
5406 IDirectPlay2Impl_AddRef,
5407 IDirectPlay2Impl_Release,
5408 IDirectPlay2Impl_AddPlayerToGroup,
5409 IDirectPlay2Impl_Close,
5410 IDirectPlay2Impl_CreateGroup,
5411 IDirectPlay2Impl_CreatePlayer,
5412 IDirectPlay2Impl_DeletePlayerFromGroup,
5413 IDirectPlay2Impl_DestroyGroup,
5414 IDirectPlay2Impl_DestroyPlayer,
5415 IDirectPlay2Impl_EnumGroupPlayers,
5416 IDirectPlay2Impl_EnumGroups,
5417 IDirectPlay2Impl_EnumPlayers,
5418 IDirectPlay2Impl_EnumSessions,
5419 IDirectPlay2Impl_GetCaps,
5420 IDirectPlay2Impl_GetGroupData,
5421 IDirectPlay2Impl_GetGroupName,
5422 IDirectPlay2Impl_GetMessageCount,
5423 IDirectPlay2Impl_GetPlayerAddress,
5424 IDirectPlay2Impl_GetPlayerCaps,
5425 IDirectPlay2Impl_GetPlayerData,
5426 IDirectPlay2Impl_GetPlayerName,
5427 IDirectPlay2Impl_GetSessionDesc,
5428 IDirectPlay2Impl_Initialize,
5429 IDirectPlay2Impl_Open,
5430 IDirectPlay2Impl_Receive,
5431 IDirectPlay2Impl_Send,
5432 IDirectPlay2Impl_SetGroupData,
5433 IDirectPlay2Impl_SetGroupName,
5434 IDirectPlay2Impl_SetPlayerData,
5435 IDirectPlay2Impl_SetPlayerName,
5436 IDirectPlay2Impl_SetSessionDesc
5439 static const IDirectPlay2Vtbl dp2A_vt =
5441 IDirectPlay2AImpl_QueryInterface,
5442 IDirectPlay2AImpl_AddRef,
5443 IDirectPlay2AImpl_Release,
5444 IDirectPlay2AImpl_AddPlayerToGroup,
5445 IDirectPlay2AImpl_Close,
5446 IDirectPlay2AImpl_CreateGroup,
5447 IDirectPlay2AImpl_CreatePlayer,
5448 IDirectPlay2AImpl_DeletePlayerFromGroup,
5449 IDirectPlay2AImpl_DestroyGroup,
5450 IDirectPlay2AImpl_DestroyPlayer,
5451 IDirectPlay2AImpl_EnumGroupPlayers,
5452 IDirectPlay2AImpl_EnumGroups,
5453 IDirectPlay2AImpl_EnumPlayers,
5454 IDirectPlay2AImpl_EnumSessions,
5455 IDirectPlay2AImpl_GetCaps,
5456 IDirectPlay2AImpl_GetGroupData,
5457 IDirectPlay2AImpl_GetGroupName,
5458 IDirectPlay2AImpl_GetMessageCount,
5459 IDirectPlay2AImpl_GetPlayerAddress,
5460 IDirectPlay2AImpl_GetPlayerCaps,
5461 IDirectPlay2AImpl_GetPlayerData,
5462 IDirectPlay2AImpl_GetPlayerName,
5463 IDirectPlay2AImpl_GetSessionDesc,
5464 IDirectPlay2AImpl_Initialize,
5465 IDirectPlay2AImpl_Open,
5466 IDirectPlay2AImpl_Receive,
5467 IDirectPlay2AImpl_Send,
5468 IDirectPlay2AImpl_SetGroupData,
5469 IDirectPlay2AImpl_SetGroupName,
5470 IDirectPlay2AImpl_SetPlayerData,
5471 IDirectPlay2AImpl_SetPlayerName,
5472 IDirectPlay2AImpl_SetSessionDesc
5475 static const IDirectPlay3Vtbl dp3_vt =
5477 IDirectPlay3Impl_QueryInterface,
5478 IDirectPlay3Impl_AddRef,
5479 IDirectPlay3Impl_Release,
5480 IDirectPlay3Impl_AddPlayerToGroup,
5481 IDirectPlay3Impl_Close,
5482 IDirectPlay3Impl_CreateGroup,
5483 IDirectPlay3Impl_CreatePlayer,
5484 IDirectPlay3Impl_DeletePlayerFromGroup,
5485 IDirectPlay3Impl_DestroyGroup,
5486 IDirectPlay3Impl_DestroyPlayer,
5487 IDirectPlay3Impl_EnumGroupPlayers,
5488 IDirectPlay3Impl_EnumGroups,
5489 IDirectPlay3Impl_EnumPlayers,
5490 IDirectPlay3Impl_EnumSessions,
5491 IDirectPlay3Impl_GetCaps,
5492 IDirectPlay3Impl_GetGroupData,
5493 IDirectPlay3Impl_GetGroupName,
5494 IDirectPlay3Impl_GetMessageCount,
5495 IDirectPlay3Impl_GetPlayerAddress,
5496 IDirectPlay3Impl_GetPlayerCaps,
5497 IDirectPlay3Impl_GetPlayerData,
5498 IDirectPlay3Impl_GetPlayerName,
5499 IDirectPlay3Impl_GetSessionDesc,
5500 IDirectPlay3Impl_Initialize,
5501 IDirectPlay3Impl_Open,
5502 IDirectPlay3Impl_Receive,
5503 IDirectPlay3Impl_Send,
5504 IDirectPlay3Impl_SetGroupData,
5505 IDirectPlay3Impl_SetGroupName,
5506 IDirectPlay3Impl_SetPlayerData,
5507 IDirectPlay3Impl_SetPlayerName,
5508 IDirectPlay3Impl_SetSessionDesc,
5509 IDirectPlay3Impl_AddGroupToGroup,
5510 IDirectPlay3Impl_CreateGroupInGroup,
5511 IDirectPlay3Impl_DeleteGroupFromGroup,
5512 IDirectPlay3Impl_EnumConnections,
5513 IDirectPlay3Impl_EnumGroupsInGroup,
5514 IDirectPlay3Impl_GetGroupConnectionSettings,
5515 IDirectPlay3Impl_InitializeConnection,
5516 IDirectPlay3Impl_SecureOpen,
5517 IDirectPlay3Impl_SendChatMessage,
5518 IDirectPlay3Impl_SetGroupConnectionSettings,
5519 IDirectPlay3Impl_StartSession,
5520 IDirectPlay3Impl_GetGroupFlags,
5521 IDirectPlay3Impl_GetGroupParent,
5522 IDirectPlay3Impl_GetPlayerAccount,
5523 IDirectPlay3Impl_GetPlayerFlags
5526 static const IDirectPlay3Vtbl dp3A_vt =
5528 IDirectPlay3AImpl_QueryInterface,
5529 IDirectPlay3AImpl_AddRef,
5530 IDirectPlay3AImpl_Release,
5531 IDirectPlay3AImpl_AddPlayerToGroup,
5532 IDirectPlay3AImpl_Close,
5533 IDirectPlay3AImpl_CreateGroup,
5534 IDirectPlay3AImpl_CreatePlayer,
5535 IDirectPlay3AImpl_DeletePlayerFromGroup,
5536 IDirectPlay3AImpl_DestroyGroup,
5537 IDirectPlay3AImpl_DestroyPlayer,
5538 IDirectPlay3AImpl_EnumGroupPlayers,
5539 IDirectPlay3AImpl_EnumGroups,
5540 IDirectPlay3AImpl_EnumPlayers,
5541 IDirectPlay3AImpl_EnumSessions,
5542 IDirectPlay3AImpl_GetCaps,
5543 IDirectPlay3AImpl_GetGroupData,
5544 IDirectPlay3AImpl_GetGroupName,
5545 IDirectPlay3AImpl_GetMessageCount,
5546 IDirectPlay3AImpl_GetPlayerAddress,
5547 IDirectPlay3AImpl_GetPlayerCaps,
5548 IDirectPlay3AImpl_GetPlayerData,
5549 IDirectPlay3AImpl_GetPlayerName,
5550 IDirectPlay3AImpl_GetSessionDesc,
5551 IDirectPlay3AImpl_Initialize,
5552 IDirectPlay3AImpl_Open,
5553 IDirectPlay3AImpl_Receive,
5554 IDirectPlay3AImpl_Send,
5555 IDirectPlay3AImpl_SetGroupData,
5556 IDirectPlay3AImpl_SetGroupName,
5557 IDirectPlay3AImpl_SetPlayerData,
5558 IDirectPlay3AImpl_SetPlayerName,
5559 IDirectPlay3AImpl_SetSessionDesc,
5560 IDirectPlay3AImpl_AddGroupToGroup,
5561 IDirectPlay3AImpl_CreateGroupInGroup,
5562 IDirectPlay3AImpl_DeleteGroupFromGroup,
5563 IDirectPlay3AImpl_EnumConnections,
5564 IDirectPlay3AImpl_EnumGroupsInGroup,
5565 IDirectPlay3AImpl_GetGroupConnectionSettings,
5566 IDirectPlay3AImpl_InitializeConnection,
5567 IDirectPlay3AImpl_SecureOpen,
5568 IDirectPlay3AImpl_SendChatMessage,
5569 IDirectPlay3AImpl_SetGroupConnectionSettings,
5570 IDirectPlay3AImpl_StartSession,
5571 IDirectPlay3AImpl_GetGroupFlags,
5572 IDirectPlay3AImpl_GetGroupParent,
5573 IDirectPlay3AImpl_GetPlayerAccount,
5574 IDirectPlay3AImpl_GetPlayerFlags
5577 static const IDirectPlay4Vtbl dp4_vt =
5579 IDirectPlay4Impl_QueryInterface,
5580 IDirectPlay4Impl_AddRef,
5581 IDirectPlay4Impl_Release,
5582 IDirectPlay4Impl_AddPlayerToGroup,
5583 IDirectPlay4Impl_Close,
5584 IDirectPlay4Impl_CreateGroup,
5585 IDirectPlay4Impl_CreatePlayer,
5586 IDirectPlay4Impl_DeletePlayerFromGroup,
5587 IDirectPlay4Impl_DestroyGroup,
5588 IDirectPlay4Impl_DestroyPlayer,
5589 IDirectPlay4Impl_EnumGroupPlayers,
5590 IDirectPlay4Impl_EnumGroups,
5591 IDirectPlay4Impl_EnumPlayers,
5592 IDirectPlay4Impl_EnumSessions,
5593 IDirectPlay4Impl_GetCaps,
5594 IDirectPlay4Impl_GetGroupData,
5595 IDirectPlay4Impl_GetGroupName,
5596 IDirectPlay4Impl_GetMessageCount,
5597 IDirectPlay4Impl_GetPlayerAddress,
5598 IDirectPlay4Impl_GetPlayerCaps,
5599 IDirectPlay4Impl_GetPlayerData,
5600 IDirectPlay4Impl_GetPlayerName,
5601 IDirectPlay4Impl_GetSessionDesc,
5602 IDirectPlay4Impl_Initialize,
5603 IDirectPlay4Impl_Open,
5604 IDirectPlay4Impl_Receive,
5605 IDirectPlay4Impl_Send,
5606 IDirectPlay4Impl_SetGroupData,
5607 IDirectPlay4Impl_SetGroupName,
5608 IDirectPlay4Impl_SetPlayerData,
5609 IDirectPlay4Impl_SetPlayerName,
5610 IDirectPlay4Impl_SetSessionDesc,
5611 IDirectPlay4Impl_AddGroupToGroup,
5612 IDirectPlay4Impl_CreateGroupInGroup,
5613 IDirectPlay4Impl_DeleteGroupFromGroup,
5614 IDirectPlay4Impl_EnumConnections,
5615 IDirectPlay4Impl_EnumGroupsInGroup,
5616 IDirectPlay4Impl_GetGroupConnectionSettings,
5617 IDirectPlay4Impl_InitializeConnection,
5618 IDirectPlay4Impl_SecureOpen,
5619 IDirectPlay4Impl_SendChatMessage,
5620 IDirectPlay4Impl_SetGroupConnectionSettings,
5621 IDirectPlay4Impl_StartSession,
5622 IDirectPlay4Impl_GetGroupFlags,
5623 IDirectPlay4Impl_GetGroupParent,
5624 IDirectPlay4Impl_GetPlayerAccount,
5625 IDirectPlay4Impl_GetPlayerFlags,
5626 IDirectPlay4Impl_GetGroupOwner,
5627 IDirectPlay4Impl_SetGroupOwner,
5628 IDirectPlay4Impl_SendEx,
5629 IDirectPlay4Impl_GetMessageQueue,
5630 IDirectPlay4Impl_CancelMessage,
5631 IDirectPlay4Impl_CancelPriority
5634 static const IDirectPlay4Vtbl dp4A_vt =
5636 IDirectPlay4AImpl_QueryInterface,
5637 IDirectPlay4AImpl_AddRef,
5638 IDirectPlay4AImpl_Release,
5639 IDirectPlay4AImpl_AddPlayerToGroup,
5640 IDirectPlay4AImpl_Close,
5641 IDirectPlay4AImpl_CreateGroup,
5642 IDirectPlay4AImpl_CreatePlayer,
5643 IDirectPlay4AImpl_DeletePlayerFromGroup,
5644 IDirectPlay4AImpl_DestroyGroup,
5645 IDirectPlay4AImpl_DestroyPlayer,
5646 IDirectPlay4AImpl_EnumGroupPlayers,
5647 IDirectPlay4AImpl_EnumGroups,
5648 IDirectPlay4AImpl_EnumPlayers,
5649 IDirectPlay4AImpl_EnumSessions,
5650 IDirectPlay4AImpl_GetCaps,
5651 IDirectPlay4AImpl_GetGroupData,
5652 IDirectPlay4AImpl_GetGroupName,
5653 IDirectPlay4AImpl_GetMessageCount,
5654 IDirectPlay4AImpl_GetPlayerAddress,
5655 IDirectPlay4AImpl_GetPlayerCaps,
5656 IDirectPlay4AImpl_GetPlayerData,
5657 IDirectPlay4AImpl_GetPlayerName,
5658 IDirectPlay4AImpl_GetSessionDesc,
5659 IDirectPlay4AImpl_Initialize,
5660 IDirectPlay4AImpl_Open,
5661 IDirectPlay4AImpl_Receive,
5662 IDirectPlay4AImpl_Send,
5663 IDirectPlay4AImpl_SetGroupData,
5664 IDirectPlay4AImpl_SetGroupName,
5665 IDirectPlay4AImpl_SetPlayerData,
5666 IDirectPlay4AImpl_SetPlayerName,
5667 IDirectPlay4AImpl_SetSessionDesc,
5668 IDirectPlay4AImpl_AddGroupToGroup,
5669 IDirectPlay4AImpl_CreateGroupInGroup,
5670 IDirectPlay4AImpl_DeleteGroupFromGroup,
5671 IDirectPlay4AImpl_EnumConnections,
5672 IDirectPlay4AImpl_EnumGroupsInGroup,
5673 IDirectPlay4AImpl_GetGroupConnectionSettings,
5674 IDirectPlay4AImpl_InitializeConnection,
5675 IDirectPlay4AImpl_SecureOpen,
5676 IDirectPlay4AImpl_SendChatMessage,
5677 IDirectPlay4AImpl_SetGroupConnectionSettings,
5678 IDirectPlay4AImpl_StartSession,
5679 IDirectPlay4AImpl_GetGroupFlags,
5680 IDirectPlay4AImpl_GetGroupParent,
5681 IDirectPlay4AImpl_GetPlayerAccount,
5682 IDirectPlay4AImpl_GetPlayerFlags,
5683 IDirectPlay4AImpl_GetGroupOwner,
5684 IDirectPlay4AImpl_SetGroupOwner,
5685 IDirectPlay4AImpl_SendEx,
5686 IDirectPlay4AImpl_GetMessageQueue,
5687 IDirectPlay4AImpl_CancelMessage,
5688 IDirectPlay4AImpl_CancelPriority
5691 HRESULT dplay_create( REFIID riid, void **ppv )
5693 IDirectPlayImpl *obj;
5694 HRESULT hr;
5696 TRACE( "(%s, %p)\n", debugstr_guid( riid ), ppv );
5698 *ppv = NULL;
5699 obj = HeapAlloc( GetProcessHeap(), 0, sizeof( *obj ) );
5700 if ( !obj )
5701 return DPERR_OUTOFMEMORY;
5703 obj->IDirectPlay_iface.lpVtbl = &dp_vt;
5704 obj->IDirectPlay2A_iface.lpVtbl = &dp2A_vt;
5705 obj->IDirectPlay2_iface.lpVtbl = &dp2_vt;
5706 obj->IDirectPlay3A_iface.lpVtbl = &dp3A_vt;
5707 obj->IDirectPlay3_iface.lpVtbl = &dp3_vt;
5708 obj->IDirectPlay4A_iface.lpVtbl = &dp4A_vt;
5709 obj->IDirectPlay4_iface.lpVtbl = &dp4_vt;
5710 obj->numIfaces = 1;
5711 obj->ref = 0;
5712 obj->ref2A = 0;
5713 obj->ref2 = 0;
5714 obj->ref3A = 0;
5715 obj->ref3 = 0;
5716 obj->ref4A = 0;
5717 obj->ref4 = 1;
5719 InitializeCriticalSection( &obj->lock );
5720 obj->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectPlayImpl.lock");
5722 if ( DP_CreateDirectPlay2( obj ) )
5723 hr = IDirectPlayX_QueryInterface( &obj->IDirectPlay4_iface, riid, ppv );
5724 else
5725 hr = DPERR_NOMEMORY;
5726 IDirectPlayX_Release( &obj->IDirectPlay4_iface );
5728 return hr;
5732 HRESULT DP_GetSPPlayerData( IDirectPlayImpl *lpDP, DPID idPlayer, void **lplpData )
5734 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5736 if( lpPlayer == NULL )
5738 return DPERR_INVALIDPLAYER;
5741 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
5743 return DP_OK;
5746 HRESULT DP_SetSPPlayerData( IDirectPlayImpl *lpDP, DPID idPlayer, void *lpData )
5748 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5750 if( lpPlayer == NULL )
5752 return DPERR_INVALIDPLAYER;
5755 lpPlayer->lpPData->lpSPPlayerData = lpData;
5757 return DP_OK;
5760 /***************************************************************************
5761 * DirectPlayEnumerateAW
5763 * The pointer to the structure lpContext will be filled with the
5764 * appropriate data for each service offered by the OS. These services are
5765 * not necessarily available on this particular machine but are defined
5766 * as simple service providers under the "Service Providers" registry key.
5767 * This structure is then passed to lpEnumCallback for each of the different
5768 * services.
5770 * This API is useful only for applications written using DirectX3 or
5771 * worse. It is superseded by IDirectPlay3::EnumConnections which also
5772 * gives information on the actual connections.
5774 * defn of a service provider:
5775 * A dynamic-link library used by DirectPlay to communicate over a network.
5776 * The service provider contains all the network-specific code required
5777 * to send and receive messages. Online services and network operators can
5778 * supply service providers to use specialized hardware, protocols, communications
5779 * media, and network resources.
5782 static HRESULT DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA,
5783 LPDPENUMDPCALLBACKW lpEnumCallbackW,
5784 LPVOID lpContext)
5786 HKEY hkResult;
5787 static const WCHAR searchSubKey[] = {
5788 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
5789 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
5790 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
5791 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
5792 static const WCHAR guidKey[] = { 'G', 'u', 'i', 'd', 0 };
5793 static const WCHAR descW[] = { 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', 'W', 0 };
5795 DWORD dwIndex;
5796 FILETIME filetime;
5798 char *descriptionA = NULL;
5799 DWORD max_sizeOfDescriptionA = 0;
5800 WCHAR *descriptionW = NULL;
5801 DWORD max_sizeOfDescriptionW = 0;
5803 if (!lpEnumCallbackA && !lpEnumCallbackW)
5805 return DPERR_INVALIDPARAMS;
5808 /* Need to loop over the service providers in the registry */
5809 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, searchSubKey,
5810 0, KEY_READ, &hkResult) != ERROR_SUCCESS)
5812 /* Hmmm. Does this mean that there are no service providers? */
5813 ERR(": no service provider key in the registry - check your Wine installation !!!\n");
5814 return DPERR_GENERIC;
5817 /* Traverse all the service providers we have available */
5818 dwIndex = 0;
5819 while (1)
5821 WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */
5822 DWORD sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR);
5823 HKEY hkServiceProvider;
5824 GUID serviceProviderGUID;
5825 WCHAR guidKeyContent[(2 * 16) + 1 + 6 /* This corresponds to '{....-..-..-..-......}' */ ];
5826 DWORD sizeOfGuidKeyContent = sizeof(guidKeyContent);
5827 LONG ret_value;
5829 ret_value = RegEnumKeyExW(hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
5830 NULL, NULL, NULL, &filetime);
5831 if (ret_value == ERROR_NO_MORE_ITEMS)
5832 break;
5833 else if (ret_value != ERROR_SUCCESS)
5835 ERR(": could not enumerate on service provider key.\n");
5836 return DPERR_EXCEPTION;
5838 TRACE(" this time through sub-key %s.\n", debugstr_w(subKeyName));
5840 /* Open the key for this service provider */
5841 if (RegOpenKeyExW(hkResult, subKeyName, 0, KEY_READ, &hkServiceProvider) != ERROR_SUCCESS)
5843 ERR(": could not open registry key for service provider %s.\n", debugstr_w(subKeyName));
5844 continue;
5847 /* Get the GUID from the registry */
5848 if (RegQueryValueExW(hkServiceProvider, guidKey,
5849 NULL, NULL, (LPBYTE) guidKeyContent, &sizeOfGuidKeyContent) != ERROR_SUCCESS)
5851 ERR(": missing GUID registry data member for service provider %s.\n", debugstr_w(subKeyName));
5852 continue;
5854 if (sizeOfGuidKeyContent != sizeof(guidKeyContent))
5856 ERR(": invalid format for the GUID registry data member for service provider %s (%s).\n", debugstr_w(subKeyName), debugstr_w(guidKeyContent));
5857 continue;
5859 CLSIDFromString(guidKeyContent, &serviceProviderGUID );
5861 /* The enumeration will return FALSE if we are not to continue.
5863 * Note: on my windows box, major / minor version is 6 / 0 for all service providers
5864 * and have no relation to any of the two dwReserved1 and dwReserved2 keys.
5865 * I think that it simply means that they are in-line with DirectX 6.0
5867 if (lpEnumCallbackA)
5869 DWORD sizeOfDescription = 0;
5871 /* Note that this is the A case of this function, so use the A variant to get the description string */
5872 if (RegQueryValueExA(hkServiceProvider, "DescriptionA",
5873 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5875 ERR(": missing 'DescriptionA' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5876 continue;
5878 if (sizeOfDescription > max_sizeOfDescriptionA)
5880 HeapFree(GetProcessHeap(), 0, descriptionA);
5881 max_sizeOfDescriptionA = sizeOfDescription;
5883 descriptionA = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5884 RegQueryValueExA(hkServiceProvider, "DescriptionA",
5885 NULL, NULL, (LPBYTE) descriptionA, &sizeOfDescription);
5887 if (!lpEnumCallbackA(&serviceProviderGUID, descriptionA, 6, 0, lpContext))
5888 goto end;
5890 else
5892 DWORD sizeOfDescription = 0;
5894 if (RegQueryValueExW(hkServiceProvider, descW,
5895 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5897 ERR(": missing 'DescriptionW' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5898 continue;
5900 if (sizeOfDescription > max_sizeOfDescriptionW)
5902 HeapFree(GetProcessHeap(), 0, descriptionW);
5903 max_sizeOfDescriptionW = sizeOfDescription;
5905 descriptionW = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5906 RegQueryValueExW(hkServiceProvider, descW,
5907 NULL, NULL, (LPBYTE) descriptionW, &sizeOfDescription);
5909 if (!lpEnumCallbackW(&serviceProviderGUID, descriptionW, 6, 0, lpContext))
5910 goto end;
5913 dwIndex++;
5916 end:
5917 HeapFree(GetProcessHeap(), 0, descriptionA);
5918 HeapFree(GetProcessHeap(), 0, descriptionW);
5920 return DP_OK;
5923 /***************************************************************************
5924 * DirectPlayEnumerate [DPLAYX.9]
5925 * DirectPlayEnumerateA [DPLAYX.2]
5927 HRESULT WINAPI DirectPlayEnumerateA(LPDPENUMDPCALLBACKA lpEnumCallback, LPVOID lpContext )
5929 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5931 return DirectPlayEnumerateAW(lpEnumCallback, NULL, lpContext);
5934 /***************************************************************************
5935 * DirectPlayEnumerateW [DPLAYX.3]
5937 HRESULT WINAPI DirectPlayEnumerateW(LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5939 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5941 return DirectPlayEnumerateAW(NULL, lpEnumCallback, lpContext);
5944 typedef struct tagCreateEnum
5946 LPVOID lpConn;
5947 LPCGUID lpGuid;
5948 } CreateEnumData, *lpCreateEnumData;
5950 /* Find and copy the matching connection for the SP guid */
5951 static BOOL CALLBACK cbDPCreateEnumConnections(
5952 LPCGUID lpguidSP,
5953 LPVOID lpConnection,
5954 DWORD dwConnectionSize,
5955 LPCDPNAME lpName,
5956 DWORD dwFlags,
5957 LPVOID lpContext)
5959 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5961 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5963 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5965 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5966 dwConnectionSize );
5967 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5969 /* Found the record that we were looking for */
5970 return FALSE;
5973 /* Haven't found what were looking for yet */
5974 return TRUE;
5978 /***************************************************************************
5979 * DirectPlayCreate [DPLAYX.1]
5982 HRESULT WINAPI DirectPlayCreate
5983 ( LPGUID lpGUID, LPDIRECTPLAY *lplpDP, IUnknown *pUnk )
5985 HRESULT hr;
5986 LPDIRECTPLAY3A lpDP3A;
5987 CreateEnumData cbData;
5989 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5991 if( pUnk != NULL )
5993 return CLASS_E_NOAGGREGATION;
5996 if( (lplpDP == NULL) || (lpGUID == NULL) )
5998 return DPERR_INVALIDPARAMS;
6001 if ( dplay_create( &IID_IDirectPlay, (void**)lplpDP ) != DP_OK )
6002 return DPERR_UNAVAILABLE;
6004 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
6006 /* The GUID_NULL means don't bind a service provider. Just return the
6007 interface as is */
6008 return DP_OK;
6011 /* Bind the desired service provider since lpGUID is non NULL */
6012 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
6014 /* We're going to use a DP3 interface */
6015 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
6016 (LPVOID*)&lpDP3A );
6017 if( FAILED(hr) )
6019 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
6020 return hr;
6023 cbData.lpConn = NULL;
6024 cbData.lpGuid = lpGUID;
6026 /* We were given a service provider, find info about it... */
6027 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
6028 &cbData, DPCONNECTION_DIRECTPLAY );
6029 if( ( FAILED(hr) ) ||
6030 ( cbData.lpConn == NULL )
6033 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
6034 IDirectPlayX_Release( lpDP3A );
6035 return DPERR_UNAVAILABLE;
6038 /* Initialize the service provider */
6039 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
6040 if( FAILED(hr) )
6042 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
6043 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
6044 IDirectPlayX_Release( lpDP3A );
6045 return hr;
6048 /* Release our version of the interface now that we're done with it */
6049 IDirectPlayX_Release( lpDP3A );
6050 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
6052 return DP_OK;