dplayx: Enumeration needs to be reseted before opening a session
[wine/gsoc_dplay.git] / dlls / dplayx / dplay.c
blob540b32df716be19d9acafed7b6b97d457d06646c
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 #include "config.h"
21 #include "wine/port.h"
23 #include <stdarg.h>
24 #include <string.h>
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
28 #include "windef.h"
29 #include "winerror.h"
30 #include "winbase.h"
31 #include "winnt.h"
32 #include "winreg.h"
33 #include "winnls.h"
34 #include "wine/unicode.h"
35 #include "wine/debug.h"
37 #include "dpinit.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( IDirectPlay2AImpl* This, DPID dpid );
54 static lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* iface, LPDPID lpid,
55 LPDPNAME lpName, DWORD dwFlags,
56 HANDLE hEvent, BOOL bAnsi );
57 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, const DPNAME *lpSrc, BOOL bAnsi );
58 static void DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
59 LPVOID lpData, DWORD dwDataSize );
61 static lpGroupData DP_CreateGroup( IDirectPlay2AImpl* iface, const DPID *lpid,
62 const DPNAME *lpName, DWORD dwFlags,
63 DPID idParent, BOOL bAnsi );
64 static void DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
65 LPVOID lpData, DWORD dwDataSize );
66 static void DP_DeleteDPNameStruct( LPDPNAME lpDPName );
67 static void DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid );
68 static BOOL CALLBACK cbDeletePlayerFromAllGroups( DPID dpId,
69 DWORD dwPlayerType,
70 LPCDPNAME lpName,
71 DWORD dwFlags,
72 LPVOID lpContext );
73 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid );
74 static BOOL CALLBACK cbRemoveGroupOrPlayer( DPID dpId, DWORD dwPlayerType,
75 LPCDPNAME lpName, DWORD dwFlags,
76 LPVOID lpContext );
77 static void DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid );
79 /* Forward declarations of virtual tables */
80 static const IDirectPlay2Vtbl directPlay2AVT;
81 static const IDirectPlay3Vtbl directPlay3AVT;
82 static const IDirectPlay4Vtbl directPlay4AVT;
84 static const IDirectPlay2Vtbl directPlay2WVT;
85 static const IDirectPlay3Vtbl directPlay3WVT;
86 static const IDirectPlay4Vtbl directPlay4WVT;
88 /* Helper methods for player/group interfaces */
89 static HRESULT DP_IF_DeletePlayerFromGroup
90 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
91 DPID idPlayer, BOOL bAnsi );
92 static HRESULT DP_IF_CreatePlayer
93 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, LPDPID lpidPlayer,
94 LPDPNAME lpPlayerName, HANDLE hEvent, LPVOID lpData,
95 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
96 static HRESULT DP_IF_DestroyGroup
97 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi );
98 static HRESULT DP_IF_DestroyPlayer
99 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi );
100 static HRESULT DP_IF_EnumGroupPlayers
101 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
102 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
103 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
104 static HRESULT DP_IF_EnumGroups
105 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
106 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
107 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
108 static HRESULT DP_IF_EnumPlayers
109 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
110 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
111 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
112 static HRESULT DP_IF_GetGroupData
113 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
114 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
115 static HRESULT DP_IF_GetGroupName
116 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
117 LPDWORD lpdwDataSize, BOOL bAnsi );
118 static HRESULT DP_IF_GetPlayerData
119 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
120 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
121 static HRESULT DP_IF_GetPlayerName
122 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
123 LPDWORD lpdwDataSize, BOOL bAnsi );
124 static HRESULT DP_IF_SetGroupName
125 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
126 DWORD dwFlags, BOOL bAnsi );
127 static HRESULT DP_IF_SetPlayerData
128 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
129 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
130 static HRESULT DP_IF_SetPlayerName
131 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
132 DWORD dwFlags, BOOL bAnsi );
133 static HRESULT DP_IF_AddGroupToGroup
134 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
135 static HRESULT DP_IF_CreateGroup
136 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
137 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
138 DWORD dwFlags, BOOL bAnsi );
139 static HRESULT DP_IF_CreateGroupInGroup
140 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
141 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
142 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
143 static HRESULT DP_IF_AddPlayerToGroup
144 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
145 DPID idPlayer, BOOL bAnsi );
146 static HRESULT DP_IF_DeleteGroupFromGroup
147 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
148 static HRESULT DP_SetSessionDesc
149 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
150 DWORD dwFlags, BOOL bInitial, BOOL bAnsi );
151 static HRESULT DP_SecureOpen
152 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
153 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
154 BOOL bAnsi );
155 static HRESULT DP_SendEx
156 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
157 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
158 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi );
159 static HRESULT DP_IF_Receive
160 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
161 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi );
162 static HRESULT DP_IF_GetMessageQueue
163 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
164 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi );
165 static HRESULT DP_SP_SendEx
166 ( IDirectPlay2Impl* This, DWORD dwFlags,
167 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
168 LPVOID lpContext, LPDWORD lpdwMsgID );
169 static HRESULT DP_IF_SetGroupData
170 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
171 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
172 static HRESULT DP_IF_GetPlayerCaps
173 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
174 DWORD dwFlags );
175 static HRESULT DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi );
176 static HRESULT DP_IF_CancelMessage
177 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
178 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi );
179 static HRESULT DP_IF_EnumGroupsInGroup
180 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
181 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
182 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
183 static HRESULT DP_IF_GetGroupParent
184 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
185 BOOL bAnsi );
186 static HRESULT DP_IF_GetCaps
187 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags );
188 static HRESULT DP_IF_EnumSessions
189 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
190 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
191 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
192 static HRESULT DP_IF_InitializeConnection
193 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi );
194 static BOOL CALLBACK cbDPCreateEnumConnections( LPCGUID lpguidSP,
195 LPVOID lpConnection, DWORD dwConnectionSize, LPCDPNAME lpName,
196 DWORD dwFlags, LPVOID lpContext );
197 static BOOL DP_BuildCompoundAddr( GUID guidDataType, LPGUID lpcSpGuid,
198 LPVOID* lplpAddrBuf, LPDWORD lpdwBufSize );
202 static inline DPID DP_NextObjectId(void);
203 static DPID DP_GetRemoteNextObjectId(void);
205 static DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi );
206 static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc,
207 LPCDPSESSIONDESC2 srcSessDesc, BOOL bAnsi );
210 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp );
211 static HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider );
212 static HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hServiceProvider );
219 #define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */
220 #define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported
221 we don't have to change much */
222 #define DPID_NAME_SERVER 0x19a9d65b /* Don't ask me why */
224 /* Strip out dwFlag values which cannot be sent in the CREATEGROUP msg */
225 #define DPMSG_CREATEGROUP_DWFLAGS(x) ( (x) & DPGROUP_HIDDEN )
227 /* Strip out all dwFlags values for CREATEPLAYER msg */
228 #define DPMSG_CREATEPLAYER_DWFLAGS(x) 0
230 static LONG kludgePlayerGroupId = 1000;
232 /* ------------------------------------------------------------------ */
235 static BOOL DP_CreateIUnknown( LPVOID lpDP )
237 IDirectPlay2AImpl *This = lpDP;
239 This->unk = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->unk) ) );
240 if ( This->unk == NULL )
242 return FALSE;
245 InitializeCriticalSection( &This->unk->DP_lock );
246 This->unk->DP_lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectPlay2AImpl*->DirectPlayIUnknownData*->DP_lock");
248 return TRUE;
251 static BOOL DP_DestroyIUnknown( LPVOID lpDP )
253 IDirectPlay2AImpl *This = lpDP;
255 This->unk->DP_lock.DebugInfo->Spare[0] = 0;
256 DeleteCriticalSection( &This->unk->DP_lock );
257 HeapFree( GetProcessHeap(), 0, This->unk );
259 return TRUE;
262 static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
264 IDirectPlay2AImpl *This = lpDP;
266 This->dp2 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp2) ) );
267 if ( This->dp2 == NULL )
269 return FALSE;
272 This->dp2->bConnectionOpen = FALSE;
274 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
275 This->dp2->dwEnumSessionLock = 0;
277 This->dp2->bHostInterface = FALSE;
279 DPQ_INIT(This->dp2->receiveMsgs);
280 DPQ_INIT(This->dp2->sendMsgs);
281 DPQ_INIT(This->dp2->replysExpected);
283 if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
285 /* FIXME: Memory leak */
286 return FALSE;
289 /* Provide an initial session desc with nothing in it */
290 This->dp2->lpSessionDesc = HeapAlloc( GetProcessHeap(),
291 HEAP_ZERO_MEMORY,
292 sizeof( *This->dp2->lpSessionDesc ) );
293 if( This->dp2->lpSessionDesc == NULL )
295 /* FIXME: Memory leak */
296 return FALSE;
298 This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc );
300 /* We are emulating a dp 6 implementation */
301 This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION;
303 This->dp2->spData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
304 sizeof( *This->dp2->spData.lpCB ) );
305 This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB );
306 This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION;
308 /* This is the pointer to the service provider */
309 if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP,
310 (LPVOID*)&This->dp2->spData.lpISP, This ) )
313 /* FIXME: Memory leak */
314 return FALSE;
317 /* Setup lobby provider information */
318 This->dp2->dplspData.dwSPVersion = DPSP_MAJORVERSION;
319 This->dp2->dplspData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
320 sizeof( *This->dp2->dplspData.lpCB ) );
321 This->dp2->dplspData.lpCB->dwSize = sizeof( *This->dp2->dplspData.lpCB );
323 if( FAILED( DPLSP_CreateInterface( &IID_IDPLobbySP,
324 (LPVOID*)&This->dp2->dplspData.lpISP, This ) )
327 /* FIXME: Memory leak */
328 return FALSE;
331 return TRUE;
334 /* Definition of the global function in dplayx_queue.h. #
335 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
336 DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
338 HeapFree( GetProcessHeap(), 0, elem );
341 static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
343 IDirectPlay2AImpl *This = lpDP;
345 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
347 TerminateThread( This->dp2->hEnumSessionThread, 0 );
348 CloseHandle( This->dp2->hEnumSessionThread );
351 /* Finish with the SP - have it shutdown */
352 if( This->dp2->spData.lpCB->ShutdownEx )
354 DPSP_SHUTDOWNDATA data;
356 TRACE( "Calling SP ShutdownEx\n" );
358 data.lpISP = This->dp2->spData.lpISP;
360 (*This->dp2->spData.lpCB->ShutdownEx)( &data );
362 else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
364 TRACE( "Calling obsolete SP Shutdown\n" );
365 (*This->dp2->spData.lpCB->Shutdown)();
368 /* Unload the SP (if it exists) */
369 if( This->dp2->hServiceProvider != 0 )
371 FreeLibrary( This->dp2->hServiceProvider );
374 /* Unload the Lobby Provider (if it exists) */
375 if( This->dp2->hDPLobbyProvider != 0 )
377 FreeLibrary( This->dp2->hDPLobbyProvider );
380 /* FIXME: Need to delete receive and send msgs queue contents */
382 NS_DeleteSessionCache( This->dp2->lpNameServerData );
384 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
386 IDirectPlaySP_Release( This->dp2->spData.lpISP );
388 /* Delete the contents */
389 HeapFree( GetProcessHeap(), 0, This->dp2 );
391 return TRUE;
394 static BOOL DP_CreateDirectPlay3( LPVOID lpDP )
396 IDirectPlay3AImpl *This = lpDP;
398 This->dp3 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp3) ) );
399 if ( This->dp3 == NULL )
401 return FALSE;
404 return TRUE;
407 static BOOL DP_DestroyDirectPlay3( LPVOID lpDP )
409 IDirectPlay3AImpl *This = lpDP;
411 /* Delete the contents */
412 HeapFree( GetProcessHeap(), 0, This->dp3 );
414 return TRUE;
417 static BOOL DP_CreateDirectPlay4( LPVOID lpDP )
419 IDirectPlay4AImpl *This = lpDP;
421 This->dp4 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp4) ) );
422 if ( This->dp4 == NULL )
424 return FALSE;
427 return TRUE;
430 static BOOL DP_DestroyDirectPlay4( LPVOID lpDP )
432 IDirectPlay3AImpl *This = lpDP;
434 /* Delete the contents */
435 HeapFree( GetProcessHeap(), 0, This->dp4 );
437 return TRUE;
441 /* Create a new interface */
442 HRESULT DP_CreateInterface
443 ( REFIID riid, LPVOID* ppvObj )
445 TRACE( " for %s\n", debugstr_guid( riid ) );
447 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
448 sizeof( IDirectPlay2Impl ) );
450 if( *ppvObj == NULL )
452 return DPERR_OUTOFMEMORY;
455 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
457 IDirectPlay2Impl *This = *ppvObj;
458 This->lpVtbl = &directPlay2WVT;
460 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
462 IDirectPlay2AImpl *This = *ppvObj;
463 This->lpVtbl = &directPlay2AVT;
465 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
467 IDirectPlay3Impl *This = *ppvObj;
468 This->lpVtbl = &directPlay3WVT;
470 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
472 IDirectPlay3AImpl *This = *ppvObj;
473 This->lpVtbl = &directPlay3AVT;
475 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
477 IDirectPlay4Impl *This = *ppvObj;
478 This->lpVtbl = &directPlay4WVT;
480 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
482 IDirectPlay4AImpl *This = *ppvObj;
483 This->lpVtbl = &directPlay4AVT;
485 else
487 /* Unsupported interface */
488 HeapFree( GetProcessHeap(), 0, *ppvObj );
489 *ppvObj = NULL;
491 return E_NOINTERFACE;
494 /* Initialize it */
495 if ( DP_CreateIUnknown( *ppvObj ) &&
496 DP_CreateDirectPlay2( *ppvObj ) &&
497 DP_CreateDirectPlay3( *ppvObj ) &&
498 DP_CreateDirectPlay4( *ppvObj )
501 IDirectPlayX_AddRef( (LPDIRECTPLAY2A)*ppvObj );
503 return S_OK;
506 /* Initialize failed, destroy it */
507 DP_DestroyDirectPlay4( *ppvObj );
508 DP_DestroyDirectPlay3( *ppvObj );
509 DP_DestroyDirectPlay2( *ppvObj );
510 DP_DestroyIUnknown( *ppvObj );
512 HeapFree( GetProcessHeap(), 0, *ppvObj );
514 *ppvObj = NULL;
515 return DPERR_NOMEMORY;
519 /* Direct Play methods */
521 /* Shared between all dplay types */
522 static HRESULT WINAPI DP_QueryInterface
523 ( LPDIRECTPLAY2 iface, REFIID riid, LPVOID* ppvObj )
525 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
526 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
528 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
529 sizeof( *This ) );
531 if( *ppvObj == NULL )
533 return DPERR_OUTOFMEMORY;
536 CopyMemory( *ppvObj, This, sizeof( *This ) );
537 (*(IDirectPlay2Impl**)ppvObj)->ulInterfaceRef = 0;
539 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
541 IDirectPlay2Impl *This = *ppvObj;
542 This->lpVtbl = &directPlay2WVT;
544 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
546 IDirectPlay2AImpl *This = *ppvObj;
547 This->lpVtbl = &directPlay2AVT;
549 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
551 IDirectPlay3Impl *This = *ppvObj;
552 This->lpVtbl = &directPlay3WVT;
554 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
556 IDirectPlay3AImpl *This = *ppvObj;
557 This->lpVtbl = &directPlay3AVT;
559 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
561 IDirectPlay4Impl *This = *ppvObj;
562 This->lpVtbl = &directPlay4WVT;
564 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
566 IDirectPlay4AImpl *This = *ppvObj;
567 This->lpVtbl = &directPlay4AVT;
569 else
571 /* Unsupported interface */
572 HeapFree( GetProcessHeap(), 0, *ppvObj );
573 *ppvObj = NULL;
575 return E_NOINTERFACE;
578 IDirectPlayX_AddRef( (LPDIRECTPLAY2)*ppvObj );
580 return S_OK;
583 /* Shared between all dplay types */
584 static ULONG WINAPI DP_AddRef
585 ( LPDIRECTPLAY3 iface )
587 ULONG ulInterfaceRefCount, ulObjRefCount;
588 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
590 ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
591 ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
593 TRACE( "ref count incremented to %u:%u for %p\n",
594 ulInterfaceRefCount, ulObjRefCount, This );
596 return ulObjRefCount;
599 static ULONG WINAPI DP_Release
600 ( LPDIRECTPLAY3 iface )
602 ULONG ulInterfaceRefCount, ulObjRefCount;
604 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
606 ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
607 ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
609 TRACE( "ref count decremented to %u:%u for %p\n",
610 ulInterfaceRefCount, ulObjRefCount, This );
612 /* Deallocate if this is the last reference to the object */
613 if( ulObjRefCount == 0 )
615 /* If we're destroying the object, this must be the last ref
616 of the last interface */
617 DP_DestroyDirectPlay4( This );
618 DP_DestroyDirectPlay3( This );
619 DP_DestroyDirectPlay2( This );
620 DP_DestroyIUnknown( This );
623 /* Deallocate the interface */
624 if( ulInterfaceRefCount == 0 )
626 HeapFree( GetProcessHeap(), 0, This );
629 return ulObjRefCount;
632 static inline DPID DP_NextObjectId(void)
634 return (DPID)InterlockedIncrement( &kludgePlayerGroupId );
637 /* *lplpReply will be non NULL iff there is something to reply */
638 HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpcMessageBody,
639 DWORD dwMessageBodySize, LPCVOID lpcMessageHeader,
640 WORD wCommandId, WORD wVersion,
641 LPVOID* lplpReply, LPDWORD lpdwMsgSize )
643 TRACE( "(%p)->(%p,0x%08x,%p,0x%x,%u)\n",
644 This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId,
645 wVersion );
647 switch( wCommandId )
649 /* Name server needs to handle this request */
650 case DPMSGCMD_ENUMSESSIONS:
652 /* Reply expected */
653 NS_ReplyToEnumSessionsRequest( lpcMessageBody, lplpReply, lpdwMsgSize, This );
655 break;
658 /* Name server needs to handle this request */
659 case DPMSGCMD_ENUMSESSIONSREPLY:
661 /* No reply expected */
662 NS_AddRemoteComputerAsNameServer( lpcMessageHeader,
663 This->dp2->spData.dwSPHeaderSize,
664 lpcMessageBody,
665 This->dp2->lpNameServerData );
666 break;
669 case DPMSGCMD_REQUESTPLAYERID:
671 LPDPSP_MSG_REQUESTPLAYERID lpcMsg = lpcMessageBody;
672 LPDPSP_MSG_REQUESTPLAYERREPLY lpReply;
674 *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
676 *lplpReply = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, *lpdwMsgSize );
678 FIXME( "Ignoring Flags 0x%08x in request msg\n", lpcMsg->Flags );
680 /* Setup the reply */
681 lpReply = (LPDPSP_MSG_REQUESTPLAYERREPLY)( (LPBYTE)(*lplpReply) +
682 This->dp2->spData.dwSPHeaderSize );
684 lpReply->envelope.dwMagic = DPMSG_SIGNATURE;
685 lpReply->envelope.wCommandId = DPMSGCMD_REQUESTPLAYERREPLY;
686 lpReply->envelope.wVersion = DX61AVERSION;
688 lpReply->ID = DP_NextObjectId();
690 TRACE( "Allocating new playerid 0x%08x from remote request\n",
691 lpReply->ID );
693 break;
696 case DPMSGCMD_ADDFORWARD:
697 case DPMSGCMD_REQUESTPLAYERREPLY:
699 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
700 break;
703 case DPMSGCMD_ADDFORWARDREQUEST:
705 /*LPCDPSP_MSG_ADDFORWARDREQUEST lpcMsg =
706 (LPCDPSP_MSG_ADDFORWARDREQUEST) lpcMessageBody;*/
708 /* TODO: Send ADDFORWARD messages to all the players to populate
709 * their name tables.
710 * Start NametablePopulation timer and wait for ADDFORWARDACKs */
711 FIXME( "Spread name table population messages\n" );
713 /* TODO remember to set local addr somewhere */
714 /* call NS_SetLocalAddr with a SOCKADDR_IN */
716 break;
719 case DPMSGCMD_SUPERENUMPLAYERSREPLY:
721 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
722 break;
725 case DPMSGCMD_ADDFORWARDACK:
727 /* When we receive an ADDFORWARDACK for each of the ADDFORWARDs
728 * we've sent, send a SUPERENUMPLAYERSREPLY back to the peer
729 * that sent the ADDFORWARDREQUEST */
730 /* TODO: We'll skip this for now and just send the SUPERENUMPLAYERSREPLY
731 * right away when we get a ADDFORWARDREQUEST */
732 break;
735 default:
737 FIXME( "Unknown wCommandId 0x%08x. Ignoring message\n", wCommandId );
738 return DPERR_GENERIC;
742 return DP_OK;
746 static HRESULT DP_IF_AddPlayerToGroup
747 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
748 DPID idPlayer, BOOL bAnsi )
750 lpGroupData lpGData;
751 lpPlayerList lpPList;
752 lpPlayerList lpNewPList;
754 TRACE( "(%p)->(%p,0x%08x,0x%08x,%u)\n",
755 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
757 if( This->dp2->connectionInitialized == NO_PROVIDER )
759 return DPERR_UNINITIALIZED;
762 /* Find the group */
763 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
765 return DPERR_INVALIDGROUP;
768 /* Find the player */
769 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
771 return DPERR_INVALIDPLAYER;
774 /* Create a player list (ie "shortcut" ) */
775 lpNewPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewPList ) );
776 if( lpNewPList == NULL )
778 return DPERR_CANTADDPLAYER;
781 /* Add the shortcut */
782 lpPList->lpPData->uRef++;
783 lpNewPList->lpPData = lpPList->lpPData;
785 /* Add the player to the list of players for this group */
786 DPQ_INSERT(lpGData->players,lpNewPList,players);
788 /* Let the SP know that we've added a player to the group */
789 if( This->dp2->spData.lpCB->AddPlayerToGroup )
791 DPSP_ADDPLAYERTOGROUPDATA data;
793 TRACE( "Calling SP AddPlayerToGroup\n" );
795 data.idPlayer = idPlayer;
796 data.idGroup = idGroup;
797 data.lpISP = This->dp2->spData.lpISP;
799 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
802 /* Inform all other peers of the addition of player to the group. If there are
803 * no peers keep this event quiet.
804 * Also, if this event was the result of another machine sending it to us,
805 * don't bother rebroadcasting it.
807 if( ( lpMsgHdr == NULL ) &&
808 This->dp2->lpSessionDesc &&
809 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
811 DPMSG_ADDPLAYERTOGROUP msg;
812 msg.dwType = DPSYS_ADDPLAYERTOGROUP;
814 msg.dpIdGroup = idGroup;
815 msg.dpIdPlayer = idPlayer;
817 /* FIXME: Correct to just use send effectively? */
818 /* FIXME: Should size include data w/ message or just message "header" */
819 /* FIXME: Check return code */
820 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
823 return DP_OK;
826 static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
827 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
829 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
830 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, TRUE );
833 static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
834 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
836 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
837 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, FALSE );
840 static HRESULT DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi )
842 HRESULT hr = DP_OK;
844 TRACE("(%p)->(%u)\n", This, bAnsi );
846 /* FIXME: Need to find a new host I assume (how?) */
847 /* FIXME: Need to destroy all local groups */
848 /* FIXME: Need to migrate all remotely visible players to the new host */
850 /* Invoke the SP callback to inform of session close */
851 if( This->dp2->spData.lpCB->CloseEx )
853 DPSP_CLOSEDATA data;
855 TRACE( "Calling SP CloseEx\n" );
857 data.lpISP = This->dp2->spData.lpISP;
859 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
862 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
864 TRACE( "Calling SP Close (obsolete interface)\n" );
866 hr = (*This->dp2->spData.lpCB->Close)();
869 if ( !FAILED(hr) )
871 This->dp2->bConnectionOpen = FALSE;
874 return hr;
877 static HRESULT WINAPI DirectPlay2AImpl_Close
878 ( LPDIRECTPLAY2A iface )
880 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
881 return DP_IF_Close( This, TRUE );
884 static HRESULT WINAPI DirectPlay2WImpl_Close
885 ( LPDIRECTPLAY2 iface )
887 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
888 return DP_IF_Close( This, FALSE );
891 static
892 lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, const DPID *lpid,
893 const DPNAME *lpName, DWORD dwFlags,
894 DPID idParent, BOOL bAnsi )
896 lpGroupData lpGData;
898 /* Allocate the new space and add to end of high level group list */
899 lpGData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGData ) );
901 if( lpGData == NULL )
903 return NULL;
906 DPQ_INIT(lpGData->groups);
907 DPQ_INIT(lpGData->players);
909 /* Set the desired player ID - no sanity checking to see if it exists */
910 lpGData->dpid = *lpid;
912 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
914 /* FIXME: Should we check that the parent exists? */
915 lpGData->parent = idParent;
917 /* FIXME: Should we validate the dwFlags? */
918 lpGData->dwFlags = dwFlags;
920 TRACE( "Created group id 0x%08x\n", *lpid );
922 return lpGData;
925 /* This method assumes that all links to it are already deleted */
926 static void
927 DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid )
929 lpGroupList lpGList;
931 TRACE( "(%p)->(0x%08x)\n", This, dpid );
933 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
935 if( lpGList == NULL )
937 ERR( "DPID 0x%08x not found\n", dpid );
938 return;
941 if( --(lpGList->lpGData->uRef) )
943 FIXME( "Why is this not the last reference to group?\n" );
944 DebugBreak();
947 /* Delete player */
948 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
949 HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
951 /* Remove and Delete Player List object */
952 HeapFree( GetProcessHeap(), 0, lpGList );
956 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid )
958 lpGroupList lpGroups;
960 TRACE( "(%p)->(0x%08x)\n", This, dpid );
962 if( dpid == DPID_SYSTEM_GROUP )
964 return This->dp2->lpSysGroup;
966 else
968 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
971 if( lpGroups == NULL )
973 return NULL;
976 return lpGroups->lpGData;
979 static HRESULT DP_IF_CreateGroup
980 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
981 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
982 DWORD dwFlags, BOOL bAnsi )
984 lpGroupData lpGData;
986 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
987 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
988 dwFlags, bAnsi );
990 /* If the name is not specified, we must provide one */
991 if( DPID_UNKNOWN == *lpidGroup )
993 /* If we are the name server, we decide on the group ids. If not, we
994 * must ask for one before attempting a creation.
996 if( This->dp2->bHostInterface )
998 *lpidGroup = DP_NextObjectId();
1000 else
1002 *lpidGroup = DP_GetRemoteNextObjectId();
1006 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
1007 DPID_NOPARENT_GROUP, bAnsi );
1009 if( lpGData == NULL )
1011 return DPERR_CANTADDPLAYER; /* yes player not group */
1014 if( DPID_SYSTEM_GROUP == *lpidGroup )
1016 This->dp2->lpSysGroup = lpGData;
1017 TRACE( "Inserting system group\n" );
1019 else
1021 /* Insert into the system group */
1022 lpGroupList lpGroup = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGroup ) );
1023 lpGroup->lpGData = lpGData;
1025 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
1028 /* Something is now referencing this data */
1029 lpGData->uRef++;
1031 /* Set all the important stuff for the group */
1032 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
1034 /* FIXME: We should only create the system group if GetCaps returns
1035 * DPCAPS_GROUPOPTIMIZED.
1038 /* Let the SP know that we've created this group */
1039 if( This->dp2->spData.lpCB->CreateGroup )
1041 DPSP_CREATEGROUPDATA data;
1042 DWORD dwCreateFlags = 0;
1044 TRACE( "Calling SP CreateGroup\n" );
1046 if( *lpidGroup == DPID_NOPARENT_GROUP )
1047 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
1049 if( lpMsgHdr == NULL )
1050 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1052 if( dwFlags & DPGROUP_HIDDEN )
1053 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
1055 data.idGroup = *lpidGroup;
1056 data.dwFlags = dwCreateFlags;
1057 data.lpSPMessageHeader = lpMsgHdr;
1058 data.lpISP = This->dp2->spData.lpISP;
1060 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1063 /* Inform all other peers of the creation of a new group. If there are
1064 * no peers keep this event quiet.
1065 * Also if this message was sent to us, don't rebroadcast.
1067 if( ( lpMsgHdr == NULL ) &&
1068 This->dp2->lpSessionDesc &&
1069 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1071 DPMSG_CREATEPLAYERORGROUP msg;
1072 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1074 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1075 msg.dpId = *lpidGroup;
1076 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1077 msg.lpData = lpData;
1078 msg.dwDataSize = dwDataSize;
1079 msg.dpnName = *lpGroupName;
1080 msg.dpIdParent = DPID_NOPARENT_GROUP;
1081 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
1083 /* FIXME: Correct to just use send effectively? */
1084 /* FIXME: Should size include data w/ message or just message "header" */
1085 /* FIXME: Check return code */
1086 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
1087 0, 0, NULL, NULL, bAnsi );
1090 return DP_OK;
1093 static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
1094 ( LPDIRECTPLAY2A iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1095 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1097 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1099 if( This->dp2->connectionInitialized == NO_PROVIDER )
1101 return DPERR_UNINITIALIZED;
1104 if( lpidGroup == NULL ||
1105 !This->dp2->bConnectionOpen ||
1106 dwDataSize >= MAXDWORD ||
1107 ( lpData == NULL && dwDataSize != 0 ) )
1109 return DPERR_INVALIDPARAMS;
1112 *lpidGroup = DPID_UNKNOWN;
1114 return DP_IF_CreateGroup( This, NULL, lpidGroup,
1115 lpGroupName, lpData, dwDataSize, dwFlags, TRUE );
1118 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
1119 ( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1120 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1122 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1124 if( This->dp2->connectionInitialized == NO_PROVIDER )
1126 return DPERR_UNINITIALIZED;
1129 if( lpidGroup == NULL ||
1130 !This->dp2->bConnectionOpen ||
1131 dwDataSize >= MAXDWORD ||
1132 ( lpData == NULL && dwDataSize != 0 ) )
1134 return DPERR_INVALIDPARAMS;
1137 *lpidGroup = DPID_UNKNOWN;
1139 return DP_IF_CreateGroup( This, NULL, lpidGroup,
1140 lpGroupName, lpData, dwDataSize, dwFlags, FALSE );
1144 static void
1145 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
1146 LPVOID lpData, DWORD dwDataSize )
1148 /* Clear out the data with this player */
1149 if( dwFlags & DPSET_LOCAL )
1151 if ( lpGData->dwLocalDataSize != 0 )
1153 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
1154 lpGData->lpLocalData = NULL;
1155 lpGData->dwLocalDataSize = 0;
1158 else
1160 if( lpGData->dwRemoteDataSize != 0 )
1162 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
1163 lpGData->lpRemoteData = NULL;
1164 lpGData->dwRemoteDataSize = 0;
1168 /* Reallocate for new data */
1169 if( lpData != NULL )
1171 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1172 sizeof( dwDataSize ) );
1173 CopyMemory( lpNewData, lpData, dwDataSize );
1175 if( dwFlags & DPSET_LOCAL )
1177 lpGData->lpLocalData = lpData;
1178 lpGData->dwLocalDataSize = dwDataSize;
1180 else
1182 lpGData->lpRemoteData = lpNewData;
1183 lpGData->dwRemoteDataSize = dwDataSize;
1189 /* This function will just create the storage for the new player. */
1190 static
1191 lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid,
1192 LPDPNAME lpName, DWORD dwFlags,
1193 HANDLE hEvent, BOOL bAnsi )
1195 lpPlayerData lpPData;
1197 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
1199 /* Allocate the storage for the player and associate it with list element */
1200 lpPData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPData ) );
1201 if( lpPData == NULL )
1203 return NULL;
1206 /* Set the desired player ID */
1207 lpPData->dpid = *lpid;
1209 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
1211 lpPData->dwFlags = dwFlags;
1213 /* If we were given an event handle, duplicate it */
1214 if( hEvent != 0 )
1216 if( !DuplicateHandle( GetCurrentProcess(), hEvent,
1217 GetCurrentProcess(), &lpPData->hEvent,
1218 0, FALSE, DUPLICATE_SAME_ACCESS )
1221 /* FIXME: Memory leak */
1222 ERR( "Can't duplicate player msg handle %p\n", hEvent );
1226 /* Initialize the SP data section */
1227 lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData();
1229 TRACE( "Created player id 0x%08x\n", *lpid );
1231 if( ~dwFlags & DPLAYI_PLAYER_SYSPLAYER )
1232 This->dp2->lpSessionDesc->dwCurrentPlayers++;
1234 return lpPData;
1237 /* Delete the contents of the DPNAME struct */
1238 static void
1239 DP_DeleteDPNameStruct( LPDPNAME lpDPName )
1241 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u1.lpszShortNameA );
1242 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u2.lpszLongNameA );
1245 /* This method assumes that all links to it are already deleted */
1246 static void
1247 DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid )
1249 lpPlayerList lpPList;
1251 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1253 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1255 if( lpPList == NULL )
1257 ERR( "DPID 0x%08x not found\n", dpid );
1258 return;
1261 /* Verify that this is the last reference to the data */
1262 if( --(lpPList->lpPData->uRef) )
1264 FIXME( "Why is this not the last reference to player?\n" );
1265 DebugBreak();
1268 /* Delete player */
1269 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1271 CloseHandle( lpPList->lpPData->hEvent );
1272 HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
1274 /* Delete Player List object */
1275 HeapFree( GetProcessHeap(), 0, lpPList );
1278 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid )
1280 lpPlayerList lpPlayers;
1282 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1284 if(This->dp2->lpSysGroup == NULL)
1285 return NULL;
1287 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1289 return lpPlayers;
1292 /* Basic area for Dst must already be allocated */
1293 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, const DPNAME *lpSrc, BOOL bAnsi )
1295 if( lpSrc == NULL )
1297 ZeroMemory( lpDst, sizeof( *lpDst ) );
1298 lpDst->dwSize = sizeof( *lpDst );
1299 return TRUE;
1302 if( lpSrc->dwSize != sizeof( *lpSrc) )
1304 return FALSE;
1307 /* Delete any existing pointers */
1308 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1309 HeapFree( GetProcessHeap(), 0, lpDst->u2.lpszLongNameA );
1311 /* Copy as required */
1312 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1314 if( bAnsi )
1316 if( lpSrc->u1.lpszShortNameA )
1318 lpDst->u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), 0,
1319 strlen(lpSrc->u1.lpszShortNameA)+1 );
1320 strcpy( lpDst->u1.lpszShortNameA, lpSrc->u1.lpszShortNameA );
1322 if( lpSrc->u2.lpszLongNameA )
1324 lpDst->u2.lpszLongNameA = HeapAlloc( GetProcessHeap(), 0,
1325 strlen(lpSrc->u2.lpszLongNameA)+1 );
1326 strcpy( lpDst->u2.lpszLongNameA, lpSrc->u2.lpszLongNameA );
1329 else
1331 if( lpSrc->u1.lpszShortNameA )
1333 lpDst->u1.lpszShortName = HeapAlloc( GetProcessHeap(), 0,
1334 (strlenW(lpSrc->u1.lpszShortName)+1)*sizeof(WCHAR) );
1335 strcpyW( lpDst->u1.lpszShortName, lpSrc->u1.lpszShortName );
1337 if( lpSrc->u2.lpszLongNameA )
1339 lpDst->u2.lpszLongName = HeapAlloc( GetProcessHeap(), 0,
1340 (strlenW(lpSrc->u2.lpszLongName)+1)*sizeof(WCHAR) );
1341 strcpyW( lpDst->u2.lpszLongName, lpSrc->u2.lpszLongName );
1345 return TRUE;
1348 static void
1349 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
1350 LPVOID lpData, DWORD dwDataSize )
1352 /* Clear out the data with this player */
1353 if( dwFlags & DPSET_LOCAL )
1355 if ( lpPData->dwLocalDataSize != 0 )
1357 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
1358 lpPData->lpLocalData = NULL;
1359 lpPData->dwLocalDataSize = 0;
1362 else
1364 if( lpPData->dwRemoteDataSize != 0 )
1366 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
1367 lpPData->lpRemoteData = NULL;
1368 lpPData->dwRemoteDataSize = 0;
1372 /* Reallocate for new data */
1373 if( lpData != NULL )
1375 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1376 sizeof( dwDataSize ) );
1377 CopyMemory( lpNewData, lpData, dwDataSize );
1379 if( dwFlags & DPSET_LOCAL )
1381 lpPData->lpLocalData = lpData;
1382 lpPData->dwLocalDataSize = dwDataSize;
1384 else
1386 lpPData->lpRemoteData = lpNewData;
1387 lpPData->dwRemoteDataSize = dwDataSize;
1393 static HRESULT DP_IF_CreatePlayer
1394 ( IDirectPlay2Impl* This,
1395 LPVOID lpMsgHdr, /* NULL for local creation, non NULL for remote creation */
1396 LPDPID lpidPlayer,
1397 LPDPNAME lpPlayerName,
1398 HANDLE hEvent,
1399 LPVOID lpData,
1400 DWORD dwDataSize,
1401 DWORD dwFlags,
1402 BOOL bAnsi )
1404 HRESULT hr = DP_OK;
1405 lpPlayerData lpPData;
1406 lpPlayerList lpPList;
1408 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1409 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1410 dwDataSize, dwFlags, bAnsi );
1412 if( dwFlags == 0 )
1414 dwFlags = DPPLAYER_SPECTATOR;
1417 if( lpidPlayer == NULL )
1419 return DPERR_INVALIDPARAMS;
1423 /* Determine the creation flags for the player. These will be passed
1424 * to the name server if requesting a player id and to the SP when
1425 * informing it of the player creation
1428 if( dwFlags & DPPLAYER_SERVERPLAYER )
1430 if( *lpidPlayer == DPID_SERVERPLAYER )
1432 /* Server player for the host interface */
1433 dwFlags |= DPLAYI_PLAYER_APPSERVER;
1435 else if( *lpidPlayer == DPID_NAME_SERVER )
1437 /* Name server - master of everything */
1438 dwFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
1440 else
1442 /* Server player for a non host interface */
1443 dwFlags |= DPLAYI_PLAYER_SYSPLAYER;
1447 if( lpMsgHdr == NULL )
1448 dwFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1451 /* Verify we know how to handle all the flags */
1452 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1453 ( dwFlags & DPPLAYER_SPECTATOR )
1457 /* Assume non fatal failure */
1458 ERR( "unknown dwFlags = 0x%08x\n", dwFlags );
1461 /* If the name is not specified, we must provide one */
1462 if( *lpidPlayer == DPID_UNKNOWN )
1464 /* If we are the session master, we dish out the group/player ids */
1465 if( This->dp2->bHostInterface )
1467 *lpidPlayer = DP_NextObjectId();
1469 else
1471 hr = DP_MSG_SendRequestPlayerId( This, dwFlags & 0x000000FF, lpidPlayer );
1473 if( FAILED(hr) )
1475 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1476 return hr;
1480 else
1482 /* Verify that we don't already have this player */
1484 lpPlayerList lpPlayers = NULL;
1485 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players,
1486 lpPData->dpid, ==, *lpidPlayer, lpPlayers );
1488 if (lpPlayers != NULL)
1490 return DPERR_CANTCREATEPLAYER;
1495 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwFlags,
1496 hEvent, bAnsi );
1498 if( lpPData == NULL )
1500 return DPERR_CANTADDPLAYER;
1503 /* Create the list object and link it in */
1504 lpPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPList ) );
1505 if( lpPList == NULL )
1507 FIXME( "Memory leak\n" );
1508 return DPERR_CANTADDPLAYER;
1511 lpPData->uRef = 1;
1512 lpPList->lpPData = lpPData;
1514 /* Add the player to the system group */
1515 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1517 /* Update the information and send it to all players in the session */
1518 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
1520 /* Let the SP know that we've created this player */
1521 if( This->dp2->spData.lpCB->CreatePlayer )
1523 DPSP_CREATEPLAYERDATA data;
1525 data.idPlayer = *lpidPlayer;
1526 data.dwFlags = dwFlags;
1527 data.lpSPMessageHeader = lpMsgHdr;
1528 data.lpISP = This->dp2->spData.lpISP;
1530 TRACE( "Calling SP CreatePlayer 0x%08x: dwFlags: 0x%08x lpMsgHdr: %p\n",
1531 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
1533 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1536 if( FAILED(hr) )
1538 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1539 return hr;
1542 /* Now let the SP know that this player is a member of the system group */
1543 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1545 DPSP_ADDPLAYERTOGROUPDATA data;
1547 data.idPlayer = *lpidPlayer;
1548 data.idGroup = DPID_SYSTEM_GROUP;
1549 data.lpISP = This->dp2->spData.lpISP;
1551 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1553 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1556 if( FAILED(hr) )
1558 ERR( "Failed to add player to sys group with sp: %s\n",
1559 DPLAYX_HresultToString(hr) );
1560 return hr;
1563 #if 1
1564 if( This->dp2->bHostInterface == FALSE )
1566 /* Let the name server know about the creation of this player */
1567 /* FIXME: Is this only to be done for the creation of a server player or
1568 * is this used for regular players? If only for server players, move
1569 * this call to DP_SecureOpen(...);
1572 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
1574 #else
1575 /* Inform all other peers of the creation of a new player. If there are
1576 * no peers keep this quiet.
1577 * Also, if this was a remote event, no need to rebroadcast it.
1579 if( ( lpMsgHdr == NULL ) &&
1580 This->dp2->lpSessionDesc &&
1581 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1583 DPMSG_CREATEPLAYERORGROUP msg;
1584 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1586 msg.dwPlayerType = DPPLAYERTYPE_PLAYER;
1587 msg.dpId = *lpidPlayer;
1588 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */
1589 msg.lpData = lpData;
1590 msg.dwDataSize = dwDataSize;
1591 msg.dpnName = *lpPlayerName;
1592 msg.dpIdParent = DPID_NOPARENT_GROUP;
1593 msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
1595 /* FIXME: Correct to just use send effectively? */
1596 /* FIXME: Should size include data w/ message or just message "header" */
1597 /* FIXME: Check return code */
1598 hr = DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
1599 sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
1601 #endif
1603 return hr;
1606 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
1607 ( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1608 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1610 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1612 if( This->dp2->connectionInitialized == NO_PROVIDER )
1614 return DPERR_UNINITIALIZED;
1617 if( lpidPlayer == NULL || !This->dp2->bConnectionOpen )
1619 return DPERR_INVALIDPARAMS;
1622 if ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_NEWPLAYERSDISABLED )
1624 return DPERR_CANTCREATEPLAYER;
1627 if( dwFlags & DPPLAYER_SERVERPLAYER )
1629 *lpidPlayer = DPID_SERVERPLAYER;
1631 else
1633 *lpidPlayer = DPID_UNKNOWN;
1636 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1637 lpData, dwDataSize, dwFlags, TRUE );
1640 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
1641 ( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1642 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1644 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1646 if( This->dp2->connectionInitialized == NO_PROVIDER )
1648 return DPERR_UNINITIALIZED;
1651 if( lpidPlayer == NULL || !This->dp2->bConnectionOpen )
1653 return DPERR_INVALIDPARAMS;
1656 if ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_NEWPLAYERSDISABLED )
1658 return DPERR_CANTCREATEPLAYER;
1661 if( dwFlags & DPPLAYER_SERVERPLAYER )
1663 *lpidPlayer = DPID_SERVERPLAYER;
1665 else
1667 *lpidPlayer = DPID_UNKNOWN;
1670 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1671 lpData, dwDataSize, dwFlags, FALSE );
1674 static DPID DP_GetRemoteNextObjectId(void)
1676 FIXME( ":stub\n" );
1678 /* Hack solution */
1679 return DP_NextObjectId();
1682 static HRESULT DP_IF_DeletePlayerFromGroup
1683 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
1684 DPID idPlayer, BOOL bAnsi )
1686 HRESULT hr = DP_OK;
1688 lpGroupData lpGData;
1689 lpPlayerList lpPList;
1691 TRACE( "(%p)->(%p,0x%08x,0x%08x,%u)\n",
1692 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
1694 /* Find the group */
1695 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1697 return DPERR_INVALIDGROUP;
1700 /* Find the player */
1701 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
1703 return DPERR_INVALIDPLAYER;
1706 /* Remove the player shortcut from the group */
1707 DPQ_REMOVE_ENTRY( lpGData->players, players, lpPData->dpid, ==, idPlayer, lpPList );
1709 if( lpPList == NULL )
1711 return DPERR_INVALIDPLAYER;
1714 /* One less reference */
1715 lpPList->lpPData->uRef--;
1717 /* Delete the Player List element */
1718 HeapFree( GetProcessHeap(), 0, lpPList );
1720 /* Inform the SP if they care */
1721 if( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1723 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1725 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1727 data.idPlayer = idPlayer;
1728 data.idGroup = idGroup;
1729 data.lpISP = This->dp2->spData.lpISP;
1731 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1734 /* Need to send a DELETEPLAYERFROMGROUP message */
1735 FIXME( "Need to send a message\n" );
1737 return hr;
1740 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
1741 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
1743 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1744 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, TRUE );
1747 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
1748 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
1750 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1751 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, FALSE );
1754 typedef struct _DPRGOPContext
1756 IDirectPlay3Impl* This;
1757 BOOL bAnsi;
1758 DPID idGroup;
1759 } DPRGOPContext, *lpDPRGOPContext;
1761 static BOOL CALLBACK
1762 cbRemoveGroupOrPlayer(
1763 DPID dpId,
1764 DWORD dwPlayerType,
1765 LPCDPNAME lpName,
1766 DWORD dwFlags,
1767 LPVOID lpContext )
1769 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1771 TRACE( "Removing element:0x%08x (type:0x%08x) from element:0x%08x\n",
1772 dpId, dwPlayerType, lpCtxt->idGroup );
1774 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1776 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt->This, lpCtxt->idGroup,
1777 dpId )
1781 ERR( "Unable to delete group 0x%08x from group 0x%08x\n",
1782 dpId, lpCtxt->idGroup );
1785 else
1787 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl*)lpCtxt->This,
1788 NULL, lpCtxt->idGroup,
1789 dpId, lpCtxt->bAnsi )
1793 ERR( "Unable to delete player 0x%08x from grp 0x%08x\n",
1794 dpId, lpCtxt->idGroup );
1798 return TRUE; /* Continue enumeration */
1801 static HRESULT DP_IF_DestroyGroup
1802 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi )
1804 lpGroupData lpGData;
1805 DPRGOPContext context;
1807 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1808 This, lpMsgHdr, idGroup, bAnsi );
1810 /* Find the group */
1811 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1813 return DPERR_INVALIDPLAYER; /* yes player */
1816 context.This = (IDirectPlay3Impl*)This;
1817 context.bAnsi = bAnsi;
1818 context.idGroup = idGroup;
1820 /* Remove all players that this group has */
1821 DP_IF_EnumGroupPlayers( This, idGroup, NULL,
1822 cbRemoveGroupOrPlayer, &context, 0, bAnsi );
1824 /* Remove all links to groups that this group has since this is dp3 */
1825 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This, idGroup, NULL,
1826 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1828 /* Remove this group from the parent group - if it has one */
1829 if( ( idGroup != DPID_SYSTEM_GROUP ) &&
1830 ( lpGData->parent != DPID_SYSTEM_GROUP )
1833 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl*)This, lpGData->parent,
1834 idGroup );
1837 /* Now delete this group data and list from the system group */
1838 DP_DeleteGroup( This, idGroup );
1840 /* Let the SP know that we've destroyed this group */
1841 if( This->dp2->spData.lpCB->DeleteGroup )
1843 DPSP_DELETEGROUPDATA data;
1845 FIXME( "data.dwFlags is incorrect\n" );
1847 data.idGroup = idGroup;
1848 data.dwFlags = 0;
1849 data.lpISP = This->dp2->spData.lpISP;
1851 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1854 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1856 return DP_OK;
1859 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
1860 ( LPDIRECTPLAY2A iface, DPID idGroup )
1862 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1863 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
1866 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
1867 ( LPDIRECTPLAY2 iface, DPID idGroup )
1869 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1870 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
1873 typedef struct _DPFAGContext
1875 IDirectPlay2Impl* This;
1876 DPID idPlayer;
1877 BOOL bAnsi;
1878 } DPFAGContext, *lpDPFAGContext;
1880 static HRESULT DP_IF_DestroyPlayer
1881 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi )
1883 DPFAGContext cbContext;
1885 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1886 This, lpMsgHdr, idPlayer, bAnsi );
1888 if( This->dp2->connectionInitialized == NO_PROVIDER )
1890 return DPERR_UNINITIALIZED;
1893 if( DP_FindPlayer( This, idPlayer ) == NULL )
1895 return DPERR_INVALIDPLAYER;
1898 /* FIXME: If the player is remote, we must be the host to delete this */
1900 cbContext.This = This;
1901 cbContext.idPlayer = idPlayer;
1902 cbContext.bAnsi = bAnsi;
1904 /* Find each group and call DeletePlayerFromGroup if the player is a
1905 member of the group */
1906 DP_IF_EnumGroups( This, NULL, cbDeletePlayerFromAllGroups,
1907 &cbContext, DPENUMGROUPS_ALL, bAnsi );
1909 /* Now delete player and player list from the sys group */
1910 DP_DeletePlayer( This, idPlayer );
1912 /* Let the SP know that we've destroyed this group */
1913 if( This->dp2->spData.lpCB->DeletePlayer )
1915 DPSP_DELETEPLAYERDATA data;
1917 FIXME( "data.dwFlags is incorrect\n" );
1919 data.idPlayer = idPlayer;
1920 data.dwFlags = 0;
1921 data.lpISP = This->dp2->spData.lpISP;
1923 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
1926 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
1928 return DP_OK;
1931 static BOOL CALLBACK
1932 cbDeletePlayerFromAllGroups(
1933 DPID dpId,
1934 DWORD dwPlayerType,
1935 LPCDPNAME lpName,
1936 DWORD dwFlags,
1937 LPVOID lpContext )
1939 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
1941 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1943 DP_IF_DeletePlayerFromGroup( lpCtxt->This, NULL, dpId, lpCtxt->idPlayer,
1944 lpCtxt->bAnsi );
1946 /* Enumerate all groups in this group since this will normally only
1947 * be called for top level groups
1949 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)lpCtxt->This,
1950 dpId, NULL,
1951 cbDeletePlayerFromAllGroups,
1952 lpContext, DPENUMGROUPS_ALL,
1953 lpCtxt->bAnsi );
1956 else
1958 ERR( "Group callback has dwPlayerType = 0x%08x\n", dwPlayerType );
1961 return TRUE;
1964 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
1965 ( LPDIRECTPLAY2A iface, DPID idPlayer )
1967 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1968 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
1971 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
1972 ( LPDIRECTPLAY2 iface, DPID idPlayer )
1974 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1975 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
1978 static HRESULT DP_IF_EnumGroupPlayers
1979 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
1980 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1981 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1983 lpGroupData lpGData;
1984 lpPlayerList lpPList;
1986 FIXME("(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
1987 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
1988 lpContext, dwFlags, bAnsi );
1990 if( This->dp2->connectionInitialized == NO_PROVIDER )
1992 return DPERR_UNINITIALIZED;
1995 if( !This->dp2->bConnectionOpen )
1997 return DPERR_NOSESSIONS;
2000 if( ( lpEnumPlayersCallback2 == NULL ) ||
2001 ( ( dwFlags & DPENUMPLAYERS_SESSION ) && ( lpguidInstance == NULL ) ) )
2003 return DPERR_INVALIDPARAMS;
2006 /* Find the group */
2007 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2009 return DPERR_INVALIDGROUP;
2012 if( DPQ_IS_EMPTY( lpGData->players ) )
2014 return DP_OK;
2017 lpPList = DPQ_FIRST( lpGData->players );
2019 /* Walk the players in this group */
2020 for( ;; )
2022 /* We do not enum the name server or app server as they are of no
2023 * consequence to the end user.
2025 if( ( lpPList->lpPData->dpid != DPID_NAME_SERVER ) &&
2026 ( lpPList->lpPData->dpid != DPID_SERVERPLAYER )
2030 /* FIXME: Need to add stuff for dwFlags checking */
2032 if( !lpEnumPlayersCallback2( lpPList->lpPData->dpid, DPPLAYERTYPE_PLAYER,
2033 &lpPList->lpPData->name,
2034 lpPList->lpPData->dwFlags,
2035 lpContext )
2038 /* User requested break */
2039 return DP_OK;
2043 if( DPQ_IS_ENDOFLIST( lpPList->players ) )
2045 break;
2048 lpPList = DPQ_NEXT( lpPList->players );
2051 return DP_OK;
2054 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
2055 ( LPDIRECTPLAY2A iface, DPID idGroup, LPGUID lpguidInstance,
2056 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2057 LPVOID lpContext, DWORD dwFlags )
2059 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2060 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2061 lpEnumPlayersCallback2, lpContext,
2062 dwFlags, TRUE );
2065 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
2066 ( LPDIRECTPLAY2 iface, DPID idGroup, LPGUID lpguidInstance,
2067 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2068 LPVOID lpContext, DWORD dwFlags )
2070 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2071 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2072 lpEnumPlayersCallback2, lpContext,
2073 dwFlags, FALSE );
2076 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2077 static HRESULT DP_IF_EnumGroups
2078 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2079 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2080 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2082 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This,
2083 DPID_SYSTEM_GROUP, lpguidInstance,
2084 lpEnumPlayersCallback2, lpContext,
2085 dwFlags, bAnsi );
2088 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
2089 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2090 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2091 LPVOID lpContext, DWORD dwFlags )
2093 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2094 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2095 lpContext, dwFlags, TRUE );
2098 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
2099 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2100 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2101 LPVOID lpContext, DWORD dwFlags )
2103 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2104 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2105 lpContext, dwFlags, FALSE );
2108 static HRESULT DP_IF_EnumPlayers
2109 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2110 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2111 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2113 return DP_IF_EnumGroupPlayers( This, DPID_SYSTEM_GROUP, lpguidInstance,
2114 lpEnumPlayersCallback2, lpContext,
2115 dwFlags, bAnsi );
2118 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
2119 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2120 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2121 LPVOID lpContext, DWORD dwFlags )
2123 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2124 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2125 lpContext, dwFlags, TRUE );
2128 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
2129 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2130 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2131 LPVOID lpContext, DWORD dwFlags )
2133 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2134 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2135 lpContext, dwFlags, FALSE );
2138 /* This function should call the registered callback function that the user
2139 passed into EnumSessions for each entry available.
2141 static void DP_InvokeEnumSessionCallbacks
2142 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2143 LPVOID lpNSInfo,
2144 DWORD dwTimeout,
2145 LPVOID lpContext )
2147 LPDPSESSIONDESC2 lpSessionDesc;
2149 FIXME( ": not checking for conditions\n" );
2151 /* Not sure if this should be pruning but it's convenient */
2152 NS_PruneSessionCache( lpNSInfo );
2154 NS_ResetSessionEnumeration( lpNSInfo );
2156 /* Enumerate all sessions */
2157 /* FIXME: Need to indicate ANSI */
2158 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2160 TRACE( "EnumSessionsCallback2 invoked\n" );
2161 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2163 return;
2167 /* Invoke one last time to indicate that there is no more to come */
2168 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2171 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2173 EnumSessionAsyncCallbackData* data = lpContext;
2174 HANDLE hSuicideRequest = data->hSuicideRequest;
2175 DWORD dwTimeout = data->dwTimeout;
2177 TRACE( "Thread started with timeout = 0x%08x\n", dwTimeout );
2179 for( ;; )
2181 HRESULT hr;
2183 /* Sleep up to dwTimeout waiting for request to terminate thread */
2184 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2186 TRACE( "Thread terminating on terminate request\n" );
2187 break;
2190 /* Now resend the enum request */
2191 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2192 data->dwEnumSessionFlags,
2193 data->lpSpData );
2195 if( FAILED(hr) )
2197 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2198 /* FIXME: Should we kill this thread? How to inform the main thread? */
2203 TRACE( "Thread terminating\n" );
2205 /* Clean up the thread data */
2206 CloseHandle( hSuicideRequest );
2207 HeapFree( GetProcessHeap(), 0, lpContext );
2209 /* FIXME: Need to have some notification to main app thread that this is
2210 * dead. It would serve two purposes. 1) allow sync on termination
2211 * so that we don't actually send something to ourselves when we
2212 * become name server (race condition) and 2) so that if we die
2213 * abnormally something else will be able to tell.
2216 return 1;
2219 static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
2221 /* Does a thread exist? If so we were doing an async enum session */
2222 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2224 TRACE( "Killing EnumSession thread %p\n",
2225 This->dp2->hEnumSessionThread );
2227 /* Request that the thread kill itself nicely */
2228 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2229 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2231 /* We no longer need to know about the thread */
2232 CloseHandle( This->dp2->hEnumSessionThread );
2234 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2238 static HRESULT DP_IF_EnumSessions
2239 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2240 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2241 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2243 HRESULT hr = DP_OK;
2245 TRACE( "(%p)->(%p,0x%08x,%p,%p,0x%08x,%u)\n",
2246 This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags,
2247 bAnsi );
2248 if( This->dp2->connectionInitialized == NO_PROVIDER )
2250 return DPERR_UNINITIALIZED;
2253 if( (lpsd == NULL) || (lpsd->dwSize != sizeof(DPSESSIONDESC2)) )
2255 return DPERR_INVALIDPARAMS;
2258 /* Can't enumerate if the session is already open */
2259 if( This->dp2->bConnectionOpen )
2261 return DPERR_GENERIC;
2264 #if 1
2265 /* The loading of a lobby provider _seems_ to require a backdoor loading
2266 * of the service provider to also associate with this DP object. This is
2267 * because the app doesn't seem to have to call EnumConnections and
2268 * InitializeConnection for the SP before calling this method. As such
2269 * we'll do their dirty work for them with a quick hack so as to always
2270 * load the TCP/IP service provider.
2272 * The correct solution would seem to involve creating a dialog box which
2273 * contains the possible SPs. These dialog boxes most likely follow SDK
2274 * examples.
2276 if( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
2278 LPVOID lpConnection;
2279 DWORD dwSize;
2281 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2283 if( !DP_BuildCompoundAddr( DPAID_ServiceProvider, (LPGUID)&DPSPGUID_TCPIP,
2284 &lpConnection, &dwSize ) )
2286 ERR( "Can't build compound addr\n" );
2287 return DPERR_GENERIC;
2290 hr = DP_IF_InitializeConnection( (IDirectPlay3Impl*)This, lpConnection,
2291 0, bAnsi );
2292 if( FAILED(hr) )
2294 return hr;
2297 /* Free up the address buffer */
2298 HeapFree( GetProcessHeap(), 0, lpConnection );
2300 /* The SP is now initialized */
2301 This->dp2->bSPInitialized = TRUE;
2303 #endif
2306 /* Use the service provider default? */
2307 if( dwTimeout == 0 )
2309 DPCAPS spCaps;
2310 spCaps.dwSize = sizeof( spCaps );
2312 DP_IF_GetCaps( This, &spCaps, 0 );
2313 dwTimeout = spCaps.dwTimeout;
2315 /* The service provider doesn't provide one either! */
2316 if( dwTimeout == 0 )
2318 /* Provide the TCP/IP default */
2319 dwTimeout = DPMSG_WAIT_5_SECS;
2323 if( dwFlags & DPENUMSESSIONS_STOPASYNC )
2325 DP_KillEnumSessionThread( This );
2326 return hr;
2329 if( ( dwFlags & DPENUMSESSIONS_ASYNC ) )
2331 /* Enumerate everything presently in the local session cache */
2332 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2333 This->dp2->lpNameServerData, dwTimeout,
2334 lpContext );
2336 if( This->dp2->dwEnumSessionLock != 0 )
2337 return DPERR_CONNECTING;
2339 /* See if we've already created a thread to service this interface */
2340 if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2342 DWORD dwThreadId;
2343 This->dp2->dwEnumSessionLock++;
2345 /* Send the first enum request inline since the user may cancel a dialog
2346 * if one is presented. Also, may also have a connecting return code.
2348 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2349 dwFlags, &This->dp2->spData );
2351 if( SUCCEEDED(hr) )
2353 EnumSessionAsyncCallbackData* lpData
2354 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpData ) );
2355 /* FIXME: need to kill the thread on object deletion */
2356 lpData->lpSpData = &This->dp2->spData;
2358 lpData->requestGuid = lpsd->guidApplication;
2359 lpData->dwEnumSessionFlags = dwFlags;
2360 lpData->dwTimeout = dwTimeout;
2362 This->dp2->hKillEnumSessionThreadEvent =
2363 CreateEventW( NULL, TRUE, FALSE, NULL );
2365 if( !DuplicateHandle( GetCurrentProcess(),
2366 This->dp2->hKillEnumSessionThreadEvent,
2367 GetCurrentProcess(),
2368 &lpData->hSuicideRequest,
2369 0, FALSE, DUPLICATE_SAME_ACCESS )
2372 ERR( "Can't duplicate thread killing handle\n" );
2375 TRACE( ": creating EnumSessionsRequest thread\n" );
2377 This->dp2->hEnumSessionThread = CreateThread( NULL,
2379 DP_EnumSessionsSendAsyncRequestThread,
2380 lpData,
2382 &dwThreadId );
2384 This->dp2->dwEnumSessionLock--;
2387 else
2389 /* Invalidate the session cache for the interface */
2390 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2392 /* Send the broadcast for session enumeration */
2393 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2394 dwFlags,
2395 &This->dp2->spData );
2398 SleepEx( dwTimeout, FALSE );
2400 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2401 This->dp2->lpNameServerData, dwTimeout,
2402 lpContext );
2405 return hr;
2408 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2409 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2410 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2411 LPVOID lpContext, DWORD dwFlags )
2413 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2414 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2415 lpContext, dwFlags, TRUE );
2418 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2419 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2420 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2421 LPVOID lpContext, DWORD dwFlags )
2423 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2424 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2425 lpContext, dwFlags, FALSE );
2428 static HRESULT DP_IF_GetPlayerCaps
2429 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
2430 DWORD dwFlags )
2432 DPSP_GETCAPSDATA data;
2434 TRACE("(%p)->(0x%08x,%p,0x%08x)\n", This, idPlayer, lpDPCaps, dwFlags);
2436 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2438 return DPERR_UNINITIALIZED;
2441 if ( lpDPCaps->dwSize != sizeof(DPCAPS) )
2443 return DPERR_INVALIDPARAMS;
2446 /* Query the service provider */
2447 data.idPlayer = idPlayer;
2448 data.dwFlags = dwFlags;
2449 data.lpCaps = lpDPCaps;
2450 data.lpISP = This->dp2->spData.lpISP;
2452 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2455 static HRESULT DP_IF_GetCaps
2456 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags )
2458 return DP_IF_GetPlayerCaps( This, DPID_ALLPLAYERS, lpDPCaps, dwFlags );
2461 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2462 ( LPDIRECTPLAY2A iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2464 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2465 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2468 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2469 ( LPDIRECTPLAY2 iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2471 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2472 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2475 static HRESULT DP_IF_GetGroupData
2476 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2477 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2479 lpGroupData lpGData;
2480 DWORD dwRequiredBufferSize;
2481 LPVOID lpCopyDataFrom;
2483 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2484 This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi );
2486 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2488 return DPERR_INVALIDGROUP;
2491 /* How much buffer is required? */
2492 if( dwFlags & DPSET_LOCAL )
2494 dwRequiredBufferSize = lpGData->dwLocalDataSize;
2495 lpCopyDataFrom = lpGData->lpLocalData;
2497 else
2499 dwRequiredBufferSize = lpGData->dwRemoteDataSize;
2500 lpCopyDataFrom = lpGData->lpRemoteData;
2503 /* Is the user requesting to know how big a buffer is required? */
2504 if( ( lpData == NULL ) ||
2505 ( *lpdwDataSize < dwRequiredBufferSize )
2508 *lpdwDataSize = dwRequiredBufferSize;
2509 return DPERR_BUFFERTOOSMALL;
2512 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2514 return DP_OK;
2517 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2518 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2519 LPDWORD lpdwDataSize, DWORD dwFlags )
2521 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2522 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2523 dwFlags, TRUE );
2526 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2527 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2528 LPDWORD lpdwDataSize, DWORD dwFlags )
2530 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2531 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2532 dwFlags, FALSE );
2535 static HRESULT DP_IF_GetGroupName
2536 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2537 LPDWORD lpdwDataSize, BOOL bAnsi )
2539 lpGroupData lpGData;
2540 LPDPNAME lpName = lpData;
2541 DWORD dwRequiredDataSize;
2543 FIXME("(%p)->(0x%08x,%p,%p,%u) ANSI ignored\n",
2544 This, idGroup, lpData, lpdwDataSize, bAnsi );
2546 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2548 return DPERR_INVALIDGROUP;
2551 dwRequiredDataSize = lpGData->name.dwSize;
2553 if( lpGData->name.u1.lpszShortNameA )
2555 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
2558 if( lpGData->name.u2.lpszLongNameA )
2560 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
2563 if( ( lpData == NULL ) ||
2564 ( *lpdwDataSize < dwRequiredDataSize )
2567 *lpdwDataSize = dwRequiredDataSize;
2568 return DPERR_BUFFERTOOSMALL;
2571 /* Copy the structure */
2572 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2574 if( lpGData->name.u1.lpszShortNameA )
2576 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2577 lpGData->name.u1.lpszShortNameA );
2579 else
2581 lpName->u1.lpszShortNameA = NULL;
2584 if( lpGData->name.u1.lpszShortNameA )
2586 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2587 lpGData->name.u2.lpszLongNameA );
2589 else
2591 lpName->u2.lpszLongNameA = NULL;
2594 return DP_OK;
2597 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2598 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2599 LPDWORD lpdwDataSize )
2601 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2602 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2605 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2606 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2607 LPDWORD lpdwDataSize )
2609 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2610 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2613 static HRESULT DP_IF_GetMessageCount
2614 ( IDirectPlay2Impl* This, DPID idPlayer,
2615 LPDWORD lpdwCount, BOOL bAnsi )
2617 FIXME("(%p)->(0x%08x,%p,%u): stub\n", This, idPlayer, lpdwCount, bAnsi );
2618 return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer,
2619 DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL,
2620 bAnsi );
2623 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2624 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDWORD lpdwCount )
2626 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2627 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, TRUE );
2630 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2631 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDWORD lpdwCount )
2633 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2634 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, FALSE );
2637 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2638 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2640 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2641 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2642 return DP_OK;
2645 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2646 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2648 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2649 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2650 return DP_OK;
2653 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2654 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2655 DWORD dwFlags )
2657 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2658 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2661 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2662 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2663 DWORD dwFlags )
2665 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2666 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2669 static HRESULT DP_IF_GetPlayerData
2670 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2671 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2673 lpPlayerList lpPList;
2674 DWORD dwRequiredBufferSize;
2675 LPVOID lpCopyDataFrom;
2677 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2678 This, idPlayer, lpData, lpdwDataSize, dwFlags, bAnsi );
2680 if( This->dp2->connectionInitialized == NO_PROVIDER )
2682 return DPERR_UNINITIALIZED;
2685 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2687 return DPERR_INVALIDPLAYER;
2690 if( lpdwDataSize == NULL )
2692 return DPERR_INVALIDPARAMS;
2695 /* How much buffer is required? */
2696 if( dwFlags & DPSET_LOCAL )
2698 dwRequiredBufferSize = lpPList->lpPData->dwLocalDataSize;
2699 lpCopyDataFrom = lpPList->lpPData->lpLocalData;
2701 else
2703 dwRequiredBufferSize = lpPList->lpPData->dwRemoteDataSize;
2704 lpCopyDataFrom = lpPList->lpPData->lpRemoteData;
2707 /* Is the user requesting to know how big a buffer is required? */
2708 if( ( lpData == NULL ) ||
2709 ( *lpdwDataSize < dwRequiredBufferSize )
2712 *lpdwDataSize = dwRequiredBufferSize;
2713 return DPERR_BUFFERTOOSMALL;
2716 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2718 return DP_OK;
2721 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2722 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2723 LPDWORD lpdwDataSize, DWORD dwFlags )
2725 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2726 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2727 dwFlags, TRUE );
2730 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2731 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2732 LPDWORD lpdwDataSize, DWORD dwFlags )
2734 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2735 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2736 dwFlags, FALSE );
2739 static HRESULT DP_IF_GetPlayerName
2740 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2741 LPDWORD lpdwDataSize, BOOL bAnsi )
2743 lpPlayerList lpPList;
2744 LPDPNAME lpName = lpData;
2745 DWORD dwRequiredDataSize;
2747 FIXME( "(%p)->(0x%08x,%p,%p,%u): ANSI\n",
2748 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2750 if( This->dp2->connectionInitialized == NO_PROVIDER )
2752 return DPERR_UNINITIALIZED;
2755 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2757 return DPERR_INVALIDPLAYER;
2760 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
2762 if( lpPList->lpPData->name.u1.lpszShortNameA )
2764 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
2767 if( lpPList->lpPData->name.u2.lpszLongNameA )
2769 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
2772 if( ( lpData == NULL ) ||
2773 ( *lpdwDataSize < dwRequiredDataSize )
2776 *lpdwDataSize = dwRequiredDataSize;
2777 return DPERR_BUFFERTOOSMALL;
2780 /* Copy the structure */
2781 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
2783 if( lpPList->lpPData->name.u1.lpszShortNameA )
2785 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2786 lpPList->lpPData->name.u1.lpszShortNameA );
2788 else
2790 lpName->u1.lpszShortNameA = NULL;
2793 if( lpPList->lpPData->name.u1.lpszShortNameA )
2795 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2796 lpPList->lpPData->name.u2.lpszLongNameA );
2798 else
2800 lpName->u2.lpszLongNameA = NULL;
2803 return DP_OK;
2806 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2807 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2808 LPDWORD lpdwDataSize )
2810 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2811 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
2814 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2815 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2816 LPDWORD lpdwDataSize )
2818 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2819 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
2822 static HRESULT DP_GetSessionDesc
2823 ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize,
2824 BOOL bAnsi )
2826 DWORD dwRequiredSize;
2828 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
2830 if( This->dp2->connectionInitialized == NO_PROVIDER )
2832 return DPERR_UNINITIALIZED;
2835 if( !This->dp2->bConnectionOpen )
2837 return DPERR_NOSESSIONS;
2840 if( ( lpdwDataSize == NULL ) || ( *lpdwDataSize >= MAXDWORD ) )
2842 return DPERR_INVALIDPARAMS;
2845 /* FIXME: Get from This->dp2->lpSessionDesc */
2846 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
2848 if ( ( lpData == NULL ) ||
2849 ( *lpdwDataSize < dwRequiredSize )
2852 *lpdwDataSize = dwRequiredSize;
2853 return DPERR_BUFFERTOOSMALL;
2856 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
2858 return DP_OK;
2861 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
2862 ( LPDIRECTPLAY2A iface, LPVOID lpData, LPDWORD lpdwDataSize )
2864 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2865 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2868 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
2869 ( LPDIRECTPLAY2 iface, LPVOID lpData, LPDWORD lpdwDataSize )
2871 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2872 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2875 /* Intended only for COM compatibility. Always returns an error. */
2876 static HRESULT WINAPI DirectPlay2AImpl_Initialize
2877 ( LPDIRECTPLAY2A iface, LPGUID lpGUID )
2879 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2880 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2881 return DPERR_ALREADYINITIALIZED;
2884 /* Intended only for COM compatibility. Always returns an error. */
2885 static HRESULT WINAPI DirectPlay2WImpl_Initialize
2886 ( LPDIRECTPLAY2 iface, LPGUID lpGUID )
2888 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2889 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2890 return DPERR_ALREADYINITIALIZED;
2894 static HRESULT DP_SecureOpen
2895 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
2896 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
2897 BOOL bAnsi )
2899 HRESULT hr = DP_OK;
2901 FIXME( "(%p)->(%p,0x%08x,%p,%p): partial stub\n",
2902 This, lpsd, dwFlags, lpSecurity, lpCredentials );
2904 if( ( lpsd == NULL ) ||
2905 ( lpsd->dwSize != sizeof(DPSESSIONDESC2) ) )
2907 return DPERR_INVALIDPARAMS;
2910 if( This->dp2->bConnectionOpen )
2912 TRACE( ": rejecting already open connection.\n" );
2913 return DPERR_ALREADYINITIALIZED;
2916 /* If we're enumerating, kill the thread */
2917 DP_KillEnumSessionThread( This );
2919 if( dwFlags & DPOPEN_JOIN )
2921 LPDPSESSIONDESC2 current = NULL;
2922 NS_ResetSessionEnumeration( This->dp2->lpNameServerData );
2923 while( ( current = NS_WalkSessions( This->dp2->lpNameServerData ) ) )
2925 if ( IsEqualGUID( &lpsd->guidInstance, &current->guidInstance ) )
2926 break;
2928 if ( current == NULL )
2929 return DPERR_NOSESSIONS;
2931 else if( dwFlags & DPOPEN_CREATE )
2933 /* Rightoo - this computer is the host and the local computer needs to be
2934 the name server so that others can join this session */
2935 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
2937 This->dp2->bHostInterface = TRUE;
2939 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
2940 if( FAILED( hr ) )
2942 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
2943 return hr;
2947 /* Invoke the conditional callback for the service provider */
2948 if( This->dp2->spData.lpCB->Open )
2950 DPSP_OPENDATA data;
2952 FIXME( "Not all data fields are correct. Need new parameter\n" );
2954 data.bCreate = (dwFlags & DPOPEN_CREATE ) ? TRUE : FALSE;
2955 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
2956 : NS_GetNSAddr( This->dp2->lpNameServerData );
2957 data.lpISP = This->dp2->spData.lpISP;
2958 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) ? TRUE : FALSE;
2959 data.dwOpenFlags = dwFlags;
2960 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
2962 hr = (*This->dp2->spData.lpCB->Open)(&data);
2963 if( FAILED( hr ) )
2965 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
2966 return hr;
2971 /* Create the system group of which everything is a part of */
2972 DPID systemGroup = DPID_SYSTEM_GROUP;
2974 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
2975 NULL, 0, 0, TRUE );
2979 if( dwFlags & DPOPEN_JOIN )
2981 DPID dpidServerId = DPID_UNKNOWN;
2983 /* Create the server player for this interface. This way we can receive
2984 * messages for this session.
2986 /* FIXME: I suppose that we should be setting an event for a receive
2987 * type of thing. That way the messaging thread could know to wake
2988 * up. DPlay would then trigger the hEvent for the player the
2989 * message is directed to.
2991 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
2993 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
2996 else if( dwFlags & DPOPEN_CREATE )
2998 DPID dpidNameServerId = DPID_NAME_SERVER;
3000 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
3001 0, DPPLAYER_SERVERPLAYER, bAnsi );
3004 if( FAILED(hr) )
3006 ERR( "Couldn't create name server/system player: %s\n",
3007 DPLAYX_HresultToString(hr) );
3009 else
3011 This->dp2->bConnectionOpen = TRUE;
3014 return hr;
3017 static HRESULT WINAPI DirectPlay2AImpl_Open
3018 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
3020 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3021 TRACE("(%p)->(%p,0x%08x)\n", This, lpsd, dwFlags );
3022 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, TRUE );
3025 static HRESULT WINAPI DirectPlay2WImpl_Open
3026 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
3028 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3029 TRACE("(%p)->(%p,0x%08x)\n", This, lpsd, dwFlags );
3030 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, FALSE );
3033 static HRESULT DP_IF_Receive
3034 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
3035 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi )
3037 LPDPMSG lpMsg = NULL;
3039 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p,%u): stub\n",
3040 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
3042 if( This->dp2->connectionInitialized == NO_PROVIDER )
3044 return DPERR_UNINITIALIZED;
3047 if( dwFlags == 0 )
3049 dwFlags = DPRECEIVE_ALL;
3052 /* If the lpData is NULL, we must be peeking the message */
3053 if( ( lpData == NULL ) &&
3054 !( dwFlags & DPRECEIVE_PEEK )
3057 return DPERR_INVALIDPARAMS;
3060 if( dwFlags & DPRECEIVE_ALL )
3062 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
3064 if( !( dwFlags & DPRECEIVE_PEEK ) )
3066 FIXME( "Remove from queue\n" );
3069 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
3070 ( dwFlags & DPRECEIVE_FROMPLAYER )
3073 FIXME( "Find matching message 0x%08x\n", dwFlags );
3075 else
3077 ERR( "Hmmm..dwFlags 0x%08x\n", dwFlags );
3080 if( lpMsg == NULL )
3082 return DPERR_NOMESSAGES;
3085 /* Copy into the provided buffer */
3086 if (lpData) CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
3088 return DP_OK;
3091 static HRESULT WINAPI DirectPlay2AImpl_Receive
3092 ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo,
3093 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
3095 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3096 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
3097 lpData, lpdwDataSize, TRUE );
3100 static HRESULT WINAPI DirectPlay2WImpl_Receive
3101 ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo,
3102 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
3104 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3105 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
3106 lpData, lpdwDataSize, FALSE );
3109 static HRESULT WINAPI DirectPlay2AImpl_Send
3110 ( LPDIRECTPLAY2A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3112 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3113 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3114 0, 0, NULL, NULL, TRUE );
3117 static HRESULT WINAPI DirectPlay2WImpl_Send
3118 ( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3120 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3121 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3122 0, 0, NULL, NULL, FALSE );
3125 static HRESULT DP_IF_SetGroupData
3126 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
3127 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3129 lpGroupData lpGData;
3131 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3132 This, idGroup, lpData, dwDataSize, dwFlags, bAnsi );
3134 /* Parameter check */
3135 if( ( lpData == NULL ) &&
3136 ( dwDataSize != 0 )
3139 return DPERR_INVALIDPARAMS;
3142 /* Find the pointer to the data for this player */
3143 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3145 return DPERR_INVALIDOBJECT;
3148 if( !(dwFlags & DPSET_LOCAL) )
3150 FIXME( "Was this group created by this interface?\n" );
3151 /* FIXME: If this is a remote update need to allow it but not
3152 * send a message.
3156 DP_SetGroupData( lpGData, dwFlags, lpData, dwDataSize );
3158 /* FIXME: Only send a message if this group is local to the session otherwise
3159 * it will have been rejected above
3161 if( !(dwFlags & DPSET_LOCAL) )
3163 FIXME( "Send msg?\n" );
3166 return DP_OK;
3169 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
3170 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
3171 DWORD dwDataSize, DWORD dwFlags )
3173 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3174 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, TRUE );
3177 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
3178 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
3179 DWORD dwDataSize, DWORD dwFlags )
3181 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3182 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, FALSE );
3185 static HRESULT DP_IF_SetGroupName
3186 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
3187 DWORD dwFlags, BOOL bAnsi )
3189 lpGroupData lpGData;
3191 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n", This, idGroup,
3192 lpGroupName, dwFlags, bAnsi );
3194 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3196 return DPERR_INVALIDGROUP;
3199 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
3201 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3202 FIXME( "Message not sent and dwFlags ignored\n" );
3204 return DP_OK;
3207 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
3208 ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName,
3209 DWORD dwFlags )
3211 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3212 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
3215 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
3216 ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName,
3217 DWORD dwFlags )
3219 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3220 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
3223 static HRESULT DP_IF_SetPlayerData
3224 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
3225 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3227 lpPlayerList lpPList;
3229 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3230 This, idPlayer, lpData, dwDataSize, dwFlags, bAnsi );
3232 if( This->dp2->connectionInitialized == NO_PROVIDER )
3234 return DPERR_UNINITIALIZED;
3237 /* Parameter check */
3238 if( ( ( lpData == NULL ) && ( dwDataSize != 0 ) ) ||
3239 ( dwDataSize >= MAXDWORD ) )
3241 return DPERR_INVALIDPARAMS;
3244 /* Find the pointer to the data for this player */
3245 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3247 return DPERR_INVALIDPLAYER;
3250 if( !(dwFlags & DPSET_LOCAL) )
3252 FIXME( "Was this group created by this interface?\n" );
3253 /* FIXME: If this is a remote update need to allow it but not
3254 * send a message.
3258 DP_SetPlayerData( lpPList->lpPData, dwFlags, lpData, dwDataSize );
3260 if( !(dwFlags & DPSET_LOCAL) )
3262 FIXME( "Send msg?\n" );
3265 return DP_OK;
3268 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3269 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
3270 DWORD dwDataSize, DWORD dwFlags )
3272 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3273 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3274 dwFlags, TRUE );
3277 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3278 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
3279 DWORD dwDataSize, DWORD dwFlags )
3281 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3282 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3283 dwFlags, FALSE );
3286 static HRESULT DP_IF_SetPlayerName
3287 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
3288 DWORD dwFlags, BOOL bAnsi )
3290 lpPlayerList lpPList;
3292 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n",
3293 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3295 if( This->dp2->connectionInitialized == NO_PROVIDER )
3297 return DPERR_UNINITIALIZED;
3300 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3302 return DPERR_INVALIDGROUP;
3305 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3307 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3308 FIXME( "Message not sent and dwFlags ignored\n" );
3310 return DP_OK;
3313 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3314 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName,
3315 DWORD dwFlags )
3317 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3318 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3321 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3322 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName,
3323 DWORD dwFlags )
3325 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3326 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3329 static HRESULT DP_SetSessionDesc
3330 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
3331 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3333 DWORD dwRequiredSize;
3334 LPDPSESSIONDESC2 lpTempSessDesc;
3336 TRACE( "(%p)->(%p,0x%08x,%u,%u)\n",
3337 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3339 if( dwFlags || (lpSessDesc == NULL) )
3341 return DPERR_INVALIDPARAMS;
3344 /* Illegal combinations of flags */
3345 if ( ( lpSessDesc->dwFlags & DPSESSION_MIGRATEHOST ) &&
3346 ( lpSessDesc->dwFlags & ( DPSESSION_CLIENTSERVER |
3347 DPSESSION_MULTICASTSERVER |
3348 DPSESSION_SECURESERVER ) ) )
3350 return DPERR_INVALIDFLAGS;
3353 /* Only the host is allowed to update the session desc */
3354 if( !This->dp2->bHostInterface )
3356 return DPERR_ACCESSDENIED;
3359 /* FIXME: Copy into This->dp2->lpSessionDesc */
3360 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3361 lpTempSessDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize );
3363 if( lpTempSessDesc == NULL )
3365 return DPERR_OUTOFMEMORY;
3368 /* Free the old */
3369 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3371 This->dp2->lpSessionDesc = lpTempSessDesc;
3372 /* Set the new */
3373 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3374 if( bInitial )
3376 /*Initializing session GUID*/
3377 CoCreateGuid( &(This->dp2->lpSessionDesc->guidInstance) );
3379 /* If this is an external invocation of the interface, we should be
3380 * letting everyone know that things have changed. Otherwise this is
3381 * just an initialization and it doesn't need to be propagated.
3383 if( !bInitial )
3385 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3388 return DP_OK;
3391 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3392 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3394 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3396 if( This->dp2->connectionInitialized == NO_PROVIDER )
3398 return DPERR_UNINITIALIZED;
3401 if( !This->dp2->bConnectionOpen )
3403 return DPERR_NOSESSIONS;
3406 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3409 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3410 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3412 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3414 if( This->dp2->connectionInitialized == NO_PROVIDER )
3416 return DPERR_UNINITIALIZED;
3419 if( !This->dp2->bConnectionOpen )
3421 return DPERR_NOSESSIONS;
3424 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3427 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3428 static DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3430 DWORD dwSize = 0;
3432 if( lpSessDesc == NULL )
3434 /* Hmmm..don't need any size? */
3435 ERR( "NULL lpSessDesc\n" );
3436 return dwSize;
3439 dwSize += sizeof( *lpSessDesc );
3441 if( bAnsi )
3443 if( lpSessDesc->u1.lpszSessionNameA )
3445 dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1;
3448 if( lpSessDesc->u2.lpszPasswordA )
3450 dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1;
3453 else /* UNICODE */
3455 if( lpSessDesc->u1.lpszSessionName )
3457 dwSize += sizeof( WCHAR ) *
3458 ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 );
3461 if( lpSessDesc->u2.lpszPassword )
3463 dwSize += sizeof( WCHAR ) *
3464 ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 );
3468 return dwSize;
3471 /* Assumes that contiguous buffers are already allocated. */
3472 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3473 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3475 BYTE* lpStartOfFreeSpace;
3477 if( lpSessionDest == NULL )
3479 ERR( "NULL lpSessionDest\n" );
3480 return;
3483 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3485 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3487 if( bAnsi )
3489 if( lpSessionSrc->u1.lpszSessionNameA )
3491 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3492 lpSessionDest->u1.lpszSessionNameA );
3493 lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3494 lpStartOfFreeSpace +=
3495 lstrlenA( lpSessionDest->u1.lpszSessionNameA ) + 1;
3498 if( lpSessionSrc->u2.lpszPasswordA )
3500 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3501 lpSessionDest->u2.lpszPasswordA );
3502 lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3503 lpStartOfFreeSpace +=
3504 lstrlenA( lpSessionDest->u2.lpszPasswordA ) + 1;
3507 else /* UNICODE */
3509 if( lpSessionSrc->u1.lpszSessionName )
3511 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3512 lpSessionDest->u1.lpszSessionName );
3513 lpSessionDest->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3514 lpStartOfFreeSpace += sizeof(WCHAR) *
3515 ( lstrlenW( lpSessionDest->u1.lpszSessionName ) + 1 );
3518 if( lpSessionSrc->u2.lpszPassword )
3520 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3521 lpSessionDest->u2.lpszPassword );
3522 lpSessionDest->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3523 lpStartOfFreeSpace += sizeof(WCHAR) *
3524 ( lstrlenW( lpSessionDest->u2.lpszPassword ) + 1 );
3530 static HRESULT DP_IF_AddGroupToGroup
3531 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3533 lpGroupData lpGData;
3534 lpGroupList lpNewGList;
3536 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, idParentGroup, idGroup );
3538 if( This->dp2->connectionInitialized == NO_PROVIDER )
3540 return DPERR_UNINITIALIZED;
3543 if( DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) == NULL )
3545 return DPERR_INVALIDGROUP;
3548 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3550 return DPERR_INVALIDGROUP;
3553 /* Create a player list (ie "shortcut" ) */
3554 lpNewGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewGList ) );
3555 if( lpNewGList == NULL )
3557 return DPERR_CANTADDPLAYER;
3560 /* Add the shortcut */
3561 lpGData->uRef++;
3562 lpNewGList->lpGData = lpGData;
3564 /* Add the player to the list of players for this group */
3565 DPQ_INSERT( lpGData->groups, lpNewGList, groups );
3567 /* Send a ADDGROUPTOGROUP message */
3568 FIXME( "Not sending message\n" );
3570 return DP_OK;
3573 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3574 ( LPDIRECTPLAY3A iface, DPID idParentGroup, DPID idGroup )
3576 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3577 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3580 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3581 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3583 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3584 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3587 static HRESULT DP_IF_CreateGroupInGroup
3588 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
3589 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
3590 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3592 lpGroupData lpGParentData;
3593 lpGroupList lpGList;
3594 lpGroupData lpGData;
3596 TRACE( "(%p)->(0x%08x,%p,%p,%p,0x%08x,0x%08x,%u)\n",
3597 This, idParentGroup, lpidGroup, lpGroupName, lpData,
3598 dwDataSize, dwFlags, bAnsi );
3600 /* Verify that the specified parent is valid */
3601 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This,
3602 idParentGroup ) ) == NULL
3605 return DPERR_INVALIDGROUP;
3608 lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName,
3609 dwFlags, idParentGroup, bAnsi );
3611 if( lpGData == NULL )
3613 return DPERR_CANTADDPLAYER; /* yes player not group */
3616 /* Something else is referencing this data */
3617 lpGData->uRef++;
3619 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
3621 /* The list has now been inserted into the interface group list. We now
3622 need to put a "shortcut" to this group in the parent group */
3623 lpGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGList ) );
3624 if( lpGList == NULL )
3626 FIXME( "Memory leak\n" );
3627 return DPERR_CANTADDPLAYER; /* yes player not group */
3630 lpGList->lpGData = lpGData;
3632 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
3634 /* Let the SP know that we've created this group */
3635 if( This->dp2->spData.lpCB->CreateGroup )
3637 DPSP_CREATEGROUPDATA data;
3639 TRACE( "Calling SP CreateGroup\n" );
3641 data.idGroup = *lpidGroup;
3642 data.dwFlags = dwFlags;
3643 data.lpSPMessageHeader = lpMsgHdr;
3644 data.lpISP = This->dp2->spData.lpISP;
3646 (*This->dp2->spData.lpCB->CreateGroup)( &data );
3649 /* Inform all other peers of the creation of a new group. If there are
3650 * no peers keep this quiet.
3652 if( This->dp2->lpSessionDesc &&
3653 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
3655 DPMSG_CREATEPLAYERORGROUP msg;
3657 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
3658 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
3659 msg.dpId = *lpidGroup;
3660 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
3661 msg.lpData = lpData;
3662 msg.dwDataSize = dwDataSize;
3663 msg.dpnName = *lpGroupName;
3665 /* FIXME: Correct to just use send effectively? */
3666 /* FIXME: Should size include data w/ message or just message "header" */
3667 /* FIXME: Check return code */
3668 DP_SendEx( (IDirectPlay2Impl*)This,
3669 DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
3670 0, 0, NULL, NULL, bAnsi );
3673 return DP_OK;
3676 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3677 ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup,
3678 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3679 DWORD dwFlags )
3681 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3683 if( This->dp2->connectionInitialized == NO_PROVIDER )
3685 return DPERR_UNINITIALIZED;
3688 if( lpidGroup == NULL ||
3689 !This->dp2->bConnectionOpen ||
3690 dwDataSize >= MAXDWORD ||
3691 ( lpData == NULL && dwDataSize != 0 ) )
3693 return DPERR_INVALIDPARAMS;
3696 *lpidGroup = DPID_UNKNOWN;
3698 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3699 lpGroupName, lpData, dwDataSize, dwFlags,
3700 TRUE );
3703 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3704 ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup,
3705 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3706 DWORD dwFlags )
3708 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3710 if( This->dp2->connectionInitialized == NO_PROVIDER )
3712 return DPERR_UNINITIALIZED;
3715 if( lpidGroup == NULL ||
3716 !This->dp2->bConnectionOpen ||
3717 dwDataSize >= MAXDWORD ||
3718 ( lpData == NULL && dwDataSize != 0 ) )
3720 return DPERR_INVALIDPARAMS;
3723 *lpidGroup = DPID_UNKNOWN;
3725 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3726 lpGroupName, lpData, dwDataSize,
3727 dwFlags, FALSE );
3730 static HRESULT DP_IF_DeleteGroupFromGroup
3731 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3733 lpGroupList lpGList;
3734 lpGroupData lpGParentData;
3736 TRACE("(%p)->(0x%08x,0x%08x)\n", This, idParentGroup, idGroup );
3738 /* Is the parent group valid? */
3739 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3741 return DPERR_INVALIDGROUP;
3744 /* Remove the group from the parent group queue */
3745 DPQ_REMOVE_ENTRY( lpGParentData->groups, groups, lpGData->dpid, ==, idGroup, lpGList );
3747 if( lpGList == NULL )
3749 return DPERR_INVALIDGROUP;
3752 /* Decrement the ref count */
3753 lpGList->lpGData->uRef--;
3755 /* Free up the list item */
3756 HeapFree( GetProcessHeap(), 0, lpGList );
3758 /* Should send a DELETEGROUPFROMGROUP message */
3759 FIXME( "message not sent\n" );
3761 return DP_OK;
3764 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3765 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3767 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3768 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3771 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3772 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3774 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3775 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3777 static BOOL DP_BuildCompoundAddr( GUID guidDataType,
3778 LPGUID lpcSpGuid,
3779 LPVOID* lplpAddrBuf,
3780 LPDWORD lpdwBufSize )
3782 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3783 HRESULT hr;
3785 dpCompoundAddress.dwDataSize = sizeof( GUID );
3786 dpCompoundAddress.guidDataType = guidDataType;
3787 dpCompoundAddress.lpData = lpcSpGuid;
3789 *lplpAddrBuf = NULL;
3790 *lpdwBufSize = 0;
3792 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3793 lpdwBufSize, TRUE );
3795 if( hr != DPERR_BUFFERTOOSMALL )
3797 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3798 return FALSE;
3801 /* Now allocate the buffer */
3802 *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3803 *lpdwBufSize );
3805 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3806 lpdwBufSize, TRUE );
3807 if( FAILED(hr) )
3809 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3810 return FALSE;
3813 return TRUE;
3816 static HRESULT WINAPI DP_IF_EnumConnections
3817 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication,
3818 LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext,
3819 DWORD dwFlags, BOOL bAnsi )
3821 HKEY hkResult;
3822 WCHAR searchSubKeySP[] = {
3823 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
3824 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
3825 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
3826 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
3827 WCHAR searchSubKeyLP[] = {
3828 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
3829 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
3830 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
3831 'L', 'o', 'b', 'b', 'y', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
3832 WCHAR guidDataSubKey[] = { 'G', 'u', 'i', 'd', 0 };
3833 WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */
3834 DWORD dwIndex, sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR);
3835 FILETIME filetime;
3837 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
3838 if( dwFlags == 0 )
3840 dwFlags = DPCONNECTION_DIRECTPLAY;
3843 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
3844 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) ) )
3846 return DPERR_INVALIDFLAGS;
3849 if( !lpEnumCallback )
3851 return DPERR_INVALIDPARAMS;
3855 /* Need to loop over the service providers in the registry */
3856 if( RegOpenKeyExW( HKEY_LOCAL_MACHINE,
3857 ( dwFlags & DPCONNECTION_DIRECTPLAY ) ? searchSubKeySP
3858 : searchSubKeyLP,
3859 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3861 /* Hmmm. Does this mean that there are no service providers? */
3862 ERR(": no service providers?\n");
3863 return DP_OK;
3867 /* Traverse all the service providers we have available */
3868 for( dwIndex=0;
3869 RegEnumKeyExW( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3870 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3871 ++dwIndex, sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR) )
3873 HKEY hkServiceProvider;
3874 GUID serviceProviderGUID;
3875 WCHAR guidKeyContent[39];
3876 DWORD sizeOfReturnBuffer = sizeof(guidKeyContent);
3877 DPNAME dpName;
3878 BOOL continueEnumeration = TRUE;
3880 LPVOID lpAddressBuffer = NULL;
3881 DWORD dwAddressBufferSize = 0;
3884 TRACE(" this time through: %s\n", debugstr_w(subKeyName) );
3886 /* Get a handle for this particular service provider */
3887 if( RegOpenKeyExW( hkResult, subKeyName, 0, KEY_READ,
3888 &hkServiceProvider ) != ERROR_SUCCESS )
3890 ERR(": what the heck is going on?\n" );
3891 continue;
3894 if( RegQueryValueExW( hkServiceProvider, guidDataSubKey,
3895 NULL, NULL, (LPBYTE)guidKeyContent,
3896 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3898 ERR(": missing GUID registry data members\n" );
3899 RegCloseKey(hkServiceProvider);
3900 continue;
3902 RegCloseKey(hkServiceProvider);
3904 CLSIDFromString( guidKeyContent, &serviceProviderGUID );
3906 /* Fill in the DPNAME struct for the service provider */
3907 dpName.dwSize = sizeof( dpName );
3908 dpName.dwFlags = 0;
3909 if ( bAnsi )
3911 dpName.u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3912 sizeOfSubKeyName+1 );
3913 WideCharToMultiByte( CP_ACP, 0, subKeyName,
3914 -1, dpName.u1.lpszShortNameA, -1, 0, 0);
3915 dpName.u2.lpszLongNameA = NULL;
3917 else
3919 dpName.u1.lpszShortName = subKeyName;
3920 dpName.u2.lpszLongName = NULL;
3923 /* Create the compound address for the service provider.
3924 * NOTE: This is a gruesome architectural scar right now. DP
3925 * uses DPL and DPL uses DP. Nasty stuff. This may be why the
3926 * native dll just gets around this little bit by allocating an
3927 * 80 byte buffer which isn't even filled with a valid compound
3928 * address. Oh well. Creating a proper compound address is the
3929 * way to go anyways despite this method taking slightly more
3930 * heap space and realtime :) */
3932 if ( DP_BuildCompoundAddr( ( ( dwFlags & DPCONNECTION_DIRECTPLAY )
3933 ? DPAID_ServiceProvider
3934 : DPAID_LobbyProvider ),
3935 &serviceProviderGUID,
3936 &lpAddressBuffer,
3937 &dwAddressBufferSize ) )
3939 /* The enumeration will return FALSE if we are not to continue */
3940 continueEnumeration = lpEnumCallback( &serviceProviderGUID, lpAddressBuffer,
3941 dwAddressBufferSize, &dpName,
3942 dwFlags, lpContext );
3944 else
3946 ERR( "Couldn't build compound address\n" );
3949 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
3950 if ( bAnsi )
3951 HeapFree( GetProcessHeap(), 0, dpName.u1.lpszShortNameA );
3953 if (!continueEnumeration)
3954 return DP_OK;
3957 return DP_OK;
3960 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
3961 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3963 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3964 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3965 return DP_IF_EnumConnections( iface, lpguidApplication, lpEnumCallback, lpContext, dwFlags, TRUE );
3968 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
3969 ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3971 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3972 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3973 return DP_IF_EnumConnections( iface, lpguidApplication, lpEnumCallback, lpContext, dwFlags, FALSE );
3976 static HRESULT DP_IF_EnumGroupsInGroup
3977 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
3978 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
3979 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
3981 lpGroupList lpGList;
3982 lpGroupData lpGData;
3984 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
3985 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
3986 lpContext, dwFlags, bAnsi );
3988 if( This->dp2->connectionInitialized == NO_PROVIDER )
3990 return DPERR_UNINITIALIZED;
3993 if( !This->dp2->bConnectionOpen )
3995 return DPERR_NOSESSIONS;
3998 if( ( lpEnumPlayersCallback2 == NULL ) ||
3999 ( ( dwFlags & DPENUMGROUPS_SESSION ) && ( lpguidInstance == NULL ) ) )
4001 return DPERR_INVALIDPARAMS;
4004 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4006 return DPERR_INVALIDGROUP;
4009 if( DPQ_IS_EMPTY( lpGData->groups ) )
4011 return DP_OK;
4014 lpGList = DPQ_FIRST( lpGData->groups );
4016 for( ;; )
4018 /* FIXME: Should check dwFlags for match here */
4020 if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP,
4021 &lpGList->lpGData->name, dwFlags,
4022 lpContext ) )
4024 return DP_OK; /* User requested break */
4027 if( DPQ_IS_ENDOFLIST( lpGList->groups ) )
4029 break;
4032 lpGList = DPQ_NEXT( lpGList->groups );
4036 return DP_OK;
4039 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
4040 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
4041 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
4042 DWORD dwFlags )
4044 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4045 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
4046 lpEnumPlayersCallback2, lpContext, dwFlags,
4047 TRUE );
4050 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
4051 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
4052 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
4053 DWORD dwFlags )
4055 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4056 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
4057 lpEnumPlayersCallback2, lpContext, dwFlags,
4058 FALSE );
4061 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
4062 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
4064 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4065 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
4066 return DP_OK;
4069 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
4070 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
4072 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4073 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
4074 return DP_OK;
4077 static BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
4078 REFGUID guidDataType,
4079 DWORD dwDataSize,
4080 LPCVOID lpData,
4081 LPVOID lpContext )
4083 /* Looking for the GUID of the provider to load */
4084 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
4085 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
4088 TRACE( "Found SP/LP (%s) %s (data size = 0x%08x)\n",
4089 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
4091 if( dwDataSize != sizeof( GUID ) )
4093 ERR( "Invalid sp/lp guid size 0x%08x\n", dwDataSize );
4096 memcpy( lpContext, lpData, dwDataSize );
4098 /* There shouldn't be more than 1 GUID/compound address */
4099 return FALSE;
4102 /* Still waiting for what we want */
4103 return TRUE;
4107 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
4108 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
4110 UINT i;
4111 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4112 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
4113 LPCSTR guidDataSubKey = "Guid";
4114 LPCSTR majVerDataSubKey = "dwReserved1";
4115 LPCSTR minVerDataSubKey = "dwReserved2";
4116 LPCSTR pathSubKey = "Path";
4118 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
4120 /* FIXME: Cloned code with a quick hack. */
4121 for( i=0; i<2; i++ )
4123 HKEY hkResult;
4124 LPCSTR searchSubKey;
4125 char subKeyName[51];
4126 DWORD dwIndex, sizeOfSubKeyName=50;
4127 FILETIME filetime;
4129 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
4130 *lpbIsDpSp = (i == 0) ? TRUE : FALSE;
4133 /* Need to loop over the service providers in the registry */
4134 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4135 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4137 /* Hmmm. Does this mean that there are no service providers? */
4138 ERR(": no service providers?\n");
4139 return 0;
4142 /* Traverse all the service providers we have available */
4143 for( dwIndex=0;
4144 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4145 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4146 ++dwIndex, sizeOfSubKeyName=51 )
4149 HKEY hkServiceProvider;
4150 GUID serviceProviderGUID;
4151 DWORD returnType, sizeOfReturnBuffer = 255;
4152 char returnBuffer[256];
4153 WCHAR buff[51];
4154 DWORD dwTemp, len;
4156 TRACE(" this time through: %s\n", subKeyName );
4158 /* Get a handle for this particular service provider */
4159 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4160 &hkServiceProvider ) != ERROR_SUCCESS )
4162 ERR(": what the heck is going on?\n" );
4163 continue;
4166 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4167 NULL, &returnType, (LPBYTE)returnBuffer,
4168 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4170 ERR(": missing GUID registry data members\n" );
4171 continue;
4174 /* FIXME: Check return types to ensure we're interpreting data right */
4175 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4176 CLSIDFromString( buff, &serviceProviderGUID );
4177 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4179 /* Determine if this is the Service Provider that the user asked for */
4180 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
4182 continue;
4185 if( i == 0 ) /* DP SP */
4187 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
4188 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
4189 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
4192 sizeOfReturnBuffer = 255;
4194 /* Get dwReserved1 */
4195 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
4196 NULL, &returnType, (LPBYTE)returnBuffer,
4197 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4199 ERR(": missing dwReserved1 registry data members\n") ;
4200 continue;
4203 if( i == 0 )
4204 memcpy( &lpSpData->dwReserved1, returnBuffer, sizeof(lpSpData->dwReserved1) );
4206 sizeOfReturnBuffer = 255;
4208 /* Get dwReserved2 */
4209 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4210 NULL, &returnType, (LPBYTE)returnBuffer,
4211 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4213 ERR(": missing dwReserved1 registry data members\n") ;
4214 continue;
4217 if( i == 0 )
4218 memcpy( &lpSpData->dwReserved2, returnBuffer, sizeof(lpSpData->dwReserved2) );
4220 sizeOfReturnBuffer = 255;
4222 /* Get the path for this service provider */
4223 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
4224 NULL, NULL, (LPBYTE)returnBuffer,
4225 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
4227 ERR(": missing PATH registry data members: 0x%08x\n", dwTemp );
4228 continue;
4231 TRACE( "Loading %s\n", returnBuffer );
4232 return LoadLibraryA( returnBuffer );
4236 return 0;
4239 static
4240 HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider )
4242 HRESULT hr;
4243 LPDPSP_SPINIT SPInit;
4245 /* Initialize the service provider by calling SPInit */
4246 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4248 if( SPInit == NULL )
4250 ERR( "Service provider doesn't provide SPInit interface?\n" );
4251 FreeLibrary( hServiceProvider );
4252 return DPERR_UNAVAILABLE;
4255 TRACE( "Calling SPInit (DP SP entry point)\n" );
4257 hr = (*SPInit)( &This->dp2->spData );
4259 if( FAILED(hr) )
4261 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4262 FreeLibrary( hServiceProvider );
4263 return hr;
4266 /* FIXME: Need to verify the sanity of the returned callback table
4267 * using IsBadCodePtr */
4268 This->dp2->bSPInitialized = TRUE;
4270 /* This interface is now initialized as a DP object */
4271 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
4273 /* Store the handle of the module so that we can unload it later */
4274 This->dp2->hServiceProvider = hServiceProvider;
4276 return hr;
4279 static
4280 HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hLobbyProvider )
4282 HRESULT hr;
4283 LPSP_INIT DPLSPInit;
4285 /* Initialize the service provider by calling SPInit */
4286 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
4288 if( DPLSPInit == NULL )
4290 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4291 FreeLibrary( hLobbyProvider );
4292 return DPERR_UNAVAILABLE;
4295 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4297 hr = (*DPLSPInit)( &This->dp2->dplspData );
4299 if( FAILED(hr) )
4301 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4302 FreeLibrary( hLobbyProvider );
4303 return hr;
4306 /* FIXME: Need to verify the sanity of the returned callback table
4307 * using IsBadCodePtr */
4309 This->dp2->bDPLSPInitialized = TRUE;
4311 /* This interface is now initialized as a lobby object */
4312 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
4314 /* Store the handle of the module so that we can unload it later */
4315 This->dp2->hDPLobbyProvider = hLobbyProvider;
4317 return hr;
4320 static HRESULT DP_IF_InitializeConnection
4321 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi )
4323 HMODULE hServiceProvider;
4324 HRESULT hr;
4325 GUID guidSP;
4326 const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
4327 BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4329 TRACE("(%p)->(%p,0x%08x,%u)\n", This, lpConnection, dwFlags, bAnsi );
4331 if ( lpConnection == NULL )
4333 return DPERR_INVALIDPARAMS;
4336 if( dwFlags != 0 )
4338 return DPERR_INVALIDFLAGS;
4341 if( This->dp2->connectionInitialized != NO_PROVIDER )
4343 return DPERR_ALREADYINITIALIZED;
4346 /* Find out what the requested SP is and how large this buffer is */
4347 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
4348 dwAddrSize, &guidSP );
4350 if( FAILED(hr) )
4352 ERR( "Invalid compound address?\n" );
4353 return DPERR_UNAVAILABLE;
4356 /* Load the service provider */
4357 hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp );
4359 if( hServiceProvider == 0 )
4361 ERR( "Unable to load service provider %s\n", debugstr_guid(&guidSP) );
4362 return DPERR_UNAVAILABLE;
4365 if( bIsDpSp )
4367 /* Fill in what we can of the Service Provider required information.
4368 * The rest was be done in DP_LoadSP
4370 This->dp2->spData.lpAddress = lpConnection;
4371 This->dp2->spData.dwAddressSize = dwAddrSize;
4372 This->dp2->spData.lpGuid = &guidSP;
4374 hr = DP_InitializeDPSP( This, hServiceProvider );
4376 else
4378 This->dp2->dplspData.lpAddress = lpConnection;
4380 hr = DP_InitializeDPLSP( This, hServiceProvider );
4383 if( FAILED(hr) )
4385 return hr;
4388 return DP_OK;
4391 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4392 ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
4394 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4395 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE );
4398 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4399 ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
4401 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4402 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE );
4405 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4406 ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4407 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4409 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4410 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4413 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4414 ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4415 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4417 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4418 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4421 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4422 ( LPDIRECTPLAY3A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4424 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4425 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4426 return DP_OK;
4429 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4430 ( LPDIRECTPLAY3 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4432 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4433 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4434 return DP_OK;
4437 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4438 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4440 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4441 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4442 return DP_OK;
4445 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4446 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4448 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4449 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4450 return DP_OK;
4453 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4454 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup )
4456 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4457 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, dwFlags, idGroup );
4458 return DP_OK;
4461 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4462 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup )
4464 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4465 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, dwFlags, idGroup );
4466 return DP_OK;
4469 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4470 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDWORD lpdwFlags )
4472 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4473 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpdwFlags );
4474 return DP_OK;
4477 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4478 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDWORD lpdwFlags )
4480 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4481 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpdwFlags );
4482 return DP_OK;
4485 static HRESULT DP_IF_GetGroupParent
4486 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
4487 BOOL bAnsi )
4489 lpGroupData lpGData;
4491 TRACE("(%p)->(0x%08x,%p,%u)\n", This, idGroup, lpidGroup, bAnsi );
4493 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4495 return DPERR_INVALIDGROUP;
4498 *lpidGroup = lpGData->dpid;
4500 return DP_OK;
4503 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4504 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
4506 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4507 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE );
4509 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4510 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
4512 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4513 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE );
4516 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4517 ( LPDIRECTPLAY3A iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4519 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4520 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4521 return DP_OK;
4524 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4525 ( LPDIRECTPLAY3 iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4527 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4528 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4529 return DP_OK;
4532 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4533 ( LPDIRECTPLAY3A iface, DPID idPlayer, LPDWORD lpdwFlags )
4535 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4536 FIXME("(%p)->(0x%08x,%p): stub\n", This, idPlayer, lpdwFlags );
4537 return DP_OK;
4540 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4541 ( LPDIRECTPLAY3 iface, DPID idPlayer, LPDWORD lpdwFlags )
4543 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4544 FIXME("(%p)->(0x%08x,%p): stub\n", This, idPlayer, lpdwFlags );
4545 return DP_OK;
4548 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4549 ( LPDIRECTPLAY4A iface, DPID idGroup, LPDPID lpidGroupOwner )
4551 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4552 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpidGroupOwner );
4553 return DP_OK;
4556 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4557 ( LPDIRECTPLAY4 iface, DPID idGroup, LPDPID lpidGroupOwner )
4559 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4560 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpidGroupOwner );
4561 return DP_OK;
4564 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4565 ( LPDIRECTPLAY4A iface, DPID idGroup , DPID idGroupOwner )
4567 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4568 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, idGroup, idGroupOwner );
4569 return DP_OK;
4572 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4573 ( LPDIRECTPLAY4 iface, DPID idGroup , DPID idGroupOwner )
4575 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4576 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, idGroup, idGroupOwner );
4577 return DP_OK;
4580 static HRESULT DP_SendEx
4581 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4582 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4583 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi )
4585 BOOL bValidDestination = FALSE;
4587 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,0x%08x,0x%08x,0x%08x,%p,%p,%u)"
4588 ": stub\n",
4589 This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority,
4590 dwTimeout, lpContext, lpdwMsgID, bAnsi );
4592 if( This->dp2->connectionInitialized == NO_PROVIDER )
4594 return DPERR_UNINITIALIZED;
4597 /* FIXME: Add parameter checking */
4598 /* FIXME: First call to this needs to acquire a message id which will be
4599 * used for multiple sends
4602 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4604 /* Verify that the message is being sent from a valid local player. The
4605 * from player may be anonymous DPID_UNKNOWN
4607 if( idFrom != DPID_UNKNOWN )
4609 if( DP_FindPlayer( This, idFrom ) == NULL )
4611 WARN( "INFO: Invalid from player 0x%08x\n", idFrom );
4612 return DPERR_INVALIDPLAYER;
4616 /* Verify that the message is being sent to a valid player, group or to
4617 * everyone. If it's valid, send it to those players.
4619 if( idTo == DPID_ALLPLAYERS )
4621 bValidDestination = TRUE;
4623 /* See if SP has the ability to multicast. If so, use it */
4624 if( This->dp2->spData.lpCB->SendToGroupEx )
4626 FIXME( "Use group sendex to group 0\n" );
4628 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4630 FIXME( "Use obsolete group send to group 0\n" );
4632 else /* No multicast, multiplicate */
4634 /* Send to all players we know about */
4635 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4639 if( ( !bValidDestination ) &&
4640 ( DP_FindPlayer( This, idTo ) != NULL )
4643 bValidDestination = TRUE;
4645 /* Have the service provider send this message */
4646 /* FIXME: Could optimize for local interface sends */
4647 return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority,
4648 dwTimeout, lpContext, lpdwMsgID );
4651 if( ( !bValidDestination ) &&
4652 ( DP_FindAnyGroup( This, idTo ) != NULL )
4655 bValidDestination = TRUE;
4657 /* See if SP has the ability to multicast. If so, use it */
4658 if( This->dp2->spData.lpCB->SendToGroupEx )
4660 FIXME( "Use group sendex\n" );
4662 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4664 FIXME( "Use obsolete group send to group\n" );
4666 else /* No multicast, multiplicate */
4668 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4671 #if 0
4672 if( bExpectReply )
4674 DWORD dwWaitReturn;
4676 This->dp2->hReplyEvent = CreateEventW( NULL, FALSE, FALSE, NULL );
4678 dwWaitReturn = WaitForSingleObject( hReplyEvent, dwTimeout );
4679 if( dwWaitReturn != WAIT_OBJECT_0 )
4681 ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
4684 #endif
4687 if( !bValidDestination )
4689 return DPERR_INVALIDPLAYER;
4691 else
4693 /* FIXME: Should return what the send returned */
4694 return DP_OK;
4699 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4700 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4701 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4702 LPVOID lpContext, LPDWORD lpdwMsgID )
4704 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4705 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4706 dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE );
4709 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4710 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4711 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4712 LPVOID lpContext, LPDWORD lpdwMsgID )
4714 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4715 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4716 dwPriority, dwTimeout, lpContext, lpdwMsgID, FALSE );
4719 static HRESULT DP_SP_SendEx
4720 ( IDirectPlay2Impl* This, DWORD dwFlags,
4721 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4722 LPVOID lpContext, LPDWORD lpdwMsgID )
4724 LPDPMSG lpMElem;
4726 FIXME( ": stub\n" );
4728 /* FIXME: This queuing should only be for async messages */
4730 lpMElem = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpMElem ) );
4731 lpMElem->msg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
4733 CopyMemory( lpMElem->msg, lpData, dwDataSize );
4735 /* FIXME: Need to queue based on priority */
4736 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
4738 return DP_OK;
4741 static HRESULT DP_IF_GetMessageQueue
4742 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4743 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi )
4745 HRESULT hr = DP_OK;
4747 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%p,%u): semi stub\n",
4748 This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi );
4750 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4751 /* FIXME: What about sends which are not immediate? */
4753 if( This->dp2->spData.lpCB->GetMessageQueue )
4755 DPSP_GETMESSAGEQUEUEDATA data;
4757 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4759 /* FIXME: None of this is documented :( */
4761 data.lpISP = This->dp2->spData.lpISP;
4762 data.dwFlags = dwFlags;
4763 data.idFrom = idFrom;
4764 data.idTo = idTo;
4765 data.lpdwNumMsgs = lpdwNumMsgs;
4766 data.lpdwNumBytes = lpdwNumBytes;
4768 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
4770 else
4772 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4775 return hr;
4778 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4779 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4780 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4782 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4783 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4784 lpdwNumBytes, TRUE );
4787 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4788 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4789 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4791 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4792 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4793 lpdwNumBytes, FALSE );
4796 static HRESULT DP_IF_CancelMessage
4797 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
4798 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi )
4800 HRESULT hr = DP_OK;
4802 FIXME( "(%p)->(0x%08x,0x%08x,%u): semi stub\n",
4803 This, dwMsgID, dwFlags, bAnsi );
4805 if( This->dp2->spData.lpCB->Cancel )
4807 DPSP_CANCELDATA data;
4809 TRACE( "Calling SP Cancel\n" );
4811 /* FIXME: Undocumented callback */
4813 data.lpISP = This->dp2->spData.lpISP;
4814 data.dwFlags = dwFlags;
4815 data.lprglpvSPMsgID = NULL;
4816 data.cSPMsgID = dwMsgID;
4817 data.dwMinPriority = dwMinPriority;
4818 data.dwMaxPriority = dwMaxPriority;
4820 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
4822 else
4824 FIXME( "SP doesn't implement Cancel\n" );
4827 return hr;
4830 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
4831 ( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags )
4833 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4835 if( dwFlags != 0 )
4837 return DPERR_INVALIDFLAGS;
4840 if( dwMsgID == 0 )
4842 dwFlags |= DPCANCELSEND_ALL;
4845 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE );
4848 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
4849 ( LPDIRECTPLAY4 iface, DWORD dwMsgID, DWORD dwFlags )
4851 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4853 if( dwFlags != 0 )
4855 return DPERR_INVALIDFLAGS;
4858 if( dwMsgID == 0 )
4860 dwFlags |= DPCANCELSEND_ALL;
4863 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, FALSE );
4866 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
4867 ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4868 DWORD dwFlags )
4870 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4872 if( dwFlags != 0 )
4874 return DPERR_INVALIDFLAGS;
4877 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4878 dwMaxPriority, TRUE );
4881 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
4882 ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4883 DWORD dwFlags )
4885 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4887 if( dwFlags != 0 )
4889 return DPERR_INVALIDFLAGS;
4892 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4893 dwMaxPriority, FALSE );
4896 /* Note: Hack so we can reuse the old functions without compiler warnings */
4897 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4898 # define XCAST(fun) (typeof(directPlay2WVT.fun))
4899 #else
4900 # define XCAST(fun) (void*)
4901 #endif
4903 static const IDirectPlay2Vtbl directPlay2WVT =
4905 XCAST(QueryInterface)DP_QueryInterface,
4906 XCAST(AddRef)DP_AddRef,
4907 XCAST(Release)DP_Release,
4909 DirectPlay2WImpl_AddPlayerToGroup,
4910 DirectPlay2WImpl_Close,
4911 DirectPlay2WImpl_CreateGroup,
4912 DirectPlay2WImpl_CreatePlayer,
4913 DirectPlay2WImpl_DeletePlayerFromGroup,
4914 DirectPlay2WImpl_DestroyGroup,
4915 DirectPlay2WImpl_DestroyPlayer,
4916 DirectPlay2WImpl_EnumGroupPlayers,
4917 DirectPlay2WImpl_EnumGroups,
4918 DirectPlay2WImpl_EnumPlayers,
4919 DirectPlay2WImpl_EnumSessions,
4920 DirectPlay2WImpl_GetCaps,
4921 DirectPlay2WImpl_GetGroupData,
4922 DirectPlay2WImpl_GetGroupName,
4923 DirectPlay2WImpl_GetMessageCount,
4924 DirectPlay2WImpl_GetPlayerAddress,
4925 DirectPlay2WImpl_GetPlayerCaps,
4926 DirectPlay2WImpl_GetPlayerData,
4927 DirectPlay2WImpl_GetPlayerName,
4928 DirectPlay2WImpl_GetSessionDesc,
4929 DirectPlay2WImpl_Initialize,
4930 DirectPlay2WImpl_Open,
4931 DirectPlay2WImpl_Receive,
4932 DirectPlay2WImpl_Send,
4933 DirectPlay2WImpl_SetGroupData,
4934 DirectPlay2WImpl_SetGroupName,
4935 DirectPlay2WImpl_SetPlayerData,
4936 DirectPlay2WImpl_SetPlayerName,
4937 DirectPlay2WImpl_SetSessionDesc
4939 #undef XCAST
4941 /* Note: Hack so we can reuse the old functions without compiler warnings */
4942 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4943 # define XCAST(fun) (typeof(directPlay2AVT.fun))
4944 #else
4945 # define XCAST(fun) (void*)
4946 #endif
4948 static const IDirectPlay2Vtbl directPlay2AVT =
4950 XCAST(QueryInterface)DP_QueryInterface,
4951 XCAST(AddRef)DP_AddRef,
4952 XCAST(Release)DP_Release,
4954 DirectPlay2AImpl_AddPlayerToGroup,
4955 DirectPlay2AImpl_Close,
4956 DirectPlay2AImpl_CreateGroup,
4957 DirectPlay2AImpl_CreatePlayer,
4958 DirectPlay2AImpl_DeletePlayerFromGroup,
4959 DirectPlay2AImpl_DestroyGroup,
4960 DirectPlay2AImpl_DestroyPlayer,
4961 DirectPlay2AImpl_EnumGroupPlayers,
4962 DirectPlay2AImpl_EnumGroups,
4963 DirectPlay2AImpl_EnumPlayers,
4964 DirectPlay2AImpl_EnumSessions,
4965 DirectPlay2AImpl_GetCaps,
4966 DirectPlay2AImpl_GetGroupData,
4967 DirectPlay2AImpl_GetGroupName,
4968 DirectPlay2AImpl_GetMessageCount,
4969 DirectPlay2AImpl_GetPlayerAddress,
4970 DirectPlay2AImpl_GetPlayerCaps,
4971 DirectPlay2AImpl_GetPlayerData,
4972 DirectPlay2AImpl_GetPlayerName,
4973 DirectPlay2AImpl_GetSessionDesc,
4974 DirectPlay2AImpl_Initialize,
4975 DirectPlay2AImpl_Open,
4976 DirectPlay2AImpl_Receive,
4977 DirectPlay2AImpl_Send,
4978 DirectPlay2AImpl_SetGroupData,
4979 DirectPlay2AImpl_SetGroupName,
4980 DirectPlay2AImpl_SetPlayerData,
4981 DirectPlay2AImpl_SetPlayerName,
4982 DirectPlay2AImpl_SetSessionDesc
4984 #undef XCAST
4987 /* Note: Hack so we can reuse the old functions without compiler warnings */
4988 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4989 # define XCAST(fun) (typeof(directPlay3AVT.fun))
4990 #else
4991 # define XCAST(fun) (void*)
4992 #endif
4994 static const IDirectPlay3Vtbl directPlay3AVT =
4996 XCAST(QueryInterface)DP_QueryInterface,
4997 XCAST(AddRef)DP_AddRef,
4998 XCAST(Release)DP_Release,
5000 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
5001 XCAST(Close)DirectPlay2AImpl_Close,
5002 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
5003 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
5004 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
5005 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
5006 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
5007 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
5008 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
5009 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
5010 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
5011 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
5012 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
5013 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
5014 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5015 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5016 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5017 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5018 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5019 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5020 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5021 XCAST(Open)DirectPlay2AImpl_Open,
5022 XCAST(Receive)DirectPlay2AImpl_Receive,
5023 XCAST(Send)DirectPlay2AImpl_Send,
5024 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5025 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5026 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5027 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5028 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5030 DirectPlay3AImpl_AddGroupToGroup,
5031 DirectPlay3AImpl_CreateGroupInGroup,
5032 DirectPlay3AImpl_DeleteGroupFromGroup,
5033 DirectPlay3AImpl_EnumConnections,
5034 DirectPlay3AImpl_EnumGroupsInGroup,
5035 DirectPlay3AImpl_GetGroupConnectionSettings,
5036 DirectPlay3AImpl_InitializeConnection,
5037 DirectPlay3AImpl_SecureOpen,
5038 DirectPlay3AImpl_SendChatMessage,
5039 DirectPlay3AImpl_SetGroupConnectionSettings,
5040 DirectPlay3AImpl_StartSession,
5041 DirectPlay3AImpl_GetGroupFlags,
5042 DirectPlay3AImpl_GetGroupParent,
5043 DirectPlay3AImpl_GetPlayerAccount,
5044 DirectPlay3AImpl_GetPlayerFlags
5046 #undef XCAST
5048 /* Note: Hack so we can reuse the old functions without compiler warnings */
5049 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5050 # define XCAST(fun) (typeof(directPlay3WVT.fun))
5051 #else
5052 # define XCAST(fun) (void*)
5053 #endif
5054 static const IDirectPlay3Vtbl directPlay3WVT =
5056 XCAST(QueryInterface)DP_QueryInterface,
5057 XCAST(AddRef)DP_AddRef,
5058 XCAST(Release)DP_Release,
5060 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
5061 XCAST(Close)DirectPlay2WImpl_Close,
5062 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
5063 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
5064 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
5065 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
5066 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5067 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5068 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5069 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5070 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5071 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5072 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5073 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5074 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5075 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5076 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5077 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5078 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5079 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5080 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5081 XCAST(Open)DirectPlay2WImpl_Open,
5082 XCAST(Receive)DirectPlay2WImpl_Receive,
5083 XCAST(Send)DirectPlay2WImpl_Send,
5084 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5085 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5086 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5087 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5088 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5090 DirectPlay3WImpl_AddGroupToGroup,
5091 DirectPlay3WImpl_CreateGroupInGroup,
5092 DirectPlay3WImpl_DeleteGroupFromGroup,
5093 DirectPlay3WImpl_EnumConnections,
5094 DirectPlay3WImpl_EnumGroupsInGroup,
5095 DirectPlay3WImpl_GetGroupConnectionSettings,
5096 DirectPlay3WImpl_InitializeConnection,
5097 DirectPlay3WImpl_SecureOpen,
5098 DirectPlay3WImpl_SendChatMessage,
5099 DirectPlay3WImpl_SetGroupConnectionSettings,
5100 DirectPlay3WImpl_StartSession,
5101 DirectPlay3WImpl_GetGroupFlags,
5102 DirectPlay3WImpl_GetGroupParent,
5103 DirectPlay3WImpl_GetPlayerAccount,
5104 DirectPlay3WImpl_GetPlayerFlags
5106 #undef XCAST
5108 /* Note: Hack so we can reuse the old functions without compiler warnings */
5109 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5110 # define XCAST(fun) (typeof(directPlay4WVT.fun))
5111 #else
5112 # define XCAST(fun) (void*)
5113 #endif
5114 static const IDirectPlay4Vtbl directPlay4WVT =
5116 XCAST(QueryInterface)DP_QueryInterface,
5117 XCAST(AddRef)DP_AddRef,
5118 XCAST(Release)DP_Release,
5120 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
5121 XCAST(Close)DirectPlay2WImpl_Close,
5122 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
5123 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
5124 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
5125 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
5126 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5127 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5128 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5129 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5130 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5131 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5132 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5133 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5134 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5135 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5136 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5137 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5138 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5139 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5140 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5141 XCAST(Open)DirectPlay2WImpl_Open,
5142 XCAST(Receive)DirectPlay2WImpl_Receive,
5143 XCAST(Send)DirectPlay2WImpl_Send,
5144 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5145 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5146 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5147 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5148 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5150 XCAST(AddGroupToGroup)DirectPlay3WImpl_AddGroupToGroup,
5151 XCAST(CreateGroupInGroup)DirectPlay3WImpl_CreateGroupInGroup,
5152 XCAST(DeleteGroupFromGroup)DirectPlay3WImpl_DeleteGroupFromGroup,
5153 XCAST(EnumConnections)DirectPlay3WImpl_EnumConnections,
5154 XCAST(EnumGroupsInGroup)DirectPlay3WImpl_EnumGroupsInGroup,
5155 XCAST(GetGroupConnectionSettings)DirectPlay3WImpl_GetGroupConnectionSettings,
5156 XCAST(InitializeConnection)DirectPlay3WImpl_InitializeConnection,
5157 XCAST(SecureOpen)DirectPlay3WImpl_SecureOpen,
5158 XCAST(SendChatMessage)DirectPlay3WImpl_SendChatMessage,
5159 XCAST(SetGroupConnectionSettings)DirectPlay3WImpl_SetGroupConnectionSettings,
5160 XCAST(StartSession)DirectPlay3WImpl_StartSession,
5161 XCAST(GetGroupFlags)DirectPlay3WImpl_GetGroupFlags,
5162 XCAST(GetGroupParent)DirectPlay3WImpl_GetGroupParent,
5163 XCAST(GetPlayerAccount)DirectPlay3WImpl_GetPlayerAccount,
5164 XCAST(GetPlayerFlags)DirectPlay3WImpl_GetPlayerFlags,
5166 DirectPlay4WImpl_GetGroupOwner,
5167 DirectPlay4WImpl_SetGroupOwner,
5168 DirectPlay4WImpl_SendEx,
5169 DirectPlay4WImpl_GetMessageQueue,
5170 DirectPlay4WImpl_CancelMessage,
5171 DirectPlay4WImpl_CancelPriority
5173 #undef XCAST
5176 /* Note: Hack so we can reuse the old functions without compiler warnings */
5177 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5178 # define XCAST(fun) (typeof(directPlay4AVT.fun))
5179 #else
5180 # define XCAST(fun) (void*)
5181 #endif
5182 static const IDirectPlay4Vtbl directPlay4AVT =
5184 XCAST(QueryInterface)DP_QueryInterface,
5185 XCAST(AddRef)DP_AddRef,
5186 XCAST(Release)DP_Release,
5188 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
5189 XCAST(Close)DirectPlay2AImpl_Close,
5190 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
5191 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
5192 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
5193 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
5194 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
5195 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
5196 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
5197 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
5198 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
5199 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
5200 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
5201 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
5202 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5203 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5204 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5205 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5206 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5207 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5208 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5209 XCAST(Open)DirectPlay2AImpl_Open,
5210 XCAST(Receive)DirectPlay2AImpl_Receive,
5211 XCAST(Send)DirectPlay2AImpl_Send,
5212 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5213 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5214 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5215 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5216 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5218 XCAST(AddGroupToGroup)DirectPlay3AImpl_AddGroupToGroup,
5219 XCAST(CreateGroupInGroup)DirectPlay3AImpl_CreateGroupInGroup,
5220 XCAST(DeleteGroupFromGroup)DirectPlay3AImpl_DeleteGroupFromGroup,
5221 XCAST(EnumConnections)DirectPlay3AImpl_EnumConnections,
5222 XCAST(EnumGroupsInGroup)DirectPlay3AImpl_EnumGroupsInGroup,
5223 XCAST(GetGroupConnectionSettings)DirectPlay3AImpl_GetGroupConnectionSettings,
5224 XCAST(InitializeConnection)DirectPlay3AImpl_InitializeConnection,
5225 XCAST(SecureOpen)DirectPlay3AImpl_SecureOpen,
5226 XCAST(SendChatMessage)DirectPlay3AImpl_SendChatMessage,
5227 XCAST(SetGroupConnectionSettings)DirectPlay3AImpl_SetGroupConnectionSettings,
5228 XCAST(StartSession)DirectPlay3AImpl_StartSession,
5229 XCAST(GetGroupFlags)DirectPlay3AImpl_GetGroupFlags,
5230 XCAST(GetGroupParent)DirectPlay3AImpl_GetGroupParent,
5231 XCAST(GetPlayerAccount)DirectPlay3AImpl_GetPlayerAccount,
5232 XCAST(GetPlayerFlags)DirectPlay3AImpl_GetPlayerFlags,
5234 DirectPlay4AImpl_GetGroupOwner,
5235 DirectPlay4AImpl_SetGroupOwner,
5236 DirectPlay4AImpl_SendEx,
5237 DirectPlay4AImpl_GetMessageQueue,
5238 DirectPlay4AImpl_CancelMessage,
5239 DirectPlay4AImpl_CancelPriority
5241 #undef XCAST
5243 HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP,
5244 DPID idPlayer,
5245 LPVOID* lplpData )
5247 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5249 if( lpPlayer == NULL )
5251 return DPERR_INVALIDPLAYER;
5254 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
5256 return DP_OK;
5259 HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP,
5260 DPID idPlayer,
5261 LPVOID lpData )
5263 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5265 if( lpPlayer == NULL )
5267 return DPERR_INVALIDPLAYER;
5270 lpPlayer->lpPData->lpSPPlayerData = lpData;
5272 return DP_OK;
5275 /***************************************************************************
5276 * DirectPlayEnumerateAW
5278 * The pointer to the structure lpContext will be filled with the
5279 * appropriate data for each service offered by the OS. These services are
5280 * not necessarily available on this particular machine but are defined
5281 * as simple service providers under the "Service Providers" registry key.
5282 * This structure is then passed to lpEnumCallback for each of the different
5283 * services.
5285 * This API is useful only for applications written using DirectX3 or
5286 * worse. It is superseded by IDirectPlay3::EnumConnections which also
5287 * gives information on the actual connections.
5289 * defn of a service provider:
5290 * A dynamic-link library used by DirectPlay to communicate over a network.
5291 * The service provider contains all the network-specific code required
5292 * to send and receive messages. Online services and network operators can
5293 * supply service providers to use specialized hardware, protocols, communications
5294 * media, and network resources.
5297 static HRESULT DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA,
5298 LPDPENUMDPCALLBACKW lpEnumCallbackW,
5299 LPVOID lpContext)
5301 HKEY hkResult;
5302 static const WCHAR searchSubKey[] = {
5303 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
5304 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
5305 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
5306 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
5307 static const WCHAR guidKey[] = { 'G', 'u', 'i', 'd', 0 };
5308 static const WCHAR descW[] = { 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', 'W', 0 };
5310 DWORD dwIndex;
5311 FILETIME filetime;
5313 char *descriptionA = NULL;
5314 DWORD max_sizeOfDescriptionA = 0;
5315 WCHAR *descriptionW = NULL;
5316 DWORD max_sizeOfDescriptionW = 0;
5318 if (!lpEnumCallbackA && !lpEnumCallbackW)
5320 return DPERR_INVALIDPARAMS;
5323 /* Need to loop over the service providers in the registry */
5324 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, searchSubKey,
5325 0, KEY_READ, &hkResult) != ERROR_SUCCESS)
5327 /* Hmmm. Does this mean that there are no service providers? */
5328 ERR(": no service provider key in the registry - check your Wine installation !!!\n");
5329 return DPERR_GENERIC;
5332 /* Traverse all the service providers we have available */
5333 dwIndex = 0;
5334 while (1)
5336 WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */
5337 DWORD sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR);
5338 HKEY hkServiceProvider;
5339 GUID serviceProviderGUID;
5340 WCHAR guidKeyContent[(2 * 16) + 1 + 6 /* This corresponds to '{....-..-..-..-......}' */ ];
5341 DWORD sizeOfGuidKeyContent = sizeof(guidKeyContent);
5342 LONG ret_value;
5344 ret_value = RegEnumKeyExW(hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
5345 NULL, NULL, NULL, &filetime);
5346 if (ret_value == ERROR_NO_MORE_ITEMS)
5347 break;
5348 else if (ret_value != ERROR_SUCCESS)
5350 ERR(": could not enumerate on service provider key.\n");
5351 return DPERR_EXCEPTION;
5353 TRACE(" this time through sub-key %s.\n", debugstr_w(subKeyName));
5355 /* Open the key for this service provider */
5356 if (RegOpenKeyExW(hkResult, subKeyName, 0, KEY_READ, &hkServiceProvider) != ERROR_SUCCESS)
5358 ERR(": could not open registry key for service provider %s.\n", debugstr_w(subKeyName));
5359 continue;
5362 /* Get the GUID from the registry */
5363 if (RegQueryValueExW(hkServiceProvider, guidKey,
5364 NULL, NULL, (LPBYTE) guidKeyContent, &sizeOfGuidKeyContent) != ERROR_SUCCESS)
5366 ERR(": missing GUID registry data member for service provider %s.\n", debugstr_w(subKeyName));
5367 continue;
5369 if (sizeOfGuidKeyContent != sizeof(guidKeyContent))
5371 ERR(": invalid format for the GUID registry data member for service provider %s (%s).\n", debugstr_w(subKeyName), debugstr_w(guidKeyContent));
5372 continue;
5374 CLSIDFromString(guidKeyContent, &serviceProviderGUID );
5376 /* The enumeration will return FALSE if we are not to continue.
5378 * Note: on my windows box, major / minor version is 6 / 0 for all service providers
5379 * and have no relation to any of the two dwReserved1 and dwReserved2 keys.
5380 * I think that it simply means that they are in-line with DirectX 6.0
5382 if (lpEnumCallbackA)
5384 DWORD sizeOfDescription = 0;
5386 /* Note that this is the A case of this function, so use the A variant to get the description string */
5387 if (RegQueryValueExA(hkServiceProvider, "DescriptionA",
5388 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5390 ERR(": missing 'DescriptionA' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5391 continue;
5393 if (sizeOfDescription > max_sizeOfDescriptionA)
5395 HeapFree(GetProcessHeap(), 0, descriptionA);
5396 max_sizeOfDescriptionA = sizeOfDescription;
5398 descriptionA = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5399 RegQueryValueExA(hkServiceProvider, "DescriptionA",
5400 NULL, NULL, (LPBYTE) descriptionA, &sizeOfDescription);
5402 if (!lpEnumCallbackA(&serviceProviderGUID, descriptionA, 6, 0, lpContext))
5403 goto end;
5405 else
5407 DWORD sizeOfDescription = 0;
5409 if (RegQueryValueExW(hkServiceProvider, descW,
5410 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5412 ERR(": missing 'DescriptionW' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5413 continue;
5415 if (sizeOfDescription > max_sizeOfDescriptionW)
5417 HeapFree(GetProcessHeap(), 0, descriptionW);
5418 max_sizeOfDescriptionW = sizeOfDescription;
5420 descriptionW = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5421 RegQueryValueExW(hkServiceProvider, descW,
5422 NULL, NULL, (LPBYTE) descriptionW, &sizeOfDescription);
5424 if (!lpEnumCallbackW(&serviceProviderGUID, descriptionW, 6, 0, lpContext))
5425 goto end;
5428 dwIndex++;
5431 end:
5432 HeapFree(GetProcessHeap(), 0, descriptionA);
5433 HeapFree(GetProcessHeap(), 0, descriptionW);
5435 return DP_OK;
5438 /***************************************************************************
5439 * DirectPlayEnumerate [DPLAYX.9]
5440 * DirectPlayEnumerateA [DPLAYX.2]
5442 HRESULT WINAPI DirectPlayEnumerateA(LPDPENUMDPCALLBACKA lpEnumCallback, LPVOID lpContext )
5444 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5446 return DirectPlayEnumerateAW(lpEnumCallback, NULL, lpContext);
5449 /***************************************************************************
5450 * DirectPlayEnumerateW [DPLAYX.3]
5452 HRESULT WINAPI DirectPlayEnumerateW(LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5454 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5456 return DirectPlayEnumerateAW(NULL, lpEnumCallback, lpContext);
5459 typedef struct tagCreateEnum
5461 LPVOID lpConn;
5462 LPCGUID lpGuid;
5463 } CreateEnumData, *lpCreateEnumData;
5465 /* Find and copy the matching connection for the SP guid */
5466 static BOOL CALLBACK cbDPCreateEnumConnections(
5467 LPCGUID lpguidSP,
5468 LPVOID lpConnection,
5469 DWORD dwConnectionSize,
5470 LPCDPNAME lpName,
5471 DWORD dwFlags,
5472 LPVOID lpContext)
5474 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5476 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5478 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5480 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5481 dwConnectionSize );
5482 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5484 /* Found the record that we were looking for */
5485 return FALSE;
5488 /* Haven't found what were looking for yet */
5489 return TRUE;
5493 /***************************************************************************
5494 * DirectPlayCreate [DPLAYX.1]
5497 HRESULT WINAPI DirectPlayCreate
5498 ( LPGUID lpGUID, LPDIRECTPLAY *lplpDP, IUnknown *pUnk )
5500 HRESULT hr;
5501 LPDIRECTPLAY3A lpDP3A;
5502 CreateEnumData cbData;
5504 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5506 if( pUnk != NULL )
5508 return CLASS_E_NOAGGREGATION;
5511 if( (lplpDP == NULL) || (lpGUID == NULL) )
5513 return DPERR_INVALIDPARAMS;
5517 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5518 give them an IDirectPlay2A object and hope that doesn't cause problems */
5519 if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
5521 return DPERR_UNAVAILABLE;
5524 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
5526 /* The GUID_NULL means don't bind a service provider. Just return the
5527 interface as is */
5528 return DP_OK;
5531 /* Bind the desired service provider since lpGUID is non NULL */
5532 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
5534 /* We're going to use a DP3 interface */
5535 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
5536 (LPVOID*)&lpDP3A );
5537 if( FAILED(hr) )
5539 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
5540 return hr;
5543 cbData.lpConn = NULL;
5544 cbData.lpGuid = lpGUID;
5546 /* We were given a service provider, find info about it... */
5547 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
5548 &cbData, DPCONNECTION_DIRECTPLAY );
5549 if( ( FAILED(hr) ) ||
5550 ( cbData.lpConn == NULL )
5553 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
5554 IDirectPlayX_Release( lpDP3A );
5555 return DPERR_UNAVAILABLE;
5558 /* Initialize the service provider */
5559 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
5560 if( FAILED(hr) )
5562 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
5563 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5564 IDirectPlayX_Release( lpDP3A );
5565 return hr;
5568 /* Release our version of the interface now that we're done with it */
5569 IDirectPlayX_Release( lpDP3A );
5570 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5572 return DP_OK;