Convert remaining source files to utf-8.
[wine/multimedia.git] / dlls / dplayx / dplay.c
blob91090cb957e02b85d8159936c4f0ce0ecf21f219
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 if( This->dp2->connectionInitialized == NO_PROVIDER )
798 return DPERR_UNINITIALIZED;
801 /* Find the group */
802 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
804 return DPERR_INVALIDGROUP;
807 /* Find the player */
808 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
810 return DPERR_INVALIDPLAYER;
813 /* Create a player list (ie "shortcut" ) */
814 lpNewPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewPList ) );
815 if( lpNewPList == NULL )
817 return DPERR_CANTADDPLAYER;
820 /* Add the shortcut */
821 lpPList->lpPData->uRef++;
822 lpNewPList->lpPData = lpPList->lpPData;
824 /* Add the player to the list of players for this group */
825 DPQ_INSERT(lpGData->players,lpNewPList,players);
827 /* Let the SP know that we've added a player to the group */
828 if( This->dp2->spData.lpCB->AddPlayerToGroup )
830 DPSP_ADDPLAYERTOGROUPDATA data;
832 TRACE( "Calling SP AddPlayerToGroup\n" );
834 data.idPlayer = idPlayer;
835 data.idGroup = idGroup;
836 data.lpISP = This->dp2->spData.lpISP;
838 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
841 /* Inform all other peers of the addition of player to the group. If there are
842 * no peers keep this event quiet.
843 * Also, if this event was the result of another machine sending it to us,
844 * don't bother rebroadcasting it.
846 if( ( lpMsgHdr == NULL ) &&
847 This->dp2->lpSessionDesc &&
848 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
850 DPMSG_ADDPLAYERTOGROUP msg;
851 msg.dwType = DPSYS_ADDPLAYERTOGROUP;
853 msg.dpIdGroup = idGroup;
854 msg.dpIdPlayer = idPlayer;
856 /* FIXME: Correct to just use send effectively? */
857 /* FIXME: Should size include data w/ message or just message "header" */
858 /* FIXME: Check return code */
859 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
862 return DP_OK;
865 static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
866 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
868 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
869 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, TRUE );
872 static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
873 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
875 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
876 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, FALSE );
879 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi )
881 HRESULT hr = DP_OK;
883 TRACE("(%p)->(%u)\n", This, bAnsi );
885 /* FIXME: Need to find a new host I assume (how?) */
886 /* FIXME: Need to destroy all local groups */
887 /* FIXME: Need to migrate all remotely visible players to the new host */
889 /* Invoke the SP callback to inform of session close */
890 if( This->dp2->spData.lpCB->CloseEx )
892 DPSP_CLOSEDATA data;
894 TRACE( "Calling SP CloseEx\n" );
896 data.lpISP = This->dp2->spData.lpISP;
898 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
901 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
903 TRACE( "Calling SP Close (obsolete interface)\n" );
905 hr = (*This->dp2->spData.lpCB->Close)();
908 return hr;
911 static HRESULT WINAPI DirectPlay2AImpl_Close
912 ( LPDIRECTPLAY2A iface )
914 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
915 return DP_IF_Close( This, TRUE );
918 static HRESULT WINAPI DirectPlay2WImpl_Close
919 ( LPDIRECTPLAY2 iface )
921 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
922 return DP_IF_Close( This, FALSE );
925 static
926 lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, const DPID *lpid,
927 const DPNAME *lpName, DWORD dwFlags,
928 DPID idParent, BOOL bAnsi )
930 lpGroupData lpGData;
932 /* Allocate the new space and add to end of high level group list */
933 lpGData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGData ) );
935 if( lpGData == NULL )
937 return NULL;
940 DPQ_INIT(lpGData->groups);
941 DPQ_INIT(lpGData->players);
943 /* Set the desired player ID - no sanity checking to see if it exists */
944 lpGData->dpid = *lpid;
946 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
948 /* FIXME: Should we check that the parent exists? */
949 lpGData->parent = idParent;
951 /* FIXME: Should we validate the dwFlags? */
952 lpGData->dwFlags = dwFlags;
954 TRACE( "Created group id 0x%08x\n", *lpid );
956 return lpGData;
959 /* This method assumes that all links to it are already deleted */
960 static void
961 DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid )
963 lpGroupList lpGList;
965 TRACE( "(%p)->(0x%08x)\n", This, dpid );
967 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
969 if( lpGList == NULL )
971 ERR( "DPID 0x%08x not found\n", dpid );
972 return;
975 if( --(lpGList->lpGData->uRef) )
977 FIXME( "Why is this not the last reference to group?\n" );
978 DebugBreak();
981 /* Delete player */
982 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
983 HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
985 /* Remove and Delete Player List object */
986 HeapFree( GetProcessHeap(), 0, lpGList );
990 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid )
992 lpGroupList lpGroups;
994 TRACE( "(%p)->(0x%08x)\n", This, dpid );
996 if( dpid == DPID_SYSTEM_GROUP )
998 return This->dp2->lpSysGroup;
1000 else
1002 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
1005 if( lpGroups == NULL )
1007 return NULL;
1010 return lpGroups->lpGData;
1013 static HRESULT WINAPI DP_IF_CreateGroup
1014 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
1015 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
1016 DWORD dwFlags, BOOL bAnsi )
1018 lpGroupData lpGData;
1020 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1021 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
1022 dwFlags, bAnsi );
1024 if( This->dp2->connectionInitialized == NO_PROVIDER )
1026 return DPERR_UNINITIALIZED;
1029 /* If the name is not specified, we must provide one */
1030 if( DPID_UNKNOWN == *lpidGroup )
1032 /* If we are the name server, we decide on the group ids. If not, we
1033 * must ask for one before attempting a creation.
1035 if( This->dp2->bHostInterface )
1037 *lpidGroup = DP_NextObjectId();
1039 else
1041 *lpidGroup = DP_GetRemoteNextObjectId();
1045 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
1046 DPID_NOPARENT_GROUP, bAnsi );
1048 if( lpGData == NULL )
1050 return DPERR_CANTADDPLAYER; /* yes player not group */
1053 if( DPID_SYSTEM_GROUP == *lpidGroup )
1055 This->dp2->lpSysGroup = lpGData;
1056 TRACE( "Inserting system group\n" );
1058 else
1060 /* Insert into the system group */
1061 lpGroupList lpGroup = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGroup ) );
1062 lpGroup->lpGData = lpGData;
1064 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
1067 /* Something is now referencing this data */
1068 lpGData->uRef++;
1070 /* Set all the important stuff for the group */
1071 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
1073 /* FIXME: We should only create the system group if GetCaps returns
1074 * DPCAPS_GROUPOPTIMIZED.
1077 /* Let the SP know that we've created this group */
1078 if( This->dp2->spData.lpCB->CreateGroup )
1080 DPSP_CREATEGROUPDATA data;
1081 DWORD dwCreateFlags = 0;
1083 TRACE( "Calling SP CreateGroup\n" );
1085 if( *lpidGroup == DPID_NOPARENT_GROUP )
1086 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
1088 if( lpMsgHdr == NULL )
1089 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1091 if( dwFlags & DPGROUP_HIDDEN )
1092 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
1094 data.idGroup = *lpidGroup;
1095 data.dwFlags = dwCreateFlags;
1096 data.lpSPMessageHeader = lpMsgHdr;
1097 data.lpISP = This->dp2->spData.lpISP;
1099 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1102 /* Inform all other peers of the creation of a new group. If there are
1103 * no peers keep this event quiet.
1104 * Also if this message was sent to us, don't rebroadcast.
1106 if( ( lpMsgHdr == NULL ) &&
1107 This->dp2->lpSessionDesc &&
1108 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1110 DPMSG_CREATEPLAYERORGROUP msg;
1111 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1113 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1114 msg.dpId = *lpidGroup;
1115 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1116 msg.lpData = lpData;
1117 msg.dwDataSize = dwDataSize;
1118 msg.dpnName = *lpGroupName;
1119 msg.dpIdParent = DPID_NOPARENT_GROUP;
1120 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
1122 /* FIXME: Correct to just use send effectively? */
1123 /* FIXME: Should size include data w/ message or just message "header" */
1124 /* FIXME: Check return code */
1125 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
1126 0, 0, NULL, NULL, bAnsi );
1129 return DP_OK;
1132 static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
1133 ( LPDIRECTPLAY2A 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, TRUE );
1142 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
1143 ( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1144 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1146 *lpidGroup = DPID_UNKNOWN;
1148 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1149 lpGroupName, lpData, dwDataSize, dwFlags, FALSE );
1153 static void
1154 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
1155 LPVOID lpData, DWORD dwDataSize )
1157 /* Clear out the data with this player */
1158 if( dwFlags & DPSET_LOCAL )
1160 if ( lpGData->dwLocalDataSize != 0 )
1162 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
1163 lpGData->lpLocalData = NULL;
1164 lpGData->dwLocalDataSize = 0;
1167 else
1169 if( lpGData->dwRemoteDataSize != 0 )
1171 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
1172 lpGData->lpRemoteData = NULL;
1173 lpGData->dwRemoteDataSize = 0;
1177 /* Reallocate for new data */
1178 if( lpData != NULL )
1180 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1181 sizeof( dwDataSize ) );
1182 CopyMemory( lpNewData, lpData, dwDataSize );
1184 if( dwFlags & DPSET_LOCAL )
1186 lpGData->lpLocalData = lpData;
1187 lpGData->dwLocalDataSize = dwDataSize;
1189 else
1191 lpGData->lpRemoteData = lpNewData;
1192 lpGData->dwRemoteDataSize = dwDataSize;
1198 /* This function will just create the storage for the new player. */
1199 static
1200 lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid,
1201 LPDPNAME lpName, DWORD dwFlags,
1202 HANDLE hEvent, BOOL bAnsi )
1204 lpPlayerData lpPData;
1206 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
1208 /* Allocate the storage for the player and associate it with list element */
1209 lpPData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPData ) );
1210 if( lpPData == NULL )
1212 return NULL;
1215 /* Set the desired player ID */
1216 lpPData->dpid = *lpid;
1218 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
1220 lpPData->dwFlags = dwFlags;
1222 /* If we were given an event handle, duplicate it */
1223 if( hEvent != 0 )
1225 if( !DuplicateHandle( GetCurrentProcess(), hEvent,
1226 GetCurrentProcess(), &lpPData->hEvent,
1227 0, FALSE, DUPLICATE_SAME_ACCESS )
1230 /* FIXME: Memory leak */
1231 ERR( "Can't duplicate player msg handle %p\n", hEvent );
1235 /* Initialize the SP data section */
1236 lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData();
1238 TRACE( "Created player id 0x%08x\n", *lpid );
1240 if( ~dwFlags & DPLAYI_PLAYER_SYSPLAYER )
1241 This->dp2->lpSessionDesc->dwCurrentPlayers++;
1243 return lpPData;
1246 /* Delete the contents of the DPNAME struct */
1247 static void
1248 DP_DeleteDPNameStruct( LPDPNAME lpDPName )
1250 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u1.lpszShortNameA );
1251 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u2.lpszLongNameA );
1254 /* This method assumes that all links to it are already deleted */
1255 static void
1256 DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid )
1258 lpPlayerList lpPList;
1260 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1262 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1264 if( lpPList == NULL )
1266 ERR( "DPID 0x%08x not found\n", dpid );
1267 return;
1270 /* Verify that this is the last reference to the data */
1271 if( --(lpPList->lpPData->uRef) )
1273 FIXME( "Why is this not the last reference to player?\n" );
1274 DebugBreak();
1277 /* Delete player */
1278 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1280 CloseHandle( lpPList->lpPData->hEvent );
1281 HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
1283 /* Delete Player List object */
1284 HeapFree( GetProcessHeap(), 0, lpPList );
1287 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid )
1289 lpPlayerList lpPlayers;
1291 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1293 if(This->dp2->lpSysGroup == NULL)
1294 return NULL;
1296 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1298 return lpPlayers;
1301 /* Basic area for Dst must already be allocated */
1302 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, const DPNAME *lpSrc, BOOL bAnsi )
1304 if( lpSrc == NULL )
1306 ZeroMemory( lpDst, sizeof( *lpDst ) );
1307 lpDst->dwSize = sizeof( *lpDst );
1308 return TRUE;
1311 if( lpSrc->dwSize != sizeof( *lpSrc) )
1313 return FALSE;
1316 /* Delete any existing pointers */
1317 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1318 HeapFree( GetProcessHeap(), 0, lpDst->u2.lpszLongNameA );
1320 /* Copy as required */
1321 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1323 if( bAnsi )
1325 if( lpSrc->u1.lpszShortNameA )
1327 lpDst->u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), 0,
1328 strlen(lpSrc->u1.lpszShortNameA)+1 );
1329 strcpy( lpDst->u1.lpszShortNameA, lpSrc->u1.lpszShortNameA );
1331 if( lpSrc->u2.lpszLongNameA )
1333 lpDst->u2.lpszLongNameA = HeapAlloc( GetProcessHeap(), 0,
1334 strlen(lpSrc->u2.lpszLongNameA)+1 );
1335 strcpy( lpDst->u2.lpszLongNameA, lpSrc->u2.lpszLongNameA );
1338 else
1340 if( lpSrc->u1.lpszShortNameA )
1342 lpDst->u1.lpszShortName = HeapAlloc( GetProcessHeap(), 0,
1343 (strlenW(lpSrc->u1.lpszShortName)+1)*sizeof(WCHAR) );
1344 strcpyW( lpDst->u1.lpszShortName, lpSrc->u1.lpszShortName );
1346 if( lpSrc->u2.lpszLongNameA )
1348 lpDst->u2.lpszLongName = HeapAlloc( GetProcessHeap(), 0,
1349 (strlenW(lpSrc->u2.lpszLongName)+1)*sizeof(WCHAR) );
1350 strcpyW( lpDst->u2.lpszLongName, lpSrc->u2.lpszLongName );
1354 return TRUE;
1357 static void
1358 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
1359 LPVOID lpData, DWORD dwDataSize )
1361 /* Clear out the data with this player */
1362 if( dwFlags & DPSET_LOCAL )
1364 if ( lpPData->dwLocalDataSize != 0 )
1366 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
1367 lpPData->lpLocalData = NULL;
1368 lpPData->dwLocalDataSize = 0;
1371 else
1373 if( lpPData->dwRemoteDataSize != 0 )
1375 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
1376 lpPData->lpRemoteData = NULL;
1377 lpPData->dwRemoteDataSize = 0;
1381 /* Reallocate for new data */
1382 if( lpData != NULL )
1384 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1385 sizeof( dwDataSize ) );
1386 CopyMemory( lpNewData, lpData, dwDataSize );
1388 if( dwFlags & DPSET_LOCAL )
1390 lpPData->lpLocalData = lpData;
1391 lpPData->dwLocalDataSize = dwDataSize;
1393 else
1395 lpPData->lpRemoteData = lpNewData;
1396 lpPData->dwRemoteDataSize = dwDataSize;
1402 static HRESULT WINAPI DP_IF_CreatePlayer
1403 ( IDirectPlay2Impl* This,
1404 LPVOID lpMsgHdr, /* NULL for local creation, non NULL for remote creation */
1405 LPDPID lpidPlayer,
1406 LPDPNAME lpPlayerName,
1407 HANDLE hEvent,
1408 LPVOID lpData,
1409 DWORD dwDataSize,
1410 DWORD dwFlags,
1411 BOOL bAnsi )
1413 HRESULT hr = DP_OK;
1414 lpPlayerData lpPData;
1415 lpPlayerList lpPList;
1416 DWORD dwCreateFlags = 0;
1418 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1419 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1420 dwDataSize, dwFlags, bAnsi );
1421 if( This->dp2->connectionInitialized == NO_PROVIDER )
1423 return DPERR_UNINITIALIZED;
1426 if( dwFlags == 0 )
1428 dwFlags = DPPLAYER_SPECTATOR;
1431 if( lpidPlayer == NULL )
1433 return DPERR_INVALIDPARAMS;
1437 /* Determine the creation flags for the player. These will be passed
1438 * to the name server if requesting a player id and to the SP when
1439 * informing it of the player creation
1442 if( dwFlags & DPPLAYER_SERVERPLAYER )
1444 if( *lpidPlayer == DPID_SERVERPLAYER )
1446 /* Server player for the host interface */
1447 dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
1449 else if( *lpidPlayer == DPID_NAME_SERVER )
1451 /* Name server - master of everything */
1452 dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
1454 else
1456 /* Server player for a non host interface */
1457 dwCreateFlags |= DPLAYI_PLAYER_SYSPLAYER;
1461 if( lpMsgHdr == NULL )
1462 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1465 /* Verify we know how to handle all the flags */
1466 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1467 ( dwFlags & DPPLAYER_SPECTATOR )
1471 /* Assume non fatal failure */
1472 ERR( "unknown dwFlags = 0x%08x\n", dwFlags );
1475 /* If the name is not specified, we must provide one */
1476 if( *lpidPlayer == DPID_UNKNOWN )
1478 /* If we are the session master, we dish out the group/player ids */
1479 if( This->dp2->bHostInterface )
1481 *lpidPlayer = DP_NextObjectId();
1483 else
1485 hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer );
1487 if( FAILED(hr) )
1489 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1490 return hr;
1494 else
1496 /* FIXME: Would be nice to perhaps verify that we don't already have
1497 * this player.
1501 /* We pass creation flags, so we can distinguish sysplayers and not count them in the current
1502 player total */
1503 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwCreateFlags,
1504 hEvent, bAnsi );
1506 if( lpPData == NULL )
1508 return DPERR_CANTADDPLAYER;
1511 /* Create the list object and link it in */
1512 lpPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPList ) );
1513 if( lpPList == NULL )
1515 FIXME( "Memory leak\n" );
1516 return DPERR_CANTADDPLAYER;
1519 lpPData->uRef = 1;
1520 lpPList->lpPData = lpPData;
1522 /* Add the player to the system group */
1523 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1525 /* Update the information and send it to all players in the session */
1526 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
1528 /* Let the SP know that we've created this player */
1529 if( This->dp2->spData.lpCB->CreatePlayer )
1531 DPSP_CREATEPLAYERDATA data;
1533 data.idPlayer = *lpidPlayer;
1534 data.dwFlags = dwCreateFlags;
1535 data.lpSPMessageHeader = lpMsgHdr;
1536 data.lpISP = This->dp2->spData.lpISP;
1538 TRACE( "Calling SP CreatePlayer 0x%08x: dwFlags: 0x%08x lpMsgHdr: %p\n",
1539 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
1541 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1544 if( FAILED(hr) )
1546 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1547 return hr;
1550 /* Now let the SP know that this player is a member of the system group */
1551 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1553 DPSP_ADDPLAYERTOGROUPDATA data;
1555 data.idPlayer = *lpidPlayer;
1556 data.idGroup = DPID_SYSTEM_GROUP;
1557 data.lpISP = This->dp2->spData.lpISP;
1559 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1561 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1564 if( FAILED(hr) )
1566 ERR( "Failed to add player to sys group with sp: %s\n",
1567 DPLAYX_HresultToString(hr) );
1568 return hr;
1571 #if 1
1572 if( This->dp2->bHostInterface == FALSE )
1574 /* Let the name server know about the creation of this player */
1575 /* FIXME: Is this only to be done for the creation of a server player or
1576 * is this used for regular players? If only for server players, move
1577 * this call to DP_SecureOpen(...);
1579 #if 0
1580 TRACE( "Sending message to self to get my addr\n" );
1581 DP_MSG_ToSelf( This, *lpidPlayer ); /* This is a hack right now */
1582 #endif
1584 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
1586 #else
1587 /* Inform all other peers of the creation of a new player. If there are
1588 * no peers keep this quiet.
1589 * Also, if this was a remote event, no need to rebroadcast it.
1591 if( ( lpMsgHdr == NULL ) &&
1592 This->dp2->lpSessionDesc &&
1593 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1595 DPMSG_CREATEPLAYERORGROUP msg;
1596 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1598 msg.dwPlayerType = DPPLAYERTYPE_PLAYER;
1599 msg.dpId = *lpidPlayer;
1600 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */
1601 msg.lpData = lpData;
1602 msg.dwDataSize = dwDataSize;
1603 msg.dpnName = *lpPlayerName;
1604 msg.dpIdParent = DPID_NOPARENT_GROUP;
1605 msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
1607 /* FIXME: Correct to just use send effectively? */
1608 /* FIXME: Should size include data w/ message or just message "header" */
1609 /* FIXME: Check return code */
1610 hr = DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
1611 sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
1613 #endif
1615 return hr;
1618 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
1619 ( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1620 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1622 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1624 if( lpidPlayer == NULL )
1626 return DPERR_INVALIDPARAMS;
1629 if( dwFlags & DPPLAYER_SERVERPLAYER )
1631 *lpidPlayer = DPID_SERVERPLAYER;
1633 else
1635 *lpidPlayer = DPID_UNKNOWN;
1638 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1639 lpData, dwDataSize, dwFlags, TRUE );
1642 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
1643 ( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1644 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1646 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1648 if( lpidPlayer == NULL )
1650 return DPERR_INVALIDPARAMS;
1653 if( dwFlags & DPPLAYER_SERVERPLAYER )
1655 *lpidPlayer = DPID_SERVERPLAYER;
1657 else
1659 *lpidPlayer = DPID_UNKNOWN;
1662 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1663 lpData, dwDataSize, dwFlags, FALSE );
1666 static DPID DP_GetRemoteNextObjectId(void)
1668 FIXME( ":stub\n" );
1670 /* Hack solution */
1671 return DP_NextObjectId();
1674 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
1675 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
1676 DPID idPlayer, BOOL bAnsi )
1678 HRESULT hr = DP_OK;
1680 lpGroupData lpGData;
1681 lpPlayerList lpPList;
1683 TRACE( "(%p)->(%p,0x%08x,0x%08x,%u)\n",
1684 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
1686 /* Find the group */
1687 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1689 return DPERR_INVALIDGROUP;
1692 /* Find the player */
1693 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
1695 return DPERR_INVALIDPLAYER;
1698 /* Remove the player shortcut from the group */
1699 DPQ_REMOVE_ENTRY( lpGData->players, players, lpPData->dpid, ==, idPlayer, lpPList );
1701 if( lpPList == NULL )
1703 return DPERR_INVALIDPLAYER;
1706 /* One less reference */
1707 lpPList->lpPData->uRef--;
1709 /* Delete the Player List element */
1710 HeapFree( GetProcessHeap(), 0, lpPList );
1712 /* Inform the SP if they care */
1713 if( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1715 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1717 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1719 data.idPlayer = idPlayer;
1720 data.idGroup = idGroup;
1721 data.lpISP = This->dp2->spData.lpISP;
1723 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1726 /* Need to send a DELETEPLAYERFROMGROUP message */
1727 FIXME( "Need to send a message\n" );
1729 return hr;
1732 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
1733 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
1735 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1736 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, TRUE );
1739 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
1740 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
1742 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1743 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, FALSE );
1746 typedef struct _DPRGOPContext
1748 IDirectPlay3Impl* This;
1749 BOOL bAnsi;
1750 DPID idGroup;
1751 } DPRGOPContext, *lpDPRGOPContext;
1753 static BOOL CALLBACK
1754 cbRemoveGroupOrPlayer(
1755 DPID dpId,
1756 DWORD dwPlayerType,
1757 LPCDPNAME lpName,
1758 DWORD dwFlags,
1759 LPVOID lpContext )
1761 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1763 TRACE( "Removing element:0x%08x (type:0x%08x) from element:0x%08x\n",
1764 dpId, dwPlayerType, lpCtxt->idGroup );
1766 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1768 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt->This, lpCtxt->idGroup,
1769 dpId )
1773 ERR( "Unable to delete group 0x%08x from group 0x%08x\n",
1774 dpId, lpCtxt->idGroup );
1777 else
1779 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl*)lpCtxt->This,
1780 NULL, lpCtxt->idGroup,
1781 dpId, lpCtxt->bAnsi )
1785 ERR( "Unable to delete player 0x%08x from grp 0x%08x\n",
1786 dpId, lpCtxt->idGroup );
1790 return TRUE; /* Continue enumeration */
1793 static HRESULT WINAPI DP_IF_DestroyGroup
1794 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi )
1796 lpGroupData lpGData;
1797 DPRGOPContext context;
1799 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1800 This, lpMsgHdr, idGroup, bAnsi );
1802 /* Find the group */
1803 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1805 return DPERR_INVALIDPLAYER; /* yes player */
1808 context.This = (IDirectPlay3Impl*)This;
1809 context.bAnsi = bAnsi;
1810 context.idGroup = idGroup;
1812 /* Remove all players that this group has */
1813 DP_IF_EnumGroupPlayers( This, idGroup, NULL,
1814 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1816 /* Remove all links to groups that this group has since this is dp3 */
1817 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This, idGroup, NULL,
1818 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1820 /* Remove this group from the parent group - if it has one */
1821 if( ( idGroup != DPID_SYSTEM_GROUP ) &&
1822 ( lpGData->parent != DPID_SYSTEM_GROUP )
1825 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl*)This, lpGData->parent,
1826 idGroup );
1829 /* Now delete this group data and list from the system group */
1830 DP_DeleteGroup( This, idGroup );
1832 /* Let the SP know that we've destroyed this group */
1833 if( This->dp2->spData.lpCB->DeleteGroup )
1835 DPSP_DELETEGROUPDATA data;
1837 FIXME( "data.dwFlags is incorrect\n" );
1839 data.idGroup = idGroup;
1840 data.dwFlags = 0;
1841 data.lpISP = This->dp2->spData.lpISP;
1843 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1846 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1848 return DP_OK;
1851 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
1852 ( LPDIRECTPLAY2A iface, DPID idGroup )
1854 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1855 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
1858 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
1859 ( LPDIRECTPLAY2 iface, DPID idGroup )
1861 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1862 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
1865 typedef struct _DPFAGContext
1867 IDirectPlay2Impl* This;
1868 DPID idPlayer;
1869 BOOL bAnsi;
1870 } DPFAGContext, *lpDPFAGContext;
1872 static HRESULT WINAPI DP_IF_DestroyPlayer
1873 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi )
1875 DPFAGContext cbContext;
1877 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1878 This, lpMsgHdr, idPlayer, bAnsi );
1880 if( This->dp2->connectionInitialized == NO_PROVIDER )
1882 return DPERR_UNINITIALIZED;
1885 if( DP_FindPlayer( This, idPlayer ) == NULL )
1887 return DPERR_INVALIDPLAYER;
1890 /* FIXME: If the player is remote, we must be the host to delete this */
1892 cbContext.This = This;
1893 cbContext.idPlayer = idPlayer;
1894 cbContext.bAnsi = bAnsi;
1896 /* Find each group and call DeletePlayerFromGroup if the player is a
1897 member of the group */
1898 DP_IF_EnumGroups( This, NULL, cbDeletePlayerFromAllGroups,
1899 (LPVOID)&cbContext, DPENUMGROUPS_ALL, bAnsi );
1901 /* Now delete player and player list from the sys group */
1902 DP_DeletePlayer( This, idPlayer );
1904 /* Let the SP know that we've destroyed this group */
1905 if( This->dp2->spData.lpCB->DeletePlayer )
1907 DPSP_DELETEPLAYERDATA data;
1909 FIXME( "data.dwFlags is incorrect\n" );
1911 data.idPlayer = idPlayer;
1912 data.dwFlags = 0;
1913 data.lpISP = This->dp2->spData.lpISP;
1915 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
1918 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
1920 return DP_OK;
1923 static BOOL CALLBACK
1924 cbDeletePlayerFromAllGroups(
1925 DPID dpId,
1926 DWORD dwPlayerType,
1927 LPCDPNAME lpName,
1928 DWORD dwFlags,
1929 LPVOID lpContext )
1931 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
1933 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1935 DP_IF_DeletePlayerFromGroup( lpCtxt->This, NULL, dpId, lpCtxt->idPlayer,
1936 lpCtxt->bAnsi );
1938 /* Enumerate all groups in this group since this will normally only
1939 * be called for top level groups
1941 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)lpCtxt->This,
1942 dpId, NULL,
1943 cbDeletePlayerFromAllGroups,
1944 lpContext, DPENUMGROUPS_ALL,
1945 lpCtxt->bAnsi );
1948 else
1950 ERR( "Group callback has dwPlayerType = 0x%08x\n", dwPlayerType );
1953 return TRUE;
1956 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
1957 ( LPDIRECTPLAY2A iface, DPID idPlayer )
1959 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1960 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
1963 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
1964 ( LPDIRECTPLAY2 iface, DPID idPlayer )
1966 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1967 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
1970 static HRESULT WINAPI DP_IF_EnumGroupPlayers
1971 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
1972 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1973 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1975 lpGroupData lpGData;
1976 lpPlayerList lpPList;
1978 FIXME("(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
1979 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
1980 lpContext, dwFlags, bAnsi );
1982 if( This->dp2->connectionInitialized == NO_PROVIDER )
1984 return DPERR_UNINITIALIZED;
1987 /* Find the group */
1988 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1990 return DPERR_INVALIDGROUP;
1993 if( DPQ_IS_EMPTY( lpGData->players ) )
1995 return DP_OK;
1998 lpPList = DPQ_FIRST( lpGData->players );
2000 /* Walk the players in this group */
2001 for( ;; )
2003 /* We do not enum the name server or app server as they are of no
2004 * consequence to the end user.
2006 if( ( lpPList->lpPData->dpid != DPID_NAME_SERVER ) &&
2007 ( lpPList->lpPData->dpid != DPID_SERVERPLAYER )
2011 /* FIXME: Need to add stuff for dwFlags checking */
2013 if( !lpEnumPlayersCallback2( lpPList->lpPData->dpid, DPPLAYERTYPE_PLAYER,
2014 &lpPList->lpPData->name,
2015 lpPList->lpPData->dwFlags,
2016 lpContext )
2019 /* User requested break */
2020 return DP_OK;
2024 if( DPQ_IS_ENDOFLIST( lpPList->players ) )
2026 break;
2029 lpPList = DPQ_NEXT( lpPList->players );
2032 return DP_OK;
2035 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
2036 ( LPDIRECTPLAY2A iface, DPID idGroup, LPGUID lpguidInstance,
2037 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2038 LPVOID lpContext, DWORD dwFlags )
2040 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2041 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2042 lpEnumPlayersCallback2, lpContext,
2043 dwFlags, TRUE );
2046 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
2047 ( LPDIRECTPLAY2 iface, DPID idGroup, LPGUID lpguidInstance,
2048 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2049 LPVOID lpContext, DWORD dwFlags )
2051 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2052 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2053 lpEnumPlayersCallback2, lpContext,
2054 dwFlags, FALSE );
2057 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2058 static HRESULT WINAPI DP_IF_EnumGroups
2059 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2060 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2061 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2063 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This,
2064 DPID_SYSTEM_GROUP, lpguidInstance,
2065 lpEnumPlayersCallback2, lpContext,
2066 dwFlags, bAnsi );
2069 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
2070 ( LPDIRECTPLAY2A 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, TRUE );
2079 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
2080 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2081 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2082 LPVOID lpContext, DWORD dwFlags )
2084 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2085 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2086 lpContext, dwFlags, FALSE );
2089 static HRESULT WINAPI DP_IF_EnumPlayers
2090 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2091 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2092 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2094 return DP_IF_EnumGroupPlayers( This, DPID_SYSTEM_GROUP, lpguidInstance,
2095 lpEnumPlayersCallback2, lpContext,
2096 dwFlags, bAnsi );
2099 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
2100 ( LPDIRECTPLAY2A 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, TRUE );
2109 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
2110 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2111 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2112 LPVOID lpContext, DWORD dwFlags )
2114 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2115 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2116 lpContext, dwFlags, FALSE );
2119 /* This function should call the registered callback function that the user
2120 passed into EnumSessions for each entry available.
2122 static void DP_InvokeEnumSessionCallbacks
2123 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2124 LPVOID lpNSInfo,
2125 DWORD dwTimeout,
2126 LPVOID lpContext )
2128 LPDPSESSIONDESC2 lpSessionDesc;
2130 FIXME( ": not checking for conditions\n" );
2132 /* Not sure if this should be pruning but it's convenient */
2133 NS_PruneSessionCache( lpNSInfo );
2135 NS_ResetSessionEnumeration( lpNSInfo );
2137 /* Enumerate all sessions */
2138 /* FIXME: Need to indicate ANSI */
2139 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2141 TRACE( "EnumSessionsCallback2 invoked\n" );
2142 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2144 return;
2148 /* Invoke one last time to indicate that there is no more to come */
2149 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2152 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2154 EnumSessionAsyncCallbackData* data = (EnumSessionAsyncCallbackData*)lpContext;
2155 HANDLE hSuicideRequest = data->hSuicideRequest;
2156 DWORD dwTimeout = data->dwTimeout;
2158 TRACE( "Thread started with timeout = 0x%08x\n", dwTimeout );
2160 for( ;; )
2162 HRESULT hr;
2164 /* Sleep up to dwTimeout waiting for request to terminate thread */
2165 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2167 TRACE( "Thread terminating on terminate request\n" );
2168 break;
2171 /* Now resend the enum request */
2172 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2173 data->dwEnumSessionFlags,
2174 data->lpSpData );
2176 if( FAILED(hr) )
2178 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2179 /* FIXME: Should we kill this thread? How to inform the main thread? */
2184 TRACE( "Thread terminating\n" );
2186 /* Clean up the thread data */
2187 CloseHandle( hSuicideRequest );
2188 HeapFree( GetProcessHeap(), 0, lpContext );
2190 /* FIXME: Need to have some notification to main app thread that this is
2191 * dead. It would serve two purposes. 1) allow sync on termination
2192 * so that we don't actually send something to ourselves when we
2193 * become name server (race condition) and 2) so that if we die
2194 * abnormally something else will be able to tell.
2197 return 1;
2200 static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
2202 /* Does a thread exist? If so we were doing an async enum session */
2203 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2205 TRACE( "Killing EnumSession thread %p\n",
2206 This->dp2->hEnumSessionThread );
2208 /* Request that the thread kill itself nicely */
2209 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2210 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2212 /* We no longer need to know about the thread */
2213 CloseHandle( This->dp2->hEnumSessionThread );
2215 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2219 static HRESULT WINAPI DP_IF_EnumSessions
2220 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2221 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2222 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2224 HRESULT hr = DP_OK;
2226 TRACE( "(%p)->(%p,0x%08x,%p,%p,0x%08x,%u)\n",
2227 This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags,
2228 bAnsi );
2229 if( This->dp2->connectionInitialized == NO_PROVIDER )
2231 return DPERR_UNINITIALIZED;
2234 /* Can't enumerate if the interface is already open */
2235 if( This->dp2->bConnectionOpen )
2237 return DPERR_GENERIC;
2240 #if 1
2241 /* The loading of a lobby provider _seems_ to require a backdoor loading
2242 * of the service provider to also associate with this DP object. This is
2243 * because the app doesn't seem to have to call EnumConnections and
2244 * InitializeConnection for the SP before calling this method. As such
2245 * we'll do their dirty work for them with a quick hack so as to always
2246 * load the TCP/IP service provider.
2248 * The correct solution would seem to involve creating a dialog box which
2249 * contains the possible SPs. These dialog boxes most likely follow SDK
2250 * examples.
2252 if( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
2254 LPVOID lpConnection;
2255 DWORD dwSize;
2257 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2259 if( !DP_BuildSPCompoundAddr( (LPGUID)&DPSPGUID_TCPIP, &lpConnection, &dwSize ) )
2261 ERR( "Can't build compound addr\n" );
2262 return DPERR_GENERIC;
2265 hr = DP_IF_InitializeConnection( (IDirectPlay3Impl*)This, lpConnection,
2266 0, bAnsi );
2267 if( FAILED(hr) )
2269 return hr;
2272 /* Free up the address buffer */
2273 HeapFree( GetProcessHeap(), 0, lpConnection );
2275 /* The SP is now initialized */
2276 This->dp2->bSPInitialized = TRUE;
2278 #endif
2281 /* Use the service provider default? */
2282 if( dwTimeout == 0 )
2284 DPCAPS spCaps;
2285 spCaps.dwSize = sizeof( spCaps );
2287 DP_IF_GetCaps( This, &spCaps, 0 );
2288 dwTimeout = spCaps.dwTimeout;
2290 /* The service provider doesn't provide one either! */
2291 if( dwTimeout == 0 )
2293 /* Provide the TCP/IP default */
2294 dwTimeout = DPMSG_WAIT_5_SECS;
2298 if( dwFlags & DPENUMSESSIONS_STOPASYNC )
2300 DP_KillEnumSessionThread( This );
2301 return hr;
2304 if( ( dwFlags & DPENUMSESSIONS_ASYNC ) )
2306 /* Enumerate everything presently in the local session cache */
2307 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2308 This->dp2->lpNameServerData, dwTimeout,
2309 lpContext );
2311 if( This->dp2->dwEnumSessionLock != 0 )
2312 return DPERR_CONNECTING;
2314 /* See if we've already created a thread to service this interface */
2315 if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2317 DWORD dwThreadId;
2318 This->dp2->dwEnumSessionLock++;
2320 /* Send the first enum request inline since the user may cancel a dialog
2321 * if one is presented. Also, may also have a connecting return code.
2323 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2324 dwFlags, &This->dp2->spData );
2326 if( SUCCEEDED(hr) )
2328 EnumSessionAsyncCallbackData* lpData
2329 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpData ) );
2330 /* FIXME: need to kill the thread on object deletion */
2331 lpData->lpSpData = &This->dp2->spData;
2333 lpData->requestGuid = lpsd->guidApplication;
2334 lpData->dwEnumSessionFlags = dwFlags;
2335 lpData->dwTimeout = dwTimeout;
2337 This->dp2->hKillEnumSessionThreadEvent =
2338 CreateEventW( NULL, TRUE, FALSE, NULL );
2340 if( !DuplicateHandle( GetCurrentProcess(),
2341 This->dp2->hKillEnumSessionThreadEvent,
2342 GetCurrentProcess(),
2343 &lpData->hSuicideRequest,
2344 0, FALSE, DUPLICATE_SAME_ACCESS )
2347 ERR( "Can't duplicate thread killing handle\n" );
2350 TRACE( ": creating EnumSessionsRequest thread\n" );
2352 This->dp2->hEnumSessionThread = CreateThread( NULL,
2354 DP_EnumSessionsSendAsyncRequestThread,
2355 lpData,
2357 &dwThreadId );
2359 This->dp2->dwEnumSessionLock--;
2362 else
2364 /* Invalidate the session cache for the interface */
2365 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2367 /* Send the broadcast for session enumeration */
2368 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2369 dwFlags,
2370 &This->dp2->spData );
2373 SleepEx( dwTimeout, FALSE );
2375 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2376 This->dp2->lpNameServerData, dwTimeout,
2377 lpContext );
2380 return hr;
2383 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2384 ( LPDIRECTPLAY2A 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, TRUE );
2393 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2394 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2395 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2396 LPVOID lpContext, DWORD dwFlags )
2398 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2399 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2400 lpContext, dwFlags, FALSE );
2403 static HRESULT WINAPI DP_IF_GetPlayerCaps
2404 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
2405 DWORD dwFlags )
2407 DPSP_GETCAPSDATA data;
2409 TRACE("(%p)->(0x%08x,%p,0x%08x)\n", This, idPlayer, lpDPCaps, dwFlags);
2411 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2413 return DPERR_UNINITIALIZED;
2416 /* Query the service provider */
2417 data.idPlayer = idPlayer;
2418 data.dwFlags = dwFlags;
2419 data.lpCaps = lpDPCaps;
2420 data.lpISP = This->dp2->spData.lpISP;
2422 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2425 static HRESULT WINAPI DP_IF_GetCaps
2426 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags )
2428 return DP_IF_GetPlayerCaps( This, DPID_ALLPLAYERS, lpDPCaps, dwFlags );
2431 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2432 ( LPDIRECTPLAY2A iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2434 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2435 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2438 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2439 ( LPDIRECTPLAY2 iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2441 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2442 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2445 static HRESULT WINAPI DP_IF_GetGroupData
2446 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2447 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2449 lpGroupData lpGData;
2450 DWORD dwRequiredBufferSize;
2451 LPVOID lpCopyDataFrom;
2453 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2454 This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi );
2456 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2458 return DPERR_INVALIDGROUP;
2461 /* How much buffer is required? */
2462 if( dwFlags & DPSET_LOCAL )
2464 dwRequiredBufferSize = lpGData->dwLocalDataSize;
2465 lpCopyDataFrom = lpGData->lpLocalData;
2467 else
2469 dwRequiredBufferSize = lpGData->dwRemoteDataSize;
2470 lpCopyDataFrom = lpGData->lpRemoteData;
2473 /* Is the user requesting to know how big a buffer is required? */
2474 if( ( lpData == NULL ) ||
2475 ( *lpdwDataSize < dwRequiredBufferSize )
2478 *lpdwDataSize = dwRequiredBufferSize;
2479 return DPERR_BUFFERTOOSMALL;
2482 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2484 return DP_OK;
2487 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2488 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2489 LPDWORD lpdwDataSize, DWORD dwFlags )
2491 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2492 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2493 dwFlags, TRUE );
2496 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2497 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2498 LPDWORD lpdwDataSize, DWORD dwFlags )
2500 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2501 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2502 dwFlags, FALSE );
2505 static HRESULT WINAPI DP_IF_GetGroupName
2506 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2507 LPDWORD lpdwDataSize, BOOL bAnsi )
2509 lpGroupData lpGData;
2510 LPDPNAME lpName = (LPDPNAME)lpData;
2511 DWORD dwRequiredDataSize;
2513 FIXME("(%p)->(0x%08x,%p,%p,%u) ANSI ignored\n",
2514 This, idGroup, lpData, lpdwDataSize, bAnsi );
2516 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2518 return DPERR_INVALIDGROUP;
2521 dwRequiredDataSize = lpGData->name.dwSize;
2523 if( lpGData->name.u1.lpszShortNameA )
2525 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
2528 if( lpGData->name.u2.lpszLongNameA )
2530 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
2533 if( ( lpData == NULL ) ||
2534 ( *lpdwDataSize < dwRequiredDataSize )
2537 *lpdwDataSize = dwRequiredDataSize;
2538 return DPERR_BUFFERTOOSMALL;
2541 /* Copy the structure */
2542 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2544 if( lpGData->name.u1.lpszShortNameA )
2546 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2547 lpGData->name.u1.lpszShortNameA );
2549 else
2551 lpName->u1.lpszShortNameA = NULL;
2554 if( lpGData->name.u1.lpszShortNameA )
2556 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2557 lpGData->name.u2.lpszLongNameA );
2559 else
2561 lpName->u2.lpszLongNameA = NULL;
2564 return DP_OK;
2567 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2568 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2569 LPDWORD lpdwDataSize )
2571 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2572 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2575 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2576 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2577 LPDWORD lpdwDataSize )
2579 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2580 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2583 static HRESULT WINAPI DP_IF_GetMessageCount
2584 ( IDirectPlay2Impl* This, DPID idPlayer,
2585 LPDWORD lpdwCount, BOOL bAnsi )
2587 FIXME("(%p)->(0x%08x,%p,%u): stub\n", This, idPlayer, lpdwCount, bAnsi );
2588 return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer,
2589 DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL,
2590 bAnsi );
2593 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2594 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDWORD lpdwCount )
2596 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2597 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, TRUE );
2600 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2601 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDWORD lpdwCount )
2603 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2604 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, FALSE );
2607 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2608 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2610 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2611 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2612 return DP_OK;
2615 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2616 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2618 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2619 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2620 return DP_OK;
2623 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2624 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2625 DWORD dwFlags )
2627 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2628 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2631 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2632 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2633 DWORD dwFlags )
2635 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2636 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2639 static HRESULT WINAPI DP_IF_GetPlayerData
2640 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2641 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2643 lpPlayerList lpPList;
2644 DWORD dwRequiredBufferSize;
2645 LPVOID lpCopyDataFrom;
2647 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2648 This, idPlayer, lpData, lpdwDataSize, dwFlags, bAnsi );
2650 if( This->dp2->connectionInitialized == NO_PROVIDER )
2652 return DPERR_UNINITIALIZED;
2655 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2657 return DPERR_INVALIDPLAYER;
2660 /* How much buffer is required? */
2661 if( dwFlags & DPSET_LOCAL )
2663 dwRequiredBufferSize = lpPList->lpPData->dwLocalDataSize;
2664 lpCopyDataFrom = lpPList->lpPData->lpLocalData;
2666 else
2668 dwRequiredBufferSize = lpPList->lpPData->dwRemoteDataSize;
2669 lpCopyDataFrom = lpPList->lpPData->lpRemoteData;
2672 /* Is the user requesting to know how big a buffer is required? */
2673 if( ( lpData == NULL ) ||
2674 ( *lpdwDataSize < dwRequiredBufferSize )
2677 *lpdwDataSize = dwRequiredBufferSize;
2678 return DPERR_BUFFERTOOSMALL;
2681 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2683 return DP_OK;
2686 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2687 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2688 LPDWORD lpdwDataSize, DWORD dwFlags )
2690 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2691 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2692 dwFlags, TRUE );
2695 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2696 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2697 LPDWORD lpdwDataSize, DWORD dwFlags )
2699 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2700 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2701 dwFlags, FALSE );
2704 static HRESULT WINAPI DP_IF_GetPlayerName
2705 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2706 LPDWORD lpdwDataSize, BOOL bAnsi )
2708 lpPlayerList lpPList;
2709 LPDPNAME lpName = (LPDPNAME)lpData;
2710 DWORD dwRequiredDataSize;
2712 FIXME( "(%p)->(0x%08x,%p,%p,%u): ANSI\n",
2713 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2715 if( This->dp2->connectionInitialized == NO_PROVIDER )
2717 return DPERR_UNINITIALIZED;
2720 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2722 return DPERR_INVALIDPLAYER;
2725 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
2727 if( lpPList->lpPData->name.u1.lpszShortNameA )
2729 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
2732 if( lpPList->lpPData->name.u2.lpszLongNameA )
2734 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
2737 if( ( lpData == NULL ) ||
2738 ( *lpdwDataSize < dwRequiredDataSize )
2741 *lpdwDataSize = dwRequiredDataSize;
2742 return DPERR_BUFFERTOOSMALL;
2745 /* Copy the structure */
2746 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
2748 if( lpPList->lpPData->name.u1.lpszShortNameA )
2750 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2751 lpPList->lpPData->name.u1.lpszShortNameA );
2753 else
2755 lpName->u1.lpszShortNameA = NULL;
2758 if( lpPList->lpPData->name.u1.lpszShortNameA )
2760 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2761 lpPList->lpPData->name.u2.lpszLongNameA );
2763 else
2765 lpName->u2.lpszLongNameA = NULL;
2768 return DP_OK;
2771 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2772 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2773 LPDWORD lpdwDataSize )
2775 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2776 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
2779 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2780 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2781 LPDWORD lpdwDataSize )
2783 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2784 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
2787 static HRESULT WINAPI DP_GetSessionDesc
2788 ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize,
2789 BOOL bAnsi )
2791 DWORD dwRequiredSize;
2793 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
2795 if( This->dp2->connectionInitialized == NO_PROVIDER )
2797 return DPERR_UNINITIALIZED;
2800 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
2802 return DPERR_INVALIDPARAMS;
2805 /* FIXME: Get from This->dp2->lpSessionDesc */
2806 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
2808 if ( ( lpData == NULL ) ||
2809 ( *lpdwDataSize < dwRequiredSize )
2812 *lpdwDataSize = dwRequiredSize;
2813 return DPERR_BUFFERTOOSMALL;
2816 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
2818 return DP_OK;
2821 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
2822 ( LPDIRECTPLAY2A iface, LPVOID lpData, LPDWORD lpdwDataSize )
2824 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2825 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2828 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
2829 ( LPDIRECTPLAY2 iface, LPVOID lpData, LPDWORD lpdwDataSize )
2831 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2832 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2835 /* Intended only for COM compatibility. Always returns an error. */
2836 static HRESULT WINAPI DirectPlay2AImpl_Initialize
2837 ( LPDIRECTPLAY2A iface, LPGUID lpGUID )
2839 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2840 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2841 return DPERR_ALREADYINITIALIZED;
2844 /* Intended only for COM compatibility. Always returns an error. */
2845 static HRESULT WINAPI DirectPlay2WImpl_Initialize
2846 ( LPDIRECTPLAY2 iface, LPGUID lpGUID )
2848 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2849 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2850 return DPERR_ALREADYINITIALIZED;
2854 static HRESULT WINAPI DP_SecureOpen
2855 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
2856 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
2857 BOOL bAnsi )
2859 HRESULT hr = DP_OK;
2861 FIXME( "(%p)->(%p,0x%08x,%p,%p): partial stub\n",
2862 This, lpsd, dwFlags, lpSecurity, lpCredentials );
2864 if( This->dp2->connectionInitialized == NO_PROVIDER )
2866 return DPERR_UNINITIALIZED;
2869 if( lpsd->dwSize != sizeof(DPSESSIONDESC2) )
2871 TRACE( ": rejecting invalid dpsd size (%d).\n", lpsd->dwSize );
2872 return DPERR_INVALIDPARAMS;
2875 if( This->dp2->bConnectionOpen )
2877 TRACE( ": rejecting already open connection.\n" );
2878 return DPERR_ALREADYINITIALIZED;
2881 /* If we're enumerating, kill the thread */
2882 DP_KillEnumSessionThread( This );
2884 if( dwFlags & DPOPEN_CREATE )
2886 /* Rightoo - this computer is the host and the local computer needs to be
2887 the name server so that others can join this session */
2888 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
2890 This->dp2->bHostInterface = TRUE;
2892 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
2893 if( FAILED( hr ) )
2895 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
2896 return hr;
2900 /* Invoke the conditional callback for the service provider */
2901 if( This->dp2->spData.lpCB->Open )
2903 DPSP_OPENDATA data;
2905 FIXME( "Not all data fields are correct. Need new parameter\n" );
2907 data.bCreate = (dwFlags & DPOPEN_CREATE ) ? TRUE : FALSE;
2908 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
2909 : NS_GetNSAddr( This->dp2->lpNameServerData );
2910 data.lpISP = This->dp2->spData.lpISP;
2911 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) ? TRUE : FALSE;
2912 data.dwOpenFlags = dwFlags;
2913 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
2915 hr = (*This->dp2->spData.lpCB->Open)(&data);
2916 if( FAILED( hr ) )
2918 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
2919 return hr;
2924 /* Create the system group of which everything is a part of */
2925 DPID systemGroup = DPID_SYSTEM_GROUP;
2927 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
2928 NULL, 0, 0, TRUE );
2932 if( dwFlags & DPOPEN_JOIN )
2934 DPID dpidServerId = DPID_UNKNOWN;
2936 /* Create the server player for this interface. This way we can receive
2937 * messages for this session.
2939 /* FIXME: I suppose that we should be setting an event for a receive
2940 * type of thing. That way the messaging thread could know to wake
2941 * up. DPlay would then trigger the hEvent for the player the
2942 * message is directed to.
2944 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
2946 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
2949 else if( dwFlags & DPOPEN_CREATE )
2951 DPID dpidNameServerId = DPID_NAME_SERVER;
2953 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
2954 0, DPPLAYER_SERVERPLAYER, bAnsi );
2957 if( FAILED(hr) )
2959 ERR( "Couldn't create name server/system player: %s\n",
2960 DPLAYX_HresultToString(hr) );
2963 return hr;
2966 static HRESULT WINAPI DirectPlay2AImpl_Open
2967 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2969 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2970 TRACE("(%p)->(%p,0x%08x)\n", This, lpsd, dwFlags );
2971 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, TRUE );
2974 static HRESULT WINAPI DirectPlay2WImpl_Open
2975 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2977 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2978 TRACE("(%p)->(%p,0x%08x)\n", This, lpsd, dwFlags );
2979 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, FALSE );
2982 static HRESULT WINAPI DP_IF_Receive
2983 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
2984 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi )
2986 LPDPMSG lpMsg = NULL;
2988 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p,%u): stub\n",
2989 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
2991 if( This->dp2->connectionInitialized == NO_PROVIDER )
2993 return DPERR_UNINITIALIZED;
2996 if( dwFlags == 0 )
2998 dwFlags = DPRECEIVE_ALL;
3001 /* If the lpData is NULL, we must be peeking the message */
3002 if( ( lpData == NULL ) &&
3003 !( dwFlags & DPRECEIVE_PEEK )
3006 return DPERR_INVALIDPARAMS;
3009 if( dwFlags & DPRECEIVE_ALL )
3011 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
3013 if( !( dwFlags & DPRECEIVE_PEEK ) )
3015 FIXME( "Remove from queue\n" );
3018 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
3019 ( dwFlags & DPRECEIVE_FROMPLAYER )
3022 FIXME( "Find matching message 0x%08x\n", dwFlags );
3024 else
3026 ERR( "Hmmm..dwFlags 0x%08x\n", dwFlags );
3029 if( lpMsg == NULL )
3031 return DPERR_NOMESSAGES;
3034 /* Copy into the provided buffer */
3035 if (lpData) CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
3037 return DP_OK;
3040 static HRESULT WINAPI DirectPlay2AImpl_Receive
3041 ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo,
3042 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
3044 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3045 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
3046 lpData, lpdwDataSize, TRUE );
3049 static HRESULT WINAPI DirectPlay2WImpl_Receive
3050 ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo,
3051 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
3053 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3054 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
3055 lpData, lpdwDataSize, FALSE );
3058 static HRESULT WINAPI DirectPlay2AImpl_Send
3059 ( LPDIRECTPLAY2A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3061 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3062 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3063 0, 0, NULL, NULL, TRUE );
3066 static HRESULT WINAPI DirectPlay2WImpl_Send
3067 ( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3069 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3070 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3071 0, 0, NULL, NULL, FALSE );
3074 static HRESULT WINAPI DP_IF_SetGroupData
3075 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
3076 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3078 lpGroupData lpGData;
3080 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3081 This, idGroup, lpData, dwDataSize, dwFlags, bAnsi );
3083 /* Parameter check */
3084 if( ( lpData == NULL ) &&
3085 ( dwDataSize != 0 )
3088 return DPERR_INVALIDPARAMS;
3091 /* Find the pointer to the data for this player */
3092 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3094 return DPERR_INVALIDOBJECT;
3097 if( !(dwFlags & DPSET_LOCAL) )
3099 FIXME( "Was this group created by this interface?\n" );
3100 /* FIXME: If this is a remote update need to allow it but not
3101 * send a message.
3105 DP_SetGroupData( lpGData, dwFlags, lpData, dwDataSize );
3107 /* FIXME: Only send a message if this group is local to the session otherwise
3108 * it will have been rejected above
3110 if( !(dwFlags & DPSET_LOCAL) )
3112 FIXME( "Send msg?\n" );
3115 return DP_OK;
3118 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
3119 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
3120 DWORD dwDataSize, DWORD dwFlags )
3122 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3123 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, TRUE );
3126 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
3127 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
3128 DWORD dwDataSize, DWORD dwFlags )
3130 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3131 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, FALSE );
3134 static HRESULT WINAPI DP_IF_SetGroupName
3135 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
3136 DWORD dwFlags, BOOL bAnsi )
3138 lpGroupData lpGData;
3140 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n", This, idGroup,
3141 lpGroupName, dwFlags, bAnsi );
3143 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3145 return DPERR_INVALIDGROUP;
3148 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
3150 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3151 FIXME( "Message not sent and dwFlags ignored\n" );
3153 return DP_OK;
3156 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
3157 ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName,
3158 DWORD dwFlags )
3160 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3161 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
3164 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
3165 ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName,
3166 DWORD dwFlags )
3168 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3169 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
3172 static HRESULT WINAPI DP_IF_SetPlayerData
3173 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
3174 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3176 lpPlayerList lpPList;
3178 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3179 This, idPlayer, lpData, dwDataSize, dwFlags, bAnsi );
3181 if( This->dp2->connectionInitialized == NO_PROVIDER )
3183 return DPERR_UNINITIALIZED;
3186 /* Parameter check */
3187 if( ( lpData == NULL ) &&
3188 ( dwDataSize != 0 )
3191 return DPERR_INVALIDPARAMS;
3194 /* Find the pointer to the data for this player */
3195 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3197 return DPERR_INVALIDPLAYER;
3200 if( !(dwFlags & DPSET_LOCAL) )
3202 FIXME( "Was this group created by this interface?\n" );
3203 /* FIXME: If this is a remote update need to allow it but not
3204 * send a message.
3208 DP_SetPlayerData( lpPList->lpPData, dwFlags, lpData, dwDataSize );
3210 if( !(dwFlags & DPSET_LOCAL) )
3212 FIXME( "Send msg?\n" );
3215 return DP_OK;
3218 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3219 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
3220 DWORD dwDataSize, DWORD dwFlags )
3222 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3223 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3224 dwFlags, TRUE );
3227 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3228 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
3229 DWORD dwDataSize, DWORD dwFlags )
3231 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3232 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3233 dwFlags, FALSE );
3236 static HRESULT WINAPI DP_IF_SetPlayerName
3237 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
3238 DWORD dwFlags, BOOL bAnsi )
3240 lpPlayerList lpPList;
3242 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n",
3243 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3245 if( This->dp2->connectionInitialized == NO_PROVIDER )
3247 return DPERR_UNINITIALIZED;
3250 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3252 return DPERR_INVALIDGROUP;
3255 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3257 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3258 FIXME( "Message not sent and dwFlags ignored\n" );
3260 return DP_OK;
3263 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3264 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName,
3265 DWORD dwFlags )
3267 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3268 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3271 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3272 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName,
3273 DWORD dwFlags )
3275 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3276 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3279 static HRESULT WINAPI DP_SetSessionDesc
3280 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
3281 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3283 DWORD dwRequiredSize;
3284 LPDPSESSIONDESC2 lpTempSessDesc;
3286 TRACE( "(%p)->(%p,0x%08x,%u,%u)\n",
3287 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3289 if( This->dp2->connectionInitialized == NO_PROVIDER )
3291 return DPERR_UNINITIALIZED;
3294 if( dwFlags )
3296 return DPERR_INVALIDPARAMS;
3299 /* Only the host is allowed to update the session desc */
3300 if( !This->dp2->bHostInterface )
3302 return DPERR_ACCESSDENIED;
3305 /* FIXME: Copy into This->dp2->lpSessionDesc */
3306 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3307 lpTempSessDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize );
3309 if( lpTempSessDesc == NULL )
3311 return DPERR_OUTOFMEMORY;
3314 /* Free the old */
3315 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3317 This->dp2->lpSessionDesc = lpTempSessDesc;
3318 /* Set the new */
3319 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3320 if( bInitial )
3322 /*Initializing session GUID*/
3323 CoCreateGuid( &(This->dp2->lpSessionDesc->guidInstance) );
3325 /* If this is an external invocation of the interface, we should be
3326 * letting everyone know that things have changed. Otherwise this is
3327 * just an initialization and it doesn't need to be propagated.
3329 if( !bInitial )
3331 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3334 return DP_OK;
3337 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3338 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3340 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3341 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3344 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3345 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3347 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3348 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3351 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3352 DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3354 DWORD dwSize = 0;
3356 if( lpSessDesc == NULL )
3358 /* Hmmm..don't need any size? */
3359 ERR( "NULL lpSessDesc\n" );
3360 return dwSize;
3363 dwSize += sizeof( *lpSessDesc );
3365 if( bAnsi )
3367 if( lpSessDesc->u1.lpszSessionNameA )
3369 dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1;
3372 if( lpSessDesc->u2.lpszPasswordA )
3374 dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1;
3377 else /* UNICODE */
3379 if( lpSessDesc->u1.lpszSessionName )
3381 dwSize += sizeof( WCHAR ) *
3382 ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 );
3385 if( lpSessDesc->u2.lpszPassword )
3387 dwSize += sizeof( WCHAR ) *
3388 ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 );
3392 return dwSize;
3395 /* Assumes that contiguous buffers are already allocated. */
3396 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3397 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3399 BYTE* lpStartOfFreeSpace;
3401 if( lpSessionDest == NULL )
3403 ERR( "NULL lpSessionDest\n" );
3404 return;
3407 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3409 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3411 if( bAnsi )
3413 if( lpSessionSrc->u1.lpszSessionNameA )
3415 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3416 lpSessionDest->u1.lpszSessionNameA );
3417 lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3418 lpStartOfFreeSpace +=
3419 lstrlenA( lpSessionDest->u1.lpszSessionNameA ) + 1;
3422 if( lpSessionSrc->u2.lpszPasswordA )
3424 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3425 lpSessionDest->u2.lpszPasswordA );
3426 lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3427 lpStartOfFreeSpace +=
3428 lstrlenA( lpSessionDest->u2.lpszPasswordA ) + 1;
3431 else /* UNICODE */
3433 if( lpSessionSrc->u1.lpszSessionName )
3435 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3436 lpSessionDest->u1.lpszSessionName );
3437 lpSessionDest->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3438 lpStartOfFreeSpace += sizeof(WCHAR) *
3439 ( lstrlenW( lpSessionDest->u1.lpszSessionName ) + 1 );
3442 if( lpSessionSrc->u2.lpszPassword )
3444 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3445 lpSessionDest->u2.lpszPassword );
3446 lpSessionDest->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3447 lpStartOfFreeSpace += sizeof(WCHAR) *
3448 ( lstrlenW( lpSessionDest->u2.lpszPassword ) + 1 );
3454 static HRESULT WINAPI DP_IF_AddGroupToGroup
3455 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3457 lpGroupData lpGData;
3458 lpGroupList lpNewGList;
3460 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, idParentGroup, idGroup );
3462 if( This->dp2->connectionInitialized == NO_PROVIDER )
3464 return DPERR_UNINITIALIZED;
3467 if( DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) == NULL )
3469 return DPERR_INVALIDGROUP;
3472 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3474 return DPERR_INVALIDGROUP;
3477 /* Create a player list (ie "shortcut" ) */
3478 lpNewGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewGList ) );
3479 if( lpNewGList == NULL )
3481 return DPERR_CANTADDPLAYER;
3484 /* Add the shortcut */
3485 lpGData->uRef++;
3486 lpNewGList->lpGData = lpGData;
3488 /* Add the player to the list of players for this group */
3489 DPQ_INSERT( lpGData->groups, lpNewGList, groups );
3491 /* Send a ADDGROUPTOGROUP message */
3492 FIXME( "Not sending message\n" );
3494 return DP_OK;
3497 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3498 ( LPDIRECTPLAY3A iface, DPID idParentGroup, DPID idGroup )
3500 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3501 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3504 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3505 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3507 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3508 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3511 static HRESULT WINAPI DP_IF_CreateGroupInGroup
3512 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
3513 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
3514 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3516 lpGroupData lpGParentData;
3517 lpGroupList lpGList;
3518 lpGroupData lpGData;
3520 TRACE( "(%p)->(0x%08x,%p,%p,%p,0x%08x,0x%08x,%u)\n",
3521 This, idParentGroup, lpidGroup, lpGroupName, lpData,
3522 dwDataSize, dwFlags, bAnsi );
3524 if( This->dp2->connectionInitialized == NO_PROVIDER )
3526 return DPERR_UNINITIALIZED;
3529 /* Verify that the specified parent is valid */
3530 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This,
3531 idParentGroup ) ) == NULL
3534 return DPERR_INVALIDGROUP;
3537 lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName,
3538 dwFlags, idParentGroup, bAnsi );
3540 if( lpGData == NULL )
3542 return DPERR_CANTADDPLAYER; /* yes player not group */
3545 /* Something else is referencing this data */
3546 lpGData->uRef++;
3548 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
3550 /* The list has now been inserted into the interface group list. We now
3551 need to put a "shortcut" to this group in the parent group */
3552 lpGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGList ) );
3553 if( lpGList == NULL )
3555 FIXME( "Memory leak\n" );
3556 return DPERR_CANTADDPLAYER; /* yes player not group */
3559 lpGList->lpGData = lpGData;
3561 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
3563 /* Let the SP know that we've created this group */
3564 if( This->dp2->spData.lpCB->CreateGroup )
3566 DPSP_CREATEGROUPDATA data;
3568 TRACE( "Calling SP CreateGroup\n" );
3570 data.idGroup = *lpidGroup;
3571 data.dwFlags = dwFlags;
3572 data.lpSPMessageHeader = lpMsgHdr;
3573 data.lpISP = This->dp2->spData.lpISP;
3575 (*This->dp2->spData.lpCB->CreateGroup)( &data );
3578 /* Inform all other peers of the creation of a new group. If there are
3579 * no peers keep this quiet.
3581 if( This->dp2->lpSessionDesc &&
3582 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
3584 DPMSG_CREATEPLAYERORGROUP msg;
3586 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
3587 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
3588 msg.dpId = *lpidGroup;
3589 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
3590 msg.lpData = lpData;
3591 msg.dwDataSize = dwDataSize;
3592 msg.dpnName = *lpGroupName;
3594 /* FIXME: Correct to just use send effectively? */
3595 /* FIXME: Should size include data w/ message or just message "header" */
3596 /* FIXME: Check return code */
3597 DP_SendEx( (IDirectPlay2Impl*)This,
3598 DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
3599 0, 0, NULL, NULL, bAnsi );
3602 return DP_OK;
3605 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3606 ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup,
3607 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3608 DWORD dwFlags )
3610 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3612 *lpidGroup = DPID_UNKNOWN;
3614 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3615 lpGroupName, lpData, dwDataSize, dwFlags,
3616 TRUE );
3619 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3620 ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup,
3621 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3622 DWORD dwFlags )
3624 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3626 *lpidGroup = DPID_UNKNOWN;
3628 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3629 lpGroupName, lpData, dwDataSize,
3630 dwFlags, FALSE );
3633 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
3634 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3636 lpGroupList lpGList;
3637 lpGroupData lpGParentData;
3639 TRACE("(%p)->(0x%08x,0x%08x)\n", This, idParentGroup, idGroup );
3641 /* Is the parent group valid? */
3642 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3644 return DPERR_INVALIDGROUP;
3647 /* Remove the group from the parent group queue */
3648 DPQ_REMOVE_ENTRY( lpGParentData->groups, groups, lpGData->dpid, ==, idGroup, lpGList );
3650 if( lpGList == NULL )
3652 return DPERR_INVALIDGROUP;
3655 /* Decrement the ref count */
3656 lpGList->lpGData->uRef--;
3658 /* Free up the list item */
3659 HeapFree( GetProcessHeap(), 0, lpGList );
3661 /* Should send a DELETEGROUPFROMGROUP message */
3662 FIXME( "message not sent\n" );
3664 return DP_OK;
3667 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3668 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3670 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3671 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3674 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3675 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3677 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3678 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3681 static
3682 BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
3683 LPDWORD lpdwBufSize )
3685 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3686 HRESULT hr;
3688 dpCompoundAddress.dwDataSize = sizeof( GUID );
3689 dpCompoundAddress.guidDataType = DPAID_ServiceProvider;
3690 dpCompoundAddress.lpData = lpcSpGuid;
3692 *lplpAddrBuf = NULL;
3693 *lpdwBufSize = 0;
3695 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3696 lpdwBufSize, TRUE );
3698 if( hr != DPERR_BUFFERTOOSMALL )
3700 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3701 return FALSE;
3704 /* Now allocate the buffer */
3705 *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3706 *lpdwBufSize );
3708 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3709 lpdwBufSize, TRUE );
3710 if( FAILED(hr) )
3712 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3713 return FALSE;
3716 return TRUE;
3719 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
3720 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3722 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3723 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3725 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
3726 if( dwFlags == 0 )
3728 dwFlags = DPCONNECTION_DIRECTPLAY;
3731 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
3732 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) )
3735 return DPERR_INVALIDFLAGS;
3738 if( !lpEnumCallback )
3740 return DPERR_INVALIDPARAMS;
3743 /* Enumerate DirectPlay service providers */
3744 if( dwFlags & DPCONNECTION_DIRECTPLAY )
3746 HKEY hkResult;
3747 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3748 LPCSTR guidDataSubKey = "Guid";
3749 char subKeyName[51];
3750 DWORD dwIndex, sizeOfSubKeyName=50;
3751 FILETIME filetime;
3753 /* Need to loop over the service providers in the registry */
3754 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3755 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3757 /* Hmmm. Does this mean that there are no service providers? */
3758 ERR(": no service providers?\n");
3759 return DP_OK;
3763 /* Traverse all the service providers we have available */
3764 for( dwIndex=0;
3765 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3766 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3767 ++dwIndex, sizeOfSubKeyName=51 )
3770 HKEY hkServiceProvider;
3771 GUID serviceProviderGUID;
3772 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3773 char returnBuffer[51];
3774 WCHAR buff[51];
3775 DPNAME dpName;
3776 BOOL bBuildPass;
3778 LPVOID lpAddressBuffer = NULL;
3779 DWORD dwAddressBufferSize = 0;
3781 TRACE(" this time through: %s\n", subKeyName );
3783 /* Get a handle for this particular service provider */
3784 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3785 &hkServiceProvider ) != ERROR_SUCCESS )
3787 ERR(": what the heck is going on?\n" );
3788 continue;
3791 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3792 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
3793 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3795 ERR(": missing GUID registry data members\n" );
3796 RegCloseKey(hkServiceProvider);
3797 continue;
3799 RegCloseKey(hkServiceProvider);
3801 /* FIXME: Check return types to ensure we're interpreting data right */
3802 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3803 CLSIDFromString( buff, &serviceProviderGUID );
3804 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3806 /* Fill in the DPNAME struct for the service provider */
3807 dpName.dwSize = sizeof( dpName );
3808 dpName.dwFlags = 0;
3809 dpName.u1.lpszShortNameA = subKeyName;
3810 dpName.u2.lpszLongNameA = NULL;
3812 /* Create the compound address for the service provider.
3813 * NOTE: This is a gruesome architectural scar right now. DP
3814 * uses DPL and DPL uses DP. Nasty stuff. This may be why the
3815 * native dll just gets around this little bit by allocating an
3816 * 80 byte buffer which isn't even filled with a valid compound
3817 * address. Oh well. Creating a proper compound address is the
3818 * way to go anyways despite this method taking slightly more
3819 * heap space and realtime :) */
3821 bBuildPass = DP_BuildSPCompoundAddr( &serviceProviderGUID,
3822 &lpAddressBuffer,
3823 &dwAddressBufferSize );
3824 if( !bBuildPass )
3826 ERR( "Can't build compound addr\n" );
3827 return DPERR_GENERIC;
3830 /* The enumeration will return FALSE if we are not to continue */
3831 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3832 &dpName, dwFlags, lpContext ) )
3834 return DP_OK;
3839 /* Enumerate DirectPlayLobby service providers */
3840 if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY )
3842 HKEY hkResult;
3843 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3844 LPCSTR guidDataSubKey = "Guid";
3845 char subKeyName[51];
3846 DWORD dwIndex, sizeOfSubKeyName=50;
3847 FILETIME filetime;
3849 /* Need to loop over the service providers in the registry */
3850 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3851 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3853 /* Hmmm. Does this mean that there are no service providers? */
3854 ERR(": no service providers?\n");
3855 return DP_OK;
3859 /* Traverse all the lobby providers we have available */
3860 for( dwIndex=0;
3861 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3862 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3863 ++dwIndex, sizeOfSubKeyName=51 )
3866 HKEY hkServiceProvider;
3867 GUID serviceProviderGUID;
3868 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3869 char returnBuffer[51];
3870 WCHAR buff[51];
3871 DPNAME dpName;
3872 HRESULT hr;
3874 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3875 LPVOID lpAddressBuffer = NULL;
3876 DWORD dwAddressBufferSize = 0;
3878 TRACE(" this time through: %s\n", subKeyName );
3880 /* Get a handle for this particular service provider */
3881 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3882 &hkServiceProvider ) != ERROR_SUCCESS )
3884 ERR(": what the heck is going on?\n" );
3885 continue;
3888 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3889 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
3890 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3892 ERR(": missing GUID registry data members\n" );
3893 RegCloseKey(hkServiceProvider);
3894 continue;
3896 RegCloseKey(hkServiceProvider);
3898 /* FIXME: Check return types to ensure we're interpreting data right */
3899 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3900 CLSIDFromString( buff, &serviceProviderGUID );
3901 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3903 /* Fill in the DPNAME struct for the service provider */
3904 dpName.dwSize = sizeof( dpName );
3905 dpName.dwFlags = 0;
3906 dpName.u1.lpszShortNameA = subKeyName;
3907 dpName.u2.lpszLongNameA = NULL;
3909 /* Create the compound address for the service provider.
3910 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
3911 nast stuff. This may be why the native dll just gets around this little bit by
3912 allocating an 80 byte buffer which isn't even a filled with a valid compound
3913 address. Oh well. Creating a proper compound address is the way to go anyways
3914 despite this method taking slightly more heap space and realtime :) */
3916 dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
3917 dpCompoundAddress.dwDataSize = sizeof( GUID );
3918 dpCompoundAddress.lpData = &serviceProviderGUID;
3920 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3921 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
3923 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3924 return hr;
3927 /* Now allocate the buffer */
3928 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
3930 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3931 &dwAddressBufferSize, TRUE ) ) != DP_OK )
3933 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3934 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
3935 return hr;
3938 /* The enumeration will return FALSE if we are not to continue */
3939 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3940 &dpName, dwFlags, lpContext ) )
3942 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
3943 return DP_OK;
3945 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
3949 return DP_OK;
3952 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
3953 ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3955 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3956 FIXME("(%p)->(%p,%p,%p,0x%08x): stub\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3957 return DP_OK;
3960 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
3961 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
3962 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
3963 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
3965 lpGroupList lpGList;
3966 lpGroupData lpGData;
3968 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
3969 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
3970 lpContext, dwFlags, bAnsi );
3972 if( This->dp2->connectionInitialized == NO_PROVIDER )
3974 return DPERR_UNINITIALIZED;
3977 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3979 return DPERR_INVALIDGROUP;
3982 if( DPQ_IS_EMPTY( lpGData->groups ) )
3984 return DP_OK;
3987 lpGList = DPQ_FIRST( lpGData->groups );
3989 for( ;; )
3991 /* FIXME: Should check dwFlags for match here */
3993 if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP,
3994 &lpGList->lpGData->name, dwFlags,
3995 lpContext ) )
3997 return DP_OK; /* User requested break */
4000 if( DPQ_IS_ENDOFLIST( lpGList->groups ) )
4002 break;
4005 lpGList = DPQ_NEXT( lpGList->groups );
4009 return DP_OK;
4012 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
4013 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
4014 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
4015 DWORD dwFlags )
4017 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4018 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
4019 lpEnumPlayersCallback2, lpContext, dwFlags,
4020 TRUE );
4023 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
4024 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
4025 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
4026 DWORD dwFlags )
4028 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4029 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
4030 lpEnumPlayersCallback2, lpContext, dwFlags,
4031 FALSE );
4034 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
4035 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
4037 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4038 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
4039 return DP_OK;
4042 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
4043 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
4045 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4046 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
4047 return DP_OK;
4050 static BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
4051 REFGUID guidDataType,
4052 DWORD dwDataSize,
4053 LPCVOID lpData,
4054 LPVOID lpContext )
4056 /* Looking for the GUID of the provider to load */
4057 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
4058 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
4061 TRACE( "Found SP/LP (%s) %s (data size = 0x%08x)\n",
4062 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
4064 if( dwDataSize != sizeof( GUID ) )
4066 ERR( "Invalid sp/lp guid size 0x%08x\n", dwDataSize );
4069 memcpy( lpContext, lpData, dwDataSize );
4071 /* There shouldn't be more than 1 GUID/compound address */
4072 return FALSE;
4075 /* Still waiting for what we want */
4076 return TRUE;
4080 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
4081 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
4083 UINT i;
4084 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4085 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
4086 LPCSTR guidDataSubKey = "Guid";
4087 LPCSTR majVerDataSubKey = "dwReserved1";
4088 LPCSTR minVerDataSubKey = "dwReserved2";
4089 LPCSTR pathSubKey = "Path";
4091 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
4093 /* FIXME: Cloned code with a quick hack. */
4094 for( i=0; i<2; i++ )
4096 HKEY hkResult;
4097 LPCSTR searchSubKey;
4098 char subKeyName[51];
4099 DWORD dwIndex, sizeOfSubKeyName=50;
4100 FILETIME filetime;
4102 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
4103 *lpbIsDpSp = (i == 0) ? TRUE : FALSE;
4106 /* Need to loop over the service providers in the registry */
4107 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4108 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4110 /* Hmmm. Does this mean that there are no service providers? */
4111 ERR(": no service providers?\n");
4112 return 0;
4115 /* Traverse all the service providers we have available */
4116 for( dwIndex=0;
4117 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4118 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4119 ++dwIndex, sizeOfSubKeyName=51 )
4122 HKEY hkServiceProvider;
4123 GUID serviceProviderGUID;
4124 DWORD returnType, sizeOfReturnBuffer = 255;
4125 char returnBuffer[256];
4126 WCHAR buff[51];
4127 DWORD dwTemp, len;
4129 TRACE(" this time through: %s\n", subKeyName );
4131 /* Get a handle for this particular service provider */
4132 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4133 &hkServiceProvider ) != ERROR_SUCCESS )
4135 ERR(": what the heck is going on?\n" );
4136 continue;
4139 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4140 NULL, &returnType, (LPBYTE)returnBuffer,
4141 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4143 ERR(": missing GUID registry data members\n" );
4144 continue;
4147 /* FIXME: Check return types to ensure we're interpreting data right */
4148 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4149 CLSIDFromString( buff, &serviceProviderGUID );
4150 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4152 /* Determine if this is the Service Provider that the user asked for */
4153 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
4155 continue;
4158 if( i == 0 ) /* DP SP */
4160 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
4161 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
4162 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
4165 sizeOfReturnBuffer = 255;
4167 /* Get dwReserved1 */
4168 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
4169 NULL, &returnType, (LPBYTE)returnBuffer,
4170 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4172 ERR(": missing dwReserved1 registry data members\n") ;
4173 continue;
4176 if( i == 0 )
4177 memcpy( &lpSpData->dwReserved1, returnBuffer, sizeof(lpSpData->dwReserved1) );
4179 sizeOfReturnBuffer = 255;
4181 /* Get dwReserved2 */
4182 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4183 NULL, &returnType, (LPBYTE)returnBuffer,
4184 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4186 ERR(": missing dwReserved1 registry data members\n") ;
4187 continue;
4190 if( i == 0 )
4191 memcpy( &lpSpData->dwReserved2, returnBuffer, sizeof(lpSpData->dwReserved2) );
4193 sizeOfReturnBuffer = 255;
4195 /* Get the path for this service provider */
4196 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
4197 NULL, NULL, (LPBYTE)returnBuffer,
4198 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
4200 ERR(": missing PATH registry data members: 0x%08x\n", dwTemp );
4201 continue;
4204 TRACE( "Loading %s\n", returnBuffer );
4205 return LoadLibraryA( returnBuffer );
4209 return 0;
4212 static
4213 HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider )
4215 HRESULT hr;
4216 LPDPSP_SPINIT SPInit;
4218 /* Initialize the service provider by calling SPInit */
4219 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4221 if( SPInit == NULL )
4223 ERR( "Service provider doesn't provide SPInit interface?\n" );
4224 FreeLibrary( hServiceProvider );
4225 return DPERR_UNAVAILABLE;
4228 TRACE( "Calling SPInit (DP SP entry point)\n" );
4230 hr = (*SPInit)( &This->dp2->spData );
4232 if( FAILED(hr) )
4234 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4235 FreeLibrary( hServiceProvider );
4236 return hr;
4239 /* FIXME: Need to verify the sanity of the returned callback table
4240 * using IsBadCodePtr */
4241 This->dp2->bSPInitialized = TRUE;
4243 /* This interface is now initialized as a DP object */
4244 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
4246 /* Store the handle of the module so that we can unload it later */
4247 This->dp2->hServiceProvider = hServiceProvider;
4249 return hr;
4252 static
4253 HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hLobbyProvider )
4255 HRESULT hr;
4256 LPSP_INIT DPLSPInit;
4258 /* Initialize the service provider by calling SPInit */
4259 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
4261 if( DPLSPInit == NULL )
4263 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4264 FreeLibrary( hLobbyProvider );
4265 return DPERR_UNAVAILABLE;
4268 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4270 hr = (*DPLSPInit)( &This->dp2->dplspData );
4272 if( FAILED(hr) )
4274 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4275 FreeLibrary( hLobbyProvider );
4276 return hr;
4279 /* FIXME: Need to verify the sanity of the returned callback table
4280 * using IsBadCodePtr */
4282 This->dp2->bDPLSPInitialized = TRUE;
4284 /* This interface is now initialized as a lobby object */
4285 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
4287 /* Store the handle of the module so that we can unload it later */
4288 This->dp2->hDPLobbyProvider = hLobbyProvider;
4290 return hr;
4293 static HRESULT WINAPI DP_IF_InitializeConnection
4294 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi )
4296 HMODULE hServiceProvider;
4297 HRESULT hr;
4298 GUID guidSP;
4299 const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
4300 BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4302 TRACE("(%p)->(%p,0x%08x,%u)\n", This, lpConnection, dwFlags, bAnsi );
4304 if ( lpConnection == NULL )
4306 return DPERR_INVALIDPARAMS;
4309 if( dwFlags != 0 )
4311 return DPERR_INVALIDFLAGS;
4314 if( This->dp2->connectionInitialized != NO_PROVIDER )
4316 return DPERR_ALREADYINITIALIZED;
4319 /* Find out what the requested SP is and how large this buffer is */
4320 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
4321 dwAddrSize, &guidSP );
4323 if( FAILED(hr) )
4325 ERR( "Invalid compound address?\n" );
4326 return DPERR_UNAVAILABLE;
4329 /* Load the service provider */
4330 hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp );
4332 if( hServiceProvider == 0 )
4334 ERR( "Unable to load service provider %s\n", debugstr_guid(&guidSP) );
4335 return DPERR_UNAVAILABLE;
4338 if( bIsDpSp )
4340 /* Fill in what we can of the Service Provider required information.
4341 * The rest was be done in DP_LoadSP
4343 This->dp2->spData.lpAddress = lpConnection;
4344 This->dp2->spData.dwAddressSize = dwAddrSize;
4345 This->dp2->spData.lpGuid = &guidSP;
4347 hr = DP_InitializeDPSP( This, hServiceProvider );
4349 else
4351 This->dp2->dplspData.lpAddress = lpConnection;
4353 hr = DP_InitializeDPLSP( This, hServiceProvider );
4356 if( FAILED(hr) )
4358 return hr;
4361 return DP_OK;
4364 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4365 ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
4367 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4369 /* This may not be externally invoked once either an SP or LP is initialized */
4370 if( This->dp2->connectionInitialized != NO_PROVIDER )
4372 return DPERR_ALREADYINITIALIZED;
4375 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE );
4378 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4379 ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
4381 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4383 /* This may not be externally invoked once either an SP or LP is initialized */
4384 if( This->dp2->connectionInitialized != NO_PROVIDER )
4386 return DPERR_ALREADYINITIALIZED;
4389 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE );
4392 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4393 ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4394 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4396 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4397 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4400 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4401 ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4402 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4404 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4405 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4408 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4409 ( LPDIRECTPLAY3A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4411 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4412 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4413 return DP_OK;
4416 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4417 ( LPDIRECTPLAY3 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4419 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4420 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4421 return DP_OK;
4424 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4425 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4427 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4428 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4429 return DP_OK;
4432 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4433 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4435 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4436 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4437 return DP_OK;
4440 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4441 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup )
4443 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4444 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, dwFlags, idGroup );
4445 return DP_OK;
4448 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4449 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup )
4451 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4452 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, dwFlags, idGroup );
4453 return DP_OK;
4456 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4457 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDWORD lpdwFlags )
4459 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4460 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpdwFlags );
4461 return DP_OK;
4464 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4465 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDWORD lpdwFlags )
4467 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4468 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpdwFlags );
4469 return DP_OK;
4472 static HRESULT WINAPI DP_IF_GetGroupParent
4473 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
4474 BOOL bAnsi )
4476 lpGroupData lpGData;
4478 TRACE("(%p)->(0x%08x,%p,%u)\n", This, idGroup, lpidGroup, bAnsi );
4480 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4482 return DPERR_INVALIDGROUP;
4485 *lpidGroup = lpGData->dpid;
4487 return DP_OK;
4490 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4491 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
4493 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4494 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE );
4496 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4497 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
4499 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4500 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE );
4503 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4504 ( LPDIRECTPLAY3A iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4506 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4507 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4508 return DP_OK;
4511 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4512 ( LPDIRECTPLAY3 iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4514 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4515 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4516 return DP_OK;
4519 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4520 ( LPDIRECTPLAY3A iface, DPID idPlayer, LPDWORD lpdwFlags )
4522 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4523 FIXME("(%p)->(0x%08x,%p): stub\n", This, idPlayer, lpdwFlags );
4524 return DP_OK;
4527 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4528 ( LPDIRECTPLAY3 iface, DPID idPlayer, LPDWORD lpdwFlags )
4530 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4531 FIXME("(%p)->(0x%08x,%p): stub\n", This, idPlayer, lpdwFlags );
4532 return DP_OK;
4535 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4536 ( LPDIRECTPLAY4A iface, DPID idGroup, LPDPID lpidGroupOwner )
4538 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4539 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpidGroupOwner );
4540 return DP_OK;
4543 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4544 ( LPDIRECTPLAY4 iface, DPID idGroup, LPDPID lpidGroupOwner )
4546 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4547 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpidGroupOwner );
4548 return DP_OK;
4551 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4552 ( LPDIRECTPLAY4A iface, DPID idGroup , DPID idGroupOwner )
4554 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4555 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, idGroup, idGroupOwner );
4556 return DP_OK;
4559 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4560 ( LPDIRECTPLAY4 iface, DPID idGroup , DPID idGroupOwner )
4562 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4563 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, idGroup, idGroupOwner );
4564 return DP_OK;
4567 static HRESULT WINAPI DP_SendEx
4568 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4569 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4570 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi )
4572 BOOL bValidDestination = FALSE;
4574 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,0x%08x,0x%08x,0x%08x,%p,%p,%u)"
4575 ": stub\n",
4576 This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority,
4577 dwTimeout, lpContext, lpdwMsgID, bAnsi );
4579 if( This->dp2->connectionInitialized == NO_PROVIDER )
4581 return DPERR_UNINITIALIZED;
4584 /* FIXME: Add parameter checking */
4585 /* FIXME: First call to this needs to acquire a message id which will be
4586 * used for multiple sends
4589 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4591 /* Verify that the message is being sent from a valid local player. The
4592 * from player may be anonymous DPID_UNKNOWN
4594 if( idFrom != DPID_UNKNOWN )
4596 if( DP_FindPlayer( This, idFrom ) == NULL )
4598 WARN( "INFO: Invalid from player 0x%08x\n", idFrom );
4599 return DPERR_INVALIDPLAYER;
4603 /* Verify that the message is being sent to a valid player, group or to
4604 * everyone. If it's valid, send it to those players.
4606 if( idTo == DPID_ALLPLAYERS )
4608 bValidDestination = TRUE;
4610 /* See if SP has the ability to multicast. If so, use it */
4611 if( This->dp2->spData.lpCB->SendToGroupEx )
4613 FIXME( "Use group sendex to group 0\n" );
4615 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4617 FIXME( "Use obsolete group send to group 0\n" );
4619 else /* No multicast, multiplicate */
4621 /* Send to all players we know about */
4622 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4626 if( ( !bValidDestination ) &&
4627 ( DP_FindPlayer( This, idTo ) != NULL )
4630 bValidDestination = TRUE;
4632 /* Have the service provider send this message */
4633 /* FIXME: Could optimize for local interface sends */
4634 return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority,
4635 dwTimeout, lpContext, lpdwMsgID );
4638 if( ( !bValidDestination ) &&
4639 ( DP_FindAnyGroup( This, idTo ) != NULL )
4642 bValidDestination = TRUE;
4644 /* See if SP has the ability to multicast. If so, use it */
4645 if( This->dp2->spData.lpCB->SendToGroupEx )
4647 FIXME( "Use group sendex\n" );
4649 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4651 FIXME( "Use obsolete group send to group\n" );
4653 else /* No multicast, multiplicate */
4655 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4658 #if 0
4659 if( bExpectReply )
4661 DWORD dwWaitReturn;
4663 This->dp2->hReplyEvent = CreateEventW( NULL, FALSE, FALSE, NULL );
4665 dwWaitReturn = WaitForSingleObject( hReplyEvent, dwTimeout );
4666 if( dwWaitReturn != WAIT_OBJECT_0 )
4668 ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
4671 #endif
4674 if( !bValidDestination )
4676 return DPERR_INVALIDPLAYER;
4678 else
4680 /* FIXME: Should return what the send returned */
4681 return DP_OK;
4686 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4687 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4688 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4689 LPVOID lpContext, LPDWORD lpdwMsgID )
4691 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4692 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4693 dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE );
4696 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4697 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4698 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4699 LPVOID lpContext, LPDWORD lpdwMsgID )
4701 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4702 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4703 dwPriority, dwTimeout, lpContext, lpdwMsgID, FALSE );
4706 static HRESULT WINAPI DP_SP_SendEx
4707 ( IDirectPlay2Impl* This, DWORD dwFlags,
4708 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4709 LPVOID lpContext, LPDWORD lpdwMsgID )
4711 LPDPMSG lpMElem;
4713 FIXME( ": stub\n" );
4715 /* FIXME: This queuing should only be for async messages */
4717 lpMElem = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpMElem ) );
4718 lpMElem->msg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
4720 CopyMemory( lpMElem->msg, lpData, dwDataSize );
4722 /* FIXME: Need to queue based on priority */
4723 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
4725 return DP_OK;
4728 static HRESULT WINAPI DP_IF_GetMessageQueue
4729 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4730 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi )
4732 HRESULT hr = DP_OK;
4734 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%p,%u): semi stub\n",
4735 This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi );
4737 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4738 /* FIXME: What about sends which are not immediate? */
4740 if( This->dp2->spData.lpCB->GetMessageQueue )
4742 DPSP_GETMESSAGEQUEUEDATA data;
4744 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4746 /* FIXME: None of this is documented :( */
4748 data.lpISP = This->dp2->spData.lpISP;
4749 data.dwFlags = dwFlags;
4750 data.idFrom = idFrom;
4751 data.idTo = idTo;
4752 data.lpdwNumMsgs = lpdwNumMsgs;
4753 data.lpdwNumBytes = lpdwNumBytes;
4755 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
4757 else
4759 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4762 return hr;
4765 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4766 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4767 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4769 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4770 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4771 lpdwNumBytes, TRUE );
4774 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4775 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4776 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4778 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4779 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4780 lpdwNumBytes, FALSE );
4783 static HRESULT WINAPI DP_IF_CancelMessage
4784 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
4785 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi )
4787 HRESULT hr = DP_OK;
4789 FIXME( "(%p)->(0x%08x,0x%08x,%u): semi stub\n",
4790 This, dwMsgID, dwFlags, bAnsi );
4792 if( This->dp2->spData.lpCB->Cancel )
4794 DPSP_CANCELDATA data;
4796 TRACE( "Calling SP Cancel\n" );
4798 /* FIXME: Undocumented callback */
4800 data.lpISP = This->dp2->spData.lpISP;
4801 data.dwFlags = dwFlags;
4802 data.lprglpvSPMsgID = NULL;
4803 data.cSPMsgID = dwMsgID;
4804 data.dwMinPriority = dwMinPriority;
4805 data.dwMaxPriority = dwMaxPriority;
4807 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
4809 else
4811 FIXME( "SP doesn't implement Cancel\n" );
4814 return hr;
4817 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
4818 ( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags )
4820 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4822 if( dwFlags != 0 )
4824 return DPERR_INVALIDFLAGS;
4827 if( dwMsgID == 0 )
4829 dwFlags |= DPCANCELSEND_ALL;
4832 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE );
4835 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
4836 ( LPDIRECTPLAY4 iface, DWORD dwMsgID, DWORD dwFlags )
4838 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4840 if( dwFlags != 0 )
4842 return DPERR_INVALIDFLAGS;
4845 if( dwMsgID == 0 )
4847 dwFlags |= DPCANCELSEND_ALL;
4850 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, FALSE );
4853 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
4854 ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4855 DWORD dwFlags )
4857 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4859 if( dwFlags != 0 )
4861 return DPERR_INVALIDFLAGS;
4864 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4865 dwMaxPriority, TRUE );
4868 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
4869 ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4870 DWORD dwFlags )
4872 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4874 if( dwFlags != 0 )
4876 return DPERR_INVALIDFLAGS;
4879 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4880 dwMaxPriority, FALSE );
4883 /* Note: Hack so we can reuse the old functions without compiler warnings */
4884 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4885 # define XCAST(fun) (typeof(directPlay2WVT.fun))
4886 #else
4887 # define XCAST(fun) (void*)
4888 #endif
4890 static const IDirectPlay2Vtbl directPlay2WVT =
4892 XCAST(QueryInterface)DP_QueryInterface,
4893 XCAST(AddRef)DP_AddRef,
4894 XCAST(Release)DP_Release,
4896 DirectPlay2WImpl_AddPlayerToGroup,
4897 DirectPlay2WImpl_Close,
4898 DirectPlay2WImpl_CreateGroup,
4899 DirectPlay2WImpl_CreatePlayer,
4900 DirectPlay2WImpl_DeletePlayerFromGroup,
4901 DirectPlay2WImpl_DestroyGroup,
4902 DirectPlay2WImpl_DestroyPlayer,
4903 DirectPlay2WImpl_EnumGroupPlayers,
4904 DirectPlay2WImpl_EnumGroups,
4905 DirectPlay2WImpl_EnumPlayers,
4906 DirectPlay2WImpl_EnumSessions,
4907 DirectPlay2WImpl_GetCaps,
4908 DirectPlay2WImpl_GetGroupData,
4909 DirectPlay2WImpl_GetGroupName,
4910 DirectPlay2WImpl_GetMessageCount,
4911 DirectPlay2WImpl_GetPlayerAddress,
4912 DirectPlay2WImpl_GetPlayerCaps,
4913 DirectPlay2WImpl_GetPlayerData,
4914 DirectPlay2WImpl_GetPlayerName,
4915 DirectPlay2WImpl_GetSessionDesc,
4916 DirectPlay2WImpl_Initialize,
4917 DirectPlay2WImpl_Open,
4918 DirectPlay2WImpl_Receive,
4919 DirectPlay2WImpl_Send,
4920 DirectPlay2WImpl_SetGroupData,
4921 DirectPlay2WImpl_SetGroupName,
4922 DirectPlay2WImpl_SetPlayerData,
4923 DirectPlay2WImpl_SetPlayerName,
4924 DirectPlay2WImpl_SetSessionDesc
4926 #undef XCAST
4928 /* Note: Hack so we can reuse the old functions without compiler warnings */
4929 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4930 # define XCAST(fun) (typeof(directPlay2AVT.fun))
4931 #else
4932 # define XCAST(fun) (void*)
4933 #endif
4935 static const IDirectPlay2Vtbl directPlay2AVT =
4937 XCAST(QueryInterface)DP_QueryInterface,
4938 XCAST(AddRef)DP_AddRef,
4939 XCAST(Release)DP_Release,
4941 DirectPlay2AImpl_AddPlayerToGroup,
4942 DirectPlay2AImpl_Close,
4943 DirectPlay2AImpl_CreateGroup,
4944 DirectPlay2AImpl_CreatePlayer,
4945 DirectPlay2AImpl_DeletePlayerFromGroup,
4946 DirectPlay2AImpl_DestroyGroup,
4947 DirectPlay2AImpl_DestroyPlayer,
4948 DirectPlay2AImpl_EnumGroupPlayers,
4949 DirectPlay2AImpl_EnumGroups,
4950 DirectPlay2AImpl_EnumPlayers,
4951 DirectPlay2AImpl_EnumSessions,
4952 DirectPlay2AImpl_GetCaps,
4953 DirectPlay2AImpl_GetGroupData,
4954 DirectPlay2AImpl_GetGroupName,
4955 DirectPlay2AImpl_GetMessageCount,
4956 DirectPlay2AImpl_GetPlayerAddress,
4957 DirectPlay2AImpl_GetPlayerCaps,
4958 DirectPlay2AImpl_GetPlayerData,
4959 DirectPlay2AImpl_GetPlayerName,
4960 DirectPlay2AImpl_GetSessionDesc,
4961 DirectPlay2AImpl_Initialize,
4962 DirectPlay2AImpl_Open,
4963 DirectPlay2AImpl_Receive,
4964 DirectPlay2AImpl_Send,
4965 DirectPlay2AImpl_SetGroupData,
4966 DirectPlay2AImpl_SetGroupName,
4967 DirectPlay2AImpl_SetPlayerData,
4968 DirectPlay2AImpl_SetPlayerName,
4969 DirectPlay2AImpl_SetSessionDesc
4971 #undef XCAST
4974 /* Note: Hack so we can reuse the old functions without compiler warnings */
4975 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4976 # define XCAST(fun) (typeof(directPlay3AVT.fun))
4977 #else
4978 # define XCAST(fun) (void*)
4979 #endif
4981 static const IDirectPlay3Vtbl directPlay3AVT =
4983 XCAST(QueryInterface)DP_QueryInterface,
4984 XCAST(AddRef)DP_AddRef,
4985 XCAST(Release)DP_Release,
4987 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
4988 XCAST(Close)DirectPlay2AImpl_Close,
4989 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
4990 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
4991 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
4992 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
4993 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
4994 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
4995 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
4996 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
4997 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
4998 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
4999 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
5000 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
5001 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5002 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5003 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5004 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5005 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5006 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5007 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5008 XCAST(Open)DirectPlay2AImpl_Open,
5009 XCAST(Receive)DirectPlay2AImpl_Receive,
5010 XCAST(Send)DirectPlay2AImpl_Send,
5011 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5012 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5013 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5014 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5015 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5017 DirectPlay3AImpl_AddGroupToGroup,
5018 DirectPlay3AImpl_CreateGroupInGroup,
5019 DirectPlay3AImpl_DeleteGroupFromGroup,
5020 DirectPlay3AImpl_EnumConnections,
5021 DirectPlay3AImpl_EnumGroupsInGroup,
5022 DirectPlay3AImpl_GetGroupConnectionSettings,
5023 DirectPlay3AImpl_InitializeConnection,
5024 DirectPlay3AImpl_SecureOpen,
5025 DirectPlay3AImpl_SendChatMessage,
5026 DirectPlay3AImpl_SetGroupConnectionSettings,
5027 DirectPlay3AImpl_StartSession,
5028 DirectPlay3AImpl_GetGroupFlags,
5029 DirectPlay3AImpl_GetGroupParent,
5030 DirectPlay3AImpl_GetPlayerAccount,
5031 DirectPlay3AImpl_GetPlayerFlags
5033 #undef XCAST
5035 /* Note: Hack so we can reuse the old functions without compiler warnings */
5036 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5037 # define XCAST(fun) (typeof(directPlay3WVT.fun))
5038 #else
5039 # define XCAST(fun) (void*)
5040 #endif
5041 static const IDirectPlay3Vtbl directPlay3WVT =
5043 XCAST(QueryInterface)DP_QueryInterface,
5044 XCAST(AddRef)DP_AddRef,
5045 XCAST(Release)DP_Release,
5047 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
5048 XCAST(Close)DirectPlay2WImpl_Close,
5049 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
5050 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
5051 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
5052 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
5053 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5054 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5055 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5056 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5057 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5058 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5059 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5060 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5061 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5062 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5063 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5064 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5065 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5066 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5067 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5068 XCAST(Open)DirectPlay2WImpl_Open,
5069 XCAST(Receive)DirectPlay2WImpl_Receive,
5070 XCAST(Send)DirectPlay2WImpl_Send,
5071 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5072 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5073 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5074 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5075 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5077 DirectPlay3WImpl_AddGroupToGroup,
5078 DirectPlay3WImpl_CreateGroupInGroup,
5079 DirectPlay3WImpl_DeleteGroupFromGroup,
5080 DirectPlay3WImpl_EnumConnections,
5081 DirectPlay3WImpl_EnumGroupsInGroup,
5082 DirectPlay3WImpl_GetGroupConnectionSettings,
5083 DirectPlay3WImpl_InitializeConnection,
5084 DirectPlay3WImpl_SecureOpen,
5085 DirectPlay3WImpl_SendChatMessage,
5086 DirectPlay3WImpl_SetGroupConnectionSettings,
5087 DirectPlay3WImpl_StartSession,
5088 DirectPlay3WImpl_GetGroupFlags,
5089 DirectPlay3WImpl_GetGroupParent,
5090 DirectPlay3WImpl_GetPlayerAccount,
5091 DirectPlay3WImpl_GetPlayerFlags
5093 #undef XCAST
5095 /* Note: Hack so we can reuse the old functions without compiler warnings */
5096 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5097 # define XCAST(fun) (typeof(directPlay4WVT.fun))
5098 #else
5099 # define XCAST(fun) (void*)
5100 #endif
5101 static const IDirectPlay4Vtbl directPlay4WVT =
5103 XCAST(QueryInterface)DP_QueryInterface,
5104 XCAST(AddRef)DP_AddRef,
5105 XCAST(Release)DP_Release,
5107 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
5108 XCAST(Close)DirectPlay2WImpl_Close,
5109 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
5110 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
5111 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
5112 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
5113 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5114 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5115 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5116 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5117 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5118 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5119 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5120 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5121 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5122 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5123 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5124 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5125 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5126 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5127 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5128 XCAST(Open)DirectPlay2WImpl_Open,
5129 XCAST(Receive)DirectPlay2WImpl_Receive,
5130 XCAST(Send)DirectPlay2WImpl_Send,
5131 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5132 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5133 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5134 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5135 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5137 XCAST(AddGroupToGroup)DirectPlay3WImpl_AddGroupToGroup,
5138 XCAST(CreateGroupInGroup)DirectPlay3WImpl_CreateGroupInGroup,
5139 XCAST(DeleteGroupFromGroup)DirectPlay3WImpl_DeleteGroupFromGroup,
5140 XCAST(EnumConnections)DirectPlay3WImpl_EnumConnections,
5141 XCAST(EnumGroupsInGroup)DirectPlay3WImpl_EnumGroupsInGroup,
5142 XCAST(GetGroupConnectionSettings)DirectPlay3WImpl_GetGroupConnectionSettings,
5143 XCAST(InitializeConnection)DirectPlay3WImpl_InitializeConnection,
5144 XCAST(SecureOpen)DirectPlay3WImpl_SecureOpen,
5145 XCAST(SendChatMessage)DirectPlay3WImpl_SendChatMessage,
5146 XCAST(SetGroupConnectionSettings)DirectPlay3WImpl_SetGroupConnectionSettings,
5147 XCAST(StartSession)DirectPlay3WImpl_StartSession,
5148 XCAST(GetGroupFlags)DirectPlay3WImpl_GetGroupFlags,
5149 XCAST(GetGroupParent)DirectPlay3WImpl_GetGroupParent,
5150 XCAST(GetPlayerAccount)DirectPlay3WImpl_GetPlayerAccount,
5151 XCAST(GetPlayerFlags)DirectPlay3WImpl_GetPlayerFlags,
5153 DirectPlay4WImpl_GetGroupOwner,
5154 DirectPlay4WImpl_SetGroupOwner,
5155 DirectPlay4WImpl_SendEx,
5156 DirectPlay4WImpl_GetMessageQueue,
5157 DirectPlay4WImpl_CancelMessage,
5158 DirectPlay4WImpl_CancelPriority
5160 #undef XCAST
5163 /* Note: Hack so we can reuse the old functions without compiler warnings */
5164 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5165 # define XCAST(fun) (typeof(directPlay4AVT.fun))
5166 #else
5167 # define XCAST(fun) (void*)
5168 #endif
5169 static const IDirectPlay4Vtbl directPlay4AVT =
5171 XCAST(QueryInterface)DP_QueryInterface,
5172 XCAST(AddRef)DP_AddRef,
5173 XCAST(Release)DP_Release,
5175 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
5176 XCAST(Close)DirectPlay2AImpl_Close,
5177 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
5178 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
5179 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
5180 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
5181 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
5182 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
5183 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
5184 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
5185 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
5186 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
5187 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
5188 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
5189 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5190 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5191 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5192 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5193 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5194 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5195 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5196 XCAST(Open)DirectPlay2AImpl_Open,
5197 XCAST(Receive)DirectPlay2AImpl_Receive,
5198 XCAST(Send)DirectPlay2AImpl_Send,
5199 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5200 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5201 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5202 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5203 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5205 XCAST(AddGroupToGroup)DirectPlay3AImpl_AddGroupToGroup,
5206 XCAST(CreateGroupInGroup)DirectPlay3AImpl_CreateGroupInGroup,
5207 XCAST(DeleteGroupFromGroup)DirectPlay3AImpl_DeleteGroupFromGroup,
5208 XCAST(EnumConnections)DirectPlay3AImpl_EnumConnections,
5209 XCAST(EnumGroupsInGroup)DirectPlay3AImpl_EnumGroupsInGroup,
5210 XCAST(GetGroupConnectionSettings)DirectPlay3AImpl_GetGroupConnectionSettings,
5211 XCAST(InitializeConnection)DirectPlay3AImpl_InitializeConnection,
5212 XCAST(SecureOpen)DirectPlay3AImpl_SecureOpen,
5213 XCAST(SendChatMessage)DirectPlay3AImpl_SendChatMessage,
5214 XCAST(SetGroupConnectionSettings)DirectPlay3AImpl_SetGroupConnectionSettings,
5215 XCAST(StartSession)DirectPlay3AImpl_StartSession,
5216 XCAST(GetGroupFlags)DirectPlay3AImpl_GetGroupFlags,
5217 XCAST(GetGroupParent)DirectPlay3AImpl_GetGroupParent,
5218 XCAST(GetPlayerAccount)DirectPlay3AImpl_GetPlayerAccount,
5219 XCAST(GetPlayerFlags)DirectPlay3AImpl_GetPlayerFlags,
5221 DirectPlay4AImpl_GetGroupOwner,
5222 DirectPlay4AImpl_SetGroupOwner,
5223 DirectPlay4AImpl_SendEx,
5224 DirectPlay4AImpl_GetMessageQueue,
5225 DirectPlay4AImpl_CancelMessage,
5226 DirectPlay4AImpl_CancelPriority
5228 #undef XCAST
5230 HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP,
5231 DPID idPlayer,
5232 LPVOID* lplpData )
5234 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5236 if( lpPlayer == NULL )
5238 return DPERR_INVALIDPLAYER;
5241 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
5243 return DP_OK;
5246 HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP,
5247 DPID idPlayer,
5248 LPVOID lpData )
5250 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5252 if( lpPlayer == NULL )
5254 return DPERR_INVALIDPLAYER;
5257 lpPlayer->lpPData->lpSPPlayerData = lpData;
5259 return DP_OK;
5262 /***************************************************************************
5263 * DirectPlayEnumerateAW
5265 * The pointer to the structure lpContext will be filled with the
5266 * appropriate data for each service offered by the OS. These services are
5267 * not necessarily available on this particular machine but are defined
5268 * as simple service providers under the "Service Providers" registry key.
5269 * This structure is then passed to lpEnumCallback for each of the different
5270 * services.
5272 * This API is useful only for applications written using DirectX3 or
5273 * worse. It is superseded by IDirectPlay3::EnumConnections which also
5274 * gives information on the actual connections.
5276 * defn of a service provider:
5277 * A dynamic-link library used by DirectPlay to communicate over a network.
5278 * The service provider contains all the network-specific code required
5279 * to send and receive messages. Online services and network operators can
5280 * supply service providers to use specialized hardware, protocols, communications
5281 * media, and network resources.
5284 static HRESULT DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA,
5285 LPDPENUMDPCALLBACKW lpEnumCallbackW,
5286 LPVOID lpContext)
5288 HKEY hkResult;
5289 static const WCHAR searchSubKey[] = {
5290 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
5291 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
5292 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
5293 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
5294 static const WCHAR guidKey[] = { 'G', 'u', 'i', 'd', 0 };
5295 static const WCHAR descW[] = { 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', 'W', 0 };
5297 DWORD dwIndex;
5298 FILETIME filetime;
5300 char *descriptionA = NULL;
5301 DWORD max_sizeOfDescriptionA = 0;
5302 WCHAR *descriptionW = NULL;
5303 DWORD max_sizeOfDescriptionW = 0;
5305 if (!lpEnumCallbackA && !lpEnumCallbackW)
5307 return DPERR_INVALIDPARAMS;
5310 /* Need to loop over the service providers in the registry */
5311 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, searchSubKey,
5312 0, KEY_READ, &hkResult) != ERROR_SUCCESS)
5314 /* Hmmm. Does this mean that there are no service providers? */
5315 ERR(": no service provider key in the registry - check your Wine installation !!!\n");
5316 return DPERR_GENERIC;
5319 /* Traverse all the service providers we have available */
5320 dwIndex = 0;
5321 while (1)
5323 WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */
5324 DWORD sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR);
5325 HKEY hkServiceProvider;
5326 GUID serviceProviderGUID;
5327 WCHAR guidKeyContent[(2 * 16) + 1 + 6 /* This corresponds to '{....-..-..-..-......}' */ ];
5328 DWORD sizeOfGuidKeyContent = sizeof(guidKeyContent);
5329 LONG ret_value;
5331 ret_value = RegEnumKeyExW(hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
5332 NULL, NULL, NULL, &filetime);
5333 if (ret_value == ERROR_NO_MORE_ITEMS)
5334 break;
5335 else if (ret_value != ERROR_SUCCESS)
5337 ERR(": could not enumerate on service provider key.\n");
5338 return DPERR_EXCEPTION;
5340 TRACE(" this time through sub-key %s.\n", debugstr_w(subKeyName));
5342 /* Open the key for this service provider */
5343 if (RegOpenKeyExW(hkResult, subKeyName, 0, KEY_READ, &hkServiceProvider) != ERROR_SUCCESS)
5345 ERR(": could not open registry key for service provider %s.\n", debugstr_w(subKeyName));
5346 continue;
5349 /* Get the GUID from the registry */
5350 if (RegQueryValueExW(hkServiceProvider, guidKey,
5351 NULL, NULL, (LPBYTE) guidKeyContent, &sizeOfGuidKeyContent) != ERROR_SUCCESS)
5353 ERR(": missing GUID registry data member for service provider %s.\n", debugstr_w(subKeyName));
5354 continue;
5356 if (sizeOfGuidKeyContent != sizeof(guidKeyContent))
5358 ERR(": invalid format for the GUID registry data member for service provider %s (%s).\n", debugstr_w(subKeyName), debugstr_w(guidKeyContent));
5359 continue;
5361 CLSIDFromString(guidKeyContent, &serviceProviderGUID );
5363 /* The enumeration will return FALSE if we are not to continue.
5365 * Note: on my windows box, major / minor version is 6 / 0 for all service providers
5366 * and have no relation to any of the two dwReserved1 and dwReserved2 keys.
5367 * I think that it simply means that they are in-line with DirectX 6.0
5369 if (lpEnumCallbackA)
5371 DWORD sizeOfDescription = 0;
5373 /* Note that this is the A case of this function, so use the A variant to get the description string */
5374 if (RegQueryValueExA(hkServiceProvider, "DescriptionA",
5375 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5377 ERR(": missing 'DescriptionA' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5378 continue;
5380 if (sizeOfDescription > max_sizeOfDescriptionA)
5382 HeapFree(GetProcessHeap(), 0, descriptionA);
5383 max_sizeOfDescriptionA = sizeOfDescription;
5385 descriptionA = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5386 RegQueryValueExA(hkServiceProvider, "DescriptionA",
5387 NULL, NULL, (LPBYTE) descriptionA, &sizeOfDescription);
5389 if (!lpEnumCallbackA(&serviceProviderGUID, descriptionA, 6, 0, lpContext))
5390 goto end;
5392 else
5394 DWORD sizeOfDescription = 0;
5396 if (RegQueryValueExW(hkServiceProvider, descW,
5397 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5399 ERR(": missing 'DescriptionW' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5400 continue;
5402 if (sizeOfDescription > max_sizeOfDescriptionW)
5404 HeapFree(GetProcessHeap(), 0, descriptionW);
5405 max_sizeOfDescriptionW = sizeOfDescription;
5407 descriptionW = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5408 RegQueryValueExW(hkServiceProvider, descW,
5409 NULL, NULL, (LPBYTE) descriptionW, &sizeOfDescription);
5411 if (!lpEnumCallbackW(&serviceProviderGUID, descriptionW, 6, 0, lpContext))
5412 goto end;
5415 dwIndex++;
5418 end:
5419 HeapFree(GetProcessHeap(), 0, descriptionA);
5420 HeapFree(GetProcessHeap(), 0, descriptionW);
5422 return DP_OK;
5425 /***************************************************************************
5426 * DirectPlayEnumerate [DPLAYX.9]
5427 * DirectPlayEnumerateA [DPLAYX.2]
5429 HRESULT WINAPI DirectPlayEnumerateA(LPDPENUMDPCALLBACKA lpEnumCallback, LPVOID lpContext )
5431 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5433 return DirectPlayEnumerateAW(lpEnumCallback, NULL, lpContext);
5436 /***************************************************************************
5437 * DirectPlayEnumerateW [DPLAYX.3]
5439 HRESULT WINAPI DirectPlayEnumerateW(LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5441 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5443 return DirectPlayEnumerateAW(NULL, lpEnumCallback, lpContext);
5446 typedef struct tagCreateEnum
5448 LPVOID lpConn;
5449 LPCGUID lpGuid;
5450 } CreateEnumData, *lpCreateEnumData;
5452 /* Find and copy the matching connection for the SP guid */
5453 static BOOL CALLBACK cbDPCreateEnumConnections(
5454 LPCGUID lpguidSP,
5455 LPVOID lpConnection,
5456 DWORD dwConnectionSize,
5457 LPCDPNAME lpName,
5458 DWORD dwFlags,
5459 LPVOID lpContext)
5461 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5463 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5465 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5467 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5468 dwConnectionSize );
5469 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5471 /* Found the record that we were looking for */
5472 return FALSE;
5475 /* Haven't found what were looking for yet */
5476 return TRUE;
5480 /***************************************************************************
5481 * DirectPlayCreate [DPLAYX.1]
5484 HRESULT WINAPI DirectPlayCreate
5485 ( LPGUID lpGUID, LPDIRECTPLAY *lplpDP, IUnknown *pUnk )
5487 HRESULT hr;
5488 LPDIRECTPLAY3A lpDP3A;
5489 CreateEnumData cbData;
5491 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5493 if( pUnk != NULL )
5495 return CLASS_E_NOAGGREGATION;
5498 if( (lplpDP == NULL) || (lpGUID == NULL) )
5500 return DPERR_INVALIDPARAMS;
5504 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5505 give them an IDirectPlay2A object and hope that doesn't cause problems */
5506 if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
5508 return DPERR_UNAVAILABLE;
5511 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
5513 /* The GUID_NULL means don't bind a service provider. Just return the
5514 interface as is */
5515 return DP_OK;
5518 /* Bind the desired service provider since lpGUID is non NULL */
5519 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
5521 /* We're going to use a DP3 interface */
5522 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
5523 (LPVOID*)&lpDP3A );
5524 if( FAILED(hr) )
5526 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
5527 return hr;
5530 cbData.lpConn = NULL;
5531 cbData.lpGuid = lpGUID;
5533 /* We were given a service provider, find info about it... */
5534 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
5535 &cbData, DPCONNECTION_DIRECTPLAY );
5536 if( ( FAILED(hr) ) ||
5537 ( cbData.lpConn == NULL )
5540 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
5541 IDirectPlayX_Release( lpDP3A );
5542 return DPERR_UNAVAILABLE;
5545 /* Initialize the service provider */
5546 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
5547 if( FAILED(hr) )
5549 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
5550 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5551 IDirectPlayX_Release( lpDP3A );
5552 return hr;
5555 /* Release our version of the interface now that we're done with it */
5556 IDirectPlayX_Release( lpDP3A );
5557 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5559 return DP_OK;