msvcrt: Don't include MSVC 7.0+ exception functions in SOs for older DLLs.
[wine.git] / dlls / dplayx / dplay.c
blobfde068138e5638308ba705413d73d5e30e702821
1 /* Direct Play 2,3,4 Implementation
3 * Copyright 1998,1999,2000,2001 - Peter Hunnisett
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #define COBJMACROS
21 #include "config.h"
22 #include "wine/port.h"
24 #include <stdarg.h>
25 #include <string.h>
27 #define NONAMELESSUNION
29 #include "windef.h"
30 #include "winerror.h"
31 #include "winbase.h"
32 #include "winnt.h"
33 #include "winreg.h"
34 #include "winnls.h"
35 #include "wine/unicode.h"
36 #include "wine/debug.h"
38 #include "dplayx_global.h"
39 #include "name_server.h"
40 #include "dplayx_queue.h"
41 #include "wine/dplaysp.h"
42 #include "dplay_global.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(dplay);
46 /* FIXME: Should this be externed? */
47 extern HRESULT DPL_CreateCompoundAddress
48 ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
49 LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
52 /* Local function prototypes */
53 static lpPlayerList DP_FindPlayer( IDirectPlayImpl *This, DPID dpid );
54 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, const DPNAME *lpSrc, BOOL bAnsi );
55 static void DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
56 LPVOID lpData, DWORD dwDataSize );
57 static void DP_DeleteDPNameStruct( LPDPNAME lpDPName );
58 static BOOL CALLBACK cbDeletePlayerFromAllGroups( DPID dpId,
59 DWORD dwPlayerType,
60 LPCDPNAME lpName,
61 DWORD dwFlags,
62 LPVOID lpContext );
63 static lpGroupData DP_FindAnyGroup( IDirectPlayImpl *This, DPID dpid );
65 /* Helper methods for player/group interfaces */
66 static HRESULT DP_SetSessionDesc( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpSessDesc,
67 DWORD dwFlags, BOOL bInitial, BOOL bAnsi );
68 static HRESULT DP_SP_SendEx( IDirectPlayImpl *This, DWORD dwFlags, void *lpData, DWORD dwDataSize,
69 DWORD dwPriority, DWORD dwTimeout, void *lpContext, DWORD *lpdwMsgID );
70 static BOOL DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
71 LPDWORD lpdwBufSize );
73 static DPID DP_GetRemoteNextObjectId(void);
75 static DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi );
76 static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc,
77 LPCDPSESSIONDESC2 srcSessDesc, BOOL bAnsi );
80 #define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */
81 #define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported
82 we don't have to change much */
83 #define DPID_NAME_SERVER 0x19a9d65b /* Don't ask me why */
85 /* Strip out dwFlag values which cannot be sent in the CREATEGROUP msg */
86 #define DPMSG_CREATEGROUP_DWFLAGS(x) ( (x) & DPGROUP_HIDDEN )
88 /* Strip out all dwFlags values for CREATEPLAYER msg */
89 #define DPMSG_CREATEPLAYER_DWFLAGS(x) 0
91 static LONG kludgePlayerGroupId = 1000;
94 static inline IDirectPlayImpl *impl_from_IDirectPlay( IDirectPlay *iface )
96 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay_iface );
99 static inline IDirectPlayImpl *impl_from_IDirectPlay2( IDirectPlay2 *iface )
101 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay2_iface );
104 static inline IDirectPlayImpl *impl_from_IDirectPlay2A( IDirectPlay2A *iface )
106 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay2A_iface );
109 static inline IDirectPlayImpl *impl_from_IDirectPlay3A( IDirectPlay3A *iface )
111 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay3A_iface );
114 static inline IDirectPlayImpl *impl_from_IDirectPlay3( IDirectPlay3 *iface )
116 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay3_iface );
119 static inline IDirectPlayImpl *impl_from_IDirectPlay4A( IDirectPlay4A *iface )
121 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay4A_iface );
124 static inline IDirectPlayImpl *impl_from_IDirectPlay4( IDirectPlay4 *iface )
126 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay4_iface );
129 static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
131 IDirectPlayImpl *This = lpDP;
133 This->dp2 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp2) ) );
134 if ( This->dp2 == NULL )
136 return FALSE;
139 This->dp2->bConnectionOpen = FALSE;
141 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
142 This->dp2->dwEnumSessionLock = 0;
144 This->dp2->bHostInterface = FALSE;
146 DPQ_INIT(This->dp2->receiveMsgs);
147 DPQ_INIT(This->dp2->sendMsgs);
148 DPQ_INIT(This->dp2->repliesExpected);
150 if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
152 /* FIXME: Memory leak */
153 return FALSE;
156 /* Provide an initial session desc with nothing in it */
157 This->dp2->lpSessionDesc = HeapAlloc( GetProcessHeap(),
158 HEAP_ZERO_MEMORY,
159 sizeof( *This->dp2->lpSessionDesc ) );
160 if( This->dp2->lpSessionDesc == NULL )
162 /* FIXME: Memory leak */
163 return FALSE;
165 This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc );
167 /* We are emulating a dp 6 implementation */
168 This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION;
170 This->dp2->spData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
171 sizeof( *This->dp2->spData.lpCB ) );
172 This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB );
173 This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION;
175 /* This is the pointer to the service provider */
176 if ( FAILED( dplaysp_create( &IID_IDirectPlaySP, (void**)&This->dp2->spData.lpISP, This ) ) )
178 /* FIXME: Memory leak */
179 return FALSE;
182 /* Setup lobby provider information */
183 This->dp2->dplspData.dwSPVersion = DPSP_MAJORVERSION;
184 This->dp2->dplspData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
185 sizeof( *This->dp2->dplspData.lpCB ) );
186 This->dp2->dplspData.lpCB->dwSize = sizeof( *This->dp2->dplspData.lpCB );
188 if( FAILED( dplobbysp_create( &IID_IDPLobbySP, (void**)&This->dp2->dplspData.lpISP, This ) )
191 /* FIXME: Memory leak */
192 return FALSE;
195 return TRUE;
198 /* Definition of the global function in dplayx_queue.h. #
199 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
200 DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
202 HeapFree( GetProcessHeap(), 0, elem );
205 static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
207 IDirectPlayImpl *This = lpDP;
209 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
211 TerminateThread( This->dp2->hEnumSessionThread, 0 );
212 CloseHandle( This->dp2->hEnumSessionThread );
215 /* Finish with the SP - have it shutdown */
216 if( This->dp2->spData.lpCB->ShutdownEx )
218 DPSP_SHUTDOWNDATA data;
220 TRACE( "Calling SP ShutdownEx\n" );
222 data.lpISP = This->dp2->spData.lpISP;
224 (*This->dp2->spData.lpCB->ShutdownEx)( &data );
226 else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
228 TRACE( "Calling obsolete SP Shutdown\n" );
229 (*This->dp2->spData.lpCB->Shutdown)();
232 /* Unload the SP (if it exists) */
233 if( This->dp2->hServiceProvider != 0 )
235 FreeLibrary( This->dp2->hServiceProvider );
238 /* Unload the Lobby Provider (if it exists) */
239 if( This->dp2->hDPLobbyProvider != 0 )
241 FreeLibrary( This->dp2->hDPLobbyProvider );
244 /* FIXME: Need to delete receive and send msgs queue contents */
246 NS_DeleteSessionCache( This->dp2->lpNameServerData );
248 HeapFree( GetProcessHeap(), 0, This->dp2->dplspData.lpCB);
249 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
251 IDirectPlaySP_Release( This->dp2->spData.lpISP );
253 /* Delete the contents */
254 HeapFree( GetProcessHeap(), 0, This->dp2 );
256 return TRUE;
259 static void dplay_destroy(IDirectPlayImpl *obj)
261 DP_DestroyDirectPlay2( obj );
262 obj->lock.DebugInfo->Spare[0] = 0;
263 DeleteCriticalSection( &obj->lock );
264 HeapFree( GetProcessHeap(), 0, obj );
267 static inline DPID DP_NextObjectId(void)
269 return (DPID)InterlockedIncrement( &kludgePlayerGroupId );
272 /* *lplpReply will be non NULL iff there is something to reply */
273 HRESULT DP_HandleMessage( IDirectPlayImpl *This, const void *lpcMessageBody,
274 DWORD dwMessageBodySize, const void *lpcMessageHeader, WORD wCommandId, WORD wVersion,
275 void **lplpReply, DWORD *lpdwMsgSize )
277 TRACE( "(%p)->(%p,0x%08x,%p,%u,%u)\n",
278 This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId,
279 wVersion );
281 switch( wCommandId )
283 /* Name server needs to handle this request */
284 case DPMSGCMD_ENUMSESSIONSREQUEST:
285 /* Reply expected */
286 NS_ReplyToEnumSessionsRequest( lpcMessageBody, lplpReply, lpdwMsgSize, This );
287 break;
289 /* Name server needs to handle this request */
290 case DPMSGCMD_ENUMSESSIONSREPLY:
291 /* No reply expected */
292 NS_AddRemoteComputerAsNameServer( lpcMessageHeader,
293 This->dp2->spData.dwSPHeaderSize,
294 lpcMessageBody,
295 This->dp2->lpNameServerData );
296 break;
298 case DPMSGCMD_REQUESTNEWPLAYERID:
300 LPCDPMSG_REQUESTNEWPLAYERID lpcMsg = lpcMessageBody;
302 LPDPMSG_NEWPLAYERIDREPLY lpReply;
304 *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
306 *lplpReply = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, *lpdwMsgSize );
308 FIXME( "Ignoring dwFlags 0x%08x in request msg\n",
309 lpcMsg->dwFlags );
311 /* Setup the reply */
312 lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) +
313 This->dp2->spData.dwSPHeaderSize );
315 lpReply->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
316 lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY;
317 lpReply->envelope.wVersion = DPMSGVER_DP6;
319 lpReply->dpidNewPlayerId = DP_NextObjectId();
321 TRACE( "Allocating new playerid 0x%08x from remote request\n",
322 lpReply->dpidNewPlayerId );
323 break;
326 case DPMSGCMD_GETNAMETABLEREPLY:
327 case DPMSGCMD_NEWPLAYERIDREPLY:
328 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
329 break;
331 case DPMSGCMD_JUSTENVELOPE:
332 TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08x\n", lpcMessageHeader, ((const DWORD *)lpcMessageHeader)[1] );
333 NS_SetLocalAddr( This->dp2->lpNameServerData, lpcMessageHeader, 20 );
334 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
336 case DPMSGCMD_FORWARDADDPLAYER:
337 TRACE( "Sending message to self to get my addr\n" );
338 DP_MSG_ToSelf( This, 1 ); /* This is a hack right now */
339 break;
341 case DPMSGCMD_FORWARDADDPLAYERNACK:
342 DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
343 break;
345 default:
346 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
347 DebugBreak();
348 break;
351 /* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */
353 return DP_OK;
357 static HRESULT WINAPI IDirectPlayImpl_QueryInterface( IDirectPlay *iface, REFIID riid, void **ppv )
359 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
360 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
363 static ULONG WINAPI IDirectPlayImpl_AddRef( IDirectPlay *iface )
365 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
366 ULONG ref = InterlockedIncrement( &This->ref );
368 TRACE( "(%p) ref=%d\n", This, ref );
370 if ( ref == 1 )
371 InterlockedIncrement( &This->numIfaces );
373 return ref;
376 static ULONG WINAPI IDirectPlayImpl_Release( IDirectPlay *iface )
378 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
379 ULONG ref = InterlockedDecrement( &This->ref );
381 TRACE( "(%p) ref=%d\n", This, ref );
383 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
384 dplay_destroy( This );
386 return ref;
389 static HRESULT WINAPI IDirectPlayImpl_AddPlayerToGroup( IDirectPlay *iface, DPID group,
390 DPID player )
392 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
393 FIXME( "(%p)->(0x%08x,0x%08x): stub\n", This, group, player );
394 return E_NOTIMPL;
397 static HRESULT WINAPI IDirectPlayImpl_Close( IDirectPlay *iface )
399 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
400 FIXME( "(%p): stub\n", This );
401 return E_NOTIMPL;
404 static HRESULT WINAPI IDirectPlayImpl_CreatePlayer( IDirectPlay *iface, DPID *player,
405 LPSTR name, LPSTR fullname, HANDLE *event )
407 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
408 FIXME( "(%p)->(%p,%s,%s,%p): stub\n", This, player, debugstr_a( name ), debugstr_a( fullname ),
409 event );
410 return E_NOTIMPL;
413 static HRESULT WINAPI IDirectPlayImpl_CreateGroup( IDirectPlay *iface, DPID *group, LPSTR name,
414 LPSTR fullname )
416 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
417 FIXME( "(%p)->(%p,%s,%s): stub\n", This, group, debugstr_a( name ), debugstr_a( fullname ) );
418 return E_NOTIMPL;
421 static HRESULT WINAPI IDirectPlayImpl_DeletePlayerFromGroup( IDirectPlay *iface, DPID group,
422 DPID player )
424 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
425 FIXME( "(%p)->(0x%08x,0x%08x): stub\n", This, group, player );
426 return E_NOTIMPL;
429 static HRESULT WINAPI IDirectPlayImpl_DestroyPlayer( IDirectPlay *iface, DPID player )
431 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
432 FIXME( "(%p)->(0x%08x): stub\n", This, player );
433 return E_NOTIMPL;
436 static HRESULT WINAPI IDirectPlayImpl_DestroyGroup( IDirectPlay *iface, DPID group )
438 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
439 FIXME( "(%p)->(0x%08x): stub\n", This, group );
440 return E_NOTIMPL;
443 static HRESULT WINAPI IDirectPlayImpl_EnableNewPlayers( IDirectPlay *iface, BOOL enable )
445 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
446 FIXME( "(%p)->(%d): stub\n", This, enable );
447 return E_NOTIMPL;
450 static HRESULT WINAPI IDirectPlayImpl_EnumGroupPlayers( IDirectPlay *iface, DPID group,
451 LPDPENUMPLAYERSCALLBACK enumplayercb, void *context, DWORD flags )
453 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
454 FIXME( "(%p)->(0x%08x,%p,%p,0x%08x): stub\n", This, group, enumplayercb, context, flags );
455 return E_NOTIMPL;
458 static HRESULT WINAPI IDirectPlayImpl_EnumGroups( IDirectPlay *iface, DWORD session,
459 LPDPENUMPLAYERSCALLBACK enumplayercb, void *context, DWORD flags )
461 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
462 FIXME( "(%p)->(0x%08x,%p,%p,0x%08x): stub\n", This, session, enumplayercb, context, flags );
463 return E_NOTIMPL;
466 static HRESULT WINAPI IDirectPlayImpl_EnumPlayers( IDirectPlay *iface, DWORD session,
467 LPDPENUMPLAYERSCALLBACK enumplayercb, void *context, DWORD flags )
469 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
470 FIXME( "(%p)->(0x%08x,%p,%p,0x%08x): stub\n", This, session, enumplayercb, context, flags );
471 return E_NOTIMPL;
474 static HRESULT WINAPI IDirectPlayImpl_EnumSessions( IDirectPlay *iface, DPSESSIONDESC *sdesc,
475 DWORD timeout, LPDPENUMSESSIONSCALLBACK enumsessioncb, void *context, DWORD flags )
477 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
478 FIXME( "(%p)->(%p,%u,%p,%p,0x%08x): stub\n", This, sdesc, timeout, enumsessioncb, context,
479 flags );
480 return E_NOTIMPL;
483 static HRESULT WINAPI IDirectPlayImpl_GetCaps( IDirectPlay *iface, DPCAPS *caps )
485 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
486 FIXME( "(%p)->(%p): stub\n", This, caps );
487 return E_NOTIMPL;
490 static HRESULT WINAPI IDirectPlayImpl_GetMessageCount( IDirectPlay *iface, DPID player,
491 DWORD *count )
493 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
494 FIXME( "(%p)->(0x%08x,%p): stub\n", This, player, count );
495 return E_NOTIMPL;
498 static HRESULT WINAPI IDirectPlayImpl_GetPlayerCaps( IDirectPlay *iface, DPID player, DPCAPS *caps )
500 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
501 FIXME( "(%p)->(0x%08x,%p): stub\n", This, player, caps );
502 return E_NOTIMPL;
505 static HRESULT WINAPI IDirectPlayImpl_GetPlayerName( IDirectPlay *iface, DPID player, LPSTR name,
506 DWORD *size_name, LPSTR fullname, DWORD *size_fullname )
508 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
509 FIXME( "(%p)->(0x%08x,%p,%p,%p,%p): stub\n", This, player, name, size_name, fullname,
510 size_fullname );
511 return E_NOTIMPL;
514 static HRESULT WINAPI IDirectPlayImpl_Initialize( IDirectPlay *iface, GUID *guid )
516 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
517 FIXME( "(%p)->(%p): stub\n", This, guid );
518 return E_NOTIMPL;
521 static HRESULT WINAPI IDirectPlayImpl_Open( IDirectPlay *iface, DPSESSIONDESC *sdesc )
523 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
524 FIXME( "(%p)->(%p): stub\n", This, sdesc );
525 return E_NOTIMPL;
528 static HRESULT WINAPI IDirectPlayImpl_Receive( IDirectPlay *iface, DPID *from, DPID *to,
529 DWORD flags, void *data, DWORD *size )
531 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
532 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p): stub\n", This, from, to, flags, data, size );
533 return E_NOTIMPL;
536 static HRESULT WINAPI IDirectPlayImpl_SaveSession( IDirectPlay *iface, LPSTR reserved )
538 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
539 FIXME( "(%p)->(%p): stub\n", This, reserved );
540 return E_NOTIMPL;
543 static HRESULT WINAPI IDirectPlayImpl_Send( IDirectPlay *iface, DPID from, DPID to, DWORD flags,
544 void *data, DWORD size )
546 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
547 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%u): stub\n", This, from, to, flags, data, size );
548 return E_NOTIMPL;
551 static HRESULT WINAPI IDirectPlayImpl_SetPlayerName( IDirectPlay *iface, DPID player, LPSTR name,
552 LPSTR fullname )
554 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
555 FIXME( "(%p)->(0x%08x,%s,%s): stub\n", This, player, debugstr_a( name ),
556 debugstr_a ( fullname ) );
557 return E_NOTIMPL;
560 static const IDirectPlayVtbl dp_vt =
562 IDirectPlayImpl_QueryInterface,
563 IDirectPlayImpl_AddRef,
564 IDirectPlayImpl_Release,
565 IDirectPlayImpl_AddPlayerToGroup,
566 IDirectPlayImpl_Close,
567 IDirectPlayImpl_CreatePlayer,
568 IDirectPlayImpl_CreateGroup,
569 IDirectPlayImpl_DeletePlayerFromGroup,
570 IDirectPlayImpl_DestroyPlayer,
571 IDirectPlayImpl_DestroyGroup,
572 IDirectPlayImpl_EnableNewPlayers,
573 IDirectPlayImpl_EnumGroupPlayers,
574 IDirectPlayImpl_EnumGroups,
575 IDirectPlayImpl_EnumPlayers,
576 IDirectPlayImpl_EnumSessions,
577 IDirectPlayImpl_GetCaps,
578 IDirectPlayImpl_GetMessageCount,
579 IDirectPlayImpl_GetPlayerCaps,
580 IDirectPlayImpl_GetPlayerName,
581 IDirectPlayImpl_Initialize,
582 IDirectPlayImpl_Open,
583 IDirectPlayImpl_Receive,
584 IDirectPlayImpl_SaveSession,
585 IDirectPlayImpl_Send,
586 IDirectPlayImpl_SetPlayerName,
590 static HRESULT WINAPI IDirectPlay2AImpl_QueryInterface( IDirectPlay2A *iface, REFIID riid,
591 void **ppv )
593 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
594 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
597 static HRESULT WINAPI IDirectPlay2Impl_QueryInterface( IDirectPlay2 *iface, REFIID riid,
598 void **ppv )
600 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
601 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
604 static HRESULT WINAPI IDirectPlay3AImpl_QueryInterface( IDirectPlay3A *iface, REFIID riid,
605 void **ppv )
607 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
608 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
611 static HRESULT WINAPI IDirectPlay3Impl_QueryInterface( IDirectPlay3 *iface, REFIID riid,
612 void **ppv )
614 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
615 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
618 static HRESULT WINAPI IDirectPlay4AImpl_QueryInterface( IDirectPlay4A *iface, REFIID riid,
619 void **ppv )
621 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
622 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
625 static HRESULT WINAPI IDirectPlay4Impl_QueryInterface( IDirectPlay4 *iface, REFIID riid,
626 void **ppv )
628 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
630 if ( IsEqualGUID( &IID_IUnknown, riid ) )
632 TRACE( "(%p)->(IID_IUnknown %p)\n", This, ppv );
633 *ppv = &This->IDirectPlay_iface;
635 else if ( IsEqualGUID( &IID_IDirectPlay, riid ) )
637 TRACE( "(%p)->(IID_IDirectPlay %p)\n", This, ppv );
638 *ppv = &This->IDirectPlay_iface;
640 else if ( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
642 TRACE( "(%p)->(IID_IDirectPlay2A %p)\n", This, ppv );
643 *ppv = &This->IDirectPlay2A_iface;
645 else if ( IsEqualGUID( &IID_IDirectPlay2, riid ) )
647 TRACE( "(%p)->(IID_IDirectPlay2 %p)\n", This, ppv );
648 *ppv = &This->IDirectPlay2_iface;
650 else if ( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
652 TRACE( "(%p)->(IID_IDirectPlay3A %p)\n", This, ppv );
653 *ppv = &This->IDirectPlay3A_iface;
655 else if ( IsEqualGUID( &IID_IDirectPlay3, riid ) )
657 TRACE( "(%p)->(IID_IDirectPlay3 %p)\n", This, ppv );
658 *ppv = &This->IDirectPlay3_iface;
660 else if ( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
662 TRACE( "(%p)->(IID_IDirectPlay4A %p)\n", This, ppv );
663 *ppv = &This->IDirectPlay4A_iface;
665 else if ( IsEqualGUID( &IID_IDirectPlay4, riid ) )
667 TRACE( "(%p)->(IID_IDirectPlay4 %p)\n", This, ppv );
668 *ppv = &This->IDirectPlay4_iface;
670 else
672 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
673 *ppv = NULL;
674 return E_NOINTERFACE;
677 IUnknown_AddRef((IUnknown*)*ppv);
678 return S_OK;
681 static ULONG WINAPI IDirectPlay2AImpl_AddRef( IDirectPlay2A *iface )
683 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
684 ULONG ref = InterlockedIncrement( &This->ref2A );
686 TRACE( "(%p) ref2A=%d\n", This, ref );
688 if ( ref == 1 )
689 InterlockedIncrement( &This->numIfaces );
691 return ref;
694 static ULONG WINAPI IDirectPlay2Impl_AddRef( IDirectPlay2 *iface )
696 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
697 ULONG ref = InterlockedIncrement( &This->ref2 );
699 TRACE( "(%p) ref2=%d\n", This, ref );
701 if ( ref == 1 )
702 InterlockedIncrement( &This->numIfaces );
704 return ref;
707 static ULONG WINAPI IDirectPlay3AImpl_AddRef( IDirectPlay3A *iface )
709 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
710 ULONG ref = InterlockedIncrement( &This->ref3A );
712 TRACE( "(%p) ref3A=%d\n", This, ref );
714 if ( ref == 1 )
715 InterlockedIncrement( &This->numIfaces );
717 return ref;
720 static ULONG WINAPI IDirectPlay3Impl_AddRef( IDirectPlay3 *iface )
722 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
723 ULONG ref = InterlockedIncrement( &This->ref3 );
725 TRACE( "(%p) ref3=%d\n", This, ref );
727 if ( ref == 1 )
728 InterlockedIncrement( &This->numIfaces );
730 return ref;
733 static ULONG WINAPI IDirectPlay4AImpl_AddRef(IDirectPlay4A *iface)
735 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
736 ULONG ref = InterlockedIncrement( &This->ref4A );
738 TRACE( "(%p) ref4A=%d\n", This, ref );
740 if ( ref == 1 )
741 InterlockedIncrement( &This->numIfaces );
743 return ref;
746 static ULONG WINAPI IDirectPlay4Impl_AddRef(IDirectPlay4 *iface)
748 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
749 ULONG ref = InterlockedIncrement( &This->ref4 );
751 TRACE( "(%p) ref4=%d\n", This, ref );
753 if ( ref == 1 )
754 InterlockedIncrement( &This->numIfaces );
756 return ref;
759 static ULONG WINAPI IDirectPlay2AImpl_Release( IDirectPlay2A *iface )
761 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
762 ULONG ref = InterlockedDecrement( &This->ref2A );
764 TRACE( "(%p) ref2A=%d\n", This, ref );
766 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
767 dplay_destroy( This );
769 return ref;
772 static ULONG WINAPI IDirectPlay2Impl_Release( IDirectPlay2 *iface )
774 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
775 ULONG ref = InterlockedDecrement( &This->ref2 );
777 TRACE( "(%p) ref2=%d\n", This, ref );
779 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
780 dplay_destroy( This );
782 return ref;
785 static ULONG WINAPI IDirectPlay3AImpl_Release( IDirectPlay3A *iface )
787 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
788 ULONG ref = InterlockedDecrement( &This->ref3A );
790 TRACE( "(%p) ref3A=%d\n", This, ref );
792 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
793 dplay_destroy( This );
795 return ref;
798 static ULONG WINAPI IDirectPlay3Impl_Release( IDirectPlay3 *iface )
800 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
801 ULONG ref = InterlockedDecrement( &This->ref3 );
803 TRACE( "(%p) ref3=%d\n", This, ref );
805 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
806 dplay_destroy( This );
808 return ref;
811 static ULONG WINAPI IDirectPlay4AImpl_Release(IDirectPlay4A *iface)
813 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
814 ULONG ref = InterlockedDecrement( &This->ref4A );
816 TRACE( "(%p) ref4A=%d\n", This, ref );
818 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
819 dplay_destroy( This );
821 return ref;
824 static ULONG WINAPI IDirectPlay4Impl_Release(IDirectPlay4 *iface)
826 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
827 ULONG ref = InterlockedDecrement( &This->ref4 );
829 TRACE( "(%p) ref4=%d\n", This, ref );
831 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
832 dplay_destroy( This );
834 return ref;
837 static HRESULT WINAPI IDirectPlay2AImpl_AddPlayerToGroup( IDirectPlay2A *iface, DPID group,
838 DPID player )
840 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
841 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4A_iface, group, player );
844 static HRESULT WINAPI IDirectPlay2Impl_AddPlayerToGroup( IDirectPlay2 *iface, DPID group,
845 DPID player )
847 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
848 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
851 static HRESULT WINAPI IDirectPlay3AImpl_AddPlayerToGroup( IDirectPlay3A *iface, DPID group,
852 DPID player )
854 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
855 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
858 static HRESULT WINAPI IDirectPlay3Impl_AddPlayerToGroup( IDirectPlay3 *iface, DPID group,
859 DPID player )
861 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
862 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
865 static HRESULT WINAPI IDirectPlay4AImpl_AddPlayerToGroup( IDirectPlay4A *iface, DPID group,
866 DPID player )
868 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
869 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
872 static HRESULT WINAPI IDirectPlay4Impl_AddPlayerToGroup( IDirectPlay4 *iface, DPID group,
873 DPID player )
875 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
876 lpGroupData gdata;
877 lpPlayerList plist;
878 lpPlayerList newplist;
880 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, group, player );
882 if ( This->dp2->connectionInitialized == NO_PROVIDER )
883 return DPERR_UNINITIALIZED;
885 /* Find the group */
886 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
887 return DPERR_INVALIDGROUP;
889 /* Find the player */
890 if ( ( plist = DP_FindPlayer( This, player ) ) == NULL )
891 return DPERR_INVALIDPLAYER;
893 /* Create a player list (ie "shortcut" ) */
894 newplist = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *newplist ) );
895 if ( !newplist )
896 return DPERR_CANTADDPLAYER;
898 /* Add the shortcut */
899 plist->lpPData->uRef++;
900 newplist->lpPData = plist->lpPData;
902 /* Add the player to the list of players for this group */
903 DPQ_INSERT(gdata->players, newplist, players);
905 /* Let the SP know that we've added a player to the group */
906 if ( This->dp2->spData.lpCB->AddPlayerToGroup )
908 DPSP_ADDPLAYERTOGROUPDATA data;
910 TRACE( "Calling SP AddPlayerToGroup\n" );
912 data.idPlayer = player;
913 data.idGroup = group;
914 data.lpISP = This->dp2->spData.lpISP;
916 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
919 /* Inform all other peers of the addition of player to the group. If there are
920 * no peers keep this event quiet.
921 * Also, if this event was the result of another machine sending it to us,
922 * don't bother rebroadcasting it.
924 if ( This->dp2->lpSessionDesc &&
925 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
927 DPMSG_ADDPLAYERTOGROUP msg;
928 msg.dwType = DPSYS_ADDPLAYERTOGROUP;
930 msg.dpIdGroup = group;
931 msg.dpIdPlayer = player;
933 /* FIXME: Correct to just use send effectively? */
934 /* FIXME: Should size include data w/ message or just message "header" */
935 /* FIXME: Check return code */
936 IDirectPlayX_SendEx( iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
937 0, 0, NULL, NULL );
940 return DP_OK;
943 static HRESULT WINAPI IDirectPlay2AImpl_Close( IDirectPlay2A *iface )
945 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
946 return IDirectPlayX_Close( &This->IDirectPlay4A_iface );
949 static HRESULT WINAPI IDirectPlay2Impl_Close( IDirectPlay2 *iface )
951 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
952 return IDirectPlayX_Close( &This->IDirectPlay4_iface );
955 static HRESULT WINAPI IDirectPlay3AImpl_Close( IDirectPlay3A *iface )
957 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
958 return IDirectPlayX_Close( &This->IDirectPlay4_iface );
961 static HRESULT WINAPI IDirectPlay3Impl_Close( IDirectPlay3 *iface )
963 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
964 return IDirectPlayX_Close( &This->IDirectPlay4_iface );
967 static HRESULT WINAPI IDirectPlay4AImpl_Close( IDirectPlay4A *iface )
969 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
970 return IDirectPlayX_Close( &This->IDirectPlay4_iface);
973 static HRESULT WINAPI IDirectPlay4Impl_Close( IDirectPlay4 *iface )
975 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
976 HRESULT hr = DP_OK;
978 TRACE( "(%p)\n", This );
980 /* FIXME: Need to find a new host I assume (how?) */
981 /* FIXME: Need to destroy all local groups */
982 /* FIXME: Need to migrate all remotely visible players to the new host */
984 /* Invoke the SP callback to inform of session close */
985 if( This->dp2->spData.lpCB->CloseEx )
987 DPSP_CLOSEDATA data;
989 TRACE( "Calling SP CloseEx\n" );
990 data.lpISP = This->dp2->spData.lpISP;
991 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
993 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
995 TRACE( "Calling SP Close (obsolete interface)\n" );
996 hr = (*This->dp2->spData.lpCB->Close)();
999 return hr;
1002 static lpGroupData DP_CreateGroup( IDirectPlayImpl *This, const DPID *lpid, const DPNAME *lpName,
1003 DWORD dwFlags, DPID idParent, BOOL bAnsi )
1005 lpGroupData lpGData;
1007 /* Allocate the new space and add to end of high level group list */
1008 lpGData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGData ) );
1010 if( lpGData == NULL )
1012 return NULL;
1015 DPQ_INIT(lpGData->groups);
1016 DPQ_INIT(lpGData->players);
1018 /* Set the desired player ID - no sanity checking to see if it exists */
1019 lpGData->dpid = *lpid;
1021 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
1023 /* FIXME: Should we check that the parent exists? */
1024 lpGData->parent = idParent;
1026 /* FIXME: Should we validate the dwFlags? */
1027 lpGData->dwFlags = dwFlags;
1029 TRACE( "Created group id 0x%08x\n", *lpid );
1031 return lpGData;
1034 /* This method assumes that all links to it are already deleted */
1035 static void DP_DeleteGroup( IDirectPlayImpl *This, DPID dpid )
1037 lpGroupList lpGList;
1039 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1041 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
1043 if( lpGList == NULL )
1045 ERR( "DPID 0x%08x not found\n", dpid );
1046 return;
1049 if( --(lpGList->lpGData->uRef) )
1051 FIXME( "Why is this not the last reference to group?\n" );
1052 DebugBreak();
1055 /* Delete player */
1056 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
1057 HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
1059 /* Remove and Delete Player List object */
1060 HeapFree( GetProcessHeap(), 0, lpGList );
1064 static lpGroupData DP_FindAnyGroup( IDirectPlayImpl *This, DPID dpid )
1066 lpGroupList lpGroups;
1068 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1070 if( dpid == DPID_SYSTEM_GROUP )
1072 return This->dp2->lpSysGroup;
1074 else
1076 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
1079 if( lpGroups == NULL )
1081 return NULL;
1084 return lpGroups->lpGData;
1087 static HRESULT DP_IF_CreateGroup( IDirectPlayImpl *This, void *lpMsgHdr, DPID *lpidGroup,
1088 DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
1090 lpGroupData lpGData;
1092 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1093 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
1094 dwFlags, bAnsi );
1096 if( This->dp2->connectionInitialized == NO_PROVIDER )
1098 return DPERR_UNINITIALIZED;
1101 /* If the name is not specified, we must provide one */
1102 if( DPID_UNKNOWN == *lpidGroup )
1104 /* If we are the name server, we decide on the group ids. If not, we
1105 * must ask for one before attempting a creation.
1107 if( This->dp2->bHostInterface )
1109 *lpidGroup = DP_NextObjectId();
1111 else
1113 *lpidGroup = DP_GetRemoteNextObjectId();
1117 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
1118 DPID_NOPARENT_GROUP, bAnsi );
1120 if( lpGData == NULL )
1122 return DPERR_CANTADDPLAYER; /* yes player not group */
1125 if( DPID_SYSTEM_GROUP == *lpidGroup )
1127 This->dp2->lpSysGroup = lpGData;
1128 TRACE( "Inserting system group\n" );
1130 else
1132 /* Insert into the system group */
1133 lpGroupList lpGroup = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGroup ) );
1134 lpGroup->lpGData = lpGData;
1136 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
1139 /* Something is now referencing this data */
1140 lpGData->uRef++;
1142 /* Set all the important stuff for the group */
1143 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
1145 /* FIXME: We should only create the system group if GetCaps returns
1146 * DPCAPS_GROUPOPTIMIZED.
1149 /* Let the SP know that we've created this group */
1150 if( This->dp2->spData.lpCB->CreateGroup )
1152 DPSP_CREATEGROUPDATA data;
1153 DWORD dwCreateFlags = 0;
1155 TRACE( "Calling SP CreateGroup\n" );
1157 if( *lpidGroup == DPID_NOPARENT_GROUP )
1158 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
1160 if( lpMsgHdr == NULL )
1161 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1163 if( dwFlags & DPGROUP_HIDDEN )
1164 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
1166 data.idGroup = *lpidGroup;
1167 data.dwFlags = dwCreateFlags;
1168 data.lpSPMessageHeader = lpMsgHdr;
1169 data.lpISP = This->dp2->spData.lpISP;
1171 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1174 /* Inform all other peers of the creation of a new group. If there are
1175 * no peers keep this event quiet.
1176 * Also if this message was sent to us, don't rebroadcast.
1178 if( ( lpMsgHdr == NULL ) &&
1179 This->dp2->lpSessionDesc &&
1180 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1182 DPMSG_CREATEPLAYERORGROUP msg;
1183 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1185 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1186 msg.dpId = *lpidGroup;
1187 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1188 msg.lpData = lpData;
1189 msg.dwDataSize = dwDataSize;
1190 msg.dpnName = *lpGroupName;
1191 msg.dpIdParent = DPID_NOPARENT_GROUP;
1192 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
1194 /* FIXME: Correct to just use send effectively? */
1195 /* FIXME: Should size include data w/ message or just message "header" */
1196 /* FIXME: Check return code */
1197 IDirectPlayX_SendEx( &This->IDirectPlay4_iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
1198 sizeof( msg ), 0, 0, NULL, NULL );
1201 return DP_OK;
1204 static HRESULT WINAPI IDirectPlay2AImpl_CreateGroup( IDirectPlay2A *iface, DPID *lpidGroup,
1205 DPNAME *name, void *data, DWORD size, DWORD flags )
1207 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
1208 return IDirectPlayX_CreateGroup( &This->IDirectPlay4A_iface, lpidGroup, name, data, size,
1209 flags );
1212 static HRESULT WINAPI IDirectPlay2Impl_CreateGroup( IDirectPlay2 *iface, DPID *lpidGroup,
1213 DPNAME *name, void *data, DWORD size, DWORD flags )
1215 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
1216 return IDirectPlayX_CreateGroup( &This->IDirectPlay4_iface, lpidGroup, name, data, size,
1217 flags );
1220 static HRESULT WINAPI IDirectPlay3AImpl_CreateGroup( IDirectPlay3A *iface, DPID *group,
1221 DPNAME *name, void *data, DWORD size, DWORD flags )
1223 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
1224 return IDirectPlayX_CreateGroup( &This->IDirectPlay4_iface, group, name, data, size,
1225 flags );
1228 static HRESULT WINAPI IDirectPlay3Impl_CreateGroup( IDirectPlay3 *iface, DPID *lpidGroup,
1229 DPNAME *name, void *data, DWORD size, DWORD flags )
1231 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
1232 return IDirectPlayX_CreateGroup( &This->IDirectPlay4_iface, lpidGroup, name, data, size,
1233 flags );
1236 static HRESULT WINAPI IDirectPlay4AImpl_CreateGroup( IDirectPlay4A *iface, DPID *lpidGroup,
1237 DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1239 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
1241 *lpidGroup = DPID_UNKNOWN;
1243 return DP_IF_CreateGroup( This, NULL, lpidGroup, lpGroupName, lpData, dwDataSize, dwFlags,
1244 TRUE );
1247 static HRESULT WINAPI IDirectPlay4Impl_CreateGroup( IDirectPlay4 *iface, DPID *lpidGroup,
1248 DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1250 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
1252 *lpidGroup = DPID_UNKNOWN;
1254 return DP_IF_CreateGroup( This, NULL, lpidGroup, lpGroupName, lpData, dwDataSize, dwFlags,
1255 FALSE );
1259 static void
1260 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
1261 LPVOID lpData, DWORD dwDataSize )
1263 /* Clear out the data with this player */
1264 if( dwFlags & DPSET_LOCAL )
1266 if ( lpGData->dwLocalDataSize != 0 )
1268 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
1269 lpGData->lpLocalData = NULL;
1270 lpGData->dwLocalDataSize = 0;
1273 else
1275 if( lpGData->dwRemoteDataSize != 0 )
1277 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
1278 lpGData->lpRemoteData = NULL;
1279 lpGData->dwRemoteDataSize = 0;
1283 /* Reallocate for new data */
1284 if( lpData != NULL )
1286 if( dwFlags & DPSET_LOCAL )
1288 lpGData->lpLocalData = lpData;
1289 lpGData->dwLocalDataSize = dwDataSize;
1291 else
1293 lpGData->lpRemoteData = HeapAlloc( GetProcessHeap(), 0, dwDataSize );
1294 CopyMemory( lpGData->lpRemoteData, lpData, dwDataSize );
1295 lpGData->dwRemoteDataSize = dwDataSize;
1301 /* This function will just create the storage for the new player. */
1302 static lpPlayerData DP_CreatePlayer( IDirectPlayImpl *This, DPID *lpid, DPNAME *lpName,
1303 DWORD dwFlags, HANDLE hEvent, BOOL bAnsi )
1305 lpPlayerData lpPData;
1307 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
1309 /* Allocate the storage for the player and associate it with list element */
1310 lpPData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPData ) );
1311 if( lpPData == NULL )
1313 return NULL;
1316 /* Set the desired player ID */
1317 lpPData->dpid = *lpid;
1319 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
1321 lpPData->dwFlags = dwFlags;
1323 /* If we were given an event handle, duplicate it */
1324 if( hEvent != 0 )
1326 if( !DuplicateHandle( GetCurrentProcess(), hEvent,
1327 GetCurrentProcess(), &lpPData->hEvent,
1328 0, FALSE, DUPLICATE_SAME_ACCESS )
1331 /* FIXME: Memory leak */
1332 ERR( "Can't duplicate player msg handle %p\n", hEvent );
1336 /* Initialize the SP data section */
1337 lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData();
1339 TRACE( "Created player id 0x%08x\n", *lpid );
1341 if( ~dwFlags & DPLAYI_PLAYER_SYSPLAYER )
1342 This->dp2->lpSessionDesc->dwCurrentPlayers++;
1344 return lpPData;
1347 /* Delete the contents of the DPNAME struct */
1348 static void
1349 DP_DeleteDPNameStruct( LPDPNAME lpDPName )
1351 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u1.lpszShortNameA );
1352 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u2.lpszLongNameA );
1355 /* This method assumes that all links to it are already deleted */
1356 static void DP_DeletePlayer( IDirectPlayImpl *This, DPID dpid )
1358 lpPlayerList lpPList;
1360 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1362 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1364 if( lpPList == NULL )
1366 ERR( "DPID 0x%08x not found\n", dpid );
1367 return;
1370 /* Verify that this is the last reference to the data */
1371 if( --(lpPList->lpPData->uRef) )
1373 FIXME( "Why is this not the last reference to player?\n" );
1374 DebugBreak();
1377 /* Delete player */
1378 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1380 CloseHandle( lpPList->lpPData->hEvent );
1381 HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
1383 /* Delete Player List object */
1384 HeapFree( GetProcessHeap(), 0, lpPList );
1387 static lpPlayerList DP_FindPlayer( IDirectPlayImpl *This, DPID dpid )
1389 lpPlayerList lpPlayers;
1391 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1393 if(This->dp2->lpSysGroup == NULL)
1394 return NULL;
1396 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1398 return lpPlayers;
1401 /* Basic area for Dst must already be allocated */
1402 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, const DPNAME *lpSrc, BOOL bAnsi )
1404 if( lpSrc == NULL )
1406 ZeroMemory( lpDst, sizeof( *lpDst ) );
1407 lpDst->dwSize = sizeof( *lpDst );
1408 return TRUE;
1411 if( lpSrc->dwSize != sizeof( *lpSrc) )
1413 return FALSE;
1416 /* Delete any existing pointers */
1417 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1418 HeapFree( GetProcessHeap(), 0, lpDst->u2.lpszLongNameA );
1420 /* Copy as required */
1421 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1423 if( bAnsi )
1425 if( lpSrc->u1.lpszShortNameA )
1427 lpDst->u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), 0,
1428 strlen(lpSrc->u1.lpszShortNameA)+1 );
1429 strcpy( lpDst->u1.lpszShortNameA, lpSrc->u1.lpszShortNameA );
1431 if( lpSrc->u2.lpszLongNameA )
1433 lpDst->u2.lpszLongNameA = HeapAlloc( GetProcessHeap(), 0,
1434 strlen(lpSrc->u2.lpszLongNameA)+1 );
1435 strcpy( lpDst->u2.lpszLongNameA, lpSrc->u2.lpszLongNameA );
1438 else
1440 if( lpSrc->u1.lpszShortNameA )
1442 lpDst->u1.lpszShortName = HeapAlloc( GetProcessHeap(), 0,
1443 (strlenW(lpSrc->u1.lpszShortName)+1)*sizeof(WCHAR) );
1444 strcpyW( lpDst->u1.lpszShortName, lpSrc->u1.lpszShortName );
1446 if( lpSrc->u2.lpszLongNameA )
1448 lpDst->u2.lpszLongName = HeapAlloc( GetProcessHeap(), 0,
1449 (strlenW(lpSrc->u2.lpszLongName)+1)*sizeof(WCHAR) );
1450 strcpyW( lpDst->u2.lpszLongName, lpSrc->u2.lpszLongName );
1454 return TRUE;
1457 static void
1458 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
1459 LPVOID lpData, DWORD dwDataSize )
1461 /* Clear out the data with this player */
1462 if( dwFlags & DPSET_LOCAL )
1464 if ( lpPData->dwLocalDataSize != 0 )
1466 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
1467 lpPData->lpLocalData = NULL;
1468 lpPData->dwLocalDataSize = 0;
1471 else
1473 if( lpPData->dwRemoteDataSize != 0 )
1475 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
1476 lpPData->lpRemoteData = NULL;
1477 lpPData->dwRemoteDataSize = 0;
1481 /* Reallocate for new data */
1482 if( lpData != NULL )
1485 if( dwFlags & DPSET_LOCAL )
1487 lpPData->lpLocalData = lpData;
1488 lpPData->dwLocalDataSize = dwDataSize;
1490 else
1492 lpPData->lpRemoteData = HeapAlloc( GetProcessHeap(), 0, dwDataSize );
1493 CopyMemory( lpPData->lpRemoteData, lpData, dwDataSize );
1494 lpPData->dwRemoteDataSize = dwDataSize;
1500 /* Note: lpMsgHdr is NULL for local creation, non NULL for remote creation */
1501 static HRESULT DP_IF_CreatePlayer( IDirectPlayImpl *This, void *lpMsgHdr, DPID *lpidPlayer,
1502 DPNAME *lpPlayerName, HANDLE hEvent, void *lpData, DWORD dwDataSize, DWORD dwFlags,
1503 BOOL bAnsi )
1505 HRESULT hr = DP_OK;
1506 lpPlayerData lpPData;
1507 lpPlayerList lpPList;
1508 DWORD dwCreateFlags = 0;
1510 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1511 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1512 dwDataSize, dwFlags, bAnsi );
1513 if( This->dp2->connectionInitialized == NO_PROVIDER )
1515 return DPERR_UNINITIALIZED;
1518 if( dwFlags == 0 )
1520 dwFlags = DPPLAYER_SPECTATOR;
1523 if( lpidPlayer == NULL )
1525 return DPERR_INVALIDPARAMS;
1529 /* Determine the creation flags for the player. These will be passed
1530 * to the name server if requesting a player id and to the SP when
1531 * informing it of the player creation
1534 if( dwFlags & DPPLAYER_SERVERPLAYER )
1536 if( *lpidPlayer == DPID_SERVERPLAYER )
1538 /* Server player for the host interface */
1539 dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
1541 else if( *lpidPlayer == DPID_NAME_SERVER )
1543 /* Name server - master of everything */
1544 dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
1546 else
1548 /* Server player for a non host interface */
1549 dwCreateFlags |= DPLAYI_PLAYER_SYSPLAYER;
1553 if( lpMsgHdr == NULL )
1554 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1557 /* Verify we know how to handle all the flags */
1558 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1559 ( dwFlags & DPPLAYER_SPECTATOR )
1563 /* Assume non fatal failure */
1564 ERR( "unknown dwFlags = 0x%08x\n", dwFlags );
1567 /* If the name is not specified, we must provide one */
1568 if( *lpidPlayer == DPID_UNKNOWN )
1570 /* If we are the session master, we dish out the group/player ids */
1571 if( This->dp2->bHostInterface )
1573 *lpidPlayer = DP_NextObjectId();
1575 else
1577 hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer );
1579 if( FAILED(hr) )
1581 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1582 return hr;
1586 else
1588 /* FIXME: Would be nice to perhaps verify that we don't already have
1589 * this player.
1593 /* We pass creation flags, so we can distinguish sysplayers and not count them in the current
1594 player total */
1595 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwCreateFlags,
1596 hEvent, bAnsi );
1597 /* Create the list object and link it in */
1598 lpPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPList ) );
1599 if( !lpPData || !lpPList )
1601 HeapFree( GetProcessHeap(), 0, lpPData );
1602 HeapFree( GetProcessHeap(), 0, lpPList );
1603 return DPERR_CANTADDPLAYER;
1606 lpPData->uRef = 1;
1607 lpPList->lpPData = lpPData;
1609 /* Add the player to the system group */
1610 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1612 /* Update the information and send it to all players in the session */
1613 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
1615 /* Let the SP know that we've created this player */
1616 if( This->dp2->spData.lpCB->CreatePlayer )
1618 DPSP_CREATEPLAYERDATA data;
1620 data.idPlayer = *lpidPlayer;
1621 data.dwFlags = dwCreateFlags;
1622 data.lpSPMessageHeader = lpMsgHdr;
1623 data.lpISP = This->dp2->spData.lpISP;
1625 TRACE( "Calling SP CreatePlayer 0x%08x: dwFlags: 0x%08x lpMsgHdr: %p\n",
1626 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
1628 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1631 if( FAILED(hr) )
1633 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1634 return hr;
1637 /* Now let the SP know that this player is a member of the system group */
1638 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1640 DPSP_ADDPLAYERTOGROUPDATA data;
1642 data.idPlayer = *lpidPlayer;
1643 data.idGroup = DPID_SYSTEM_GROUP;
1644 data.lpISP = This->dp2->spData.lpISP;
1646 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1648 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1651 if( FAILED(hr) )
1653 ERR( "Failed to add player to sys group with sp: %s\n",
1654 DPLAYX_HresultToString(hr) );
1655 return hr;
1658 #if 1
1659 if( !This->dp2->bHostInterface )
1661 /* Let the name server know about the creation of this player */
1662 /* FIXME: Is this only to be done for the creation of a server player or
1663 * is this used for regular players? If only for server players, move
1664 * this call to DP_SecureOpen(...);
1666 #if 0
1667 TRACE( "Sending message to self to get my addr\n" );
1668 DP_MSG_ToSelf( This, *lpidPlayer ); /* This is a hack right now */
1669 #endif
1671 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
1673 #else
1674 /* Inform all other peers of the creation of a new player. If there are
1675 * no peers keep this quiet.
1676 * Also, if this was a remote event, no need to rebroadcast it.
1678 if( ( lpMsgHdr == NULL ) &&
1679 This->dp2->lpSessionDesc &&
1680 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1682 DPMSG_CREATEPLAYERORGROUP msg;
1683 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1685 msg.dwPlayerType = DPPLAYERTYPE_PLAYER;
1686 msg.dpId = *lpidPlayer;
1687 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */
1688 msg.lpData = lpData;
1689 msg.dwDataSize = dwDataSize;
1690 msg.dpnName = *lpPlayerName;
1691 msg.dpIdParent = DPID_NOPARENT_GROUP;
1692 msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
1694 /* FIXME: Correct to just use send effectively? */
1695 /* FIXME: Should size include data w/ message or just message "header" */
1696 /* FIXME: Check return code */
1697 hr = IDirectPlayX_SendEx( &This->IDirectPlay4_iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0,
1698 &msg, sizeof( msg ), 0, 0, NULL, NULL );
1700 #endif
1702 return hr;
1705 static HRESULT WINAPI IDirectPlay2AImpl_CreatePlayer( IDirectPlay2A *iface, DPID *lpidPlayer,
1706 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags )
1708 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
1709 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4A_iface, lpidPlayer, name, event, data,
1710 size, flags );
1713 static HRESULT WINAPI IDirectPlay2Impl_CreatePlayer( IDirectPlay2 *iface, DPID *lpidPlayer,
1714 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags )
1716 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
1717 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4_iface, lpidPlayer, name, event, data,
1718 size, flags );
1721 static HRESULT WINAPI IDirectPlay3AImpl_CreatePlayer( IDirectPlay3A *iface, DPID *lpidPlayer,
1722 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags )
1724 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
1725 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4_iface, lpidPlayer, name, event, data,
1726 size, flags );
1729 static HRESULT WINAPI IDirectPlay3Impl_CreatePlayer( IDirectPlay3 *iface, DPID *lpidPlayer,
1730 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags )
1732 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
1733 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4_iface, lpidPlayer, name, event, data,
1734 size, flags );
1737 static HRESULT WINAPI IDirectPlay4AImpl_CreatePlayer( IDirectPlay4A *iface, DPID *lpidPlayer,
1738 DPNAME *lpPlayerName, HANDLE hEvent, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1740 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
1742 if( lpidPlayer == NULL )
1744 return DPERR_INVALIDPARAMS;
1747 if( dwFlags & DPPLAYER_SERVERPLAYER )
1749 *lpidPlayer = DPID_SERVERPLAYER;
1751 else
1753 *lpidPlayer = DPID_UNKNOWN;
1756 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1757 lpData, dwDataSize, dwFlags, TRUE );
1760 static HRESULT WINAPI IDirectPlay4Impl_CreatePlayer( IDirectPlay4 *iface, DPID *lpidPlayer,
1761 DPNAME *lpPlayerName, HANDLE hEvent, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1763 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
1765 if( lpidPlayer == NULL )
1767 return DPERR_INVALIDPARAMS;
1770 if( dwFlags & DPPLAYER_SERVERPLAYER )
1772 *lpidPlayer = DPID_SERVERPLAYER;
1774 else
1776 *lpidPlayer = DPID_UNKNOWN;
1779 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1780 lpData, dwDataSize, dwFlags, FALSE );
1783 static DPID DP_GetRemoteNextObjectId(void)
1785 FIXME( ":stub\n" );
1787 /* Hack solution */
1788 return DP_NextObjectId();
1791 static HRESULT WINAPI IDirectPlay2AImpl_DeletePlayerFromGroup( IDirectPlay2A *iface, DPID group,
1792 DPID player )
1794 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
1795 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4A_iface, group, player );
1798 static HRESULT WINAPI IDirectPlay2Impl_DeletePlayerFromGroup( IDirectPlay2 *iface, DPID group,
1799 DPID player )
1801 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
1802 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1805 static HRESULT WINAPI IDirectPlay3AImpl_DeletePlayerFromGroup( IDirectPlay3A *iface, DPID group,
1806 DPID player )
1808 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
1809 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1812 static HRESULT WINAPI IDirectPlay3Impl_DeletePlayerFromGroup( IDirectPlay3 *iface, DPID group,
1813 DPID player )
1815 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
1816 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1819 static HRESULT WINAPI IDirectPlay4AImpl_DeletePlayerFromGroup( IDirectPlay4A *iface, DPID group,
1820 DPID player )
1822 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
1823 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1826 static HRESULT WINAPI IDirectPlay4Impl_DeletePlayerFromGroup( IDirectPlay4 *iface, DPID group,
1827 DPID player )
1829 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
1830 HRESULT hr = DP_OK;
1832 lpGroupData gdata;
1833 lpPlayerList plist;
1835 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, group, player );
1837 /* Find the group */
1838 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
1839 return DPERR_INVALIDGROUP;
1841 /* Find the player */
1842 if ( DP_FindPlayer( This, player ) == NULL )
1843 return DPERR_INVALIDPLAYER;
1845 /* Remove the player shortcut from the group */
1846 DPQ_REMOVE_ENTRY( gdata->players, players, lpPData->dpid, ==, player, plist );
1848 if ( !plist )
1849 return DPERR_INVALIDPLAYER;
1851 /* One less reference */
1852 plist->lpPData->uRef--;
1854 /* Delete the Player List element */
1855 HeapFree( GetProcessHeap(), 0, plist );
1857 /* Inform the SP if they care */
1858 if ( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1860 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1862 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1863 data.idPlayer = player;
1864 data.idGroup = group;
1865 data.lpISP = This->dp2->spData.lpISP;
1866 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1869 /* Need to send a DELETEPLAYERFROMGROUP message */
1870 FIXME( "Need to send a message\n" );
1872 return hr;
1875 typedef struct _DPRGOPContext
1877 IDirectPlayImpl *This;
1878 BOOL bAnsi;
1879 DPID idGroup;
1880 } DPRGOPContext, *lpDPRGOPContext;
1882 static BOOL CALLBACK
1883 cbRemoveGroupOrPlayer(
1884 DPID dpId,
1885 DWORD dwPlayerType,
1886 LPCDPNAME lpName,
1887 DWORD dwFlags,
1888 LPVOID lpContext )
1890 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1892 TRACE( "Removing element:0x%08x (type:0x%08x) from element:0x%08x\n",
1893 dpId, dwPlayerType, lpCtxt->idGroup );
1895 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1897 if ( FAILED( IDirectPlayX_DeleteGroupFromGroup( &lpCtxt->This->IDirectPlay4_iface,
1898 lpCtxt->idGroup, dpId ) ) )
1899 ERR( "Unable to delete group 0x%08x from group 0x%08x\n", dpId, lpCtxt->idGroup );
1901 else if ( FAILED( IDirectPlayX_DeletePlayerFromGroup( &lpCtxt->This->IDirectPlay4_iface,
1902 lpCtxt->idGroup, dpId ) ) )
1903 ERR( "Unable to delete player 0x%08x from grp 0x%08x\n", dpId, lpCtxt->idGroup );
1905 return TRUE; /* Continue enumeration */
1908 static HRESULT DP_IF_DestroyGroup( IDirectPlayImpl *This, void *lpMsgHdr, DPID idGroup, BOOL bAnsi )
1910 lpGroupData lpGData;
1911 DPRGOPContext context;
1913 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1914 This, lpMsgHdr, idGroup, bAnsi );
1916 /* Find the group */
1917 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1919 return DPERR_INVALIDPLAYER; /* yes player */
1922 context.This = This;
1923 context.bAnsi = bAnsi;
1924 context.idGroup = idGroup;
1926 /* Remove all players that this group has */
1927 IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, idGroup, NULL, cbRemoveGroupOrPlayer,
1928 &context, 0 );
1930 /* Remove all links to groups that this group has since this is dp3 */
1931 IDirectPlayX_EnumGroupsInGroup( &This->IDirectPlay4_iface, idGroup, NULL, cbRemoveGroupOrPlayer,
1932 (void*)&context, 0 );
1934 /* Remove this group from the parent group - if it has one */
1935 if( ( idGroup != DPID_SYSTEM_GROUP ) && ( lpGData->parent != DPID_SYSTEM_GROUP ) )
1936 IDirectPlayX_DeleteGroupFromGroup( &This->IDirectPlay4_iface, lpGData->parent, idGroup );
1938 /* Now delete this group data and list from the system group */
1939 DP_DeleteGroup( This, idGroup );
1941 /* Let the SP know that we've destroyed this group */
1942 if( This->dp2->spData.lpCB->DeleteGroup )
1944 DPSP_DELETEGROUPDATA data;
1946 FIXME( "data.dwFlags is incorrect\n" );
1948 data.idGroup = idGroup;
1949 data.dwFlags = 0;
1950 data.lpISP = This->dp2->spData.lpISP;
1952 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1955 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1957 return DP_OK;
1960 static HRESULT WINAPI IDirectPlay2AImpl_DestroyGroup( IDirectPlay2A *iface, DPID group )
1962 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
1963 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4A_iface, group );
1966 static HRESULT WINAPI IDirectPlay2Impl_DestroyGroup( IDirectPlay2 *iface, DPID group )
1968 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
1969 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4_iface, group );
1972 static HRESULT WINAPI IDirectPlay3AImpl_DestroyGroup( IDirectPlay3A *iface, DPID group )
1974 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
1975 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4_iface, group );
1978 static HRESULT WINAPI IDirectPlay3Impl_DestroyGroup( IDirectPlay3 *iface, DPID group )
1980 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
1981 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4_iface, group );
1984 static HRESULT WINAPI IDirectPlay4AImpl_DestroyGroup( IDirectPlay4A *iface, DPID idGroup )
1986 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
1987 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
1990 static HRESULT WINAPI IDirectPlay4Impl_DestroyGroup( IDirectPlay4 *iface, DPID idGroup )
1992 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
1993 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
1996 typedef struct _DPFAGContext
1998 IDirectPlayImpl *This;
1999 DPID idPlayer;
2000 BOOL bAnsi;
2001 } DPFAGContext, *lpDPFAGContext;
2003 static HRESULT DP_IF_DestroyPlayer( IDirectPlayImpl *This, void *lpMsgHdr, DPID idPlayer,
2004 BOOL bAnsi )
2006 DPFAGContext cbContext;
2008 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
2009 This, lpMsgHdr, idPlayer, bAnsi );
2011 if( This->dp2->connectionInitialized == NO_PROVIDER )
2013 return DPERR_UNINITIALIZED;
2016 if( DP_FindPlayer( This, idPlayer ) == NULL )
2018 return DPERR_INVALIDPLAYER;
2021 /* FIXME: If the player is remote, we must be the host to delete this */
2023 cbContext.This = This;
2024 cbContext.idPlayer = idPlayer;
2025 cbContext.bAnsi = bAnsi;
2027 /* Find each group and call DeletePlayerFromGroup if the player is a
2028 member of the group */
2029 IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, NULL, cbDeletePlayerFromAllGroups, &cbContext,
2030 DPENUMGROUPS_ALL );
2032 /* Now delete player and player list from the sys group */
2033 DP_DeletePlayer( This, idPlayer );
2035 /* Let the SP know that we've destroyed this group */
2036 if( This->dp2->spData.lpCB->DeletePlayer )
2038 DPSP_DELETEPLAYERDATA data;
2040 FIXME( "data.dwFlags is incorrect\n" );
2042 data.idPlayer = idPlayer;
2043 data.dwFlags = 0;
2044 data.lpISP = This->dp2->spData.lpISP;
2046 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
2049 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
2051 return DP_OK;
2054 static BOOL CALLBACK
2055 cbDeletePlayerFromAllGroups(
2056 DPID dpId,
2057 DWORD dwPlayerType,
2058 LPCDPNAME lpName,
2059 DWORD dwFlags,
2060 LPVOID lpContext )
2062 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
2064 if( dwPlayerType == DPPLAYERTYPE_GROUP )
2066 IDirectPlayX_DeletePlayerFromGroup( &lpCtxt->This->IDirectPlay4_iface, dpId, lpCtxt->idPlayer );
2068 /* Enumerate all groups in this group since this will normally only
2069 * be called for top level groups
2071 IDirectPlayX_EnumGroupsInGroup( &lpCtxt->This->IDirectPlay4_iface, dpId, NULL,
2072 cbDeletePlayerFromAllGroups, lpContext, DPENUMGROUPS_ALL);
2075 else
2077 ERR( "Group callback has dwPlayerType = 0x%08x\n", dwPlayerType );
2080 return TRUE;
2083 static HRESULT WINAPI IDirectPlay2AImpl_DestroyPlayer( IDirectPlay2A *iface, DPID player )
2085 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2086 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4A_iface, player );
2089 static HRESULT WINAPI IDirectPlay2Impl_DestroyPlayer( IDirectPlay2 *iface, DPID player )
2091 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2092 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4_iface, player );
2095 static HRESULT WINAPI IDirectPlay3AImpl_DestroyPlayer( IDirectPlay3A *iface, DPID player )
2097 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2098 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4_iface, player );
2101 static HRESULT WINAPI IDirectPlay3Impl_DestroyPlayer( IDirectPlay3 *iface, DPID player )
2103 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2104 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4_iface, player );
2107 static HRESULT WINAPI IDirectPlay4AImpl_DestroyPlayer( IDirectPlay4A *iface, DPID idPlayer )
2109 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2110 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
2113 static HRESULT WINAPI IDirectPlay4Impl_DestroyPlayer( IDirectPlay4 *iface, DPID idPlayer )
2115 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2116 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
2119 static HRESULT WINAPI IDirectPlay2AImpl_EnumGroupPlayers( IDirectPlay2A *iface, DPID group,
2120 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2122 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2123 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4A_iface, group, instance,
2124 enumplayercb, context, flags );
2127 static HRESULT WINAPI IDirectPlay2Impl_EnumGroupPlayers( IDirectPlay2 *iface, DPID group,
2128 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2130 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2131 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance,
2132 enumplayercb, context, flags );
2135 static HRESULT WINAPI IDirectPlay3AImpl_EnumGroupPlayers( IDirectPlay3A *iface, DPID group,
2136 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2138 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2139 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance,
2140 enumplayercb, context, flags );
2143 static HRESULT WINAPI IDirectPlay3Impl_EnumGroupPlayers( IDirectPlay3 *iface, DPID group,
2144 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2146 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2147 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance,
2148 enumplayercb, context, flags );
2151 static HRESULT WINAPI IDirectPlay4AImpl_EnumGroupPlayers( IDirectPlay4A *iface, DPID group,
2152 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2154 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2155 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance, enumplayercb,
2156 context, flags );
2159 static HRESULT WINAPI IDirectPlay4Impl_EnumGroupPlayers( IDirectPlay4 *iface, DPID group,
2160 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2162 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2163 lpGroupData gdata;
2164 lpPlayerList plist;
2166 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x): semi stub\n", This, group, instance, enumplayercb,
2167 context, flags );
2169 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2170 return DPERR_UNINITIALIZED;
2172 /* Find the group */
2173 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
2174 return DPERR_INVALIDGROUP;
2176 if ( DPQ_IS_EMPTY( gdata->players ) )
2177 return DP_OK;
2179 /* Walk the players in this group */
2180 for( plist = DPQ_FIRST( gdata->players ); ; plist = DPQ_NEXT( plist->players ) )
2182 /* We do not enum the name server or app server as they are of no
2183 * consequence to the end user.
2185 if ( ( plist->lpPData->dpid != DPID_NAME_SERVER ) &&
2186 ( plist->lpPData->dpid != DPID_SERVERPLAYER ) )
2188 /* FIXME: Need to add stuff for flags checking */
2189 if ( !enumplayercb( plist->lpPData->dpid, DPPLAYERTYPE_PLAYER,
2190 &plist->lpPData->name, plist->lpPData->dwFlags, context ) )
2191 /* User requested break */
2192 return DP_OK;
2195 if ( DPQ_IS_ENDOFLIST( plist->players ) )
2196 break;
2198 return DP_OK;
2201 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2202 static HRESULT WINAPI IDirectPlay2AImpl_EnumGroups( IDirectPlay2A *iface, GUID *instance,
2203 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2205 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2206 return IDirectPlayX_EnumGroups( &This->IDirectPlay4A_iface, instance, enumplayercb, context,
2207 flags );
2210 static HRESULT WINAPI IDirectPlay2Impl_EnumGroups( IDirectPlay2 *iface, GUID *instance,
2211 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2213 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2214 return IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2215 flags );
2218 static HRESULT WINAPI IDirectPlay3AImpl_EnumGroups( IDirectPlay3A *iface, GUID *instance,
2219 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2221 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2222 return IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2223 flags );
2226 static HRESULT WINAPI IDirectPlay3Impl_EnumGroups( IDirectPlay3 *iface, GUID *instance,
2227 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2229 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2230 return IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2231 flags );
2234 static HRESULT WINAPI IDirectPlay4AImpl_EnumGroups( IDirectPlay4A *iface, GUID *instance,
2235 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2237 return IDirectPlayX_EnumGroupsInGroup( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2238 context, flags );
2241 static HRESULT WINAPI IDirectPlay4Impl_EnumGroups ( IDirectPlay4 *iface, GUID *instance,
2242 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2244 return IDirectPlayX_EnumGroupsInGroup( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2245 context, flags );
2248 static HRESULT WINAPI IDirectPlay2AImpl_EnumPlayers( IDirectPlay2A *iface, GUID *instance,
2249 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2251 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2252 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4A_iface, instance, enumplayercb, context,
2253 flags );
2256 static HRESULT WINAPI IDirectPlay2Impl_EnumPlayers( IDirectPlay2 *iface, GUID *instance,
2257 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2259 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2260 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2261 flags );
2264 static HRESULT WINAPI IDirectPlay3AImpl_EnumPlayers( IDirectPlay3A *iface, GUID *instance,
2265 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2267 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2268 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2269 flags );
2272 static HRESULT WINAPI IDirectPlay3Impl_EnumPlayers( IDirectPlay3 *iface, GUID *instance,
2273 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2275 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2276 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2277 flags );
2280 static HRESULT WINAPI IDirectPlay4AImpl_EnumPlayers( IDirectPlay4A *iface, GUID *instance,
2281 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2283 return IDirectPlayX_EnumGroupPlayers( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2284 context, flags );
2287 static HRESULT WINAPI IDirectPlay4Impl_EnumPlayers( IDirectPlay4 *iface, GUID *instance,
2288 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2290 return IDirectPlayX_EnumGroupPlayers( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2291 context, flags );
2294 /* This function should call the registered callback function that the user
2295 passed into EnumSessions for each entry available.
2297 static void DP_InvokeEnumSessionCallbacks
2298 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2299 LPVOID lpNSInfo,
2300 DWORD dwTimeout,
2301 LPVOID lpContext )
2303 LPDPSESSIONDESC2 lpSessionDesc;
2305 FIXME( ": not checking for conditions\n" );
2307 /* Not sure if this should be pruning but it's convenient */
2308 NS_PruneSessionCache( lpNSInfo );
2310 NS_ResetSessionEnumeration( lpNSInfo );
2312 /* Enumerate all sessions */
2313 /* FIXME: Need to indicate ANSI */
2314 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2316 TRACE( "EnumSessionsCallback2 invoked\n" );
2317 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2319 return;
2323 /* Invoke one last time to indicate that there is no more to come */
2324 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2327 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2329 EnumSessionAsyncCallbackData* data = lpContext;
2330 HANDLE hSuicideRequest = data->hSuicideRequest;
2331 DWORD dwTimeout = data->dwTimeout;
2333 TRACE( "Thread started with timeout = 0x%08x\n", dwTimeout );
2335 for( ;; )
2337 HRESULT hr;
2339 /* Sleep up to dwTimeout waiting for request to terminate thread */
2340 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2342 TRACE( "Thread terminating on terminate request\n" );
2343 break;
2346 /* Now resend the enum request */
2347 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2348 data->dwEnumSessionFlags,
2349 data->lpSpData );
2351 if( FAILED(hr) )
2353 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2354 /* FIXME: Should we kill this thread? How to inform the main thread? */
2359 TRACE( "Thread terminating\n" );
2361 /* Clean up the thread data */
2362 CloseHandle( hSuicideRequest );
2363 HeapFree( GetProcessHeap(), 0, lpContext );
2365 /* FIXME: Need to have some notification to main app thread that this is
2366 * dead. It would serve two purposes. 1) allow sync on termination
2367 * so that we don't actually send something to ourselves when we
2368 * become name server (race condition) and 2) so that if we die
2369 * abnormally something else will be able to tell.
2372 return 1;
2375 static void DP_KillEnumSessionThread( IDirectPlayImpl *This )
2377 /* Does a thread exist? If so we were doing an async enum session */
2378 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2380 TRACE( "Killing EnumSession thread %p\n",
2381 This->dp2->hEnumSessionThread );
2383 /* Request that the thread kill itself nicely */
2384 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2385 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2387 /* We no longer need to know about the thread */
2388 CloseHandle( This->dp2->hEnumSessionThread );
2390 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2394 static HRESULT WINAPI IDirectPlay2AImpl_EnumSessions( IDirectPlay2A *iface, DPSESSIONDESC2 *sdesc,
2395 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2397 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2398 return IDirectPlayX_EnumSessions( &This->IDirectPlay4A_iface, sdesc, timeout, enumsessioncb,
2399 context, flags );
2402 static HRESULT WINAPI IDirectPlay2Impl_EnumSessions( IDirectPlay2 *iface, DPSESSIONDESC2 *sdesc,
2403 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2405 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2406 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2407 context, flags );
2410 static HRESULT WINAPI IDirectPlay3AImpl_EnumSessions( IDirectPlay3A *iface, DPSESSIONDESC2 *sdesc,
2411 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2413 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2414 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2415 context, flags );
2418 static HRESULT WINAPI IDirectPlay3Impl_EnumSessions( IDirectPlay3 *iface, DPSESSIONDESC2 *sdesc,
2419 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2421 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2422 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2423 context, flags );
2426 static HRESULT WINAPI IDirectPlay4AImpl_EnumSessions( IDirectPlay4A *iface, DPSESSIONDESC2 *sdesc,
2427 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2429 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2430 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2431 context, flags );
2434 static HRESULT WINAPI IDirectPlay4Impl_EnumSessions( IDirectPlay4 *iface, DPSESSIONDESC2 *sdesc,
2435 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2437 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2438 void *connection;
2439 DWORD size;
2440 HRESULT hr = DP_OK;
2442 TRACE( "(%p)->(%p,0x%08x,%p,%p,0x%08x)\n", This, sdesc, timeout, enumsessioncb,
2443 context, flags );
2445 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2446 return DPERR_UNINITIALIZED;
2448 /* Can't enumerate if the interface is already open */
2449 if ( This->dp2->bConnectionOpen )
2450 return DPERR_GENERIC;
2452 /* The loading of a lobby provider _seems_ to require a backdoor loading
2453 * of the service provider to also associate with this DP object. This is
2454 * because the app doesn't seem to have to call EnumConnections and
2455 * InitializeConnection for the SP before calling this method. As such
2456 * we'll do their dirty work for them with a quick hack so as to always
2457 * load the TCP/IP service provider.
2459 * The correct solution would seem to involve creating a dialog box which
2460 * contains the possible SPs. These dialog boxes most likely follow SDK
2461 * examples.
2463 if ( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
2465 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2467 if ( !DP_BuildSPCompoundAddr( (GUID*)&DPSPGUID_TCPIP, &connection, &size ) )
2469 ERR( "Can't build compound addr\n" );
2470 return DPERR_GENERIC;
2473 hr = IDirectPlayX_InitializeConnection( &This->IDirectPlay4_iface, connection, 0 );
2474 if ( FAILED(hr) )
2475 return hr;
2477 HeapFree( GetProcessHeap(), 0, connection );
2478 This->dp2->bSPInitialized = TRUE;
2482 /* Use the service provider default? */
2483 if ( !timeout )
2485 DPCAPS caps;
2486 caps.dwSize = sizeof( caps );
2488 IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, &caps, 0 );
2489 timeout = caps.dwTimeout;
2490 if ( !timeout )
2491 timeout = DPMSG_WAIT_5_SECS; /* Provide the TCP/IP default */
2494 if ( flags & DPENUMSESSIONS_STOPASYNC )
2496 DP_KillEnumSessionThread( This );
2497 return hr;
2500 if ( flags & DPENUMSESSIONS_ASYNC )
2502 /* Enumerate everything presently in the local session cache */
2503 DP_InvokeEnumSessionCallbacks( enumsessioncb, This->dp2->lpNameServerData, timeout,
2504 context );
2506 if ( This->dp2->dwEnumSessionLock )
2507 return DPERR_CONNECTING;
2509 /* See if we've already created a thread to service this interface */
2510 if ( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2512 DWORD tid;
2513 This->dp2->dwEnumSessionLock++;
2515 /* Send the first enum request inline since the user may cancel a dialog
2516 * if one is presented. Also, may also have a connecting return code.
2518 hr = NS_SendSessionRequestBroadcast( &sdesc->guidApplication, flags,
2519 &This->dp2->spData );
2521 if ( SUCCEEDED(hr) )
2523 EnumSessionAsyncCallbackData* data = HeapAlloc( GetProcessHeap(),
2524 HEAP_ZERO_MEMORY, sizeof( *data ) );
2525 /* FIXME: need to kill the thread on object deletion */
2526 data->lpSpData = &This->dp2->spData;
2527 data->requestGuid = sdesc->guidApplication;
2528 data->dwEnumSessionFlags = flags;
2529 data->dwTimeout = timeout;
2531 This->dp2->hKillEnumSessionThreadEvent = CreateEventW( NULL, TRUE, FALSE, NULL );
2532 if ( !DuplicateHandle( GetCurrentProcess(), This->dp2->hKillEnumSessionThreadEvent,
2533 GetCurrentProcess(), &data->hSuicideRequest, 0, FALSE,
2534 DUPLICATE_SAME_ACCESS ) )
2535 ERR( "Can't duplicate thread killing handle\n" );
2537 TRACE( ": creating EnumSessionsRequest thread\n" );
2538 This->dp2->hEnumSessionThread = CreateThread( NULL, 0,
2539 DP_EnumSessionsSendAsyncRequestThread, data, 0, &tid );
2541 This->dp2->dwEnumSessionLock--;
2544 else
2546 /* Invalidate the session cache for the interface */
2547 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2548 /* Send the broadcast for session enumeration */
2549 hr = NS_SendSessionRequestBroadcast( &sdesc->guidApplication, flags, &This->dp2->spData );
2550 SleepEx( timeout, FALSE );
2551 DP_InvokeEnumSessionCallbacks( enumsessioncb, This->dp2->lpNameServerData, timeout,
2552 context );
2555 return hr;
2558 static HRESULT WINAPI IDirectPlay2AImpl_GetCaps( IDirectPlay2A *iface, DPCAPS *caps, DWORD flags )
2560 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2561 return IDirectPlayX_GetCaps( &This->IDirectPlay4A_iface, caps, flags );
2564 static HRESULT WINAPI IDirectPlay2Impl_GetCaps( IDirectPlay2 *iface, DPCAPS *caps, DWORD flags )
2566 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2567 return IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, caps, flags );
2570 static HRESULT WINAPI IDirectPlay3AImpl_GetCaps( IDirectPlay3A *iface, DPCAPS *caps, DWORD flags )
2572 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2573 return IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, caps, flags );
2576 static HRESULT WINAPI IDirectPlay3Impl_GetCaps( IDirectPlay3 *iface, DPCAPS *caps, DWORD flags )
2578 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2579 return IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, caps, flags );
2582 static HRESULT WINAPI IDirectPlay4AImpl_GetCaps( IDirectPlay4A *iface, DPCAPS *caps, DWORD flags )
2584 return IDirectPlayX_GetPlayerCaps( iface, DPID_ALLPLAYERS, caps, flags );
2587 static HRESULT WINAPI IDirectPlay4Impl_GetCaps( IDirectPlay4 *iface, DPCAPS *caps, DWORD flags )
2589 return IDirectPlayX_GetPlayerCaps( iface, DPID_ALLPLAYERS, caps, flags );
2592 static HRESULT WINAPI IDirectPlay2AImpl_GetGroupData( IDirectPlay2A *iface, DPID group, void *data,
2593 DWORD *size, DWORD flags )
2595 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2596 return IDirectPlayX_GetGroupData( &This->IDirectPlay4A_iface, group, data, size, flags );
2599 static HRESULT WINAPI IDirectPlay2Impl_GetGroupData( IDirectPlay2 *iface, DPID group, void *data,
2600 DWORD *size, DWORD flags )
2602 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2603 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2606 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupData( IDirectPlay3A *iface, DPID group, void *data,
2607 DWORD *size, DWORD flags )
2609 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2610 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2613 static HRESULT WINAPI IDirectPlay3Impl_GetGroupData( IDirectPlay3 *iface, DPID group, void *data,
2614 DWORD *size, DWORD flags )
2616 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2617 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2620 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupData( IDirectPlay4A *iface, DPID group,
2621 void *data, DWORD *size, DWORD flags )
2623 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2624 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2627 static HRESULT WINAPI IDirectPlay4Impl_GetGroupData( IDirectPlay4 *iface, DPID group,
2628 void *data, DWORD *size, DWORD flags )
2630 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2631 lpGroupData gdata;
2632 DWORD bufsize;
2633 void *src;
2635 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x)\n", This, group, data, size, flags );
2637 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
2638 return DPERR_INVALIDGROUP;
2640 /* How much buffer is required? */
2641 if ( flags & DPSET_LOCAL )
2643 bufsize = gdata->dwLocalDataSize;
2644 src = gdata->lpLocalData;
2646 else
2648 bufsize = gdata->dwRemoteDataSize;
2649 src = gdata->lpRemoteData;
2652 /* Is the user requesting to know how big a buffer is required? */
2653 if ( !data || *size < bufsize )
2655 *size = bufsize;
2656 return DPERR_BUFFERTOOSMALL;
2659 CopyMemory( data, src, bufsize );
2661 return DP_OK;
2664 static HRESULT DP_IF_GetGroupName( IDirectPlayImpl *This, DPID idGroup, void *lpData,
2665 DWORD *lpdwDataSize, BOOL bAnsi )
2667 lpGroupData lpGData;
2668 LPDPNAME lpName = lpData;
2669 DWORD dwRequiredDataSize;
2671 FIXME("(%p)->(0x%08x,%p,%p,%u) ANSI ignored\n",
2672 This, idGroup, lpData, lpdwDataSize, bAnsi );
2674 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2676 return DPERR_INVALIDGROUP;
2679 dwRequiredDataSize = lpGData->name.dwSize;
2681 if( lpGData->name.u1.lpszShortNameA )
2683 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
2686 if( lpGData->name.u2.lpszLongNameA )
2688 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
2691 if( ( lpData == NULL ) ||
2692 ( *lpdwDataSize < dwRequiredDataSize )
2695 *lpdwDataSize = dwRequiredDataSize;
2696 return DPERR_BUFFERTOOSMALL;
2699 /* Copy the structure */
2700 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2702 if( lpGData->name.u1.lpszShortNameA )
2704 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2705 lpGData->name.u1.lpszShortNameA );
2707 else
2709 lpName->u1.lpszShortNameA = NULL;
2712 if( lpGData->name.u1.lpszShortNameA )
2714 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2715 lpGData->name.u2.lpszLongNameA );
2717 else
2719 lpName->u2.lpszLongNameA = NULL;
2722 return DP_OK;
2725 static HRESULT WINAPI IDirectPlay2AImpl_GetGroupName( IDirectPlay2A *iface, DPID group, void *data,
2726 DWORD *size )
2728 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2729 return IDirectPlayX_GetGroupName( &This->IDirectPlay4A_iface, group, data, size );
2732 static HRESULT WINAPI IDirectPlay2Impl_GetGroupName( IDirectPlay2 *iface, DPID group, void *data,
2733 DWORD *size )
2735 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2736 return IDirectPlayX_GetGroupName( &This->IDirectPlay4_iface, group, data, size );
2739 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupName( IDirectPlay3A *iface, DPID group, void *data,
2740 DWORD *size )
2742 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2743 return IDirectPlayX_GetGroupName( &This->IDirectPlay4_iface, group, data, size );
2746 static HRESULT WINAPI IDirectPlay3Impl_GetGroupName( IDirectPlay3 *iface, DPID group, void *data,
2747 DWORD *size )
2749 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2750 return IDirectPlayX_GetGroupName( &This->IDirectPlay4_iface, group, data, size );
2753 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupName( IDirectPlay4A *iface, DPID idGroup,
2754 void *lpData, DWORD *lpdwDataSize )
2756 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2757 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2760 static HRESULT WINAPI IDirectPlay4Impl_GetGroupName( IDirectPlay4 *iface, DPID idGroup,
2761 void *lpData, DWORD *lpdwDataSize )
2763 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2764 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2767 static HRESULT WINAPI IDirectPlay2AImpl_GetMessageCount( IDirectPlay2A *iface, DPID player,
2768 DWORD *count )
2770 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2771 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4A_iface, player, count );
2774 static HRESULT WINAPI IDirectPlay2Impl_GetMessageCount( IDirectPlay2 *iface, DPID player,
2775 DWORD *count )
2777 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2778 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4_iface, player, count );
2781 static HRESULT WINAPI IDirectPlay3AImpl_GetMessageCount( IDirectPlay3A *iface, DPID player,
2782 DWORD *count )
2784 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2785 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4_iface, player, count );
2788 static HRESULT WINAPI IDirectPlay3Impl_GetMessageCount( IDirectPlay3 *iface, DPID player,
2789 DWORD *count )
2791 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2792 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4_iface, player, count );
2795 static HRESULT WINAPI IDirectPlay4AImpl_GetMessageCount( IDirectPlay4A *iface, DPID player,
2796 DWORD *count )
2798 return IDirectPlayX_GetMessageQueue( iface, 0, player, DPMESSAGEQUEUE_RECEIVE, count, NULL );
2801 static HRESULT WINAPI IDirectPlay4Impl_GetMessageCount( IDirectPlay4 *iface, DPID player,
2802 DWORD *count )
2804 return IDirectPlayX_GetMessageQueue( iface, 0, player, DPMESSAGEQUEUE_RECEIVE, count, NULL );
2807 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerAddress( IDirectPlay2A *iface, DPID player,
2808 void *data, DWORD *size )
2810 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2811 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4A_iface, player, data, size );
2814 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerAddress( IDirectPlay2 *iface, DPID player,
2815 void *data, DWORD *size )
2817 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2818 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4_iface, player, data, size );
2821 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerAddress( IDirectPlay3A *iface, DPID player,
2822 void *data, DWORD *size )
2824 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2825 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4_iface, player, data, size );
2828 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerAddress( IDirectPlay3 *iface, DPID player,
2829 void *data, DWORD *size )
2831 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2832 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4_iface, player, data, size );
2835 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerAddress( IDirectPlay4A *iface, DPID player,
2836 void *data, DWORD *size )
2838 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2839 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, player, data, size );
2840 return DP_OK;
2843 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerAddress( IDirectPlay4 *iface, DPID player,
2844 void *data, DWORD *size )
2846 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2847 FIXME( "(%p)->(0x%08x,%p,%p): stub\n", This, player, data, size );
2848 return DP_OK;
2851 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerCaps( IDirectPlay2A *iface, DPID player,
2852 DPCAPS *caps, DWORD flags )
2854 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2855 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4A_iface, player, caps, flags );
2858 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerCaps( IDirectPlay2 *iface, DPID player,
2859 DPCAPS *caps, DWORD flags )
2861 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2862 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2865 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerCaps( IDirectPlay3A *iface, DPID player,
2866 DPCAPS *caps, DWORD flags )
2868 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2869 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2872 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerCaps( IDirectPlay3 *iface, DPID player,
2873 DPCAPS *caps, DWORD flags )
2875 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2876 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2879 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerCaps( IDirectPlay4A *iface, DPID player,
2880 DPCAPS *caps, DWORD flags )
2882 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2883 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2886 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerCaps( IDirectPlay4 *iface, DPID player,
2887 DPCAPS *caps, DWORD flags )
2889 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2890 DPSP_GETCAPSDATA data;
2892 TRACE( "(%p)->(0x%08x,%p,0x%08x)\n", This, player, caps, flags);
2894 if ( !caps )
2895 return DPERR_INVALIDPARAMS;
2897 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2898 return DPERR_UNINITIALIZED;
2900 if( caps->dwSize != sizeof(DPCAPS) )
2901 return DPERR_INVALIDPARAMS;
2903 /* Query the service provider */
2904 data.idPlayer = player;
2905 data.dwFlags = flags;
2906 data.lpCaps = caps;
2907 data.lpISP = This->dp2->spData.lpISP;
2909 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2912 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerData( IDirectPlay2A *iface, DPID player,
2913 void *data, DWORD *size, DWORD flags )
2915 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2916 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4A_iface, player, data, size, flags );
2919 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerData( IDirectPlay2 *iface, DPID player,
2920 void *data, DWORD *size, DWORD flags )
2922 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2923 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2926 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerData( IDirectPlay3A *iface, DPID player,
2927 void *data, DWORD *size, DWORD flags )
2929 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2930 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2933 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerData( IDirectPlay3 *iface, DPID player,
2934 void *data, DWORD *size, DWORD flags )
2936 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2937 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2940 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerData( IDirectPlay4A *iface, DPID player,
2941 void *data, DWORD *size, DWORD flags )
2943 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2944 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2947 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerData( IDirectPlay4 *iface, DPID player,
2948 void *data, DWORD *size, DWORD flags )
2950 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2951 lpPlayerList plist;
2952 DWORD bufsize;
2953 void *src;
2955 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x)\n", This, player, data, size, flags );
2957 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2958 return DPERR_UNINITIALIZED;
2960 if ( ( plist = DP_FindPlayer( This, player ) ) == NULL )
2961 return DPERR_INVALIDPLAYER;
2963 if ( flags & DPSET_LOCAL )
2965 bufsize = plist->lpPData->dwLocalDataSize;
2966 src = plist->lpPData->lpLocalData;
2968 else
2970 bufsize = plist->lpPData->dwRemoteDataSize;
2971 src = plist->lpPData->lpRemoteData;
2974 /* Is the user requesting to know how big a buffer is required? */
2975 if ( !data || *size < bufsize )
2977 *size = bufsize;
2978 return DPERR_BUFFERTOOSMALL;
2981 CopyMemory( data, src, bufsize );
2983 return DP_OK;
2986 static HRESULT DP_IF_GetPlayerName( IDirectPlayImpl *This, DPID idPlayer, void *lpData,
2987 DWORD *lpdwDataSize, BOOL bAnsi )
2989 lpPlayerList lpPList;
2990 LPDPNAME lpName = lpData;
2991 DWORD dwRequiredDataSize;
2993 FIXME( "(%p)->(0x%08x,%p,%p,%u): ANSI\n",
2994 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2996 if( This->dp2->connectionInitialized == NO_PROVIDER )
2998 return DPERR_UNINITIALIZED;
3001 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3003 return DPERR_INVALIDPLAYER;
3006 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
3008 if( lpPList->lpPData->name.u1.lpszShortNameA )
3010 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
3013 if( lpPList->lpPData->name.u2.lpszLongNameA )
3015 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
3018 if( ( lpData == NULL ) ||
3019 ( *lpdwDataSize < dwRequiredDataSize )
3022 *lpdwDataSize = dwRequiredDataSize;
3023 return DPERR_BUFFERTOOSMALL;
3026 /* Copy the structure */
3027 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
3029 if( lpPList->lpPData->name.u1.lpszShortNameA )
3031 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
3032 lpPList->lpPData->name.u1.lpszShortNameA );
3034 else
3036 lpName->u1.lpszShortNameA = NULL;
3039 if( lpPList->lpPData->name.u1.lpszShortNameA )
3041 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
3042 lpPList->lpPData->name.u2.lpszLongNameA );
3044 else
3046 lpName->u2.lpszLongNameA = NULL;
3049 return DP_OK;
3052 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerName( IDirectPlay2A *iface, DPID player,
3053 void *data, DWORD *size )
3055 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3056 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4A_iface, player, data, size );
3059 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerName( IDirectPlay2 *iface, DPID player,
3060 void *data, DWORD *size )
3062 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3063 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4_iface, player, data, size );
3066 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerName( IDirectPlay3A *iface, DPID player,
3067 void *data, DWORD *size )
3069 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3070 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4_iface, player, data, size );
3073 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerName( IDirectPlay3 *iface, DPID player,
3074 void *data, DWORD *size )
3076 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3077 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4_iface, player, data, size );
3080 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerName( IDirectPlay4A *iface, DPID idPlayer,
3081 void *lpData, DWORD *lpdwDataSize )
3083 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3084 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
3087 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerName( IDirectPlay4 *iface, DPID idPlayer,
3088 void *lpData, DWORD *lpdwDataSize )
3090 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3091 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
3094 static HRESULT DP_GetSessionDesc( IDirectPlayImpl *This, void *lpData, DWORD *lpdwDataSize,
3095 BOOL bAnsi )
3097 DWORD dwRequiredSize;
3099 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
3101 if( This->dp2->connectionInitialized == NO_PROVIDER )
3103 return DPERR_UNINITIALIZED;
3106 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
3108 return DPERR_INVALIDPARAMS;
3111 /* FIXME: Get from This->dp2->lpSessionDesc */
3112 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
3114 if ( ( lpData == NULL ) ||
3115 ( *lpdwDataSize < dwRequiredSize )
3118 *lpdwDataSize = dwRequiredSize;
3119 return DPERR_BUFFERTOOSMALL;
3122 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
3124 return DP_OK;
3127 static HRESULT WINAPI IDirectPlay2AImpl_GetSessionDesc( IDirectPlay2A *iface, void *data,
3128 DWORD *size )
3130 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3131 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4A_iface, data, size );
3134 static HRESULT WINAPI IDirectPlay2Impl_GetSessionDesc( IDirectPlay2 *iface, void *data,
3135 DWORD *size )
3137 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3138 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4_iface, data, size );
3141 static HRESULT WINAPI IDirectPlay3AImpl_GetSessionDesc( IDirectPlay3A *iface, void *data,
3142 DWORD *size )
3144 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3145 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4_iface, data, size );
3148 static HRESULT WINAPI IDirectPlay3Impl_GetSessionDesc( IDirectPlay3 *iface, void *data,
3149 DWORD *size )
3151 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3152 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4_iface, data, size );
3155 static HRESULT WINAPI IDirectPlay4AImpl_GetSessionDesc( IDirectPlay4A *iface, void *lpData,
3156 DWORD *lpdwDataSize )
3158 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3159 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
3162 static HRESULT WINAPI IDirectPlay4Impl_GetSessionDesc( IDirectPlay4 *iface, void *lpData,
3163 DWORD *lpdwDataSize )
3165 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3166 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
3169 static HRESULT WINAPI IDirectPlay2AImpl_Initialize( IDirectPlay2A *iface, GUID *guid )
3171 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3172 return IDirectPlayX_Initialize( &This->IDirectPlay4A_iface, guid );
3175 static HRESULT WINAPI IDirectPlay2Impl_Initialize( IDirectPlay2 *iface, GUID *guid )
3177 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3178 return IDirectPlayX_Initialize( &This->IDirectPlay4_iface, guid );
3181 static HRESULT WINAPI IDirectPlay3AImpl_Initialize( IDirectPlay3A *iface, GUID *guid )
3183 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3184 return IDirectPlayX_Initialize( &This->IDirectPlay4_iface, guid );
3187 static HRESULT WINAPI IDirectPlay3Impl_Initialize( IDirectPlay3 *iface, GUID *guid )
3189 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3190 return IDirectPlayX_Initialize( &This->IDirectPlay4_iface, guid );
3193 /* Intended only for COM compatibility. Always returns an error. */
3194 static HRESULT WINAPI IDirectPlay4AImpl_Initialize( IDirectPlay4A *iface, GUID *guid )
3196 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3197 TRACE("(%p)->(%p): no-op\n", This, guid );
3198 return DPERR_ALREADYINITIALIZED;
3201 static HRESULT WINAPI IDirectPlay4Impl_Initialize( IDirectPlay4 *iface, GUID *guid )
3203 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3204 TRACE( "(%p)->(%p): no-op\n", This, guid );
3205 return DPERR_ALREADYINITIALIZED;
3209 static HRESULT DP_SecureOpen( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpsd, DWORD dwFlags,
3210 const DPSECURITYDESC *lpSecurity, const DPCREDENTIALS *lpCredentials, BOOL bAnsi )
3212 HRESULT hr = DP_OK;
3214 FIXME( "(%p)->(%p,0x%08x,%p,%p): partial stub\n",
3215 This, lpsd, dwFlags, lpSecurity, lpCredentials );
3217 if( This->dp2->connectionInitialized == NO_PROVIDER )
3219 return DPERR_UNINITIALIZED;
3222 if( lpsd->dwSize != sizeof(DPSESSIONDESC2) )
3224 TRACE( ": rejecting invalid dpsd size (%d).\n", lpsd->dwSize );
3225 return DPERR_INVALIDPARAMS;
3228 if( This->dp2->bConnectionOpen )
3230 TRACE( ": rejecting already open connection.\n" );
3231 return DPERR_ALREADYINITIALIZED;
3234 /* If we're enumerating, kill the thread */
3235 DP_KillEnumSessionThread( This );
3237 if( dwFlags & DPOPEN_CREATE )
3239 /* Rightoo - this computer is the host and the local computer needs to be
3240 the name server so that others can join this session */
3241 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
3243 This->dp2->bHostInterface = TRUE;
3245 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
3246 if( FAILED( hr ) )
3248 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
3249 return hr;
3253 /* Invoke the conditional callback for the service provider */
3254 if( This->dp2->spData.lpCB->Open )
3256 DPSP_OPENDATA data;
3258 FIXME( "Not all data fields are correct. Need new parameter\n" );
3260 data.bCreate = (dwFlags & DPOPEN_CREATE ) != 0;
3261 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
3262 : NS_GetNSAddr( This->dp2->lpNameServerData );
3263 data.lpISP = This->dp2->spData.lpISP;
3264 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) != 0;
3265 data.dwOpenFlags = dwFlags;
3266 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
3268 hr = (*This->dp2->spData.lpCB->Open)(&data);
3269 if( FAILED( hr ) )
3271 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
3272 return hr;
3277 /* Create the system group of which everything is a part of */
3278 DPID systemGroup = DPID_SYSTEM_GROUP;
3280 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
3281 NULL, 0, 0, TRUE );
3285 if( dwFlags & DPOPEN_JOIN )
3287 DPID dpidServerId = DPID_UNKNOWN;
3289 /* Create the server player for this interface. This way we can receive
3290 * messages for this session.
3292 /* FIXME: I suppose that we should be setting an event for a receive
3293 * type of thing. That way the messaging thread could know to wake
3294 * up. DPlay would then trigger the hEvent for the player the
3295 * message is directed to.
3297 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
3299 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
3302 else if( dwFlags & DPOPEN_CREATE )
3304 DPID dpidNameServerId = DPID_NAME_SERVER;
3306 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
3307 0, DPPLAYER_SERVERPLAYER, bAnsi );
3310 if( FAILED(hr) )
3312 ERR( "Couldn't create name server/system player: %s\n",
3313 DPLAYX_HresultToString(hr) );
3316 return hr;
3319 static HRESULT WINAPI IDirectPlay2AImpl_Open( IDirectPlay2A *iface, DPSESSIONDESC2 *sdesc,
3320 DWORD flags )
3322 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3323 return IDirectPlayX_Open( &This->IDirectPlay4A_iface, sdesc, flags );
3326 static HRESULT WINAPI IDirectPlay2Impl_Open( IDirectPlay2 *iface, DPSESSIONDESC2 *sdesc,
3327 DWORD flags )
3329 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3330 return IDirectPlayX_Open( &This->IDirectPlay4_iface, sdesc, flags );
3333 static HRESULT WINAPI IDirectPlay3AImpl_Open( IDirectPlay3A *iface, DPSESSIONDESC2 *sdesc,
3334 DWORD flags )
3336 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3337 return IDirectPlayX_Open( &This->IDirectPlay4_iface, sdesc, flags );
3340 static HRESULT WINAPI IDirectPlay3Impl_Open( IDirectPlay3 *iface, DPSESSIONDESC2 *sdesc,
3341 DWORD flags )
3343 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3344 return IDirectPlayX_Open( &This->IDirectPlay4_iface, sdesc, flags );
3347 static HRESULT WINAPI IDirectPlay4AImpl_Open( IDirectPlay4A *iface, DPSESSIONDESC2 *sdesc,
3348 DWORD flags )
3350 return IDirectPlayX_SecureOpen( iface, sdesc, flags, NULL, NULL );
3353 static HRESULT WINAPI IDirectPlay4Impl_Open( IDirectPlay4 *iface, DPSESSIONDESC2 *sdesc,
3354 DWORD flags )
3356 return IDirectPlayX_SecureOpen( iface, sdesc, flags, NULL, NULL );
3359 static HRESULT DP_IF_Receive( IDirectPlayImpl *This, DPID *lpidFrom, DPID *lpidTo, DWORD dwFlags,
3360 void *lpData, DWORD *lpdwDataSize, BOOL bAnsi )
3362 LPDPMSG lpMsg = NULL;
3364 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p,%u): stub\n",
3365 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
3367 if( This->dp2->connectionInitialized == NO_PROVIDER )
3369 return DPERR_UNINITIALIZED;
3372 if( dwFlags == 0 )
3374 dwFlags = DPRECEIVE_ALL;
3377 /* If the lpData is NULL, we must be peeking the message */
3378 if( ( lpData == NULL ) &&
3379 !( dwFlags & DPRECEIVE_PEEK )
3382 return DPERR_INVALIDPARAMS;
3385 if( dwFlags & DPRECEIVE_ALL )
3387 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
3389 if( !( dwFlags & DPRECEIVE_PEEK ) )
3391 FIXME( "Remove from queue\n" );
3394 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
3395 ( dwFlags & DPRECEIVE_FROMPLAYER )
3398 FIXME( "Find matching message 0x%08x\n", dwFlags );
3400 else
3402 ERR( "Hmmm..dwFlags 0x%08x\n", dwFlags );
3405 if( lpMsg == NULL )
3407 return DPERR_NOMESSAGES;
3410 /* Copy into the provided buffer */
3411 if (lpData) CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
3413 return DP_OK;
3416 static HRESULT WINAPI IDirectPlay2AImpl_Receive( IDirectPlay2A *iface, DPID *from, DPID *to,
3417 DWORD flags, void *data, DWORD *size )
3419 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3420 return IDirectPlayX_Receive( &This->IDirectPlay4A_iface, from, to, flags, data, size );
3423 static HRESULT WINAPI IDirectPlay2Impl_Receive( IDirectPlay2 *iface, DPID *from, DPID *to,
3424 DWORD flags, void *data, DWORD *size )
3426 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3427 return IDirectPlayX_Receive( &This->IDirectPlay4_iface, from, to, flags, data, size );
3430 static HRESULT WINAPI IDirectPlay3AImpl_Receive( IDirectPlay3A *iface, DPID *from, DPID *to,
3431 DWORD flags, void *data, DWORD *size )
3433 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3434 return IDirectPlayX_Receive( &This->IDirectPlay4_iface, from, to, flags, data, size );
3437 static HRESULT WINAPI IDirectPlay3Impl_Receive( IDirectPlay3 *iface, DPID *from, DPID *to,
3438 DWORD flags, void *data, DWORD *size )
3440 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3441 return IDirectPlayX_Receive( &This->IDirectPlay4_iface, from, to, flags, data, size );
3444 static HRESULT WINAPI IDirectPlay4AImpl_Receive( IDirectPlay4A *iface, DPID *lpidFrom,
3445 DPID *lpidTo, DWORD dwFlags, void *lpData, DWORD *lpdwDataSize )
3447 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3448 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, TRUE );
3451 static HRESULT WINAPI IDirectPlay4Impl_Receive( IDirectPlay4 *iface, DPID *lpidFrom,
3452 DPID *lpidTo, DWORD dwFlags, void *lpData, DWORD *lpdwDataSize )
3454 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3455 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, FALSE );
3458 static HRESULT WINAPI IDirectPlay2AImpl_Send( IDirectPlay2A *iface, DPID from, DPID to,
3459 DWORD flags, void *data, DWORD size )
3461 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3462 return IDirectPlayX_Send( &This->IDirectPlay4A_iface, from, to, flags, data, size );
3465 static HRESULT WINAPI IDirectPlay2Impl_Send( IDirectPlay2 *iface, DPID from, DPID to,
3466 DWORD flags, void *data, DWORD size )
3468 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3469 return IDirectPlayX_Send( &This->IDirectPlay4_iface, from, to, flags, data, size );
3472 static HRESULT WINAPI IDirectPlay3AImpl_Send( IDirectPlay3A *iface, DPID from, DPID to,
3473 DWORD flags, void *data, DWORD size )
3475 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3476 return IDirectPlayX_Send( &This->IDirectPlay4_iface, from, to, flags, data, size );
3479 static HRESULT WINAPI IDirectPlay3Impl_Send( IDirectPlay3 *iface, DPID from, DPID to,
3480 DWORD flags, void *data, DWORD size )
3482 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3483 return IDirectPlayX_Send( &This->IDirectPlay4_iface, from, to, flags, data, size );
3486 static HRESULT WINAPI IDirectPlay4AImpl_Send( IDirectPlay4A *iface, DPID from, DPID to,
3487 DWORD flags, void *data, DWORD size )
3489 return IDirectPlayX_SendEx( iface, from, to, flags, data, size, 0, 0, NULL, NULL );
3492 static HRESULT WINAPI IDirectPlay4Impl_Send( IDirectPlay4 *iface, DPID from, DPID to,
3493 DWORD flags, void *data, DWORD size )
3495 return IDirectPlayX_SendEx( iface, from, to, flags, data, size, 0, 0, NULL, NULL );
3498 static HRESULT WINAPI IDirectPlay2AImpl_SetGroupData( IDirectPlay2A *iface, DPID group, void *data,
3499 DWORD size, DWORD flags )
3501 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3502 return IDirectPlayX_SetGroupData( &This->IDirectPlay4A_iface, group, data, size, flags );
3505 static HRESULT WINAPI IDirectPlay2Impl_SetGroupData( IDirectPlay2 *iface, DPID group, void *data,
3506 DWORD size, DWORD flags )
3508 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3509 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3512 static HRESULT WINAPI IDirectPlay3AImpl_SetGroupData( IDirectPlay3A *iface, DPID group, void *data,
3513 DWORD size, DWORD flags )
3515 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3516 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3519 static HRESULT WINAPI IDirectPlay3Impl_SetGroupData( IDirectPlay3 *iface, DPID group, void *data,
3520 DWORD size, DWORD flags )
3522 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3523 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3526 static HRESULT WINAPI IDirectPlay4AImpl_SetGroupData( IDirectPlay4A *iface, DPID group, void *data,
3527 DWORD size, DWORD flags )
3529 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3530 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3533 static HRESULT WINAPI IDirectPlay4Impl_SetGroupData( IDirectPlay4 *iface, DPID group, void *data,
3534 DWORD size, DWORD flags )
3536 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3537 lpGroupData gdata;
3539 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x)\n", This, group, data, size, flags );
3541 /* Parameter check */
3542 if ( !data && size )
3543 return DPERR_INVALIDPARAMS;
3545 /* Find the pointer to the data for this player */
3546 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
3547 return DPERR_INVALIDOBJECT;
3549 if ( !(flags & DPSET_LOCAL) )
3551 FIXME( "Was this group created by this interface?\n" );
3552 /* FIXME: If this is a remote update need to allow it but not
3553 * send a message.
3557 DP_SetGroupData( gdata, flags, data, size );
3559 /* FIXME: Only send a message if this group is local to the session otherwise
3560 * it will have been rejected above
3562 if ( !(flags & DPSET_LOCAL) )
3563 FIXME( "Send msg?\n" );
3565 return DP_OK;
3568 static HRESULT DP_IF_SetGroupName( IDirectPlayImpl *This, DPID idGroup, DPNAME *lpGroupName,
3569 DWORD dwFlags, BOOL bAnsi )
3571 lpGroupData lpGData;
3573 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n", This, idGroup,
3574 lpGroupName, dwFlags, bAnsi );
3576 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3578 return DPERR_INVALIDGROUP;
3581 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
3583 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3584 FIXME( "Message not sent and dwFlags ignored\n" );
3586 return DP_OK;
3589 static HRESULT WINAPI IDirectPlay2AImpl_SetGroupName( IDirectPlay2A *iface, DPID group,
3590 DPNAME *name, DWORD flags )
3592 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3593 return IDirectPlayX_SetGroupName( &This->IDirectPlay4A_iface, group, name, flags );
3596 static HRESULT WINAPI IDirectPlay2Impl_SetGroupName( IDirectPlay2 *iface, DPID group,
3597 DPNAME *name, DWORD flags )
3599 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3600 return IDirectPlayX_SetGroupName( &This->IDirectPlay4_iface, group, name, flags );
3603 static HRESULT WINAPI IDirectPlay3AImpl_SetGroupName( IDirectPlay3A *iface, DPID group,
3604 DPNAME *name, DWORD flags )
3606 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3607 return IDirectPlayX_SetGroupName( &This->IDirectPlay4_iface, group, name, flags );
3610 static HRESULT WINAPI IDirectPlay3Impl_SetGroupName( IDirectPlay3 *iface, DPID group,
3611 DPNAME *name, DWORD flags )
3613 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3614 return IDirectPlayX_SetGroupName( &This->IDirectPlay4_iface, group, name, flags );
3617 static HRESULT WINAPI IDirectPlay4AImpl_SetGroupName( IDirectPlay4A *iface, DPID idGroup,
3618 DPNAME *lpGroupName, DWORD dwFlags )
3620 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3621 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
3624 static HRESULT WINAPI IDirectPlay4Impl_SetGroupName( IDirectPlay4 *iface, DPID idGroup,
3625 DPNAME *lpGroupName, DWORD dwFlags )
3627 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3628 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
3631 static HRESULT WINAPI IDirectPlay2AImpl_SetPlayerData( IDirectPlay2A *iface, DPID player,
3632 void *data, DWORD size, DWORD flags )
3634 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3635 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4A_iface, player, data, size, flags );
3638 static HRESULT WINAPI IDirectPlay2Impl_SetPlayerData( IDirectPlay2 *iface, DPID player,
3639 void *data, DWORD size, DWORD flags )
3641 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3642 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
3645 static HRESULT WINAPI IDirectPlay3AImpl_SetPlayerData( IDirectPlay3A *iface, DPID player,
3646 void *data, DWORD size, DWORD flags )
3648 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3649 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
3652 static HRESULT WINAPI IDirectPlay3Impl_SetPlayerData( IDirectPlay3 *iface, DPID player,
3653 void *data, DWORD size, DWORD flags )
3655 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3656 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
3659 static HRESULT WINAPI IDirectPlay4AImpl_SetPlayerData( IDirectPlay4A *iface, DPID player,
3660 void *data, DWORD size, DWORD flags )
3662 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3663 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
3666 static HRESULT WINAPI IDirectPlay4Impl_SetPlayerData( IDirectPlay4 *iface, DPID player,
3667 void *data, DWORD size, DWORD flags )
3669 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3670 lpPlayerList plist;
3672 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x)\n", This, player, data, size, flags );
3674 if ( This->dp2->connectionInitialized == NO_PROVIDER )
3675 return DPERR_UNINITIALIZED;
3677 /* Parameter check */
3678 if ( !data && size )
3679 return DPERR_INVALIDPARAMS;
3681 /* Find the pointer to the data for this player */
3682 if ( (plist = DP_FindPlayer( This, player )) == NULL )
3683 return DPERR_INVALIDPLAYER;
3685 if ( !(flags & DPSET_LOCAL) )
3687 FIXME( "Was this group created by this interface?\n" );
3688 /* FIXME: If this is a remote update need to allow it but not
3689 * send a message.
3693 DP_SetPlayerData( plist->lpPData, flags, data, size );
3695 if ( !(flags & DPSET_LOCAL) )
3696 FIXME( "Send msg?\n" );
3698 return DP_OK;
3701 static HRESULT DP_IF_SetPlayerName( IDirectPlayImpl *This, DPID idPlayer, DPNAME *lpPlayerName,
3702 DWORD dwFlags, BOOL bAnsi )
3704 lpPlayerList lpPList;
3706 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n",
3707 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3709 if( This->dp2->connectionInitialized == NO_PROVIDER )
3711 return DPERR_UNINITIALIZED;
3714 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3716 return DPERR_INVALIDGROUP;
3719 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3721 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3722 FIXME( "Message not sent and dwFlags ignored\n" );
3724 return DP_OK;
3727 static HRESULT WINAPI IDirectPlay2AImpl_SetPlayerName( IDirectPlay2A *iface, DPID player,
3728 DPNAME *name, DWORD flags )
3730 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3731 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4A_iface, player, name, flags );
3734 static HRESULT WINAPI IDirectPlay2Impl_SetPlayerName( IDirectPlay2 *iface, DPID player,
3735 DPNAME *name, DWORD flags )
3737 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3738 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4_iface, player, name, flags );
3741 static HRESULT WINAPI IDirectPlay3AImpl_SetPlayerName( IDirectPlay3A *iface, DPID player,
3742 DPNAME *name, DWORD flags )
3744 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3745 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4_iface, player, name, flags );
3748 static HRESULT WINAPI IDirectPlay3Impl_SetPlayerName( IDirectPlay3 *iface, DPID player,
3749 DPNAME *name, DWORD flags )
3751 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3752 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4_iface, player, name, flags );
3755 static HRESULT WINAPI IDirectPlay4AImpl_SetPlayerName( IDirectPlay4A *iface, DPID idPlayer,
3756 DPNAME *lpPlayerName, DWORD dwFlags )
3758 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3759 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3762 static HRESULT WINAPI IDirectPlay4Impl_SetPlayerName( IDirectPlay4 *iface, DPID idPlayer,
3763 DPNAME *lpPlayerName, DWORD dwFlags )
3765 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3766 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3769 static HRESULT DP_SetSessionDesc( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpSessDesc,
3770 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3772 DWORD dwRequiredSize;
3773 LPDPSESSIONDESC2 lpTempSessDesc;
3775 TRACE( "(%p)->(%p,0x%08x,%u,%u)\n",
3776 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3778 if( This->dp2->connectionInitialized == NO_PROVIDER )
3780 return DPERR_UNINITIALIZED;
3783 if( dwFlags )
3785 return DPERR_INVALIDPARAMS;
3788 /* Only the host is allowed to update the session desc */
3789 if( !This->dp2->bHostInterface )
3791 return DPERR_ACCESSDENIED;
3794 /* FIXME: Copy into This->dp2->lpSessionDesc */
3795 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3796 lpTempSessDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize );
3798 if( lpTempSessDesc == NULL )
3800 return DPERR_OUTOFMEMORY;
3803 /* Free the old */
3804 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3806 This->dp2->lpSessionDesc = lpTempSessDesc;
3807 /* Set the new */
3808 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3809 if( bInitial )
3811 /*Initializing session GUID*/
3812 CoCreateGuid( &(This->dp2->lpSessionDesc->guidInstance) );
3814 /* If this is an external invocation of the interface, we should be
3815 * letting everyone know that things have changed. Otherwise this is
3816 * just an initialization and it doesn't need to be propagated.
3818 if( !bInitial )
3820 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3823 return DP_OK;
3826 static HRESULT WINAPI IDirectPlay2AImpl_SetSessionDesc( IDirectPlay2A *iface, DPSESSIONDESC2 *sdesc,
3827 DWORD flags )
3829 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3830 return IDirectPlayX_SetSessionDesc( &This->IDirectPlay4A_iface, sdesc, flags );
3833 static HRESULT WINAPI IDirectPlay2Impl_SetSessionDesc( IDirectPlay2 *iface, DPSESSIONDESC2 *sdesc,
3834 DWORD flags )
3836 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3837 return IDirectPlayX_SetSessionDesc( &This->IDirectPlay4_iface, sdesc, flags );
3840 static HRESULT WINAPI IDirectPlay3AImpl_SetSessionDesc( IDirectPlay3A *iface, DPSESSIONDESC2 *sdesc,
3841 DWORD flags )
3843 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3844 return IDirectPlayX_SetSessionDesc( &This->IDirectPlay4_iface, sdesc, flags );
3847 static HRESULT WINAPI IDirectPlay3Impl_SetSessionDesc( IDirectPlay3 *iface, DPSESSIONDESC2 *sdesc,
3848 DWORD flags )
3850 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3851 return IDirectPlayX_SetSessionDesc( &This->IDirectPlay4_iface, sdesc, flags );
3854 static HRESULT WINAPI IDirectPlay4AImpl_SetSessionDesc( IDirectPlay4A *iface,
3855 DPSESSIONDESC2 *lpSessDesc, DWORD dwFlags )
3857 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3858 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3861 static HRESULT WINAPI IDirectPlay4Impl_SetSessionDesc( IDirectPlay4 *iface,
3862 DPSESSIONDESC2 *lpSessDesc, DWORD dwFlags )
3864 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3865 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3868 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3869 static DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3871 DWORD dwSize = 0;
3873 if( lpSessDesc == NULL )
3875 /* Hmmm..don't need any size? */
3876 ERR( "NULL lpSessDesc\n" );
3877 return dwSize;
3880 dwSize += sizeof( *lpSessDesc );
3882 if( bAnsi )
3884 if( lpSessDesc->u1.lpszSessionNameA )
3886 dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1;
3889 if( lpSessDesc->u2.lpszPasswordA )
3891 dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1;
3894 else /* UNICODE */
3896 if( lpSessDesc->u1.lpszSessionName )
3898 dwSize += sizeof( WCHAR ) *
3899 ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 );
3902 if( lpSessDesc->u2.lpszPassword )
3904 dwSize += sizeof( WCHAR ) *
3905 ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 );
3909 return dwSize;
3912 /* Assumes that contiguous buffers are already allocated. */
3913 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3914 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3916 BYTE* lpStartOfFreeSpace;
3918 if( lpSessionDest == NULL )
3920 ERR( "NULL lpSessionDest\n" );
3921 return;
3924 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3926 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3928 if( bAnsi )
3930 if( lpSessionSrc->u1.lpszSessionNameA )
3932 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3933 lpSessionDest->u1.lpszSessionNameA );
3934 lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3935 lpStartOfFreeSpace +=
3936 lstrlenA( lpSessionDest->u1.lpszSessionNameA ) + 1;
3939 if( lpSessionSrc->u2.lpszPasswordA )
3941 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3942 lpSessionDest->u2.lpszPasswordA );
3943 lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3946 else /* UNICODE */
3948 if( lpSessionSrc->u1.lpszSessionName )
3950 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3951 lpSessionDest->u1.lpszSessionName );
3952 lpSessionDest->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3953 lpStartOfFreeSpace += sizeof(WCHAR) *
3954 ( lstrlenW( lpSessionDest->u1.lpszSessionName ) + 1 );
3957 if( lpSessionSrc->u2.lpszPassword )
3959 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3960 lpSessionDest->u2.lpszPassword );
3961 lpSessionDest->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3966 static HRESULT WINAPI IDirectPlay3AImpl_AddGroupToGroup( IDirectPlay3A *iface, DPID parent,
3967 DPID group )
3969 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3970 return IDirectPlayX_AddGroupToGroup( &This->IDirectPlay4A_iface, parent, group );
3973 static HRESULT WINAPI IDirectPlay3Impl_AddGroupToGroup( IDirectPlay3 *iface, DPID parent,
3974 DPID group )
3976 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3977 return IDirectPlayX_AddGroupToGroup( &This->IDirectPlay4_iface, parent, group );
3980 static HRESULT WINAPI IDirectPlay4AImpl_AddGroupToGroup( IDirectPlay4A *iface, DPID parent,
3981 DPID group )
3983 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3984 return IDirectPlayX_AddGroupToGroup( &This->IDirectPlay4_iface, parent, group );
3987 static HRESULT WINAPI IDirectPlay4Impl_AddGroupToGroup( IDirectPlay4 *iface, DPID parent,
3988 DPID group )
3990 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3991 lpGroupData gdata;
3992 lpGroupList glist;
3994 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, parent, group );
3996 if ( This->dp2->connectionInitialized == NO_PROVIDER )
3997 return DPERR_UNINITIALIZED;
3999 if ( !DP_FindAnyGroup(This, parent ) )
4000 return DPERR_INVALIDGROUP;
4002 if ( ( gdata = DP_FindAnyGroup(This, group ) ) == NULL )
4003 return DPERR_INVALIDGROUP;
4005 /* Create a player list (ie "shortcut" ) */
4006 glist = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *glist ) );
4007 if ( !glist )
4008 return DPERR_CANTADDPLAYER;
4010 /* Add the shortcut */
4011 gdata->uRef++;
4012 glist->lpGData = gdata;
4014 /* Add the player to the list of players for this group */
4015 DPQ_INSERT( gdata->groups, glist, groups );
4017 /* Send a ADDGROUPTOGROUP message */
4018 FIXME( "Not sending message\n" );
4020 return DP_OK;
4023 static HRESULT DP_IF_CreateGroupInGroup( IDirectPlayImpl *This, void *lpMsgHdr, DPID idParentGroup,
4024 DPID *lpidGroup, DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags,
4025 BOOL bAnsi )
4027 lpGroupData lpGParentData;
4028 lpGroupList lpGList;
4029 lpGroupData lpGData;
4031 TRACE( "(%p)->(0x%08x,%p,%p,%p,0x%08x,0x%08x,%u)\n",
4032 This, idParentGroup, lpidGroup, lpGroupName, lpData,
4033 dwDataSize, dwFlags, bAnsi );
4035 if( This->dp2->connectionInitialized == NO_PROVIDER )
4037 return DPERR_UNINITIALIZED;
4040 /* Verify that the specified parent is valid */
4041 if( ( lpGParentData = DP_FindAnyGroup(This, idParentGroup ) ) == NULL )
4042 return DPERR_INVALIDGROUP;
4044 lpGData = DP_CreateGroup(This, lpidGroup, lpGroupName, dwFlags, idParentGroup, bAnsi );
4046 if( lpGData == NULL )
4048 return DPERR_CANTADDPLAYER; /* yes player not group */
4051 /* Something else is referencing this data */
4052 lpGData->uRef++;
4054 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
4056 /* The list has now been inserted into the interface group list. We now
4057 need to put a "shortcut" to this group in the parent group */
4058 lpGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGList ) );
4059 if( lpGList == NULL )
4061 FIXME( "Memory leak\n" );
4062 return DPERR_CANTADDPLAYER; /* yes player not group */
4065 lpGList->lpGData = lpGData;
4067 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
4069 /* Let the SP know that we've created this group */
4070 if( This->dp2->spData.lpCB->CreateGroup )
4072 DPSP_CREATEGROUPDATA data;
4074 TRACE( "Calling SP CreateGroup\n" );
4076 data.idGroup = *lpidGroup;
4077 data.dwFlags = dwFlags;
4078 data.lpSPMessageHeader = lpMsgHdr;
4079 data.lpISP = This->dp2->spData.lpISP;
4081 (*This->dp2->spData.lpCB->CreateGroup)( &data );
4084 /* Inform all other peers of the creation of a new group. If there are
4085 * no peers keep this quiet.
4087 if( This->dp2->lpSessionDesc &&
4088 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
4090 DPMSG_CREATEPLAYERORGROUP msg;
4092 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
4093 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
4094 msg.dpId = *lpidGroup;
4095 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
4096 msg.lpData = lpData;
4097 msg.dwDataSize = dwDataSize;
4098 msg.dpnName = *lpGroupName;
4100 /* FIXME: Correct to just use send effectively? */
4101 /* FIXME: Should size include data w/ message or just message "header" */
4102 /* FIXME: Check return code */
4103 IDirectPlayX_SendEx( &This->IDirectPlay4_iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
4104 sizeof( msg ), 0, 0, NULL, NULL );
4107 return DP_OK;
4110 static HRESULT WINAPI IDirectPlay3AImpl_CreateGroupInGroup( IDirectPlay3A *iface, DPID parent,
4111 DPID *group, DPNAME *name, void *data, DWORD size, DWORD flags )
4113 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4114 return IDirectPlayX_CreateGroupInGroup( &This->IDirectPlay4A_iface, parent, group, name,
4115 data, size, flags );
4118 static HRESULT WINAPI IDirectPlay3Impl_CreateGroupInGroup( IDirectPlay3 *iface, DPID parent,
4119 DPID *group, DPNAME *name, void *data, DWORD size, DWORD flags )
4121 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4122 return IDirectPlayX_CreateGroupInGroup( &This->IDirectPlay4_iface, parent, group, name,
4123 data, size, flags );
4126 static HRESULT WINAPI IDirectPlay4AImpl_CreateGroupInGroup( IDirectPlay4A *iface,
4127 DPID idParentGroup, DPID *lpidGroup, DPNAME *lpGroupName, void *lpData, DWORD dwDataSize,
4128 DWORD dwFlags )
4130 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4132 *lpidGroup = DPID_UNKNOWN;
4134 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup, lpGroupName, lpData,
4135 dwDataSize, dwFlags, TRUE );
4138 static HRESULT WINAPI IDirectPlay4Impl_CreateGroupInGroup( IDirectPlay4 *iface, DPID idParentGroup,
4139 DPID *lpidGroup, DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags )
4141 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4143 *lpidGroup = DPID_UNKNOWN;
4145 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup, lpGroupName, lpData,
4146 dwDataSize, dwFlags, FALSE );
4149 static HRESULT WINAPI IDirectPlay3AImpl_DeleteGroupFromGroup( IDirectPlay3A *iface, DPID parent,
4150 DPID group )
4152 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4153 return IDirectPlayX_DeleteGroupFromGroup( &This->IDirectPlay4A_iface, parent, group );
4156 static HRESULT WINAPI IDirectPlay3Impl_DeleteGroupFromGroup( IDirectPlay3 *iface, DPID parent,
4157 DPID group )
4159 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4160 return IDirectPlayX_DeleteGroupFromGroup( &This->IDirectPlay4_iface, parent, group );
4163 static HRESULT WINAPI IDirectPlay4AImpl_DeleteGroupFromGroup( IDirectPlay4A *iface, DPID parent,
4164 DPID group )
4166 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4167 return IDirectPlayX_DeleteGroupFromGroup( &This->IDirectPlay4_iface, parent, group );
4170 static HRESULT WINAPI IDirectPlay4Impl_DeleteGroupFromGroup( IDirectPlay4 *iface, DPID parent,
4171 DPID group )
4173 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4174 lpGroupList glist;
4175 lpGroupData parentdata;
4177 TRACE("(%p)->(0x%08x,0x%08x)\n", This, parent, group );
4179 /* Is the parent group valid? */
4180 if ( ( parentdata = DP_FindAnyGroup(This, parent ) ) == NULL )
4181 return DPERR_INVALIDGROUP;
4183 /* Remove the group from the parent group queue */
4184 DPQ_REMOVE_ENTRY( parentdata->groups, groups, lpGData->dpid, ==, group, glist );
4186 if ( glist == NULL )
4187 return DPERR_INVALIDGROUP;
4189 /* Decrement the ref count */
4190 glist->lpGData->uRef--;
4192 /* Free up the list item */
4193 HeapFree( GetProcessHeap(), 0, glist );
4195 /* Should send a DELETEGROUPFROMGROUP message */
4196 FIXME( "message not sent\n" );
4198 return DP_OK;
4201 static BOOL DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
4202 LPDWORD lpdwBufSize )
4204 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
4205 HRESULT hr;
4207 dpCompoundAddress.dwDataSize = sizeof( GUID );
4208 dpCompoundAddress.guidDataType = DPAID_ServiceProvider;
4209 dpCompoundAddress.lpData = lpcSpGuid;
4211 *lplpAddrBuf = NULL;
4212 *lpdwBufSize = 0;
4214 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
4215 lpdwBufSize, TRUE );
4217 if( hr != DPERR_BUFFERTOOSMALL )
4219 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
4220 return FALSE;
4223 /* Now allocate the buffer */
4224 *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4225 *lpdwBufSize );
4227 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
4228 lpdwBufSize, TRUE );
4229 if( FAILED(hr) )
4231 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
4232 return FALSE;
4235 return TRUE;
4238 static HRESULT WINAPI IDirectPlay3AImpl_EnumConnections( IDirectPlay3A *iface,
4239 const GUID *application, LPDPENUMCONNECTIONSCALLBACK enumcb, void *context, DWORD flags )
4241 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4242 return IDirectPlayX_EnumConnections( &This->IDirectPlay4A_iface, application, enumcb, context,
4243 flags );
4246 static HRESULT WINAPI IDirectPlay3Impl_EnumConnections( IDirectPlay3 *iface,
4247 const GUID *application, LPDPENUMCONNECTIONSCALLBACK enumcb, void *context, DWORD flags )
4249 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4250 return IDirectPlayX_EnumConnections( &This->IDirectPlay4_iface, application, enumcb, context,
4251 flags );
4254 static HRESULT WINAPI IDirectPlay4AImpl_EnumConnections( IDirectPlay4A *iface,
4255 const GUID *lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, void *lpContext,
4256 DWORD dwFlags )
4258 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4259 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
4261 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
4262 if( dwFlags == 0 )
4264 dwFlags = DPCONNECTION_DIRECTPLAY;
4267 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
4268 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) )
4271 return DPERR_INVALIDFLAGS;
4274 if( !lpEnumCallback )
4276 return DPERR_INVALIDPARAMS;
4279 /* Enumerate DirectPlay service providers */
4280 if( dwFlags & DPCONNECTION_DIRECTPLAY )
4282 HKEY hkResult;
4283 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4284 LPCSTR guidDataSubKey = "Guid";
4285 char subKeyName[51];
4286 DWORD dwIndex, sizeOfSubKeyName=50;
4287 FILETIME filetime;
4289 /* Need to loop over the service providers in the registry */
4290 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4291 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4293 /* Hmmm. Does this mean that there are no service providers? */
4294 ERR(": no service providers?\n");
4295 return DP_OK;
4299 /* Traverse all the service providers we have available */
4300 for( dwIndex=0;
4301 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4302 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4303 ++dwIndex, sizeOfSubKeyName=51 )
4306 HKEY hkServiceProvider;
4307 GUID serviceProviderGUID;
4308 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
4309 char returnBuffer[51];
4310 WCHAR buff[51];
4311 DPNAME dpName;
4312 BOOL bBuildPass;
4314 LPVOID lpAddressBuffer = NULL;
4315 DWORD dwAddressBufferSize = 0;
4317 TRACE(" this time through: %s\n", subKeyName );
4319 /* Get a handle for this particular service provider */
4320 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4321 &hkServiceProvider ) != ERROR_SUCCESS )
4323 ERR(": what the heck is going on?\n" );
4324 continue;
4327 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4328 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
4329 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4331 ERR(": missing GUID registry data members\n" );
4332 RegCloseKey(hkServiceProvider);
4333 continue;
4335 RegCloseKey(hkServiceProvider);
4337 /* FIXME: Check return types to ensure we're interpreting data right */
4338 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4339 CLSIDFromString( buff, &serviceProviderGUID );
4340 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4342 /* Fill in the DPNAME struct for the service provider */
4343 dpName.dwSize = sizeof( dpName );
4344 dpName.dwFlags = 0;
4345 dpName.u1.lpszShortNameA = subKeyName;
4346 dpName.u2.lpszLongNameA = NULL;
4348 /* Create the compound address for the service provider.
4349 * NOTE: This is a gruesome architectural scar right now. DP
4350 * uses DPL and DPL uses DP. Nasty stuff. This may be why the
4351 * native dll just gets around this little bit by allocating an
4352 * 80 byte buffer which isn't even filled with a valid compound
4353 * address. Oh well. Creating a proper compound address is the
4354 * way to go anyways despite this method taking slightly more
4355 * heap space and realtime :) */
4357 bBuildPass = DP_BuildSPCompoundAddr( &serviceProviderGUID,
4358 &lpAddressBuffer,
4359 &dwAddressBufferSize );
4360 if( !bBuildPass )
4362 ERR( "Can't build compound addr\n" );
4363 return DPERR_GENERIC;
4366 /* The enumeration will return FALSE if we are not to continue */
4367 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
4368 &dpName, dwFlags, lpContext ) )
4370 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
4371 return DP_OK;
4373 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
4377 /* Enumerate DirectPlayLobby service providers */
4378 if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY )
4380 HKEY hkResult;
4381 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
4382 LPCSTR guidDataSubKey = "Guid";
4383 char subKeyName[51];
4384 DWORD dwIndex, sizeOfSubKeyName=50;
4385 FILETIME filetime;
4387 /* Need to loop over the service providers in the registry */
4388 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4389 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4391 TRACE("No Lobby Providers have been registered.\n");
4392 return DP_OK;
4396 /* Traverse all the lobby providers we have available */
4397 for( dwIndex=0;
4398 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4399 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4400 ++dwIndex, sizeOfSubKeyName=51 )
4403 HKEY hkServiceProvider;
4404 GUID serviceProviderGUID;
4405 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
4406 char returnBuffer[51];
4407 WCHAR buff[51];
4408 DPNAME dpName;
4409 HRESULT hr;
4411 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
4412 LPVOID lpAddressBuffer = NULL;
4413 DWORD dwAddressBufferSize = 0;
4415 TRACE(" this time through: %s\n", subKeyName );
4417 /* Get a handle for this particular service provider */
4418 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4419 &hkServiceProvider ) != ERROR_SUCCESS )
4421 ERR(": what the heck is going on?\n" );
4422 continue;
4425 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4426 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
4427 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4429 ERR(": missing GUID registry data members\n" );
4430 RegCloseKey(hkServiceProvider);
4431 continue;
4433 RegCloseKey(hkServiceProvider);
4435 /* FIXME: Check return types to ensure we're interpreting data right */
4436 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4437 CLSIDFromString( buff, &serviceProviderGUID );
4438 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4440 /* Fill in the DPNAME struct for the service provider */
4441 dpName.dwSize = sizeof( dpName );
4442 dpName.dwFlags = 0;
4443 dpName.u1.lpszShortNameA = subKeyName;
4444 dpName.u2.lpszLongNameA = NULL;
4446 /* Create the compound address for the service provider.
4447 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
4448 nast stuff. This may be why the native dll just gets around this little bit by
4449 allocating an 80 byte buffer which isn't even a filled with a valid compound
4450 address. Oh well. Creating a proper compound address is the way to go anyways
4451 despite this method taking slightly more heap space and realtime :) */
4453 dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
4454 dpCompoundAddress.dwDataSize = sizeof( GUID );
4455 dpCompoundAddress.lpData = &serviceProviderGUID;
4457 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
4458 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
4460 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
4461 return hr;
4464 /* Now allocate the buffer */
4465 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
4467 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
4468 &dwAddressBufferSize, TRUE ) ) != DP_OK )
4470 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
4471 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
4472 return hr;
4475 /* The enumeration will return FALSE if we are not to continue */
4476 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
4477 &dpName, dwFlags, lpContext ) )
4479 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
4480 return DP_OK;
4482 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
4486 return DP_OK;
4489 static HRESULT WINAPI IDirectPlay4Impl_EnumConnections( IDirectPlay4 *iface,
4490 const GUID *application, LPDPENUMCONNECTIONSCALLBACK enumcb, void *context, DWORD flags )
4492 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4493 return IDirectPlayX_EnumConnections( &This->IDirectPlay4A_iface, application, enumcb, context,
4494 flags );
4497 static HRESULT WINAPI IDirectPlay3AImpl_EnumGroupsInGroup( IDirectPlay3A *iface, DPID group,
4498 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
4500 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4501 return IDirectPlayX_EnumGroupsInGroup( &This->IDirectPlay4A_iface, group, instance,
4502 enumplayercb, context, flags );
4505 static HRESULT WINAPI IDirectPlay3Impl_EnumGroupsInGroup( IDirectPlay3 *iface, DPID group,
4506 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
4508 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4509 return IDirectPlayX_EnumGroupsInGroup( &This->IDirectPlay4_iface, group, instance,
4510 enumplayercb, context, flags );
4513 static HRESULT WINAPI IDirectPlay4AImpl_EnumGroupsInGroup( IDirectPlay4A *iface, DPID group,
4514 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
4516 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4517 return IDirectPlayX_EnumGroupsInGroup( &This->IDirectPlay4_iface, group, instance,
4518 enumplayercb, context, flags );
4521 static HRESULT WINAPI IDirectPlay4Impl_EnumGroupsInGroup( IDirectPlay4 *iface, DPID group,
4522 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
4524 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4525 lpGroupList glist;
4526 lpGroupData gdata;
4528 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x): semi stub\n", This, group, instance, enumplayercb,
4529 context, flags );
4531 if ( This->dp2->connectionInitialized == NO_PROVIDER )
4532 return DPERR_UNINITIALIZED;
4534 if ( ( gdata = DP_FindAnyGroup(This, group ) ) == NULL )
4535 return DPERR_INVALIDGROUP;
4537 if ( DPQ_IS_EMPTY( gdata->groups ) )
4538 return DP_OK;
4541 for( glist = DPQ_FIRST( gdata->groups ); ; glist = DPQ_NEXT( glist->groups ) )
4543 /* FIXME: Should check flags for match here */
4544 if ( !(*enumplayercb)( glist->lpGData->dpid, DPPLAYERTYPE_GROUP, &glist->lpGData->name,
4545 flags, context ) )
4546 return DP_OK; /* User requested break */
4548 if ( DPQ_IS_ENDOFLIST( glist->groups ) )
4549 break;
4552 return DP_OK;
4555 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupConnectionSettings( IDirectPlay3A *iface,
4556 DWORD flags, DPID group, void *data, DWORD *size )
4558 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4559 return IDirectPlayX_GetGroupConnectionSettings( &This->IDirectPlay4A_iface, flags, group,
4560 data, size );
4563 static HRESULT WINAPI IDirectPlay3Impl_GetGroupConnectionSettings( IDirectPlay3 *iface,
4564 DWORD flags, DPID group, void *data, DWORD *size )
4566 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4567 return IDirectPlayX_GetGroupConnectionSettings( &This->IDirectPlay4_iface, flags, group,
4568 data, size );
4571 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupConnectionSettings( IDirectPlay4A *iface,
4572 DWORD flags, DPID group, void *data, DWORD *size )
4574 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4575 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, flags, group, data, size );
4576 return DP_OK;
4579 static HRESULT WINAPI IDirectPlay4Impl_GetGroupConnectionSettings( IDirectPlay4 *iface, DWORD flags,
4580 DPID group, void *data, DWORD *size )
4582 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4583 FIXME( "(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, flags, group, data, size );
4584 return DP_OK;
4587 static BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
4588 REFGUID guidDataType,
4589 DWORD dwDataSize,
4590 LPCVOID lpData,
4591 LPVOID lpContext )
4593 /* Looking for the GUID of the provider to load */
4594 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
4595 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
4598 TRACE( "Found SP/LP (%s) %s (data size = 0x%08x)\n",
4599 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
4601 if( dwDataSize != sizeof( GUID ) )
4603 ERR( "Invalid sp/lp guid size 0x%08x\n", dwDataSize );
4606 memcpy( lpContext, lpData, dwDataSize );
4608 /* There shouldn't be more than 1 GUID/compound address */
4609 return FALSE;
4612 /* Still waiting for what we want */
4613 return TRUE;
4617 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
4618 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
4620 UINT i;
4621 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4622 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
4623 LPCSTR guidDataSubKey = "Guid";
4624 LPCSTR majVerDataSubKey = "dwReserved1";
4625 LPCSTR minVerDataSubKey = "dwReserved2";
4626 LPCSTR pathSubKey = "Path";
4628 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
4630 /* FIXME: Cloned code with a quick hack. */
4631 for( i=0; i<2; i++ )
4633 HKEY hkResult;
4634 LPCSTR searchSubKey;
4635 char subKeyName[51];
4636 DWORD dwIndex, sizeOfSubKeyName=50;
4637 FILETIME filetime;
4639 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
4640 *lpbIsDpSp = (i == 0);
4643 /* Need to loop over the service providers in the registry */
4644 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4645 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4647 /* Hmmm. Does this mean that there are no service providers? */
4648 ERR(": no service providers?\n");
4649 return 0;
4652 /* Traverse all the service providers we have available */
4653 for( dwIndex=0;
4654 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4655 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4656 ++dwIndex, sizeOfSubKeyName=51 )
4659 HKEY hkServiceProvider;
4660 GUID serviceProviderGUID;
4661 DWORD returnType, sizeOfReturnBuffer = 255;
4662 char returnBuffer[256];
4663 WCHAR buff[51];
4664 DWORD dwTemp, len;
4666 TRACE(" this time through: %s\n", subKeyName );
4668 /* Get a handle for this particular service provider */
4669 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4670 &hkServiceProvider ) != ERROR_SUCCESS )
4672 ERR(": what the heck is going on?\n" );
4673 continue;
4676 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4677 NULL, &returnType, (LPBYTE)returnBuffer,
4678 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4680 ERR(": missing GUID registry data members\n" );
4681 continue;
4684 /* FIXME: Check return types to ensure we're interpreting data right */
4685 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4686 CLSIDFromString( buff, &serviceProviderGUID );
4687 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4689 /* Determine if this is the Service Provider that the user asked for */
4690 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
4692 continue;
4695 if( i == 0 ) /* DP SP */
4697 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
4698 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
4699 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
4702 sizeOfReturnBuffer = 255;
4704 /* Get dwReserved1 */
4705 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
4706 NULL, &returnType, (LPBYTE)returnBuffer,
4707 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4709 ERR(": missing dwReserved1 registry data members\n") ;
4710 continue;
4713 if( i == 0 )
4714 memcpy( &lpSpData->dwReserved1, returnBuffer, sizeof(lpSpData->dwReserved1) );
4716 sizeOfReturnBuffer = 255;
4718 /* Get dwReserved2 */
4719 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4720 NULL, &returnType, (LPBYTE)returnBuffer,
4721 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4723 ERR(": missing dwReserved1 registry data members\n") ;
4724 continue;
4727 if( i == 0 )
4728 memcpy( &lpSpData->dwReserved2, returnBuffer, sizeof(lpSpData->dwReserved2) );
4730 sizeOfReturnBuffer = 255;
4732 /* Get the path for this service provider */
4733 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
4734 NULL, NULL, (LPBYTE)returnBuffer,
4735 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
4737 ERR(": missing PATH registry data members: 0x%08x\n", dwTemp );
4738 continue;
4741 TRACE( "Loading %s\n", returnBuffer );
4742 return LoadLibraryA( returnBuffer );
4746 return 0;
4749 static HRESULT DP_InitializeDPSP( IDirectPlayImpl *This, HMODULE hServiceProvider )
4751 HRESULT hr;
4752 LPDPSP_SPINIT SPInit;
4754 /* Initialize the service provider by calling SPInit */
4755 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4757 if( SPInit == NULL )
4759 ERR( "Service provider doesn't provide SPInit interface?\n" );
4760 FreeLibrary( hServiceProvider );
4761 return DPERR_UNAVAILABLE;
4764 TRACE( "Calling SPInit (DP SP entry point)\n" );
4766 hr = (*SPInit)( &This->dp2->spData );
4768 if( FAILED(hr) )
4770 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4771 FreeLibrary( hServiceProvider );
4772 return hr;
4775 /* FIXME: Need to verify the sanity of the returned callback table
4776 * using IsBadCodePtr */
4777 This->dp2->bSPInitialized = TRUE;
4779 /* This interface is now initialized as a DP object */
4780 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
4782 /* Store the handle of the module so that we can unload it later */
4783 This->dp2->hServiceProvider = hServiceProvider;
4785 return hr;
4788 static HRESULT DP_InitializeDPLSP( IDirectPlayImpl *This, HMODULE hLobbyProvider )
4790 HRESULT hr;
4791 LPSP_INIT DPLSPInit;
4793 /* Initialize the service provider by calling SPInit */
4794 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
4796 if( DPLSPInit == NULL )
4798 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4799 FreeLibrary( hLobbyProvider );
4800 return DPERR_UNAVAILABLE;
4803 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4805 hr = (*DPLSPInit)( &This->dp2->dplspData );
4807 if( FAILED(hr) )
4809 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4810 FreeLibrary( hLobbyProvider );
4811 return hr;
4814 /* FIXME: Need to verify the sanity of the returned callback table
4815 * using IsBadCodePtr */
4817 This->dp2->bDPLSPInitialized = TRUE;
4819 /* This interface is now initialized as a lobby object */
4820 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
4822 /* Store the handle of the module so that we can unload it later */
4823 This->dp2->hDPLobbyProvider = hLobbyProvider;
4825 return hr;
4828 static HRESULT WINAPI IDirectPlay3AImpl_InitializeConnection( IDirectPlay3A *iface,
4829 void *connection, DWORD flags )
4831 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4832 return IDirectPlayX_InitializeConnection( &This->IDirectPlay4A_iface, connection, flags );
4835 static HRESULT WINAPI IDirectPlay3Impl_InitializeConnection( IDirectPlay3 *iface,
4836 void *connection, DWORD flags )
4838 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4839 return IDirectPlayX_InitializeConnection( &This->IDirectPlay4_iface, connection, flags );
4842 static HRESULT WINAPI IDirectPlay4AImpl_InitializeConnection( IDirectPlay4A *iface,
4843 void *connection, DWORD flags )
4845 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4846 return IDirectPlayX_InitializeConnection( &This->IDirectPlay4_iface, connection, flags );
4849 static HRESULT WINAPI IDirectPlay4Impl_InitializeConnection( IDirectPlay4 *iface,
4850 void *connection, DWORD flags )
4852 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4853 HMODULE servprov;
4854 GUID sp;
4855 const DWORD size = 80; /* FIXME: Need to calculate it correctly */
4856 BOOL is_dp_sp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4857 HRESULT hr;
4859 TRACE( "(%p)->(%p,0x%08x)\n", This, connection, flags );
4861 if ( !connection )
4862 return DPERR_INVALIDPARAMS;
4864 if ( flags )
4865 return DPERR_INVALIDFLAGS;
4867 if ( This->dp2->connectionInitialized != NO_PROVIDER )
4868 return DPERR_ALREADYINITIALIZED;
4870 /* Find out what the requested SP is and how large this buffer is */
4871 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, connection, size, &sp );
4873 if ( FAILED(hr) )
4875 ERR( "Invalid compound address?\n" );
4876 return DPERR_UNAVAILABLE;
4879 /* Load the service provider */
4880 servprov = DP_LoadSP( &sp, &This->dp2->spData, &is_dp_sp );
4882 if ( !servprov )
4884 ERR( "Unable to load service provider %s\n", debugstr_guid(&sp) );
4885 return DPERR_UNAVAILABLE;
4888 if ( is_dp_sp )
4890 /* Fill in what we can of the Service Provider required information.
4891 * The rest was be done in DP_LoadSP
4893 This->dp2->spData.lpAddress = connection;
4894 This->dp2->spData.dwAddressSize = size;
4895 This->dp2->spData.lpGuid = &sp;
4896 hr = DP_InitializeDPSP( This, servprov );
4898 else
4900 This->dp2->dplspData.lpAddress = connection;
4901 hr = DP_InitializeDPLSP( This, servprov );
4904 if ( FAILED(hr) )
4905 return hr;
4907 return DP_OK;
4910 static HRESULT WINAPI IDirectPlay3AImpl_SecureOpen( IDirectPlay3A *iface,
4911 const DPSESSIONDESC2 *sdesc, DWORD flags, const DPSECURITYDESC *security,
4912 const DPCREDENTIALS *credentials )
4914 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4915 return IDirectPlayX_SecureOpen( &This->IDirectPlay4A_iface, sdesc, flags, security,
4916 credentials );
4919 static HRESULT WINAPI IDirectPlay3Impl_SecureOpen( IDirectPlay3 *iface,
4920 const DPSESSIONDESC2 *sdesc, DWORD flags, const DPSECURITYDESC *security,
4921 const DPCREDENTIALS *credentials )
4923 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4924 return IDirectPlayX_SecureOpen( &This->IDirectPlay4_iface, sdesc, flags, security,
4925 credentials );
4928 static HRESULT WINAPI IDirectPlay4AImpl_SecureOpen( IDirectPlay4A *iface,
4929 const DPSESSIONDESC2 *lpsd, DWORD dwFlags, const DPSECURITYDESC *lpSecurity,
4930 const DPCREDENTIALS *lpCredentials )
4932 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4933 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4936 static HRESULT WINAPI IDirectPlay4Impl_SecureOpen( IDirectPlay4 *iface,
4937 const DPSESSIONDESC2 *lpsd, DWORD dwFlags, const DPSECURITYDESC *lpSecurity,
4938 const DPCREDENTIALS *lpCredentials )
4940 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4941 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4944 static HRESULT WINAPI IDirectPlay3AImpl_SendChatMessage( IDirectPlay3A *iface, DPID from, DPID to,
4945 DWORD flags, DPCHAT *chatmsg )
4947 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4948 return IDirectPlayX_SendChatMessage( &This->IDirectPlay4A_iface, from, to, flags, chatmsg );
4951 static HRESULT WINAPI IDirectPlay3Impl_SendChatMessage( IDirectPlay3 *iface, DPID from, DPID to,
4952 DWORD flags, DPCHAT *chatmsg )
4954 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4955 return IDirectPlayX_SendChatMessage( &This->IDirectPlay4_iface, from, to, flags, chatmsg );
4958 static HRESULT WINAPI IDirectPlay4AImpl_SendChatMessage( IDirectPlay4A *iface, DPID from,
4959 DPID to, DWORD flags, DPCHAT *chatmsg )
4961 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4962 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, from, to, flags, chatmsg );
4963 return DP_OK;
4966 static HRESULT WINAPI IDirectPlay4Impl_SendChatMessage( IDirectPlay4 *iface, DPID from, DPID to,
4967 DWORD flags, DPCHAT *chatmsg )
4969 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4970 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, from, to, flags, chatmsg );
4971 return DP_OK;
4974 static HRESULT WINAPI IDirectPlay3AImpl_SetGroupConnectionSettings( IDirectPlay3A *iface,
4975 DWORD flags, DPID group, DPLCONNECTION *connection )
4977 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4978 return IDirectPlayX_SetGroupConnectionSettings( &This->IDirectPlay4A_iface, flags, group,
4979 connection );
4982 static HRESULT WINAPI IDirectPlay3Impl_SetGroupConnectionSettings( IDirectPlay3 *iface,
4983 DWORD flags, DPID group, DPLCONNECTION *connection )
4985 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4986 return IDirectPlayX_SetGroupConnectionSettings( &This->IDirectPlay4_iface, flags, group,
4987 connection );
4990 static HRESULT WINAPI IDirectPlay4AImpl_SetGroupConnectionSettings( IDirectPlay4A *iface,
4991 DWORD flags, DPID group, DPLCONNECTION *connection )
4993 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4994 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, flags, group, connection );
4995 return DP_OK;
4998 static HRESULT WINAPI IDirectPlay4Impl_SetGroupConnectionSettings( IDirectPlay4 *iface, DWORD flags,
4999 DPID group, DPLCONNECTION *connection )
5001 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5002 FIXME( "(%p)->(0x%08x,0x%08x,%p): stub\n", This, flags, group, connection );
5003 return DP_OK;
5006 static HRESULT WINAPI IDirectPlay3AImpl_StartSession( IDirectPlay3A *iface, DWORD flags,
5007 DPID group )
5009 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
5010 return IDirectPlayX_StartSession( &This->IDirectPlay4A_iface, flags, group );
5013 static HRESULT WINAPI IDirectPlay3Impl_StartSession( IDirectPlay3 *iface, DWORD flags,
5014 DPID group )
5016 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
5017 return IDirectPlayX_StartSession( &This->IDirectPlay4_iface, flags, group );
5020 static HRESULT WINAPI IDirectPlay4AImpl_StartSession( IDirectPlay4A *iface, DWORD flags,
5021 DPID group )
5023 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5024 return IDirectPlayX_StartSession( &This->IDirectPlay4_iface, flags, group );
5027 static HRESULT WINAPI IDirectPlay4Impl_StartSession( IDirectPlay4 *iface, DWORD flags, DPID group )
5029 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5030 FIXME( "(%p)->(0x%08x,0x%08x): stub\n", This, flags, group );
5031 return DP_OK;
5034 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupFlags( IDirectPlay3A *iface, DPID group,
5035 DWORD *flags )
5037 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
5038 return IDirectPlayX_GetGroupFlags( &This->IDirectPlay4A_iface, group, flags );
5041 static HRESULT WINAPI IDirectPlay3Impl_GetGroupFlags( IDirectPlay3 *iface, DPID group,
5042 DWORD *flags )
5044 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
5045 return IDirectPlayX_GetGroupFlags( &This->IDirectPlay4_iface, group, flags );
5048 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupFlags( IDirectPlay4A *iface, DPID group,
5049 DWORD *flags )
5051 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5052 return IDirectPlayX_GetGroupFlags( &This->IDirectPlay4_iface, group, flags );
5055 static HRESULT WINAPI IDirectPlay4Impl_GetGroupFlags( IDirectPlay4 *iface, DPID group,
5056 DWORD *flags )
5058 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5059 FIXME( "(%p)->(0x%08x,%p): stub\n", This, group, flags );
5060 return DP_OK;
5063 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupParent( IDirectPlay3A *iface, DPID group,
5064 DPID *parent )
5066 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
5067 return IDirectPlayX_GetGroupParent( &This->IDirectPlay4A_iface, group, parent );
5070 static HRESULT WINAPI IDirectPlay3Impl_GetGroupParent( IDirectPlay3 *iface, DPID group,
5071 DPID *parent )
5073 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
5074 return IDirectPlayX_GetGroupParent( &This->IDirectPlay4_iface, group, parent );
5077 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupParent( IDirectPlay4A *iface, DPID group,
5078 DPID *parent )
5080 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5081 return IDirectPlayX_GetGroupParent( &This->IDirectPlay4_iface, group, parent );
5084 static HRESULT WINAPI IDirectPlay4Impl_GetGroupParent( IDirectPlay4 *iface, DPID group,
5085 DPID *parent )
5087 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5088 lpGroupData gdata;
5090 TRACE( "(%p)->(0x%08x,%p)\n", This, group, parent );
5092 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
5093 return DPERR_INVALIDGROUP;
5095 *parent = gdata->dpid;
5097 return DP_OK;
5100 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerAccount( IDirectPlay3A *iface, DPID player,
5101 DWORD flags, void *data, DWORD *size )
5103 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
5104 return IDirectPlayX_GetPlayerAccount( &This->IDirectPlay4A_iface, player, flags, data, size );
5107 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerAccount( IDirectPlay3 *iface, DPID player,
5108 DWORD flags, void *data, DWORD *size )
5110 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
5111 return IDirectPlayX_GetPlayerAccount( &This->IDirectPlay4_iface, player, flags, data, size );
5114 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerAccount( IDirectPlay4A *iface, DPID player,
5115 DWORD flags, void *data, DWORD *size )
5117 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5118 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, player, flags, data, size );
5119 return DP_OK;
5122 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerAccount( IDirectPlay4 *iface, DPID player,
5123 DWORD flags, void *data, DWORD *size )
5125 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5126 FIXME( "(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, player, flags, data, size );
5127 return DP_OK;
5130 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerFlags( IDirectPlay3A *iface, DPID player,
5131 DWORD *flags )
5133 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
5134 return IDirectPlayX_GetPlayerFlags( &This->IDirectPlay4A_iface, player, flags );
5137 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerFlags( IDirectPlay3 *iface, DPID player,
5138 DWORD *flags )
5140 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
5141 return IDirectPlayX_GetPlayerFlags( &This->IDirectPlay4_iface, player, flags );
5144 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerFlags( IDirectPlay4A *iface, DPID player,
5145 DWORD *flags )
5147 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5148 return IDirectPlayX_GetPlayerFlags( &This->IDirectPlay4_iface, player, flags );
5151 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerFlags( IDirectPlay4 *iface, DPID player,
5152 DWORD *flags )
5154 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5155 FIXME( "(%p)->(0x%08x,%p): stub\n", This, player, flags );
5156 return DP_OK;
5159 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupOwner( IDirectPlay4A *iface, DPID group,
5160 DPID *owner )
5162 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5163 return IDirectPlayX_GetGroupOwner( &This->IDirectPlay4_iface, group, owner );
5166 static HRESULT WINAPI IDirectPlay4Impl_GetGroupOwner( IDirectPlay4 *iface, DPID group,
5167 DPID *owner )
5169 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5170 FIXME( "(%p)->(0x%08x,%p): stub\n", This, group, owner );
5171 return DP_OK;
5174 static HRESULT WINAPI IDirectPlay4AImpl_SetGroupOwner( IDirectPlay4A *iface, DPID group,
5175 DPID owner )
5177 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5178 return IDirectPlayX_SetGroupOwner( &This->IDirectPlay4_iface, group, owner );
5181 static HRESULT WINAPI IDirectPlay4Impl_SetGroupOwner( IDirectPlay4 *iface, DPID group ,
5182 DPID owner )
5184 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5185 FIXME( "(%p)->(0x%08x,0x%08x): stub\n", This, group, owner );
5186 return DP_OK;
5189 static HRESULT WINAPI IDirectPlay4AImpl_SendEx( IDirectPlay4A *iface, DPID from, DPID to,
5190 DWORD flags, void *data, DWORD size, DWORD priority, DWORD timeout, void *context,
5191 DWORD *msgid )
5193 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5194 return IDirectPlayX_SendEx( &This->IDirectPlay4_iface, from, to, flags, data, size, priority,
5195 timeout, context, msgid );
5198 static HRESULT WINAPI IDirectPlay4Impl_SendEx( IDirectPlay4 *iface, DPID from, DPID to,
5199 DWORD flags, void *data, DWORD size, DWORD priority, DWORD timeout, void *context,
5200 DWORD *msgid )
5202 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5204 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,0x%08x,0x%08x,0x%08x,%p,%p): semi-stub\n",
5205 This, from, to, flags, data, size, priority, timeout, context, msgid );
5207 if ( This->dp2->connectionInitialized == NO_PROVIDER )
5208 return DPERR_UNINITIALIZED;
5210 /* FIXME: Add parameter checking */
5211 /* FIXME: First call to this needs to acquire a message id which will be
5212 * used for multiple sends
5215 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
5217 /* Verify that the message is being sent from a valid local player. The
5218 * from player may be anonymous DPID_UNKNOWN
5220 if ( from != DPID_UNKNOWN && !DP_FindPlayer( This, from ) )
5222 WARN( "INFO: Invalid from player 0x%08x\n", from );
5223 return DPERR_INVALIDPLAYER;
5226 /* Verify that the message is being sent to a valid player, group or to
5227 * everyone. If it's valid, send it to those players.
5229 if ( to == DPID_ALLPLAYERS )
5231 /* See if SP has the ability to multicast. If so, use it */
5232 if ( This->dp2->spData.lpCB->SendToGroupEx )
5233 FIXME( "Use group sendex to group 0\n" );
5234 else if ( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
5235 FIXME( "Use obsolete group send to group 0\n" );
5236 else /* No multicast, multiplicate */
5237 FIXME( "Send to all players using EnumPlayersInGroup\n" );
5239 else if ( DP_FindPlayer( This, to ) )
5241 /* Have the service provider send this message */
5242 /* FIXME: Could optimize for local interface sends */
5243 return DP_SP_SendEx( This, flags, data, size, priority, timeout, context, msgid );
5245 else if ( DP_FindAnyGroup( This, to ) )
5247 /* See if SP has the ability to multicast. If so, use it */
5248 if ( This->dp2->spData.lpCB->SendToGroupEx )
5249 FIXME( "Use group sendex\n" );
5250 else if ( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
5251 FIXME( "Use obsolete group send to group\n" );
5252 else /* No multicast, multiplicate */
5253 FIXME( "Send to all players using EnumPlayersInGroup\n" );
5256 else
5257 return DPERR_INVALIDPLAYER;
5259 /* FIXME: Should return what the send returned */
5260 return DP_OK;
5263 static HRESULT DP_SP_SendEx( IDirectPlayImpl *This, DWORD dwFlags, void *lpData, DWORD dwDataSize,
5264 DWORD dwPriority, DWORD dwTimeout, void *lpContext, DWORD *lpdwMsgID )
5266 LPDPMSG lpMElem;
5268 FIXME( ": stub\n" );
5270 /* FIXME: This queuing should only be for async messages */
5272 lpMElem = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpMElem ) );
5273 lpMElem->msg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
5275 CopyMemory( lpMElem->msg, lpData, dwDataSize );
5277 /* FIXME: Need to queue based on priority */
5278 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
5280 return DP_OK;
5283 static HRESULT WINAPI IDirectPlay4AImpl_GetMessageQueue( IDirectPlay4A *iface, DPID from, DPID to,
5284 DWORD flags, DWORD *msgs, DWORD *bytes )
5286 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5287 return IDirectPlayX_GetMessageQueue( &This->IDirectPlay4_iface, from, to, flags, msgs, bytes );
5290 static HRESULT WINAPI IDirectPlay4Impl_GetMessageQueue( IDirectPlay4 *iface, DPID from, DPID to,
5291 DWORD flags, DWORD *msgs, DWORD *bytes )
5293 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5294 HRESULT hr = DP_OK;
5296 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%p): semi-stub\n", This, from, to, flags, msgs, bytes );
5298 /* FIXME: Do we need to do from and to sanity checking here? */
5299 /* FIXME: What about sends which are not immediate? */
5301 if ( This->dp2->spData.lpCB->GetMessageQueue )
5303 DPSP_GETMESSAGEQUEUEDATA data;
5305 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
5307 /* FIXME: None of this is documented :( */
5308 data.lpISP = This->dp2->spData.lpISP;
5309 data.dwFlags = flags;
5310 data.idFrom = from;
5311 data.idTo = to;
5312 data.lpdwNumMsgs = msgs;
5313 data.lpdwNumBytes = bytes;
5315 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
5317 else
5318 FIXME( "No SP for GetMessageQueue - fake some data\n" );
5320 return hr;
5323 static HRESULT dplay_cancelmsg ( IDirectPlayImpl* This, DWORD msgid, DWORD flags, DWORD minprio,
5324 DWORD maxprio )
5326 HRESULT hr = DP_OK;
5328 FIXME( "(%p)->(0x%08x,0x%08x): semi stub\n", This, msgid, flags );
5330 if ( This->dp2->spData.lpCB->Cancel )
5332 DPSP_CANCELDATA data;
5334 TRACE( "Calling SP Cancel\n" );
5336 /* FIXME: Undocumented callback */
5338 data.lpISP = This->dp2->spData.lpISP;
5339 data.dwFlags = flags;
5340 data.lprglpvSPMsgID = NULL;
5341 data.cSPMsgID = msgid;
5342 data.dwMinPriority = minprio;
5343 data.dwMaxPriority = maxprio;
5345 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
5347 else
5348 FIXME( "SP doesn't implement Cancel\n" );
5350 return hr;
5353 static HRESULT WINAPI IDirectPlay4AImpl_CancelMessage( IDirectPlay4A *iface, DWORD msgid,
5354 DWORD flags )
5356 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5357 return IDirectPlayX_CancelMessage( &This->IDirectPlay4_iface, msgid, flags );
5360 static HRESULT WINAPI IDirectPlay4Impl_CancelMessage( IDirectPlay4 *iface, DWORD msgid,
5361 DWORD flags )
5363 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5365 if ( flags != 0 )
5366 return DPERR_INVALIDFLAGS;
5368 if ( msgid == 0 )
5369 flags |= DPCANCELSEND_ALL;
5371 return dplay_cancelmsg( This, msgid, flags, 0, 0 );
5374 static HRESULT WINAPI IDirectPlay4AImpl_CancelPriority( IDirectPlay4A *iface, DWORD minprio,
5375 DWORD maxprio, DWORD flags )
5377 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5378 return IDirectPlayX_CancelPriority( &This->IDirectPlay4_iface, minprio, maxprio, flags );
5381 static HRESULT WINAPI IDirectPlay4Impl_CancelPriority( IDirectPlay4 *iface, DWORD minprio,
5382 DWORD maxprio, DWORD flags )
5384 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5386 if ( flags != 0 )
5387 return DPERR_INVALIDFLAGS;
5389 return dplay_cancelmsg( This, 0, DPCANCELSEND_PRIORITY, minprio, maxprio );
5392 static const IDirectPlay2Vtbl dp2_vt =
5394 IDirectPlay2Impl_QueryInterface,
5395 IDirectPlay2Impl_AddRef,
5396 IDirectPlay2Impl_Release,
5397 IDirectPlay2Impl_AddPlayerToGroup,
5398 IDirectPlay2Impl_Close,
5399 IDirectPlay2Impl_CreateGroup,
5400 IDirectPlay2Impl_CreatePlayer,
5401 IDirectPlay2Impl_DeletePlayerFromGroup,
5402 IDirectPlay2Impl_DestroyGroup,
5403 IDirectPlay2Impl_DestroyPlayer,
5404 IDirectPlay2Impl_EnumGroupPlayers,
5405 IDirectPlay2Impl_EnumGroups,
5406 IDirectPlay2Impl_EnumPlayers,
5407 IDirectPlay2Impl_EnumSessions,
5408 IDirectPlay2Impl_GetCaps,
5409 IDirectPlay2Impl_GetGroupData,
5410 IDirectPlay2Impl_GetGroupName,
5411 IDirectPlay2Impl_GetMessageCount,
5412 IDirectPlay2Impl_GetPlayerAddress,
5413 IDirectPlay2Impl_GetPlayerCaps,
5414 IDirectPlay2Impl_GetPlayerData,
5415 IDirectPlay2Impl_GetPlayerName,
5416 IDirectPlay2Impl_GetSessionDesc,
5417 IDirectPlay2Impl_Initialize,
5418 IDirectPlay2Impl_Open,
5419 IDirectPlay2Impl_Receive,
5420 IDirectPlay2Impl_Send,
5421 IDirectPlay2Impl_SetGroupData,
5422 IDirectPlay2Impl_SetGroupName,
5423 IDirectPlay2Impl_SetPlayerData,
5424 IDirectPlay2Impl_SetPlayerName,
5425 IDirectPlay2Impl_SetSessionDesc
5428 static const IDirectPlay2Vtbl dp2A_vt =
5430 IDirectPlay2AImpl_QueryInterface,
5431 IDirectPlay2AImpl_AddRef,
5432 IDirectPlay2AImpl_Release,
5433 IDirectPlay2AImpl_AddPlayerToGroup,
5434 IDirectPlay2AImpl_Close,
5435 IDirectPlay2AImpl_CreateGroup,
5436 IDirectPlay2AImpl_CreatePlayer,
5437 IDirectPlay2AImpl_DeletePlayerFromGroup,
5438 IDirectPlay2AImpl_DestroyGroup,
5439 IDirectPlay2AImpl_DestroyPlayer,
5440 IDirectPlay2AImpl_EnumGroupPlayers,
5441 IDirectPlay2AImpl_EnumGroups,
5442 IDirectPlay2AImpl_EnumPlayers,
5443 IDirectPlay2AImpl_EnumSessions,
5444 IDirectPlay2AImpl_GetCaps,
5445 IDirectPlay2AImpl_GetGroupData,
5446 IDirectPlay2AImpl_GetGroupName,
5447 IDirectPlay2AImpl_GetMessageCount,
5448 IDirectPlay2AImpl_GetPlayerAddress,
5449 IDirectPlay2AImpl_GetPlayerCaps,
5450 IDirectPlay2AImpl_GetPlayerData,
5451 IDirectPlay2AImpl_GetPlayerName,
5452 IDirectPlay2AImpl_GetSessionDesc,
5453 IDirectPlay2AImpl_Initialize,
5454 IDirectPlay2AImpl_Open,
5455 IDirectPlay2AImpl_Receive,
5456 IDirectPlay2AImpl_Send,
5457 IDirectPlay2AImpl_SetGroupData,
5458 IDirectPlay2AImpl_SetGroupName,
5459 IDirectPlay2AImpl_SetPlayerData,
5460 IDirectPlay2AImpl_SetPlayerName,
5461 IDirectPlay2AImpl_SetSessionDesc
5464 static const IDirectPlay3Vtbl dp3_vt =
5466 IDirectPlay3Impl_QueryInterface,
5467 IDirectPlay3Impl_AddRef,
5468 IDirectPlay3Impl_Release,
5469 IDirectPlay3Impl_AddPlayerToGroup,
5470 IDirectPlay3Impl_Close,
5471 IDirectPlay3Impl_CreateGroup,
5472 IDirectPlay3Impl_CreatePlayer,
5473 IDirectPlay3Impl_DeletePlayerFromGroup,
5474 IDirectPlay3Impl_DestroyGroup,
5475 IDirectPlay3Impl_DestroyPlayer,
5476 IDirectPlay3Impl_EnumGroupPlayers,
5477 IDirectPlay3Impl_EnumGroups,
5478 IDirectPlay3Impl_EnumPlayers,
5479 IDirectPlay3Impl_EnumSessions,
5480 IDirectPlay3Impl_GetCaps,
5481 IDirectPlay3Impl_GetGroupData,
5482 IDirectPlay3Impl_GetGroupName,
5483 IDirectPlay3Impl_GetMessageCount,
5484 IDirectPlay3Impl_GetPlayerAddress,
5485 IDirectPlay3Impl_GetPlayerCaps,
5486 IDirectPlay3Impl_GetPlayerData,
5487 IDirectPlay3Impl_GetPlayerName,
5488 IDirectPlay3Impl_GetSessionDesc,
5489 IDirectPlay3Impl_Initialize,
5490 IDirectPlay3Impl_Open,
5491 IDirectPlay3Impl_Receive,
5492 IDirectPlay3Impl_Send,
5493 IDirectPlay3Impl_SetGroupData,
5494 IDirectPlay3Impl_SetGroupName,
5495 IDirectPlay3Impl_SetPlayerData,
5496 IDirectPlay3Impl_SetPlayerName,
5497 IDirectPlay3Impl_SetSessionDesc,
5498 IDirectPlay3Impl_AddGroupToGroup,
5499 IDirectPlay3Impl_CreateGroupInGroup,
5500 IDirectPlay3Impl_DeleteGroupFromGroup,
5501 IDirectPlay3Impl_EnumConnections,
5502 IDirectPlay3Impl_EnumGroupsInGroup,
5503 IDirectPlay3Impl_GetGroupConnectionSettings,
5504 IDirectPlay3Impl_InitializeConnection,
5505 IDirectPlay3Impl_SecureOpen,
5506 IDirectPlay3Impl_SendChatMessage,
5507 IDirectPlay3Impl_SetGroupConnectionSettings,
5508 IDirectPlay3Impl_StartSession,
5509 IDirectPlay3Impl_GetGroupFlags,
5510 IDirectPlay3Impl_GetGroupParent,
5511 IDirectPlay3Impl_GetPlayerAccount,
5512 IDirectPlay3Impl_GetPlayerFlags
5515 static const IDirectPlay3Vtbl dp3A_vt =
5517 IDirectPlay3AImpl_QueryInterface,
5518 IDirectPlay3AImpl_AddRef,
5519 IDirectPlay3AImpl_Release,
5520 IDirectPlay3AImpl_AddPlayerToGroup,
5521 IDirectPlay3AImpl_Close,
5522 IDirectPlay3AImpl_CreateGroup,
5523 IDirectPlay3AImpl_CreatePlayer,
5524 IDirectPlay3AImpl_DeletePlayerFromGroup,
5525 IDirectPlay3AImpl_DestroyGroup,
5526 IDirectPlay3AImpl_DestroyPlayer,
5527 IDirectPlay3AImpl_EnumGroupPlayers,
5528 IDirectPlay3AImpl_EnumGroups,
5529 IDirectPlay3AImpl_EnumPlayers,
5530 IDirectPlay3AImpl_EnumSessions,
5531 IDirectPlay3AImpl_GetCaps,
5532 IDirectPlay3AImpl_GetGroupData,
5533 IDirectPlay3AImpl_GetGroupName,
5534 IDirectPlay3AImpl_GetMessageCount,
5535 IDirectPlay3AImpl_GetPlayerAddress,
5536 IDirectPlay3AImpl_GetPlayerCaps,
5537 IDirectPlay3AImpl_GetPlayerData,
5538 IDirectPlay3AImpl_GetPlayerName,
5539 IDirectPlay3AImpl_GetSessionDesc,
5540 IDirectPlay3AImpl_Initialize,
5541 IDirectPlay3AImpl_Open,
5542 IDirectPlay3AImpl_Receive,
5543 IDirectPlay3AImpl_Send,
5544 IDirectPlay3AImpl_SetGroupData,
5545 IDirectPlay3AImpl_SetGroupName,
5546 IDirectPlay3AImpl_SetPlayerData,
5547 IDirectPlay3AImpl_SetPlayerName,
5548 IDirectPlay3AImpl_SetSessionDesc,
5549 IDirectPlay3AImpl_AddGroupToGroup,
5550 IDirectPlay3AImpl_CreateGroupInGroup,
5551 IDirectPlay3AImpl_DeleteGroupFromGroup,
5552 IDirectPlay3AImpl_EnumConnections,
5553 IDirectPlay3AImpl_EnumGroupsInGroup,
5554 IDirectPlay3AImpl_GetGroupConnectionSettings,
5555 IDirectPlay3AImpl_InitializeConnection,
5556 IDirectPlay3AImpl_SecureOpen,
5557 IDirectPlay3AImpl_SendChatMessage,
5558 IDirectPlay3AImpl_SetGroupConnectionSettings,
5559 IDirectPlay3AImpl_StartSession,
5560 IDirectPlay3AImpl_GetGroupFlags,
5561 IDirectPlay3AImpl_GetGroupParent,
5562 IDirectPlay3AImpl_GetPlayerAccount,
5563 IDirectPlay3AImpl_GetPlayerFlags
5566 static const IDirectPlay4Vtbl dp4_vt =
5568 IDirectPlay4Impl_QueryInterface,
5569 IDirectPlay4Impl_AddRef,
5570 IDirectPlay4Impl_Release,
5571 IDirectPlay4Impl_AddPlayerToGroup,
5572 IDirectPlay4Impl_Close,
5573 IDirectPlay4Impl_CreateGroup,
5574 IDirectPlay4Impl_CreatePlayer,
5575 IDirectPlay4Impl_DeletePlayerFromGroup,
5576 IDirectPlay4Impl_DestroyGroup,
5577 IDirectPlay4Impl_DestroyPlayer,
5578 IDirectPlay4Impl_EnumGroupPlayers,
5579 IDirectPlay4Impl_EnumGroups,
5580 IDirectPlay4Impl_EnumPlayers,
5581 IDirectPlay4Impl_EnumSessions,
5582 IDirectPlay4Impl_GetCaps,
5583 IDirectPlay4Impl_GetGroupData,
5584 IDirectPlay4Impl_GetGroupName,
5585 IDirectPlay4Impl_GetMessageCount,
5586 IDirectPlay4Impl_GetPlayerAddress,
5587 IDirectPlay4Impl_GetPlayerCaps,
5588 IDirectPlay4Impl_GetPlayerData,
5589 IDirectPlay4Impl_GetPlayerName,
5590 IDirectPlay4Impl_GetSessionDesc,
5591 IDirectPlay4Impl_Initialize,
5592 IDirectPlay4Impl_Open,
5593 IDirectPlay4Impl_Receive,
5594 IDirectPlay4Impl_Send,
5595 IDirectPlay4Impl_SetGroupData,
5596 IDirectPlay4Impl_SetGroupName,
5597 IDirectPlay4Impl_SetPlayerData,
5598 IDirectPlay4Impl_SetPlayerName,
5599 IDirectPlay4Impl_SetSessionDesc,
5600 IDirectPlay4Impl_AddGroupToGroup,
5601 IDirectPlay4Impl_CreateGroupInGroup,
5602 IDirectPlay4Impl_DeleteGroupFromGroup,
5603 IDirectPlay4Impl_EnumConnections,
5604 IDirectPlay4Impl_EnumGroupsInGroup,
5605 IDirectPlay4Impl_GetGroupConnectionSettings,
5606 IDirectPlay4Impl_InitializeConnection,
5607 IDirectPlay4Impl_SecureOpen,
5608 IDirectPlay4Impl_SendChatMessage,
5609 IDirectPlay4Impl_SetGroupConnectionSettings,
5610 IDirectPlay4Impl_StartSession,
5611 IDirectPlay4Impl_GetGroupFlags,
5612 IDirectPlay4Impl_GetGroupParent,
5613 IDirectPlay4Impl_GetPlayerAccount,
5614 IDirectPlay4Impl_GetPlayerFlags,
5615 IDirectPlay4Impl_GetGroupOwner,
5616 IDirectPlay4Impl_SetGroupOwner,
5617 IDirectPlay4Impl_SendEx,
5618 IDirectPlay4Impl_GetMessageQueue,
5619 IDirectPlay4Impl_CancelMessage,
5620 IDirectPlay4Impl_CancelPriority
5623 static const IDirectPlay4Vtbl dp4A_vt =
5625 IDirectPlay4AImpl_QueryInterface,
5626 IDirectPlay4AImpl_AddRef,
5627 IDirectPlay4AImpl_Release,
5628 IDirectPlay4AImpl_AddPlayerToGroup,
5629 IDirectPlay4AImpl_Close,
5630 IDirectPlay4AImpl_CreateGroup,
5631 IDirectPlay4AImpl_CreatePlayer,
5632 IDirectPlay4AImpl_DeletePlayerFromGroup,
5633 IDirectPlay4AImpl_DestroyGroup,
5634 IDirectPlay4AImpl_DestroyPlayer,
5635 IDirectPlay4AImpl_EnumGroupPlayers,
5636 IDirectPlay4AImpl_EnumGroups,
5637 IDirectPlay4AImpl_EnumPlayers,
5638 IDirectPlay4AImpl_EnumSessions,
5639 IDirectPlay4AImpl_GetCaps,
5640 IDirectPlay4AImpl_GetGroupData,
5641 IDirectPlay4AImpl_GetGroupName,
5642 IDirectPlay4AImpl_GetMessageCount,
5643 IDirectPlay4AImpl_GetPlayerAddress,
5644 IDirectPlay4AImpl_GetPlayerCaps,
5645 IDirectPlay4AImpl_GetPlayerData,
5646 IDirectPlay4AImpl_GetPlayerName,
5647 IDirectPlay4AImpl_GetSessionDesc,
5648 IDirectPlay4AImpl_Initialize,
5649 IDirectPlay4AImpl_Open,
5650 IDirectPlay4AImpl_Receive,
5651 IDirectPlay4AImpl_Send,
5652 IDirectPlay4AImpl_SetGroupData,
5653 IDirectPlay4AImpl_SetGroupName,
5654 IDirectPlay4AImpl_SetPlayerData,
5655 IDirectPlay4AImpl_SetPlayerName,
5656 IDirectPlay4AImpl_SetSessionDesc,
5657 IDirectPlay4AImpl_AddGroupToGroup,
5658 IDirectPlay4AImpl_CreateGroupInGroup,
5659 IDirectPlay4AImpl_DeleteGroupFromGroup,
5660 IDirectPlay4AImpl_EnumConnections,
5661 IDirectPlay4AImpl_EnumGroupsInGroup,
5662 IDirectPlay4AImpl_GetGroupConnectionSettings,
5663 IDirectPlay4AImpl_InitializeConnection,
5664 IDirectPlay4AImpl_SecureOpen,
5665 IDirectPlay4AImpl_SendChatMessage,
5666 IDirectPlay4AImpl_SetGroupConnectionSettings,
5667 IDirectPlay4AImpl_StartSession,
5668 IDirectPlay4AImpl_GetGroupFlags,
5669 IDirectPlay4AImpl_GetGroupParent,
5670 IDirectPlay4AImpl_GetPlayerAccount,
5671 IDirectPlay4AImpl_GetPlayerFlags,
5672 IDirectPlay4AImpl_GetGroupOwner,
5673 IDirectPlay4AImpl_SetGroupOwner,
5674 IDirectPlay4AImpl_SendEx,
5675 IDirectPlay4AImpl_GetMessageQueue,
5676 IDirectPlay4AImpl_CancelMessage,
5677 IDirectPlay4AImpl_CancelPriority
5680 HRESULT dplay_create( REFIID riid, void **ppv )
5682 IDirectPlayImpl *obj;
5683 HRESULT hr;
5685 TRACE( "(%s, %p)\n", debugstr_guid( riid ), ppv );
5687 *ppv = NULL;
5688 obj = HeapAlloc( GetProcessHeap(), 0, sizeof( *obj ) );
5689 if ( !obj )
5690 return DPERR_OUTOFMEMORY;
5692 obj->IDirectPlay_iface.lpVtbl = &dp_vt;
5693 obj->IDirectPlay2A_iface.lpVtbl = &dp2A_vt;
5694 obj->IDirectPlay2_iface.lpVtbl = &dp2_vt;
5695 obj->IDirectPlay3A_iface.lpVtbl = &dp3A_vt;
5696 obj->IDirectPlay3_iface.lpVtbl = &dp3_vt;
5697 obj->IDirectPlay4A_iface.lpVtbl = &dp4A_vt;
5698 obj->IDirectPlay4_iface.lpVtbl = &dp4_vt;
5699 obj->numIfaces = 1;
5700 obj->ref = 0;
5701 obj->ref2A = 0;
5702 obj->ref2 = 0;
5703 obj->ref3A = 0;
5704 obj->ref3 = 0;
5705 obj->ref4A = 0;
5706 obj->ref4 = 1;
5708 InitializeCriticalSection( &obj->lock );
5709 obj->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectPlayImpl.lock");
5711 if ( DP_CreateDirectPlay2( obj ) )
5712 hr = IDirectPlayX_QueryInterface( &obj->IDirectPlay4_iface, riid, ppv );
5713 else
5714 hr = DPERR_NOMEMORY;
5715 IDirectPlayX_Release( &obj->IDirectPlay4_iface );
5717 return hr;
5721 HRESULT DP_GetSPPlayerData( IDirectPlayImpl *lpDP, DPID idPlayer, void **lplpData )
5723 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5725 if( lpPlayer == NULL )
5727 return DPERR_INVALIDPLAYER;
5730 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
5732 return DP_OK;
5735 HRESULT DP_SetSPPlayerData( IDirectPlayImpl *lpDP, DPID idPlayer, void *lpData )
5737 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5739 if( lpPlayer == NULL )
5741 return DPERR_INVALIDPLAYER;
5744 lpPlayer->lpPData->lpSPPlayerData = lpData;
5746 return DP_OK;
5749 /***************************************************************************
5750 * DirectPlayEnumerateAW
5752 * The pointer to the structure lpContext will be filled with the
5753 * appropriate data for each service offered by the OS. These services are
5754 * not necessarily available on this particular machine but are defined
5755 * as simple service providers under the "Service Providers" registry key.
5756 * This structure is then passed to lpEnumCallback for each of the different
5757 * services.
5759 * This API is useful only for applications written using DirectX3 or
5760 * worse. It is superseded by IDirectPlay3::EnumConnections which also
5761 * gives information on the actual connections.
5763 * defn of a service provider:
5764 * A dynamic-link library used by DirectPlay to communicate over a network.
5765 * The service provider contains all the network-specific code required
5766 * to send and receive messages. Online services and network operators can
5767 * supply service providers to use specialized hardware, protocols, communications
5768 * media, and network resources.
5771 static HRESULT DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA,
5772 LPDPENUMDPCALLBACKW lpEnumCallbackW,
5773 LPVOID lpContext)
5775 HKEY hkResult;
5776 static const WCHAR searchSubKey[] = {
5777 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
5778 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
5779 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
5780 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
5781 static const WCHAR guidKey[] = { 'G', 'u', 'i', 'd', 0 };
5782 static const WCHAR descW[] = { 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', 'W', 0 };
5784 DWORD dwIndex;
5785 FILETIME filetime;
5787 char *descriptionA = NULL;
5788 DWORD max_sizeOfDescriptionA = 0;
5789 WCHAR *descriptionW = NULL;
5790 DWORD max_sizeOfDescriptionW = 0;
5791 DWORD sizeOfSubKeyName;
5792 WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */
5793 LONG ret_value;
5794 static GUID *guid_cache;
5795 static int cache_count;
5797 if (!lpEnumCallbackA && !lpEnumCallbackW)
5799 return DPERR_INVALIDPARAMS;
5802 /* Need to loop over the service providers in the registry */
5803 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, searchSubKey,
5804 0, KEY_READ, &hkResult) != ERROR_SUCCESS)
5806 /* Hmmm. Does this mean that there are no service providers? */
5807 ERR(": no service provider key in the registry - check your Wine installation !!!\n");
5808 return DPERR_GENERIC;
5811 dwIndex = 0;
5814 sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR);
5815 ret_value = RegEnumKeyW(hkResult, dwIndex, subKeyName, sizeOfSubKeyName);
5816 dwIndex++;
5818 while (ret_value == ERROR_SUCCESS);
5819 /* The game Swing from bug 37185 expects GUID values to persist after
5820 * the end of the enumeration. */
5821 if (cache_count < dwIndex)
5823 HeapFree(GetProcessHeap(), 0, guid_cache);
5824 guid_cache = HeapAlloc(GetProcessHeap(), 0, sizeof(GUID) * dwIndex);
5825 if (!guid_cache)
5827 ERR(": failed to allocate required memory.\n");
5828 return DPERR_EXCEPTION;
5830 cache_count = dwIndex;
5832 /* Traverse all the service providers we have available */
5833 dwIndex = 0;
5834 while (1)
5836 HKEY hkServiceProvider;
5837 WCHAR guidKeyContent[(2 * 16) + 1 + 6 /* This corresponds to '{....-..-..-..-......}' */ ];
5838 DWORD sizeOfGuidKeyContent = sizeof(guidKeyContent);
5840 sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR);
5841 ret_value = RegEnumKeyExW(hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
5842 NULL, NULL, NULL, &filetime);
5843 if (ret_value == ERROR_NO_MORE_ITEMS)
5844 break;
5845 else if (ret_value != ERROR_SUCCESS)
5847 ERR(": could not enumerate on service provider key.\n");
5848 return DPERR_EXCEPTION;
5850 TRACE(" this time through sub-key %s.\n", debugstr_w(subKeyName));
5852 /* Open the key for this service provider */
5853 if (RegOpenKeyExW(hkResult, subKeyName, 0, KEY_READ, &hkServiceProvider) != ERROR_SUCCESS)
5855 ERR(": could not open registry key for service provider %s.\n", debugstr_w(subKeyName));
5856 continue;
5859 /* Get the GUID from the registry */
5860 if (RegQueryValueExW(hkServiceProvider, guidKey,
5861 NULL, NULL, (LPBYTE) guidKeyContent, &sizeOfGuidKeyContent) != ERROR_SUCCESS)
5863 ERR(": missing GUID registry data member for service provider %s.\n", debugstr_w(subKeyName));
5864 continue;
5866 if (sizeOfGuidKeyContent != sizeof(guidKeyContent))
5868 ERR(": invalid format for the GUID registry data member for service provider %s (%s).\n", debugstr_w(subKeyName), debugstr_w(guidKeyContent));
5869 continue;
5871 CLSIDFromString(guidKeyContent, &guid_cache[dwIndex]);
5873 /* The enumeration will return FALSE if we are not to continue.
5875 * Note: on my windows box, major / minor version is 6 / 0 for all service providers
5876 * and have no relation to any of the two dwReserved1 and dwReserved2 keys.
5877 * I think that it simply means that they are in-line with DirectX 6.0
5879 if (lpEnumCallbackA)
5881 DWORD sizeOfDescription = 0;
5883 /* Note that this is the A case of this function, so use the A variant to get the description string */
5884 if (RegQueryValueExA(hkServiceProvider, "DescriptionA",
5885 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5887 ERR(": missing 'DescriptionA' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5888 continue;
5890 if (sizeOfDescription > max_sizeOfDescriptionA)
5892 HeapFree(GetProcessHeap(), 0, descriptionA);
5893 max_sizeOfDescriptionA = sizeOfDescription;
5895 descriptionA = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5896 RegQueryValueExA(hkServiceProvider, "DescriptionA",
5897 NULL, NULL, (LPBYTE) descriptionA, &sizeOfDescription);
5899 if (!lpEnumCallbackA(&guid_cache[dwIndex], descriptionA, 6, 0, lpContext))
5900 goto end;
5902 else
5904 DWORD sizeOfDescription = 0;
5906 if (RegQueryValueExW(hkServiceProvider, descW,
5907 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5909 ERR(": missing 'DescriptionW' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5910 continue;
5912 if (sizeOfDescription > max_sizeOfDescriptionW)
5914 HeapFree(GetProcessHeap(), 0, descriptionW);
5915 max_sizeOfDescriptionW = sizeOfDescription;
5917 descriptionW = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5918 RegQueryValueExW(hkServiceProvider, descW,
5919 NULL, NULL, (LPBYTE) descriptionW, &sizeOfDescription);
5921 if (!lpEnumCallbackW(&guid_cache[dwIndex], descriptionW, 6, 0, lpContext))
5922 goto end;
5925 dwIndex++;
5928 end:
5929 HeapFree(GetProcessHeap(), 0, descriptionA);
5930 HeapFree(GetProcessHeap(), 0, descriptionW);
5932 return DP_OK;
5935 /***************************************************************************
5936 * DirectPlayEnumerate [DPLAYX.9]
5937 * DirectPlayEnumerateA [DPLAYX.2]
5939 HRESULT WINAPI DirectPlayEnumerateA(LPDPENUMDPCALLBACKA lpEnumCallback, LPVOID lpContext )
5941 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5943 return DirectPlayEnumerateAW(lpEnumCallback, NULL, lpContext);
5946 /***************************************************************************
5947 * DirectPlayEnumerateW [DPLAYX.3]
5949 HRESULT WINAPI DirectPlayEnumerateW(LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5951 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5953 return DirectPlayEnumerateAW(NULL, lpEnumCallback, lpContext);
5956 typedef struct tagCreateEnum
5958 LPVOID lpConn;
5959 LPCGUID lpGuid;
5960 } CreateEnumData, *lpCreateEnumData;
5962 /* Find and copy the matching connection for the SP guid */
5963 static BOOL CALLBACK cbDPCreateEnumConnections(
5964 LPCGUID lpguidSP,
5965 LPVOID lpConnection,
5966 DWORD dwConnectionSize,
5967 LPCDPNAME lpName,
5968 DWORD dwFlags,
5969 LPVOID lpContext)
5971 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5973 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5975 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5977 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5978 dwConnectionSize );
5979 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5981 /* Found the record that we were looking for */
5982 return FALSE;
5985 /* Haven't found what were looking for yet */
5986 return TRUE;
5990 /***************************************************************************
5991 * DirectPlayCreate [DPLAYX.1]
5994 HRESULT WINAPI DirectPlayCreate
5995 ( LPGUID lpGUID, LPDIRECTPLAY *lplpDP, IUnknown *pUnk )
5997 HRESULT hr;
5998 LPDIRECTPLAY3A lpDP3A;
5999 CreateEnumData cbData;
6001 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
6003 if( pUnk != NULL )
6005 return CLASS_E_NOAGGREGATION;
6008 if( (lplpDP == NULL) || (lpGUID == NULL) )
6010 return DPERR_INVALIDPARAMS;
6013 if ( dplay_create( &IID_IDirectPlay, (void**)lplpDP ) != DP_OK )
6014 return DPERR_UNAVAILABLE;
6016 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
6018 /* The GUID_NULL means don't bind a service provider. Just return the
6019 interface as is */
6020 return DP_OK;
6023 /* Bind the desired service provider since lpGUID is non NULL */
6024 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
6026 /* We're going to use a DP3 interface */
6027 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
6028 (LPVOID*)&lpDP3A );
6029 if( FAILED(hr) )
6031 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
6032 return hr;
6035 cbData.lpConn = NULL;
6036 cbData.lpGuid = lpGUID;
6038 /* We were given a service provider, find info about it... */
6039 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
6040 &cbData, DPCONNECTION_DIRECTPLAY );
6041 if( ( FAILED(hr) ) ||
6042 ( cbData.lpConn == NULL )
6045 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
6046 IDirectPlayX_Release( lpDP3A );
6047 return DPERR_UNAVAILABLE;
6050 /* Initialize the service provider */
6051 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
6052 if( FAILED(hr) )
6054 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
6055 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
6056 IDirectPlayX_Release( lpDP3A );
6057 return hr;
6060 /* Release our version of the interface now that we're done with it */
6061 IDirectPlayX_Release( lpDP3A );
6062 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
6064 return DP_OK;