dplayx: Tests for Get/SetPlayerName.
[wine/gsoc_dplay.git] / dlls / dplayx / dplay.c
blobc150d7e8578e00acf5e482c3045495699cc95d4e
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( lpidPlayer == NULL )
1616 return DPERR_INVALIDPARAMS;
1619 if( dwFlags & DPPLAYER_SERVERPLAYER )
1621 *lpidPlayer = DPID_SERVERPLAYER;
1623 else
1625 *lpidPlayer = DPID_UNKNOWN;
1628 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1629 lpData, dwDataSize, dwFlags, TRUE );
1632 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
1633 ( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1634 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1636 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1638 if( lpidPlayer == NULL )
1640 return DPERR_INVALIDPARAMS;
1643 if( dwFlags & DPPLAYER_SERVERPLAYER )
1645 *lpidPlayer = DPID_SERVERPLAYER;
1647 else
1649 *lpidPlayer = DPID_UNKNOWN;
1652 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1653 lpData, dwDataSize, dwFlags, FALSE );
1656 static DPID DP_GetRemoteNextObjectId(void)
1658 FIXME( ":stub\n" );
1660 /* Hack solution */
1661 return DP_NextObjectId();
1664 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
1665 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
1666 DPID idPlayer, BOOL bAnsi )
1668 HRESULT hr = DP_OK;
1670 lpGroupData lpGData;
1671 lpPlayerList lpPList;
1673 TRACE( "(%p)->(%p,0x%08x,0x%08x,%u)\n",
1674 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
1676 /* Find the group */
1677 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1679 return DPERR_INVALIDGROUP;
1682 /* Find the player */
1683 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
1685 return DPERR_INVALIDPLAYER;
1688 /* Remove the player shortcut from the group */
1689 DPQ_REMOVE_ENTRY( lpGData->players, players, lpPData->dpid, ==, idPlayer, lpPList );
1691 if( lpPList == NULL )
1693 return DPERR_INVALIDPLAYER;
1696 /* One less reference */
1697 lpPList->lpPData->uRef--;
1699 /* Delete the Player List element */
1700 HeapFree( GetProcessHeap(), 0, lpPList );
1702 /* Inform the SP if they care */
1703 if( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1705 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1707 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1709 data.idPlayer = idPlayer;
1710 data.idGroup = idGroup;
1711 data.lpISP = This->dp2->spData.lpISP;
1713 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1716 /* Need to send a DELETEPLAYERFROMGROUP message */
1717 FIXME( "Need to send a message\n" );
1719 return hr;
1722 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
1723 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
1725 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1726 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, TRUE );
1729 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
1730 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
1732 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1733 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, FALSE );
1736 typedef struct _DPRGOPContext
1738 IDirectPlay3Impl* This;
1739 BOOL bAnsi;
1740 DPID idGroup;
1741 } DPRGOPContext, *lpDPRGOPContext;
1743 static BOOL CALLBACK
1744 cbRemoveGroupOrPlayer(
1745 DPID dpId,
1746 DWORD dwPlayerType,
1747 LPCDPNAME lpName,
1748 DWORD dwFlags,
1749 LPVOID lpContext )
1751 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1753 TRACE( "Removing element:0x%08x (type:0x%08x) from element:0x%08x\n",
1754 dpId, dwPlayerType, lpCtxt->idGroup );
1756 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1758 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt->This, lpCtxt->idGroup,
1759 dpId )
1763 ERR( "Unable to delete group 0x%08x from group 0x%08x\n",
1764 dpId, lpCtxt->idGroup );
1767 else
1769 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl*)lpCtxt->This,
1770 NULL, lpCtxt->idGroup,
1771 dpId, lpCtxt->bAnsi )
1775 ERR( "Unable to delete player 0x%08x from grp 0x%08x\n",
1776 dpId, lpCtxt->idGroup );
1780 return TRUE; /* Continue enumeration */
1783 static HRESULT WINAPI DP_IF_DestroyGroup
1784 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi )
1786 lpGroupData lpGData;
1787 DPRGOPContext context;
1789 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1790 This, lpMsgHdr, idGroup, bAnsi );
1792 /* Find the group */
1793 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1795 return DPERR_INVALIDPLAYER; /* yes player */
1798 context.This = (IDirectPlay3Impl*)This;
1799 context.bAnsi = bAnsi;
1800 context.idGroup = idGroup;
1802 /* Remove all players that this group has */
1803 DP_IF_EnumGroupPlayers( This, idGroup, NULL,
1804 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1806 /* Remove all links to groups that this group has since this is dp3 */
1807 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This, idGroup, NULL,
1808 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1810 /* Remove this group from the parent group - if it has one */
1811 if( ( idGroup != DPID_SYSTEM_GROUP ) &&
1812 ( lpGData->parent != DPID_SYSTEM_GROUP )
1815 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl*)This, lpGData->parent,
1816 idGroup );
1819 /* Now delete this group data and list from the system group */
1820 DP_DeleteGroup( This, idGroup );
1822 /* Let the SP know that we've destroyed this group */
1823 if( This->dp2->spData.lpCB->DeleteGroup )
1825 DPSP_DELETEGROUPDATA data;
1827 FIXME( "data.dwFlags is incorrect\n" );
1829 data.idGroup = idGroup;
1830 data.dwFlags = 0;
1831 data.lpISP = This->dp2->spData.lpISP;
1833 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1836 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1838 return DP_OK;
1841 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
1842 ( LPDIRECTPLAY2A iface, DPID idGroup )
1844 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1845 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
1848 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
1849 ( LPDIRECTPLAY2 iface, DPID idGroup )
1851 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1852 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
1855 typedef struct _DPFAGContext
1857 IDirectPlay2Impl* This;
1858 DPID idPlayer;
1859 BOOL bAnsi;
1860 } DPFAGContext, *lpDPFAGContext;
1862 static HRESULT WINAPI DP_IF_DestroyPlayer
1863 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi )
1865 DPFAGContext cbContext;
1867 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1868 This, lpMsgHdr, idPlayer, bAnsi );
1870 if( This->dp2->connectionInitialized == NO_PROVIDER )
1872 return DPERR_UNINITIALIZED;
1875 if( DP_FindPlayer( This, idPlayer ) == NULL )
1877 return DPERR_INVALIDPLAYER;
1880 /* FIXME: If the player is remote, we must be the host to delete this */
1882 cbContext.This = This;
1883 cbContext.idPlayer = idPlayer;
1884 cbContext.bAnsi = bAnsi;
1886 /* Find each group and call DeletePlayerFromGroup if the player is a
1887 member of the group */
1888 DP_IF_EnumGroups( This, NULL, cbDeletePlayerFromAllGroups,
1889 (LPVOID)&cbContext, DPENUMGROUPS_ALL, bAnsi );
1891 /* Now delete player and player list from the sys group */
1892 DP_DeletePlayer( This, idPlayer );
1894 /* Let the SP know that we've destroyed this group */
1895 if( This->dp2->spData.lpCB->DeletePlayer )
1897 DPSP_DELETEPLAYERDATA data;
1899 FIXME( "data.dwFlags is incorrect\n" );
1901 data.idPlayer = idPlayer;
1902 data.dwFlags = 0;
1903 data.lpISP = This->dp2->spData.lpISP;
1905 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
1908 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
1910 return DP_OK;
1913 static BOOL CALLBACK
1914 cbDeletePlayerFromAllGroups(
1915 DPID dpId,
1916 DWORD dwPlayerType,
1917 LPCDPNAME lpName,
1918 DWORD dwFlags,
1919 LPVOID lpContext )
1921 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
1923 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1925 DP_IF_DeletePlayerFromGroup( lpCtxt->This, NULL, dpId, lpCtxt->idPlayer,
1926 lpCtxt->bAnsi );
1928 /* Enumerate all groups in this group since this will normally only
1929 * be called for top level groups
1931 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)lpCtxt->This,
1932 dpId, NULL,
1933 cbDeletePlayerFromAllGroups,
1934 lpContext, DPENUMGROUPS_ALL,
1935 lpCtxt->bAnsi );
1938 else
1940 ERR( "Group callback has dwPlayerType = 0x%08x\n", dwPlayerType );
1943 return TRUE;
1946 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
1947 ( LPDIRECTPLAY2A iface, DPID idPlayer )
1949 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1950 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
1953 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
1954 ( LPDIRECTPLAY2 iface, DPID idPlayer )
1956 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1957 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
1960 static HRESULT WINAPI DP_IF_EnumGroupPlayers
1961 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
1962 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1963 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1965 lpGroupData lpGData;
1966 lpPlayerList lpPList;
1968 FIXME("(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
1969 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
1970 lpContext, dwFlags, bAnsi );
1972 if( This->dp2->connectionInitialized == NO_PROVIDER )
1974 return DPERR_UNINITIALIZED;
1977 /* Find the group */
1978 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1980 return DPERR_INVALIDGROUP;
1983 if( DPQ_IS_EMPTY( lpGData->players ) )
1985 return DP_OK;
1988 lpPList = DPQ_FIRST( lpGData->players );
1990 /* Walk the players in this group */
1991 for( ;; )
1993 /* We do not enum the name server or app server as they are of no
1994 * consequence to the end user.
1996 if( ( lpPList->lpPData->dpid != DPID_NAME_SERVER ) &&
1997 ( lpPList->lpPData->dpid != DPID_SERVERPLAYER )
2001 /* FIXME: Need to add stuff for dwFlags checking */
2003 if( !lpEnumPlayersCallback2( lpPList->lpPData->dpid, DPPLAYERTYPE_PLAYER,
2004 &lpPList->lpPData->name,
2005 lpPList->lpPData->dwFlags,
2006 lpContext )
2009 /* User requested break */
2010 return DP_OK;
2014 if( DPQ_IS_ENDOFLIST( lpPList->players ) )
2016 break;
2019 lpPList = DPQ_NEXT( lpPList->players );
2022 return DP_OK;
2025 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
2026 ( LPDIRECTPLAY2A iface, DPID idGroup, LPGUID lpguidInstance,
2027 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2028 LPVOID lpContext, DWORD dwFlags )
2030 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2031 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2032 lpEnumPlayersCallback2, lpContext,
2033 dwFlags, TRUE );
2036 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
2037 ( LPDIRECTPLAY2 iface, DPID idGroup, LPGUID lpguidInstance,
2038 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2039 LPVOID lpContext, DWORD dwFlags )
2041 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2042 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2043 lpEnumPlayersCallback2, lpContext,
2044 dwFlags, FALSE );
2047 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2048 static HRESULT WINAPI DP_IF_EnumGroups
2049 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2050 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2051 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2053 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This,
2054 DPID_SYSTEM_GROUP, lpguidInstance,
2055 lpEnumPlayersCallback2, lpContext,
2056 dwFlags, bAnsi );
2059 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
2060 ( LPDIRECTPLAY2A 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, TRUE );
2069 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
2070 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2071 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2072 LPVOID lpContext, DWORD dwFlags )
2074 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2075 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2076 lpContext, dwFlags, FALSE );
2079 static HRESULT WINAPI DP_IF_EnumPlayers
2080 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2081 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2082 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2084 return DP_IF_EnumGroupPlayers( This, DPID_SYSTEM_GROUP, lpguidInstance,
2085 lpEnumPlayersCallback2, lpContext,
2086 dwFlags, bAnsi );
2089 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
2090 ( LPDIRECTPLAY2A 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, TRUE );
2099 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
2100 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2101 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2102 LPVOID lpContext, DWORD dwFlags )
2104 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2105 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2106 lpContext, dwFlags, FALSE );
2109 /* This function should call the registered callback function that the user
2110 passed into EnumSessions for each entry available.
2112 static void DP_InvokeEnumSessionCallbacks
2113 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2114 LPVOID lpNSInfo,
2115 DWORD dwTimeout,
2116 LPVOID lpContext )
2118 LPDPSESSIONDESC2 lpSessionDesc;
2120 FIXME( ": not checking for conditions\n" );
2122 /* Not sure if this should be pruning but it's convenient */
2123 NS_PruneSessionCache( lpNSInfo );
2125 NS_ResetSessionEnumeration( lpNSInfo );
2127 /* Enumerate all sessions */
2128 /* FIXME: Need to indicate ANSI */
2129 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2131 TRACE( "EnumSessionsCallback2 invoked\n" );
2132 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2134 return;
2138 /* Invoke one last time to indicate that there is no more to come */
2139 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2142 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2144 EnumSessionAsyncCallbackData* data = (EnumSessionAsyncCallbackData*)lpContext;
2145 HANDLE hSuicideRequest = data->hSuicideRequest;
2146 DWORD dwTimeout = data->dwTimeout;
2148 TRACE( "Thread started with timeout = 0x%08x\n", dwTimeout );
2150 for( ;; )
2152 HRESULT hr;
2154 /* Sleep up to dwTimeout waiting for request to terminate thread */
2155 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2157 TRACE( "Thread terminating on terminate request\n" );
2158 break;
2161 /* Now resend the enum request */
2162 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2163 data->dwEnumSessionFlags,
2164 data->lpSpData );
2166 if( FAILED(hr) )
2168 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2169 /* FIXME: Should we kill this thread? How to inform the main thread? */
2174 TRACE( "Thread terminating\n" );
2176 /* Clean up the thread data */
2177 CloseHandle( hSuicideRequest );
2178 HeapFree( GetProcessHeap(), 0, lpContext );
2180 /* FIXME: Need to have some notification to main app thread that this is
2181 * dead. It would serve two purposes. 1) allow sync on termination
2182 * so that we don't actually send something to ourselves when we
2183 * become name server (race condition) and 2) so that if we die
2184 * abnormally something else will be able to tell.
2187 return 1;
2190 static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
2192 /* Does a thread exist? If so we were doing an async enum session */
2193 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2195 TRACE( "Killing EnumSession thread %p\n",
2196 This->dp2->hEnumSessionThread );
2198 /* Request that the thread kill itself nicely */
2199 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2200 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2202 /* We no longer need to know about the thread */
2203 CloseHandle( This->dp2->hEnumSessionThread );
2205 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2209 static HRESULT WINAPI DP_IF_EnumSessions
2210 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2211 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2212 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2214 HRESULT hr = DP_OK;
2216 TRACE( "(%p)->(%p,0x%08x,%p,%p,0x%08x,%u)\n",
2217 This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags,
2218 bAnsi );
2219 if( This->dp2->connectionInitialized == NO_PROVIDER )
2221 return DPERR_UNINITIALIZED;
2224 /* Can't enumerate if the interface is already open */
2225 if( This->dp2->bConnectionOpen )
2227 return DPERR_GENERIC;
2230 #if 1
2231 /* The loading of a lobby provider _seems_ to require a backdoor loading
2232 * of the service provider to also associate with this DP object. This is
2233 * because the app doesn't seem to have to call EnumConnections and
2234 * InitializeConnection for the SP before calling this method. As such
2235 * we'll do their dirty work for them with a quick hack so as to always
2236 * load the TCP/IP service provider.
2238 * The correct solution would seem to involve creating a dialog box which
2239 * contains the possible SPs. These dialog boxes most likely follow SDK
2240 * examples.
2242 if( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
2244 LPVOID lpConnection;
2245 DWORD dwSize;
2247 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2249 if( !DP_BuildSPCompoundAddr( (LPGUID)&DPSPGUID_TCPIP, &lpConnection, &dwSize ) )
2251 ERR( "Can't build compound addr\n" );
2252 return DPERR_GENERIC;
2255 hr = DP_IF_InitializeConnection( (IDirectPlay3Impl*)This, lpConnection,
2256 0, bAnsi );
2257 if( FAILED(hr) )
2259 return hr;
2262 /* Free up the address buffer */
2263 HeapFree( GetProcessHeap(), 0, lpConnection );
2265 /* The SP is now initialized */
2266 This->dp2->bSPInitialized = TRUE;
2268 #endif
2271 /* Use the service provider default? */
2272 if( dwTimeout == 0 )
2274 DPCAPS spCaps;
2275 spCaps.dwSize = sizeof( spCaps );
2277 DP_IF_GetCaps( This, &spCaps, 0 );
2278 dwTimeout = spCaps.dwTimeout;
2280 /* The service provider doesn't provide one either! */
2281 if( dwTimeout == 0 )
2283 /* Provide the TCP/IP default */
2284 dwTimeout = DPMSG_WAIT_5_SECS;
2288 if( dwFlags & DPENUMSESSIONS_STOPASYNC )
2290 DP_KillEnumSessionThread( This );
2291 return hr;
2294 if( ( dwFlags & DPENUMSESSIONS_ASYNC ) )
2296 /* Enumerate everything presently in the local session cache */
2297 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2298 This->dp2->lpNameServerData, dwTimeout,
2299 lpContext );
2301 if( This->dp2->dwEnumSessionLock != 0 )
2302 return DPERR_CONNECTING;
2304 /* See if we've already created a thread to service this interface */
2305 if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2307 DWORD dwThreadId;
2308 This->dp2->dwEnumSessionLock++;
2310 /* Send the first enum request inline since the user may cancel a dialog
2311 * if one is presented. Also, may also have a connecting return code.
2313 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2314 dwFlags, &This->dp2->spData );
2316 if( !FAILED(hr) )
2318 EnumSessionAsyncCallbackData* lpData
2319 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpData ) );
2320 /* FIXME: need to kill the thread on object deletion */
2321 lpData->lpSpData = &This->dp2->spData;
2323 lpData->requestGuid = lpsd->guidApplication;
2324 lpData->dwEnumSessionFlags = dwFlags;
2325 lpData->dwTimeout = dwTimeout;
2327 This->dp2->hKillEnumSessionThreadEvent =
2328 CreateEventW( NULL, TRUE, FALSE, NULL );
2330 if( !DuplicateHandle( GetCurrentProcess(),
2331 This->dp2->hKillEnumSessionThreadEvent,
2332 GetCurrentProcess(),
2333 &lpData->hSuicideRequest,
2334 0, FALSE, DUPLICATE_SAME_ACCESS )
2337 ERR( "Can't duplicate thread killing handle\n" );
2340 TRACE( ": creating EnumSessionsRequest thread\n" );
2342 This->dp2->hEnumSessionThread = CreateThread( NULL,
2344 DP_EnumSessionsSendAsyncRequestThread,
2345 lpData,
2347 &dwThreadId );
2349 This->dp2->dwEnumSessionLock--;
2352 else
2354 /* Invalidate the session cache for the interface */
2355 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2357 /* Send the broadcast for session enumeration */
2358 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2359 dwFlags,
2360 &This->dp2->spData );
2363 SleepEx( dwTimeout, FALSE );
2365 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2366 This->dp2->lpNameServerData, dwTimeout,
2367 lpContext );
2370 return hr;
2373 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2374 ( LPDIRECTPLAY2A 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, TRUE );
2383 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2384 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2385 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2386 LPVOID lpContext, DWORD dwFlags )
2388 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2389 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2390 lpContext, dwFlags, FALSE );
2393 static HRESULT WINAPI DP_IF_GetPlayerCaps
2394 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
2395 DWORD dwFlags )
2397 DPSP_GETCAPSDATA data;
2399 TRACE("(%p)->(0x%08x,%p,0x%08x)\n", This, idPlayer, lpDPCaps, dwFlags);
2401 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2403 return DPERR_UNINITIALIZED;
2406 /* Query the service provider */
2407 data.idPlayer = idPlayer;
2408 data.dwFlags = dwFlags;
2409 data.lpCaps = lpDPCaps;
2410 data.lpISP = This->dp2->spData.lpISP;
2412 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2415 static HRESULT WINAPI DP_IF_GetCaps
2416 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags )
2418 return DP_IF_GetPlayerCaps( This, DPID_ALLPLAYERS, lpDPCaps, dwFlags );
2421 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2422 ( LPDIRECTPLAY2A iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2424 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2425 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2428 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2429 ( LPDIRECTPLAY2 iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2431 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2432 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2435 static HRESULT WINAPI DP_IF_GetGroupData
2436 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2437 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2439 lpGroupData lpGData;
2440 DWORD dwRequiredBufferSize;
2441 LPVOID lpCopyDataFrom;
2443 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2444 This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi );
2446 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2448 return DPERR_INVALIDGROUP;
2451 /* How much buffer is required? */
2452 if( dwFlags & DPSET_LOCAL )
2454 dwRequiredBufferSize = lpGData->dwLocalDataSize;
2455 lpCopyDataFrom = lpGData->lpLocalData;
2457 else
2459 dwRequiredBufferSize = lpGData->dwRemoteDataSize;
2460 lpCopyDataFrom = lpGData->lpRemoteData;
2463 /* Is the user requesting to know how big a buffer is required? */
2464 if( ( lpData == NULL ) ||
2465 ( *lpdwDataSize < dwRequiredBufferSize )
2468 *lpdwDataSize = dwRequiredBufferSize;
2469 return DPERR_BUFFERTOOSMALL;
2472 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2474 return DP_OK;
2477 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2478 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2479 LPDWORD lpdwDataSize, DWORD dwFlags )
2481 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2482 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2483 dwFlags, TRUE );
2486 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2487 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2488 LPDWORD lpdwDataSize, DWORD dwFlags )
2490 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2491 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2492 dwFlags, FALSE );
2495 static HRESULT WINAPI DP_IF_GetGroupName
2496 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2497 LPDWORD lpdwDataSize, BOOL bAnsi )
2499 lpGroupData lpGData;
2500 LPDPNAME lpName = (LPDPNAME)lpData;
2501 DWORD dwRequiredDataSize;
2503 FIXME("(%p)->(0x%08x,%p,%p,%u) ANSI ignored\n",
2504 This, idGroup, lpData, lpdwDataSize, bAnsi );
2506 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2508 return DPERR_INVALIDGROUP;
2511 dwRequiredDataSize = lpGData->name.dwSize;
2513 if( lpGData->name.u1.lpszShortNameA )
2515 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
2518 if( lpGData->name.u2.lpszLongNameA )
2520 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
2523 if( ( lpData == NULL ) ||
2524 ( *lpdwDataSize < dwRequiredDataSize )
2527 *lpdwDataSize = dwRequiredDataSize;
2528 return DPERR_BUFFERTOOSMALL;
2531 /* Copy the structure */
2532 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2534 if( lpGData->name.u1.lpszShortNameA )
2536 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2537 lpGData->name.u1.lpszShortNameA );
2539 else
2541 lpName->u1.lpszShortNameA = NULL;
2544 if( lpGData->name.u1.lpszShortNameA )
2546 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2547 lpGData->name.u2.lpszLongNameA );
2549 else
2551 lpName->u2.lpszLongNameA = NULL;
2554 return DP_OK;
2557 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2558 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2559 LPDWORD lpdwDataSize )
2561 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2562 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2565 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2566 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2567 LPDWORD lpdwDataSize )
2569 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2570 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2573 static HRESULT WINAPI DP_IF_GetMessageCount
2574 ( IDirectPlay2Impl* This, DPID idPlayer,
2575 LPDWORD lpdwCount, BOOL bAnsi )
2577 FIXME("(%p)->(0x%08x,%p,%u): stub\n", This, idPlayer, lpdwCount, bAnsi );
2578 return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer,
2579 DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL,
2580 bAnsi );
2583 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2584 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDWORD lpdwCount )
2586 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2587 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, TRUE );
2590 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2591 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDWORD lpdwCount )
2593 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2594 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, FALSE );
2597 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2598 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2600 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2601 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2602 return DP_OK;
2605 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2606 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2608 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2609 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2610 return DP_OK;
2613 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2614 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2615 DWORD dwFlags )
2617 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2618 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2621 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2622 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2623 DWORD dwFlags )
2625 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2626 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2629 static HRESULT WINAPI DP_IF_GetPlayerData
2630 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2631 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2633 lpPlayerList lpPList;
2634 DWORD dwRequiredBufferSize;
2635 LPVOID lpCopyDataFrom;
2637 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2638 This, idPlayer, lpData, lpdwDataSize, dwFlags, bAnsi );
2640 if( This->dp2->connectionInitialized == NO_PROVIDER )
2642 return DPERR_UNINITIALIZED;
2645 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2647 return DPERR_INVALIDPLAYER;
2650 /* How much buffer is required? */
2651 if( dwFlags & DPSET_LOCAL )
2653 dwRequiredBufferSize = lpPList->lpPData->dwLocalDataSize;
2654 lpCopyDataFrom = lpPList->lpPData->lpLocalData;
2656 else
2658 dwRequiredBufferSize = lpPList->lpPData->dwRemoteDataSize;
2659 lpCopyDataFrom = lpPList->lpPData->lpRemoteData;
2662 /* Is the user requesting to know how big a buffer is required? */
2663 if( ( lpData == NULL ) ||
2664 ( *lpdwDataSize < dwRequiredBufferSize )
2667 *lpdwDataSize = dwRequiredBufferSize;
2668 return DPERR_BUFFERTOOSMALL;
2671 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2673 return DP_OK;
2676 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2677 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2678 LPDWORD lpdwDataSize, DWORD dwFlags )
2680 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2681 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2682 dwFlags, TRUE );
2685 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2686 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2687 LPDWORD lpdwDataSize, DWORD dwFlags )
2689 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2690 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2691 dwFlags, FALSE );
2694 static HRESULT WINAPI DP_IF_GetPlayerName
2695 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2696 LPDWORD lpdwDataSize, BOOL bAnsi )
2698 lpPlayerList lpPList;
2699 LPDPNAME lpName = (LPDPNAME)lpData;
2700 DWORD dwRequiredDataSize;
2702 FIXME( "(%p)->(0x%08x,%p,%p,%u): ANSI\n",
2703 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2705 if( This->dp2->connectionInitialized == NO_PROVIDER )
2707 return DPERR_UNINITIALIZED;
2710 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2712 return DPERR_INVALIDPLAYER;
2715 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
2717 if( lpPList->lpPData->name.u1.lpszShortNameA )
2719 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
2722 if( lpPList->lpPData->name.u2.lpszLongNameA )
2724 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
2727 if( ( lpData == NULL ) ||
2728 ( *lpdwDataSize < dwRequiredDataSize )
2731 *lpdwDataSize = dwRequiredDataSize;
2732 return DPERR_BUFFERTOOSMALL;
2735 /* Copy the structure */
2736 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
2738 if( lpPList->lpPData->name.u1.lpszShortNameA )
2740 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2741 lpPList->lpPData->name.u1.lpszShortNameA );
2743 else
2745 lpName->u1.lpszShortNameA = NULL;
2748 if( lpPList->lpPData->name.u1.lpszShortNameA )
2750 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2751 lpPList->lpPData->name.u2.lpszLongNameA );
2753 else
2755 lpName->u2.lpszLongNameA = NULL;
2758 return DP_OK;
2761 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2762 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2763 LPDWORD lpdwDataSize )
2765 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2766 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
2769 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2770 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2771 LPDWORD lpdwDataSize )
2773 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2774 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
2777 static HRESULT WINAPI DP_GetSessionDesc
2778 ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize,
2779 BOOL bAnsi )
2781 DWORD dwRequiredSize;
2783 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
2785 if( This->dp2->connectionInitialized == NO_PROVIDER )
2787 return DPERR_UNINITIALIZED;
2790 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
2792 return DPERR_INVALIDPARAMS;
2795 /* FIXME: Get from This->dp2->lpSessionDesc */
2796 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
2798 if ( ( lpData == NULL ) ||
2799 ( *lpdwDataSize < dwRequiredSize )
2802 *lpdwDataSize = dwRequiredSize;
2803 return DPERR_BUFFERTOOSMALL;
2806 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
2808 return DP_OK;
2811 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
2812 ( LPDIRECTPLAY2A iface, LPVOID lpData, LPDWORD lpdwDataSize )
2814 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2815 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2818 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
2819 ( LPDIRECTPLAY2 iface, LPVOID lpData, LPDWORD lpdwDataSize )
2821 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2822 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2825 /* Intended only for COM compatibility. Always returns an error. */
2826 static HRESULT WINAPI DirectPlay2AImpl_Initialize
2827 ( LPDIRECTPLAY2A iface, LPGUID lpGUID )
2829 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2830 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2831 return DPERR_ALREADYINITIALIZED;
2834 /* Intended only for COM compatibility. Always returns an error. */
2835 static HRESULT WINAPI DirectPlay2WImpl_Initialize
2836 ( LPDIRECTPLAY2 iface, LPGUID lpGUID )
2838 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2839 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2840 return DPERR_ALREADYINITIALIZED;
2844 static HRESULT WINAPI DP_SecureOpen
2845 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
2846 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
2847 BOOL bAnsi )
2849 HRESULT hr = DP_OK;
2851 FIXME( "(%p)->(%p,0x%08x,%p,%p): partial stub\n",
2852 This, lpsd, dwFlags, lpSecurity, lpCredentials );
2854 if( This->dp2->connectionInitialized == NO_PROVIDER )
2856 return DPERR_UNINITIALIZED;
2859 if( lpsd->dwSize != sizeof(DPSESSIONDESC2) )
2861 TRACE( ": rejecting invalid dpsd size (%d).\n", lpsd->dwSize );
2862 return DPERR_INVALIDPARAMS;
2865 if( This->dp2->bConnectionOpen )
2867 TRACE( ": rejecting already open connection.\n" );
2868 return DPERR_ALREADYINITIALIZED;
2871 /* If we're enumerating, kill the thread */
2872 DP_KillEnumSessionThread( This );
2874 if( dwFlags & DPOPEN_CREATE )
2876 /* Rightoo - this computer is the host and the local computer needs to be
2877 the name server so that others can join this session */
2878 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
2880 This->dp2->bHostInterface = TRUE;
2882 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
2883 if( FAILED( hr ) )
2885 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
2886 return hr;
2890 /* Invoke the conditional callback for the service provider */
2891 if( This->dp2->spData.lpCB->Open )
2893 DPSP_OPENDATA data;
2895 FIXME( "Not all data fields are correct. Need new parameter\n" );
2897 data.bCreate = (dwFlags & DPOPEN_CREATE ) ? TRUE : FALSE;
2898 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
2899 : NS_GetNSAddr( This->dp2->lpNameServerData );
2900 data.lpISP = This->dp2->spData.lpISP;
2901 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) ? TRUE : FALSE;
2902 data.dwOpenFlags = dwFlags;
2903 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
2905 hr = (*This->dp2->spData.lpCB->Open)(&data);
2906 if( FAILED( hr ) )
2908 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
2909 return hr;
2914 /* Create the system group of which everything is a part of */
2915 DPID systemGroup = DPID_SYSTEM_GROUP;
2917 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
2918 NULL, 0, 0, TRUE );
2922 if( dwFlags & DPOPEN_JOIN )
2924 DPID dpidServerId = DPID_UNKNOWN;
2926 /* Create the server player for this interface. This way we can receive
2927 * messages for this session.
2929 /* FIXME: I suppose that we should be setting an event for a receive
2930 * type of thing. That way the messaging thread could know to wake
2931 * up. DPlay would then trigger the hEvent for the player the
2932 * message is directed to.
2934 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
2936 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
2939 else if( dwFlags & DPOPEN_CREATE )
2941 DPID dpidNameServerId = DPID_NAME_SERVER;
2943 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
2944 0, DPPLAYER_SERVERPLAYER, bAnsi );
2947 if( FAILED(hr) )
2949 ERR( "Couldn't create name server/system player: %s\n",
2950 DPLAYX_HresultToString(hr) );
2953 return hr;
2956 static HRESULT WINAPI DirectPlay2AImpl_Open
2957 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2959 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2960 TRACE("(%p)->(%p,0x%08x)\n", This, lpsd, dwFlags );
2961 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, TRUE );
2964 static HRESULT WINAPI DirectPlay2WImpl_Open
2965 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2967 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2968 TRACE("(%p)->(%p,0x%08x)\n", This, lpsd, dwFlags );
2969 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, FALSE );
2972 static HRESULT WINAPI DP_IF_Receive
2973 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
2974 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi )
2976 LPDPMSG lpMsg = NULL;
2978 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p,%u): stub\n",
2979 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
2981 if( This->dp2->connectionInitialized == NO_PROVIDER )
2983 return DPERR_UNINITIALIZED;
2986 if( dwFlags == 0 )
2988 dwFlags = DPRECEIVE_ALL;
2991 /* If the lpData is NULL, we must be peeking the message */
2992 if( ( lpData == NULL ) &&
2993 !( dwFlags & DPRECEIVE_PEEK )
2996 return DPERR_INVALIDPARAMS;
2999 if( dwFlags & DPRECEIVE_ALL )
3001 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
3003 if( !( dwFlags & DPRECEIVE_PEEK ) )
3005 FIXME( "Remove from queue\n" );
3008 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
3009 ( dwFlags & DPRECEIVE_FROMPLAYER )
3012 FIXME( "Find matching message 0x%08x\n", dwFlags );
3014 else
3016 ERR( "Hmmm..dwFlags 0x%08x\n", dwFlags );
3019 if( lpMsg == NULL )
3021 return DPERR_NOMESSAGES;
3024 /* Copy into the provided buffer */
3025 CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
3027 return DP_OK;
3030 static HRESULT WINAPI DirectPlay2AImpl_Receive
3031 ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo,
3032 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
3034 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3035 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
3036 lpData, lpdwDataSize, TRUE );
3039 static HRESULT WINAPI DirectPlay2WImpl_Receive
3040 ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo,
3041 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
3043 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3044 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
3045 lpData, lpdwDataSize, FALSE );
3048 static HRESULT WINAPI DirectPlay2AImpl_Send
3049 ( LPDIRECTPLAY2A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3051 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3052 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3053 0, 0, NULL, NULL, TRUE );
3056 static HRESULT WINAPI DirectPlay2WImpl_Send
3057 ( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3059 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3060 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3061 0, 0, NULL, NULL, FALSE );
3064 static HRESULT WINAPI DP_IF_SetGroupData
3065 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
3066 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3068 lpGroupData lpGData;
3070 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3071 This, idGroup, lpData, dwDataSize, dwFlags, bAnsi );
3073 /* Parameter check */
3074 if( ( lpData == NULL ) &&
3075 ( dwDataSize != 0 )
3078 return DPERR_INVALIDPARAMS;
3081 /* Find the pointer to the data for this player */
3082 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3084 return DPERR_INVALIDOBJECT;
3087 if( !(dwFlags & DPSET_LOCAL) )
3089 FIXME( "Was this group created by this interface?\n" );
3090 /* FIXME: If this is a remote update need to allow it but not
3091 * send a message.
3095 DP_SetGroupData( lpGData, dwFlags, lpData, dwDataSize );
3097 /* FIXME: Only send a message if this group is local to the session otherwise
3098 * it will have been rejected above
3100 if( !(dwFlags & DPSET_LOCAL) )
3102 FIXME( "Send msg?\n" );
3105 return DP_OK;
3108 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
3109 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
3110 DWORD dwDataSize, DWORD dwFlags )
3112 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3113 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, TRUE );
3116 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
3117 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
3118 DWORD dwDataSize, DWORD dwFlags )
3120 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3121 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, FALSE );
3124 static HRESULT WINAPI DP_IF_SetGroupName
3125 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
3126 DWORD dwFlags, BOOL bAnsi )
3128 lpGroupData lpGData;
3130 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n", This, idGroup,
3131 lpGroupName, dwFlags, bAnsi );
3133 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3135 return DPERR_INVALIDGROUP;
3138 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
3140 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3141 FIXME( "Message not sent and dwFlags ignored\n" );
3143 return DP_OK;
3146 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
3147 ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName,
3148 DWORD dwFlags )
3150 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3151 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
3154 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
3155 ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName,
3156 DWORD dwFlags )
3158 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3159 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
3162 static HRESULT WINAPI DP_IF_SetPlayerData
3163 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
3164 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3166 lpPlayerList lpPList;
3168 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3169 This, idPlayer, lpData, dwDataSize, dwFlags, bAnsi );
3171 if( This->dp2->connectionInitialized == NO_PROVIDER )
3173 return DPERR_UNINITIALIZED;
3176 /* Parameter check */
3177 if( ( lpData == NULL ) &&
3178 ( dwDataSize != 0 )
3181 return DPERR_INVALIDPARAMS;
3184 /* Find the pointer to the data for this player */
3185 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3187 return DPERR_INVALIDPLAYER;
3190 if( !(dwFlags & DPSET_LOCAL) )
3192 FIXME( "Was this group created by this interface?\n" );
3193 /* FIXME: If this is a remote update need to allow it but not
3194 * send a message.
3198 DP_SetPlayerData( lpPList->lpPData, dwFlags, lpData, dwDataSize );
3200 if( !(dwFlags & DPSET_LOCAL) )
3202 FIXME( "Send msg?\n" );
3205 return DP_OK;
3208 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3209 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
3210 DWORD dwDataSize, DWORD dwFlags )
3212 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3213 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3214 dwFlags, TRUE );
3217 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3218 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
3219 DWORD dwDataSize, DWORD dwFlags )
3221 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3222 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3223 dwFlags, FALSE );
3226 static HRESULT WINAPI DP_IF_SetPlayerName
3227 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
3228 DWORD dwFlags, BOOL bAnsi )
3230 lpPlayerList lpPList;
3232 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n",
3233 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3235 if( This->dp2->connectionInitialized == NO_PROVIDER )
3237 return DPERR_UNINITIALIZED;
3240 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3242 return DPERR_INVALIDGROUP;
3245 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3247 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3248 FIXME( "Message not sent and dwFlags ignored\n" );
3250 return DP_OK;
3253 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3254 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName,
3255 DWORD dwFlags )
3257 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3258 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3261 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3262 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName,
3263 DWORD dwFlags )
3265 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3266 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3269 static HRESULT WINAPI DP_SetSessionDesc
3270 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
3271 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3273 DWORD dwRequiredSize;
3274 LPDPSESSIONDESC2 lpTempSessDesc;
3276 TRACE( "(%p)->(%p,0x%08x,%u,%u)\n",
3277 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3279 if( This->dp2->connectionInitialized == NO_PROVIDER )
3281 return DPERR_UNINITIALIZED;
3284 if( dwFlags )
3286 return DPERR_INVALIDPARAMS;
3289 /* Only the host is allowed to update the session desc */
3290 if( !This->dp2->bHostInterface )
3292 return DPERR_ACCESSDENIED;
3295 /* FIXME: Copy into This->dp2->lpSessionDesc */
3296 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3297 lpTempSessDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize );
3299 if( lpTempSessDesc == NULL )
3301 return DPERR_OUTOFMEMORY;
3304 /* Free the old */
3305 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3307 This->dp2->lpSessionDesc = lpTempSessDesc;
3308 /* Set the new */
3309 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3310 if( bInitial )
3312 /*Initializing session GUID*/
3313 CoCreateGuid( &(This->dp2->lpSessionDesc->guidInstance) );
3315 /* If this is an external invocation of the interface, we should be
3316 * letting everyone know that things have changed. Otherwise this is
3317 * just an initialization and it doesn't need to be propagated.
3319 if( !bInitial )
3321 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3324 return DP_OK;
3327 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3328 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3330 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3331 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3334 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3335 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3337 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3338 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3341 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3342 DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3344 DWORD dwSize = 0;
3346 if( lpSessDesc == NULL )
3348 /* Hmmm..don't need any size? */
3349 ERR( "NULL lpSessDesc\n" );
3350 return dwSize;
3353 dwSize += sizeof( *lpSessDesc );
3355 if( bAnsi )
3357 if( lpSessDesc->u1.lpszSessionNameA )
3359 dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1;
3362 if( lpSessDesc->u2.lpszPasswordA )
3364 dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1;
3367 else /* UNICODE */
3369 if( lpSessDesc->u1.lpszSessionName )
3371 dwSize += sizeof( WCHAR ) *
3372 ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 );
3375 if( lpSessDesc->u2.lpszPassword )
3377 dwSize += sizeof( WCHAR ) *
3378 ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 );
3382 return dwSize;
3385 /* Assumes that contiguous buffers are already allocated. */
3386 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3387 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3389 BYTE* lpStartOfFreeSpace;
3391 if( lpSessionDest == NULL )
3393 ERR( "NULL lpSessionDest\n" );
3394 return;
3397 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3399 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3401 if( bAnsi )
3403 if( lpSessionSrc->u1.lpszSessionNameA )
3405 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3406 lpSessionDest->u1.lpszSessionNameA );
3407 lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3408 lpStartOfFreeSpace +=
3409 lstrlenA( lpSessionDest->u1.lpszSessionNameA ) + 1;
3412 if( lpSessionSrc->u2.lpszPasswordA )
3414 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3415 lpSessionDest->u2.lpszPasswordA );
3416 lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3417 lpStartOfFreeSpace +=
3418 lstrlenA( lpSessionDest->u2.lpszPasswordA ) + 1;
3421 else /* UNICODE */
3423 if( lpSessionSrc->u1.lpszSessionName )
3425 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3426 lpSessionDest->u1.lpszSessionName );
3427 lpSessionDest->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3428 lpStartOfFreeSpace += sizeof(WCHAR) *
3429 ( lstrlenW( lpSessionDest->u1.lpszSessionName ) + 1 );
3432 if( lpSessionSrc->u2.lpszPassword )
3434 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3435 lpSessionDest->u2.lpszPassword );
3436 lpSessionDest->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3437 lpStartOfFreeSpace += sizeof(WCHAR) *
3438 ( lstrlenW( lpSessionDest->u2.lpszPassword ) + 1 );
3444 static HRESULT WINAPI DP_IF_AddGroupToGroup
3445 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3447 lpGroupData lpGData;
3448 lpGroupList lpNewGList;
3450 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, idParentGroup, idGroup );
3452 if( DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) == NULL )
3454 return DPERR_INVALIDGROUP;
3457 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3459 return DPERR_INVALIDGROUP;
3462 /* Create a player list (ie "shortcut" ) */
3463 lpNewGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewGList ) );
3464 if( lpNewGList == NULL )
3466 return DPERR_CANTADDPLAYER;
3469 /* Add the shortcut */
3470 lpGData->uRef++;
3471 lpNewGList->lpGData = lpGData;
3473 /* Add the player to the list of players for this group */
3474 DPQ_INSERT( lpGData->groups, lpNewGList, groups );
3476 /* Send a ADDGROUPTOGROUP message */
3477 FIXME( "Not sending message\n" );
3479 return DP_OK;
3482 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3483 ( LPDIRECTPLAY3A iface, DPID idParentGroup, DPID idGroup )
3485 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3486 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3489 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3490 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3492 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3493 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3496 static HRESULT WINAPI DP_IF_CreateGroupInGroup
3497 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
3498 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
3499 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3501 lpGroupData lpGParentData;
3502 lpGroupList lpGList;
3503 lpGroupData lpGData;
3505 TRACE( "(%p)->(0x%08x,%p,%p,%p,0x%08x,0x%08x,%u)\n",
3506 This, idParentGroup, lpidGroup, lpGroupName, lpData,
3507 dwDataSize, dwFlags, bAnsi );
3509 /* Verify that the specified parent is valid */
3510 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This,
3511 idParentGroup ) ) == NULL
3514 return DPERR_INVALIDGROUP;
3517 lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName,
3518 dwFlags, idParentGroup, bAnsi );
3520 if( lpGData == NULL )
3522 return DPERR_CANTADDPLAYER; /* yes player not group */
3525 /* Something else is referencing this data */
3526 lpGData->uRef++;
3528 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
3530 /* The list has now been inserted into the interface group list. We now
3531 need to put a "shortcut" to this group in the parent group */
3532 lpGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGList ) );
3533 if( lpGList == NULL )
3535 FIXME( "Memory leak\n" );
3536 return DPERR_CANTADDPLAYER; /* yes player not group */
3539 lpGList->lpGData = lpGData;
3541 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
3543 /* Let the SP know that we've created this group */
3544 if( This->dp2->spData.lpCB->CreateGroup )
3546 DPSP_CREATEGROUPDATA data;
3548 TRACE( "Calling SP CreateGroup\n" );
3550 data.idGroup = *lpidGroup;
3551 data.dwFlags = dwFlags;
3552 data.lpSPMessageHeader = lpMsgHdr;
3553 data.lpISP = This->dp2->spData.lpISP;
3555 (*This->dp2->spData.lpCB->CreateGroup)( &data );
3558 /* Inform all other peers of the creation of a new group. If there are
3559 * no peers keep this quiet.
3561 if( This->dp2->lpSessionDesc &&
3562 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
3564 DPMSG_CREATEPLAYERORGROUP msg;
3566 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
3567 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
3568 msg.dpId = *lpidGroup;
3569 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
3570 msg.lpData = lpData;
3571 msg.dwDataSize = dwDataSize;
3572 msg.dpnName = *lpGroupName;
3574 /* FIXME: Correct to just use send effectively? */
3575 /* FIXME: Should size include data w/ message or just message "header" */
3576 /* FIXME: Check return code */
3577 DP_SendEx( (IDirectPlay2Impl*)This,
3578 DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
3579 0, 0, NULL, NULL, bAnsi );
3582 return DP_OK;
3585 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3586 ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup,
3587 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3588 DWORD dwFlags )
3590 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3592 *lpidGroup = DPID_UNKNOWN;
3594 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3595 lpGroupName, lpData, dwDataSize, dwFlags,
3596 TRUE );
3599 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3600 ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup,
3601 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3602 DWORD dwFlags )
3604 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3606 *lpidGroup = DPID_UNKNOWN;
3608 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3609 lpGroupName, lpData, dwDataSize,
3610 dwFlags, FALSE );
3613 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
3614 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3616 lpGroupList lpGList;
3617 lpGroupData lpGParentData;
3619 TRACE("(%p)->(0x%08x,0x%08x)\n", This, idParentGroup, idGroup );
3621 /* Is the parent group valid? */
3622 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3624 return DPERR_INVALIDGROUP;
3627 /* Remove the group from the parent group queue */
3628 DPQ_REMOVE_ENTRY( lpGParentData->groups, groups, lpGData->dpid, ==, idGroup, lpGList );
3630 if( lpGList == NULL )
3632 return DPERR_INVALIDGROUP;
3635 /* Decrement the ref count */
3636 lpGList->lpGData->uRef--;
3638 /* Free up the list item */
3639 HeapFree( GetProcessHeap(), 0, lpGList );
3641 /* Should send a DELETEGROUPFROMGROUP message */
3642 FIXME( "message not sent\n" );
3644 return DP_OK;
3647 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3648 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3650 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3651 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3654 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3655 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3657 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3658 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3661 static
3662 BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
3663 LPDWORD lpdwBufSize )
3665 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3666 HRESULT hr;
3668 dpCompoundAddress.dwDataSize = sizeof( GUID );
3669 dpCompoundAddress.guidDataType = DPAID_ServiceProvider;
3670 dpCompoundAddress.lpData = lpcSpGuid;
3672 *lplpAddrBuf = NULL;
3673 *lpdwBufSize = 0;
3675 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3676 lpdwBufSize, TRUE );
3678 if( hr != DPERR_BUFFERTOOSMALL )
3680 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3681 return FALSE;
3684 /* Now allocate the buffer */
3685 *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3686 *lpdwBufSize );
3688 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3689 lpdwBufSize, TRUE );
3690 if( FAILED(hr) )
3692 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3693 return FALSE;
3696 return TRUE;
3699 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
3700 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3702 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3703 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3705 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
3706 if( dwFlags == 0 )
3708 dwFlags = DPCONNECTION_DIRECTPLAY;
3711 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
3712 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) )
3715 return DPERR_INVALIDFLAGS;
3718 if( !lpEnumCallback )
3720 return DPERR_INVALIDPARAMS;
3723 /* Enumerate DirectPlay service providers */
3724 if( dwFlags & DPCONNECTION_DIRECTPLAY )
3726 HKEY hkResult;
3727 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3728 LPCSTR guidDataSubKey = "Guid";
3729 char subKeyName[51];
3730 DWORD dwIndex, sizeOfSubKeyName=50;
3731 FILETIME filetime;
3733 /* Need to loop over the service providers in the registry */
3734 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3735 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3737 /* Hmmm. Does this mean that there are no service providers? */
3738 ERR(": no service providers?\n");
3739 return DP_OK;
3743 /* Traverse all the service providers we have available */
3744 for( dwIndex=0;
3745 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3746 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3747 ++dwIndex, sizeOfSubKeyName=51 )
3750 HKEY hkServiceProvider;
3751 GUID serviceProviderGUID;
3752 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3753 char returnBuffer[51];
3754 WCHAR buff[51];
3755 DPNAME dpName;
3756 BOOL bBuildPass;
3758 LPVOID lpAddressBuffer = NULL;
3759 DWORD dwAddressBufferSize = 0;
3761 TRACE(" this time through: %s\n", subKeyName );
3763 /* Get a handle for this particular service provider */
3764 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3765 &hkServiceProvider ) != ERROR_SUCCESS )
3767 ERR(": what the heck is going on?\n" );
3768 continue;
3771 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3772 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
3773 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3775 ERR(": missing GUID registry data members\n" );
3776 RegCloseKey(hkServiceProvider);
3777 continue;
3779 RegCloseKey(hkServiceProvider);
3781 /* FIXME: Check return types to ensure we're interpreting data right */
3782 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3783 CLSIDFromString( buff, &serviceProviderGUID );
3784 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3786 /* Fill in the DPNAME struct for the service provider */
3787 dpName.dwSize = sizeof( dpName );
3788 dpName.dwFlags = 0;
3789 dpName.u1.lpszShortNameA = subKeyName;
3790 dpName.u2.lpszLongNameA = NULL;
3792 /* Create the compound address for the service provider.
3793 * NOTE: This is a gruesome architectural scar right now. DP
3794 * uses DPL and DPL uses DP. Nasty stuff. This may be why the
3795 * native dll just gets around this little bit by allocating an
3796 * 80 byte buffer which isn't even filled with a valid compound
3797 * address. Oh well. Creating a proper compound address is the
3798 * way to go anyways despite this method taking slightly more
3799 * heap space and realtime :) */
3801 bBuildPass = DP_BuildSPCompoundAddr( &serviceProviderGUID,
3802 &lpAddressBuffer,
3803 &dwAddressBufferSize );
3804 if( !bBuildPass )
3806 ERR( "Can't build compound addr\n" );
3807 return DPERR_GENERIC;
3810 /* The enumeration will return FALSE if we are not to continue */
3811 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3812 &dpName, dwFlags, lpContext ) )
3814 return DP_OK;
3819 /* Enumerate DirectPlayLobby service providers */
3820 if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY )
3822 HKEY hkResult;
3823 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3824 LPCSTR guidDataSubKey = "Guid";
3825 char subKeyName[51];
3826 DWORD dwIndex, sizeOfSubKeyName=50;
3827 FILETIME filetime;
3829 /* Need to loop over the service providers in the registry */
3830 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3831 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3833 /* Hmmm. Does this mean that there are no service providers? */
3834 ERR(": no service providers?\n");
3835 return DP_OK;
3839 /* Traverse all the lobby providers we have available */
3840 for( dwIndex=0;
3841 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3842 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3843 ++dwIndex, sizeOfSubKeyName=51 )
3846 HKEY hkServiceProvider;
3847 GUID serviceProviderGUID;
3848 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3849 char returnBuffer[51];
3850 WCHAR buff[51];
3851 DPNAME dpName;
3852 HRESULT hr;
3854 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3855 LPVOID lpAddressBuffer = NULL;
3856 DWORD dwAddressBufferSize = 0;
3858 TRACE(" this time through: %s\n", subKeyName );
3860 /* Get a handle for this particular service provider */
3861 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3862 &hkServiceProvider ) != ERROR_SUCCESS )
3864 ERR(": what the heck is going on?\n" );
3865 continue;
3868 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3869 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
3870 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3872 ERR(": missing GUID registry data members\n" );
3873 RegCloseKey(hkServiceProvider);
3874 continue;
3876 RegCloseKey(hkServiceProvider);
3878 /* FIXME: Check return types to ensure we're interpreting data right */
3879 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3880 CLSIDFromString( buff, &serviceProviderGUID );
3881 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3883 /* Fill in the DPNAME struct for the service provider */
3884 dpName.dwSize = sizeof( dpName );
3885 dpName.dwFlags = 0;
3886 dpName.u1.lpszShortNameA = subKeyName;
3887 dpName.u2.lpszLongNameA = NULL;
3889 /* Create the compound address for the service provider.
3890 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
3891 nast stuff. This may be why the native dll just gets around this little bit by
3892 allocating an 80 byte buffer which isn't even a filled with a valid compound
3893 address. Oh well. Creating a proper compound address is the way to go anyways
3894 despite this method taking slightly more heap space and realtime :) */
3896 dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
3897 dpCompoundAddress.dwDataSize = sizeof( GUID );
3898 dpCompoundAddress.lpData = &serviceProviderGUID;
3900 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3901 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
3903 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3904 return hr;
3907 /* Now allocate the buffer */
3908 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
3910 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3911 &dwAddressBufferSize, TRUE ) ) != DP_OK )
3913 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3914 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
3915 return hr;
3918 /* The enumeration will return FALSE if we are not to continue */
3919 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3920 &dpName, dwFlags, lpContext ) )
3922 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
3923 return DP_OK;
3925 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
3929 return DP_OK;
3932 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
3933 ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3935 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3936 FIXME("(%p)->(%p,%p,%p,0x%08x): stub\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3937 return DP_OK;
3940 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
3941 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
3942 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
3943 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
3945 lpGroupList lpGList;
3946 lpGroupData lpGData;
3948 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
3949 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
3950 lpContext, dwFlags, bAnsi );
3952 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3954 return DPERR_INVALIDGROUP;
3957 if( DPQ_IS_EMPTY( lpGData->groups ) )
3959 return DP_OK;
3962 lpGList = DPQ_FIRST( lpGData->groups );
3964 for( ;; )
3966 /* FIXME: Should check dwFlags for match here */
3968 if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP,
3969 &lpGList->lpGData->name, dwFlags,
3970 lpContext ) )
3972 return DP_OK; /* User requested break */
3975 if( DPQ_IS_ENDOFLIST( lpGList->groups ) )
3977 break;
3980 lpGList = DPQ_NEXT( lpGList->groups );
3984 return DP_OK;
3987 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
3988 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3989 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3990 DWORD dwFlags )
3992 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3993 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3994 lpEnumPlayersCallback2, lpContext, dwFlags,
3995 TRUE );
3998 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
3999 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
4000 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
4001 DWORD dwFlags )
4003 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4004 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
4005 lpEnumPlayersCallback2, lpContext, dwFlags,
4006 FALSE );
4009 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
4010 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
4012 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4013 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
4014 return DP_OK;
4017 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
4018 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
4020 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4021 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
4022 return DP_OK;
4025 static BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
4026 REFGUID guidDataType,
4027 DWORD dwDataSize,
4028 LPCVOID lpData,
4029 LPVOID lpContext )
4031 /* Looking for the GUID of the provider to load */
4032 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
4033 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
4036 TRACE( "Found SP/LP (%s) %s (data size = 0x%08x)\n",
4037 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
4039 if( dwDataSize != sizeof( GUID ) )
4041 ERR( "Invalid sp/lp guid size 0x%08x\n", dwDataSize );
4044 memcpy( lpContext, lpData, dwDataSize );
4046 /* There shouldn't be more than 1 GUID/compound address */
4047 return FALSE;
4050 /* Still waiting for what we want */
4051 return TRUE;
4055 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
4056 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
4058 UINT i;
4059 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4060 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
4061 LPCSTR guidDataSubKey = "Guid";
4062 LPCSTR majVerDataSubKey = "dwReserved1";
4063 LPCSTR minVerDataSubKey = "dwReserved2";
4064 LPCSTR pathSubKey = "Path";
4066 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
4068 /* FIXME: Cloned code with a quick hack. */
4069 for( i=0; i<2; i++ )
4071 HKEY hkResult;
4072 LPCSTR searchSubKey;
4073 char subKeyName[51];
4074 DWORD dwIndex, sizeOfSubKeyName=50;
4075 FILETIME filetime;
4077 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
4078 *lpbIsDpSp = (i == 0) ? TRUE : FALSE;
4081 /* Need to loop over the service providers in the registry */
4082 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4083 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4085 /* Hmmm. Does this mean that there are no service providers? */
4086 ERR(": no service providers?\n");
4087 return 0;
4090 /* Traverse all the service providers we have available */
4091 for( dwIndex=0;
4092 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4093 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4094 ++dwIndex, sizeOfSubKeyName=51 )
4097 HKEY hkServiceProvider;
4098 GUID serviceProviderGUID;
4099 DWORD returnType, sizeOfReturnBuffer = 255;
4100 char returnBuffer[256];
4101 WCHAR buff[51];
4102 DWORD dwTemp, len;
4104 TRACE(" this time through: %s\n", subKeyName );
4106 /* Get a handle for this particular service provider */
4107 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4108 &hkServiceProvider ) != ERROR_SUCCESS )
4110 ERR(": what the heck is going on?\n" );
4111 continue;
4114 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4115 NULL, &returnType, (LPBYTE)returnBuffer,
4116 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4118 ERR(": missing GUID registry data members\n" );
4119 continue;
4122 /* FIXME: Check return types to ensure we're interpreting data right */
4123 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4124 CLSIDFromString( buff, &serviceProviderGUID );
4125 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4127 /* Determine if this is the Service Provider that the user asked for */
4128 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
4130 continue;
4133 if( i == 0 ) /* DP SP */
4135 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
4136 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
4137 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
4140 sizeOfReturnBuffer = 255;
4142 /* Get dwReserved1 */
4143 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
4144 NULL, &returnType, (LPBYTE)returnBuffer,
4145 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4147 ERR(": missing dwReserved1 registry data members\n") ;
4148 continue;
4151 if( i == 0 )
4152 memcpy( &lpSpData->dwReserved1, returnBuffer, sizeof(lpSpData->dwReserved1) );
4154 sizeOfReturnBuffer = 255;
4156 /* Get dwReserved2 */
4157 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4158 NULL, &returnType, (LPBYTE)returnBuffer,
4159 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4161 ERR(": missing dwReserved1 registry data members\n") ;
4162 continue;
4165 if( i == 0 )
4166 memcpy( &lpSpData->dwReserved2, returnBuffer, sizeof(lpSpData->dwReserved2) );
4168 sizeOfReturnBuffer = 255;
4170 /* Get the path for this service provider */
4171 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
4172 NULL, NULL, (LPBYTE)returnBuffer,
4173 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
4175 ERR(": missing PATH registry data members: 0x%08x\n", dwTemp );
4176 continue;
4179 TRACE( "Loading %s\n", returnBuffer );
4180 return LoadLibraryA( returnBuffer );
4184 return 0;
4187 static
4188 HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider )
4190 HRESULT hr;
4191 LPDPSP_SPINIT SPInit;
4193 /* Initialize the service provider by calling SPInit */
4194 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4196 if( SPInit == NULL )
4198 ERR( "Service provider doesn't provide SPInit interface?\n" );
4199 FreeLibrary( hServiceProvider );
4200 return DPERR_UNAVAILABLE;
4203 TRACE( "Calling SPInit (DP SP entry point)\n" );
4205 hr = (*SPInit)( &This->dp2->spData );
4207 if( FAILED(hr) )
4209 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4210 FreeLibrary( hServiceProvider );
4211 return hr;
4214 /* FIXME: Need to verify the sanity of the returned callback table
4215 * using IsBadCodePtr */
4216 This->dp2->bSPInitialized = TRUE;
4218 /* This interface is now initialized as a DP object */
4219 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
4221 /* Store the handle of the module so that we can unload it later */
4222 This->dp2->hServiceProvider = hServiceProvider;
4224 return hr;
4227 static
4228 HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hLobbyProvider )
4230 HRESULT hr;
4231 LPSP_INIT DPLSPInit;
4233 /* Initialize the service provider by calling SPInit */
4234 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
4236 if( DPLSPInit == NULL )
4238 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4239 FreeLibrary( hLobbyProvider );
4240 return DPERR_UNAVAILABLE;
4243 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4245 hr = (*DPLSPInit)( &This->dp2->dplspData );
4247 if( FAILED(hr) )
4249 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4250 FreeLibrary( hLobbyProvider );
4251 return hr;
4254 /* FIXME: Need to verify the sanity of the returned callback table
4255 * using IsBadCodePtr */
4257 This->dp2->bDPLSPInitialized = TRUE;
4259 /* This interface is now initialized as a lobby object */
4260 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
4262 /* Store the handle of the module so that we can unload it later */
4263 This->dp2->hDPLobbyProvider = hLobbyProvider;
4265 return hr;
4268 static HRESULT WINAPI DP_IF_InitializeConnection
4269 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi )
4271 HMODULE hServiceProvider;
4272 HRESULT hr;
4273 GUID guidSP;
4274 const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
4275 BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4277 TRACE("(%p)->(%p,0x%08x,%u)\n", This, lpConnection, dwFlags, bAnsi );
4279 if ( lpConnection == NULL )
4281 return DPERR_INVALIDPARAMS;
4284 if( dwFlags != 0 )
4286 return DPERR_INVALIDFLAGS;
4289 if( This->dp2->connectionInitialized != NO_PROVIDER )
4291 return DPERR_ALREADYINITIALIZED;
4294 /* Find out what the requested SP is and how large this buffer is */
4295 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
4296 dwAddrSize, &guidSP );
4298 if( FAILED(hr) )
4300 ERR( "Invalid compound address?\n" );
4301 return DPERR_UNAVAILABLE;
4304 /* Load the service provider */
4305 hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp );
4307 if( hServiceProvider == 0 )
4309 ERR( "Unable to load service provider %s\n", debugstr_guid(&guidSP) );
4310 return DPERR_UNAVAILABLE;
4313 if( bIsDpSp )
4315 /* Fill in what we can of the Service Provider required information.
4316 * The rest was be done in DP_LoadSP
4318 This->dp2->spData.lpAddress = lpConnection;
4319 This->dp2->spData.dwAddressSize = dwAddrSize;
4320 This->dp2->spData.lpGuid = &guidSP;
4322 hr = DP_InitializeDPSP( This, hServiceProvider );
4324 else
4326 This->dp2->dplspData.lpAddress = lpConnection;
4328 hr = DP_InitializeDPLSP( This, hServiceProvider );
4331 if( FAILED(hr) )
4333 return hr;
4336 return DP_OK;
4339 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4340 ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
4342 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4344 /* This may not be externally invoked once either an SP or LP is initialized */
4345 if( This->dp2->connectionInitialized != NO_PROVIDER )
4347 return DPERR_ALREADYINITIALIZED;
4350 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE );
4353 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4354 ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
4356 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4358 /* This may not be externally invoked once either an SP or LP is initialized */
4359 if( This->dp2->connectionInitialized != NO_PROVIDER )
4361 return DPERR_ALREADYINITIALIZED;
4364 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE );
4367 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4368 ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4369 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4371 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4372 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4375 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4376 ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4377 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4379 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4380 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4383 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4384 ( LPDIRECTPLAY3A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4386 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4387 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4388 return DP_OK;
4391 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4392 ( LPDIRECTPLAY3 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4394 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4395 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4396 return DP_OK;
4399 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4400 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4402 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4403 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4404 return DP_OK;
4407 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4408 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4410 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4411 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4412 return DP_OK;
4415 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4416 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup )
4418 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4419 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, dwFlags, idGroup );
4420 return DP_OK;
4423 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4424 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup )
4426 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4427 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, dwFlags, idGroup );
4428 return DP_OK;
4431 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4432 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDWORD lpdwFlags )
4434 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4435 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpdwFlags );
4436 return DP_OK;
4439 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4440 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDWORD lpdwFlags )
4442 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4443 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpdwFlags );
4444 return DP_OK;
4447 static HRESULT WINAPI DP_IF_GetGroupParent
4448 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
4449 BOOL bAnsi )
4451 lpGroupData lpGData;
4453 TRACE("(%p)->(0x%08x,%p,%u)\n", This, idGroup, lpidGroup, bAnsi );
4455 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4457 return DPERR_INVALIDGROUP;
4460 *lpidGroup = lpGData->dpid;
4462 return DP_OK;
4465 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4466 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
4468 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4469 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE );
4471 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4472 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
4474 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4475 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE );
4478 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4479 ( LPDIRECTPLAY3A iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4481 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4482 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4483 return DP_OK;
4486 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4487 ( LPDIRECTPLAY3 iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4489 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4490 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4491 return DP_OK;
4494 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4495 ( LPDIRECTPLAY3A iface, DPID idPlayer, LPDWORD lpdwFlags )
4497 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4498 FIXME("(%p)->(0x%08x,%p): stub\n", This, idPlayer, lpdwFlags );
4499 return DP_OK;
4502 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4503 ( LPDIRECTPLAY3 iface, DPID idPlayer, LPDWORD lpdwFlags )
4505 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4506 FIXME("(%p)->(0x%08x,%p): stub\n", This, idPlayer, lpdwFlags );
4507 return DP_OK;
4510 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4511 ( LPDIRECTPLAY4A iface, DPID idGroup, LPDPID lpidGroupOwner )
4513 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4514 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpidGroupOwner );
4515 return DP_OK;
4518 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4519 ( LPDIRECTPLAY4 iface, DPID idGroup, LPDPID lpidGroupOwner )
4521 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4522 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpidGroupOwner );
4523 return DP_OK;
4526 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4527 ( LPDIRECTPLAY4A iface, DPID idGroup , DPID idGroupOwner )
4529 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4530 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, idGroup, idGroupOwner );
4531 return DP_OK;
4534 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4535 ( LPDIRECTPLAY4 iface, DPID idGroup , DPID idGroupOwner )
4537 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4538 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, idGroup, idGroupOwner );
4539 return DP_OK;
4542 static HRESULT WINAPI DP_SendEx
4543 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4544 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4545 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi )
4547 BOOL bValidDestination = FALSE;
4549 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,0x%08x,0x%08x,0x%08x,%p,%p,%u)"
4550 ": stub\n",
4551 This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority,
4552 dwTimeout, lpContext, lpdwMsgID, bAnsi );
4554 /* FIXME: Add parameter checking */
4555 /* FIXME: First call to this needs to acquire a message id which will be
4556 * used for multiple sends
4559 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4561 /* Verify that the message is being sent from a valid local player. The
4562 * from player may be anonymous DPID_UNKNOWN
4564 if( idFrom != DPID_UNKNOWN )
4566 if( DP_FindPlayer( This, idFrom ) == NULL )
4568 WARN( "INFO: Invalid from player 0x%08x\n", idFrom );
4569 return DPERR_INVALIDPLAYER;
4573 /* Verify that the message is being sent to a valid player, group or to
4574 * everyone. If it's valid, send it to those players.
4576 if( idTo == DPID_ALLPLAYERS )
4578 bValidDestination = TRUE;
4580 /* See if SP has the ability to multicast. If so, use it */
4581 if( This->dp2->spData.lpCB->SendToGroupEx )
4583 FIXME( "Use group sendex to group 0\n" );
4585 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4587 FIXME( "Use obsolete group send to group 0\n" );
4589 else /* No multicast, multiplicate */
4591 /* Send to all players we know about */
4592 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4596 if( ( !bValidDestination ) &&
4597 ( DP_FindPlayer( This, idTo ) != NULL )
4600 bValidDestination = TRUE;
4602 /* Have the service provider send this message */
4603 /* FIXME: Could optimize for local interface sends */
4604 return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority,
4605 dwTimeout, lpContext, lpdwMsgID );
4608 if( ( !bValidDestination ) &&
4609 ( DP_FindAnyGroup( This, idTo ) != NULL )
4612 bValidDestination = TRUE;
4614 /* See if SP has the ability to multicast. If so, use it */
4615 if( This->dp2->spData.lpCB->SendToGroupEx )
4617 FIXME( "Use group sendex\n" );
4619 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4621 FIXME( "Use obsolete group send to group\n" );
4623 else /* No multicast, multiplicate */
4625 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4628 #if 0
4629 if( bExpectReply )
4631 DWORD dwWaitReturn;
4633 This->dp2->hReplyEvent = CreateEventW( NULL, FALSE, FALSE, NULL );
4635 dwWaitReturn = WaitForSingleObject( hReplyEvent, dwTimeout );
4636 if( dwWaitReturn != WAIT_OBJECT_0 )
4638 ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
4641 #endif
4644 if( !bValidDestination )
4646 return DPERR_INVALIDPLAYER;
4648 else
4650 /* FIXME: Should return what the send returned */
4651 return DP_OK;
4656 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4657 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4658 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4659 LPVOID lpContext, LPDWORD lpdwMsgID )
4661 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4662 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4663 dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE );
4666 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4667 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4668 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4669 LPVOID lpContext, LPDWORD lpdwMsgID )
4671 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4672 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4673 dwPriority, dwTimeout, lpContext, lpdwMsgID, FALSE );
4676 static HRESULT WINAPI DP_SP_SendEx
4677 ( IDirectPlay2Impl* This, DWORD dwFlags,
4678 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4679 LPVOID lpContext, LPDWORD lpdwMsgID )
4681 LPDPMSG lpMElem;
4683 FIXME( ": stub\n" );
4685 /* FIXME: This queuing should only be for async messages */
4687 lpMElem = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpMElem ) );
4688 lpMElem->msg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
4690 CopyMemory( lpMElem->msg, lpData, dwDataSize );
4692 /* FIXME: Need to queue based on priority */
4693 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
4695 return DP_OK;
4698 static HRESULT WINAPI DP_IF_GetMessageQueue
4699 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4700 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi )
4702 HRESULT hr = DP_OK;
4704 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%p,%u): semi stub\n",
4705 This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi );
4707 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4708 /* FIXME: What about sends which are not immediate? */
4710 if( This->dp2->spData.lpCB->GetMessageQueue )
4712 DPSP_GETMESSAGEQUEUEDATA data;
4714 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4716 /* FIXME: None of this is documented :( */
4718 data.lpISP = This->dp2->spData.lpISP;
4719 data.dwFlags = dwFlags;
4720 data.idFrom = idFrom;
4721 data.idTo = idTo;
4722 data.lpdwNumMsgs = lpdwNumMsgs;
4723 data.lpdwNumBytes = lpdwNumBytes;
4725 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
4727 else
4729 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4732 return hr;
4735 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4736 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4737 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4739 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4740 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4741 lpdwNumBytes, TRUE );
4744 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4745 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4746 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4748 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4749 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4750 lpdwNumBytes, FALSE );
4753 static HRESULT WINAPI DP_IF_CancelMessage
4754 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
4755 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi )
4757 HRESULT hr = DP_OK;
4759 FIXME( "(%p)->(0x%08x,0x%08x,%u): semi stub\n",
4760 This, dwMsgID, dwFlags, bAnsi );
4762 if( This->dp2->spData.lpCB->Cancel )
4764 DPSP_CANCELDATA data;
4766 TRACE( "Calling SP Cancel\n" );
4768 /* FIXME: Undocumented callback */
4770 data.lpISP = This->dp2->spData.lpISP;
4771 data.dwFlags = dwFlags;
4772 data.lprglpvSPMsgID = NULL;
4773 data.cSPMsgID = dwMsgID;
4774 data.dwMinPriority = dwMinPriority;
4775 data.dwMaxPriority = dwMaxPriority;
4777 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
4779 else
4781 FIXME( "SP doesn't implement Cancel\n" );
4784 return hr;
4787 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
4788 ( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags )
4790 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4792 if( dwFlags != 0 )
4794 return DPERR_INVALIDFLAGS;
4797 if( dwMsgID == 0 )
4799 dwFlags |= DPCANCELSEND_ALL;
4802 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE );
4805 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
4806 ( LPDIRECTPLAY4 iface, DWORD dwMsgID, DWORD dwFlags )
4808 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4810 if( dwFlags != 0 )
4812 return DPERR_INVALIDFLAGS;
4815 if( dwMsgID == 0 )
4817 dwFlags |= DPCANCELSEND_ALL;
4820 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, FALSE );
4823 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
4824 ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4825 DWORD dwFlags )
4827 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4829 if( dwFlags != 0 )
4831 return DPERR_INVALIDFLAGS;
4834 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4835 dwMaxPriority, TRUE );
4838 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
4839 ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4840 DWORD dwFlags )
4842 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4844 if( dwFlags != 0 )
4846 return DPERR_INVALIDFLAGS;
4849 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4850 dwMaxPriority, FALSE );
4853 /* Note: Hack so we can reuse the old functions without compiler warnings */
4854 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4855 # define XCAST(fun) (typeof(directPlay2WVT.fun))
4856 #else
4857 # define XCAST(fun) (void*)
4858 #endif
4860 static const IDirectPlay2Vtbl directPlay2WVT =
4862 XCAST(QueryInterface)DP_QueryInterface,
4863 XCAST(AddRef)DP_AddRef,
4864 XCAST(Release)DP_Release,
4866 DirectPlay2WImpl_AddPlayerToGroup,
4867 DirectPlay2WImpl_Close,
4868 DirectPlay2WImpl_CreateGroup,
4869 DirectPlay2WImpl_CreatePlayer,
4870 DirectPlay2WImpl_DeletePlayerFromGroup,
4871 DirectPlay2WImpl_DestroyGroup,
4872 DirectPlay2WImpl_DestroyPlayer,
4873 DirectPlay2WImpl_EnumGroupPlayers,
4874 DirectPlay2WImpl_EnumGroups,
4875 DirectPlay2WImpl_EnumPlayers,
4876 DirectPlay2WImpl_EnumSessions,
4877 DirectPlay2WImpl_GetCaps,
4878 DirectPlay2WImpl_GetGroupData,
4879 DirectPlay2WImpl_GetGroupName,
4880 DirectPlay2WImpl_GetMessageCount,
4881 DirectPlay2WImpl_GetPlayerAddress,
4882 DirectPlay2WImpl_GetPlayerCaps,
4883 DirectPlay2WImpl_GetPlayerData,
4884 DirectPlay2WImpl_GetPlayerName,
4885 DirectPlay2WImpl_GetSessionDesc,
4886 DirectPlay2WImpl_Initialize,
4887 DirectPlay2WImpl_Open,
4888 DirectPlay2WImpl_Receive,
4889 DirectPlay2WImpl_Send,
4890 DirectPlay2WImpl_SetGroupData,
4891 DirectPlay2WImpl_SetGroupName,
4892 DirectPlay2WImpl_SetPlayerData,
4893 DirectPlay2WImpl_SetPlayerName,
4894 DirectPlay2WImpl_SetSessionDesc
4896 #undef XCAST
4898 /* Note: Hack so we can reuse the old functions without compiler warnings */
4899 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4900 # define XCAST(fun) (typeof(directPlay2AVT.fun))
4901 #else
4902 # define XCAST(fun) (void*)
4903 #endif
4905 static const IDirectPlay2Vtbl directPlay2AVT =
4907 XCAST(QueryInterface)DP_QueryInterface,
4908 XCAST(AddRef)DP_AddRef,
4909 XCAST(Release)DP_Release,
4911 DirectPlay2AImpl_AddPlayerToGroup,
4912 DirectPlay2AImpl_Close,
4913 DirectPlay2AImpl_CreateGroup,
4914 DirectPlay2AImpl_CreatePlayer,
4915 DirectPlay2AImpl_DeletePlayerFromGroup,
4916 DirectPlay2AImpl_DestroyGroup,
4917 DirectPlay2AImpl_DestroyPlayer,
4918 DirectPlay2AImpl_EnumGroupPlayers,
4919 DirectPlay2AImpl_EnumGroups,
4920 DirectPlay2AImpl_EnumPlayers,
4921 DirectPlay2AImpl_EnumSessions,
4922 DirectPlay2AImpl_GetCaps,
4923 DirectPlay2AImpl_GetGroupData,
4924 DirectPlay2AImpl_GetGroupName,
4925 DirectPlay2AImpl_GetMessageCount,
4926 DirectPlay2AImpl_GetPlayerAddress,
4927 DirectPlay2AImpl_GetPlayerCaps,
4928 DirectPlay2AImpl_GetPlayerData,
4929 DirectPlay2AImpl_GetPlayerName,
4930 DirectPlay2AImpl_GetSessionDesc,
4931 DirectPlay2AImpl_Initialize,
4932 DirectPlay2AImpl_Open,
4933 DirectPlay2AImpl_Receive,
4934 DirectPlay2AImpl_Send,
4935 DirectPlay2AImpl_SetGroupData,
4936 DirectPlay2AImpl_SetGroupName,
4937 DirectPlay2AImpl_SetPlayerData,
4938 DirectPlay2AImpl_SetPlayerName,
4939 DirectPlay2AImpl_SetSessionDesc
4941 #undef XCAST
4944 /* Note: Hack so we can reuse the old functions without compiler warnings */
4945 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4946 # define XCAST(fun) (typeof(directPlay3AVT.fun))
4947 #else
4948 # define XCAST(fun) (void*)
4949 #endif
4951 static const IDirectPlay3Vtbl directPlay3AVT =
4953 XCAST(QueryInterface)DP_QueryInterface,
4954 XCAST(AddRef)DP_AddRef,
4955 XCAST(Release)DP_Release,
4957 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
4958 XCAST(Close)DirectPlay2AImpl_Close,
4959 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
4960 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
4961 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
4962 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
4963 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
4964 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
4965 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
4966 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
4967 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
4968 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
4969 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
4970 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
4971 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
4972 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
4973 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
4974 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
4975 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
4976 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
4977 XCAST(Initialize)DirectPlay2AImpl_Initialize,
4978 XCAST(Open)DirectPlay2AImpl_Open,
4979 XCAST(Receive)DirectPlay2AImpl_Receive,
4980 XCAST(Send)DirectPlay2AImpl_Send,
4981 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
4982 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
4983 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
4984 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
4985 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
4987 DirectPlay3AImpl_AddGroupToGroup,
4988 DirectPlay3AImpl_CreateGroupInGroup,
4989 DirectPlay3AImpl_DeleteGroupFromGroup,
4990 DirectPlay3AImpl_EnumConnections,
4991 DirectPlay3AImpl_EnumGroupsInGroup,
4992 DirectPlay3AImpl_GetGroupConnectionSettings,
4993 DirectPlay3AImpl_InitializeConnection,
4994 DirectPlay3AImpl_SecureOpen,
4995 DirectPlay3AImpl_SendChatMessage,
4996 DirectPlay3AImpl_SetGroupConnectionSettings,
4997 DirectPlay3AImpl_StartSession,
4998 DirectPlay3AImpl_GetGroupFlags,
4999 DirectPlay3AImpl_GetGroupParent,
5000 DirectPlay3AImpl_GetPlayerAccount,
5001 DirectPlay3AImpl_GetPlayerFlags
5003 #undef XCAST
5005 /* Note: Hack so we can reuse the old functions without compiler warnings */
5006 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5007 # define XCAST(fun) (typeof(directPlay3WVT.fun))
5008 #else
5009 # define XCAST(fun) (void*)
5010 #endif
5011 static const IDirectPlay3Vtbl directPlay3WVT =
5013 XCAST(QueryInterface)DP_QueryInterface,
5014 XCAST(AddRef)DP_AddRef,
5015 XCAST(Release)DP_Release,
5017 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
5018 XCAST(Close)DirectPlay2WImpl_Close,
5019 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
5020 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
5021 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
5022 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
5023 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5024 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5025 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5026 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5027 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5028 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5029 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5030 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5031 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5032 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5033 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5034 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5035 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5036 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5037 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5038 XCAST(Open)DirectPlay2WImpl_Open,
5039 XCAST(Receive)DirectPlay2WImpl_Receive,
5040 XCAST(Send)DirectPlay2WImpl_Send,
5041 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5042 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5043 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5044 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5045 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5047 DirectPlay3WImpl_AddGroupToGroup,
5048 DirectPlay3WImpl_CreateGroupInGroup,
5049 DirectPlay3WImpl_DeleteGroupFromGroup,
5050 DirectPlay3WImpl_EnumConnections,
5051 DirectPlay3WImpl_EnumGroupsInGroup,
5052 DirectPlay3WImpl_GetGroupConnectionSettings,
5053 DirectPlay3WImpl_InitializeConnection,
5054 DirectPlay3WImpl_SecureOpen,
5055 DirectPlay3WImpl_SendChatMessage,
5056 DirectPlay3WImpl_SetGroupConnectionSettings,
5057 DirectPlay3WImpl_StartSession,
5058 DirectPlay3WImpl_GetGroupFlags,
5059 DirectPlay3WImpl_GetGroupParent,
5060 DirectPlay3WImpl_GetPlayerAccount,
5061 DirectPlay3WImpl_GetPlayerFlags
5063 #undef XCAST
5065 /* Note: Hack so we can reuse the old functions without compiler warnings */
5066 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5067 # define XCAST(fun) (typeof(directPlay4WVT.fun))
5068 #else
5069 # define XCAST(fun) (void*)
5070 #endif
5071 static const IDirectPlay4Vtbl directPlay4WVT =
5073 XCAST(QueryInterface)DP_QueryInterface,
5074 XCAST(AddRef)DP_AddRef,
5075 XCAST(Release)DP_Release,
5077 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
5078 XCAST(Close)DirectPlay2WImpl_Close,
5079 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
5080 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
5081 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
5082 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
5083 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5084 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5085 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5086 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5087 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5088 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5089 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5090 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5091 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5092 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5093 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5094 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5095 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5096 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5097 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5098 XCAST(Open)DirectPlay2WImpl_Open,
5099 XCAST(Receive)DirectPlay2WImpl_Receive,
5100 XCAST(Send)DirectPlay2WImpl_Send,
5101 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5102 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5103 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5104 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5105 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5107 XCAST(AddGroupToGroup)DirectPlay3WImpl_AddGroupToGroup,
5108 XCAST(CreateGroupInGroup)DirectPlay3WImpl_CreateGroupInGroup,
5109 XCAST(DeleteGroupFromGroup)DirectPlay3WImpl_DeleteGroupFromGroup,
5110 XCAST(EnumConnections)DirectPlay3WImpl_EnumConnections,
5111 XCAST(EnumGroupsInGroup)DirectPlay3WImpl_EnumGroupsInGroup,
5112 XCAST(GetGroupConnectionSettings)DirectPlay3WImpl_GetGroupConnectionSettings,
5113 XCAST(InitializeConnection)DirectPlay3WImpl_InitializeConnection,
5114 XCAST(SecureOpen)DirectPlay3WImpl_SecureOpen,
5115 XCAST(SendChatMessage)DirectPlay3WImpl_SendChatMessage,
5116 XCAST(SetGroupConnectionSettings)DirectPlay3WImpl_SetGroupConnectionSettings,
5117 XCAST(StartSession)DirectPlay3WImpl_StartSession,
5118 XCAST(GetGroupFlags)DirectPlay3WImpl_GetGroupFlags,
5119 XCAST(GetGroupParent)DirectPlay3WImpl_GetGroupParent,
5120 XCAST(GetPlayerAccount)DirectPlay3WImpl_GetPlayerAccount,
5121 XCAST(GetPlayerFlags)DirectPlay3WImpl_GetPlayerFlags,
5123 DirectPlay4WImpl_GetGroupOwner,
5124 DirectPlay4WImpl_SetGroupOwner,
5125 DirectPlay4WImpl_SendEx,
5126 DirectPlay4WImpl_GetMessageQueue,
5127 DirectPlay4WImpl_CancelMessage,
5128 DirectPlay4WImpl_CancelPriority
5130 #undef XCAST
5133 /* Note: Hack so we can reuse the old functions without compiler warnings */
5134 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5135 # define XCAST(fun) (typeof(directPlay4AVT.fun))
5136 #else
5137 # define XCAST(fun) (void*)
5138 #endif
5139 static const IDirectPlay4Vtbl directPlay4AVT =
5141 XCAST(QueryInterface)DP_QueryInterface,
5142 XCAST(AddRef)DP_AddRef,
5143 XCAST(Release)DP_Release,
5145 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
5146 XCAST(Close)DirectPlay2AImpl_Close,
5147 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
5148 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
5149 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
5150 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
5151 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
5152 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
5153 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
5154 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
5155 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
5156 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
5157 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
5158 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
5159 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5160 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5161 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5162 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5163 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5164 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5165 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5166 XCAST(Open)DirectPlay2AImpl_Open,
5167 XCAST(Receive)DirectPlay2AImpl_Receive,
5168 XCAST(Send)DirectPlay2AImpl_Send,
5169 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5170 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5171 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5172 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5173 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5175 XCAST(AddGroupToGroup)DirectPlay3AImpl_AddGroupToGroup,
5176 XCAST(CreateGroupInGroup)DirectPlay3AImpl_CreateGroupInGroup,
5177 XCAST(DeleteGroupFromGroup)DirectPlay3AImpl_DeleteGroupFromGroup,
5178 XCAST(EnumConnections)DirectPlay3AImpl_EnumConnections,
5179 XCAST(EnumGroupsInGroup)DirectPlay3AImpl_EnumGroupsInGroup,
5180 XCAST(GetGroupConnectionSettings)DirectPlay3AImpl_GetGroupConnectionSettings,
5181 XCAST(InitializeConnection)DirectPlay3AImpl_InitializeConnection,
5182 XCAST(SecureOpen)DirectPlay3AImpl_SecureOpen,
5183 XCAST(SendChatMessage)DirectPlay3AImpl_SendChatMessage,
5184 XCAST(SetGroupConnectionSettings)DirectPlay3AImpl_SetGroupConnectionSettings,
5185 XCAST(StartSession)DirectPlay3AImpl_StartSession,
5186 XCAST(GetGroupFlags)DirectPlay3AImpl_GetGroupFlags,
5187 XCAST(GetGroupParent)DirectPlay3AImpl_GetGroupParent,
5188 XCAST(GetPlayerAccount)DirectPlay3AImpl_GetPlayerAccount,
5189 XCAST(GetPlayerFlags)DirectPlay3AImpl_GetPlayerFlags,
5191 DirectPlay4AImpl_GetGroupOwner,
5192 DirectPlay4AImpl_SetGroupOwner,
5193 DirectPlay4AImpl_SendEx,
5194 DirectPlay4AImpl_GetMessageQueue,
5195 DirectPlay4AImpl_CancelMessage,
5196 DirectPlay4AImpl_CancelPriority
5198 #undef XCAST
5200 HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP,
5201 DPID idPlayer,
5202 LPVOID* lplpData )
5204 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5206 if( lpPlayer == NULL )
5208 return DPERR_INVALIDPLAYER;
5211 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
5213 return DP_OK;
5216 HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP,
5217 DPID idPlayer,
5218 LPVOID lpData )
5220 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5222 if( lpPlayer == NULL )
5224 return DPERR_INVALIDPLAYER;
5227 lpPlayer->lpPData->lpSPPlayerData = lpData;
5229 return DP_OK;
5232 /***************************************************************************
5233 * DirectPlayEnumerateAW
5235 * The pointer to the structure lpContext will be filled with the
5236 * appropriate data for each service offered by the OS. These services are
5237 * not necessarily available on this particular machine but are defined
5238 * as simple service providers under the "Service Providers" registry key.
5239 * This structure is then passed to lpEnumCallback for each of the different
5240 * services.
5242 * This API is useful only for applications written using DirectX3 or
5243 * worse. It is superseded by IDirectPlay3::EnumConnections which also
5244 * gives information on the actual connections.
5246 * defn of a service provider:
5247 * A dynamic-link library used by DirectPlay to communicate over a network.
5248 * The service provider contains all the network-specific code required
5249 * to send and receive messages. Online services and network operators can
5250 * supply service providers to use specialized hardware, protocols, communications
5251 * media, and network resources.
5254 static HRESULT DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA,
5255 LPDPENUMDPCALLBACKW lpEnumCallbackW,
5256 LPVOID lpContext)
5258 HKEY hkResult;
5259 static const WCHAR searchSubKey[] = {
5260 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
5261 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
5262 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
5263 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
5264 static const WCHAR guidKey[] = { 'G', 'u', 'i', 'd', 0 };
5265 static const WCHAR descW[] = { 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', 'W', 0 };
5267 DWORD dwIndex;
5268 FILETIME filetime;
5270 char *descriptionA = NULL;
5271 DWORD max_sizeOfDescriptionA = 0;
5272 WCHAR *descriptionW = NULL;
5273 DWORD max_sizeOfDescriptionW = 0;
5275 if (!lpEnumCallbackA && !lpEnumCallbackW)
5277 return DPERR_INVALIDPARAMS;
5280 /* Need to loop over the service providers in the registry */
5281 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, searchSubKey,
5282 0, KEY_READ, &hkResult) != ERROR_SUCCESS)
5284 /* Hmmm. Does this mean that there are no service providers? */
5285 ERR(": no service provider key in the registry - check your Wine installation !!!\n");
5286 return DPERR_GENERIC;
5289 /* Traverse all the service providers we have available */
5290 dwIndex = 0;
5291 while (1)
5293 WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */
5294 DWORD sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR);
5295 HKEY hkServiceProvider;
5296 GUID serviceProviderGUID;
5297 WCHAR guidKeyContent[(2 * 16) + 1 + 6 /* This corresponds to '{....-..-..-..-......}' */ ];
5298 DWORD sizeOfGuidKeyContent = sizeof(guidKeyContent);
5299 LONG ret_value;
5301 ret_value = RegEnumKeyExW(hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
5302 NULL, NULL, NULL, &filetime);
5303 if (ret_value == ERROR_NO_MORE_ITEMS)
5304 break;
5305 else if (ret_value != ERROR_SUCCESS)
5307 ERR(": could not enumerate on service provider key.\n");
5308 return DPERR_EXCEPTION;
5310 TRACE(" this time through sub-key %s.\n", debugstr_w(subKeyName));
5312 /* Open the key for this service provider */
5313 if (RegOpenKeyExW(hkResult, subKeyName, 0, KEY_READ, &hkServiceProvider) != ERROR_SUCCESS)
5315 ERR(": could not open registry key for service provider %s.\n", debugstr_w(subKeyName));
5316 continue;
5319 /* Get the GUID from the registry */
5320 if (RegQueryValueExW(hkServiceProvider, guidKey,
5321 NULL, NULL, (LPBYTE) guidKeyContent, &sizeOfGuidKeyContent) != ERROR_SUCCESS)
5323 ERR(": missing GUID registry data member for service provider %s.\n", debugstr_w(subKeyName));
5324 continue;
5326 if (sizeOfGuidKeyContent != sizeof(guidKeyContent))
5328 ERR(": invalid format for the GUID registry data member for service provider %s (%s).\n", debugstr_w(subKeyName), debugstr_w(guidKeyContent));
5329 continue;
5331 CLSIDFromString(guidKeyContent, &serviceProviderGUID );
5333 /* The enumeration will return FALSE if we are not to continue.
5335 * Note: on my windows box, major / minor version is 6 / 0 for all service providers
5336 * and have no relation to any of the two dwReserved1 and dwReserved2 keys.
5337 * I think that it simply means that they are in-line with DirectX 6.0
5339 if (lpEnumCallbackA)
5341 DWORD sizeOfDescription = 0;
5343 /* Note that this is the A case of this function, so use the A variant to get the description string */
5344 if (RegQueryValueExA(hkServiceProvider, "DescriptionA",
5345 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5347 ERR(": missing 'DescriptionA' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5348 continue;
5350 if (sizeOfDescription > max_sizeOfDescriptionA)
5352 HeapFree(GetProcessHeap(), 0, descriptionA);
5353 max_sizeOfDescriptionA = sizeOfDescription;
5355 descriptionA = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5356 RegQueryValueExA(hkServiceProvider, "DescriptionA",
5357 NULL, NULL, (LPBYTE) descriptionA, &sizeOfDescription);
5359 if (!lpEnumCallbackA(&serviceProviderGUID, descriptionA, 6, 0, lpContext))
5360 goto end;
5362 else
5364 DWORD sizeOfDescription = 0;
5366 if (RegQueryValueExW(hkServiceProvider, descW,
5367 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5369 ERR(": missing 'DescriptionW' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5370 continue;
5372 if (sizeOfDescription > max_sizeOfDescriptionW)
5374 HeapFree(GetProcessHeap(), 0, descriptionW);
5375 max_sizeOfDescriptionW = sizeOfDescription;
5377 descriptionW = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5378 RegQueryValueExW(hkServiceProvider, descW,
5379 NULL, NULL, (LPBYTE) descriptionW, &sizeOfDescription);
5381 if (!lpEnumCallbackW(&serviceProviderGUID, descriptionW, 6, 0, lpContext))
5382 goto end;
5385 dwIndex++;
5388 end:
5389 HeapFree(GetProcessHeap(), 0, descriptionA);
5390 HeapFree(GetProcessHeap(), 0, descriptionW);
5392 return DP_OK;
5395 /***************************************************************************
5396 * DirectPlayEnumerate [DPLAYX.9]
5397 * DirectPlayEnumerateA [DPLAYX.2]
5399 HRESULT WINAPI DirectPlayEnumerateA(LPDPENUMDPCALLBACKA lpEnumCallback, LPVOID lpContext )
5401 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5403 return DirectPlayEnumerateAW(lpEnumCallback, NULL, lpContext);
5406 /***************************************************************************
5407 * DirectPlayEnumerateW [DPLAYX.3]
5409 HRESULT WINAPI DirectPlayEnumerateW(LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5411 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5413 return DirectPlayEnumerateAW(NULL, lpEnumCallback, lpContext);
5416 typedef struct tagCreateEnum
5418 LPVOID lpConn;
5419 LPCGUID lpGuid;
5420 } CreateEnumData, *lpCreateEnumData;
5422 /* Find and copy the matching connection for the SP guid */
5423 static BOOL CALLBACK cbDPCreateEnumConnections(
5424 LPCGUID lpguidSP,
5425 LPVOID lpConnection,
5426 DWORD dwConnectionSize,
5427 LPCDPNAME lpName,
5428 DWORD dwFlags,
5429 LPVOID lpContext)
5431 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5433 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5435 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5437 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5438 dwConnectionSize );
5439 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5441 /* Found the record that we were looking for */
5442 return FALSE;
5445 /* Haven't found what were looking for yet */
5446 return TRUE;
5450 /***************************************************************************
5451 * DirectPlayCreate [DPLAYX.1]
5454 HRESULT WINAPI DirectPlayCreate
5455 ( LPGUID lpGUID, LPDIRECTPLAY *lplpDP, IUnknown *pUnk )
5457 HRESULT hr;
5458 LPDIRECTPLAY3A lpDP3A;
5459 CreateEnumData cbData;
5461 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5463 if( pUnk != NULL )
5465 return CLASS_E_NOAGGREGATION;
5468 if( (lplpDP == NULL) || (lpGUID == NULL) )
5470 return DPERR_INVALIDPARAMS;
5474 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5475 give them an IDirectPlay2A object and hope that doesn't cause problems */
5476 if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
5478 return DPERR_UNAVAILABLE;
5481 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
5483 /* The GUID_NULL means don't bind a service provider. Just return the
5484 interface as is */
5485 return DP_OK;
5488 /* Bind the desired service provider since lpGUID is non NULL */
5489 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
5491 /* We're going to use a DP3 interface */
5492 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
5493 (LPVOID*)&lpDP3A );
5494 if( FAILED(hr) )
5496 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
5497 return hr;
5500 cbData.lpConn = NULL;
5501 cbData.lpGuid = lpGUID;
5503 /* We were given a service provider, find info about it... */
5504 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
5505 &cbData, DPCONNECTION_DIRECTPLAY );
5506 if( ( FAILED(hr) ) ||
5507 ( cbData.lpConn == NULL )
5510 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
5511 IDirectPlayX_Release( lpDP3A );
5512 return DPERR_UNAVAILABLE;
5515 /* Initialize the service provider */
5516 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
5517 if( FAILED(hr) )
5519 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
5520 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5521 IDirectPlayX_Release( lpDP3A );
5522 return hr;
5525 /* Release our version of the interface now that we're done with it */
5526 IDirectPlayX_Release( lpDP3A );
5527 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5529 return DP_OK;