ntdll: Connect syscall frames across user callbacks on x86-64.
[wine.git] / dlls / dplayx / dplay.c
blob6945e34b7e8f9e1b6fbcaf4000e60dff5f8701bd
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
22 #include <stdarg.h>
23 #include <string.h>
25 #include "windef.h"
26 #include "winerror.h"
27 #include "winbase.h"
28 #include "winnt.h"
29 #include "winreg.h"
30 #include "winnls.h"
31 #include "wine/debug.h"
33 #include "dplayx_global.h"
34 #include "name_server.h"
35 #include "dplayx_queue.h"
36 #include "wine/dplaysp.h"
37 #include "dplay_global.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(dplay);
41 /* FIXME: Should this be externed? */
42 extern HRESULT DPL_CreateCompoundAddress
43 ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
44 LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
47 /* Local function prototypes */
48 static lpPlayerList DP_FindPlayer( IDirectPlayImpl *This, DPID dpid );
49 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, const DPNAME *lpSrc, BOOL bAnsi );
50 static void DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
51 LPVOID lpData, DWORD dwDataSize );
52 static void DP_DeleteDPNameStruct( LPDPNAME lpDPName );
53 static BOOL CALLBACK cbDeletePlayerFromAllGroups( DPID dpId,
54 DWORD dwPlayerType,
55 LPCDPNAME lpName,
56 DWORD dwFlags,
57 LPVOID lpContext );
58 static lpGroupData DP_FindAnyGroup( IDirectPlayImpl *This, DPID dpid );
60 /* Helper methods for player/group interfaces */
61 static HRESULT DP_SetSessionDesc( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpSessDesc,
62 DWORD dwFlags, BOOL bInitial, BOOL bAnsi );
63 static HRESULT DP_SP_SendEx( IDirectPlayImpl *This, DWORD dwFlags, void *lpData, DWORD dwDataSize,
64 DWORD dwPriority, DWORD dwTimeout, void *lpContext, DWORD *lpdwMsgID );
65 static BOOL DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
66 LPDWORD lpdwBufSize );
68 static DPID DP_GetRemoteNextObjectId(void);
70 static DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi );
71 static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc,
72 LPCDPSESSIONDESC2 srcSessDesc, BOOL bAnsi );
75 #define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */
76 #define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported
77 we don't have to change much */
78 #define DPID_NAME_SERVER 0x19a9d65b /* Don't ask me why */
80 /* Strip out dwFlag values which cannot be sent in the CREATEGROUP msg */
81 #define DPMSG_CREATEGROUP_DWFLAGS(x) ( (x) & DPGROUP_HIDDEN )
83 /* Strip out all dwFlags values for CREATEPLAYER msg */
84 #define DPMSG_CREATEPLAYER_DWFLAGS(x) 0
86 static LONG kludgePlayerGroupId = 1000;
89 static inline IDirectPlayImpl *impl_from_IDirectPlay( IDirectPlay *iface )
91 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay_iface );
94 static inline IDirectPlayImpl *impl_from_IDirectPlay2( IDirectPlay2 *iface )
96 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay2_iface );
99 static inline IDirectPlayImpl *impl_from_IDirectPlay2A( IDirectPlay2A *iface )
101 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay2A_iface );
104 static inline IDirectPlayImpl *impl_from_IDirectPlay3A( IDirectPlay3A *iface )
106 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay3A_iface );
109 static inline IDirectPlayImpl *impl_from_IDirectPlay3( IDirectPlay3 *iface )
111 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay3_iface );
114 static inline IDirectPlayImpl *impl_from_IDirectPlay4A( IDirectPlay4A *iface )
116 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay4A_iface );
119 static inline IDirectPlayImpl *impl_from_IDirectPlay4( IDirectPlay4 *iface )
121 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay4_iface );
124 static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
126 IDirectPlayImpl *This = lpDP;
128 This->dp2 = calloc( 1, sizeof( *(This->dp2) ) );
129 if ( This->dp2 == NULL )
131 return FALSE;
134 This->dp2->bConnectionOpen = FALSE;
136 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
137 This->dp2->dwEnumSessionLock = 0;
139 This->dp2->bHostInterface = FALSE;
141 DPQ_INIT(This->dp2->receiveMsgs);
142 DPQ_INIT(This->dp2->sendMsgs);
143 DPQ_INIT(This->dp2->repliesExpected);
145 if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
147 /* FIXME: Memory leak */
148 return FALSE;
151 /* Provide an initial session desc with nothing in it */
152 This->dp2->lpSessionDesc = calloc( 1, sizeof( *This->dp2->lpSessionDesc ) );
153 if( This->dp2->lpSessionDesc == NULL )
155 /* FIXME: Memory leak */
156 return FALSE;
158 This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc );
160 /* We are emulating a dp 6 implementation */
161 This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION;
163 This->dp2->spData.lpCB = calloc( 1, sizeof( *This->dp2->spData.lpCB ) );
164 This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB );
165 This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION;
167 /* This is the pointer to the service provider */
168 if ( FAILED( dplaysp_create( &IID_IDirectPlaySP, (void**)&This->dp2->spData.lpISP, This ) ) )
170 /* FIXME: Memory leak */
171 return FALSE;
174 /* Setup lobby provider information */
175 This->dp2->dplspData.dwSPVersion = DPSP_MAJORVERSION;
176 This->dp2->dplspData.lpCB = calloc( 1, sizeof( *This->dp2->dplspData.lpCB ) );
177 This->dp2->dplspData.lpCB->dwSize = sizeof( *This->dp2->dplspData.lpCB );
179 if( FAILED( dplobbysp_create( &IID_IDPLobbySP, (void**)&This->dp2->dplspData.lpISP, This ) )
182 /* FIXME: Memory leak */
183 return FALSE;
186 return TRUE;
189 /* Definition of the global function in dplayx_queue.h. #
190 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
191 DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
193 free( elem );
196 static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
198 IDirectPlayImpl *This = lpDP;
200 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
202 TerminateThread( This->dp2->hEnumSessionThread, 0 );
203 CloseHandle( This->dp2->hEnumSessionThread );
206 /* Finish with the SP - have it shutdown */
207 if( This->dp2->spData.lpCB->ShutdownEx )
209 DPSP_SHUTDOWNDATA data;
211 TRACE( "Calling SP ShutdownEx\n" );
213 data.lpISP = This->dp2->spData.lpISP;
215 (*This->dp2->spData.lpCB->ShutdownEx)( &data );
217 else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
219 TRACE( "Calling obsolete SP Shutdown\n" );
220 (*This->dp2->spData.lpCB->Shutdown)();
223 /* Unload the SP (if it exists) */
224 if( This->dp2->hServiceProvider != 0 )
226 FreeLibrary( This->dp2->hServiceProvider );
229 /* Unload the Lobby Provider (if it exists) */
230 if( This->dp2->hDPLobbyProvider != 0 )
232 FreeLibrary( This->dp2->hDPLobbyProvider );
235 /* FIXME: Need to delete receive and send msgs queue contents */
237 NS_DeleteSessionCache( This->dp2->lpNameServerData );
239 free( This->dp2->dplspData.lpCB);
240 free( This->dp2->lpSessionDesc );
242 IDirectPlaySP_Release( This->dp2->spData.lpISP );
244 /* Delete the contents */
245 free( This->dp2 );
247 return TRUE;
250 static void dplay_destroy(IDirectPlayImpl *obj)
252 DP_DestroyDirectPlay2( obj );
253 obj->lock.DebugInfo->Spare[0] = 0;
254 DeleteCriticalSection( &obj->lock );
255 free( obj );
258 static inline DPID DP_NextObjectId(void)
260 return (DPID)InterlockedIncrement( &kludgePlayerGroupId );
263 /* *lplpReply will be non NULL iff there is something to reply */
264 HRESULT DP_HandleMessage( IDirectPlayImpl *This, const void *lpcMessageBody,
265 DWORD dwMessageBodySize, const void *lpcMessageHeader, WORD wCommandId, WORD wVersion,
266 void **lplpReply, DWORD *lpdwMsgSize )
268 TRACE( "(%p)->(%p,0x%08lx,%p,%u,%u)\n",
269 This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId,
270 wVersion );
272 switch( wCommandId )
274 /* Name server needs to handle this request */
275 case DPMSGCMD_ENUMSESSIONSREQUEST:
276 /* Reply expected */
277 NS_ReplyToEnumSessionsRequest( lpcMessageBody, lplpReply, lpdwMsgSize, This );
278 break;
280 /* Name server needs to handle this request */
281 case DPMSGCMD_ENUMSESSIONSREPLY:
282 /* No reply expected */
283 NS_AddRemoteComputerAsNameServer( lpcMessageHeader,
284 This->dp2->spData.dwSPHeaderSize,
285 lpcMessageBody,
286 This->dp2->lpNameServerData );
287 break;
289 case DPMSGCMD_REQUESTNEWPLAYERID:
291 LPCDPMSG_REQUESTNEWPLAYERID lpcMsg = lpcMessageBody;
293 LPDPMSG_NEWPLAYERIDREPLY lpReply;
295 *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
297 *lplpReply = calloc( 1, *lpdwMsgSize );
299 FIXME( "Ignoring dwFlags 0x%08lx in request msg\n",
300 lpcMsg->dwFlags );
302 /* Setup the reply */
303 lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) +
304 This->dp2->spData.dwSPHeaderSize );
306 lpReply->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
307 lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY;
308 lpReply->envelope.wVersion = DPMSGVER_DP6;
310 lpReply->dpidNewPlayerId = DP_NextObjectId();
312 TRACE( "Allocating new playerid 0x%08lx from remote request\n",
313 lpReply->dpidNewPlayerId );
314 break;
317 case DPMSGCMD_GETNAMETABLEREPLY:
318 case DPMSGCMD_NEWPLAYERIDREPLY:
319 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
320 break;
322 case DPMSGCMD_JUSTENVELOPE:
323 TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08lx\n", lpcMessageHeader, ((const DWORD *)lpcMessageHeader)[1] );
324 NS_SetLocalAddr( This->dp2->lpNameServerData, lpcMessageHeader, 20 );
325 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
327 case DPMSGCMD_FORWARDADDPLAYER:
328 TRACE( "Sending message to self to get my addr\n" );
329 DP_MSG_ToSelf( This, 1 ); /* This is a hack right now */
330 break;
332 case DPMSGCMD_FORWARDADDPLAYERNACK:
333 DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
334 break;
336 default:
337 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
338 DebugBreak();
339 break;
342 /* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */
344 return DP_OK;
348 static HRESULT WINAPI IDirectPlayImpl_QueryInterface( IDirectPlay *iface, REFIID riid, void **ppv )
350 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
351 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
354 static ULONG WINAPI IDirectPlayImpl_AddRef( IDirectPlay *iface )
356 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
357 ULONG ref = InterlockedIncrement( &This->ref );
359 TRACE( "(%p) ref=%ld\n", This, ref );
361 if ( ref == 1 )
362 InterlockedIncrement( &This->numIfaces );
364 return ref;
367 static ULONG WINAPI IDirectPlayImpl_Release( IDirectPlay *iface )
369 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
370 ULONG ref = InterlockedDecrement( &This->ref );
372 TRACE( "(%p) ref=%ld\n", This, ref );
374 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
375 dplay_destroy( This );
377 return ref;
380 static HRESULT WINAPI IDirectPlayImpl_AddPlayerToGroup( IDirectPlay *iface, DPID group,
381 DPID player )
383 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
384 FIXME( "(%p)->(0x%08lx,0x%08lx): stub\n", This, group, player );
385 return E_NOTIMPL;
388 static HRESULT WINAPI IDirectPlayImpl_Close( IDirectPlay *iface )
390 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
391 FIXME( "(%p): stub\n", This );
392 return E_NOTIMPL;
395 static HRESULT WINAPI IDirectPlayImpl_CreatePlayer( IDirectPlay *iface, DPID *player,
396 LPSTR name, LPSTR fullname, HANDLE *event )
398 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
399 FIXME( "(%p)->(%p,%s,%s,%p): stub\n", This, player, debugstr_a( name ), debugstr_a( fullname ),
400 event );
401 return E_NOTIMPL;
404 static HRESULT WINAPI IDirectPlayImpl_CreateGroup( IDirectPlay *iface, DPID *group, LPSTR name,
405 LPSTR fullname )
407 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
408 FIXME( "(%p)->(%p,%s,%s): stub\n", This, group, debugstr_a( name ), debugstr_a( fullname ) );
409 return E_NOTIMPL;
412 static HRESULT WINAPI IDirectPlayImpl_DeletePlayerFromGroup( IDirectPlay *iface, DPID group,
413 DPID player )
415 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
416 FIXME( "(%p)->(0x%08lx,0x%08lx): stub\n", This, group, player );
417 return E_NOTIMPL;
420 static HRESULT WINAPI IDirectPlayImpl_DestroyPlayer( IDirectPlay *iface, DPID player )
422 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
423 FIXME( "(%p)->(0x%08lx): stub\n", This, player );
424 return E_NOTIMPL;
427 static HRESULT WINAPI IDirectPlayImpl_DestroyGroup( IDirectPlay *iface, DPID group )
429 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
430 FIXME( "(%p)->(0x%08lx): stub\n", This, group );
431 return E_NOTIMPL;
434 static HRESULT WINAPI IDirectPlayImpl_EnableNewPlayers( IDirectPlay *iface, BOOL enable )
436 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
437 FIXME( "(%p)->(%d): stub\n", This, enable );
438 return E_NOTIMPL;
441 static HRESULT WINAPI IDirectPlayImpl_EnumGroupPlayers( IDirectPlay *iface, DPID group,
442 LPDPENUMPLAYERSCALLBACK enumplayercb, void *context, DWORD flags )
444 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
445 FIXME( "(%p)->(0x%08lx,%p,%p,0x%08lx): stub\n", This, group, enumplayercb, context, flags );
446 return E_NOTIMPL;
449 static HRESULT WINAPI IDirectPlayImpl_EnumGroups( IDirectPlay *iface, DWORD session,
450 LPDPENUMPLAYERSCALLBACK enumplayercb, void *context, DWORD flags )
452 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
453 FIXME( "(%p)->(0x%08lx,%p,%p,0x%08lx): stub\n", This, session, enumplayercb, context, flags );
454 return E_NOTIMPL;
457 static HRESULT WINAPI IDirectPlayImpl_EnumPlayers( IDirectPlay *iface, DWORD session,
458 LPDPENUMPLAYERSCALLBACK enumplayercb, void *context, DWORD flags )
460 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
461 FIXME( "(%p)->(0x%08lx,%p,%p,0x%08lx): stub\n", This, session, enumplayercb, context, flags );
462 return E_NOTIMPL;
465 static HRESULT WINAPI IDirectPlayImpl_EnumSessions( IDirectPlay *iface, DPSESSIONDESC *sdesc,
466 DWORD timeout, LPDPENUMSESSIONSCALLBACK enumsessioncb, void *context, DWORD flags )
468 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
469 FIXME( "(%p)->(%p,%lu,%p,%p,0x%08lx): stub\n", This, sdesc, timeout, enumsessioncb, context,
470 flags );
471 return E_NOTIMPL;
474 static HRESULT WINAPI IDirectPlayImpl_GetCaps( IDirectPlay *iface, DPCAPS *caps )
476 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
477 FIXME( "(%p)->(%p): stub\n", This, caps );
478 return E_NOTIMPL;
481 static HRESULT WINAPI IDirectPlayImpl_GetMessageCount( IDirectPlay *iface, DPID player,
482 DWORD *count )
484 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
485 FIXME( "(%p)->(0x%08lx,%p): stub\n", This, player, count );
486 return E_NOTIMPL;
489 static HRESULT WINAPI IDirectPlayImpl_GetPlayerCaps( IDirectPlay *iface, DPID player, DPCAPS *caps )
491 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
492 FIXME( "(%p)->(0x%08lx,%p): stub\n", This, player, caps );
493 return E_NOTIMPL;
496 static HRESULT WINAPI IDirectPlayImpl_GetPlayerName( IDirectPlay *iface, DPID player, LPSTR name,
497 DWORD *size_name, LPSTR fullname, DWORD *size_fullname )
499 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
500 FIXME( "(%p)->(0x%08lx,%p,%p,%p,%p): stub\n", This, player, name, size_name, fullname,
501 size_fullname );
502 return E_NOTIMPL;
505 static HRESULT WINAPI IDirectPlayImpl_Initialize( IDirectPlay *iface, GUID *guid )
507 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
508 FIXME( "(%p)->(%p): stub\n", This, guid );
509 return E_NOTIMPL;
512 static HRESULT WINAPI IDirectPlayImpl_Open( IDirectPlay *iface, DPSESSIONDESC *sdesc )
514 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
515 FIXME( "(%p)->(%p): stub\n", This, sdesc );
516 return E_NOTIMPL;
519 static HRESULT WINAPI IDirectPlayImpl_Receive( IDirectPlay *iface, DPID *from, DPID *to,
520 DWORD flags, void *data, DWORD *size )
522 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
523 FIXME( "(%p)->(%p,%p,0x%08lx,%p,%p): stub\n", This, from, to, flags, data, size );
524 return E_NOTIMPL;
527 static HRESULT WINAPI IDirectPlayImpl_SaveSession( IDirectPlay *iface, LPSTR reserved )
529 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
530 FIXME( "(%p)->(%p): stub\n", This, reserved );
531 return E_NOTIMPL;
534 static HRESULT WINAPI IDirectPlayImpl_Send( IDirectPlay *iface, DPID from, DPID to, DWORD flags,
535 void *data, DWORD size )
537 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
538 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,%lu): stub\n", This, from, to, flags, data, size );
539 return E_NOTIMPL;
542 static HRESULT WINAPI IDirectPlayImpl_SetPlayerName( IDirectPlay *iface, DPID player, LPSTR name,
543 LPSTR fullname )
545 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
546 FIXME( "(%p)->(0x%08lx,%s,%s): stub\n", This, player, debugstr_a( name ),
547 debugstr_a ( fullname ) );
548 return E_NOTIMPL;
551 static const IDirectPlayVtbl dp_vt =
553 IDirectPlayImpl_QueryInterface,
554 IDirectPlayImpl_AddRef,
555 IDirectPlayImpl_Release,
556 IDirectPlayImpl_AddPlayerToGroup,
557 IDirectPlayImpl_Close,
558 IDirectPlayImpl_CreatePlayer,
559 IDirectPlayImpl_CreateGroup,
560 IDirectPlayImpl_DeletePlayerFromGroup,
561 IDirectPlayImpl_DestroyPlayer,
562 IDirectPlayImpl_DestroyGroup,
563 IDirectPlayImpl_EnableNewPlayers,
564 IDirectPlayImpl_EnumGroupPlayers,
565 IDirectPlayImpl_EnumGroups,
566 IDirectPlayImpl_EnumPlayers,
567 IDirectPlayImpl_EnumSessions,
568 IDirectPlayImpl_GetCaps,
569 IDirectPlayImpl_GetMessageCount,
570 IDirectPlayImpl_GetPlayerCaps,
571 IDirectPlayImpl_GetPlayerName,
572 IDirectPlayImpl_Initialize,
573 IDirectPlayImpl_Open,
574 IDirectPlayImpl_Receive,
575 IDirectPlayImpl_SaveSession,
576 IDirectPlayImpl_Send,
577 IDirectPlayImpl_SetPlayerName,
581 static HRESULT WINAPI IDirectPlay2AImpl_QueryInterface( IDirectPlay2A *iface, REFIID riid,
582 void **ppv )
584 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
585 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
588 static HRESULT WINAPI IDirectPlay2Impl_QueryInterface( IDirectPlay2 *iface, REFIID riid,
589 void **ppv )
591 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
592 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
595 static HRESULT WINAPI IDirectPlay3AImpl_QueryInterface( IDirectPlay3A *iface, REFIID riid,
596 void **ppv )
598 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
599 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
602 static HRESULT WINAPI IDirectPlay3Impl_QueryInterface( IDirectPlay3 *iface, REFIID riid,
603 void **ppv )
605 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
606 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
609 static HRESULT WINAPI IDirectPlay4AImpl_QueryInterface( IDirectPlay4A *iface, REFIID riid,
610 void **ppv )
612 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
613 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
616 static HRESULT WINAPI IDirectPlay4Impl_QueryInterface( IDirectPlay4 *iface, REFIID riid,
617 void **ppv )
619 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
621 if ( IsEqualGUID( &IID_IUnknown, riid ) )
623 TRACE( "(%p)->(IID_IUnknown %p)\n", This, ppv );
624 *ppv = &This->IDirectPlay_iface;
626 else if ( IsEqualGUID( &IID_IDirectPlay, riid ) )
628 TRACE( "(%p)->(IID_IDirectPlay %p)\n", This, ppv );
629 *ppv = &This->IDirectPlay_iface;
631 else if ( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
633 TRACE( "(%p)->(IID_IDirectPlay2A %p)\n", This, ppv );
634 *ppv = &This->IDirectPlay2A_iface;
636 else if ( IsEqualGUID( &IID_IDirectPlay2, riid ) )
638 TRACE( "(%p)->(IID_IDirectPlay2 %p)\n", This, ppv );
639 *ppv = &This->IDirectPlay2_iface;
641 else if ( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
643 TRACE( "(%p)->(IID_IDirectPlay3A %p)\n", This, ppv );
644 *ppv = &This->IDirectPlay3A_iface;
646 else if ( IsEqualGUID( &IID_IDirectPlay3, riid ) )
648 TRACE( "(%p)->(IID_IDirectPlay3 %p)\n", This, ppv );
649 *ppv = &This->IDirectPlay3_iface;
651 else if ( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
653 TRACE( "(%p)->(IID_IDirectPlay4A %p)\n", This, ppv );
654 *ppv = &This->IDirectPlay4A_iface;
656 else if ( IsEqualGUID( &IID_IDirectPlay4, riid ) )
658 TRACE( "(%p)->(IID_IDirectPlay4 %p)\n", This, ppv );
659 *ppv = &This->IDirectPlay4_iface;
661 else
663 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
664 *ppv = NULL;
665 return E_NOINTERFACE;
668 IUnknown_AddRef((IUnknown*)*ppv);
669 return S_OK;
672 static ULONG WINAPI IDirectPlay2AImpl_AddRef( IDirectPlay2A *iface )
674 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
675 ULONG ref = InterlockedIncrement( &This->ref2A );
677 TRACE( "(%p) ref2A=%ld\n", This, ref );
679 if ( ref == 1 )
680 InterlockedIncrement( &This->numIfaces );
682 return ref;
685 static ULONG WINAPI IDirectPlay2Impl_AddRef( IDirectPlay2 *iface )
687 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
688 ULONG ref = InterlockedIncrement( &This->ref2 );
690 TRACE( "(%p) ref2=%ld\n", This, ref );
692 if ( ref == 1 )
693 InterlockedIncrement( &This->numIfaces );
695 return ref;
698 static ULONG WINAPI IDirectPlay3AImpl_AddRef( IDirectPlay3A *iface )
700 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
701 ULONG ref = InterlockedIncrement( &This->ref3A );
703 TRACE( "(%p) ref3A=%ld\n", This, ref );
705 if ( ref == 1 )
706 InterlockedIncrement( &This->numIfaces );
708 return ref;
711 static ULONG WINAPI IDirectPlay3Impl_AddRef( IDirectPlay3 *iface )
713 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
714 ULONG ref = InterlockedIncrement( &This->ref3 );
716 TRACE( "(%p) ref3=%ld\n", This, ref );
718 if ( ref == 1 )
719 InterlockedIncrement( &This->numIfaces );
721 return ref;
724 static ULONG WINAPI IDirectPlay4AImpl_AddRef(IDirectPlay4A *iface)
726 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
727 ULONG ref = InterlockedIncrement( &This->ref4A );
729 TRACE( "(%p) ref4A=%ld\n", This, ref );
731 if ( ref == 1 )
732 InterlockedIncrement( &This->numIfaces );
734 return ref;
737 static ULONG WINAPI IDirectPlay4Impl_AddRef(IDirectPlay4 *iface)
739 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
740 ULONG ref = InterlockedIncrement( &This->ref4 );
742 TRACE( "(%p) ref4=%ld\n", This, ref );
744 if ( ref == 1 )
745 InterlockedIncrement( &This->numIfaces );
747 return ref;
750 static ULONG WINAPI IDirectPlay2AImpl_Release( IDirectPlay2A *iface )
752 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
753 ULONG ref = InterlockedDecrement( &This->ref2A );
755 TRACE( "(%p) ref2A=%ld\n", This, ref );
757 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
758 dplay_destroy( This );
760 return ref;
763 static ULONG WINAPI IDirectPlay2Impl_Release( IDirectPlay2 *iface )
765 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
766 ULONG ref = InterlockedDecrement( &This->ref2 );
768 TRACE( "(%p) ref2=%ld\n", This, ref );
770 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
771 dplay_destroy( This );
773 return ref;
776 static ULONG WINAPI IDirectPlay3AImpl_Release( IDirectPlay3A *iface )
778 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
779 ULONG ref = InterlockedDecrement( &This->ref3A );
781 TRACE( "(%p) ref3A=%ld\n", This, ref );
783 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
784 dplay_destroy( This );
786 return ref;
789 static ULONG WINAPI IDirectPlay3Impl_Release( IDirectPlay3 *iface )
791 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
792 ULONG ref = InterlockedDecrement( &This->ref3 );
794 TRACE( "(%p) ref3=%ld\n", This, ref );
796 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
797 dplay_destroy( This );
799 return ref;
802 static ULONG WINAPI IDirectPlay4AImpl_Release(IDirectPlay4A *iface)
804 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
805 ULONG ref = InterlockedDecrement( &This->ref4A );
807 TRACE( "(%p) ref4A=%ld\n", This, ref );
809 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
810 dplay_destroy( This );
812 return ref;
815 static ULONG WINAPI IDirectPlay4Impl_Release(IDirectPlay4 *iface)
817 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
818 ULONG ref = InterlockedDecrement( &This->ref4 );
820 TRACE( "(%p) ref4=%ld\n", This, ref );
822 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
823 dplay_destroy( This );
825 return ref;
828 static HRESULT WINAPI IDirectPlay2AImpl_AddPlayerToGroup( IDirectPlay2A *iface, DPID group,
829 DPID player )
831 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
832 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4A_iface, group, player );
835 static HRESULT WINAPI IDirectPlay2Impl_AddPlayerToGroup( IDirectPlay2 *iface, DPID group,
836 DPID player )
838 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
839 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
842 static HRESULT WINAPI IDirectPlay3AImpl_AddPlayerToGroup( IDirectPlay3A *iface, DPID group,
843 DPID player )
845 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
846 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
849 static HRESULT WINAPI IDirectPlay3Impl_AddPlayerToGroup( IDirectPlay3 *iface, DPID group,
850 DPID player )
852 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
853 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
856 static HRESULT WINAPI IDirectPlay4AImpl_AddPlayerToGroup( IDirectPlay4A *iface, DPID group,
857 DPID player )
859 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
860 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
863 static HRESULT WINAPI IDirectPlay4Impl_AddPlayerToGroup( IDirectPlay4 *iface, DPID group,
864 DPID player )
866 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
867 lpGroupData gdata;
868 lpPlayerList plist;
869 lpPlayerList newplist;
871 TRACE( "(%p)->(0x%08lx,0x%08lx)\n", This, group, player );
873 if ( This->dp2->connectionInitialized == NO_PROVIDER )
874 return DPERR_UNINITIALIZED;
876 /* Find the group */
877 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
878 return DPERR_INVALIDGROUP;
880 /* Find the player */
881 if ( ( plist = DP_FindPlayer( This, player ) ) == NULL )
882 return DPERR_INVALIDPLAYER;
884 /* Create a player list (ie "shortcut" ) */
885 newplist = calloc( 1, sizeof( *newplist ) );
886 if ( !newplist )
887 return DPERR_CANTADDPLAYER;
889 /* Add the shortcut */
890 plist->lpPData->uRef++;
891 newplist->lpPData = plist->lpPData;
893 /* Add the player to the list of players for this group */
894 DPQ_INSERT(gdata->players, newplist, players);
896 /* Let the SP know that we've added a player to the group */
897 if ( This->dp2->spData.lpCB->AddPlayerToGroup )
899 DPSP_ADDPLAYERTOGROUPDATA data;
901 TRACE( "Calling SP AddPlayerToGroup\n" );
903 data.idPlayer = player;
904 data.idGroup = group;
905 data.lpISP = This->dp2->spData.lpISP;
907 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
910 /* Inform all other peers of the addition of player to the group. If there are
911 * no peers keep this event quiet.
912 * Also, if this event was the result of another machine sending it to us,
913 * don't bother rebroadcasting it.
915 if ( This->dp2->lpSessionDesc &&
916 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
918 DPMSG_ADDPLAYERTOGROUP msg;
919 msg.dwType = DPSYS_ADDPLAYERTOGROUP;
921 msg.dpIdGroup = group;
922 msg.dpIdPlayer = player;
924 /* FIXME: Correct to just use send effectively? */
925 /* FIXME: Should size include data w/ message or just message "header" */
926 /* FIXME: Check return code */
927 IDirectPlayX_SendEx( iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
928 0, 0, NULL, NULL );
931 return DP_OK;
934 static HRESULT WINAPI IDirectPlay2AImpl_Close( IDirectPlay2A *iface )
936 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
937 return IDirectPlayX_Close( &This->IDirectPlay4A_iface );
940 static HRESULT WINAPI IDirectPlay2Impl_Close( IDirectPlay2 *iface )
942 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
943 return IDirectPlayX_Close( &This->IDirectPlay4_iface );
946 static HRESULT WINAPI IDirectPlay3AImpl_Close( IDirectPlay3A *iface )
948 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
949 return IDirectPlayX_Close( &This->IDirectPlay4_iface );
952 static HRESULT WINAPI IDirectPlay3Impl_Close( IDirectPlay3 *iface )
954 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
955 return IDirectPlayX_Close( &This->IDirectPlay4_iface );
958 static HRESULT WINAPI IDirectPlay4AImpl_Close( IDirectPlay4A *iface )
960 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
961 return IDirectPlayX_Close( &This->IDirectPlay4_iface);
964 static HRESULT WINAPI IDirectPlay4Impl_Close( IDirectPlay4 *iface )
966 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
967 HRESULT hr = DP_OK;
969 TRACE( "(%p)\n", This );
971 /* FIXME: Need to find a new host I assume (how?) */
972 /* FIXME: Need to destroy all local groups */
973 /* FIXME: Need to migrate all remotely visible players to the new host */
975 /* Invoke the SP callback to inform of session close */
976 if( This->dp2->spData.lpCB->CloseEx )
978 DPSP_CLOSEDATA data;
980 TRACE( "Calling SP CloseEx\n" );
981 data.lpISP = This->dp2->spData.lpISP;
982 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
984 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
986 TRACE( "Calling SP Close (obsolete interface)\n" );
987 hr = (*This->dp2->spData.lpCB->Close)();
990 return hr;
993 static lpGroupData DP_CreateGroup( IDirectPlayImpl *This, const DPID *lpid, const DPNAME *lpName,
994 DWORD dwFlags, DPID idParent, BOOL bAnsi )
996 lpGroupData lpGData;
998 /* Allocate the new space and add to end of high level group list */
999 lpGData = calloc( 1, sizeof( *lpGData ) );
1001 if( lpGData == NULL )
1003 return NULL;
1006 DPQ_INIT(lpGData->groups);
1007 DPQ_INIT(lpGData->players);
1009 /* Set the desired player ID - no sanity checking to see if it exists */
1010 lpGData->dpid = *lpid;
1012 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
1014 /* FIXME: Should we check that the parent exists? */
1015 lpGData->parent = idParent;
1017 /* FIXME: Should we validate the dwFlags? */
1018 lpGData->dwFlags = dwFlags;
1020 TRACE( "Created group id 0x%08lx\n", *lpid );
1022 return lpGData;
1025 /* This method assumes that all links to it are already deleted */
1026 static void DP_DeleteGroup( IDirectPlayImpl *This, DPID dpid )
1028 lpGroupList lpGList;
1030 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
1032 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
1034 if( lpGList == NULL )
1036 ERR( "DPID 0x%08lx not found\n", dpid );
1037 return;
1040 if( --(lpGList->lpGData->uRef) )
1042 FIXME( "Why is this not the last reference to group?\n" );
1043 DebugBreak();
1046 /* Delete player */
1047 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
1048 free( lpGList->lpGData );
1050 /* Remove and Delete Player List object */
1051 free( lpGList );
1055 static lpGroupData DP_FindAnyGroup( IDirectPlayImpl *This, DPID dpid )
1057 lpGroupList lpGroups;
1059 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
1061 if( dpid == DPID_SYSTEM_GROUP )
1063 return This->dp2->lpSysGroup;
1065 else
1067 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
1070 if( lpGroups == NULL )
1072 return NULL;
1075 return lpGroups->lpGData;
1078 static HRESULT DP_IF_CreateGroup( IDirectPlayImpl *This, void *lpMsgHdr, DPID *lpidGroup,
1079 DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
1081 lpGroupData lpGData;
1083 TRACE( "(%p)->(%p,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
1084 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
1085 dwFlags, bAnsi );
1087 if( This->dp2->connectionInitialized == NO_PROVIDER )
1089 return DPERR_UNINITIALIZED;
1092 /* If the name is not specified, we must provide one */
1093 if( DPID_UNKNOWN == *lpidGroup )
1095 /* If we are the name server, we decide on the group ids. If not, we
1096 * must ask for one before attempting a creation.
1098 if( This->dp2->bHostInterface )
1100 *lpidGroup = DP_NextObjectId();
1102 else
1104 *lpidGroup = DP_GetRemoteNextObjectId();
1108 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
1109 DPID_NOPARENT_GROUP, bAnsi );
1111 if( lpGData == NULL )
1113 return DPERR_CANTADDPLAYER; /* yes player not group */
1116 if( DPID_SYSTEM_GROUP == *lpidGroup )
1118 This->dp2->lpSysGroup = lpGData;
1119 TRACE( "Inserting system group\n" );
1121 else
1123 /* Insert into the system group */
1124 lpGroupList lpGroup = calloc( 1, sizeof( *lpGroup ) );
1125 lpGroup->lpGData = lpGData;
1127 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
1130 /* Something is now referencing this data */
1131 lpGData->uRef++;
1133 /* Set all the important stuff for the group */
1134 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
1136 /* FIXME: We should only create the system group if GetCaps returns
1137 * DPCAPS_GROUPOPTIMIZED.
1140 /* Let the SP know that we've created this group */
1141 if( This->dp2->spData.lpCB->CreateGroup )
1143 DPSP_CREATEGROUPDATA data;
1144 DWORD dwCreateFlags = 0;
1146 TRACE( "Calling SP CreateGroup\n" );
1148 if( *lpidGroup == DPID_NOPARENT_GROUP )
1149 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
1151 if( lpMsgHdr == NULL )
1152 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1154 if( dwFlags & DPGROUP_HIDDEN )
1155 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
1157 data.idGroup = *lpidGroup;
1158 data.dwFlags = dwCreateFlags;
1159 data.lpSPMessageHeader = lpMsgHdr;
1160 data.lpISP = This->dp2->spData.lpISP;
1162 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1165 /* Inform all other peers of the creation of a new group. If there are
1166 * no peers keep this event quiet.
1167 * Also if this message was sent to us, don't rebroadcast.
1169 if( ( lpMsgHdr == NULL ) &&
1170 This->dp2->lpSessionDesc &&
1171 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1173 DPMSG_CREATEPLAYERORGROUP msg;
1174 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1176 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1177 msg.dpId = *lpidGroup;
1178 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1179 msg.lpData = lpData;
1180 msg.dwDataSize = dwDataSize;
1181 msg.dpnName = *lpGroupName;
1182 msg.dpIdParent = DPID_NOPARENT_GROUP;
1183 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
1185 /* FIXME: Correct to just use send effectively? */
1186 /* FIXME: Should size include data w/ message or just message "header" */
1187 /* FIXME: Check return code */
1188 IDirectPlayX_SendEx( &This->IDirectPlay4_iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
1189 sizeof( msg ), 0, 0, NULL, NULL );
1192 return DP_OK;
1195 static HRESULT WINAPI IDirectPlay2AImpl_CreateGroup( IDirectPlay2A *iface, DPID *lpidGroup,
1196 DPNAME *name, void *data, DWORD size, DWORD flags )
1198 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
1199 return IDirectPlayX_CreateGroup( &This->IDirectPlay4A_iface, lpidGroup, name, data, size,
1200 flags );
1203 static HRESULT WINAPI IDirectPlay2Impl_CreateGroup( IDirectPlay2 *iface, DPID *lpidGroup,
1204 DPNAME *name, void *data, DWORD size, DWORD flags )
1206 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
1207 return IDirectPlayX_CreateGroup( &This->IDirectPlay4_iface, lpidGroup, name, data, size,
1208 flags );
1211 static HRESULT WINAPI IDirectPlay3AImpl_CreateGroup( IDirectPlay3A *iface, DPID *group,
1212 DPNAME *name, void *data, DWORD size, DWORD flags )
1214 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
1215 return IDirectPlayX_CreateGroup( &This->IDirectPlay4_iface, group, name, data, size,
1216 flags );
1219 static HRESULT WINAPI IDirectPlay3Impl_CreateGroup( IDirectPlay3 *iface, DPID *lpidGroup,
1220 DPNAME *name, void *data, DWORD size, DWORD flags )
1222 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
1223 return IDirectPlayX_CreateGroup( &This->IDirectPlay4_iface, lpidGroup, name, data, size,
1224 flags );
1227 static HRESULT WINAPI IDirectPlay4AImpl_CreateGroup( IDirectPlay4A *iface, DPID *lpidGroup,
1228 DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1230 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
1232 *lpidGroup = DPID_UNKNOWN;
1234 return DP_IF_CreateGroup( This, NULL, lpidGroup, lpGroupName, lpData, dwDataSize, dwFlags,
1235 TRUE );
1238 static HRESULT WINAPI IDirectPlay4Impl_CreateGroup( IDirectPlay4 *iface, DPID *lpidGroup,
1239 DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1241 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
1243 *lpidGroup = DPID_UNKNOWN;
1245 return DP_IF_CreateGroup( This, NULL, lpidGroup, lpGroupName, lpData, dwDataSize, dwFlags,
1246 FALSE );
1250 static void
1251 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
1252 LPVOID lpData, DWORD dwDataSize )
1254 /* Clear out the data with this player */
1255 if( dwFlags & DPSET_LOCAL )
1257 if ( lpGData->dwLocalDataSize != 0 )
1259 free( lpGData->lpLocalData );
1260 lpGData->lpLocalData = NULL;
1261 lpGData->dwLocalDataSize = 0;
1264 else
1266 if( lpGData->dwRemoteDataSize != 0 )
1268 free( lpGData->lpRemoteData );
1269 lpGData->lpRemoteData = NULL;
1270 lpGData->dwRemoteDataSize = 0;
1274 /* Reallocate for new data */
1275 if( lpData != NULL )
1277 if( dwFlags & DPSET_LOCAL )
1279 lpGData->lpLocalData = lpData;
1280 lpGData->dwLocalDataSize = dwDataSize;
1282 else
1284 lpGData->lpRemoteData = malloc( dwDataSize );
1285 CopyMemory( lpGData->lpRemoteData, lpData, dwDataSize );
1286 lpGData->dwRemoteDataSize = dwDataSize;
1292 /* This function will just create the storage for the new player. */
1293 static lpPlayerData DP_CreatePlayer( IDirectPlayImpl *This, DPID *lpid, DPNAME *lpName,
1294 DWORD dwFlags, HANDLE hEvent, BOOL bAnsi )
1296 lpPlayerData lpPData;
1298 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
1300 /* Allocate the storage for the player and associate it with list element */
1301 lpPData = calloc( 1, sizeof( *lpPData ) );
1302 if( lpPData == NULL )
1304 return NULL;
1307 /* Set the desired player ID */
1308 lpPData->dpid = *lpid;
1310 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
1312 lpPData->dwFlags = dwFlags;
1314 /* If we were given an event handle, duplicate it */
1315 if( hEvent != 0 )
1317 if( !DuplicateHandle( GetCurrentProcess(), hEvent,
1318 GetCurrentProcess(), &lpPData->hEvent,
1319 0, FALSE, DUPLICATE_SAME_ACCESS )
1322 /* FIXME: Memory leak */
1323 ERR( "Can't duplicate player msg handle %p\n", hEvent );
1327 /* Initialize the SP data section */
1328 lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData();
1330 TRACE( "Created player id 0x%08lx\n", *lpid );
1332 if( ~dwFlags & DPLAYI_PLAYER_SYSPLAYER )
1333 This->dp2->lpSessionDesc->dwCurrentPlayers++;
1335 return lpPData;
1338 /* Delete the contents of the DPNAME struct */
1339 static void
1340 DP_DeleteDPNameStruct( LPDPNAME lpDPName )
1342 free( lpDPName->lpszShortNameA );
1343 free( lpDPName->lpszLongNameA );
1346 /* This method assumes that all links to it are already deleted */
1347 static void DP_DeletePlayer( IDirectPlayImpl *This, DPID dpid )
1349 lpPlayerList lpPList;
1351 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
1353 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1355 if( lpPList == NULL )
1357 ERR( "DPID 0x%08lx not found\n", dpid );
1358 return;
1361 /* Verify that this is the last reference to the data */
1362 if( --(lpPList->lpPData->uRef) )
1364 FIXME( "Why is this not the last reference to player?\n" );
1365 DebugBreak();
1368 /* Delete player */
1369 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1371 CloseHandle( lpPList->lpPData->hEvent );
1372 free( lpPList->lpPData );
1374 /* Delete Player List object */
1375 free( lpPList );
1378 static lpPlayerList DP_FindPlayer( IDirectPlayImpl *This, DPID dpid )
1380 lpPlayerList lpPlayers;
1382 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
1384 if(This->dp2->lpSysGroup == NULL)
1385 return NULL;
1387 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1389 return lpPlayers;
1392 /* Basic area for Dst must already be allocated */
1393 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, const DPNAME *lpSrc, BOOL bAnsi )
1395 if( lpSrc == NULL )
1397 ZeroMemory( lpDst, sizeof( *lpDst ) );
1398 lpDst->dwSize = sizeof( *lpDst );
1399 return TRUE;
1402 if( lpSrc->dwSize != sizeof( *lpSrc) )
1404 return FALSE;
1407 /* Delete any existing pointers */
1408 free( lpDst->lpszShortNameA );
1409 free( lpDst->lpszLongNameA );
1411 /* Copy as required */
1412 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1414 if( bAnsi )
1416 lpDst->lpszShortNameA = strdup( lpSrc->lpszShortNameA );
1417 lpDst->lpszLongNameA = strdup( lpSrc->lpszLongNameA );
1419 else
1421 lpDst->lpszShortName = wcsdup( lpSrc->lpszShortName );
1422 lpDst->lpszLongName = wcsdup( lpSrc->lpszLongName );
1425 return TRUE;
1428 static void
1429 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
1430 LPVOID lpData, DWORD dwDataSize )
1432 /* Clear out the data with this player */
1433 if( dwFlags & DPSET_LOCAL )
1435 if ( lpPData->dwLocalDataSize != 0 )
1437 free( lpPData->lpLocalData );
1438 lpPData->lpLocalData = NULL;
1439 lpPData->dwLocalDataSize = 0;
1442 else
1444 if( lpPData->dwRemoteDataSize != 0 )
1446 free( lpPData->lpRemoteData );
1447 lpPData->lpRemoteData = NULL;
1448 lpPData->dwRemoteDataSize = 0;
1452 /* Reallocate for new data */
1453 if( lpData != NULL )
1456 if( dwFlags & DPSET_LOCAL )
1458 lpPData->lpLocalData = lpData;
1459 lpPData->dwLocalDataSize = dwDataSize;
1461 else
1463 lpPData->lpRemoteData = malloc( dwDataSize );
1464 CopyMemory( lpPData->lpRemoteData, lpData, dwDataSize );
1465 lpPData->dwRemoteDataSize = dwDataSize;
1471 /* Note: lpMsgHdr is NULL for local creation, non NULL for remote creation */
1472 static HRESULT DP_IF_CreatePlayer( IDirectPlayImpl *This, void *lpMsgHdr, DPID *lpidPlayer,
1473 DPNAME *lpPlayerName, HANDLE hEvent, void *lpData, DWORD dwDataSize, DWORD dwFlags,
1474 BOOL bAnsi )
1476 HRESULT hr = DP_OK;
1477 lpPlayerData lpPData;
1478 lpPlayerList lpPList;
1479 DWORD dwCreateFlags = 0;
1481 TRACE( "(%p)->(%p,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
1482 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1483 dwDataSize, dwFlags, bAnsi );
1484 if( This->dp2->connectionInitialized == NO_PROVIDER )
1486 return DPERR_UNINITIALIZED;
1489 if( dwFlags == 0 )
1491 dwFlags = DPPLAYER_SPECTATOR;
1494 if( lpidPlayer == NULL )
1496 return DPERR_INVALIDPARAMS;
1500 /* Determine the creation flags for the player. These will be passed
1501 * to the name server if requesting a player id and to the SP when
1502 * informing it of the player creation
1505 if( dwFlags & DPPLAYER_SERVERPLAYER )
1507 if( *lpidPlayer == DPID_SERVERPLAYER )
1509 /* Server player for the host interface */
1510 dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
1512 else if( *lpidPlayer == DPID_NAME_SERVER )
1514 /* Name server - master of everything */
1515 dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
1517 else
1519 /* Server player for a non host interface */
1520 dwCreateFlags |= DPLAYI_PLAYER_SYSPLAYER;
1524 if( lpMsgHdr == NULL )
1525 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1528 /* Verify we know how to handle all the flags */
1529 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1530 ( dwFlags & DPPLAYER_SPECTATOR )
1534 /* Assume non fatal failure */
1535 ERR( "unknown dwFlags = 0x%08lx\n", dwFlags );
1538 /* If the name is not specified, we must provide one */
1539 if( *lpidPlayer == DPID_UNKNOWN )
1541 /* If we are the session master, we dish out the group/player ids */
1542 if( This->dp2->bHostInterface )
1544 *lpidPlayer = DP_NextObjectId();
1546 else
1548 hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer );
1550 if( FAILED(hr) )
1552 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1553 return hr;
1557 else
1559 /* FIXME: Would be nice to perhaps verify that we don't already have
1560 * this player.
1564 /* We pass creation flags, so we can distinguish sysplayers and not count them in the current
1565 player total */
1566 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwCreateFlags,
1567 hEvent, bAnsi );
1568 /* Create the list object and link it in */
1569 lpPList = calloc( 1, sizeof( *lpPList ) );
1570 if( !lpPData || !lpPList )
1572 free( lpPData );
1573 free( lpPList );
1574 return DPERR_CANTADDPLAYER;
1577 lpPData->uRef = 1;
1578 lpPList->lpPData = lpPData;
1580 /* Add the player to the system group */
1581 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1583 /* Update the information and send it to all players in the session */
1584 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
1586 /* Let the SP know that we've created this player */
1587 if( This->dp2->spData.lpCB->CreatePlayer )
1589 DPSP_CREATEPLAYERDATA data;
1591 data.idPlayer = *lpidPlayer;
1592 data.dwFlags = dwCreateFlags;
1593 data.lpSPMessageHeader = lpMsgHdr;
1594 data.lpISP = This->dp2->spData.lpISP;
1596 TRACE( "Calling SP CreatePlayer 0x%08lx: dwFlags: 0x%08lx lpMsgHdr: %p\n",
1597 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
1599 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1602 if( FAILED(hr) )
1604 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1605 return hr;
1608 /* Now let the SP know that this player is a member of the system group */
1609 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1611 DPSP_ADDPLAYERTOGROUPDATA data;
1613 data.idPlayer = *lpidPlayer;
1614 data.idGroup = DPID_SYSTEM_GROUP;
1615 data.lpISP = This->dp2->spData.lpISP;
1617 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1619 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1622 if( FAILED(hr) )
1624 ERR( "Failed to add player to sys group with sp: %s\n",
1625 DPLAYX_HresultToString(hr) );
1626 return hr;
1629 #if 1
1630 if( !This->dp2->bHostInterface )
1632 /* Let the name server know about the creation of this player */
1633 /* FIXME: Is this only to be done for the creation of a server player or
1634 * is this used for regular players? If only for server players, move
1635 * this call to DP_SecureOpen(...);
1637 #if 0
1638 TRACE( "Sending message to self to get my addr\n" );
1639 DP_MSG_ToSelf( This, *lpidPlayer ); /* This is a hack right now */
1640 #endif
1642 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
1644 #else
1645 /* Inform all other peers of the creation of a new player. If there are
1646 * no peers keep this quiet.
1647 * Also, if this was a remote event, no need to rebroadcast it.
1649 if( ( lpMsgHdr == NULL ) &&
1650 This->dp2->lpSessionDesc &&
1651 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1653 DPMSG_CREATEPLAYERORGROUP msg;
1654 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1656 msg.dwPlayerType = DPPLAYERTYPE_PLAYER;
1657 msg.dpId = *lpidPlayer;
1658 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */
1659 msg.lpData = lpData;
1660 msg.dwDataSize = dwDataSize;
1661 msg.dpnName = *lpPlayerName;
1662 msg.dpIdParent = DPID_NOPARENT_GROUP;
1663 msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
1665 /* FIXME: Correct to just use send effectively? */
1666 /* FIXME: Should size include data w/ message or just message "header" */
1667 /* FIXME: Check return code */
1668 hr = IDirectPlayX_SendEx( &This->IDirectPlay4_iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0,
1669 &msg, sizeof( msg ), 0, 0, NULL, NULL );
1671 #endif
1673 return hr;
1676 static HRESULT WINAPI IDirectPlay2AImpl_CreatePlayer( IDirectPlay2A *iface, DPID *lpidPlayer,
1677 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags )
1679 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
1680 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4A_iface, lpidPlayer, name, event, data,
1681 size, flags );
1684 static HRESULT WINAPI IDirectPlay2Impl_CreatePlayer( IDirectPlay2 *iface, DPID *lpidPlayer,
1685 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags )
1687 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
1688 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4_iface, lpidPlayer, name, event, data,
1689 size, flags );
1692 static HRESULT WINAPI IDirectPlay3AImpl_CreatePlayer( IDirectPlay3A *iface, DPID *lpidPlayer,
1693 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags )
1695 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
1696 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4_iface, lpidPlayer, name, event, data,
1697 size, flags );
1700 static HRESULT WINAPI IDirectPlay3Impl_CreatePlayer( IDirectPlay3 *iface, DPID *lpidPlayer,
1701 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags )
1703 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
1704 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4_iface, lpidPlayer, name, event, data,
1705 size, flags );
1708 static HRESULT WINAPI IDirectPlay4AImpl_CreatePlayer( IDirectPlay4A *iface, DPID *lpidPlayer,
1709 DPNAME *lpPlayerName, HANDLE hEvent, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1711 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
1713 if( lpidPlayer == NULL )
1715 return DPERR_INVALIDPARAMS;
1718 if( dwFlags & DPPLAYER_SERVERPLAYER )
1720 *lpidPlayer = DPID_SERVERPLAYER;
1722 else
1724 *lpidPlayer = DPID_UNKNOWN;
1727 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1728 lpData, dwDataSize, dwFlags, TRUE );
1731 static HRESULT WINAPI IDirectPlay4Impl_CreatePlayer( IDirectPlay4 *iface, DPID *lpidPlayer,
1732 DPNAME *lpPlayerName, HANDLE hEvent, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1734 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
1736 if( lpidPlayer == NULL )
1738 return DPERR_INVALIDPARAMS;
1741 if( dwFlags & DPPLAYER_SERVERPLAYER )
1743 *lpidPlayer = DPID_SERVERPLAYER;
1745 else
1747 *lpidPlayer = DPID_UNKNOWN;
1750 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1751 lpData, dwDataSize, dwFlags, FALSE );
1754 static DPID DP_GetRemoteNextObjectId(void)
1756 FIXME( ":stub\n" );
1758 /* Hack solution */
1759 return DP_NextObjectId();
1762 static HRESULT WINAPI IDirectPlay2AImpl_DeletePlayerFromGroup( IDirectPlay2A *iface, DPID group,
1763 DPID player )
1765 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
1766 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4A_iface, group, player );
1769 static HRESULT WINAPI IDirectPlay2Impl_DeletePlayerFromGroup( IDirectPlay2 *iface, DPID group,
1770 DPID player )
1772 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
1773 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1776 static HRESULT WINAPI IDirectPlay3AImpl_DeletePlayerFromGroup( IDirectPlay3A *iface, DPID group,
1777 DPID player )
1779 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
1780 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1783 static HRESULT WINAPI IDirectPlay3Impl_DeletePlayerFromGroup( IDirectPlay3 *iface, DPID group,
1784 DPID player )
1786 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
1787 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1790 static HRESULT WINAPI IDirectPlay4AImpl_DeletePlayerFromGroup( IDirectPlay4A *iface, DPID group,
1791 DPID player )
1793 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
1794 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1797 static HRESULT WINAPI IDirectPlay4Impl_DeletePlayerFromGroup( IDirectPlay4 *iface, DPID group,
1798 DPID player )
1800 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
1801 HRESULT hr = DP_OK;
1803 lpGroupData gdata;
1804 lpPlayerList plist;
1806 TRACE( "(%p)->(0x%08lx,0x%08lx)\n", This, group, player );
1808 /* Find the group */
1809 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
1810 return DPERR_INVALIDGROUP;
1812 /* Find the player */
1813 if ( DP_FindPlayer( This, player ) == NULL )
1814 return DPERR_INVALIDPLAYER;
1816 /* Remove the player shortcut from the group */
1817 DPQ_REMOVE_ENTRY( gdata->players, players, lpPData->dpid, ==, player, plist );
1819 if ( !plist )
1820 return DPERR_INVALIDPLAYER;
1822 /* One less reference */
1823 plist->lpPData->uRef--;
1825 /* Delete the Player List element */
1826 free( plist );
1828 /* Inform the SP if they care */
1829 if ( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1831 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1833 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1834 data.idPlayer = player;
1835 data.idGroup = group;
1836 data.lpISP = This->dp2->spData.lpISP;
1837 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1840 /* Need to send a DELETEPLAYERFROMGROUP message */
1841 FIXME( "Need to send a message\n" );
1843 return hr;
1846 typedef struct _DPRGOPContext
1848 IDirectPlayImpl *This;
1849 BOOL bAnsi;
1850 DPID idGroup;
1851 } DPRGOPContext, *lpDPRGOPContext;
1853 static BOOL CALLBACK
1854 cbRemoveGroupOrPlayer(
1855 DPID dpId,
1856 DWORD dwPlayerType,
1857 LPCDPNAME lpName,
1858 DWORD dwFlags,
1859 LPVOID lpContext )
1861 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1863 TRACE( "Removing element:0x%08lx (type:0x%08lx) from element:0x%08lx\n",
1864 dpId, dwPlayerType, lpCtxt->idGroup );
1866 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1868 if ( FAILED( IDirectPlayX_DeleteGroupFromGroup( &lpCtxt->This->IDirectPlay4_iface,
1869 lpCtxt->idGroup, dpId ) ) )
1870 ERR( "Unable to delete group 0x%08lx from group 0x%08lx\n", dpId, lpCtxt->idGroup );
1872 else if ( FAILED( IDirectPlayX_DeletePlayerFromGroup( &lpCtxt->This->IDirectPlay4_iface,
1873 lpCtxt->idGroup, dpId ) ) )
1874 ERR( "Unable to delete player 0x%08lx from grp 0x%08lx\n", dpId, lpCtxt->idGroup );
1876 return TRUE; /* Continue enumeration */
1879 static HRESULT DP_IF_DestroyGroup( IDirectPlayImpl *This, void *lpMsgHdr, DPID idGroup, BOOL bAnsi )
1881 lpGroupData lpGData;
1882 DPRGOPContext context;
1884 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
1885 This, lpMsgHdr, idGroup, bAnsi );
1887 /* Find the group */
1888 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1890 return DPERR_INVALIDPLAYER; /* yes player */
1893 context.This = This;
1894 context.bAnsi = bAnsi;
1895 context.idGroup = idGroup;
1897 /* Remove all players that this group has */
1898 IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, idGroup, NULL, cbRemoveGroupOrPlayer,
1899 &context, 0 );
1901 /* Remove all links to groups that this group has since this is dp3 */
1902 IDirectPlayX_EnumGroupsInGroup( &This->IDirectPlay4_iface, idGroup, NULL, cbRemoveGroupOrPlayer,
1903 (void*)&context, 0 );
1905 /* Remove this group from the parent group - if it has one */
1906 if( ( idGroup != DPID_SYSTEM_GROUP ) && ( lpGData->parent != DPID_SYSTEM_GROUP ) )
1907 IDirectPlayX_DeleteGroupFromGroup( &This->IDirectPlay4_iface, lpGData->parent, idGroup );
1909 /* Now delete this group data and list from the system group */
1910 DP_DeleteGroup( This, idGroup );
1912 /* Let the SP know that we've destroyed this group */
1913 if( This->dp2->spData.lpCB->DeleteGroup )
1915 DPSP_DELETEGROUPDATA data;
1917 FIXME( "data.dwFlags is incorrect\n" );
1919 data.idGroup = idGroup;
1920 data.dwFlags = 0;
1921 data.lpISP = This->dp2->spData.lpISP;
1923 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1926 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1928 return DP_OK;
1931 static HRESULT WINAPI IDirectPlay2AImpl_DestroyGroup( IDirectPlay2A *iface, DPID group )
1933 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
1934 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4A_iface, group );
1937 static HRESULT WINAPI IDirectPlay2Impl_DestroyGroup( IDirectPlay2 *iface, DPID group )
1939 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
1940 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4_iface, group );
1943 static HRESULT WINAPI IDirectPlay3AImpl_DestroyGroup( IDirectPlay3A *iface, DPID group )
1945 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
1946 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4_iface, group );
1949 static HRESULT WINAPI IDirectPlay3Impl_DestroyGroup( IDirectPlay3 *iface, DPID group )
1951 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
1952 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4_iface, group );
1955 static HRESULT WINAPI IDirectPlay4AImpl_DestroyGroup( IDirectPlay4A *iface, DPID idGroup )
1957 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
1958 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
1961 static HRESULT WINAPI IDirectPlay4Impl_DestroyGroup( IDirectPlay4 *iface, DPID idGroup )
1963 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
1964 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
1967 typedef struct _DPFAGContext
1969 IDirectPlayImpl *This;
1970 DPID idPlayer;
1971 BOOL bAnsi;
1972 } DPFAGContext, *lpDPFAGContext;
1974 static HRESULT DP_IF_DestroyPlayer( IDirectPlayImpl *This, void *lpMsgHdr, DPID idPlayer,
1975 BOOL bAnsi )
1977 DPFAGContext cbContext;
1979 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
1980 This, lpMsgHdr, idPlayer, bAnsi );
1982 if( This->dp2->connectionInitialized == NO_PROVIDER )
1984 return DPERR_UNINITIALIZED;
1987 if( DP_FindPlayer( This, idPlayer ) == NULL )
1989 return DPERR_INVALIDPLAYER;
1992 /* FIXME: If the player is remote, we must be the host to delete this */
1994 cbContext.This = This;
1995 cbContext.idPlayer = idPlayer;
1996 cbContext.bAnsi = bAnsi;
1998 /* Find each group and call DeletePlayerFromGroup if the player is a
1999 member of the group */
2000 IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, NULL, cbDeletePlayerFromAllGroups, &cbContext,
2001 DPENUMGROUPS_ALL );
2003 /* Now delete player and player list from the sys group */
2004 DP_DeletePlayer( This, idPlayer );
2006 /* Let the SP know that we've destroyed this group */
2007 if( This->dp2->spData.lpCB->DeletePlayer )
2009 DPSP_DELETEPLAYERDATA data;
2011 FIXME( "data.dwFlags is incorrect\n" );
2013 data.idPlayer = idPlayer;
2014 data.dwFlags = 0;
2015 data.lpISP = This->dp2->spData.lpISP;
2017 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
2020 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
2022 return DP_OK;
2025 static BOOL CALLBACK
2026 cbDeletePlayerFromAllGroups(
2027 DPID dpId,
2028 DWORD dwPlayerType,
2029 LPCDPNAME lpName,
2030 DWORD dwFlags,
2031 LPVOID lpContext )
2033 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
2035 if( dwPlayerType == DPPLAYERTYPE_GROUP )
2037 IDirectPlayX_DeletePlayerFromGroup( &lpCtxt->This->IDirectPlay4_iface, dpId, lpCtxt->idPlayer );
2039 /* Enumerate all groups in this group since this will normally only
2040 * be called for top level groups
2042 IDirectPlayX_EnumGroupsInGroup( &lpCtxt->This->IDirectPlay4_iface, dpId, NULL,
2043 cbDeletePlayerFromAllGroups, lpContext, DPENUMGROUPS_ALL);
2046 else
2048 ERR( "Group callback has dwPlayerType = 0x%08lx\n", dwPlayerType );
2051 return TRUE;
2054 static HRESULT WINAPI IDirectPlay2AImpl_DestroyPlayer( IDirectPlay2A *iface, DPID player )
2056 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2057 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4A_iface, player );
2060 static HRESULT WINAPI IDirectPlay2Impl_DestroyPlayer( IDirectPlay2 *iface, DPID player )
2062 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2063 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4_iface, player );
2066 static HRESULT WINAPI IDirectPlay3AImpl_DestroyPlayer( IDirectPlay3A *iface, DPID player )
2068 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2069 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4_iface, player );
2072 static HRESULT WINAPI IDirectPlay3Impl_DestroyPlayer( IDirectPlay3 *iface, DPID player )
2074 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2075 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4_iface, player );
2078 static HRESULT WINAPI IDirectPlay4AImpl_DestroyPlayer( IDirectPlay4A *iface, DPID idPlayer )
2080 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2081 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
2084 static HRESULT WINAPI IDirectPlay4Impl_DestroyPlayer( IDirectPlay4 *iface, DPID idPlayer )
2086 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2087 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
2090 static HRESULT WINAPI IDirectPlay2AImpl_EnumGroupPlayers( IDirectPlay2A *iface, DPID group,
2091 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2093 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2094 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4A_iface, group, instance,
2095 enumplayercb, context, flags );
2098 static HRESULT WINAPI IDirectPlay2Impl_EnumGroupPlayers( IDirectPlay2 *iface, DPID group,
2099 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2101 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2102 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance,
2103 enumplayercb, context, flags );
2106 static HRESULT WINAPI IDirectPlay3AImpl_EnumGroupPlayers( IDirectPlay3A *iface, DPID group,
2107 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2109 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2110 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance,
2111 enumplayercb, context, flags );
2114 static HRESULT WINAPI IDirectPlay3Impl_EnumGroupPlayers( IDirectPlay3 *iface, DPID group,
2115 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2117 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2118 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance,
2119 enumplayercb, context, flags );
2122 static HRESULT WINAPI IDirectPlay4AImpl_EnumGroupPlayers( IDirectPlay4A *iface, DPID group,
2123 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2125 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2126 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance, enumplayercb,
2127 context, flags );
2130 static HRESULT WINAPI IDirectPlay4Impl_EnumGroupPlayers( IDirectPlay4 *iface, DPID group,
2131 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2133 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2134 lpGroupData gdata;
2135 lpPlayerList plist;
2137 FIXME( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx): semi stub\n", This, group, instance, enumplayercb,
2138 context, flags );
2140 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2141 return DPERR_UNINITIALIZED;
2143 /* Find the group */
2144 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
2145 return DPERR_INVALIDGROUP;
2147 if ( DPQ_IS_EMPTY( gdata->players ) )
2148 return DP_OK;
2150 /* Walk the players in this group */
2151 for( plist = DPQ_FIRST( gdata->players ); ; plist = DPQ_NEXT( plist->players ) )
2153 /* We do not enum the name server or app server as they are of no
2154 * consequence to the end user.
2156 if ( ( plist->lpPData->dpid != DPID_NAME_SERVER ) &&
2157 ( plist->lpPData->dpid != DPID_SERVERPLAYER ) )
2159 /* FIXME: Need to add stuff for flags checking */
2160 if ( !enumplayercb( plist->lpPData->dpid, DPPLAYERTYPE_PLAYER,
2161 &plist->lpPData->name, plist->lpPData->dwFlags, context ) )
2162 /* User requested break */
2163 return DP_OK;
2166 if ( DPQ_IS_ENDOFLIST( plist->players ) )
2167 break;
2169 return DP_OK;
2172 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2173 static HRESULT WINAPI IDirectPlay2AImpl_EnumGroups( IDirectPlay2A *iface, GUID *instance,
2174 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2176 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2177 return IDirectPlayX_EnumGroups( &This->IDirectPlay4A_iface, instance, enumplayercb, context,
2178 flags );
2181 static HRESULT WINAPI IDirectPlay2Impl_EnumGroups( IDirectPlay2 *iface, GUID *instance,
2182 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2184 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2185 return IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2186 flags );
2189 static HRESULT WINAPI IDirectPlay3AImpl_EnumGroups( IDirectPlay3A *iface, GUID *instance,
2190 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2192 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2193 return IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2194 flags );
2197 static HRESULT WINAPI IDirectPlay3Impl_EnumGroups( IDirectPlay3 *iface, GUID *instance,
2198 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2200 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2201 return IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2202 flags );
2205 static HRESULT WINAPI IDirectPlay4AImpl_EnumGroups( IDirectPlay4A *iface, GUID *instance,
2206 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2208 return IDirectPlayX_EnumGroupsInGroup( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2209 context, flags );
2212 static HRESULT WINAPI IDirectPlay4Impl_EnumGroups ( IDirectPlay4 *iface, GUID *instance,
2213 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2215 return IDirectPlayX_EnumGroupsInGroup( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2216 context, flags );
2219 static HRESULT WINAPI IDirectPlay2AImpl_EnumPlayers( IDirectPlay2A *iface, GUID *instance,
2220 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2222 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2223 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4A_iface, instance, enumplayercb, context,
2224 flags );
2227 static HRESULT WINAPI IDirectPlay2Impl_EnumPlayers( IDirectPlay2 *iface, GUID *instance,
2228 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2230 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2231 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2232 flags );
2235 static HRESULT WINAPI IDirectPlay3AImpl_EnumPlayers( IDirectPlay3A *iface, GUID *instance,
2236 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2238 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2239 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2240 flags );
2243 static HRESULT WINAPI IDirectPlay3Impl_EnumPlayers( IDirectPlay3 *iface, GUID *instance,
2244 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2246 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2247 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2248 flags );
2251 static HRESULT WINAPI IDirectPlay4AImpl_EnumPlayers( IDirectPlay4A *iface, GUID *instance,
2252 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2254 return IDirectPlayX_EnumGroupPlayers( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2255 context, flags );
2258 static HRESULT WINAPI IDirectPlay4Impl_EnumPlayers( IDirectPlay4 *iface, GUID *instance,
2259 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2261 return IDirectPlayX_EnumGroupPlayers( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2262 context, flags );
2265 /* This function should call the registered callback function that the user
2266 passed into EnumSessions for each entry available.
2268 static void DP_InvokeEnumSessionCallbacks
2269 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2270 LPVOID lpNSInfo,
2271 DWORD dwTimeout,
2272 LPVOID lpContext )
2274 LPDPSESSIONDESC2 lpSessionDesc;
2276 FIXME( ": not checking for conditions\n" );
2278 /* Not sure if this should be pruning but it's convenient */
2279 NS_PruneSessionCache( lpNSInfo );
2281 NS_ResetSessionEnumeration( lpNSInfo );
2283 /* Enumerate all sessions */
2284 /* FIXME: Need to indicate ANSI */
2285 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2287 TRACE( "EnumSessionsCallback2 invoked\n" );
2288 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2290 return;
2294 /* Invoke one last time to indicate that there is no more to come */
2295 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2298 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2300 EnumSessionAsyncCallbackData* data = lpContext;
2301 HANDLE hSuicideRequest = data->hSuicideRequest;
2302 DWORD dwTimeout = data->dwTimeout;
2304 TRACE( "Thread started with timeout = 0x%08lx\n", dwTimeout );
2306 for( ;; )
2308 HRESULT hr;
2310 /* Sleep up to dwTimeout waiting for request to terminate thread */
2311 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2313 TRACE( "Thread terminating on terminate request\n" );
2314 break;
2317 /* Now resend the enum request */
2318 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2319 data->dwEnumSessionFlags,
2320 data->lpSpData );
2322 if( FAILED(hr) )
2324 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2325 /* FIXME: Should we kill this thread? How to inform the main thread? */
2330 TRACE( "Thread terminating\n" );
2332 /* Clean up the thread data */
2333 CloseHandle( hSuicideRequest );
2334 free( lpContext );
2336 /* FIXME: Need to have some notification to main app thread that this is
2337 * dead. It would serve two purposes. 1) allow sync on termination
2338 * so that we don't actually send something to ourselves when we
2339 * become name server (race condition) and 2) so that if we die
2340 * abnormally something else will be able to tell.
2343 return 1;
2346 static void DP_KillEnumSessionThread( IDirectPlayImpl *This )
2348 /* Does a thread exist? If so we were doing an async enum session */
2349 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2351 TRACE( "Killing EnumSession thread %p\n",
2352 This->dp2->hEnumSessionThread );
2354 /* Request that the thread kill itself nicely */
2355 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2356 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2358 /* We no longer need to know about the thread */
2359 CloseHandle( This->dp2->hEnumSessionThread );
2361 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2365 static HRESULT WINAPI IDirectPlay2AImpl_EnumSessions( IDirectPlay2A *iface, DPSESSIONDESC2 *sdesc,
2366 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2368 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2369 return IDirectPlayX_EnumSessions( &This->IDirectPlay4A_iface, sdesc, timeout, enumsessioncb,
2370 context, flags );
2373 static HRESULT WINAPI IDirectPlay2Impl_EnumSessions( IDirectPlay2 *iface, DPSESSIONDESC2 *sdesc,
2374 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2376 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2377 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2378 context, flags );
2381 static HRESULT WINAPI IDirectPlay3AImpl_EnumSessions( IDirectPlay3A *iface, DPSESSIONDESC2 *sdesc,
2382 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2384 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2385 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2386 context, flags );
2389 static HRESULT WINAPI IDirectPlay3Impl_EnumSessions( IDirectPlay3 *iface, DPSESSIONDESC2 *sdesc,
2390 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2392 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2393 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2394 context, flags );
2397 static HRESULT WINAPI IDirectPlay4AImpl_EnumSessions( IDirectPlay4A *iface, DPSESSIONDESC2 *sdesc,
2398 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2400 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2401 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2402 context, flags );
2405 static HRESULT WINAPI IDirectPlay4Impl_EnumSessions( IDirectPlay4 *iface, DPSESSIONDESC2 *sdesc,
2406 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2408 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2409 void *connection;
2410 DWORD size;
2411 HRESULT hr = DP_OK;
2413 TRACE( "(%p)->(%p,0x%08lx,%p,%p,0x%08lx)\n", This, sdesc, timeout, enumsessioncb,
2414 context, flags );
2416 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2417 return DPERR_UNINITIALIZED;
2419 /* Can't enumerate if the interface is already open */
2420 if ( This->dp2->bConnectionOpen )
2421 return DPERR_GENERIC;
2423 /* The loading of a lobby provider _seems_ to require a backdoor loading
2424 * of the service provider to also associate with this DP object. This is
2425 * because the app doesn't seem to have to call EnumConnections and
2426 * InitializeConnection for the SP before calling this method. As such
2427 * we'll do their dirty work for them with a quick hack so as to always
2428 * load the TCP/IP service provider.
2430 * The correct solution would seem to involve creating a dialog box which
2431 * contains the possible SPs. These dialog boxes most likely follow SDK
2432 * examples.
2434 if ( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
2436 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2438 if ( !DP_BuildSPCompoundAddr( (GUID*)&DPSPGUID_TCPIP, &connection, &size ) )
2440 ERR( "Can't build compound addr\n" );
2441 return DPERR_GENERIC;
2444 hr = IDirectPlayX_InitializeConnection( &This->IDirectPlay4_iface, connection, 0 );
2445 if ( FAILED(hr) )
2446 return hr;
2448 free( connection );
2449 This->dp2->bSPInitialized = TRUE;
2453 /* Use the service provider default? */
2454 if ( !timeout )
2456 DPCAPS caps;
2457 caps.dwSize = sizeof( caps );
2459 IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, &caps, 0 );
2460 timeout = caps.dwTimeout;
2461 if ( !timeout )
2462 timeout = DPMSG_WAIT_5_SECS; /* Provide the TCP/IP default */
2465 if ( flags & DPENUMSESSIONS_STOPASYNC )
2467 DP_KillEnumSessionThread( This );
2468 return hr;
2471 if ( flags & DPENUMSESSIONS_ASYNC )
2473 /* Enumerate everything presently in the local session cache */
2474 DP_InvokeEnumSessionCallbacks( enumsessioncb, This->dp2->lpNameServerData, timeout,
2475 context );
2477 if ( This->dp2->dwEnumSessionLock )
2478 return DPERR_CONNECTING;
2480 /* See if we've already created a thread to service this interface */
2481 if ( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2483 DWORD tid;
2484 This->dp2->dwEnumSessionLock++;
2486 /* Send the first enum request inline since the user may cancel a dialog
2487 * if one is presented. Also, may also have a connecting return code.
2489 hr = NS_SendSessionRequestBroadcast( &sdesc->guidApplication, flags,
2490 &This->dp2->spData );
2492 if ( SUCCEEDED(hr) )
2494 EnumSessionAsyncCallbackData* data = calloc( 1, sizeof( *data ) );
2495 /* FIXME: need to kill the thread on object deletion */
2496 data->lpSpData = &This->dp2->spData;
2497 data->requestGuid = sdesc->guidApplication;
2498 data->dwEnumSessionFlags = flags;
2499 data->dwTimeout = timeout;
2501 This->dp2->hKillEnumSessionThreadEvent = CreateEventW( NULL, TRUE, FALSE, NULL );
2502 if ( !DuplicateHandle( GetCurrentProcess(), This->dp2->hKillEnumSessionThreadEvent,
2503 GetCurrentProcess(), &data->hSuicideRequest, 0, FALSE,
2504 DUPLICATE_SAME_ACCESS ) )
2505 ERR( "Can't duplicate thread killing handle\n" );
2507 TRACE( ": creating EnumSessionsRequest thread\n" );
2508 This->dp2->hEnumSessionThread = CreateThread( NULL, 0,
2509 DP_EnumSessionsSendAsyncRequestThread, data, 0, &tid );
2511 This->dp2->dwEnumSessionLock--;
2514 else
2516 /* Invalidate the session cache for the interface */
2517 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2518 /* Send the broadcast for session enumeration */
2519 hr = NS_SendSessionRequestBroadcast( &sdesc->guidApplication, flags, &This->dp2->spData );
2520 SleepEx( timeout, FALSE );
2521 DP_InvokeEnumSessionCallbacks( enumsessioncb, This->dp2->lpNameServerData, timeout,
2522 context );
2525 return hr;
2528 static HRESULT WINAPI IDirectPlay2AImpl_GetCaps( IDirectPlay2A *iface, DPCAPS *caps, DWORD flags )
2530 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2531 return IDirectPlayX_GetCaps( &This->IDirectPlay4A_iface, caps, flags );
2534 static HRESULT WINAPI IDirectPlay2Impl_GetCaps( IDirectPlay2 *iface, DPCAPS *caps, DWORD flags )
2536 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2537 return IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, caps, flags );
2540 static HRESULT WINAPI IDirectPlay3AImpl_GetCaps( IDirectPlay3A *iface, DPCAPS *caps, DWORD flags )
2542 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2543 return IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, caps, flags );
2546 static HRESULT WINAPI IDirectPlay3Impl_GetCaps( IDirectPlay3 *iface, DPCAPS *caps, DWORD flags )
2548 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2549 return IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, caps, flags );
2552 static HRESULT WINAPI IDirectPlay4AImpl_GetCaps( IDirectPlay4A *iface, DPCAPS *caps, DWORD flags )
2554 return IDirectPlayX_GetPlayerCaps( iface, DPID_ALLPLAYERS, caps, flags );
2557 static HRESULT WINAPI IDirectPlay4Impl_GetCaps( IDirectPlay4 *iface, DPCAPS *caps, DWORD flags )
2559 return IDirectPlayX_GetPlayerCaps( iface, DPID_ALLPLAYERS, caps, flags );
2562 static HRESULT WINAPI IDirectPlay2AImpl_GetGroupData( IDirectPlay2A *iface, DPID group, void *data,
2563 DWORD *size, DWORD flags )
2565 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2566 return IDirectPlayX_GetGroupData( &This->IDirectPlay4A_iface, group, data, size, flags );
2569 static HRESULT WINAPI IDirectPlay2Impl_GetGroupData( IDirectPlay2 *iface, DPID group, void *data,
2570 DWORD *size, DWORD flags )
2572 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2573 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2576 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupData( IDirectPlay3A *iface, DPID group, void *data,
2577 DWORD *size, DWORD flags )
2579 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2580 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2583 static HRESULT WINAPI IDirectPlay3Impl_GetGroupData( IDirectPlay3 *iface, DPID group, void *data,
2584 DWORD *size, DWORD flags )
2586 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2587 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2590 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupData( IDirectPlay4A *iface, DPID group,
2591 void *data, DWORD *size, DWORD flags )
2593 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2594 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2597 static HRESULT WINAPI IDirectPlay4Impl_GetGroupData( IDirectPlay4 *iface, DPID group,
2598 void *data, DWORD *size, DWORD flags )
2600 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2601 lpGroupData gdata;
2602 DWORD bufsize;
2603 void *src;
2605 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx)\n", This, group, data, size, flags );
2607 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
2608 return DPERR_INVALIDGROUP;
2610 /* How much buffer is required? */
2611 if ( flags & DPSET_LOCAL )
2613 bufsize = gdata->dwLocalDataSize;
2614 src = gdata->lpLocalData;
2616 else
2618 bufsize = gdata->dwRemoteDataSize;
2619 src = gdata->lpRemoteData;
2622 /* Is the user requesting to know how big a buffer is required? */
2623 if ( !data || *size < bufsize )
2625 *size = bufsize;
2626 return DPERR_BUFFERTOOSMALL;
2629 CopyMemory( data, src, bufsize );
2631 return DP_OK;
2634 static HRESULT DP_IF_GetGroupName( IDirectPlayImpl *This, DPID idGroup, void *lpData,
2635 DWORD *lpdwDataSize, BOOL bAnsi )
2637 lpGroupData lpGData;
2638 LPDPNAME lpName = lpData;
2639 DWORD dwRequiredDataSize;
2641 FIXME("(%p)->(0x%08lx,%p,%p,%u) ANSI ignored\n",
2642 This, idGroup, lpData, lpdwDataSize, bAnsi );
2644 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2646 return DPERR_INVALIDGROUP;
2649 dwRequiredDataSize = lpGData->name.dwSize;
2651 if( lpGData->name.lpszShortNameA )
2653 dwRequiredDataSize += strlen( lpGData->name.lpszShortNameA ) + 1;
2656 if( lpGData->name.lpszLongNameA )
2658 dwRequiredDataSize += strlen( lpGData->name.lpszLongNameA ) + 1;
2661 if( ( lpData == NULL ) ||
2662 ( *lpdwDataSize < dwRequiredDataSize )
2665 *lpdwDataSize = dwRequiredDataSize;
2666 return DPERR_BUFFERTOOSMALL;
2669 /* Copy the structure */
2670 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2672 if( lpGData->name.lpszShortNameA )
2674 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2675 lpGData->name.lpszShortNameA );
2677 else
2679 lpName->lpszShortNameA = NULL;
2682 if( lpGData->name.lpszShortNameA )
2684 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2685 lpGData->name.lpszShortNameA );
2687 else
2689 lpName->lpszLongNameA = NULL;
2692 return DP_OK;
2695 static HRESULT WINAPI IDirectPlay2AImpl_GetGroupName( IDirectPlay2A *iface, DPID group, void *data,
2696 DWORD *size )
2698 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2699 return IDirectPlayX_GetGroupName( &This->IDirectPlay4A_iface, group, data, size );
2702 static HRESULT WINAPI IDirectPlay2Impl_GetGroupName( IDirectPlay2 *iface, DPID group, void *data,
2703 DWORD *size )
2705 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2706 return IDirectPlayX_GetGroupName( &This->IDirectPlay4_iface, group, data, size );
2709 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupName( IDirectPlay3A *iface, DPID group, void *data,
2710 DWORD *size )
2712 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2713 return IDirectPlayX_GetGroupName( &This->IDirectPlay4_iface, group, data, size );
2716 static HRESULT WINAPI IDirectPlay3Impl_GetGroupName( IDirectPlay3 *iface, DPID group, void *data,
2717 DWORD *size )
2719 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2720 return IDirectPlayX_GetGroupName( &This->IDirectPlay4_iface, group, data, size );
2723 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupName( IDirectPlay4A *iface, DPID idGroup,
2724 void *lpData, DWORD *lpdwDataSize )
2726 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2727 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2730 static HRESULT WINAPI IDirectPlay4Impl_GetGroupName( IDirectPlay4 *iface, DPID idGroup,
2731 void *lpData, DWORD *lpdwDataSize )
2733 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2734 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2737 static HRESULT WINAPI IDirectPlay2AImpl_GetMessageCount( IDirectPlay2A *iface, DPID player,
2738 DWORD *count )
2740 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2741 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4A_iface, player, count );
2744 static HRESULT WINAPI IDirectPlay2Impl_GetMessageCount( IDirectPlay2 *iface, DPID player,
2745 DWORD *count )
2747 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2748 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4_iface, player, count );
2751 static HRESULT WINAPI IDirectPlay3AImpl_GetMessageCount( IDirectPlay3A *iface, DPID player,
2752 DWORD *count )
2754 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2755 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4_iface, player, count );
2758 static HRESULT WINAPI IDirectPlay3Impl_GetMessageCount( IDirectPlay3 *iface, DPID player,
2759 DWORD *count )
2761 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2762 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4_iface, player, count );
2765 static HRESULT WINAPI IDirectPlay4AImpl_GetMessageCount( IDirectPlay4A *iface, DPID player,
2766 DWORD *count )
2768 return IDirectPlayX_GetMessageQueue( iface, 0, player, DPMESSAGEQUEUE_RECEIVE, count, NULL );
2771 static HRESULT WINAPI IDirectPlay4Impl_GetMessageCount( IDirectPlay4 *iface, DPID player,
2772 DWORD *count )
2774 return IDirectPlayX_GetMessageQueue( iface, 0, player, DPMESSAGEQUEUE_RECEIVE, count, NULL );
2777 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerAddress( IDirectPlay2A *iface, DPID player,
2778 void *data, DWORD *size )
2780 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2781 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4A_iface, player, data, size );
2784 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerAddress( IDirectPlay2 *iface, DPID player,
2785 void *data, DWORD *size )
2787 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2788 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4_iface, player, data, size );
2791 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerAddress( IDirectPlay3A *iface, DPID player,
2792 void *data, DWORD *size )
2794 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2795 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4_iface, player, data, size );
2798 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerAddress( IDirectPlay3 *iface, DPID player,
2799 void *data, DWORD *size )
2801 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2802 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4_iface, player, data, size );
2805 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerAddress( IDirectPlay4A *iface, DPID player,
2806 void *data, DWORD *size )
2808 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2809 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, player, data, size );
2810 return DP_OK;
2813 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerAddress( IDirectPlay4 *iface, DPID player,
2814 void *data, DWORD *size )
2816 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2817 FIXME( "(%p)->(0x%08lx,%p,%p): stub\n", This, player, data, size );
2818 return DP_OK;
2821 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerCaps( IDirectPlay2A *iface, DPID player,
2822 DPCAPS *caps, DWORD flags )
2824 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2825 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4A_iface, player, caps, flags );
2828 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerCaps( IDirectPlay2 *iface, DPID player,
2829 DPCAPS *caps, DWORD flags )
2831 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2832 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2835 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerCaps( IDirectPlay3A *iface, DPID player,
2836 DPCAPS *caps, DWORD flags )
2838 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2839 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2842 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerCaps( IDirectPlay3 *iface, DPID player,
2843 DPCAPS *caps, DWORD flags )
2845 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2846 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2849 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerCaps( IDirectPlay4A *iface, DPID player,
2850 DPCAPS *caps, DWORD flags )
2852 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2853 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2856 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerCaps( IDirectPlay4 *iface, DPID player,
2857 DPCAPS *caps, DWORD flags )
2859 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2860 DPSP_GETCAPSDATA data;
2862 TRACE( "(%p)->(0x%08lx,%p,0x%08lx)\n", This, player, caps, flags);
2864 if ( !caps )
2865 return DPERR_INVALIDPARAMS;
2867 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2868 return DPERR_UNINITIALIZED;
2870 if( caps->dwSize != sizeof(DPCAPS) )
2871 return DPERR_INVALIDPARAMS;
2873 /* Query the service provider */
2874 data.idPlayer = player;
2875 data.dwFlags = flags;
2876 data.lpCaps = caps;
2877 data.lpISP = This->dp2->spData.lpISP;
2879 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2882 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerData( IDirectPlay2A *iface, DPID player,
2883 void *data, DWORD *size, DWORD flags )
2885 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2886 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4A_iface, player, data, size, flags );
2889 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerData( IDirectPlay2 *iface, DPID player,
2890 void *data, DWORD *size, DWORD flags )
2892 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2893 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2896 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerData( IDirectPlay3A *iface, DPID player,
2897 void *data, DWORD *size, DWORD flags )
2899 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2900 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2903 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerData( IDirectPlay3 *iface, DPID player,
2904 void *data, DWORD *size, DWORD flags )
2906 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2907 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2910 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerData( IDirectPlay4A *iface, DPID player,
2911 void *data, DWORD *size, DWORD flags )
2913 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2914 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2917 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerData( IDirectPlay4 *iface, DPID player,
2918 void *data, DWORD *size, DWORD flags )
2920 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2921 lpPlayerList plist;
2922 DWORD bufsize;
2923 void *src;
2925 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx)\n", This, player, data, size, flags );
2927 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2928 return DPERR_UNINITIALIZED;
2930 if ( ( plist = DP_FindPlayer( This, player ) ) == NULL )
2931 return DPERR_INVALIDPLAYER;
2933 if ( flags & DPSET_LOCAL )
2935 bufsize = plist->lpPData->dwLocalDataSize;
2936 src = plist->lpPData->lpLocalData;
2938 else
2940 bufsize = plist->lpPData->dwRemoteDataSize;
2941 src = plist->lpPData->lpRemoteData;
2944 /* Is the user requesting to know how big a buffer is required? */
2945 if ( !data || *size < bufsize )
2947 *size = bufsize;
2948 return DPERR_BUFFERTOOSMALL;
2951 CopyMemory( data, src, bufsize );
2953 return DP_OK;
2956 static HRESULT DP_IF_GetPlayerName( IDirectPlayImpl *This, DPID idPlayer, void *lpData,
2957 DWORD *lpdwDataSize, BOOL bAnsi )
2959 lpPlayerList lpPList;
2960 LPDPNAME lpName = lpData;
2961 DWORD dwRequiredDataSize;
2963 FIXME( "(%p)->(0x%08lx,%p,%p,%u): ANSI\n",
2964 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2966 if( This->dp2->connectionInitialized == NO_PROVIDER )
2968 return DPERR_UNINITIALIZED;
2971 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2973 return DPERR_INVALIDPLAYER;
2976 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
2978 if( lpPList->lpPData->name.lpszShortNameA )
2980 dwRequiredDataSize += strlen( lpPList->lpPData->name.lpszShortNameA ) + 1;
2983 if( lpPList->lpPData->name.lpszLongNameA )
2985 dwRequiredDataSize += strlen( lpPList->lpPData->name.lpszLongNameA ) + 1;
2988 if( ( lpData == NULL ) ||
2989 ( *lpdwDataSize < dwRequiredDataSize )
2992 *lpdwDataSize = dwRequiredDataSize;
2993 return DPERR_BUFFERTOOSMALL;
2996 /* Copy the structure */
2997 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
2999 if( lpPList->lpPData->name.lpszShortNameA )
3001 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
3002 lpPList->lpPData->name.lpszShortNameA );
3004 else
3006 lpName->lpszShortNameA = NULL;
3009 if( lpPList->lpPData->name.lpszShortNameA )
3011 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
3012 lpPList->lpPData->name.lpszLongNameA );
3014 else
3016 lpName->lpszLongNameA = NULL;
3019 return DP_OK;
3022 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerName( IDirectPlay2A *iface, DPID player,
3023 void *data, DWORD *size )
3025 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3026 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4A_iface, player, data, size );
3029 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerName( IDirectPlay2 *iface, DPID player,
3030 void *data, DWORD *size )
3032 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3033 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4_iface, player, data, size );
3036 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerName( IDirectPlay3A *iface, DPID player,
3037 void *data, DWORD *size )
3039 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3040 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4_iface, player, data, size );
3043 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerName( IDirectPlay3 *iface, DPID player,
3044 void *data, DWORD *size )
3046 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3047 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4_iface, player, data, size );
3050 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerName( IDirectPlay4A *iface, DPID idPlayer,
3051 void *lpData, DWORD *lpdwDataSize )
3053 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3054 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
3057 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerName( IDirectPlay4 *iface, DPID idPlayer,
3058 void *lpData, DWORD *lpdwDataSize )
3060 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3061 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
3064 static HRESULT DP_GetSessionDesc( IDirectPlayImpl *This, void *lpData, DWORD *lpdwDataSize,
3065 BOOL bAnsi )
3067 DWORD dwRequiredSize;
3069 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
3071 if( This->dp2->connectionInitialized == NO_PROVIDER )
3073 return DPERR_UNINITIALIZED;
3076 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
3078 return DPERR_INVALIDPARAMS;
3081 /* FIXME: Get from This->dp2->lpSessionDesc */
3082 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
3084 if ( ( lpData == NULL ) ||
3085 ( *lpdwDataSize < dwRequiredSize )
3088 *lpdwDataSize = dwRequiredSize;
3089 return DPERR_BUFFERTOOSMALL;
3092 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
3094 return DP_OK;
3097 static HRESULT WINAPI IDirectPlay2AImpl_GetSessionDesc( IDirectPlay2A *iface, void *data,
3098 DWORD *size )
3100 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3101 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4A_iface, data, size );
3104 static HRESULT WINAPI IDirectPlay2Impl_GetSessionDesc( IDirectPlay2 *iface, void *data,
3105 DWORD *size )
3107 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3108 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4_iface, data, size );
3111 static HRESULT WINAPI IDirectPlay3AImpl_GetSessionDesc( IDirectPlay3A *iface, void *data,
3112 DWORD *size )
3114 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3115 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4_iface, data, size );
3118 static HRESULT WINAPI IDirectPlay3Impl_GetSessionDesc( IDirectPlay3 *iface, void *data,
3119 DWORD *size )
3121 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3122 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4_iface, data, size );
3125 static HRESULT WINAPI IDirectPlay4AImpl_GetSessionDesc( IDirectPlay4A *iface, void *lpData,
3126 DWORD *lpdwDataSize )
3128 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3129 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
3132 static HRESULT WINAPI IDirectPlay4Impl_GetSessionDesc( IDirectPlay4 *iface, void *lpData,
3133 DWORD *lpdwDataSize )
3135 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3136 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
3139 static HRESULT WINAPI IDirectPlay2AImpl_Initialize( IDirectPlay2A *iface, GUID *guid )
3141 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3142 return IDirectPlayX_Initialize( &This->IDirectPlay4A_iface, guid );
3145 static HRESULT WINAPI IDirectPlay2Impl_Initialize( IDirectPlay2 *iface, GUID *guid )
3147 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3148 return IDirectPlayX_Initialize( &This->IDirectPlay4_iface, guid );
3151 static HRESULT WINAPI IDirectPlay3AImpl_Initialize( IDirectPlay3A *iface, GUID *guid )
3153 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3154 return IDirectPlayX_Initialize( &This->IDirectPlay4_iface, guid );
3157 static HRESULT WINAPI IDirectPlay3Impl_Initialize( IDirectPlay3 *iface, GUID *guid )
3159 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3160 return IDirectPlayX_Initialize( &This->IDirectPlay4_iface, guid );
3163 /* Intended only for COM compatibility. Always returns an error. */
3164 static HRESULT WINAPI IDirectPlay4AImpl_Initialize( IDirectPlay4A *iface, GUID *guid )
3166 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3167 TRACE("(%p)->(%p): no-op\n", This, guid );
3168 return DPERR_ALREADYINITIALIZED;
3171 static HRESULT WINAPI IDirectPlay4Impl_Initialize( IDirectPlay4 *iface, GUID *guid )
3173 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3174 TRACE( "(%p)->(%p): no-op\n", This, guid );
3175 return DPERR_ALREADYINITIALIZED;
3179 static HRESULT DP_SecureOpen( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpsd, DWORD dwFlags,
3180 const DPSECURITYDESC *lpSecurity, const DPCREDENTIALS *lpCredentials, BOOL bAnsi )
3182 HRESULT hr = DP_OK;
3184 FIXME( "(%p)->(%p,0x%08lx,%p,%p): partial stub\n",
3185 This, lpsd, dwFlags, lpSecurity, lpCredentials );
3187 if( This->dp2->connectionInitialized == NO_PROVIDER )
3189 return DPERR_UNINITIALIZED;
3192 if( lpsd->dwSize != sizeof(DPSESSIONDESC2) )
3194 TRACE( ": rejecting invalid dpsd size (%ld).\n", lpsd->dwSize );
3195 return DPERR_INVALIDPARAMS;
3198 if( This->dp2->bConnectionOpen )
3200 TRACE( ": rejecting already open connection.\n" );
3201 return DPERR_ALREADYINITIALIZED;
3204 /* If we're enumerating, kill the thread */
3205 DP_KillEnumSessionThread( This );
3207 if( dwFlags & DPOPEN_CREATE )
3209 /* Rightoo - this computer is the host and the local computer needs to be
3210 the name server so that others can join this session */
3211 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
3213 This->dp2->bHostInterface = TRUE;
3215 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
3216 if( FAILED( hr ) )
3218 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
3219 return hr;
3223 /* Invoke the conditional callback for the service provider */
3224 if( This->dp2->spData.lpCB->Open )
3226 DPSP_OPENDATA data;
3228 FIXME( "Not all data fields are correct. Need new parameter\n" );
3230 data.bCreate = (dwFlags & DPOPEN_CREATE ) != 0;
3231 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
3232 : NS_GetNSAddr( This->dp2->lpNameServerData );
3233 data.lpISP = This->dp2->spData.lpISP;
3234 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) != 0;
3235 data.dwOpenFlags = dwFlags;
3236 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
3238 hr = (*This->dp2->spData.lpCB->Open)(&data);
3239 if( FAILED( hr ) )
3241 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
3242 return hr;
3247 /* Create the system group of which everything is a part of */
3248 DPID systemGroup = DPID_SYSTEM_GROUP;
3250 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
3251 NULL, 0, 0, TRUE );
3255 if( dwFlags & DPOPEN_JOIN )
3257 DPID dpidServerId = DPID_UNKNOWN;
3259 /* Create the server player for this interface. This way we can receive
3260 * messages for this session.
3262 /* FIXME: I suppose that we should be setting an event for a receive
3263 * type of thing. That way the messaging thread could know to wake
3264 * up. DPlay would then trigger the hEvent for the player the
3265 * message is directed to.
3267 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
3269 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
3272 else if( dwFlags & DPOPEN_CREATE )
3274 DPID dpidNameServerId = DPID_NAME_SERVER;
3276 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
3277 0, DPPLAYER_SERVERPLAYER, bAnsi );
3280 if( FAILED(hr) )
3282 ERR( "Couldn't create name server/system player: %s\n",
3283 DPLAYX_HresultToString(hr) );
3286 return hr;
3289 static HRESULT WINAPI IDirectPlay2AImpl_Open( IDirectPlay2A *iface, DPSESSIONDESC2 *sdesc,
3290 DWORD flags )
3292 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3293 return IDirectPlayX_Open( &This->IDirectPlay4A_iface, sdesc, flags );
3296 static HRESULT WINAPI IDirectPlay2Impl_Open( IDirectPlay2 *iface, DPSESSIONDESC2 *sdesc,
3297 DWORD flags )
3299 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3300 return IDirectPlayX_Open( &This->IDirectPlay4_iface, sdesc, flags );
3303 static HRESULT WINAPI IDirectPlay3AImpl_Open( IDirectPlay3A *iface, DPSESSIONDESC2 *sdesc,
3304 DWORD flags )
3306 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3307 return IDirectPlayX_Open( &This->IDirectPlay4_iface, sdesc, flags );
3310 static HRESULT WINAPI IDirectPlay3Impl_Open( IDirectPlay3 *iface, DPSESSIONDESC2 *sdesc,
3311 DWORD flags )
3313 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3314 return IDirectPlayX_Open( &This->IDirectPlay4_iface, sdesc, flags );
3317 static HRESULT WINAPI IDirectPlay4AImpl_Open( IDirectPlay4A *iface, DPSESSIONDESC2 *sdesc,
3318 DWORD flags )
3320 return IDirectPlayX_SecureOpen( iface, sdesc, flags, NULL, NULL );
3323 static HRESULT WINAPI IDirectPlay4Impl_Open( IDirectPlay4 *iface, DPSESSIONDESC2 *sdesc,
3324 DWORD flags )
3326 return IDirectPlayX_SecureOpen( iface, sdesc, flags, NULL, NULL );
3329 static HRESULT DP_IF_Receive( IDirectPlayImpl *This, DPID *lpidFrom, DPID *lpidTo, DWORD dwFlags,
3330 void *lpData, DWORD *lpdwDataSize, BOOL bAnsi )
3332 LPDPMSG lpMsg = NULL;
3334 FIXME( "(%p)->(%p,%p,0x%08lx,%p,%p,%u): stub\n",
3335 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
3337 if( This->dp2->connectionInitialized == NO_PROVIDER )
3339 return DPERR_UNINITIALIZED;
3342 if( dwFlags == 0 )
3344 dwFlags = DPRECEIVE_ALL;
3347 /* If the lpData is NULL, we must be peeking the message */
3348 if( ( lpData == NULL ) &&
3349 !( dwFlags & DPRECEIVE_PEEK )
3352 return DPERR_INVALIDPARAMS;
3355 if( dwFlags & DPRECEIVE_ALL )
3357 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
3359 if( !( dwFlags & DPRECEIVE_PEEK ) )
3361 FIXME( "Remove from queue\n" );
3364 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
3365 ( dwFlags & DPRECEIVE_FROMPLAYER )
3368 FIXME( "Find matching message 0x%08lx\n", dwFlags );
3370 else
3372 ERR( "Hmmm..dwFlags 0x%08lx\n", dwFlags );
3375 if( lpMsg == NULL )
3377 return DPERR_NOMESSAGES;
3380 /* Copy into the provided buffer */
3381 if (lpData) CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
3383 return DP_OK;
3386 static HRESULT WINAPI IDirectPlay2AImpl_Receive( IDirectPlay2A *iface, DPID *from, DPID *to,
3387 DWORD flags, void *data, DWORD *size )
3389 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3390 return IDirectPlayX_Receive( &This->IDirectPlay4A_iface, from, to, flags, data, size );
3393 static HRESULT WINAPI IDirectPlay2Impl_Receive( IDirectPlay2 *iface, DPID *from, DPID *to,
3394 DWORD flags, void *data, DWORD *size )
3396 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3397 return IDirectPlayX_Receive( &This->IDirectPlay4_iface, from, to, flags, data, size );
3400 static HRESULT WINAPI IDirectPlay3AImpl_Receive( IDirectPlay3A *iface, DPID *from, DPID *to,
3401 DWORD flags, void *data, DWORD *size )
3403 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3404 return IDirectPlayX_Receive( &This->IDirectPlay4_iface, from, to, flags, data, size );
3407 static HRESULT WINAPI IDirectPlay3Impl_Receive( IDirectPlay3 *iface, DPID *from, DPID *to,
3408 DWORD flags, void *data, DWORD *size )
3410 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3411 return IDirectPlayX_Receive( &This->IDirectPlay4_iface, from, to, flags, data, size );
3414 static HRESULT WINAPI IDirectPlay4AImpl_Receive( IDirectPlay4A *iface, DPID *lpidFrom,
3415 DPID *lpidTo, DWORD dwFlags, void *lpData, DWORD *lpdwDataSize )
3417 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3418 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, TRUE );
3421 static HRESULT WINAPI IDirectPlay4Impl_Receive( IDirectPlay4 *iface, DPID *lpidFrom,
3422 DPID *lpidTo, DWORD dwFlags, void *lpData, DWORD *lpdwDataSize )
3424 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3425 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, FALSE );
3428 static HRESULT WINAPI IDirectPlay2AImpl_Send( IDirectPlay2A *iface, DPID from, DPID to,
3429 DWORD flags, void *data, DWORD size )
3431 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3432 return IDirectPlayX_Send( &This->IDirectPlay4A_iface, from, to, flags, data, size );
3435 static HRESULT WINAPI IDirectPlay2Impl_Send( IDirectPlay2 *iface, DPID from, DPID to,
3436 DWORD flags, void *data, DWORD size )
3438 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3439 return IDirectPlayX_Send( &This->IDirectPlay4_iface, from, to, flags, data, size );
3442 static HRESULT WINAPI IDirectPlay3AImpl_Send( IDirectPlay3A *iface, DPID from, DPID to,
3443 DWORD flags, void *data, DWORD size )
3445 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3446 return IDirectPlayX_Send( &This->IDirectPlay4_iface, from, to, flags, data, size );
3449 static HRESULT WINAPI IDirectPlay3Impl_Send( IDirectPlay3 *iface, DPID from, DPID to,
3450 DWORD flags, void *data, DWORD size )
3452 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3453 return IDirectPlayX_Send( &This->IDirectPlay4_iface, from, to, flags, data, size );
3456 static HRESULT WINAPI IDirectPlay4AImpl_Send( IDirectPlay4A *iface, DPID from, DPID to,
3457 DWORD flags, void *data, DWORD size )
3459 return IDirectPlayX_SendEx( iface, from, to, flags, data, size, 0, 0, NULL, NULL );
3462 static HRESULT WINAPI IDirectPlay4Impl_Send( IDirectPlay4 *iface, DPID from, DPID to,
3463 DWORD flags, void *data, DWORD size )
3465 return IDirectPlayX_SendEx( iface, from, to, flags, data, size, 0, 0, NULL, NULL );
3468 static HRESULT WINAPI IDirectPlay2AImpl_SetGroupData( IDirectPlay2A *iface, DPID group, void *data,
3469 DWORD size, DWORD flags )
3471 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3472 return IDirectPlayX_SetGroupData( &This->IDirectPlay4A_iface, group, data, size, flags );
3475 static HRESULT WINAPI IDirectPlay2Impl_SetGroupData( IDirectPlay2 *iface, DPID group, void *data,
3476 DWORD size, DWORD flags )
3478 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3479 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3482 static HRESULT WINAPI IDirectPlay3AImpl_SetGroupData( IDirectPlay3A *iface, DPID group, void *data,
3483 DWORD size, DWORD flags )
3485 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3486 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3489 static HRESULT WINAPI IDirectPlay3Impl_SetGroupData( IDirectPlay3 *iface, DPID group, void *data,
3490 DWORD size, DWORD flags )
3492 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3493 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3496 static HRESULT WINAPI IDirectPlay4AImpl_SetGroupData( IDirectPlay4A *iface, DPID group, void *data,
3497 DWORD size, DWORD flags )
3499 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3500 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3503 static HRESULT WINAPI IDirectPlay4Impl_SetGroupData( IDirectPlay4 *iface, DPID group, void *data,
3504 DWORD size, DWORD flags )
3506 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3507 lpGroupData gdata;
3509 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx)\n", This, group, data, size, flags );
3511 /* Parameter check */
3512 if ( !data && size )
3513 return DPERR_INVALIDPARAMS;
3515 /* Find the pointer to the data for this player */
3516 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
3517 return DPERR_INVALIDOBJECT;
3519 if ( !(flags & DPSET_LOCAL) )
3521 FIXME( "Was this group created by this interface?\n" );
3522 /* FIXME: If this is a remote update need to allow it but not
3523 * send a message.
3527 DP_SetGroupData( gdata, flags, data, size );
3529 /* FIXME: Only send a message if this group is local to the session otherwise
3530 * it will have been rejected above
3532 if ( !(flags & DPSET_LOCAL) )
3533 FIXME( "Send msg?\n" );
3535 return DP_OK;
3538 static HRESULT DP_IF_SetGroupName( IDirectPlayImpl *This, DPID idGroup, DPNAME *lpGroupName,
3539 DWORD dwFlags, BOOL bAnsi )
3541 lpGroupData lpGData;
3543 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n", This, idGroup,
3544 lpGroupName, dwFlags, bAnsi );
3546 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3548 return DPERR_INVALIDGROUP;
3551 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
3553 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3554 FIXME( "Message not sent and dwFlags ignored\n" );
3556 return DP_OK;
3559 static HRESULT WINAPI IDirectPlay2AImpl_SetGroupName( IDirectPlay2A *iface, DPID group,
3560 DPNAME *name, DWORD flags )
3562 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3563 return IDirectPlayX_SetGroupName( &This->IDirectPlay4A_iface, group, name, flags );
3566 static HRESULT WINAPI IDirectPlay2Impl_SetGroupName( IDirectPlay2 *iface, DPID group,
3567 DPNAME *name, DWORD flags )
3569 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3570 return IDirectPlayX_SetGroupName( &This->IDirectPlay4_iface, group, name, flags );
3573 static HRESULT WINAPI IDirectPlay3AImpl_SetGroupName( IDirectPlay3A *iface, DPID group,
3574 DPNAME *name, DWORD flags )
3576 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3577 return IDirectPlayX_SetGroupName( &This->IDirectPlay4_iface, group, name, flags );
3580 static HRESULT WINAPI IDirectPlay3Impl_SetGroupName( IDirectPlay3 *iface, DPID group,
3581 DPNAME *name, DWORD flags )
3583 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3584 return IDirectPlayX_SetGroupName( &This->IDirectPlay4_iface, group, name, flags );
3587 static HRESULT WINAPI IDirectPlay4AImpl_SetGroupName( IDirectPlay4A *iface, DPID idGroup,
3588 DPNAME *lpGroupName, DWORD dwFlags )
3590 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3591 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
3594 static HRESULT WINAPI IDirectPlay4Impl_SetGroupName( IDirectPlay4 *iface, DPID idGroup,
3595 DPNAME *lpGroupName, DWORD dwFlags )
3597 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3598 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
3601 static HRESULT WINAPI IDirectPlay2AImpl_SetPlayerData( IDirectPlay2A *iface, DPID player,
3602 void *data, DWORD size, DWORD flags )
3604 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3605 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4A_iface, player, data, size, flags );
3608 static HRESULT WINAPI IDirectPlay2Impl_SetPlayerData( IDirectPlay2 *iface, DPID player,
3609 void *data, DWORD size, DWORD flags )
3611 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3612 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
3615 static HRESULT WINAPI IDirectPlay3AImpl_SetPlayerData( IDirectPlay3A *iface, DPID player,
3616 void *data, DWORD size, DWORD flags )
3618 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3619 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
3622 static HRESULT WINAPI IDirectPlay3Impl_SetPlayerData( IDirectPlay3 *iface, DPID player,
3623 void *data, DWORD size, DWORD flags )
3625 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3626 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
3629 static HRESULT WINAPI IDirectPlay4AImpl_SetPlayerData( IDirectPlay4A *iface, DPID player,
3630 void *data, DWORD size, DWORD flags )
3632 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3633 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
3636 static HRESULT WINAPI IDirectPlay4Impl_SetPlayerData( IDirectPlay4 *iface, DPID player,
3637 void *data, DWORD size, DWORD flags )
3639 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3640 lpPlayerList plist;
3642 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx)\n", This, player, data, size, flags );
3644 if ( This->dp2->connectionInitialized == NO_PROVIDER )
3645 return DPERR_UNINITIALIZED;
3647 /* Parameter check */
3648 if ( !data && size )
3649 return DPERR_INVALIDPARAMS;
3651 /* Find the pointer to the data for this player */
3652 if ( (plist = DP_FindPlayer( This, player )) == NULL )
3653 return DPERR_INVALIDPLAYER;
3655 if ( !(flags & DPSET_LOCAL) )
3657 FIXME( "Was this group created by this interface?\n" );
3658 /* FIXME: If this is a remote update need to allow it but not
3659 * send a message.
3663 DP_SetPlayerData( plist->lpPData, flags, data, size );
3665 if ( !(flags & DPSET_LOCAL) )
3666 FIXME( "Send msg?\n" );
3668 return DP_OK;
3671 static HRESULT DP_IF_SetPlayerName( IDirectPlayImpl *This, DPID idPlayer, DPNAME *lpPlayerName,
3672 DWORD dwFlags, BOOL bAnsi )
3674 lpPlayerList lpPList;
3676 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n",
3677 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3679 if( This->dp2->connectionInitialized == NO_PROVIDER )
3681 return DPERR_UNINITIALIZED;
3684 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3686 return DPERR_INVALIDGROUP;
3689 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3691 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3692 FIXME( "Message not sent and dwFlags ignored\n" );
3694 return DP_OK;
3697 static HRESULT WINAPI IDirectPlay2AImpl_SetPlayerName( IDirectPlay2A *iface, DPID player,
3698 DPNAME *name, DWORD flags )
3700 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3701 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4A_iface, player, name, flags );
3704 static HRESULT WINAPI IDirectPlay2Impl_SetPlayerName( IDirectPlay2 *iface, DPID player,
3705 DPNAME *name, DWORD flags )
3707 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3708 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4_iface, player, name, flags );
3711 static HRESULT WINAPI IDirectPlay3AImpl_SetPlayerName( IDirectPlay3A *iface, DPID player,
3712 DPNAME *name, DWORD flags )
3714 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3715 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4_iface, player, name, flags );
3718 static HRESULT WINAPI IDirectPlay3Impl_SetPlayerName( IDirectPlay3 *iface, DPID player,
3719 DPNAME *name, DWORD flags )
3721 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3722 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4_iface, player, name, flags );
3725 static HRESULT WINAPI IDirectPlay4AImpl_SetPlayerName( IDirectPlay4A *iface, DPID idPlayer,
3726 DPNAME *lpPlayerName, DWORD dwFlags )
3728 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3729 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3732 static HRESULT WINAPI IDirectPlay4Impl_SetPlayerName( IDirectPlay4 *iface, DPID idPlayer,
3733 DPNAME *lpPlayerName, DWORD dwFlags )
3735 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3736 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3739 static HRESULT DP_SetSessionDesc( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpSessDesc,
3740 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3742 DWORD dwRequiredSize;
3743 LPDPSESSIONDESC2 lpTempSessDesc;
3745 TRACE( "(%p)->(%p,0x%08lx,%u,%u)\n",
3746 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3748 if( This->dp2->connectionInitialized == NO_PROVIDER )
3750 return DPERR_UNINITIALIZED;
3753 if( dwFlags )
3755 return DPERR_INVALIDPARAMS;
3758 /* Only the host is allowed to update the session desc */
3759 if( !This->dp2->bHostInterface )
3761 return DPERR_ACCESSDENIED;
3764 /* FIXME: Copy into This->dp2->lpSessionDesc */
3765 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3766 lpTempSessDesc = calloc( 1, dwRequiredSize );
3768 if( lpTempSessDesc == NULL )
3770 return DPERR_OUTOFMEMORY;
3773 /* Free the old */
3774 free( This->dp2->lpSessionDesc );
3776 This->dp2->lpSessionDesc = lpTempSessDesc;
3777 /* Set the new */
3778 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3779 if( bInitial )
3781 /*Initializing session GUID*/
3782 CoCreateGuid( &(This->dp2->lpSessionDesc->guidInstance) );
3784 /* If this is an external invocation of the interface, we should be
3785 * letting everyone know that things have changed. Otherwise this is
3786 * just an initialization and it doesn't need to be propagated.
3788 if( !bInitial )
3790 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3793 return DP_OK;
3796 static HRESULT WINAPI IDirectPlay2AImpl_SetSessionDesc( IDirectPlay2A *iface, DPSESSIONDESC2 *sdesc,
3797 DWORD flags )
3799 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3800 return IDirectPlayX_SetSessionDesc( &This->IDirectPlay4A_iface, sdesc, flags );
3803 static HRESULT WINAPI IDirectPlay2Impl_SetSessionDesc( IDirectPlay2 *iface, DPSESSIONDESC2 *sdesc,
3804 DWORD flags )
3806 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3807 return IDirectPlayX_SetSessionDesc( &This->IDirectPlay4_iface, sdesc, flags );
3810 static HRESULT WINAPI IDirectPlay3AImpl_SetSessionDesc( IDirectPlay3A *iface, DPSESSIONDESC2 *sdesc,
3811 DWORD flags )
3813 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3814 return IDirectPlayX_SetSessionDesc( &This->IDirectPlay4_iface, sdesc, flags );
3817 static HRESULT WINAPI IDirectPlay3Impl_SetSessionDesc( IDirectPlay3 *iface, DPSESSIONDESC2 *sdesc,
3818 DWORD flags )
3820 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3821 return IDirectPlayX_SetSessionDesc( &This->IDirectPlay4_iface, sdesc, flags );
3824 static HRESULT WINAPI IDirectPlay4AImpl_SetSessionDesc( IDirectPlay4A *iface,
3825 DPSESSIONDESC2 *lpSessDesc, DWORD dwFlags )
3827 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3828 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3831 static HRESULT WINAPI IDirectPlay4Impl_SetSessionDesc( IDirectPlay4 *iface,
3832 DPSESSIONDESC2 *lpSessDesc, DWORD dwFlags )
3834 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3835 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3838 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3839 static DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3841 DWORD dwSize = 0;
3843 if( lpSessDesc == NULL )
3845 /* Hmmm..don't need any size? */
3846 ERR( "NULL lpSessDesc\n" );
3847 return dwSize;
3850 dwSize += sizeof( *lpSessDesc );
3852 if( bAnsi )
3854 if( lpSessDesc->lpszSessionNameA )
3856 dwSize += lstrlenA( lpSessDesc->lpszSessionNameA ) + 1;
3859 if( lpSessDesc->lpszPasswordA )
3861 dwSize += lstrlenA( lpSessDesc->lpszPasswordA ) + 1;
3864 else /* UNICODE */
3866 if( lpSessDesc->lpszSessionName )
3868 dwSize += sizeof( WCHAR ) *
3869 ( lstrlenW( lpSessDesc->lpszSessionName ) + 1 );
3872 if( lpSessDesc->lpszPassword )
3874 dwSize += sizeof( WCHAR ) *
3875 ( lstrlenW( lpSessDesc->lpszPassword ) + 1 );
3879 return dwSize;
3882 /* Assumes that contiguous buffers are already allocated. */
3883 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3884 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3886 BYTE* lpStartOfFreeSpace;
3888 if( lpSessionDest == NULL )
3890 ERR( "NULL lpSessionDest\n" );
3891 return;
3894 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3896 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3898 if( bAnsi )
3900 if( lpSessionSrc->lpszSessionNameA )
3902 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3903 lpSessionDest->lpszSessionNameA );
3904 lpSessionDest->lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3905 lpStartOfFreeSpace +=
3906 lstrlenA( lpSessionDest->lpszSessionNameA ) + 1;
3909 if( lpSessionSrc->lpszPasswordA )
3911 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3912 lpSessionDest->lpszPasswordA );
3913 lpSessionDest->lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3916 else /* UNICODE */
3918 if( lpSessionSrc->lpszSessionName )
3920 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3921 lpSessionDest->lpszSessionName );
3922 lpSessionDest->lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3923 lpStartOfFreeSpace += sizeof(WCHAR) *
3924 ( lstrlenW( lpSessionDest->lpszSessionName ) + 1 );
3927 if( lpSessionSrc->lpszPassword )
3929 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3930 lpSessionDest->lpszPassword );
3931 lpSessionDest->lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3936 static HRESULT WINAPI IDirectPlay3AImpl_AddGroupToGroup( IDirectPlay3A *iface, DPID parent,
3937 DPID group )
3939 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3940 return IDirectPlayX_AddGroupToGroup( &This->IDirectPlay4A_iface, parent, group );
3943 static HRESULT WINAPI IDirectPlay3Impl_AddGroupToGroup( IDirectPlay3 *iface, DPID parent,
3944 DPID group )
3946 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3947 return IDirectPlayX_AddGroupToGroup( &This->IDirectPlay4_iface, parent, group );
3950 static HRESULT WINAPI IDirectPlay4AImpl_AddGroupToGroup( IDirectPlay4A *iface, DPID parent,
3951 DPID group )
3953 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3954 return IDirectPlayX_AddGroupToGroup( &This->IDirectPlay4_iface, parent, group );
3957 static HRESULT WINAPI IDirectPlay4Impl_AddGroupToGroup( IDirectPlay4 *iface, DPID parent,
3958 DPID group )
3960 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3961 lpGroupData gdata;
3962 lpGroupList glist;
3964 TRACE( "(%p)->(0x%08lx,0x%08lx)\n", This, parent, group );
3966 if ( This->dp2->connectionInitialized == NO_PROVIDER )
3967 return DPERR_UNINITIALIZED;
3969 if ( !DP_FindAnyGroup(This, parent ) )
3970 return DPERR_INVALIDGROUP;
3972 if ( ( gdata = DP_FindAnyGroup(This, group ) ) == NULL )
3973 return DPERR_INVALIDGROUP;
3975 /* Create a player list (ie "shortcut" ) */
3976 glist = calloc( 1, sizeof( *glist ) );
3977 if ( !glist )
3978 return DPERR_CANTADDPLAYER;
3980 /* Add the shortcut */
3981 gdata->uRef++;
3982 glist->lpGData = gdata;
3984 /* Add the player to the list of players for this group */
3985 DPQ_INSERT( gdata->groups, glist, groups );
3987 /* Send a ADDGROUPTOGROUP message */
3988 FIXME( "Not sending message\n" );
3990 return DP_OK;
3993 static HRESULT DP_IF_CreateGroupInGroup( IDirectPlayImpl *This, void *lpMsgHdr, DPID idParentGroup,
3994 DPID *lpidGroup, DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags,
3995 BOOL bAnsi )
3997 lpGroupData lpGParentData;
3998 lpGroupList lpGList;
3999 lpGroupData lpGData;
4001 TRACE( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
4002 This, idParentGroup, lpidGroup, lpGroupName, lpData,
4003 dwDataSize, dwFlags, bAnsi );
4005 if( This->dp2->connectionInitialized == NO_PROVIDER )
4007 return DPERR_UNINITIALIZED;
4010 /* Verify that the specified parent is valid */
4011 if( ( lpGParentData = DP_FindAnyGroup(This, idParentGroup ) ) == NULL )
4012 return DPERR_INVALIDGROUP;
4014 lpGData = DP_CreateGroup(This, lpidGroup, lpGroupName, dwFlags, idParentGroup, bAnsi );
4016 if( lpGData == NULL )
4018 return DPERR_CANTADDPLAYER; /* yes player not group */
4021 /* Something else is referencing this data */
4022 lpGData->uRef++;
4024 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
4026 /* The list has now been inserted into the interface group list. We now
4027 need to put a "shortcut" to this group in the parent group */
4028 lpGList = calloc( 1, sizeof( *lpGList ) );
4029 if( lpGList == NULL )
4031 FIXME( "Memory leak\n" );
4032 return DPERR_CANTADDPLAYER; /* yes player not group */
4035 lpGList->lpGData = lpGData;
4037 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
4039 /* Let the SP know that we've created this group */
4040 if( This->dp2->spData.lpCB->CreateGroup )
4042 DPSP_CREATEGROUPDATA data;
4044 TRACE( "Calling SP CreateGroup\n" );
4046 data.idGroup = *lpidGroup;
4047 data.dwFlags = dwFlags;
4048 data.lpSPMessageHeader = lpMsgHdr;
4049 data.lpISP = This->dp2->spData.lpISP;
4051 (*This->dp2->spData.lpCB->CreateGroup)( &data );
4054 /* Inform all other peers of the creation of a new group. If there are
4055 * no peers keep this quiet.
4057 if( This->dp2->lpSessionDesc &&
4058 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
4060 DPMSG_CREATEPLAYERORGROUP msg;
4062 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
4063 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
4064 msg.dpId = *lpidGroup;
4065 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
4066 msg.lpData = lpData;
4067 msg.dwDataSize = dwDataSize;
4068 msg.dpnName = *lpGroupName;
4070 /* FIXME: Correct to just use send effectively? */
4071 /* FIXME: Should size include data w/ message or just message "header" */
4072 /* FIXME: Check return code */
4073 IDirectPlayX_SendEx( &This->IDirectPlay4_iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
4074 sizeof( msg ), 0, 0, NULL, NULL );
4077 return DP_OK;
4080 static HRESULT WINAPI IDirectPlay3AImpl_CreateGroupInGroup( IDirectPlay3A *iface, DPID parent,
4081 DPID *group, DPNAME *name, void *data, DWORD size, DWORD flags )
4083 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4084 return IDirectPlayX_CreateGroupInGroup( &This->IDirectPlay4A_iface, parent, group, name,
4085 data, size, flags );
4088 static HRESULT WINAPI IDirectPlay3Impl_CreateGroupInGroup( IDirectPlay3 *iface, DPID parent,
4089 DPID *group, DPNAME *name, void *data, DWORD size, DWORD flags )
4091 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4092 return IDirectPlayX_CreateGroupInGroup( &This->IDirectPlay4_iface, parent, group, name,
4093 data, size, flags );
4096 static HRESULT WINAPI IDirectPlay4AImpl_CreateGroupInGroup( IDirectPlay4A *iface,
4097 DPID idParentGroup, DPID *lpidGroup, DPNAME *lpGroupName, void *lpData, DWORD dwDataSize,
4098 DWORD dwFlags )
4100 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4102 *lpidGroup = DPID_UNKNOWN;
4104 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup, lpGroupName, lpData,
4105 dwDataSize, dwFlags, TRUE );
4108 static HRESULT WINAPI IDirectPlay4Impl_CreateGroupInGroup( IDirectPlay4 *iface, DPID idParentGroup,
4109 DPID *lpidGroup, DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags )
4111 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4113 *lpidGroup = DPID_UNKNOWN;
4115 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup, lpGroupName, lpData,
4116 dwDataSize, dwFlags, FALSE );
4119 static HRESULT WINAPI IDirectPlay3AImpl_DeleteGroupFromGroup( IDirectPlay3A *iface, DPID parent,
4120 DPID group )
4122 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4123 return IDirectPlayX_DeleteGroupFromGroup( &This->IDirectPlay4A_iface, parent, group );
4126 static HRESULT WINAPI IDirectPlay3Impl_DeleteGroupFromGroup( IDirectPlay3 *iface, DPID parent,
4127 DPID group )
4129 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4130 return IDirectPlayX_DeleteGroupFromGroup( &This->IDirectPlay4_iface, parent, group );
4133 static HRESULT WINAPI IDirectPlay4AImpl_DeleteGroupFromGroup( IDirectPlay4A *iface, DPID parent,
4134 DPID group )
4136 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4137 return IDirectPlayX_DeleteGroupFromGroup( &This->IDirectPlay4_iface, parent, group );
4140 static HRESULT WINAPI IDirectPlay4Impl_DeleteGroupFromGroup( IDirectPlay4 *iface, DPID parent,
4141 DPID group )
4143 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4144 lpGroupList glist;
4145 lpGroupData parentdata;
4147 TRACE("(%p)->(0x%08lx,0x%08lx)\n", This, parent, group );
4149 /* Is the parent group valid? */
4150 if ( ( parentdata = DP_FindAnyGroup(This, parent ) ) == NULL )
4151 return DPERR_INVALIDGROUP;
4153 /* Remove the group from the parent group queue */
4154 DPQ_REMOVE_ENTRY( parentdata->groups, groups, lpGData->dpid, ==, group, glist );
4156 if ( glist == NULL )
4157 return DPERR_INVALIDGROUP;
4159 /* Decrement the ref count */
4160 glist->lpGData->uRef--;
4162 /* Free up the list item */
4163 free( glist );
4165 /* Should send a DELETEGROUPFROMGROUP message */
4166 FIXME( "message not sent\n" );
4168 return DP_OK;
4171 static BOOL DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
4172 LPDWORD lpdwBufSize )
4174 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
4175 HRESULT hr;
4177 dpCompoundAddress.dwDataSize = sizeof( GUID );
4178 dpCompoundAddress.guidDataType = DPAID_ServiceProvider;
4179 dpCompoundAddress.lpData = lpcSpGuid;
4181 *lplpAddrBuf = NULL;
4182 *lpdwBufSize = 0;
4184 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
4185 lpdwBufSize, TRUE );
4187 if( hr != DPERR_BUFFERTOOSMALL )
4189 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
4190 return FALSE;
4193 /* Now allocate the buffer */
4194 *lplpAddrBuf = calloc( 1, *lpdwBufSize );
4196 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
4197 lpdwBufSize, TRUE );
4198 if( FAILED(hr) )
4200 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
4201 return FALSE;
4204 return TRUE;
4207 static HRESULT WINAPI IDirectPlay3AImpl_EnumConnections( IDirectPlay3A *iface,
4208 const GUID *application, LPDPENUMCONNECTIONSCALLBACK enumcb, void *context, DWORD flags )
4210 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4211 return IDirectPlayX_EnumConnections( &This->IDirectPlay4A_iface, application, enumcb, context,
4212 flags );
4215 static HRESULT WINAPI IDirectPlay3Impl_EnumConnections( IDirectPlay3 *iface,
4216 const GUID *application, LPDPENUMCONNECTIONSCALLBACK enumcb, void *context, DWORD flags )
4218 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4219 return IDirectPlayX_EnumConnections( &This->IDirectPlay4_iface, application, enumcb, context,
4220 flags );
4223 static HRESULT WINAPI IDirectPlay4AImpl_EnumConnections( IDirectPlay4A *iface,
4224 const GUID *lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, void *lpContext,
4225 DWORD dwFlags )
4227 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4228 TRACE("(%p)->(%p,%p,%p,0x%08lx)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
4230 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
4231 if( dwFlags == 0 )
4233 dwFlags = DPCONNECTION_DIRECTPLAY;
4236 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
4237 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) )
4240 return DPERR_INVALIDFLAGS;
4243 if( !lpEnumCallback )
4245 return DPERR_INVALIDPARAMS;
4248 /* Enumerate DirectPlay service providers */
4249 if( dwFlags & DPCONNECTION_DIRECTPLAY )
4251 HKEY hkResult;
4252 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4253 LPCSTR guidDataSubKey = "Guid";
4254 char subKeyName[51];
4255 DWORD dwIndex, sizeOfSubKeyName=50;
4256 FILETIME filetime;
4258 /* Need to loop over the service providers in the registry */
4259 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4260 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4262 /* Hmmm. Does this mean that there are no service providers? */
4263 ERR(": no service providers?\n");
4264 return DP_OK;
4268 /* Traverse all the service providers we have available */
4269 for( dwIndex=0;
4270 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4271 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4272 ++dwIndex, sizeOfSubKeyName=51 )
4275 HKEY hkServiceProvider;
4276 GUID serviceProviderGUID;
4277 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
4278 char returnBuffer[51];
4279 WCHAR buff[51];
4280 DPNAME dpName;
4281 BOOL bBuildPass;
4283 LPVOID lpAddressBuffer = NULL;
4284 DWORD dwAddressBufferSize = 0;
4286 TRACE(" this time through: %s\n", subKeyName );
4288 /* Get a handle for this particular service provider */
4289 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4290 &hkServiceProvider ) != ERROR_SUCCESS )
4292 ERR(": what the heck is going on?\n" );
4293 continue;
4296 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4297 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
4298 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4300 ERR(": missing GUID registry data members\n" );
4301 RegCloseKey(hkServiceProvider);
4302 continue;
4304 RegCloseKey(hkServiceProvider);
4306 /* FIXME: Check return types to ensure we're interpreting data right */
4307 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, ARRAY_SIZE( buff ));
4308 CLSIDFromString( buff, &serviceProviderGUID );
4309 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4311 /* Fill in the DPNAME struct for the service provider */
4312 dpName.dwSize = sizeof( dpName );
4313 dpName.dwFlags = 0;
4314 dpName.lpszShortNameA = subKeyName;
4315 dpName.lpszLongNameA = NULL;
4317 /* Create the compound address for the service provider.
4318 * NOTE: This is a gruesome architectural scar right now. DP
4319 * uses DPL and DPL uses DP. Nasty stuff. This may be why the
4320 * native dll just gets around this little bit by allocating an
4321 * 80 byte buffer which isn't even filled with a valid compound
4322 * address. Oh well. Creating a proper compound address is the
4323 * way to go anyways despite this method taking slightly more
4324 * heap space and realtime :) */
4326 bBuildPass = DP_BuildSPCompoundAddr( &serviceProviderGUID,
4327 &lpAddressBuffer,
4328 &dwAddressBufferSize );
4329 if( !bBuildPass )
4331 ERR( "Can't build compound addr\n" );
4332 return DPERR_GENERIC;
4335 /* The enumeration will return FALSE if we are not to continue */
4336 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
4337 &dpName, dwFlags, lpContext ) )
4339 free( lpAddressBuffer );
4340 return DP_OK;
4342 free( lpAddressBuffer );
4346 /* Enumerate DirectPlayLobby service providers */
4347 if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY )
4349 HKEY hkResult;
4350 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
4351 LPCSTR guidDataSubKey = "Guid";
4352 char subKeyName[51];
4353 DWORD dwIndex, sizeOfSubKeyName=50;
4354 FILETIME filetime;
4356 /* Need to loop over the service providers in the registry */
4357 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4358 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4360 TRACE("No Lobby Providers have been registered.\n");
4361 return DP_OK;
4365 /* Traverse all the lobby providers we have available */
4366 for( dwIndex=0;
4367 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4368 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4369 ++dwIndex, sizeOfSubKeyName=51 )
4372 HKEY hkServiceProvider;
4373 GUID serviceProviderGUID;
4374 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
4375 char returnBuffer[51];
4376 WCHAR buff[51];
4377 DPNAME dpName;
4378 HRESULT hr;
4380 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
4381 LPVOID lpAddressBuffer = NULL;
4382 DWORD dwAddressBufferSize = 0;
4384 TRACE(" this time through: %s\n", subKeyName );
4386 /* Get a handle for this particular service provider */
4387 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4388 &hkServiceProvider ) != ERROR_SUCCESS )
4390 ERR(": what the heck is going on?\n" );
4391 continue;
4394 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4395 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
4396 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4398 ERR(": missing GUID registry data members\n" );
4399 RegCloseKey(hkServiceProvider);
4400 continue;
4402 RegCloseKey(hkServiceProvider);
4404 /* FIXME: Check return types to ensure we're interpreting data right */
4405 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, ARRAY_SIZE( buff ));
4406 CLSIDFromString( buff, &serviceProviderGUID );
4407 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4409 /* Fill in the DPNAME struct for the service provider */
4410 dpName.dwSize = sizeof( dpName );
4411 dpName.dwFlags = 0;
4412 dpName.lpszShortNameA = subKeyName;
4413 dpName.lpszLongNameA = NULL;
4415 /* Create the compound address for the service provider.
4416 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
4417 nast stuff. This may be why the native dll just gets around this little bit by
4418 allocating an 80 byte buffer which isn't even a filled with a valid compound
4419 address. Oh well. Creating a proper compound address is the way to go anyways
4420 despite this method taking slightly more heap space and realtime :) */
4422 dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
4423 dpCompoundAddress.dwDataSize = sizeof( GUID );
4424 dpCompoundAddress.lpData = &serviceProviderGUID;
4426 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
4427 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
4429 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
4430 return hr;
4433 /* Now allocate the buffer */
4434 lpAddressBuffer = calloc( 1, dwAddressBufferSize );
4436 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
4437 &dwAddressBufferSize, TRUE ) ) != DP_OK )
4439 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
4440 free( lpAddressBuffer );
4441 return hr;
4444 /* The enumeration will return FALSE if we are not to continue */
4445 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
4446 &dpName, dwFlags, lpContext ) )
4448 free( lpAddressBuffer );
4449 return DP_OK;
4451 free( lpAddressBuffer );
4455 return DP_OK;
4458 static HRESULT WINAPI IDirectPlay4Impl_EnumConnections( IDirectPlay4 *iface,
4459 const GUID *application, LPDPENUMCONNECTIONSCALLBACK enumcb, void *context, DWORD flags )
4461 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4462 return IDirectPlayX_EnumConnections( &This->IDirectPlay4A_iface, application, enumcb, context,
4463 flags );
4466 static HRESULT WINAPI IDirectPlay3AImpl_EnumGroupsInGroup( IDirectPlay3A *iface, DPID group,
4467 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
4469 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4470 return IDirectPlayX_EnumGroupsInGroup( &This->IDirectPlay4A_iface, group, instance,
4471 enumplayercb, context, flags );
4474 static HRESULT WINAPI IDirectPlay3Impl_EnumGroupsInGroup( IDirectPlay3 *iface, DPID group,
4475 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
4477 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4478 return IDirectPlayX_EnumGroupsInGroup( &This->IDirectPlay4_iface, group, instance,
4479 enumplayercb, context, flags );
4482 static HRESULT WINAPI IDirectPlay4AImpl_EnumGroupsInGroup( IDirectPlay4A *iface, DPID group,
4483 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
4485 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4486 return IDirectPlayX_EnumGroupsInGroup( &This->IDirectPlay4_iface, group, instance,
4487 enumplayercb, context, flags );
4490 static HRESULT WINAPI IDirectPlay4Impl_EnumGroupsInGroup( IDirectPlay4 *iface, DPID group,
4491 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
4493 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4494 lpGroupList glist;
4495 lpGroupData gdata;
4497 FIXME( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx): semi stub\n", This, group, instance, enumplayercb,
4498 context, flags );
4500 if ( This->dp2->connectionInitialized == NO_PROVIDER )
4501 return DPERR_UNINITIALIZED;
4503 if ( ( gdata = DP_FindAnyGroup(This, group ) ) == NULL )
4504 return DPERR_INVALIDGROUP;
4506 if ( DPQ_IS_EMPTY( gdata->groups ) )
4507 return DP_OK;
4510 for( glist = DPQ_FIRST( gdata->groups ); ; glist = DPQ_NEXT( glist->groups ) )
4512 /* FIXME: Should check flags for match here */
4513 if ( !(*enumplayercb)( glist->lpGData->dpid, DPPLAYERTYPE_GROUP, &glist->lpGData->name,
4514 flags, context ) )
4515 return DP_OK; /* User requested break */
4517 if ( DPQ_IS_ENDOFLIST( glist->groups ) )
4518 break;
4521 return DP_OK;
4524 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupConnectionSettings( IDirectPlay3A *iface,
4525 DWORD flags, DPID group, void *data, DWORD *size )
4527 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4528 return IDirectPlayX_GetGroupConnectionSettings( &This->IDirectPlay4A_iface, flags, group,
4529 data, size );
4532 static HRESULT WINAPI IDirectPlay3Impl_GetGroupConnectionSettings( IDirectPlay3 *iface,
4533 DWORD flags, DPID group, void *data, DWORD *size )
4535 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4536 return IDirectPlayX_GetGroupConnectionSettings( &This->IDirectPlay4_iface, flags, group,
4537 data, size );
4540 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupConnectionSettings( IDirectPlay4A *iface,
4541 DWORD flags, DPID group, void *data, DWORD *size )
4543 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4544 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, flags, group, data, size );
4545 return DP_OK;
4548 static HRESULT WINAPI IDirectPlay4Impl_GetGroupConnectionSettings( IDirectPlay4 *iface, DWORD flags,
4549 DPID group, void *data, DWORD *size )
4551 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4552 FIXME( "(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, flags, group, data, size );
4553 return DP_OK;
4556 static BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
4557 REFGUID guidDataType,
4558 DWORD dwDataSize,
4559 LPCVOID lpData,
4560 LPVOID lpContext )
4562 /* Looking for the GUID of the provider to load */
4563 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
4564 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
4567 TRACE( "Found SP/LP (%s) %s (data size = 0x%08lx)\n",
4568 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
4570 if( dwDataSize != sizeof( GUID ) )
4572 ERR( "Invalid sp/lp guid size 0x%08lx\n", dwDataSize );
4575 memcpy( lpContext, lpData, dwDataSize );
4577 /* There shouldn't be more than 1 GUID/compound address */
4578 return FALSE;
4581 /* Still waiting for what we want */
4582 return TRUE;
4586 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
4587 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
4589 UINT i;
4590 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4591 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
4592 LPCSTR guidDataSubKey = "Guid";
4593 LPCSTR majVerDataSubKey = "dwReserved1";
4594 LPCSTR minVerDataSubKey = "dwReserved2";
4595 LPCSTR pathSubKey = "Path";
4597 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
4599 /* FIXME: Cloned code with a quick hack. */
4600 for( i=0; i<2; i++ )
4602 HKEY hkResult;
4603 LPCSTR searchSubKey;
4604 char subKeyName[51];
4605 DWORD dwIndex, sizeOfSubKeyName=50;
4606 FILETIME filetime;
4608 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
4609 *lpbIsDpSp = (i == 0);
4612 /* Need to loop over the service providers in the registry */
4613 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4614 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4616 /* Hmmm. Does this mean that there are no service providers? */
4617 ERR(": no service providers?\n");
4618 return 0;
4621 /* Traverse all the service providers we have available */
4622 for( dwIndex=0;
4623 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4624 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4625 ++dwIndex, sizeOfSubKeyName=51 )
4628 HKEY hkServiceProvider;
4629 GUID serviceProviderGUID;
4630 DWORD returnType, sizeOfReturnBuffer = 255;
4631 char returnBuffer[256];
4632 WCHAR buff[51];
4633 DWORD dwTemp, len;
4635 TRACE(" this time through: %s\n", subKeyName );
4637 /* Get a handle for this particular service provider */
4638 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4639 &hkServiceProvider ) != ERROR_SUCCESS )
4641 ERR(": what the heck is going on?\n" );
4642 continue;
4645 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4646 NULL, &returnType, (LPBYTE)returnBuffer,
4647 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4649 ERR(": missing GUID registry data members\n" );
4650 continue;
4653 /* FIXME: Check return types to ensure we're interpreting data right */
4654 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, ARRAY_SIZE( buff ));
4655 CLSIDFromString( buff, &serviceProviderGUID );
4656 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4658 /* Determine if this is the Service Provider that the user asked for */
4659 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
4661 continue;
4664 if( i == 0 ) /* DP SP */
4666 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
4667 lpSpData->lpszName = malloc( len * sizeof(WCHAR) );
4668 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
4671 sizeOfReturnBuffer = 255;
4673 /* Get dwReserved1 */
4674 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
4675 NULL, &returnType, (LPBYTE)returnBuffer,
4676 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4678 ERR(": missing dwReserved1 registry data members\n") ;
4679 continue;
4682 if( i == 0 )
4683 memcpy( &lpSpData->dwReserved1, returnBuffer, sizeof(lpSpData->dwReserved1) );
4685 sizeOfReturnBuffer = 255;
4687 /* Get dwReserved2 */
4688 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4689 NULL, &returnType, (LPBYTE)returnBuffer,
4690 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4692 ERR(": missing dwReserved1 registry data members\n") ;
4693 continue;
4696 if( i == 0 )
4697 memcpy( &lpSpData->dwReserved2, returnBuffer, sizeof(lpSpData->dwReserved2) );
4699 sizeOfReturnBuffer = 255;
4701 /* Get the path for this service provider */
4702 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
4703 NULL, NULL, (LPBYTE)returnBuffer,
4704 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
4706 ERR(": missing PATH registry data members: 0x%08lx\n", dwTemp );
4707 continue;
4710 TRACE( "Loading %s\n", returnBuffer );
4711 return LoadLibraryA( returnBuffer );
4715 return 0;
4718 static HRESULT DP_InitializeDPSP( IDirectPlayImpl *This, HMODULE hServiceProvider )
4720 HRESULT hr;
4721 LPDPSP_SPINIT SPInit;
4723 /* Initialize the service provider by calling SPInit */
4724 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4726 if( SPInit == NULL )
4728 ERR( "Service provider doesn't provide SPInit interface?\n" );
4729 FreeLibrary( hServiceProvider );
4730 return DPERR_UNAVAILABLE;
4733 TRACE( "Calling SPInit (DP SP entry point)\n" );
4735 hr = (*SPInit)( &This->dp2->spData );
4737 if( FAILED(hr) )
4739 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4740 FreeLibrary( hServiceProvider );
4741 return hr;
4744 /* FIXME: Need to verify the sanity of the returned callback table
4745 * using IsBadCodePtr */
4746 This->dp2->bSPInitialized = TRUE;
4748 /* This interface is now initialized as a DP object */
4749 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
4751 /* Store the handle of the module so that we can unload it later */
4752 This->dp2->hServiceProvider = hServiceProvider;
4754 return hr;
4757 static HRESULT DP_InitializeDPLSP( IDirectPlayImpl *This, HMODULE hLobbyProvider )
4759 HRESULT hr;
4760 LPSP_INIT DPLSPInit;
4762 /* Initialize the service provider by calling SPInit */
4763 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
4765 if( DPLSPInit == NULL )
4767 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4768 FreeLibrary( hLobbyProvider );
4769 return DPERR_UNAVAILABLE;
4772 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4774 hr = (*DPLSPInit)( &This->dp2->dplspData );
4776 if( FAILED(hr) )
4778 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4779 FreeLibrary( hLobbyProvider );
4780 return hr;
4783 /* FIXME: Need to verify the sanity of the returned callback table
4784 * using IsBadCodePtr */
4786 This->dp2->bDPLSPInitialized = TRUE;
4788 /* This interface is now initialized as a lobby object */
4789 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
4791 /* Store the handle of the module so that we can unload it later */
4792 This->dp2->hDPLobbyProvider = hLobbyProvider;
4794 return hr;
4797 static HRESULT WINAPI IDirectPlay3AImpl_InitializeConnection( IDirectPlay3A *iface,
4798 void *connection, DWORD flags )
4800 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4801 return IDirectPlayX_InitializeConnection( &This->IDirectPlay4A_iface, connection, flags );
4804 static HRESULT WINAPI IDirectPlay3Impl_InitializeConnection( IDirectPlay3 *iface,
4805 void *connection, DWORD flags )
4807 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4808 return IDirectPlayX_InitializeConnection( &This->IDirectPlay4_iface, connection, flags );
4811 static HRESULT WINAPI IDirectPlay4AImpl_InitializeConnection( IDirectPlay4A *iface,
4812 void *connection, DWORD flags )
4814 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4815 return IDirectPlayX_InitializeConnection( &This->IDirectPlay4_iface, connection, flags );
4818 static HRESULT WINAPI IDirectPlay4Impl_InitializeConnection( IDirectPlay4 *iface,
4819 void *connection, DWORD flags )
4821 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4822 HMODULE servprov;
4823 GUID sp;
4824 const DWORD size = 80; /* FIXME: Need to calculate it correctly */
4825 BOOL is_dp_sp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4826 HRESULT hr;
4828 TRACE( "(%p)->(%p,0x%08lx)\n", This, connection, flags );
4830 if ( !connection )
4831 return DPERR_INVALIDPARAMS;
4833 if ( flags )
4834 return DPERR_INVALIDFLAGS;
4836 if ( This->dp2->connectionInitialized != NO_PROVIDER )
4837 return DPERR_ALREADYINITIALIZED;
4839 /* Find out what the requested SP is and how large this buffer is */
4840 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, connection, size, &sp );
4842 if ( FAILED(hr) )
4844 ERR( "Invalid compound address?\n" );
4845 return DPERR_UNAVAILABLE;
4848 /* Load the service provider */
4849 servprov = DP_LoadSP( &sp, &This->dp2->spData, &is_dp_sp );
4851 if ( !servprov )
4853 ERR( "Unable to load service provider %s\n", debugstr_guid(&sp) );
4854 return DPERR_UNAVAILABLE;
4857 if ( is_dp_sp )
4859 /* Fill in what we can of the Service Provider required information.
4860 * The rest was be done in DP_LoadSP
4862 This->dp2->spData.lpAddress = connection;
4863 This->dp2->spData.dwAddressSize = size;
4864 This->dp2->spData.lpGuid = &sp;
4865 hr = DP_InitializeDPSP( This, servprov );
4867 else
4869 This->dp2->dplspData.lpAddress = connection;
4870 hr = DP_InitializeDPLSP( This, servprov );
4873 if ( FAILED(hr) )
4874 return hr;
4876 return DP_OK;
4879 static HRESULT WINAPI IDirectPlay3AImpl_SecureOpen( IDirectPlay3A *iface,
4880 const DPSESSIONDESC2 *sdesc, DWORD flags, const DPSECURITYDESC *security,
4881 const DPCREDENTIALS *credentials )
4883 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4884 return IDirectPlayX_SecureOpen( &This->IDirectPlay4A_iface, sdesc, flags, security,
4885 credentials );
4888 static HRESULT WINAPI IDirectPlay3Impl_SecureOpen( IDirectPlay3 *iface,
4889 const DPSESSIONDESC2 *sdesc, DWORD flags, const DPSECURITYDESC *security,
4890 const DPCREDENTIALS *credentials )
4892 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4893 return IDirectPlayX_SecureOpen( &This->IDirectPlay4_iface, sdesc, flags, security,
4894 credentials );
4897 static HRESULT WINAPI IDirectPlay4AImpl_SecureOpen( IDirectPlay4A *iface,
4898 const DPSESSIONDESC2 *lpsd, DWORD dwFlags, const DPSECURITYDESC *lpSecurity,
4899 const DPCREDENTIALS *lpCredentials )
4901 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4902 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4905 static HRESULT WINAPI IDirectPlay4Impl_SecureOpen( IDirectPlay4 *iface,
4906 const DPSESSIONDESC2 *lpsd, DWORD dwFlags, const DPSECURITYDESC *lpSecurity,
4907 const DPCREDENTIALS *lpCredentials )
4909 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4910 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4913 static HRESULT WINAPI IDirectPlay3AImpl_SendChatMessage( IDirectPlay3A *iface, DPID from, DPID to,
4914 DWORD flags, DPCHAT *chatmsg )
4916 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4917 return IDirectPlayX_SendChatMessage( &This->IDirectPlay4A_iface, from, to, flags, chatmsg );
4920 static HRESULT WINAPI IDirectPlay3Impl_SendChatMessage( IDirectPlay3 *iface, DPID from, DPID to,
4921 DWORD flags, DPCHAT *chatmsg )
4923 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4924 return IDirectPlayX_SendChatMessage( &This->IDirectPlay4_iface, from, to, flags, chatmsg );
4927 static HRESULT WINAPI IDirectPlay4AImpl_SendChatMessage( IDirectPlay4A *iface, DPID from,
4928 DPID to, DWORD flags, DPCHAT *chatmsg )
4930 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4931 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, from, to, flags, chatmsg );
4932 return DP_OK;
4935 static HRESULT WINAPI IDirectPlay4Impl_SendChatMessage( IDirectPlay4 *iface, DPID from, DPID to,
4936 DWORD flags, DPCHAT *chatmsg )
4938 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4939 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, from, to, flags, chatmsg );
4940 return DP_OK;
4943 static HRESULT WINAPI IDirectPlay3AImpl_SetGroupConnectionSettings( IDirectPlay3A *iface,
4944 DWORD flags, DPID group, DPLCONNECTION *connection )
4946 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4947 return IDirectPlayX_SetGroupConnectionSettings( &This->IDirectPlay4A_iface, flags, group,
4948 connection );
4951 static HRESULT WINAPI IDirectPlay3Impl_SetGroupConnectionSettings( IDirectPlay3 *iface,
4952 DWORD flags, DPID group, DPLCONNECTION *connection )
4954 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4955 return IDirectPlayX_SetGroupConnectionSettings( &This->IDirectPlay4_iface, flags, group,
4956 connection );
4959 static HRESULT WINAPI IDirectPlay4AImpl_SetGroupConnectionSettings( IDirectPlay4A *iface,
4960 DWORD flags, DPID group, DPLCONNECTION *connection )
4962 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4963 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, flags, group, connection );
4964 return DP_OK;
4967 static HRESULT WINAPI IDirectPlay4Impl_SetGroupConnectionSettings( IDirectPlay4 *iface, DWORD flags,
4968 DPID group, DPLCONNECTION *connection )
4970 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4971 FIXME( "(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, flags, group, connection );
4972 return DP_OK;
4975 static HRESULT WINAPI IDirectPlay3AImpl_StartSession( IDirectPlay3A *iface, DWORD flags,
4976 DPID group )
4978 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4979 return IDirectPlayX_StartSession( &This->IDirectPlay4A_iface, flags, group );
4982 static HRESULT WINAPI IDirectPlay3Impl_StartSession( IDirectPlay3 *iface, DWORD flags,
4983 DPID group )
4985 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4986 return IDirectPlayX_StartSession( &This->IDirectPlay4_iface, flags, group );
4989 static HRESULT WINAPI IDirectPlay4AImpl_StartSession( IDirectPlay4A *iface, DWORD flags,
4990 DPID group )
4992 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4993 return IDirectPlayX_StartSession( &This->IDirectPlay4_iface, flags, group );
4996 static HRESULT WINAPI IDirectPlay4Impl_StartSession( IDirectPlay4 *iface, DWORD flags, DPID group )
4998 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4999 FIXME( "(%p)->(0x%08lx,0x%08lx): stub\n", This, flags, group );
5000 return DP_OK;
5003 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupFlags( IDirectPlay3A *iface, DPID group,
5004 DWORD *flags )
5006 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
5007 return IDirectPlayX_GetGroupFlags( &This->IDirectPlay4A_iface, group, flags );
5010 static HRESULT WINAPI IDirectPlay3Impl_GetGroupFlags( IDirectPlay3 *iface, DPID group,
5011 DWORD *flags )
5013 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
5014 return IDirectPlayX_GetGroupFlags( &This->IDirectPlay4_iface, group, flags );
5017 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupFlags( IDirectPlay4A *iface, DPID group,
5018 DWORD *flags )
5020 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5021 return IDirectPlayX_GetGroupFlags( &This->IDirectPlay4_iface, group, flags );
5024 static HRESULT WINAPI IDirectPlay4Impl_GetGroupFlags( IDirectPlay4 *iface, DPID group,
5025 DWORD *flags )
5027 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5028 FIXME( "(%p)->(0x%08lx,%p): stub\n", This, group, flags );
5029 return DP_OK;
5032 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupParent( IDirectPlay3A *iface, DPID group,
5033 DPID *parent )
5035 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
5036 return IDirectPlayX_GetGroupParent( &This->IDirectPlay4A_iface, group, parent );
5039 static HRESULT WINAPI IDirectPlay3Impl_GetGroupParent( IDirectPlay3 *iface, DPID group,
5040 DPID *parent )
5042 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
5043 return IDirectPlayX_GetGroupParent( &This->IDirectPlay4_iface, group, parent );
5046 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupParent( IDirectPlay4A *iface, DPID group,
5047 DPID *parent )
5049 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5050 return IDirectPlayX_GetGroupParent( &This->IDirectPlay4_iface, group, parent );
5053 static HRESULT WINAPI IDirectPlay4Impl_GetGroupParent( IDirectPlay4 *iface, DPID group,
5054 DPID *parent )
5056 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5057 lpGroupData gdata;
5059 TRACE( "(%p)->(0x%08lx,%p)\n", This, group, parent );
5061 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
5062 return DPERR_INVALIDGROUP;
5064 *parent = gdata->dpid;
5066 return DP_OK;
5069 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerAccount( IDirectPlay3A *iface, DPID player,
5070 DWORD flags, void *data, DWORD *size )
5072 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
5073 return IDirectPlayX_GetPlayerAccount( &This->IDirectPlay4A_iface, player, flags, data, size );
5076 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerAccount( IDirectPlay3 *iface, DPID player,
5077 DWORD flags, void *data, DWORD *size )
5079 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
5080 return IDirectPlayX_GetPlayerAccount( &This->IDirectPlay4_iface, player, flags, data, size );
5083 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerAccount( IDirectPlay4A *iface, DPID player,
5084 DWORD flags, void *data, DWORD *size )
5086 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5087 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, player, flags, data, size );
5088 return DP_OK;
5091 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerAccount( IDirectPlay4 *iface, DPID player,
5092 DWORD flags, void *data, DWORD *size )
5094 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5095 FIXME( "(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, player, flags, data, size );
5096 return DP_OK;
5099 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerFlags( IDirectPlay3A *iface, DPID player,
5100 DWORD *flags )
5102 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
5103 return IDirectPlayX_GetPlayerFlags( &This->IDirectPlay4A_iface, player, flags );
5106 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerFlags( IDirectPlay3 *iface, DPID player,
5107 DWORD *flags )
5109 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
5110 return IDirectPlayX_GetPlayerFlags( &This->IDirectPlay4_iface, player, flags );
5113 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerFlags( IDirectPlay4A *iface, DPID player,
5114 DWORD *flags )
5116 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5117 return IDirectPlayX_GetPlayerFlags( &This->IDirectPlay4_iface, player, flags );
5120 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerFlags( IDirectPlay4 *iface, DPID player,
5121 DWORD *flags )
5123 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5124 FIXME( "(%p)->(0x%08lx,%p): stub\n", This, player, flags );
5125 return DP_OK;
5128 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupOwner( IDirectPlay4A *iface, DPID group,
5129 DPID *owner )
5131 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5132 return IDirectPlayX_GetGroupOwner( &This->IDirectPlay4_iface, group, owner );
5135 static HRESULT WINAPI IDirectPlay4Impl_GetGroupOwner( IDirectPlay4 *iface, DPID group,
5136 DPID *owner )
5138 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5139 FIXME( "(%p)->(0x%08lx,%p): stub\n", This, group, owner );
5140 return DP_OK;
5143 static HRESULT WINAPI IDirectPlay4AImpl_SetGroupOwner( IDirectPlay4A *iface, DPID group,
5144 DPID owner )
5146 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5147 return IDirectPlayX_SetGroupOwner( &This->IDirectPlay4_iface, group, owner );
5150 static HRESULT WINAPI IDirectPlay4Impl_SetGroupOwner( IDirectPlay4 *iface, DPID group ,
5151 DPID owner )
5153 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5154 FIXME( "(%p)->(0x%08lx,0x%08lx): stub\n", This, group, owner );
5155 return DP_OK;
5158 static HRESULT WINAPI IDirectPlay4AImpl_SendEx( IDirectPlay4A *iface, DPID from, DPID to,
5159 DWORD flags, void *data, DWORD size, DWORD priority, DWORD timeout, void *context,
5160 DWORD *msgid )
5162 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5163 return IDirectPlayX_SendEx( &This->IDirectPlay4_iface, from, to, flags, data, size, priority,
5164 timeout, context, msgid );
5167 static HRESULT WINAPI IDirectPlay4Impl_SendEx( IDirectPlay4 *iface, DPID from, DPID to,
5168 DWORD flags, void *data, DWORD size, DWORD priority, DWORD timeout, void *context,
5169 DWORD *msgid )
5171 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5173 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx,0x%08lx,0x%08lx,%p,%p): semi-stub\n",
5174 This, from, to, flags, data, size, priority, timeout, context, msgid );
5176 if ( This->dp2->connectionInitialized == NO_PROVIDER )
5177 return DPERR_UNINITIALIZED;
5179 /* FIXME: Add parameter checking */
5180 /* FIXME: First call to this needs to acquire a message id which will be
5181 * used for multiple sends
5184 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
5186 /* Verify that the message is being sent from a valid local player. The
5187 * from player may be anonymous DPID_UNKNOWN
5189 if ( from != DPID_UNKNOWN && !DP_FindPlayer( This, from ) )
5191 WARN( "INFO: Invalid from player 0x%08lx\n", from );
5192 return DPERR_INVALIDPLAYER;
5195 /* Verify that the message is being sent to a valid player, group or to
5196 * everyone. If it's valid, send it to those players.
5198 if ( to == DPID_ALLPLAYERS )
5200 /* See if SP has the ability to multicast. If so, use it */
5201 if ( This->dp2->spData.lpCB->SendToGroupEx )
5202 FIXME( "Use group sendex to group 0\n" );
5203 else if ( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
5204 FIXME( "Use obsolete group send to group 0\n" );
5205 else /* No multicast, multiplicate */
5206 FIXME( "Send to all players using EnumPlayersInGroup\n" );
5208 else if ( DP_FindPlayer( This, to ) )
5210 /* Have the service provider send this message */
5211 /* FIXME: Could optimize for local interface sends */
5212 return DP_SP_SendEx( This, flags, data, size, priority, timeout, context, msgid );
5214 else if ( DP_FindAnyGroup( This, to ) )
5216 /* See if SP has the ability to multicast. If so, use it */
5217 if ( This->dp2->spData.lpCB->SendToGroupEx )
5218 FIXME( "Use group sendex\n" );
5219 else if ( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
5220 FIXME( "Use obsolete group send to group\n" );
5221 else /* No multicast, multiplicate */
5222 FIXME( "Send to all players using EnumPlayersInGroup\n" );
5225 else
5226 return DPERR_INVALIDPLAYER;
5228 /* FIXME: Should return what the send returned */
5229 return DP_OK;
5232 static HRESULT DP_SP_SendEx( IDirectPlayImpl *This, DWORD dwFlags, void *lpData, DWORD dwDataSize,
5233 DWORD dwPriority, DWORD dwTimeout, void *lpContext, DWORD *lpdwMsgID )
5235 LPDPMSG lpMElem;
5237 FIXME( ": stub\n" );
5239 /* FIXME: This queuing should only be for async messages */
5241 lpMElem = calloc( 1, sizeof( *lpMElem ) );
5242 lpMElem->msg = malloc( dwDataSize );
5244 CopyMemory( lpMElem->msg, lpData, dwDataSize );
5246 /* FIXME: Need to queue based on priority */
5247 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
5249 return DP_OK;
5252 static HRESULT WINAPI IDirectPlay4AImpl_GetMessageQueue( IDirectPlay4A *iface, DPID from, DPID to,
5253 DWORD flags, DWORD *msgs, DWORD *bytes )
5255 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5256 return IDirectPlayX_GetMessageQueue( &This->IDirectPlay4_iface, from, to, flags, msgs, bytes );
5259 static HRESULT WINAPI IDirectPlay4Impl_GetMessageQueue( IDirectPlay4 *iface, DPID from, DPID to,
5260 DWORD flags, DWORD *msgs, DWORD *bytes )
5262 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5263 HRESULT hr = DP_OK;
5265 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,%p): semi-stub\n", This, from, to, flags, msgs, bytes );
5267 /* FIXME: Do we need to do from and to sanity checking here? */
5268 /* FIXME: What about sends which are not immediate? */
5270 if ( This->dp2->spData.lpCB->GetMessageQueue )
5272 DPSP_GETMESSAGEQUEUEDATA data;
5274 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
5276 /* FIXME: None of this is documented :( */
5277 data.lpISP = This->dp2->spData.lpISP;
5278 data.dwFlags = flags;
5279 data.idFrom = from;
5280 data.idTo = to;
5281 data.lpdwNumMsgs = msgs;
5282 data.lpdwNumBytes = bytes;
5284 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
5286 else
5287 FIXME( "No SP for GetMessageQueue - fake some data\n" );
5289 return hr;
5292 static HRESULT dplay_cancelmsg ( IDirectPlayImpl* This, DWORD msgid, DWORD flags, DWORD minprio,
5293 DWORD maxprio )
5295 HRESULT hr = DP_OK;
5297 FIXME( "(%p)->(0x%08lx,0x%08lx): semi stub\n", This, msgid, flags );
5299 if ( This->dp2->spData.lpCB->Cancel )
5301 DPSP_CANCELDATA data;
5303 TRACE( "Calling SP Cancel\n" );
5305 /* FIXME: Undocumented callback */
5307 data.lpISP = This->dp2->spData.lpISP;
5308 data.dwFlags = flags;
5309 data.lprglpvSPMsgID = NULL;
5310 data.cSPMsgID = msgid;
5311 data.dwMinPriority = minprio;
5312 data.dwMaxPriority = maxprio;
5314 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
5316 else
5317 FIXME( "SP doesn't implement Cancel\n" );
5319 return hr;
5322 static HRESULT WINAPI IDirectPlay4AImpl_CancelMessage( IDirectPlay4A *iface, DWORD msgid,
5323 DWORD flags )
5325 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5326 return IDirectPlayX_CancelMessage( &This->IDirectPlay4_iface, msgid, flags );
5329 static HRESULT WINAPI IDirectPlay4Impl_CancelMessage( IDirectPlay4 *iface, DWORD msgid,
5330 DWORD flags )
5332 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5334 if ( flags != 0 )
5335 return DPERR_INVALIDFLAGS;
5337 if ( msgid == 0 )
5338 flags |= DPCANCELSEND_ALL;
5340 return dplay_cancelmsg( This, msgid, flags, 0, 0 );
5343 static HRESULT WINAPI IDirectPlay4AImpl_CancelPriority( IDirectPlay4A *iface, DWORD minprio,
5344 DWORD maxprio, DWORD flags )
5346 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5347 return IDirectPlayX_CancelPriority( &This->IDirectPlay4_iface, minprio, maxprio, flags );
5350 static HRESULT WINAPI IDirectPlay4Impl_CancelPriority( IDirectPlay4 *iface, DWORD minprio,
5351 DWORD maxprio, DWORD flags )
5353 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5355 if ( flags != 0 )
5356 return DPERR_INVALIDFLAGS;
5358 return dplay_cancelmsg( This, 0, DPCANCELSEND_PRIORITY, minprio, maxprio );
5361 static const IDirectPlay2Vtbl dp2_vt =
5363 IDirectPlay2Impl_QueryInterface,
5364 IDirectPlay2Impl_AddRef,
5365 IDirectPlay2Impl_Release,
5366 IDirectPlay2Impl_AddPlayerToGroup,
5367 IDirectPlay2Impl_Close,
5368 IDirectPlay2Impl_CreateGroup,
5369 IDirectPlay2Impl_CreatePlayer,
5370 IDirectPlay2Impl_DeletePlayerFromGroup,
5371 IDirectPlay2Impl_DestroyGroup,
5372 IDirectPlay2Impl_DestroyPlayer,
5373 IDirectPlay2Impl_EnumGroupPlayers,
5374 IDirectPlay2Impl_EnumGroups,
5375 IDirectPlay2Impl_EnumPlayers,
5376 IDirectPlay2Impl_EnumSessions,
5377 IDirectPlay2Impl_GetCaps,
5378 IDirectPlay2Impl_GetGroupData,
5379 IDirectPlay2Impl_GetGroupName,
5380 IDirectPlay2Impl_GetMessageCount,
5381 IDirectPlay2Impl_GetPlayerAddress,
5382 IDirectPlay2Impl_GetPlayerCaps,
5383 IDirectPlay2Impl_GetPlayerData,
5384 IDirectPlay2Impl_GetPlayerName,
5385 IDirectPlay2Impl_GetSessionDesc,
5386 IDirectPlay2Impl_Initialize,
5387 IDirectPlay2Impl_Open,
5388 IDirectPlay2Impl_Receive,
5389 IDirectPlay2Impl_Send,
5390 IDirectPlay2Impl_SetGroupData,
5391 IDirectPlay2Impl_SetGroupName,
5392 IDirectPlay2Impl_SetPlayerData,
5393 IDirectPlay2Impl_SetPlayerName,
5394 IDirectPlay2Impl_SetSessionDesc
5397 static const IDirectPlay2Vtbl dp2A_vt =
5399 IDirectPlay2AImpl_QueryInterface,
5400 IDirectPlay2AImpl_AddRef,
5401 IDirectPlay2AImpl_Release,
5402 IDirectPlay2AImpl_AddPlayerToGroup,
5403 IDirectPlay2AImpl_Close,
5404 IDirectPlay2AImpl_CreateGroup,
5405 IDirectPlay2AImpl_CreatePlayer,
5406 IDirectPlay2AImpl_DeletePlayerFromGroup,
5407 IDirectPlay2AImpl_DestroyGroup,
5408 IDirectPlay2AImpl_DestroyPlayer,
5409 IDirectPlay2AImpl_EnumGroupPlayers,
5410 IDirectPlay2AImpl_EnumGroups,
5411 IDirectPlay2AImpl_EnumPlayers,
5412 IDirectPlay2AImpl_EnumSessions,
5413 IDirectPlay2AImpl_GetCaps,
5414 IDirectPlay2AImpl_GetGroupData,
5415 IDirectPlay2AImpl_GetGroupName,
5416 IDirectPlay2AImpl_GetMessageCount,
5417 IDirectPlay2AImpl_GetPlayerAddress,
5418 IDirectPlay2AImpl_GetPlayerCaps,
5419 IDirectPlay2AImpl_GetPlayerData,
5420 IDirectPlay2AImpl_GetPlayerName,
5421 IDirectPlay2AImpl_GetSessionDesc,
5422 IDirectPlay2AImpl_Initialize,
5423 IDirectPlay2AImpl_Open,
5424 IDirectPlay2AImpl_Receive,
5425 IDirectPlay2AImpl_Send,
5426 IDirectPlay2AImpl_SetGroupData,
5427 IDirectPlay2AImpl_SetGroupName,
5428 IDirectPlay2AImpl_SetPlayerData,
5429 IDirectPlay2AImpl_SetPlayerName,
5430 IDirectPlay2AImpl_SetSessionDesc
5433 static const IDirectPlay3Vtbl dp3_vt =
5435 IDirectPlay3Impl_QueryInterface,
5436 IDirectPlay3Impl_AddRef,
5437 IDirectPlay3Impl_Release,
5438 IDirectPlay3Impl_AddPlayerToGroup,
5439 IDirectPlay3Impl_Close,
5440 IDirectPlay3Impl_CreateGroup,
5441 IDirectPlay3Impl_CreatePlayer,
5442 IDirectPlay3Impl_DeletePlayerFromGroup,
5443 IDirectPlay3Impl_DestroyGroup,
5444 IDirectPlay3Impl_DestroyPlayer,
5445 IDirectPlay3Impl_EnumGroupPlayers,
5446 IDirectPlay3Impl_EnumGroups,
5447 IDirectPlay3Impl_EnumPlayers,
5448 IDirectPlay3Impl_EnumSessions,
5449 IDirectPlay3Impl_GetCaps,
5450 IDirectPlay3Impl_GetGroupData,
5451 IDirectPlay3Impl_GetGroupName,
5452 IDirectPlay3Impl_GetMessageCount,
5453 IDirectPlay3Impl_GetPlayerAddress,
5454 IDirectPlay3Impl_GetPlayerCaps,
5455 IDirectPlay3Impl_GetPlayerData,
5456 IDirectPlay3Impl_GetPlayerName,
5457 IDirectPlay3Impl_GetSessionDesc,
5458 IDirectPlay3Impl_Initialize,
5459 IDirectPlay3Impl_Open,
5460 IDirectPlay3Impl_Receive,
5461 IDirectPlay3Impl_Send,
5462 IDirectPlay3Impl_SetGroupData,
5463 IDirectPlay3Impl_SetGroupName,
5464 IDirectPlay3Impl_SetPlayerData,
5465 IDirectPlay3Impl_SetPlayerName,
5466 IDirectPlay3Impl_SetSessionDesc,
5467 IDirectPlay3Impl_AddGroupToGroup,
5468 IDirectPlay3Impl_CreateGroupInGroup,
5469 IDirectPlay3Impl_DeleteGroupFromGroup,
5470 IDirectPlay3Impl_EnumConnections,
5471 IDirectPlay3Impl_EnumGroupsInGroup,
5472 IDirectPlay3Impl_GetGroupConnectionSettings,
5473 IDirectPlay3Impl_InitializeConnection,
5474 IDirectPlay3Impl_SecureOpen,
5475 IDirectPlay3Impl_SendChatMessage,
5476 IDirectPlay3Impl_SetGroupConnectionSettings,
5477 IDirectPlay3Impl_StartSession,
5478 IDirectPlay3Impl_GetGroupFlags,
5479 IDirectPlay3Impl_GetGroupParent,
5480 IDirectPlay3Impl_GetPlayerAccount,
5481 IDirectPlay3Impl_GetPlayerFlags
5484 static const IDirectPlay3Vtbl dp3A_vt =
5486 IDirectPlay3AImpl_QueryInterface,
5487 IDirectPlay3AImpl_AddRef,
5488 IDirectPlay3AImpl_Release,
5489 IDirectPlay3AImpl_AddPlayerToGroup,
5490 IDirectPlay3AImpl_Close,
5491 IDirectPlay3AImpl_CreateGroup,
5492 IDirectPlay3AImpl_CreatePlayer,
5493 IDirectPlay3AImpl_DeletePlayerFromGroup,
5494 IDirectPlay3AImpl_DestroyGroup,
5495 IDirectPlay3AImpl_DestroyPlayer,
5496 IDirectPlay3AImpl_EnumGroupPlayers,
5497 IDirectPlay3AImpl_EnumGroups,
5498 IDirectPlay3AImpl_EnumPlayers,
5499 IDirectPlay3AImpl_EnumSessions,
5500 IDirectPlay3AImpl_GetCaps,
5501 IDirectPlay3AImpl_GetGroupData,
5502 IDirectPlay3AImpl_GetGroupName,
5503 IDirectPlay3AImpl_GetMessageCount,
5504 IDirectPlay3AImpl_GetPlayerAddress,
5505 IDirectPlay3AImpl_GetPlayerCaps,
5506 IDirectPlay3AImpl_GetPlayerData,
5507 IDirectPlay3AImpl_GetPlayerName,
5508 IDirectPlay3AImpl_GetSessionDesc,
5509 IDirectPlay3AImpl_Initialize,
5510 IDirectPlay3AImpl_Open,
5511 IDirectPlay3AImpl_Receive,
5512 IDirectPlay3AImpl_Send,
5513 IDirectPlay3AImpl_SetGroupData,
5514 IDirectPlay3AImpl_SetGroupName,
5515 IDirectPlay3AImpl_SetPlayerData,
5516 IDirectPlay3AImpl_SetPlayerName,
5517 IDirectPlay3AImpl_SetSessionDesc,
5518 IDirectPlay3AImpl_AddGroupToGroup,
5519 IDirectPlay3AImpl_CreateGroupInGroup,
5520 IDirectPlay3AImpl_DeleteGroupFromGroup,
5521 IDirectPlay3AImpl_EnumConnections,
5522 IDirectPlay3AImpl_EnumGroupsInGroup,
5523 IDirectPlay3AImpl_GetGroupConnectionSettings,
5524 IDirectPlay3AImpl_InitializeConnection,
5525 IDirectPlay3AImpl_SecureOpen,
5526 IDirectPlay3AImpl_SendChatMessage,
5527 IDirectPlay3AImpl_SetGroupConnectionSettings,
5528 IDirectPlay3AImpl_StartSession,
5529 IDirectPlay3AImpl_GetGroupFlags,
5530 IDirectPlay3AImpl_GetGroupParent,
5531 IDirectPlay3AImpl_GetPlayerAccount,
5532 IDirectPlay3AImpl_GetPlayerFlags
5535 static const IDirectPlay4Vtbl dp4_vt =
5537 IDirectPlay4Impl_QueryInterface,
5538 IDirectPlay4Impl_AddRef,
5539 IDirectPlay4Impl_Release,
5540 IDirectPlay4Impl_AddPlayerToGroup,
5541 IDirectPlay4Impl_Close,
5542 IDirectPlay4Impl_CreateGroup,
5543 IDirectPlay4Impl_CreatePlayer,
5544 IDirectPlay4Impl_DeletePlayerFromGroup,
5545 IDirectPlay4Impl_DestroyGroup,
5546 IDirectPlay4Impl_DestroyPlayer,
5547 IDirectPlay4Impl_EnumGroupPlayers,
5548 IDirectPlay4Impl_EnumGroups,
5549 IDirectPlay4Impl_EnumPlayers,
5550 IDirectPlay4Impl_EnumSessions,
5551 IDirectPlay4Impl_GetCaps,
5552 IDirectPlay4Impl_GetGroupData,
5553 IDirectPlay4Impl_GetGroupName,
5554 IDirectPlay4Impl_GetMessageCount,
5555 IDirectPlay4Impl_GetPlayerAddress,
5556 IDirectPlay4Impl_GetPlayerCaps,
5557 IDirectPlay4Impl_GetPlayerData,
5558 IDirectPlay4Impl_GetPlayerName,
5559 IDirectPlay4Impl_GetSessionDesc,
5560 IDirectPlay4Impl_Initialize,
5561 IDirectPlay4Impl_Open,
5562 IDirectPlay4Impl_Receive,
5563 IDirectPlay4Impl_Send,
5564 IDirectPlay4Impl_SetGroupData,
5565 IDirectPlay4Impl_SetGroupName,
5566 IDirectPlay4Impl_SetPlayerData,
5567 IDirectPlay4Impl_SetPlayerName,
5568 IDirectPlay4Impl_SetSessionDesc,
5569 IDirectPlay4Impl_AddGroupToGroup,
5570 IDirectPlay4Impl_CreateGroupInGroup,
5571 IDirectPlay4Impl_DeleteGroupFromGroup,
5572 IDirectPlay4Impl_EnumConnections,
5573 IDirectPlay4Impl_EnumGroupsInGroup,
5574 IDirectPlay4Impl_GetGroupConnectionSettings,
5575 IDirectPlay4Impl_InitializeConnection,
5576 IDirectPlay4Impl_SecureOpen,
5577 IDirectPlay4Impl_SendChatMessage,
5578 IDirectPlay4Impl_SetGroupConnectionSettings,
5579 IDirectPlay4Impl_StartSession,
5580 IDirectPlay4Impl_GetGroupFlags,
5581 IDirectPlay4Impl_GetGroupParent,
5582 IDirectPlay4Impl_GetPlayerAccount,
5583 IDirectPlay4Impl_GetPlayerFlags,
5584 IDirectPlay4Impl_GetGroupOwner,
5585 IDirectPlay4Impl_SetGroupOwner,
5586 IDirectPlay4Impl_SendEx,
5587 IDirectPlay4Impl_GetMessageQueue,
5588 IDirectPlay4Impl_CancelMessage,
5589 IDirectPlay4Impl_CancelPriority
5592 static const IDirectPlay4Vtbl dp4A_vt =
5594 IDirectPlay4AImpl_QueryInterface,
5595 IDirectPlay4AImpl_AddRef,
5596 IDirectPlay4AImpl_Release,
5597 IDirectPlay4AImpl_AddPlayerToGroup,
5598 IDirectPlay4AImpl_Close,
5599 IDirectPlay4AImpl_CreateGroup,
5600 IDirectPlay4AImpl_CreatePlayer,
5601 IDirectPlay4AImpl_DeletePlayerFromGroup,
5602 IDirectPlay4AImpl_DestroyGroup,
5603 IDirectPlay4AImpl_DestroyPlayer,
5604 IDirectPlay4AImpl_EnumGroupPlayers,
5605 IDirectPlay4AImpl_EnumGroups,
5606 IDirectPlay4AImpl_EnumPlayers,
5607 IDirectPlay4AImpl_EnumSessions,
5608 IDirectPlay4AImpl_GetCaps,
5609 IDirectPlay4AImpl_GetGroupData,
5610 IDirectPlay4AImpl_GetGroupName,
5611 IDirectPlay4AImpl_GetMessageCount,
5612 IDirectPlay4AImpl_GetPlayerAddress,
5613 IDirectPlay4AImpl_GetPlayerCaps,
5614 IDirectPlay4AImpl_GetPlayerData,
5615 IDirectPlay4AImpl_GetPlayerName,
5616 IDirectPlay4AImpl_GetSessionDesc,
5617 IDirectPlay4AImpl_Initialize,
5618 IDirectPlay4AImpl_Open,
5619 IDirectPlay4AImpl_Receive,
5620 IDirectPlay4AImpl_Send,
5621 IDirectPlay4AImpl_SetGroupData,
5622 IDirectPlay4AImpl_SetGroupName,
5623 IDirectPlay4AImpl_SetPlayerData,
5624 IDirectPlay4AImpl_SetPlayerName,
5625 IDirectPlay4AImpl_SetSessionDesc,
5626 IDirectPlay4AImpl_AddGroupToGroup,
5627 IDirectPlay4AImpl_CreateGroupInGroup,
5628 IDirectPlay4AImpl_DeleteGroupFromGroup,
5629 IDirectPlay4AImpl_EnumConnections,
5630 IDirectPlay4AImpl_EnumGroupsInGroup,
5631 IDirectPlay4AImpl_GetGroupConnectionSettings,
5632 IDirectPlay4AImpl_InitializeConnection,
5633 IDirectPlay4AImpl_SecureOpen,
5634 IDirectPlay4AImpl_SendChatMessage,
5635 IDirectPlay4AImpl_SetGroupConnectionSettings,
5636 IDirectPlay4AImpl_StartSession,
5637 IDirectPlay4AImpl_GetGroupFlags,
5638 IDirectPlay4AImpl_GetGroupParent,
5639 IDirectPlay4AImpl_GetPlayerAccount,
5640 IDirectPlay4AImpl_GetPlayerFlags,
5641 IDirectPlay4AImpl_GetGroupOwner,
5642 IDirectPlay4AImpl_SetGroupOwner,
5643 IDirectPlay4AImpl_SendEx,
5644 IDirectPlay4AImpl_GetMessageQueue,
5645 IDirectPlay4AImpl_CancelMessage,
5646 IDirectPlay4AImpl_CancelPriority
5649 HRESULT dplay_create( REFIID riid, void **ppv )
5651 IDirectPlayImpl *obj;
5652 HRESULT hr;
5654 TRACE( "(%s, %p)\n", debugstr_guid( riid ), ppv );
5656 *ppv = NULL;
5657 obj = malloc( sizeof( *obj ) );
5658 if ( !obj )
5659 return DPERR_OUTOFMEMORY;
5661 obj->IDirectPlay_iface.lpVtbl = &dp_vt;
5662 obj->IDirectPlay2A_iface.lpVtbl = &dp2A_vt;
5663 obj->IDirectPlay2_iface.lpVtbl = &dp2_vt;
5664 obj->IDirectPlay3A_iface.lpVtbl = &dp3A_vt;
5665 obj->IDirectPlay3_iface.lpVtbl = &dp3_vt;
5666 obj->IDirectPlay4A_iface.lpVtbl = &dp4A_vt;
5667 obj->IDirectPlay4_iface.lpVtbl = &dp4_vt;
5668 obj->numIfaces = 1;
5669 obj->ref = 0;
5670 obj->ref2A = 0;
5671 obj->ref2 = 0;
5672 obj->ref3A = 0;
5673 obj->ref3 = 0;
5674 obj->ref4A = 0;
5675 obj->ref4 = 1;
5677 InitializeCriticalSection( &obj->lock );
5678 obj->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectPlayImpl.lock");
5680 if ( DP_CreateDirectPlay2( obj ) )
5681 hr = IDirectPlayX_QueryInterface( &obj->IDirectPlay4_iface, riid, ppv );
5682 else
5683 hr = DPERR_NOMEMORY;
5684 IDirectPlayX_Release( &obj->IDirectPlay4_iface );
5686 return hr;
5690 HRESULT DP_GetSPPlayerData( IDirectPlayImpl *lpDP, DPID idPlayer, void **lplpData )
5692 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5694 if( lpPlayer == NULL )
5696 return DPERR_INVALIDPLAYER;
5699 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
5701 return DP_OK;
5704 HRESULT DP_SetSPPlayerData( IDirectPlayImpl *lpDP, DPID idPlayer, void *lpData )
5706 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5708 if( lpPlayer == NULL )
5710 return DPERR_INVALIDPLAYER;
5713 lpPlayer->lpPData->lpSPPlayerData = lpData;
5715 return DP_OK;
5718 /***************************************************************************
5719 * DirectPlayEnumerateAW
5721 * The pointer to the structure lpContext will be filled with the
5722 * appropriate data for each service offered by the OS. These services are
5723 * not necessarily available on this particular machine but are defined
5724 * as simple service providers under the "Service Providers" registry key.
5725 * This structure is then passed to lpEnumCallback for each of the different
5726 * services.
5728 * This API is useful only for applications written using DirectX3 or
5729 * worse. It is superseded by IDirectPlay3::EnumConnections which also
5730 * gives information on the actual connections.
5732 * defn of a service provider:
5733 * A dynamic-link library used by DirectPlay to communicate over a network.
5734 * The service provider contains all the network-specific code required
5735 * to send and receive messages. Online services and network operators can
5736 * supply service providers to use specialized hardware, protocols, communications
5737 * media, and network resources.
5740 static HRESULT DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA,
5741 LPDPENUMDPCALLBACKW lpEnumCallbackW,
5742 LPVOID lpContext)
5744 HKEY hkResult;
5745 DWORD dwIndex;
5746 FILETIME filetime;
5748 char *descriptionA = NULL;
5749 DWORD max_sizeOfDescriptionA = 0;
5750 WCHAR *descriptionW = NULL;
5751 DWORD max_sizeOfDescriptionW = 0;
5752 DWORD sizeOfSubKeyName;
5753 WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */
5754 LONG ret_value;
5755 static GUID *guid_cache;
5756 static int cache_count;
5758 if (!lpEnumCallbackA && !lpEnumCallbackW)
5760 return DPERR_INVALIDPARAMS;
5763 /* Need to loop over the service providers in the registry */
5764 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\DirectPlay\\Service Providers",
5765 0, KEY_READ, &hkResult) != ERROR_SUCCESS)
5767 /* Hmmm. Does this mean that there are no service providers? */
5768 ERR(": no service provider key in the registry - check your Wine installation !!!\n");
5769 return DPERR_GENERIC;
5772 dwIndex = 0;
5775 sizeOfSubKeyName = ARRAY_SIZE(subKeyName);
5776 ret_value = RegEnumKeyW(hkResult, dwIndex, subKeyName, sizeOfSubKeyName);
5777 dwIndex++;
5779 while (ret_value == ERROR_SUCCESS);
5780 /* The game Swing from bug 37185 expects GUID values to persist after
5781 * the end of the enumeration. */
5782 if (cache_count < dwIndex)
5784 free(guid_cache);
5785 guid_cache = malloc(sizeof(GUID) * dwIndex);
5786 if (!guid_cache)
5788 ERR(": failed to allocate required memory.\n");
5789 return DPERR_EXCEPTION;
5791 cache_count = dwIndex;
5793 /* Traverse all the service providers we have available */
5794 dwIndex = 0;
5795 while (1)
5797 HKEY hkServiceProvider;
5798 WCHAR guidKeyContent[(2 * 16) + 1 + 6 /* This corresponds to '{....-..-..-..-......}' */ ];
5799 DWORD sizeOfGuidKeyContent = sizeof(guidKeyContent);
5801 sizeOfSubKeyName = ARRAY_SIZE(subKeyName);
5802 ret_value = RegEnumKeyExW(hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
5803 NULL, NULL, NULL, &filetime);
5804 if (ret_value == ERROR_NO_MORE_ITEMS)
5805 break;
5806 else if (ret_value != ERROR_SUCCESS)
5808 ERR(": could not enumerate on service provider key.\n");
5809 return DPERR_EXCEPTION;
5811 TRACE(" this time through sub-key %s.\n", debugstr_w(subKeyName));
5813 /* Open the key for this service provider */
5814 if (RegOpenKeyExW(hkResult, subKeyName, 0, KEY_READ, &hkServiceProvider) != ERROR_SUCCESS)
5816 ERR(": could not open registry key for service provider %s.\n", debugstr_w(subKeyName));
5817 continue;
5820 /* Get the GUID from the registry */
5821 if (RegQueryValueExW(hkServiceProvider, L"Guid",
5822 NULL, NULL, (LPBYTE) guidKeyContent, &sizeOfGuidKeyContent) != ERROR_SUCCESS)
5824 ERR(": missing GUID registry data member for service provider %s.\n", debugstr_w(subKeyName));
5825 continue;
5827 if (sizeOfGuidKeyContent != sizeof(guidKeyContent))
5829 ERR(": invalid format for the GUID registry data member for service provider %s (%s).\n", debugstr_w(subKeyName), debugstr_w(guidKeyContent));
5830 continue;
5832 CLSIDFromString(guidKeyContent, &guid_cache[dwIndex]);
5834 /* The enumeration will return FALSE if we are not to continue.
5836 * Note: on my windows box, major / minor version is 6 / 0 for all service providers
5837 * and have no relation to any of the two dwReserved1 and dwReserved2 keys.
5838 * I think that it simply means that they are in-line with DirectX 6.0
5840 if (lpEnumCallbackA)
5842 DWORD sizeOfDescription = 0;
5844 /* Note that this is the A case of this function, so use the A variant to get the description string */
5845 if (RegQueryValueExA(hkServiceProvider, "DescriptionA",
5846 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5848 ERR(": missing 'DescriptionA' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5849 continue;
5851 if (sizeOfDescription > max_sizeOfDescriptionA)
5853 free(descriptionA);
5854 max_sizeOfDescriptionA = sizeOfDescription;
5856 descriptionA = malloc(sizeOfDescription);
5857 RegQueryValueExA(hkServiceProvider, "DescriptionA",
5858 NULL, NULL, (LPBYTE) descriptionA, &sizeOfDescription);
5860 if (!lpEnumCallbackA(&guid_cache[dwIndex], descriptionA, 6, 0, lpContext))
5861 goto end;
5863 else
5865 DWORD sizeOfDescription = 0;
5867 if (RegQueryValueExW(hkServiceProvider, L"DescriptionW",
5868 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5870 ERR(": missing 'DescriptionW' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5871 continue;
5873 if (sizeOfDescription > max_sizeOfDescriptionW)
5875 free(descriptionW);
5876 max_sizeOfDescriptionW = sizeOfDescription;
5878 descriptionW = malloc(sizeOfDescription);
5879 RegQueryValueExW(hkServiceProvider, L"DescriptionW",
5880 NULL, NULL, (LPBYTE) descriptionW, &sizeOfDescription);
5882 if (!lpEnumCallbackW(&guid_cache[dwIndex], descriptionW, 6, 0, lpContext))
5883 goto end;
5886 dwIndex++;
5889 end:
5890 free(descriptionA);
5891 free(descriptionW);
5893 return DP_OK;
5896 /***************************************************************************
5897 * DirectPlayEnumerate [DPLAYX.9]
5898 * DirectPlayEnumerateA [DPLAYX.2]
5900 HRESULT WINAPI DirectPlayEnumerateA(LPDPENUMDPCALLBACKA lpEnumCallback, LPVOID lpContext )
5902 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5904 return DirectPlayEnumerateAW(lpEnumCallback, NULL, lpContext);
5907 /***************************************************************************
5908 * DirectPlayEnumerateW [DPLAYX.3]
5910 HRESULT WINAPI DirectPlayEnumerateW(LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5912 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5914 return DirectPlayEnumerateAW(NULL, lpEnumCallback, lpContext);
5917 typedef struct tagCreateEnum
5919 LPVOID lpConn;
5920 LPCGUID lpGuid;
5921 } CreateEnumData, *lpCreateEnumData;
5923 /* Find and copy the matching connection for the SP guid */
5924 static BOOL CALLBACK cbDPCreateEnumConnections(
5925 LPCGUID lpguidSP,
5926 LPVOID lpConnection,
5927 DWORD dwConnectionSize,
5928 LPCDPNAME lpName,
5929 DWORD dwFlags,
5930 LPVOID lpContext)
5932 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5934 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5936 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5938 lpData->lpConn = malloc( dwConnectionSize );
5939 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5941 /* Found the record that we were looking for */
5942 return FALSE;
5945 /* Haven't found what were looking for yet */
5946 return TRUE;
5950 /***************************************************************************
5951 * DirectPlayCreate [DPLAYX.1]
5954 HRESULT WINAPI DirectPlayCreate
5955 ( LPGUID lpGUID, LPDIRECTPLAY *lplpDP, IUnknown *pUnk )
5957 HRESULT hr;
5958 LPDIRECTPLAY3A lpDP3A;
5959 CreateEnumData cbData;
5961 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5963 if( pUnk != NULL )
5965 return CLASS_E_NOAGGREGATION;
5968 if( (lplpDP == NULL) || (lpGUID == NULL) )
5970 return DPERR_INVALIDPARAMS;
5973 if ( dplay_create( &IID_IDirectPlay, (void**)lplpDP ) != DP_OK )
5974 return DPERR_UNAVAILABLE;
5976 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
5978 /* The GUID_NULL means don't bind a service provider. Just return the
5979 interface as is */
5980 return DP_OK;
5983 /* Bind the desired service provider since lpGUID is non NULL */
5984 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
5986 /* We're going to use a DP3 interface */
5987 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
5988 (LPVOID*)&lpDP3A );
5989 if( FAILED(hr) )
5991 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
5992 return hr;
5995 cbData.lpConn = NULL;
5996 cbData.lpGuid = lpGUID;
5998 /* We were given a service provider, find info about it... */
5999 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
6000 &cbData, DPCONNECTION_DIRECTPLAY );
6001 if( ( FAILED(hr) ) ||
6002 ( cbData.lpConn == NULL )
6005 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
6006 IDirectPlayX_Release( lpDP3A );
6007 return DPERR_UNAVAILABLE;
6010 /* Initialize the service provider */
6011 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
6012 if( FAILED(hr) )
6014 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
6015 free( cbData.lpConn );
6016 IDirectPlayX_Release( lpDP3A );
6017 return hr;
6020 /* Release our version of the interface now that we're done with it */
6021 IDirectPlayX_Release( lpDP3A );
6022 free( cbData.lpConn );
6024 return DP_OK;