ws2_32/tests: Add tests for InetNtopW.
[wine.git] / dlls / dplayx / dplay.c
blob92062d310d4bfc5c52e957d5e652573b34a58473
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
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 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
328 break;
330 case DPMSGCMD_JUSTENVELOPE:
331 TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08x\n", lpcMessageHeader, ((const DWORD *)lpcMessageHeader)[1] );
332 NS_SetLocalAddr( This->dp2->lpNameServerData, lpcMessageHeader, 20 );
333 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
335 case DPMSGCMD_FORWARDADDPLAYER:
336 TRACE( "Sending message to self to get my addr\n" );
337 DP_MSG_ToSelf( This, 1 ); /* This is a hack right now */
338 break;
340 case DPMSGCMD_FORWARDADDPLAYERNACK:
341 DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
342 break;
344 default:
345 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
346 DebugBreak();
347 break;
350 /* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */
352 return DP_OK;
356 static HRESULT WINAPI IDirectPlayImpl_QueryInterface( IDirectPlay *iface, REFIID riid, void **ppv )
358 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
359 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
362 static ULONG WINAPI IDirectPlayImpl_AddRef( IDirectPlay *iface )
364 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
365 ULONG ref = InterlockedIncrement( &This->ref );
367 TRACE( "(%p) ref=%d\n", This, ref );
369 if ( ref == 1 )
370 InterlockedIncrement( &This->numIfaces );
372 return ref;
375 static ULONG WINAPI IDirectPlayImpl_Release( IDirectPlay *iface )
377 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
378 ULONG ref = InterlockedDecrement( &This->ref );
380 TRACE( "(%p) ref=%d\n", This, ref );
382 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
383 dplay_destroy( This );
385 return ref;
388 static HRESULT WINAPI IDirectPlayImpl_AddPlayerToGroup( IDirectPlay *iface, DPID group,
389 DPID player )
391 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
392 FIXME( "(%p)->(0x%08x,0x%08x): stub\n", This, group, player );
393 return E_NOTIMPL;
396 static HRESULT WINAPI IDirectPlayImpl_Close( IDirectPlay *iface )
398 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
399 FIXME( "(%p): stub\n", This );
400 return E_NOTIMPL;
403 static HRESULT WINAPI IDirectPlayImpl_CreatePlayer( IDirectPlay *iface, DPID *player,
404 LPSTR name, LPSTR fullname, HANDLE *event )
406 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
407 FIXME( "(%p)->(%p,%s,%s,%p): stub\n", This, player, debugstr_a( name ), debugstr_a( fullname ),
408 event );
409 return E_NOTIMPL;
412 static HRESULT WINAPI IDirectPlayImpl_CreateGroup( IDirectPlay *iface, DPID *group, LPSTR name,
413 LPSTR fullname )
415 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
416 FIXME( "(%p)->(%p,%s,%s): stub\n", This, group, debugstr_a( name ), debugstr_a( fullname ) );
417 return E_NOTIMPL;
420 static HRESULT WINAPI IDirectPlayImpl_DeletePlayerFromGroup( IDirectPlay *iface, DPID group,
421 DPID player )
423 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
424 FIXME( "(%p)->(0x%08x,0x%08x): stub\n", This, group, player );
425 return E_NOTIMPL;
428 static HRESULT WINAPI IDirectPlayImpl_DestroyPlayer( IDirectPlay *iface, DPID player )
430 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
431 FIXME( "(%p)->(0x%08x): stub\n", This, player );
432 return E_NOTIMPL;
435 static HRESULT WINAPI IDirectPlayImpl_DestroyGroup( IDirectPlay *iface, DPID group )
437 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
438 FIXME( "(%p)->(0x%08x): stub\n", This, group );
439 return E_NOTIMPL;
442 static HRESULT WINAPI IDirectPlayImpl_EnableNewPlayers( IDirectPlay *iface, BOOL enable )
444 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
445 FIXME( "(%p)->(%d): stub\n", This, enable );
446 return E_NOTIMPL;
449 static HRESULT WINAPI IDirectPlayImpl_EnumGroupPlayers( IDirectPlay *iface, DPID group,
450 LPDPENUMPLAYERSCALLBACK enumplayercb, void *context, DWORD flags )
452 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
453 FIXME( "(%p)->(0x%08x,%p,%p,0x%08x): stub\n", This, group, enumplayercb, context, flags );
454 return E_NOTIMPL;
457 static HRESULT WINAPI IDirectPlayImpl_EnumGroups( IDirectPlay *iface, DWORD session,
458 LPDPENUMPLAYERSCALLBACK enumplayercb, void *context, DWORD flags )
460 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
461 FIXME( "(%p)->(0x%08x,%p,%p,0x%08x): stub\n", This, session, enumplayercb, context, flags );
462 return E_NOTIMPL;
465 static HRESULT WINAPI IDirectPlayImpl_EnumPlayers( IDirectPlay *iface, DWORD session,
466 LPDPENUMPLAYERSCALLBACK enumplayercb, void *context, DWORD flags )
468 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
469 FIXME( "(%p)->(0x%08x,%p,%p,0x%08x): stub\n", This, session, enumplayercb, context, flags );
470 return E_NOTIMPL;
473 static HRESULT WINAPI IDirectPlayImpl_EnumSessions( IDirectPlay *iface, DPSESSIONDESC *sdesc,
474 DWORD timeout, LPDPENUMSESSIONSCALLBACK enumsessioncb, void *context, DWORD flags )
476 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
477 FIXME( "(%p)->(%p,%u,%p,%p,0x%08x): stub\n", This, sdesc, timeout, enumsessioncb, context,
478 flags );
479 return E_NOTIMPL;
482 static HRESULT WINAPI IDirectPlayImpl_GetCaps( IDirectPlay *iface, DPCAPS *caps )
484 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
485 FIXME( "(%p)->(%p): stub\n", This, caps );
486 return E_NOTIMPL;
489 static HRESULT WINAPI IDirectPlayImpl_GetMessageCount( IDirectPlay *iface, DPID player,
490 DWORD *count )
492 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
493 FIXME( "(%p)->(0x%08x,%p): stub\n", This, player, count );
494 return E_NOTIMPL;
497 static HRESULT WINAPI IDirectPlayImpl_GetPlayerCaps( IDirectPlay *iface, DPID player, DPCAPS *caps )
499 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
500 FIXME( "(%p)->(0x%08x,%p): stub\n", This, player, caps );
501 return E_NOTIMPL;
504 static HRESULT WINAPI IDirectPlayImpl_GetPlayerName( IDirectPlay *iface, DPID player, LPSTR name,
505 DWORD *size_name, LPSTR fullname, DWORD *size_fullname )
507 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
508 FIXME( "(%p)->(0x%08x,%p,%p,%p,%p): stub\n", This, player, name, size_name, fullname,
509 size_fullname );
510 return E_NOTIMPL;
513 static HRESULT WINAPI IDirectPlayImpl_Initialize( IDirectPlay *iface, GUID *guid )
515 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
516 FIXME( "(%p)->(%p): stub\n", This, guid );
517 return E_NOTIMPL;
520 static HRESULT WINAPI IDirectPlayImpl_Open( IDirectPlay *iface, DPSESSIONDESC *sdesc )
522 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
523 FIXME( "(%p)->(%p): stub\n", This, sdesc );
524 return E_NOTIMPL;
527 static HRESULT WINAPI IDirectPlayImpl_Receive( IDirectPlay *iface, DPID *from, DPID *to,
528 DWORD flags, void *data, DWORD *size )
530 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
531 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p): stub\n", This, from, to, flags, data, size );
532 return E_NOTIMPL;
535 static HRESULT WINAPI IDirectPlayImpl_SaveSession( IDirectPlay *iface, LPSTR reserved )
537 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
538 FIXME( "(%p)->(%p): stub\n", This, reserved );
539 return E_NOTIMPL;
542 static HRESULT WINAPI IDirectPlayImpl_Send( IDirectPlay *iface, DPID from, DPID to, DWORD flags,
543 void *data, DWORD size )
545 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
546 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%u): stub\n", This, from, to, flags, data, size );
547 return E_NOTIMPL;
550 static HRESULT WINAPI IDirectPlayImpl_SetPlayerName( IDirectPlay *iface, DPID player, LPSTR name,
551 LPSTR fullname )
553 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
554 FIXME( "(%p)->(0x%08x,%s,%s): stub\n", This, player, debugstr_a( name ),
555 debugstr_a ( fullname ) );
556 return E_NOTIMPL;
559 static const IDirectPlayVtbl dp_vt =
561 IDirectPlayImpl_QueryInterface,
562 IDirectPlayImpl_AddRef,
563 IDirectPlayImpl_Release,
564 IDirectPlayImpl_AddPlayerToGroup,
565 IDirectPlayImpl_Close,
566 IDirectPlayImpl_CreatePlayer,
567 IDirectPlayImpl_CreateGroup,
568 IDirectPlayImpl_DeletePlayerFromGroup,
569 IDirectPlayImpl_DestroyPlayer,
570 IDirectPlayImpl_DestroyGroup,
571 IDirectPlayImpl_EnableNewPlayers,
572 IDirectPlayImpl_EnumGroupPlayers,
573 IDirectPlayImpl_EnumGroups,
574 IDirectPlayImpl_EnumPlayers,
575 IDirectPlayImpl_EnumSessions,
576 IDirectPlayImpl_GetCaps,
577 IDirectPlayImpl_GetMessageCount,
578 IDirectPlayImpl_GetPlayerCaps,
579 IDirectPlayImpl_GetPlayerName,
580 IDirectPlayImpl_Initialize,
581 IDirectPlayImpl_Open,
582 IDirectPlayImpl_Receive,
583 IDirectPlayImpl_SaveSession,
584 IDirectPlayImpl_Send,
585 IDirectPlayImpl_SetPlayerName,
589 static HRESULT WINAPI IDirectPlay2AImpl_QueryInterface( IDirectPlay2A *iface, REFIID riid,
590 void **ppv )
592 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
593 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
596 static HRESULT WINAPI IDirectPlay2Impl_QueryInterface( IDirectPlay2 *iface, REFIID riid,
597 void **ppv )
599 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
600 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
603 static HRESULT WINAPI IDirectPlay3AImpl_QueryInterface( IDirectPlay3A *iface, REFIID riid,
604 void **ppv )
606 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
607 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
610 static HRESULT WINAPI IDirectPlay3Impl_QueryInterface( IDirectPlay3 *iface, REFIID riid,
611 void **ppv )
613 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
614 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
617 static HRESULT WINAPI IDirectPlay4AImpl_QueryInterface( IDirectPlay4A *iface, REFIID riid,
618 void **ppv )
620 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
621 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
624 static HRESULT WINAPI IDirectPlay4Impl_QueryInterface( IDirectPlay4 *iface, REFIID riid,
625 void **ppv )
627 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
629 if ( IsEqualGUID( &IID_IUnknown, riid ) )
631 TRACE( "(%p)->(IID_IUnknown %p)\n", This, ppv );
632 *ppv = &This->IDirectPlay_iface;
634 else if ( IsEqualGUID( &IID_IDirectPlay, riid ) )
636 TRACE( "(%p)->(IID_IDirectPlay %p)\n", This, ppv );
637 *ppv = &This->IDirectPlay_iface;
639 else if ( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
641 TRACE( "(%p)->(IID_IDirectPlay2A %p)\n", This, ppv );
642 *ppv = &This->IDirectPlay2A_iface;
644 else if ( IsEqualGUID( &IID_IDirectPlay2, riid ) )
646 TRACE( "(%p)->(IID_IDirectPlay2 %p)\n", This, ppv );
647 *ppv = &This->IDirectPlay2_iface;
649 else if ( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
651 TRACE( "(%p)->(IID_IDirectPlay3A %p)\n", This, ppv );
652 *ppv = &This->IDirectPlay3A_iface;
654 else if ( IsEqualGUID( &IID_IDirectPlay3, riid ) )
656 TRACE( "(%p)->(IID_IDirectPlay3 %p)\n", This, ppv );
657 *ppv = &This->IDirectPlay3_iface;
659 else if ( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
661 TRACE( "(%p)->(IID_IDirectPlay4A %p)\n", This, ppv );
662 *ppv = &This->IDirectPlay4A_iface;
664 else if ( IsEqualGUID( &IID_IDirectPlay4, riid ) )
666 TRACE( "(%p)->(IID_IDirectPlay4 %p)\n", This, ppv );
667 *ppv = &This->IDirectPlay4_iface;
669 else
671 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
672 *ppv = NULL;
673 return E_NOINTERFACE;
676 IUnknown_AddRef((IUnknown*)*ppv);
677 return S_OK;
680 static ULONG WINAPI IDirectPlay2AImpl_AddRef( IDirectPlay2A *iface )
682 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
683 ULONG ref = InterlockedIncrement( &This->ref2A );
685 TRACE( "(%p) ref2A=%d\n", This, ref );
687 if ( ref == 1 )
688 InterlockedIncrement( &This->numIfaces );
690 return ref;
693 static ULONG WINAPI IDirectPlay2Impl_AddRef( IDirectPlay2 *iface )
695 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
696 ULONG ref = InterlockedIncrement( &This->ref2 );
698 TRACE( "(%p) ref2=%d\n", This, ref );
700 if ( ref == 1 )
701 InterlockedIncrement( &This->numIfaces );
703 return ref;
706 static ULONG WINAPI IDirectPlay3AImpl_AddRef( IDirectPlay3A *iface )
708 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
709 ULONG ref = InterlockedIncrement( &This->ref3A );
711 TRACE( "(%p) ref3A=%d\n", This, ref );
713 if ( ref == 1 )
714 InterlockedIncrement( &This->numIfaces );
716 return ref;
719 static ULONG WINAPI IDirectPlay3Impl_AddRef( IDirectPlay3 *iface )
721 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
722 ULONG ref = InterlockedIncrement( &This->ref3 );
724 TRACE( "(%p) ref3=%d\n", This, ref );
726 if ( ref == 1 )
727 InterlockedIncrement( &This->numIfaces );
729 return ref;
732 static ULONG WINAPI IDirectPlay4AImpl_AddRef(IDirectPlay4A *iface)
734 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
735 ULONG ref = InterlockedIncrement( &This->ref4A );
737 TRACE( "(%p) ref4A=%d\n", This, ref );
739 if ( ref == 1 )
740 InterlockedIncrement( &This->numIfaces );
742 return ref;
745 static ULONG WINAPI IDirectPlay4Impl_AddRef(IDirectPlay4 *iface)
747 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
748 ULONG ref = InterlockedIncrement( &This->ref4 );
750 TRACE( "(%p) ref4=%d\n", This, ref );
752 if ( ref == 1 )
753 InterlockedIncrement( &This->numIfaces );
755 return ref;
758 static ULONG WINAPI IDirectPlay2AImpl_Release( IDirectPlay2A *iface )
760 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
761 ULONG ref = InterlockedDecrement( &This->ref2A );
763 TRACE( "(%p) ref2A=%d\n", This, ref );
765 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
766 dplay_destroy( This );
768 return ref;
771 static ULONG WINAPI IDirectPlay2Impl_Release( IDirectPlay2 *iface )
773 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
774 ULONG ref = InterlockedDecrement( &This->ref2 );
776 TRACE( "(%p) ref2=%d\n", This, ref );
778 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
779 dplay_destroy( This );
781 return ref;
784 static ULONG WINAPI IDirectPlay3AImpl_Release( IDirectPlay3A *iface )
786 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
787 ULONG ref = InterlockedDecrement( &This->ref3A );
789 TRACE( "(%p) ref3A=%d\n", This, ref );
791 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
792 dplay_destroy( This );
794 return ref;
797 static ULONG WINAPI IDirectPlay3Impl_Release( IDirectPlay3 *iface )
799 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
800 ULONG ref = InterlockedDecrement( &This->ref3 );
802 TRACE( "(%p) ref3=%d\n", This, ref );
804 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
805 dplay_destroy( This );
807 return ref;
810 static ULONG WINAPI IDirectPlay4AImpl_Release(IDirectPlay4A *iface)
812 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
813 ULONG ref = InterlockedDecrement( &This->ref4A );
815 TRACE( "(%p) ref4A=%d\n", This, ref );
817 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
818 dplay_destroy( This );
820 return ref;
823 static ULONG WINAPI IDirectPlay4Impl_Release(IDirectPlay4 *iface)
825 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
826 ULONG ref = InterlockedDecrement( &This->ref4 );
828 TRACE( "(%p) ref4=%d\n", This, ref );
830 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
831 dplay_destroy( This );
833 return ref;
836 static HRESULT WINAPI IDirectPlay2AImpl_AddPlayerToGroup( IDirectPlay2A *iface, DPID group,
837 DPID player )
839 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
840 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4A_iface, group, player );
843 static HRESULT WINAPI IDirectPlay2Impl_AddPlayerToGroup( IDirectPlay2 *iface, DPID group,
844 DPID player )
846 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
847 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
850 static HRESULT WINAPI IDirectPlay3AImpl_AddPlayerToGroup( IDirectPlay3A *iface, DPID group,
851 DPID player )
853 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
854 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
857 static HRESULT WINAPI IDirectPlay3Impl_AddPlayerToGroup( IDirectPlay3 *iface, DPID group,
858 DPID player )
860 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
861 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
864 static HRESULT WINAPI IDirectPlay4AImpl_AddPlayerToGroup( IDirectPlay4A *iface, DPID group,
865 DPID player )
867 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
868 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
871 static HRESULT WINAPI IDirectPlay4Impl_AddPlayerToGroup( IDirectPlay4 *iface, DPID group,
872 DPID player )
874 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
875 lpGroupData gdata;
876 lpPlayerList plist;
877 lpPlayerList newplist;
879 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, group, player );
881 if ( This->dp2->connectionInitialized == NO_PROVIDER )
882 return DPERR_UNINITIALIZED;
884 /* Find the group */
885 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
886 return DPERR_INVALIDGROUP;
888 /* Find the player */
889 if ( ( plist = DP_FindPlayer( This, player ) ) == NULL )
890 return DPERR_INVALIDPLAYER;
892 /* Create a player list (ie "shortcut" ) */
893 newplist = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *newplist ) );
894 if ( !newplist )
895 return DPERR_CANTADDPLAYER;
897 /* Add the shortcut */
898 plist->lpPData->uRef++;
899 newplist->lpPData = plist->lpPData;
901 /* Add the player to the list of players for this group */
902 DPQ_INSERT(gdata->players, newplist, players);
904 /* Let the SP know that we've added a player to the group */
905 if ( This->dp2->spData.lpCB->AddPlayerToGroup )
907 DPSP_ADDPLAYERTOGROUPDATA data;
909 TRACE( "Calling SP AddPlayerToGroup\n" );
911 data.idPlayer = player;
912 data.idGroup = group;
913 data.lpISP = This->dp2->spData.lpISP;
915 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
918 /* Inform all other peers of the addition of player to the group. If there are
919 * no peers keep this event quiet.
920 * Also, if this event was the result of another machine sending it to us,
921 * don't bother rebroadcasting it.
923 if ( This->dp2->lpSessionDesc &&
924 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
926 DPMSG_ADDPLAYERTOGROUP msg;
927 msg.dwType = DPSYS_ADDPLAYERTOGROUP;
929 msg.dpIdGroup = group;
930 msg.dpIdPlayer = player;
932 /* FIXME: Correct to just use send effectively? */
933 /* FIXME: Should size include data w/ message or just message "header" */
934 /* FIXME: Check return code */
935 IDirectPlayX_SendEx( iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
936 0, 0, NULL, NULL );
939 return DP_OK;
942 static HRESULT WINAPI IDirectPlay2AImpl_Close( IDirectPlay2A *iface )
944 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
945 return IDirectPlayX_Close( &This->IDirectPlay4A_iface );
948 static HRESULT WINAPI IDirectPlay2Impl_Close( IDirectPlay2 *iface )
950 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
951 return IDirectPlayX_Close( &This->IDirectPlay4_iface );
954 static HRESULT WINAPI IDirectPlay3AImpl_Close( IDirectPlay3A *iface )
956 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
957 return IDirectPlayX_Close( &This->IDirectPlay4_iface );
960 static HRESULT WINAPI IDirectPlay3Impl_Close( IDirectPlay3 *iface )
962 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
963 return IDirectPlayX_Close( &This->IDirectPlay4_iface );
966 static HRESULT WINAPI IDirectPlay4AImpl_Close( IDirectPlay4A *iface )
968 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
969 return IDirectPlayX_Close( &This->IDirectPlay4_iface);
972 static HRESULT WINAPI IDirectPlay4Impl_Close( IDirectPlay4 *iface )
974 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
975 HRESULT hr = DP_OK;
977 TRACE( "(%p)\n", This );
979 /* FIXME: Need to find a new host I assume (how?) */
980 /* FIXME: Need to destroy all local groups */
981 /* FIXME: Need to migrate all remotely visible players to the new host */
983 /* Invoke the SP callback to inform of session close */
984 if( This->dp2->spData.lpCB->CloseEx )
986 DPSP_CLOSEDATA data;
988 TRACE( "Calling SP CloseEx\n" );
989 data.lpISP = This->dp2->spData.lpISP;
990 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
992 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
994 TRACE( "Calling SP Close (obsolete interface)\n" );
995 hr = (*This->dp2->spData.lpCB->Close)();
998 return hr;
1001 static lpGroupData DP_CreateGroup( IDirectPlayImpl *This, const DPID *lpid, const DPNAME *lpName,
1002 DWORD dwFlags, DPID idParent, BOOL bAnsi )
1004 lpGroupData lpGData;
1006 /* Allocate the new space and add to end of high level group list */
1007 lpGData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGData ) );
1009 if( lpGData == NULL )
1011 return NULL;
1014 DPQ_INIT(lpGData->groups);
1015 DPQ_INIT(lpGData->players);
1017 /* Set the desired player ID - no sanity checking to see if it exists */
1018 lpGData->dpid = *lpid;
1020 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
1022 /* FIXME: Should we check that the parent exists? */
1023 lpGData->parent = idParent;
1025 /* FIXME: Should we validate the dwFlags? */
1026 lpGData->dwFlags = dwFlags;
1028 TRACE( "Created group id 0x%08x\n", *lpid );
1030 return lpGData;
1033 /* This method assumes that all links to it are already deleted */
1034 static void DP_DeleteGroup( IDirectPlayImpl *This, DPID dpid )
1036 lpGroupList lpGList;
1038 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1040 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
1042 if( lpGList == NULL )
1044 ERR( "DPID 0x%08x not found\n", dpid );
1045 return;
1048 if( --(lpGList->lpGData->uRef) )
1050 FIXME( "Why is this not the last reference to group?\n" );
1051 DebugBreak();
1054 /* Delete player */
1055 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
1056 HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
1058 /* Remove and Delete Player List object */
1059 HeapFree( GetProcessHeap(), 0, lpGList );
1063 static lpGroupData DP_FindAnyGroup( IDirectPlayImpl *This, DPID dpid )
1065 lpGroupList lpGroups;
1067 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1069 if( dpid == DPID_SYSTEM_GROUP )
1071 return This->dp2->lpSysGroup;
1073 else
1075 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
1078 if( lpGroups == NULL )
1080 return NULL;
1083 return lpGroups->lpGData;
1086 static HRESULT DP_IF_CreateGroup( IDirectPlayImpl *This, void *lpMsgHdr, DPID *lpidGroup,
1087 DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
1089 lpGroupData lpGData;
1091 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1092 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
1093 dwFlags, bAnsi );
1095 if( This->dp2->connectionInitialized == NO_PROVIDER )
1097 return DPERR_UNINITIALIZED;
1100 /* If the name is not specified, we must provide one */
1101 if( DPID_UNKNOWN == *lpidGroup )
1103 /* If we are the name server, we decide on the group ids. If not, we
1104 * must ask for one before attempting a creation.
1106 if( This->dp2->bHostInterface )
1108 *lpidGroup = DP_NextObjectId();
1110 else
1112 *lpidGroup = DP_GetRemoteNextObjectId();
1116 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
1117 DPID_NOPARENT_GROUP, bAnsi );
1119 if( lpGData == NULL )
1121 return DPERR_CANTADDPLAYER; /* yes player not group */
1124 if( DPID_SYSTEM_GROUP == *lpidGroup )
1126 This->dp2->lpSysGroup = lpGData;
1127 TRACE( "Inserting system group\n" );
1129 else
1131 /* Insert into the system group */
1132 lpGroupList lpGroup = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGroup ) );
1133 lpGroup->lpGData = lpGData;
1135 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
1138 /* Something is now referencing this data */
1139 lpGData->uRef++;
1141 /* Set all the important stuff for the group */
1142 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
1144 /* FIXME: We should only create the system group if GetCaps returns
1145 * DPCAPS_GROUPOPTIMIZED.
1148 /* Let the SP know that we've created this group */
1149 if( This->dp2->spData.lpCB->CreateGroup )
1151 DPSP_CREATEGROUPDATA data;
1152 DWORD dwCreateFlags = 0;
1154 TRACE( "Calling SP CreateGroup\n" );
1156 if( *lpidGroup == DPID_NOPARENT_GROUP )
1157 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
1159 if( lpMsgHdr == NULL )
1160 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1162 if( dwFlags & DPGROUP_HIDDEN )
1163 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
1165 data.idGroup = *lpidGroup;
1166 data.dwFlags = dwCreateFlags;
1167 data.lpSPMessageHeader = lpMsgHdr;
1168 data.lpISP = This->dp2->spData.lpISP;
1170 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1173 /* Inform all other peers of the creation of a new group. If there are
1174 * no peers keep this event quiet.
1175 * Also if this message was sent to us, don't rebroadcast.
1177 if( ( lpMsgHdr == NULL ) &&
1178 This->dp2->lpSessionDesc &&
1179 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1181 DPMSG_CREATEPLAYERORGROUP msg;
1182 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1184 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1185 msg.dpId = *lpidGroup;
1186 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1187 msg.lpData = lpData;
1188 msg.dwDataSize = dwDataSize;
1189 msg.dpnName = *lpGroupName;
1190 msg.dpIdParent = DPID_NOPARENT_GROUP;
1191 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
1193 /* FIXME: Correct to just use send effectively? */
1194 /* FIXME: Should size include data w/ message or just message "header" */
1195 /* FIXME: Check return code */
1196 IDirectPlayX_SendEx( &This->IDirectPlay4_iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
1197 sizeof( msg ), 0, 0, NULL, NULL );
1200 return DP_OK;
1203 static HRESULT WINAPI IDirectPlay2AImpl_CreateGroup( IDirectPlay2A *iface, DPID *lpidGroup,
1204 DPNAME *name, void *data, DWORD size, DWORD flags )
1206 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
1207 return IDirectPlayX_CreateGroup( &This->IDirectPlay4A_iface, lpidGroup, name, data, size,
1208 flags );
1211 static HRESULT WINAPI IDirectPlay2Impl_CreateGroup( IDirectPlay2 *iface, DPID *lpidGroup,
1212 DPNAME *name, void *data, DWORD size, DWORD flags )
1214 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
1215 return IDirectPlayX_CreateGroup( &This->IDirectPlay4_iface, lpidGroup, name, data, size,
1216 flags );
1219 static HRESULT WINAPI IDirectPlay3AImpl_CreateGroup( IDirectPlay3A *iface, DPID *group,
1220 DPNAME *name, void *data, DWORD size, DWORD flags )
1222 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
1223 return IDirectPlayX_CreateGroup( &This->IDirectPlay4_iface, group, name, data, size,
1224 flags );
1227 static HRESULT WINAPI IDirectPlay3Impl_CreateGroup( IDirectPlay3 *iface, DPID *lpidGroup,
1228 DPNAME *name, void *data, DWORD size, DWORD flags )
1230 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
1231 return IDirectPlayX_CreateGroup( &This->IDirectPlay4_iface, lpidGroup, name, data, size,
1232 flags );
1235 static HRESULT WINAPI IDirectPlay4AImpl_CreateGroup( IDirectPlay4A *iface, DPID *lpidGroup,
1236 DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1238 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
1240 *lpidGroup = DPID_UNKNOWN;
1242 return DP_IF_CreateGroup( This, NULL, lpidGroup, lpGroupName, lpData, dwDataSize, dwFlags,
1243 TRUE );
1246 static HRESULT WINAPI IDirectPlay4Impl_CreateGroup( IDirectPlay4 *iface, DPID *lpidGroup,
1247 DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1249 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
1251 *lpidGroup = DPID_UNKNOWN;
1253 return DP_IF_CreateGroup( This, NULL, lpidGroup, lpGroupName, lpData, dwDataSize, dwFlags,
1254 FALSE );
1258 static void
1259 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
1260 LPVOID lpData, DWORD dwDataSize )
1262 /* Clear out the data with this player */
1263 if( dwFlags & DPSET_LOCAL )
1265 if ( lpGData->dwLocalDataSize != 0 )
1267 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
1268 lpGData->lpLocalData = NULL;
1269 lpGData->dwLocalDataSize = 0;
1272 else
1274 if( lpGData->dwRemoteDataSize != 0 )
1276 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
1277 lpGData->lpRemoteData = NULL;
1278 lpGData->dwRemoteDataSize = 0;
1282 /* Reallocate for new data */
1283 if( lpData != NULL )
1285 if( dwFlags & DPSET_LOCAL )
1287 lpGData->lpLocalData = lpData;
1288 lpGData->dwLocalDataSize = dwDataSize;
1290 else
1292 lpGData->lpRemoteData = HeapAlloc( GetProcessHeap(), 0, dwDataSize );
1293 CopyMemory( lpGData->lpRemoteData, lpData, dwDataSize );
1294 lpGData->dwRemoteDataSize = dwDataSize;
1300 /* This function will just create the storage for the new player. */
1301 static lpPlayerData DP_CreatePlayer( IDirectPlayImpl *This, DPID *lpid, DPNAME *lpName,
1302 DWORD dwFlags, HANDLE hEvent, BOOL bAnsi )
1304 lpPlayerData lpPData;
1306 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
1308 /* Allocate the storage for the player and associate it with list element */
1309 lpPData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPData ) );
1310 if( lpPData == NULL )
1312 return NULL;
1315 /* Set the desired player ID */
1316 lpPData->dpid = *lpid;
1318 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
1320 lpPData->dwFlags = dwFlags;
1322 /* If we were given an event handle, duplicate it */
1323 if( hEvent != 0 )
1325 if( !DuplicateHandle( GetCurrentProcess(), hEvent,
1326 GetCurrentProcess(), &lpPData->hEvent,
1327 0, FALSE, DUPLICATE_SAME_ACCESS )
1330 /* FIXME: Memory leak */
1331 ERR( "Can't duplicate player msg handle %p\n", hEvent );
1335 /* Initialize the SP data section */
1336 lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData();
1338 TRACE( "Created player id 0x%08x\n", *lpid );
1340 if( ~dwFlags & DPLAYI_PLAYER_SYSPLAYER )
1341 This->dp2->lpSessionDesc->dwCurrentPlayers++;
1343 return lpPData;
1346 /* Delete the contents of the DPNAME struct */
1347 static void
1348 DP_DeleteDPNameStruct( LPDPNAME lpDPName )
1350 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u1.lpszShortNameA );
1351 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u2.lpszLongNameA );
1354 /* This method assumes that all links to it are already deleted */
1355 static void DP_DeletePlayer( IDirectPlayImpl *This, DPID dpid )
1357 lpPlayerList lpPList;
1359 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1361 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1363 if( lpPList == NULL )
1365 ERR( "DPID 0x%08x not found\n", dpid );
1366 return;
1369 /* Verify that this is the last reference to the data */
1370 if( --(lpPList->lpPData->uRef) )
1372 FIXME( "Why is this not the last reference to player?\n" );
1373 DebugBreak();
1376 /* Delete player */
1377 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1379 CloseHandle( lpPList->lpPData->hEvent );
1380 HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
1382 /* Delete Player List object */
1383 HeapFree( GetProcessHeap(), 0, lpPList );
1386 static lpPlayerList DP_FindPlayer( IDirectPlayImpl *This, DPID dpid )
1388 lpPlayerList lpPlayers;
1390 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1392 if(This->dp2->lpSysGroup == NULL)
1393 return NULL;
1395 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1397 return lpPlayers;
1400 /* Basic area for Dst must already be allocated */
1401 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, const DPNAME *lpSrc, BOOL bAnsi )
1403 if( lpSrc == NULL )
1405 ZeroMemory( lpDst, sizeof( *lpDst ) );
1406 lpDst->dwSize = sizeof( *lpDst );
1407 return TRUE;
1410 if( lpSrc->dwSize != sizeof( *lpSrc) )
1412 return FALSE;
1415 /* Delete any existing pointers */
1416 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1417 HeapFree( GetProcessHeap(), 0, lpDst->u2.lpszLongNameA );
1419 /* Copy as required */
1420 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1422 if( bAnsi )
1424 if( lpSrc->u1.lpszShortNameA )
1426 lpDst->u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), 0,
1427 strlen(lpSrc->u1.lpszShortNameA)+1 );
1428 strcpy( lpDst->u1.lpszShortNameA, lpSrc->u1.lpszShortNameA );
1430 if( lpSrc->u2.lpszLongNameA )
1432 lpDst->u2.lpszLongNameA = HeapAlloc( GetProcessHeap(), 0,
1433 strlen(lpSrc->u2.lpszLongNameA)+1 );
1434 strcpy( lpDst->u2.lpszLongNameA, lpSrc->u2.lpszLongNameA );
1437 else
1439 if( lpSrc->u1.lpszShortNameA )
1441 lpDst->u1.lpszShortName = HeapAlloc( GetProcessHeap(), 0,
1442 (strlenW(lpSrc->u1.lpszShortName)+1)*sizeof(WCHAR) );
1443 strcpyW( lpDst->u1.lpszShortName, lpSrc->u1.lpszShortName );
1445 if( lpSrc->u2.lpszLongNameA )
1447 lpDst->u2.lpszLongName = HeapAlloc( GetProcessHeap(), 0,
1448 (strlenW(lpSrc->u2.lpszLongName)+1)*sizeof(WCHAR) );
1449 strcpyW( lpDst->u2.lpszLongName, lpSrc->u2.lpszLongName );
1453 return TRUE;
1456 static void
1457 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
1458 LPVOID lpData, DWORD dwDataSize )
1460 /* Clear out the data with this player */
1461 if( dwFlags & DPSET_LOCAL )
1463 if ( lpPData->dwLocalDataSize != 0 )
1465 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
1466 lpPData->lpLocalData = NULL;
1467 lpPData->dwLocalDataSize = 0;
1470 else
1472 if( lpPData->dwRemoteDataSize != 0 )
1474 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
1475 lpPData->lpRemoteData = NULL;
1476 lpPData->dwRemoteDataSize = 0;
1480 /* Reallocate for new data */
1481 if( lpData != NULL )
1484 if( dwFlags & DPSET_LOCAL )
1486 lpPData->lpLocalData = lpData;
1487 lpPData->dwLocalDataSize = dwDataSize;
1489 else
1491 lpPData->lpRemoteData = HeapAlloc( GetProcessHeap(), 0, dwDataSize );
1492 CopyMemory( lpPData->lpRemoteData, lpData, dwDataSize );
1493 lpPData->dwRemoteDataSize = dwDataSize;
1499 /* Note: lpMsgHdr is NULL for local creation, non NULL for remote creation */
1500 static HRESULT DP_IF_CreatePlayer( IDirectPlayImpl *This, void *lpMsgHdr, DPID *lpidPlayer,
1501 DPNAME *lpPlayerName, HANDLE hEvent, void *lpData, DWORD dwDataSize, DWORD dwFlags,
1502 BOOL bAnsi )
1504 HRESULT hr = DP_OK;
1505 lpPlayerData lpPData;
1506 lpPlayerList lpPList;
1507 DWORD dwCreateFlags = 0;
1509 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1510 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1511 dwDataSize, dwFlags, bAnsi );
1512 if( This->dp2->connectionInitialized == NO_PROVIDER )
1514 return DPERR_UNINITIALIZED;
1517 if( dwFlags == 0 )
1519 dwFlags = DPPLAYER_SPECTATOR;
1522 if( lpidPlayer == NULL )
1524 return DPERR_INVALIDPARAMS;
1528 /* Determine the creation flags for the player. These will be passed
1529 * to the name server if requesting a player id and to the SP when
1530 * informing it of the player creation
1533 if( dwFlags & DPPLAYER_SERVERPLAYER )
1535 if( *lpidPlayer == DPID_SERVERPLAYER )
1537 /* Server player for the host interface */
1538 dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
1540 else if( *lpidPlayer == DPID_NAME_SERVER )
1542 /* Name server - master of everything */
1543 dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
1545 else
1547 /* Server player for a non host interface */
1548 dwCreateFlags |= DPLAYI_PLAYER_SYSPLAYER;
1552 if( lpMsgHdr == NULL )
1553 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1556 /* Verify we know how to handle all the flags */
1557 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1558 ( dwFlags & DPPLAYER_SPECTATOR )
1562 /* Assume non fatal failure */
1563 ERR( "unknown dwFlags = 0x%08x\n", dwFlags );
1566 /* If the name is not specified, we must provide one */
1567 if( *lpidPlayer == DPID_UNKNOWN )
1569 /* If we are the session master, we dish out the group/player ids */
1570 if( This->dp2->bHostInterface )
1572 *lpidPlayer = DP_NextObjectId();
1574 else
1576 hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer );
1578 if( FAILED(hr) )
1580 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1581 return hr;
1585 else
1587 /* FIXME: Would be nice to perhaps verify that we don't already have
1588 * this player.
1592 /* We pass creation flags, so we can distinguish sysplayers and not count them in the current
1593 player total */
1594 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwCreateFlags,
1595 hEvent, bAnsi );
1596 /* Create the list object and link it in */
1597 lpPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPList ) );
1598 if( !lpPData || !lpPList )
1600 HeapFree( GetProcessHeap(), 0, lpPData );
1601 HeapFree( GetProcessHeap(), 0, lpPList );
1602 return DPERR_CANTADDPLAYER;
1605 lpPData->uRef = 1;
1606 lpPList->lpPData = lpPData;
1608 /* Add the player to the system group */
1609 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1611 /* Update the information and send it to all players in the session */
1612 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
1614 /* Let the SP know that we've created this player */
1615 if( This->dp2->spData.lpCB->CreatePlayer )
1617 DPSP_CREATEPLAYERDATA data;
1619 data.idPlayer = *lpidPlayer;
1620 data.dwFlags = dwCreateFlags;
1621 data.lpSPMessageHeader = lpMsgHdr;
1622 data.lpISP = This->dp2->spData.lpISP;
1624 TRACE( "Calling SP CreatePlayer 0x%08x: dwFlags: 0x%08x lpMsgHdr: %p\n",
1625 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
1627 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1630 if( FAILED(hr) )
1632 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1633 return hr;
1636 /* Now let the SP know that this player is a member of the system group */
1637 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1639 DPSP_ADDPLAYERTOGROUPDATA data;
1641 data.idPlayer = *lpidPlayer;
1642 data.idGroup = DPID_SYSTEM_GROUP;
1643 data.lpISP = This->dp2->spData.lpISP;
1645 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1647 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1650 if( FAILED(hr) )
1652 ERR( "Failed to add player to sys group with sp: %s\n",
1653 DPLAYX_HresultToString(hr) );
1654 return hr;
1657 #if 1
1658 if( !This->dp2->bHostInterface )
1660 /* Let the name server know about the creation of this player */
1661 /* FIXME: Is this only to be done for the creation of a server player or
1662 * is this used for regular players? If only for server players, move
1663 * this call to DP_SecureOpen(...);
1665 #if 0
1666 TRACE( "Sending message to self to get my addr\n" );
1667 DP_MSG_ToSelf( This, *lpidPlayer ); /* This is a hack right now */
1668 #endif
1670 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
1672 #else
1673 /* Inform all other peers of the creation of a new player. If there are
1674 * no peers keep this quiet.
1675 * Also, if this was a remote event, no need to rebroadcast it.
1677 if( ( lpMsgHdr == NULL ) &&
1678 This->dp2->lpSessionDesc &&
1679 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1681 DPMSG_CREATEPLAYERORGROUP msg;
1682 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1684 msg.dwPlayerType = DPPLAYERTYPE_PLAYER;
1685 msg.dpId = *lpidPlayer;
1686 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */
1687 msg.lpData = lpData;
1688 msg.dwDataSize = dwDataSize;
1689 msg.dpnName = *lpPlayerName;
1690 msg.dpIdParent = DPID_NOPARENT_GROUP;
1691 msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
1693 /* FIXME: Correct to just use send effectively? */
1694 /* FIXME: Should size include data w/ message or just message "header" */
1695 /* FIXME: Check return code */
1696 hr = IDirectPlayX_SendEx( &This->IDirectPlay4_iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0,
1697 &msg, sizeof( msg ), 0, 0, NULL, NULL );
1699 #endif
1701 return hr;
1704 static HRESULT WINAPI IDirectPlay2AImpl_CreatePlayer( IDirectPlay2A *iface, DPID *lpidPlayer,
1705 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags )
1707 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
1708 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4A_iface, lpidPlayer, name, event, data,
1709 size, flags );
1712 static HRESULT WINAPI IDirectPlay2Impl_CreatePlayer( IDirectPlay2 *iface, DPID *lpidPlayer,
1713 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags )
1715 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
1716 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4_iface, lpidPlayer, name, event, data,
1717 size, flags );
1720 static HRESULT WINAPI IDirectPlay3AImpl_CreatePlayer( IDirectPlay3A *iface, DPID *lpidPlayer,
1721 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags )
1723 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
1724 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4_iface, lpidPlayer, name, event, data,
1725 size, flags );
1728 static HRESULT WINAPI IDirectPlay3Impl_CreatePlayer( IDirectPlay3 *iface, DPID *lpidPlayer,
1729 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags )
1731 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
1732 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4_iface, lpidPlayer, name, event, data,
1733 size, flags );
1736 static HRESULT WINAPI IDirectPlay4AImpl_CreatePlayer( IDirectPlay4A *iface, DPID *lpidPlayer,
1737 DPNAME *lpPlayerName, HANDLE hEvent, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1739 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
1741 if( lpidPlayer == NULL )
1743 return DPERR_INVALIDPARAMS;
1746 if( dwFlags & DPPLAYER_SERVERPLAYER )
1748 *lpidPlayer = DPID_SERVERPLAYER;
1750 else
1752 *lpidPlayer = DPID_UNKNOWN;
1755 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1756 lpData, dwDataSize, dwFlags, TRUE );
1759 static HRESULT WINAPI IDirectPlay4Impl_CreatePlayer( IDirectPlay4 *iface, DPID *lpidPlayer,
1760 DPNAME *lpPlayerName, HANDLE hEvent, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1762 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
1764 if( lpidPlayer == NULL )
1766 return DPERR_INVALIDPARAMS;
1769 if( dwFlags & DPPLAYER_SERVERPLAYER )
1771 *lpidPlayer = DPID_SERVERPLAYER;
1773 else
1775 *lpidPlayer = DPID_UNKNOWN;
1778 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1779 lpData, dwDataSize, dwFlags, FALSE );
1782 static DPID DP_GetRemoteNextObjectId(void)
1784 FIXME( ":stub\n" );
1786 /* Hack solution */
1787 return DP_NextObjectId();
1790 static HRESULT WINAPI IDirectPlay2AImpl_DeletePlayerFromGroup( IDirectPlay2A *iface, DPID group,
1791 DPID player )
1793 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
1794 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4A_iface, group, player );
1797 static HRESULT WINAPI IDirectPlay2Impl_DeletePlayerFromGroup( IDirectPlay2 *iface, DPID group,
1798 DPID player )
1800 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
1801 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1804 static HRESULT WINAPI IDirectPlay3AImpl_DeletePlayerFromGroup( IDirectPlay3A *iface, DPID group,
1805 DPID player )
1807 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
1808 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1811 static HRESULT WINAPI IDirectPlay3Impl_DeletePlayerFromGroup( IDirectPlay3 *iface, DPID group,
1812 DPID player )
1814 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
1815 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1818 static HRESULT WINAPI IDirectPlay4AImpl_DeletePlayerFromGroup( IDirectPlay4A *iface, DPID group,
1819 DPID player )
1821 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
1822 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1825 static HRESULT WINAPI IDirectPlay4Impl_DeletePlayerFromGroup( IDirectPlay4 *iface, DPID group,
1826 DPID player )
1828 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
1829 HRESULT hr = DP_OK;
1831 lpGroupData gdata;
1832 lpPlayerList plist;
1834 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, group, player );
1836 /* Find the group */
1837 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
1838 return DPERR_INVALIDGROUP;
1840 /* Find the player */
1841 if ( DP_FindPlayer( This, player ) == NULL )
1842 return DPERR_INVALIDPLAYER;
1844 /* Remove the player shortcut from the group */
1845 DPQ_REMOVE_ENTRY( gdata->players, players, lpPData->dpid, ==, player, plist );
1847 if ( !plist )
1848 return DPERR_INVALIDPLAYER;
1850 /* One less reference */
1851 plist->lpPData->uRef--;
1853 /* Delete the Player List element */
1854 HeapFree( GetProcessHeap(), 0, plist );
1856 /* Inform the SP if they care */
1857 if ( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1859 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1861 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1862 data.idPlayer = player;
1863 data.idGroup = group;
1864 data.lpISP = This->dp2->spData.lpISP;
1865 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1868 /* Need to send a DELETEPLAYERFROMGROUP message */
1869 FIXME( "Need to send a message\n" );
1871 return hr;
1874 typedef struct _DPRGOPContext
1876 IDirectPlayImpl *This;
1877 BOOL bAnsi;
1878 DPID idGroup;
1879 } DPRGOPContext, *lpDPRGOPContext;
1881 static BOOL CALLBACK
1882 cbRemoveGroupOrPlayer(
1883 DPID dpId,
1884 DWORD dwPlayerType,
1885 LPCDPNAME lpName,
1886 DWORD dwFlags,
1887 LPVOID lpContext )
1889 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1891 TRACE( "Removing element:0x%08x (type:0x%08x) from element:0x%08x\n",
1892 dpId, dwPlayerType, lpCtxt->idGroup );
1894 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1896 if ( FAILED( IDirectPlayX_DeleteGroupFromGroup( &lpCtxt->This->IDirectPlay4_iface,
1897 lpCtxt->idGroup, dpId ) ) )
1898 ERR( "Unable to delete group 0x%08x from group 0x%08x\n", dpId, lpCtxt->idGroup );
1900 else if ( FAILED( IDirectPlayX_DeletePlayerFromGroup( &lpCtxt->This->IDirectPlay4_iface,
1901 lpCtxt->idGroup, dpId ) ) )
1902 ERR( "Unable to delete player 0x%08x from grp 0x%08x\n", dpId, lpCtxt->idGroup );
1904 return TRUE; /* Continue enumeration */
1907 static HRESULT DP_IF_DestroyGroup( IDirectPlayImpl *This, void *lpMsgHdr, DPID idGroup, BOOL bAnsi )
1909 lpGroupData lpGData;
1910 DPRGOPContext context;
1912 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1913 This, lpMsgHdr, idGroup, bAnsi );
1915 /* Find the group */
1916 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1918 return DPERR_INVALIDPLAYER; /* yes player */
1921 context.This = This;
1922 context.bAnsi = bAnsi;
1923 context.idGroup = idGroup;
1925 /* Remove all players that this group has */
1926 IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, idGroup, NULL, cbRemoveGroupOrPlayer,
1927 &context, 0 );
1929 /* Remove all links to groups that this group has since this is dp3 */
1930 IDirectPlayX_EnumGroupsInGroup( &This->IDirectPlay4_iface, idGroup, NULL, cbRemoveGroupOrPlayer,
1931 (void*)&context, 0 );
1933 /* Remove this group from the parent group - if it has one */
1934 if( ( idGroup != DPID_SYSTEM_GROUP ) && ( lpGData->parent != DPID_SYSTEM_GROUP ) )
1935 IDirectPlayX_DeleteGroupFromGroup( &This->IDirectPlay4_iface, lpGData->parent, idGroup );
1937 /* Now delete this group data and list from the system group */
1938 DP_DeleteGroup( This, idGroup );
1940 /* Let the SP know that we've destroyed this group */
1941 if( This->dp2->spData.lpCB->DeleteGroup )
1943 DPSP_DELETEGROUPDATA data;
1945 FIXME( "data.dwFlags is incorrect\n" );
1947 data.idGroup = idGroup;
1948 data.dwFlags = 0;
1949 data.lpISP = This->dp2->spData.lpISP;
1951 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1954 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1956 return DP_OK;
1959 static HRESULT WINAPI IDirectPlay2AImpl_DestroyGroup( IDirectPlay2A *iface, DPID group )
1961 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
1962 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4A_iface, group );
1965 static HRESULT WINAPI IDirectPlay2Impl_DestroyGroup( IDirectPlay2 *iface, DPID group )
1967 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
1968 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4_iface, group );
1971 static HRESULT WINAPI IDirectPlay3AImpl_DestroyGroup( IDirectPlay3A *iface, DPID group )
1973 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
1974 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4_iface, group );
1977 static HRESULT WINAPI IDirectPlay3Impl_DestroyGroup( IDirectPlay3 *iface, DPID group )
1979 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
1980 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4_iface, group );
1983 static HRESULT WINAPI IDirectPlay4AImpl_DestroyGroup( IDirectPlay4A *iface, DPID idGroup )
1985 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
1986 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
1989 static HRESULT WINAPI IDirectPlay4Impl_DestroyGroup( IDirectPlay4 *iface, DPID idGroup )
1991 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
1992 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
1995 typedef struct _DPFAGContext
1997 IDirectPlayImpl *This;
1998 DPID idPlayer;
1999 BOOL bAnsi;
2000 } DPFAGContext, *lpDPFAGContext;
2002 static HRESULT DP_IF_DestroyPlayer( IDirectPlayImpl *This, void *lpMsgHdr, DPID idPlayer,
2003 BOOL bAnsi )
2005 DPFAGContext cbContext;
2007 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
2008 This, lpMsgHdr, idPlayer, bAnsi );
2010 if( This->dp2->connectionInitialized == NO_PROVIDER )
2012 return DPERR_UNINITIALIZED;
2015 if( DP_FindPlayer( This, idPlayer ) == NULL )
2017 return DPERR_INVALIDPLAYER;
2020 /* FIXME: If the player is remote, we must be the host to delete this */
2022 cbContext.This = This;
2023 cbContext.idPlayer = idPlayer;
2024 cbContext.bAnsi = bAnsi;
2026 /* Find each group and call DeletePlayerFromGroup if the player is a
2027 member of the group */
2028 IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, NULL, cbDeletePlayerFromAllGroups, &cbContext,
2029 DPENUMGROUPS_ALL );
2031 /* Now delete player and player list from the sys group */
2032 DP_DeletePlayer( This, idPlayer );
2034 /* Let the SP know that we've destroyed this group */
2035 if( This->dp2->spData.lpCB->DeletePlayer )
2037 DPSP_DELETEPLAYERDATA data;
2039 FIXME( "data.dwFlags is incorrect\n" );
2041 data.idPlayer = idPlayer;
2042 data.dwFlags = 0;
2043 data.lpISP = This->dp2->spData.lpISP;
2045 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
2048 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
2050 return DP_OK;
2053 static BOOL CALLBACK
2054 cbDeletePlayerFromAllGroups(
2055 DPID dpId,
2056 DWORD dwPlayerType,
2057 LPCDPNAME lpName,
2058 DWORD dwFlags,
2059 LPVOID lpContext )
2061 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
2063 if( dwPlayerType == DPPLAYERTYPE_GROUP )
2065 IDirectPlayX_DeletePlayerFromGroup( &lpCtxt->This->IDirectPlay4_iface, dpId, lpCtxt->idPlayer );
2067 /* Enumerate all groups in this group since this will normally only
2068 * be called for top level groups
2070 IDirectPlayX_EnumGroupsInGroup( &lpCtxt->This->IDirectPlay4_iface, dpId, NULL,
2071 cbDeletePlayerFromAllGroups, lpContext, DPENUMGROUPS_ALL);
2074 else
2076 ERR( "Group callback has dwPlayerType = 0x%08x\n", dwPlayerType );
2079 return TRUE;
2082 static HRESULT WINAPI IDirectPlay2AImpl_DestroyPlayer( IDirectPlay2A *iface, DPID player )
2084 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2085 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4A_iface, player );
2088 static HRESULT WINAPI IDirectPlay2Impl_DestroyPlayer( IDirectPlay2 *iface, DPID player )
2090 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2091 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4_iface, player );
2094 static HRESULT WINAPI IDirectPlay3AImpl_DestroyPlayer( IDirectPlay3A *iface, DPID player )
2096 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2097 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4_iface, player );
2100 static HRESULT WINAPI IDirectPlay3Impl_DestroyPlayer( IDirectPlay3 *iface, DPID player )
2102 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2103 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4_iface, player );
2106 static HRESULT WINAPI IDirectPlay4AImpl_DestroyPlayer( IDirectPlay4A *iface, DPID idPlayer )
2108 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2109 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
2112 static HRESULT WINAPI IDirectPlay4Impl_DestroyPlayer( IDirectPlay4 *iface, DPID idPlayer )
2114 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2115 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
2118 static HRESULT WINAPI IDirectPlay2AImpl_EnumGroupPlayers( IDirectPlay2A *iface, DPID group,
2119 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2121 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2122 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4A_iface, group, instance,
2123 enumplayercb, context, flags );
2126 static HRESULT WINAPI IDirectPlay2Impl_EnumGroupPlayers( IDirectPlay2 *iface, DPID group,
2127 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2129 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2130 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance,
2131 enumplayercb, context, flags );
2134 static HRESULT WINAPI IDirectPlay3AImpl_EnumGroupPlayers( IDirectPlay3A *iface, DPID group,
2135 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2137 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2138 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance,
2139 enumplayercb, context, flags );
2142 static HRESULT WINAPI IDirectPlay3Impl_EnumGroupPlayers( IDirectPlay3 *iface, DPID group,
2143 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2145 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2146 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance,
2147 enumplayercb, context, flags );
2150 static HRESULT WINAPI IDirectPlay4AImpl_EnumGroupPlayers( IDirectPlay4A *iface, DPID group,
2151 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2153 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2154 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance, enumplayercb,
2155 context, flags );
2158 static HRESULT WINAPI IDirectPlay4Impl_EnumGroupPlayers( IDirectPlay4 *iface, DPID group,
2159 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2161 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2162 lpGroupData gdata;
2163 lpPlayerList plist;
2165 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x): semi stub\n", This, group, instance, enumplayercb,
2166 context, flags );
2168 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2169 return DPERR_UNINITIALIZED;
2171 /* Find the group */
2172 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
2173 return DPERR_INVALIDGROUP;
2175 if ( DPQ_IS_EMPTY( gdata->players ) )
2176 return DP_OK;
2178 /* Walk the players in this group */
2179 for( plist = DPQ_FIRST( gdata->players ); ; plist = DPQ_NEXT( plist->players ) )
2181 /* We do not enum the name server or app server as they are of no
2182 * consequence to the end user.
2184 if ( ( plist->lpPData->dpid != DPID_NAME_SERVER ) &&
2185 ( plist->lpPData->dpid != DPID_SERVERPLAYER ) )
2187 /* FIXME: Need to add stuff for flags checking */
2188 if ( !enumplayercb( plist->lpPData->dpid, DPPLAYERTYPE_PLAYER,
2189 &plist->lpPData->name, plist->lpPData->dwFlags, context ) )
2190 /* User requested break */
2191 return DP_OK;
2194 if ( DPQ_IS_ENDOFLIST( plist->players ) )
2195 break;
2197 return DP_OK;
2200 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2201 static HRESULT WINAPI IDirectPlay2AImpl_EnumGroups( IDirectPlay2A *iface, GUID *instance,
2202 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2204 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2205 return IDirectPlayX_EnumGroups( &This->IDirectPlay4A_iface, instance, enumplayercb, context,
2206 flags );
2209 static HRESULT WINAPI IDirectPlay2Impl_EnumGroups( IDirectPlay2 *iface, GUID *instance,
2210 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2212 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2213 return IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2214 flags );
2217 static HRESULT WINAPI IDirectPlay3AImpl_EnumGroups( IDirectPlay3A *iface, GUID *instance,
2218 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2220 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2221 return IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2222 flags );
2225 static HRESULT WINAPI IDirectPlay3Impl_EnumGroups( IDirectPlay3 *iface, GUID *instance,
2226 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2228 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2229 return IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2230 flags );
2233 static HRESULT WINAPI IDirectPlay4AImpl_EnumGroups( IDirectPlay4A *iface, GUID *instance,
2234 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2236 return IDirectPlayX_EnumGroupsInGroup( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2237 context, flags );
2240 static HRESULT WINAPI IDirectPlay4Impl_EnumGroups ( IDirectPlay4 *iface, GUID *instance,
2241 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2243 return IDirectPlayX_EnumGroupsInGroup( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2244 context, flags );
2247 static HRESULT WINAPI IDirectPlay2AImpl_EnumPlayers( IDirectPlay2A *iface, GUID *instance,
2248 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2250 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2251 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4A_iface, instance, enumplayercb, context,
2252 flags );
2255 static HRESULT WINAPI IDirectPlay2Impl_EnumPlayers( IDirectPlay2 *iface, GUID *instance,
2256 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2258 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2259 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2260 flags );
2263 static HRESULT WINAPI IDirectPlay3AImpl_EnumPlayers( IDirectPlay3A *iface, GUID *instance,
2264 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2266 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2267 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2268 flags );
2271 static HRESULT WINAPI IDirectPlay3Impl_EnumPlayers( IDirectPlay3 *iface, GUID *instance,
2272 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2274 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2275 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2276 flags );
2279 static HRESULT WINAPI IDirectPlay4AImpl_EnumPlayers( IDirectPlay4A *iface, GUID *instance,
2280 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2282 return IDirectPlayX_EnumGroupPlayers( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2283 context, flags );
2286 static HRESULT WINAPI IDirectPlay4Impl_EnumPlayers( IDirectPlay4 *iface, GUID *instance,
2287 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2289 return IDirectPlayX_EnumGroupPlayers( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2290 context, flags );
2293 /* This function should call the registered callback function that the user
2294 passed into EnumSessions for each entry available.
2296 static void DP_InvokeEnumSessionCallbacks
2297 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2298 LPVOID lpNSInfo,
2299 DWORD dwTimeout,
2300 LPVOID lpContext )
2302 LPDPSESSIONDESC2 lpSessionDesc;
2304 FIXME( ": not checking for conditions\n" );
2306 /* Not sure if this should be pruning but it's convenient */
2307 NS_PruneSessionCache( lpNSInfo );
2309 NS_ResetSessionEnumeration( lpNSInfo );
2311 /* Enumerate all sessions */
2312 /* FIXME: Need to indicate ANSI */
2313 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2315 TRACE( "EnumSessionsCallback2 invoked\n" );
2316 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2318 return;
2322 /* Invoke one last time to indicate that there is no more to come */
2323 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2326 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2328 EnumSessionAsyncCallbackData* data = lpContext;
2329 HANDLE hSuicideRequest = data->hSuicideRequest;
2330 DWORD dwTimeout = data->dwTimeout;
2332 TRACE( "Thread started with timeout = 0x%08x\n", dwTimeout );
2334 for( ;; )
2336 HRESULT hr;
2338 /* Sleep up to dwTimeout waiting for request to terminate thread */
2339 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2341 TRACE( "Thread terminating on terminate request\n" );
2342 break;
2345 /* Now resend the enum request */
2346 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2347 data->dwEnumSessionFlags,
2348 data->lpSpData );
2350 if( FAILED(hr) )
2352 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2353 /* FIXME: Should we kill this thread? How to inform the main thread? */
2358 TRACE( "Thread terminating\n" );
2360 /* Clean up the thread data */
2361 CloseHandle( hSuicideRequest );
2362 HeapFree( GetProcessHeap(), 0, lpContext );
2364 /* FIXME: Need to have some notification to main app thread that this is
2365 * dead. It would serve two purposes. 1) allow sync on termination
2366 * so that we don't actually send something to ourselves when we
2367 * become name server (race condition) and 2) so that if we die
2368 * abnormally something else will be able to tell.
2371 return 1;
2374 static void DP_KillEnumSessionThread( IDirectPlayImpl *This )
2376 /* Does a thread exist? If so we were doing an async enum session */
2377 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2379 TRACE( "Killing EnumSession thread %p\n",
2380 This->dp2->hEnumSessionThread );
2382 /* Request that the thread kill itself nicely */
2383 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2384 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2386 /* We no longer need to know about the thread */
2387 CloseHandle( This->dp2->hEnumSessionThread );
2389 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2393 static HRESULT WINAPI IDirectPlay2AImpl_EnumSessions( IDirectPlay2A *iface, DPSESSIONDESC2 *sdesc,
2394 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2396 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2397 return IDirectPlayX_EnumSessions( &This->IDirectPlay4A_iface, sdesc, timeout, enumsessioncb,
2398 context, flags );
2401 static HRESULT WINAPI IDirectPlay2Impl_EnumSessions( IDirectPlay2 *iface, DPSESSIONDESC2 *sdesc,
2402 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2404 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2405 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2406 context, flags );
2409 static HRESULT WINAPI IDirectPlay3AImpl_EnumSessions( IDirectPlay3A *iface, DPSESSIONDESC2 *sdesc,
2410 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2412 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2413 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2414 context, flags );
2417 static HRESULT WINAPI IDirectPlay3Impl_EnumSessions( IDirectPlay3 *iface, DPSESSIONDESC2 *sdesc,
2418 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2420 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2421 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2422 context, flags );
2425 static HRESULT WINAPI IDirectPlay4AImpl_EnumSessions( IDirectPlay4A *iface, DPSESSIONDESC2 *sdesc,
2426 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2428 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2429 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2430 context, flags );
2433 static HRESULT WINAPI IDirectPlay4Impl_EnumSessions( IDirectPlay4 *iface, DPSESSIONDESC2 *sdesc,
2434 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2436 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2437 void *connection;
2438 DWORD size;
2439 HRESULT hr = DP_OK;
2441 TRACE( "(%p)->(%p,0x%08x,%p,%p,0x%08x)\n", This, sdesc, timeout, enumsessioncb,
2442 context, flags );
2444 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2445 return DPERR_UNINITIALIZED;
2447 /* Can't enumerate if the interface is already open */
2448 if ( This->dp2->bConnectionOpen )
2449 return DPERR_GENERIC;
2451 /* The loading of a lobby provider _seems_ to require a backdoor loading
2452 * of the service provider to also associate with this DP object. This is
2453 * because the app doesn't seem to have to call EnumConnections and
2454 * InitializeConnection for the SP before calling this method. As such
2455 * we'll do their dirty work for them with a quick hack so as to always
2456 * load the TCP/IP service provider.
2458 * The correct solution would seem to involve creating a dialog box which
2459 * contains the possible SPs. These dialog boxes most likely follow SDK
2460 * examples.
2462 if ( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
2464 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2466 if ( !DP_BuildSPCompoundAddr( (GUID*)&DPSPGUID_TCPIP, &connection, &size ) )
2468 ERR( "Can't build compound addr\n" );
2469 return DPERR_GENERIC;
2472 hr = IDirectPlayX_InitializeConnection( &This->IDirectPlay4_iface, connection, 0 );
2473 if ( FAILED(hr) )
2474 return hr;
2476 HeapFree( GetProcessHeap(), 0, connection );
2477 This->dp2->bSPInitialized = TRUE;
2481 /* Use the service provider default? */
2482 if ( !timeout )
2484 DPCAPS caps;
2485 caps.dwSize = sizeof( caps );
2487 IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, &caps, 0 );
2488 timeout = caps.dwTimeout;
2489 if ( !timeout )
2490 timeout = DPMSG_WAIT_5_SECS; /* Provide the TCP/IP default */
2493 if ( flags & DPENUMSESSIONS_STOPASYNC )
2495 DP_KillEnumSessionThread( This );
2496 return hr;
2499 if ( flags & DPENUMSESSIONS_ASYNC )
2501 /* Enumerate everything presently in the local session cache */
2502 DP_InvokeEnumSessionCallbacks( enumsessioncb, This->dp2->lpNameServerData, timeout,
2503 context );
2505 if ( This->dp2->dwEnumSessionLock )
2506 return DPERR_CONNECTING;
2508 /* See if we've already created a thread to service this interface */
2509 if ( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2511 DWORD tid;
2512 This->dp2->dwEnumSessionLock++;
2514 /* Send the first enum request inline since the user may cancel a dialog
2515 * if one is presented. Also, may also have a connecting return code.
2517 hr = NS_SendSessionRequestBroadcast( &sdesc->guidApplication, flags,
2518 &This->dp2->spData );
2520 if ( SUCCEEDED(hr) )
2522 EnumSessionAsyncCallbackData* data = HeapAlloc( GetProcessHeap(),
2523 HEAP_ZERO_MEMORY, sizeof( *data ) );
2524 /* FIXME: need to kill the thread on object deletion */
2525 data->lpSpData = &This->dp2->spData;
2526 data->requestGuid = sdesc->guidApplication;
2527 data->dwEnumSessionFlags = flags;
2528 data->dwTimeout = timeout;
2530 This->dp2->hKillEnumSessionThreadEvent = CreateEventW( NULL, TRUE, FALSE, NULL );
2531 if ( !DuplicateHandle( GetCurrentProcess(), This->dp2->hKillEnumSessionThreadEvent,
2532 GetCurrentProcess(), &data->hSuicideRequest, 0, FALSE,
2533 DUPLICATE_SAME_ACCESS ) )
2534 ERR( "Can't duplicate thread killing handle\n" );
2536 TRACE( ": creating EnumSessionsRequest thread\n" );
2537 This->dp2->hEnumSessionThread = CreateThread( NULL, 0,
2538 DP_EnumSessionsSendAsyncRequestThread, data, 0, &tid );
2540 This->dp2->dwEnumSessionLock--;
2543 else
2545 /* Invalidate the session cache for the interface */
2546 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2547 /* Send the broadcast for session enumeration */
2548 hr = NS_SendSessionRequestBroadcast( &sdesc->guidApplication, flags, &This->dp2->spData );
2549 SleepEx( timeout, FALSE );
2550 DP_InvokeEnumSessionCallbacks( enumsessioncb, This->dp2->lpNameServerData, timeout,
2551 context );
2554 return hr;
2557 static HRESULT WINAPI IDirectPlay2AImpl_GetCaps( IDirectPlay2A *iface, DPCAPS *caps, DWORD flags )
2559 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2560 return IDirectPlayX_GetCaps( &This->IDirectPlay4A_iface, caps, flags );
2563 static HRESULT WINAPI IDirectPlay2Impl_GetCaps( IDirectPlay2 *iface, DPCAPS *caps, DWORD flags )
2565 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2566 return IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, caps, flags );
2569 static HRESULT WINAPI IDirectPlay3AImpl_GetCaps( IDirectPlay3A *iface, DPCAPS *caps, DWORD flags )
2571 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2572 return IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, caps, flags );
2575 static HRESULT WINAPI IDirectPlay3Impl_GetCaps( IDirectPlay3 *iface, DPCAPS *caps, DWORD flags )
2577 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2578 return IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, caps, flags );
2581 static HRESULT WINAPI IDirectPlay4AImpl_GetCaps( IDirectPlay4A *iface, DPCAPS *caps, DWORD flags )
2583 return IDirectPlayX_GetPlayerCaps( iface, DPID_ALLPLAYERS, caps, flags );
2586 static HRESULT WINAPI IDirectPlay4Impl_GetCaps( IDirectPlay4 *iface, DPCAPS *caps, DWORD flags )
2588 return IDirectPlayX_GetPlayerCaps( iface, DPID_ALLPLAYERS, caps, flags );
2591 static HRESULT WINAPI IDirectPlay2AImpl_GetGroupData( IDirectPlay2A *iface, DPID group, void *data,
2592 DWORD *size, DWORD flags )
2594 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2595 return IDirectPlayX_GetGroupData( &This->IDirectPlay4A_iface, group, data, size, flags );
2598 static HRESULT WINAPI IDirectPlay2Impl_GetGroupData( IDirectPlay2 *iface, DPID group, void *data,
2599 DWORD *size, DWORD flags )
2601 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2602 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2605 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupData( IDirectPlay3A *iface, DPID group, void *data,
2606 DWORD *size, DWORD flags )
2608 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2609 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2612 static HRESULT WINAPI IDirectPlay3Impl_GetGroupData( IDirectPlay3 *iface, DPID group, void *data,
2613 DWORD *size, DWORD flags )
2615 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2616 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2619 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupData( IDirectPlay4A *iface, DPID group,
2620 void *data, DWORD *size, DWORD flags )
2622 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2623 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2626 static HRESULT WINAPI IDirectPlay4Impl_GetGroupData( IDirectPlay4 *iface, DPID group,
2627 void *data, DWORD *size, DWORD flags )
2629 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2630 lpGroupData gdata;
2631 DWORD bufsize;
2632 void *src;
2634 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x)\n", This, group, data, size, flags );
2636 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
2637 return DPERR_INVALIDGROUP;
2639 /* How much buffer is required? */
2640 if ( flags & DPSET_LOCAL )
2642 bufsize = gdata->dwLocalDataSize;
2643 src = gdata->lpLocalData;
2645 else
2647 bufsize = gdata->dwRemoteDataSize;
2648 src = gdata->lpRemoteData;
2651 /* Is the user requesting to know how big a buffer is required? */
2652 if ( !data || *size < bufsize )
2654 *size = bufsize;
2655 return DPERR_BUFFERTOOSMALL;
2658 CopyMemory( data, src, bufsize );
2660 return DP_OK;
2663 static HRESULT DP_IF_GetGroupName( IDirectPlayImpl *This, DPID idGroup, void *lpData,
2664 DWORD *lpdwDataSize, BOOL bAnsi )
2666 lpGroupData lpGData;
2667 LPDPNAME lpName = lpData;
2668 DWORD dwRequiredDataSize;
2670 FIXME("(%p)->(0x%08x,%p,%p,%u) ANSI ignored\n",
2671 This, idGroup, lpData, lpdwDataSize, bAnsi );
2673 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2675 return DPERR_INVALIDGROUP;
2678 dwRequiredDataSize = lpGData->name.dwSize;
2680 if( lpGData->name.u1.lpszShortNameA )
2682 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
2685 if( lpGData->name.u2.lpszLongNameA )
2687 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
2690 if( ( lpData == NULL ) ||
2691 ( *lpdwDataSize < dwRequiredDataSize )
2694 *lpdwDataSize = dwRequiredDataSize;
2695 return DPERR_BUFFERTOOSMALL;
2698 /* Copy the structure */
2699 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2701 if( lpGData->name.u1.lpszShortNameA )
2703 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2704 lpGData->name.u1.lpszShortNameA );
2706 else
2708 lpName->u1.lpszShortNameA = NULL;
2711 if( lpGData->name.u1.lpszShortNameA )
2713 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2714 lpGData->name.u2.lpszLongNameA );
2716 else
2718 lpName->u2.lpszLongNameA = NULL;
2721 return DP_OK;
2724 static HRESULT WINAPI IDirectPlay2AImpl_GetGroupName( IDirectPlay2A *iface, DPID group, void *data,
2725 DWORD *size )
2727 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2728 return IDirectPlayX_GetGroupName( &This->IDirectPlay4A_iface, group, data, size );
2731 static HRESULT WINAPI IDirectPlay2Impl_GetGroupName( IDirectPlay2 *iface, DPID group, void *data,
2732 DWORD *size )
2734 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2735 return IDirectPlayX_GetGroupName( &This->IDirectPlay4_iface, group, data, size );
2738 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupName( IDirectPlay3A *iface, DPID group, void *data,
2739 DWORD *size )
2741 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2742 return IDirectPlayX_GetGroupName( &This->IDirectPlay4_iface, group, data, size );
2745 static HRESULT WINAPI IDirectPlay3Impl_GetGroupName( IDirectPlay3 *iface, DPID group, void *data,
2746 DWORD *size )
2748 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2749 return IDirectPlayX_GetGroupName( &This->IDirectPlay4_iface, group, data, size );
2752 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupName( IDirectPlay4A *iface, DPID idGroup,
2753 void *lpData, DWORD *lpdwDataSize )
2755 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2756 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2759 static HRESULT WINAPI IDirectPlay4Impl_GetGroupName( IDirectPlay4 *iface, DPID idGroup,
2760 void *lpData, DWORD *lpdwDataSize )
2762 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2763 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2766 static HRESULT WINAPI IDirectPlay2AImpl_GetMessageCount( IDirectPlay2A *iface, DPID player,
2767 DWORD *count )
2769 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2770 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4A_iface, player, count );
2773 static HRESULT WINAPI IDirectPlay2Impl_GetMessageCount( IDirectPlay2 *iface, DPID player,
2774 DWORD *count )
2776 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2777 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4_iface, player, count );
2780 static HRESULT WINAPI IDirectPlay3AImpl_GetMessageCount( IDirectPlay3A *iface, DPID player,
2781 DWORD *count )
2783 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2784 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4_iface, player, count );
2787 static HRESULT WINAPI IDirectPlay3Impl_GetMessageCount( IDirectPlay3 *iface, DPID player,
2788 DWORD *count )
2790 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2791 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4_iface, player, count );
2794 static HRESULT WINAPI IDirectPlay4AImpl_GetMessageCount( IDirectPlay4A *iface, DPID player,
2795 DWORD *count )
2797 return IDirectPlayX_GetMessageQueue( iface, 0, player, DPMESSAGEQUEUE_RECEIVE, count, NULL );
2800 static HRESULT WINAPI IDirectPlay4Impl_GetMessageCount( IDirectPlay4 *iface, DPID player,
2801 DWORD *count )
2803 return IDirectPlayX_GetMessageQueue( iface, 0, player, DPMESSAGEQUEUE_RECEIVE, count, NULL );
2806 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerAddress( IDirectPlay2A *iface, DPID player,
2807 void *data, DWORD *size )
2809 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2810 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4A_iface, player, data, size );
2813 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerAddress( IDirectPlay2 *iface, DPID player,
2814 void *data, DWORD *size )
2816 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2817 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4_iface, player, data, size );
2820 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerAddress( IDirectPlay3A *iface, DPID player,
2821 void *data, DWORD *size )
2823 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2824 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4_iface, player, data, size );
2827 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerAddress( IDirectPlay3 *iface, DPID player,
2828 void *data, DWORD *size )
2830 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2831 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4_iface, player, data, size );
2834 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerAddress( IDirectPlay4A *iface, DPID player,
2835 void *data, DWORD *size )
2837 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2838 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, player, data, size );
2839 return DP_OK;
2842 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerAddress( IDirectPlay4 *iface, DPID player,
2843 void *data, DWORD *size )
2845 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2846 FIXME( "(%p)->(0x%08x,%p,%p): stub\n", This, player, data, size );
2847 return DP_OK;
2850 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerCaps( IDirectPlay2A *iface, DPID player,
2851 DPCAPS *caps, DWORD flags )
2853 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2854 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4A_iface, player, caps, flags );
2857 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerCaps( IDirectPlay2 *iface, DPID player,
2858 DPCAPS *caps, DWORD flags )
2860 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2861 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2864 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerCaps( IDirectPlay3A *iface, DPID player,
2865 DPCAPS *caps, DWORD flags )
2867 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2868 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2871 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerCaps( IDirectPlay3 *iface, DPID player,
2872 DPCAPS *caps, DWORD flags )
2874 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2875 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2878 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerCaps( IDirectPlay4A *iface, DPID player,
2879 DPCAPS *caps, DWORD flags )
2881 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2882 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2885 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerCaps( IDirectPlay4 *iface, DPID player,
2886 DPCAPS *caps, DWORD flags )
2888 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2889 DPSP_GETCAPSDATA data;
2891 TRACE( "(%p)->(0x%08x,%p,0x%08x)\n", This, player, caps, flags);
2893 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2894 return DPERR_UNINITIALIZED;
2896 /* Query the service provider */
2897 data.idPlayer = player;
2898 data.dwFlags = flags;
2899 data.lpCaps = caps;
2900 data.lpISP = This->dp2->spData.lpISP;
2902 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2905 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerData( IDirectPlay2A *iface, DPID player,
2906 void *data, DWORD *size, DWORD flags )
2908 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2909 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4A_iface, player, data, size, flags );
2912 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerData( IDirectPlay2 *iface, DPID player,
2913 void *data, DWORD *size, DWORD flags )
2915 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2916 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2919 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerData( IDirectPlay3A *iface, DPID player,
2920 void *data, DWORD *size, DWORD flags )
2922 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2923 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2926 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerData( IDirectPlay3 *iface, DPID player,
2927 void *data, DWORD *size, DWORD flags )
2929 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2930 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2933 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerData( IDirectPlay4A *iface, DPID player,
2934 void *data, DWORD *size, DWORD flags )
2936 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2937 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2940 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerData( IDirectPlay4 *iface, DPID player,
2941 void *data, DWORD *size, DWORD flags )
2943 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2944 lpPlayerList plist;
2945 DWORD bufsize;
2946 void *src;
2948 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x)\n", This, player, data, size, flags );
2950 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2951 return DPERR_UNINITIALIZED;
2953 if ( ( plist = DP_FindPlayer( This, player ) ) == NULL )
2954 return DPERR_INVALIDPLAYER;
2956 if ( flags & DPSET_LOCAL )
2958 bufsize = plist->lpPData->dwLocalDataSize;
2959 src = plist->lpPData->lpLocalData;
2961 else
2963 bufsize = plist->lpPData->dwRemoteDataSize;
2964 src = plist->lpPData->lpRemoteData;
2967 /* Is the user requesting to know how big a buffer is required? */
2968 if ( !data || *size < bufsize )
2970 *size = bufsize;
2971 return DPERR_BUFFERTOOSMALL;
2974 CopyMemory( data, src, bufsize );
2976 return DP_OK;
2979 static HRESULT DP_IF_GetPlayerName( IDirectPlayImpl *This, DPID idPlayer, void *lpData,
2980 DWORD *lpdwDataSize, BOOL bAnsi )
2982 lpPlayerList lpPList;
2983 LPDPNAME lpName = lpData;
2984 DWORD dwRequiredDataSize;
2986 FIXME( "(%p)->(0x%08x,%p,%p,%u): ANSI\n",
2987 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2989 if( This->dp2->connectionInitialized == NO_PROVIDER )
2991 return DPERR_UNINITIALIZED;
2994 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2996 return DPERR_INVALIDPLAYER;
2999 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
3001 if( lpPList->lpPData->name.u1.lpszShortNameA )
3003 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
3006 if( lpPList->lpPData->name.u2.lpszLongNameA )
3008 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
3011 if( ( lpData == NULL ) ||
3012 ( *lpdwDataSize < dwRequiredDataSize )
3015 *lpdwDataSize = dwRequiredDataSize;
3016 return DPERR_BUFFERTOOSMALL;
3019 /* Copy the structure */
3020 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
3022 if( lpPList->lpPData->name.u1.lpszShortNameA )
3024 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
3025 lpPList->lpPData->name.u1.lpszShortNameA );
3027 else
3029 lpName->u1.lpszShortNameA = NULL;
3032 if( lpPList->lpPData->name.u1.lpszShortNameA )
3034 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
3035 lpPList->lpPData->name.u2.lpszLongNameA );
3037 else
3039 lpName->u2.lpszLongNameA = NULL;
3042 return DP_OK;
3045 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerName( IDirectPlay2A *iface, DPID player,
3046 void *data, DWORD *size )
3048 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3049 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4A_iface, player, data, size );
3052 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerName( IDirectPlay2 *iface, DPID player,
3053 void *data, DWORD *size )
3055 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3056 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4_iface, player, data, size );
3059 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerName( IDirectPlay3A *iface, DPID player,
3060 void *data, DWORD *size )
3062 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3063 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4_iface, player, data, size );
3066 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerName( IDirectPlay3 *iface, DPID player,
3067 void *data, DWORD *size )
3069 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3070 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4_iface, player, data, size );
3073 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerName( IDirectPlay4A *iface, DPID idPlayer,
3074 void *lpData, DWORD *lpdwDataSize )
3076 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3077 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
3080 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerName( IDirectPlay4 *iface, DPID idPlayer,
3081 void *lpData, DWORD *lpdwDataSize )
3083 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3084 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
3087 static HRESULT DP_GetSessionDesc( IDirectPlayImpl *This, void *lpData, DWORD *lpdwDataSize,
3088 BOOL bAnsi )
3090 DWORD dwRequiredSize;
3092 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
3094 if( This->dp2->connectionInitialized == NO_PROVIDER )
3096 return DPERR_UNINITIALIZED;
3099 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
3101 return DPERR_INVALIDPARAMS;
3104 /* FIXME: Get from This->dp2->lpSessionDesc */
3105 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
3107 if ( ( lpData == NULL ) ||
3108 ( *lpdwDataSize < dwRequiredSize )
3111 *lpdwDataSize = dwRequiredSize;
3112 return DPERR_BUFFERTOOSMALL;
3115 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
3117 return DP_OK;
3120 static HRESULT WINAPI IDirectPlay2AImpl_GetSessionDesc( IDirectPlay2A *iface, void *data,
3121 DWORD *size )
3123 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3124 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4A_iface, data, size );
3127 static HRESULT WINAPI IDirectPlay2Impl_GetSessionDesc( IDirectPlay2 *iface, void *data,
3128 DWORD *size )
3130 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3131 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4_iface, data, size );
3134 static HRESULT WINAPI IDirectPlay3AImpl_GetSessionDesc( IDirectPlay3A *iface, void *data,
3135 DWORD *size )
3137 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3138 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4_iface, data, size );
3141 static HRESULT WINAPI IDirectPlay3Impl_GetSessionDesc( IDirectPlay3 *iface, void *data,
3142 DWORD *size )
3144 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3145 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4_iface, data, size );
3148 static HRESULT WINAPI IDirectPlay4AImpl_GetSessionDesc( IDirectPlay4A *iface, void *lpData,
3149 DWORD *lpdwDataSize )
3151 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3152 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
3155 static HRESULT WINAPI IDirectPlay4Impl_GetSessionDesc( IDirectPlay4 *iface, void *lpData,
3156 DWORD *lpdwDataSize )
3158 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3159 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
3162 static HRESULT WINAPI IDirectPlay2AImpl_Initialize( IDirectPlay2A *iface, GUID *guid )
3164 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3165 return IDirectPlayX_Initialize( &This->IDirectPlay4A_iface, guid );
3168 static HRESULT WINAPI IDirectPlay2Impl_Initialize( IDirectPlay2 *iface, GUID *guid )
3170 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3171 return IDirectPlayX_Initialize( &This->IDirectPlay4_iface, guid );
3174 static HRESULT WINAPI IDirectPlay3AImpl_Initialize( IDirectPlay3A *iface, GUID *guid )
3176 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3177 return IDirectPlayX_Initialize( &This->IDirectPlay4_iface, guid );
3180 static HRESULT WINAPI IDirectPlay3Impl_Initialize( IDirectPlay3 *iface, GUID *guid )
3182 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3183 return IDirectPlayX_Initialize( &This->IDirectPlay4_iface, guid );
3186 /* Intended only for COM compatibility. Always returns an error. */
3187 static HRESULT WINAPI IDirectPlay4AImpl_Initialize( IDirectPlay4A *iface, GUID *guid )
3189 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3190 TRACE("(%p)->(%p): no-op\n", This, guid );
3191 return DPERR_ALREADYINITIALIZED;
3194 static HRESULT WINAPI IDirectPlay4Impl_Initialize( IDirectPlay4 *iface, GUID *guid )
3196 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3197 TRACE( "(%p)->(%p): no-op\n", This, guid );
3198 return DPERR_ALREADYINITIALIZED;
3202 static HRESULT DP_SecureOpen( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpsd, DWORD dwFlags,
3203 const DPSECURITYDESC *lpSecurity, const DPCREDENTIALS *lpCredentials, BOOL bAnsi )
3205 HRESULT hr = DP_OK;
3207 FIXME( "(%p)->(%p,0x%08x,%p,%p): partial stub\n",
3208 This, lpsd, dwFlags, lpSecurity, lpCredentials );
3210 if( This->dp2->connectionInitialized == NO_PROVIDER )
3212 return DPERR_UNINITIALIZED;
3215 if( lpsd->dwSize != sizeof(DPSESSIONDESC2) )
3217 TRACE( ": rejecting invalid dpsd size (%d).\n", lpsd->dwSize );
3218 return DPERR_INVALIDPARAMS;
3221 if( This->dp2->bConnectionOpen )
3223 TRACE( ": rejecting already open connection.\n" );
3224 return DPERR_ALREADYINITIALIZED;
3227 /* If we're enumerating, kill the thread */
3228 DP_KillEnumSessionThread( This );
3230 if( dwFlags & DPOPEN_CREATE )
3232 /* Rightoo - this computer is the host and the local computer needs to be
3233 the name server so that others can join this session */
3234 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
3236 This->dp2->bHostInterface = TRUE;
3238 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
3239 if( FAILED( hr ) )
3241 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
3242 return hr;
3246 /* Invoke the conditional callback for the service provider */
3247 if( This->dp2->spData.lpCB->Open )
3249 DPSP_OPENDATA data;
3251 FIXME( "Not all data fields are correct. Need new parameter\n" );
3253 data.bCreate = (dwFlags & DPOPEN_CREATE ) != 0;
3254 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
3255 : NS_GetNSAddr( This->dp2->lpNameServerData );
3256 data.lpISP = This->dp2->spData.lpISP;
3257 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) != 0;
3258 data.dwOpenFlags = dwFlags;
3259 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
3261 hr = (*This->dp2->spData.lpCB->Open)(&data);
3262 if( FAILED( hr ) )
3264 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
3265 return hr;
3270 /* Create the system group of which everything is a part of */
3271 DPID systemGroup = DPID_SYSTEM_GROUP;
3273 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
3274 NULL, 0, 0, TRUE );
3278 if( dwFlags & DPOPEN_JOIN )
3280 DPID dpidServerId = DPID_UNKNOWN;
3282 /* Create the server player for this interface. This way we can receive
3283 * messages for this session.
3285 /* FIXME: I suppose that we should be setting an event for a receive
3286 * type of thing. That way the messaging thread could know to wake
3287 * up. DPlay would then trigger the hEvent for the player the
3288 * message is directed to.
3290 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
3292 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
3295 else if( dwFlags & DPOPEN_CREATE )
3297 DPID dpidNameServerId = DPID_NAME_SERVER;
3299 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
3300 0, DPPLAYER_SERVERPLAYER, bAnsi );
3303 if( FAILED(hr) )
3305 ERR( "Couldn't create name server/system player: %s\n",
3306 DPLAYX_HresultToString(hr) );
3309 return hr;
3312 static HRESULT WINAPI IDirectPlay2AImpl_Open( IDirectPlay2A *iface, DPSESSIONDESC2 *sdesc,
3313 DWORD flags )
3315 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3316 return IDirectPlayX_Open( &This->IDirectPlay4A_iface, sdesc, flags );
3319 static HRESULT WINAPI IDirectPlay2Impl_Open( IDirectPlay2 *iface, DPSESSIONDESC2 *sdesc,
3320 DWORD flags )
3322 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3323 return IDirectPlayX_Open( &This->IDirectPlay4_iface, sdesc, flags );
3326 static HRESULT WINAPI IDirectPlay3AImpl_Open( IDirectPlay3A *iface, DPSESSIONDESC2 *sdesc,
3327 DWORD flags )
3329 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3330 return IDirectPlayX_Open( &This->IDirectPlay4_iface, sdesc, flags );
3333 static HRESULT WINAPI IDirectPlay3Impl_Open( IDirectPlay3 *iface, DPSESSIONDESC2 *sdesc,
3334 DWORD flags )
3336 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3337 return IDirectPlayX_Open( &This->IDirectPlay4_iface, sdesc, flags );
3340 static HRESULT WINAPI IDirectPlay4AImpl_Open( IDirectPlay4A *iface, DPSESSIONDESC2 *sdesc,
3341 DWORD flags )
3343 return IDirectPlayX_SecureOpen( iface, sdesc, flags, NULL, NULL );
3346 static HRESULT WINAPI IDirectPlay4Impl_Open( IDirectPlay4 *iface, DPSESSIONDESC2 *sdesc,
3347 DWORD flags )
3349 return IDirectPlayX_SecureOpen( iface, sdesc, flags, NULL, NULL );
3352 static HRESULT DP_IF_Receive( IDirectPlayImpl *This, DPID *lpidFrom, DPID *lpidTo, DWORD dwFlags,
3353 void *lpData, DWORD *lpdwDataSize, BOOL bAnsi )
3355 LPDPMSG lpMsg = NULL;
3357 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p,%u): stub\n",
3358 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
3360 if( This->dp2->connectionInitialized == NO_PROVIDER )
3362 return DPERR_UNINITIALIZED;
3365 if( dwFlags == 0 )
3367 dwFlags = DPRECEIVE_ALL;
3370 /* If the lpData is NULL, we must be peeking the message */
3371 if( ( lpData == NULL ) &&
3372 !( dwFlags & DPRECEIVE_PEEK )
3375 return DPERR_INVALIDPARAMS;
3378 if( dwFlags & DPRECEIVE_ALL )
3380 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
3382 if( !( dwFlags & DPRECEIVE_PEEK ) )
3384 FIXME( "Remove from queue\n" );
3387 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
3388 ( dwFlags & DPRECEIVE_FROMPLAYER )
3391 FIXME( "Find matching message 0x%08x\n", dwFlags );
3393 else
3395 ERR( "Hmmm..dwFlags 0x%08x\n", dwFlags );
3398 if( lpMsg == NULL )
3400 return DPERR_NOMESSAGES;
3403 /* Copy into the provided buffer */
3404 if (lpData) CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
3406 return DP_OK;
3409 static HRESULT WINAPI IDirectPlay2AImpl_Receive( IDirectPlay2A *iface, DPID *from, DPID *to,
3410 DWORD flags, void *data, DWORD *size )
3412 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3413 return IDirectPlayX_Receive( &This->IDirectPlay4A_iface, from, to, flags, data, size );
3416 static HRESULT WINAPI IDirectPlay2Impl_Receive( IDirectPlay2 *iface, DPID *from, DPID *to,
3417 DWORD flags, void *data, DWORD *size )
3419 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3420 return IDirectPlayX_Receive( &This->IDirectPlay4_iface, from, to, flags, data, size );
3423 static HRESULT WINAPI IDirectPlay3AImpl_Receive( IDirectPlay3A *iface, DPID *from, DPID *to,
3424 DWORD flags, void *data, DWORD *size )
3426 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3427 return IDirectPlayX_Receive( &This->IDirectPlay4_iface, from, to, flags, data, size );
3430 static HRESULT WINAPI IDirectPlay3Impl_Receive( IDirectPlay3 *iface, DPID *from, DPID *to,
3431 DWORD flags, void *data, DWORD *size )
3433 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3434 return IDirectPlayX_Receive( &This->IDirectPlay4_iface, from, to, flags, data, size );
3437 static HRESULT WINAPI IDirectPlay4AImpl_Receive( IDirectPlay4A *iface, DPID *lpidFrom,
3438 DPID *lpidTo, DWORD dwFlags, void *lpData, DWORD *lpdwDataSize )
3440 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3441 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, TRUE );
3444 static HRESULT WINAPI IDirectPlay4Impl_Receive( IDirectPlay4 *iface, DPID *lpidFrom,
3445 DPID *lpidTo, DWORD dwFlags, void *lpData, DWORD *lpdwDataSize )
3447 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3448 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, FALSE );
3451 static HRESULT WINAPI IDirectPlay2AImpl_Send( IDirectPlay2A *iface, DPID from, DPID to,
3452 DWORD flags, void *data, DWORD size )
3454 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3455 return IDirectPlayX_Send( &This->IDirectPlay4A_iface, from, to, flags, data, size );
3458 static HRESULT WINAPI IDirectPlay2Impl_Send( IDirectPlay2 *iface, DPID from, DPID to,
3459 DWORD flags, void *data, DWORD size )
3461 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3462 return IDirectPlayX_Send( &This->IDirectPlay4_iface, from, to, flags, data, size );
3465 static HRESULT WINAPI IDirectPlay3AImpl_Send( IDirectPlay3A *iface, DPID from, DPID to,
3466 DWORD flags, void *data, DWORD size )
3468 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3469 return IDirectPlayX_Send( &This->IDirectPlay4_iface, from, to, flags, data, size );
3472 static HRESULT WINAPI IDirectPlay3Impl_Send( IDirectPlay3 *iface, DPID from, DPID to,
3473 DWORD flags, void *data, DWORD size )
3475 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3476 return IDirectPlayX_Send( &This->IDirectPlay4_iface, from, to, flags, data, size );
3479 static HRESULT WINAPI IDirectPlay4AImpl_Send( IDirectPlay4A *iface, DPID from, DPID to,
3480 DWORD flags, void *data, DWORD size )
3482 return IDirectPlayX_SendEx( iface, from, to, flags, data, size, 0, 0, NULL, NULL );
3485 static HRESULT WINAPI IDirectPlay4Impl_Send( IDirectPlay4 *iface, DPID from, DPID to,
3486 DWORD flags, void *data, DWORD size )
3488 return IDirectPlayX_SendEx( iface, from, to, flags, data, size, 0, 0, NULL, NULL );
3491 static HRESULT WINAPI IDirectPlay2AImpl_SetGroupData( IDirectPlay2A *iface, DPID group, void *data,
3492 DWORD size, DWORD flags )
3494 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3495 return IDirectPlayX_SetGroupData( &This->IDirectPlay4A_iface, group, data, size, flags );
3498 static HRESULT WINAPI IDirectPlay2Impl_SetGroupData( IDirectPlay2 *iface, DPID group, void *data,
3499 DWORD size, DWORD flags )
3501 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3502 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3505 static HRESULT WINAPI IDirectPlay3AImpl_SetGroupData( IDirectPlay3A *iface, DPID group, void *data,
3506 DWORD size, DWORD flags )
3508 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3509 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3512 static HRESULT WINAPI IDirectPlay3Impl_SetGroupData( IDirectPlay3 *iface, DPID group, void *data,
3513 DWORD size, DWORD flags )
3515 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3516 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3519 static HRESULT WINAPI IDirectPlay4AImpl_SetGroupData( IDirectPlay4A *iface, DPID group, void *data,
3520 DWORD size, DWORD flags )
3522 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3523 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3526 static HRESULT WINAPI IDirectPlay4Impl_SetGroupData( IDirectPlay4 *iface, DPID group, void *data,
3527 DWORD size, DWORD flags )
3529 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3530 lpGroupData gdata;
3532 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x)\n", This, group, data, size, flags );
3534 /* Parameter check */
3535 if ( !data && size )
3536 return DPERR_INVALIDPARAMS;
3538 /* Find the pointer to the data for this player */
3539 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
3540 return DPERR_INVALIDOBJECT;
3542 if ( !(flags & DPSET_LOCAL) )
3544 FIXME( "Was this group created by this interface?\n" );
3545 /* FIXME: If this is a remote update need to allow it but not
3546 * send a message.
3550 DP_SetGroupData( gdata, flags, data, size );
3552 /* FIXME: Only send a message if this group is local to the session otherwise
3553 * it will have been rejected above
3555 if ( !(flags & DPSET_LOCAL) )
3556 FIXME( "Send msg?\n" );
3558 return DP_OK;
3561 static HRESULT DP_IF_SetGroupName( IDirectPlayImpl *This, DPID idGroup, DPNAME *lpGroupName,
3562 DWORD dwFlags, BOOL bAnsi )
3564 lpGroupData lpGData;
3566 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n", This, idGroup,
3567 lpGroupName, dwFlags, bAnsi );
3569 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3571 return DPERR_INVALIDGROUP;
3574 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
3576 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3577 FIXME( "Message not sent and dwFlags ignored\n" );
3579 return DP_OK;
3582 static HRESULT WINAPI IDirectPlay2AImpl_SetGroupName( IDirectPlay2A *iface, DPID group,
3583 DPNAME *name, DWORD flags )
3585 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3586 return IDirectPlayX_SetGroupName( &This->IDirectPlay4A_iface, group, name, flags );
3589 static HRESULT WINAPI IDirectPlay2Impl_SetGroupName( IDirectPlay2 *iface, DPID group,
3590 DPNAME *name, DWORD flags )
3592 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3593 return IDirectPlayX_SetGroupName( &This->IDirectPlay4_iface, group, name, flags );
3596 static HRESULT WINAPI IDirectPlay3AImpl_SetGroupName( IDirectPlay3A *iface, DPID group,
3597 DPNAME *name, DWORD flags )
3599 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3600 return IDirectPlayX_SetGroupName( &This->IDirectPlay4_iface, group, name, flags );
3603 static HRESULT WINAPI IDirectPlay3Impl_SetGroupName( IDirectPlay3 *iface, DPID group,
3604 DPNAME *name, DWORD flags )
3606 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3607 return IDirectPlayX_SetGroupName( &This->IDirectPlay4_iface, group, name, flags );
3610 static HRESULT WINAPI IDirectPlay4AImpl_SetGroupName( IDirectPlay4A *iface, DPID idGroup,
3611 DPNAME *lpGroupName, DWORD dwFlags )
3613 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3614 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
3617 static HRESULT WINAPI IDirectPlay4Impl_SetGroupName( IDirectPlay4 *iface, DPID idGroup,
3618 DPNAME *lpGroupName, DWORD dwFlags )
3620 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3621 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
3624 static HRESULT WINAPI IDirectPlay2AImpl_SetPlayerData( IDirectPlay2A *iface, DPID player,
3625 void *data, DWORD size, DWORD flags )
3627 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3628 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4A_iface, player, data, size, flags );
3631 static HRESULT WINAPI IDirectPlay2Impl_SetPlayerData( IDirectPlay2 *iface, DPID player,
3632 void *data, DWORD size, DWORD flags )
3634 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3635 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
3638 static HRESULT WINAPI IDirectPlay3AImpl_SetPlayerData( IDirectPlay3A *iface, DPID player,
3639 void *data, DWORD size, DWORD flags )
3641 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3642 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
3645 static HRESULT WINAPI IDirectPlay3Impl_SetPlayerData( IDirectPlay3 *iface, DPID player,
3646 void *data, DWORD size, DWORD flags )
3648 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3649 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
3652 static HRESULT WINAPI IDirectPlay4AImpl_SetPlayerData( IDirectPlay4A *iface, DPID player,
3653 void *data, DWORD size, DWORD flags )
3655 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3656 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
3659 static HRESULT WINAPI IDirectPlay4Impl_SetPlayerData( IDirectPlay4 *iface, DPID player,
3660 void *data, DWORD size, DWORD flags )
3662 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3663 lpPlayerList plist;
3665 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x)\n", This, player, data, size, flags );
3667 if ( This->dp2->connectionInitialized == NO_PROVIDER )
3668 return DPERR_UNINITIALIZED;
3670 /* Parameter check */
3671 if ( !data && size )
3672 return DPERR_INVALIDPARAMS;
3674 /* Find the pointer to the data for this player */
3675 if ( (plist = DP_FindPlayer( This, player )) == NULL )
3676 return DPERR_INVALIDPLAYER;
3678 if ( !(flags & DPSET_LOCAL) )
3680 FIXME( "Was this group created by this interface?\n" );
3681 /* FIXME: If this is a remote update need to allow it but not
3682 * send a message.
3686 DP_SetPlayerData( plist->lpPData, flags, data, size );
3688 if ( !(flags & DPSET_LOCAL) )
3689 FIXME( "Send msg?\n" );
3691 return DP_OK;
3694 static HRESULT DP_IF_SetPlayerName( IDirectPlayImpl *This, DPID idPlayer, DPNAME *lpPlayerName,
3695 DWORD dwFlags, BOOL bAnsi )
3697 lpPlayerList lpPList;
3699 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n",
3700 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3702 if( This->dp2->connectionInitialized == NO_PROVIDER )
3704 return DPERR_UNINITIALIZED;
3707 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3709 return DPERR_INVALIDGROUP;
3712 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3714 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3715 FIXME( "Message not sent and dwFlags ignored\n" );
3717 return DP_OK;
3720 static HRESULT WINAPI IDirectPlay2AImpl_SetPlayerName( IDirectPlay2A *iface, DPID player,
3721 DPNAME *name, DWORD flags )
3723 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3724 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4A_iface, player, name, flags );
3727 static HRESULT WINAPI IDirectPlay2Impl_SetPlayerName( IDirectPlay2 *iface, DPID player,
3728 DPNAME *name, DWORD flags )
3730 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3731 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4_iface, player, name, flags );
3734 static HRESULT WINAPI IDirectPlay3AImpl_SetPlayerName( IDirectPlay3A *iface, DPID player,
3735 DPNAME *name, DWORD flags )
3737 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3738 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4_iface, player, name, flags );
3741 static HRESULT WINAPI IDirectPlay3Impl_SetPlayerName( IDirectPlay3 *iface, DPID player,
3742 DPNAME *name, DWORD flags )
3744 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3745 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4_iface, player, name, flags );
3748 static HRESULT WINAPI IDirectPlay4AImpl_SetPlayerName( IDirectPlay4A *iface, DPID idPlayer,
3749 DPNAME *lpPlayerName, DWORD dwFlags )
3751 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3752 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3755 static HRESULT WINAPI IDirectPlay4Impl_SetPlayerName( IDirectPlay4 *iface, DPID idPlayer,
3756 DPNAME *lpPlayerName, DWORD dwFlags )
3758 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3759 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3762 static HRESULT DP_SetSessionDesc( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpSessDesc,
3763 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3765 DWORD dwRequiredSize;
3766 LPDPSESSIONDESC2 lpTempSessDesc;
3768 TRACE( "(%p)->(%p,0x%08x,%u,%u)\n",
3769 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3771 if( This->dp2->connectionInitialized == NO_PROVIDER )
3773 return DPERR_UNINITIALIZED;
3776 if( dwFlags )
3778 return DPERR_INVALIDPARAMS;
3781 /* Only the host is allowed to update the session desc */
3782 if( !This->dp2->bHostInterface )
3784 return DPERR_ACCESSDENIED;
3787 /* FIXME: Copy into This->dp2->lpSessionDesc */
3788 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3789 lpTempSessDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize );
3791 if( lpTempSessDesc == NULL )
3793 return DPERR_OUTOFMEMORY;
3796 /* Free the old */
3797 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3799 This->dp2->lpSessionDesc = lpTempSessDesc;
3800 /* Set the new */
3801 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3802 if( bInitial )
3804 /*Initializing session GUID*/
3805 CoCreateGuid( &(This->dp2->lpSessionDesc->guidInstance) );
3807 /* If this is an external invocation of the interface, we should be
3808 * letting everyone know that things have changed. Otherwise this is
3809 * just an initialization and it doesn't need to be propagated.
3811 if( !bInitial )
3813 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3816 return DP_OK;
3819 static HRESULT WINAPI IDirectPlay2AImpl_SetSessionDesc( IDirectPlay2A *iface, DPSESSIONDESC2 *sdesc,
3820 DWORD flags )
3822 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3823 return IDirectPlayX_SetSessionDesc( &This->IDirectPlay4A_iface, sdesc, flags );
3826 static HRESULT WINAPI IDirectPlay2Impl_SetSessionDesc( IDirectPlay2 *iface, DPSESSIONDESC2 *sdesc,
3827 DWORD flags )
3829 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3830 return IDirectPlayX_SetSessionDesc( &This->IDirectPlay4_iface, sdesc, flags );
3833 static HRESULT WINAPI IDirectPlay3AImpl_SetSessionDesc( IDirectPlay3A *iface, DPSESSIONDESC2 *sdesc,
3834 DWORD flags )
3836 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3837 return IDirectPlayX_SetSessionDesc( &This->IDirectPlay4_iface, sdesc, flags );
3840 static HRESULT WINAPI IDirectPlay3Impl_SetSessionDesc( IDirectPlay3 *iface, DPSESSIONDESC2 *sdesc,
3841 DWORD flags )
3843 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3844 return IDirectPlayX_SetSessionDesc( &This->IDirectPlay4_iface, sdesc, flags );
3847 static HRESULT WINAPI IDirectPlay4AImpl_SetSessionDesc( IDirectPlay4A *iface,
3848 DPSESSIONDESC2 *lpSessDesc, DWORD dwFlags )
3850 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3851 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3854 static HRESULT WINAPI IDirectPlay4Impl_SetSessionDesc( IDirectPlay4 *iface,
3855 DPSESSIONDESC2 *lpSessDesc, DWORD dwFlags )
3857 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3858 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3861 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3862 static DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3864 DWORD dwSize = 0;
3866 if( lpSessDesc == NULL )
3868 /* Hmmm..don't need any size? */
3869 ERR( "NULL lpSessDesc\n" );
3870 return dwSize;
3873 dwSize += sizeof( *lpSessDesc );
3875 if( bAnsi )
3877 if( lpSessDesc->u1.lpszSessionNameA )
3879 dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1;
3882 if( lpSessDesc->u2.lpszPasswordA )
3884 dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1;
3887 else /* UNICODE */
3889 if( lpSessDesc->u1.lpszSessionName )
3891 dwSize += sizeof( WCHAR ) *
3892 ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 );
3895 if( lpSessDesc->u2.lpszPassword )
3897 dwSize += sizeof( WCHAR ) *
3898 ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 );
3902 return dwSize;
3905 /* Assumes that contiguous buffers are already allocated. */
3906 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3907 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3909 BYTE* lpStartOfFreeSpace;
3911 if( lpSessionDest == NULL )
3913 ERR( "NULL lpSessionDest\n" );
3914 return;
3917 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3919 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3921 if( bAnsi )
3923 if( lpSessionSrc->u1.lpszSessionNameA )
3925 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3926 lpSessionDest->u1.lpszSessionNameA );
3927 lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3928 lpStartOfFreeSpace +=
3929 lstrlenA( lpSessionDest->u1.lpszSessionNameA ) + 1;
3932 if( lpSessionSrc->u2.lpszPasswordA )
3934 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3935 lpSessionDest->u2.lpszPasswordA );
3936 lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3939 else /* UNICODE */
3941 if( lpSessionSrc->u1.lpszSessionName )
3943 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3944 lpSessionDest->u1.lpszSessionName );
3945 lpSessionDest->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3946 lpStartOfFreeSpace += sizeof(WCHAR) *
3947 ( lstrlenW( lpSessionDest->u1.lpszSessionName ) + 1 );
3950 if( lpSessionSrc->u2.lpszPassword )
3952 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3953 lpSessionDest->u2.lpszPassword );
3954 lpSessionDest->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3959 static HRESULT WINAPI IDirectPlay3AImpl_AddGroupToGroup( IDirectPlay3A *iface, DPID parent,
3960 DPID group )
3962 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3963 return IDirectPlayX_AddGroupToGroup( &This->IDirectPlay4A_iface, parent, group );
3966 static HRESULT WINAPI IDirectPlay3Impl_AddGroupToGroup( IDirectPlay3 *iface, DPID parent,
3967 DPID group )
3969 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3970 return IDirectPlayX_AddGroupToGroup( &This->IDirectPlay4_iface, parent, group );
3973 static HRESULT WINAPI IDirectPlay4AImpl_AddGroupToGroup( IDirectPlay4A *iface, DPID parent,
3974 DPID group )
3976 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3977 return IDirectPlayX_AddGroupToGroup( &This->IDirectPlay4_iface, parent, group );
3980 static HRESULT WINAPI IDirectPlay4Impl_AddGroupToGroup( IDirectPlay4 *iface, DPID parent,
3981 DPID group )
3983 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3984 lpGroupData gdata;
3985 lpGroupList glist;
3987 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, parent, group );
3989 if ( This->dp2->connectionInitialized == NO_PROVIDER )
3990 return DPERR_UNINITIALIZED;
3992 if ( !DP_FindAnyGroup(This, parent ) )
3993 return DPERR_INVALIDGROUP;
3995 if ( ( gdata = DP_FindAnyGroup(This, group ) ) == NULL )
3996 return DPERR_INVALIDGROUP;
3998 /* Create a player list (ie "shortcut" ) */
3999 glist = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *glist ) );
4000 if ( !glist )
4001 return DPERR_CANTADDPLAYER;
4003 /* Add the shortcut */
4004 gdata->uRef++;
4005 glist->lpGData = gdata;
4007 /* Add the player to the list of players for this group */
4008 DPQ_INSERT( gdata->groups, glist, groups );
4010 /* Send a ADDGROUPTOGROUP message */
4011 FIXME( "Not sending message\n" );
4013 return DP_OK;
4016 static HRESULT DP_IF_CreateGroupInGroup( IDirectPlayImpl *This, void *lpMsgHdr, DPID idParentGroup,
4017 DPID *lpidGroup, DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags,
4018 BOOL bAnsi )
4020 lpGroupData lpGParentData;
4021 lpGroupList lpGList;
4022 lpGroupData lpGData;
4024 TRACE( "(%p)->(0x%08x,%p,%p,%p,0x%08x,0x%08x,%u)\n",
4025 This, idParentGroup, lpidGroup, lpGroupName, lpData,
4026 dwDataSize, dwFlags, bAnsi );
4028 if( This->dp2->connectionInitialized == NO_PROVIDER )
4030 return DPERR_UNINITIALIZED;
4033 /* Verify that the specified parent is valid */
4034 if( ( lpGParentData = DP_FindAnyGroup(This, idParentGroup ) ) == NULL )
4035 return DPERR_INVALIDGROUP;
4037 lpGData = DP_CreateGroup(This, lpidGroup, lpGroupName, dwFlags, idParentGroup, bAnsi );
4039 if( lpGData == NULL )
4041 return DPERR_CANTADDPLAYER; /* yes player not group */
4044 /* Something else is referencing this data */
4045 lpGData->uRef++;
4047 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
4049 /* The list has now been inserted into the interface group list. We now
4050 need to put a "shortcut" to this group in the parent group */
4051 lpGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGList ) );
4052 if( lpGList == NULL )
4054 FIXME( "Memory leak\n" );
4055 return DPERR_CANTADDPLAYER; /* yes player not group */
4058 lpGList->lpGData = lpGData;
4060 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
4062 /* Let the SP know that we've created this group */
4063 if( This->dp2->spData.lpCB->CreateGroup )
4065 DPSP_CREATEGROUPDATA data;
4067 TRACE( "Calling SP CreateGroup\n" );
4069 data.idGroup = *lpidGroup;
4070 data.dwFlags = dwFlags;
4071 data.lpSPMessageHeader = lpMsgHdr;
4072 data.lpISP = This->dp2->spData.lpISP;
4074 (*This->dp2->spData.lpCB->CreateGroup)( &data );
4077 /* Inform all other peers of the creation of a new group. If there are
4078 * no peers keep this quiet.
4080 if( This->dp2->lpSessionDesc &&
4081 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
4083 DPMSG_CREATEPLAYERORGROUP msg;
4085 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
4086 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
4087 msg.dpId = *lpidGroup;
4088 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
4089 msg.lpData = lpData;
4090 msg.dwDataSize = dwDataSize;
4091 msg.dpnName = *lpGroupName;
4093 /* FIXME: Correct to just use send effectively? */
4094 /* FIXME: Should size include data w/ message or just message "header" */
4095 /* FIXME: Check return code */
4096 IDirectPlayX_SendEx( &This->IDirectPlay4_iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
4097 sizeof( msg ), 0, 0, NULL, NULL );
4100 return DP_OK;
4103 static HRESULT WINAPI IDirectPlay3AImpl_CreateGroupInGroup( IDirectPlay3A *iface, DPID parent,
4104 DPID *group, DPNAME *name, void *data, DWORD size, DWORD flags )
4106 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4107 return IDirectPlayX_CreateGroupInGroup( &This->IDirectPlay4A_iface, parent, group, name,
4108 data, size, flags );
4111 static HRESULT WINAPI IDirectPlay3Impl_CreateGroupInGroup( IDirectPlay3 *iface, DPID parent,
4112 DPID *group, DPNAME *name, void *data, DWORD size, DWORD flags )
4114 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4115 return IDirectPlayX_CreateGroupInGroup( &This->IDirectPlay4_iface, parent, group, name,
4116 data, size, flags );
4119 static HRESULT WINAPI IDirectPlay4AImpl_CreateGroupInGroup( IDirectPlay4A *iface,
4120 DPID idParentGroup, DPID *lpidGroup, DPNAME *lpGroupName, void *lpData, DWORD dwDataSize,
4121 DWORD dwFlags )
4123 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4125 *lpidGroup = DPID_UNKNOWN;
4127 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup, lpGroupName, lpData,
4128 dwDataSize, dwFlags, TRUE );
4131 static HRESULT WINAPI IDirectPlay4Impl_CreateGroupInGroup( IDirectPlay4 *iface, DPID idParentGroup,
4132 DPID *lpidGroup, DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags )
4134 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4136 *lpidGroup = DPID_UNKNOWN;
4138 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup, lpGroupName, lpData,
4139 dwDataSize, dwFlags, FALSE );
4142 static HRESULT WINAPI IDirectPlay3AImpl_DeleteGroupFromGroup( IDirectPlay3A *iface, DPID parent,
4143 DPID group )
4145 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4146 return IDirectPlayX_DeleteGroupFromGroup( &This->IDirectPlay4A_iface, parent, group );
4149 static HRESULT WINAPI IDirectPlay3Impl_DeleteGroupFromGroup( IDirectPlay3 *iface, DPID parent,
4150 DPID group )
4152 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4153 return IDirectPlayX_DeleteGroupFromGroup( &This->IDirectPlay4_iface, parent, group );
4156 static HRESULT WINAPI IDirectPlay4AImpl_DeleteGroupFromGroup( IDirectPlay4A *iface, DPID parent,
4157 DPID group )
4159 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4160 return IDirectPlayX_DeleteGroupFromGroup( &This->IDirectPlay4_iface, parent, group );
4163 static HRESULT WINAPI IDirectPlay4Impl_DeleteGroupFromGroup( IDirectPlay4 *iface, DPID parent,
4164 DPID group )
4166 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4167 lpGroupList glist;
4168 lpGroupData parentdata;
4170 TRACE("(%p)->(0x%08x,0x%08x)\n", This, parent, group );
4172 /* Is the parent group valid? */
4173 if ( ( parentdata = DP_FindAnyGroup(This, parent ) ) == NULL )
4174 return DPERR_INVALIDGROUP;
4176 /* Remove the group from the parent group queue */
4177 DPQ_REMOVE_ENTRY( parentdata->groups, groups, lpGData->dpid, ==, group, glist );
4179 if ( glist == NULL )
4180 return DPERR_INVALIDGROUP;
4182 /* Decrement the ref count */
4183 glist->lpGData->uRef--;
4185 /* Free up the list item */
4186 HeapFree( GetProcessHeap(), 0, glist );
4188 /* Should send a DELETEGROUPFROMGROUP message */
4189 FIXME( "message not sent\n" );
4191 return DP_OK;
4194 static BOOL DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
4195 LPDWORD lpdwBufSize )
4197 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
4198 HRESULT hr;
4200 dpCompoundAddress.dwDataSize = sizeof( GUID );
4201 dpCompoundAddress.guidDataType = DPAID_ServiceProvider;
4202 dpCompoundAddress.lpData = lpcSpGuid;
4204 *lplpAddrBuf = NULL;
4205 *lpdwBufSize = 0;
4207 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
4208 lpdwBufSize, TRUE );
4210 if( hr != DPERR_BUFFERTOOSMALL )
4212 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
4213 return FALSE;
4216 /* Now allocate the buffer */
4217 *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4218 *lpdwBufSize );
4220 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
4221 lpdwBufSize, TRUE );
4222 if( FAILED(hr) )
4224 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
4225 return FALSE;
4228 return TRUE;
4231 static HRESULT WINAPI IDirectPlay3AImpl_EnumConnections( IDirectPlay3A *iface,
4232 const GUID *application, LPDPENUMCONNECTIONSCALLBACK enumcb, void *context, DWORD flags )
4234 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4235 return IDirectPlayX_EnumConnections( &This->IDirectPlay4A_iface, application, enumcb, context,
4236 flags );
4239 static HRESULT WINAPI IDirectPlay3Impl_EnumConnections( IDirectPlay3 *iface,
4240 const GUID *application, LPDPENUMCONNECTIONSCALLBACK enumcb, void *context, DWORD flags )
4242 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4243 return IDirectPlayX_EnumConnections( &This->IDirectPlay4_iface, application, enumcb, context,
4244 flags );
4247 static HRESULT WINAPI IDirectPlay4AImpl_EnumConnections( IDirectPlay4A *iface,
4248 const GUID *lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, void *lpContext,
4249 DWORD dwFlags )
4251 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4252 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
4254 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
4255 if( dwFlags == 0 )
4257 dwFlags = DPCONNECTION_DIRECTPLAY;
4260 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
4261 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) )
4264 return DPERR_INVALIDFLAGS;
4267 if( !lpEnumCallback )
4269 return DPERR_INVALIDPARAMS;
4272 /* Enumerate DirectPlay service providers */
4273 if( dwFlags & DPCONNECTION_DIRECTPLAY )
4275 HKEY hkResult;
4276 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4277 LPCSTR guidDataSubKey = "Guid";
4278 char subKeyName[51];
4279 DWORD dwIndex, sizeOfSubKeyName=50;
4280 FILETIME filetime;
4282 /* Need to loop over the service providers in the registry */
4283 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4284 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4286 /* Hmmm. Does this mean that there are no service providers? */
4287 ERR(": no service providers?\n");
4288 return DP_OK;
4292 /* Traverse all the service providers we have available */
4293 for( dwIndex=0;
4294 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4295 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4296 ++dwIndex, sizeOfSubKeyName=51 )
4299 HKEY hkServiceProvider;
4300 GUID serviceProviderGUID;
4301 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
4302 char returnBuffer[51];
4303 WCHAR buff[51];
4304 DPNAME dpName;
4305 BOOL bBuildPass;
4307 LPVOID lpAddressBuffer = NULL;
4308 DWORD dwAddressBufferSize = 0;
4310 TRACE(" this time through: %s\n", subKeyName );
4312 /* Get a handle for this particular service provider */
4313 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4314 &hkServiceProvider ) != ERROR_SUCCESS )
4316 ERR(": what the heck is going on?\n" );
4317 continue;
4320 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4321 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
4322 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4324 ERR(": missing GUID registry data members\n" );
4325 RegCloseKey(hkServiceProvider);
4326 continue;
4328 RegCloseKey(hkServiceProvider);
4330 /* FIXME: Check return types to ensure we're interpreting data right */
4331 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4332 CLSIDFromString( buff, &serviceProviderGUID );
4333 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4335 /* Fill in the DPNAME struct for the service provider */
4336 dpName.dwSize = sizeof( dpName );
4337 dpName.dwFlags = 0;
4338 dpName.u1.lpszShortNameA = subKeyName;
4339 dpName.u2.lpszLongNameA = NULL;
4341 /* Create the compound address for the service provider.
4342 * NOTE: This is a gruesome architectural scar right now. DP
4343 * uses DPL and DPL uses DP. Nasty stuff. This may be why the
4344 * native dll just gets around this little bit by allocating an
4345 * 80 byte buffer which isn't even filled with a valid compound
4346 * address. Oh well. Creating a proper compound address is the
4347 * way to go anyways despite this method taking slightly more
4348 * heap space and realtime :) */
4350 bBuildPass = DP_BuildSPCompoundAddr( &serviceProviderGUID,
4351 &lpAddressBuffer,
4352 &dwAddressBufferSize );
4353 if( !bBuildPass )
4355 ERR( "Can't build compound addr\n" );
4356 return DPERR_GENERIC;
4359 /* The enumeration will return FALSE if we are not to continue */
4360 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
4361 &dpName, dwFlags, lpContext ) )
4363 return DP_OK;
4368 /* Enumerate DirectPlayLobby service providers */
4369 if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY )
4371 HKEY hkResult;
4372 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
4373 LPCSTR guidDataSubKey = "Guid";
4374 char subKeyName[51];
4375 DWORD dwIndex, sizeOfSubKeyName=50;
4376 FILETIME filetime;
4378 /* Need to loop over the service providers in the registry */
4379 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4380 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4382 /* Hmmm. Does this mean that there are no service providers? */
4383 ERR(": no service providers?\n");
4384 return DP_OK;
4388 /* Traverse all the lobby providers we have available */
4389 for( dwIndex=0;
4390 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4391 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4392 ++dwIndex, sizeOfSubKeyName=51 )
4395 HKEY hkServiceProvider;
4396 GUID serviceProviderGUID;
4397 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
4398 char returnBuffer[51];
4399 WCHAR buff[51];
4400 DPNAME dpName;
4401 HRESULT hr;
4403 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
4404 LPVOID lpAddressBuffer = NULL;
4405 DWORD dwAddressBufferSize = 0;
4407 TRACE(" this time through: %s\n", subKeyName );
4409 /* Get a handle for this particular service provider */
4410 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4411 &hkServiceProvider ) != ERROR_SUCCESS )
4413 ERR(": what the heck is going on?\n" );
4414 continue;
4417 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4418 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
4419 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4421 ERR(": missing GUID registry data members\n" );
4422 RegCloseKey(hkServiceProvider);
4423 continue;
4425 RegCloseKey(hkServiceProvider);
4427 /* FIXME: Check return types to ensure we're interpreting data right */
4428 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4429 CLSIDFromString( buff, &serviceProviderGUID );
4430 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4432 /* Fill in the DPNAME struct for the service provider */
4433 dpName.dwSize = sizeof( dpName );
4434 dpName.dwFlags = 0;
4435 dpName.u1.lpszShortNameA = subKeyName;
4436 dpName.u2.lpszLongNameA = NULL;
4438 /* Create the compound address for the service provider.
4439 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
4440 nast stuff. This may be why the native dll just gets around this little bit by
4441 allocating an 80 byte buffer which isn't even a filled with a valid compound
4442 address. Oh well. Creating a proper compound address is the way to go anyways
4443 despite this method taking slightly more heap space and realtime :) */
4445 dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
4446 dpCompoundAddress.dwDataSize = sizeof( GUID );
4447 dpCompoundAddress.lpData = &serviceProviderGUID;
4449 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
4450 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
4452 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
4453 return hr;
4456 /* Now allocate the buffer */
4457 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
4459 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
4460 &dwAddressBufferSize, TRUE ) ) != DP_OK )
4462 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
4463 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
4464 return hr;
4467 /* The enumeration will return FALSE if we are not to continue */
4468 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
4469 &dpName, dwFlags, lpContext ) )
4471 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
4472 return DP_OK;
4474 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
4478 return DP_OK;
4481 static HRESULT WINAPI IDirectPlay4Impl_EnumConnections( IDirectPlay4 *iface,
4482 const GUID *application, LPDPENUMCONNECTIONSCALLBACK enumcb, void *context, DWORD flags )
4484 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4485 FIXME( "(%p)->(%p,%p,%p,0x%08x): stub\n", This, application, enumcb, context, flags );
4486 return DP_OK;
4489 static HRESULT WINAPI IDirectPlay3AImpl_EnumGroupsInGroup( IDirectPlay3A *iface, DPID group,
4490 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
4492 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4493 return IDirectPlayX_EnumGroupsInGroup( &This->IDirectPlay4A_iface, group, instance,
4494 enumplayercb, context, flags );
4497 static HRESULT WINAPI IDirectPlay3Impl_EnumGroupsInGroup( IDirectPlay3 *iface, DPID group,
4498 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
4500 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4501 return IDirectPlayX_EnumGroupsInGroup( &This->IDirectPlay4_iface, group, instance,
4502 enumplayercb, context, flags );
4505 static HRESULT WINAPI IDirectPlay4AImpl_EnumGroupsInGroup( IDirectPlay4A *iface, DPID group,
4506 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
4508 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4509 return IDirectPlayX_EnumGroupsInGroup( &This->IDirectPlay4_iface, group, instance,
4510 enumplayercb, context, flags );
4513 static HRESULT WINAPI IDirectPlay4Impl_EnumGroupsInGroup( IDirectPlay4 *iface, DPID group,
4514 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
4516 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4517 lpGroupList glist;
4518 lpGroupData gdata;
4520 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x): semi stub\n", This, group, instance, enumplayercb,
4521 context, flags );
4523 if ( This->dp2->connectionInitialized == NO_PROVIDER )
4524 return DPERR_UNINITIALIZED;
4526 if ( ( gdata = DP_FindAnyGroup(This, group ) ) == NULL )
4527 return DPERR_INVALIDGROUP;
4529 if ( DPQ_IS_EMPTY( gdata->groups ) )
4530 return DP_OK;
4533 for( glist = DPQ_FIRST( gdata->groups ); ; glist = DPQ_NEXT( glist->groups ) )
4535 /* FIXME: Should check flags for match here */
4536 if ( !(*enumplayercb)( glist->lpGData->dpid, DPPLAYERTYPE_GROUP, &glist->lpGData->name,
4537 flags, context ) )
4538 return DP_OK; /* User requested break */
4540 if ( DPQ_IS_ENDOFLIST( glist->groups ) )
4541 break;
4544 return DP_OK;
4547 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupConnectionSettings( IDirectPlay3A *iface,
4548 DWORD flags, DPID group, void *data, DWORD *size )
4550 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4551 return IDirectPlayX_GetGroupConnectionSettings( &This->IDirectPlay4A_iface, flags, group,
4552 data, size );
4555 static HRESULT WINAPI IDirectPlay3Impl_GetGroupConnectionSettings( IDirectPlay3 *iface,
4556 DWORD flags, DPID group, void *data, DWORD *size )
4558 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4559 return IDirectPlayX_GetGroupConnectionSettings( &This->IDirectPlay4_iface, flags, group,
4560 data, size );
4563 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupConnectionSettings( IDirectPlay4A *iface,
4564 DWORD flags, DPID group, void *data, DWORD *size )
4566 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4567 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, flags, group, data, size );
4568 return DP_OK;
4571 static HRESULT WINAPI IDirectPlay4Impl_GetGroupConnectionSettings( IDirectPlay4 *iface, DWORD flags,
4572 DPID group, void *data, DWORD *size )
4574 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4575 FIXME( "(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, flags, group, data, size );
4576 return DP_OK;
4579 static BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
4580 REFGUID guidDataType,
4581 DWORD dwDataSize,
4582 LPCVOID lpData,
4583 LPVOID lpContext )
4585 /* Looking for the GUID of the provider to load */
4586 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
4587 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
4590 TRACE( "Found SP/LP (%s) %s (data size = 0x%08x)\n",
4591 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
4593 if( dwDataSize != sizeof( GUID ) )
4595 ERR( "Invalid sp/lp guid size 0x%08x\n", dwDataSize );
4598 memcpy( lpContext, lpData, dwDataSize );
4600 /* There shouldn't be more than 1 GUID/compound address */
4601 return FALSE;
4604 /* Still waiting for what we want */
4605 return TRUE;
4609 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
4610 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
4612 UINT i;
4613 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4614 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
4615 LPCSTR guidDataSubKey = "Guid";
4616 LPCSTR majVerDataSubKey = "dwReserved1";
4617 LPCSTR minVerDataSubKey = "dwReserved2";
4618 LPCSTR pathSubKey = "Path";
4620 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
4622 /* FIXME: Cloned code with a quick hack. */
4623 for( i=0; i<2; i++ )
4625 HKEY hkResult;
4626 LPCSTR searchSubKey;
4627 char subKeyName[51];
4628 DWORD dwIndex, sizeOfSubKeyName=50;
4629 FILETIME filetime;
4631 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
4632 *lpbIsDpSp = (i == 0);
4635 /* Need to loop over the service providers in the registry */
4636 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4637 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4639 /* Hmmm. Does this mean that there are no service providers? */
4640 ERR(": no service providers?\n");
4641 return 0;
4644 /* Traverse all the service providers we have available */
4645 for( dwIndex=0;
4646 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4647 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4648 ++dwIndex, sizeOfSubKeyName=51 )
4651 HKEY hkServiceProvider;
4652 GUID serviceProviderGUID;
4653 DWORD returnType, sizeOfReturnBuffer = 255;
4654 char returnBuffer[256];
4655 WCHAR buff[51];
4656 DWORD dwTemp, len;
4658 TRACE(" this time through: %s\n", subKeyName );
4660 /* Get a handle for this particular service provider */
4661 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4662 &hkServiceProvider ) != ERROR_SUCCESS )
4664 ERR(": what the heck is going on?\n" );
4665 continue;
4668 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4669 NULL, &returnType, (LPBYTE)returnBuffer,
4670 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4672 ERR(": missing GUID registry data members\n" );
4673 continue;
4676 /* FIXME: Check return types to ensure we're interpreting data right */
4677 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4678 CLSIDFromString( buff, &serviceProviderGUID );
4679 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4681 /* Determine if this is the Service Provider that the user asked for */
4682 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
4684 continue;
4687 if( i == 0 ) /* DP SP */
4689 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
4690 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
4691 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
4694 sizeOfReturnBuffer = 255;
4696 /* Get dwReserved1 */
4697 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
4698 NULL, &returnType, (LPBYTE)returnBuffer,
4699 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4701 ERR(": missing dwReserved1 registry data members\n") ;
4702 continue;
4705 if( i == 0 )
4706 memcpy( &lpSpData->dwReserved1, returnBuffer, sizeof(lpSpData->dwReserved1) );
4708 sizeOfReturnBuffer = 255;
4710 /* Get dwReserved2 */
4711 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4712 NULL, &returnType, (LPBYTE)returnBuffer,
4713 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4715 ERR(": missing dwReserved1 registry data members\n") ;
4716 continue;
4719 if( i == 0 )
4720 memcpy( &lpSpData->dwReserved2, returnBuffer, sizeof(lpSpData->dwReserved2) );
4722 sizeOfReturnBuffer = 255;
4724 /* Get the path for this service provider */
4725 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
4726 NULL, NULL, (LPBYTE)returnBuffer,
4727 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
4729 ERR(": missing PATH registry data members: 0x%08x\n", dwTemp );
4730 continue;
4733 TRACE( "Loading %s\n", returnBuffer );
4734 return LoadLibraryA( returnBuffer );
4738 return 0;
4741 static HRESULT DP_InitializeDPSP( IDirectPlayImpl *This, HMODULE hServiceProvider )
4743 HRESULT hr;
4744 LPDPSP_SPINIT SPInit;
4746 /* Initialize the service provider by calling SPInit */
4747 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4749 if( SPInit == NULL )
4751 ERR( "Service provider doesn't provide SPInit interface?\n" );
4752 FreeLibrary( hServiceProvider );
4753 return DPERR_UNAVAILABLE;
4756 TRACE( "Calling SPInit (DP SP entry point)\n" );
4758 hr = (*SPInit)( &This->dp2->spData );
4760 if( FAILED(hr) )
4762 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4763 FreeLibrary( hServiceProvider );
4764 return hr;
4767 /* FIXME: Need to verify the sanity of the returned callback table
4768 * using IsBadCodePtr */
4769 This->dp2->bSPInitialized = TRUE;
4771 /* This interface is now initialized as a DP object */
4772 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
4774 /* Store the handle of the module so that we can unload it later */
4775 This->dp2->hServiceProvider = hServiceProvider;
4777 return hr;
4780 static HRESULT DP_InitializeDPLSP( IDirectPlayImpl *This, HMODULE hLobbyProvider )
4782 HRESULT hr;
4783 LPSP_INIT DPLSPInit;
4785 /* Initialize the service provider by calling SPInit */
4786 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
4788 if( DPLSPInit == NULL )
4790 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4791 FreeLibrary( hLobbyProvider );
4792 return DPERR_UNAVAILABLE;
4795 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4797 hr = (*DPLSPInit)( &This->dp2->dplspData );
4799 if( FAILED(hr) )
4801 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4802 FreeLibrary( hLobbyProvider );
4803 return hr;
4806 /* FIXME: Need to verify the sanity of the returned callback table
4807 * using IsBadCodePtr */
4809 This->dp2->bDPLSPInitialized = TRUE;
4811 /* This interface is now initialized as a lobby object */
4812 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
4814 /* Store the handle of the module so that we can unload it later */
4815 This->dp2->hDPLobbyProvider = hLobbyProvider;
4817 return hr;
4820 static HRESULT WINAPI IDirectPlay3AImpl_InitializeConnection( IDirectPlay3A *iface,
4821 void *connection, DWORD flags )
4823 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4824 return IDirectPlayX_InitializeConnection( &This->IDirectPlay4A_iface, connection, flags );
4827 static HRESULT WINAPI IDirectPlay3Impl_InitializeConnection( IDirectPlay3 *iface,
4828 void *connection, DWORD flags )
4830 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4831 return IDirectPlayX_InitializeConnection( &This->IDirectPlay4_iface, connection, flags );
4834 static HRESULT WINAPI IDirectPlay4AImpl_InitializeConnection( IDirectPlay4A *iface,
4835 void *connection, DWORD flags )
4837 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4838 return IDirectPlayX_InitializeConnection( &This->IDirectPlay4_iface, connection, flags );
4841 static HRESULT WINAPI IDirectPlay4Impl_InitializeConnection( IDirectPlay4 *iface,
4842 void *connection, DWORD flags )
4844 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4845 HMODULE servprov;
4846 GUID sp;
4847 const DWORD size = 80; /* FIXME: Need to calculate it correctly */
4848 BOOL is_dp_sp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4849 HRESULT hr;
4851 TRACE( "(%p)->(%p,0x%08x)\n", This, connection, flags );
4853 if ( !connection )
4854 return DPERR_INVALIDPARAMS;
4856 if ( flags )
4857 return DPERR_INVALIDFLAGS;
4859 if ( This->dp2->connectionInitialized != NO_PROVIDER )
4860 return DPERR_ALREADYINITIALIZED;
4862 /* Find out what the requested SP is and how large this buffer is */
4863 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, connection, size, &sp );
4865 if ( FAILED(hr) )
4867 ERR( "Invalid compound address?\n" );
4868 return DPERR_UNAVAILABLE;
4871 /* Load the service provider */
4872 servprov = DP_LoadSP( &sp, &This->dp2->spData, &is_dp_sp );
4874 if ( !servprov )
4876 ERR( "Unable to load service provider %s\n", debugstr_guid(&sp) );
4877 return DPERR_UNAVAILABLE;
4880 if ( is_dp_sp )
4882 /* Fill in what we can of the Service Provider required information.
4883 * The rest was be done in DP_LoadSP
4885 This->dp2->spData.lpAddress = connection;
4886 This->dp2->spData.dwAddressSize = size;
4887 This->dp2->spData.lpGuid = &sp;
4888 hr = DP_InitializeDPSP( This, servprov );
4890 else
4892 This->dp2->dplspData.lpAddress = connection;
4893 hr = DP_InitializeDPLSP( This, servprov );
4896 if ( FAILED(hr) )
4897 return hr;
4899 return DP_OK;
4902 static HRESULT WINAPI IDirectPlay3AImpl_SecureOpen( IDirectPlay3A *iface,
4903 const DPSESSIONDESC2 *sdesc, DWORD flags, const DPSECURITYDESC *security,
4904 const DPCREDENTIALS *credentials )
4906 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4907 return IDirectPlayX_SecureOpen( &This->IDirectPlay4A_iface, sdesc, flags, security,
4908 credentials );
4911 static HRESULT WINAPI IDirectPlay3Impl_SecureOpen( IDirectPlay3 *iface,
4912 const DPSESSIONDESC2 *sdesc, DWORD flags, const DPSECURITYDESC *security,
4913 const DPCREDENTIALS *credentials )
4915 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4916 return IDirectPlayX_SecureOpen( &This->IDirectPlay4_iface, sdesc, flags, security,
4917 credentials );
4920 static HRESULT WINAPI IDirectPlay4AImpl_SecureOpen( IDirectPlay4A *iface,
4921 const DPSESSIONDESC2 *lpsd, DWORD dwFlags, const DPSECURITYDESC *lpSecurity,
4922 const DPCREDENTIALS *lpCredentials )
4924 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4925 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4928 static HRESULT WINAPI IDirectPlay4Impl_SecureOpen( IDirectPlay4 *iface,
4929 const DPSESSIONDESC2 *lpsd, DWORD dwFlags, const DPSECURITYDESC *lpSecurity,
4930 const DPCREDENTIALS *lpCredentials )
4932 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4933 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4936 static HRESULT WINAPI IDirectPlay3AImpl_SendChatMessage( IDirectPlay3A *iface, DPID from, DPID to,
4937 DWORD flags, DPCHAT *chatmsg )
4939 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4940 return IDirectPlayX_SendChatMessage( &This->IDirectPlay4A_iface, from, to, flags, chatmsg );
4943 static HRESULT WINAPI IDirectPlay3Impl_SendChatMessage( IDirectPlay3 *iface, DPID from, DPID to,
4944 DWORD flags, DPCHAT *chatmsg )
4946 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4947 return IDirectPlayX_SendChatMessage( &This->IDirectPlay4_iface, from, to, flags, chatmsg );
4950 static HRESULT WINAPI IDirectPlay4AImpl_SendChatMessage( IDirectPlay4A *iface, DPID from,
4951 DPID to, DWORD flags, DPCHAT *chatmsg )
4953 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4954 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, from, to, flags, chatmsg );
4955 return DP_OK;
4958 static HRESULT WINAPI IDirectPlay4Impl_SendChatMessage( IDirectPlay4 *iface, DPID from, DPID to,
4959 DWORD flags, DPCHAT *chatmsg )
4961 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4962 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, from, to, flags, chatmsg );
4963 return DP_OK;
4966 static HRESULT WINAPI IDirectPlay3AImpl_SetGroupConnectionSettings( IDirectPlay3A *iface,
4967 DWORD flags, DPID group, DPLCONNECTION *connection )
4969 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4970 return IDirectPlayX_SetGroupConnectionSettings( &This->IDirectPlay4A_iface, flags, group,
4971 connection );
4974 static HRESULT WINAPI IDirectPlay3Impl_SetGroupConnectionSettings( IDirectPlay3 *iface,
4975 DWORD flags, DPID group, DPLCONNECTION *connection )
4977 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4978 return IDirectPlayX_SetGroupConnectionSettings( &This->IDirectPlay4_iface, flags, group,
4979 connection );
4982 static HRESULT WINAPI IDirectPlay4AImpl_SetGroupConnectionSettings( IDirectPlay4A *iface,
4983 DWORD flags, DPID group, DPLCONNECTION *connection )
4985 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4986 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, flags, group, connection );
4987 return DP_OK;
4990 static HRESULT WINAPI IDirectPlay4Impl_SetGroupConnectionSettings( IDirectPlay4 *iface, DWORD flags,
4991 DPID group, DPLCONNECTION *connection )
4993 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4994 FIXME( "(%p)->(0x%08x,0x%08x,%p): stub\n", This, flags, group, connection );
4995 return DP_OK;
4998 static HRESULT WINAPI IDirectPlay3AImpl_StartSession( IDirectPlay3A *iface, DWORD flags,
4999 DPID group )
5001 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
5002 return IDirectPlayX_StartSession( &This->IDirectPlay4A_iface, flags, group );
5005 static HRESULT WINAPI IDirectPlay3Impl_StartSession( IDirectPlay3 *iface, DWORD flags,
5006 DPID group )
5008 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
5009 return IDirectPlayX_StartSession( &This->IDirectPlay4_iface, flags, group );
5012 static HRESULT WINAPI IDirectPlay4AImpl_StartSession( IDirectPlay4A *iface, DWORD flags,
5013 DPID group )
5015 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5016 return IDirectPlayX_StartSession( &This->IDirectPlay4_iface, flags, group );
5019 static HRESULT WINAPI IDirectPlay4Impl_StartSession( IDirectPlay4 *iface, DWORD flags, DPID group )
5021 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5022 FIXME( "(%p)->(0x%08x,0x%08x): stub\n", This, flags, group );
5023 return DP_OK;
5026 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupFlags( IDirectPlay3A *iface, DPID group,
5027 DWORD *flags )
5029 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
5030 return IDirectPlayX_GetGroupFlags( &This->IDirectPlay4A_iface, group, flags );
5033 static HRESULT WINAPI IDirectPlay3Impl_GetGroupFlags( IDirectPlay3 *iface, DPID group,
5034 DWORD *flags )
5036 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
5037 return IDirectPlayX_GetGroupFlags( &This->IDirectPlay4_iface, group, flags );
5040 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupFlags( IDirectPlay4A *iface, DPID group,
5041 DWORD *flags )
5043 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5044 return IDirectPlayX_GetGroupFlags( &This->IDirectPlay4_iface, group, flags );
5047 static HRESULT WINAPI IDirectPlay4Impl_GetGroupFlags( IDirectPlay4 *iface, DPID group,
5048 DWORD *flags )
5050 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5051 FIXME( "(%p)->(0x%08x,%p): stub\n", This, group, flags );
5052 return DP_OK;
5055 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupParent( IDirectPlay3A *iface, DPID group,
5056 DPID *parent )
5058 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
5059 return IDirectPlayX_GetGroupParent( &This->IDirectPlay4A_iface, group, parent );
5062 static HRESULT WINAPI IDirectPlay3Impl_GetGroupParent( IDirectPlay3 *iface, DPID group,
5063 DPID *parent )
5065 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
5066 return IDirectPlayX_GetGroupParent( &This->IDirectPlay4_iface, group, parent );
5069 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupParent( IDirectPlay4A *iface, DPID group,
5070 DPID *parent )
5072 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5073 return IDirectPlayX_GetGroupParent( &This->IDirectPlay4_iface, group, parent );
5076 static HRESULT WINAPI IDirectPlay4Impl_GetGroupParent( IDirectPlay4 *iface, DPID group,
5077 DPID *parent )
5079 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5080 lpGroupData gdata;
5082 TRACE( "(%p)->(0x%08x,%p)\n", This, group, parent );
5084 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
5085 return DPERR_INVALIDGROUP;
5087 *parent = gdata->dpid;
5089 return DP_OK;
5092 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerAccount( IDirectPlay3A *iface, DPID player,
5093 DWORD flags, void *data, DWORD *size )
5095 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
5096 return IDirectPlayX_GetPlayerAccount( &This->IDirectPlay4A_iface, player, flags, data, size );
5099 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerAccount( IDirectPlay3 *iface, DPID player,
5100 DWORD flags, void *data, DWORD *size )
5102 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
5103 return IDirectPlayX_GetPlayerAccount( &This->IDirectPlay4_iface, player, flags, data, size );
5106 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerAccount( IDirectPlay4A *iface, DPID player,
5107 DWORD flags, void *data, DWORD *size )
5109 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5110 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, player, flags, data, size );
5111 return DP_OK;
5114 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerAccount( IDirectPlay4 *iface, DPID player,
5115 DWORD flags, void *data, DWORD *size )
5117 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5118 FIXME( "(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, player, flags, data, size );
5119 return DP_OK;
5122 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerFlags( IDirectPlay3A *iface, DPID player,
5123 DWORD *flags )
5125 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
5126 return IDirectPlayX_GetPlayerFlags( &This->IDirectPlay4A_iface, player, flags );
5129 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerFlags( IDirectPlay3 *iface, DPID player,
5130 DWORD *flags )
5132 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
5133 return IDirectPlayX_GetPlayerFlags( &This->IDirectPlay4_iface, player, flags );
5136 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerFlags( IDirectPlay4A *iface, DPID player,
5137 DWORD *flags )
5139 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5140 return IDirectPlayX_GetPlayerFlags( &This->IDirectPlay4_iface, player, flags );
5143 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerFlags( IDirectPlay4 *iface, DPID player,
5144 DWORD *flags )
5146 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5147 FIXME( "(%p)->(0x%08x,%p): stub\n", This, player, flags );
5148 return DP_OK;
5151 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupOwner( IDirectPlay4A *iface, DPID group,
5152 DPID *owner )
5154 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5155 return IDirectPlayX_GetGroupOwner( &This->IDirectPlay4_iface, group, owner );
5158 static HRESULT WINAPI IDirectPlay4Impl_GetGroupOwner( IDirectPlay4 *iface, DPID group,
5159 DPID *owner )
5161 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5162 FIXME( "(%p)->(0x%08x,%p): stub\n", This, group, owner );
5163 return DP_OK;
5166 static HRESULT WINAPI IDirectPlay4AImpl_SetGroupOwner( IDirectPlay4A *iface, DPID group,
5167 DPID owner )
5169 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5170 return IDirectPlayX_SetGroupOwner( &This->IDirectPlay4_iface, group, owner );
5173 static HRESULT WINAPI IDirectPlay4Impl_SetGroupOwner( IDirectPlay4 *iface, DPID group ,
5174 DPID owner )
5176 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5177 FIXME( "(%p)->(0x%08x,0x%08x): stub\n", This, group, owner );
5178 return DP_OK;
5181 static HRESULT WINAPI IDirectPlay4AImpl_SendEx( IDirectPlay4A *iface, DPID from, DPID to,
5182 DWORD flags, void *data, DWORD size, DWORD priority, DWORD timeout, void *context,
5183 DWORD *msgid )
5185 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5186 return IDirectPlayX_SendEx( &This->IDirectPlay4_iface, from, to, flags, data, size, priority,
5187 timeout, context, msgid );
5190 static HRESULT WINAPI IDirectPlay4Impl_SendEx( IDirectPlay4 *iface, DPID from, DPID to,
5191 DWORD flags, void *data, DWORD size, DWORD priority, DWORD timeout, void *context,
5192 DWORD *msgid )
5194 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5196 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,0x%08x,0x%08x,0x%08x,%p,%p): semi-stub\n",
5197 This, from, to, flags, data, size, priority, timeout, context, msgid );
5199 if ( This->dp2->connectionInitialized == NO_PROVIDER )
5200 return DPERR_UNINITIALIZED;
5202 /* FIXME: Add parameter checking */
5203 /* FIXME: First call to this needs to acquire a message id which will be
5204 * used for multiple sends
5207 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
5209 /* Verify that the message is being sent from a valid local player. The
5210 * from player may be anonymous DPID_UNKNOWN
5212 if ( from != DPID_UNKNOWN && !DP_FindPlayer( This, from ) )
5214 WARN( "INFO: Invalid from player 0x%08x\n", from );
5215 return DPERR_INVALIDPLAYER;
5218 /* Verify that the message is being sent to a valid player, group or to
5219 * everyone. If it's valid, send it to those players.
5221 if ( to == DPID_ALLPLAYERS )
5223 /* See if SP has the ability to multicast. If so, use it */
5224 if ( This->dp2->spData.lpCB->SendToGroupEx )
5225 FIXME( "Use group sendex to group 0\n" );
5226 else if ( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
5227 FIXME( "Use obsolete group send to group 0\n" );
5228 else /* No multicast, multiplicate */
5229 FIXME( "Send to all players using EnumPlayersInGroup\n" );
5231 else if ( DP_FindPlayer( This, to ) )
5233 /* Have the service provider send this message */
5234 /* FIXME: Could optimize for local interface sends */
5235 return DP_SP_SendEx( This, flags, data, size, priority, timeout, context, msgid );
5237 else if ( DP_FindAnyGroup( This, to ) )
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\n" );
5242 else if ( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
5243 FIXME( "Use obsolete group send to group\n" );
5244 else /* No multicast, multiplicate */
5245 FIXME( "Send to all players using EnumPlayersInGroup\n" );
5248 else
5249 return DPERR_INVALIDPLAYER;
5251 /* FIXME: Should return what the send returned */
5252 return DP_OK;
5255 static HRESULT DP_SP_SendEx( IDirectPlayImpl *This, DWORD dwFlags, void *lpData, DWORD dwDataSize,
5256 DWORD dwPriority, DWORD dwTimeout, void *lpContext, DWORD *lpdwMsgID )
5258 LPDPMSG lpMElem;
5260 FIXME( ": stub\n" );
5262 /* FIXME: This queuing should only be for async messages */
5264 lpMElem = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpMElem ) );
5265 lpMElem->msg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
5267 CopyMemory( lpMElem->msg, lpData, dwDataSize );
5269 /* FIXME: Need to queue based on priority */
5270 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
5272 return DP_OK;
5275 static HRESULT WINAPI IDirectPlay4AImpl_GetMessageQueue( IDirectPlay4A *iface, DPID from, DPID to,
5276 DWORD flags, DWORD *msgs, DWORD *bytes )
5278 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5279 return IDirectPlayX_GetMessageQueue( &This->IDirectPlay4_iface, from, to, flags, msgs, bytes );
5282 static HRESULT WINAPI IDirectPlay4Impl_GetMessageQueue( IDirectPlay4 *iface, DPID from, DPID to,
5283 DWORD flags, DWORD *msgs, DWORD *bytes )
5285 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5286 HRESULT hr = DP_OK;
5288 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%p): semi-stub\n", This, from, to, flags, msgs, bytes );
5290 /* FIXME: Do we need to do from and to sanity checking here? */
5291 /* FIXME: What about sends which are not immediate? */
5293 if ( This->dp2->spData.lpCB->GetMessageQueue )
5295 DPSP_GETMESSAGEQUEUEDATA data;
5297 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
5299 /* FIXME: None of this is documented :( */
5300 data.lpISP = This->dp2->spData.lpISP;
5301 data.dwFlags = flags;
5302 data.idFrom = from;
5303 data.idTo = to;
5304 data.lpdwNumMsgs = msgs;
5305 data.lpdwNumBytes = bytes;
5307 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
5309 else
5310 FIXME( "No SP for GetMessageQueue - fake some data\n" );
5312 return hr;
5315 static HRESULT dplay_cancelmsg ( IDirectPlayImpl* This, DWORD msgid, DWORD flags, DWORD minprio,
5316 DWORD maxprio )
5318 HRESULT hr = DP_OK;
5320 FIXME( "(%p)->(0x%08x,0x%08x): semi stub\n", This, msgid, flags );
5322 if ( This->dp2->spData.lpCB->Cancel )
5324 DPSP_CANCELDATA data;
5326 TRACE( "Calling SP Cancel\n" );
5328 /* FIXME: Undocumented callback */
5330 data.lpISP = This->dp2->spData.lpISP;
5331 data.dwFlags = flags;
5332 data.lprglpvSPMsgID = NULL;
5333 data.cSPMsgID = msgid;
5334 data.dwMinPriority = minprio;
5335 data.dwMaxPriority = maxprio;
5337 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
5339 else
5340 FIXME( "SP doesn't implement Cancel\n" );
5342 return hr;
5345 static HRESULT WINAPI IDirectPlay4AImpl_CancelMessage( IDirectPlay4A *iface, DWORD msgid,
5346 DWORD flags )
5348 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5349 return IDirectPlayX_CancelMessage( &This->IDirectPlay4_iface, msgid, flags );
5352 static HRESULT WINAPI IDirectPlay4Impl_CancelMessage( IDirectPlay4 *iface, DWORD msgid,
5353 DWORD flags )
5355 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5357 if ( flags != 0 )
5358 return DPERR_INVALIDFLAGS;
5360 if ( msgid == 0 )
5361 flags |= DPCANCELSEND_ALL;
5363 return dplay_cancelmsg( This, msgid, flags, 0, 0 );
5366 static HRESULT WINAPI IDirectPlay4AImpl_CancelPriority( IDirectPlay4A *iface, DWORD minprio,
5367 DWORD maxprio, DWORD flags )
5369 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5370 return IDirectPlayX_CancelPriority( &This->IDirectPlay4_iface, minprio, maxprio, flags );
5373 static HRESULT WINAPI IDirectPlay4Impl_CancelPriority( IDirectPlay4 *iface, DWORD minprio,
5374 DWORD maxprio, DWORD flags )
5376 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5378 if ( flags != 0 )
5379 return DPERR_INVALIDFLAGS;
5381 return dplay_cancelmsg( This, 0, DPCANCELSEND_PRIORITY, minprio, maxprio );
5384 static const IDirectPlay2Vtbl dp2_vt =
5386 IDirectPlay2Impl_QueryInterface,
5387 IDirectPlay2Impl_AddRef,
5388 IDirectPlay2Impl_Release,
5389 IDirectPlay2Impl_AddPlayerToGroup,
5390 IDirectPlay2Impl_Close,
5391 IDirectPlay2Impl_CreateGroup,
5392 IDirectPlay2Impl_CreatePlayer,
5393 IDirectPlay2Impl_DeletePlayerFromGroup,
5394 IDirectPlay2Impl_DestroyGroup,
5395 IDirectPlay2Impl_DestroyPlayer,
5396 IDirectPlay2Impl_EnumGroupPlayers,
5397 IDirectPlay2Impl_EnumGroups,
5398 IDirectPlay2Impl_EnumPlayers,
5399 IDirectPlay2Impl_EnumSessions,
5400 IDirectPlay2Impl_GetCaps,
5401 IDirectPlay2Impl_GetGroupData,
5402 IDirectPlay2Impl_GetGroupName,
5403 IDirectPlay2Impl_GetMessageCount,
5404 IDirectPlay2Impl_GetPlayerAddress,
5405 IDirectPlay2Impl_GetPlayerCaps,
5406 IDirectPlay2Impl_GetPlayerData,
5407 IDirectPlay2Impl_GetPlayerName,
5408 IDirectPlay2Impl_GetSessionDesc,
5409 IDirectPlay2Impl_Initialize,
5410 IDirectPlay2Impl_Open,
5411 IDirectPlay2Impl_Receive,
5412 IDirectPlay2Impl_Send,
5413 IDirectPlay2Impl_SetGroupData,
5414 IDirectPlay2Impl_SetGroupName,
5415 IDirectPlay2Impl_SetPlayerData,
5416 IDirectPlay2Impl_SetPlayerName,
5417 IDirectPlay2Impl_SetSessionDesc
5420 static const IDirectPlay2Vtbl dp2A_vt =
5422 IDirectPlay2AImpl_QueryInterface,
5423 IDirectPlay2AImpl_AddRef,
5424 IDirectPlay2AImpl_Release,
5425 IDirectPlay2AImpl_AddPlayerToGroup,
5426 IDirectPlay2AImpl_Close,
5427 IDirectPlay2AImpl_CreateGroup,
5428 IDirectPlay2AImpl_CreatePlayer,
5429 IDirectPlay2AImpl_DeletePlayerFromGroup,
5430 IDirectPlay2AImpl_DestroyGroup,
5431 IDirectPlay2AImpl_DestroyPlayer,
5432 IDirectPlay2AImpl_EnumGroupPlayers,
5433 IDirectPlay2AImpl_EnumGroups,
5434 IDirectPlay2AImpl_EnumPlayers,
5435 IDirectPlay2AImpl_EnumSessions,
5436 IDirectPlay2AImpl_GetCaps,
5437 IDirectPlay2AImpl_GetGroupData,
5438 IDirectPlay2AImpl_GetGroupName,
5439 IDirectPlay2AImpl_GetMessageCount,
5440 IDirectPlay2AImpl_GetPlayerAddress,
5441 IDirectPlay2AImpl_GetPlayerCaps,
5442 IDirectPlay2AImpl_GetPlayerData,
5443 IDirectPlay2AImpl_GetPlayerName,
5444 IDirectPlay2AImpl_GetSessionDesc,
5445 IDirectPlay2AImpl_Initialize,
5446 IDirectPlay2AImpl_Open,
5447 IDirectPlay2AImpl_Receive,
5448 IDirectPlay2AImpl_Send,
5449 IDirectPlay2AImpl_SetGroupData,
5450 IDirectPlay2AImpl_SetGroupName,
5451 IDirectPlay2AImpl_SetPlayerData,
5452 IDirectPlay2AImpl_SetPlayerName,
5453 IDirectPlay2AImpl_SetSessionDesc
5456 static const IDirectPlay3Vtbl dp3_vt =
5458 IDirectPlay3Impl_QueryInterface,
5459 IDirectPlay3Impl_AddRef,
5460 IDirectPlay3Impl_Release,
5461 IDirectPlay3Impl_AddPlayerToGroup,
5462 IDirectPlay3Impl_Close,
5463 IDirectPlay3Impl_CreateGroup,
5464 IDirectPlay3Impl_CreatePlayer,
5465 IDirectPlay3Impl_DeletePlayerFromGroup,
5466 IDirectPlay3Impl_DestroyGroup,
5467 IDirectPlay3Impl_DestroyPlayer,
5468 IDirectPlay3Impl_EnumGroupPlayers,
5469 IDirectPlay3Impl_EnumGroups,
5470 IDirectPlay3Impl_EnumPlayers,
5471 IDirectPlay3Impl_EnumSessions,
5472 IDirectPlay3Impl_GetCaps,
5473 IDirectPlay3Impl_GetGroupData,
5474 IDirectPlay3Impl_GetGroupName,
5475 IDirectPlay3Impl_GetMessageCount,
5476 IDirectPlay3Impl_GetPlayerAddress,
5477 IDirectPlay3Impl_GetPlayerCaps,
5478 IDirectPlay3Impl_GetPlayerData,
5479 IDirectPlay3Impl_GetPlayerName,
5480 IDirectPlay3Impl_GetSessionDesc,
5481 IDirectPlay3Impl_Initialize,
5482 IDirectPlay3Impl_Open,
5483 IDirectPlay3Impl_Receive,
5484 IDirectPlay3Impl_Send,
5485 IDirectPlay3Impl_SetGroupData,
5486 IDirectPlay3Impl_SetGroupName,
5487 IDirectPlay3Impl_SetPlayerData,
5488 IDirectPlay3Impl_SetPlayerName,
5489 IDirectPlay3Impl_SetSessionDesc,
5490 IDirectPlay3Impl_AddGroupToGroup,
5491 IDirectPlay3Impl_CreateGroupInGroup,
5492 IDirectPlay3Impl_DeleteGroupFromGroup,
5493 IDirectPlay3Impl_EnumConnections,
5494 IDirectPlay3Impl_EnumGroupsInGroup,
5495 IDirectPlay3Impl_GetGroupConnectionSettings,
5496 IDirectPlay3Impl_InitializeConnection,
5497 IDirectPlay3Impl_SecureOpen,
5498 IDirectPlay3Impl_SendChatMessage,
5499 IDirectPlay3Impl_SetGroupConnectionSettings,
5500 IDirectPlay3Impl_StartSession,
5501 IDirectPlay3Impl_GetGroupFlags,
5502 IDirectPlay3Impl_GetGroupParent,
5503 IDirectPlay3Impl_GetPlayerAccount,
5504 IDirectPlay3Impl_GetPlayerFlags
5507 static const IDirectPlay3Vtbl dp3A_vt =
5509 IDirectPlay3AImpl_QueryInterface,
5510 IDirectPlay3AImpl_AddRef,
5511 IDirectPlay3AImpl_Release,
5512 IDirectPlay3AImpl_AddPlayerToGroup,
5513 IDirectPlay3AImpl_Close,
5514 IDirectPlay3AImpl_CreateGroup,
5515 IDirectPlay3AImpl_CreatePlayer,
5516 IDirectPlay3AImpl_DeletePlayerFromGroup,
5517 IDirectPlay3AImpl_DestroyGroup,
5518 IDirectPlay3AImpl_DestroyPlayer,
5519 IDirectPlay3AImpl_EnumGroupPlayers,
5520 IDirectPlay3AImpl_EnumGroups,
5521 IDirectPlay3AImpl_EnumPlayers,
5522 IDirectPlay3AImpl_EnumSessions,
5523 IDirectPlay3AImpl_GetCaps,
5524 IDirectPlay3AImpl_GetGroupData,
5525 IDirectPlay3AImpl_GetGroupName,
5526 IDirectPlay3AImpl_GetMessageCount,
5527 IDirectPlay3AImpl_GetPlayerAddress,
5528 IDirectPlay3AImpl_GetPlayerCaps,
5529 IDirectPlay3AImpl_GetPlayerData,
5530 IDirectPlay3AImpl_GetPlayerName,
5531 IDirectPlay3AImpl_GetSessionDesc,
5532 IDirectPlay3AImpl_Initialize,
5533 IDirectPlay3AImpl_Open,
5534 IDirectPlay3AImpl_Receive,
5535 IDirectPlay3AImpl_Send,
5536 IDirectPlay3AImpl_SetGroupData,
5537 IDirectPlay3AImpl_SetGroupName,
5538 IDirectPlay3AImpl_SetPlayerData,
5539 IDirectPlay3AImpl_SetPlayerName,
5540 IDirectPlay3AImpl_SetSessionDesc,
5541 IDirectPlay3AImpl_AddGroupToGroup,
5542 IDirectPlay3AImpl_CreateGroupInGroup,
5543 IDirectPlay3AImpl_DeleteGroupFromGroup,
5544 IDirectPlay3AImpl_EnumConnections,
5545 IDirectPlay3AImpl_EnumGroupsInGroup,
5546 IDirectPlay3AImpl_GetGroupConnectionSettings,
5547 IDirectPlay3AImpl_InitializeConnection,
5548 IDirectPlay3AImpl_SecureOpen,
5549 IDirectPlay3AImpl_SendChatMessage,
5550 IDirectPlay3AImpl_SetGroupConnectionSettings,
5551 IDirectPlay3AImpl_StartSession,
5552 IDirectPlay3AImpl_GetGroupFlags,
5553 IDirectPlay3AImpl_GetGroupParent,
5554 IDirectPlay3AImpl_GetPlayerAccount,
5555 IDirectPlay3AImpl_GetPlayerFlags
5558 static const IDirectPlay4Vtbl dp4_vt =
5560 IDirectPlay4Impl_QueryInterface,
5561 IDirectPlay4Impl_AddRef,
5562 IDirectPlay4Impl_Release,
5563 IDirectPlay4Impl_AddPlayerToGroup,
5564 IDirectPlay4Impl_Close,
5565 IDirectPlay4Impl_CreateGroup,
5566 IDirectPlay4Impl_CreatePlayer,
5567 IDirectPlay4Impl_DeletePlayerFromGroup,
5568 IDirectPlay4Impl_DestroyGroup,
5569 IDirectPlay4Impl_DestroyPlayer,
5570 IDirectPlay4Impl_EnumGroupPlayers,
5571 IDirectPlay4Impl_EnumGroups,
5572 IDirectPlay4Impl_EnumPlayers,
5573 IDirectPlay4Impl_EnumSessions,
5574 IDirectPlay4Impl_GetCaps,
5575 IDirectPlay4Impl_GetGroupData,
5576 IDirectPlay4Impl_GetGroupName,
5577 IDirectPlay4Impl_GetMessageCount,
5578 IDirectPlay4Impl_GetPlayerAddress,
5579 IDirectPlay4Impl_GetPlayerCaps,
5580 IDirectPlay4Impl_GetPlayerData,
5581 IDirectPlay4Impl_GetPlayerName,
5582 IDirectPlay4Impl_GetSessionDesc,
5583 IDirectPlay4Impl_Initialize,
5584 IDirectPlay4Impl_Open,
5585 IDirectPlay4Impl_Receive,
5586 IDirectPlay4Impl_Send,
5587 IDirectPlay4Impl_SetGroupData,
5588 IDirectPlay4Impl_SetGroupName,
5589 IDirectPlay4Impl_SetPlayerData,
5590 IDirectPlay4Impl_SetPlayerName,
5591 IDirectPlay4Impl_SetSessionDesc,
5592 IDirectPlay4Impl_AddGroupToGroup,
5593 IDirectPlay4Impl_CreateGroupInGroup,
5594 IDirectPlay4Impl_DeleteGroupFromGroup,
5595 IDirectPlay4Impl_EnumConnections,
5596 IDirectPlay4Impl_EnumGroupsInGroup,
5597 IDirectPlay4Impl_GetGroupConnectionSettings,
5598 IDirectPlay4Impl_InitializeConnection,
5599 IDirectPlay4Impl_SecureOpen,
5600 IDirectPlay4Impl_SendChatMessage,
5601 IDirectPlay4Impl_SetGroupConnectionSettings,
5602 IDirectPlay4Impl_StartSession,
5603 IDirectPlay4Impl_GetGroupFlags,
5604 IDirectPlay4Impl_GetGroupParent,
5605 IDirectPlay4Impl_GetPlayerAccount,
5606 IDirectPlay4Impl_GetPlayerFlags,
5607 IDirectPlay4Impl_GetGroupOwner,
5608 IDirectPlay4Impl_SetGroupOwner,
5609 IDirectPlay4Impl_SendEx,
5610 IDirectPlay4Impl_GetMessageQueue,
5611 IDirectPlay4Impl_CancelMessage,
5612 IDirectPlay4Impl_CancelPriority
5615 static const IDirectPlay4Vtbl dp4A_vt =
5617 IDirectPlay4AImpl_QueryInterface,
5618 IDirectPlay4AImpl_AddRef,
5619 IDirectPlay4AImpl_Release,
5620 IDirectPlay4AImpl_AddPlayerToGroup,
5621 IDirectPlay4AImpl_Close,
5622 IDirectPlay4AImpl_CreateGroup,
5623 IDirectPlay4AImpl_CreatePlayer,
5624 IDirectPlay4AImpl_DeletePlayerFromGroup,
5625 IDirectPlay4AImpl_DestroyGroup,
5626 IDirectPlay4AImpl_DestroyPlayer,
5627 IDirectPlay4AImpl_EnumGroupPlayers,
5628 IDirectPlay4AImpl_EnumGroups,
5629 IDirectPlay4AImpl_EnumPlayers,
5630 IDirectPlay4AImpl_EnumSessions,
5631 IDirectPlay4AImpl_GetCaps,
5632 IDirectPlay4AImpl_GetGroupData,
5633 IDirectPlay4AImpl_GetGroupName,
5634 IDirectPlay4AImpl_GetMessageCount,
5635 IDirectPlay4AImpl_GetPlayerAddress,
5636 IDirectPlay4AImpl_GetPlayerCaps,
5637 IDirectPlay4AImpl_GetPlayerData,
5638 IDirectPlay4AImpl_GetPlayerName,
5639 IDirectPlay4AImpl_GetSessionDesc,
5640 IDirectPlay4AImpl_Initialize,
5641 IDirectPlay4AImpl_Open,
5642 IDirectPlay4AImpl_Receive,
5643 IDirectPlay4AImpl_Send,
5644 IDirectPlay4AImpl_SetGroupData,
5645 IDirectPlay4AImpl_SetGroupName,
5646 IDirectPlay4AImpl_SetPlayerData,
5647 IDirectPlay4AImpl_SetPlayerName,
5648 IDirectPlay4AImpl_SetSessionDesc,
5649 IDirectPlay4AImpl_AddGroupToGroup,
5650 IDirectPlay4AImpl_CreateGroupInGroup,
5651 IDirectPlay4AImpl_DeleteGroupFromGroup,
5652 IDirectPlay4AImpl_EnumConnections,
5653 IDirectPlay4AImpl_EnumGroupsInGroup,
5654 IDirectPlay4AImpl_GetGroupConnectionSettings,
5655 IDirectPlay4AImpl_InitializeConnection,
5656 IDirectPlay4AImpl_SecureOpen,
5657 IDirectPlay4AImpl_SendChatMessage,
5658 IDirectPlay4AImpl_SetGroupConnectionSettings,
5659 IDirectPlay4AImpl_StartSession,
5660 IDirectPlay4AImpl_GetGroupFlags,
5661 IDirectPlay4AImpl_GetGroupParent,
5662 IDirectPlay4AImpl_GetPlayerAccount,
5663 IDirectPlay4AImpl_GetPlayerFlags,
5664 IDirectPlay4AImpl_GetGroupOwner,
5665 IDirectPlay4AImpl_SetGroupOwner,
5666 IDirectPlay4AImpl_SendEx,
5667 IDirectPlay4AImpl_GetMessageQueue,
5668 IDirectPlay4AImpl_CancelMessage,
5669 IDirectPlay4AImpl_CancelPriority
5672 HRESULT dplay_create( REFIID riid, void **ppv )
5674 IDirectPlayImpl *obj;
5675 HRESULT hr;
5677 TRACE( "(%s, %p)\n", debugstr_guid( riid ), ppv );
5679 *ppv = NULL;
5680 obj = HeapAlloc( GetProcessHeap(), 0, sizeof( *obj ) );
5681 if ( !obj )
5682 return DPERR_OUTOFMEMORY;
5684 obj->IDirectPlay_iface.lpVtbl = &dp_vt;
5685 obj->IDirectPlay2A_iface.lpVtbl = &dp2A_vt;
5686 obj->IDirectPlay2_iface.lpVtbl = &dp2_vt;
5687 obj->IDirectPlay3A_iface.lpVtbl = &dp3A_vt;
5688 obj->IDirectPlay3_iface.lpVtbl = &dp3_vt;
5689 obj->IDirectPlay4A_iface.lpVtbl = &dp4A_vt;
5690 obj->IDirectPlay4_iface.lpVtbl = &dp4_vt;
5691 obj->numIfaces = 1;
5692 obj->ref = 0;
5693 obj->ref2A = 0;
5694 obj->ref2 = 0;
5695 obj->ref3A = 0;
5696 obj->ref3 = 0;
5697 obj->ref4A = 0;
5698 obj->ref4 = 1;
5700 InitializeCriticalSection( &obj->lock );
5701 obj->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectPlayImpl.lock");
5703 if ( DP_CreateDirectPlay2( obj ) )
5704 hr = IDirectPlayX_QueryInterface( &obj->IDirectPlay4_iface, riid, ppv );
5705 else
5706 hr = DPERR_NOMEMORY;
5707 IDirectPlayX_Release( &obj->IDirectPlay4_iface );
5709 return hr;
5713 HRESULT DP_GetSPPlayerData( IDirectPlayImpl *lpDP, DPID idPlayer, void **lplpData )
5715 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5717 if( lpPlayer == NULL )
5719 return DPERR_INVALIDPLAYER;
5722 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
5724 return DP_OK;
5727 HRESULT DP_SetSPPlayerData( IDirectPlayImpl *lpDP, DPID idPlayer, void *lpData )
5729 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5731 if( lpPlayer == NULL )
5733 return DPERR_INVALIDPLAYER;
5736 lpPlayer->lpPData->lpSPPlayerData = lpData;
5738 return DP_OK;
5741 /***************************************************************************
5742 * DirectPlayEnumerateAW
5744 * The pointer to the structure lpContext will be filled with the
5745 * appropriate data for each service offered by the OS. These services are
5746 * not necessarily available on this particular machine but are defined
5747 * as simple service providers under the "Service Providers" registry key.
5748 * This structure is then passed to lpEnumCallback for each of the different
5749 * services.
5751 * This API is useful only for applications written using DirectX3 or
5752 * worse. It is superseded by IDirectPlay3::EnumConnections which also
5753 * gives information on the actual connections.
5755 * defn of a service provider:
5756 * A dynamic-link library used by DirectPlay to communicate over a network.
5757 * The service provider contains all the network-specific code required
5758 * to send and receive messages. Online services and network operators can
5759 * supply service providers to use specialized hardware, protocols, communications
5760 * media, and network resources.
5763 static HRESULT DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA,
5764 LPDPENUMDPCALLBACKW lpEnumCallbackW,
5765 LPVOID lpContext)
5767 HKEY hkResult;
5768 static const WCHAR searchSubKey[] = {
5769 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
5770 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
5771 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
5772 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
5773 static const WCHAR guidKey[] = { 'G', 'u', 'i', 'd', 0 };
5774 static const WCHAR descW[] = { 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', 'W', 0 };
5776 DWORD dwIndex;
5777 FILETIME filetime;
5779 char *descriptionA = NULL;
5780 DWORD max_sizeOfDescriptionA = 0;
5781 WCHAR *descriptionW = NULL;
5782 DWORD max_sizeOfDescriptionW = 0;
5783 DWORD sizeOfSubKeyName;
5784 WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */
5785 LONG ret_value;
5786 static GUID *guid_cache;
5787 static int cache_count;
5789 if (!lpEnumCallbackA && !lpEnumCallbackW)
5791 return DPERR_INVALIDPARAMS;
5794 /* Need to loop over the service providers in the registry */
5795 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, searchSubKey,
5796 0, KEY_READ, &hkResult) != ERROR_SUCCESS)
5798 /* Hmmm. Does this mean that there are no service providers? */
5799 ERR(": no service provider key in the registry - check your Wine installation !!!\n");
5800 return DPERR_GENERIC;
5803 dwIndex = 0;
5806 sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR);
5807 ret_value = RegEnumKeyW(hkResult, dwIndex, subKeyName, sizeOfSubKeyName);
5808 dwIndex++;
5810 while (ret_value == ERROR_SUCCESS);
5811 /* The game Swing from bug 37185 expects GUID values to persist after
5812 * the end of the enumeration. */
5813 if (cache_count < dwIndex)
5815 HeapFree(GetProcessHeap(), 0, guid_cache);
5816 guid_cache = HeapAlloc(GetProcessHeap(), 0, sizeof(GUID) * dwIndex);
5817 if (!guid_cache)
5819 ERR(": failed to allocate required memory.\n");
5820 return DPERR_EXCEPTION;
5822 cache_count = dwIndex;
5824 /* Traverse all the service providers we have available */
5825 dwIndex = 0;
5826 while (1)
5828 HKEY hkServiceProvider;
5829 WCHAR guidKeyContent[(2 * 16) + 1 + 6 /* This corresponds to '{....-..-..-..-......}' */ ];
5830 DWORD sizeOfGuidKeyContent = sizeof(guidKeyContent);
5832 sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR);
5833 ret_value = RegEnumKeyExW(hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
5834 NULL, NULL, NULL, &filetime);
5835 if (ret_value == ERROR_NO_MORE_ITEMS)
5836 break;
5837 else if (ret_value != ERROR_SUCCESS)
5839 ERR(": could not enumerate on service provider key.\n");
5840 return DPERR_EXCEPTION;
5842 TRACE(" this time through sub-key %s.\n", debugstr_w(subKeyName));
5844 /* Open the key for this service provider */
5845 if (RegOpenKeyExW(hkResult, subKeyName, 0, KEY_READ, &hkServiceProvider) != ERROR_SUCCESS)
5847 ERR(": could not open registry key for service provider %s.\n", debugstr_w(subKeyName));
5848 continue;
5851 /* Get the GUID from the registry */
5852 if (RegQueryValueExW(hkServiceProvider, guidKey,
5853 NULL, NULL, (LPBYTE) guidKeyContent, &sizeOfGuidKeyContent) != ERROR_SUCCESS)
5855 ERR(": missing GUID registry data member for service provider %s.\n", debugstr_w(subKeyName));
5856 continue;
5858 if (sizeOfGuidKeyContent != sizeof(guidKeyContent))
5860 ERR(": invalid format for the GUID registry data member for service provider %s (%s).\n", debugstr_w(subKeyName), debugstr_w(guidKeyContent));
5861 continue;
5863 CLSIDFromString(guidKeyContent, &guid_cache[dwIndex]);
5865 /* The enumeration will return FALSE if we are not to continue.
5867 * Note: on my windows box, major / minor version is 6 / 0 for all service providers
5868 * and have no relation to any of the two dwReserved1 and dwReserved2 keys.
5869 * I think that it simply means that they are in-line with DirectX 6.0
5871 if (lpEnumCallbackA)
5873 DWORD sizeOfDescription = 0;
5875 /* Note that this is the A case of this function, so use the A variant to get the description string */
5876 if (RegQueryValueExA(hkServiceProvider, "DescriptionA",
5877 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5879 ERR(": missing 'DescriptionA' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5880 continue;
5882 if (sizeOfDescription > max_sizeOfDescriptionA)
5884 HeapFree(GetProcessHeap(), 0, descriptionA);
5885 max_sizeOfDescriptionA = sizeOfDescription;
5887 descriptionA = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5888 RegQueryValueExA(hkServiceProvider, "DescriptionA",
5889 NULL, NULL, (LPBYTE) descriptionA, &sizeOfDescription);
5891 if (!lpEnumCallbackA(&guid_cache[dwIndex], descriptionA, 6, 0, lpContext))
5892 goto end;
5894 else
5896 DWORD sizeOfDescription = 0;
5898 if (RegQueryValueExW(hkServiceProvider, descW,
5899 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5901 ERR(": missing 'DescriptionW' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5902 continue;
5904 if (sizeOfDescription > max_sizeOfDescriptionW)
5906 HeapFree(GetProcessHeap(), 0, descriptionW);
5907 max_sizeOfDescriptionW = sizeOfDescription;
5909 descriptionW = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5910 RegQueryValueExW(hkServiceProvider, descW,
5911 NULL, NULL, (LPBYTE) descriptionW, &sizeOfDescription);
5913 if (!lpEnumCallbackW(&guid_cache[dwIndex], descriptionW, 6, 0, lpContext))
5914 goto end;
5917 dwIndex++;
5920 end:
5921 HeapFree(GetProcessHeap(), 0, descriptionA);
5922 HeapFree(GetProcessHeap(), 0, descriptionW);
5924 return DP_OK;
5927 /***************************************************************************
5928 * DirectPlayEnumerate [DPLAYX.9]
5929 * DirectPlayEnumerateA [DPLAYX.2]
5931 HRESULT WINAPI DirectPlayEnumerateA(LPDPENUMDPCALLBACKA lpEnumCallback, LPVOID lpContext )
5933 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5935 return DirectPlayEnumerateAW(lpEnumCallback, NULL, lpContext);
5938 /***************************************************************************
5939 * DirectPlayEnumerateW [DPLAYX.3]
5941 HRESULT WINAPI DirectPlayEnumerateW(LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5943 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5945 return DirectPlayEnumerateAW(NULL, lpEnumCallback, lpContext);
5948 typedef struct tagCreateEnum
5950 LPVOID lpConn;
5951 LPCGUID lpGuid;
5952 } CreateEnumData, *lpCreateEnumData;
5954 /* Find and copy the matching connection for the SP guid */
5955 static BOOL CALLBACK cbDPCreateEnumConnections(
5956 LPCGUID lpguidSP,
5957 LPVOID lpConnection,
5958 DWORD dwConnectionSize,
5959 LPCDPNAME lpName,
5960 DWORD dwFlags,
5961 LPVOID lpContext)
5963 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5965 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5967 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5969 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5970 dwConnectionSize );
5971 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5973 /* Found the record that we were looking for */
5974 return FALSE;
5977 /* Haven't found what were looking for yet */
5978 return TRUE;
5982 /***************************************************************************
5983 * DirectPlayCreate [DPLAYX.1]
5986 HRESULT WINAPI DirectPlayCreate
5987 ( LPGUID lpGUID, LPDIRECTPLAY *lplpDP, IUnknown *pUnk )
5989 HRESULT hr;
5990 LPDIRECTPLAY3A lpDP3A;
5991 CreateEnumData cbData;
5993 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5995 if( pUnk != NULL )
5997 return CLASS_E_NOAGGREGATION;
6000 if( (lplpDP == NULL) || (lpGUID == NULL) )
6002 return DPERR_INVALIDPARAMS;
6005 if ( dplay_create( &IID_IDirectPlay, (void**)lplpDP ) != DP_OK )
6006 return DPERR_UNAVAILABLE;
6008 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
6010 /* The GUID_NULL means don't bind a service provider. Just return the
6011 interface as is */
6012 return DP_OK;
6015 /* Bind the desired service provider since lpGUID is non NULL */
6016 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
6018 /* We're going to use a DP3 interface */
6019 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
6020 (LPVOID*)&lpDP3A );
6021 if( FAILED(hr) )
6023 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
6024 return hr;
6027 cbData.lpConn = NULL;
6028 cbData.lpGuid = lpGUID;
6030 /* We were given a service provider, find info about it... */
6031 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
6032 &cbData, DPCONNECTION_DIRECTPLAY );
6033 if( ( FAILED(hr) ) ||
6034 ( cbData.lpConn == NULL )
6037 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
6038 IDirectPlayX_Release( lpDP3A );
6039 return DPERR_UNAVAILABLE;
6042 /* Initialize the service provider */
6043 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
6044 if( FAILED(hr) )
6046 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
6047 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
6048 IDirectPlayX_Release( lpDP3A );
6049 return hr;
6052 /* Release our version of the interface now that we're done with it */
6053 IDirectPlayX_Release( lpDP3A );
6054 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
6056 return DP_OK;