push 5b66f3b36e7323272378316c923222b908f6e2d3
[wine/hacks.git] / dlls / dplayx / dplay.c
blob1ba7d7e215020e6f8c6032ad380715d113eb2620
1 /* Direct Play 2,3,4 Implementation
3 * Copyright 1998,1999,2000,2001 - Peter Hunnisett
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "config.h"
21 #include "wine/port.h"
23 #include <stdarg.h>
24 #include <string.h>
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
28 #include "windef.h"
29 #include "winerror.h"
30 #include "winbase.h"
31 #include "winnt.h"
32 #include "winreg.h"
33 #include "winnls.h"
34 #include "wine/unicode.h"
35 #include "wine/debug.h"
37 #include "dpinit.h"
38 #include "dplayx_global.h"
39 #include "name_server.h"
40 #include "dplayx_queue.h"
41 #include "wine/dplaysp.h"
42 #include "dplay_global.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(dplay);
46 /* FIXME: Should this be externed? */
47 extern HRESULT DPL_CreateCompoundAddress
48 ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
49 LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
52 /* Local function prototypes */
53 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid );
54 static lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* iface, LPDPID lpid,
55 LPDPNAME lpName, DWORD dwFlags,
56 HANDLE hEvent, BOOL bAnsi );
57 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, const DPNAME *lpSrc, BOOL bAnsi );
58 static void DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
59 LPVOID lpData, DWORD dwDataSize );
61 static lpGroupData DP_CreateGroup( IDirectPlay2AImpl* iface, const DPID *lpid,
62 const DPNAME *lpName, DWORD dwFlags,
63 DPID idParent, BOOL bAnsi );
64 static void DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
65 LPVOID lpData, DWORD dwDataSize );
66 static void DP_DeleteDPNameStruct( LPDPNAME lpDPName );
67 static void DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid );
68 static BOOL CALLBACK cbDeletePlayerFromAllGroups( DPID dpId,
69 DWORD dwPlayerType,
70 LPCDPNAME lpName,
71 DWORD dwFlags,
72 LPVOID lpContext );
73 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid );
74 static BOOL CALLBACK cbRemoveGroupOrPlayer( DPID dpId, DWORD dwPlayerType,
75 LPCDPNAME lpName, DWORD dwFlags,
76 LPVOID lpContext );
77 static void DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid );
79 /* Forward declarations of virtual tables */
80 static const IDirectPlay2Vtbl directPlay2AVT;
81 static const IDirectPlay3Vtbl directPlay3AVT;
82 static const IDirectPlay4Vtbl directPlay4AVT;
84 static const IDirectPlay2Vtbl directPlay2WVT;
85 static const IDirectPlay3Vtbl directPlay3WVT;
86 static const IDirectPlay4Vtbl directPlay4WVT;
88 /* Helper methods for player/group interfaces */
89 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
90 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
91 DPID idPlayer, BOOL bAnsi );
92 static HRESULT WINAPI DP_IF_CreatePlayer
93 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, LPDPID lpidPlayer,
94 LPDPNAME lpPlayerName, HANDLE hEvent, LPVOID lpData,
95 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
96 static HRESULT WINAPI DP_IF_DestroyGroup
97 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi );
98 static HRESULT WINAPI DP_IF_DestroyPlayer
99 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi );
100 static HRESULT WINAPI DP_IF_EnumGroupPlayers
101 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
102 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
103 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
104 static HRESULT WINAPI DP_IF_EnumGroups
105 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
106 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
107 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
108 static HRESULT WINAPI DP_IF_EnumPlayers
109 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
110 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
111 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
112 static HRESULT WINAPI DP_IF_GetGroupData
113 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
114 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
115 static HRESULT WINAPI DP_IF_GetGroupName
116 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
117 LPDWORD lpdwDataSize, BOOL bAnsi );
118 static HRESULT WINAPI DP_IF_GetPlayerData
119 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
120 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
121 static HRESULT WINAPI DP_IF_GetPlayerName
122 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
123 LPDWORD lpdwDataSize, BOOL bAnsi );
124 static HRESULT WINAPI DP_IF_SetGroupName
125 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
126 DWORD dwFlags, BOOL bAnsi );
127 static HRESULT WINAPI DP_IF_SetPlayerData
128 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
129 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
130 static HRESULT WINAPI DP_IF_SetPlayerName
131 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
132 DWORD dwFlags, BOOL bAnsi );
133 static HRESULT WINAPI DP_IF_AddGroupToGroup
134 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
135 static HRESULT WINAPI DP_IF_CreateGroup
136 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
137 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
138 DWORD dwFlags, BOOL bAnsi );
139 static HRESULT WINAPI DP_IF_CreateGroupInGroup
140 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
141 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
142 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
143 static HRESULT WINAPI DP_IF_AddPlayerToGroup
144 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
145 DPID idPlayer, BOOL bAnsi );
146 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
147 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
148 static HRESULT WINAPI DP_SetSessionDesc
149 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
150 DWORD dwFlags, BOOL bInitial, BOOL bAnsi );
151 static HRESULT WINAPI DP_SecureOpen
152 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
153 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
154 BOOL bAnsi );
155 static HRESULT WINAPI DP_SendEx
156 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
157 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
158 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi );
159 static HRESULT WINAPI DP_IF_Receive
160 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
161 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi );
162 static HRESULT WINAPI DP_IF_GetMessageQueue
163 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
164 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi );
165 static HRESULT WINAPI DP_SP_SendEx
166 ( IDirectPlay2Impl* This, DWORD dwFlags,
167 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
168 LPVOID lpContext, LPDWORD lpdwMsgID );
169 static HRESULT WINAPI DP_IF_SetGroupData
170 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
171 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
172 static HRESULT WINAPI DP_IF_GetPlayerCaps
173 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
174 DWORD dwFlags );
175 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi );
176 static HRESULT WINAPI DP_IF_CancelMessage
177 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
178 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi );
179 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
180 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
181 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
182 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
183 static HRESULT WINAPI DP_IF_GetGroupParent
184 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
185 BOOL bAnsi );
186 static HRESULT WINAPI DP_IF_GetCaps
187 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags );
188 static HRESULT WINAPI DP_IF_EnumSessions
189 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
190 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
191 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
192 static HRESULT WINAPI DP_IF_InitializeConnection
193 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi );
194 static BOOL CALLBACK cbDPCreateEnumConnections( LPCGUID lpguidSP,
195 LPVOID lpConnection, DWORD dwConnectionSize, LPCDPNAME lpName,
196 DWORD dwFlags, LPVOID lpContext );
197 static BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
198 LPDWORD lpdwBufSize );
202 static inline DPID DP_NextObjectId(void);
203 static DPID DP_GetRemoteNextObjectId(void);
206 static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc,
207 LPCDPSESSIONDESC2 srcSessDesc, BOOL bAnsi );
210 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp );
211 static HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider );
212 static HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hServiceProvider );
219 #define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */
220 #define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported
221 we don't have to change much */
222 #define DPID_NAME_SERVER 0x19a9d65b /* Don't ask me why */
224 /* Strip out dwFlag values which cannot be sent in the CREATEGROUP msg */
225 #define DPMSG_CREATEGROUP_DWFLAGS(x) ( (x) & DPGROUP_HIDDEN )
227 /* Strip out all dwFlags values for CREATEPLAYER msg */
228 #define DPMSG_CREATEPLAYER_DWFLAGS(x) 0
230 static LONG kludgePlayerGroupId = 1000;
232 /* ------------------------------------------------------------------ */
235 static BOOL DP_CreateIUnknown( LPVOID lpDP )
237 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;
239 This->unk = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->unk) ) );
240 if ( This->unk == NULL )
242 return FALSE;
245 InitializeCriticalSection( &This->unk->DP_lock );
246 This->unk->DP_lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectPlay2AImpl*->DirectPlayIUnknownData*->DP_lock");
248 return TRUE;
251 static BOOL DP_DestroyIUnknown( LPVOID lpDP )
253 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;
255 This->unk->DP_lock.DebugInfo->Spare[0] = 0;
256 DeleteCriticalSection( &This->unk->DP_lock );
257 HeapFree( GetProcessHeap(), 0, This->unk );
259 return TRUE;
262 static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
264 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;
266 This->dp2 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp2) ) );
267 if ( This->dp2 == NULL )
269 return FALSE;
272 This->dp2->bConnectionOpen = FALSE;
274 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
275 This->dp2->dwEnumSessionLock = 0;
277 This->dp2->bHostInterface = FALSE;
279 DPQ_INIT(This->dp2->receiveMsgs);
280 DPQ_INIT(This->dp2->sendMsgs);
281 DPQ_INIT(This->dp2->replysExpected);
283 if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
285 /* FIXME: Memory leak */
286 return FALSE;
289 /* Provide an initial session desc with nothing in it */
290 This->dp2->lpSessionDesc = HeapAlloc( GetProcessHeap(),
291 HEAP_ZERO_MEMORY,
292 sizeof( *This->dp2->lpSessionDesc ) );
293 if( This->dp2->lpSessionDesc == NULL )
295 /* FIXME: Memory leak */
296 return FALSE;
298 This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc );
300 /* We are emulating a dp 6 implementation */
301 This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION;
303 This->dp2->spData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
304 sizeof( *This->dp2->spData.lpCB ) );
305 This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB );
306 This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION;
308 /* This is the pointer to the service provider */
309 if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP,
310 (LPVOID*)&This->dp2->spData.lpISP, This ) )
313 /* FIXME: Memory leak */
314 return FALSE;
317 /* Setup lobby provider information */
318 This->dp2->dplspData.dwSPVersion = DPSP_MAJORVERSION;
319 This->dp2->dplspData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
320 sizeof( *This->dp2->dplspData.lpCB ) );
321 This->dp2->dplspData.lpCB->dwSize = sizeof( *This->dp2->dplspData.lpCB );
323 if( FAILED( DPLSP_CreateInterface( &IID_IDPLobbySP,
324 (LPVOID*)&This->dp2->dplspData.lpISP, This ) )
327 /* FIXME: Memory leak */
328 return FALSE;
331 return TRUE;
334 /* Definition of the global function in dplayx_queue.h. #
335 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
336 DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
338 HeapFree( GetProcessHeap(), 0, elem );
341 /* Function to delete the list of groups with this interface. Needs to
342 * delete the group and player lists associated with this group as well
343 * as the group data associated with this group. It should not delete
344 * player data as that is shared with the top player list and will be
345 * deleted with that.
347 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList );
348 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList )
350 DPQ_DELETEQ( elem->lpGData->groups, groups,
351 lpGroupList, cbDeleteElemFromHeap );
352 DPQ_DELETEQ( elem->lpGData->players, players,
353 lpPlayerList, cbDeleteElemFromHeap );
354 HeapFree( GetProcessHeap(), 0, elem->lpGData );
355 HeapFree( GetProcessHeap(), 0, elem );
358 /* Function to delete the list of players with this interface. Needs to
359 * delete the player data for all players as well.
361 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList );
362 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList )
364 HeapFree( GetProcessHeap(), 0, elem->lpPData );
365 HeapFree( GetProcessHeap(), 0, elem );
368 static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
370 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;
372 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
374 TerminateThread( This->dp2->hEnumSessionThread, 0 );
375 CloseHandle( This->dp2->hEnumSessionThread );
378 /* Finish with the SP - have it shutdown */
379 if( This->dp2->spData.lpCB->ShutdownEx )
381 DPSP_SHUTDOWNDATA data;
383 TRACE( "Calling SP ShutdownEx\n" );
385 data.lpISP = This->dp2->spData.lpISP;
387 (*This->dp2->spData.lpCB->ShutdownEx)( &data );
389 else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
391 TRACE( "Calling obsolete SP Shutdown\n" );
392 (*This->dp2->spData.lpCB->Shutdown)();
395 /* Unload the SP (if it exists) */
396 if( This->dp2->hServiceProvider != 0 )
398 FreeLibrary( This->dp2->hServiceProvider );
401 /* Unload the Lobby Provider (if it exists) */
402 if( This->dp2->hDPLobbyProvider != 0 )
404 FreeLibrary( This->dp2->hDPLobbyProvider );
407 #if 0
408 DPQ_DELETEQ( This->dp2->players, players, lpPlayerList, cbDeletePlayerElem );
409 DPQ_DELETEQ( This->dp2->groups, groups, lpGroupList, cbDeleteGroupsElem );
410 #endif
412 /* FIXME: Need to delete receive and send msgs queue contents */
414 NS_DeleteSessionCache( This->dp2->lpNameServerData );
416 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
418 IDirectPlaySP_Release( This->dp2->spData.lpISP );
420 /* Delete the contents */
421 HeapFree( GetProcessHeap(), 0, This->dp2 );
423 return TRUE;
426 static BOOL DP_CreateDirectPlay3( LPVOID lpDP )
428 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;
430 This->dp3 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp3) ) );
431 if ( This->dp3 == NULL )
433 return FALSE;
436 return TRUE;
439 static BOOL DP_DestroyDirectPlay3( LPVOID lpDP )
441 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;
443 /* Delete the contents */
444 HeapFree( GetProcessHeap(), 0, This->dp3 );
446 return TRUE;
449 static BOOL DP_CreateDirectPlay4( LPVOID lpDP )
451 IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)lpDP;
453 This->dp4 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp4) ) );
454 if ( This->dp4 == NULL )
456 return FALSE;
459 return TRUE;
462 static BOOL DP_DestroyDirectPlay4( LPVOID lpDP )
464 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;
466 /* Delete the contents */
467 HeapFree( GetProcessHeap(), 0, This->dp4 );
469 return TRUE;
473 /* Create a new interface */
474 HRESULT DP_CreateInterface
475 ( REFIID riid, LPVOID* ppvObj )
477 TRACE( " for %s\n", debugstr_guid( riid ) );
479 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
480 sizeof( IDirectPlay2Impl ) );
482 if( *ppvObj == NULL )
484 return DPERR_OUTOFMEMORY;
487 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
489 IDirectPlay2Impl *This = (IDirectPlay2Impl *)*ppvObj;
490 This->lpVtbl = &directPlay2WVT;
492 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
494 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)*ppvObj;
495 This->lpVtbl = &directPlay2AVT;
497 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
499 IDirectPlay3Impl *This = (IDirectPlay3Impl *)*ppvObj;
500 This->lpVtbl = &directPlay3WVT;
502 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
504 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)*ppvObj;
505 This->lpVtbl = &directPlay3AVT;
507 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
509 IDirectPlay4Impl *This = (IDirectPlay4Impl *)*ppvObj;
510 This->lpVtbl = &directPlay4WVT;
512 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
514 IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)*ppvObj;
515 This->lpVtbl = &directPlay4AVT;
517 else
519 /* Unsupported interface */
520 HeapFree( GetProcessHeap(), 0, *ppvObj );
521 *ppvObj = NULL;
523 return E_NOINTERFACE;
526 /* Initialize it */
527 if ( DP_CreateIUnknown( *ppvObj ) &&
528 DP_CreateDirectPlay2( *ppvObj ) &&
529 DP_CreateDirectPlay3( *ppvObj ) &&
530 DP_CreateDirectPlay4( *ppvObj )
533 IDirectPlayX_AddRef( (LPDIRECTPLAY2A)*ppvObj );
535 return S_OK;
538 /* Initialize failed, destroy it */
539 DP_DestroyDirectPlay4( *ppvObj );
540 DP_DestroyDirectPlay3( *ppvObj );
541 DP_DestroyDirectPlay2( *ppvObj );
542 DP_DestroyIUnknown( *ppvObj );
544 HeapFree( GetProcessHeap(), 0, *ppvObj );
546 *ppvObj = NULL;
547 return DPERR_NOMEMORY;
551 /* Direct Play methods */
553 /* Shared between all dplay types */
554 static HRESULT WINAPI DP_QueryInterface
555 ( LPDIRECTPLAY2 iface, REFIID riid, LPVOID* ppvObj )
557 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
558 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
560 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
561 sizeof( *This ) );
563 if( *ppvObj == NULL )
565 return DPERR_OUTOFMEMORY;
568 CopyMemory( *ppvObj, This, sizeof( *This ) );
569 (*(IDirectPlay2Impl**)ppvObj)->ulInterfaceRef = 0;
571 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
573 IDirectPlay2Impl *This = (IDirectPlay2Impl *)*ppvObj;
574 This->lpVtbl = &directPlay2WVT;
576 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
578 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)*ppvObj;
579 This->lpVtbl = &directPlay2AVT;
581 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
583 IDirectPlay3Impl *This = (IDirectPlay3Impl *)*ppvObj;
584 This->lpVtbl = &directPlay3WVT;
586 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
588 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)*ppvObj;
589 This->lpVtbl = &directPlay3AVT;
591 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
593 IDirectPlay4Impl *This = (IDirectPlay4Impl *)*ppvObj;
594 This->lpVtbl = &directPlay4WVT;
596 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
598 IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)*ppvObj;
599 This->lpVtbl = &directPlay4AVT;
601 else
603 /* Unsupported interface */
604 HeapFree( GetProcessHeap(), 0, *ppvObj );
605 *ppvObj = NULL;
607 return E_NOINTERFACE;
610 IDirectPlayX_AddRef( (LPDIRECTPLAY2)*ppvObj );
612 return S_OK;
615 /* Shared between all dplay types */
616 static ULONG WINAPI DP_AddRef
617 ( LPDIRECTPLAY3 iface )
619 ULONG ulInterfaceRefCount, ulObjRefCount;
620 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
622 ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
623 ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
625 TRACE( "ref count incremented to %u:%u for %p\n",
626 ulInterfaceRefCount, ulObjRefCount, This );
628 return ulObjRefCount;
631 static ULONG WINAPI DP_Release
632 ( LPDIRECTPLAY3 iface )
634 ULONG ulInterfaceRefCount, ulObjRefCount;
636 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
638 ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
639 ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
641 TRACE( "ref count decremented to %u:%u for %p\n",
642 ulInterfaceRefCount, ulObjRefCount, This );
644 /* Deallocate if this is the last reference to the object */
645 if( ulObjRefCount == 0 )
647 /* If we're destroying the object, this must be the last ref
648 of the last interface */
649 DP_DestroyDirectPlay4( This );
650 DP_DestroyDirectPlay3( This );
651 DP_DestroyDirectPlay2( This );
652 DP_DestroyIUnknown( This );
655 /* Deallocate the interface */
656 if( ulInterfaceRefCount == 0 )
658 HeapFree( GetProcessHeap(), 0, This );
661 return ulObjRefCount;
664 static inline DPID DP_NextObjectId(void)
666 return (DPID)InterlockedIncrement( &kludgePlayerGroupId );
669 /* *lplpReply will be non NULL iff there is something to reply */
670 HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpcMessageBody,
671 DWORD dwMessageBodySize, LPCVOID lpcMessageHeader,
672 WORD wCommandId, WORD wVersion,
673 LPVOID* lplpReply, LPDWORD lpdwMsgSize )
675 TRACE( "(%p)->(%p,0x%08x,%p,%u,%u)\n",
676 This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId,
677 wVersion );
679 switch( wCommandId )
681 /* Name server needs to handle this request */
682 case DPMSGCMD_ENUMSESSIONSREQUEST:
684 /* Reply expected */
685 NS_ReplyToEnumSessionsRequest( lpcMessageBody, lplpReply, lpdwMsgSize, This );
687 break;
690 /* Name server needs to handle this request */
691 case DPMSGCMD_ENUMSESSIONSREPLY:
693 /* No reply expected */
694 NS_AddRemoteComputerAsNameServer( lpcMessageHeader,
695 This->dp2->spData.dwSPHeaderSize,
696 lpcMessageBody,
697 This->dp2->lpNameServerData );
698 break;
701 case DPMSGCMD_REQUESTNEWPLAYERID:
703 LPCDPMSG_REQUESTNEWPLAYERID lpcMsg =
704 (LPCDPMSG_REQUESTNEWPLAYERID)lpcMessageBody;
706 LPDPMSG_NEWPLAYERIDREPLY lpReply;
708 *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
710 *lplpReply = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, *lpdwMsgSize );
712 FIXME( "Ignoring dwFlags 0x%08x in request msg\n",
713 lpcMsg->dwFlags );
715 /* Setup the reply */
716 lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) +
717 This->dp2->spData.dwSPHeaderSize );
719 lpReply->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
720 lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY;
721 lpReply->envelope.wVersion = DPMSGVER_DP6;
723 lpReply->dpidNewPlayerId = DP_NextObjectId();
725 TRACE( "Allocating new playerid 0x%08x from remote request\n",
726 lpReply->dpidNewPlayerId );
728 break;
731 case DPMSGCMD_GETNAMETABLEREPLY:
732 case DPMSGCMD_NEWPLAYERIDREPLY:
735 #if 0
736 if( wCommandId == DPMSGCMD_NEWPLAYERIDREPLY )
737 DebugBreak();
738 #endif
739 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
741 break;
744 #if 1
745 case DPMSGCMD_JUSTENVELOPE:
747 TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08x\n", lpcMessageHeader, ((const DWORD *)lpcMessageHeader)[1] );
748 NS_SetLocalAddr( This->dp2->lpNameServerData, lpcMessageHeader, 20 );
749 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
751 #endif
753 case DPMSGCMD_FORWARDADDPLAYER:
755 #if 0
756 DebugBreak();
757 #endif
758 #if 1
759 TRACE( "Sending message to self to get my addr\n" );
760 DP_MSG_ToSelf( This, 1 ); /* This is a hack right now */
761 #endif
762 break;
765 case DPMSGCMD_FORWARDADDPLAYERNACK:
767 DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
768 break;
771 default:
773 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
774 DebugBreak();
775 break;
779 /* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */
781 return DP_OK;
785 static HRESULT WINAPI DP_IF_AddPlayerToGroup
786 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
787 DPID idPlayer, BOOL bAnsi )
789 lpGroupData lpGData;
790 lpPlayerList lpPList;
791 lpPlayerList lpNewPList;
793 TRACE( "(%p)->(%p,0x%08x,0x%08x,%u)\n",
794 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
796 /* Find the group */
797 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
799 return DPERR_INVALIDGROUP;
802 /* Find the player */
803 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
805 return DPERR_INVALIDPLAYER;
808 /* Create a player list (ie "shortcut" ) */
809 lpNewPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewPList ) );
810 if( lpNewPList == NULL )
812 return DPERR_CANTADDPLAYER;
815 /* Add the shortcut */
816 lpPList->lpPData->uRef++;
817 lpNewPList->lpPData = lpPList->lpPData;
819 /* Add the player to the list of players for this group */
820 DPQ_INSERT(lpGData->players,lpNewPList,players);
822 /* Let the SP know that we've added a player to the group */
823 if( This->dp2->spData.lpCB->AddPlayerToGroup )
825 DPSP_ADDPLAYERTOGROUPDATA data;
827 TRACE( "Calling SP AddPlayerToGroup\n" );
829 data.idPlayer = idPlayer;
830 data.idGroup = idGroup;
831 data.lpISP = This->dp2->spData.lpISP;
833 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
836 /* Inform all other peers of the addition of player to the group. If there are
837 * no peers keep this event quiet.
838 * Also, if this event was the result of another machine sending it to us,
839 * don't bother rebroadcasting it.
841 if( ( lpMsgHdr == NULL ) &&
842 This->dp2->lpSessionDesc &&
843 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
845 DPMSG_ADDPLAYERTOGROUP msg;
846 msg.dwType = DPSYS_ADDPLAYERTOGROUP;
848 msg.dpIdGroup = idGroup;
849 msg.dpIdPlayer = idPlayer;
851 /* FIXME: Correct to just use send effectively? */
852 /* FIXME: Should size include data w/ message or just message "header" */
853 /* FIXME: Check return code */
854 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
857 return DP_OK;
860 static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
861 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
863 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
864 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, TRUE );
867 static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
868 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
870 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
871 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, FALSE );
874 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi )
876 HRESULT hr = DP_OK;
878 TRACE("(%p)->(%u)\n", This, bAnsi );
880 /* FIXME: Need to find a new host I assume (how?) */
881 /* FIXME: Need to destroy all local groups */
882 /* FIXME: Need to migrate all remotely visible players to the new host */
884 /* Invoke the SP callback to inform of session close */
885 if( This->dp2->spData.lpCB->CloseEx )
887 DPSP_CLOSEDATA data;
889 TRACE( "Calling SP CloseEx\n" );
891 data.lpISP = This->dp2->spData.lpISP;
893 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
896 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
898 TRACE( "Calling SP Close (obsolete interface)\n" );
900 hr = (*This->dp2->spData.lpCB->Close)();
903 return hr;
906 static HRESULT WINAPI DirectPlay2AImpl_Close
907 ( LPDIRECTPLAY2A iface )
909 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
910 return DP_IF_Close( This, TRUE );
913 static HRESULT WINAPI DirectPlay2WImpl_Close
914 ( LPDIRECTPLAY2 iface )
916 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
917 return DP_IF_Close( This, FALSE );
920 static
921 lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, const DPID *lpid,
922 const DPNAME *lpName, DWORD dwFlags,
923 DPID idParent, BOOL bAnsi )
925 lpGroupData lpGData;
927 /* Allocate the new space and add to end of high level group list */
928 lpGData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGData ) );
930 if( lpGData == NULL )
932 return NULL;
935 DPQ_INIT(lpGData->groups);
936 DPQ_INIT(lpGData->players);
938 /* Set the desired player ID - no sanity checking to see if it exists */
939 lpGData->dpid = *lpid;
941 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
943 /* FIXME: Should we check that the parent exists? */
944 lpGData->parent = idParent;
946 /* FIXME: Should we validate the dwFlags? */
947 lpGData->dwFlags = dwFlags;
949 TRACE( "Created group id 0x%08x\n", *lpid );
951 return lpGData;
954 /* This method assumes that all links to it are already deleted */
955 static void
956 DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid )
958 lpGroupList lpGList;
960 TRACE( "(%p)->(0x%08x)\n", This, dpid );
962 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
964 if( lpGList == NULL )
966 ERR( "DPID 0x%08x not found\n", dpid );
967 return;
970 if( --(lpGList->lpGData->uRef) )
972 FIXME( "Why is this not the last reference to group?\n" );
973 DebugBreak();
976 /* Delete player */
977 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
978 HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
980 /* Remove and Delete Player List object */
981 HeapFree( GetProcessHeap(), 0, lpGList );
985 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid )
987 lpGroupList lpGroups;
989 TRACE( "(%p)->(0x%08x)\n", This, dpid );
991 if( dpid == DPID_SYSTEM_GROUP )
993 return This->dp2->lpSysGroup;
995 else
997 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
1000 if( lpGroups == NULL )
1002 return NULL;
1005 return lpGroups->lpGData;
1008 static HRESULT WINAPI DP_IF_CreateGroup
1009 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
1010 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
1011 DWORD dwFlags, BOOL bAnsi )
1013 lpGroupData lpGData;
1015 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1016 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
1017 dwFlags, bAnsi );
1019 /* If the name is not specified, we must provide one */
1020 if( DPID_UNKNOWN == *lpidGroup )
1022 /* If we are the name server, we decide on the group ids. If not, we
1023 * must ask for one before attempting a creation.
1025 if( This->dp2->bHostInterface )
1027 *lpidGroup = DP_NextObjectId();
1029 else
1031 *lpidGroup = DP_GetRemoteNextObjectId();
1035 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
1036 DPID_NOPARENT_GROUP, bAnsi );
1038 if( lpGData == NULL )
1040 return DPERR_CANTADDPLAYER; /* yes player not group */
1043 if( DPID_SYSTEM_GROUP == *lpidGroup )
1045 This->dp2->lpSysGroup = lpGData;
1046 TRACE( "Inserting system group\n" );
1048 else
1050 /* Insert into the system group */
1051 lpGroupList lpGroup = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGroup ) );
1052 lpGroup->lpGData = lpGData;
1054 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
1057 /* Something is now referencing this data */
1058 lpGData->uRef++;
1060 /* Set all the important stuff for the group */
1061 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
1063 /* FIXME: We should only create the system group if GetCaps returns
1064 * DPCAPS_GROUPOPTIMIZED.
1067 /* Let the SP know that we've created this group */
1068 if( This->dp2->spData.lpCB->CreateGroup )
1070 DPSP_CREATEGROUPDATA data;
1071 DWORD dwCreateFlags = 0;
1073 TRACE( "Calling SP CreateGroup\n" );
1075 if( *lpidGroup == DPID_NOPARENT_GROUP )
1076 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
1078 if( lpMsgHdr == NULL )
1079 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1081 if( dwFlags & DPGROUP_HIDDEN )
1082 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
1084 data.idGroup = *lpidGroup;
1085 data.dwFlags = dwCreateFlags;
1086 data.lpSPMessageHeader = lpMsgHdr;
1087 data.lpISP = This->dp2->spData.lpISP;
1089 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1092 /* Inform all other peers of the creation of a new group. If there are
1093 * no peers keep this event quiet.
1094 * Also if this message was sent to us, don't rebroadcast.
1096 if( ( lpMsgHdr == NULL ) &&
1097 This->dp2->lpSessionDesc &&
1098 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1100 DPMSG_CREATEPLAYERORGROUP msg;
1101 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1103 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1104 msg.dpId = *lpidGroup;
1105 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1106 msg.lpData = lpData;
1107 msg.dwDataSize = dwDataSize;
1108 msg.dpnName = *lpGroupName;
1109 msg.dpIdParent = DPID_NOPARENT_GROUP;
1110 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
1112 /* FIXME: Correct to just use send effectively? */
1113 /* FIXME: Should size include data w/ message or just message "header" */
1114 /* FIXME: Check return code */
1115 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
1116 0, 0, NULL, NULL, bAnsi );
1119 return DP_OK;
1122 static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
1123 ( LPDIRECTPLAY2A iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1124 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1126 *lpidGroup = DPID_UNKNOWN;
1128 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1129 lpGroupName, lpData, dwDataSize, dwFlags, TRUE );
1132 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
1133 ( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1134 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1136 *lpidGroup = DPID_UNKNOWN;
1138 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1139 lpGroupName, lpData, dwDataSize, dwFlags, FALSE );
1143 static void
1144 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
1145 LPVOID lpData, DWORD dwDataSize )
1147 /* Clear out the data with this player */
1148 if( dwFlags & DPSET_LOCAL )
1150 if ( lpGData->dwLocalDataSize != 0 )
1152 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
1153 lpGData->lpLocalData = NULL;
1154 lpGData->dwLocalDataSize = 0;
1157 else
1159 if( lpGData->dwRemoteDataSize != 0 )
1161 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
1162 lpGData->lpRemoteData = NULL;
1163 lpGData->dwRemoteDataSize = 0;
1167 /* Reallocate for new data */
1168 if( lpData != NULL )
1170 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1171 sizeof( dwDataSize ) );
1172 CopyMemory( lpNewData, lpData, dwDataSize );
1174 if( dwFlags & DPSET_LOCAL )
1176 lpGData->lpLocalData = lpData;
1177 lpGData->dwLocalDataSize = dwDataSize;
1179 else
1181 lpGData->lpRemoteData = lpNewData;
1182 lpGData->dwRemoteDataSize = dwDataSize;
1188 /* This function will just create the storage for the new player. */
1189 static
1190 lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid,
1191 LPDPNAME lpName, DWORD dwFlags,
1192 HANDLE hEvent, BOOL bAnsi )
1194 lpPlayerData lpPData;
1196 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
1198 /* Allocate the storage for the player and associate it with list element */
1199 lpPData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPData ) );
1200 if( lpPData == NULL )
1202 return NULL;
1205 /* Set the desired player ID */
1206 lpPData->dpid = *lpid;
1208 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
1210 lpPData->dwFlags = dwFlags;
1212 /* If we were given an event handle, duplicate it */
1213 if( hEvent != 0 )
1215 if( !DuplicateHandle( GetCurrentProcess(), hEvent,
1216 GetCurrentProcess(), &lpPData->hEvent,
1217 0, FALSE, DUPLICATE_SAME_ACCESS )
1220 /* FIXME: Memory leak */
1221 ERR( "Can't duplicate player msg handle %p\n", hEvent );
1225 /* Initialize the SP data section */
1226 lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData();
1228 TRACE( "Created player id 0x%08x\n", *lpid );
1230 if( ~dwFlags & DPLAYI_PLAYER_SYSPLAYER )
1231 This->dp2->lpSessionDesc->dwCurrentPlayers++;
1233 return lpPData;
1236 /* Delete the contents of the DPNAME struct */
1237 static void
1238 DP_DeleteDPNameStruct( LPDPNAME lpDPName )
1240 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u1.lpszShortNameA );
1241 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u2.lpszLongNameA );
1244 /* This method assumes that all links to it are already deleted */
1245 static void
1246 DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid )
1248 lpPlayerList lpPList;
1250 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1252 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1254 if( lpPList == NULL )
1256 ERR( "DPID 0x%08x not found\n", dpid );
1257 return;
1260 /* Verify that this is the last reference to the data */
1261 if( --(lpPList->lpPData->uRef) )
1263 FIXME( "Why is this not the last reference to player?\n" );
1264 DebugBreak();
1267 /* Delete player */
1268 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1270 CloseHandle( lpPList->lpPData->hEvent );
1271 HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
1273 /* Delete Player List object */
1274 HeapFree( GetProcessHeap(), 0, lpPList );
1277 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid )
1279 lpPlayerList lpPlayers;
1281 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1283 if(This->dp2->lpSysGroup == NULL)
1284 return NULL;
1286 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1288 return lpPlayers;
1291 /* Basic area for Dst must already be allocated */
1292 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, const DPNAME *lpSrc, BOOL bAnsi )
1294 if( lpSrc == NULL )
1296 ZeroMemory( lpDst, sizeof( *lpDst ) );
1297 lpDst->dwSize = sizeof( *lpDst );
1298 return TRUE;
1301 if( lpSrc->dwSize != sizeof( *lpSrc) )
1303 return FALSE;
1306 /* Delete any existing pointers */
1307 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1308 HeapFree( GetProcessHeap(), 0, lpDst->u2.lpszLongNameA );
1310 /* Copy as required */
1311 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1313 if( bAnsi )
1315 if( lpSrc->u1.lpszShortNameA )
1317 lpDst->u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), 0,
1318 strlen(lpSrc->u1.lpszShortNameA)+1 );
1319 strcpy( lpDst->u1.lpszShortNameA, lpSrc->u1.lpszShortNameA );
1321 if( lpSrc->u2.lpszLongNameA )
1323 lpDst->u2.lpszLongNameA = HeapAlloc( GetProcessHeap(), 0,
1324 strlen(lpSrc->u2.lpszLongNameA)+1 );
1325 strcpy( lpDst->u2.lpszLongNameA, lpSrc->u2.lpszLongNameA );
1328 else
1330 if( lpSrc->u1.lpszShortNameA )
1332 lpDst->u1.lpszShortName = HeapAlloc( GetProcessHeap(), 0,
1333 (strlenW(lpSrc->u1.lpszShortName)+1)*sizeof(WCHAR) );
1334 strcpyW( lpDst->u1.lpszShortName, lpSrc->u1.lpszShortName );
1336 if( lpSrc->u2.lpszLongNameA )
1338 lpDst->u2.lpszLongName = HeapAlloc( GetProcessHeap(), 0,
1339 (strlenW(lpSrc->u2.lpszLongName)+1)*sizeof(WCHAR) );
1340 strcpyW( lpDst->u2.lpszLongName, lpSrc->u2.lpszLongName );
1344 return TRUE;
1347 static void
1348 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
1349 LPVOID lpData, DWORD dwDataSize )
1351 /* Clear out the data with this player */
1352 if( dwFlags & DPSET_LOCAL )
1354 if ( lpPData->dwLocalDataSize != 0 )
1356 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
1357 lpPData->lpLocalData = NULL;
1358 lpPData->dwLocalDataSize = 0;
1361 else
1363 if( lpPData->dwRemoteDataSize != 0 )
1365 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
1366 lpPData->lpRemoteData = NULL;
1367 lpPData->dwRemoteDataSize = 0;
1371 /* Reallocate for new data */
1372 if( lpData != NULL )
1374 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1375 sizeof( dwDataSize ) );
1376 CopyMemory( lpNewData, lpData, dwDataSize );
1378 if( dwFlags & DPSET_LOCAL )
1380 lpPData->lpLocalData = lpData;
1381 lpPData->dwLocalDataSize = dwDataSize;
1383 else
1385 lpPData->lpRemoteData = lpNewData;
1386 lpPData->dwRemoteDataSize = dwDataSize;
1392 static HRESULT WINAPI DP_IF_CreatePlayer
1393 ( IDirectPlay2Impl* This,
1394 LPVOID lpMsgHdr, /* NULL for local creation, non NULL for remote creation */
1395 LPDPID lpidPlayer,
1396 LPDPNAME lpPlayerName,
1397 HANDLE hEvent,
1398 LPVOID lpData,
1399 DWORD dwDataSize,
1400 DWORD dwFlags,
1401 BOOL bAnsi )
1403 HRESULT hr = DP_OK;
1404 lpPlayerData lpPData;
1405 lpPlayerList lpPList;
1406 DWORD dwCreateFlags = 0;
1408 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1409 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1410 dwDataSize, dwFlags, bAnsi );
1412 if( dwFlags == 0 )
1414 dwFlags = DPPLAYER_SPECTATOR;
1417 if( lpidPlayer == NULL )
1419 return DPERR_INVALIDPARAMS;
1423 /* Determine the creation flags for the player. These will be passed
1424 * to the name server if requesting a player id and to the SP when
1425 * informing it of the player creation
1428 if( dwFlags & DPPLAYER_SERVERPLAYER )
1430 if( *lpidPlayer == DPID_SERVERPLAYER )
1432 /* Server player for the host interface */
1433 dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
1435 else if( *lpidPlayer == DPID_NAME_SERVER )
1437 /* Name server - master of everything */
1438 dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
1440 else
1442 /* Server player for a non host interface */
1443 dwCreateFlags |= DPLAYI_PLAYER_SYSPLAYER;
1447 if( lpMsgHdr == NULL )
1448 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1451 /* Verify we know how to handle all the flags */
1452 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1453 ( dwFlags & DPPLAYER_SPECTATOR )
1457 /* Assume non fatal failure */
1458 ERR( "unknown dwFlags = 0x%08x\n", dwFlags );
1461 /* If the name is not specified, we must provide one */
1462 if( *lpidPlayer == DPID_UNKNOWN )
1464 /* If we are the session master, we dish out the group/player ids */
1465 if( This->dp2->bHostInterface )
1467 *lpidPlayer = DP_NextObjectId();
1469 else
1471 hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer );
1473 if( FAILED(hr) )
1475 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1476 return hr;
1480 else
1482 /* FIXME: Would be nice to perhaps verify that we don't already have
1483 * this player.
1487 /* We pass creation flags, so we can distinguish sysplayers and not count them in the current
1488 player total */
1489 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwCreateFlags,
1490 hEvent, bAnsi );
1492 if( lpPData == NULL )
1494 return DPERR_CANTADDPLAYER;
1497 /* Create the list object and link it in */
1498 lpPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPList ) );
1499 if( lpPList == NULL )
1501 FIXME( "Memory leak\n" );
1502 return DPERR_CANTADDPLAYER;
1505 lpPData->uRef = 1;
1506 lpPList->lpPData = lpPData;
1508 /* Add the player to the system group */
1509 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1511 /* Update the information and send it to all players in the session */
1512 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
1514 /* Let the SP know that we've created this player */
1515 if( This->dp2->spData.lpCB->CreatePlayer )
1517 DPSP_CREATEPLAYERDATA data;
1519 data.idPlayer = *lpidPlayer;
1520 data.dwFlags = dwCreateFlags;
1521 data.lpSPMessageHeader = lpMsgHdr;
1522 data.lpISP = This->dp2->spData.lpISP;
1524 TRACE( "Calling SP CreatePlayer 0x%08x: dwFlags: 0x%08x lpMsgHdr: %p\n",
1525 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
1527 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1530 if( FAILED(hr) )
1532 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1533 return hr;
1536 /* Now let the SP know that this player is a member of the system group */
1537 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1539 DPSP_ADDPLAYERTOGROUPDATA data;
1541 data.idPlayer = *lpidPlayer;
1542 data.idGroup = DPID_SYSTEM_GROUP;
1543 data.lpISP = This->dp2->spData.lpISP;
1545 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1547 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1550 if( FAILED(hr) )
1552 ERR( "Failed to add player to sys group with sp: %s\n",
1553 DPLAYX_HresultToString(hr) );
1554 return hr;
1557 #if 1
1558 if( This->dp2->bHostInterface == FALSE )
1560 /* Let the name server know about the creation of this player */
1561 /* FIXME: Is this only to be done for the creation of a server player or
1562 * is this used for regular players? If only for server players, move
1563 * this call to DP_SecureOpen(...);
1565 #if 0
1566 TRACE( "Sending message to self to get my addr\n" );
1567 DP_MSG_ToSelf( This, *lpidPlayer ); /* This is a hack right now */
1568 #endif
1570 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
1572 #else
1573 /* Inform all other peers of the creation of a new player. If there are
1574 * no peers keep this quiet.
1575 * Also, if this was a remote event, no need to rebroadcast it.
1577 if( ( lpMsgHdr == NULL ) &&
1578 This->dp2->lpSessionDesc &&
1579 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1581 DPMSG_CREATEPLAYERORGROUP msg;
1582 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1584 msg.dwPlayerType = DPPLAYERTYPE_PLAYER;
1585 msg.dpId = *lpidPlayer;
1586 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */
1587 msg.lpData = lpData;
1588 msg.dwDataSize = dwDataSize;
1589 msg.dpnName = *lpPlayerName;
1590 msg.dpIdParent = DPID_NOPARENT_GROUP;
1591 msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
1593 /* FIXME: Correct to just use send effectively? */
1594 /* FIXME: Should size include data w/ message or just message "header" */
1595 /* FIXME: Check return code */
1596 hr = DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
1597 sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
1599 #endif
1601 return hr;
1604 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
1605 ( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1606 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1608 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1610 if( dwFlags & DPPLAYER_SERVERPLAYER )
1612 *lpidPlayer = DPID_SERVERPLAYER;
1614 else
1616 *lpidPlayer = DPID_UNKNOWN;
1619 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1620 lpData, dwDataSize, dwFlags, TRUE );
1623 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
1624 ( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1625 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1627 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
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, FALSE );
1642 static DPID DP_GetRemoteNextObjectId(void)
1644 FIXME( ":stub\n" );
1646 /* Hack solution */
1647 return DP_NextObjectId();
1650 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
1651 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
1652 DPID idPlayer, BOOL bAnsi )
1654 HRESULT hr = DP_OK;
1656 lpGroupData lpGData;
1657 lpPlayerList lpPList;
1659 TRACE( "(%p)->(%p,0x%08x,0x%08x,%u)\n",
1660 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
1662 /* Find the group */
1663 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1665 return DPERR_INVALIDGROUP;
1668 /* Find the player */
1669 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
1671 return DPERR_INVALIDPLAYER;
1674 /* Remove the player shortcut from the group */
1675 DPQ_REMOVE_ENTRY( lpGData->players, players, lpPData->dpid, ==, idPlayer, lpPList );
1677 if( lpPList == NULL )
1679 return DPERR_INVALIDPLAYER;
1682 /* One less reference */
1683 lpPList->lpPData->uRef--;
1685 /* Delete the Player List element */
1686 HeapFree( GetProcessHeap(), 0, lpPList );
1688 /* Inform the SP if they care */
1689 if( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1691 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1693 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1695 data.idPlayer = idPlayer;
1696 data.idGroup = idGroup;
1697 data.lpISP = This->dp2->spData.lpISP;
1699 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1702 /* Need to send a DELETEPLAYERFROMGROUP message */
1703 FIXME( "Need to send a message\n" );
1705 return hr;
1708 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
1709 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
1711 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1712 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, TRUE );
1715 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
1716 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
1718 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1719 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, FALSE );
1722 typedef struct _DPRGOPContext
1724 IDirectPlay3Impl* This;
1725 BOOL bAnsi;
1726 DPID idGroup;
1727 } DPRGOPContext, *lpDPRGOPContext;
1729 static BOOL CALLBACK
1730 cbRemoveGroupOrPlayer(
1731 DPID dpId,
1732 DWORD dwPlayerType,
1733 LPCDPNAME lpName,
1734 DWORD dwFlags,
1735 LPVOID lpContext )
1737 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1739 TRACE( "Removing element:0x%08x (type:0x%08x) from element:0x%08x\n",
1740 dpId, dwPlayerType, lpCtxt->idGroup );
1742 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1744 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt->This, lpCtxt->idGroup,
1745 dpId )
1749 ERR( "Unable to delete group 0x%08x from group 0x%08x\n",
1750 dpId, lpCtxt->idGroup );
1753 else
1755 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl*)lpCtxt->This,
1756 NULL, lpCtxt->idGroup,
1757 dpId, lpCtxt->bAnsi )
1761 ERR( "Unable to delete player 0x%08x from grp 0x%08x\n",
1762 dpId, lpCtxt->idGroup );
1766 return TRUE; /* Continue enumeration */
1769 static HRESULT WINAPI DP_IF_DestroyGroup
1770 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi )
1772 lpGroupData lpGData;
1773 DPRGOPContext context;
1775 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1776 This, lpMsgHdr, idGroup, bAnsi );
1778 /* Find the group */
1779 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1781 return DPERR_INVALIDPLAYER; /* yes player */
1784 context.This = (IDirectPlay3Impl*)This;
1785 context.bAnsi = bAnsi;
1786 context.idGroup = idGroup;
1788 /* Remove all players that this group has */
1789 DP_IF_EnumGroupPlayers( This, idGroup, NULL,
1790 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1792 /* Remove all links to groups that this group has since this is dp3 */
1793 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This, idGroup, NULL,
1794 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1796 /* Remove this group from the parent group - if it has one */
1797 if( ( idGroup != DPID_SYSTEM_GROUP ) &&
1798 ( lpGData->parent != DPID_SYSTEM_GROUP )
1801 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl*)This, lpGData->parent,
1802 idGroup );
1805 /* Now delete this group data and list from the system group */
1806 DP_DeleteGroup( This, idGroup );
1808 /* Let the SP know that we've destroyed this group */
1809 if( This->dp2->spData.lpCB->DeleteGroup )
1811 DPSP_DELETEGROUPDATA data;
1813 FIXME( "data.dwFlags is incorrect\n" );
1815 data.idGroup = idGroup;
1816 data.dwFlags = 0;
1817 data.lpISP = This->dp2->spData.lpISP;
1819 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1822 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1824 return DP_OK;
1827 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
1828 ( LPDIRECTPLAY2A iface, DPID idGroup )
1830 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1831 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
1834 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
1835 ( LPDIRECTPLAY2 iface, DPID idGroup )
1837 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1838 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
1841 typedef struct _DPFAGContext
1843 IDirectPlay2Impl* This;
1844 DPID idPlayer;
1845 BOOL bAnsi;
1846 } DPFAGContext, *lpDPFAGContext;
1848 static HRESULT WINAPI DP_IF_DestroyPlayer
1849 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi )
1851 DPFAGContext cbContext;
1853 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1854 This, lpMsgHdr, idPlayer, bAnsi );
1856 if( This->dp2->connectionInitialized == NO_PROVIDER )
1858 return DPERR_UNINITIALIZED;
1861 if( DP_FindPlayer( This, idPlayer ) == NULL )
1863 return DPERR_INVALIDPLAYER;
1866 /* FIXME: If the player is remote, we must be the host to delete this */
1868 cbContext.This = This;
1869 cbContext.idPlayer = idPlayer;
1870 cbContext.bAnsi = bAnsi;
1872 /* Find each group and call DeletePlayerFromGroup if the player is a
1873 member of the group */
1874 DP_IF_EnumGroups( This, NULL, cbDeletePlayerFromAllGroups,
1875 (LPVOID)&cbContext, DPENUMGROUPS_ALL, bAnsi );
1877 /* Now delete player and player list from the sys group */
1878 DP_DeletePlayer( This, idPlayer );
1880 /* Let the SP know that we've destroyed this group */
1881 if( This->dp2->spData.lpCB->DeletePlayer )
1883 DPSP_DELETEPLAYERDATA data;
1885 FIXME( "data.dwFlags is incorrect\n" );
1887 data.idPlayer = idPlayer;
1888 data.dwFlags = 0;
1889 data.lpISP = This->dp2->spData.lpISP;
1891 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
1894 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
1896 return DP_OK;
1899 static BOOL CALLBACK
1900 cbDeletePlayerFromAllGroups(
1901 DPID dpId,
1902 DWORD dwPlayerType,
1903 LPCDPNAME lpName,
1904 DWORD dwFlags,
1905 LPVOID lpContext )
1907 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
1909 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1911 DP_IF_DeletePlayerFromGroup( lpCtxt->This, NULL, dpId, lpCtxt->idPlayer,
1912 lpCtxt->bAnsi );
1914 /* Enumerate all groups in this group since this will normally only
1915 * be called for top level groups
1917 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)lpCtxt->This,
1918 dpId, NULL,
1919 cbDeletePlayerFromAllGroups,
1920 lpContext, DPENUMGROUPS_ALL,
1921 lpCtxt->bAnsi );
1924 else
1926 ERR( "Group callback has dwPlayerType = 0x%08x\n", dwPlayerType );
1929 return TRUE;
1932 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
1933 ( LPDIRECTPLAY2A iface, DPID idPlayer )
1935 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1936 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
1939 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
1940 ( LPDIRECTPLAY2 iface, DPID idPlayer )
1942 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1943 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
1946 static HRESULT WINAPI DP_IF_EnumGroupPlayers
1947 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
1948 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1949 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1951 lpGroupData lpGData;
1952 lpPlayerList lpPList;
1954 FIXME("(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
1955 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
1956 lpContext, dwFlags, bAnsi );
1958 if( This->dp2->connectionInitialized == NO_PROVIDER )
1960 return DPERR_UNINITIALIZED;
1963 /* Find the group */
1964 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1966 return DPERR_INVALIDGROUP;
1969 if( DPQ_IS_EMPTY( lpGData->players ) )
1971 return DP_OK;
1974 lpPList = DPQ_FIRST( lpGData->players );
1976 /* Walk the players in this group */
1977 for( ;; )
1979 /* We do not enum the name server or app server as they are of no
1980 * consequence to the end user.
1982 if( ( lpPList->lpPData->dpid != DPID_NAME_SERVER ) &&
1983 ( lpPList->lpPData->dpid != DPID_SERVERPLAYER )
1987 /* FIXME: Need to add stuff for dwFlags checking */
1989 if( !lpEnumPlayersCallback2( lpPList->lpPData->dpid, DPPLAYERTYPE_PLAYER,
1990 &lpPList->lpPData->name,
1991 lpPList->lpPData->dwFlags,
1992 lpContext )
1995 /* User requested break */
1996 return DP_OK;
2000 if( DPQ_IS_ENDOFLIST( lpPList->players ) )
2002 break;
2005 lpPList = DPQ_NEXT( lpPList->players );
2008 return DP_OK;
2011 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
2012 ( LPDIRECTPLAY2A iface, DPID idGroup, LPGUID lpguidInstance,
2013 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2014 LPVOID lpContext, DWORD dwFlags )
2016 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2017 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2018 lpEnumPlayersCallback2, lpContext,
2019 dwFlags, TRUE );
2022 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
2023 ( LPDIRECTPLAY2 iface, DPID idGroup, LPGUID lpguidInstance,
2024 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2025 LPVOID lpContext, DWORD dwFlags )
2027 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2028 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2029 lpEnumPlayersCallback2, lpContext,
2030 dwFlags, FALSE );
2033 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2034 static HRESULT WINAPI DP_IF_EnumGroups
2035 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2036 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2037 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2039 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This,
2040 DPID_SYSTEM_GROUP, lpguidInstance,
2041 lpEnumPlayersCallback2, lpContext,
2042 dwFlags, bAnsi );
2045 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
2046 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2047 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2048 LPVOID lpContext, DWORD dwFlags )
2050 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2051 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2052 lpContext, dwFlags, TRUE );
2055 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
2056 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2057 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2058 LPVOID lpContext, DWORD dwFlags )
2060 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2061 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2062 lpContext, dwFlags, FALSE );
2065 static HRESULT WINAPI DP_IF_EnumPlayers
2066 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2067 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2068 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2070 return DP_IF_EnumGroupPlayers( This, DPID_SYSTEM_GROUP, lpguidInstance,
2071 lpEnumPlayersCallback2, lpContext,
2072 dwFlags, bAnsi );
2075 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
2076 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2077 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2078 LPVOID lpContext, DWORD dwFlags )
2080 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2081 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2082 lpContext, dwFlags, TRUE );
2085 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
2086 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2087 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2088 LPVOID lpContext, DWORD dwFlags )
2090 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2091 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2092 lpContext, dwFlags, FALSE );
2095 /* This function should call the registered callback function that the user
2096 passed into EnumSessions for each entry available.
2098 static void DP_InvokeEnumSessionCallbacks
2099 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2100 LPVOID lpNSInfo,
2101 DWORD dwTimeout,
2102 LPVOID lpContext )
2104 LPDPSESSIONDESC2 lpSessionDesc;
2106 FIXME( ": not checking for conditions\n" );
2108 /* Not sure if this should be pruning but it's convenient */
2109 NS_PruneSessionCache( lpNSInfo );
2111 NS_ResetSessionEnumeration( lpNSInfo );
2113 /* Enumerate all sessions */
2114 /* FIXME: Need to indicate ANSI */
2115 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2117 TRACE( "EnumSessionsCallback2 invoked\n" );
2118 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2120 return;
2124 /* Invoke one last time to indicate that there is no more to come */
2125 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2128 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2130 EnumSessionAsyncCallbackData* data = (EnumSessionAsyncCallbackData*)lpContext;
2131 HANDLE hSuicideRequest = data->hSuicideRequest;
2132 DWORD dwTimeout = data->dwTimeout;
2134 TRACE( "Thread started with timeout = 0x%08x\n", dwTimeout );
2136 for( ;; )
2138 HRESULT hr;
2140 /* Sleep up to dwTimeout waiting for request to terminate thread */
2141 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2143 TRACE( "Thread terminating on terminate request\n" );
2144 break;
2147 /* Now resend the enum request */
2148 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2149 data->dwEnumSessionFlags,
2150 data->lpSpData );
2152 if( FAILED(hr) )
2154 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2155 /* FIXME: Should we kill this thread? How to inform the main thread? */
2160 TRACE( "Thread terminating\n" );
2162 /* Clean up the thread data */
2163 CloseHandle( hSuicideRequest );
2164 HeapFree( GetProcessHeap(), 0, lpContext );
2166 /* FIXME: Need to have some notification to main app thread that this is
2167 * dead. It would serve two purposes. 1) allow sync on termination
2168 * so that we don't actually send something to ourselves when we
2169 * become name server (race condition) and 2) so that if we die
2170 * abnormally something else will be able to tell.
2173 return 1;
2176 static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
2178 /* Does a thread exist? If so we were doing an async enum session */
2179 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2181 TRACE( "Killing EnumSession thread %p\n",
2182 This->dp2->hEnumSessionThread );
2184 /* Request that the thread kill itself nicely */
2185 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2186 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2188 /* We no longer need to know about the thread */
2189 CloseHandle( This->dp2->hEnumSessionThread );
2191 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2195 static HRESULT WINAPI DP_IF_EnumSessions
2196 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2197 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2198 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2200 HRESULT hr = DP_OK;
2202 TRACE( "(%p)->(%p,0x%08x,%p,%p,0x%08x,%u)\n",
2203 This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags,
2204 bAnsi );
2206 /* Can't enumerate if the interface is already open */
2207 if( This->dp2->bConnectionOpen )
2209 return DPERR_GENERIC;
2212 #if 1
2213 /* The loading of a lobby provider _seems_ to require a backdoor loading
2214 * of the service provider to also associate with this DP object. This is
2215 * because the app doesn't seem to have to call EnumConnections and
2216 * InitializeConnection for the SP before calling this method. As such
2217 * we'll do their dirty work for them with a quick hack so as to always
2218 * load the TCP/IP service provider.
2220 * The correct solution would seem to involve creating a dialog box which
2221 * contains the possible SPs. These dialog boxes most likely follow SDK
2222 * examples.
2224 if( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
2226 LPVOID lpConnection;
2227 DWORD dwSize;
2229 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2231 if( !DP_BuildSPCompoundAddr( (LPGUID)&DPSPGUID_TCPIP, &lpConnection, &dwSize ) )
2233 ERR( "Can't build compound addr\n" );
2234 return DPERR_GENERIC;
2237 hr = DP_IF_InitializeConnection( (IDirectPlay3Impl*)This, lpConnection,
2238 0, bAnsi );
2239 if( FAILED(hr) )
2241 return hr;
2244 /* Free up the address buffer */
2245 HeapFree( GetProcessHeap(), 0, lpConnection );
2247 /* The SP is now initialized */
2248 This->dp2->bSPInitialized = TRUE;
2250 #endif
2253 /* Use the service provider default? */
2254 if( dwTimeout == 0 )
2256 DPCAPS spCaps;
2257 spCaps.dwSize = sizeof( spCaps );
2259 DP_IF_GetCaps( This, &spCaps, 0 );
2260 dwTimeout = spCaps.dwTimeout;
2262 /* The service provider doesn't provide one either! */
2263 if( dwTimeout == 0 )
2265 /* Provide the TCP/IP default */
2266 dwTimeout = DPMSG_WAIT_5_SECS;
2270 if( dwFlags & DPENUMSESSIONS_STOPASYNC )
2272 DP_KillEnumSessionThread( This );
2273 return hr;
2276 if( ( dwFlags & DPENUMSESSIONS_ASYNC ) )
2278 /* Enumerate everything presently in the local session cache */
2279 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2280 This->dp2->lpNameServerData, dwTimeout,
2281 lpContext );
2283 if( This->dp2->dwEnumSessionLock != 0 )
2284 return DPERR_CONNECTING;
2286 /* See if we've already created a thread to service this interface */
2287 if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2289 DWORD dwThreadId;
2290 This->dp2->dwEnumSessionLock++;
2292 /* Send the first enum request inline since the user may cancel a dialog
2293 * if one is presented. Also, may also have a connecting return code.
2295 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2296 dwFlags, &This->dp2->spData );
2298 if( !FAILED(hr) )
2300 EnumSessionAsyncCallbackData* lpData
2301 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpData ) );
2302 /* FIXME: need to kill the thread on object deletion */
2303 lpData->lpSpData = &This->dp2->spData;
2305 lpData->requestGuid = lpsd->guidApplication;
2306 lpData->dwEnumSessionFlags = dwFlags;
2307 lpData->dwTimeout = dwTimeout;
2309 This->dp2->hKillEnumSessionThreadEvent =
2310 CreateEventW( NULL, TRUE, FALSE, NULL );
2312 if( !DuplicateHandle( GetCurrentProcess(),
2313 This->dp2->hKillEnumSessionThreadEvent,
2314 GetCurrentProcess(),
2315 &lpData->hSuicideRequest,
2316 0, FALSE, DUPLICATE_SAME_ACCESS )
2319 ERR( "Can't duplicate thread killing handle\n" );
2322 TRACE( ": creating EnumSessionsRequest thread\n" );
2324 This->dp2->hEnumSessionThread = CreateThread( NULL,
2326 DP_EnumSessionsSendAsyncRequestThread,
2327 lpData,
2329 &dwThreadId );
2331 This->dp2->dwEnumSessionLock--;
2334 else
2336 /* Invalidate the session cache for the interface */
2337 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2339 /* Send the broadcast for session enumeration */
2340 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2341 dwFlags,
2342 &This->dp2->spData );
2345 SleepEx( dwTimeout, FALSE );
2347 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2348 This->dp2->lpNameServerData, dwTimeout,
2349 lpContext );
2352 return hr;
2355 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2356 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2357 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2358 LPVOID lpContext, DWORD dwFlags )
2360 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2361 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2362 lpContext, dwFlags, TRUE );
2365 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2366 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2367 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2368 LPVOID lpContext, DWORD dwFlags )
2370 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2371 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2372 lpContext, dwFlags, FALSE );
2375 static HRESULT WINAPI DP_IF_GetPlayerCaps
2376 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
2377 DWORD dwFlags )
2379 DPSP_GETCAPSDATA data;
2381 TRACE("(%p)->(0x%08x,%p,0x%08x)\n", This, idPlayer, lpDPCaps, dwFlags);
2383 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2385 return DPERR_UNINITIALIZED;
2388 /* Query the service provider */
2389 data.idPlayer = idPlayer;
2390 data.dwFlags = dwFlags;
2391 data.lpCaps = lpDPCaps;
2392 data.lpISP = This->dp2->spData.lpISP;
2394 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2397 static HRESULT WINAPI DP_IF_GetCaps
2398 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags )
2400 return DP_IF_GetPlayerCaps( This, DPID_ALLPLAYERS, lpDPCaps, dwFlags );
2403 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2404 ( LPDIRECTPLAY2A iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2406 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2407 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2410 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2411 ( LPDIRECTPLAY2 iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2413 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2414 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2417 static HRESULT WINAPI DP_IF_GetGroupData
2418 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2419 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2421 lpGroupData lpGData;
2422 DWORD dwRequiredBufferSize;
2423 LPVOID lpCopyDataFrom;
2425 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2426 This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi );
2428 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2430 return DPERR_INVALIDGROUP;
2433 /* How much buffer is required? */
2434 if( dwFlags & DPSET_LOCAL )
2436 dwRequiredBufferSize = lpGData->dwLocalDataSize;
2437 lpCopyDataFrom = lpGData->lpLocalData;
2439 else
2441 dwRequiredBufferSize = lpGData->dwRemoteDataSize;
2442 lpCopyDataFrom = lpGData->lpRemoteData;
2445 /* Is the user requesting to know how big a buffer is required? */
2446 if( ( lpData == NULL ) ||
2447 ( *lpdwDataSize < dwRequiredBufferSize )
2450 *lpdwDataSize = dwRequiredBufferSize;
2451 return DPERR_BUFFERTOOSMALL;
2454 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2456 return DP_OK;
2459 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2460 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2461 LPDWORD lpdwDataSize, DWORD dwFlags )
2463 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2464 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2465 dwFlags, TRUE );
2468 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2469 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2470 LPDWORD lpdwDataSize, DWORD dwFlags )
2472 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2473 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2474 dwFlags, FALSE );
2477 static HRESULT WINAPI DP_IF_GetGroupName
2478 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2479 LPDWORD lpdwDataSize, BOOL bAnsi )
2481 lpGroupData lpGData;
2482 LPDPNAME lpName = (LPDPNAME)lpData;
2483 DWORD dwRequiredDataSize;
2485 FIXME("(%p)->(0x%08x,%p,%p,%u) ANSI ignored\n",
2486 This, idGroup, lpData, lpdwDataSize, bAnsi );
2488 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2490 return DPERR_INVALIDGROUP;
2493 dwRequiredDataSize = lpGData->name.dwSize;
2495 if( lpGData->name.u1.lpszShortNameA )
2497 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
2500 if( lpGData->name.u2.lpszLongNameA )
2502 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
2505 if( ( lpData == NULL ) ||
2506 ( *lpdwDataSize < dwRequiredDataSize )
2509 *lpdwDataSize = dwRequiredDataSize;
2510 return DPERR_BUFFERTOOSMALL;
2513 /* Copy the structure */
2514 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2516 if( lpGData->name.u1.lpszShortNameA )
2518 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2519 lpGData->name.u1.lpszShortNameA );
2521 else
2523 lpName->u1.lpszShortNameA = NULL;
2526 if( lpGData->name.u1.lpszShortNameA )
2528 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2529 lpGData->name.u2.lpszLongNameA );
2531 else
2533 lpName->u2.lpszLongNameA = NULL;
2536 return DP_OK;
2539 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2540 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2541 LPDWORD lpdwDataSize )
2543 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2544 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2547 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2548 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2549 LPDWORD lpdwDataSize )
2551 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2552 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2555 static HRESULT WINAPI DP_IF_GetMessageCount
2556 ( IDirectPlay2Impl* This, DPID idPlayer,
2557 LPDWORD lpdwCount, BOOL bAnsi )
2559 FIXME("(%p)->(0x%08x,%p,%u): stub\n", This, idPlayer, lpdwCount, bAnsi );
2560 return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer,
2561 DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL,
2562 bAnsi );
2565 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2566 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDWORD lpdwCount )
2568 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2569 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, TRUE );
2572 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2573 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDWORD lpdwCount )
2575 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2576 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, FALSE );
2579 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2580 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2582 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2583 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2584 return DP_OK;
2587 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2588 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2590 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2591 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2592 return DP_OK;
2595 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2596 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2597 DWORD dwFlags )
2599 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2600 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2603 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2604 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2605 DWORD dwFlags )
2607 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2608 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2611 static HRESULT WINAPI DP_IF_GetPlayerData
2612 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2613 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2615 lpPlayerList lpPList;
2616 DWORD dwRequiredBufferSize;
2617 LPVOID lpCopyDataFrom;
2619 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2620 This, idPlayer, lpData, lpdwDataSize, dwFlags, bAnsi );
2622 if( This->dp2->connectionInitialized == NO_PROVIDER )
2624 return DPERR_UNINITIALIZED;
2627 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2629 return DPERR_INVALIDPLAYER;
2632 /* How much buffer is required? */
2633 if( dwFlags & DPSET_LOCAL )
2635 dwRequiredBufferSize = lpPList->lpPData->dwLocalDataSize;
2636 lpCopyDataFrom = lpPList->lpPData->lpLocalData;
2638 else
2640 dwRequiredBufferSize = lpPList->lpPData->dwRemoteDataSize;
2641 lpCopyDataFrom = lpPList->lpPData->lpRemoteData;
2644 /* Is the user requesting to know how big a buffer is required? */
2645 if( ( lpData == NULL ) ||
2646 ( *lpdwDataSize < dwRequiredBufferSize )
2649 *lpdwDataSize = dwRequiredBufferSize;
2650 return DPERR_BUFFERTOOSMALL;
2653 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2655 return DP_OK;
2658 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2659 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2660 LPDWORD lpdwDataSize, DWORD dwFlags )
2662 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2663 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2664 dwFlags, TRUE );
2667 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2668 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2669 LPDWORD lpdwDataSize, DWORD dwFlags )
2671 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2672 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2673 dwFlags, FALSE );
2676 static HRESULT WINAPI DP_IF_GetPlayerName
2677 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2678 LPDWORD lpdwDataSize, BOOL bAnsi )
2680 lpPlayerList lpPList;
2681 LPDPNAME lpName = (LPDPNAME)lpData;
2682 DWORD dwRequiredDataSize;
2684 FIXME( "(%p)->(0x%08x,%p,%p,%u): ANSI\n",
2685 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2687 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2689 return DPERR_INVALIDPLAYER;
2692 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
2694 if( lpPList->lpPData->name.u1.lpszShortNameA )
2696 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
2699 if( lpPList->lpPData->name.u2.lpszLongNameA )
2701 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
2704 if( ( lpData == NULL ) ||
2705 ( *lpdwDataSize < dwRequiredDataSize )
2708 *lpdwDataSize = dwRequiredDataSize;
2709 return DPERR_BUFFERTOOSMALL;
2712 /* Copy the structure */
2713 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
2715 if( lpPList->lpPData->name.u1.lpszShortNameA )
2717 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2718 lpPList->lpPData->name.u1.lpszShortNameA );
2720 else
2722 lpName->u1.lpszShortNameA = NULL;
2725 if( lpPList->lpPData->name.u1.lpszShortNameA )
2727 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2728 lpPList->lpPData->name.u2.lpszLongNameA );
2730 else
2732 lpName->u2.lpszLongNameA = NULL;
2735 return DP_OK;
2738 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2739 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2740 LPDWORD lpdwDataSize )
2742 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2743 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
2746 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2747 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2748 LPDWORD lpdwDataSize )
2750 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2751 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
2754 static HRESULT WINAPI DP_GetSessionDesc
2755 ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize,
2756 BOOL bAnsi )
2758 DWORD dwRequiredSize;
2760 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
2762 if( This->dp2->connectionInitialized == NO_PROVIDER )
2764 return DPERR_UNINITIALIZED;
2767 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
2769 return DPERR_INVALIDPARAMS;
2772 /* FIXME: Get from This->dp2->lpSessionDesc */
2773 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
2775 if ( ( lpData == NULL ) ||
2776 ( *lpdwDataSize < dwRequiredSize )
2779 *lpdwDataSize = dwRequiredSize;
2780 return DPERR_BUFFERTOOSMALL;
2783 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
2785 return DP_OK;
2788 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
2789 ( LPDIRECTPLAY2A iface, LPVOID lpData, LPDWORD lpdwDataSize )
2791 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2792 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2795 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
2796 ( LPDIRECTPLAY2 iface, LPVOID lpData, LPDWORD lpdwDataSize )
2798 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2799 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2802 /* Intended only for COM compatibility. Always returns an error. */
2803 static HRESULT WINAPI DirectPlay2AImpl_Initialize
2804 ( LPDIRECTPLAY2A iface, LPGUID lpGUID )
2806 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2807 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2808 return DPERR_ALREADYINITIALIZED;
2811 /* Intended only for COM compatibility. Always returns an error. */
2812 static HRESULT WINAPI DirectPlay2WImpl_Initialize
2813 ( LPDIRECTPLAY2 iface, LPGUID lpGUID )
2815 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2816 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2817 return DPERR_ALREADYINITIALIZED;
2821 static HRESULT WINAPI DP_SecureOpen
2822 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
2823 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
2824 BOOL bAnsi )
2826 HRESULT hr = DP_OK;
2828 FIXME( "(%p)->(%p,0x%08x,%p,%p): partial stub\n",
2829 This, lpsd, dwFlags, lpSecurity, lpCredentials );
2831 if( This->dp2->bConnectionOpen )
2833 TRACE( ": rejecting already open connection.\n" );
2834 return DPERR_ALREADYINITIALIZED;
2837 /* If we're enumerating, kill the thread */
2838 DP_KillEnumSessionThread( This );
2840 if( dwFlags & DPOPEN_CREATE )
2842 /* Rightoo - this computer is the host and the local computer needs to be
2843 the name server so that others can join this session */
2844 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
2846 This->dp2->bHostInterface = TRUE;
2848 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
2849 if( FAILED( hr ) )
2851 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
2852 return hr;
2856 /* Invoke the conditional callback for the service provider */
2857 if( This->dp2->spData.lpCB->Open )
2859 DPSP_OPENDATA data;
2861 FIXME( "Not all data fields are correct. Need new parameter\n" );
2863 data.bCreate = (dwFlags & DPOPEN_CREATE ) ? TRUE : FALSE;
2864 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
2865 : NS_GetNSAddr( This->dp2->lpNameServerData );
2866 data.lpISP = This->dp2->spData.lpISP;
2867 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) ? TRUE : FALSE;
2868 data.dwOpenFlags = dwFlags;
2869 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
2871 hr = (*This->dp2->spData.lpCB->Open)(&data);
2872 if( FAILED( hr ) )
2874 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
2875 return hr;
2880 /* Create the system group of which everything is a part of */
2881 DPID systemGroup = DPID_SYSTEM_GROUP;
2883 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
2884 NULL, 0, 0, TRUE );
2888 if( dwFlags & DPOPEN_JOIN )
2890 DPID dpidServerId = DPID_UNKNOWN;
2892 /* Create the server player for this interface. This way we can receive
2893 * messages for this session.
2895 /* FIXME: I suppose that we should be setting an event for a receive
2896 * type of thing. That way the messaging thread could know to wake
2897 * up. DPlay would then trigger the hEvent for the player the
2898 * message is directed to.
2900 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
2902 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
2905 else if( dwFlags & DPOPEN_CREATE )
2907 DPID dpidNameServerId = DPID_NAME_SERVER;
2909 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
2910 0, DPPLAYER_SERVERPLAYER, bAnsi );
2913 if( FAILED(hr) )
2915 ERR( "Couldn't create name server/system player: %s\n",
2916 DPLAYX_HresultToString(hr) );
2919 return hr;
2922 static HRESULT WINAPI DirectPlay2AImpl_Open
2923 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2925 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2926 TRACE("(%p)->(%p,0x%08x)\n", This, lpsd, dwFlags );
2927 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, TRUE );
2930 static HRESULT WINAPI DirectPlay2WImpl_Open
2931 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2933 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2934 TRACE("(%p)->(%p,0x%08x)\n", This, lpsd, dwFlags );
2935 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, FALSE );
2938 static HRESULT WINAPI DP_IF_Receive
2939 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
2940 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi )
2942 LPDPMSG lpMsg = NULL;
2944 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p,%u): stub\n",
2945 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
2947 if( This->dp2->connectionInitialized == NO_PROVIDER )
2949 return DPERR_UNINITIALIZED;
2952 if( dwFlags == 0 )
2954 dwFlags = DPRECEIVE_ALL;
2957 /* If the lpData is NULL, we must be peeking the message */
2958 if( ( lpData == NULL ) &&
2959 !( dwFlags & DPRECEIVE_PEEK )
2962 return DPERR_INVALIDPARAMS;
2965 if( dwFlags & DPRECEIVE_ALL )
2967 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
2969 if( !( dwFlags & DPRECEIVE_PEEK ) )
2971 FIXME( "Remove from queue\n" );
2974 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
2975 ( dwFlags & DPRECEIVE_FROMPLAYER )
2978 FIXME( "Find matching message 0x%08x\n", dwFlags );
2980 else
2982 ERR( "Hmmm..dwFlags 0x%08x\n", dwFlags );
2985 if( lpMsg == NULL )
2987 return DPERR_NOMESSAGES;
2990 /* Copy into the provided buffer */
2991 CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
2993 return DP_OK;
2996 static HRESULT WINAPI DirectPlay2AImpl_Receive
2997 ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo,
2998 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
3000 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3001 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
3002 lpData, lpdwDataSize, TRUE );
3005 static HRESULT WINAPI DirectPlay2WImpl_Receive
3006 ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo,
3007 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
3009 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3010 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
3011 lpData, lpdwDataSize, FALSE );
3014 static HRESULT WINAPI DirectPlay2AImpl_Send
3015 ( LPDIRECTPLAY2A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3017 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3018 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3019 0, 0, NULL, NULL, TRUE );
3022 static HRESULT WINAPI DirectPlay2WImpl_Send
3023 ( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3025 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3026 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3027 0, 0, NULL, NULL, FALSE );
3030 static HRESULT WINAPI DP_IF_SetGroupData
3031 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
3032 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3034 lpGroupData lpGData;
3036 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3037 This, idGroup, lpData, dwDataSize, dwFlags, bAnsi );
3039 /* Parameter check */
3040 if( ( lpData == NULL ) &&
3041 ( dwDataSize != 0 )
3044 return DPERR_INVALIDPARAMS;
3047 /* Find the pointer to the data for this player */
3048 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3050 return DPERR_INVALIDOBJECT;
3053 if( !(dwFlags & DPSET_LOCAL) )
3055 FIXME( "Was this group created by this interface?\n" );
3056 /* FIXME: If this is a remote update need to allow it but not
3057 * send a message.
3061 DP_SetGroupData( lpGData, dwFlags, lpData, dwDataSize );
3063 /* FIXME: Only send a message if this group is local to the session otherwise
3064 * it will have been rejected above
3066 if( !(dwFlags & DPSET_LOCAL) )
3068 FIXME( "Send msg?\n" );
3071 return DP_OK;
3074 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
3075 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
3076 DWORD dwDataSize, DWORD dwFlags )
3078 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3079 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, TRUE );
3082 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
3083 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
3084 DWORD dwDataSize, DWORD dwFlags )
3086 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3087 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, FALSE );
3090 static HRESULT WINAPI DP_IF_SetGroupName
3091 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
3092 DWORD dwFlags, BOOL bAnsi )
3094 lpGroupData lpGData;
3096 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n", This, idGroup,
3097 lpGroupName, dwFlags, bAnsi );
3099 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3101 return DPERR_INVALIDGROUP;
3104 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
3106 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3107 FIXME( "Message not sent and dwFlags ignored\n" );
3109 return DP_OK;
3112 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
3113 ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName,
3114 DWORD dwFlags )
3116 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3117 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
3120 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
3121 ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName,
3122 DWORD dwFlags )
3124 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3125 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
3128 static HRESULT WINAPI DP_IF_SetPlayerData
3129 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
3130 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3132 lpPlayerList lpPList;
3134 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3135 This, idPlayer, lpData, dwDataSize, dwFlags, bAnsi );
3137 /* Parameter check */
3138 if( ( lpData == NULL ) &&
3139 ( dwDataSize != 0 )
3142 return DPERR_INVALIDPARAMS;
3145 /* Find the pointer to the data for this player */
3146 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3148 return DPERR_INVALIDPLAYER;
3151 if( !(dwFlags & DPSET_LOCAL) )
3153 FIXME( "Was this group created by this interface?\n" );
3154 /* FIXME: If this is a remote update need to allow it but not
3155 * send a message.
3159 DP_SetPlayerData( lpPList->lpPData, dwFlags, lpData, dwDataSize );
3161 if( !(dwFlags & DPSET_LOCAL) )
3163 FIXME( "Send msg?\n" );
3166 return DP_OK;
3169 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3170 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
3171 DWORD dwDataSize, DWORD dwFlags )
3173 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3174 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3175 dwFlags, TRUE );
3178 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3179 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
3180 DWORD dwDataSize, DWORD dwFlags )
3182 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3183 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3184 dwFlags, FALSE );
3187 static HRESULT WINAPI DP_IF_SetPlayerName
3188 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
3189 DWORD dwFlags, BOOL bAnsi )
3191 lpPlayerList lpPList;
3193 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n",
3194 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3196 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3198 return DPERR_INVALIDGROUP;
3201 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3203 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3204 FIXME( "Message not sent and dwFlags ignored\n" );
3206 return DP_OK;
3209 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3210 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName,
3211 DWORD dwFlags )
3213 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3214 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3217 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3218 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName,
3219 DWORD dwFlags )
3221 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3222 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3225 static HRESULT WINAPI DP_SetSessionDesc
3226 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
3227 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3229 DWORD dwRequiredSize;
3230 LPDPSESSIONDESC2 lpTempSessDesc;
3232 TRACE( "(%p)->(%p,0x%08x,%u,%u)\n",
3233 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3235 if( This->dp2->connectionInitialized == NO_PROVIDER )
3237 return DPERR_UNINITIALIZED;
3240 if( dwFlags )
3242 return DPERR_INVALIDPARAMS;
3245 /* Only the host is allowed to update the session desc */
3246 if( !This->dp2->bHostInterface )
3248 return DPERR_ACCESSDENIED;
3251 /* FIXME: Copy into This->dp2->lpSessionDesc */
3252 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3253 lpTempSessDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize );
3255 if( lpTempSessDesc == NULL )
3257 return DPERR_OUTOFMEMORY;
3260 /* Free the old */
3261 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3263 This->dp2->lpSessionDesc = lpTempSessDesc;
3264 /* Set the new */
3265 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3266 if( bInitial )
3268 /*Initializing session GUID*/
3269 CoCreateGuid( &(This->dp2->lpSessionDesc->guidInstance) );
3271 /* If this is an external invocation of the interface, we should be
3272 * letting everyone know that things have changed. Otherwise this is
3273 * just an initialization and it doesn't need to be propagated.
3275 if( !bInitial )
3277 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3280 return DP_OK;
3283 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3284 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3286 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3287 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3290 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3291 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3293 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3294 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3297 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3298 DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3300 DWORD dwSize = 0;
3302 if( lpSessDesc == NULL )
3304 /* Hmmm..don't need any size? */
3305 ERR( "NULL lpSessDesc\n" );
3306 return dwSize;
3309 dwSize += sizeof( *lpSessDesc );
3311 if( bAnsi )
3313 if( lpSessDesc->u1.lpszSessionNameA )
3315 dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1;
3318 if( lpSessDesc->u2.lpszPasswordA )
3320 dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1;
3323 else /* UNICODE */
3325 if( lpSessDesc->u1.lpszSessionName )
3327 dwSize += sizeof( WCHAR ) *
3328 ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 );
3331 if( lpSessDesc->u2.lpszPassword )
3333 dwSize += sizeof( WCHAR ) *
3334 ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 );
3338 return dwSize;
3341 /* Assumes that contiguous buffers are already allocated. */
3342 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3343 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3345 BYTE* lpStartOfFreeSpace;
3347 if( lpSessionDest == NULL )
3349 ERR( "NULL lpSessionDest\n" );
3350 return;
3353 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3355 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3357 if( bAnsi )
3359 if( lpSessionSrc->u1.lpszSessionNameA )
3361 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3362 lpSessionDest->u1.lpszSessionNameA );
3363 lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3364 lpStartOfFreeSpace +=
3365 lstrlenA( lpSessionDest->u1.lpszSessionNameA ) + 1;
3368 if( lpSessionSrc->u2.lpszPasswordA )
3370 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3371 lpSessionDest->u2.lpszPasswordA );
3372 lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3373 lpStartOfFreeSpace +=
3374 lstrlenA( lpSessionDest->u2.lpszPasswordA ) + 1;
3377 else /* UNICODE */
3379 if( lpSessionSrc->u1.lpszSessionName )
3381 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3382 lpSessionDest->u1.lpszSessionName );
3383 lpSessionDest->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3384 lpStartOfFreeSpace += sizeof(WCHAR) *
3385 ( lstrlenW( lpSessionDest->u1.lpszSessionName ) + 1 );
3388 if( lpSessionSrc->u2.lpszPassword )
3390 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3391 lpSessionDest->u2.lpszPassword );
3392 lpSessionDest->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3393 lpStartOfFreeSpace += sizeof(WCHAR) *
3394 ( lstrlenW( lpSessionDest->u2.lpszPassword ) + 1 );
3400 static HRESULT WINAPI DP_IF_AddGroupToGroup
3401 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3403 lpGroupData lpGData;
3404 lpGroupList lpNewGList;
3406 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, idParentGroup, idGroup );
3408 if( DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) == NULL )
3410 return DPERR_INVALIDGROUP;
3413 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3415 return DPERR_INVALIDGROUP;
3418 /* Create a player list (ie "shortcut" ) */
3419 lpNewGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewGList ) );
3420 if( lpNewGList == NULL )
3422 return DPERR_CANTADDPLAYER;
3425 /* Add the shortcut */
3426 lpGData->uRef++;
3427 lpNewGList->lpGData = lpGData;
3429 /* Add the player to the list of players for this group */
3430 DPQ_INSERT( lpGData->groups, lpNewGList, groups );
3432 /* Send a ADDGROUPTOGROUP message */
3433 FIXME( "Not sending message\n" );
3435 return DP_OK;
3438 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3439 ( LPDIRECTPLAY3A iface, DPID idParentGroup, DPID idGroup )
3441 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3442 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3445 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3446 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3448 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3449 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3452 static HRESULT WINAPI DP_IF_CreateGroupInGroup
3453 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
3454 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
3455 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3457 lpGroupData lpGParentData;
3458 lpGroupList lpGList;
3459 lpGroupData lpGData;
3461 TRACE( "(%p)->(0x%08x,%p,%p,%p,0x%08x,0x%08x,%u)\n",
3462 This, idParentGroup, lpidGroup, lpGroupName, lpData,
3463 dwDataSize, dwFlags, bAnsi );
3465 /* Verify that the specified parent is valid */
3466 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This,
3467 idParentGroup ) ) == NULL
3470 return DPERR_INVALIDGROUP;
3473 lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName,
3474 dwFlags, idParentGroup, bAnsi );
3476 if( lpGData == NULL )
3478 return DPERR_CANTADDPLAYER; /* yes player not group */
3481 /* Something else is referencing this data */
3482 lpGData->uRef++;
3484 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
3486 /* The list has now been inserted into the interface group list. We now
3487 need to put a "shortcut" to this group in the parent group */
3488 lpGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGList ) );
3489 if( lpGList == NULL )
3491 FIXME( "Memory leak\n" );
3492 return DPERR_CANTADDPLAYER; /* yes player not group */
3495 lpGList->lpGData = lpGData;
3497 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
3499 /* Let the SP know that we've created this group */
3500 if( This->dp2->spData.lpCB->CreateGroup )
3502 DPSP_CREATEGROUPDATA data;
3504 TRACE( "Calling SP CreateGroup\n" );
3506 data.idGroup = *lpidGroup;
3507 data.dwFlags = dwFlags;
3508 data.lpSPMessageHeader = lpMsgHdr;
3509 data.lpISP = This->dp2->spData.lpISP;
3511 (*This->dp2->spData.lpCB->CreateGroup)( &data );
3514 /* Inform all other peers of the creation of a new group. If there are
3515 * no peers keep this quiet.
3517 if( This->dp2->lpSessionDesc &&
3518 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
3520 DPMSG_CREATEPLAYERORGROUP msg;
3522 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
3523 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
3524 msg.dpId = *lpidGroup;
3525 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
3526 msg.lpData = lpData;
3527 msg.dwDataSize = dwDataSize;
3528 msg.dpnName = *lpGroupName;
3530 /* FIXME: Correct to just use send effectively? */
3531 /* FIXME: Should size include data w/ message or just message "header" */
3532 /* FIXME: Check return code */
3533 DP_SendEx( (IDirectPlay2Impl*)This,
3534 DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
3535 0, 0, NULL, NULL, bAnsi );
3538 return DP_OK;
3541 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3542 ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup,
3543 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3544 DWORD dwFlags )
3546 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3548 *lpidGroup = DPID_UNKNOWN;
3550 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3551 lpGroupName, lpData, dwDataSize, dwFlags,
3552 TRUE );
3555 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3556 ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup,
3557 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3558 DWORD dwFlags )
3560 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3562 *lpidGroup = DPID_UNKNOWN;
3564 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3565 lpGroupName, lpData, dwDataSize,
3566 dwFlags, FALSE );
3569 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
3570 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3572 lpGroupList lpGList;
3573 lpGroupData lpGParentData;
3575 TRACE("(%p)->(0x%08x,0x%08x)\n", This, idParentGroup, idGroup );
3577 /* Is the parent group valid? */
3578 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3580 return DPERR_INVALIDGROUP;
3583 /* Remove the group from the parent group queue */
3584 DPQ_REMOVE_ENTRY( lpGParentData->groups, groups, lpGData->dpid, ==, idGroup, lpGList );
3586 if( lpGList == NULL )
3588 return DPERR_INVALIDGROUP;
3591 /* Decrement the ref count */
3592 lpGList->lpGData->uRef--;
3594 /* Free up the list item */
3595 HeapFree( GetProcessHeap(), 0, lpGList );
3597 /* Should send a DELETEGROUPFROMGROUP message */
3598 FIXME( "message not sent\n" );
3600 return DP_OK;
3603 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3604 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3606 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3607 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3610 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3611 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3613 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3614 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3617 static
3618 BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
3619 LPDWORD lpdwBufSize )
3621 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3622 HRESULT hr;
3624 dpCompoundAddress.dwDataSize = sizeof( GUID );
3625 dpCompoundAddress.guidDataType = DPAID_ServiceProvider;
3626 dpCompoundAddress.lpData = lpcSpGuid;
3628 *lplpAddrBuf = NULL;
3629 *lpdwBufSize = 0;
3631 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3632 lpdwBufSize, TRUE );
3634 if( hr != DPERR_BUFFERTOOSMALL )
3636 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3637 return FALSE;
3640 /* Now allocate the buffer */
3641 *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3642 *lpdwBufSize );
3644 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3645 lpdwBufSize, TRUE );
3646 if( FAILED(hr) )
3648 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3649 return FALSE;
3652 return TRUE;
3655 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
3656 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3658 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3659 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3661 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
3662 if( dwFlags == 0 )
3664 dwFlags = DPCONNECTION_DIRECTPLAY;
3667 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
3668 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) )
3671 return DPERR_INVALIDFLAGS;
3674 if( !lpEnumCallback )
3676 return DPERR_INVALIDPARAMS;
3679 /* Enumerate DirectPlay service providers */
3680 if( dwFlags & DPCONNECTION_DIRECTPLAY )
3682 HKEY hkResult;
3683 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3684 LPCSTR guidDataSubKey = "Guid";
3685 char subKeyName[51];
3686 DWORD dwIndex, sizeOfSubKeyName=50;
3687 FILETIME filetime;
3689 /* Need to loop over the service providers in the registry */
3690 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3691 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3693 /* Hmmm. Does this mean that there are no service providers? */
3694 ERR(": no service providers?\n");
3695 return DP_OK;
3699 /* Traverse all the service providers we have available */
3700 for( dwIndex=0;
3701 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3702 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3703 ++dwIndex, sizeOfSubKeyName=51 )
3706 HKEY hkServiceProvider;
3707 GUID serviceProviderGUID;
3708 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3709 char returnBuffer[51];
3710 WCHAR buff[51];
3711 DPNAME dpName;
3712 BOOL bBuildPass;
3714 LPVOID lpAddressBuffer = NULL;
3715 DWORD dwAddressBufferSize = 0;
3717 TRACE(" this time through: %s\n", subKeyName );
3719 /* Get a handle for this particular service provider */
3720 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3721 &hkServiceProvider ) != ERROR_SUCCESS )
3723 ERR(": what the heck is going on?\n" );
3724 continue;
3727 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3728 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
3729 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3731 ERR(": missing GUID registry data members\n" );
3732 RegCloseKey(hkServiceProvider);
3733 continue;
3735 RegCloseKey(hkServiceProvider);
3737 /* FIXME: Check return types to ensure we're interpreting data right */
3738 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3739 CLSIDFromString( buff, &serviceProviderGUID );
3740 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3742 /* Fill in the DPNAME struct for the service provider */
3743 dpName.dwSize = sizeof( dpName );
3744 dpName.dwFlags = 0;
3745 dpName.u1.lpszShortNameA = subKeyName;
3746 dpName.u2.lpszLongNameA = NULL;
3748 /* Create the compound address for the service provider.
3749 * NOTE: This is a gruesome architectural scar right now. DP
3750 * uses DPL and DPL uses DP. Nasty stuff. This may be why the
3751 * native dll just gets around this little bit by allocating an
3752 * 80 byte buffer which isn't even filled with a valid compound
3753 * address. Oh well. Creating a proper compound address is the
3754 * way to go anyways despite this method taking slightly more
3755 * heap space and realtime :) */
3757 bBuildPass = DP_BuildSPCompoundAddr( &serviceProviderGUID,
3758 &lpAddressBuffer,
3759 &dwAddressBufferSize );
3760 if( !bBuildPass )
3762 ERR( "Can't build compound addr\n" );
3763 return DPERR_GENERIC;
3766 /* The enumeration will return FALSE if we are not to continue */
3767 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3768 &dpName, dwFlags, lpContext ) )
3770 return DP_OK;
3775 /* Enumerate DirectPlayLobby service providers */
3776 if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY )
3778 HKEY hkResult;
3779 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3780 LPCSTR guidDataSubKey = "Guid";
3781 char subKeyName[51];
3782 DWORD dwIndex, sizeOfSubKeyName=50;
3783 FILETIME filetime;
3785 /* Need to loop over the service providers in the registry */
3786 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3787 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3789 /* Hmmm. Does this mean that there are no service providers? */
3790 ERR(": no service providers?\n");
3791 return DP_OK;
3795 /* Traverse all the lobby providers we have available */
3796 for( dwIndex=0;
3797 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3798 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3799 ++dwIndex, sizeOfSubKeyName=51 )
3802 HKEY hkServiceProvider;
3803 GUID serviceProviderGUID;
3804 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3805 char returnBuffer[51];
3806 WCHAR buff[51];
3807 DPNAME dpName;
3808 HRESULT hr;
3810 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3811 LPVOID lpAddressBuffer = NULL;
3812 DWORD dwAddressBufferSize = 0;
3814 TRACE(" this time through: %s\n", subKeyName );
3816 /* Get a handle for this particular service provider */
3817 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3818 &hkServiceProvider ) != ERROR_SUCCESS )
3820 ERR(": what the heck is going on?\n" );
3821 continue;
3824 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3825 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
3826 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3828 ERR(": missing GUID registry data members\n" );
3829 RegCloseKey(hkServiceProvider);
3830 continue;
3832 RegCloseKey(hkServiceProvider);
3834 /* FIXME: Check return types to ensure we're interpreting data right */
3835 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3836 CLSIDFromString( buff, &serviceProviderGUID );
3837 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3839 /* Fill in the DPNAME struct for the service provider */
3840 dpName.dwSize = sizeof( dpName );
3841 dpName.dwFlags = 0;
3842 dpName.u1.lpszShortNameA = subKeyName;
3843 dpName.u2.lpszLongNameA = NULL;
3845 /* Create the compound address for the service provider.
3846 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
3847 nast stuff. This may be why the native dll just gets around this little bit by
3848 allocating an 80 byte buffer which isn't even a filled with a valid compound
3849 address. Oh well. Creating a proper compound address is the way to go anyways
3850 despite this method taking slightly more heap space and realtime :) */
3852 dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
3853 dpCompoundAddress.dwDataSize = sizeof( GUID );
3854 dpCompoundAddress.lpData = &serviceProviderGUID;
3856 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3857 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
3859 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3860 return hr;
3863 /* Now allocate the buffer */
3864 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
3866 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3867 &dwAddressBufferSize, TRUE ) ) != DP_OK )
3869 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3870 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
3871 return hr;
3874 /* The enumeration will return FALSE if we are not to continue */
3875 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3876 &dpName, dwFlags, lpContext ) )
3878 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
3879 return DP_OK;
3881 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
3885 return DP_OK;
3888 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
3889 ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3891 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3892 FIXME("(%p)->(%p,%p,%p,0x%08x): stub\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3893 return DP_OK;
3896 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
3897 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
3898 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
3899 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
3901 lpGroupList lpGList;
3902 lpGroupData lpGData;
3904 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
3905 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
3906 lpContext, dwFlags, bAnsi );
3908 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3910 return DPERR_INVALIDGROUP;
3913 if( DPQ_IS_EMPTY( lpGData->groups ) )
3915 return DP_OK;
3918 lpGList = DPQ_FIRST( lpGData->groups );
3920 for( ;; )
3922 /* FIXME: Should check dwFlags for match here */
3924 if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP,
3925 &lpGList->lpGData->name, dwFlags,
3926 lpContext ) )
3928 return DP_OK; /* User requested break */
3931 if( DPQ_IS_ENDOFLIST( lpGList->groups ) )
3933 break;
3936 lpGList = DPQ_NEXT( lpGList->groups );
3940 return DP_OK;
3943 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
3944 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3945 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3946 DWORD dwFlags )
3948 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3949 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3950 lpEnumPlayersCallback2, lpContext, dwFlags,
3951 TRUE );
3954 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
3955 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3956 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3957 DWORD dwFlags )
3959 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3960 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3961 lpEnumPlayersCallback2, lpContext, dwFlags,
3962 FALSE );
3965 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
3966 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3968 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3969 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3970 return DP_OK;
3973 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
3974 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3976 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3977 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3978 return DP_OK;
3981 static BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
3982 REFGUID guidDataType,
3983 DWORD dwDataSize,
3984 LPCVOID lpData,
3985 LPVOID lpContext )
3987 /* Looking for the GUID of the provider to load */
3988 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
3989 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
3992 TRACE( "Found SP/LP (%s) %s (data size = 0x%08x)\n",
3993 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
3995 if( dwDataSize != sizeof( GUID ) )
3997 ERR( "Invalid sp/lp guid size 0x%08x\n", dwDataSize );
4000 memcpy( lpContext, lpData, dwDataSize );
4002 /* There shouldn't be more than 1 GUID/compound address */
4003 return FALSE;
4006 /* Still waiting for what we want */
4007 return TRUE;
4011 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
4012 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
4014 UINT i;
4015 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4016 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
4017 LPCSTR guidDataSubKey = "Guid";
4018 LPCSTR majVerDataSubKey = "dwReserved1";
4019 LPCSTR minVerDataSubKey = "dwReserved2";
4020 LPCSTR pathSubKey = "Path";
4022 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
4024 /* FIXME: Cloned code with a quick hack. */
4025 for( i=0; i<2; i++ )
4027 HKEY hkResult;
4028 LPCSTR searchSubKey;
4029 char subKeyName[51];
4030 DWORD dwIndex, sizeOfSubKeyName=50;
4031 FILETIME filetime;
4033 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
4034 *lpbIsDpSp = (i == 0) ? TRUE : FALSE;
4037 /* Need to loop over the service providers in the registry */
4038 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4039 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4041 /* Hmmm. Does this mean that there are no service providers? */
4042 ERR(": no service providers?\n");
4043 return 0;
4046 /* Traverse all the service providers we have available */
4047 for( dwIndex=0;
4048 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4049 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4050 ++dwIndex, sizeOfSubKeyName=51 )
4053 HKEY hkServiceProvider;
4054 GUID serviceProviderGUID;
4055 DWORD returnType, sizeOfReturnBuffer = 255;
4056 char returnBuffer[256];
4057 WCHAR buff[51];
4058 DWORD dwTemp, len;
4060 TRACE(" this time through: %s\n", subKeyName );
4062 /* Get a handle for this particular service provider */
4063 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4064 &hkServiceProvider ) != ERROR_SUCCESS )
4066 ERR(": what the heck is going on?\n" );
4067 continue;
4070 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4071 NULL, &returnType, (LPBYTE)returnBuffer,
4072 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4074 ERR(": missing GUID registry data members\n" );
4075 continue;
4078 /* FIXME: Check return types to ensure we're interpreting data right */
4079 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4080 CLSIDFromString( buff, &serviceProviderGUID );
4081 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4083 /* Determine if this is the Service Provider that the user asked for */
4084 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
4086 continue;
4089 if( i == 0 ) /* DP SP */
4091 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
4092 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
4093 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
4096 sizeOfReturnBuffer = 255;
4098 /* Get dwReserved1 */
4099 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
4100 NULL, &returnType, (LPBYTE)returnBuffer,
4101 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4103 ERR(": missing dwReserved1 registry data members\n") ;
4104 continue;
4107 if( i == 0 )
4108 memcpy( &lpSpData->dwReserved1, returnBuffer, sizeof(lpSpData->dwReserved1) );
4110 sizeOfReturnBuffer = 255;
4112 /* Get dwReserved2 */
4113 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4114 NULL, &returnType, (LPBYTE)returnBuffer,
4115 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4117 ERR(": missing dwReserved1 registry data members\n") ;
4118 continue;
4121 if( i == 0 )
4122 memcpy( &lpSpData->dwReserved2, returnBuffer, sizeof(lpSpData->dwReserved2) );
4124 sizeOfReturnBuffer = 255;
4126 /* Get the path for this service provider */
4127 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
4128 NULL, NULL, (LPBYTE)returnBuffer,
4129 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
4131 ERR(": missing PATH registry data members: 0x%08x\n", dwTemp );
4132 continue;
4135 TRACE( "Loading %s\n", returnBuffer );
4136 return LoadLibraryA( returnBuffer );
4140 return 0;
4143 static
4144 HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider )
4146 HRESULT hr;
4147 LPDPSP_SPINIT SPInit;
4149 /* Initialize the service provider by calling SPInit */
4150 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4152 if( SPInit == NULL )
4154 ERR( "Service provider doesn't provide SPInit interface?\n" );
4155 FreeLibrary( hServiceProvider );
4156 return DPERR_UNAVAILABLE;
4159 TRACE( "Calling SPInit (DP SP entry point)\n" );
4161 hr = (*SPInit)( &This->dp2->spData );
4163 if( FAILED(hr) )
4165 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4166 FreeLibrary( hServiceProvider );
4167 return hr;
4170 /* FIXME: Need to verify the sanity of the returned callback table
4171 * using IsBadCodePtr */
4172 This->dp2->bSPInitialized = TRUE;
4174 /* This interface is now initialized as a DP object */
4175 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
4177 /* Store the handle of the module so that we can unload it later */
4178 This->dp2->hServiceProvider = hServiceProvider;
4180 return hr;
4183 static
4184 HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hLobbyProvider )
4186 HRESULT hr;
4187 LPSP_INIT DPLSPInit;
4189 /* Initialize the service provider by calling SPInit */
4190 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
4192 if( DPLSPInit == NULL )
4194 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4195 FreeLibrary( hLobbyProvider );
4196 return DPERR_UNAVAILABLE;
4199 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4201 hr = (*DPLSPInit)( &This->dp2->dplspData );
4203 if( FAILED(hr) )
4205 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4206 FreeLibrary( hLobbyProvider );
4207 return hr;
4210 /* FIXME: Need to verify the sanity of the returned callback table
4211 * using IsBadCodePtr */
4213 This->dp2->bDPLSPInitialized = TRUE;
4215 /* This interface is now initialized as a lobby object */
4216 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
4218 /* Store the handle of the module so that we can unload it later */
4219 This->dp2->hDPLobbyProvider = hLobbyProvider;
4221 return hr;
4224 static HRESULT WINAPI DP_IF_InitializeConnection
4225 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi )
4227 HMODULE hServiceProvider;
4228 HRESULT hr;
4229 GUID guidSP;
4230 const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
4231 BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4233 TRACE("(%p)->(%p,0x%08x,%u)\n", This, lpConnection, dwFlags, bAnsi );
4235 if ( lpConnection == NULL )
4237 return DPERR_INVALIDPARAMS;
4240 if( dwFlags != 0 )
4242 return DPERR_INVALIDFLAGS;
4245 if( This->dp2->connectionInitialized != NO_PROVIDER )
4247 return DPERR_ALREADYINITIALIZED;
4250 /* Find out what the requested SP is and how large this buffer is */
4251 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
4252 dwAddrSize, &guidSP );
4254 if( FAILED(hr) )
4256 ERR( "Invalid compound address?\n" );
4257 return DPERR_UNAVAILABLE;
4260 /* Load the service provider */
4261 hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp );
4263 if( hServiceProvider == 0 )
4265 ERR( "Unable to load service provider %s\n", debugstr_guid(&guidSP) );
4266 return DPERR_UNAVAILABLE;
4269 if( bIsDpSp )
4271 /* Fill in what we can of the Service Provider required information.
4272 * The rest was be done in DP_LoadSP
4274 This->dp2->spData.lpAddress = lpConnection;
4275 This->dp2->spData.dwAddressSize = dwAddrSize;
4276 This->dp2->spData.lpGuid = &guidSP;
4278 hr = DP_InitializeDPSP( This, hServiceProvider );
4280 else
4282 This->dp2->dplspData.lpAddress = lpConnection;
4284 hr = DP_InitializeDPLSP( This, hServiceProvider );
4287 if( FAILED(hr) )
4289 return hr;
4292 return DP_OK;
4295 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4296 ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
4298 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4300 /* This may not be externally invoked once either an SP or LP is initialized */
4301 if( This->dp2->connectionInitialized != NO_PROVIDER )
4303 return DPERR_ALREADYINITIALIZED;
4306 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE );
4309 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4310 ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
4312 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4314 /* This may not be externally invoked once either an SP or LP is initialized */
4315 if( This->dp2->connectionInitialized != NO_PROVIDER )
4317 return DPERR_ALREADYINITIALIZED;
4320 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE );
4323 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4324 ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4325 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4327 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4328 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4331 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4332 ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4333 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4335 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4336 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4339 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4340 ( LPDIRECTPLAY3A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4342 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4343 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4344 return DP_OK;
4347 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4348 ( LPDIRECTPLAY3 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4350 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4351 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4352 return DP_OK;
4355 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4356 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4358 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4359 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4360 return DP_OK;
4363 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4364 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4366 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4367 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4368 return DP_OK;
4371 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4372 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup )
4374 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4375 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, dwFlags, idGroup );
4376 return DP_OK;
4379 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4380 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup )
4382 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4383 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, dwFlags, idGroup );
4384 return DP_OK;
4387 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4388 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDWORD lpdwFlags )
4390 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4391 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpdwFlags );
4392 return DP_OK;
4395 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4396 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDWORD lpdwFlags )
4398 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4399 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpdwFlags );
4400 return DP_OK;
4403 static HRESULT WINAPI DP_IF_GetGroupParent
4404 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
4405 BOOL bAnsi )
4407 lpGroupData lpGData;
4409 TRACE("(%p)->(0x%08x,%p,%u)\n", This, idGroup, lpidGroup, bAnsi );
4411 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4413 return DPERR_INVALIDGROUP;
4416 *lpidGroup = lpGData->dpid;
4418 return DP_OK;
4421 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4422 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
4424 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4425 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE );
4427 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4428 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
4430 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4431 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE );
4434 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4435 ( LPDIRECTPLAY3A iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4437 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4438 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4439 return DP_OK;
4442 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4443 ( LPDIRECTPLAY3 iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4445 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4446 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4447 return DP_OK;
4450 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4451 ( LPDIRECTPLAY3A iface, DPID idPlayer, LPDWORD lpdwFlags )
4453 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4454 FIXME("(%p)->(0x%08x,%p): stub\n", This, idPlayer, lpdwFlags );
4455 return DP_OK;
4458 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4459 ( LPDIRECTPLAY3 iface, DPID idPlayer, LPDWORD lpdwFlags )
4461 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4462 FIXME("(%p)->(0x%08x,%p): stub\n", This, idPlayer, lpdwFlags );
4463 return DP_OK;
4466 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4467 ( LPDIRECTPLAY4A iface, DPID idGroup, LPDPID lpidGroupOwner )
4469 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4470 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpidGroupOwner );
4471 return DP_OK;
4474 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4475 ( LPDIRECTPLAY4 iface, DPID idGroup, LPDPID lpidGroupOwner )
4477 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4478 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpidGroupOwner );
4479 return DP_OK;
4482 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4483 ( LPDIRECTPLAY4A iface, DPID idGroup , DPID idGroupOwner )
4485 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4486 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, idGroup, idGroupOwner );
4487 return DP_OK;
4490 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4491 ( LPDIRECTPLAY4 iface, DPID idGroup , DPID idGroupOwner )
4493 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4494 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, idGroup, idGroupOwner );
4495 return DP_OK;
4498 static HRESULT WINAPI DP_SendEx
4499 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4500 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4501 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi )
4503 BOOL bValidDestination = FALSE;
4505 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,0x%08x,0x%08x,0x%08x,%p,%p,%u)"
4506 ": stub\n",
4507 This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority,
4508 dwTimeout, lpContext, lpdwMsgID, bAnsi );
4510 /* FIXME: Add parameter checking */
4511 /* FIXME: First call to this needs to acquire a message id which will be
4512 * used for multiple sends
4515 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4517 /* Verify that the message is being sent from a valid local player. The
4518 * from player may be anonymous DPID_UNKNOWN
4520 if( idFrom != DPID_UNKNOWN )
4522 if( DP_FindPlayer( This, idFrom ) == NULL )
4524 WARN( "INFO: Invalid from player 0x%08x\n", idFrom );
4525 return DPERR_INVALIDPLAYER;
4529 /* Verify that the message is being sent to a valid player, group or to
4530 * everyone. If it's valid, send it to those players.
4532 if( idTo == DPID_ALLPLAYERS )
4534 bValidDestination = TRUE;
4536 /* See if SP has the ability to multicast. If so, use it */
4537 if( This->dp2->spData.lpCB->SendToGroupEx )
4539 FIXME( "Use group sendex to group 0\n" );
4541 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4543 FIXME( "Use obsolete group send to group 0\n" );
4545 else /* No multicast, multiplicate */
4547 /* Send to all players we know about */
4548 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4552 if( ( !bValidDestination ) &&
4553 ( DP_FindPlayer( This, idTo ) != NULL )
4556 bValidDestination = TRUE;
4558 /* Have the service provider send this message */
4559 /* FIXME: Could optimize for local interface sends */
4560 return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority,
4561 dwTimeout, lpContext, lpdwMsgID );
4564 if( ( !bValidDestination ) &&
4565 ( DP_FindAnyGroup( This, idTo ) != NULL )
4568 bValidDestination = TRUE;
4570 /* See if SP has the ability to multicast. If so, use it */
4571 if( This->dp2->spData.lpCB->SendToGroupEx )
4573 FIXME( "Use group sendex\n" );
4575 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4577 FIXME( "Use obsolete group send to group\n" );
4579 else /* No multicast, multiplicate */
4581 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4584 #if 0
4585 if( bExpectReply )
4587 DWORD dwWaitReturn;
4589 This->dp2->hReplyEvent = CreateEventW( NULL, FALSE, FALSE, NULL );
4591 dwWaitReturn = WaitForSingleObject( hReplyEvent, dwTimeout );
4592 if( dwWaitReturn != WAIT_OBJECT_0 )
4594 ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
4597 #endif
4600 if( !bValidDestination )
4602 return DPERR_INVALIDPLAYER;
4604 else
4606 /* FIXME: Should return what the send returned */
4607 return DP_OK;
4612 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4613 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4614 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4615 LPVOID lpContext, LPDWORD lpdwMsgID )
4617 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4618 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4619 dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE );
4622 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4623 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4624 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4625 LPVOID lpContext, LPDWORD lpdwMsgID )
4627 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4628 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4629 dwPriority, dwTimeout, lpContext, lpdwMsgID, FALSE );
4632 static HRESULT WINAPI DP_SP_SendEx
4633 ( IDirectPlay2Impl* This, DWORD dwFlags,
4634 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4635 LPVOID lpContext, LPDWORD lpdwMsgID )
4637 LPDPMSG lpMElem;
4639 FIXME( ": stub\n" );
4641 /* FIXME: This queuing should only be for async messages */
4643 lpMElem = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpMElem ) );
4644 lpMElem->msg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
4646 CopyMemory( lpMElem->msg, lpData, dwDataSize );
4648 /* FIXME: Need to queue based on priority */
4649 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
4651 return DP_OK;
4654 static HRESULT WINAPI DP_IF_GetMessageQueue
4655 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4656 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi )
4658 HRESULT hr = DP_OK;
4660 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%p,%u): semi stub\n",
4661 This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi );
4663 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4664 /* FIXME: What about sends which are not immediate? */
4666 if( This->dp2->spData.lpCB->GetMessageQueue )
4668 DPSP_GETMESSAGEQUEUEDATA data;
4670 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4672 /* FIXME: None of this is documented :( */
4674 data.lpISP = This->dp2->spData.lpISP;
4675 data.dwFlags = dwFlags;
4676 data.idFrom = idFrom;
4677 data.idTo = idTo;
4678 data.lpdwNumMsgs = lpdwNumMsgs;
4679 data.lpdwNumBytes = lpdwNumBytes;
4681 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
4683 else
4685 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4688 return hr;
4691 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4692 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4693 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4695 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4696 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4697 lpdwNumBytes, TRUE );
4700 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4701 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4702 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4704 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4705 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4706 lpdwNumBytes, FALSE );
4709 static HRESULT WINAPI DP_IF_CancelMessage
4710 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
4711 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi )
4713 HRESULT hr = DP_OK;
4715 FIXME( "(%p)->(0x%08x,0x%08x,%u): semi stub\n",
4716 This, dwMsgID, dwFlags, bAnsi );
4718 if( This->dp2->spData.lpCB->Cancel )
4720 DPSP_CANCELDATA data;
4722 TRACE( "Calling SP Cancel\n" );
4724 /* FIXME: Undocumented callback */
4726 data.lpISP = This->dp2->spData.lpISP;
4727 data.dwFlags = dwFlags;
4728 data.lprglpvSPMsgID = NULL;
4729 data.cSPMsgID = dwMsgID;
4730 data.dwMinPriority = dwMinPriority;
4731 data.dwMaxPriority = dwMaxPriority;
4733 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
4735 else
4737 FIXME( "SP doesn't implement Cancel\n" );
4740 return hr;
4743 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
4744 ( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags )
4746 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4748 if( dwFlags != 0 )
4750 return DPERR_INVALIDFLAGS;
4753 if( dwMsgID == 0 )
4755 dwFlags |= DPCANCELSEND_ALL;
4758 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE );
4761 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
4762 ( LPDIRECTPLAY4 iface, DWORD dwMsgID, DWORD dwFlags )
4764 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4766 if( dwFlags != 0 )
4768 return DPERR_INVALIDFLAGS;
4771 if( dwMsgID == 0 )
4773 dwFlags |= DPCANCELSEND_ALL;
4776 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, FALSE );
4779 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
4780 ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4781 DWORD dwFlags )
4783 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4785 if( dwFlags != 0 )
4787 return DPERR_INVALIDFLAGS;
4790 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4791 dwMaxPriority, TRUE );
4794 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
4795 ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4796 DWORD dwFlags )
4798 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4800 if( dwFlags != 0 )
4802 return DPERR_INVALIDFLAGS;
4805 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4806 dwMaxPriority, FALSE );
4809 /* Note: Hack so we can reuse the old functions without compiler warnings */
4810 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4811 # define XCAST(fun) (typeof(directPlay2WVT.fun))
4812 #else
4813 # define XCAST(fun) (void*)
4814 #endif
4816 static const IDirectPlay2Vtbl directPlay2WVT =
4818 XCAST(QueryInterface)DP_QueryInterface,
4819 XCAST(AddRef)DP_AddRef,
4820 XCAST(Release)DP_Release,
4822 DirectPlay2WImpl_AddPlayerToGroup,
4823 DirectPlay2WImpl_Close,
4824 DirectPlay2WImpl_CreateGroup,
4825 DirectPlay2WImpl_CreatePlayer,
4826 DirectPlay2WImpl_DeletePlayerFromGroup,
4827 DirectPlay2WImpl_DestroyGroup,
4828 DirectPlay2WImpl_DestroyPlayer,
4829 DirectPlay2WImpl_EnumGroupPlayers,
4830 DirectPlay2WImpl_EnumGroups,
4831 DirectPlay2WImpl_EnumPlayers,
4832 DirectPlay2WImpl_EnumSessions,
4833 DirectPlay2WImpl_GetCaps,
4834 DirectPlay2WImpl_GetGroupData,
4835 DirectPlay2WImpl_GetGroupName,
4836 DirectPlay2WImpl_GetMessageCount,
4837 DirectPlay2WImpl_GetPlayerAddress,
4838 DirectPlay2WImpl_GetPlayerCaps,
4839 DirectPlay2WImpl_GetPlayerData,
4840 DirectPlay2WImpl_GetPlayerName,
4841 DirectPlay2WImpl_GetSessionDesc,
4842 DirectPlay2WImpl_Initialize,
4843 DirectPlay2WImpl_Open,
4844 DirectPlay2WImpl_Receive,
4845 DirectPlay2WImpl_Send,
4846 DirectPlay2WImpl_SetGroupData,
4847 DirectPlay2WImpl_SetGroupName,
4848 DirectPlay2WImpl_SetPlayerData,
4849 DirectPlay2WImpl_SetPlayerName,
4850 DirectPlay2WImpl_SetSessionDesc
4852 #undef XCAST
4854 /* Note: Hack so we can reuse the old functions without compiler warnings */
4855 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4856 # define XCAST(fun) (typeof(directPlay2AVT.fun))
4857 #else
4858 # define XCAST(fun) (void*)
4859 #endif
4861 static const IDirectPlay2Vtbl directPlay2AVT =
4863 XCAST(QueryInterface)DP_QueryInterface,
4864 XCAST(AddRef)DP_AddRef,
4865 XCAST(Release)DP_Release,
4867 DirectPlay2AImpl_AddPlayerToGroup,
4868 DirectPlay2AImpl_Close,
4869 DirectPlay2AImpl_CreateGroup,
4870 DirectPlay2AImpl_CreatePlayer,
4871 DirectPlay2AImpl_DeletePlayerFromGroup,
4872 DirectPlay2AImpl_DestroyGroup,
4873 DirectPlay2AImpl_DestroyPlayer,
4874 DirectPlay2AImpl_EnumGroupPlayers,
4875 DirectPlay2AImpl_EnumGroups,
4876 DirectPlay2AImpl_EnumPlayers,
4877 DirectPlay2AImpl_EnumSessions,
4878 DirectPlay2AImpl_GetCaps,
4879 DirectPlay2AImpl_GetGroupData,
4880 DirectPlay2AImpl_GetGroupName,
4881 DirectPlay2AImpl_GetMessageCount,
4882 DirectPlay2AImpl_GetPlayerAddress,
4883 DirectPlay2AImpl_GetPlayerCaps,
4884 DirectPlay2AImpl_GetPlayerData,
4885 DirectPlay2AImpl_GetPlayerName,
4886 DirectPlay2AImpl_GetSessionDesc,
4887 DirectPlay2AImpl_Initialize,
4888 DirectPlay2AImpl_Open,
4889 DirectPlay2AImpl_Receive,
4890 DirectPlay2AImpl_Send,
4891 DirectPlay2AImpl_SetGroupData,
4892 DirectPlay2AImpl_SetGroupName,
4893 DirectPlay2AImpl_SetPlayerData,
4894 DirectPlay2AImpl_SetPlayerName,
4895 DirectPlay2AImpl_SetSessionDesc
4897 #undef XCAST
4900 /* Note: Hack so we can reuse the old functions without compiler warnings */
4901 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4902 # define XCAST(fun) (typeof(directPlay3AVT.fun))
4903 #else
4904 # define XCAST(fun) (void*)
4905 #endif
4907 static const IDirectPlay3Vtbl directPlay3AVT =
4909 XCAST(QueryInterface)DP_QueryInterface,
4910 XCAST(AddRef)DP_AddRef,
4911 XCAST(Release)DP_Release,
4913 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
4914 XCAST(Close)DirectPlay2AImpl_Close,
4915 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
4916 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
4917 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
4918 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
4919 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
4920 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
4921 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
4922 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
4923 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
4924 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
4925 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
4926 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
4927 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
4928 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
4929 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
4930 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
4931 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
4932 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
4933 XCAST(Initialize)DirectPlay2AImpl_Initialize,
4934 XCAST(Open)DirectPlay2AImpl_Open,
4935 XCAST(Receive)DirectPlay2AImpl_Receive,
4936 XCAST(Send)DirectPlay2AImpl_Send,
4937 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
4938 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
4939 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
4940 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
4941 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
4943 DirectPlay3AImpl_AddGroupToGroup,
4944 DirectPlay3AImpl_CreateGroupInGroup,
4945 DirectPlay3AImpl_DeleteGroupFromGroup,
4946 DirectPlay3AImpl_EnumConnections,
4947 DirectPlay3AImpl_EnumGroupsInGroup,
4948 DirectPlay3AImpl_GetGroupConnectionSettings,
4949 DirectPlay3AImpl_InitializeConnection,
4950 DirectPlay3AImpl_SecureOpen,
4951 DirectPlay3AImpl_SendChatMessage,
4952 DirectPlay3AImpl_SetGroupConnectionSettings,
4953 DirectPlay3AImpl_StartSession,
4954 DirectPlay3AImpl_GetGroupFlags,
4955 DirectPlay3AImpl_GetGroupParent,
4956 DirectPlay3AImpl_GetPlayerAccount,
4957 DirectPlay3AImpl_GetPlayerFlags
4959 #undef XCAST
4961 /* Note: Hack so we can reuse the old functions without compiler warnings */
4962 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4963 # define XCAST(fun) (typeof(directPlay3WVT.fun))
4964 #else
4965 # define XCAST(fun) (void*)
4966 #endif
4967 static const IDirectPlay3Vtbl directPlay3WVT =
4969 XCAST(QueryInterface)DP_QueryInterface,
4970 XCAST(AddRef)DP_AddRef,
4971 XCAST(Release)DP_Release,
4973 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
4974 XCAST(Close)DirectPlay2WImpl_Close,
4975 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
4976 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
4977 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
4978 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
4979 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
4980 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
4981 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
4982 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
4983 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
4984 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
4985 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
4986 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
4987 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
4988 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
4989 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
4990 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
4991 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
4992 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
4993 XCAST(Initialize)DirectPlay2WImpl_Initialize,
4994 XCAST(Open)DirectPlay2WImpl_Open,
4995 XCAST(Receive)DirectPlay2WImpl_Receive,
4996 XCAST(Send)DirectPlay2WImpl_Send,
4997 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
4998 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
4999 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5000 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5001 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5003 DirectPlay3WImpl_AddGroupToGroup,
5004 DirectPlay3WImpl_CreateGroupInGroup,
5005 DirectPlay3WImpl_DeleteGroupFromGroup,
5006 DirectPlay3WImpl_EnumConnections,
5007 DirectPlay3WImpl_EnumGroupsInGroup,
5008 DirectPlay3WImpl_GetGroupConnectionSettings,
5009 DirectPlay3WImpl_InitializeConnection,
5010 DirectPlay3WImpl_SecureOpen,
5011 DirectPlay3WImpl_SendChatMessage,
5012 DirectPlay3WImpl_SetGroupConnectionSettings,
5013 DirectPlay3WImpl_StartSession,
5014 DirectPlay3WImpl_GetGroupFlags,
5015 DirectPlay3WImpl_GetGroupParent,
5016 DirectPlay3WImpl_GetPlayerAccount,
5017 DirectPlay3WImpl_GetPlayerFlags
5019 #undef XCAST
5021 /* Note: Hack so we can reuse the old functions without compiler warnings */
5022 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5023 # define XCAST(fun) (typeof(directPlay4WVT.fun))
5024 #else
5025 # define XCAST(fun) (void*)
5026 #endif
5027 static const IDirectPlay4Vtbl directPlay4WVT =
5029 XCAST(QueryInterface)DP_QueryInterface,
5030 XCAST(AddRef)DP_AddRef,
5031 XCAST(Release)DP_Release,
5033 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
5034 XCAST(Close)DirectPlay2WImpl_Close,
5035 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
5036 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
5037 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
5038 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
5039 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5040 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5041 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5042 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5043 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5044 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5045 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5046 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5047 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5048 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5049 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5050 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5051 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5052 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5053 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5054 XCAST(Open)DirectPlay2WImpl_Open,
5055 XCAST(Receive)DirectPlay2WImpl_Receive,
5056 XCAST(Send)DirectPlay2WImpl_Send,
5057 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5058 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5059 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5060 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5061 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5063 XCAST(AddGroupToGroup)DirectPlay3WImpl_AddGroupToGroup,
5064 XCAST(CreateGroupInGroup)DirectPlay3WImpl_CreateGroupInGroup,
5065 XCAST(DeleteGroupFromGroup)DirectPlay3WImpl_DeleteGroupFromGroup,
5066 XCAST(EnumConnections)DirectPlay3WImpl_EnumConnections,
5067 XCAST(EnumGroupsInGroup)DirectPlay3WImpl_EnumGroupsInGroup,
5068 XCAST(GetGroupConnectionSettings)DirectPlay3WImpl_GetGroupConnectionSettings,
5069 XCAST(InitializeConnection)DirectPlay3WImpl_InitializeConnection,
5070 XCAST(SecureOpen)DirectPlay3WImpl_SecureOpen,
5071 XCAST(SendChatMessage)DirectPlay3WImpl_SendChatMessage,
5072 XCAST(SetGroupConnectionSettings)DirectPlay3WImpl_SetGroupConnectionSettings,
5073 XCAST(StartSession)DirectPlay3WImpl_StartSession,
5074 XCAST(GetGroupFlags)DirectPlay3WImpl_GetGroupFlags,
5075 XCAST(GetGroupParent)DirectPlay3WImpl_GetGroupParent,
5076 XCAST(GetPlayerAccount)DirectPlay3WImpl_GetPlayerAccount,
5077 XCAST(GetPlayerFlags)DirectPlay3WImpl_GetPlayerFlags,
5079 DirectPlay4WImpl_GetGroupOwner,
5080 DirectPlay4WImpl_SetGroupOwner,
5081 DirectPlay4WImpl_SendEx,
5082 DirectPlay4WImpl_GetMessageQueue,
5083 DirectPlay4WImpl_CancelMessage,
5084 DirectPlay4WImpl_CancelPriority
5086 #undef XCAST
5089 /* Note: Hack so we can reuse the old functions without compiler warnings */
5090 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5091 # define XCAST(fun) (typeof(directPlay4AVT.fun))
5092 #else
5093 # define XCAST(fun) (void*)
5094 #endif
5095 static const IDirectPlay4Vtbl directPlay4AVT =
5097 XCAST(QueryInterface)DP_QueryInterface,
5098 XCAST(AddRef)DP_AddRef,
5099 XCAST(Release)DP_Release,
5101 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
5102 XCAST(Close)DirectPlay2AImpl_Close,
5103 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
5104 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
5105 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
5106 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
5107 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
5108 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
5109 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
5110 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
5111 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
5112 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
5113 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
5114 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
5115 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5116 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5117 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5118 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5119 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5120 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5121 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5122 XCAST(Open)DirectPlay2AImpl_Open,
5123 XCAST(Receive)DirectPlay2AImpl_Receive,
5124 XCAST(Send)DirectPlay2AImpl_Send,
5125 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5126 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5127 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5128 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5129 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5131 XCAST(AddGroupToGroup)DirectPlay3AImpl_AddGroupToGroup,
5132 XCAST(CreateGroupInGroup)DirectPlay3AImpl_CreateGroupInGroup,
5133 XCAST(DeleteGroupFromGroup)DirectPlay3AImpl_DeleteGroupFromGroup,
5134 XCAST(EnumConnections)DirectPlay3AImpl_EnumConnections,
5135 XCAST(EnumGroupsInGroup)DirectPlay3AImpl_EnumGroupsInGroup,
5136 XCAST(GetGroupConnectionSettings)DirectPlay3AImpl_GetGroupConnectionSettings,
5137 XCAST(InitializeConnection)DirectPlay3AImpl_InitializeConnection,
5138 XCAST(SecureOpen)DirectPlay3AImpl_SecureOpen,
5139 XCAST(SendChatMessage)DirectPlay3AImpl_SendChatMessage,
5140 XCAST(SetGroupConnectionSettings)DirectPlay3AImpl_SetGroupConnectionSettings,
5141 XCAST(StartSession)DirectPlay3AImpl_StartSession,
5142 XCAST(GetGroupFlags)DirectPlay3AImpl_GetGroupFlags,
5143 XCAST(GetGroupParent)DirectPlay3AImpl_GetGroupParent,
5144 XCAST(GetPlayerAccount)DirectPlay3AImpl_GetPlayerAccount,
5145 XCAST(GetPlayerFlags)DirectPlay3AImpl_GetPlayerFlags,
5147 DirectPlay4AImpl_GetGroupOwner,
5148 DirectPlay4AImpl_SetGroupOwner,
5149 DirectPlay4AImpl_SendEx,
5150 DirectPlay4AImpl_GetMessageQueue,
5151 DirectPlay4AImpl_CancelMessage,
5152 DirectPlay4AImpl_CancelPriority
5154 #undef XCAST
5156 HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP,
5157 DPID idPlayer,
5158 LPVOID* lplpData )
5160 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5162 if( lpPlayer == NULL )
5164 return DPERR_INVALIDPLAYER;
5167 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
5169 return DP_OK;
5172 HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP,
5173 DPID idPlayer,
5174 LPVOID lpData )
5176 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5178 if( lpPlayer == NULL )
5180 return DPERR_INVALIDPLAYER;
5183 lpPlayer->lpPData->lpSPPlayerData = lpData;
5185 return DP_OK;
5188 /***************************************************************************
5189 * DirectPlayEnumerateAW
5191 * The pointer to the structure lpContext will be filled with the
5192 * appropriate data for each service offered by the OS. These services are
5193 * not necessarily available on this particular machine but are defined
5194 * as simple service providers under the "Service Providers" registry key.
5195 * This structure is then passed to lpEnumCallback for each of the different
5196 * services.
5198 * This API is useful only for applications written using DirectX3 or
5199 * worse. It is superseded by IDirectPlay3::EnumConnections which also
5200 * gives information on the actual connections.
5202 * defn of a service provider:
5203 * A dynamic-link library used by DirectPlay to communicate over a network.
5204 * The service provider contains all the network-specific code required
5205 * to send and receive messages. Online services and network operators can
5206 * supply service providers to use specialized hardware, protocols, communications
5207 * media, and network resources.
5210 static HRESULT DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA,
5211 LPDPENUMDPCALLBACKW lpEnumCallbackW,
5212 LPVOID lpContext)
5214 HKEY hkResult;
5215 static const WCHAR searchSubKey[] = {
5216 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
5217 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
5218 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
5219 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
5220 static const WCHAR guidKey[] = { 'G', 'u', 'i', 'd', 0 };
5221 static const WCHAR descW[] = { 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', 'W', 0 };
5223 DWORD dwIndex;
5224 FILETIME filetime;
5226 char *descriptionA = NULL;
5227 DWORD max_sizeOfDescriptionA = 0;
5228 WCHAR *descriptionW = NULL;
5229 DWORD max_sizeOfDescriptionW = 0;
5231 if (!lpEnumCallbackA && !lpEnumCallbackW)
5233 return DPERR_INVALIDPARAMS;
5236 /* Need to loop over the service providers in the registry */
5237 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, searchSubKey,
5238 0, KEY_READ, &hkResult) != ERROR_SUCCESS)
5240 /* Hmmm. Does this mean that there are no service providers? */
5241 ERR(": no service provider key in the registry - check your Wine installation !!!\n");
5242 return DPERR_GENERIC;
5245 /* Traverse all the service providers we have available */
5246 dwIndex = 0;
5247 while (1)
5249 WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */
5250 DWORD sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR);
5251 HKEY hkServiceProvider;
5252 GUID serviceProviderGUID;
5253 WCHAR guidKeyContent[(2 * 16) + 1 + 6 /* This corresponds to '{....-..-..-..-......}' */ ];
5254 DWORD sizeOfGuidKeyContent = sizeof(guidKeyContent);
5255 LONG ret_value;
5257 ret_value = RegEnumKeyExW(hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
5258 NULL, NULL, NULL, &filetime);
5259 if (ret_value == ERROR_NO_MORE_ITEMS)
5260 break;
5261 else if (ret_value != ERROR_SUCCESS)
5263 ERR(": could not enumerate on service provider key.\n");
5264 return DPERR_EXCEPTION;
5266 TRACE(" this time through sub-key %s.\n", debugstr_w(subKeyName));
5268 /* Open the key for this service provider */
5269 if (RegOpenKeyExW(hkResult, subKeyName, 0, KEY_READ, &hkServiceProvider) != ERROR_SUCCESS)
5271 ERR(": could not open registry key for service provider %s.\n", debugstr_w(subKeyName));
5272 continue;
5275 /* Get the GUID from the registry */
5276 if (RegQueryValueExW(hkServiceProvider, guidKey,
5277 NULL, NULL, (LPBYTE) guidKeyContent, &sizeOfGuidKeyContent) != ERROR_SUCCESS)
5279 ERR(": missing GUID registry data member for service provider %s.\n", debugstr_w(subKeyName));
5280 continue;
5282 if (sizeOfGuidKeyContent != sizeof(guidKeyContent))
5284 ERR(": invalid format for the GUID registry data member for service provider %s (%s).\n", debugstr_w(subKeyName), debugstr_w(guidKeyContent));
5285 continue;
5287 CLSIDFromString(guidKeyContent, &serviceProviderGUID );
5289 /* The enumeration will return FALSE if we are not to continue.
5291 * Note: on my windows box, major / minor version is 6 / 0 for all service providers
5292 * and have no relation to any of the two dwReserved1 and dwReserved2 keys.
5293 * I think that it simply means that they are in-line with DirectX 6.0
5295 if (lpEnumCallbackA)
5297 DWORD sizeOfDescription = 0;
5299 /* Note that this is the A case of this function, so use the A variant to get the description string */
5300 if (RegQueryValueExA(hkServiceProvider, "DescriptionA",
5301 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5303 ERR(": missing 'DescriptionA' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5304 continue;
5306 if (sizeOfDescription > max_sizeOfDescriptionA)
5308 HeapFree(GetProcessHeap(), 0, descriptionA);
5309 max_sizeOfDescriptionA = sizeOfDescription;
5311 descriptionA = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5312 RegQueryValueExA(hkServiceProvider, "DescriptionA",
5313 NULL, NULL, (LPBYTE) descriptionA, &sizeOfDescription);
5315 if (!lpEnumCallbackA(&serviceProviderGUID, descriptionA, 6, 0, lpContext))
5316 goto end;
5318 else
5320 DWORD sizeOfDescription = 0;
5322 if (RegQueryValueExW(hkServiceProvider, descW,
5323 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5325 ERR(": missing 'DescriptionW' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5326 continue;
5328 if (sizeOfDescription > max_sizeOfDescriptionW)
5330 HeapFree(GetProcessHeap(), 0, descriptionW);
5331 max_sizeOfDescriptionW = sizeOfDescription;
5333 descriptionW = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5334 RegQueryValueExW(hkServiceProvider, descW,
5335 NULL, NULL, (LPBYTE) descriptionW, &sizeOfDescription);
5337 if (!lpEnumCallbackW(&serviceProviderGUID, descriptionW, 6, 0, lpContext))
5338 goto end;
5341 dwIndex++;
5344 end:
5345 HeapFree(GetProcessHeap(), 0, descriptionA);
5346 HeapFree(GetProcessHeap(), 0, descriptionW);
5348 return DP_OK;
5351 /***************************************************************************
5352 * DirectPlayEnumerate [DPLAYX.9]
5353 * DirectPlayEnumerateA [DPLAYX.2]
5355 HRESULT WINAPI DirectPlayEnumerateA(LPDPENUMDPCALLBACKA lpEnumCallback, LPVOID lpContext )
5357 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5359 return DirectPlayEnumerateAW(lpEnumCallback, NULL, lpContext);
5362 /***************************************************************************
5363 * DirectPlayEnumerateW [DPLAYX.3]
5365 HRESULT WINAPI DirectPlayEnumerateW(LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5367 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5369 return DirectPlayEnumerateAW(NULL, lpEnumCallback, lpContext);
5372 typedef struct tagCreateEnum
5374 LPVOID lpConn;
5375 LPCGUID lpGuid;
5376 } CreateEnumData, *lpCreateEnumData;
5378 /* Find and copy the matching connection for the SP guid */
5379 static BOOL CALLBACK cbDPCreateEnumConnections(
5380 LPCGUID lpguidSP,
5381 LPVOID lpConnection,
5382 DWORD dwConnectionSize,
5383 LPCDPNAME lpName,
5384 DWORD dwFlags,
5385 LPVOID lpContext)
5387 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5389 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5391 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5393 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5394 dwConnectionSize );
5395 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5397 /* Found the record that we were looking for */
5398 return FALSE;
5401 /* Haven't found what were looking for yet */
5402 return TRUE;
5406 /***************************************************************************
5407 * DirectPlayCreate [DPLAYX.1]
5410 HRESULT WINAPI DirectPlayCreate
5411 ( LPGUID lpGUID, LPDIRECTPLAY *lplpDP, IUnknown *pUnk )
5413 HRESULT hr;
5414 LPDIRECTPLAY3A lpDP3A;
5415 CreateEnumData cbData;
5417 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5419 if( pUnk != NULL )
5421 return CLASS_E_NOAGGREGATION;
5424 if( (lplpDP == NULL) || (lpGUID == NULL) )
5426 return DPERR_INVALIDPARAMS;
5430 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5431 give them an IDirectPlay2A object and hope that doesn't cause problems */
5432 if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
5434 return DPERR_UNAVAILABLE;
5437 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
5439 /* The GUID_NULL means don't bind a service provider. Just return the
5440 interface as is */
5441 return DP_OK;
5444 /* Bind the desired service provider since lpGUID is non NULL */
5445 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
5447 /* We're going to use a DP3 interface */
5448 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
5449 (LPVOID*)&lpDP3A );
5450 if( FAILED(hr) )
5452 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
5453 return hr;
5456 cbData.lpConn = NULL;
5457 cbData.lpGuid = lpGUID;
5459 /* We were given a service provider, find info about it... */
5460 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
5461 &cbData, DPCONNECTION_DIRECTPLAY );
5462 if( ( FAILED(hr) ) ||
5463 ( cbData.lpConn == NULL )
5466 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
5467 IDirectPlayX_Release( lpDP3A );
5468 return DPERR_UNAVAILABLE;
5471 /* Initialize the service provider */
5472 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
5473 if( FAILED(hr) )
5475 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
5476 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5477 IDirectPlayX_Release( lpDP3A );
5478 return hr;
5481 /* Release our version of the interface now that we're done with it */
5482 IDirectPlayX_Release( lpDP3A );
5483 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5485 return DP_OK;