dplayx: Tests for EnumSessions.
[wine/gsoc_dplay.git] / dlls / dplayx / dplay.c
blob468b4391e228c131d98e6b97a3b7469760b84c00
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 WINAPI DP_IF_DeletePlayerFromGroup
90 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
91 DPID idPlayer, BOOL bAnsi );
92 static HRESULT WINAPI 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 WINAPI DP_IF_DestroyGroup
97 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi );
98 static HRESULT WINAPI DP_IF_DestroyPlayer
99 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi );
100 static HRESULT WINAPI DP_IF_EnumGroupPlayers
101 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
102 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
103 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
104 static HRESULT WINAPI DP_IF_EnumGroups
105 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
106 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
107 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
108 static HRESULT WINAPI DP_IF_EnumPlayers
109 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
110 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
111 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
112 static HRESULT WINAPI DP_IF_GetGroupData
113 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
114 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
115 static HRESULT WINAPI DP_IF_GetGroupName
116 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
117 LPDWORD lpdwDataSize, BOOL bAnsi );
118 static HRESULT WINAPI DP_IF_GetPlayerData
119 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
120 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
121 static HRESULT WINAPI DP_IF_GetPlayerName
122 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
123 LPDWORD lpdwDataSize, BOOL bAnsi );
124 static HRESULT WINAPI DP_IF_SetGroupName
125 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
126 DWORD dwFlags, BOOL bAnsi );
127 static HRESULT WINAPI DP_IF_SetPlayerData
128 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
129 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
130 static HRESULT WINAPI DP_IF_SetPlayerName
131 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
132 DWORD dwFlags, BOOL bAnsi );
133 static HRESULT WINAPI DP_IF_AddGroupToGroup
134 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
135 static HRESULT WINAPI 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 WINAPI 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 WINAPI DP_IF_AddPlayerToGroup
144 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
145 DPID idPlayer, BOOL bAnsi );
146 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
147 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
148 static HRESULT WINAPI DP_SetSessionDesc
149 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
150 DWORD dwFlags, BOOL bInitial, BOOL bAnsi );
151 static HRESULT WINAPI DP_SecureOpen
152 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
153 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
154 BOOL bAnsi );
155 static HRESULT WINAPI 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 WINAPI DP_IF_Receive
160 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
161 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi );
162 static HRESULT WINAPI DP_IF_GetMessageQueue
163 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
164 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi );
165 static HRESULT WINAPI 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 WINAPI DP_IF_SetGroupData
170 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
171 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
172 static HRESULT WINAPI DP_IF_GetPlayerCaps
173 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
174 DWORD dwFlags );
175 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi );
176 static HRESULT WINAPI DP_IF_CancelMessage
177 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
178 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi );
179 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
180 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
181 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
182 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
183 static HRESULT WINAPI DP_IF_GetGroupParent
184 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
185 BOOL bAnsi );
186 static HRESULT WINAPI DP_IF_GetCaps
187 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags );
188 static HRESULT WINAPI DP_IF_EnumSessions
189 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
190 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
191 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
192 static HRESULT WINAPI 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 WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
198 LPDWORD lpdwBufSize );
202 static inline DPID DP_NextObjectId(void);
203 static DPID DP_GetRemoteNextObjectId(void);
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 = (IDirectPlay2AImpl *)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 = (IDirectPlay2AImpl *)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 = (IDirectPlay2AImpl *)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 /* Function to delete the list of groups with this interface. Needs to
342 * delete the group and player lists associated with this group as well
343 * as the group data associated with this group. It should not delete
344 * player data as that is shared with the top player list and will be
345 * deleted with that.
347 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList );
348 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList )
350 DPQ_DELETEQ( elem->lpGData->groups, groups,
351 lpGroupList, cbDeleteElemFromHeap );
352 DPQ_DELETEQ( elem->lpGData->players, players,
353 lpPlayerList, cbDeleteElemFromHeap );
354 HeapFree( GetProcessHeap(), 0, elem->lpGData );
355 HeapFree( GetProcessHeap(), 0, elem );
358 /* Function to delete the list of players with this interface. Needs to
359 * delete the player data for all players as well.
361 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList );
362 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList )
364 HeapFree( GetProcessHeap(), 0, elem->lpPData );
365 HeapFree( GetProcessHeap(), 0, elem );
368 static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
370 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;
372 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
374 TerminateThread( This->dp2->hEnumSessionThread, 0 );
375 CloseHandle( This->dp2->hEnumSessionThread );
378 /* Finish with the SP - have it shutdown */
379 if( This->dp2->spData.lpCB->ShutdownEx )
381 DPSP_SHUTDOWNDATA data;
383 TRACE( "Calling SP ShutdownEx\n" );
385 data.lpISP = This->dp2->spData.lpISP;
387 (*This->dp2->spData.lpCB->ShutdownEx)( &data );
389 else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
391 TRACE( "Calling obsolete SP Shutdown\n" );
392 (*This->dp2->spData.lpCB->Shutdown)();
395 /* Unload the SP (if it exists) */
396 if( This->dp2->hServiceProvider != 0 )
398 FreeLibrary( This->dp2->hServiceProvider );
401 /* Unload the Lobby Provider (if it exists) */
402 if( This->dp2->hDPLobbyProvider != 0 )
404 FreeLibrary( This->dp2->hDPLobbyProvider );
407 #if 0
408 DPQ_DELETEQ( This->dp2->players, players, lpPlayerList, cbDeletePlayerElem );
409 DPQ_DELETEQ( This->dp2->groups, groups, lpGroupList, cbDeleteGroupsElem );
410 #endif
412 /* FIXME: Need to delete receive and send msgs queue contents */
414 NS_DeleteSessionCache( This->dp2->lpNameServerData );
416 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
418 IDirectPlaySP_Release( This->dp2->spData.lpISP );
420 /* Delete the contents */
421 HeapFree( GetProcessHeap(), 0, This->dp2 );
423 return TRUE;
426 static BOOL DP_CreateDirectPlay3( LPVOID lpDP )
428 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;
430 This->dp3 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp3) ) );
431 if ( This->dp3 == NULL )
433 return FALSE;
436 return TRUE;
439 static BOOL DP_DestroyDirectPlay3( LPVOID lpDP )
441 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;
443 /* Delete the contents */
444 HeapFree( GetProcessHeap(), 0, This->dp3 );
446 return TRUE;
449 static BOOL DP_CreateDirectPlay4( LPVOID lpDP )
451 IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)lpDP;
453 This->dp4 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp4) ) );
454 if ( This->dp4 == NULL )
456 return FALSE;
459 return TRUE;
462 static BOOL DP_DestroyDirectPlay4( LPVOID lpDP )
464 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;
466 /* Delete the contents */
467 HeapFree( GetProcessHeap(), 0, This->dp4 );
469 return TRUE;
473 /* Create a new interface */
474 HRESULT DP_CreateInterface
475 ( REFIID riid, LPVOID* ppvObj )
477 TRACE( " for %s\n", debugstr_guid( riid ) );
479 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
480 sizeof( IDirectPlay2Impl ) );
482 if( *ppvObj == NULL )
484 return DPERR_OUTOFMEMORY;
487 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
489 IDirectPlay2Impl *This = (IDirectPlay2Impl *)*ppvObj;
490 This->lpVtbl = &directPlay2WVT;
492 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
494 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)*ppvObj;
495 This->lpVtbl = &directPlay2AVT;
497 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
499 IDirectPlay3Impl *This = (IDirectPlay3Impl *)*ppvObj;
500 This->lpVtbl = &directPlay3WVT;
502 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
504 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)*ppvObj;
505 This->lpVtbl = &directPlay3AVT;
507 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
509 IDirectPlay4Impl *This = (IDirectPlay4Impl *)*ppvObj;
510 This->lpVtbl = &directPlay4WVT;
512 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
514 IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)*ppvObj;
515 This->lpVtbl = &directPlay4AVT;
517 else
519 /* Unsupported interface */
520 HeapFree( GetProcessHeap(), 0, *ppvObj );
521 *ppvObj = NULL;
523 return E_NOINTERFACE;
526 /* Initialize it */
527 if ( DP_CreateIUnknown( *ppvObj ) &&
528 DP_CreateDirectPlay2( *ppvObj ) &&
529 DP_CreateDirectPlay3( *ppvObj ) &&
530 DP_CreateDirectPlay4( *ppvObj )
533 IDirectPlayX_AddRef( (LPDIRECTPLAY2A)*ppvObj );
535 return S_OK;
538 /* Initialize failed, destroy it */
539 DP_DestroyDirectPlay4( *ppvObj );
540 DP_DestroyDirectPlay3( *ppvObj );
541 DP_DestroyDirectPlay2( *ppvObj );
542 DP_DestroyIUnknown( *ppvObj );
544 HeapFree( GetProcessHeap(), 0, *ppvObj );
546 *ppvObj = NULL;
547 return DPERR_NOMEMORY;
551 /* Direct Play methods */
553 /* Shared between all dplay types */
554 static HRESULT WINAPI DP_QueryInterface
555 ( LPDIRECTPLAY2 iface, REFIID riid, LPVOID* ppvObj )
557 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
558 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
560 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
561 sizeof( *This ) );
563 if( *ppvObj == NULL )
565 return DPERR_OUTOFMEMORY;
568 CopyMemory( *ppvObj, This, sizeof( *This ) );
569 (*(IDirectPlay2Impl**)ppvObj)->ulInterfaceRef = 0;
571 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
573 IDirectPlay2Impl *This = (IDirectPlay2Impl *)*ppvObj;
574 This->lpVtbl = &directPlay2WVT;
576 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
578 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)*ppvObj;
579 This->lpVtbl = &directPlay2AVT;
581 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
583 IDirectPlay3Impl *This = (IDirectPlay3Impl *)*ppvObj;
584 This->lpVtbl = &directPlay3WVT;
586 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
588 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)*ppvObj;
589 This->lpVtbl = &directPlay3AVT;
591 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
593 IDirectPlay4Impl *This = (IDirectPlay4Impl *)*ppvObj;
594 This->lpVtbl = &directPlay4WVT;
596 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
598 IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)*ppvObj;
599 This->lpVtbl = &directPlay4AVT;
601 else
603 /* Unsupported interface */
604 HeapFree( GetProcessHeap(), 0, *ppvObj );
605 *ppvObj = NULL;
607 return E_NOINTERFACE;
610 IDirectPlayX_AddRef( (LPDIRECTPLAY2)*ppvObj );
612 return S_OK;
615 /* Shared between all dplay types */
616 static ULONG WINAPI DP_AddRef
617 ( LPDIRECTPLAY3 iface )
619 ULONG ulInterfaceRefCount, ulObjRefCount;
620 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
622 ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
623 ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
625 TRACE( "ref count incremented to %u:%u for %p\n",
626 ulInterfaceRefCount, ulObjRefCount, This );
628 return ulObjRefCount;
631 static ULONG WINAPI DP_Release
632 ( LPDIRECTPLAY3 iface )
634 ULONG ulInterfaceRefCount, ulObjRefCount;
636 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
638 ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
639 ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
641 TRACE( "ref count decremented to %u:%u for %p\n",
642 ulInterfaceRefCount, ulObjRefCount, This );
644 /* Deallocate if this is the last reference to the object */
645 if( ulObjRefCount == 0 )
647 /* If we're destroying the object, this must be the last ref
648 of the last interface */
649 DP_DestroyDirectPlay4( This );
650 DP_DestroyDirectPlay3( This );
651 DP_DestroyDirectPlay2( This );
652 DP_DestroyIUnknown( This );
655 /* Deallocate the interface */
656 if( ulInterfaceRefCount == 0 )
658 HeapFree( GetProcessHeap(), 0, This );
661 return ulObjRefCount;
664 static inline DPID DP_NextObjectId(void)
666 return (DPID)InterlockedIncrement( &kludgePlayerGroupId );
669 /* *lplpReply will be non NULL iff there is something to reply */
670 HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpcMessageBody,
671 DWORD dwMessageBodySize, LPCVOID lpcMessageHeader,
672 WORD wCommandId, WORD wVersion,
673 LPVOID* lplpReply, LPDWORD lpdwMsgSize )
675 TRACE( "(%p)->(%p,0x%08x,%p,%u,%u)\n",
676 This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId,
677 wVersion );
679 switch( wCommandId )
681 /* Name server needs to handle this request */
682 case DPMSGCMD_ENUMSESSIONSREQUEST:
684 /* Reply expected */
685 NS_ReplyToEnumSessionsRequest( lpcMessageBody, lplpReply, lpdwMsgSize, This );
687 break;
690 /* Name server needs to handle this request */
691 case DPMSGCMD_ENUMSESSIONSREPLY:
693 /* No reply expected */
694 NS_AddRemoteComputerAsNameServer( lpcMessageHeader,
695 This->dp2->spData.dwSPHeaderSize,
696 lpcMessageBody,
697 This->dp2->lpNameServerData );
698 break;
701 case DPMSGCMD_REQUESTNEWPLAYERID:
703 LPCDPMSG_REQUESTNEWPLAYERID lpcMsg =
704 (LPCDPMSG_REQUESTNEWPLAYERID)lpcMessageBody;
706 LPDPMSG_NEWPLAYERIDREPLY lpReply;
708 *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
710 *lplpReply = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, *lpdwMsgSize );
712 FIXME( "Ignoring dwFlags 0x%08x in request msg\n",
713 lpcMsg->dwFlags );
715 /* Setup the reply */
716 lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) +
717 This->dp2->spData.dwSPHeaderSize );
719 lpReply->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
720 lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY;
721 lpReply->envelope.wVersion = DPMSGVER_DP6;
723 lpReply->dpidNewPlayerId = DP_NextObjectId();
725 TRACE( "Allocating new playerid 0x%08x from remote request\n",
726 lpReply->dpidNewPlayerId );
728 break;
731 case DPMSGCMD_GETNAMETABLEREPLY:
732 case DPMSGCMD_NEWPLAYERIDREPLY:
735 #if 0
736 if( wCommandId == DPMSGCMD_NEWPLAYERIDREPLY )
737 DebugBreak();
738 #endif
739 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
741 break;
744 #if 1
745 case DPMSGCMD_JUSTENVELOPE:
747 TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08x\n", lpcMessageHeader, ((const DWORD *)lpcMessageHeader)[1] );
748 NS_SetLocalAddr( This->dp2->lpNameServerData, lpcMessageHeader, 20 );
749 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
751 #endif
753 case DPMSGCMD_FORWARDADDPLAYER:
755 #if 0
756 DebugBreak();
757 #endif
758 #if 1
759 TRACE( "Sending message to self to get my addr\n" );
760 DP_MSG_ToSelf( This, 1 ); /* This is a hack right now */
761 #endif
762 break;
765 case DPMSGCMD_FORWARDADDPLAYERNACK:
767 DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
768 break;
771 default:
773 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
774 DebugBreak();
775 break;
779 /* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */
781 return DP_OK;
785 static HRESULT WINAPI DP_IF_AddPlayerToGroup
786 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
787 DPID idPlayer, BOOL bAnsi )
789 lpGroupData lpGData;
790 lpPlayerList lpPList;
791 lpPlayerList lpNewPList;
793 TRACE( "(%p)->(%p,0x%08x,0x%08x,%u)\n",
794 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
796 /* Find the group */
797 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
799 return DPERR_INVALIDGROUP;
802 /* Find the player */
803 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
805 return DPERR_INVALIDPLAYER;
808 /* Create a player list (ie "shortcut" ) */
809 lpNewPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewPList ) );
810 if( lpNewPList == NULL )
812 return DPERR_CANTADDPLAYER;
815 /* Add the shortcut */
816 lpPList->lpPData->uRef++;
817 lpNewPList->lpPData = lpPList->lpPData;
819 /* Add the player to the list of players for this group */
820 DPQ_INSERT(lpGData->players,lpNewPList,players);
822 /* Let the SP know that we've added a player to the group */
823 if( This->dp2->spData.lpCB->AddPlayerToGroup )
825 DPSP_ADDPLAYERTOGROUPDATA data;
827 TRACE( "Calling SP AddPlayerToGroup\n" );
829 data.idPlayer = idPlayer;
830 data.idGroup = idGroup;
831 data.lpISP = This->dp2->spData.lpISP;
833 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
836 /* Inform all other peers of the addition of player to the group. If there are
837 * no peers keep this event quiet.
838 * Also, if this event was the result of another machine sending it to us,
839 * don't bother rebroadcasting it.
841 if( ( lpMsgHdr == NULL ) &&
842 This->dp2->lpSessionDesc &&
843 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
845 DPMSG_ADDPLAYERTOGROUP msg;
846 msg.dwType = DPSYS_ADDPLAYERTOGROUP;
848 msg.dpIdGroup = idGroup;
849 msg.dpIdPlayer = idPlayer;
851 /* FIXME: Correct to just use send effectively? */
852 /* FIXME: Should size include data w/ message or just message "header" */
853 /* FIXME: Check return code */
854 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
857 return DP_OK;
860 static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
861 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
863 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
864 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, TRUE );
867 static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
868 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
870 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
871 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, FALSE );
874 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi )
876 HRESULT hr = DP_OK;
878 TRACE("(%p)->(%u)\n", This, bAnsi );
880 /* FIXME: Need to find a new host I assume (how?) */
881 /* FIXME: Need to destroy all local groups */
882 /* FIXME: Need to migrate all remotely visible players to the new host */
884 /* Invoke the SP callback to inform of session close */
885 if( This->dp2->spData.lpCB->CloseEx )
887 DPSP_CLOSEDATA data;
889 TRACE( "Calling SP CloseEx\n" );
891 data.lpISP = This->dp2->spData.lpISP;
893 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
896 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
898 TRACE( "Calling SP Close (obsolete interface)\n" );
900 hr = (*This->dp2->spData.lpCB->Close)();
903 return hr;
906 static HRESULT WINAPI DirectPlay2AImpl_Close
907 ( LPDIRECTPLAY2A iface )
909 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
910 return DP_IF_Close( This, TRUE );
913 static HRESULT WINAPI DirectPlay2WImpl_Close
914 ( LPDIRECTPLAY2 iface )
916 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
917 return DP_IF_Close( This, FALSE );
920 static
921 lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, const DPID *lpid,
922 const DPNAME *lpName, DWORD dwFlags,
923 DPID idParent, BOOL bAnsi )
925 lpGroupData lpGData;
927 /* Allocate the new space and add to end of high level group list */
928 lpGData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGData ) );
930 if( lpGData == NULL )
932 return NULL;
935 DPQ_INIT(lpGData->groups);
936 DPQ_INIT(lpGData->players);
938 /* Set the desired player ID - no sanity checking to see if it exists */
939 lpGData->dpid = *lpid;
941 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
943 /* FIXME: Should we check that the parent exists? */
944 lpGData->parent = idParent;
946 /* FIXME: Should we validate the dwFlags? */
947 lpGData->dwFlags = dwFlags;
949 TRACE( "Created group id 0x%08x\n", *lpid );
951 return lpGData;
954 /* This method assumes that all links to it are already deleted */
955 static void
956 DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid )
958 lpGroupList lpGList;
960 TRACE( "(%p)->(0x%08x)\n", This, dpid );
962 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
964 if( lpGList == NULL )
966 ERR( "DPID 0x%08x not found\n", dpid );
967 return;
970 if( --(lpGList->lpGData->uRef) )
972 FIXME( "Why is this not the last reference to group?\n" );
973 DebugBreak();
976 /* Delete player */
977 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
978 HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
980 /* Remove and Delete Player List object */
981 HeapFree( GetProcessHeap(), 0, lpGList );
985 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid )
987 lpGroupList lpGroups;
989 TRACE( "(%p)->(0x%08x)\n", This, dpid );
991 if( dpid == DPID_SYSTEM_GROUP )
993 return This->dp2->lpSysGroup;
995 else
997 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
1000 if( lpGroups == NULL )
1002 return NULL;
1005 return lpGroups->lpGData;
1008 static HRESULT WINAPI DP_IF_CreateGroup
1009 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
1010 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
1011 DWORD dwFlags, BOOL bAnsi )
1013 lpGroupData lpGData;
1015 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1016 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
1017 dwFlags, bAnsi );
1019 /* If the name is not specified, we must provide one */
1020 if( DPID_UNKNOWN == *lpidGroup )
1022 /* If we are the name server, we decide on the group ids. If not, we
1023 * must ask for one before attempting a creation.
1025 if( This->dp2->bHostInterface )
1027 *lpidGroup = DP_NextObjectId();
1029 else
1031 *lpidGroup = DP_GetRemoteNextObjectId();
1035 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
1036 DPID_NOPARENT_GROUP, bAnsi );
1038 if( lpGData == NULL )
1040 return DPERR_CANTADDPLAYER; /* yes player not group */
1043 if( DPID_SYSTEM_GROUP == *lpidGroup )
1045 This->dp2->lpSysGroup = lpGData;
1046 TRACE( "Inserting system group\n" );
1048 else
1050 /* Insert into the system group */
1051 lpGroupList lpGroup = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGroup ) );
1052 lpGroup->lpGData = lpGData;
1054 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
1057 /* Something is now referencing this data */
1058 lpGData->uRef++;
1060 /* Set all the important stuff for the group */
1061 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
1063 /* FIXME: We should only create the system group if GetCaps returns
1064 * DPCAPS_GROUPOPTIMIZED.
1067 /* Let the SP know that we've created this group */
1068 if( This->dp2->spData.lpCB->CreateGroup )
1070 DPSP_CREATEGROUPDATA data;
1071 DWORD dwCreateFlags = 0;
1073 TRACE( "Calling SP CreateGroup\n" );
1075 if( *lpidGroup == DPID_NOPARENT_GROUP )
1076 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
1078 if( lpMsgHdr == NULL )
1079 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1081 if( dwFlags & DPGROUP_HIDDEN )
1082 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
1084 data.idGroup = *lpidGroup;
1085 data.dwFlags = dwCreateFlags;
1086 data.lpSPMessageHeader = lpMsgHdr;
1087 data.lpISP = This->dp2->spData.lpISP;
1089 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1092 /* Inform all other peers of the creation of a new group. If there are
1093 * no peers keep this event quiet.
1094 * Also if this message was sent to us, don't rebroadcast.
1096 if( ( lpMsgHdr == NULL ) &&
1097 This->dp2->lpSessionDesc &&
1098 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1100 DPMSG_CREATEPLAYERORGROUP msg;
1101 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1103 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1104 msg.dpId = *lpidGroup;
1105 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1106 msg.lpData = lpData;
1107 msg.dwDataSize = dwDataSize;
1108 msg.dpnName = *lpGroupName;
1109 msg.dpIdParent = DPID_NOPARENT_GROUP;
1110 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
1112 /* FIXME: Correct to just use send effectively? */
1113 /* FIXME: Should size include data w/ message or just message "header" */
1114 /* FIXME: Check return code */
1115 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
1116 0, 0, NULL, NULL, bAnsi );
1119 return DP_OK;
1122 static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
1123 ( LPDIRECTPLAY2A iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1124 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1126 *lpidGroup = DPID_UNKNOWN;
1128 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1129 lpGroupName, lpData, dwDataSize, dwFlags, TRUE );
1132 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
1133 ( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1134 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1136 *lpidGroup = DPID_UNKNOWN;
1138 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1139 lpGroupName, lpData, dwDataSize, dwFlags, FALSE );
1143 static void
1144 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
1145 LPVOID lpData, DWORD dwDataSize )
1147 /* Clear out the data with this player */
1148 if( dwFlags & DPSET_LOCAL )
1150 if ( lpGData->dwLocalDataSize != 0 )
1152 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
1153 lpGData->lpLocalData = NULL;
1154 lpGData->dwLocalDataSize = 0;
1157 else
1159 if( lpGData->dwRemoteDataSize != 0 )
1161 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
1162 lpGData->lpRemoteData = NULL;
1163 lpGData->dwRemoteDataSize = 0;
1167 /* Reallocate for new data */
1168 if( lpData != NULL )
1170 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1171 sizeof( dwDataSize ) );
1172 CopyMemory( lpNewData, lpData, dwDataSize );
1174 if( dwFlags & DPSET_LOCAL )
1176 lpGData->lpLocalData = lpData;
1177 lpGData->dwLocalDataSize = dwDataSize;
1179 else
1181 lpGData->lpRemoteData = lpNewData;
1182 lpGData->dwRemoteDataSize = dwDataSize;
1188 /* This function will just create the storage for the new player. */
1189 static
1190 lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid,
1191 LPDPNAME lpName, DWORD dwFlags,
1192 HANDLE hEvent, BOOL bAnsi )
1194 lpPlayerData lpPData;
1196 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
1198 /* Allocate the storage for the player and associate it with list element */
1199 lpPData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPData ) );
1200 if( lpPData == NULL )
1202 return NULL;
1205 /* Set the desired player ID */
1206 lpPData->dpid = *lpid;
1208 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
1210 lpPData->dwFlags = dwFlags;
1212 /* If we were given an event handle, duplicate it */
1213 if( hEvent != 0 )
1215 if( !DuplicateHandle( GetCurrentProcess(), hEvent,
1216 GetCurrentProcess(), &lpPData->hEvent,
1217 0, FALSE, DUPLICATE_SAME_ACCESS )
1220 /* FIXME: Memory leak */
1221 ERR( "Can't duplicate player msg handle %p\n", hEvent );
1225 /* Initialize the SP data section */
1226 lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData();
1228 TRACE( "Created player id 0x%08x\n", *lpid );
1230 if( ~dwFlags & DPLAYI_PLAYER_SYSPLAYER )
1231 This->dp2->lpSessionDesc->dwCurrentPlayers++;
1233 return lpPData;
1236 /* Delete the contents of the DPNAME struct */
1237 static void
1238 DP_DeleteDPNameStruct( LPDPNAME lpDPName )
1240 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u1.lpszShortNameA );
1241 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u2.lpszLongNameA );
1244 /* This method assumes that all links to it are already deleted */
1245 static void
1246 DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid )
1248 lpPlayerList lpPList;
1250 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1252 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1254 if( lpPList == NULL )
1256 ERR( "DPID 0x%08x not found\n", dpid );
1257 return;
1260 /* Verify that this is the last reference to the data */
1261 if( --(lpPList->lpPData->uRef) )
1263 FIXME( "Why is this not the last reference to player?\n" );
1264 DebugBreak();
1267 /* Delete player */
1268 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1270 CloseHandle( lpPList->lpPData->hEvent );
1271 HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
1273 /* Delete Player List object */
1274 HeapFree( GetProcessHeap(), 0, lpPList );
1277 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid )
1279 lpPlayerList lpPlayers;
1281 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1283 if(This->dp2->lpSysGroup == NULL)
1284 return NULL;
1286 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1288 return lpPlayers;
1291 /* Basic area for Dst must already be allocated */
1292 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, const DPNAME *lpSrc, BOOL bAnsi )
1294 if( lpSrc == NULL )
1296 ZeroMemory( lpDst, sizeof( *lpDst ) );
1297 lpDst->dwSize = sizeof( *lpDst );
1298 return TRUE;
1301 if( lpSrc->dwSize != sizeof( *lpSrc) )
1303 return FALSE;
1306 /* Delete any existing pointers */
1307 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1308 HeapFree( GetProcessHeap(), 0, lpDst->u2.lpszLongNameA );
1310 /* Copy as required */
1311 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1313 if( bAnsi )
1315 if( lpSrc->u1.lpszShortNameA )
1317 lpDst->u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), 0,
1318 strlen(lpSrc->u1.lpszShortNameA)+1 );
1319 strcpy( lpDst->u1.lpszShortNameA, lpSrc->u1.lpszShortNameA );
1321 if( lpSrc->u2.lpszLongNameA )
1323 lpDst->u2.lpszLongNameA = HeapAlloc( GetProcessHeap(), 0,
1324 strlen(lpSrc->u2.lpszLongNameA)+1 );
1325 strcpy( lpDst->u2.lpszLongNameA, lpSrc->u2.lpszLongNameA );
1328 else
1330 if( lpSrc->u1.lpszShortNameA )
1332 lpDst->u1.lpszShortName = HeapAlloc( GetProcessHeap(), 0,
1333 (strlenW(lpSrc->u1.lpszShortName)+1)*sizeof(WCHAR) );
1334 strcpyW( lpDst->u1.lpszShortName, lpSrc->u1.lpszShortName );
1336 if( lpSrc->u2.lpszLongNameA )
1338 lpDst->u2.lpszLongName = HeapAlloc( GetProcessHeap(), 0,
1339 (strlenW(lpSrc->u2.lpszLongName)+1)*sizeof(WCHAR) );
1340 strcpyW( lpDst->u2.lpszLongName, lpSrc->u2.lpszLongName );
1344 return TRUE;
1347 static void
1348 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
1349 LPVOID lpData, DWORD dwDataSize )
1351 /* Clear out the data with this player */
1352 if( dwFlags & DPSET_LOCAL )
1354 if ( lpPData->dwLocalDataSize != 0 )
1356 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
1357 lpPData->lpLocalData = NULL;
1358 lpPData->dwLocalDataSize = 0;
1361 else
1363 if( lpPData->dwRemoteDataSize != 0 )
1365 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
1366 lpPData->lpRemoteData = NULL;
1367 lpPData->dwRemoteDataSize = 0;
1371 /* Reallocate for new data */
1372 if( lpData != NULL )
1374 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1375 sizeof( dwDataSize ) );
1376 CopyMemory( lpNewData, lpData, dwDataSize );
1378 if( dwFlags & DPSET_LOCAL )
1380 lpPData->lpLocalData = lpData;
1381 lpPData->dwLocalDataSize = dwDataSize;
1383 else
1385 lpPData->lpRemoteData = lpNewData;
1386 lpPData->dwRemoteDataSize = dwDataSize;
1392 static HRESULT WINAPI DP_IF_CreatePlayer
1393 ( IDirectPlay2Impl* This,
1394 LPVOID lpMsgHdr, /* NULL for local creation, non NULL for remote creation */
1395 LPDPID lpidPlayer,
1396 LPDPNAME lpPlayerName,
1397 HANDLE hEvent,
1398 LPVOID lpData,
1399 DWORD dwDataSize,
1400 DWORD dwFlags,
1401 BOOL bAnsi )
1403 HRESULT hr = DP_OK;
1404 lpPlayerData lpPData;
1405 lpPlayerList lpPList;
1406 DWORD dwCreateFlags = 0;
1408 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1409 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1410 dwDataSize, dwFlags, bAnsi );
1411 if( This->dp2->connectionInitialized == NO_PROVIDER )
1413 return DPERR_UNINITIALIZED;
1416 if( dwFlags == 0 )
1418 dwFlags = DPPLAYER_SPECTATOR;
1421 if( lpidPlayer == NULL )
1423 return DPERR_INVALIDPARAMS;
1427 /* Determine the creation flags for the player. These will be passed
1428 * to the name server if requesting a player id and to the SP when
1429 * informing it of the player creation
1432 if( dwFlags & DPPLAYER_SERVERPLAYER )
1434 if( *lpidPlayer == DPID_SERVERPLAYER )
1436 /* Server player for the host interface */
1437 dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
1439 else if( *lpidPlayer == DPID_NAME_SERVER )
1441 /* Name server - master of everything */
1442 dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
1444 else
1446 /* Server player for a non host interface */
1447 dwCreateFlags |= DPLAYI_PLAYER_SYSPLAYER;
1451 if( lpMsgHdr == NULL )
1452 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1455 /* Verify we know how to handle all the flags */
1456 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1457 ( dwFlags & DPPLAYER_SPECTATOR )
1461 /* Assume non fatal failure */
1462 ERR( "unknown dwFlags = 0x%08x\n", dwFlags );
1465 /* If the name is not specified, we must provide one */
1466 if( *lpidPlayer == DPID_UNKNOWN )
1468 /* If we are the session master, we dish out the group/player ids */
1469 if( This->dp2->bHostInterface )
1471 *lpidPlayer = DP_NextObjectId();
1473 else
1475 hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer );
1477 if( FAILED(hr) )
1479 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1480 return hr;
1484 else
1486 /* FIXME: Would be nice to perhaps verify that we don't already have
1487 * this player.
1491 /* We pass creation flags, so we can distinguish sysplayers and not count them in the current
1492 player total */
1493 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwCreateFlags,
1494 hEvent, bAnsi );
1496 if( lpPData == NULL )
1498 return DPERR_CANTADDPLAYER;
1501 /* Create the list object and link it in */
1502 lpPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPList ) );
1503 if( lpPList == NULL )
1505 FIXME( "Memory leak\n" );
1506 return DPERR_CANTADDPLAYER;
1509 lpPData->uRef = 1;
1510 lpPList->lpPData = lpPData;
1512 /* Add the player to the system group */
1513 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1515 /* Update the information and send it to all players in the session */
1516 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
1518 /* Let the SP know that we've created this player */
1519 if( This->dp2->spData.lpCB->CreatePlayer )
1521 DPSP_CREATEPLAYERDATA data;
1523 data.idPlayer = *lpidPlayer;
1524 data.dwFlags = dwCreateFlags;
1525 data.lpSPMessageHeader = lpMsgHdr;
1526 data.lpISP = This->dp2->spData.lpISP;
1528 TRACE( "Calling SP CreatePlayer 0x%08x: dwFlags: 0x%08x lpMsgHdr: %p\n",
1529 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
1531 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1534 if( FAILED(hr) )
1536 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1537 return hr;
1540 /* Now let the SP know that this player is a member of the system group */
1541 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1543 DPSP_ADDPLAYERTOGROUPDATA data;
1545 data.idPlayer = *lpidPlayer;
1546 data.idGroup = DPID_SYSTEM_GROUP;
1547 data.lpISP = This->dp2->spData.lpISP;
1549 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1551 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1554 if( FAILED(hr) )
1556 ERR( "Failed to add player to sys group with sp: %s\n",
1557 DPLAYX_HresultToString(hr) );
1558 return hr;
1561 #if 1
1562 if( This->dp2->bHostInterface == FALSE )
1564 /* Let the name server know about the creation of this player */
1565 /* FIXME: Is this only to be done for the creation of a server player or
1566 * is this used for regular players? If only for server players, move
1567 * this call to DP_SecureOpen(...);
1569 #if 0
1570 TRACE( "Sending message to self to get my addr\n" );
1571 DP_MSG_ToSelf( This, *lpidPlayer ); /* This is a hack right now */
1572 #endif
1574 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
1576 #else
1577 /* Inform all other peers of the creation of a new player. If there are
1578 * no peers keep this quiet.
1579 * Also, if this was a remote event, no need to rebroadcast it.
1581 if( ( lpMsgHdr == NULL ) &&
1582 This->dp2->lpSessionDesc &&
1583 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1585 DPMSG_CREATEPLAYERORGROUP msg;
1586 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1588 msg.dwPlayerType = DPPLAYERTYPE_PLAYER;
1589 msg.dpId = *lpidPlayer;
1590 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */
1591 msg.lpData = lpData;
1592 msg.dwDataSize = dwDataSize;
1593 msg.dpnName = *lpPlayerName;
1594 msg.dpIdParent = DPID_NOPARENT_GROUP;
1595 msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
1597 /* FIXME: Correct to just use send effectively? */
1598 /* FIXME: Should size include data w/ message or just message "header" */
1599 /* FIXME: Check return code */
1600 hr = DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
1601 sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
1603 #endif
1605 return hr;
1608 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
1609 ( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1610 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1612 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1614 if( dwFlags & DPPLAYER_SERVERPLAYER )
1616 *lpidPlayer = DPID_SERVERPLAYER;
1618 else
1620 *lpidPlayer = DPID_UNKNOWN;
1623 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1624 lpData, dwDataSize, dwFlags, TRUE );
1627 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
1628 ( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1629 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1631 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1633 if( dwFlags & DPPLAYER_SERVERPLAYER )
1635 *lpidPlayer = DPID_SERVERPLAYER;
1637 else
1639 *lpidPlayer = DPID_UNKNOWN;
1642 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1643 lpData, dwDataSize, dwFlags, FALSE );
1646 static DPID DP_GetRemoteNextObjectId(void)
1648 FIXME( ":stub\n" );
1650 /* Hack solution */
1651 return DP_NextObjectId();
1654 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
1655 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
1656 DPID idPlayer, BOOL bAnsi )
1658 HRESULT hr = DP_OK;
1660 lpGroupData lpGData;
1661 lpPlayerList lpPList;
1663 TRACE( "(%p)->(%p,0x%08x,0x%08x,%u)\n",
1664 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
1666 /* Find the group */
1667 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1669 return DPERR_INVALIDGROUP;
1672 /* Find the player */
1673 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
1675 return DPERR_INVALIDPLAYER;
1678 /* Remove the player shortcut from the group */
1679 DPQ_REMOVE_ENTRY( lpGData->players, players, lpPData->dpid, ==, idPlayer, lpPList );
1681 if( lpPList == NULL )
1683 return DPERR_INVALIDPLAYER;
1686 /* One less reference */
1687 lpPList->lpPData->uRef--;
1689 /* Delete the Player List element */
1690 HeapFree( GetProcessHeap(), 0, lpPList );
1692 /* Inform the SP if they care */
1693 if( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1695 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1697 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1699 data.idPlayer = idPlayer;
1700 data.idGroup = idGroup;
1701 data.lpISP = This->dp2->spData.lpISP;
1703 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1706 /* Need to send a DELETEPLAYERFROMGROUP message */
1707 FIXME( "Need to send a message\n" );
1709 return hr;
1712 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
1713 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
1715 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1716 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, TRUE );
1719 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
1720 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
1722 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1723 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, FALSE );
1726 typedef struct _DPRGOPContext
1728 IDirectPlay3Impl* This;
1729 BOOL bAnsi;
1730 DPID idGroup;
1731 } DPRGOPContext, *lpDPRGOPContext;
1733 static BOOL CALLBACK
1734 cbRemoveGroupOrPlayer(
1735 DPID dpId,
1736 DWORD dwPlayerType,
1737 LPCDPNAME lpName,
1738 DWORD dwFlags,
1739 LPVOID lpContext )
1741 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1743 TRACE( "Removing element:0x%08x (type:0x%08x) from element:0x%08x\n",
1744 dpId, dwPlayerType, lpCtxt->idGroup );
1746 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1748 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt->This, lpCtxt->idGroup,
1749 dpId )
1753 ERR( "Unable to delete group 0x%08x from group 0x%08x\n",
1754 dpId, lpCtxt->idGroup );
1757 else
1759 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl*)lpCtxt->This,
1760 NULL, lpCtxt->idGroup,
1761 dpId, lpCtxt->bAnsi )
1765 ERR( "Unable to delete player 0x%08x from grp 0x%08x\n",
1766 dpId, lpCtxt->idGroup );
1770 return TRUE; /* Continue enumeration */
1773 static HRESULT WINAPI DP_IF_DestroyGroup
1774 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi )
1776 lpGroupData lpGData;
1777 DPRGOPContext context;
1779 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1780 This, lpMsgHdr, idGroup, bAnsi );
1782 /* Find the group */
1783 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1785 return DPERR_INVALIDPLAYER; /* yes player */
1788 context.This = (IDirectPlay3Impl*)This;
1789 context.bAnsi = bAnsi;
1790 context.idGroup = idGroup;
1792 /* Remove all players that this group has */
1793 DP_IF_EnumGroupPlayers( This, idGroup, NULL,
1794 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1796 /* Remove all links to groups that this group has since this is dp3 */
1797 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This, idGroup, NULL,
1798 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1800 /* Remove this group from the parent group - if it has one */
1801 if( ( idGroup != DPID_SYSTEM_GROUP ) &&
1802 ( lpGData->parent != DPID_SYSTEM_GROUP )
1805 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl*)This, lpGData->parent,
1806 idGroup );
1809 /* Now delete this group data and list from the system group */
1810 DP_DeleteGroup( This, idGroup );
1812 /* Let the SP know that we've destroyed this group */
1813 if( This->dp2->spData.lpCB->DeleteGroup )
1815 DPSP_DELETEGROUPDATA data;
1817 FIXME( "data.dwFlags is incorrect\n" );
1819 data.idGroup = idGroup;
1820 data.dwFlags = 0;
1821 data.lpISP = This->dp2->spData.lpISP;
1823 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1826 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1828 return DP_OK;
1831 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
1832 ( LPDIRECTPLAY2A iface, DPID idGroup )
1834 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1835 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
1838 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
1839 ( LPDIRECTPLAY2 iface, DPID idGroup )
1841 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1842 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
1845 typedef struct _DPFAGContext
1847 IDirectPlay2Impl* This;
1848 DPID idPlayer;
1849 BOOL bAnsi;
1850 } DPFAGContext, *lpDPFAGContext;
1852 static HRESULT WINAPI DP_IF_DestroyPlayer
1853 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi )
1855 DPFAGContext cbContext;
1857 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1858 This, lpMsgHdr, idPlayer, bAnsi );
1860 if( This->dp2->connectionInitialized == NO_PROVIDER )
1862 return DPERR_UNINITIALIZED;
1865 if( DP_FindPlayer( This, idPlayer ) == NULL )
1867 return DPERR_INVALIDPLAYER;
1870 /* FIXME: If the player is remote, we must be the host to delete this */
1872 cbContext.This = This;
1873 cbContext.idPlayer = idPlayer;
1874 cbContext.bAnsi = bAnsi;
1876 /* Find each group and call DeletePlayerFromGroup if the player is a
1877 member of the group */
1878 DP_IF_EnumGroups( This, NULL, cbDeletePlayerFromAllGroups,
1879 (LPVOID)&cbContext, DPENUMGROUPS_ALL, bAnsi );
1881 /* Now delete player and player list from the sys group */
1882 DP_DeletePlayer( This, idPlayer );
1884 /* Let the SP know that we've destroyed this group */
1885 if( This->dp2->spData.lpCB->DeletePlayer )
1887 DPSP_DELETEPLAYERDATA data;
1889 FIXME( "data.dwFlags is incorrect\n" );
1891 data.idPlayer = idPlayer;
1892 data.dwFlags = 0;
1893 data.lpISP = This->dp2->spData.lpISP;
1895 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
1898 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
1900 return DP_OK;
1903 static BOOL CALLBACK
1904 cbDeletePlayerFromAllGroups(
1905 DPID dpId,
1906 DWORD dwPlayerType,
1907 LPCDPNAME lpName,
1908 DWORD dwFlags,
1909 LPVOID lpContext )
1911 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
1913 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1915 DP_IF_DeletePlayerFromGroup( lpCtxt->This, NULL, dpId, lpCtxt->idPlayer,
1916 lpCtxt->bAnsi );
1918 /* Enumerate all groups in this group since this will normally only
1919 * be called for top level groups
1921 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)lpCtxt->This,
1922 dpId, NULL,
1923 cbDeletePlayerFromAllGroups,
1924 lpContext, DPENUMGROUPS_ALL,
1925 lpCtxt->bAnsi );
1928 else
1930 ERR( "Group callback has dwPlayerType = 0x%08x\n", dwPlayerType );
1933 return TRUE;
1936 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
1937 ( LPDIRECTPLAY2A iface, DPID idPlayer )
1939 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1940 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
1943 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
1944 ( LPDIRECTPLAY2 iface, DPID idPlayer )
1946 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1947 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
1950 static HRESULT WINAPI DP_IF_EnumGroupPlayers
1951 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
1952 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1953 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1955 lpGroupData lpGData;
1956 lpPlayerList lpPList;
1958 FIXME("(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
1959 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
1960 lpContext, dwFlags, bAnsi );
1962 if( This->dp2->connectionInitialized == NO_PROVIDER )
1964 return DPERR_UNINITIALIZED;
1967 /* Find the group */
1968 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1970 return DPERR_INVALIDGROUP;
1973 if( DPQ_IS_EMPTY( lpGData->players ) )
1975 return DP_OK;
1978 lpPList = DPQ_FIRST( lpGData->players );
1980 /* Walk the players in this group */
1981 for( ;; )
1983 /* We do not enum the name server or app server as they are of no
1984 * consequence to the end user.
1986 if( ( lpPList->lpPData->dpid != DPID_NAME_SERVER ) &&
1987 ( lpPList->lpPData->dpid != DPID_SERVERPLAYER )
1991 /* FIXME: Need to add stuff for dwFlags checking */
1993 if( !lpEnumPlayersCallback2( lpPList->lpPData->dpid, DPPLAYERTYPE_PLAYER,
1994 &lpPList->lpPData->name,
1995 lpPList->lpPData->dwFlags,
1996 lpContext )
1999 /* User requested break */
2000 return DP_OK;
2004 if( DPQ_IS_ENDOFLIST( lpPList->players ) )
2006 break;
2009 lpPList = DPQ_NEXT( lpPList->players );
2012 return DP_OK;
2015 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
2016 ( LPDIRECTPLAY2A iface, DPID idGroup, LPGUID lpguidInstance,
2017 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2018 LPVOID lpContext, DWORD dwFlags )
2020 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2021 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2022 lpEnumPlayersCallback2, lpContext,
2023 dwFlags, TRUE );
2026 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
2027 ( LPDIRECTPLAY2 iface, DPID idGroup, LPGUID lpguidInstance,
2028 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2029 LPVOID lpContext, DWORD dwFlags )
2031 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2032 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2033 lpEnumPlayersCallback2, lpContext,
2034 dwFlags, FALSE );
2037 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2038 static HRESULT WINAPI DP_IF_EnumGroups
2039 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2040 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2041 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2043 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This,
2044 DPID_SYSTEM_GROUP, lpguidInstance,
2045 lpEnumPlayersCallback2, lpContext,
2046 dwFlags, bAnsi );
2049 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
2050 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2051 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2052 LPVOID lpContext, DWORD dwFlags )
2054 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2055 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2056 lpContext, dwFlags, TRUE );
2059 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
2060 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2061 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2062 LPVOID lpContext, DWORD dwFlags )
2064 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2065 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2066 lpContext, dwFlags, FALSE );
2069 static HRESULT WINAPI DP_IF_EnumPlayers
2070 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2071 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2072 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2074 return DP_IF_EnumGroupPlayers( This, DPID_SYSTEM_GROUP, lpguidInstance,
2075 lpEnumPlayersCallback2, lpContext,
2076 dwFlags, bAnsi );
2079 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
2080 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2081 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2082 LPVOID lpContext, DWORD dwFlags )
2084 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2085 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2086 lpContext, dwFlags, TRUE );
2089 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
2090 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2091 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2092 LPVOID lpContext, DWORD dwFlags )
2094 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2095 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2096 lpContext, dwFlags, FALSE );
2099 /* This function should call the registered callback function that the user
2100 passed into EnumSessions for each entry available.
2102 static void DP_InvokeEnumSessionCallbacks
2103 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2104 LPVOID lpNSInfo,
2105 DWORD dwTimeout,
2106 LPVOID lpContext )
2108 LPDPSESSIONDESC2 lpSessionDesc;
2110 FIXME( ": not checking for conditions\n" );
2112 /* Not sure if this should be pruning but it's convenient */
2113 NS_PruneSessionCache( lpNSInfo );
2115 NS_ResetSessionEnumeration( lpNSInfo );
2117 /* Enumerate all sessions */
2118 /* FIXME: Need to indicate ANSI */
2119 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2121 TRACE( "EnumSessionsCallback2 invoked\n" );
2122 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2124 return;
2128 /* Invoke one last time to indicate that there is no more to come */
2129 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2132 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2134 EnumSessionAsyncCallbackData* data = (EnumSessionAsyncCallbackData*)lpContext;
2135 HANDLE hSuicideRequest = data->hSuicideRequest;
2136 DWORD dwTimeout = data->dwTimeout;
2138 TRACE( "Thread started with timeout = 0x%08x\n", dwTimeout );
2140 for( ;; )
2142 HRESULT hr;
2144 /* Sleep up to dwTimeout waiting for request to terminate thread */
2145 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2147 TRACE( "Thread terminating on terminate request\n" );
2148 break;
2151 /* Now resend the enum request */
2152 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2153 data->dwEnumSessionFlags,
2154 data->lpSpData );
2156 if( FAILED(hr) )
2158 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2159 /* FIXME: Should we kill this thread? How to inform the main thread? */
2164 TRACE( "Thread terminating\n" );
2166 /* Clean up the thread data */
2167 CloseHandle( hSuicideRequest );
2168 HeapFree( GetProcessHeap(), 0, lpContext );
2170 /* FIXME: Need to have some notification to main app thread that this is
2171 * dead. It would serve two purposes. 1) allow sync on termination
2172 * so that we don't actually send something to ourselves when we
2173 * become name server (race condition) and 2) so that if we die
2174 * abnormally something else will be able to tell.
2177 return 1;
2180 static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
2182 /* Does a thread exist? If so we were doing an async enum session */
2183 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2185 TRACE( "Killing EnumSession thread %p\n",
2186 This->dp2->hEnumSessionThread );
2188 /* Request that the thread kill itself nicely */
2189 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2190 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2192 /* We no longer need to know about the thread */
2193 CloseHandle( This->dp2->hEnumSessionThread );
2195 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2199 static HRESULT WINAPI DP_IF_EnumSessions
2200 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2201 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2202 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2204 HRESULT hr = DP_OK;
2206 TRACE( "(%p)->(%p,0x%08x,%p,%p,0x%08x,%u)\n",
2207 This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags,
2208 bAnsi );
2209 if( This->dp2->connectionInitialized == NO_PROVIDER )
2211 return DPERR_UNINITIALIZED;
2214 /* Can't enumerate if the interface is already open */
2215 if( This->dp2->bConnectionOpen )
2217 return DPERR_GENERIC;
2220 #if 1
2221 /* The loading of a lobby provider _seems_ to require a backdoor loading
2222 * of the service provider to also associate with this DP object. This is
2223 * because the app doesn't seem to have to call EnumConnections and
2224 * InitializeConnection for the SP before calling this method. As such
2225 * we'll do their dirty work for them with a quick hack so as to always
2226 * load the TCP/IP service provider.
2228 * The correct solution would seem to involve creating a dialog box which
2229 * contains the possible SPs. These dialog boxes most likely follow SDK
2230 * examples.
2232 if( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
2234 LPVOID lpConnection;
2235 DWORD dwSize;
2237 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2239 if( !DP_BuildSPCompoundAddr( (LPGUID)&DPSPGUID_TCPIP, &lpConnection, &dwSize ) )
2241 ERR( "Can't build compound addr\n" );
2242 return DPERR_GENERIC;
2245 hr = DP_IF_InitializeConnection( (IDirectPlay3Impl*)This, lpConnection,
2246 0, bAnsi );
2247 if( FAILED(hr) )
2249 return hr;
2252 /* Free up the address buffer */
2253 HeapFree( GetProcessHeap(), 0, lpConnection );
2255 /* The SP is now initialized */
2256 This->dp2->bSPInitialized = TRUE;
2258 #endif
2261 /* Use the service provider default? */
2262 if( dwTimeout == 0 )
2264 DPCAPS spCaps;
2265 spCaps.dwSize = sizeof( spCaps );
2267 DP_IF_GetCaps( This, &spCaps, 0 );
2268 dwTimeout = spCaps.dwTimeout;
2270 /* The service provider doesn't provide one either! */
2271 if( dwTimeout == 0 )
2273 /* Provide the TCP/IP default */
2274 dwTimeout = DPMSG_WAIT_5_SECS;
2278 if( dwFlags & DPENUMSESSIONS_STOPASYNC )
2280 DP_KillEnumSessionThread( This );
2281 return hr;
2284 if( ( dwFlags & DPENUMSESSIONS_ASYNC ) )
2286 /* Enumerate everything presently in the local session cache */
2287 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2288 This->dp2->lpNameServerData, dwTimeout,
2289 lpContext );
2291 if( This->dp2->dwEnumSessionLock != 0 )
2292 return DPERR_CONNECTING;
2294 /* See if we've already created a thread to service this interface */
2295 if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2297 DWORD dwThreadId;
2298 This->dp2->dwEnumSessionLock++;
2300 /* Send the first enum request inline since the user may cancel a dialog
2301 * if one is presented. Also, may also have a connecting return code.
2303 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2304 dwFlags, &This->dp2->spData );
2306 if( !FAILED(hr) )
2308 EnumSessionAsyncCallbackData* lpData
2309 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpData ) );
2310 /* FIXME: need to kill the thread on object deletion */
2311 lpData->lpSpData = &This->dp2->spData;
2313 lpData->requestGuid = lpsd->guidApplication;
2314 lpData->dwEnumSessionFlags = dwFlags;
2315 lpData->dwTimeout = dwTimeout;
2317 This->dp2->hKillEnumSessionThreadEvent =
2318 CreateEventW( NULL, TRUE, FALSE, NULL );
2320 if( !DuplicateHandle( GetCurrentProcess(),
2321 This->dp2->hKillEnumSessionThreadEvent,
2322 GetCurrentProcess(),
2323 &lpData->hSuicideRequest,
2324 0, FALSE, DUPLICATE_SAME_ACCESS )
2327 ERR( "Can't duplicate thread killing handle\n" );
2330 TRACE( ": creating EnumSessionsRequest thread\n" );
2332 This->dp2->hEnumSessionThread = CreateThread( NULL,
2334 DP_EnumSessionsSendAsyncRequestThread,
2335 lpData,
2337 &dwThreadId );
2339 This->dp2->dwEnumSessionLock--;
2342 else
2344 /* Invalidate the session cache for the interface */
2345 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2347 /* Send the broadcast for session enumeration */
2348 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2349 dwFlags,
2350 &This->dp2->spData );
2353 SleepEx( dwTimeout, FALSE );
2355 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2356 This->dp2->lpNameServerData, dwTimeout,
2357 lpContext );
2360 return hr;
2363 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2364 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2365 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2366 LPVOID lpContext, DWORD dwFlags )
2368 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2369 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2370 lpContext, dwFlags, TRUE );
2373 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2374 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2375 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2376 LPVOID lpContext, DWORD dwFlags )
2378 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2379 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2380 lpContext, dwFlags, FALSE );
2383 static HRESULT WINAPI DP_IF_GetPlayerCaps
2384 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
2385 DWORD dwFlags )
2387 DPSP_GETCAPSDATA data;
2389 TRACE("(%p)->(0x%08x,%p,0x%08x)\n", This, idPlayer, lpDPCaps, dwFlags);
2391 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2393 return DPERR_UNINITIALIZED;
2396 /* Query the service provider */
2397 data.idPlayer = idPlayer;
2398 data.dwFlags = dwFlags;
2399 data.lpCaps = lpDPCaps;
2400 data.lpISP = This->dp2->spData.lpISP;
2402 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2405 static HRESULT WINAPI DP_IF_GetCaps
2406 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags )
2408 return DP_IF_GetPlayerCaps( This, DPID_ALLPLAYERS, lpDPCaps, dwFlags );
2411 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2412 ( LPDIRECTPLAY2A iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2414 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2415 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2418 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2419 ( LPDIRECTPLAY2 iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2421 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2422 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2425 static HRESULT WINAPI DP_IF_GetGroupData
2426 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2427 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2429 lpGroupData lpGData;
2430 DWORD dwRequiredBufferSize;
2431 LPVOID lpCopyDataFrom;
2433 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2434 This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi );
2436 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2438 return DPERR_INVALIDGROUP;
2441 /* How much buffer is required? */
2442 if( dwFlags & DPSET_LOCAL )
2444 dwRequiredBufferSize = lpGData->dwLocalDataSize;
2445 lpCopyDataFrom = lpGData->lpLocalData;
2447 else
2449 dwRequiredBufferSize = lpGData->dwRemoteDataSize;
2450 lpCopyDataFrom = lpGData->lpRemoteData;
2453 /* Is the user requesting to know how big a buffer is required? */
2454 if( ( lpData == NULL ) ||
2455 ( *lpdwDataSize < dwRequiredBufferSize )
2458 *lpdwDataSize = dwRequiredBufferSize;
2459 return DPERR_BUFFERTOOSMALL;
2462 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2464 return DP_OK;
2467 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2468 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2469 LPDWORD lpdwDataSize, DWORD dwFlags )
2471 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2472 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2473 dwFlags, TRUE );
2476 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2477 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2478 LPDWORD lpdwDataSize, DWORD dwFlags )
2480 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2481 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2482 dwFlags, FALSE );
2485 static HRESULT WINAPI DP_IF_GetGroupName
2486 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2487 LPDWORD lpdwDataSize, BOOL bAnsi )
2489 lpGroupData lpGData;
2490 LPDPNAME lpName = (LPDPNAME)lpData;
2491 DWORD dwRequiredDataSize;
2493 FIXME("(%p)->(0x%08x,%p,%p,%u) ANSI ignored\n",
2494 This, idGroup, lpData, lpdwDataSize, bAnsi );
2496 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2498 return DPERR_INVALIDGROUP;
2501 dwRequiredDataSize = lpGData->name.dwSize;
2503 if( lpGData->name.u1.lpszShortNameA )
2505 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
2508 if( lpGData->name.u2.lpszLongNameA )
2510 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
2513 if( ( lpData == NULL ) ||
2514 ( *lpdwDataSize < dwRequiredDataSize )
2517 *lpdwDataSize = dwRequiredDataSize;
2518 return DPERR_BUFFERTOOSMALL;
2521 /* Copy the structure */
2522 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2524 if( lpGData->name.u1.lpszShortNameA )
2526 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2527 lpGData->name.u1.lpszShortNameA );
2529 else
2531 lpName->u1.lpszShortNameA = NULL;
2534 if( lpGData->name.u1.lpszShortNameA )
2536 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2537 lpGData->name.u2.lpszLongNameA );
2539 else
2541 lpName->u2.lpszLongNameA = NULL;
2544 return DP_OK;
2547 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2548 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2549 LPDWORD lpdwDataSize )
2551 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2552 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2555 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2556 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2557 LPDWORD lpdwDataSize )
2559 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2560 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2563 static HRESULT WINAPI DP_IF_GetMessageCount
2564 ( IDirectPlay2Impl* This, DPID idPlayer,
2565 LPDWORD lpdwCount, BOOL bAnsi )
2567 FIXME("(%p)->(0x%08x,%p,%u): stub\n", This, idPlayer, lpdwCount, bAnsi );
2568 return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer,
2569 DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL,
2570 bAnsi );
2573 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2574 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDWORD lpdwCount )
2576 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2577 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, TRUE );
2580 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2581 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDWORD lpdwCount )
2583 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2584 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, FALSE );
2587 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2588 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2590 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2591 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2592 return DP_OK;
2595 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2596 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2598 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2599 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2600 return DP_OK;
2603 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2604 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2605 DWORD dwFlags )
2607 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2608 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2611 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2612 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2613 DWORD dwFlags )
2615 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2616 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2619 static HRESULT WINAPI DP_IF_GetPlayerData
2620 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2621 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2623 lpPlayerList lpPList;
2624 DWORD dwRequiredBufferSize;
2625 LPVOID lpCopyDataFrom;
2627 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2628 This, idPlayer, lpData, lpdwDataSize, dwFlags, bAnsi );
2630 if( This->dp2->connectionInitialized == NO_PROVIDER )
2632 return DPERR_UNINITIALIZED;
2635 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2637 return DPERR_INVALIDPLAYER;
2640 /* How much buffer is required? */
2641 if( dwFlags & DPSET_LOCAL )
2643 dwRequiredBufferSize = lpPList->lpPData->dwLocalDataSize;
2644 lpCopyDataFrom = lpPList->lpPData->lpLocalData;
2646 else
2648 dwRequiredBufferSize = lpPList->lpPData->dwRemoteDataSize;
2649 lpCopyDataFrom = lpPList->lpPData->lpRemoteData;
2652 /* Is the user requesting to know how big a buffer is required? */
2653 if( ( lpData == NULL ) ||
2654 ( *lpdwDataSize < dwRequiredBufferSize )
2657 *lpdwDataSize = dwRequiredBufferSize;
2658 return DPERR_BUFFERTOOSMALL;
2661 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2663 return DP_OK;
2666 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2667 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2668 LPDWORD lpdwDataSize, DWORD dwFlags )
2670 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2671 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2672 dwFlags, TRUE );
2675 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2676 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2677 LPDWORD lpdwDataSize, DWORD dwFlags )
2679 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2680 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2681 dwFlags, FALSE );
2684 static HRESULT WINAPI DP_IF_GetPlayerName
2685 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2686 LPDWORD lpdwDataSize, BOOL bAnsi )
2688 lpPlayerList lpPList;
2689 LPDPNAME lpName = (LPDPNAME)lpData;
2690 DWORD dwRequiredDataSize;
2692 FIXME( "(%p)->(0x%08x,%p,%p,%u): ANSI\n",
2693 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2695 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2697 return DPERR_INVALIDPLAYER;
2700 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
2702 if( lpPList->lpPData->name.u1.lpszShortNameA )
2704 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
2707 if( lpPList->lpPData->name.u2.lpszLongNameA )
2709 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
2712 if( ( lpData == NULL ) ||
2713 ( *lpdwDataSize < dwRequiredDataSize )
2716 *lpdwDataSize = dwRequiredDataSize;
2717 return DPERR_BUFFERTOOSMALL;
2720 /* Copy the structure */
2721 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
2723 if( lpPList->lpPData->name.u1.lpszShortNameA )
2725 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2726 lpPList->lpPData->name.u1.lpszShortNameA );
2728 else
2730 lpName->u1.lpszShortNameA = NULL;
2733 if( lpPList->lpPData->name.u1.lpszShortNameA )
2735 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2736 lpPList->lpPData->name.u2.lpszLongNameA );
2738 else
2740 lpName->u2.lpszLongNameA = NULL;
2743 return DP_OK;
2746 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2747 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2748 LPDWORD lpdwDataSize )
2750 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2751 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
2754 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2755 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2756 LPDWORD lpdwDataSize )
2758 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2759 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
2762 static HRESULT WINAPI DP_GetSessionDesc
2763 ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize,
2764 BOOL bAnsi )
2766 DWORD dwRequiredSize;
2768 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
2770 if( This->dp2->connectionInitialized == NO_PROVIDER )
2772 return DPERR_UNINITIALIZED;
2775 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
2777 return DPERR_INVALIDPARAMS;
2780 /* FIXME: Get from This->dp2->lpSessionDesc */
2781 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
2783 if ( ( lpData == NULL ) ||
2784 ( *lpdwDataSize < dwRequiredSize )
2787 *lpdwDataSize = dwRequiredSize;
2788 return DPERR_BUFFERTOOSMALL;
2791 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
2793 return DP_OK;
2796 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
2797 ( LPDIRECTPLAY2A iface, LPVOID lpData, LPDWORD lpdwDataSize )
2799 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2800 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2803 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
2804 ( LPDIRECTPLAY2 iface, LPVOID lpData, LPDWORD lpdwDataSize )
2806 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2807 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2810 /* Intended only for COM compatibility. Always returns an error. */
2811 static HRESULT WINAPI DirectPlay2AImpl_Initialize
2812 ( LPDIRECTPLAY2A iface, LPGUID lpGUID )
2814 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2815 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2816 return DPERR_ALREADYINITIALIZED;
2819 /* Intended only for COM compatibility. Always returns an error. */
2820 static HRESULT WINAPI DirectPlay2WImpl_Initialize
2821 ( LPDIRECTPLAY2 iface, LPGUID lpGUID )
2823 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2824 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2825 return DPERR_ALREADYINITIALIZED;
2829 static HRESULT WINAPI DP_SecureOpen
2830 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
2831 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
2832 BOOL bAnsi )
2834 HRESULT hr = DP_OK;
2836 FIXME( "(%p)->(%p,0x%08x,%p,%p): partial stub\n",
2837 This, lpsd, dwFlags, lpSecurity, lpCredentials );
2839 if( This->dp2->connectionInitialized == NO_PROVIDER )
2841 return DPERR_UNINITIALIZED;
2844 if( lpsd->dwSize != sizeof(DPSESSIONDESC2) )
2846 TRACE( ": rejecting invalid dpsd size (%d).\n", lpsd->dwSize );
2847 return DPERR_INVALIDPARAMS;
2850 if( This->dp2->bConnectionOpen )
2852 TRACE( ": rejecting already open connection.\n" );
2853 return DPERR_ALREADYINITIALIZED;
2856 /* If we're enumerating, kill the thread */
2857 DP_KillEnumSessionThread( This );
2859 if( dwFlags & DPOPEN_CREATE )
2861 /* Rightoo - this computer is the host and the local computer needs to be
2862 the name server so that others can join this session */
2863 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
2865 This->dp2->bHostInterface = TRUE;
2867 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
2868 if( FAILED( hr ) )
2870 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
2871 return hr;
2875 /* Invoke the conditional callback for the service provider */
2876 if( This->dp2->spData.lpCB->Open )
2878 DPSP_OPENDATA data;
2880 FIXME( "Not all data fields are correct. Need new parameter\n" );
2882 data.bCreate = (dwFlags & DPOPEN_CREATE ) ? TRUE : FALSE;
2883 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
2884 : NS_GetNSAddr( This->dp2->lpNameServerData );
2885 data.lpISP = This->dp2->spData.lpISP;
2886 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) ? TRUE : FALSE;
2887 data.dwOpenFlags = dwFlags;
2888 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
2890 hr = (*This->dp2->spData.lpCB->Open)(&data);
2891 if( FAILED( hr ) )
2893 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
2894 return hr;
2899 /* Create the system group of which everything is a part of */
2900 DPID systemGroup = DPID_SYSTEM_GROUP;
2902 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
2903 NULL, 0, 0, TRUE );
2907 if( dwFlags & DPOPEN_JOIN )
2909 DPID dpidServerId = DPID_UNKNOWN;
2911 /* Create the server player for this interface. This way we can receive
2912 * messages for this session.
2914 /* FIXME: I suppose that we should be setting an event for a receive
2915 * type of thing. That way the messaging thread could know to wake
2916 * up. DPlay would then trigger the hEvent for the player the
2917 * message is directed to.
2919 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
2921 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
2924 else if( dwFlags & DPOPEN_CREATE )
2926 DPID dpidNameServerId = DPID_NAME_SERVER;
2928 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
2929 0, DPPLAYER_SERVERPLAYER, bAnsi );
2932 if( FAILED(hr) )
2934 ERR( "Couldn't create name server/system player: %s\n",
2935 DPLAYX_HresultToString(hr) );
2938 return hr;
2941 static HRESULT WINAPI DirectPlay2AImpl_Open
2942 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2944 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2945 TRACE("(%p)->(%p,0x%08x)\n", This, lpsd, dwFlags );
2946 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, TRUE );
2949 static HRESULT WINAPI DirectPlay2WImpl_Open
2950 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2952 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2953 TRACE("(%p)->(%p,0x%08x)\n", This, lpsd, dwFlags );
2954 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, FALSE );
2957 static HRESULT WINAPI DP_IF_Receive
2958 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
2959 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi )
2961 LPDPMSG lpMsg = NULL;
2963 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p,%u): stub\n",
2964 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
2966 if( This->dp2->connectionInitialized == NO_PROVIDER )
2968 return DPERR_UNINITIALIZED;
2971 if( dwFlags == 0 )
2973 dwFlags = DPRECEIVE_ALL;
2976 /* If the lpData is NULL, we must be peeking the message */
2977 if( ( lpData == NULL ) &&
2978 !( dwFlags & DPRECEIVE_PEEK )
2981 return DPERR_INVALIDPARAMS;
2984 if( dwFlags & DPRECEIVE_ALL )
2986 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
2988 if( !( dwFlags & DPRECEIVE_PEEK ) )
2990 FIXME( "Remove from queue\n" );
2993 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
2994 ( dwFlags & DPRECEIVE_FROMPLAYER )
2997 FIXME( "Find matching message 0x%08x\n", dwFlags );
2999 else
3001 ERR( "Hmmm..dwFlags 0x%08x\n", dwFlags );
3004 if( lpMsg == NULL )
3006 return DPERR_NOMESSAGES;
3009 /* Copy into the provided buffer */
3010 CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
3012 return DP_OK;
3015 static HRESULT WINAPI DirectPlay2AImpl_Receive
3016 ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo,
3017 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
3019 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3020 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
3021 lpData, lpdwDataSize, TRUE );
3024 static HRESULT WINAPI DirectPlay2WImpl_Receive
3025 ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo,
3026 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
3028 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3029 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
3030 lpData, lpdwDataSize, FALSE );
3033 static HRESULT WINAPI DirectPlay2AImpl_Send
3034 ( LPDIRECTPLAY2A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3036 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3037 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3038 0, 0, NULL, NULL, TRUE );
3041 static HRESULT WINAPI DirectPlay2WImpl_Send
3042 ( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3044 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3045 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3046 0, 0, NULL, NULL, FALSE );
3049 static HRESULT WINAPI DP_IF_SetGroupData
3050 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
3051 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3053 lpGroupData lpGData;
3055 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3056 This, idGroup, lpData, dwDataSize, dwFlags, bAnsi );
3058 /* Parameter check */
3059 if( ( lpData == NULL ) &&
3060 ( dwDataSize != 0 )
3063 return DPERR_INVALIDPARAMS;
3066 /* Find the pointer to the data for this player */
3067 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3069 return DPERR_INVALIDOBJECT;
3072 if( !(dwFlags & DPSET_LOCAL) )
3074 FIXME( "Was this group created by this interface?\n" );
3075 /* FIXME: If this is a remote update need to allow it but not
3076 * send a message.
3080 DP_SetGroupData( lpGData, dwFlags, lpData, dwDataSize );
3082 /* FIXME: Only send a message if this group is local to the session otherwise
3083 * it will have been rejected above
3085 if( !(dwFlags & DPSET_LOCAL) )
3087 FIXME( "Send msg?\n" );
3090 return DP_OK;
3093 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
3094 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
3095 DWORD dwDataSize, DWORD dwFlags )
3097 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3098 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, TRUE );
3101 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
3102 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
3103 DWORD dwDataSize, DWORD dwFlags )
3105 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3106 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, FALSE );
3109 static HRESULT WINAPI DP_IF_SetGroupName
3110 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
3111 DWORD dwFlags, BOOL bAnsi )
3113 lpGroupData lpGData;
3115 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n", This, idGroup,
3116 lpGroupName, dwFlags, bAnsi );
3118 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3120 return DPERR_INVALIDGROUP;
3123 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
3125 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3126 FIXME( "Message not sent and dwFlags ignored\n" );
3128 return DP_OK;
3131 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
3132 ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName,
3133 DWORD dwFlags )
3135 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3136 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
3139 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
3140 ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName,
3141 DWORD dwFlags )
3143 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3144 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
3147 static HRESULT WINAPI DP_IF_SetPlayerData
3148 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
3149 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3151 lpPlayerList lpPList;
3153 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3154 This, idPlayer, lpData, dwDataSize, dwFlags, bAnsi );
3156 /* Parameter check */
3157 if( ( lpData == NULL ) &&
3158 ( dwDataSize != 0 )
3161 return DPERR_INVALIDPARAMS;
3164 /* Find the pointer to the data for this player */
3165 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3167 return DPERR_INVALIDPLAYER;
3170 if( !(dwFlags & DPSET_LOCAL) )
3172 FIXME( "Was this group created by this interface?\n" );
3173 /* FIXME: If this is a remote update need to allow it but not
3174 * send a message.
3178 DP_SetPlayerData( lpPList->lpPData, dwFlags, lpData, dwDataSize );
3180 if( !(dwFlags & DPSET_LOCAL) )
3182 FIXME( "Send msg?\n" );
3185 return DP_OK;
3188 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3189 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
3190 DWORD dwDataSize, DWORD dwFlags )
3192 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3193 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3194 dwFlags, TRUE );
3197 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3198 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
3199 DWORD dwDataSize, DWORD dwFlags )
3201 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3202 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3203 dwFlags, FALSE );
3206 static HRESULT WINAPI DP_IF_SetPlayerName
3207 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
3208 DWORD dwFlags, BOOL bAnsi )
3210 lpPlayerList lpPList;
3212 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n",
3213 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3215 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3217 return DPERR_INVALIDGROUP;
3220 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3222 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3223 FIXME( "Message not sent and dwFlags ignored\n" );
3225 return DP_OK;
3228 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3229 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName,
3230 DWORD dwFlags )
3232 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3233 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3236 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3237 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName,
3238 DWORD dwFlags )
3240 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3241 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3244 static HRESULT WINAPI DP_SetSessionDesc
3245 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
3246 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3248 DWORD dwRequiredSize;
3249 LPDPSESSIONDESC2 lpTempSessDesc;
3251 TRACE( "(%p)->(%p,0x%08x,%u,%u)\n",
3252 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3254 if( This->dp2->connectionInitialized == NO_PROVIDER )
3256 return DPERR_UNINITIALIZED;
3259 if( dwFlags )
3261 return DPERR_INVALIDPARAMS;
3264 /* Only the host is allowed to update the session desc */
3265 if( !This->dp2->bHostInterface )
3267 return DPERR_ACCESSDENIED;
3270 /* FIXME: Copy into This->dp2->lpSessionDesc */
3271 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3272 lpTempSessDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize );
3274 if( lpTempSessDesc == NULL )
3276 return DPERR_OUTOFMEMORY;
3279 /* Free the old */
3280 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3282 This->dp2->lpSessionDesc = lpTempSessDesc;
3283 /* Set the new */
3284 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3285 if( bInitial )
3287 /*Initializing session GUID*/
3288 CoCreateGuid( &(This->dp2->lpSessionDesc->guidInstance) );
3290 /* If this is an external invocation of the interface, we should be
3291 * letting everyone know that things have changed. Otherwise this is
3292 * just an initialization and it doesn't need to be propagated.
3294 if( !bInitial )
3296 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3299 return DP_OK;
3302 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3303 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3305 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3306 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3309 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3310 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3312 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3313 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3316 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3317 DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3319 DWORD dwSize = 0;
3321 if( lpSessDesc == NULL )
3323 /* Hmmm..don't need any size? */
3324 ERR( "NULL lpSessDesc\n" );
3325 return dwSize;
3328 dwSize += sizeof( *lpSessDesc );
3330 if( bAnsi )
3332 if( lpSessDesc->u1.lpszSessionNameA )
3334 dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1;
3337 if( lpSessDesc->u2.lpszPasswordA )
3339 dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1;
3342 else /* UNICODE */
3344 if( lpSessDesc->u1.lpszSessionName )
3346 dwSize += sizeof( WCHAR ) *
3347 ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 );
3350 if( lpSessDesc->u2.lpszPassword )
3352 dwSize += sizeof( WCHAR ) *
3353 ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 );
3357 return dwSize;
3360 /* Assumes that contiguous buffers are already allocated. */
3361 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3362 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3364 BYTE* lpStartOfFreeSpace;
3366 if( lpSessionDest == NULL )
3368 ERR( "NULL lpSessionDest\n" );
3369 return;
3372 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3374 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3376 if( bAnsi )
3378 if( lpSessionSrc->u1.lpszSessionNameA )
3380 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3381 lpSessionDest->u1.lpszSessionNameA );
3382 lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3383 lpStartOfFreeSpace +=
3384 lstrlenA( lpSessionDest->u1.lpszSessionNameA ) + 1;
3387 if( lpSessionSrc->u2.lpszPasswordA )
3389 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3390 lpSessionDest->u2.lpszPasswordA );
3391 lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3392 lpStartOfFreeSpace +=
3393 lstrlenA( lpSessionDest->u2.lpszPasswordA ) + 1;
3396 else /* UNICODE */
3398 if( lpSessionSrc->u1.lpszSessionName )
3400 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3401 lpSessionDest->u1.lpszSessionName );
3402 lpSessionDest->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3403 lpStartOfFreeSpace += sizeof(WCHAR) *
3404 ( lstrlenW( lpSessionDest->u1.lpszSessionName ) + 1 );
3407 if( lpSessionSrc->u2.lpszPassword )
3409 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3410 lpSessionDest->u2.lpszPassword );
3411 lpSessionDest->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3412 lpStartOfFreeSpace += sizeof(WCHAR) *
3413 ( lstrlenW( lpSessionDest->u2.lpszPassword ) + 1 );
3419 static HRESULT WINAPI DP_IF_AddGroupToGroup
3420 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3422 lpGroupData lpGData;
3423 lpGroupList lpNewGList;
3425 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, idParentGroup, idGroup );
3427 if( DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) == NULL )
3429 return DPERR_INVALIDGROUP;
3432 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3434 return DPERR_INVALIDGROUP;
3437 /* Create a player list (ie "shortcut" ) */
3438 lpNewGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewGList ) );
3439 if( lpNewGList == NULL )
3441 return DPERR_CANTADDPLAYER;
3444 /* Add the shortcut */
3445 lpGData->uRef++;
3446 lpNewGList->lpGData = lpGData;
3448 /* Add the player to the list of players for this group */
3449 DPQ_INSERT( lpGData->groups, lpNewGList, groups );
3451 /* Send a ADDGROUPTOGROUP message */
3452 FIXME( "Not sending message\n" );
3454 return DP_OK;
3457 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3458 ( LPDIRECTPLAY3A iface, DPID idParentGroup, DPID idGroup )
3460 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3461 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3464 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3465 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3467 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3468 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3471 static HRESULT WINAPI DP_IF_CreateGroupInGroup
3472 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
3473 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
3474 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3476 lpGroupData lpGParentData;
3477 lpGroupList lpGList;
3478 lpGroupData lpGData;
3480 TRACE( "(%p)->(0x%08x,%p,%p,%p,0x%08x,0x%08x,%u)\n",
3481 This, idParentGroup, lpidGroup, lpGroupName, lpData,
3482 dwDataSize, dwFlags, bAnsi );
3484 /* Verify that the specified parent is valid */
3485 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This,
3486 idParentGroup ) ) == NULL
3489 return DPERR_INVALIDGROUP;
3492 lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName,
3493 dwFlags, idParentGroup, bAnsi );
3495 if( lpGData == NULL )
3497 return DPERR_CANTADDPLAYER; /* yes player not group */
3500 /* Something else is referencing this data */
3501 lpGData->uRef++;
3503 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
3505 /* The list has now been inserted into the interface group list. We now
3506 need to put a "shortcut" to this group in the parent group */
3507 lpGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGList ) );
3508 if( lpGList == NULL )
3510 FIXME( "Memory leak\n" );
3511 return DPERR_CANTADDPLAYER; /* yes player not group */
3514 lpGList->lpGData = lpGData;
3516 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
3518 /* Let the SP know that we've created this group */
3519 if( This->dp2->spData.lpCB->CreateGroup )
3521 DPSP_CREATEGROUPDATA data;
3523 TRACE( "Calling SP CreateGroup\n" );
3525 data.idGroup = *lpidGroup;
3526 data.dwFlags = dwFlags;
3527 data.lpSPMessageHeader = lpMsgHdr;
3528 data.lpISP = This->dp2->spData.lpISP;
3530 (*This->dp2->spData.lpCB->CreateGroup)( &data );
3533 /* Inform all other peers of the creation of a new group. If there are
3534 * no peers keep this quiet.
3536 if( This->dp2->lpSessionDesc &&
3537 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
3539 DPMSG_CREATEPLAYERORGROUP msg;
3541 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
3542 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
3543 msg.dpId = *lpidGroup;
3544 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
3545 msg.lpData = lpData;
3546 msg.dwDataSize = dwDataSize;
3547 msg.dpnName = *lpGroupName;
3549 /* FIXME: Correct to just use send effectively? */
3550 /* FIXME: Should size include data w/ message or just message "header" */
3551 /* FIXME: Check return code */
3552 DP_SendEx( (IDirectPlay2Impl*)This,
3553 DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
3554 0, 0, NULL, NULL, bAnsi );
3557 return DP_OK;
3560 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3561 ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup,
3562 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3563 DWORD dwFlags )
3565 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3567 *lpidGroup = DPID_UNKNOWN;
3569 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3570 lpGroupName, lpData, dwDataSize, dwFlags,
3571 TRUE );
3574 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3575 ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup,
3576 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3577 DWORD dwFlags )
3579 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3581 *lpidGroup = DPID_UNKNOWN;
3583 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3584 lpGroupName, lpData, dwDataSize,
3585 dwFlags, FALSE );
3588 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
3589 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3591 lpGroupList lpGList;
3592 lpGroupData lpGParentData;
3594 TRACE("(%p)->(0x%08x,0x%08x)\n", This, idParentGroup, idGroup );
3596 /* Is the parent group valid? */
3597 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3599 return DPERR_INVALIDGROUP;
3602 /* Remove the group from the parent group queue */
3603 DPQ_REMOVE_ENTRY( lpGParentData->groups, groups, lpGData->dpid, ==, idGroup, lpGList );
3605 if( lpGList == NULL )
3607 return DPERR_INVALIDGROUP;
3610 /* Decrement the ref count */
3611 lpGList->lpGData->uRef--;
3613 /* Free up the list item */
3614 HeapFree( GetProcessHeap(), 0, lpGList );
3616 /* Should send a DELETEGROUPFROMGROUP message */
3617 FIXME( "message not sent\n" );
3619 return DP_OK;
3622 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3623 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3625 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3626 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3629 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3630 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3632 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3633 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3636 static
3637 BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
3638 LPDWORD lpdwBufSize )
3640 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3641 HRESULT hr;
3643 dpCompoundAddress.dwDataSize = sizeof( GUID );
3644 dpCompoundAddress.guidDataType = DPAID_ServiceProvider;
3645 dpCompoundAddress.lpData = lpcSpGuid;
3647 *lplpAddrBuf = NULL;
3648 *lpdwBufSize = 0;
3650 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3651 lpdwBufSize, TRUE );
3653 if( hr != DPERR_BUFFERTOOSMALL )
3655 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3656 return FALSE;
3659 /* Now allocate the buffer */
3660 *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3661 *lpdwBufSize );
3663 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3664 lpdwBufSize, TRUE );
3665 if( FAILED(hr) )
3667 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3668 return FALSE;
3671 return TRUE;
3674 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
3675 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3677 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3678 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3680 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
3681 if( dwFlags == 0 )
3683 dwFlags = DPCONNECTION_DIRECTPLAY;
3686 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
3687 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) )
3690 return DPERR_INVALIDFLAGS;
3693 if( !lpEnumCallback )
3695 return DPERR_INVALIDPARAMS;
3698 /* Enumerate DirectPlay service providers */
3699 if( dwFlags & DPCONNECTION_DIRECTPLAY )
3701 HKEY hkResult;
3702 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3703 LPCSTR guidDataSubKey = "Guid";
3704 char subKeyName[51];
3705 DWORD dwIndex, sizeOfSubKeyName=50;
3706 FILETIME filetime;
3708 /* Need to loop over the service providers in the registry */
3709 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3710 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3712 /* Hmmm. Does this mean that there are no service providers? */
3713 ERR(": no service providers?\n");
3714 return DP_OK;
3718 /* Traverse all the service providers we have available */
3719 for( dwIndex=0;
3720 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3721 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3722 ++dwIndex, sizeOfSubKeyName=51 )
3725 HKEY hkServiceProvider;
3726 GUID serviceProviderGUID;
3727 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3728 char returnBuffer[51];
3729 WCHAR buff[51];
3730 DPNAME dpName;
3731 BOOL bBuildPass;
3733 LPVOID lpAddressBuffer = NULL;
3734 DWORD dwAddressBufferSize = 0;
3736 TRACE(" this time through: %s\n", subKeyName );
3738 /* Get a handle for this particular service provider */
3739 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3740 &hkServiceProvider ) != ERROR_SUCCESS )
3742 ERR(": what the heck is going on?\n" );
3743 continue;
3746 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3747 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
3748 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3750 ERR(": missing GUID registry data members\n" );
3751 RegCloseKey(hkServiceProvider);
3752 continue;
3754 RegCloseKey(hkServiceProvider);
3756 /* FIXME: Check return types to ensure we're interpreting data right */
3757 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3758 CLSIDFromString( buff, &serviceProviderGUID );
3759 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3761 /* Fill in the DPNAME struct for the service provider */
3762 dpName.dwSize = sizeof( dpName );
3763 dpName.dwFlags = 0;
3764 dpName.u1.lpszShortNameA = subKeyName;
3765 dpName.u2.lpszLongNameA = NULL;
3767 /* Create the compound address for the service provider.
3768 * NOTE: This is a gruesome architectural scar right now. DP
3769 * uses DPL and DPL uses DP. Nasty stuff. This may be why the
3770 * native dll just gets around this little bit by allocating an
3771 * 80 byte buffer which isn't even filled with a valid compound
3772 * address. Oh well. Creating a proper compound address is the
3773 * way to go anyways despite this method taking slightly more
3774 * heap space and realtime :) */
3776 bBuildPass = DP_BuildSPCompoundAddr( &serviceProviderGUID,
3777 &lpAddressBuffer,
3778 &dwAddressBufferSize );
3779 if( !bBuildPass )
3781 ERR( "Can't build compound addr\n" );
3782 return DPERR_GENERIC;
3785 /* The enumeration will return FALSE if we are not to continue */
3786 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3787 &dpName, dwFlags, lpContext ) )
3789 return DP_OK;
3794 /* Enumerate DirectPlayLobby service providers */
3795 if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY )
3797 HKEY hkResult;
3798 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3799 LPCSTR guidDataSubKey = "Guid";
3800 char subKeyName[51];
3801 DWORD dwIndex, sizeOfSubKeyName=50;
3802 FILETIME filetime;
3804 /* Need to loop over the service providers in the registry */
3805 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3806 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3808 /* Hmmm. Does this mean that there are no service providers? */
3809 ERR(": no service providers?\n");
3810 return DP_OK;
3814 /* Traverse all the lobby providers we have available */
3815 for( dwIndex=0;
3816 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3817 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3818 ++dwIndex, sizeOfSubKeyName=51 )
3821 HKEY hkServiceProvider;
3822 GUID serviceProviderGUID;
3823 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3824 char returnBuffer[51];
3825 WCHAR buff[51];
3826 DPNAME dpName;
3827 HRESULT hr;
3829 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3830 LPVOID lpAddressBuffer = NULL;
3831 DWORD dwAddressBufferSize = 0;
3833 TRACE(" this time through: %s\n", subKeyName );
3835 /* Get a handle for this particular service provider */
3836 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3837 &hkServiceProvider ) != ERROR_SUCCESS )
3839 ERR(": what the heck is going on?\n" );
3840 continue;
3843 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3844 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
3845 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3847 ERR(": missing GUID registry data members\n" );
3848 RegCloseKey(hkServiceProvider);
3849 continue;
3851 RegCloseKey(hkServiceProvider);
3853 /* FIXME: Check return types to ensure we're interpreting data right */
3854 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3855 CLSIDFromString( buff, &serviceProviderGUID );
3856 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3858 /* Fill in the DPNAME struct for the service provider */
3859 dpName.dwSize = sizeof( dpName );
3860 dpName.dwFlags = 0;
3861 dpName.u1.lpszShortNameA = subKeyName;
3862 dpName.u2.lpszLongNameA = NULL;
3864 /* Create the compound address for the service provider.
3865 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
3866 nast stuff. This may be why the native dll just gets around this little bit by
3867 allocating an 80 byte buffer which isn't even a filled with a valid compound
3868 address. Oh well. Creating a proper compound address is the way to go anyways
3869 despite this method taking slightly more heap space and realtime :) */
3871 dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
3872 dpCompoundAddress.dwDataSize = sizeof( GUID );
3873 dpCompoundAddress.lpData = &serviceProviderGUID;
3875 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3876 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
3878 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3879 return hr;
3882 /* Now allocate the buffer */
3883 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
3885 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3886 &dwAddressBufferSize, TRUE ) ) != DP_OK )
3888 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3889 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
3890 return hr;
3893 /* The enumeration will return FALSE if we are not to continue */
3894 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3895 &dpName, dwFlags, lpContext ) )
3897 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
3898 return DP_OK;
3900 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
3904 return DP_OK;
3907 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
3908 ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3910 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3911 FIXME("(%p)->(%p,%p,%p,0x%08x): stub\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3912 return DP_OK;
3915 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
3916 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
3917 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
3918 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
3920 lpGroupList lpGList;
3921 lpGroupData lpGData;
3923 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
3924 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
3925 lpContext, dwFlags, bAnsi );
3927 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3929 return DPERR_INVALIDGROUP;
3932 if( DPQ_IS_EMPTY( lpGData->groups ) )
3934 return DP_OK;
3937 lpGList = DPQ_FIRST( lpGData->groups );
3939 for( ;; )
3941 /* FIXME: Should check dwFlags for match here */
3943 if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP,
3944 &lpGList->lpGData->name, dwFlags,
3945 lpContext ) )
3947 return DP_OK; /* User requested break */
3950 if( DPQ_IS_ENDOFLIST( lpGList->groups ) )
3952 break;
3955 lpGList = DPQ_NEXT( lpGList->groups );
3959 return DP_OK;
3962 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
3963 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3964 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3965 DWORD dwFlags )
3967 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3968 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3969 lpEnumPlayersCallback2, lpContext, dwFlags,
3970 TRUE );
3973 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
3974 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3975 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3976 DWORD dwFlags )
3978 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3979 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3980 lpEnumPlayersCallback2, lpContext, dwFlags,
3981 FALSE );
3984 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
3985 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3987 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3988 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3989 return DP_OK;
3992 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
3993 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3995 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3996 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3997 return DP_OK;
4000 static BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
4001 REFGUID guidDataType,
4002 DWORD dwDataSize,
4003 LPCVOID lpData,
4004 LPVOID lpContext )
4006 /* Looking for the GUID of the provider to load */
4007 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
4008 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
4011 TRACE( "Found SP/LP (%s) %s (data size = 0x%08x)\n",
4012 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
4014 if( dwDataSize != sizeof( GUID ) )
4016 ERR( "Invalid sp/lp guid size 0x%08x\n", dwDataSize );
4019 memcpy( lpContext, lpData, dwDataSize );
4021 /* There shouldn't be more than 1 GUID/compound address */
4022 return FALSE;
4025 /* Still waiting for what we want */
4026 return TRUE;
4030 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
4031 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
4033 UINT i;
4034 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4035 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
4036 LPCSTR guidDataSubKey = "Guid";
4037 LPCSTR majVerDataSubKey = "dwReserved1";
4038 LPCSTR minVerDataSubKey = "dwReserved2";
4039 LPCSTR pathSubKey = "Path";
4041 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
4043 /* FIXME: Cloned code with a quick hack. */
4044 for( i=0; i<2; i++ )
4046 HKEY hkResult;
4047 LPCSTR searchSubKey;
4048 char subKeyName[51];
4049 DWORD dwIndex, sizeOfSubKeyName=50;
4050 FILETIME filetime;
4052 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
4053 *lpbIsDpSp = (i == 0) ? TRUE : FALSE;
4056 /* Need to loop over the service providers in the registry */
4057 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4058 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4060 /* Hmmm. Does this mean that there are no service providers? */
4061 ERR(": no service providers?\n");
4062 return 0;
4065 /* Traverse all the service providers we have available */
4066 for( dwIndex=0;
4067 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4068 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4069 ++dwIndex, sizeOfSubKeyName=51 )
4072 HKEY hkServiceProvider;
4073 GUID serviceProviderGUID;
4074 DWORD returnType, sizeOfReturnBuffer = 255;
4075 char returnBuffer[256];
4076 WCHAR buff[51];
4077 DWORD dwTemp, len;
4079 TRACE(" this time through: %s\n", subKeyName );
4081 /* Get a handle for this particular service provider */
4082 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4083 &hkServiceProvider ) != ERROR_SUCCESS )
4085 ERR(": what the heck is going on?\n" );
4086 continue;
4089 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4090 NULL, &returnType, (LPBYTE)returnBuffer,
4091 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4093 ERR(": missing GUID registry data members\n" );
4094 continue;
4097 /* FIXME: Check return types to ensure we're interpreting data right */
4098 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4099 CLSIDFromString( buff, &serviceProviderGUID );
4100 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4102 /* Determine if this is the Service Provider that the user asked for */
4103 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
4105 continue;
4108 if( i == 0 ) /* DP SP */
4110 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
4111 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
4112 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
4115 sizeOfReturnBuffer = 255;
4117 /* Get dwReserved1 */
4118 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
4119 NULL, &returnType, (LPBYTE)returnBuffer,
4120 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4122 ERR(": missing dwReserved1 registry data members\n") ;
4123 continue;
4126 if( i == 0 )
4127 memcpy( &lpSpData->dwReserved1, returnBuffer, sizeof(lpSpData->dwReserved1) );
4129 sizeOfReturnBuffer = 255;
4131 /* Get dwReserved2 */
4132 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4133 NULL, &returnType, (LPBYTE)returnBuffer,
4134 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4136 ERR(": missing dwReserved1 registry data members\n") ;
4137 continue;
4140 if( i == 0 )
4141 memcpy( &lpSpData->dwReserved2, returnBuffer, sizeof(lpSpData->dwReserved2) );
4143 sizeOfReturnBuffer = 255;
4145 /* Get the path for this service provider */
4146 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
4147 NULL, NULL, (LPBYTE)returnBuffer,
4148 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
4150 ERR(": missing PATH registry data members: 0x%08x\n", dwTemp );
4151 continue;
4154 TRACE( "Loading %s\n", returnBuffer );
4155 return LoadLibraryA( returnBuffer );
4159 return 0;
4162 static
4163 HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider )
4165 HRESULT hr;
4166 LPDPSP_SPINIT SPInit;
4168 /* Initialize the service provider by calling SPInit */
4169 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4171 if( SPInit == NULL )
4173 ERR( "Service provider doesn't provide SPInit interface?\n" );
4174 FreeLibrary( hServiceProvider );
4175 return DPERR_UNAVAILABLE;
4178 TRACE( "Calling SPInit (DP SP entry point)\n" );
4180 hr = (*SPInit)( &This->dp2->spData );
4182 if( FAILED(hr) )
4184 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4185 FreeLibrary( hServiceProvider );
4186 return hr;
4189 /* FIXME: Need to verify the sanity of the returned callback table
4190 * using IsBadCodePtr */
4191 This->dp2->bSPInitialized = TRUE;
4193 /* This interface is now initialized as a DP object */
4194 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
4196 /* Store the handle of the module so that we can unload it later */
4197 This->dp2->hServiceProvider = hServiceProvider;
4199 return hr;
4202 static
4203 HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hLobbyProvider )
4205 HRESULT hr;
4206 LPSP_INIT DPLSPInit;
4208 /* Initialize the service provider by calling SPInit */
4209 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
4211 if( DPLSPInit == NULL )
4213 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4214 FreeLibrary( hLobbyProvider );
4215 return DPERR_UNAVAILABLE;
4218 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4220 hr = (*DPLSPInit)( &This->dp2->dplspData );
4222 if( FAILED(hr) )
4224 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4225 FreeLibrary( hLobbyProvider );
4226 return hr;
4229 /* FIXME: Need to verify the sanity of the returned callback table
4230 * using IsBadCodePtr */
4232 This->dp2->bDPLSPInitialized = TRUE;
4234 /* This interface is now initialized as a lobby object */
4235 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
4237 /* Store the handle of the module so that we can unload it later */
4238 This->dp2->hDPLobbyProvider = hLobbyProvider;
4240 return hr;
4243 static HRESULT WINAPI DP_IF_InitializeConnection
4244 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi )
4246 HMODULE hServiceProvider;
4247 HRESULT hr;
4248 GUID guidSP;
4249 const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
4250 BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4252 TRACE("(%p)->(%p,0x%08x,%u)\n", This, lpConnection, dwFlags, bAnsi );
4254 if ( lpConnection == NULL )
4256 return DPERR_INVALIDPARAMS;
4259 if( dwFlags != 0 )
4261 return DPERR_INVALIDFLAGS;
4264 if( This->dp2->connectionInitialized != NO_PROVIDER )
4266 return DPERR_ALREADYINITIALIZED;
4269 /* Find out what the requested SP is and how large this buffer is */
4270 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
4271 dwAddrSize, &guidSP );
4273 if( FAILED(hr) )
4275 ERR( "Invalid compound address?\n" );
4276 return DPERR_UNAVAILABLE;
4279 /* Load the service provider */
4280 hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp );
4282 if( hServiceProvider == 0 )
4284 ERR( "Unable to load service provider %s\n", debugstr_guid(&guidSP) );
4285 return DPERR_UNAVAILABLE;
4288 if( bIsDpSp )
4290 /* Fill in what we can of the Service Provider required information.
4291 * The rest was be done in DP_LoadSP
4293 This->dp2->spData.lpAddress = lpConnection;
4294 This->dp2->spData.dwAddressSize = dwAddrSize;
4295 This->dp2->spData.lpGuid = &guidSP;
4297 hr = DP_InitializeDPSP( This, hServiceProvider );
4299 else
4301 This->dp2->dplspData.lpAddress = lpConnection;
4303 hr = DP_InitializeDPLSP( This, hServiceProvider );
4306 if( FAILED(hr) )
4308 return hr;
4311 return DP_OK;
4314 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4315 ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
4317 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4319 /* This may not be externally invoked once either an SP or LP is initialized */
4320 if( This->dp2->connectionInitialized != NO_PROVIDER )
4322 return DPERR_ALREADYINITIALIZED;
4325 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE );
4328 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4329 ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
4331 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4333 /* This may not be externally invoked once either an SP or LP is initialized */
4334 if( This->dp2->connectionInitialized != NO_PROVIDER )
4336 return DPERR_ALREADYINITIALIZED;
4339 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE );
4342 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4343 ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4344 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4346 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4347 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4350 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4351 ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4352 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4354 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4355 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4358 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4359 ( LPDIRECTPLAY3A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4361 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4362 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4363 return DP_OK;
4366 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4367 ( LPDIRECTPLAY3 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4369 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4370 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4371 return DP_OK;
4374 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4375 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4377 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4378 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4379 return DP_OK;
4382 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4383 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4385 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4386 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4387 return DP_OK;
4390 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4391 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup )
4393 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4394 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, dwFlags, idGroup );
4395 return DP_OK;
4398 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4399 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup )
4401 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4402 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, dwFlags, idGroup );
4403 return DP_OK;
4406 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4407 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDWORD lpdwFlags )
4409 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4410 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpdwFlags );
4411 return DP_OK;
4414 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4415 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDWORD lpdwFlags )
4417 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4418 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpdwFlags );
4419 return DP_OK;
4422 static HRESULT WINAPI DP_IF_GetGroupParent
4423 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
4424 BOOL bAnsi )
4426 lpGroupData lpGData;
4428 TRACE("(%p)->(0x%08x,%p,%u)\n", This, idGroup, lpidGroup, bAnsi );
4430 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4432 return DPERR_INVALIDGROUP;
4435 *lpidGroup = lpGData->dpid;
4437 return DP_OK;
4440 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4441 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
4443 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4444 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE );
4446 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4447 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
4449 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4450 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE );
4453 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4454 ( LPDIRECTPLAY3A iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4456 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4457 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4458 return DP_OK;
4461 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4462 ( LPDIRECTPLAY3 iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4464 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4465 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4466 return DP_OK;
4469 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4470 ( LPDIRECTPLAY3A iface, DPID idPlayer, LPDWORD lpdwFlags )
4472 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4473 FIXME("(%p)->(0x%08x,%p): stub\n", This, idPlayer, lpdwFlags );
4474 return DP_OK;
4477 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4478 ( LPDIRECTPLAY3 iface, DPID idPlayer, LPDWORD lpdwFlags )
4480 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4481 FIXME("(%p)->(0x%08x,%p): stub\n", This, idPlayer, lpdwFlags );
4482 return DP_OK;
4485 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4486 ( LPDIRECTPLAY4A iface, DPID idGroup, LPDPID lpidGroupOwner )
4488 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4489 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpidGroupOwner );
4490 return DP_OK;
4493 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4494 ( LPDIRECTPLAY4 iface, DPID idGroup, LPDPID lpidGroupOwner )
4496 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4497 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpidGroupOwner );
4498 return DP_OK;
4501 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4502 ( LPDIRECTPLAY4A iface, DPID idGroup , DPID idGroupOwner )
4504 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4505 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, idGroup, idGroupOwner );
4506 return DP_OK;
4509 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4510 ( LPDIRECTPLAY4 iface, DPID idGroup , DPID idGroupOwner )
4512 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4513 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, idGroup, idGroupOwner );
4514 return DP_OK;
4517 static HRESULT WINAPI DP_SendEx
4518 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4519 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4520 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi )
4522 BOOL bValidDestination = FALSE;
4524 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,0x%08x,0x%08x,0x%08x,%p,%p,%u)"
4525 ": stub\n",
4526 This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority,
4527 dwTimeout, lpContext, lpdwMsgID, bAnsi );
4529 /* FIXME: Add parameter checking */
4530 /* FIXME: First call to this needs to acquire a message id which will be
4531 * used for multiple sends
4534 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4536 /* Verify that the message is being sent from a valid local player. The
4537 * from player may be anonymous DPID_UNKNOWN
4539 if( idFrom != DPID_UNKNOWN )
4541 if( DP_FindPlayer( This, idFrom ) == NULL )
4543 WARN( "INFO: Invalid from player 0x%08x\n", idFrom );
4544 return DPERR_INVALIDPLAYER;
4548 /* Verify that the message is being sent to a valid player, group or to
4549 * everyone. If it's valid, send it to those players.
4551 if( idTo == DPID_ALLPLAYERS )
4553 bValidDestination = TRUE;
4555 /* See if SP has the ability to multicast. If so, use it */
4556 if( This->dp2->spData.lpCB->SendToGroupEx )
4558 FIXME( "Use group sendex to group 0\n" );
4560 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4562 FIXME( "Use obsolete group send to group 0\n" );
4564 else /* No multicast, multiplicate */
4566 /* Send to all players we know about */
4567 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4571 if( ( !bValidDestination ) &&
4572 ( DP_FindPlayer( This, idTo ) != NULL )
4575 bValidDestination = TRUE;
4577 /* Have the service provider send this message */
4578 /* FIXME: Could optimize for local interface sends */
4579 return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority,
4580 dwTimeout, lpContext, lpdwMsgID );
4583 if( ( !bValidDestination ) &&
4584 ( DP_FindAnyGroup( This, idTo ) != NULL )
4587 bValidDestination = TRUE;
4589 /* See if SP has the ability to multicast. If so, use it */
4590 if( This->dp2->spData.lpCB->SendToGroupEx )
4592 FIXME( "Use group sendex\n" );
4594 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4596 FIXME( "Use obsolete group send to group\n" );
4598 else /* No multicast, multiplicate */
4600 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4603 #if 0
4604 if( bExpectReply )
4606 DWORD dwWaitReturn;
4608 This->dp2->hReplyEvent = CreateEventW( NULL, FALSE, FALSE, NULL );
4610 dwWaitReturn = WaitForSingleObject( hReplyEvent, dwTimeout );
4611 if( dwWaitReturn != WAIT_OBJECT_0 )
4613 ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
4616 #endif
4619 if( !bValidDestination )
4621 return DPERR_INVALIDPLAYER;
4623 else
4625 /* FIXME: Should return what the send returned */
4626 return DP_OK;
4631 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4632 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4633 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4634 LPVOID lpContext, LPDWORD lpdwMsgID )
4636 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4637 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4638 dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE );
4641 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4642 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4643 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4644 LPVOID lpContext, LPDWORD lpdwMsgID )
4646 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4647 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4648 dwPriority, dwTimeout, lpContext, lpdwMsgID, FALSE );
4651 static HRESULT WINAPI DP_SP_SendEx
4652 ( IDirectPlay2Impl* This, DWORD dwFlags,
4653 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4654 LPVOID lpContext, LPDWORD lpdwMsgID )
4656 LPDPMSG lpMElem;
4658 FIXME( ": stub\n" );
4660 /* FIXME: This queuing should only be for async messages */
4662 lpMElem = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpMElem ) );
4663 lpMElem->msg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
4665 CopyMemory( lpMElem->msg, lpData, dwDataSize );
4667 /* FIXME: Need to queue based on priority */
4668 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
4670 return DP_OK;
4673 static HRESULT WINAPI DP_IF_GetMessageQueue
4674 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4675 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi )
4677 HRESULT hr = DP_OK;
4679 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%p,%u): semi stub\n",
4680 This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi );
4682 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4683 /* FIXME: What about sends which are not immediate? */
4685 if( This->dp2->spData.lpCB->GetMessageQueue )
4687 DPSP_GETMESSAGEQUEUEDATA data;
4689 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4691 /* FIXME: None of this is documented :( */
4693 data.lpISP = This->dp2->spData.lpISP;
4694 data.dwFlags = dwFlags;
4695 data.idFrom = idFrom;
4696 data.idTo = idTo;
4697 data.lpdwNumMsgs = lpdwNumMsgs;
4698 data.lpdwNumBytes = lpdwNumBytes;
4700 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
4702 else
4704 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4707 return hr;
4710 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4711 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4712 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4714 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4715 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4716 lpdwNumBytes, TRUE );
4719 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4720 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4721 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4723 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4724 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4725 lpdwNumBytes, FALSE );
4728 static HRESULT WINAPI DP_IF_CancelMessage
4729 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
4730 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi )
4732 HRESULT hr = DP_OK;
4734 FIXME( "(%p)->(0x%08x,0x%08x,%u): semi stub\n",
4735 This, dwMsgID, dwFlags, bAnsi );
4737 if( This->dp2->spData.lpCB->Cancel )
4739 DPSP_CANCELDATA data;
4741 TRACE( "Calling SP Cancel\n" );
4743 /* FIXME: Undocumented callback */
4745 data.lpISP = This->dp2->spData.lpISP;
4746 data.dwFlags = dwFlags;
4747 data.lprglpvSPMsgID = NULL;
4748 data.cSPMsgID = dwMsgID;
4749 data.dwMinPriority = dwMinPriority;
4750 data.dwMaxPriority = dwMaxPriority;
4752 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
4754 else
4756 FIXME( "SP doesn't implement Cancel\n" );
4759 return hr;
4762 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
4763 ( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags )
4765 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4767 if( dwFlags != 0 )
4769 return DPERR_INVALIDFLAGS;
4772 if( dwMsgID == 0 )
4774 dwFlags |= DPCANCELSEND_ALL;
4777 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE );
4780 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
4781 ( LPDIRECTPLAY4 iface, DWORD dwMsgID, DWORD dwFlags )
4783 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4785 if( dwFlags != 0 )
4787 return DPERR_INVALIDFLAGS;
4790 if( dwMsgID == 0 )
4792 dwFlags |= DPCANCELSEND_ALL;
4795 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, FALSE );
4798 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
4799 ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4800 DWORD dwFlags )
4802 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4804 if( dwFlags != 0 )
4806 return DPERR_INVALIDFLAGS;
4809 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4810 dwMaxPriority, TRUE );
4813 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
4814 ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4815 DWORD dwFlags )
4817 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4819 if( dwFlags != 0 )
4821 return DPERR_INVALIDFLAGS;
4824 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4825 dwMaxPriority, FALSE );
4828 /* Note: Hack so we can reuse the old functions without compiler warnings */
4829 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4830 # define XCAST(fun) (typeof(directPlay2WVT.fun))
4831 #else
4832 # define XCAST(fun) (void*)
4833 #endif
4835 static const IDirectPlay2Vtbl directPlay2WVT =
4837 XCAST(QueryInterface)DP_QueryInterface,
4838 XCAST(AddRef)DP_AddRef,
4839 XCAST(Release)DP_Release,
4841 DirectPlay2WImpl_AddPlayerToGroup,
4842 DirectPlay2WImpl_Close,
4843 DirectPlay2WImpl_CreateGroup,
4844 DirectPlay2WImpl_CreatePlayer,
4845 DirectPlay2WImpl_DeletePlayerFromGroup,
4846 DirectPlay2WImpl_DestroyGroup,
4847 DirectPlay2WImpl_DestroyPlayer,
4848 DirectPlay2WImpl_EnumGroupPlayers,
4849 DirectPlay2WImpl_EnumGroups,
4850 DirectPlay2WImpl_EnumPlayers,
4851 DirectPlay2WImpl_EnumSessions,
4852 DirectPlay2WImpl_GetCaps,
4853 DirectPlay2WImpl_GetGroupData,
4854 DirectPlay2WImpl_GetGroupName,
4855 DirectPlay2WImpl_GetMessageCount,
4856 DirectPlay2WImpl_GetPlayerAddress,
4857 DirectPlay2WImpl_GetPlayerCaps,
4858 DirectPlay2WImpl_GetPlayerData,
4859 DirectPlay2WImpl_GetPlayerName,
4860 DirectPlay2WImpl_GetSessionDesc,
4861 DirectPlay2WImpl_Initialize,
4862 DirectPlay2WImpl_Open,
4863 DirectPlay2WImpl_Receive,
4864 DirectPlay2WImpl_Send,
4865 DirectPlay2WImpl_SetGroupData,
4866 DirectPlay2WImpl_SetGroupName,
4867 DirectPlay2WImpl_SetPlayerData,
4868 DirectPlay2WImpl_SetPlayerName,
4869 DirectPlay2WImpl_SetSessionDesc
4871 #undef XCAST
4873 /* Note: Hack so we can reuse the old functions without compiler warnings */
4874 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4875 # define XCAST(fun) (typeof(directPlay2AVT.fun))
4876 #else
4877 # define XCAST(fun) (void*)
4878 #endif
4880 static const IDirectPlay2Vtbl directPlay2AVT =
4882 XCAST(QueryInterface)DP_QueryInterface,
4883 XCAST(AddRef)DP_AddRef,
4884 XCAST(Release)DP_Release,
4886 DirectPlay2AImpl_AddPlayerToGroup,
4887 DirectPlay2AImpl_Close,
4888 DirectPlay2AImpl_CreateGroup,
4889 DirectPlay2AImpl_CreatePlayer,
4890 DirectPlay2AImpl_DeletePlayerFromGroup,
4891 DirectPlay2AImpl_DestroyGroup,
4892 DirectPlay2AImpl_DestroyPlayer,
4893 DirectPlay2AImpl_EnumGroupPlayers,
4894 DirectPlay2AImpl_EnumGroups,
4895 DirectPlay2AImpl_EnumPlayers,
4896 DirectPlay2AImpl_EnumSessions,
4897 DirectPlay2AImpl_GetCaps,
4898 DirectPlay2AImpl_GetGroupData,
4899 DirectPlay2AImpl_GetGroupName,
4900 DirectPlay2AImpl_GetMessageCount,
4901 DirectPlay2AImpl_GetPlayerAddress,
4902 DirectPlay2AImpl_GetPlayerCaps,
4903 DirectPlay2AImpl_GetPlayerData,
4904 DirectPlay2AImpl_GetPlayerName,
4905 DirectPlay2AImpl_GetSessionDesc,
4906 DirectPlay2AImpl_Initialize,
4907 DirectPlay2AImpl_Open,
4908 DirectPlay2AImpl_Receive,
4909 DirectPlay2AImpl_Send,
4910 DirectPlay2AImpl_SetGroupData,
4911 DirectPlay2AImpl_SetGroupName,
4912 DirectPlay2AImpl_SetPlayerData,
4913 DirectPlay2AImpl_SetPlayerName,
4914 DirectPlay2AImpl_SetSessionDesc
4916 #undef XCAST
4919 /* Note: Hack so we can reuse the old functions without compiler warnings */
4920 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4921 # define XCAST(fun) (typeof(directPlay3AVT.fun))
4922 #else
4923 # define XCAST(fun) (void*)
4924 #endif
4926 static const IDirectPlay3Vtbl directPlay3AVT =
4928 XCAST(QueryInterface)DP_QueryInterface,
4929 XCAST(AddRef)DP_AddRef,
4930 XCAST(Release)DP_Release,
4932 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
4933 XCAST(Close)DirectPlay2AImpl_Close,
4934 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
4935 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
4936 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
4937 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
4938 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
4939 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
4940 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
4941 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
4942 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
4943 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
4944 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
4945 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
4946 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
4947 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
4948 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
4949 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
4950 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
4951 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
4952 XCAST(Initialize)DirectPlay2AImpl_Initialize,
4953 XCAST(Open)DirectPlay2AImpl_Open,
4954 XCAST(Receive)DirectPlay2AImpl_Receive,
4955 XCAST(Send)DirectPlay2AImpl_Send,
4956 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
4957 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
4958 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
4959 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
4960 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
4962 DirectPlay3AImpl_AddGroupToGroup,
4963 DirectPlay3AImpl_CreateGroupInGroup,
4964 DirectPlay3AImpl_DeleteGroupFromGroup,
4965 DirectPlay3AImpl_EnumConnections,
4966 DirectPlay3AImpl_EnumGroupsInGroup,
4967 DirectPlay3AImpl_GetGroupConnectionSettings,
4968 DirectPlay3AImpl_InitializeConnection,
4969 DirectPlay3AImpl_SecureOpen,
4970 DirectPlay3AImpl_SendChatMessage,
4971 DirectPlay3AImpl_SetGroupConnectionSettings,
4972 DirectPlay3AImpl_StartSession,
4973 DirectPlay3AImpl_GetGroupFlags,
4974 DirectPlay3AImpl_GetGroupParent,
4975 DirectPlay3AImpl_GetPlayerAccount,
4976 DirectPlay3AImpl_GetPlayerFlags
4978 #undef XCAST
4980 /* Note: Hack so we can reuse the old functions without compiler warnings */
4981 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4982 # define XCAST(fun) (typeof(directPlay3WVT.fun))
4983 #else
4984 # define XCAST(fun) (void*)
4985 #endif
4986 static const IDirectPlay3Vtbl directPlay3WVT =
4988 XCAST(QueryInterface)DP_QueryInterface,
4989 XCAST(AddRef)DP_AddRef,
4990 XCAST(Release)DP_Release,
4992 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
4993 XCAST(Close)DirectPlay2WImpl_Close,
4994 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
4995 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
4996 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
4997 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
4998 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
4999 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5000 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5001 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5002 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5003 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5004 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5005 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5006 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5007 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5008 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5009 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5010 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5011 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5012 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5013 XCAST(Open)DirectPlay2WImpl_Open,
5014 XCAST(Receive)DirectPlay2WImpl_Receive,
5015 XCAST(Send)DirectPlay2WImpl_Send,
5016 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5017 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5018 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5019 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5020 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5022 DirectPlay3WImpl_AddGroupToGroup,
5023 DirectPlay3WImpl_CreateGroupInGroup,
5024 DirectPlay3WImpl_DeleteGroupFromGroup,
5025 DirectPlay3WImpl_EnumConnections,
5026 DirectPlay3WImpl_EnumGroupsInGroup,
5027 DirectPlay3WImpl_GetGroupConnectionSettings,
5028 DirectPlay3WImpl_InitializeConnection,
5029 DirectPlay3WImpl_SecureOpen,
5030 DirectPlay3WImpl_SendChatMessage,
5031 DirectPlay3WImpl_SetGroupConnectionSettings,
5032 DirectPlay3WImpl_StartSession,
5033 DirectPlay3WImpl_GetGroupFlags,
5034 DirectPlay3WImpl_GetGroupParent,
5035 DirectPlay3WImpl_GetPlayerAccount,
5036 DirectPlay3WImpl_GetPlayerFlags
5038 #undef XCAST
5040 /* Note: Hack so we can reuse the old functions without compiler warnings */
5041 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5042 # define XCAST(fun) (typeof(directPlay4WVT.fun))
5043 #else
5044 # define XCAST(fun) (void*)
5045 #endif
5046 static const IDirectPlay4Vtbl directPlay4WVT =
5048 XCAST(QueryInterface)DP_QueryInterface,
5049 XCAST(AddRef)DP_AddRef,
5050 XCAST(Release)DP_Release,
5052 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
5053 XCAST(Close)DirectPlay2WImpl_Close,
5054 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
5055 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
5056 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
5057 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
5058 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5059 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5060 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5061 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5062 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5063 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5064 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5065 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5066 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5067 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5068 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5069 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5070 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5071 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5072 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5073 XCAST(Open)DirectPlay2WImpl_Open,
5074 XCAST(Receive)DirectPlay2WImpl_Receive,
5075 XCAST(Send)DirectPlay2WImpl_Send,
5076 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5077 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5078 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5079 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5080 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5082 XCAST(AddGroupToGroup)DirectPlay3WImpl_AddGroupToGroup,
5083 XCAST(CreateGroupInGroup)DirectPlay3WImpl_CreateGroupInGroup,
5084 XCAST(DeleteGroupFromGroup)DirectPlay3WImpl_DeleteGroupFromGroup,
5085 XCAST(EnumConnections)DirectPlay3WImpl_EnumConnections,
5086 XCAST(EnumGroupsInGroup)DirectPlay3WImpl_EnumGroupsInGroup,
5087 XCAST(GetGroupConnectionSettings)DirectPlay3WImpl_GetGroupConnectionSettings,
5088 XCAST(InitializeConnection)DirectPlay3WImpl_InitializeConnection,
5089 XCAST(SecureOpen)DirectPlay3WImpl_SecureOpen,
5090 XCAST(SendChatMessage)DirectPlay3WImpl_SendChatMessage,
5091 XCAST(SetGroupConnectionSettings)DirectPlay3WImpl_SetGroupConnectionSettings,
5092 XCAST(StartSession)DirectPlay3WImpl_StartSession,
5093 XCAST(GetGroupFlags)DirectPlay3WImpl_GetGroupFlags,
5094 XCAST(GetGroupParent)DirectPlay3WImpl_GetGroupParent,
5095 XCAST(GetPlayerAccount)DirectPlay3WImpl_GetPlayerAccount,
5096 XCAST(GetPlayerFlags)DirectPlay3WImpl_GetPlayerFlags,
5098 DirectPlay4WImpl_GetGroupOwner,
5099 DirectPlay4WImpl_SetGroupOwner,
5100 DirectPlay4WImpl_SendEx,
5101 DirectPlay4WImpl_GetMessageQueue,
5102 DirectPlay4WImpl_CancelMessage,
5103 DirectPlay4WImpl_CancelPriority
5105 #undef XCAST
5108 /* Note: Hack so we can reuse the old functions without compiler warnings */
5109 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5110 # define XCAST(fun) (typeof(directPlay4AVT.fun))
5111 #else
5112 # define XCAST(fun) (void*)
5113 #endif
5114 static const IDirectPlay4Vtbl directPlay4AVT =
5116 XCAST(QueryInterface)DP_QueryInterface,
5117 XCAST(AddRef)DP_AddRef,
5118 XCAST(Release)DP_Release,
5120 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
5121 XCAST(Close)DirectPlay2AImpl_Close,
5122 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
5123 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
5124 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
5125 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
5126 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
5127 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
5128 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
5129 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
5130 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
5131 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
5132 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
5133 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
5134 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5135 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5136 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5137 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5138 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5139 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5140 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5141 XCAST(Open)DirectPlay2AImpl_Open,
5142 XCAST(Receive)DirectPlay2AImpl_Receive,
5143 XCAST(Send)DirectPlay2AImpl_Send,
5144 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5145 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5146 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5147 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5148 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5150 XCAST(AddGroupToGroup)DirectPlay3AImpl_AddGroupToGroup,
5151 XCAST(CreateGroupInGroup)DirectPlay3AImpl_CreateGroupInGroup,
5152 XCAST(DeleteGroupFromGroup)DirectPlay3AImpl_DeleteGroupFromGroup,
5153 XCAST(EnumConnections)DirectPlay3AImpl_EnumConnections,
5154 XCAST(EnumGroupsInGroup)DirectPlay3AImpl_EnumGroupsInGroup,
5155 XCAST(GetGroupConnectionSettings)DirectPlay3AImpl_GetGroupConnectionSettings,
5156 XCAST(InitializeConnection)DirectPlay3AImpl_InitializeConnection,
5157 XCAST(SecureOpen)DirectPlay3AImpl_SecureOpen,
5158 XCAST(SendChatMessage)DirectPlay3AImpl_SendChatMessage,
5159 XCAST(SetGroupConnectionSettings)DirectPlay3AImpl_SetGroupConnectionSettings,
5160 XCAST(StartSession)DirectPlay3AImpl_StartSession,
5161 XCAST(GetGroupFlags)DirectPlay3AImpl_GetGroupFlags,
5162 XCAST(GetGroupParent)DirectPlay3AImpl_GetGroupParent,
5163 XCAST(GetPlayerAccount)DirectPlay3AImpl_GetPlayerAccount,
5164 XCAST(GetPlayerFlags)DirectPlay3AImpl_GetPlayerFlags,
5166 DirectPlay4AImpl_GetGroupOwner,
5167 DirectPlay4AImpl_SetGroupOwner,
5168 DirectPlay4AImpl_SendEx,
5169 DirectPlay4AImpl_GetMessageQueue,
5170 DirectPlay4AImpl_CancelMessage,
5171 DirectPlay4AImpl_CancelPriority
5173 #undef XCAST
5175 HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP,
5176 DPID idPlayer,
5177 LPVOID* lplpData )
5179 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5181 if( lpPlayer == NULL )
5183 return DPERR_INVALIDPLAYER;
5186 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
5188 return DP_OK;
5191 HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP,
5192 DPID idPlayer,
5193 LPVOID lpData )
5195 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5197 if( lpPlayer == NULL )
5199 return DPERR_INVALIDPLAYER;
5202 lpPlayer->lpPData->lpSPPlayerData = lpData;
5204 return DP_OK;
5207 /***************************************************************************
5208 * DirectPlayEnumerateAW
5210 * The pointer to the structure lpContext will be filled with the
5211 * appropriate data for each service offered by the OS. These services are
5212 * not necessarily available on this particular machine but are defined
5213 * as simple service providers under the "Service Providers" registry key.
5214 * This structure is then passed to lpEnumCallback for each of the different
5215 * services.
5217 * This API is useful only for applications written using DirectX3 or
5218 * worse. It is superseded by IDirectPlay3::EnumConnections which also
5219 * gives information on the actual connections.
5221 * defn of a service provider:
5222 * A dynamic-link library used by DirectPlay to communicate over a network.
5223 * The service provider contains all the network-specific code required
5224 * to send and receive messages. Online services and network operators can
5225 * supply service providers to use specialized hardware, protocols, communications
5226 * media, and network resources.
5229 static HRESULT DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA,
5230 LPDPENUMDPCALLBACKW lpEnumCallbackW,
5231 LPVOID lpContext)
5233 HKEY hkResult;
5234 static const WCHAR searchSubKey[] = {
5235 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
5236 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
5237 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
5238 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
5239 static const WCHAR guidKey[] = { 'G', 'u', 'i', 'd', 0 };
5240 static const WCHAR descW[] = { 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', 'W', 0 };
5242 DWORD dwIndex;
5243 FILETIME filetime;
5245 char *descriptionA = NULL;
5246 DWORD max_sizeOfDescriptionA = 0;
5247 WCHAR *descriptionW = NULL;
5248 DWORD max_sizeOfDescriptionW = 0;
5250 if (!lpEnumCallbackA && !lpEnumCallbackW)
5252 return DPERR_INVALIDPARAMS;
5255 /* Need to loop over the service providers in the registry */
5256 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, searchSubKey,
5257 0, KEY_READ, &hkResult) != ERROR_SUCCESS)
5259 /* Hmmm. Does this mean that there are no service providers? */
5260 ERR(": no service provider key in the registry - check your Wine installation !!!\n");
5261 return DPERR_GENERIC;
5264 /* Traverse all the service providers we have available */
5265 dwIndex = 0;
5266 while (1)
5268 WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */
5269 DWORD sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR);
5270 HKEY hkServiceProvider;
5271 GUID serviceProviderGUID;
5272 WCHAR guidKeyContent[(2 * 16) + 1 + 6 /* This corresponds to '{....-..-..-..-......}' */ ];
5273 DWORD sizeOfGuidKeyContent = sizeof(guidKeyContent);
5274 LONG ret_value;
5276 ret_value = RegEnumKeyExW(hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
5277 NULL, NULL, NULL, &filetime);
5278 if (ret_value == ERROR_NO_MORE_ITEMS)
5279 break;
5280 else if (ret_value != ERROR_SUCCESS)
5282 ERR(": could not enumerate on service provider key.\n");
5283 return DPERR_EXCEPTION;
5285 TRACE(" this time through sub-key %s.\n", debugstr_w(subKeyName));
5287 /* Open the key for this service provider */
5288 if (RegOpenKeyExW(hkResult, subKeyName, 0, KEY_READ, &hkServiceProvider) != ERROR_SUCCESS)
5290 ERR(": could not open registry key for service provider %s.\n", debugstr_w(subKeyName));
5291 continue;
5294 /* Get the GUID from the registry */
5295 if (RegQueryValueExW(hkServiceProvider, guidKey,
5296 NULL, NULL, (LPBYTE) guidKeyContent, &sizeOfGuidKeyContent) != ERROR_SUCCESS)
5298 ERR(": missing GUID registry data member for service provider %s.\n", debugstr_w(subKeyName));
5299 continue;
5301 if (sizeOfGuidKeyContent != sizeof(guidKeyContent))
5303 ERR(": invalid format for the GUID registry data member for service provider %s (%s).\n", debugstr_w(subKeyName), debugstr_w(guidKeyContent));
5304 continue;
5306 CLSIDFromString(guidKeyContent, &serviceProviderGUID );
5308 /* The enumeration will return FALSE if we are not to continue.
5310 * Note: on my windows box, major / minor version is 6 / 0 for all service providers
5311 * and have no relation to any of the two dwReserved1 and dwReserved2 keys.
5312 * I think that it simply means that they are in-line with DirectX 6.0
5314 if (lpEnumCallbackA)
5316 DWORD sizeOfDescription = 0;
5318 /* Note that this is the A case of this function, so use the A variant to get the description string */
5319 if (RegQueryValueExA(hkServiceProvider, "DescriptionA",
5320 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5322 ERR(": missing 'DescriptionA' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5323 continue;
5325 if (sizeOfDescription > max_sizeOfDescriptionA)
5327 HeapFree(GetProcessHeap(), 0, descriptionA);
5328 max_sizeOfDescriptionA = sizeOfDescription;
5330 descriptionA = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5331 RegQueryValueExA(hkServiceProvider, "DescriptionA",
5332 NULL, NULL, (LPBYTE) descriptionA, &sizeOfDescription);
5334 if (!lpEnumCallbackA(&serviceProviderGUID, descriptionA, 6, 0, lpContext))
5335 goto end;
5337 else
5339 DWORD sizeOfDescription = 0;
5341 if (RegQueryValueExW(hkServiceProvider, descW,
5342 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5344 ERR(": missing 'DescriptionW' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5345 continue;
5347 if (sizeOfDescription > max_sizeOfDescriptionW)
5349 HeapFree(GetProcessHeap(), 0, descriptionW);
5350 max_sizeOfDescriptionW = sizeOfDescription;
5352 descriptionW = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5353 RegQueryValueExW(hkServiceProvider, descW,
5354 NULL, NULL, (LPBYTE) descriptionW, &sizeOfDescription);
5356 if (!lpEnumCallbackW(&serviceProviderGUID, descriptionW, 6, 0, lpContext))
5357 goto end;
5360 dwIndex++;
5363 end:
5364 HeapFree(GetProcessHeap(), 0, descriptionA);
5365 HeapFree(GetProcessHeap(), 0, descriptionW);
5367 return DP_OK;
5370 /***************************************************************************
5371 * DirectPlayEnumerate [DPLAYX.9]
5372 * DirectPlayEnumerateA [DPLAYX.2]
5374 HRESULT WINAPI DirectPlayEnumerateA(LPDPENUMDPCALLBACKA lpEnumCallback, LPVOID lpContext )
5376 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5378 return DirectPlayEnumerateAW(lpEnumCallback, NULL, lpContext);
5381 /***************************************************************************
5382 * DirectPlayEnumerateW [DPLAYX.3]
5384 HRESULT WINAPI DirectPlayEnumerateW(LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5386 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5388 return DirectPlayEnumerateAW(NULL, lpEnumCallback, lpContext);
5391 typedef struct tagCreateEnum
5393 LPVOID lpConn;
5394 LPCGUID lpGuid;
5395 } CreateEnumData, *lpCreateEnumData;
5397 /* Find and copy the matching connection for the SP guid */
5398 static BOOL CALLBACK cbDPCreateEnumConnections(
5399 LPCGUID lpguidSP,
5400 LPVOID lpConnection,
5401 DWORD dwConnectionSize,
5402 LPCDPNAME lpName,
5403 DWORD dwFlags,
5404 LPVOID lpContext)
5406 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5408 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5410 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5412 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5413 dwConnectionSize );
5414 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5416 /* Found the record that we were looking for */
5417 return FALSE;
5420 /* Haven't found what were looking for yet */
5421 return TRUE;
5425 /***************************************************************************
5426 * DirectPlayCreate [DPLAYX.1]
5429 HRESULT WINAPI DirectPlayCreate
5430 ( LPGUID lpGUID, LPDIRECTPLAY *lplpDP, IUnknown *pUnk )
5432 HRESULT hr;
5433 LPDIRECTPLAY3A lpDP3A;
5434 CreateEnumData cbData;
5436 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5438 if( pUnk != NULL )
5440 return CLASS_E_NOAGGREGATION;
5443 if( (lplpDP == NULL) || (lpGUID == NULL) )
5445 return DPERR_INVALIDPARAMS;
5449 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5450 give them an IDirectPlay2A object and hope that doesn't cause problems */
5451 if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
5453 return DPERR_UNAVAILABLE;
5456 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
5458 /* The GUID_NULL means don't bind a service provider. Just return the
5459 interface as is */
5460 return DP_OK;
5463 /* Bind the desired service provider since lpGUID is non NULL */
5464 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
5466 /* We're going to use a DP3 interface */
5467 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
5468 (LPVOID*)&lpDP3A );
5469 if( FAILED(hr) )
5471 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
5472 return hr;
5475 cbData.lpConn = NULL;
5476 cbData.lpGuid = lpGUID;
5478 /* We were given a service provider, find info about it... */
5479 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
5480 &cbData, DPCONNECTION_DIRECTPLAY );
5481 if( ( FAILED(hr) ) ||
5482 ( cbData.lpConn == NULL )
5485 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
5486 IDirectPlayX_Release( lpDP3A );
5487 return DPERR_UNAVAILABLE;
5490 /* Initialize the service provider */
5491 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
5492 if( FAILED(hr) )
5494 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
5495 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5496 IDirectPlayX_Release( lpDP3A );
5497 return hr;
5500 /* Release our version of the interface now that we're done with it */
5501 IDirectPlayX_Release( lpDP3A );
5502 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5504 return DP_OK;