opengl32: Fix some style issues.
[wine.git] / dlls / dplayx / dplay.c
blob20899d53745d1fbc80b78e47be1c26d68bc38c68
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( dplaysp_create( &IID_IDirectPlaySP, (void**)&This->dp2->spData.lpISP, This ) ) )
178 /* FIXME: Memory leak */
179 return FALSE;
182 /* Setup lobby provider information */
183 This->dp2->dplspData.dwSPVersion = DPSP_MAJORVERSION;
184 This->dp2->dplspData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
185 sizeof( *This->dp2->dplspData.lpCB ) );
186 This->dp2->dplspData.lpCB->dwSize = sizeof( *This->dp2->dplspData.lpCB );
188 if( FAILED( dplobbysp_create( &IID_IDPLobbySP, (void**)&This->dp2->dplspData.lpISP, This ) )
191 /* FIXME: Memory leak */
192 return FALSE;
195 return TRUE;
198 /* Definition of the global function in dplayx_queue.h. #
199 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
200 DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
202 HeapFree( GetProcessHeap(), 0, elem );
205 static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
207 IDirectPlayImpl *This = lpDP;
209 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
211 TerminateThread( This->dp2->hEnumSessionThread, 0 );
212 CloseHandle( This->dp2->hEnumSessionThread );
215 /* Finish with the SP - have it shutdown */
216 if( This->dp2->spData.lpCB->ShutdownEx )
218 DPSP_SHUTDOWNDATA data;
220 TRACE( "Calling SP ShutdownEx\n" );
222 data.lpISP = This->dp2->spData.lpISP;
224 (*This->dp2->spData.lpCB->ShutdownEx)( &data );
226 else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
228 TRACE( "Calling obsolete SP Shutdown\n" );
229 (*This->dp2->spData.lpCB->Shutdown)();
232 /* Unload the SP (if it exists) */
233 if( This->dp2->hServiceProvider != 0 )
235 FreeLibrary( This->dp2->hServiceProvider );
238 /* Unload the Lobby Provider (if it exists) */
239 if( This->dp2->hDPLobbyProvider != 0 )
241 FreeLibrary( This->dp2->hDPLobbyProvider );
244 /* FIXME: Need to delete receive and send msgs queue contents */
246 NS_DeleteSessionCache( This->dp2->lpNameServerData );
248 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
250 IDirectPlaySP_Release( This->dp2->spData.lpISP );
252 /* Delete the contents */
253 HeapFree( GetProcessHeap(), 0, This->dp2 );
255 return TRUE;
258 static void dplay_destroy(IDirectPlayImpl *obj)
260 DP_DestroyDirectPlay2( obj );
261 obj->lock.DebugInfo->Spare[0] = 0;
262 DeleteCriticalSection( &obj->lock );
263 HeapFree( GetProcessHeap(), 0, obj );
266 static inline DPID DP_NextObjectId(void)
268 return (DPID)InterlockedIncrement( &kludgePlayerGroupId );
271 /* *lplpReply will be non NULL iff there is something to reply */
272 HRESULT DP_HandleMessage( IDirectPlayImpl *This, const void *lpcMessageBody,
273 DWORD dwMessageBodySize, const void *lpcMessageHeader, WORD wCommandId, WORD wVersion,
274 void **lplpReply, DWORD *lpdwMsgSize )
276 TRACE( "(%p)->(%p,0x%08x,%p,%u,%u)\n",
277 This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId,
278 wVersion );
280 switch( wCommandId )
282 /* Name server needs to handle this request */
283 case DPMSGCMD_ENUMSESSIONSREQUEST:
284 /* Reply expected */
285 NS_ReplyToEnumSessionsRequest( lpcMessageBody, lplpReply, lpdwMsgSize, This );
286 break;
288 /* Name server needs to handle this request */
289 case DPMSGCMD_ENUMSESSIONSREPLY:
290 /* No reply expected */
291 NS_AddRemoteComputerAsNameServer( lpcMessageHeader,
292 This->dp2->spData.dwSPHeaderSize,
293 lpcMessageBody,
294 This->dp2->lpNameServerData );
295 break;
297 case DPMSGCMD_REQUESTNEWPLAYERID:
299 LPCDPMSG_REQUESTNEWPLAYERID lpcMsg = lpcMessageBody;
301 LPDPMSG_NEWPLAYERIDREPLY lpReply;
303 *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
305 *lplpReply = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, *lpdwMsgSize );
307 FIXME( "Ignoring dwFlags 0x%08x in request msg\n",
308 lpcMsg->dwFlags );
310 /* Setup the reply */
311 lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) +
312 This->dp2->spData.dwSPHeaderSize );
314 lpReply->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
315 lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY;
316 lpReply->envelope.wVersion = DPMSGVER_DP6;
318 lpReply->dpidNewPlayerId = DP_NextObjectId();
320 TRACE( "Allocating new playerid 0x%08x from remote request\n",
321 lpReply->dpidNewPlayerId );
322 break;
325 case DPMSGCMD_GETNAMETABLEREPLY:
326 case DPMSGCMD_NEWPLAYERIDREPLY:
327 #if 0
328 if( wCommandId == DPMSGCMD_NEWPLAYERIDREPLY )
329 DebugBreak();
330 #endif
331 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
332 break;
334 #if 1
335 case DPMSGCMD_JUSTENVELOPE:
336 TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08x\n", lpcMessageHeader, ((const DWORD *)lpcMessageHeader)[1] );
337 NS_SetLocalAddr( This->dp2->lpNameServerData, lpcMessageHeader, 20 );
338 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
339 #endif
341 case DPMSGCMD_FORWARDADDPLAYER:
342 #if 0
343 DebugBreak();
344 #endif
345 #if 1
346 TRACE( "Sending message to self to get my addr\n" );
347 DP_MSG_ToSelf( This, 1 ); /* This is a hack right now */
348 #endif
349 break;
351 case DPMSGCMD_FORWARDADDPLAYERNACK:
352 DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
353 break;
355 default:
356 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
357 DebugBreak();
358 break;
361 /* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */
363 return DP_OK;
367 static HRESULT WINAPI IDirectPlayImpl_QueryInterface( IDirectPlay *iface, REFIID riid, void **ppv )
369 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
370 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
373 static ULONG WINAPI IDirectPlayImpl_AddRef( IDirectPlay *iface )
375 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
376 ULONG ref = InterlockedIncrement( &This->ref );
378 TRACE( "(%p) ref=%d\n", This, ref );
380 if ( ref == 1 )
381 InterlockedIncrement( &This->numIfaces );
383 return ref;
386 static ULONG WINAPI IDirectPlayImpl_Release( IDirectPlay *iface )
388 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
389 ULONG ref = InterlockedDecrement( &This->ref );
391 TRACE( "(%p) ref=%d\n", This, ref );
393 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
394 dplay_destroy( This );
396 return ref;
399 static HRESULT WINAPI IDirectPlayImpl_AddPlayerToGroup( IDirectPlay *iface, DPID group,
400 DPID player )
402 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
403 FIXME( "(%p)->(0x%08x,0x%08x): stub\n", This, group, player );
404 return E_NOTIMPL;
407 static HRESULT WINAPI IDirectPlayImpl_Close( IDirectPlay *iface )
409 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
410 FIXME( "(%p): stub\n", This );
411 return E_NOTIMPL;
414 static HRESULT WINAPI IDirectPlayImpl_CreatePlayer( IDirectPlay *iface, DPID *player,
415 LPSTR name, LPSTR fullname, HANDLE *event )
417 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
418 FIXME( "(%p)->(%p,%s,%s,%p): stub\n", This, player, debugstr_a( name ), debugstr_a( fullname ),
419 event );
420 return E_NOTIMPL;
423 static HRESULT WINAPI IDirectPlayImpl_CreateGroup( IDirectPlay *iface, DPID *group, LPSTR name,
424 LPSTR fullname )
426 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
427 FIXME( "(%p)->(%p,%s,%s): stub\n", This, group, debugstr_a( name ), debugstr_a( fullname ) );
428 return E_NOTIMPL;
431 static HRESULT WINAPI IDirectPlayImpl_DeletePlayerFromGroup( IDirectPlay *iface, DPID group,
432 DPID player )
434 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
435 FIXME( "(%p)->(0x%08x,0x%08x): stub\n", This, group, player );
436 return E_NOTIMPL;
439 static HRESULT WINAPI IDirectPlayImpl_DestroyPlayer( IDirectPlay *iface, DPID player )
441 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
442 FIXME( "(%p)->(0x%08x): stub\n", This, player );
443 return E_NOTIMPL;
446 static HRESULT WINAPI IDirectPlayImpl_DestroyGroup( IDirectPlay *iface, DPID group )
448 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
449 FIXME( "(%p)->(0x%08x): stub\n", This, group );
450 return E_NOTIMPL;
453 static HRESULT WINAPI IDirectPlayImpl_EnableNewPlayers( IDirectPlay *iface, BOOL enable )
455 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
456 FIXME( "(%p)->(%d): stub\n", This, enable );
457 return E_NOTIMPL;
460 static HRESULT WINAPI IDirectPlayImpl_EnumGroupPlayers( IDirectPlay *iface, DPID group,
461 LPDPENUMPLAYERSCALLBACK enumplayercb, void *context, DWORD flags )
463 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
464 FIXME( "(%p)->(0x%08x,%p,%p,0x%08x): stub\n", This, group, enumplayercb, context, flags );
465 return E_NOTIMPL;
468 static HRESULT WINAPI IDirectPlayImpl_EnumGroups( IDirectPlay *iface, DWORD session,
469 LPDPENUMPLAYERSCALLBACK enumplayercb, void *context, DWORD flags )
471 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
472 FIXME( "(%p)->(0x%08x,%p,%p,0x%08x): stub\n", This, session, enumplayercb, context, flags );
473 return E_NOTIMPL;
476 static HRESULT WINAPI IDirectPlayImpl_EnumPlayers( IDirectPlay *iface, DWORD session,
477 LPDPENUMPLAYERSCALLBACK enumplayercb, void *context, DWORD flags )
479 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
480 FIXME( "(%p)->(0x%08x,%p,%p,0x%08x): stub\n", This, session, enumplayercb, context, flags );
481 return E_NOTIMPL;
484 static HRESULT WINAPI IDirectPlayImpl_EnumSessions( IDirectPlay *iface, DPSESSIONDESC *sdesc,
485 DWORD timeout, LPDPENUMSESSIONSCALLBACK enumsessioncb, void *context, DWORD flags )
487 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
488 FIXME( "(%p)->(%p,%u,%p,%p,0x%08x): stub\n", This, sdesc, timeout, enumsessioncb, context,
489 flags );
490 return E_NOTIMPL;
493 static HRESULT WINAPI IDirectPlayImpl_GetCaps( IDirectPlay *iface, DPCAPS *caps )
495 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
496 FIXME( "(%p)->(%p): stub\n", This, caps );
497 return E_NOTIMPL;
500 static HRESULT WINAPI IDirectPlayImpl_GetMessageCount( IDirectPlay *iface, DPID player,
501 DWORD *count )
503 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
504 FIXME( "(%p)->(0x%08x,%p): stub\n", This, player, count );
505 return E_NOTIMPL;
508 static HRESULT WINAPI IDirectPlayImpl_GetPlayerCaps( IDirectPlay *iface, DPID player, DPCAPS *caps )
510 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
511 FIXME( "(%p)->(0x%08x,%p): stub\n", This, player, caps );
512 return E_NOTIMPL;
515 static HRESULT WINAPI IDirectPlayImpl_GetPlayerName( IDirectPlay *iface, DPID player, LPSTR name,
516 DWORD *size_name, LPSTR fullname, DWORD *size_fullname )
518 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
519 FIXME( "(%p)->(0x%08x,%p,%p,%p,%p): stub\n", This, player, name, size_name, fullname,
520 size_fullname );
521 return E_NOTIMPL;
524 static HRESULT WINAPI IDirectPlayImpl_Initialize( IDirectPlay *iface, GUID *guid )
526 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
527 FIXME( "(%p)->(%p): stub\n", This, guid );
528 return E_NOTIMPL;
531 static HRESULT WINAPI IDirectPlayImpl_Open( IDirectPlay *iface, DPSESSIONDESC *sdesc )
533 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
534 FIXME( "(%p)->(%p): stub\n", This, sdesc );
535 return E_NOTIMPL;
538 static HRESULT WINAPI IDirectPlayImpl_Receive( IDirectPlay *iface, DPID *from, DPID *to,
539 DWORD flags, void *data, DWORD *size )
541 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
542 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p): stub\n", This, from, to, flags, data, size );
543 return E_NOTIMPL;
546 static HRESULT WINAPI IDirectPlayImpl_SaveSession( IDirectPlay *iface, LPSTR reserved )
548 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
549 FIXME( "(%p)->(%p): stub\n", This, reserved );
550 return E_NOTIMPL;
553 static HRESULT WINAPI IDirectPlayImpl_Send( IDirectPlay *iface, DPID from, DPID to, DWORD flags,
554 void *data, DWORD size )
556 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
557 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%u): stub\n", This, from, to, flags, data, size );
558 return E_NOTIMPL;
561 static HRESULT WINAPI IDirectPlayImpl_SetPlayerName( IDirectPlay *iface, DPID player, LPSTR name,
562 LPSTR fullname )
564 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
565 FIXME( "(%p)->(0x%08x,%s,%s): stub\n", This, player, debugstr_a( name ),
566 debugstr_a ( fullname ) );
567 return E_NOTIMPL;
570 static const IDirectPlayVtbl dp_vt =
572 IDirectPlayImpl_QueryInterface,
573 IDirectPlayImpl_AddRef,
574 IDirectPlayImpl_Release,
575 IDirectPlayImpl_AddPlayerToGroup,
576 IDirectPlayImpl_Close,
577 IDirectPlayImpl_CreatePlayer,
578 IDirectPlayImpl_CreateGroup,
579 IDirectPlayImpl_DeletePlayerFromGroup,
580 IDirectPlayImpl_DestroyPlayer,
581 IDirectPlayImpl_DestroyGroup,
582 IDirectPlayImpl_EnableNewPlayers,
583 IDirectPlayImpl_EnumGroupPlayers,
584 IDirectPlayImpl_EnumGroups,
585 IDirectPlayImpl_EnumPlayers,
586 IDirectPlayImpl_EnumSessions,
587 IDirectPlayImpl_GetCaps,
588 IDirectPlayImpl_GetMessageCount,
589 IDirectPlayImpl_GetPlayerCaps,
590 IDirectPlayImpl_GetPlayerName,
591 IDirectPlayImpl_Initialize,
592 IDirectPlayImpl_Open,
593 IDirectPlayImpl_Receive,
594 IDirectPlayImpl_SaveSession,
595 IDirectPlayImpl_Send,
596 IDirectPlayImpl_SetPlayerName,
600 static HRESULT WINAPI IDirectPlay2AImpl_QueryInterface( IDirectPlay2A *iface, REFIID riid,
601 void **ppv )
603 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
604 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
607 static HRESULT WINAPI IDirectPlay2Impl_QueryInterface( IDirectPlay2 *iface, REFIID riid,
608 void **ppv )
610 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
611 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
614 static HRESULT WINAPI IDirectPlay3AImpl_QueryInterface( IDirectPlay3A *iface, REFIID riid,
615 void **ppv )
617 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
618 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
621 static HRESULT WINAPI IDirectPlay3Impl_QueryInterface( IDirectPlay3 *iface, REFIID riid,
622 void **ppv )
624 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
625 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
628 static HRESULT WINAPI IDirectPlay4AImpl_QueryInterface( IDirectPlay4A *iface, REFIID riid,
629 void **ppv )
631 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
632 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
635 static HRESULT WINAPI IDirectPlay4Impl_QueryInterface( IDirectPlay4 *iface, REFIID riid,
636 void **ppv )
638 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
640 if ( IsEqualGUID( &IID_IUnknown, riid ) )
642 TRACE( "(%p)->(IID_IUnknown %p)\n", This, ppv );
643 *ppv = &This->IDirectPlay_iface;
645 else if ( IsEqualGUID( &IID_IDirectPlay, riid ) )
647 TRACE( "(%p)->(IID_IDirectPlay %p)\n", This, ppv );
648 *ppv = &This->IDirectPlay_iface;
650 else if ( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
652 TRACE( "(%p)->(IID_IDirectPlay2A %p)\n", This, ppv );
653 *ppv = &This->IDirectPlay2A_iface;
655 else if ( IsEqualGUID( &IID_IDirectPlay2, riid ) )
657 TRACE( "(%p)->(IID_IDirectPlay2 %p)\n", This, ppv );
658 *ppv = &This->IDirectPlay2_iface;
660 else if ( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
662 TRACE( "(%p)->(IID_IDirectPlay3A %p)\n", This, ppv );
663 *ppv = &This->IDirectPlay3A_iface;
665 else if ( IsEqualGUID( &IID_IDirectPlay3, riid ) )
667 TRACE( "(%p)->(IID_IDirectPlay3 %p)\n", This, ppv );
668 *ppv = &This->IDirectPlay3_iface;
670 else if ( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
672 TRACE( "(%p)->(IID_IDirectPlay4A %p)\n", This, ppv );
673 *ppv = &This->IDirectPlay4A_iface;
675 else if ( IsEqualGUID( &IID_IDirectPlay4, riid ) )
677 TRACE( "(%p)->(IID_IDirectPlay4 %p)\n", This, ppv );
678 *ppv = &This->IDirectPlay4_iface;
680 else
682 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
683 *ppv = NULL;
684 return E_NOINTERFACE;
687 IUnknown_AddRef((IUnknown*)*ppv);
688 return S_OK;
691 static ULONG WINAPI IDirectPlay2AImpl_AddRef( IDirectPlay2A *iface )
693 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
694 ULONG ref = InterlockedIncrement( &This->ref2A );
696 TRACE( "(%p) ref2A=%d\n", This, ref );
698 if ( ref == 1 )
699 InterlockedIncrement( &This->numIfaces );
701 return ref;
704 static ULONG WINAPI IDirectPlay2Impl_AddRef( IDirectPlay2 *iface )
706 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
707 ULONG ref = InterlockedIncrement( &This->ref2 );
709 TRACE( "(%p) ref2=%d\n", This, ref );
711 if ( ref == 1 )
712 InterlockedIncrement( &This->numIfaces );
714 return ref;
717 static ULONG WINAPI IDirectPlay3AImpl_AddRef( IDirectPlay3A *iface )
719 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
720 ULONG ref = InterlockedIncrement( &This->ref3A );
722 TRACE( "(%p) ref3A=%d\n", This, ref );
724 if ( ref == 1 )
725 InterlockedIncrement( &This->numIfaces );
727 return ref;
730 static ULONG WINAPI IDirectPlay3Impl_AddRef( IDirectPlay3 *iface )
732 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
733 ULONG ref = InterlockedIncrement( &This->ref3 );
735 TRACE( "(%p) ref3=%d\n", This, ref );
737 if ( ref == 1 )
738 InterlockedIncrement( &This->numIfaces );
740 return ref;
743 static ULONG WINAPI IDirectPlay4AImpl_AddRef(IDirectPlay4A *iface)
745 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
746 ULONG ref = InterlockedIncrement( &This->ref4A );
748 TRACE( "(%p) ref4A=%d\n", This, ref );
750 if ( ref == 1 )
751 InterlockedIncrement( &This->numIfaces );
753 return ref;
756 static ULONG WINAPI IDirectPlay4Impl_AddRef(IDirectPlay4 *iface)
758 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
759 ULONG ref = InterlockedIncrement( &This->ref4 );
761 TRACE( "(%p) ref4=%d\n", This, ref );
763 if ( ref == 1 )
764 InterlockedIncrement( &This->numIfaces );
766 return ref;
769 static ULONG WINAPI IDirectPlay2AImpl_Release( IDirectPlay2A *iface )
771 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
772 ULONG ref = InterlockedDecrement( &This->ref2A );
774 TRACE( "(%p) ref2A=%d\n", This, ref );
776 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
777 dplay_destroy( This );
779 return ref;
782 static ULONG WINAPI IDirectPlay2Impl_Release( IDirectPlay2 *iface )
784 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
785 ULONG ref = InterlockedDecrement( &This->ref2 );
787 TRACE( "(%p) ref2=%d\n", This, ref );
789 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
790 dplay_destroy( This );
792 return ref;
795 static ULONG WINAPI IDirectPlay3AImpl_Release( IDirectPlay3A *iface )
797 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
798 ULONG ref = InterlockedDecrement( &This->ref3A );
800 TRACE( "(%p) ref3A=%d\n", This, ref );
802 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
803 dplay_destroy( This );
805 return ref;
808 static ULONG WINAPI IDirectPlay3Impl_Release( IDirectPlay3 *iface )
810 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
811 ULONG ref = InterlockedDecrement( &This->ref3 );
813 TRACE( "(%p) ref3=%d\n", This, ref );
815 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
816 dplay_destroy( This );
818 return ref;
821 static ULONG WINAPI IDirectPlay4AImpl_Release(IDirectPlay4A *iface)
823 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
824 ULONG ref = InterlockedDecrement( &This->ref4A );
826 TRACE( "(%p) ref4A=%d\n", This, ref );
828 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
829 dplay_destroy( This );
831 return ref;
834 static ULONG WINAPI IDirectPlay4Impl_Release(IDirectPlay4 *iface)
836 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
837 ULONG ref = InterlockedDecrement( &This->ref4 );
839 TRACE( "(%p) ref4=%d\n", This, ref );
841 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
842 dplay_destroy( This );
844 return ref;
847 static HRESULT WINAPI IDirectPlay2AImpl_AddPlayerToGroup( IDirectPlay2A *iface, DPID group,
848 DPID player )
850 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
851 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4A_iface, group, player );
854 static HRESULT WINAPI IDirectPlay2Impl_AddPlayerToGroup( IDirectPlay2 *iface, DPID group,
855 DPID player )
857 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
858 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
861 static HRESULT WINAPI IDirectPlay3AImpl_AddPlayerToGroup( IDirectPlay3A *iface, DPID group,
862 DPID player )
864 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
865 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
868 static HRESULT WINAPI IDirectPlay3Impl_AddPlayerToGroup( IDirectPlay3 *iface, DPID group,
869 DPID player )
871 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
872 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
875 static HRESULT WINAPI IDirectPlay4AImpl_AddPlayerToGroup( IDirectPlay4A *iface, DPID group,
876 DPID player )
878 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
879 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
882 static HRESULT WINAPI IDirectPlay4Impl_AddPlayerToGroup( IDirectPlay4 *iface, DPID group,
883 DPID player )
885 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
886 lpGroupData gdata;
887 lpPlayerList plist;
888 lpPlayerList newplist;
890 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, group, player );
892 if ( This->dp2->connectionInitialized == NO_PROVIDER )
893 return DPERR_UNINITIALIZED;
895 /* Find the group */
896 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
897 return DPERR_INVALIDGROUP;
899 /* Find the player */
900 if ( ( plist = DP_FindPlayer( This, player ) ) == NULL )
901 return DPERR_INVALIDPLAYER;
903 /* Create a player list (ie "shortcut" ) */
904 newplist = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *newplist ) );
905 if ( !newplist )
906 return DPERR_CANTADDPLAYER;
908 /* Add the shortcut */
909 plist->lpPData->uRef++;
910 newplist->lpPData = plist->lpPData;
912 /* Add the player to the list of players for this group */
913 DPQ_INSERT(gdata->players, newplist, players);
915 /* Let the SP know that we've added a player to the group */
916 if ( This->dp2->spData.lpCB->AddPlayerToGroup )
918 DPSP_ADDPLAYERTOGROUPDATA data;
920 TRACE( "Calling SP AddPlayerToGroup\n" );
922 data.idPlayer = player;
923 data.idGroup = group;
924 data.lpISP = This->dp2->spData.lpISP;
926 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
929 /* Inform all other peers of the addition of player to the group. If there are
930 * no peers keep this event quiet.
931 * Also, if this event was the result of another machine sending it to us,
932 * don't bother rebroadcasting it.
934 if ( This->dp2->lpSessionDesc &&
935 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
937 DPMSG_ADDPLAYERTOGROUP msg;
938 msg.dwType = DPSYS_ADDPLAYERTOGROUP;
940 msg.dpIdGroup = group;
941 msg.dpIdPlayer = player;
943 /* FIXME: Correct to just use send effectively? */
944 /* FIXME: Should size include data w/ message or just message "header" */
945 /* FIXME: Check return code */
946 IDirectPlayX_SendEx( iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
947 0, 0, NULL, NULL );
950 return DP_OK;
953 static HRESULT WINAPI IDirectPlay2AImpl_Close( IDirectPlay2A *iface )
955 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
956 return IDirectPlayX_Close( &This->IDirectPlay4A_iface );
959 static HRESULT WINAPI IDirectPlay2Impl_Close( IDirectPlay2 *iface )
961 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
962 return IDirectPlayX_Close( &This->IDirectPlay4_iface );
965 static HRESULT WINAPI IDirectPlay3AImpl_Close( IDirectPlay3A *iface )
967 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
968 return IDirectPlayX_Close( &This->IDirectPlay4_iface );
971 static HRESULT WINAPI IDirectPlay3Impl_Close( IDirectPlay3 *iface )
973 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
974 return IDirectPlayX_Close( &This->IDirectPlay4_iface );
977 static HRESULT WINAPI IDirectPlay4AImpl_Close( IDirectPlay4A *iface )
979 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
980 return IDirectPlayX_Close( &This->IDirectPlay4_iface);
983 static HRESULT WINAPI IDirectPlay4Impl_Close( IDirectPlay4 *iface )
985 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
986 HRESULT hr = DP_OK;
988 TRACE( "(%p)\n", This );
990 /* FIXME: Need to find a new host I assume (how?) */
991 /* FIXME: Need to destroy all local groups */
992 /* FIXME: Need to migrate all remotely visible players to the new host */
994 /* Invoke the SP callback to inform of session close */
995 if( This->dp2->spData.lpCB->CloseEx )
997 DPSP_CLOSEDATA data;
999 TRACE( "Calling SP CloseEx\n" );
1000 data.lpISP = This->dp2->spData.lpISP;
1001 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
1003 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
1005 TRACE( "Calling SP Close (obsolete interface)\n" );
1006 hr = (*This->dp2->spData.lpCB->Close)();
1009 return hr;
1012 static lpGroupData DP_CreateGroup( IDirectPlayImpl *This, const DPID *lpid, const DPNAME *lpName,
1013 DWORD dwFlags, DPID idParent, BOOL bAnsi )
1015 lpGroupData lpGData;
1017 /* Allocate the new space and add to end of high level group list */
1018 lpGData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGData ) );
1020 if( lpGData == NULL )
1022 return NULL;
1025 DPQ_INIT(lpGData->groups);
1026 DPQ_INIT(lpGData->players);
1028 /* Set the desired player ID - no sanity checking to see if it exists */
1029 lpGData->dpid = *lpid;
1031 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
1033 /* FIXME: Should we check that the parent exists? */
1034 lpGData->parent = idParent;
1036 /* FIXME: Should we validate the dwFlags? */
1037 lpGData->dwFlags = dwFlags;
1039 TRACE( "Created group id 0x%08x\n", *lpid );
1041 return lpGData;
1044 /* This method assumes that all links to it are already deleted */
1045 static void DP_DeleteGroup( IDirectPlayImpl *This, DPID dpid )
1047 lpGroupList lpGList;
1049 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1051 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
1053 if( lpGList == NULL )
1055 ERR( "DPID 0x%08x not found\n", dpid );
1056 return;
1059 if( --(lpGList->lpGData->uRef) )
1061 FIXME( "Why is this not the last reference to group?\n" );
1062 DebugBreak();
1065 /* Delete player */
1066 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
1067 HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
1069 /* Remove and Delete Player List object */
1070 HeapFree( GetProcessHeap(), 0, lpGList );
1074 static lpGroupData DP_FindAnyGroup( IDirectPlayImpl *This, DPID dpid )
1076 lpGroupList lpGroups;
1078 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1080 if( dpid == DPID_SYSTEM_GROUP )
1082 return This->dp2->lpSysGroup;
1084 else
1086 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
1089 if( lpGroups == NULL )
1091 return NULL;
1094 return lpGroups->lpGData;
1097 static HRESULT DP_IF_CreateGroup( IDirectPlayImpl *This, void *lpMsgHdr, DPID *lpidGroup,
1098 DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
1100 lpGroupData lpGData;
1102 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1103 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
1104 dwFlags, bAnsi );
1106 if( This->dp2->connectionInitialized == NO_PROVIDER )
1108 return DPERR_UNINITIALIZED;
1111 /* If the name is not specified, we must provide one */
1112 if( DPID_UNKNOWN == *lpidGroup )
1114 /* If we are the name server, we decide on the group ids. If not, we
1115 * must ask for one before attempting a creation.
1117 if( This->dp2->bHostInterface )
1119 *lpidGroup = DP_NextObjectId();
1121 else
1123 *lpidGroup = DP_GetRemoteNextObjectId();
1127 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
1128 DPID_NOPARENT_GROUP, bAnsi );
1130 if( lpGData == NULL )
1132 return DPERR_CANTADDPLAYER; /* yes player not group */
1135 if( DPID_SYSTEM_GROUP == *lpidGroup )
1137 This->dp2->lpSysGroup = lpGData;
1138 TRACE( "Inserting system group\n" );
1140 else
1142 /* Insert into the system group */
1143 lpGroupList lpGroup = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGroup ) );
1144 lpGroup->lpGData = lpGData;
1146 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
1149 /* Something is now referencing this data */
1150 lpGData->uRef++;
1152 /* Set all the important stuff for the group */
1153 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
1155 /* FIXME: We should only create the system group if GetCaps returns
1156 * DPCAPS_GROUPOPTIMIZED.
1159 /* Let the SP know that we've created this group */
1160 if( This->dp2->spData.lpCB->CreateGroup )
1162 DPSP_CREATEGROUPDATA data;
1163 DWORD dwCreateFlags = 0;
1165 TRACE( "Calling SP CreateGroup\n" );
1167 if( *lpidGroup == DPID_NOPARENT_GROUP )
1168 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
1170 if( lpMsgHdr == NULL )
1171 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1173 if( dwFlags & DPGROUP_HIDDEN )
1174 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
1176 data.idGroup = *lpidGroup;
1177 data.dwFlags = dwCreateFlags;
1178 data.lpSPMessageHeader = lpMsgHdr;
1179 data.lpISP = This->dp2->spData.lpISP;
1181 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1184 /* Inform all other peers of the creation of a new group. If there are
1185 * no peers keep this event quiet.
1186 * Also if this message was sent to us, don't rebroadcast.
1188 if( ( lpMsgHdr == NULL ) &&
1189 This->dp2->lpSessionDesc &&
1190 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1192 DPMSG_CREATEPLAYERORGROUP msg;
1193 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1195 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1196 msg.dpId = *lpidGroup;
1197 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1198 msg.lpData = lpData;
1199 msg.dwDataSize = dwDataSize;
1200 msg.dpnName = *lpGroupName;
1201 msg.dpIdParent = DPID_NOPARENT_GROUP;
1202 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
1204 /* FIXME: Correct to just use send effectively? */
1205 /* FIXME: Should size include data w/ message or just message "header" */
1206 /* FIXME: Check return code */
1207 IDirectPlayX_SendEx( &This->IDirectPlay4_iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
1208 sizeof( msg ), 0, 0, NULL, NULL );
1211 return DP_OK;
1214 static HRESULT WINAPI IDirectPlay2AImpl_CreateGroup( IDirectPlay2A *iface, DPID *lpidGroup,
1215 DPNAME *name, void *data, DWORD size, DWORD flags )
1217 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
1218 return IDirectPlayX_CreateGroup( &This->IDirectPlay4A_iface, lpidGroup, name, data, size,
1219 flags );
1222 static HRESULT WINAPI IDirectPlay2Impl_CreateGroup( IDirectPlay2 *iface, DPID *lpidGroup,
1223 DPNAME *name, void *data, DWORD size, DWORD flags )
1225 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
1226 return IDirectPlayX_CreateGroup( &This->IDirectPlay4_iface, lpidGroup, name, data, size,
1227 flags );
1230 static HRESULT WINAPI IDirectPlay3AImpl_CreateGroup( IDirectPlay3A *iface, DPID *group,
1231 DPNAME *name, void *data, DWORD size, DWORD flags )
1233 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
1234 return IDirectPlayX_CreateGroup( &This->IDirectPlay4_iface, group, name, data, size,
1235 flags );
1238 static HRESULT WINAPI IDirectPlay3Impl_CreateGroup( IDirectPlay3 *iface, DPID *lpidGroup,
1239 DPNAME *name, void *data, DWORD size, DWORD flags )
1241 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
1242 return IDirectPlayX_CreateGroup( &This->IDirectPlay4_iface, lpidGroup, name, data, size,
1243 flags );
1246 static HRESULT WINAPI IDirectPlay4AImpl_CreateGroup( IDirectPlay4A *iface, DPID *lpidGroup,
1247 DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1249 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
1251 *lpidGroup = DPID_UNKNOWN;
1253 return DP_IF_CreateGroup( This, NULL, lpidGroup, lpGroupName, lpData, dwDataSize, dwFlags,
1254 TRUE );
1257 static HRESULT WINAPI IDirectPlay4Impl_CreateGroup( IDirectPlay4 *iface, DPID *lpidGroup,
1258 DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1260 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
1262 *lpidGroup = DPID_UNKNOWN;
1264 return DP_IF_CreateGroup( This, NULL, lpidGroup, lpGroupName, lpData, dwDataSize, dwFlags,
1265 FALSE );
1269 static void
1270 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
1271 LPVOID lpData, DWORD dwDataSize )
1273 /* Clear out the data with this player */
1274 if( dwFlags & DPSET_LOCAL )
1276 if ( lpGData->dwLocalDataSize != 0 )
1278 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
1279 lpGData->lpLocalData = NULL;
1280 lpGData->dwLocalDataSize = 0;
1283 else
1285 if( lpGData->dwRemoteDataSize != 0 )
1287 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
1288 lpGData->lpRemoteData = NULL;
1289 lpGData->dwRemoteDataSize = 0;
1293 /* Reallocate for new data */
1294 if( lpData != NULL )
1296 if( dwFlags & DPSET_LOCAL )
1298 lpGData->lpLocalData = lpData;
1299 lpGData->dwLocalDataSize = dwDataSize;
1301 else
1303 lpGData->lpRemoteData = HeapAlloc( GetProcessHeap(), 0, dwDataSize );
1304 CopyMemory( lpGData->lpRemoteData, lpData, dwDataSize );
1305 lpGData->dwRemoteDataSize = dwDataSize;
1311 /* This function will just create the storage for the new player. */
1312 static lpPlayerData DP_CreatePlayer( IDirectPlayImpl *This, DPID *lpid, DPNAME *lpName,
1313 DWORD dwFlags, HANDLE hEvent, BOOL bAnsi )
1315 lpPlayerData lpPData;
1317 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
1319 /* Allocate the storage for the player and associate it with list element */
1320 lpPData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPData ) );
1321 if( lpPData == NULL )
1323 return NULL;
1326 /* Set the desired player ID */
1327 lpPData->dpid = *lpid;
1329 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
1331 lpPData->dwFlags = dwFlags;
1333 /* If we were given an event handle, duplicate it */
1334 if( hEvent != 0 )
1336 if( !DuplicateHandle( GetCurrentProcess(), hEvent,
1337 GetCurrentProcess(), &lpPData->hEvent,
1338 0, FALSE, DUPLICATE_SAME_ACCESS )
1341 /* FIXME: Memory leak */
1342 ERR( "Can't duplicate player msg handle %p\n", hEvent );
1346 /* Initialize the SP data section */
1347 lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData();
1349 TRACE( "Created player id 0x%08x\n", *lpid );
1351 if( ~dwFlags & DPLAYI_PLAYER_SYSPLAYER )
1352 This->dp2->lpSessionDesc->dwCurrentPlayers++;
1354 return lpPData;
1357 /* Delete the contents of the DPNAME struct */
1358 static void
1359 DP_DeleteDPNameStruct( LPDPNAME lpDPName )
1361 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u1.lpszShortNameA );
1362 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u2.lpszLongNameA );
1365 /* This method assumes that all links to it are already deleted */
1366 static void DP_DeletePlayer( IDirectPlayImpl *This, DPID dpid )
1368 lpPlayerList lpPList;
1370 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1372 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1374 if( lpPList == NULL )
1376 ERR( "DPID 0x%08x not found\n", dpid );
1377 return;
1380 /* Verify that this is the last reference to the data */
1381 if( --(lpPList->lpPData->uRef) )
1383 FIXME( "Why is this not the last reference to player?\n" );
1384 DebugBreak();
1387 /* Delete player */
1388 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1390 CloseHandle( lpPList->lpPData->hEvent );
1391 HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
1393 /* Delete Player List object */
1394 HeapFree( GetProcessHeap(), 0, lpPList );
1397 static lpPlayerList DP_FindPlayer( IDirectPlayImpl *This, DPID dpid )
1399 lpPlayerList lpPlayers;
1401 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1403 if(This->dp2->lpSysGroup == NULL)
1404 return NULL;
1406 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1408 return lpPlayers;
1411 /* Basic area for Dst must already be allocated */
1412 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, const DPNAME *lpSrc, BOOL bAnsi )
1414 if( lpSrc == NULL )
1416 ZeroMemory( lpDst, sizeof( *lpDst ) );
1417 lpDst->dwSize = sizeof( *lpDst );
1418 return TRUE;
1421 if( lpSrc->dwSize != sizeof( *lpSrc) )
1423 return FALSE;
1426 /* Delete any existing pointers */
1427 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1428 HeapFree( GetProcessHeap(), 0, lpDst->u2.lpszLongNameA );
1430 /* Copy as required */
1431 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1433 if( bAnsi )
1435 if( lpSrc->u1.lpszShortNameA )
1437 lpDst->u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), 0,
1438 strlen(lpSrc->u1.lpszShortNameA)+1 );
1439 strcpy( lpDst->u1.lpszShortNameA, lpSrc->u1.lpszShortNameA );
1441 if( lpSrc->u2.lpszLongNameA )
1443 lpDst->u2.lpszLongNameA = HeapAlloc( GetProcessHeap(), 0,
1444 strlen(lpSrc->u2.lpszLongNameA)+1 );
1445 strcpy( lpDst->u2.lpszLongNameA, lpSrc->u2.lpszLongNameA );
1448 else
1450 if( lpSrc->u1.lpszShortNameA )
1452 lpDst->u1.lpszShortName = HeapAlloc( GetProcessHeap(), 0,
1453 (strlenW(lpSrc->u1.lpszShortName)+1)*sizeof(WCHAR) );
1454 strcpyW( lpDst->u1.lpszShortName, lpSrc->u1.lpszShortName );
1456 if( lpSrc->u2.lpszLongNameA )
1458 lpDst->u2.lpszLongName = HeapAlloc( GetProcessHeap(), 0,
1459 (strlenW(lpSrc->u2.lpszLongName)+1)*sizeof(WCHAR) );
1460 strcpyW( lpDst->u2.lpszLongName, lpSrc->u2.lpszLongName );
1464 return TRUE;
1467 static void
1468 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
1469 LPVOID lpData, DWORD dwDataSize )
1471 /* Clear out the data with this player */
1472 if( dwFlags & DPSET_LOCAL )
1474 if ( lpPData->dwLocalDataSize != 0 )
1476 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
1477 lpPData->lpLocalData = NULL;
1478 lpPData->dwLocalDataSize = 0;
1481 else
1483 if( lpPData->dwRemoteDataSize != 0 )
1485 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
1486 lpPData->lpRemoteData = NULL;
1487 lpPData->dwRemoteDataSize = 0;
1491 /* Reallocate for new data */
1492 if( lpData != NULL )
1495 if( dwFlags & DPSET_LOCAL )
1497 lpPData->lpLocalData = lpData;
1498 lpPData->dwLocalDataSize = dwDataSize;
1500 else
1502 lpPData->lpRemoteData = HeapAlloc( GetProcessHeap(), 0, dwDataSize );
1503 CopyMemory( lpPData->lpRemoteData, lpData, dwDataSize );
1504 lpPData->dwRemoteDataSize = dwDataSize;
1510 /* Note: lpMsgHdr is NULL for local creation, non NULL for remote creation */
1511 static HRESULT DP_IF_CreatePlayer( IDirectPlayImpl *This, void *lpMsgHdr, DPID *lpidPlayer,
1512 DPNAME *lpPlayerName, HANDLE hEvent, void *lpData, DWORD dwDataSize, DWORD dwFlags,
1513 BOOL bAnsi )
1515 HRESULT hr = DP_OK;
1516 lpPlayerData lpPData;
1517 lpPlayerList lpPList;
1518 DWORD dwCreateFlags = 0;
1520 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1521 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1522 dwDataSize, dwFlags, bAnsi );
1523 if( This->dp2->connectionInitialized == NO_PROVIDER )
1525 return DPERR_UNINITIALIZED;
1528 if( dwFlags == 0 )
1530 dwFlags = DPPLAYER_SPECTATOR;
1533 if( lpidPlayer == NULL )
1535 return DPERR_INVALIDPARAMS;
1539 /* Determine the creation flags for the player. These will be passed
1540 * to the name server if requesting a player id and to the SP when
1541 * informing it of the player creation
1544 if( dwFlags & DPPLAYER_SERVERPLAYER )
1546 if( *lpidPlayer == DPID_SERVERPLAYER )
1548 /* Server player for the host interface */
1549 dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
1551 else if( *lpidPlayer == DPID_NAME_SERVER )
1553 /* Name server - master of everything */
1554 dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
1556 else
1558 /* Server player for a non host interface */
1559 dwCreateFlags |= DPLAYI_PLAYER_SYSPLAYER;
1563 if( lpMsgHdr == NULL )
1564 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1567 /* Verify we know how to handle all the flags */
1568 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1569 ( dwFlags & DPPLAYER_SPECTATOR )
1573 /* Assume non fatal failure */
1574 ERR( "unknown dwFlags = 0x%08x\n", dwFlags );
1577 /* If the name is not specified, we must provide one */
1578 if( *lpidPlayer == DPID_UNKNOWN )
1580 /* If we are the session master, we dish out the group/player ids */
1581 if( This->dp2->bHostInterface )
1583 *lpidPlayer = DP_NextObjectId();
1585 else
1587 hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer );
1589 if( FAILED(hr) )
1591 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1592 return hr;
1596 else
1598 /* FIXME: Would be nice to perhaps verify that we don't already have
1599 * this player.
1603 /* We pass creation flags, so we can distinguish sysplayers and not count them in the current
1604 player total */
1605 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwCreateFlags,
1606 hEvent, bAnsi );
1608 if( lpPData == NULL )
1610 return DPERR_CANTADDPLAYER;
1613 /* Create the list object and link it in */
1614 lpPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPList ) );
1615 if( lpPList == NULL )
1617 FIXME( "Memory leak\n" );
1618 return DPERR_CANTADDPLAYER;
1621 lpPData->uRef = 1;
1622 lpPList->lpPData = lpPData;
1624 /* Add the player to the system group */
1625 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1627 /* Update the information and send it to all players in the session */
1628 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
1630 /* Let the SP know that we've created this player */
1631 if( This->dp2->spData.lpCB->CreatePlayer )
1633 DPSP_CREATEPLAYERDATA data;
1635 data.idPlayer = *lpidPlayer;
1636 data.dwFlags = dwCreateFlags;
1637 data.lpSPMessageHeader = lpMsgHdr;
1638 data.lpISP = This->dp2->spData.lpISP;
1640 TRACE( "Calling SP CreatePlayer 0x%08x: dwFlags: 0x%08x lpMsgHdr: %p\n",
1641 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
1643 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1646 if( FAILED(hr) )
1648 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1649 return hr;
1652 /* Now let the SP know that this player is a member of the system group */
1653 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1655 DPSP_ADDPLAYERTOGROUPDATA data;
1657 data.idPlayer = *lpidPlayer;
1658 data.idGroup = DPID_SYSTEM_GROUP;
1659 data.lpISP = This->dp2->spData.lpISP;
1661 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1663 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1666 if( FAILED(hr) )
1668 ERR( "Failed to add player to sys group with sp: %s\n",
1669 DPLAYX_HresultToString(hr) );
1670 return hr;
1673 #if 1
1674 if( This->dp2->bHostInterface == FALSE )
1676 /* Let the name server know about the creation of this player */
1677 /* FIXME: Is this only to be done for the creation of a server player or
1678 * is this used for regular players? If only for server players, move
1679 * this call to DP_SecureOpen(...);
1681 #if 0
1682 TRACE( "Sending message to self to get my addr\n" );
1683 DP_MSG_ToSelf( This, *lpidPlayer ); /* This is a hack right now */
1684 #endif
1686 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
1688 #else
1689 /* Inform all other peers of the creation of a new player. If there are
1690 * no peers keep this quiet.
1691 * Also, if this was a remote event, no need to rebroadcast it.
1693 if( ( lpMsgHdr == NULL ) &&
1694 This->dp2->lpSessionDesc &&
1695 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1697 DPMSG_CREATEPLAYERORGROUP msg;
1698 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1700 msg.dwPlayerType = DPPLAYERTYPE_PLAYER;
1701 msg.dpId = *lpidPlayer;
1702 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */
1703 msg.lpData = lpData;
1704 msg.dwDataSize = dwDataSize;
1705 msg.dpnName = *lpPlayerName;
1706 msg.dpIdParent = DPID_NOPARENT_GROUP;
1707 msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
1709 /* FIXME: Correct to just use send effectively? */
1710 /* FIXME: Should size include data w/ message or just message "header" */
1711 /* FIXME: Check return code */
1712 hr = IDirectPlayX_SendEx( &This->IDirectPlay4_iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0,
1713 &msg, sizeof( msg ), 0, 0, NULL, NULL );
1715 #endif
1717 return hr;
1720 static HRESULT WINAPI IDirectPlay2AImpl_CreatePlayer( IDirectPlay2A *iface, DPID *lpidPlayer,
1721 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags )
1723 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
1724 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4A_iface, lpidPlayer, name, event, data,
1725 size, flags );
1728 static HRESULT WINAPI IDirectPlay2Impl_CreatePlayer( IDirectPlay2 *iface, DPID *lpidPlayer,
1729 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags )
1731 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
1732 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4_iface, lpidPlayer, name, event, data,
1733 size, flags );
1736 static HRESULT WINAPI IDirectPlay3AImpl_CreatePlayer( IDirectPlay3A *iface, DPID *lpidPlayer,
1737 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags )
1739 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
1740 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4_iface, lpidPlayer, name, event, data,
1741 size, flags );
1744 static HRESULT WINAPI IDirectPlay3Impl_CreatePlayer( IDirectPlay3 *iface, DPID *lpidPlayer,
1745 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags )
1747 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
1748 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4_iface, lpidPlayer, name, event, data,
1749 size, flags );
1752 static HRESULT WINAPI IDirectPlay4AImpl_CreatePlayer( IDirectPlay4A *iface, DPID *lpidPlayer,
1753 DPNAME *lpPlayerName, HANDLE hEvent, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1755 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
1757 if( lpidPlayer == NULL )
1759 return DPERR_INVALIDPARAMS;
1762 if( dwFlags & DPPLAYER_SERVERPLAYER )
1764 *lpidPlayer = DPID_SERVERPLAYER;
1766 else
1768 *lpidPlayer = DPID_UNKNOWN;
1771 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1772 lpData, dwDataSize, dwFlags, TRUE );
1775 static HRESULT WINAPI IDirectPlay4Impl_CreatePlayer( IDirectPlay4 *iface, DPID *lpidPlayer,
1776 DPNAME *lpPlayerName, HANDLE hEvent, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1778 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
1780 if( lpidPlayer == NULL )
1782 return DPERR_INVALIDPARAMS;
1785 if( dwFlags & DPPLAYER_SERVERPLAYER )
1787 *lpidPlayer = DPID_SERVERPLAYER;
1789 else
1791 *lpidPlayer = DPID_UNKNOWN;
1794 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1795 lpData, dwDataSize, dwFlags, FALSE );
1798 static DPID DP_GetRemoteNextObjectId(void)
1800 FIXME( ":stub\n" );
1802 /* Hack solution */
1803 return DP_NextObjectId();
1806 static HRESULT WINAPI IDirectPlay2AImpl_DeletePlayerFromGroup( IDirectPlay2A *iface, DPID group,
1807 DPID player )
1809 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
1810 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4A_iface, group, player );
1813 static HRESULT WINAPI IDirectPlay2Impl_DeletePlayerFromGroup( IDirectPlay2 *iface, DPID group,
1814 DPID player )
1816 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
1817 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1820 static HRESULT WINAPI IDirectPlay3AImpl_DeletePlayerFromGroup( IDirectPlay3A *iface, DPID group,
1821 DPID player )
1823 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
1824 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1827 static HRESULT WINAPI IDirectPlay3Impl_DeletePlayerFromGroup( IDirectPlay3 *iface, DPID group,
1828 DPID player )
1830 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
1831 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1834 static HRESULT WINAPI IDirectPlay4AImpl_DeletePlayerFromGroup( IDirectPlay4A *iface, DPID group,
1835 DPID player )
1837 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
1838 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1841 static HRESULT WINAPI IDirectPlay4Impl_DeletePlayerFromGroup( IDirectPlay4 *iface, DPID group,
1842 DPID player )
1844 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
1845 HRESULT hr = DP_OK;
1847 lpGroupData gdata;
1848 lpPlayerList plist;
1850 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, group, player );
1852 /* Find the group */
1853 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
1854 return DPERR_INVALIDGROUP;
1856 /* Find the player */
1857 if ( DP_FindPlayer( This, player ) == NULL )
1858 return DPERR_INVALIDPLAYER;
1860 /* Remove the player shortcut from the group */
1861 DPQ_REMOVE_ENTRY( gdata->players, players, lpPData->dpid, ==, player, plist );
1863 if ( !plist )
1864 return DPERR_INVALIDPLAYER;
1866 /* One less reference */
1867 plist->lpPData->uRef--;
1869 /* Delete the Player List element */
1870 HeapFree( GetProcessHeap(), 0, plist );
1872 /* Inform the SP if they care */
1873 if ( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1875 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1877 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1878 data.idPlayer = player;
1879 data.idGroup = group;
1880 data.lpISP = This->dp2->spData.lpISP;
1881 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1884 /* Need to send a DELETEPLAYERFROMGROUP message */
1885 FIXME( "Need to send a message\n" );
1887 return hr;
1890 typedef struct _DPRGOPContext
1892 IDirectPlayImpl *This;
1893 BOOL bAnsi;
1894 DPID idGroup;
1895 } DPRGOPContext, *lpDPRGOPContext;
1897 static BOOL CALLBACK
1898 cbRemoveGroupOrPlayer(
1899 DPID dpId,
1900 DWORD dwPlayerType,
1901 LPCDPNAME lpName,
1902 DWORD dwFlags,
1903 LPVOID lpContext )
1905 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1907 TRACE( "Removing element:0x%08x (type:0x%08x) from element:0x%08x\n",
1908 dpId, dwPlayerType, lpCtxt->idGroup );
1910 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1912 if ( FAILED( IDirectPlayX_DeleteGroupFromGroup( &lpCtxt->This->IDirectPlay4_iface,
1913 lpCtxt->idGroup, dpId ) ) )
1914 ERR( "Unable to delete group 0x%08x from group 0x%08x\n", dpId, lpCtxt->idGroup );
1916 else if ( FAILED( IDirectPlayX_DeletePlayerFromGroup( &lpCtxt->This->IDirectPlay4_iface,
1917 lpCtxt->idGroup, dpId ) ) )
1918 ERR( "Unable to delete player 0x%08x from grp 0x%08x\n", dpId, lpCtxt->idGroup );
1920 return TRUE; /* Continue enumeration */
1923 static HRESULT DP_IF_DestroyGroup( IDirectPlayImpl *This, void *lpMsgHdr, DPID idGroup, BOOL bAnsi )
1925 lpGroupData lpGData;
1926 DPRGOPContext context;
1928 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1929 This, lpMsgHdr, idGroup, bAnsi );
1931 /* Find the group */
1932 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1934 return DPERR_INVALIDPLAYER; /* yes player */
1937 context.This = This;
1938 context.bAnsi = bAnsi;
1939 context.idGroup = idGroup;
1941 /* Remove all players that this group has */
1942 IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, idGroup, NULL, cbRemoveGroupOrPlayer,
1943 &context, 0 );
1945 /* Remove all links to groups that this group has since this is dp3 */
1946 IDirectPlayX_EnumGroupsInGroup( &This->IDirectPlay4_iface, idGroup, NULL, cbRemoveGroupOrPlayer,
1947 (void*)&context, 0 );
1949 /* Remove this group from the parent group - if it has one */
1950 if( ( idGroup != DPID_SYSTEM_GROUP ) && ( lpGData->parent != DPID_SYSTEM_GROUP ) )
1951 IDirectPlayX_DeleteGroupFromGroup( &This->IDirectPlay4_iface, lpGData->parent, idGroup );
1953 /* Now delete this group data and list from the system group */
1954 DP_DeleteGroup( This, idGroup );
1956 /* Let the SP know that we've destroyed this group */
1957 if( This->dp2->spData.lpCB->DeleteGroup )
1959 DPSP_DELETEGROUPDATA data;
1961 FIXME( "data.dwFlags is incorrect\n" );
1963 data.idGroup = idGroup;
1964 data.dwFlags = 0;
1965 data.lpISP = This->dp2->spData.lpISP;
1967 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1970 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1972 return DP_OK;
1975 static HRESULT WINAPI IDirectPlay2AImpl_DestroyGroup( IDirectPlay2A *iface, DPID group )
1977 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
1978 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4A_iface, group );
1981 static HRESULT WINAPI IDirectPlay2Impl_DestroyGroup( IDirectPlay2 *iface, DPID group )
1983 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
1984 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4_iface, group );
1987 static HRESULT WINAPI IDirectPlay3AImpl_DestroyGroup( IDirectPlay3A *iface, DPID group )
1989 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
1990 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4_iface, group );
1993 static HRESULT WINAPI IDirectPlay3Impl_DestroyGroup( IDirectPlay3 *iface, DPID group )
1995 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
1996 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4_iface, group );
1999 static HRESULT WINAPI IDirectPlay4AImpl_DestroyGroup( IDirectPlay4A *iface, DPID idGroup )
2001 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2002 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
2005 static HRESULT WINAPI IDirectPlay4Impl_DestroyGroup( IDirectPlay4 *iface, DPID idGroup )
2007 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2008 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
2011 typedef struct _DPFAGContext
2013 IDirectPlayImpl *This;
2014 DPID idPlayer;
2015 BOOL bAnsi;
2016 } DPFAGContext, *lpDPFAGContext;
2018 static HRESULT DP_IF_DestroyPlayer( IDirectPlayImpl *This, void *lpMsgHdr, DPID idPlayer,
2019 BOOL bAnsi )
2021 DPFAGContext cbContext;
2023 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
2024 This, lpMsgHdr, idPlayer, bAnsi );
2026 if( This->dp2->connectionInitialized == NO_PROVIDER )
2028 return DPERR_UNINITIALIZED;
2031 if( DP_FindPlayer( This, idPlayer ) == NULL )
2033 return DPERR_INVALIDPLAYER;
2036 /* FIXME: If the player is remote, we must be the host to delete this */
2038 cbContext.This = This;
2039 cbContext.idPlayer = idPlayer;
2040 cbContext.bAnsi = bAnsi;
2042 /* Find each group and call DeletePlayerFromGroup if the player is a
2043 member of the group */
2044 IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, NULL, cbDeletePlayerFromAllGroups, &cbContext,
2045 DPENUMGROUPS_ALL );
2047 /* Now delete player and player list from the sys group */
2048 DP_DeletePlayer( This, idPlayer );
2050 /* Let the SP know that we've destroyed this group */
2051 if( This->dp2->spData.lpCB->DeletePlayer )
2053 DPSP_DELETEPLAYERDATA data;
2055 FIXME( "data.dwFlags is incorrect\n" );
2057 data.idPlayer = idPlayer;
2058 data.dwFlags = 0;
2059 data.lpISP = This->dp2->spData.lpISP;
2061 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
2064 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
2066 return DP_OK;
2069 static BOOL CALLBACK
2070 cbDeletePlayerFromAllGroups(
2071 DPID dpId,
2072 DWORD dwPlayerType,
2073 LPCDPNAME lpName,
2074 DWORD dwFlags,
2075 LPVOID lpContext )
2077 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
2079 if( dwPlayerType == DPPLAYERTYPE_GROUP )
2081 IDirectPlayX_DeletePlayerFromGroup( &lpCtxt->This->IDirectPlay4_iface, dpId, lpCtxt->idPlayer );
2083 /* Enumerate all groups in this group since this will normally only
2084 * be called for top level groups
2086 IDirectPlayX_EnumGroupsInGroup( &lpCtxt->This->IDirectPlay4_iface, dpId, NULL,
2087 cbDeletePlayerFromAllGroups, lpContext, DPENUMGROUPS_ALL);
2090 else
2092 ERR( "Group callback has dwPlayerType = 0x%08x\n", dwPlayerType );
2095 return TRUE;
2098 static HRESULT WINAPI IDirectPlay2AImpl_DestroyPlayer( IDirectPlay2A *iface, DPID player )
2100 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2101 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4A_iface, player );
2104 static HRESULT WINAPI IDirectPlay2Impl_DestroyPlayer( IDirectPlay2 *iface, DPID player )
2106 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2107 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4_iface, player );
2110 static HRESULT WINAPI IDirectPlay3AImpl_DestroyPlayer( IDirectPlay3A *iface, DPID player )
2112 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2113 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4_iface, player );
2116 static HRESULT WINAPI IDirectPlay3Impl_DestroyPlayer( IDirectPlay3 *iface, DPID player )
2118 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2119 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4_iface, player );
2122 static HRESULT WINAPI IDirectPlay4AImpl_DestroyPlayer( IDirectPlay4A *iface, DPID idPlayer )
2124 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2125 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
2128 static HRESULT WINAPI IDirectPlay4Impl_DestroyPlayer( IDirectPlay4 *iface, DPID idPlayer )
2130 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2131 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
2134 static HRESULT WINAPI IDirectPlay2AImpl_EnumGroupPlayers( IDirectPlay2A *iface, DPID group,
2135 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2137 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2138 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4A_iface, group, instance,
2139 enumplayercb, context, flags );
2142 static HRESULT WINAPI IDirectPlay2Impl_EnumGroupPlayers( IDirectPlay2 *iface, DPID group,
2143 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2145 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2146 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance,
2147 enumplayercb, context, flags );
2150 static HRESULT WINAPI IDirectPlay3AImpl_EnumGroupPlayers( IDirectPlay3A *iface, DPID group,
2151 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2153 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2154 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance,
2155 enumplayercb, context, flags );
2158 static HRESULT WINAPI IDirectPlay3Impl_EnumGroupPlayers( IDirectPlay3 *iface, DPID group,
2159 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2161 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2162 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance,
2163 enumplayercb, context, flags );
2166 static HRESULT WINAPI IDirectPlay4AImpl_EnumGroupPlayers( IDirectPlay4A *iface, DPID group,
2167 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2169 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2170 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance, enumplayercb,
2171 context, flags );
2174 static HRESULT WINAPI IDirectPlay4Impl_EnumGroupPlayers( IDirectPlay4 *iface, DPID group,
2175 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2177 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2178 lpGroupData gdata;
2179 lpPlayerList plist;
2181 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x): semi stub\n", This, group, instance, enumplayercb,
2182 context, flags );
2184 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2185 return DPERR_UNINITIALIZED;
2187 /* Find the group */
2188 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
2189 return DPERR_INVALIDGROUP;
2191 if ( DPQ_IS_EMPTY( gdata->players ) )
2192 return DP_OK;
2194 /* Walk the players in this group */
2195 for( plist = DPQ_FIRST( gdata->players ); ; plist = DPQ_NEXT( plist->players ) )
2197 /* We do not enum the name server or app server as they are of no
2198 * consequence to the end user.
2200 if ( ( plist->lpPData->dpid != DPID_NAME_SERVER ) &&
2201 ( plist->lpPData->dpid != DPID_SERVERPLAYER ) )
2203 /* FIXME: Need to add stuff for flags checking */
2204 if ( !enumplayercb( plist->lpPData->dpid, DPPLAYERTYPE_PLAYER,
2205 &plist->lpPData->name, plist->lpPData->dwFlags, context ) )
2206 /* User requested break */
2207 return DP_OK;
2210 if ( DPQ_IS_ENDOFLIST( plist->players ) )
2211 break;
2213 return DP_OK;
2216 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2217 static HRESULT WINAPI IDirectPlay2AImpl_EnumGroups( IDirectPlay2A *iface, GUID *instance,
2218 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2220 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2221 return IDirectPlayX_EnumGroups( &This->IDirectPlay4A_iface, instance, enumplayercb, context,
2222 flags );
2225 static HRESULT WINAPI IDirectPlay2Impl_EnumGroups( IDirectPlay2 *iface, GUID *instance,
2226 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2228 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2229 return IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2230 flags );
2233 static HRESULT WINAPI IDirectPlay3AImpl_EnumGroups( IDirectPlay3A *iface, GUID *instance,
2234 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2236 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2237 return IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2238 flags );
2241 static HRESULT WINAPI IDirectPlay3Impl_EnumGroups( IDirectPlay3 *iface, GUID *instance,
2242 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2244 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2245 return IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2246 flags );
2249 static HRESULT WINAPI IDirectPlay4AImpl_EnumGroups( IDirectPlay4A *iface, GUID *instance,
2250 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2252 return IDirectPlayX_EnumGroupsInGroup( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2253 context, flags );
2256 static HRESULT WINAPI IDirectPlay4Impl_EnumGroups ( IDirectPlay4 *iface, GUID *instance,
2257 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2259 return IDirectPlayX_EnumGroupsInGroup( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2260 context, flags );
2263 static HRESULT WINAPI IDirectPlay2AImpl_EnumPlayers( IDirectPlay2A *iface, GUID *instance,
2264 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2266 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2267 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4A_iface, instance, enumplayercb, context,
2268 flags );
2271 static HRESULT WINAPI IDirectPlay2Impl_EnumPlayers( IDirectPlay2 *iface, GUID *instance,
2272 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2274 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2275 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2276 flags );
2279 static HRESULT WINAPI IDirectPlay3AImpl_EnumPlayers( IDirectPlay3A *iface, GUID *instance,
2280 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2282 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2283 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2284 flags );
2287 static HRESULT WINAPI IDirectPlay3Impl_EnumPlayers( IDirectPlay3 *iface, GUID *instance,
2288 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2290 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2291 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2292 flags );
2295 static HRESULT WINAPI IDirectPlay4AImpl_EnumPlayers( IDirectPlay4A *iface, GUID *instance,
2296 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2298 return IDirectPlayX_EnumGroupPlayers( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2299 context, flags );
2302 static HRESULT WINAPI IDirectPlay4Impl_EnumPlayers( IDirectPlay4 *iface, GUID *instance,
2303 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2305 return IDirectPlayX_EnumGroupPlayers( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2306 context, flags );
2309 /* This function should call the registered callback function that the user
2310 passed into EnumSessions for each entry available.
2312 static void DP_InvokeEnumSessionCallbacks
2313 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2314 LPVOID lpNSInfo,
2315 DWORD dwTimeout,
2316 LPVOID lpContext )
2318 LPDPSESSIONDESC2 lpSessionDesc;
2320 FIXME( ": not checking for conditions\n" );
2322 /* Not sure if this should be pruning but it's convenient */
2323 NS_PruneSessionCache( lpNSInfo );
2325 NS_ResetSessionEnumeration( lpNSInfo );
2327 /* Enumerate all sessions */
2328 /* FIXME: Need to indicate ANSI */
2329 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2331 TRACE( "EnumSessionsCallback2 invoked\n" );
2332 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2334 return;
2338 /* Invoke one last time to indicate that there is no more to come */
2339 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2342 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2344 EnumSessionAsyncCallbackData* data = lpContext;
2345 HANDLE hSuicideRequest = data->hSuicideRequest;
2346 DWORD dwTimeout = data->dwTimeout;
2348 TRACE( "Thread started with timeout = 0x%08x\n", dwTimeout );
2350 for( ;; )
2352 HRESULT hr;
2354 /* Sleep up to dwTimeout waiting for request to terminate thread */
2355 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2357 TRACE( "Thread terminating on terminate request\n" );
2358 break;
2361 /* Now resend the enum request */
2362 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2363 data->dwEnumSessionFlags,
2364 data->lpSpData );
2366 if( FAILED(hr) )
2368 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2369 /* FIXME: Should we kill this thread? How to inform the main thread? */
2374 TRACE( "Thread terminating\n" );
2376 /* Clean up the thread data */
2377 CloseHandle( hSuicideRequest );
2378 HeapFree( GetProcessHeap(), 0, lpContext );
2380 /* FIXME: Need to have some notification to main app thread that this is
2381 * dead. It would serve two purposes. 1) allow sync on termination
2382 * so that we don't actually send something to ourselves when we
2383 * become name server (race condition) and 2) so that if we die
2384 * abnormally something else will be able to tell.
2387 return 1;
2390 static void DP_KillEnumSessionThread( IDirectPlayImpl *This )
2392 /* Does a thread exist? If so we were doing an async enum session */
2393 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2395 TRACE( "Killing EnumSession thread %p\n",
2396 This->dp2->hEnumSessionThread );
2398 /* Request that the thread kill itself nicely */
2399 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2400 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2402 /* We no longer need to know about the thread */
2403 CloseHandle( This->dp2->hEnumSessionThread );
2405 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2409 static HRESULT WINAPI IDirectPlay2AImpl_EnumSessions( IDirectPlay2A *iface, DPSESSIONDESC2 *sdesc,
2410 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2412 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2413 return IDirectPlayX_EnumSessions( &This->IDirectPlay4A_iface, sdesc, timeout, enumsessioncb,
2414 context, flags );
2417 static HRESULT WINAPI IDirectPlay2Impl_EnumSessions( IDirectPlay2 *iface, DPSESSIONDESC2 *sdesc,
2418 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2420 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2421 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2422 context, flags );
2425 static HRESULT WINAPI IDirectPlay3AImpl_EnumSessions( IDirectPlay3A *iface, DPSESSIONDESC2 *sdesc,
2426 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2428 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2429 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2430 context, flags );
2433 static HRESULT WINAPI IDirectPlay3Impl_EnumSessions( IDirectPlay3 *iface, DPSESSIONDESC2 *sdesc,
2434 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2436 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2437 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2438 context, flags );
2441 static HRESULT WINAPI IDirectPlay4AImpl_EnumSessions( IDirectPlay4A *iface, DPSESSIONDESC2 *sdesc,
2442 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2444 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2445 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2446 context, flags );
2449 static HRESULT WINAPI IDirectPlay4Impl_EnumSessions( IDirectPlay4 *iface, DPSESSIONDESC2 *sdesc,
2450 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2452 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2453 void *connection;
2454 DWORD size;
2455 HRESULT hr = DP_OK;
2457 TRACE( "(%p)->(%p,0x%08x,%p,%p,0x%08x)\n", This, sdesc, timeout, enumsessioncb,
2458 context, flags );
2460 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2461 return DPERR_UNINITIALIZED;
2463 /* Can't enumerate if the interface is already open */
2464 if ( This->dp2->bConnectionOpen )
2465 return DPERR_GENERIC;
2467 /* The loading of a lobby provider _seems_ to require a backdoor loading
2468 * of the service provider to also associate with this DP object. This is
2469 * because the app doesn't seem to have to call EnumConnections and
2470 * InitializeConnection for the SP before calling this method. As such
2471 * we'll do their dirty work for them with a quick hack so as to always
2472 * load the TCP/IP service provider.
2474 * The correct solution would seem to involve creating a dialog box which
2475 * contains the possible SPs. These dialog boxes most likely follow SDK
2476 * examples.
2478 if ( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
2480 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2482 if ( !DP_BuildSPCompoundAddr( (GUID*)&DPSPGUID_TCPIP, &connection, &size ) )
2484 ERR( "Can't build compound addr\n" );
2485 return DPERR_GENERIC;
2488 hr = IDirectPlayX_InitializeConnection( &This->IDirectPlay4_iface, connection, 0 );
2489 if ( FAILED(hr) )
2490 return hr;
2492 HeapFree( GetProcessHeap(), 0, connection );
2493 This->dp2->bSPInitialized = TRUE;
2497 /* Use the service provider default? */
2498 if ( !timeout )
2500 DPCAPS caps;
2501 caps.dwSize = sizeof( caps );
2503 IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, &caps, 0 );
2504 timeout = caps.dwTimeout;
2505 if ( !timeout )
2506 timeout = DPMSG_WAIT_5_SECS; /* Provide the TCP/IP default */
2509 if ( flags & DPENUMSESSIONS_STOPASYNC )
2511 DP_KillEnumSessionThread( This );
2512 return hr;
2515 if ( flags & DPENUMSESSIONS_ASYNC )
2517 /* Enumerate everything presently in the local session cache */
2518 DP_InvokeEnumSessionCallbacks( enumsessioncb, This->dp2->lpNameServerData, timeout,
2519 context );
2521 if ( This->dp2->dwEnumSessionLock )
2522 return DPERR_CONNECTING;
2524 /* See if we've already created a thread to service this interface */
2525 if ( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2527 DWORD tid;
2528 This->dp2->dwEnumSessionLock++;
2530 /* Send the first enum request inline since the user may cancel a dialog
2531 * if one is presented. Also, may also have a connecting return code.
2533 hr = NS_SendSessionRequestBroadcast( &sdesc->guidApplication, flags,
2534 &This->dp2->spData );
2536 if ( SUCCEEDED(hr) )
2538 EnumSessionAsyncCallbackData* data = HeapAlloc( GetProcessHeap(),
2539 HEAP_ZERO_MEMORY, sizeof( *data ) );
2540 /* FIXME: need to kill the thread on object deletion */
2541 data->lpSpData = &This->dp2->spData;
2542 data->requestGuid = sdesc->guidApplication;
2543 data->dwEnumSessionFlags = flags;
2544 data->dwTimeout = timeout;
2546 This->dp2->hKillEnumSessionThreadEvent = CreateEventW( NULL, TRUE, FALSE, NULL );
2547 if ( !DuplicateHandle( GetCurrentProcess(), This->dp2->hKillEnumSessionThreadEvent,
2548 GetCurrentProcess(), &data->hSuicideRequest, 0, FALSE,
2549 DUPLICATE_SAME_ACCESS ) )
2550 ERR( "Can't duplicate thread killing handle\n" );
2552 TRACE( ": creating EnumSessionsRequest thread\n" );
2553 This->dp2->hEnumSessionThread = CreateThread( NULL, 0,
2554 DP_EnumSessionsSendAsyncRequestThread, data, 0, &tid );
2556 This->dp2->dwEnumSessionLock--;
2559 else
2561 /* Invalidate the session cache for the interface */
2562 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2563 /* Send the broadcast for session enumeration */
2564 hr = NS_SendSessionRequestBroadcast( &sdesc->guidApplication, flags, &This->dp2->spData );
2565 SleepEx( timeout, FALSE );
2566 DP_InvokeEnumSessionCallbacks( enumsessioncb, This->dp2->lpNameServerData, timeout,
2567 context );
2570 return hr;
2573 static HRESULT WINAPI IDirectPlay2AImpl_GetCaps( IDirectPlay2A *iface, DPCAPS *caps, DWORD flags )
2575 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2576 return IDirectPlayX_GetCaps( &This->IDirectPlay4A_iface, caps, flags );
2579 static HRESULT WINAPI IDirectPlay2Impl_GetCaps( IDirectPlay2 *iface, DPCAPS *caps, DWORD flags )
2581 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2582 return IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, caps, flags );
2585 static HRESULT WINAPI IDirectPlay3AImpl_GetCaps( IDirectPlay3A *iface, DPCAPS *caps, DWORD flags )
2587 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2588 return IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, caps, flags );
2591 static HRESULT WINAPI IDirectPlay3Impl_GetCaps( IDirectPlay3 *iface, DPCAPS *caps, DWORD flags )
2593 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2594 return IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, caps, flags );
2597 static HRESULT WINAPI IDirectPlay4AImpl_GetCaps( IDirectPlay4A *iface, DPCAPS *caps, DWORD flags )
2599 return IDirectPlayX_GetPlayerCaps( iface, DPID_ALLPLAYERS, caps, flags );
2602 static HRESULT WINAPI IDirectPlay4Impl_GetCaps( IDirectPlay4 *iface, DPCAPS *caps, DWORD flags )
2604 return IDirectPlayX_GetPlayerCaps( iface, DPID_ALLPLAYERS, caps, flags );
2607 static HRESULT WINAPI IDirectPlay2AImpl_GetGroupData( IDirectPlay2A *iface, DPID group, void *data,
2608 DWORD *size, DWORD flags )
2610 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2611 return IDirectPlayX_GetGroupData( &This->IDirectPlay4A_iface, group, data, size, flags );
2614 static HRESULT WINAPI IDirectPlay2Impl_GetGroupData( IDirectPlay2 *iface, DPID group, void *data,
2615 DWORD *size, DWORD flags )
2617 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2618 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2621 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupData( IDirectPlay3A *iface, DPID group, void *data,
2622 DWORD *size, DWORD flags )
2624 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2625 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2628 static HRESULT WINAPI IDirectPlay3Impl_GetGroupData( IDirectPlay3 *iface, DPID group, void *data,
2629 DWORD *size, DWORD flags )
2631 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2632 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2635 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupData( IDirectPlay4A *iface, DPID group,
2636 void *data, DWORD *size, DWORD flags )
2638 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2639 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2642 static HRESULT WINAPI IDirectPlay4Impl_GetGroupData( IDirectPlay4 *iface, DPID group,
2643 void *data, DWORD *size, DWORD flags )
2645 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2646 lpGroupData gdata;
2647 DWORD bufsize;
2648 void *src;
2650 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x)\n", This, group, data, size, flags );
2652 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
2653 return DPERR_INVALIDGROUP;
2655 /* How much buffer is required? */
2656 if ( flags & DPSET_LOCAL )
2658 bufsize = gdata->dwLocalDataSize;
2659 src = gdata->lpLocalData;
2661 else
2663 bufsize = gdata->dwRemoteDataSize;
2664 src = gdata->lpRemoteData;
2667 /* Is the user requesting to know how big a buffer is required? */
2668 if ( !data || *size < bufsize )
2670 *size = bufsize;
2671 return DPERR_BUFFERTOOSMALL;
2674 CopyMemory( data, src, bufsize );
2676 return DP_OK;
2679 static HRESULT DP_IF_GetGroupName( IDirectPlayImpl *This, DPID idGroup, void *lpData,
2680 DWORD *lpdwDataSize, BOOL bAnsi )
2682 lpGroupData lpGData;
2683 LPDPNAME lpName = lpData;
2684 DWORD dwRequiredDataSize;
2686 FIXME("(%p)->(0x%08x,%p,%p,%u) ANSI ignored\n",
2687 This, idGroup, lpData, lpdwDataSize, bAnsi );
2689 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2691 return DPERR_INVALIDGROUP;
2694 dwRequiredDataSize = lpGData->name.dwSize;
2696 if( lpGData->name.u1.lpszShortNameA )
2698 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
2701 if( lpGData->name.u2.lpszLongNameA )
2703 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
2706 if( ( lpData == NULL ) ||
2707 ( *lpdwDataSize < dwRequiredDataSize )
2710 *lpdwDataSize = dwRequiredDataSize;
2711 return DPERR_BUFFERTOOSMALL;
2714 /* Copy the structure */
2715 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2717 if( lpGData->name.u1.lpszShortNameA )
2719 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2720 lpGData->name.u1.lpszShortNameA );
2722 else
2724 lpName->u1.lpszShortNameA = NULL;
2727 if( lpGData->name.u1.lpszShortNameA )
2729 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2730 lpGData->name.u2.lpszLongNameA );
2732 else
2734 lpName->u2.lpszLongNameA = NULL;
2737 return DP_OK;
2740 static HRESULT WINAPI IDirectPlay2AImpl_GetGroupName( IDirectPlay2A *iface, DPID group, void *data,
2741 DWORD *size )
2743 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2744 return IDirectPlayX_GetGroupName( &This->IDirectPlay4A_iface, group, data, size );
2747 static HRESULT WINAPI IDirectPlay2Impl_GetGroupName( IDirectPlay2 *iface, DPID group, void *data,
2748 DWORD *size )
2750 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2751 return IDirectPlayX_GetGroupName( &This->IDirectPlay4_iface, group, data, size );
2754 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupName( IDirectPlay3A *iface, DPID group, void *data,
2755 DWORD *size )
2757 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2758 return IDirectPlayX_GetGroupName( &This->IDirectPlay4_iface, group, data, size );
2761 static HRESULT WINAPI IDirectPlay3Impl_GetGroupName( IDirectPlay3 *iface, DPID group, void *data,
2762 DWORD *size )
2764 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2765 return IDirectPlayX_GetGroupName( &This->IDirectPlay4_iface, group, data, size );
2768 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupName( IDirectPlay4A *iface, DPID idGroup,
2769 void *lpData, DWORD *lpdwDataSize )
2771 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2772 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2775 static HRESULT WINAPI IDirectPlay4Impl_GetGroupName( IDirectPlay4 *iface, DPID idGroup,
2776 void *lpData, DWORD *lpdwDataSize )
2778 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2779 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2782 static HRESULT WINAPI IDirectPlay2AImpl_GetMessageCount( IDirectPlay2A *iface, DPID player,
2783 DWORD *count )
2785 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2786 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4A_iface, player, count );
2789 static HRESULT WINAPI IDirectPlay2Impl_GetMessageCount( IDirectPlay2 *iface, DPID player,
2790 DWORD *count )
2792 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2793 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4_iface, player, count );
2796 static HRESULT WINAPI IDirectPlay3AImpl_GetMessageCount( IDirectPlay3A *iface, DPID player,
2797 DWORD *count )
2799 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2800 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4_iface, player, count );
2803 static HRESULT WINAPI IDirectPlay3Impl_GetMessageCount( IDirectPlay3 *iface, DPID player,
2804 DWORD *count )
2806 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2807 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4_iface, player, count );
2810 static HRESULT WINAPI IDirectPlay4AImpl_GetMessageCount( IDirectPlay4A *iface, DPID player,
2811 DWORD *count )
2813 return IDirectPlayX_GetMessageQueue( iface, 0, player, DPMESSAGEQUEUE_RECEIVE, count, NULL );
2816 static HRESULT WINAPI IDirectPlay4Impl_GetMessageCount( IDirectPlay4 *iface, DPID player,
2817 DWORD *count )
2819 return IDirectPlayX_GetMessageQueue( iface, 0, player, DPMESSAGEQUEUE_RECEIVE, count, NULL );
2822 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerAddress( IDirectPlay2A *iface, DPID player,
2823 void *data, DWORD *size )
2825 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2826 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4A_iface, player, data, size );
2829 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerAddress( IDirectPlay2 *iface, DPID player,
2830 void *data, DWORD *size )
2832 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2833 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4_iface, player, data, size );
2836 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerAddress( IDirectPlay3A *iface, DPID player,
2837 void *data, DWORD *size )
2839 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2840 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4_iface, player, data, size );
2843 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerAddress( IDirectPlay3 *iface, DPID player,
2844 void *data, DWORD *size )
2846 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2847 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4_iface, player, data, size );
2850 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerAddress( IDirectPlay4A *iface, DPID player,
2851 void *data, DWORD *size )
2853 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2854 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, player, data, size );
2855 return DP_OK;
2858 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerAddress( IDirectPlay4 *iface, DPID player,
2859 void *data, DWORD *size )
2861 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2862 FIXME( "(%p)->(0x%08x,%p,%p): stub\n", This, player, data, size );
2863 return DP_OK;
2866 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerCaps( IDirectPlay2A *iface, DPID player,
2867 DPCAPS *caps, DWORD flags )
2869 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2870 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4A_iface, player, caps, flags );
2873 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerCaps( IDirectPlay2 *iface, DPID player,
2874 DPCAPS *caps, DWORD flags )
2876 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2877 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2880 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerCaps( IDirectPlay3A *iface, DPID player,
2881 DPCAPS *caps, DWORD flags )
2883 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2884 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2887 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerCaps( IDirectPlay3 *iface, DPID player,
2888 DPCAPS *caps, DWORD flags )
2890 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2891 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2894 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerCaps( IDirectPlay4A *iface, DPID player,
2895 DPCAPS *caps, DWORD flags )
2897 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2898 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2901 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerCaps( IDirectPlay4 *iface, DPID player,
2902 DPCAPS *caps, DWORD flags )
2904 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2905 DPSP_GETCAPSDATA data;
2907 TRACE( "(%p)->(0x%08x,%p,0x%08x)\n", This, player, caps, flags);
2909 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2910 return DPERR_UNINITIALIZED;
2912 /* Query the service provider */
2913 data.idPlayer = player;
2914 data.dwFlags = flags;
2915 data.lpCaps = caps;
2916 data.lpISP = This->dp2->spData.lpISP;
2918 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2921 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerData( IDirectPlay2A *iface, DPID player,
2922 void *data, DWORD *size, DWORD flags )
2924 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2925 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4A_iface, player, data, size, flags );
2928 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerData( IDirectPlay2 *iface, DPID player,
2929 void *data, DWORD *size, DWORD flags )
2931 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2932 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2935 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerData( IDirectPlay3A *iface, DPID player,
2936 void *data, DWORD *size, DWORD flags )
2938 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2939 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2942 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerData( IDirectPlay3 *iface, DPID player,
2943 void *data, DWORD *size, DWORD flags )
2945 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2946 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2949 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerData( IDirectPlay4A *iface, DPID player,
2950 void *data, DWORD *size, DWORD flags )
2952 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2953 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2956 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerData( IDirectPlay4 *iface, DPID player,
2957 void *data, DWORD *size, DWORD flags )
2959 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2960 lpPlayerList plist;
2961 DWORD bufsize;
2962 void *src;
2964 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x)\n", This, player, data, size, flags );
2966 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2967 return DPERR_UNINITIALIZED;
2969 if ( ( plist = DP_FindPlayer( This, player ) ) == NULL )
2970 return DPERR_INVALIDPLAYER;
2972 if ( flags & DPSET_LOCAL )
2974 bufsize = plist->lpPData->dwLocalDataSize;
2975 src = plist->lpPData->lpLocalData;
2977 else
2979 bufsize = plist->lpPData->dwRemoteDataSize;
2980 src = plist->lpPData->lpRemoteData;
2983 /* Is the user requesting to know how big a buffer is required? */
2984 if ( !data || *size < bufsize )
2986 *size = bufsize;
2987 return DPERR_BUFFERTOOSMALL;
2990 CopyMemory( data, src, bufsize );
2992 return DP_OK;
2995 static HRESULT DP_IF_GetPlayerName( IDirectPlayImpl *This, DPID idPlayer, void *lpData,
2996 DWORD *lpdwDataSize, BOOL bAnsi )
2998 lpPlayerList lpPList;
2999 LPDPNAME lpName = lpData;
3000 DWORD dwRequiredDataSize;
3002 FIXME( "(%p)->(0x%08x,%p,%p,%u): ANSI\n",
3003 This, idPlayer, lpData, lpdwDataSize, bAnsi );
3005 if( This->dp2->connectionInitialized == NO_PROVIDER )
3007 return DPERR_UNINITIALIZED;
3010 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3012 return DPERR_INVALIDPLAYER;
3015 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
3017 if( lpPList->lpPData->name.u1.lpszShortNameA )
3019 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
3022 if( lpPList->lpPData->name.u2.lpszLongNameA )
3024 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
3027 if( ( lpData == NULL ) ||
3028 ( *lpdwDataSize < dwRequiredDataSize )
3031 *lpdwDataSize = dwRequiredDataSize;
3032 return DPERR_BUFFERTOOSMALL;
3035 /* Copy the structure */
3036 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
3038 if( lpPList->lpPData->name.u1.lpszShortNameA )
3040 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
3041 lpPList->lpPData->name.u1.lpszShortNameA );
3043 else
3045 lpName->u1.lpszShortNameA = NULL;
3048 if( lpPList->lpPData->name.u1.lpszShortNameA )
3050 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
3051 lpPList->lpPData->name.u2.lpszLongNameA );
3053 else
3055 lpName->u2.lpszLongNameA = NULL;
3058 return DP_OK;
3061 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerName( IDirectPlay2A *iface, DPID player,
3062 void *data, DWORD *size )
3064 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3065 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4A_iface, player, data, size );
3068 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerName( IDirectPlay2 *iface, DPID player,
3069 void *data, DWORD *size )
3071 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3072 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4_iface, player, data, size );
3075 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerName( IDirectPlay3A *iface, DPID player,
3076 void *data, DWORD *size )
3078 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3079 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4_iface, player, data, size );
3082 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerName( IDirectPlay3 *iface, DPID player,
3083 void *data, DWORD *size )
3085 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3086 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4_iface, player, data, size );
3089 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerName( IDirectPlay4A *iface, DPID idPlayer,
3090 void *lpData, DWORD *lpdwDataSize )
3092 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3093 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
3096 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerName( IDirectPlay4 *iface, DPID idPlayer,
3097 void *lpData, DWORD *lpdwDataSize )
3099 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3100 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
3103 static HRESULT DP_GetSessionDesc( IDirectPlayImpl *This, void *lpData, DWORD *lpdwDataSize,
3104 BOOL bAnsi )
3106 DWORD dwRequiredSize;
3108 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
3110 if( This->dp2->connectionInitialized == NO_PROVIDER )
3112 return DPERR_UNINITIALIZED;
3115 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
3117 return DPERR_INVALIDPARAMS;
3120 /* FIXME: Get from This->dp2->lpSessionDesc */
3121 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
3123 if ( ( lpData == NULL ) ||
3124 ( *lpdwDataSize < dwRequiredSize )
3127 *lpdwDataSize = dwRequiredSize;
3128 return DPERR_BUFFERTOOSMALL;
3131 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
3133 return DP_OK;
3136 static HRESULT WINAPI IDirectPlay2AImpl_GetSessionDesc( IDirectPlay2A *iface, void *data,
3137 DWORD *size )
3139 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3140 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4A_iface, data, size );
3143 static HRESULT WINAPI IDirectPlay2Impl_GetSessionDesc( IDirectPlay2 *iface, void *data,
3144 DWORD *size )
3146 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3147 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4_iface, data, size );
3150 static HRESULT WINAPI IDirectPlay3AImpl_GetSessionDesc( IDirectPlay3A *iface, void *data,
3151 DWORD *size )
3153 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3154 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4_iface, data, size );
3157 static HRESULT WINAPI IDirectPlay3Impl_GetSessionDesc( IDirectPlay3 *iface, void *data,
3158 DWORD *size )
3160 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3161 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4_iface, data, size );
3164 static HRESULT WINAPI IDirectPlay4AImpl_GetSessionDesc( IDirectPlay4A *iface, void *lpData,
3165 DWORD *lpdwDataSize )
3167 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3168 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
3171 static HRESULT WINAPI IDirectPlay4Impl_GetSessionDesc( IDirectPlay4 *iface, void *lpData,
3172 DWORD *lpdwDataSize )
3174 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3175 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
3178 static HRESULT WINAPI IDirectPlay2AImpl_Initialize( IDirectPlay2A *iface, GUID *guid )
3180 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3181 return IDirectPlayX_Initialize( &This->IDirectPlay4A_iface, guid );
3184 static HRESULT WINAPI IDirectPlay2Impl_Initialize( IDirectPlay2 *iface, GUID *guid )
3186 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3187 return IDirectPlayX_Initialize( &This->IDirectPlay4_iface, guid );
3190 static HRESULT WINAPI IDirectPlay3AImpl_Initialize( IDirectPlay3A *iface, GUID *guid )
3192 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3193 return IDirectPlayX_Initialize( &This->IDirectPlay4_iface, guid );
3196 static HRESULT WINAPI IDirectPlay3Impl_Initialize( IDirectPlay3 *iface, GUID *guid )
3198 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3199 return IDirectPlayX_Initialize( &This->IDirectPlay4_iface, guid );
3202 /* Intended only for COM compatibility. Always returns an error. */
3203 static HRESULT WINAPI IDirectPlay4AImpl_Initialize( IDirectPlay4A *iface, GUID *guid )
3205 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3206 TRACE("(%p)->(%p): no-op\n", This, guid );
3207 return DPERR_ALREADYINITIALIZED;
3210 static HRESULT WINAPI IDirectPlay4Impl_Initialize( IDirectPlay4 *iface, GUID *guid )
3212 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3213 TRACE( "(%p)->(%p): no-op\n", This, guid );
3214 return DPERR_ALREADYINITIALIZED;
3218 static HRESULT DP_SecureOpen( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpsd, DWORD dwFlags,
3219 const DPSECURITYDESC *lpSecurity, const DPCREDENTIALS *lpCredentials, BOOL bAnsi )
3221 HRESULT hr = DP_OK;
3223 FIXME( "(%p)->(%p,0x%08x,%p,%p): partial stub\n",
3224 This, lpsd, dwFlags, lpSecurity, lpCredentials );
3226 if( This->dp2->connectionInitialized == NO_PROVIDER )
3228 return DPERR_UNINITIALIZED;
3231 if( lpsd->dwSize != sizeof(DPSESSIONDESC2) )
3233 TRACE( ": rejecting invalid dpsd size (%d).\n", lpsd->dwSize );
3234 return DPERR_INVALIDPARAMS;
3237 if( This->dp2->bConnectionOpen )
3239 TRACE( ": rejecting already open connection.\n" );
3240 return DPERR_ALREADYINITIALIZED;
3243 /* If we're enumerating, kill the thread */
3244 DP_KillEnumSessionThread( This );
3246 if( dwFlags & DPOPEN_CREATE )
3248 /* Rightoo - this computer is the host and the local computer needs to be
3249 the name server so that others can join this session */
3250 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
3252 This->dp2->bHostInterface = TRUE;
3254 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
3255 if( FAILED( hr ) )
3257 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
3258 return hr;
3262 /* Invoke the conditional callback for the service provider */
3263 if( This->dp2->spData.lpCB->Open )
3265 DPSP_OPENDATA data;
3267 FIXME( "Not all data fields are correct. Need new parameter\n" );
3269 data.bCreate = (dwFlags & DPOPEN_CREATE ) != 0;
3270 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
3271 : NS_GetNSAddr( This->dp2->lpNameServerData );
3272 data.lpISP = This->dp2->spData.lpISP;
3273 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) != 0;
3274 data.dwOpenFlags = dwFlags;
3275 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
3277 hr = (*This->dp2->spData.lpCB->Open)(&data);
3278 if( FAILED( hr ) )
3280 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
3281 return hr;
3286 /* Create the system group of which everything is a part of */
3287 DPID systemGroup = DPID_SYSTEM_GROUP;
3289 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
3290 NULL, 0, 0, TRUE );
3294 if( dwFlags & DPOPEN_JOIN )
3296 DPID dpidServerId = DPID_UNKNOWN;
3298 /* Create the server player for this interface. This way we can receive
3299 * messages for this session.
3301 /* FIXME: I suppose that we should be setting an event for a receive
3302 * type of thing. That way the messaging thread could know to wake
3303 * up. DPlay would then trigger the hEvent for the player the
3304 * message is directed to.
3306 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
3308 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
3311 else if( dwFlags & DPOPEN_CREATE )
3313 DPID dpidNameServerId = DPID_NAME_SERVER;
3315 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
3316 0, DPPLAYER_SERVERPLAYER, bAnsi );
3319 if( FAILED(hr) )
3321 ERR( "Couldn't create name server/system player: %s\n",
3322 DPLAYX_HresultToString(hr) );
3325 return hr;
3328 static HRESULT WINAPI IDirectPlay2AImpl_Open( IDirectPlay2A *iface, DPSESSIONDESC2 *sdesc,
3329 DWORD flags )
3331 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3332 return IDirectPlayX_Open( &This->IDirectPlay4A_iface, sdesc, flags );
3335 static HRESULT WINAPI IDirectPlay2Impl_Open( IDirectPlay2 *iface, DPSESSIONDESC2 *sdesc,
3336 DWORD flags )
3338 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3339 return IDirectPlayX_Open( &This->IDirectPlay4_iface, sdesc, flags );
3342 static HRESULT WINAPI IDirectPlay3AImpl_Open( IDirectPlay3A *iface, DPSESSIONDESC2 *sdesc,
3343 DWORD flags )
3345 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3346 return IDirectPlayX_Open( &This->IDirectPlay4_iface, sdesc, flags );
3349 static HRESULT WINAPI IDirectPlay3Impl_Open( IDirectPlay3 *iface, DPSESSIONDESC2 *sdesc,
3350 DWORD flags )
3352 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3353 return IDirectPlayX_Open( &This->IDirectPlay4_iface, sdesc, flags );
3356 static HRESULT WINAPI IDirectPlay4AImpl_Open( IDirectPlay4A *iface, DPSESSIONDESC2 *sdesc,
3357 DWORD flags )
3359 return IDirectPlayX_SecureOpen( iface, sdesc, flags, NULL, NULL );
3362 static HRESULT WINAPI IDirectPlay4Impl_Open( IDirectPlay4 *iface, DPSESSIONDESC2 *sdesc,
3363 DWORD flags )
3365 return IDirectPlayX_SecureOpen( iface, sdesc, flags, NULL, NULL );
3368 static HRESULT DP_IF_Receive( IDirectPlayImpl *This, DPID *lpidFrom, DPID *lpidTo, DWORD dwFlags,
3369 void *lpData, DWORD *lpdwDataSize, BOOL bAnsi )
3371 LPDPMSG lpMsg = NULL;
3373 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p,%u): stub\n",
3374 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
3376 if( This->dp2->connectionInitialized == NO_PROVIDER )
3378 return DPERR_UNINITIALIZED;
3381 if( dwFlags == 0 )
3383 dwFlags = DPRECEIVE_ALL;
3386 /* If the lpData is NULL, we must be peeking the message */
3387 if( ( lpData == NULL ) &&
3388 !( dwFlags & DPRECEIVE_PEEK )
3391 return DPERR_INVALIDPARAMS;
3394 if( dwFlags & DPRECEIVE_ALL )
3396 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
3398 if( !( dwFlags & DPRECEIVE_PEEK ) )
3400 FIXME( "Remove from queue\n" );
3403 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
3404 ( dwFlags & DPRECEIVE_FROMPLAYER )
3407 FIXME( "Find matching message 0x%08x\n", dwFlags );
3409 else
3411 ERR( "Hmmm..dwFlags 0x%08x\n", dwFlags );
3414 if( lpMsg == NULL )
3416 return DPERR_NOMESSAGES;
3419 /* Copy into the provided buffer */
3420 if (lpData) CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
3422 return DP_OK;
3425 static HRESULT WINAPI IDirectPlay2AImpl_Receive( IDirectPlay2A *iface, DPID *from, DPID *to,
3426 DWORD flags, void *data, DWORD *size )
3428 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3429 return IDirectPlayX_Receive( &This->IDirectPlay4A_iface, from, to, flags, data, size );
3432 static HRESULT WINAPI IDirectPlay2Impl_Receive( IDirectPlay2 *iface, DPID *from, DPID *to,
3433 DWORD flags, void *data, DWORD *size )
3435 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3436 return IDirectPlayX_Receive( &This->IDirectPlay4_iface, from, to, flags, data, size );
3439 static HRESULT WINAPI IDirectPlay3AImpl_Receive( IDirectPlay3A *iface, DPID *from, DPID *to,
3440 DWORD flags, void *data, DWORD *size )
3442 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3443 return IDirectPlayX_Receive( &This->IDirectPlay4_iface, from, to, flags, data, size );
3446 static HRESULT WINAPI IDirectPlay3Impl_Receive( IDirectPlay3 *iface, DPID *from, DPID *to,
3447 DWORD flags, void *data, DWORD *size )
3449 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3450 return IDirectPlayX_Receive( &This->IDirectPlay4_iface, from, to, flags, data, size );
3453 static HRESULT WINAPI IDirectPlay4AImpl_Receive( IDirectPlay4A *iface, DPID *lpidFrom,
3454 DPID *lpidTo, DWORD dwFlags, void *lpData, DWORD *lpdwDataSize )
3456 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3457 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, TRUE );
3460 static HRESULT WINAPI IDirectPlay4Impl_Receive( IDirectPlay4 *iface, DPID *lpidFrom,
3461 DPID *lpidTo, DWORD dwFlags, void *lpData, DWORD *lpdwDataSize )
3463 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3464 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, FALSE );
3467 static HRESULT WINAPI IDirectPlay2AImpl_Send( IDirectPlay2A *iface, DPID from, DPID to,
3468 DWORD flags, void *data, DWORD size )
3470 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3471 return IDirectPlayX_Send( &This->IDirectPlay4A_iface, from, to, flags, data, size );
3474 static HRESULT WINAPI IDirectPlay2Impl_Send( IDirectPlay2 *iface, DPID from, DPID to,
3475 DWORD flags, void *data, DWORD size )
3477 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3478 return IDirectPlayX_Send( &This->IDirectPlay4_iface, from, to, flags, data, size );
3481 static HRESULT WINAPI IDirectPlay3AImpl_Send( IDirectPlay3A *iface, DPID from, DPID to,
3482 DWORD flags, void *data, DWORD size )
3484 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3485 return IDirectPlayX_Send( &This->IDirectPlay4_iface, from, to, flags, data, size );
3488 static HRESULT WINAPI IDirectPlay3Impl_Send( IDirectPlay3 *iface, DPID from, DPID to,
3489 DWORD flags, void *data, DWORD size )
3491 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3492 return IDirectPlayX_Send( &This->IDirectPlay4_iface, from, to, flags, data, size );
3495 static HRESULT WINAPI IDirectPlay4AImpl_Send( IDirectPlay4A *iface, DPID from, DPID to,
3496 DWORD flags, void *data, DWORD size )
3498 return IDirectPlayX_SendEx( iface, from, to, flags, data, size, 0, 0, NULL, NULL );
3501 static HRESULT WINAPI IDirectPlay4Impl_Send( IDirectPlay4 *iface, DPID from, DPID to,
3502 DWORD flags, void *data, DWORD size )
3504 return IDirectPlayX_SendEx( iface, from, to, flags, data, size, 0, 0, NULL, NULL );
3507 static HRESULT WINAPI IDirectPlay2AImpl_SetGroupData( IDirectPlay2A *iface, DPID group, void *data,
3508 DWORD size, DWORD flags )
3510 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3511 return IDirectPlayX_SetGroupData( &This->IDirectPlay4A_iface, group, data, size, flags );
3514 static HRESULT WINAPI IDirectPlay2Impl_SetGroupData( IDirectPlay2 *iface, DPID group, void *data,
3515 DWORD size, DWORD flags )
3517 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3518 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3521 static HRESULT WINAPI IDirectPlay3AImpl_SetGroupData( IDirectPlay3A *iface, DPID group, void *data,
3522 DWORD size, DWORD flags )
3524 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3525 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3528 static HRESULT WINAPI IDirectPlay3Impl_SetGroupData( IDirectPlay3 *iface, DPID group, void *data,
3529 DWORD size, DWORD flags )
3531 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3532 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3535 static HRESULT WINAPI IDirectPlay4AImpl_SetGroupData( IDirectPlay4A *iface, DPID group, void *data,
3536 DWORD size, DWORD flags )
3538 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3539 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3542 static HRESULT WINAPI IDirectPlay4Impl_SetGroupData( IDirectPlay4 *iface, DPID group, void *data,
3543 DWORD size, DWORD flags )
3545 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3546 lpGroupData gdata;
3548 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x)\n", This, group, data, size, flags );
3550 /* Parameter check */
3551 if ( !data && size )
3552 return DPERR_INVALIDPARAMS;
3554 /* Find the pointer to the data for this player */
3555 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
3556 return DPERR_INVALIDOBJECT;
3558 if ( !(flags & DPSET_LOCAL) )
3560 FIXME( "Was this group created by this interface?\n" );
3561 /* FIXME: If this is a remote update need to allow it but not
3562 * send a message.
3566 DP_SetGroupData( gdata, flags, data, size );
3568 /* FIXME: Only send a message if this group is local to the session otherwise
3569 * it will have been rejected above
3571 if ( !(flags & DPSET_LOCAL) )
3572 FIXME( "Send msg?\n" );
3574 return DP_OK;
3577 static HRESULT DP_IF_SetGroupName( IDirectPlayImpl *This, DPID idGroup, DPNAME *lpGroupName,
3578 DWORD dwFlags, BOOL bAnsi )
3580 lpGroupData lpGData;
3582 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n", This, idGroup,
3583 lpGroupName, dwFlags, bAnsi );
3585 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3587 return DPERR_INVALIDGROUP;
3590 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
3592 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3593 FIXME( "Message not sent and dwFlags ignored\n" );
3595 return DP_OK;
3598 static HRESULT WINAPI IDirectPlay2AImpl_SetGroupName( IDirectPlay2A *iface, DPID group,
3599 DPNAME *name, DWORD flags )
3601 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3602 return IDirectPlayX_SetGroupName( &This->IDirectPlay4A_iface, group, name, flags );
3605 static HRESULT WINAPI IDirectPlay2Impl_SetGroupName( IDirectPlay2 *iface, DPID group,
3606 DPNAME *name, DWORD flags )
3608 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3609 return IDirectPlayX_SetGroupName( &This->IDirectPlay4_iface, group, name, flags );
3612 static HRESULT WINAPI IDirectPlay3AImpl_SetGroupName( IDirectPlay3A *iface, DPID group,
3613 DPNAME *name, DWORD flags )
3615 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3616 return IDirectPlayX_SetGroupName( &This->IDirectPlay4_iface, group, name, flags );
3619 static HRESULT WINAPI IDirectPlay3Impl_SetGroupName( IDirectPlay3 *iface, DPID group,
3620 DPNAME *name, DWORD flags )
3622 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3623 return IDirectPlayX_SetGroupName( &This->IDirectPlay4_iface, group, name, flags );
3626 static HRESULT WINAPI IDirectPlay4AImpl_SetGroupName( IDirectPlay4A *iface, DPID idGroup,
3627 DPNAME *lpGroupName, DWORD dwFlags )
3629 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3630 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
3633 static HRESULT WINAPI IDirectPlay4Impl_SetGroupName( IDirectPlay4 *iface, DPID idGroup,
3634 DPNAME *lpGroupName, DWORD dwFlags )
3636 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3637 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
3640 static HRESULT WINAPI IDirectPlay2AImpl_SetPlayerData( IDirectPlay2A *iface, DPID player,
3641 void *data, DWORD size, DWORD flags )
3643 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3644 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4A_iface, player, data, size, flags );
3647 static HRESULT WINAPI IDirectPlay2Impl_SetPlayerData( IDirectPlay2 *iface, DPID player,
3648 void *data, DWORD size, DWORD flags )
3650 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3651 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
3654 static HRESULT WINAPI IDirectPlay3AImpl_SetPlayerData( IDirectPlay3A *iface, DPID player,
3655 void *data, DWORD size, DWORD flags )
3657 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3658 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
3661 static HRESULT WINAPI IDirectPlay3Impl_SetPlayerData( IDirectPlay3 *iface, DPID player,
3662 void *data, DWORD size, DWORD flags )
3664 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3665 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
3668 static HRESULT WINAPI IDirectPlay4AImpl_SetPlayerData( IDirectPlay4A *iface, DPID player,
3669 void *data, DWORD size, DWORD flags )
3671 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3672 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
3675 static HRESULT WINAPI IDirectPlay4Impl_SetPlayerData( IDirectPlay4 *iface, DPID player,
3676 void *data, DWORD size, DWORD flags )
3678 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3679 lpPlayerList plist;
3681 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x)\n", This, player, data, size, flags );
3683 if ( This->dp2->connectionInitialized == NO_PROVIDER )
3684 return DPERR_UNINITIALIZED;
3686 /* Parameter check */
3687 if ( !data && size )
3688 return DPERR_INVALIDPARAMS;
3690 /* Find the pointer to the data for this player */
3691 if ( (plist = DP_FindPlayer( This, player )) == NULL )
3692 return DPERR_INVALIDPLAYER;
3694 if ( !(flags & DPSET_LOCAL) )
3696 FIXME( "Was this group created by this interface?\n" );
3697 /* FIXME: If this is a remote update need to allow it but not
3698 * send a message.
3702 DP_SetPlayerData( plist->lpPData, flags, data, size );
3704 if ( !(flags & DPSET_LOCAL) )
3705 FIXME( "Send msg?\n" );
3707 return DP_OK;
3710 static HRESULT DP_IF_SetPlayerName( IDirectPlayImpl *This, DPID idPlayer, DPNAME *lpPlayerName,
3711 DWORD dwFlags, BOOL bAnsi )
3713 lpPlayerList lpPList;
3715 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n",
3716 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3718 if( This->dp2->connectionInitialized == NO_PROVIDER )
3720 return DPERR_UNINITIALIZED;
3723 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3725 return DPERR_INVALIDGROUP;
3728 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3730 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3731 FIXME( "Message not sent and dwFlags ignored\n" );
3733 return DP_OK;
3736 static HRESULT WINAPI IDirectPlay2AImpl_SetPlayerName( IDirectPlay2A *iface, DPID player,
3737 DPNAME *name, DWORD flags )
3739 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3740 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4A_iface, player, name, flags );
3743 static HRESULT WINAPI IDirectPlay2Impl_SetPlayerName( IDirectPlay2 *iface, DPID player,
3744 DPNAME *name, DWORD flags )
3746 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3747 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4_iface, player, name, flags );
3750 static HRESULT WINAPI IDirectPlay3AImpl_SetPlayerName( IDirectPlay3A *iface, DPID player,
3751 DPNAME *name, DWORD flags )
3753 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3754 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4_iface, player, name, flags );
3757 static HRESULT WINAPI IDirectPlay3Impl_SetPlayerName( IDirectPlay3 *iface, DPID player,
3758 DPNAME *name, DWORD flags )
3760 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3761 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4_iface, player, name, flags );
3764 static HRESULT WINAPI IDirectPlay4AImpl_SetPlayerName( IDirectPlay4A *iface, DPID idPlayer,
3765 DPNAME *lpPlayerName, DWORD dwFlags )
3767 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3768 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3771 static HRESULT WINAPI IDirectPlay4Impl_SetPlayerName( IDirectPlay4 *iface, DPID idPlayer,
3772 DPNAME *lpPlayerName, DWORD dwFlags )
3774 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3775 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3778 static HRESULT DP_SetSessionDesc( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpSessDesc,
3779 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3781 DWORD dwRequiredSize;
3782 LPDPSESSIONDESC2 lpTempSessDesc;
3784 TRACE( "(%p)->(%p,0x%08x,%u,%u)\n",
3785 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3787 if( This->dp2->connectionInitialized == NO_PROVIDER )
3789 return DPERR_UNINITIALIZED;
3792 if( dwFlags )
3794 return DPERR_INVALIDPARAMS;
3797 /* Only the host is allowed to update the session desc */
3798 if( !This->dp2->bHostInterface )
3800 return DPERR_ACCESSDENIED;
3803 /* FIXME: Copy into This->dp2->lpSessionDesc */
3804 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3805 lpTempSessDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize );
3807 if( lpTempSessDesc == NULL )
3809 return DPERR_OUTOFMEMORY;
3812 /* Free the old */
3813 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3815 This->dp2->lpSessionDesc = lpTempSessDesc;
3816 /* Set the new */
3817 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3818 if( bInitial )
3820 /*Initializing session GUID*/
3821 CoCreateGuid( &(This->dp2->lpSessionDesc->guidInstance) );
3823 /* If this is an external invocation of the interface, we should be
3824 * letting everyone know that things have changed. Otherwise this is
3825 * just an initialization and it doesn't need to be propagated.
3827 if( !bInitial )
3829 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3832 return DP_OK;
3835 static HRESULT WINAPI IDirectPlay2AImpl_SetSessionDesc( IDirectPlay2A *iface, DPSESSIONDESC2 *sdesc,
3836 DWORD flags )
3838 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3839 return IDirectPlayX_SetSessionDesc( &This->IDirectPlay4A_iface, sdesc, flags );
3842 static HRESULT WINAPI IDirectPlay2Impl_SetSessionDesc( IDirectPlay2 *iface, DPSESSIONDESC2 *sdesc,
3843 DWORD flags )
3845 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3846 return IDirectPlayX_SetSessionDesc( &This->IDirectPlay4_iface, sdesc, flags );
3849 static HRESULT WINAPI IDirectPlay3AImpl_SetSessionDesc( IDirectPlay3A *iface, DPSESSIONDESC2 *sdesc,
3850 DWORD flags )
3852 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3853 return IDirectPlayX_SetSessionDesc( &This->IDirectPlay4_iface, sdesc, flags );
3856 static HRESULT WINAPI IDirectPlay3Impl_SetSessionDesc( IDirectPlay3 *iface, DPSESSIONDESC2 *sdesc,
3857 DWORD flags )
3859 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3860 return IDirectPlayX_SetSessionDesc( &This->IDirectPlay4_iface, sdesc, flags );
3863 static HRESULT WINAPI IDirectPlay4AImpl_SetSessionDesc( IDirectPlay4A *iface,
3864 DPSESSIONDESC2 *lpSessDesc, DWORD dwFlags )
3866 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3867 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3870 static HRESULT WINAPI IDirectPlay4Impl_SetSessionDesc( IDirectPlay4 *iface,
3871 DPSESSIONDESC2 *lpSessDesc, DWORD dwFlags )
3873 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3874 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3877 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3878 static DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3880 DWORD dwSize = 0;
3882 if( lpSessDesc == NULL )
3884 /* Hmmm..don't need any size? */
3885 ERR( "NULL lpSessDesc\n" );
3886 return dwSize;
3889 dwSize += sizeof( *lpSessDesc );
3891 if( bAnsi )
3893 if( lpSessDesc->u1.lpszSessionNameA )
3895 dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1;
3898 if( lpSessDesc->u2.lpszPasswordA )
3900 dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1;
3903 else /* UNICODE */
3905 if( lpSessDesc->u1.lpszSessionName )
3907 dwSize += sizeof( WCHAR ) *
3908 ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 );
3911 if( lpSessDesc->u2.lpszPassword )
3913 dwSize += sizeof( WCHAR ) *
3914 ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 );
3918 return dwSize;
3921 /* Assumes that contiguous buffers are already allocated. */
3922 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3923 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3925 BYTE* lpStartOfFreeSpace;
3927 if( lpSessionDest == NULL )
3929 ERR( "NULL lpSessionDest\n" );
3930 return;
3933 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3935 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3937 if( bAnsi )
3939 if( lpSessionSrc->u1.lpszSessionNameA )
3941 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3942 lpSessionDest->u1.lpszSessionNameA );
3943 lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3944 lpStartOfFreeSpace +=
3945 lstrlenA( lpSessionDest->u1.lpszSessionNameA ) + 1;
3948 if( lpSessionSrc->u2.lpszPasswordA )
3950 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3951 lpSessionDest->u2.lpszPasswordA );
3952 lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3955 else /* UNICODE */
3957 if( lpSessionSrc->u1.lpszSessionName )
3959 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3960 lpSessionDest->u1.lpszSessionName );
3961 lpSessionDest->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3962 lpStartOfFreeSpace += sizeof(WCHAR) *
3963 ( lstrlenW( lpSessionDest->u1.lpszSessionName ) + 1 );
3966 if( lpSessionSrc->u2.lpszPassword )
3968 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3969 lpSessionDest->u2.lpszPassword );
3970 lpSessionDest->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3975 static HRESULT WINAPI IDirectPlay3AImpl_AddGroupToGroup( IDirectPlay3A *iface, DPID parent,
3976 DPID group )
3978 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3979 return IDirectPlayX_AddGroupToGroup( &This->IDirectPlay4A_iface, parent, group );
3982 static HRESULT WINAPI IDirectPlay3Impl_AddGroupToGroup( IDirectPlay3 *iface, DPID parent,
3983 DPID group )
3985 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3986 return IDirectPlayX_AddGroupToGroup( &This->IDirectPlay4_iface, parent, group );
3989 static HRESULT WINAPI IDirectPlay4AImpl_AddGroupToGroup( IDirectPlay4A *iface, DPID parent,
3990 DPID group )
3992 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3993 return IDirectPlayX_AddGroupToGroup( &This->IDirectPlay4_iface, parent, group );
3996 static HRESULT WINAPI IDirectPlay4Impl_AddGroupToGroup( IDirectPlay4 *iface, DPID parent,
3997 DPID group )
3999 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4000 lpGroupData gdata;
4001 lpGroupList glist;
4003 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, parent, group );
4005 if ( This->dp2->connectionInitialized == NO_PROVIDER )
4006 return DPERR_UNINITIALIZED;
4008 if ( !DP_FindAnyGroup(This, parent ) )
4009 return DPERR_INVALIDGROUP;
4011 if ( ( gdata = DP_FindAnyGroup(This, group ) ) == NULL )
4012 return DPERR_INVALIDGROUP;
4014 /* Create a player list (ie "shortcut" ) */
4015 glist = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *glist ) );
4016 if ( !glist )
4017 return DPERR_CANTADDPLAYER;
4019 /* Add the shortcut */
4020 gdata->uRef++;
4021 glist->lpGData = gdata;
4023 /* Add the player to the list of players for this group */
4024 DPQ_INSERT( gdata->groups, glist, groups );
4026 /* Send a ADDGROUPTOGROUP message */
4027 FIXME( "Not sending message\n" );
4029 return DP_OK;
4032 static HRESULT DP_IF_CreateGroupInGroup( IDirectPlayImpl *This, void *lpMsgHdr, DPID idParentGroup,
4033 DPID *lpidGroup, DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags,
4034 BOOL bAnsi )
4036 lpGroupData lpGParentData;
4037 lpGroupList lpGList;
4038 lpGroupData lpGData;
4040 TRACE( "(%p)->(0x%08x,%p,%p,%p,0x%08x,0x%08x,%u)\n",
4041 This, idParentGroup, lpidGroup, lpGroupName, lpData,
4042 dwDataSize, dwFlags, bAnsi );
4044 if( This->dp2->connectionInitialized == NO_PROVIDER )
4046 return DPERR_UNINITIALIZED;
4049 /* Verify that the specified parent is valid */
4050 if( ( lpGParentData = DP_FindAnyGroup(This, idParentGroup ) ) == NULL )
4051 return DPERR_INVALIDGROUP;
4053 lpGData = DP_CreateGroup(This, lpidGroup, lpGroupName, dwFlags, idParentGroup, bAnsi );
4055 if( lpGData == NULL )
4057 return DPERR_CANTADDPLAYER; /* yes player not group */
4060 /* Something else is referencing this data */
4061 lpGData->uRef++;
4063 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
4065 /* The list has now been inserted into the interface group list. We now
4066 need to put a "shortcut" to this group in the parent group */
4067 lpGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGList ) );
4068 if( lpGList == NULL )
4070 FIXME( "Memory leak\n" );
4071 return DPERR_CANTADDPLAYER; /* yes player not group */
4074 lpGList->lpGData = lpGData;
4076 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
4078 /* Let the SP know that we've created this group */
4079 if( This->dp2->spData.lpCB->CreateGroup )
4081 DPSP_CREATEGROUPDATA data;
4083 TRACE( "Calling SP CreateGroup\n" );
4085 data.idGroup = *lpidGroup;
4086 data.dwFlags = dwFlags;
4087 data.lpSPMessageHeader = lpMsgHdr;
4088 data.lpISP = This->dp2->spData.lpISP;
4090 (*This->dp2->spData.lpCB->CreateGroup)( &data );
4093 /* Inform all other peers of the creation of a new group. If there are
4094 * no peers keep this quiet.
4096 if( This->dp2->lpSessionDesc &&
4097 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
4099 DPMSG_CREATEPLAYERORGROUP msg;
4101 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
4102 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
4103 msg.dpId = *lpidGroup;
4104 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
4105 msg.lpData = lpData;
4106 msg.dwDataSize = dwDataSize;
4107 msg.dpnName = *lpGroupName;
4109 /* FIXME: Correct to just use send effectively? */
4110 /* FIXME: Should size include data w/ message or just message "header" */
4111 /* FIXME: Check return code */
4112 IDirectPlayX_SendEx( &This->IDirectPlay4_iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
4113 sizeof( msg ), 0, 0, NULL, NULL );
4116 return DP_OK;
4119 static HRESULT WINAPI IDirectPlay3AImpl_CreateGroupInGroup( IDirectPlay3A *iface, DPID parent,
4120 DPID *group, DPNAME *name, void *data, DWORD size, DWORD flags )
4122 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4123 return IDirectPlayX_CreateGroupInGroup( &This->IDirectPlay4A_iface, parent, group, name,
4124 data, size, flags );
4127 static HRESULT WINAPI IDirectPlay3Impl_CreateGroupInGroup( IDirectPlay3 *iface, DPID parent,
4128 DPID *group, DPNAME *name, void *data, DWORD size, DWORD flags )
4130 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4131 return IDirectPlayX_CreateGroupInGroup( &This->IDirectPlay4_iface, parent, group, name,
4132 data, size, flags );
4135 static HRESULT WINAPI IDirectPlay4AImpl_CreateGroupInGroup( IDirectPlay4A *iface,
4136 DPID idParentGroup, DPID *lpidGroup, DPNAME *lpGroupName, void *lpData, DWORD dwDataSize,
4137 DWORD dwFlags )
4139 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4141 *lpidGroup = DPID_UNKNOWN;
4143 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup, lpGroupName, lpData,
4144 dwDataSize, dwFlags, TRUE );
4147 static HRESULT WINAPI IDirectPlay4Impl_CreateGroupInGroup( IDirectPlay4 *iface, DPID idParentGroup,
4148 DPID *lpidGroup, DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags )
4150 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4152 *lpidGroup = DPID_UNKNOWN;
4154 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup, lpGroupName, lpData,
4155 dwDataSize, dwFlags, FALSE );
4158 static HRESULT WINAPI IDirectPlay3AImpl_DeleteGroupFromGroup( IDirectPlay3A *iface, DPID parent,
4159 DPID group )
4161 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4162 return IDirectPlayX_DeleteGroupFromGroup( &This->IDirectPlay4A_iface, parent, group );
4165 static HRESULT WINAPI IDirectPlay3Impl_DeleteGroupFromGroup( IDirectPlay3 *iface, DPID parent,
4166 DPID group )
4168 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4169 return IDirectPlayX_DeleteGroupFromGroup( &This->IDirectPlay4_iface, parent, group );
4172 static HRESULT WINAPI IDirectPlay4AImpl_DeleteGroupFromGroup( IDirectPlay4A *iface, DPID parent,
4173 DPID group )
4175 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4176 return IDirectPlayX_DeleteGroupFromGroup( &This->IDirectPlay4_iface, parent, group );
4179 static HRESULT WINAPI IDirectPlay4Impl_DeleteGroupFromGroup( IDirectPlay4 *iface, DPID parent,
4180 DPID group )
4182 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4183 lpGroupList glist;
4184 lpGroupData parentdata;
4186 TRACE("(%p)->(0x%08x,0x%08x)\n", This, parent, group );
4188 /* Is the parent group valid? */
4189 if ( ( parentdata = DP_FindAnyGroup(This, parent ) ) == NULL )
4190 return DPERR_INVALIDGROUP;
4192 /* Remove the group from the parent group queue */
4193 DPQ_REMOVE_ENTRY( parentdata->groups, groups, lpGData->dpid, ==, group, glist );
4195 if ( glist == NULL )
4196 return DPERR_INVALIDGROUP;
4198 /* Decrement the ref count */
4199 glist->lpGData->uRef--;
4201 /* Free up the list item */
4202 HeapFree( GetProcessHeap(), 0, glist );
4204 /* Should send a DELETEGROUPFROMGROUP message */
4205 FIXME( "message not sent\n" );
4207 return DP_OK;
4210 static BOOL DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
4211 LPDWORD lpdwBufSize )
4213 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
4214 HRESULT hr;
4216 dpCompoundAddress.dwDataSize = sizeof( GUID );
4217 dpCompoundAddress.guidDataType = DPAID_ServiceProvider;
4218 dpCompoundAddress.lpData = lpcSpGuid;
4220 *lplpAddrBuf = NULL;
4221 *lpdwBufSize = 0;
4223 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
4224 lpdwBufSize, TRUE );
4226 if( hr != DPERR_BUFFERTOOSMALL )
4228 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
4229 return FALSE;
4232 /* Now allocate the buffer */
4233 *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4234 *lpdwBufSize );
4236 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
4237 lpdwBufSize, TRUE );
4238 if( FAILED(hr) )
4240 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
4241 return FALSE;
4244 return TRUE;
4247 static HRESULT WINAPI IDirectPlay3AImpl_EnumConnections( IDirectPlay3A *iface,
4248 const GUID *application, LPDPENUMCONNECTIONSCALLBACK enumcb, void *context, DWORD flags )
4250 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4251 return IDirectPlayX_EnumConnections( &This->IDirectPlay4A_iface, application, enumcb, context,
4252 flags );
4255 static HRESULT WINAPI IDirectPlay3Impl_EnumConnections( IDirectPlay3 *iface,
4256 const GUID *application, LPDPENUMCONNECTIONSCALLBACK enumcb, void *context, DWORD flags )
4258 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4259 return IDirectPlayX_EnumConnections( &This->IDirectPlay4_iface, application, enumcb, context,
4260 flags );
4263 static HRESULT WINAPI IDirectPlay4AImpl_EnumConnections( IDirectPlay4A *iface,
4264 const GUID *lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, void *lpContext,
4265 DWORD dwFlags )
4267 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4268 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
4270 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
4271 if( dwFlags == 0 )
4273 dwFlags = DPCONNECTION_DIRECTPLAY;
4276 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
4277 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) )
4280 return DPERR_INVALIDFLAGS;
4283 if( !lpEnumCallback )
4285 return DPERR_INVALIDPARAMS;
4288 /* Enumerate DirectPlay service providers */
4289 if( dwFlags & DPCONNECTION_DIRECTPLAY )
4291 HKEY hkResult;
4292 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4293 LPCSTR guidDataSubKey = "Guid";
4294 char subKeyName[51];
4295 DWORD dwIndex, sizeOfSubKeyName=50;
4296 FILETIME filetime;
4298 /* Need to loop over the service providers in the registry */
4299 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4300 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4302 /* Hmmm. Does this mean that there are no service providers? */
4303 ERR(": no service providers?\n");
4304 return DP_OK;
4308 /* Traverse all the service providers we have available */
4309 for( dwIndex=0;
4310 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4311 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4312 ++dwIndex, sizeOfSubKeyName=51 )
4315 HKEY hkServiceProvider;
4316 GUID serviceProviderGUID;
4317 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
4318 char returnBuffer[51];
4319 WCHAR buff[51];
4320 DPNAME dpName;
4321 BOOL bBuildPass;
4323 LPVOID lpAddressBuffer = NULL;
4324 DWORD dwAddressBufferSize = 0;
4326 TRACE(" this time through: %s\n", subKeyName );
4328 /* Get a handle for this particular service provider */
4329 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4330 &hkServiceProvider ) != ERROR_SUCCESS )
4332 ERR(": what the heck is going on?\n" );
4333 continue;
4336 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4337 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
4338 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4340 ERR(": missing GUID registry data members\n" );
4341 RegCloseKey(hkServiceProvider);
4342 continue;
4344 RegCloseKey(hkServiceProvider);
4346 /* FIXME: Check return types to ensure we're interpreting data right */
4347 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4348 CLSIDFromString( buff, &serviceProviderGUID );
4349 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4351 /* Fill in the DPNAME struct for the service provider */
4352 dpName.dwSize = sizeof( dpName );
4353 dpName.dwFlags = 0;
4354 dpName.u1.lpszShortNameA = subKeyName;
4355 dpName.u2.lpszLongNameA = NULL;
4357 /* Create the compound address for the service provider.
4358 * NOTE: This is a gruesome architectural scar right now. DP
4359 * uses DPL and DPL uses DP. Nasty stuff. This may be why the
4360 * native dll just gets around this little bit by allocating an
4361 * 80 byte buffer which isn't even filled with a valid compound
4362 * address. Oh well. Creating a proper compound address is the
4363 * way to go anyways despite this method taking slightly more
4364 * heap space and realtime :) */
4366 bBuildPass = DP_BuildSPCompoundAddr( &serviceProviderGUID,
4367 &lpAddressBuffer,
4368 &dwAddressBufferSize );
4369 if( !bBuildPass )
4371 ERR( "Can't build compound addr\n" );
4372 return DPERR_GENERIC;
4375 /* The enumeration will return FALSE if we are not to continue */
4376 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
4377 &dpName, dwFlags, lpContext ) )
4379 return DP_OK;
4384 /* Enumerate DirectPlayLobby service providers */
4385 if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY )
4387 HKEY hkResult;
4388 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
4389 LPCSTR guidDataSubKey = "Guid";
4390 char subKeyName[51];
4391 DWORD dwIndex, sizeOfSubKeyName=50;
4392 FILETIME filetime;
4394 /* Need to loop over the service providers in the registry */
4395 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4396 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4398 /* Hmmm. Does this mean that there are no service providers? */
4399 ERR(": no service providers?\n");
4400 return DP_OK;
4404 /* Traverse all the lobby providers we have available */
4405 for( dwIndex=0;
4406 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4407 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4408 ++dwIndex, sizeOfSubKeyName=51 )
4411 HKEY hkServiceProvider;
4412 GUID serviceProviderGUID;
4413 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
4414 char returnBuffer[51];
4415 WCHAR buff[51];
4416 DPNAME dpName;
4417 HRESULT hr;
4419 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
4420 LPVOID lpAddressBuffer = NULL;
4421 DWORD dwAddressBufferSize = 0;
4423 TRACE(" this time through: %s\n", subKeyName );
4425 /* Get a handle for this particular service provider */
4426 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4427 &hkServiceProvider ) != ERROR_SUCCESS )
4429 ERR(": what the heck is going on?\n" );
4430 continue;
4433 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4434 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
4435 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4437 ERR(": missing GUID registry data members\n" );
4438 RegCloseKey(hkServiceProvider);
4439 continue;
4441 RegCloseKey(hkServiceProvider);
4443 /* FIXME: Check return types to ensure we're interpreting data right */
4444 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4445 CLSIDFromString( buff, &serviceProviderGUID );
4446 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4448 /* Fill in the DPNAME struct for the service provider */
4449 dpName.dwSize = sizeof( dpName );
4450 dpName.dwFlags = 0;
4451 dpName.u1.lpszShortNameA = subKeyName;
4452 dpName.u2.lpszLongNameA = NULL;
4454 /* Create the compound address for the service provider.
4455 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
4456 nast stuff. This may be why the native dll just gets around this little bit by
4457 allocating an 80 byte buffer which isn't even a filled with a valid compound
4458 address. Oh well. Creating a proper compound address is the way to go anyways
4459 despite this method taking slightly more heap space and realtime :) */
4461 dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
4462 dpCompoundAddress.dwDataSize = sizeof( GUID );
4463 dpCompoundAddress.lpData = &serviceProviderGUID;
4465 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
4466 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
4468 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
4469 return hr;
4472 /* Now allocate the buffer */
4473 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
4475 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
4476 &dwAddressBufferSize, TRUE ) ) != DP_OK )
4478 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
4479 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
4480 return hr;
4483 /* The enumeration will return FALSE if we are not to continue */
4484 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
4485 &dpName, dwFlags, lpContext ) )
4487 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
4488 return DP_OK;
4490 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
4494 return DP_OK;
4497 static HRESULT WINAPI IDirectPlay4Impl_EnumConnections( IDirectPlay4 *iface,
4498 const GUID *application, LPDPENUMCONNECTIONSCALLBACK enumcb, void *context, DWORD flags )
4500 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4501 FIXME( "(%p)->(%p,%p,%p,0x%08x): stub\n", This, application, enumcb, context, flags );
4502 return DP_OK;
4505 static HRESULT WINAPI IDirectPlay3AImpl_EnumGroupsInGroup( IDirectPlay3A *iface, DPID group,
4506 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
4508 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4509 return IDirectPlayX_EnumGroupsInGroup( &This->IDirectPlay4A_iface, group, instance,
4510 enumplayercb, context, flags );
4513 static HRESULT WINAPI IDirectPlay3Impl_EnumGroupsInGroup( IDirectPlay3 *iface, DPID group,
4514 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
4516 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4517 return IDirectPlayX_EnumGroupsInGroup( &This->IDirectPlay4_iface, group, instance,
4518 enumplayercb, context, flags );
4521 static HRESULT WINAPI IDirectPlay4AImpl_EnumGroupsInGroup( IDirectPlay4A *iface, DPID group,
4522 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
4524 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4525 return IDirectPlayX_EnumGroupsInGroup( &This->IDirectPlay4_iface, group, instance,
4526 enumplayercb, context, flags );
4529 static HRESULT WINAPI IDirectPlay4Impl_EnumGroupsInGroup( IDirectPlay4 *iface, DPID group,
4530 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
4532 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4533 lpGroupList glist;
4534 lpGroupData gdata;
4536 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x): semi stub\n", This, group, instance, enumplayercb,
4537 context, flags );
4539 if ( This->dp2->connectionInitialized == NO_PROVIDER )
4540 return DPERR_UNINITIALIZED;
4542 if ( ( gdata = DP_FindAnyGroup(This, group ) ) == NULL )
4543 return DPERR_INVALIDGROUP;
4545 if ( DPQ_IS_EMPTY( gdata->groups ) )
4546 return DP_OK;
4549 for( glist = DPQ_FIRST( gdata->groups ); ; glist = DPQ_NEXT( glist->groups ) )
4551 /* FIXME: Should check flags for match here */
4552 if ( !(*enumplayercb)( glist->lpGData->dpid, DPPLAYERTYPE_GROUP, &glist->lpGData->name,
4553 flags, context ) )
4554 return DP_OK; /* User requested break */
4556 if ( DPQ_IS_ENDOFLIST( glist->groups ) )
4557 break;
4560 return DP_OK;
4563 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupConnectionSettings( IDirectPlay3A *iface,
4564 DWORD flags, DPID group, void *data, DWORD *size )
4566 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4567 return IDirectPlayX_GetGroupConnectionSettings( &This->IDirectPlay4A_iface, flags, group,
4568 data, size );
4571 static HRESULT WINAPI IDirectPlay3Impl_GetGroupConnectionSettings( IDirectPlay3 *iface,
4572 DWORD flags, DPID group, void *data, DWORD *size )
4574 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4575 return IDirectPlayX_GetGroupConnectionSettings( &This->IDirectPlay4_iface, flags, group,
4576 data, size );
4579 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupConnectionSettings( IDirectPlay4A *iface,
4580 DWORD flags, DPID group, void *data, DWORD *size )
4582 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4583 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, flags, group, data, size );
4584 return DP_OK;
4587 static HRESULT WINAPI IDirectPlay4Impl_GetGroupConnectionSettings( IDirectPlay4 *iface, DWORD flags,
4588 DPID group, void *data, DWORD *size )
4590 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4591 FIXME( "(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, flags, group, data, size );
4592 return DP_OK;
4595 static BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
4596 REFGUID guidDataType,
4597 DWORD dwDataSize,
4598 LPCVOID lpData,
4599 LPVOID lpContext )
4601 /* Looking for the GUID of the provider to load */
4602 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
4603 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
4606 TRACE( "Found SP/LP (%s) %s (data size = 0x%08x)\n",
4607 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
4609 if( dwDataSize != sizeof( GUID ) )
4611 ERR( "Invalid sp/lp guid size 0x%08x\n", dwDataSize );
4614 memcpy( lpContext, lpData, dwDataSize );
4616 /* There shouldn't be more than 1 GUID/compound address */
4617 return FALSE;
4620 /* Still waiting for what we want */
4621 return TRUE;
4625 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
4626 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
4628 UINT i;
4629 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4630 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
4631 LPCSTR guidDataSubKey = "Guid";
4632 LPCSTR majVerDataSubKey = "dwReserved1";
4633 LPCSTR minVerDataSubKey = "dwReserved2";
4634 LPCSTR pathSubKey = "Path";
4636 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
4638 /* FIXME: Cloned code with a quick hack. */
4639 for( i=0; i<2; i++ )
4641 HKEY hkResult;
4642 LPCSTR searchSubKey;
4643 char subKeyName[51];
4644 DWORD dwIndex, sizeOfSubKeyName=50;
4645 FILETIME filetime;
4647 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
4648 *lpbIsDpSp = (i == 0) ? TRUE : FALSE;
4651 /* Need to loop over the service providers in the registry */
4652 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4653 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4655 /* Hmmm. Does this mean that there are no service providers? */
4656 ERR(": no service providers?\n");
4657 return 0;
4660 /* Traverse all the service providers we have available */
4661 for( dwIndex=0;
4662 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4663 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4664 ++dwIndex, sizeOfSubKeyName=51 )
4667 HKEY hkServiceProvider;
4668 GUID serviceProviderGUID;
4669 DWORD returnType, sizeOfReturnBuffer = 255;
4670 char returnBuffer[256];
4671 WCHAR buff[51];
4672 DWORD dwTemp, len;
4674 TRACE(" this time through: %s\n", subKeyName );
4676 /* Get a handle for this particular service provider */
4677 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4678 &hkServiceProvider ) != ERROR_SUCCESS )
4680 ERR(": what the heck is going on?\n" );
4681 continue;
4684 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4685 NULL, &returnType, (LPBYTE)returnBuffer,
4686 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4688 ERR(": missing GUID registry data members\n" );
4689 continue;
4692 /* FIXME: Check return types to ensure we're interpreting data right */
4693 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4694 CLSIDFromString( buff, &serviceProviderGUID );
4695 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4697 /* Determine if this is the Service Provider that the user asked for */
4698 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
4700 continue;
4703 if( i == 0 ) /* DP SP */
4705 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
4706 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
4707 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
4710 sizeOfReturnBuffer = 255;
4712 /* Get dwReserved1 */
4713 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
4714 NULL, &returnType, (LPBYTE)returnBuffer,
4715 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4717 ERR(": missing dwReserved1 registry data members\n") ;
4718 continue;
4721 if( i == 0 )
4722 memcpy( &lpSpData->dwReserved1, returnBuffer, sizeof(lpSpData->dwReserved1) );
4724 sizeOfReturnBuffer = 255;
4726 /* Get dwReserved2 */
4727 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4728 NULL, &returnType, (LPBYTE)returnBuffer,
4729 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4731 ERR(": missing dwReserved1 registry data members\n") ;
4732 continue;
4735 if( i == 0 )
4736 memcpy( &lpSpData->dwReserved2, returnBuffer, sizeof(lpSpData->dwReserved2) );
4738 sizeOfReturnBuffer = 255;
4740 /* Get the path for this service provider */
4741 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
4742 NULL, NULL, (LPBYTE)returnBuffer,
4743 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
4745 ERR(": missing PATH registry data members: 0x%08x\n", dwTemp );
4746 continue;
4749 TRACE( "Loading %s\n", returnBuffer );
4750 return LoadLibraryA( returnBuffer );
4754 return 0;
4757 static HRESULT DP_InitializeDPSP( IDirectPlayImpl *This, HMODULE hServiceProvider )
4759 HRESULT hr;
4760 LPDPSP_SPINIT SPInit;
4762 /* Initialize the service provider by calling SPInit */
4763 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4765 if( SPInit == NULL )
4767 ERR( "Service provider doesn't provide SPInit interface?\n" );
4768 FreeLibrary( hServiceProvider );
4769 return DPERR_UNAVAILABLE;
4772 TRACE( "Calling SPInit (DP SP entry point)\n" );
4774 hr = (*SPInit)( &This->dp2->spData );
4776 if( FAILED(hr) )
4778 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4779 FreeLibrary( hServiceProvider );
4780 return hr;
4783 /* FIXME: Need to verify the sanity of the returned callback table
4784 * using IsBadCodePtr */
4785 This->dp2->bSPInitialized = TRUE;
4787 /* This interface is now initialized as a DP object */
4788 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
4790 /* Store the handle of the module so that we can unload it later */
4791 This->dp2->hServiceProvider = hServiceProvider;
4793 return hr;
4796 static HRESULT DP_InitializeDPLSP( IDirectPlayImpl *This, HMODULE hLobbyProvider )
4798 HRESULT hr;
4799 LPSP_INIT DPLSPInit;
4801 /* Initialize the service provider by calling SPInit */
4802 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
4804 if( DPLSPInit == NULL )
4806 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4807 FreeLibrary( hLobbyProvider );
4808 return DPERR_UNAVAILABLE;
4811 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4813 hr = (*DPLSPInit)( &This->dp2->dplspData );
4815 if( FAILED(hr) )
4817 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4818 FreeLibrary( hLobbyProvider );
4819 return hr;
4822 /* FIXME: Need to verify the sanity of the returned callback table
4823 * using IsBadCodePtr */
4825 This->dp2->bDPLSPInitialized = TRUE;
4827 /* This interface is now initialized as a lobby object */
4828 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
4830 /* Store the handle of the module so that we can unload it later */
4831 This->dp2->hDPLobbyProvider = hLobbyProvider;
4833 return hr;
4836 static HRESULT WINAPI IDirectPlay3AImpl_InitializeConnection( IDirectPlay3A *iface,
4837 void *connection, DWORD flags )
4839 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4840 return IDirectPlayX_InitializeConnection( &This->IDirectPlay4A_iface, connection, flags );
4843 static HRESULT WINAPI IDirectPlay3Impl_InitializeConnection( IDirectPlay3 *iface,
4844 void *connection, DWORD flags )
4846 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4847 return IDirectPlayX_InitializeConnection( &This->IDirectPlay4_iface, connection, flags );
4850 static HRESULT WINAPI IDirectPlay4AImpl_InitializeConnection( IDirectPlay4A *iface,
4851 void *connection, DWORD flags )
4853 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4854 return IDirectPlayX_InitializeConnection( &This->IDirectPlay4_iface, connection, flags );
4857 static HRESULT WINAPI IDirectPlay4Impl_InitializeConnection( IDirectPlay4 *iface,
4858 void *connection, DWORD flags )
4860 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4861 HMODULE servprov;
4862 GUID sp;
4863 const DWORD size = 80; /* FIXME: Need to calculate it correctly */
4864 BOOL is_dp_sp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4865 HRESULT hr;
4867 TRACE( "(%p)->(%p,0x%08x)\n", This, connection, flags );
4869 if ( !connection )
4870 return DPERR_INVALIDPARAMS;
4872 if ( flags )
4873 return DPERR_INVALIDFLAGS;
4875 if ( This->dp2->connectionInitialized != NO_PROVIDER )
4876 return DPERR_ALREADYINITIALIZED;
4878 /* Find out what the requested SP is and how large this buffer is */
4879 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, connection, size, &sp );
4881 if ( FAILED(hr) )
4883 ERR( "Invalid compound address?\n" );
4884 return DPERR_UNAVAILABLE;
4887 /* Load the service provider */
4888 servprov = DP_LoadSP( &sp, &This->dp2->spData, &is_dp_sp );
4890 if ( !servprov )
4892 ERR( "Unable to load service provider %s\n", debugstr_guid(&sp) );
4893 return DPERR_UNAVAILABLE;
4896 if ( is_dp_sp )
4898 /* Fill in what we can of the Service Provider required information.
4899 * The rest was be done in DP_LoadSP
4901 This->dp2->spData.lpAddress = connection;
4902 This->dp2->spData.dwAddressSize = size;
4903 This->dp2->spData.lpGuid = &sp;
4904 hr = DP_InitializeDPSP( This, servprov );
4906 else
4908 This->dp2->dplspData.lpAddress = connection;
4909 hr = DP_InitializeDPLSP( This, servprov );
4912 if ( FAILED(hr) )
4913 return hr;
4915 return DP_OK;
4918 static HRESULT WINAPI IDirectPlay3AImpl_SecureOpen( IDirectPlay3A *iface,
4919 const DPSESSIONDESC2 *sdesc, DWORD flags, const DPSECURITYDESC *security,
4920 const DPCREDENTIALS *credentials )
4922 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4923 return IDirectPlayX_SecureOpen( &This->IDirectPlay4A_iface, sdesc, flags, security,
4924 credentials );
4927 static HRESULT WINAPI IDirectPlay3Impl_SecureOpen( IDirectPlay3 *iface,
4928 const DPSESSIONDESC2 *sdesc, DWORD flags, const DPSECURITYDESC *security,
4929 const DPCREDENTIALS *credentials )
4931 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4932 return IDirectPlayX_SecureOpen( &This->IDirectPlay4_iface, sdesc, flags, security,
4933 credentials );
4936 static HRESULT WINAPI IDirectPlay4AImpl_SecureOpen( IDirectPlay4A *iface,
4937 const DPSESSIONDESC2 *lpsd, DWORD dwFlags, const DPSECURITYDESC *lpSecurity,
4938 const DPCREDENTIALS *lpCredentials )
4940 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4941 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4944 static HRESULT WINAPI IDirectPlay4Impl_SecureOpen( IDirectPlay4 *iface,
4945 const DPSESSIONDESC2 *lpsd, DWORD dwFlags, const DPSECURITYDESC *lpSecurity,
4946 const DPCREDENTIALS *lpCredentials )
4948 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4949 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4952 static HRESULT WINAPI IDirectPlay3AImpl_SendChatMessage( IDirectPlay3A *iface, DPID from, DPID to,
4953 DWORD flags, DPCHAT *chatmsg )
4955 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4956 return IDirectPlayX_SendChatMessage( &This->IDirectPlay4A_iface, from, to, flags, chatmsg );
4959 static HRESULT WINAPI IDirectPlay3Impl_SendChatMessage( IDirectPlay3 *iface, DPID from, DPID to,
4960 DWORD flags, DPCHAT *chatmsg )
4962 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4963 return IDirectPlayX_SendChatMessage( &This->IDirectPlay4_iface, from, to, flags, chatmsg );
4966 static HRESULT WINAPI IDirectPlay4AImpl_SendChatMessage( IDirectPlay4A *iface, DPID from,
4967 DPID to, DWORD flags, DPCHAT *chatmsg )
4969 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4970 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, from, to, flags, chatmsg );
4971 return DP_OK;
4974 static HRESULT WINAPI IDirectPlay4Impl_SendChatMessage( IDirectPlay4 *iface, DPID from, DPID to,
4975 DWORD flags, DPCHAT *chatmsg )
4977 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4978 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, from, to, flags, chatmsg );
4979 return DP_OK;
4982 static HRESULT WINAPI IDirectPlay3AImpl_SetGroupConnectionSettings( IDirectPlay3A *iface,
4983 DWORD flags, DPID group, DPLCONNECTION *connection )
4985 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4986 return IDirectPlayX_SetGroupConnectionSettings( &This->IDirectPlay4A_iface, flags, group,
4987 connection );
4990 static HRESULT WINAPI IDirectPlay3Impl_SetGroupConnectionSettings( IDirectPlay3 *iface,
4991 DWORD flags, DPID group, DPLCONNECTION *connection )
4993 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4994 return IDirectPlayX_SetGroupConnectionSettings( &This->IDirectPlay4_iface, flags, group,
4995 connection );
4998 static HRESULT WINAPI IDirectPlay4AImpl_SetGroupConnectionSettings( IDirectPlay4A *iface,
4999 DWORD flags, DPID group, DPLCONNECTION *connection )
5001 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5002 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, flags, group, connection );
5003 return DP_OK;
5006 static HRESULT WINAPI IDirectPlay4Impl_SetGroupConnectionSettings( IDirectPlay4 *iface, DWORD flags,
5007 DPID group, DPLCONNECTION *connection )
5009 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5010 FIXME( "(%p)->(0x%08x,0x%08x,%p): stub\n", This, flags, group, connection );
5011 return DP_OK;
5014 static HRESULT WINAPI IDirectPlay3AImpl_StartSession( IDirectPlay3A *iface, DWORD flags,
5015 DPID group )
5017 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
5018 return IDirectPlayX_StartSession( &This->IDirectPlay4A_iface, flags, group );
5021 static HRESULT WINAPI IDirectPlay3Impl_StartSession( IDirectPlay3 *iface, DWORD flags,
5022 DPID group )
5024 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
5025 return IDirectPlayX_StartSession( &This->IDirectPlay4_iface, flags, group );
5028 static HRESULT WINAPI IDirectPlay4AImpl_StartSession( IDirectPlay4A *iface, DWORD flags,
5029 DPID group )
5031 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5032 return IDirectPlayX_StartSession( &This->IDirectPlay4_iface, flags, group );
5035 static HRESULT WINAPI IDirectPlay4Impl_StartSession( IDirectPlay4 *iface, DWORD flags, DPID group )
5037 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5038 FIXME( "(%p)->(0x%08x,0x%08x): stub\n", This, flags, group );
5039 return DP_OK;
5042 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupFlags( IDirectPlay3A *iface, DPID group,
5043 DWORD *flags )
5045 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
5046 return IDirectPlayX_GetGroupFlags( &This->IDirectPlay4A_iface, group, flags );
5049 static HRESULT WINAPI IDirectPlay3Impl_GetGroupFlags( IDirectPlay3 *iface, DPID group,
5050 DWORD *flags )
5052 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
5053 return IDirectPlayX_GetGroupFlags( &This->IDirectPlay4_iface, group, flags );
5056 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupFlags( IDirectPlay4A *iface, DPID group,
5057 DWORD *flags )
5059 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5060 return IDirectPlayX_GetGroupFlags( &This->IDirectPlay4_iface, group, flags );
5063 static HRESULT WINAPI IDirectPlay4Impl_GetGroupFlags( IDirectPlay4 *iface, DPID group,
5064 DWORD *flags )
5066 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5067 FIXME( "(%p)->(0x%08x,%p): stub\n", This, group, flags );
5068 return DP_OK;
5071 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupParent( IDirectPlay3A *iface, DPID group,
5072 DPID *parent )
5074 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
5075 return IDirectPlayX_GetGroupParent( &This->IDirectPlay4A_iface, group, parent );
5078 static HRESULT WINAPI IDirectPlay3Impl_GetGroupParent( IDirectPlay3 *iface, DPID group,
5079 DPID *parent )
5081 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
5082 return IDirectPlayX_GetGroupParent( &This->IDirectPlay4_iface, group, parent );
5085 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupParent( IDirectPlay4A *iface, DPID group,
5086 DPID *parent )
5088 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5089 return IDirectPlayX_GetGroupParent( &This->IDirectPlay4_iface, group, parent );
5092 static HRESULT WINAPI IDirectPlay4Impl_GetGroupParent( IDirectPlay4 *iface, DPID group,
5093 DPID *parent )
5095 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5096 lpGroupData gdata;
5098 TRACE( "(%p)->(0x%08x,%p)\n", This, group, parent );
5100 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
5101 return DPERR_INVALIDGROUP;
5103 *parent = gdata->dpid;
5105 return DP_OK;
5108 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerAccount( IDirectPlay3A *iface, DPID player,
5109 DWORD flags, void *data, DWORD *size )
5111 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
5112 return IDirectPlayX_GetPlayerAccount( &This->IDirectPlay4A_iface, player, flags, data, size );
5115 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerAccount( IDirectPlay3 *iface, DPID player,
5116 DWORD flags, void *data, DWORD *size )
5118 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
5119 return IDirectPlayX_GetPlayerAccount( &This->IDirectPlay4_iface, player, flags, data, size );
5122 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerAccount( IDirectPlay4A *iface, DPID player,
5123 DWORD flags, void *data, DWORD *size )
5125 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5126 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, player, flags, data, size );
5127 return DP_OK;
5130 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerAccount( IDirectPlay4 *iface, DPID player,
5131 DWORD flags, void *data, DWORD *size )
5133 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5134 FIXME( "(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, player, flags, data, size );
5135 return DP_OK;
5138 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerFlags( IDirectPlay3A *iface, DPID player,
5139 DWORD *flags )
5141 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
5142 return IDirectPlayX_GetPlayerFlags( &This->IDirectPlay4A_iface, player, flags );
5145 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerFlags( IDirectPlay3 *iface, DPID player,
5146 DWORD *flags )
5148 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
5149 return IDirectPlayX_GetPlayerFlags( &This->IDirectPlay4_iface, player, flags );
5152 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerFlags( IDirectPlay4A *iface, DPID player,
5153 DWORD *flags )
5155 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5156 return IDirectPlayX_GetPlayerFlags( &This->IDirectPlay4_iface, player, flags );
5159 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerFlags( IDirectPlay4 *iface, DPID player,
5160 DWORD *flags )
5162 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5163 FIXME( "(%p)->(0x%08x,%p): stub\n", This, player, flags );
5164 return DP_OK;
5167 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupOwner( IDirectPlay4A *iface, DPID group,
5168 DPID *owner )
5170 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5171 return IDirectPlayX_GetGroupOwner( &This->IDirectPlay4_iface, group, owner );
5174 static HRESULT WINAPI IDirectPlay4Impl_GetGroupOwner( IDirectPlay4 *iface, DPID group,
5175 DPID *owner )
5177 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5178 FIXME( "(%p)->(0x%08x,%p): stub\n", This, group, owner );
5179 return DP_OK;
5182 static HRESULT WINAPI IDirectPlay4AImpl_SetGroupOwner( IDirectPlay4A *iface, DPID group,
5183 DPID owner )
5185 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5186 return IDirectPlayX_SetGroupOwner( &This->IDirectPlay4_iface, group, owner );
5189 static HRESULT WINAPI IDirectPlay4Impl_SetGroupOwner( IDirectPlay4 *iface, DPID group ,
5190 DPID owner )
5192 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5193 FIXME( "(%p)->(0x%08x,0x%08x): stub\n", This, group, owner );
5194 return DP_OK;
5197 static HRESULT WINAPI IDirectPlay4AImpl_SendEx( IDirectPlay4A *iface, DPID from, DPID to,
5198 DWORD flags, void *data, DWORD size, DWORD priority, DWORD timeout, void *context,
5199 DWORD *msgid )
5201 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5202 return IDirectPlayX_SendEx( &This->IDirectPlay4_iface, from, to, flags, data, size, priority,
5203 timeout, context, msgid );
5206 static HRESULT WINAPI IDirectPlay4Impl_SendEx( IDirectPlay4 *iface, DPID from, DPID to,
5207 DWORD flags, void *data, DWORD size, DWORD priority, DWORD timeout, void *context,
5208 DWORD *msgid )
5210 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5212 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,0x%08x,0x%08x,0x%08x,%p,%p): semi-stub\n",
5213 This, from, to, flags, data, size, priority, timeout, context, msgid );
5215 if ( This->dp2->connectionInitialized == NO_PROVIDER )
5216 return DPERR_UNINITIALIZED;
5218 /* FIXME: Add parameter checking */
5219 /* FIXME: First call to this needs to acquire a message id which will be
5220 * used for multiple sends
5223 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
5225 /* Verify that the message is being sent from a valid local player. The
5226 * from player may be anonymous DPID_UNKNOWN
5228 if ( from != DPID_UNKNOWN && !DP_FindPlayer( This, from ) )
5230 WARN( "INFO: Invalid from player 0x%08x\n", from );
5231 return DPERR_INVALIDPLAYER;
5234 /* Verify that the message is being sent to a valid player, group or to
5235 * everyone. If it's valid, send it to those players.
5237 if ( to == DPID_ALLPLAYERS )
5239 /* See if SP has the ability to multicast. If so, use it */
5240 if ( This->dp2->spData.lpCB->SendToGroupEx )
5241 FIXME( "Use group sendex to group 0\n" );
5242 else if ( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
5243 FIXME( "Use obsolete group send to group 0\n" );
5244 else /* No multicast, multiplicate */
5245 FIXME( "Send to all players using EnumPlayersInGroup\n" );
5247 else if ( DP_FindPlayer( This, to ) )
5249 /* Have the service provider send this message */
5250 /* FIXME: Could optimize for local interface sends */
5251 return DP_SP_SendEx( This, flags, data, size, priority, timeout, context, msgid );
5253 else if ( DP_FindAnyGroup( This, to ) )
5255 /* See if SP has the ability to multicast. If so, use it */
5256 if ( This->dp2->spData.lpCB->SendToGroupEx )
5257 FIXME( "Use group sendex\n" );
5258 else if ( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
5259 FIXME( "Use obsolete group send to group\n" );
5260 else /* No multicast, multiplicate */
5261 FIXME( "Send to all players using EnumPlayersInGroup\n" );
5264 else
5265 return DPERR_INVALIDPLAYER;
5267 /* FIXME: Should return what the send returned */
5268 return DP_OK;
5271 static HRESULT DP_SP_SendEx( IDirectPlayImpl *This, DWORD dwFlags, void *lpData, DWORD dwDataSize,
5272 DWORD dwPriority, DWORD dwTimeout, void *lpContext, DWORD *lpdwMsgID )
5274 LPDPMSG lpMElem;
5276 FIXME( ": stub\n" );
5278 /* FIXME: This queuing should only be for async messages */
5280 lpMElem = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpMElem ) );
5281 lpMElem->msg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
5283 CopyMemory( lpMElem->msg, lpData, dwDataSize );
5285 /* FIXME: Need to queue based on priority */
5286 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
5288 return DP_OK;
5291 static HRESULT WINAPI IDirectPlay4AImpl_GetMessageQueue( IDirectPlay4A *iface, DPID from, DPID to,
5292 DWORD flags, DWORD *msgs, DWORD *bytes )
5294 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5295 return IDirectPlayX_GetMessageQueue( &This->IDirectPlay4_iface, from, to, flags, msgs, bytes );
5298 static HRESULT WINAPI IDirectPlay4Impl_GetMessageQueue( IDirectPlay4 *iface, DPID from, DPID to,
5299 DWORD flags, DWORD *msgs, DWORD *bytes )
5301 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5302 HRESULT hr = DP_OK;
5304 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%p): semi-stub\n", This, from, to, flags, msgs, bytes );
5306 /* FIXME: Do we need to do from and to sanity checking here? */
5307 /* FIXME: What about sends which are not immediate? */
5309 if ( This->dp2->spData.lpCB->GetMessageQueue )
5311 DPSP_GETMESSAGEQUEUEDATA data;
5313 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
5315 /* FIXME: None of this is documented :( */
5316 data.lpISP = This->dp2->spData.lpISP;
5317 data.dwFlags = flags;
5318 data.idFrom = from;
5319 data.idTo = to;
5320 data.lpdwNumMsgs = msgs;
5321 data.lpdwNumBytes = bytes;
5323 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
5325 else
5326 FIXME( "No SP for GetMessageQueue - fake some data\n" );
5328 return hr;
5331 static HRESULT dplay_cancelmsg ( IDirectPlayImpl* This, DWORD msgid, DWORD flags, DWORD minprio,
5332 DWORD maxprio )
5334 HRESULT hr = DP_OK;
5336 FIXME( "(%p)->(0x%08x,0x%08x): semi stub\n", This, msgid, flags );
5338 if ( This->dp2->spData.lpCB->Cancel )
5340 DPSP_CANCELDATA data;
5342 TRACE( "Calling SP Cancel\n" );
5344 /* FIXME: Undocumented callback */
5346 data.lpISP = This->dp2->spData.lpISP;
5347 data.dwFlags = flags;
5348 data.lprglpvSPMsgID = NULL;
5349 data.cSPMsgID = msgid;
5350 data.dwMinPriority = minprio;
5351 data.dwMaxPriority = maxprio;
5353 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
5355 else
5356 FIXME( "SP doesn't implement Cancel\n" );
5358 return hr;
5361 static HRESULT WINAPI IDirectPlay4AImpl_CancelMessage( IDirectPlay4A *iface, DWORD msgid,
5362 DWORD flags )
5364 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5365 return IDirectPlayX_CancelMessage( &This->IDirectPlay4_iface, msgid, flags );
5368 static HRESULT WINAPI IDirectPlay4Impl_CancelMessage( IDirectPlay4 *iface, DWORD msgid,
5369 DWORD flags )
5371 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5373 if ( flags != 0 )
5374 return DPERR_INVALIDFLAGS;
5376 if ( msgid == 0 )
5377 flags |= DPCANCELSEND_ALL;
5379 return dplay_cancelmsg( This, msgid, flags, 0, 0 );
5382 static HRESULT WINAPI IDirectPlay4AImpl_CancelPriority( IDirectPlay4A *iface, DWORD minprio,
5383 DWORD maxprio, DWORD flags )
5385 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5386 return IDirectPlayX_CancelPriority( &This->IDirectPlay4_iface, minprio, maxprio, flags );
5389 static HRESULT WINAPI IDirectPlay4Impl_CancelPriority( IDirectPlay4 *iface, DWORD minprio,
5390 DWORD maxprio, DWORD flags )
5392 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5394 if ( flags != 0 )
5395 return DPERR_INVALIDFLAGS;
5397 return dplay_cancelmsg( This, 0, DPCANCELSEND_PRIORITY, minprio, maxprio );
5400 static const IDirectPlay2Vtbl dp2_vt =
5402 IDirectPlay2Impl_QueryInterface,
5403 IDirectPlay2Impl_AddRef,
5404 IDirectPlay2Impl_Release,
5405 IDirectPlay2Impl_AddPlayerToGroup,
5406 IDirectPlay2Impl_Close,
5407 IDirectPlay2Impl_CreateGroup,
5408 IDirectPlay2Impl_CreatePlayer,
5409 IDirectPlay2Impl_DeletePlayerFromGroup,
5410 IDirectPlay2Impl_DestroyGroup,
5411 IDirectPlay2Impl_DestroyPlayer,
5412 IDirectPlay2Impl_EnumGroupPlayers,
5413 IDirectPlay2Impl_EnumGroups,
5414 IDirectPlay2Impl_EnumPlayers,
5415 IDirectPlay2Impl_EnumSessions,
5416 IDirectPlay2Impl_GetCaps,
5417 IDirectPlay2Impl_GetGroupData,
5418 IDirectPlay2Impl_GetGroupName,
5419 IDirectPlay2Impl_GetMessageCount,
5420 IDirectPlay2Impl_GetPlayerAddress,
5421 IDirectPlay2Impl_GetPlayerCaps,
5422 IDirectPlay2Impl_GetPlayerData,
5423 IDirectPlay2Impl_GetPlayerName,
5424 IDirectPlay2Impl_GetSessionDesc,
5425 IDirectPlay2Impl_Initialize,
5426 IDirectPlay2Impl_Open,
5427 IDirectPlay2Impl_Receive,
5428 IDirectPlay2Impl_Send,
5429 IDirectPlay2Impl_SetGroupData,
5430 IDirectPlay2Impl_SetGroupName,
5431 IDirectPlay2Impl_SetPlayerData,
5432 IDirectPlay2Impl_SetPlayerName,
5433 IDirectPlay2Impl_SetSessionDesc
5436 static const IDirectPlay2Vtbl dp2A_vt =
5438 IDirectPlay2AImpl_QueryInterface,
5439 IDirectPlay2AImpl_AddRef,
5440 IDirectPlay2AImpl_Release,
5441 IDirectPlay2AImpl_AddPlayerToGroup,
5442 IDirectPlay2AImpl_Close,
5443 IDirectPlay2AImpl_CreateGroup,
5444 IDirectPlay2AImpl_CreatePlayer,
5445 IDirectPlay2AImpl_DeletePlayerFromGroup,
5446 IDirectPlay2AImpl_DestroyGroup,
5447 IDirectPlay2AImpl_DestroyPlayer,
5448 IDirectPlay2AImpl_EnumGroupPlayers,
5449 IDirectPlay2AImpl_EnumGroups,
5450 IDirectPlay2AImpl_EnumPlayers,
5451 IDirectPlay2AImpl_EnumSessions,
5452 IDirectPlay2AImpl_GetCaps,
5453 IDirectPlay2AImpl_GetGroupData,
5454 IDirectPlay2AImpl_GetGroupName,
5455 IDirectPlay2AImpl_GetMessageCount,
5456 IDirectPlay2AImpl_GetPlayerAddress,
5457 IDirectPlay2AImpl_GetPlayerCaps,
5458 IDirectPlay2AImpl_GetPlayerData,
5459 IDirectPlay2AImpl_GetPlayerName,
5460 IDirectPlay2AImpl_GetSessionDesc,
5461 IDirectPlay2AImpl_Initialize,
5462 IDirectPlay2AImpl_Open,
5463 IDirectPlay2AImpl_Receive,
5464 IDirectPlay2AImpl_Send,
5465 IDirectPlay2AImpl_SetGroupData,
5466 IDirectPlay2AImpl_SetGroupName,
5467 IDirectPlay2AImpl_SetPlayerData,
5468 IDirectPlay2AImpl_SetPlayerName,
5469 IDirectPlay2AImpl_SetSessionDesc
5472 static const IDirectPlay3Vtbl dp3_vt =
5474 IDirectPlay3Impl_QueryInterface,
5475 IDirectPlay3Impl_AddRef,
5476 IDirectPlay3Impl_Release,
5477 IDirectPlay3Impl_AddPlayerToGroup,
5478 IDirectPlay3Impl_Close,
5479 IDirectPlay3Impl_CreateGroup,
5480 IDirectPlay3Impl_CreatePlayer,
5481 IDirectPlay3Impl_DeletePlayerFromGroup,
5482 IDirectPlay3Impl_DestroyGroup,
5483 IDirectPlay3Impl_DestroyPlayer,
5484 IDirectPlay3Impl_EnumGroupPlayers,
5485 IDirectPlay3Impl_EnumGroups,
5486 IDirectPlay3Impl_EnumPlayers,
5487 IDirectPlay3Impl_EnumSessions,
5488 IDirectPlay3Impl_GetCaps,
5489 IDirectPlay3Impl_GetGroupData,
5490 IDirectPlay3Impl_GetGroupName,
5491 IDirectPlay3Impl_GetMessageCount,
5492 IDirectPlay3Impl_GetPlayerAddress,
5493 IDirectPlay3Impl_GetPlayerCaps,
5494 IDirectPlay3Impl_GetPlayerData,
5495 IDirectPlay3Impl_GetPlayerName,
5496 IDirectPlay3Impl_GetSessionDesc,
5497 IDirectPlay3Impl_Initialize,
5498 IDirectPlay3Impl_Open,
5499 IDirectPlay3Impl_Receive,
5500 IDirectPlay3Impl_Send,
5501 IDirectPlay3Impl_SetGroupData,
5502 IDirectPlay3Impl_SetGroupName,
5503 IDirectPlay3Impl_SetPlayerData,
5504 IDirectPlay3Impl_SetPlayerName,
5505 IDirectPlay3Impl_SetSessionDesc,
5506 IDirectPlay3Impl_AddGroupToGroup,
5507 IDirectPlay3Impl_CreateGroupInGroup,
5508 IDirectPlay3Impl_DeleteGroupFromGroup,
5509 IDirectPlay3Impl_EnumConnections,
5510 IDirectPlay3Impl_EnumGroupsInGroup,
5511 IDirectPlay3Impl_GetGroupConnectionSettings,
5512 IDirectPlay3Impl_InitializeConnection,
5513 IDirectPlay3Impl_SecureOpen,
5514 IDirectPlay3Impl_SendChatMessage,
5515 IDirectPlay3Impl_SetGroupConnectionSettings,
5516 IDirectPlay3Impl_StartSession,
5517 IDirectPlay3Impl_GetGroupFlags,
5518 IDirectPlay3Impl_GetGroupParent,
5519 IDirectPlay3Impl_GetPlayerAccount,
5520 IDirectPlay3Impl_GetPlayerFlags
5523 static const IDirectPlay3Vtbl dp3A_vt =
5525 IDirectPlay3AImpl_QueryInterface,
5526 IDirectPlay3AImpl_AddRef,
5527 IDirectPlay3AImpl_Release,
5528 IDirectPlay3AImpl_AddPlayerToGroup,
5529 IDirectPlay3AImpl_Close,
5530 IDirectPlay3AImpl_CreateGroup,
5531 IDirectPlay3AImpl_CreatePlayer,
5532 IDirectPlay3AImpl_DeletePlayerFromGroup,
5533 IDirectPlay3AImpl_DestroyGroup,
5534 IDirectPlay3AImpl_DestroyPlayer,
5535 IDirectPlay3AImpl_EnumGroupPlayers,
5536 IDirectPlay3AImpl_EnumGroups,
5537 IDirectPlay3AImpl_EnumPlayers,
5538 IDirectPlay3AImpl_EnumSessions,
5539 IDirectPlay3AImpl_GetCaps,
5540 IDirectPlay3AImpl_GetGroupData,
5541 IDirectPlay3AImpl_GetGroupName,
5542 IDirectPlay3AImpl_GetMessageCount,
5543 IDirectPlay3AImpl_GetPlayerAddress,
5544 IDirectPlay3AImpl_GetPlayerCaps,
5545 IDirectPlay3AImpl_GetPlayerData,
5546 IDirectPlay3AImpl_GetPlayerName,
5547 IDirectPlay3AImpl_GetSessionDesc,
5548 IDirectPlay3AImpl_Initialize,
5549 IDirectPlay3AImpl_Open,
5550 IDirectPlay3AImpl_Receive,
5551 IDirectPlay3AImpl_Send,
5552 IDirectPlay3AImpl_SetGroupData,
5553 IDirectPlay3AImpl_SetGroupName,
5554 IDirectPlay3AImpl_SetPlayerData,
5555 IDirectPlay3AImpl_SetPlayerName,
5556 IDirectPlay3AImpl_SetSessionDesc,
5557 IDirectPlay3AImpl_AddGroupToGroup,
5558 IDirectPlay3AImpl_CreateGroupInGroup,
5559 IDirectPlay3AImpl_DeleteGroupFromGroup,
5560 IDirectPlay3AImpl_EnumConnections,
5561 IDirectPlay3AImpl_EnumGroupsInGroup,
5562 IDirectPlay3AImpl_GetGroupConnectionSettings,
5563 IDirectPlay3AImpl_InitializeConnection,
5564 IDirectPlay3AImpl_SecureOpen,
5565 IDirectPlay3AImpl_SendChatMessage,
5566 IDirectPlay3AImpl_SetGroupConnectionSettings,
5567 IDirectPlay3AImpl_StartSession,
5568 IDirectPlay3AImpl_GetGroupFlags,
5569 IDirectPlay3AImpl_GetGroupParent,
5570 IDirectPlay3AImpl_GetPlayerAccount,
5571 IDirectPlay3AImpl_GetPlayerFlags
5574 static const IDirectPlay4Vtbl dp4_vt =
5576 IDirectPlay4Impl_QueryInterface,
5577 IDirectPlay4Impl_AddRef,
5578 IDirectPlay4Impl_Release,
5579 IDirectPlay4Impl_AddPlayerToGroup,
5580 IDirectPlay4Impl_Close,
5581 IDirectPlay4Impl_CreateGroup,
5582 IDirectPlay4Impl_CreatePlayer,
5583 IDirectPlay4Impl_DeletePlayerFromGroup,
5584 IDirectPlay4Impl_DestroyGroup,
5585 IDirectPlay4Impl_DestroyPlayer,
5586 IDirectPlay4Impl_EnumGroupPlayers,
5587 IDirectPlay4Impl_EnumGroups,
5588 IDirectPlay4Impl_EnumPlayers,
5589 IDirectPlay4Impl_EnumSessions,
5590 IDirectPlay4Impl_GetCaps,
5591 IDirectPlay4Impl_GetGroupData,
5592 IDirectPlay4Impl_GetGroupName,
5593 IDirectPlay4Impl_GetMessageCount,
5594 IDirectPlay4Impl_GetPlayerAddress,
5595 IDirectPlay4Impl_GetPlayerCaps,
5596 IDirectPlay4Impl_GetPlayerData,
5597 IDirectPlay4Impl_GetPlayerName,
5598 IDirectPlay4Impl_GetSessionDesc,
5599 IDirectPlay4Impl_Initialize,
5600 IDirectPlay4Impl_Open,
5601 IDirectPlay4Impl_Receive,
5602 IDirectPlay4Impl_Send,
5603 IDirectPlay4Impl_SetGroupData,
5604 IDirectPlay4Impl_SetGroupName,
5605 IDirectPlay4Impl_SetPlayerData,
5606 IDirectPlay4Impl_SetPlayerName,
5607 IDirectPlay4Impl_SetSessionDesc,
5608 IDirectPlay4Impl_AddGroupToGroup,
5609 IDirectPlay4Impl_CreateGroupInGroup,
5610 IDirectPlay4Impl_DeleteGroupFromGroup,
5611 IDirectPlay4Impl_EnumConnections,
5612 IDirectPlay4Impl_EnumGroupsInGroup,
5613 IDirectPlay4Impl_GetGroupConnectionSettings,
5614 IDirectPlay4Impl_InitializeConnection,
5615 IDirectPlay4Impl_SecureOpen,
5616 IDirectPlay4Impl_SendChatMessage,
5617 IDirectPlay4Impl_SetGroupConnectionSettings,
5618 IDirectPlay4Impl_StartSession,
5619 IDirectPlay4Impl_GetGroupFlags,
5620 IDirectPlay4Impl_GetGroupParent,
5621 IDirectPlay4Impl_GetPlayerAccount,
5622 IDirectPlay4Impl_GetPlayerFlags,
5623 IDirectPlay4Impl_GetGroupOwner,
5624 IDirectPlay4Impl_SetGroupOwner,
5625 IDirectPlay4Impl_SendEx,
5626 IDirectPlay4Impl_GetMessageQueue,
5627 IDirectPlay4Impl_CancelMessage,
5628 IDirectPlay4Impl_CancelPriority
5631 static const IDirectPlay4Vtbl dp4A_vt =
5633 IDirectPlay4AImpl_QueryInterface,
5634 IDirectPlay4AImpl_AddRef,
5635 IDirectPlay4AImpl_Release,
5636 IDirectPlay4AImpl_AddPlayerToGroup,
5637 IDirectPlay4AImpl_Close,
5638 IDirectPlay4AImpl_CreateGroup,
5639 IDirectPlay4AImpl_CreatePlayer,
5640 IDirectPlay4AImpl_DeletePlayerFromGroup,
5641 IDirectPlay4AImpl_DestroyGroup,
5642 IDirectPlay4AImpl_DestroyPlayer,
5643 IDirectPlay4AImpl_EnumGroupPlayers,
5644 IDirectPlay4AImpl_EnumGroups,
5645 IDirectPlay4AImpl_EnumPlayers,
5646 IDirectPlay4AImpl_EnumSessions,
5647 IDirectPlay4AImpl_GetCaps,
5648 IDirectPlay4AImpl_GetGroupData,
5649 IDirectPlay4AImpl_GetGroupName,
5650 IDirectPlay4AImpl_GetMessageCount,
5651 IDirectPlay4AImpl_GetPlayerAddress,
5652 IDirectPlay4AImpl_GetPlayerCaps,
5653 IDirectPlay4AImpl_GetPlayerData,
5654 IDirectPlay4AImpl_GetPlayerName,
5655 IDirectPlay4AImpl_GetSessionDesc,
5656 IDirectPlay4AImpl_Initialize,
5657 IDirectPlay4AImpl_Open,
5658 IDirectPlay4AImpl_Receive,
5659 IDirectPlay4AImpl_Send,
5660 IDirectPlay4AImpl_SetGroupData,
5661 IDirectPlay4AImpl_SetGroupName,
5662 IDirectPlay4AImpl_SetPlayerData,
5663 IDirectPlay4AImpl_SetPlayerName,
5664 IDirectPlay4AImpl_SetSessionDesc,
5665 IDirectPlay4AImpl_AddGroupToGroup,
5666 IDirectPlay4AImpl_CreateGroupInGroup,
5667 IDirectPlay4AImpl_DeleteGroupFromGroup,
5668 IDirectPlay4AImpl_EnumConnections,
5669 IDirectPlay4AImpl_EnumGroupsInGroup,
5670 IDirectPlay4AImpl_GetGroupConnectionSettings,
5671 IDirectPlay4AImpl_InitializeConnection,
5672 IDirectPlay4AImpl_SecureOpen,
5673 IDirectPlay4AImpl_SendChatMessage,
5674 IDirectPlay4AImpl_SetGroupConnectionSettings,
5675 IDirectPlay4AImpl_StartSession,
5676 IDirectPlay4AImpl_GetGroupFlags,
5677 IDirectPlay4AImpl_GetGroupParent,
5678 IDirectPlay4AImpl_GetPlayerAccount,
5679 IDirectPlay4AImpl_GetPlayerFlags,
5680 IDirectPlay4AImpl_GetGroupOwner,
5681 IDirectPlay4AImpl_SetGroupOwner,
5682 IDirectPlay4AImpl_SendEx,
5683 IDirectPlay4AImpl_GetMessageQueue,
5684 IDirectPlay4AImpl_CancelMessage,
5685 IDirectPlay4AImpl_CancelPriority
5688 HRESULT dplay_create( REFIID riid, void **ppv )
5690 IDirectPlayImpl *obj;
5691 HRESULT hr;
5693 TRACE( "(%s, %p)\n", debugstr_guid( riid ), ppv );
5695 *ppv = NULL;
5696 obj = HeapAlloc( GetProcessHeap(), 0, sizeof( *obj ) );
5697 if ( !obj )
5698 return DPERR_OUTOFMEMORY;
5700 obj->IDirectPlay_iface.lpVtbl = &dp_vt;
5701 obj->IDirectPlay2A_iface.lpVtbl = &dp2A_vt;
5702 obj->IDirectPlay2_iface.lpVtbl = &dp2_vt;
5703 obj->IDirectPlay3A_iface.lpVtbl = &dp3A_vt;
5704 obj->IDirectPlay3_iface.lpVtbl = &dp3_vt;
5705 obj->IDirectPlay4A_iface.lpVtbl = &dp4A_vt;
5706 obj->IDirectPlay4_iface.lpVtbl = &dp4_vt;
5707 obj->numIfaces = 1;
5708 obj->ref = 0;
5709 obj->ref2A = 0;
5710 obj->ref2 = 0;
5711 obj->ref3A = 0;
5712 obj->ref3 = 0;
5713 obj->ref4A = 0;
5714 obj->ref4 = 1;
5716 InitializeCriticalSection( &obj->lock );
5717 obj->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectPlayImpl.lock");
5719 if ( DP_CreateDirectPlay2( obj ) )
5720 hr = IDirectPlayX_QueryInterface( &obj->IDirectPlay4_iface, riid, ppv );
5721 else
5722 hr = DPERR_NOMEMORY;
5723 IDirectPlayX_Release( &obj->IDirectPlay4_iface );
5725 return hr;
5729 HRESULT DP_GetSPPlayerData( IDirectPlayImpl *lpDP, DPID idPlayer, void **lplpData )
5731 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5733 if( lpPlayer == NULL )
5735 return DPERR_INVALIDPLAYER;
5738 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
5740 return DP_OK;
5743 HRESULT DP_SetSPPlayerData( IDirectPlayImpl *lpDP, DPID idPlayer, void *lpData )
5745 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5747 if( lpPlayer == NULL )
5749 return DPERR_INVALIDPLAYER;
5752 lpPlayer->lpPData->lpSPPlayerData = lpData;
5754 return DP_OK;
5757 /***************************************************************************
5758 * DirectPlayEnumerateAW
5760 * The pointer to the structure lpContext will be filled with the
5761 * appropriate data for each service offered by the OS. These services are
5762 * not necessarily available on this particular machine but are defined
5763 * as simple service providers under the "Service Providers" registry key.
5764 * This structure is then passed to lpEnumCallback for each of the different
5765 * services.
5767 * This API is useful only for applications written using DirectX3 or
5768 * worse. It is superseded by IDirectPlay3::EnumConnections which also
5769 * gives information on the actual connections.
5771 * defn of a service provider:
5772 * A dynamic-link library used by DirectPlay to communicate over a network.
5773 * The service provider contains all the network-specific code required
5774 * to send and receive messages. Online services and network operators can
5775 * supply service providers to use specialized hardware, protocols, communications
5776 * media, and network resources.
5779 static HRESULT DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA,
5780 LPDPENUMDPCALLBACKW lpEnumCallbackW,
5781 LPVOID lpContext)
5783 HKEY hkResult;
5784 static const WCHAR searchSubKey[] = {
5785 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
5786 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
5787 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
5788 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
5789 static const WCHAR guidKey[] = { 'G', 'u', 'i', 'd', 0 };
5790 static const WCHAR descW[] = { 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', 'W', 0 };
5792 DWORD dwIndex;
5793 FILETIME filetime;
5795 char *descriptionA = NULL;
5796 DWORD max_sizeOfDescriptionA = 0;
5797 WCHAR *descriptionW = NULL;
5798 DWORD max_sizeOfDescriptionW = 0;
5800 if (!lpEnumCallbackA && !lpEnumCallbackW)
5802 return DPERR_INVALIDPARAMS;
5805 /* Need to loop over the service providers in the registry */
5806 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, searchSubKey,
5807 0, KEY_READ, &hkResult) != ERROR_SUCCESS)
5809 /* Hmmm. Does this mean that there are no service providers? */
5810 ERR(": no service provider key in the registry - check your Wine installation !!!\n");
5811 return DPERR_GENERIC;
5814 /* Traverse all the service providers we have available */
5815 dwIndex = 0;
5816 while (1)
5818 WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */
5819 DWORD sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR);
5820 HKEY hkServiceProvider;
5821 GUID serviceProviderGUID;
5822 WCHAR guidKeyContent[(2 * 16) + 1 + 6 /* This corresponds to '{....-..-..-..-......}' */ ];
5823 DWORD sizeOfGuidKeyContent = sizeof(guidKeyContent);
5824 LONG ret_value;
5826 ret_value = RegEnumKeyExW(hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
5827 NULL, NULL, NULL, &filetime);
5828 if (ret_value == ERROR_NO_MORE_ITEMS)
5829 break;
5830 else if (ret_value != ERROR_SUCCESS)
5832 ERR(": could not enumerate on service provider key.\n");
5833 return DPERR_EXCEPTION;
5835 TRACE(" this time through sub-key %s.\n", debugstr_w(subKeyName));
5837 /* Open the key for this service provider */
5838 if (RegOpenKeyExW(hkResult, subKeyName, 0, KEY_READ, &hkServiceProvider) != ERROR_SUCCESS)
5840 ERR(": could not open registry key for service provider %s.\n", debugstr_w(subKeyName));
5841 continue;
5844 /* Get the GUID from the registry */
5845 if (RegQueryValueExW(hkServiceProvider, guidKey,
5846 NULL, NULL, (LPBYTE) guidKeyContent, &sizeOfGuidKeyContent) != ERROR_SUCCESS)
5848 ERR(": missing GUID registry data member for service provider %s.\n", debugstr_w(subKeyName));
5849 continue;
5851 if (sizeOfGuidKeyContent != sizeof(guidKeyContent))
5853 ERR(": invalid format for the GUID registry data member for service provider %s (%s).\n", debugstr_w(subKeyName), debugstr_w(guidKeyContent));
5854 continue;
5856 CLSIDFromString(guidKeyContent, &serviceProviderGUID );
5858 /* The enumeration will return FALSE if we are not to continue.
5860 * Note: on my windows box, major / minor version is 6 / 0 for all service providers
5861 * and have no relation to any of the two dwReserved1 and dwReserved2 keys.
5862 * I think that it simply means that they are in-line with DirectX 6.0
5864 if (lpEnumCallbackA)
5866 DWORD sizeOfDescription = 0;
5868 /* Note that this is the A case of this function, so use the A variant to get the description string */
5869 if (RegQueryValueExA(hkServiceProvider, "DescriptionA",
5870 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5872 ERR(": missing 'DescriptionA' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5873 continue;
5875 if (sizeOfDescription > max_sizeOfDescriptionA)
5877 HeapFree(GetProcessHeap(), 0, descriptionA);
5878 max_sizeOfDescriptionA = sizeOfDescription;
5880 descriptionA = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5881 RegQueryValueExA(hkServiceProvider, "DescriptionA",
5882 NULL, NULL, (LPBYTE) descriptionA, &sizeOfDescription);
5884 if (!lpEnumCallbackA(&serviceProviderGUID, descriptionA, 6, 0, lpContext))
5885 goto end;
5887 else
5889 DWORD sizeOfDescription = 0;
5891 if (RegQueryValueExW(hkServiceProvider, descW,
5892 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5894 ERR(": missing 'DescriptionW' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5895 continue;
5897 if (sizeOfDescription > max_sizeOfDescriptionW)
5899 HeapFree(GetProcessHeap(), 0, descriptionW);
5900 max_sizeOfDescriptionW = sizeOfDescription;
5902 descriptionW = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5903 RegQueryValueExW(hkServiceProvider, descW,
5904 NULL, NULL, (LPBYTE) descriptionW, &sizeOfDescription);
5906 if (!lpEnumCallbackW(&serviceProviderGUID, descriptionW, 6, 0, lpContext))
5907 goto end;
5910 dwIndex++;
5913 end:
5914 HeapFree(GetProcessHeap(), 0, descriptionA);
5915 HeapFree(GetProcessHeap(), 0, descriptionW);
5917 return DP_OK;
5920 /***************************************************************************
5921 * DirectPlayEnumerate [DPLAYX.9]
5922 * DirectPlayEnumerateA [DPLAYX.2]
5924 HRESULT WINAPI DirectPlayEnumerateA(LPDPENUMDPCALLBACKA lpEnumCallback, LPVOID lpContext )
5926 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5928 return DirectPlayEnumerateAW(lpEnumCallback, NULL, lpContext);
5931 /***************************************************************************
5932 * DirectPlayEnumerateW [DPLAYX.3]
5934 HRESULT WINAPI DirectPlayEnumerateW(LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5936 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5938 return DirectPlayEnumerateAW(NULL, lpEnumCallback, lpContext);
5941 typedef struct tagCreateEnum
5943 LPVOID lpConn;
5944 LPCGUID lpGuid;
5945 } CreateEnumData, *lpCreateEnumData;
5947 /* Find and copy the matching connection for the SP guid */
5948 static BOOL CALLBACK cbDPCreateEnumConnections(
5949 LPCGUID lpguidSP,
5950 LPVOID lpConnection,
5951 DWORD dwConnectionSize,
5952 LPCDPNAME lpName,
5953 DWORD dwFlags,
5954 LPVOID lpContext)
5956 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5958 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5960 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5962 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5963 dwConnectionSize );
5964 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5966 /* Found the record that we were looking for */
5967 return FALSE;
5970 /* Haven't found what were looking for yet */
5971 return TRUE;
5975 /***************************************************************************
5976 * DirectPlayCreate [DPLAYX.1]
5979 HRESULT WINAPI DirectPlayCreate
5980 ( LPGUID lpGUID, LPDIRECTPLAY *lplpDP, IUnknown *pUnk )
5982 HRESULT hr;
5983 LPDIRECTPLAY3A lpDP3A;
5984 CreateEnumData cbData;
5986 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5988 if( pUnk != NULL )
5990 return CLASS_E_NOAGGREGATION;
5993 if( (lplpDP == NULL) || (lpGUID == NULL) )
5995 return DPERR_INVALIDPARAMS;
5998 if ( dplay_create( &IID_IDirectPlay, (void**)lplpDP ) != DP_OK )
5999 return DPERR_UNAVAILABLE;
6001 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
6003 /* The GUID_NULL means don't bind a service provider. Just return the
6004 interface as is */
6005 return DP_OK;
6008 /* Bind the desired service provider since lpGUID is non NULL */
6009 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
6011 /* We're going to use a DP3 interface */
6012 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
6013 (LPVOID*)&lpDP3A );
6014 if( FAILED(hr) )
6016 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
6017 return hr;
6020 cbData.lpConn = NULL;
6021 cbData.lpGuid = lpGUID;
6023 /* We were given a service provider, find info about it... */
6024 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
6025 &cbData, DPCONNECTION_DIRECTPLAY );
6026 if( ( FAILED(hr) ) ||
6027 ( cbData.lpConn == NULL )
6030 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
6031 IDirectPlayX_Release( lpDP3A );
6032 return DPERR_UNAVAILABLE;
6035 /* Initialize the service provider */
6036 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
6037 if( FAILED(hr) )
6039 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
6040 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
6041 IDirectPlayX_Release( lpDP3A );
6042 return hr;
6045 /* Release our version of the interface now that we're done with it */
6046 IDirectPlayX_Release( lpDP3A );
6047 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
6049 return DP_OK;