dplayx: Fixed typo
[wine/gsoc_dplay.git] / dlls / dplayx / dplay.c
blob95e0add03005fbbd4b9dc4d93ab8a07cc01909d4
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 FIXME( "This should happen after we received all the DPMSGCMD_ADDFORWARDACKs\n" );
717 DP_MSG_ReplyToEnumPlayersRequest( This, lplpReply, lpdwMsgSize );
719 break;
722 case DPMSGCMD_SUPERENUMPLAYERSREPLY:
724 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
725 break;
728 case DPMSGCMD_ADDFORWARDACK:
730 /* When we receive an ADDFORWARDACK for each of the ADDFORWARDs
731 * we've sent, send a SUPERENUMPLAYERSREPLY back to the peer
732 * that sent the ADDFORWARDREQUEST */
733 /* TODO: We'll skip this for now and just send the SUPERENUMPLAYERSREPLY
734 * right away when we get a ADDFORWARDREQUEST */
735 break;
738 default:
740 FIXME( "Unknown wCommandId 0x%08x. Ignoring message\n", wCommandId );
741 return DPERR_GENERIC;
745 return DP_OK;
749 static HRESULT DP_IF_AddPlayerToGroup
750 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
751 DPID idPlayer, BOOL bAnsi )
753 lpGroupData lpGData;
754 lpPlayerList lpPList;
755 lpPlayerList lpNewPList;
757 TRACE( "(%p)->(%p,0x%08x,0x%08x,%u)\n",
758 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
760 if( This->dp2->connectionInitialized == NO_PROVIDER )
762 return DPERR_UNINITIALIZED;
765 /* Find the group */
766 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
768 return DPERR_INVALIDGROUP;
771 /* Find the player */
772 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
774 return DPERR_INVALIDPLAYER;
777 /* Create a player list (ie "shortcut" ) */
778 lpNewPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewPList ) );
779 if( lpNewPList == NULL )
781 return DPERR_CANTADDPLAYER;
784 /* Add the shortcut */
785 lpPList->lpPData->uRef++;
786 lpNewPList->lpPData = lpPList->lpPData;
788 /* Add the player to the list of players for this group */
789 DPQ_INSERT(lpGData->players,lpNewPList,players);
791 /* Let the SP know that we've added a player to the group */
792 if( This->dp2->spData.lpCB->AddPlayerToGroup )
794 DPSP_ADDPLAYERTOGROUPDATA data;
796 TRACE( "Calling SP AddPlayerToGroup\n" );
798 data.idPlayer = idPlayer;
799 data.idGroup = idGroup;
800 data.lpISP = This->dp2->spData.lpISP;
802 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
805 /* Inform all other peers of the addition of player to the group. If there are
806 * no peers keep this event quiet.
807 * Also, if this event was the result of another machine sending it to us,
808 * don't bother rebroadcasting it.
810 if( ( lpMsgHdr == NULL ) &&
811 This->dp2->lpSessionDesc &&
812 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
814 DPMSG_ADDPLAYERTOGROUP msg;
815 msg.dwType = DPSYS_ADDPLAYERTOGROUP;
817 msg.dpIdGroup = idGroup;
818 msg.dpIdPlayer = idPlayer;
820 /* FIXME: Correct to just use send effectively? */
821 /* FIXME: Should size include data w/ message or just message "header" */
822 /* FIXME: Check return code */
823 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
826 return DP_OK;
829 static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
830 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
832 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
833 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, TRUE );
836 static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
837 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
839 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
840 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, FALSE );
843 static HRESULT DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi )
845 HRESULT hr = DP_OK;
847 TRACE("(%p)->(%u)\n", This, bAnsi );
849 /* FIXME: Need to find a new host I assume (how?) */
850 /* FIXME: Need to destroy all local groups */
851 /* FIXME: Need to migrate all remotely visible players to the new host */
853 /* Invoke the SP callback to inform of session close */
854 if( This->dp2->spData.lpCB->CloseEx )
856 DPSP_CLOSEDATA data;
858 TRACE( "Calling SP CloseEx\n" );
860 data.lpISP = This->dp2->spData.lpISP;
862 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
865 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
867 TRACE( "Calling SP Close (obsolete interface)\n" );
869 hr = (*This->dp2->spData.lpCB->Close)();
872 if ( !FAILED(hr) )
874 This->dp2->bConnectionOpen = FALSE;
877 return hr;
880 static HRESULT WINAPI DirectPlay2AImpl_Close
881 ( LPDIRECTPLAY2A iface )
883 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
884 return DP_IF_Close( This, TRUE );
887 static HRESULT WINAPI DirectPlay2WImpl_Close
888 ( LPDIRECTPLAY2 iface )
890 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
891 return DP_IF_Close( This, FALSE );
894 static
895 lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, const DPID *lpid,
896 const DPNAME *lpName, DWORD dwFlags,
897 DPID idParent, BOOL bAnsi )
899 lpGroupData lpGData;
901 /* Allocate the new space and add to end of high level group list */
902 lpGData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGData ) );
904 if( lpGData == NULL )
906 return NULL;
909 DPQ_INIT(lpGData->groups);
910 DPQ_INIT(lpGData->players);
912 /* Set the desired player ID - no sanity checking to see if it exists */
913 lpGData->dpid = *lpid;
915 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
917 /* FIXME: Should we check that the parent exists? */
918 lpGData->parent = idParent;
920 /* FIXME: Should we validate the dwFlags? */
921 lpGData->dwFlags = dwFlags;
923 TRACE( "Created group id 0x%08x\n", *lpid );
925 return lpGData;
928 /* This method assumes that all links to it are already deleted */
929 static void
930 DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid )
932 lpGroupList lpGList;
934 TRACE( "(%p)->(0x%08x)\n", This, dpid );
936 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
938 if( lpGList == NULL )
940 ERR( "DPID 0x%08x not found\n", dpid );
941 return;
944 if( --(lpGList->lpGData->uRef) )
946 FIXME( "Why is this not the last reference to group?\n" );
947 DebugBreak();
950 /* Delete player */
951 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
952 HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
954 /* Remove and Delete Player List object */
955 HeapFree( GetProcessHeap(), 0, lpGList );
959 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid )
961 lpGroupList lpGroups;
963 TRACE( "(%p)->(0x%08x)\n", This, dpid );
965 if( dpid == DPID_SYSTEM_GROUP )
967 return This->dp2->lpSysGroup;
969 else
971 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
974 if( lpGroups == NULL )
976 return NULL;
979 return lpGroups->lpGData;
982 static HRESULT DP_IF_CreateGroup
983 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
984 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
985 DWORD dwFlags, BOOL bAnsi )
987 lpGroupData lpGData;
989 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
990 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
991 dwFlags, bAnsi );
993 /* If the name is not specified, we must provide one */
994 if( DPID_UNKNOWN == *lpidGroup )
996 /* If we are the name server, we decide on the group ids. If not, we
997 * must ask for one before attempting a creation.
999 if( This->dp2->bHostInterface )
1001 *lpidGroup = DP_NextObjectId();
1003 else
1005 *lpidGroup = DP_GetRemoteNextObjectId();
1009 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
1010 DPID_NOPARENT_GROUP, bAnsi );
1012 if( lpGData == NULL )
1014 return DPERR_CANTADDPLAYER; /* yes player not group */
1017 if( DPID_SYSTEM_GROUP == *lpidGroup )
1019 This->dp2->lpSysGroup = lpGData;
1020 TRACE( "Inserting system group\n" );
1022 else
1024 /* Insert into the system group */
1025 lpGroupList lpGroup = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGroup ) );
1026 lpGroup->lpGData = lpGData;
1028 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
1031 /* Something is now referencing this data */
1032 lpGData->uRef++;
1034 /* Set all the important stuff for the group */
1035 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
1037 /* FIXME: We should only create the system group if GetCaps returns
1038 * DPCAPS_GROUPOPTIMIZED.
1041 /* Let the SP know that we've created this group */
1042 if( This->dp2->spData.lpCB->CreateGroup )
1044 DPSP_CREATEGROUPDATA data;
1045 DWORD dwCreateFlags = 0;
1047 TRACE( "Calling SP CreateGroup\n" );
1049 if( *lpidGroup == DPID_NOPARENT_GROUP )
1050 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
1052 if( lpMsgHdr == NULL )
1053 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1055 if( dwFlags & DPGROUP_HIDDEN )
1056 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
1058 data.idGroup = *lpidGroup;
1059 data.dwFlags = dwCreateFlags;
1060 data.lpSPMessageHeader = lpMsgHdr;
1061 data.lpISP = This->dp2->spData.lpISP;
1063 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1066 /* Inform all other peers of the creation of a new group. If there are
1067 * no peers keep this event quiet.
1068 * Also if this message was sent to us, don't rebroadcast.
1070 if( ( lpMsgHdr == NULL ) &&
1071 This->dp2->lpSessionDesc &&
1072 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1074 DPMSG_CREATEPLAYERORGROUP msg;
1075 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1077 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1078 msg.dpId = *lpidGroup;
1079 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1080 msg.lpData = lpData;
1081 msg.dwDataSize = dwDataSize;
1082 msg.dpnName = *lpGroupName;
1083 msg.dpIdParent = DPID_NOPARENT_GROUP;
1084 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
1086 /* FIXME: Correct to just use send effectively? */
1087 /* FIXME: Should size include data w/ message or just message "header" */
1088 /* FIXME: Check return code */
1089 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
1090 0, 0, NULL, NULL, bAnsi );
1093 return DP_OK;
1096 static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
1097 ( LPDIRECTPLAY2A iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1098 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1100 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1102 if( This->dp2->connectionInitialized == NO_PROVIDER )
1104 return DPERR_UNINITIALIZED;
1107 if( lpidGroup == NULL ||
1108 !This->dp2->bConnectionOpen ||
1109 dwDataSize >= MAXDWORD ||
1110 ( lpData == NULL && dwDataSize != 0 ) )
1112 return DPERR_INVALIDPARAMS;
1115 *lpidGroup = DPID_UNKNOWN;
1117 return DP_IF_CreateGroup( This, NULL, lpidGroup,
1118 lpGroupName, lpData, dwDataSize, dwFlags, TRUE );
1121 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
1122 ( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1123 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1125 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1127 if( This->dp2->connectionInitialized == NO_PROVIDER )
1129 return DPERR_UNINITIALIZED;
1132 if( lpidGroup == NULL ||
1133 !This->dp2->bConnectionOpen ||
1134 dwDataSize >= MAXDWORD ||
1135 ( lpData == NULL && dwDataSize != 0 ) )
1137 return DPERR_INVALIDPARAMS;
1140 *lpidGroup = DPID_UNKNOWN;
1142 return DP_IF_CreateGroup( This, NULL, lpidGroup,
1143 lpGroupName, lpData, dwDataSize, dwFlags, FALSE );
1147 static void
1148 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
1149 LPVOID lpData, DWORD dwDataSize )
1151 /* Clear out the data with this player */
1152 if( dwFlags & DPSET_LOCAL )
1154 if ( lpGData->dwLocalDataSize != 0 )
1156 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
1157 lpGData->lpLocalData = NULL;
1158 lpGData->dwLocalDataSize = 0;
1161 else
1163 if( lpGData->dwRemoteDataSize != 0 )
1165 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
1166 lpGData->lpRemoteData = NULL;
1167 lpGData->dwRemoteDataSize = 0;
1171 /* Reallocate for new data */
1172 if( lpData != NULL )
1174 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1175 sizeof( dwDataSize ) );
1176 CopyMemory( lpNewData, lpData, dwDataSize );
1178 if( dwFlags & DPSET_LOCAL )
1180 lpGData->lpLocalData = lpData;
1181 lpGData->dwLocalDataSize = dwDataSize;
1183 else
1185 lpGData->lpRemoteData = lpNewData;
1186 lpGData->dwRemoteDataSize = dwDataSize;
1192 /* This function will just create the storage for the new player. */
1193 static
1194 lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid,
1195 LPDPNAME lpName, DWORD dwFlags,
1196 HANDLE hEvent, BOOL bAnsi )
1198 lpPlayerData lpPData;
1200 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
1202 /* Allocate the storage for the player and associate it with list element */
1203 lpPData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPData ) );
1204 if( lpPData == NULL )
1206 return NULL;
1209 /* Set the desired player ID */
1210 lpPData->dpid = *lpid;
1212 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
1214 lpPData->dwFlags = dwFlags;
1216 /* If we were given an event handle, duplicate it */
1217 if( hEvent != 0 )
1219 if( !DuplicateHandle( GetCurrentProcess(), hEvent,
1220 GetCurrentProcess(), &lpPData->hEvent,
1221 0, FALSE, DUPLICATE_SAME_ACCESS )
1224 /* FIXME: Memory leak */
1225 ERR( "Can't duplicate player msg handle %p\n", hEvent );
1229 /* Initialize the SP data section */
1230 lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData();
1232 TRACE( "Created player id 0x%08x\n", *lpid );
1234 if( ~dwFlags & DPLAYI_PLAYER_SYSPLAYER )
1235 This->dp2->lpSessionDesc->dwCurrentPlayers++;
1237 return lpPData;
1240 /* Delete the contents of the DPNAME struct */
1241 static void
1242 DP_DeleteDPNameStruct( LPDPNAME lpDPName )
1244 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u1.lpszShortNameA );
1245 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u2.lpszLongNameA );
1248 /* This method assumes that all links to it are already deleted */
1249 static void
1250 DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid )
1252 lpPlayerList lpPList;
1254 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1256 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1258 if( lpPList == NULL )
1260 ERR( "DPID 0x%08x not found\n", dpid );
1261 return;
1264 /* Verify that this is the last reference to the data */
1265 if( --(lpPList->lpPData->uRef) )
1267 FIXME( "Why is this not the last reference to player?\n" );
1268 DebugBreak();
1271 /* Delete player */
1272 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1274 CloseHandle( lpPList->lpPData->hEvent );
1275 HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
1277 /* Delete Player List object */
1278 HeapFree( GetProcessHeap(), 0, lpPList );
1281 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid )
1283 lpPlayerList lpPlayers;
1285 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1287 if(This->dp2->lpSysGroup == NULL)
1288 return NULL;
1290 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1292 return lpPlayers;
1295 /* Basic area for Dst must already be allocated */
1296 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, const DPNAME *lpSrc, BOOL bAnsi )
1298 if( lpSrc == NULL )
1300 ZeroMemory( lpDst, sizeof( *lpDst ) );
1301 lpDst->dwSize = sizeof( *lpDst );
1302 return TRUE;
1305 if( lpSrc->dwSize != sizeof( *lpSrc) )
1307 return FALSE;
1310 /* Delete any existing pointers */
1311 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1312 HeapFree( GetProcessHeap(), 0, lpDst->u2.lpszLongNameA );
1314 /* Copy as required */
1315 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1317 if( bAnsi )
1319 if( lpSrc->u1.lpszShortNameA )
1321 lpDst->u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), 0,
1322 strlen(lpSrc->u1.lpszShortNameA)+1 );
1323 strcpy( lpDst->u1.lpszShortNameA, lpSrc->u1.lpszShortNameA );
1325 else
1327 lpDst->u1.lpszShortNameA = NULL;
1329 if( lpSrc->u2.lpszLongNameA )
1331 lpDst->u2.lpszLongNameA = HeapAlloc( GetProcessHeap(), 0,
1332 strlen(lpSrc->u2.lpszLongNameA)+1 );
1333 strcpy( lpDst->u2.lpszLongNameA, lpSrc->u2.lpszLongNameA );
1335 else
1337 lpDst->u2.lpszLongNameA = NULL;
1340 else
1342 if( lpSrc->u1.lpszShortNameA )
1344 lpDst->u1.lpszShortName = HeapAlloc( GetProcessHeap(), 0,
1345 (strlenW(lpSrc->u1.lpszShortName)+1)*sizeof(WCHAR) );
1346 strcpyW( lpDst->u1.lpszShortName, lpSrc->u1.lpszShortName );
1348 else
1350 lpDst->u1.lpszShortNameA = NULL;
1352 if( lpSrc->u2.lpszLongNameA )
1354 lpDst->u2.lpszLongName = HeapAlloc( GetProcessHeap(), 0,
1355 (strlenW(lpSrc->u2.lpszLongName)+1)*sizeof(WCHAR) );
1356 strcpyW( lpDst->u2.lpszLongName, lpSrc->u2.lpszLongName );
1358 else
1360 lpDst->u2.lpszLongNameA = NULL;
1364 return TRUE;
1367 static void
1368 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
1369 LPVOID lpData, DWORD dwDataSize )
1371 /* Clear out the data with this player */
1372 if( dwFlags & DPSET_LOCAL )
1374 if ( lpPData->dwLocalDataSize != 0 )
1376 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
1377 lpPData->lpLocalData = NULL;
1378 lpPData->dwLocalDataSize = 0;
1381 else
1383 if( lpPData->dwRemoteDataSize != 0 )
1385 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
1386 lpPData->lpRemoteData = NULL;
1387 lpPData->dwRemoteDataSize = 0;
1391 /* Reallocate for new data */
1392 if( lpData != NULL )
1394 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1395 sizeof( dwDataSize ) );
1396 CopyMemory( lpNewData, lpData, dwDataSize );
1398 if( dwFlags & DPSET_LOCAL )
1400 lpPData->lpLocalData = lpData;
1401 lpPData->dwLocalDataSize = dwDataSize;
1403 else
1405 lpPData->lpRemoteData = lpNewData;
1406 lpPData->dwRemoteDataSize = dwDataSize;
1412 static HRESULT DP_IF_CreatePlayer
1413 ( IDirectPlay2Impl* This,
1414 LPVOID lpMsgHdr, /* NULL for local creation, non NULL for remote creation */
1415 LPDPID lpidPlayer,
1416 LPDPNAME lpPlayerName,
1417 HANDLE hEvent,
1418 LPVOID lpData,
1419 DWORD dwDataSize,
1420 DWORD dwFlags,
1421 BOOL bAnsi )
1423 HRESULT hr = DP_OK;
1424 lpPlayerData lpPData;
1425 lpPlayerList lpPList;
1427 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1428 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1429 dwDataSize, dwFlags, bAnsi );
1431 if( dwFlags == 0 )
1433 dwFlags = DPPLAYER_SPECTATOR;
1436 if( lpidPlayer == NULL )
1438 return DPERR_INVALIDPARAMS;
1442 /* Determine the creation flags for the player. These will be passed
1443 * to the name server if requesting a player id and to the SP when
1444 * informing it of the player creation
1447 if( dwFlags & DPPLAYER_SERVERPLAYER )
1449 if( *lpidPlayer == DPID_SERVERPLAYER )
1451 /* Server player for the host interface */
1452 dwFlags |= DPLAYI_PLAYER_APPSERVER;
1454 else if( *lpidPlayer == DPID_NAME_SERVER )
1456 /* Name server - master of everything */
1457 dwFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
1459 else
1461 /* Server player for a non host interface */
1462 dwFlags |= DPLAYI_PLAYER_SYSPLAYER;
1466 if( lpMsgHdr == NULL )
1467 dwFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1470 /* Verify we know how to handle all the flags */
1471 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1472 ( dwFlags & DPPLAYER_SPECTATOR )
1476 /* Assume non fatal failure */
1477 ERR( "unknown dwFlags = 0x%08x\n", dwFlags );
1480 /* If the name is not specified, we must provide one */
1481 if( *lpidPlayer == DPID_UNKNOWN )
1483 /* If we are the session master, we dish out the group/player ids */
1484 if( This->dp2->bHostInterface )
1486 *lpidPlayer = DP_NextObjectId();
1488 else
1490 hr = DP_MSG_SendRequestPlayerId( This, dwFlags & 0x000000FF, lpidPlayer );
1492 if( FAILED(hr) )
1494 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1495 return hr;
1499 else
1501 /* Verify that we don't already have this player */
1503 lpPlayerList lpPlayers = NULL;
1504 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players,
1505 lpPData->dpid, ==, *lpidPlayer, lpPlayers );
1507 if (lpPlayers != NULL)
1509 return DPERR_CANTCREATEPLAYER;
1514 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwFlags,
1515 hEvent, bAnsi );
1517 if( lpPData == NULL )
1519 return DPERR_CANTADDPLAYER;
1522 /* Create the list object and link it in */
1523 lpPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPList ) );
1524 if( lpPList == NULL )
1526 FIXME( "Memory leak\n" );
1527 return DPERR_CANTADDPLAYER;
1530 lpPData->uRef = 1;
1531 lpPList->lpPData = lpPData;
1533 /* Add the player to the system group */
1534 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1536 /* Update the information and send it to all players in the session */
1537 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
1539 /* Let the SP know that we've created this player */
1540 if( This->dp2->spData.lpCB->CreatePlayer )
1542 DPSP_CREATEPLAYERDATA data;
1544 data.idPlayer = *lpidPlayer;
1545 data.dwFlags = dwFlags;
1546 data.lpSPMessageHeader = lpMsgHdr;
1547 data.lpISP = This->dp2->spData.lpISP;
1549 TRACE( "Calling SP CreatePlayer 0x%08x: dwFlags: 0x%08x lpMsgHdr: %p\n",
1550 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
1552 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1555 if( FAILED(hr) )
1557 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1558 return hr;
1561 /* Now let the SP know that this player is a member of the system group */
1562 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1564 DPSP_ADDPLAYERTOGROUPDATA data;
1566 data.idPlayer = *lpidPlayer;
1567 data.idGroup = DPID_SYSTEM_GROUP;
1568 data.lpISP = This->dp2->spData.lpISP;
1570 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1572 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1575 if( FAILED(hr) )
1577 ERR( "Failed to add player to sys group with sp: %s\n",
1578 DPLAYX_HresultToString(hr) );
1579 return hr;
1582 #if 1
1583 if( This->dp2->bHostInterface == FALSE )
1585 /* Let the name server know about the creation of this player */
1586 /* FIXME: Is this only to be done for the creation of a server player or
1587 * is this used for regular players? If only for server players, move
1588 * this call to DP_SecureOpen(...);
1591 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
1593 #else
1594 /* Inform all other peers of the creation of a new player. If there are
1595 * no peers keep this quiet.
1596 * Also, if this was a remote event, no need to rebroadcast it.
1598 if( ( lpMsgHdr == NULL ) &&
1599 This->dp2->lpSessionDesc &&
1600 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1602 DPMSG_CREATEPLAYERORGROUP msg;
1603 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1605 msg.dwPlayerType = DPPLAYERTYPE_PLAYER;
1606 msg.dpId = *lpidPlayer;
1607 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */
1608 msg.lpData = lpData;
1609 msg.dwDataSize = dwDataSize;
1610 msg.dpnName = *lpPlayerName;
1611 msg.dpIdParent = DPID_NOPARENT_GROUP;
1612 msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
1614 /* FIXME: Correct to just use send effectively? */
1615 /* FIXME: Should size include data w/ message or just message "header" */
1616 /* FIXME: Check return code */
1617 hr = DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
1618 sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
1620 #endif
1622 return hr;
1625 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
1626 ( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1627 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1629 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1631 if( This->dp2->connectionInitialized == NO_PROVIDER )
1633 return DPERR_UNINITIALIZED;
1636 if( lpidPlayer == NULL || !This->dp2->bConnectionOpen )
1638 return DPERR_INVALIDPARAMS;
1641 if ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_NEWPLAYERSDISABLED )
1643 return DPERR_CANTCREATEPLAYER;
1646 if( dwFlags & DPPLAYER_SERVERPLAYER )
1648 *lpidPlayer = DPID_SERVERPLAYER;
1650 else
1652 *lpidPlayer = DPID_UNKNOWN;
1655 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1656 lpData, dwDataSize, dwFlags, TRUE );
1659 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
1660 ( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1661 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1663 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1665 if( This->dp2->connectionInitialized == NO_PROVIDER )
1667 return DPERR_UNINITIALIZED;
1670 if( lpidPlayer == NULL || !This->dp2->bConnectionOpen )
1672 return DPERR_INVALIDPARAMS;
1675 if ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_NEWPLAYERSDISABLED )
1677 return DPERR_CANTCREATEPLAYER;
1680 if( dwFlags & DPPLAYER_SERVERPLAYER )
1682 *lpidPlayer = DPID_SERVERPLAYER;
1684 else
1686 *lpidPlayer = DPID_UNKNOWN;
1689 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1690 lpData, dwDataSize, dwFlags, FALSE );
1693 static DPID DP_GetRemoteNextObjectId(void)
1695 FIXME( ":stub\n" );
1697 /* Hack solution */
1698 return DP_NextObjectId();
1701 static HRESULT DP_IF_DeletePlayerFromGroup
1702 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
1703 DPID idPlayer, BOOL bAnsi )
1705 HRESULT hr = DP_OK;
1707 lpGroupData lpGData;
1708 lpPlayerList lpPList;
1710 TRACE( "(%p)->(%p,0x%08x,0x%08x,%u)\n",
1711 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
1713 /* Find the group */
1714 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1716 return DPERR_INVALIDGROUP;
1719 /* Find the player */
1720 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
1722 return DPERR_INVALIDPLAYER;
1725 /* Remove the player shortcut from the group */
1726 DPQ_REMOVE_ENTRY( lpGData->players, players, lpPData->dpid, ==, idPlayer, lpPList );
1728 if( lpPList == NULL )
1730 return DPERR_INVALIDPLAYER;
1733 /* One less reference */
1734 lpPList->lpPData->uRef--;
1736 /* Delete the Player List element */
1737 HeapFree( GetProcessHeap(), 0, lpPList );
1739 /* Inform the SP if they care */
1740 if( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1742 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1744 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1746 data.idPlayer = idPlayer;
1747 data.idGroup = idGroup;
1748 data.lpISP = This->dp2->spData.lpISP;
1750 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1753 /* Need to send a DELETEPLAYERFROMGROUP message */
1754 FIXME( "Need to send a message\n" );
1756 return hr;
1759 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
1760 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
1762 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1763 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, TRUE );
1766 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
1767 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
1769 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1770 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, FALSE );
1773 typedef struct _DPRGOPContext
1775 IDirectPlay3Impl* This;
1776 BOOL bAnsi;
1777 DPID idGroup;
1778 } DPRGOPContext, *lpDPRGOPContext;
1780 static BOOL CALLBACK
1781 cbRemoveGroupOrPlayer(
1782 DPID dpId,
1783 DWORD dwPlayerType,
1784 LPCDPNAME lpName,
1785 DWORD dwFlags,
1786 LPVOID lpContext )
1788 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1790 TRACE( "Removing element:0x%08x (type:0x%08x) from element:0x%08x\n",
1791 dpId, dwPlayerType, lpCtxt->idGroup );
1793 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1795 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt->This, lpCtxt->idGroup,
1796 dpId )
1800 ERR( "Unable to delete group 0x%08x from group 0x%08x\n",
1801 dpId, lpCtxt->idGroup );
1804 else
1806 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl*)lpCtxt->This,
1807 NULL, lpCtxt->idGroup,
1808 dpId, lpCtxt->bAnsi )
1812 ERR( "Unable to delete player 0x%08x from grp 0x%08x\n",
1813 dpId, lpCtxt->idGroup );
1817 return TRUE; /* Continue enumeration */
1820 static HRESULT DP_IF_DestroyGroup
1821 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi )
1823 lpGroupData lpGData;
1824 DPRGOPContext context;
1826 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1827 This, lpMsgHdr, idGroup, bAnsi );
1829 /* Find the group */
1830 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1832 return DPERR_INVALIDPLAYER; /* yes player */
1835 context.This = (IDirectPlay3Impl*)This;
1836 context.bAnsi = bAnsi;
1837 context.idGroup = idGroup;
1839 /* Remove all players that this group has */
1840 DP_IF_EnumGroupPlayers( This, idGroup, NULL,
1841 cbRemoveGroupOrPlayer, &context, 0, bAnsi );
1843 /* Remove all links to groups that this group has since this is dp3 */
1844 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This, idGroup, NULL,
1845 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1847 /* Remove this group from the parent group - if it has one */
1848 if( ( idGroup != DPID_SYSTEM_GROUP ) &&
1849 ( lpGData->parent != DPID_SYSTEM_GROUP )
1852 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl*)This, lpGData->parent,
1853 idGroup );
1856 /* Now delete this group data and list from the system group */
1857 DP_DeleteGroup( This, idGroup );
1859 /* Let the SP know that we've destroyed this group */
1860 if( This->dp2->spData.lpCB->DeleteGroup )
1862 DPSP_DELETEGROUPDATA data;
1864 FIXME( "data.dwFlags is incorrect\n" );
1866 data.idGroup = idGroup;
1867 data.dwFlags = 0;
1868 data.lpISP = This->dp2->spData.lpISP;
1870 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1873 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1875 return DP_OK;
1878 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
1879 ( LPDIRECTPLAY2A iface, DPID idGroup )
1881 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1882 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
1885 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
1886 ( LPDIRECTPLAY2 iface, DPID idGroup )
1888 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1889 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
1892 typedef struct _DPFAGContext
1894 IDirectPlay2Impl* This;
1895 DPID idPlayer;
1896 BOOL bAnsi;
1897 } DPFAGContext, *lpDPFAGContext;
1899 static HRESULT DP_IF_DestroyPlayer
1900 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi )
1902 DPFAGContext cbContext;
1904 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1905 This, lpMsgHdr, idPlayer, bAnsi );
1907 if( This->dp2->connectionInitialized == NO_PROVIDER )
1909 return DPERR_UNINITIALIZED;
1912 if( DP_FindPlayer( This, idPlayer ) == NULL )
1914 return DPERR_INVALIDPLAYER;
1917 /* FIXME: If the player is remote, we must be the host to delete this */
1919 cbContext.This = This;
1920 cbContext.idPlayer = idPlayer;
1921 cbContext.bAnsi = bAnsi;
1923 /* Find each group and call DeletePlayerFromGroup if the player is a
1924 member of the group */
1925 DP_IF_EnumGroups( This, NULL, cbDeletePlayerFromAllGroups,
1926 &cbContext, DPENUMGROUPS_ALL, bAnsi );
1928 /* Now delete player and player list from the sys group */
1929 DP_DeletePlayer( This, idPlayer );
1931 /* Let the SP know that we've destroyed this group */
1932 if( This->dp2->spData.lpCB->DeletePlayer )
1934 DPSP_DELETEPLAYERDATA data;
1936 FIXME( "data.dwFlags is incorrect\n" );
1938 data.idPlayer = idPlayer;
1939 data.dwFlags = 0;
1940 data.lpISP = This->dp2->spData.lpISP;
1942 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
1945 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
1947 return DP_OK;
1950 static BOOL CALLBACK
1951 cbDeletePlayerFromAllGroups(
1952 DPID dpId,
1953 DWORD dwPlayerType,
1954 LPCDPNAME lpName,
1955 DWORD dwFlags,
1956 LPVOID lpContext )
1958 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
1960 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1962 DP_IF_DeletePlayerFromGroup( lpCtxt->This, NULL, dpId, lpCtxt->idPlayer,
1963 lpCtxt->bAnsi );
1965 /* Enumerate all groups in this group since this will normally only
1966 * be called for top level groups
1968 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)lpCtxt->This,
1969 dpId, NULL,
1970 cbDeletePlayerFromAllGroups,
1971 lpContext, DPENUMGROUPS_ALL,
1972 lpCtxt->bAnsi );
1975 else
1977 ERR( "Group callback has dwPlayerType = 0x%08x\n", dwPlayerType );
1980 return TRUE;
1983 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
1984 ( LPDIRECTPLAY2A iface, DPID idPlayer )
1986 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1987 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
1990 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
1991 ( LPDIRECTPLAY2 iface, DPID idPlayer )
1993 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1994 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
1997 static HRESULT DP_IF_EnumGroupPlayers
1998 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
1999 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2000 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2002 lpGroupData lpGData;
2003 lpPlayerList lpPList;
2005 FIXME("(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
2006 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
2007 lpContext, dwFlags, bAnsi );
2009 if( This->dp2->connectionInitialized == NO_PROVIDER )
2011 return DPERR_UNINITIALIZED;
2014 if( !This->dp2->bConnectionOpen )
2016 return DPERR_NOSESSIONS;
2019 if( ( lpEnumPlayersCallback2 == NULL ) ||
2020 ( ( dwFlags & DPENUMPLAYERS_SESSION ) && ( lpguidInstance == NULL ) ) )
2022 return DPERR_INVALIDPARAMS;
2025 /* Find the group */
2026 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2028 return DPERR_INVALIDGROUP;
2031 if( DPQ_IS_EMPTY( lpGData->players ) )
2033 return DP_OK;
2036 lpPList = DPQ_FIRST( lpGData->players );
2038 /* Walk the players in this group */
2039 for( ;; )
2041 /* We do not enum the name server or app server as they are of no
2042 * consequence to the end user.
2044 if( ( lpPList->lpPData->dpid != DPID_NAME_SERVER ) &&
2045 ( lpPList->lpPData->dpid != DPID_SERVERPLAYER )
2049 /* FIXME: Need to add stuff for dwFlags checking */
2051 if( !lpEnumPlayersCallback2( lpPList->lpPData->dpid, DPPLAYERTYPE_PLAYER,
2052 &lpPList->lpPData->name,
2053 lpPList->lpPData->dwFlags,
2054 lpContext )
2057 /* User requested break */
2058 return DP_OK;
2062 if( DPQ_IS_ENDOFLIST( lpPList->players ) )
2064 break;
2067 lpPList = DPQ_NEXT( lpPList->players );
2070 return DP_OK;
2073 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
2074 ( LPDIRECTPLAY2A iface, DPID idGroup, LPGUID lpguidInstance,
2075 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2076 LPVOID lpContext, DWORD dwFlags )
2078 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2079 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2080 lpEnumPlayersCallback2, lpContext,
2081 dwFlags, TRUE );
2084 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
2085 ( LPDIRECTPLAY2 iface, DPID idGroup, LPGUID lpguidInstance,
2086 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2087 LPVOID lpContext, DWORD dwFlags )
2089 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2090 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2091 lpEnumPlayersCallback2, lpContext,
2092 dwFlags, FALSE );
2095 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2096 static HRESULT DP_IF_EnumGroups
2097 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2098 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2099 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2101 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This,
2102 DPID_SYSTEM_GROUP, lpguidInstance,
2103 lpEnumPlayersCallback2, lpContext,
2104 dwFlags, bAnsi );
2107 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
2108 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2109 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2110 LPVOID lpContext, DWORD dwFlags )
2112 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2113 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2114 lpContext, dwFlags, TRUE );
2117 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
2118 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2119 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2120 LPVOID lpContext, DWORD dwFlags )
2122 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2123 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2124 lpContext, dwFlags, FALSE );
2127 static HRESULT DP_IF_EnumPlayers
2128 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2129 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2130 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2132 return DP_IF_EnumGroupPlayers( This, DPID_SYSTEM_GROUP, lpguidInstance,
2133 lpEnumPlayersCallback2, lpContext,
2134 dwFlags, bAnsi );
2137 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
2138 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2139 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2140 LPVOID lpContext, DWORD dwFlags )
2142 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2143 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2144 lpContext, dwFlags, TRUE );
2147 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
2148 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2149 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2150 LPVOID lpContext, DWORD dwFlags )
2152 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2153 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2154 lpContext, dwFlags, FALSE );
2157 /* This function should call the registered callback function that the user
2158 passed into EnumSessions for each entry available.
2160 static void DP_InvokeEnumSessionCallbacks
2161 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2162 LPVOID lpNSInfo,
2163 DWORD dwTimeout,
2164 LPVOID lpContext )
2166 LPDPSESSIONDESC2 lpSessionDesc;
2168 FIXME( ": not checking for conditions\n" );
2170 /* Not sure if this should be pruning but it's convenient */
2171 NS_PruneSessionCache( lpNSInfo );
2173 NS_ResetSessionEnumeration( lpNSInfo );
2175 /* Enumerate all sessions */
2176 /* FIXME: Need to indicate ANSI */
2177 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2179 TRACE( "EnumSessionsCallback2 invoked\n" );
2180 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2182 return;
2186 /* Invoke one last time to indicate that there is no more to come */
2187 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2190 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2192 EnumSessionAsyncCallbackData* data = lpContext;
2193 HANDLE hSuicideRequest = data->hSuicideRequest;
2194 DWORD dwTimeout = data->dwTimeout;
2196 TRACE( "Thread started with timeout = 0x%08x\n", dwTimeout );
2198 for( ;; )
2200 HRESULT hr;
2202 /* Sleep up to dwTimeout waiting for request to terminate thread */
2203 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2205 TRACE( "Thread terminating on terminate request\n" );
2206 break;
2209 /* Now resend the enum request */
2210 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2211 data->dwEnumSessionFlags,
2212 data->lpSpData );
2214 if( FAILED(hr) )
2216 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2217 /* FIXME: Should we kill this thread? How to inform the main thread? */
2222 TRACE( "Thread terminating\n" );
2224 /* Clean up the thread data */
2225 CloseHandle( hSuicideRequest );
2226 HeapFree( GetProcessHeap(), 0, lpContext );
2228 /* FIXME: Need to have some notification to main app thread that this is
2229 * dead. It would serve two purposes. 1) allow sync on termination
2230 * so that we don't actually send something to ourselves when we
2231 * become name server (race condition) and 2) so that if we die
2232 * abnormally something else will be able to tell.
2235 return 1;
2238 static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
2240 /* Does a thread exist? If so we were doing an async enum session */
2241 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2243 TRACE( "Killing EnumSession thread %p\n",
2244 This->dp2->hEnumSessionThread );
2246 /* Request that the thread kill itself nicely */
2247 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2248 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2250 /* We no longer need to know about the thread */
2251 CloseHandle( This->dp2->hEnumSessionThread );
2253 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2257 static HRESULT DP_IF_EnumSessions
2258 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2259 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2260 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2262 HRESULT hr = DP_OK;
2264 TRACE( "(%p)->(%p,0x%08x,%p,%p,0x%08x,%u)\n",
2265 This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags,
2266 bAnsi );
2267 if( This->dp2->connectionInitialized == NO_PROVIDER )
2269 return DPERR_UNINITIALIZED;
2272 if( (lpsd == NULL) || (lpsd->dwSize != sizeof(DPSESSIONDESC2)) )
2274 return DPERR_INVALIDPARAMS;
2277 /* Can't enumerate if the session is already open */
2278 if( This->dp2->bConnectionOpen )
2280 return DPERR_GENERIC;
2283 #if 1
2284 /* The loading of a lobby provider _seems_ to require a backdoor loading
2285 * of the service provider to also associate with this DP object. This is
2286 * because the app doesn't seem to have to call EnumConnections and
2287 * InitializeConnection for the SP before calling this method. As such
2288 * we'll do their dirty work for them with a quick hack so as to always
2289 * load the TCP/IP service provider.
2291 * The correct solution would seem to involve creating a dialog box which
2292 * contains the possible SPs. These dialog boxes most likely follow SDK
2293 * examples.
2295 if( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
2297 LPVOID lpConnection;
2298 DWORD dwSize;
2300 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2302 if( !DP_BuildCompoundAddr( DPAID_ServiceProvider, (LPGUID)&DPSPGUID_TCPIP,
2303 &lpConnection, &dwSize ) )
2305 ERR( "Can't build compound addr\n" );
2306 return DPERR_GENERIC;
2309 hr = DP_IF_InitializeConnection( (IDirectPlay3Impl*)This, lpConnection,
2310 0, bAnsi );
2311 if( FAILED(hr) )
2313 return hr;
2316 /* Free up the address buffer */
2317 HeapFree( GetProcessHeap(), 0, lpConnection );
2319 /* The SP is now initialized */
2320 This->dp2->bSPInitialized = TRUE;
2322 #endif
2325 /* Use the service provider default? */
2326 if( dwTimeout == 0 )
2328 DPCAPS spCaps;
2329 spCaps.dwSize = sizeof( spCaps );
2331 DP_IF_GetCaps( This, &spCaps, 0 );
2332 dwTimeout = spCaps.dwTimeout;
2334 /* The service provider doesn't provide one either! */
2335 if( dwTimeout == 0 )
2337 /* Provide the TCP/IP default */
2338 dwTimeout = DPMSG_WAIT_5_SECS;
2342 if( dwFlags & DPENUMSESSIONS_STOPASYNC )
2344 DP_KillEnumSessionThread( This );
2345 return hr;
2348 if( ( dwFlags & DPENUMSESSIONS_ASYNC ) )
2350 /* Enumerate everything presently in the local session cache */
2351 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2352 This->dp2->lpNameServerData, dwTimeout,
2353 lpContext );
2355 if( This->dp2->dwEnumSessionLock != 0 )
2356 return DPERR_CONNECTING;
2358 /* See if we've already created a thread to service this interface */
2359 if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2361 DWORD dwThreadId;
2362 This->dp2->dwEnumSessionLock++;
2364 /* Send the first enum request inline since the user may cancel a dialog
2365 * if one is presented. Also, may also have a connecting return code.
2367 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2368 dwFlags, &This->dp2->spData );
2370 if( SUCCEEDED(hr) )
2372 EnumSessionAsyncCallbackData* lpData
2373 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpData ) );
2374 /* FIXME: need to kill the thread on object deletion */
2375 lpData->lpSpData = &This->dp2->spData;
2377 lpData->requestGuid = lpsd->guidApplication;
2378 lpData->dwEnumSessionFlags = dwFlags;
2379 lpData->dwTimeout = dwTimeout;
2381 This->dp2->hKillEnumSessionThreadEvent =
2382 CreateEventW( NULL, TRUE, FALSE, NULL );
2384 if( !DuplicateHandle( GetCurrentProcess(),
2385 This->dp2->hKillEnumSessionThreadEvent,
2386 GetCurrentProcess(),
2387 &lpData->hSuicideRequest,
2388 0, FALSE, DUPLICATE_SAME_ACCESS )
2391 ERR( "Can't duplicate thread killing handle\n" );
2394 TRACE( ": creating EnumSessionsRequest thread\n" );
2396 This->dp2->hEnumSessionThread = CreateThread( NULL,
2398 DP_EnumSessionsSendAsyncRequestThread,
2399 lpData,
2401 &dwThreadId );
2403 This->dp2->dwEnumSessionLock--;
2406 else
2408 /* Invalidate the session cache for the interface */
2409 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2411 /* Send the broadcast for session enumeration */
2412 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2413 dwFlags,
2414 &This->dp2->spData );
2417 SleepEx( dwTimeout, FALSE );
2419 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2420 This->dp2->lpNameServerData, dwTimeout,
2421 lpContext );
2424 return hr;
2427 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2428 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2429 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2430 LPVOID lpContext, DWORD dwFlags )
2432 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2433 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2434 lpContext, dwFlags, TRUE );
2437 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2438 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2439 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2440 LPVOID lpContext, DWORD dwFlags )
2442 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2443 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2444 lpContext, dwFlags, FALSE );
2447 static HRESULT DP_IF_GetPlayerCaps
2448 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
2449 DWORD dwFlags )
2451 DPSP_GETCAPSDATA data;
2453 TRACE("(%p)->(0x%08x,%p,0x%08x)\n", This, idPlayer, lpDPCaps, dwFlags);
2455 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2457 return DPERR_UNINITIALIZED;
2460 if ( lpDPCaps->dwSize != sizeof(DPCAPS) )
2462 return DPERR_INVALIDPARAMS;
2465 /* Query the service provider */
2466 data.idPlayer = idPlayer;
2467 data.dwFlags = dwFlags;
2468 data.lpCaps = lpDPCaps;
2469 data.lpISP = This->dp2->spData.lpISP;
2471 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2474 static HRESULT DP_IF_GetCaps
2475 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags )
2477 return DP_IF_GetPlayerCaps( This, DPID_ALLPLAYERS, lpDPCaps, dwFlags );
2480 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2481 ( LPDIRECTPLAY2A iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2483 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2484 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2487 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2488 ( LPDIRECTPLAY2 iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2490 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2491 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2494 static HRESULT DP_IF_GetGroupData
2495 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2496 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2498 lpGroupData lpGData;
2499 DWORD dwRequiredBufferSize;
2500 LPVOID lpCopyDataFrom;
2502 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2503 This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi );
2505 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2507 return DPERR_INVALIDGROUP;
2510 /* How much buffer is required? */
2511 if( dwFlags & DPSET_LOCAL )
2513 dwRequiredBufferSize = lpGData->dwLocalDataSize;
2514 lpCopyDataFrom = lpGData->lpLocalData;
2516 else
2518 dwRequiredBufferSize = lpGData->dwRemoteDataSize;
2519 lpCopyDataFrom = lpGData->lpRemoteData;
2522 /* Is the user requesting to know how big a buffer is required? */
2523 if( ( lpData == NULL ) ||
2524 ( *lpdwDataSize < dwRequiredBufferSize )
2527 *lpdwDataSize = dwRequiredBufferSize;
2528 return DPERR_BUFFERTOOSMALL;
2531 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2533 return DP_OK;
2536 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2537 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2538 LPDWORD lpdwDataSize, DWORD dwFlags )
2540 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2541 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2542 dwFlags, TRUE );
2545 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2546 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2547 LPDWORD lpdwDataSize, DWORD dwFlags )
2549 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2550 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2551 dwFlags, FALSE );
2554 static HRESULT DP_IF_GetGroupName
2555 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2556 LPDWORD lpdwDataSize, BOOL bAnsi )
2558 lpGroupData lpGData;
2559 LPDPNAME lpName = lpData;
2560 DWORD dwRequiredDataSize;
2562 FIXME("(%p)->(0x%08x,%p,%p,%u) ANSI ignored\n",
2563 This, idGroup, lpData, lpdwDataSize, bAnsi );
2565 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2567 return DPERR_INVALIDGROUP;
2570 dwRequiredDataSize = lpGData->name.dwSize;
2572 if( lpGData->name.u1.lpszShortNameA )
2574 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
2577 if( lpGData->name.u2.lpszLongNameA )
2579 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
2582 if( ( lpData == NULL ) ||
2583 ( *lpdwDataSize < dwRequiredDataSize )
2586 *lpdwDataSize = dwRequiredDataSize;
2587 return DPERR_BUFFERTOOSMALL;
2590 /* Copy the structure */
2591 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2593 if( lpGData->name.u1.lpszShortNameA )
2595 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2596 lpGData->name.u1.lpszShortNameA );
2598 else
2600 lpName->u1.lpszShortNameA = NULL;
2603 if( lpGData->name.u1.lpszShortNameA )
2605 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2606 lpGData->name.u2.lpszLongNameA );
2608 else
2610 lpName->u2.lpszLongNameA = NULL;
2613 return DP_OK;
2616 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2617 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2618 LPDWORD lpdwDataSize )
2620 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2621 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2624 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2625 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2626 LPDWORD lpdwDataSize )
2628 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2629 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2632 static HRESULT DP_IF_GetMessageCount
2633 ( IDirectPlay2Impl* This, DPID idPlayer,
2634 LPDWORD lpdwCount, BOOL bAnsi )
2636 FIXME("(%p)->(0x%08x,%p,%u): stub\n", This, idPlayer, lpdwCount, bAnsi );
2637 return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer,
2638 DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL,
2639 bAnsi );
2642 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2643 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDWORD lpdwCount )
2645 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2646 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, TRUE );
2649 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2650 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDWORD lpdwCount )
2652 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2653 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, FALSE );
2656 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2657 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2659 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2660 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2661 return DP_OK;
2664 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2665 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2667 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2668 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2669 return DP_OK;
2672 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2673 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2674 DWORD dwFlags )
2676 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2677 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2680 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2681 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2682 DWORD dwFlags )
2684 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2685 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2688 static HRESULT DP_IF_GetPlayerData
2689 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2690 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2692 lpPlayerList lpPList;
2693 DWORD dwRequiredBufferSize;
2694 LPVOID lpCopyDataFrom;
2696 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2697 This, idPlayer, lpData, lpdwDataSize, dwFlags, bAnsi );
2699 if( This->dp2->connectionInitialized == NO_PROVIDER )
2701 return DPERR_UNINITIALIZED;
2704 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2706 return DPERR_INVALIDPLAYER;
2709 if( lpdwDataSize == NULL )
2711 return DPERR_INVALIDPARAMS;
2714 /* How much buffer is required? */
2715 if( dwFlags & DPSET_LOCAL )
2717 dwRequiredBufferSize = lpPList->lpPData->dwLocalDataSize;
2718 lpCopyDataFrom = lpPList->lpPData->lpLocalData;
2720 else
2722 dwRequiredBufferSize = lpPList->lpPData->dwRemoteDataSize;
2723 lpCopyDataFrom = lpPList->lpPData->lpRemoteData;
2726 /* Is the user requesting to know how big a buffer is required? */
2727 if( ( lpData == NULL ) ||
2728 ( *lpdwDataSize < dwRequiredBufferSize )
2731 *lpdwDataSize = dwRequiredBufferSize;
2732 return DPERR_BUFFERTOOSMALL;
2735 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2737 return DP_OK;
2740 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2741 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2742 LPDWORD lpdwDataSize, DWORD dwFlags )
2744 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2745 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2746 dwFlags, TRUE );
2749 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2750 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2751 LPDWORD lpdwDataSize, DWORD dwFlags )
2753 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2754 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2755 dwFlags, FALSE );
2758 static HRESULT DP_IF_GetPlayerName
2759 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2760 LPDWORD lpdwDataSize, BOOL bAnsi )
2762 lpPlayerList lpPList;
2763 LPDPNAME lpName = lpData;
2764 DWORD dwRequiredDataSize;
2766 FIXME( "(%p)->(0x%08x,%p,%p,%u): ANSI\n",
2767 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2769 if( This->dp2->connectionInitialized == NO_PROVIDER )
2771 return DPERR_UNINITIALIZED;
2774 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2776 return DPERR_INVALIDPLAYER;
2779 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
2781 if( lpPList->lpPData->name.u1.lpszShortNameA )
2783 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
2786 if( lpPList->lpPData->name.u2.lpszLongNameA )
2788 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
2791 if( ( lpData == NULL ) ||
2792 ( *lpdwDataSize < dwRequiredDataSize )
2795 *lpdwDataSize = dwRequiredDataSize;
2796 return DPERR_BUFFERTOOSMALL;
2799 /* Copy the structure */
2800 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
2802 if( lpPList->lpPData->name.u1.lpszShortNameA )
2804 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2805 lpPList->lpPData->name.u1.lpszShortNameA );
2807 else
2809 lpName->u1.lpszShortNameA = NULL;
2812 if( lpPList->lpPData->name.u2.lpszLongNameA )
2814 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2815 lpPList->lpPData->name.u2.lpszLongNameA );
2817 else
2819 lpName->u2.lpszLongNameA = NULL;
2822 return DP_OK;
2825 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2826 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2827 LPDWORD lpdwDataSize )
2829 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2830 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
2833 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2834 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2835 LPDWORD lpdwDataSize )
2837 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2838 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
2841 static HRESULT DP_GetSessionDesc
2842 ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize,
2843 BOOL bAnsi )
2845 DWORD dwRequiredSize;
2847 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
2849 if( This->dp2->connectionInitialized == NO_PROVIDER )
2851 return DPERR_UNINITIALIZED;
2854 if( !This->dp2->bConnectionOpen )
2856 return DPERR_NOSESSIONS;
2859 if( ( lpdwDataSize == NULL ) || ( *lpdwDataSize >= MAXDWORD ) )
2861 return DPERR_INVALIDPARAMS;
2864 /* FIXME: Get from This->dp2->lpSessionDesc */
2865 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
2867 if ( ( lpData == NULL ) ||
2868 ( *lpdwDataSize < dwRequiredSize )
2871 *lpdwDataSize = dwRequiredSize;
2872 return DPERR_BUFFERTOOSMALL;
2875 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
2877 return DP_OK;
2880 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
2881 ( LPDIRECTPLAY2A iface, LPVOID lpData, LPDWORD lpdwDataSize )
2883 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2884 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2887 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
2888 ( LPDIRECTPLAY2 iface, LPVOID lpData, LPDWORD lpdwDataSize )
2890 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2891 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2894 /* Intended only for COM compatibility. Always returns an error. */
2895 static HRESULT WINAPI DirectPlay2AImpl_Initialize
2896 ( LPDIRECTPLAY2A iface, LPGUID lpGUID )
2898 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2899 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2900 return DPERR_ALREADYINITIALIZED;
2903 /* Intended only for COM compatibility. Always returns an error. */
2904 static HRESULT WINAPI DirectPlay2WImpl_Initialize
2905 ( LPDIRECTPLAY2 iface, LPGUID lpGUID )
2907 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2908 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2909 return DPERR_ALREADYINITIALIZED;
2913 static HRESULT DP_SecureOpen
2914 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
2915 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
2916 BOOL bAnsi )
2918 HRESULT hr = DP_OK;
2920 FIXME( "(%p)->(%p,0x%08x,%p,%p): partial stub\n",
2921 This, lpsd, dwFlags, lpSecurity, lpCredentials );
2923 if( ( lpsd == NULL ) ||
2924 ( lpsd->dwSize != sizeof(DPSESSIONDESC2) ) )
2926 return DPERR_INVALIDPARAMS;
2929 if( This->dp2->bConnectionOpen )
2931 TRACE( ": rejecting already open connection.\n" );
2932 return DPERR_ALREADYINITIALIZED;
2935 /* If we're enumerating, kill the thread */
2936 DP_KillEnumSessionThread( This );
2938 if( dwFlags & DPOPEN_JOIN )
2940 LPDPSESSIONDESC2 current = NULL;
2941 NS_ResetSessionEnumeration( This->dp2->lpNameServerData );
2942 while( ( current = NS_WalkSessions( This->dp2->lpNameServerData ) ) )
2944 if ( IsEqualGUID( &lpsd->guidInstance, &current->guidInstance ) )
2945 break;
2947 if ( current == NULL )
2948 return DPERR_NOSESSIONS;
2950 else if( dwFlags & DPOPEN_CREATE )
2952 /* Rightoo - this computer is the host and the local computer needs to be
2953 the name server so that others can join this session */
2954 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
2956 This->dp2->bHostInterface = TRUE;
2958 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
2959 if( FAILED( hr ) )
2961 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
2962 return hr;
2966 /* Invoke the conditional callback for the service provider */
2967 if( This->dp2->spData.lpCB->Open )
2969 DPSP_OPENDATA data;
2971 FIXME( "Not all data fields are correct. Need new parameter\n" );
2973 data.bCreate = (dwFlags & DPOPEN_CREATE ) ? TRUE : FALSE;
2974 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
2975 : NS_GetNSAddr( This->dp2->lpNameServerData );
2976 data.lpISP = This->dp2->spData.lpISP;
2977 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) ? TRUE : FALSE;
2978 data.dwOpenFlags = dwFlags;
2979 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
2981 hr = (*This->dp2->spData.lpCB->Open)(&data);
2982 if( FAILED( hr ) )
2984 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
2985 return hr;
2990 /* Create the system group of which everything is a part of */
2991 DPID systemGroup = DPID_SYSTEM_GROUP;
2993 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
2994 NULL, 0, 0, TRUE );
2998 if( dwFlags & DPOPEN_JOIN )
3000 DPID dpidServerId = DPID_UNKNOWN;
3002 /* Create the server player for this interface. This way we can receive
3003 * messages for this session.
3005 /* FIXME: I suppose that we should be setting an event for a receive
3006 * type of thing. That way the messaging thread could know to wake
3007 * up. DPlay would then trigger the hEvent for the player the
3008 * message is directed to.
3010 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
3012 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
3015 else if( dwFlags & DPOPEN_CREATE )
3017 DPID dpidNameServerId = DPID_NAME_SERVER;
3019 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
3020 0, DPPLAYER_SERVERPLAYER, bAnsi );
3023 if( FAILED(hr) )
3025 ERR( "Couldn't create name server/system player: %s\n",
3026 DPLAYX_HresultToString(hr) );
3028 else
3030 This->dp2->bConnectionOpen = TRUE;
3033 return hr;
3036 static HRESULT WINAPI DirectPlay2AImpl_Open
3037 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
3039 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3040 TRACE("(%p)->(%p,0x%08x)\n", This, lpsd, dwFlags );
3041 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, TRUE );
3044 static HRESULT WINAPI DirectPlay2WImpl_Open
3045 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
3047 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3048 TRACE("(%p)->(%p,0x%08x)\n", This, lpsd, dwFlags );
3049 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, FALSE );
3052 static HRESULT DP_IF_Receive
3053 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
3054 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi )
3056 LPDPMSG lpMsg = NULL;
3058 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p,%u): stub\n",
3059 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
3061 if( This->dp2->connectionInitialized == NO_PROVIDER )
3063 return DPERR_UNINITIALIZED;
3066 if( dwFlags == 0 )
3068 dwFlags = DPRECEIVE_ALL;
3071 /* If the lpData is NULL, we must be peeking the message */
3072 if( ( lpData == NULL ) &&
3073 !( dwFlags & DPRECEIVE_PEEK )
3076 return DPERR_INVALIDPARAMS;
3079 if( dwFlags & DPRECEIVE_ALL )
3081 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
3083 if( !( dwFlags & DPRECEIVE_PEEK ) )
3085 FIXME( "Remove from queue\n" );
3088 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
3089 ( dwFlags & DPRECEIVE_FROMPLAYER )
3092 FIXME( "Find matching message 0x%08x\n", dwFlags );
3094 else
3096 ERR( "Hmmm..dwFlags 0x%08x\n", dwFlags );
3099 if( lpMsg == NULL )
3101 return DPERR_NOMESSAGES;
3104 /* Copy into the provided buffer */
3105 if (lpData) CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
3107 return DP_OK;
3110 static HRESULT WINAPI DirectPlay2AImpl_Receive
3111 ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo,
3112 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
3114 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3115 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
3116 lpData, lpdwDataSize, TRUE );
3119 static HRESULT WINAPI DirectPlay2WImpl_Receive
3120 ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo,
3121 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
3123 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3124 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
3125 lpData, lpdwDataSize, FALSE );
3128 static HRESULT WINAPI DirectPlay2AImpl_Send
3129 ( LPDIRECTPLAY2A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3131 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3132 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3133 0, 0, NULL, NULL, TRUE );
3136 static HRESULT WINAPI DirectPlay2WImpl_Send
3137 ( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3139 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3140 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3141 0, 0, NULL, NULL, FALSE );
3144 static HRESULT DP_IF_SetGroupData
3145 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
3146 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3148 lpGroupData lpGData;
3150 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3151 This, idGroup, lpData, dwDataSize, dwFlags, bAnsi );
3153 /* Parameter check */
3154 if( ( lpData == NULL ) &&
3155 ( dwDataSize != 0 )
3158 return DPERR_INVALIDPARAMS;
3161 /* Find the pointer to the data for this player */
3162 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3164 return DPERR_INVALIDOBJECT;
3167 if( !(dwFlags & DPSET_LOCAL) )
3169 FIXME( "Was this group created by this interface?\n" );
3170 /* FIXME: If this is a remote update need to allow it but not
3171 * send a message.
3175 DP_SetGroupData( lpGData, dwFlags, lpData, dwDataSize );
3177 /* FIXME: Only send a message if this group is local to the session otherwise
3178 * it will have been rejected above
3180 if( !(dwFlags & DPSET_LOCAL) )
3182 FIXME( "Send msg?\n" );
3185 return DP_OK;
3188 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
3189 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
3190 DWORD dwDataSize, DWORD dwFlags )
3192 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3193 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, TRUE );
3196 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
3197 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
3198 DWORD dwDataSize, DWORD dwFlags )
3200 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3201 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, FALSE );
3204 static HRESULT DP_IF_SetGroupName
3205 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
3206 DWORD dwFlags, BOOL bAnsi )
3208 lpGroupData lpGData;
3210 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n", This, idGroup,
3211 lpGroupName, dwFlags, bAnsi );
3213 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3215 return DPERR_INVALIDGROUP;
3218 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
3220 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3221 FIXME( "Message not sent and dwFlags ignored\n" );
3223 return DP_OK;
3226 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
3227 ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName,
3228 DWORD dwFlags )
3230 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3231 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
3234 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
3235 ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName,
3236 DWORD dwFlags )
3238 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3239 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
3242 static HRESULT DP_IF_SetPlayerData
3243 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
3244 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3246 lpPlayerList lpPList;
3248 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3249 This, idPlayer, lpData, dwDataSize, dwFlags, bAnsi );
3251 if( This->dp2->connectionInitialized == NO_PROVIDER )
3253 return DPERR_UNINITIALIZED;
3256 /* Parameter check */
3257 if( ( ( lpData == NULL ) && ( dwDataSize != 0 ) ) ||
3258 ( dwDataSize >= MAXDWORD ) )
3260 return DPERR_INVALIDPARAMS;
3263 /* Find the pointer to the data for this player */
3264 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3266 return DPERR_INVALIDPLAYER;
3269 if( !(dwFlags & DPSET_LOCAL) )
3271 FIXME( "Was this group created by this interface?\n" );
3272 /* FIXME: If this is a remote update need to allow it but not
3273 * send a message.
3277 DP_SetPlayerData( lpPList->lpPData, dwFlags, lpData, dwDataSize );
3279 if( !(dwFlags & DPSET_LOCAL) )
3281 FIXME( "Send msg?\n" );
3284 return DP_OK;
3287 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3288 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
3289 DWORD dwDataSize, DWORD dwFlags )
3291 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3292 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3293 dwFlags, TRUE );
3296 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3297 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
3298 DWORD dwDataSize, DWORD dwFlags )
3300 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3301 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3302 dwFlags, FALSE );
3305 static HRESULT DP_IF_SetPlayerName
3306 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
3307 DWORD dwFlags, BOOL bAnsi )
3309 lpPlayerList lpPList;
3311 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n",
3312 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3314 if( This->dp2->connectionInitialized == NO_PROVIDER )
3316 return DPERR_UNINITIALIZED;
3319 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3321 return DPERR_INVALIDGROUP;
3324 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3326 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3327 FIXME( "Message not sent and dwFlags ignored\n" );
3329 return DP_OK;
3332 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3333 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName,
3334 DWORD dwFlags )
3336 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3337 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3340 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3341 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName,
3342 DWORD dwFlags )
3344 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3345 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3348 static HRESULT DP_SetSessionDesc
3349 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
3350 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3352 DWORD dwRequiredSize;
3353 LPDPSESSIONDESC2 lpTempSessDesc;
3355 TRACE( "(%p)->(%p,0x%08x,%u,%u)\n",
3356 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3358 if( dwFlags || (lpSessDesc == NULL) )
3360 return DPERR_INVALIDPARAMS;
3363 /* Illegal combinations of flags */
3364 if ( ( lpSessDesc->dwFlags & DPSESSION_MIGRATEHOST ) &&
3365 ( lpSessDesc->dwFlags & ( DPSESSION_CLIENTSERVER |
3366 DPSESSION_MULTICASTSERVER |
3367 DPSESSION_SECURESERVER ) ) )
3369 return DPERR_INVALIDFLAGS;
3372 /* Only the host is allowed to update the session desc */
3373 if( !This->dp2->bHostInterface )
3375 return DPERR_ACCESSDENIED;
3378 /* FIXME: Copy into This->dp2->lpSessionDesc */
3379 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3380 lpTempSessDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize );
3382 if( lpTempSessDesc == NULL )
3384 return DPERR_OUTOFMEMORY;
3387 /* Free the old */
3388 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3390 This->dp2->lpSessionDesc = lpTempSessDesc;
3391 /* Set the new */
3392 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3393 if( bInitial )
3395 /*Initializing session GUID*/
3396 CoCreateGuid( &(This->dp2->lpSessionDesc->guidInstance) );
3398 /* If this is an external invocation of the interface, we should be
3399 * letting everyone know that things have changed. Otherwise this is
3400 * just an initialization and it doesn't need to be propagated.
3402 if( !bInitial )
3404 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3407 return DP_OK;
3410 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3411 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3413 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3415 if( This->dp2->connectionInitialized == NO_PROVIDER )
3417 return DPERR_UNINITIALIZED;
3420 if( !This->dp2->bConnectionOpen )
3422 return DPERR_NOSESSIONS;
3425 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3428 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3429 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3431 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3433 if( This->dp2->connectionInitialized == NO_PROVIDER )
3435 return DPERR_UNINITIALIZED;
3438 if( !This->dp2->bConnectionOpen )
3440 return DPERR_NOSESSIONS;
3443 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3446 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3447 static DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3449 DWORD dwSize = 0;
3451 if( lpSessDesc == NULL )
3453 /* Hmmm..don't need any size? */
3454 ERR( "NULL lpSessDesc\n" );
3455 return dwSize;
3458 dwSize += sizeof( *lpSessDesc );
3460 if( bAnsi )
3462 if( lpSessDesc->u1.lpszSessionNameA )
3464 dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1;
3467 if( lpSessDesc->u2.lpszPasswordA )
3469 dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1;
3472 else /* UNICODE */
3474 if( lpSessDesc->u1.lpszSessionName )
3476 dwSize += sizeof( WCHAR ) *
3477 ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 );
3480 if( lpSessDesc->u2.lpszPassword )
3482 dwSize += sizeof( WCHAR ) *
3483 ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 );
3487 return dwSize;
3490 /* Assumes that contiguous buffers are already allocated. */
3491 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3492 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3494 BYTE* lpStartOfFreeSpace;
3496 if( lpSessionDest == NULL )
3498 ERR( "NULL lpSessionDest\n" );
3499 return;
3502 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3504 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3506 if( bAnsi )
3508 if( lpSessionSrc->u1.lpszSessionNameA )
3510 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3511 lpSessionDest->u1.lpszSessionNameA );
3512 lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3513 lpStartOfFreeSpace +=
3514 lstrlenA( lpSessionDest->u1.lpszSessionNameA ) + 1;
3517 if( lpSessionSrc->u2.lpszPasswordA )
3519 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3520 lpSessionDest->u2.lpszPasswordA );
3521 lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3522 lpStartOfFreeSpace +=
3523 lstrlenA( lpSessionDest->u2.lpszPasswordA ) + 1;
3526 else /* UNICODE */
3528 if( lpSessionSrc->u1.lpszSessionName )
3530 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3531 lpSessionDest->u1.lpszSessionName );
3532 lpSessionDest->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3533 lpStartOfFreeSpace += sizeof(WCHAR) *
3534 ( lstrlenW( lpSessionDest->u1.lpszSessionName ) + 1 );
3537 if( lpSessionSrc->u2.lpszPassword )
3539 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3540 lpSessionDest->u2.lpszPassword );
3541 lpSessionDest->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3542 lpStartOfFreeSpace += sizeof(WCHAR) *
3543 ( lstrlenW( lpSessionDest->u2.lpszPassword ) + 1 );
3549 static HRESULT DP_IF_AddGroupToGroup
3550 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3552 lpGroupData lpGData;
3553 lpGroupList lpNewGList;
3555 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, idParentGroup, idGroup );
3557 if( This->dp2->connectionInitialized == NO_PROVIDER )
3559 return DPERR_UNINITIALIZED;
3562 if( DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) == NULL )
3564 return DPERR_INVALIDGROUP;
3567 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3569 return DPERR_INVALIDGROUP;
3572 /* Create a player list (ie "shortcut" ) */
3573 lpNewGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewGList ) );
3574 if( lpNewGList == NULL )
3576 return DPERR_CANTADDPLAYER;
3579 /* Add the shortcut */
3580 lpGData->uRef++;
3581 lpNewGList->lpGData = lpGData;
3583 /* Add the player to the list of players for this group */
3584 DPQ_INSERT( lpGData->groups, lpNewGList, groups );
3586 /* Send a ADDGROUPTOGROUP message */
3587 FIXME( "Not sending message\n" );
3589 return DP_OK;
3592 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3593 ( LPDIRECTPLAY3A iface, DPID idParentGroup, DPID idGroup )
3595 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3596 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3599 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3600 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3602 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3603 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3606 static HRESULT DP_IF_CreateGroupInGroup
3607 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
3608 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
3609 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3611 lpGroupData lpGParentData;
3612 lpGroupList lpGList;
3613 lpGroupData lpGData;
3615 TRACE( "(%p)->(0x%08x,%p,%p,%p,0x%08x,0x%08x,%u)\n",
3616 This, idParentGroup, lpidGroup, lpGroupName, lpData,
3617 dwDataSize, dwFlags, bAnsi );
3619 /* Verify that the specified parent is valid */
3620 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This,
3621 idParentGroup ) ) == NULL
3624 return DPERR_INVALIDGROUP;
3627 lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName,
3628 dwFlags, idParentGroup, bAnsi );
3630 if( lpGData == NULL )
3632 return DPERR_CANTADDPLAYER; /* yes player not group */
3635 /* Something else is referencing this data */
3636 lpGData->uRef++;
3638 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
3640 /* The list has now been inserted into the interface group list. We now
3641 need to put a "shortcut" to this group in the parent group */
3642 lpGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGList ) );
3643 if( lpGList == NULL )
3645 FIXME( "Memory leak\n" );
3646 return DPERR_CANTADDPLAYER; /* yes player not group */
3649 lpGList->lpGData = lpGData;
3651 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
3653 /* Let the SP know that we've created this group */
3654 if( This->dp2->spData.lpCB->CreateGroup )
3656 DPSP_CREATEGROUPDATA data;
3658 TRACE( "Calling SP CreateGroup\n" );
3660 data.idGroup = *lpidGroup;
3661 data.dwFlags = dwFlags;
3662 data.lpSPMessageHeader = lpMsgHdr;
3663 data.lpISP = This->dp2->spData.lpISP;
3665 (*This->dp2->spData.lpCB->CreateGroup)( &data );
3668 /* Inform all other peers of the creation of a new group. If there are
3669 * no peers keep this quiet.
3671 if( This->dp2->lpSessionDesc &&
3672 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
3674 DPMSG_CREATEPLAYERORGROUP msg;
3676 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
3677 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
3678 msg.dpId = *lpidGroup;
3679 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
3680 msg.lpData = lpData;
3681 msg.dwDataSize = dwDataSize;
3682 msg.dpnName = *lpGroupName;
3684 /* FIXME: Correct to just use send effectively? */
3685 /* FIXME: Should size include data w/ message or just message "header" */
3686 /* FIXME: Check return code */
3687 DP_SendEx( (IDirectPlay2Impl*)This,
3688 DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
3689 0, 0, NULL, NULL, bAnsi );
3692 return DP_OK;
3695 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3696 ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup,
3697 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3698 DWORD dwFlags )
3700 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3702 if( This->dp2->connectionInitialized == NO_PROVIDER )
3704 return DPERR_UNINITIALIZED;
3707 if( lpidGroup == NULL ||
3708 !This->dp2->bConnectionOpen ||
3709 dwDataSize >= MAXDWORD ||
3710 ( lpData == NULL && dwDataSize != 0 ) )
3712 return DPERR_INVALIDPARAMS;
3715 *lpidGroup = DPID_UNKNOWN;
3717 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3718 lpGroupName, lpData, dwDataSize, dwFlags,
3719 TRUE );
3722 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3723 ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup,
3724 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3725 DWORD dwFlags )
3727 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3729 if( This->dp2->connectionInitialized == NO_PROVIDER )
3731 return DPERR_UNINITIALIZED;
3734 if( lpidGroup == NULL ||
3735 !This->dp2->bConnectionOpen ||
3736 dwDataSize >= MAXDWORD ||
3737 ( lpData == NULL && dwDataSize != 0 ) )
3739 return DPERR_INVALIDPARAMS;
3742 *lpidGroup = DPID_UNKNOWN;
3744 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3745 lpGroupName, lpData, dwDataSize,
3746 dwFlags, FALSE );
3749 static HRESULT DP_IF_DeleteGroupFromGroup
3750 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3752 lpGroupList lpGList;
3753 lpGroupData lpGParentData;
3755 TRACE("(%p)->(0x%08x,0x%08x)\n", This, idParentGroup, idGroup );
3757 /* Is the parent group valid? */
3758 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3760 return DPERR_INVALIDGROUP;
3763 /* Remove the group from the parent group queue */
3764 DPQ_REMOVE_ENTRY( lpGParentData->groups, groups, lpGData->dpid, ==, idGroup, lpGList );
3766 if( lpGList == NULL )
3768 return DPERR_INVALIDGROUP;
3771 /* Decrement the ref count */
3772 lpGList->lpGData->uRef--;
3774 /* Free up the list item */
3775 HeapFree( GetProcessHeap(), 0, lpGList );
3777 /* Should send a DELETEGROUPFROMGROUP message */
3778 FIXME( "message not sent\n" );
3780 return DP_OK;
3783 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3784 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3786 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3787 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3790 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3791 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3793 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3794 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3796 static BOOL DP_BuildCompoundAddr( GUID guidDataType,
3797 LPGUID lpcSpGuid,
3798 LPVOID* lplpAddrBuf,
3799 LPDWORD lpdwBufSize )
3801 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3802 HRESULT hr;
3804 dpCompoundAddress.dwDataSize = sizeof( GUID );
3805 dpCompoundAddress.guidDataType = guidDataType;
3806 dpCompoundAddress.lpData = lpcSpGuid;
3808 *lplpAddrBuf = NULL;
3809 *lpdwBufSize = 0;
3811 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3812 lpdwBufSize, TRUE );
3814 if( hr != DPERR_BUFFERTOOSMALL )
3816 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3817 return FALSE;
3820 /* Now allocate the buffer */
3821 *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3822 *lpdwBufSize );
3824 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3825 lpdwBufSize, TRUE );
3826 if( FAILED(hr) )
3828 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3829 return FALSE;
3832 return TRUE;
3835 static HRESULT WINAPI DP_IF_EnumConnections
3836 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication,
3837 LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext,
3838 DWORD dwFlags, BOOL bAnsi )
3840 HKEY hkResult;
3841 WCHAR searchSubKeySP[] = {
3842 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
3843 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
3844 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
3845 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
3846 WCHAR searchSubKeyLP[] = {
3847 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
3848 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
3849 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
3850 'L', 'o', 'b', 'b', 'y', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
3851 WCHAR guidDataSubKey[] = { 'G', 'u', 'i', 'd', 0 };
3852 WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */
3853 DWORD dwIndex, sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR);
3854 FILETIME filetime;
3856 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
3857 if( dwFlags == 0 )
3859 dwFlags = DPCONNECTION_DIRECTPLAY;
3862 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
3863 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) ) )
3865 return DPERR_INVALIDFLAGS;
3868 if( !lpEnumCallback )
3870 return DPERR_INVALIDPARAMS;
3874 /* Need to loop over the service providers in the registry */
3875 if( RegOpenKeyExW( HKEY_LOCAL_MACHINE,
3876 ( dwFlags & DPCONNECTION_DIRECTPLAY ) ? searchSubKeySP
3877 : searchSubKeyLP,
3878 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3880 /* Hmmm. Does this mean that there are no service providers? */
3881 ERR(": no service providers?\n");
3882 return DP_OK;
3886 /* Traverse all the service providers we have available */
3887 for( dwIndex=0;
3888 RegEnumKeyExW( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3889 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3890 ++dwIndex, sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR) )
3892 HKEY hkServiceProvider;
3893 GUID serviceProviderGUID;
3894 WCHAR guidKeyContent[39];
3895 DWORD sizeOfReturnBuffer = sizeof(guidKeyContent);
3896 DPNAME dpName;
3897 BOOL continueEnumeration = TRUE;
3899 LPVOID lpAddressBuffer = NULL;
3900 DWORD dwAddressBufferSize = 0;
3903 TRACE(" this time through: %s\n", debugstr_w(subKeyName) );
3905 /* Get a handle for this particular service provider */
3906 if( RegOpenKeyExW( hkResult, subKeyName, 0, KEY_READ,
3907 &hkServiceProvider ) != ERROR_SUCCESS )
3909 ERR(": what the heck is going on?\n" );
3910 continue;
3913 if( RegQueryValueExW( hkServiceProvider, guidDataSubKey,
3914 NULL, NULL, (LPBYTE)guidKeyContent,
3915 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3917 ERR(": missing GUID registry data members\n" );
3918 RegCloseKey(hkServiceProvider);
3919 continue;
3921 RegCloseKey(hkServiceProvider);
3923 CLSIDFromString( guidKeyContent, &serviceProviderGUID );
3925 /* Fill in the DPNAME struct for the service provider */
3926 dpName.dwSize = sizeof( dpName );
3927 dpName.dwFlags = 0;
3928 if ( bAnsi )
3930 dpName.u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3931 sizeOfSubKeyName+1 );
3932 WideCharToMultiByte( CP_ACP, 0, subKeyName,
3933 -1, dpName.u1.lpszShortNameA, -1, 0, 0);
3934 dpName.u2.lpszLongNameA = NULL;
3936 else
3938 dpName.u1.lpszShortName = subKeyName;
3939 dpName.u2.lpszLongName = NULL;
3942 /* Create the compound address for the service provider.
3943 * NOTE: This is a gruesome architectural scar right now. DP
3944 * uses DPL and DPL uses DP. Nasty stuff. This may be why the
3945 * native dll just gets around this little bit by allocating an
3946 * 80 byte buffer which isn't even filled with a valid compound
3947 * address. Oh well. Creating a proper compound address is the
3948 * way to go anyways despite this method taking slightly more
3949 * heap space and realtime :) */
3951 if ( DP_BuildCompoundAddr( ( ( dwFlags & DPCONNECTION_DIRECTPLAY )
3952 ? DPAID_ServiceProvider
3953 : DPAID_LobbyProvider ),
3954 &serviceProviderGUID,
3955 &lpAddressBuffer,
3956 &dwAddressBufferSize ) )
3958 /* The enumeration will return FALSE if we are not to continue */
3959 continueEnumeration = lpEnumCallback( &serviceProviderGUID, lpAddressBuffer,
3960 dwAddressBufferSize, &dpName,
3961 dwFlags, lpContext );
3963 else
3965 ERR( "Couldn't build compound address\n" );
3968 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
3969 if ( bAnsi )
3970 HeapFree( GetProcessHeap(), 0, dpName.u1.lpszShortNameA );
3972 if (!continueEnumeration)
3973 return DP_OK;
3976 return DP_OK;
3979 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
3980 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3982 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3983 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3984 return DP_IF_EnumConnections( iface, lpguidApplication, lpEnumCallback, lpContext, dwFlags, TRUE );
3987 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
3988 ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3990 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3991 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3992 return DP_IF_EnumConnections( iface, lpguidApplication, lpEnumCallback, lpContext, dwFlags, FALSE );
3995 static HRESULT DP_IF_EnumGroupsInGroup
3996 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
3997 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
3998 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
4000 lpGroupList lpGList;
4001 lpGroupData lpGData;
4003 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
4004 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
4005 lpContext, dwFlags, bAnsi );
4007 if( This->dp2->connectionInitialized == NO_PROVIDER )
4009 return DPERR_UNINITIALIZED;
4012 if( !This->dp2->bConnectionOpen )
4014 return DPERR_NOSESSIONS;
4017 if( ( lpEnumPlayersCallback2 == NULL ) ||
4018 ( ( dwFlags & DPENUMGROUPS_SESSION ) && ( lpguidInstance == NULL ) ) )
4020 return DPERR_INVALIDPARAMS;
4023 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4025 return DPERR_INVALIDGROUP;
4028 if( DPQ_IS_EMPTY( lpGData->groups ) )
4030 return DP_OK;
4033 lpGList = DPQ_FIRST( lpGData->groups );
4035 for( ;; )
4037 /* FIXME: Should check dwFlags for match here */
4039 if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP,
4040 &lpGList->lpGData->name, dwFlags,
4041 lpContext ) )
4043 return DP_OK; /* User requested break */
4046 if( DPQ_IS_ENDOFLIST( lpGList->groups ) )
4048 break;
4051 lpGList = DPQ_NEXT( lpGList->groups );
4055 return DP_OK;
4058 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
4059 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
4060 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
4061 DWORD dwFlags )
4063 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4064 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
4065 lpEnumPlayersCallback2, lpContext, dwFlags,
4066 TRUE );
4069 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
4070 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
4071 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
4072 DWORD dwFlags )
4074 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4075 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
4076 lpEnumPlayersCallback2, lpContext, dwFlags,
4077 FALSE );
4080 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
4081 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
4083 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4084 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
4085 return DP_OK;
4088 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
4089 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
4091 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4092 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
4093 return DP_OK;
4096 static BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
4097 REFGUID guidDataType,
4098 DWORD dwDataSize,
4099 LPCVOID lpData,
4100 LPVOID lpContext )
4102 /* Looking for the GUID of the provider to load */
4103 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
4104 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
4107 TRACE( "Found SP/LP (%s) %s (data size = 0x%08x)\n",
4108 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
4110 if( dwDataSize != sizeof( GUID ) )
4112 ERR( "Invalid sp/lp guid size 0x%08x\n", dwDataSize );
4115 memcpy( lpContext, lpData, dwDataSize );
4117 /* There shouldn't be more than 1 GUID/compound address */
4118 return FALSE;
4121 /* Still waiting for what we want */
4122 return TRUE;
4126 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
4127 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
4129 UINT i;
4130 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4131 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
4132 LPCSTR guidDataSubKey = "Guid";
4133 LPCSTR majVerDataSubKey = "dwReserved1";
4134 LPCSTR minVerDataSubKey = "dwReserved2";
4135 LPCSTR pathSubKey = "Path";
4137 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
4139 /* FIXME: Cloned code with a quick hack. */
4140 for( i=0; i<2; i++ )
4142 HKEY hkResult;
4143 LPCSTR searchSubKey;
4144 char subKeyName[51];
4145 DWORD dwIndex, sizeOfSubKeyName=50;
4146 FILETIME filetime;
4148 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
4149 *lpbIsDpSp = (i == 0) ? TRUE : FALSE;
4152 /* Need to loop over the service providers in the registry */
4153 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4154 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4156 /* Hmmm. Does this mean that there are no service providers? */
4157 ERR(": no service providers?\n");
4158 return 0;
4161 /* Traverse all the service providers we have available */
4162 for( dwIndex=0;
4163 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4164 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4165 ++dwIndex, sizeOfSubKeyName=51 )
4168 HKEY hkServiceProvider;
4169 GUID serviceProviderGUID;
4170 DWORD returnType, sizeOfReturnBuffer = 255;
4171 char returnBuffer[256];
4172 WCHAR buff[51];
4173 DWORD dwTemp, len;
4175 TRACE(" this time through: %s\n", subKeyName );
4177 /* Get a handle for this particular service provider */
4178 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4179 &hkServiceProvider ) != ERROR_SUCCESS )
4181 ERR(": what the heck is going on?\n" );
4182 continue;
4185 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4186 NULL, &returnType, (LPBYTE)returnBuffer,
4187 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4189 ERR(": missing GUID registry data members\n" );
4190 continue;
4193 /* FIXME: Check return types to ensure we're interpreting data right */
4194 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4195 CLSIDFromString( buff, &serviceProviderGUID );
4196 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4198 /* Determine if this is the Service Provider that the user asked for */
4199 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
4201 continue;
4204 if( i == 0 ) /* DP SP */
4206 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
4207 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
4208 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
4211 sizeOfReturnBuffer = 255;
4213 /* Get dwReserved1 */
4214 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
4215 NULL, &returnType, (LPBYTE)returnBuffer,
4216 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4218 ERR(": missing dwReserved1 registry data members\n") ;
4219 continue;
4222 if( i == 0 )
4223 memcpy( &lpSpData->dwReserved1, returnBuffer, sizeof(lpSpData->dwReserved1) );
4225 sizeOfReturnBuffer = 255;
4227 /* Get dwReserved2 */
4228 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4229 NULL, &returnType, (LPBYTE)returnBuffer,
4230 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4232 ERR(": missing dwReserved1 registry data members\n") ;
4233 continue;
4236 if( i == 0 )
4237 memcpy( &lpSpData->dwReserved2, returnBuffer, sizeof(lpSpData->dwReserved2) );
4239 sizeOfReturnBuffer = 255;
4241 /* Get the path for this service provider */
4242 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
4243 NULL, NULL, (LPBYTE)returnBuffer,
4244 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
4246 ERR(": missing PATH registry data members: 0x%08x\n", dwTemp );
4247 continue;
4250 TRACE( "Loading %s\n", returnBuffer );
4251 return LoadLibraryA( returnBuffer );
4255 return 0;
4258 static
4259 HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider )
4261 HRESULT hr;
4262 LPDPSP_SPINIT SPInit;
4264 /* Initialize the service provider by calling SPInit */
4265 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4267 if( SPInit == NULL )
4269 ERR( "Service provider doesn't provide SPInit interface?\n" );
4270 FreeLibrary( hServiceProvider );
4271 return DPERR_UNAVAILABLE;
4274 TRACE( "Calling SPInit (DP SP entry point)\n" );
4276 hr = (*SPInit)( &This->dp2->spData );
4278 if( FAILED(hr) )
4280 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4281 FreeLibrary( hServiceProvider );
4282 return hr;
4285 /* FIXME: Need to verify the sanity of the returned callback table
4286 * using IsBadCodePtr */
4287 This->dp2->bSPInitialized = TRUE;
4289 /* This interface is now initialized as a DP object */
4290 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
4292 /* Store the handle of the module so that we can unload it later */
4293 This->dp2->hServiceProvider = hServiceProvider;
4295 return hr;
4298 static
4299 HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hLobbyProvider )
4301 HRESULT hr;
4302 LPSP_INIT DPLSPInit;
4304 /* Initialize the service provider by calling SPInit */
4305 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
4307 if( DPLSPInit == NULL )
4309 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4310 FreeLibrary( hLobbyProvider );
4311 return DPERR_UNAVAILABLE;
4314 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4316 hr = (*DPLSPInit)( &This->dp2->dplspData );
4318 if( FAILED(hr) )
4320 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4321 FreeLibrary( hLobbyProvider );
4322 return hr;
4325 /* FIXME: Need to verify the sanity of the returned callback table
4326 * using IsBadCodePtr */
4328 This->dp2->bDPLSPInitialized = TRUE;
4330 /* This interface is now initialized as a lobby object */
4331 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
4333 /* Store the handle of the module so that we can unload it later */
4334 This->dp2->hDPLobbyProvider = hLobbyProvider;
4336 return hr;
4339 static HRESULT DP_IF_InitializeConnection
4340 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi )
4342 HMODULE hServiceProvider;
4343 HRESULT hr;
4344 GUID guidSP;
4345 const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
4346 BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4348 TRACE("(%p)->(%p,0x%08x,%u)\n", This, lpConnection, dwFlags, bAnsi );
4350 if ( lpConnection == NULL )
4352 return DPERR_INVALIDPARAMS;
4355 if( dwFlags != 0 )
4357 return DPERR_INVALIDFLAGS;
4360 if( This->dp2->connectionInitialized != NO_PROVIDER )
4362 return DPERR_ALREADYINITIALIZED;
4365 /* Find out what the requested SP is and how large this buffer is */
4366 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
4367 dwAddrSize, &guidSP );
4369 if( FAILED(hr) )
4371 ERR( "Invalid compound address?\n" );
4372 return DPERR_UNAVAILABLE;
4375 /* Load the service provider */
4376 hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp );
4378 if( hServiceProvider == 0 )
4380 ERR( "Unable to load service provider %s\n", debugstr_guid(&guidSP) );
4381 return DPERR_UNAVAILABLE;
4384 if( bIsDpSp )
4386 /* Fill in what we can of the Service Provider required information.
4387 * The rest was be done in DP_LoadSP
4389 This->dp2->spData.lpAddress = lpConnection;
4390 This->dp2->spData.dwAddressSize = dwAddrSize;
4391 This->dp2->spData.lpGuid = &guidSP;
4393 hr = DP_InitializeDPSP( This, hServiceProvider );
4395 else
4397 This->dp2->dplspData.lpAddress = lpConnection;
4399 hr = DP_InitializeDPLSP( This, hServiceProvider );
4402 if( FAILED(hr) )
4404 return hr;
4407 return DP_OK;
4410 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4411 ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
4413 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4414 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE );
4417 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4418 ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
4420 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4421 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE );
4424 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4425 ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4426 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4428 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4429 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4432 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4433 ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4434 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4436 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4437 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4440 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4441 ( LPDIRECTPLAY3A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4443 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4444 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4445 return DP_OK;
4448 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4449 ( LPDIRECTPLAY3 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4451 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4452 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4453 return DP_OK;
4456 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4457 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4459 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4460 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4461 return DP_OK;
4464 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4465 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4467 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4468 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4469 return DP_OK;
4472 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4473 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup )
4475 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4476 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, dwFlags, idGroup );
4477 return DP_OK;
4480 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4481 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup )
4483 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4484 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, dwFlags, idGroup );
4485 return DP_OK;
4488 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4489 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDWORD lpdwFlags )
4491 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4492 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpdwFlags );
4493 return DP_OK;
4496 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4497 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDWORD lpdwFlags )
4499 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4500 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpdwFlags );
4501 return DP_OK;
4504 static HRESULT DP_IF_GetGroupParent
4505 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
4506 BOOL bAnsi )
4508 lpGroupData lpGData;
4510 TRACE("(%p)->(0x%08x,%p,%u)\n", This, idGroup, lpidGroup, bAnsi );
4512 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4514 return DPERR_INVALIDGROUP;
4517 *lpidGroup = lpGData->dpid;
4519 return DP_OK;
4522 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4523 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
4525 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4526 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE );
4528 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4529 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
4531 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4532 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE );
4535 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4536 ( LPDIRECTPLAY3A iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4538 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4539 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4540 return DP_OK;
4543 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4544 ( LPDIRECTPLAY3 iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4546 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4547 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4548 return DP_OK;
4551 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4552 ( LPDIRECTPLAY3A iface, DPID idPlayer, LPDWORD lpdwFlags )
4554 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4555 FIXME("(%p)->(0x%08x,%p): stub\n", This, idPlayer, lpdwFlags );
4556 return DP_OK;
4559 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4560 ( LPDIRECTPLAY3 iface, DPID idPlayer, LPDWORD lpdwFlags )
4562 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4563 FIXME("(%p)->(0x%08x,%p): stub\n", This, idPlayer, lpdwFlags );
4564 return DP_OK;
4567 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4568 ( LPDIRECTPLAY4A iface, DPID idGroup, LPDPID lpidGroupOwner )
4570 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4571 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpidGroupOwner );
4572 return DP_OK;
4575 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4576 ( LPDIRECTPLAY4 iface, DPID idGroup, LPDPID lpidGroupOwner )
4578 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4579 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpidGroupOwner );
4580 return DP_OK;
4583 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4584 ( LPDIRECTPLAY4A iface, DPID idGroup , DPID idGroupOwner )
4586 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4587 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, idGroup, idGroupOwner );
4588 return DP_OK;
4591 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4592 ( LPDIRECTPLAY4 iface, DPID idGroup , DPID idGroupOwner )
4594 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4595 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, idGroup, idGroupOwner );
4596 return DP_OK;
4599 static HRESULT DP_SendEx
4600 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4601 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4602 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi )
4604 BOOL bValidDestination = FALSE;
4606 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,0x%08x,0x%08x,0x%08x,%p,%p,%u)"
4607 ": stub\n",
4608 This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority,
4609 dwTimeout, lpContext, lpdwMsgID, bAnsi );
4611 if( This->dp2->connectionInitialized == NO_PROVIDER )
4613 return DPERR_UNINITIALIZED;
4616 /* FIXME: Add parameter checking */
4617 /* FIXME: First call to this needs to acquire a message id which will be
4618 * used for multiple sends
4621 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4623 /* Verify that the message is being sent from a valid local player. The
4624 * from player may be anonymous DPID_UNKNOWN
4626 if( idFrom != DPID_UNKNOWN )
4628 if( DP_FindPlayer( This, idFrom ) == NULL )
4630 WARN( "INFO: Invalid from player 0x%08x\n", idFrom );
4631 return DPERR_INVALIDPLAYER;
4635 /* Verify that the message is being sent to a valid player, group or to
4636 * everyone. If it's valid, send it to those players.
4638 if( idTo == DPID_ALLPLAYERS )
4640 bValidDestination = TRUE;
4642 /* See if SP has the ability to multicast. If so, use it */
4643 if( This->dp2->spData.lpCB->SendToGroupEx )
4645 FIXME( "Use group sendex to group 0\n" );
4647 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4649 FIXME( "Use obsolete group send to group 0\n" );
4651 else /* No multicast, multiplicate */
4653 /* Send to all players we know about */
4654 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4658 if( ( !bValidDestination ) &&
4659 ( DP_FindPlayer( This, idTo ) != NULL )
4662 bValidDestination = TRUE;
4664 /* Have the service provider send this message */
4665 /* FIXME: Could optimize for local interface sends */
4666 return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority,
4667 dwTimeout, lpContext, lpdwMsgID );
4670 if( ( !bValidDestination ) &&
4671 ( DP_FindAnyGroup( This, idTo ) != NULL )
4674 bValidDestination = TRUE;
4676 /* See if SP has the ability to multicast. If so, use it */
4677 if( This->dp2->spData.lpCB->SendToGroupEx )
4679 FIXME( "Use group sendex\n" );
4681 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4683 FIXME( "Use obsolete group send to group\n" );
4685 else /* No multicast, multiplicate */
4687 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4690 #if 0
4691 if( bExpectReply )
4693 DWORD dwWaitReturn;
4695 This->dp2->hReplyEvent = CreateEventW( NULL, FALSE, FALSE, NULL );
4697 dwWaitReturn = WaitForSingleObject( hReplyEvent, dwTimeout );
4698 if( dwWaitReturn != WAIT_OBJECT_0 )
4700 ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
4703 #endif
4706 if( !bValidDestination )
4708 return DPERR_INVALIDPLAYER;
4710 else
4712 /* FIXME: Should return what the send returned */
4713 return DP_OK;
4718 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4719 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4720 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4721 LPVOID lpContext, LPDWORD lpdwMsgID )
4723 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4724 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4725 dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE );
4728 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4729 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4730 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4731 LPVOID lpContext, LPDWORD lpdwMsgID )
4733 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4734 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4735 dwPriority, dwTimeout, lpContext, lpdwMsgID, FALSE );
4738 static HRESULT DP_SP_SendEx
4739 ( IDirectPlay2Impl* This, DWORD dwFlags,
4740 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4741 LPVOID lpContext, LPDWORD lpdwMsgID )
4743 LPDPMSG lpMElem;
4745 FIXME( ": stub\n" );
4747 /* FIXME: This queuing should only be for async messages */
4749 lpMElem = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpMElem ) );
4750 lpMElem->msg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
4752 CopyMemory( lpMElem->msg, lpData, dwDataSize );
4754 /* FIXME: Need to queue based on priority */
4755 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
4757 return DP_OK;
4760 static HRESULT DP_IF_GetMessageQueue
4761 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4762 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi )
4764 HRESULT hr = DP_OK;
4766 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%p,%u): semi stub\n",
4767 This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi );
4769 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4770 /* FIXME: What about sends which are not immediate? */
4772 if( This->dp2->spData.lpCB->GetMessageQueue )
4774 DPSP_GETMESSAGEQUEUEDATA data;
4776 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4778 /* FIXME: None of this is documented :( */
4780 data.lpISP = This->dp2->spData.lpISP;
4781 data.dwFlags = dwFlags;
4782 data.idFrom = idFrom;
4783 data.idTo = idTo;
4784 data.lpdwNumMsgs = lpdwNumMsgs;
4785 data.lpdwNumBytes = lpdwNumBytes;
4787 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
4789 else
4791 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4794 return hr;
4797 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4798 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4799 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4801 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4802 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4803 lpdwNumBytes, TRUE );
4806 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4807 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4808 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4810 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4811 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4812 lpdwNumBytes, FALSE );
4815 static HRESULT DP_IF_CancelMessage
4816 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
4817 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi )
4819 HRESULT hr = DP_OK;
4821 FIXME( "(%p)->(0x%08x,0x%08x,%u): semi stub\n",
4822 This, dwMsgID, dwFlags, bAnsi );
4824 if( This->dp2->spData.lpCB->Cancel )
4826 DPSP_CANCELDATA data;
4828 TRACE( "Calling SP Cancel\n" );
4830 /* FIXME: Undocumented callback */
4832 data.lpISP = This->dp2->spData.lpISP;
4833 data.dwFlags = dwFlags;
4834 data.lprglpvSPMsgID = NULL;
4835 data.cSPMsgID = dwMsgID;
4836 data.dwMinPriority = dwMinPriority;
4837 data.dwMaxPriority = dwMaxPriority;
4839 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
4841 else
4843 FIXME( "SP doesn't implement Cancel\n" );
4846 return hr;
4849 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
4850 ( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags )
4852 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4854 if( dwFlags != 0 )
4856 return DPERR_INVALIDFLAGS;
4859 if( dwMsgID == 0 )
4861 dwFlags |= DPCANCELSEND_ALL;
4864 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE );
4867 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
4868 ( LPDIRECTPLAY4 iface, DWORD dwMsgID, DWORD dwFlags )
4870 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4872 if( dwFlags != 0 )
4874 return DPERR_INVALIDFLAGS;
4877 if( dwMsgID == 0 )
4879 dwFlags |= DPCANCELSEND_ALL;
4882 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, FALSE );
4885 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
4886 ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4887 DWORD dwFlags )
4889 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4891 if( dwFlags != 0 )
4893 return DPERR_INVALIDFLAGS;
4896 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4897 dwMaxPriority, TRUE );
4900 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
4901 ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4902 DWORD dwFlags )
4904 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4906 if( dwFlags != 0 )
4908 return DPERR_INVALIDFLAGS;
4911 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4912 dwMaxPriority, FALSE );
4915 /* Note: Hack so we can reuse the old functions without compiler warnings */
4916 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4917 # define XCAST(fun) (typeof(directPlay2WVT.fun))
4918 #else
4919 # define XCAST(fun) (void*)
4920 #endif
4922 static const IDirectPlay2Vtbl directPlay2WVT =
4924 XCAST(QueryInterface)DP_QueryInterface,
4925 XCAST(AddRef)DP_AddRef,
4926 XCAST(Release)DP_Release,
4928 DirectPlay2WImpl_AddPlayerToGroup,
4929 DirectPlay2WImpl_Close,
4930 DirectPlay2WImpl_CreateGroup,
4931 DirectPlay2WImpl_CreatePlayer,
4932 DirectPlay2WImpl_DeletePlayerFromGroup,
4933 DirectPlay2WImpl_DestroyGroup,
4934 DirectPlay2WImpl_DestroyPlayer,
4935 DirectPlay2WImpl_EnumGroupPlayers,
4936 DirectPlay2WImpl_EnumGroups,
4937 DirectPlay2WImpl_EnumPlayers,
4938 DirectPlay2WImpl_EnumSessions,
4939 DirectPlay2WImpl_GetCaps,
4940 DirectPlay2WImpl_GetGroupData,
4941 DirectPlay2WImpl_GetGroupName,
4942 DirectPlay2WImpl_GetMessageCount,
4943 DirectPlay2WImpl_GetPlayerAddress,
4944 DirectPlay2WImpl_GetPlayerCaps,
4945 DirectPlay2WImpl_GetPlayerData,
4946 DirectPlay2WImpl_GetPlayerName,
4947 DirectPlay2WImpl_GetSessionDesc,
4948 DirectPlay2WImpl_Initialize,
4949 DirectPlay2WImpl_Open,
4950 DirectPlay2WImpl_Receive,
4951 DirectPlay2WImpl_Send,
4952 DirectPlay2WImpl_SetGroupData,
4953 DirectPlay2WImpl_SetGroupName,
4954 DirectPlay2WImpl_SetPlayerData,
4955 DirectPlay2WImpl_SetPlayerName,
4956 DirectPlay2WImpl_SetSessionDesc
4958 #undef XCAST
4960 /* Note: Hack so we can reuse the old functions without compiler warnings */
4961 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4962 # define XCAST(fun) (typeof(directPlay2AVT.fun))
4963 #else
4964 # define XCAST(fun) (void*)
4965 #endif
4967 static const IDirectPlay2Vtbl directPlay2AVT =
4969 XCAST(QueryInterface)DP_QueryInterface,
4970 XCAST(AddRef)DP_AddRef,
4971 XCAST(Release)DP_Release,
4973 DirectPlay2AImpl_AddPlayerToGroup,
4974 DirectPlay2AImpl_Close,
4975 DirectPlay2AImpl_CreateGroup,
4976 DirectPlay2AImpl_CreatePlayer,
4977 DirectPlay2AImpl_DeletePlayerFromGroup,
4978 DirectPlay2AImpl_DestroyGroup,
4979 DirectPlay2AImpl_DestroyPlayer,
4980 DirectPlay2AImpl_EnumGroupPlayers,
4981 DirectPlay2AImpl_EnumGroups,
4982 DirectPlay2AImpl_EnumPlayers,
4983 DirectPlay2AImpl_EnumSessions,
4984 DirectPlay2AImpl_GetCaps,
4985 DirectPlay2AImpl_GetGroupData,
4986 DirectPlay2AImpl_GetGroupName,
4987 DirectPlay2AImpl_GetMessageCount,
4988 DirectPlay2AImpl_GetPlayerAddress,
4989 DirectPlay2AImpl_GetPlayerCaps,
4990 DirectPlay2AImpl_GetPlayerData,
4991 DirectPlay2AImpl_GetPlayerName,
4992 DirectPlay2AImpl_GetSessionDesc,
4993 DirectPlay2AImpl_Initialize,
4994 DirectPlay2AImpl_Open,
4995 DirectPlay2AImpl_Receive,
4996 DirectPlay2AImpl_Send,
4997 DirectPlay2AImpl_SetGroupData,
4998 DirectPlay2AImpl_SetGroupName,
4999 DirectPlay2AImpl_SetPlayerData,
5000 DirectPlay2AImpl_SetPlayerName,
5001 DirectPlay2AImpl_SetSessionDesc
5003 #undef XCAST
5006 /* Note: Hack so we can reuse the old functions without compiler warnings */
5007 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5008 # define XCAST(fun) (typeof(directPlay3AVT.fun))
5009 #else
5010 # define XCAST(fun) (void*)
5011 #endif
5013 static const IDirectPlay3Vtbl directPlay3AVT =
5015 XCAST(QueryInterface)DP_QueryInterface,
5016 XCAST(AddRef)DP_AddRef,
5017 XCAST(Release)DP_Release,
5019 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
5020 XCAST(Close)DirectPlay2AImpl_Close,
5021 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
5022 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
5023 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
5024 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
5025 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
5026 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
5027 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
5028 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
5029 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
5030 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
5031 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
5032 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
5033 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5034 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5035 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5036 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5037 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5038 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5039 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5040 XCAST(Open)DirectPlay2AImpl_Open,
5041 XCAST(Receive)DirectPlay2AImpl_Receive,
5042 XCAST(Send)DirectPlay2AImpl_Send,
5043 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5044 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5045 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5046 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5047 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5049 DirectPlay3AImpl_AddGroupToGroup,
5050 DirectPlay3AImpl_CreateGroupInGroup,
5051 DirectPlay3AImpl_DeleteGroupFromGroup,
5052 DirectPlay3AImpl_EnumConnections,
5053 DirectPlay3AImpl_EnumGroupsInGroup,
5054 DirectPlay3AImpl_GetGroupConnectionSettings,
5055 DirectPlay3AImpl_InitializeConnection,
5056 DirectPlay3AImpl_SecureOpen,
5057 DirectPlay3AImpl_SendChatMessage,
5058 DirectPlay3AImpl_SetGroupConnectionSettings,
5059 DirectPlay3AImpl_StartSession,
5060 DirectPlay3AImpl_GetGroupFlags,
5061 DirectPlay3AImpl_GetGroupParent,
5062 DirectPlay3AImpl_GetPlayerAccount,
5063 DirectPlay3AImpl_GetPlayerFlags
5065 #undef XCAST
5067 /* Note: Hack so we can reuse the old functions without compiler warnings */
5068 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5069 # define XCAST(fun) (typeof(directPlay3WVT.fun))
5070 #else
5071 # define XCAST(fun) (void*)
5072 #endif
5073 static const IDirectPlay3Vtbl directPlay3WVT =
5075 XCAST(QueryInterface)DP_QueryInterface,
5076 XCAST(AddRef)DP_AddRef,
5077 XCAST(Release)DP_Release,
5079 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
5080 XCAST(Close)DirectPlay2WImpl_Close,
5081 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
5082 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
5083 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
5084 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
5085 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5086 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5087 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5088 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5089 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5090 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5091 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5092 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5093 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5094 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5095 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5096 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5097 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5098 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5099 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5100 XCAST(Open)DirectPlay2WImpl_Open,
5101 XCAST(Receive)DirectPlay2WImpl_Receive,
5102 XCAST(Send)DirectPlay2WImpl_Send,
5103 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5104 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5105 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5106 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5107 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5109 DirectPlay3WImpl_AddGroupToGroup,
5110 DirectPlay3WImpl_CreateGroupInGroup,
5111 DirectPlay3WImpl_DeleteGroupFromGroup,
5112 DirectPlay3WImpl_EnumConnections,
5113 DirectPlay3WImpl_EnumGroupsInGroup,
5114 DirectPlay3WImpl_GetGroupConnectionSettings,
5115 DirectPlay3WImpl_InitializeConnection,
5116 DirectPlay3WImpl_SecureOpen,
5117 DirectPlay3WImpl_SendChatMessage,
5118 DirectPlay3WImpl_SetGroupConnectionSettings,
5119 DirectPlay3WImpl_StartSession,
5120 DirectPlay3WImpl_GetGroupFlags,
5121 DirectPlay3WImpl_GetGroupParent,
5122 DirectPlay3WImpl_GetPlayerAccount,
5123 DirectPlay3WImpl_GetPlayerFlags
5125 #undef XCAST
5127 /* Note: Hack so we can reuse the old functions without compiler warnings */
5128 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5129 # define XCAST(fun) (typeof(directPlay4WVT.fun))
5130 #else
5131 # define XCAST(fun) (void*)
5132 #endif
5133 static const IDirectPlay4Vtbl directPlay4WVT =
5135 XCAST(QueryInterface)DP_QueryInterface,
5136 XCAST(AddRef)DP_AddRef,
5137 XCAST(Release)DP_Release,
5139 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
5140 XCAST(Close)DirectPlay2WImpl_Close,
5141 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
5142 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
5143 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
5144 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
5145 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5146 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5147 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5148 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5149 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5150 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5151 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5152 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5153 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5154 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5155 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5156 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5157 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5158 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5159 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5160 XCAST(Open)DirectPlay2WImpl_Open,
5161 XCAST(Receive)DirectPlay2WImpl_Receive,
5162 XCAST(Send)DirectPlay2WImpl_Send,
5163 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5164 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5165 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5166 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5167 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5169 XCAST(AddGroupToGroup)DirectPlay3WImpl_AddGroupToGroup,
5170 XCAST(CreateGroupInGroup)DirectPlay3WImpl_CreateGroupInGroup,
5171 XCAST(DeleteGroupFromGroup)DirectPlay3WImpl_DeleteGroupFromGroup,
5172 XCAST(EnumConnections)DirectPlay3WImpl_EnumConnections,
5173 XCAST(EnumGroupsInGroup)DirectPlay3WImpl_EnumGroupsInGroup,
5174 XCAST(GetGroupConnectionSettings)DirectPlay3WImpl_GetGroupConnectionSettings,
5175 XCAST(InitializeConnection)DirectPlay3WImpl_InitializeConnection,
5176 XCAST(SecureOpen)DirectPlay3WImpl_SecureOpen,
5177 XCAST(SendChatMessage)DirectPlay3WImpl_SendChatMessage,
5178 XCAST(SetGroupConnectionSettings)DirectPlay3WImpl_SetGroupConnectionSettings,
5179 XCAST(StartSession)DirectPlay3WImpl_StartSession,
5180 XCAST(GetGroupFlags)DirectPlay3WImpl_GetGroupFlags,
5181 XCAST(GetGroupParent)DirectPlay3WImpl_GetGroupParent,
5182 XCAST(GetPlayerAccount)DirectPlay3WImpl_GetPlayerAccount,
5183 XCAST(GetPlayerFlags)DirectPlay3WImpl_GetPlayerFlags,
5185 DirectPlay4WImpl_GetGroupOwner,
5186 DirectPlay4WImpl_SetGroupOwner,
5187 DirectPlay4WImpl_SendEx,
5188 DirectPlay4WImpl_GetMessageQueue,
5189 DirectPlay4WImpl_CancelMessage,
5190 DirectPlay4WImpl_CancelPriority
5192 #undef XCAST
5195 /* Note: Hack so we can reuse the old functions without compiler warnings */
5196 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5197 # define XCAST(fun) (typeof(directPlay4AVT.fun))
5198 #else
5199 # define XCAST(fun) (void*)
5200 #endif
5201 static const IDirectPlay4Vtbl directPlay4AVT =
5203 XCAST(QueryInterface)DP_QueryInterface,
5204 XCAST(AddRef)DP_AddRef,
5205 XCAST(Release)DP_Release,
5207 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
5208 XCAST(Close)DirectPlay2AImpl_Close,
5209 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
5210 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
5211 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
5212 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
5213 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
5214 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
5215 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
5216 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
5217 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
5218 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
5219 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
5220 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
5221 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5222 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5223 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5224 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5225 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5226 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5227 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5228 XCAST(Open)DirectPlay2AImpl_Open,
5229 XCAST(Receive)DirectPlay2AImpl_Receive,
5230 XCAST(Send)DirectPlay2AImpl_Send,
5231 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5232 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5233 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5234 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5235 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5237 XCAST(AddGroupToGroup)DirectPlay3AImpl_AddGroupToGroup,
5238 XCAST(CreateGroupInGroup)DirectPlay3AImpl_CreateGroupInGroup,
5239 XCAST(DeleteGroupFromGroup)DirectPlay3AImpl_DeleteGroupFromGroup,
5240 XCAST(EnumConnections)DirectPlay3AImpl_EnumConnections,
5241 XCAST(EnumGroupsInGroup)DirectPlay3AImpl_EnumGroupsInGroup,
5242 XCAST(GetGroupConnectionSettings)DirectPlay3AImpl_GetGroupConnectionSettings,
5243 XCAST(InitializeConnection)DirectPlay3AImpl_InitializeConnection,
5244 XCAST(SecureOpen)DirectPlay3AImpl_SecureOpen,
5245 XCAST(SendChatMessage)DirectPlay3AImpl_SendChatMessage,
5246 XCAST(SetGroupConnectionSettings)DirectPlay3AImpl_SetGroupConnectionSettings,
5247 XCAST(StartSession)DirectPlay3AImpl_StartSession,
5248 XCAST(GetGroupFlags)DirectPlay3AImpl_GetGroupFlags,
5249 XCAST(GetGroupParent)DirectPlay3AImpl_GetGroupParent,
5250 XCAST(GetPlayerAccount)DirectPlay3AImpl_GetPlayerAccount,
5251 XCAST(GetPlayerFlags)DirectPlay3AImpl_GetPlayerFlags,
5253 DirectPlay4AImpl_GetGroupOwner,
5254 DirectPlay4AImpl_SetGroupOwner,
5255 DirectPlay4AImpl_SendEx,
5256 DirectPlay4AImpl_GetMessageQueue,
5257 DirectPlay4AImpl_CancelMessage,
5258 DirectPlay4AImpl_CancelPriority
5260 #undef XCAST
5262 HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP,
5263 DPID idPlayer,
5264 LPVOID* lplpData )
5266 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5268 if( lpPlayer == NULL )
5270 return DPERR_INVALIDPLAYER;
5273 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
5275 return DP_OK;
5278 HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP,
5279 DPID idPlayer,
5280 LPVOID lpData )
5282 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5284 if( lpPlayer == NULL )
5286 return DPERR_INVALIDPLAYER;
5289 lpPlayer->lpPData->lpSPPlayerData = lpData;
5291 return DP_OK;
5294 /***************************************************************************
5295 * DirectPlayEnumerateAW
5297 * The pointer to the structure lpContext will be filled with the
5298 * appropriate data for each service offered by the OS. These services are
5299 * not necessarily available on this particular machine but are defined
5300 * as simple service providers under the "Service Providers" registry key.
5301 * This structure is then passed to lpEnumCallback for each of the different
5302 * services.
5304 * This API is useful only for applications written using DirectX3 or
5305 * worse. It is superseded by IDirectPlay3::EnumConnections which also
5306 * gives information on the actual connections.
5308 * defn of a service provider:
5309 * A dynamic-link library used by DirectPlay to communicate over a network.
5310 * The service provider contains all the network-specific code required
5311 * to send and receive messages. Online services and network operators can
5312 * supply service providers to use specialized hardware, protocols, communications
5313 * media, and network resources.
5316 static HRESULT DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA,
5317 LPDPENUMDPCALLBACKW lpEnumCallbackW,
5318 LPVOID lpContext)
5320 HKEY hkResult;
5321 static const WCHAR searchSubKey[] = {
5322 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
5323 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
5324 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
5325 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
5326 static const WCHAR guidKey[] = { 'G', 'u', 'i', 'd', 0 };
5327 static const WCHAR descW[] = { 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', 'W', 0 };
5329 DWORD dwIndex;
5330 FILETIME filetime;
5332 char *descriptionA = NULL;
5333 DWORD max_sizeOfDescriptionA = 0;
5334 WCHAR *descriptionW = NULL;
5335 DWORD max_sizeOfDescriptionW = 0;
5337 if (!lpEnumCallbackA && !lpEnumCallbackW)
5339 return DPERR_INVALIDPARAMS;
5342 /* Need to loop over the service providers in the registry */
5343 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, searchSubKey,
5344 0, KEY_READ, &hkResult) != ERROR_SUCCESS)
5346 /* Hmmm. Does this mean that there are no service providers? */
5347 ERR(": no service provider key in the registry - check your Wine installation !!!\n");
5348 return DPERR_GENERIC;
5351 /* Traverse all the service providers we have available */
5352 dwIndex = 0;
5353 while (1)
5355 WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */
5356 DWORD sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR);
5357 HKEY hkServiceProvider;
5358 GUID serviceProviderGUID;
5359 WCHAR guidKeyContent[(2 * 16) + 1 + 6 /* This corresponds to '{....-..-..-..-......}' */ ];
5360 DWORD sizeOfGuidKeyContent = sizeof(guidKeyContent);
5361 LONG ret_value;
5363 ret_value = RegEnumKeyExW(hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
5364 NULL, NULL, NULL, &filetime);
5365 if (ret_value == ERROR_NO_MORE_ITEMS)
5366 break;
5367 else if (ret_value != ERROR_SUCCESS)
5369 ERR(": could not enumerate on service provider key.\n");
5370 return DPERR_EXCEPTION;
5372 TRACE(" this time through sub-key %s.\n", debugstr_w(subKeyName));
5374 /* Open the key for this service provider */
5375 if (RegOpenKeyExW(hkResult, subKeyName, 0, KEY_READ, &hkServiceProvider) != ERROR_SUCCESS)
5377 ERR(": could not open registry key for service provider %s.\n", debugstr_w(subKeyName));
5378 continue;
5381 /* Get the GUID from the registry */
5382 if (RegQueryValueExW(hkServiceProvider, guidKey,
5383 NULL, NULL, (LPBYTE) guidKeyContent, &sizeOfGuidKeyContent) != ERROR_SUCCESS)
5385 ERR(": missing GUID registry data member for service provider %s.\n", debugstr_w(subKeyName));
5386 continue;
5388 if (sizeOfGuidKeyContent != sizeof(guidKeyContent))
5390 ERR(": invalid format for the GUID registry data member for service provider %s (%s).\n", debugstr_w(subKeyName), debugstr_w(guidKeyContent));
5391 continue;
5393 CLSIDFromString(guidKeyContent, &serviceProviderGUID );
5395 /* The enumeration will return FALSE if we are not to continue.
5397 * Note: on my windows box, major / minor version is 6 / 0 for all service providers
5398 * and have no relation to any of the two dwReserved1 and dwReserved2 keys.
5399 * I think that it simply means that they are in-line with DirectX 6.0
5401 if (lpEnumCallbackA)
5403 DWORD sizeOfDescription = 0;
5405 /* Note that this is the A case of this function, so use the A variant to get the description string */
5406 if (RegQueryValueExA(hkServiceProvider, "DescriptionA",
5407 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5409 ERR(": missing 'DescriptionA' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5410 continue;
5412 if (sizeOfDescription > max_sizeOfDescriptionA)
5414 HeapFree(GetProcessHeap(), 0, descriptionA);
5415 max_sizeOfDescriptionA = sizeOfDescription;
5417 descriptionA = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5418 RegQueryValueExA(hkServiceProvider, "DescriptionA",
5419 NULL, NULL, (LPBYTE) descriptionA, &sizeOfDescription);
5421 if (!lpEnumCallbackA(&serviceProviderGUID, descriptionA, 6, 0, lpContext))
5422 goto end;
5424 else
5426 DWORD sizeOfDescription = 0;
5428 if (RegQueryValueExW(hkServiceProvider, descW,
5429 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5431 ERR(": missing 'DescriptionW' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5432 continue;
5434 if (sizeOfDescription > max_sizeOfDescriptionW)
5436 HeapFree(GetProcessHeap(), 0, descriptionW);
5437 max_sizeOfDescriptionW = sizeOfDescription;
5439 descriptionW = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5440 RegQueryValueExW(hkServiceProvider, descW,
5441 NULL, NULL, (LPBYTE) descriptionW, &sizeOfDescription);
5443 if (!lpEnumCallbackW(&serviceProviderGUID, descriptionW, 6, 0, lpContext))
5444 goto end;
5447 dwIndex++;
5450 end:
5451 HeapFree(GetProcessHeap(), 0, descriptionA);
5452 HeapFree(GetProcessHeap(), 0, descriptionW);
5454 return DP_OK;
5457 /***************************************************************************
5458 * DirectPlayEnumerate [DPLAYX.9]
5459 * DirectPlayEnumerateA [DPLAYX.2]
5461 HRESULT WINAPI DirectPlayEnumerateA(LPDPENUMDPCALLBACKA lpEnumCallback, LPVOID lpContext )
5463 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5465 return DirectPlayEnumerateAW(lpEnumCallback, NULL, lpContext);
5468 /***************************************************************************
5469 * DirectPlayEnumerateW [DPLAYX.3]
5471 HRESULT WINAPI DirectPlayEnumerateW(LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5473 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5475 return DirectPlayEnumerateAW(NULL, lpEnumCallback, lpContext);
5478 typedef struct tagCreateEnum
5480 LPVOID lpConn;
5481 LPCGUID lpGuid;
5482 } CreateEnumData, *lpCreateEnumData;
5484 /* Find and copy the matching connection for the SP guid */
5485 static BOOL CALLBACK cbDPCreateEnumConnections(
5486 LPCGUID lpguidSP,
5487 LPVOID lpConnection,
5488 DWORD dwConnectionSize,
5489 LPCDPNAME lpName,
5490 DWORD dwFlags,
5491 LPVOID lpContext)
5493 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5495 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5497 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5499 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5500 dwConnectionSize );
5501 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5503 /* Found the record that we were looking for */
5504 return FALSE;
5507 /* Haven't found what were looking for yet */
5508 return TRUE;
5512 /***************************************************************************
5513 * DirectPlayCreate [DPLAYX.1]
5516 HRESULT WINAPI DirectPlayCreate
5517 ( LPGUID lpGUID, LPDIRECTPLAY *lplpDP, IUnknown *pUnk )
5519 HRESULT hr;
5520 LPDIRECTPLAY3A lpDP3A;
5521 CreateEnumData cbData;
5523 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5525 if( pUnk != NULL )
5527 return CLASS_E_NOAGGREGATION;
5530 if( (lplpDP == NULL) || (lpGUID == NULL) )
5532 return DPERR_INVALIDPARAMS;
5536 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5537 give them an IDirectPlay2A object and hope that doesn't cause problems */
5538 if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
5540 return DPERR_UNAVAILABLE;
5543 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
5545 /* The GUID_NULL means don't bind a service provider. Just return the
5546 interface as is */
5547 return DP_OK;
5550 /* Bind the desired service provider since lpGUID is non NULL */
5551 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
5553 /* We're going to use a DP3 interface */
5554 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
5555 (LPVOID*)&lpDP3A );
5556 if( FAILED(hr) )
5558 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
5559 return hr;
5562 cbData.lpConn = NULL;
5563 cbData.lpGuid = lpGUID;
5565 /* We were given a service provider, find info about it... */
5566 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
5567 &cbData, DPCONNECTION_DIRECTPLAY );
5568 if( ( FAILED(hr) ) ||
5569 ( cbData.lpConn == NULL )
5572 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
5573 IDirectPlayX_Release( lpDP3A );
5574 return DPERR_UNAVAILABLE;
5577 /* Initialize the service provider */
5578 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
5579 if( FAILED(hr) )
5581 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
5582 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5583 IDirectPlayX_Release( lpDP3A );
5584 return hr;
5587 /* Release our version of the interface now that we're done with it */
5588 IDirectPlayX_Release( lpDP3A );
5589 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5591 return DP_OK;