dplay: Directplay should initialize session Guid, with conformance tests.
[wine/multimedia.git] / dlls / dplayx / dplay.c
blob3ca90db937ee5c93f7cf0a36444d0328490c2e49
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 "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, LPDPNAME lpSrc, BOOL bAnsi );
58 static void DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
59 LPVOID lpData, DWORD dwDataSize );
61 static lpGroupData DP_CreateGroup( IDirectPlay2AImpl* iface, LPDPID lpid,
62 LPDPNAME 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 );
247 return TRUE;
250 static BOOL DP_DestroyIUnknown( LPVOID lpDP )
252 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;
254 DeleteCriticalSection( &This->unk->DP_lock );
255 HeapFree( GetProcessHeap(), 0, This->unk );
257 return TRUE;
260 static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
262 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;
264 This->dp2 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp2) ) );
265 if ( This->dp2 == NULL )
267 return FALSE;
270 This->dp2->bConnectionOpen = FALSE;
272 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
274 This->dp2->bHostInterface = FALSE;
276 DPQ_INIT(This->dp2->receiveMsgs);
277 DPQ_INIT(This->dp2->sendMsgs);
278 DPQ_INIT(This->dp2->replysExpected);
280 if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
282 /* FIXME: Memory leak */
283 return FALSE;
286 /* Provide an initial session desc with nothing in it */
287 This->dp2->lpSessionDesc = HeapAlloc( GetProcessHeap(),
288 HEAP_ZERO_MEMORY,
289 sizeof( *This->dp2->lpSessionDesc ) );
290 if( This->dp2->lpSessionDesc == NULL )
292 /* FIXME: Memory leak */
293 return FALSE;
295 This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc );
297 /* We are emulating a dp 6 implementation */
298 This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION;
300 This->dp2->spData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
301 sizeof( *This->dp2->spData.lpCB ) );
302 This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB );
303 This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION;
305 /* This is the pointer to the service provider */
306 if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP,
307 (LPVOID*)&This->dp2->spData.lpISP, This ) )
310 /* FIXME: Memory leak */
311 return FALSE;
314 /* Setup lobby provider information */
315 This->dp2->dplspData.dwSPVersion = DPSP_MAJORVERSION;
316 This->dp2->dplspData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
317 sizeof( *This->dp2->dplspData.lpCB ) );
318 This->dp2->dplspData.lpCB->dwSize = sizeof( *This->dp2->dplspData.lpCB );
320 if( FAILED( DPLSP_CreateInterface( &IID_IDPLobbySP,
321 (LPVOID*)&This->dp2->dplspData.lpISP, This ) )
324 /* FIXME: Memory leak */
325 return FALSE;
328 return TRUE;
331 /* Definition of the global function in dplayx_queue.h. #
332 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
333 DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
335 HeapFree( GetProcessHeap(), 0, elem );
338 /* Function to delete the list of groups with this interface. Needs to
339 * delete the group and player lists associated with this group as well
340 * as the group data associated with this group. It should not delete
341 * player data as that is shared with the top player list and will be
342 * deleted with that.
344 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList );
345 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList )
347 DPQ_DELETEQ( elem->lpGData->groups, groups,
348 lpGroupList, cbDeleteElemFromHeap );
349 DPQ_DELETEQ( elem->lpGData->players, players,
350 lpPlayerList, cbDeleteElemFromHeap );
351 HeapFree( GetProcessHeap(), 0, elem->lpGData );
352 HeapFree( GetProcessHeap(), 0, elem );
355 /* Function to delete the list of players with this interface. Needs to
356 * delete the player data for all players as well.
358 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList );
359 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList )
361 HeapFree( GetProcessHeap(), 0, elem->lpPData );
362 HeapFree( GetProcessHeap(), 0, elem );
365 static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
367 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;
369 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
371 TerminateThread( This->dp2->hEnumSessionThread, 0 );
372 CloseHandle( This->dp2->hEnumSessionThread );
375 /* Finish with the SP - have it shutdown */
376 if( This->dp2->spData.lpCB->ShutdownEx )
378 DPSP_SHUTDOWNDATA data;
380 TRACE( "Calling SP ShutdownEx\n" );
382 data.lpISP = This->dp2->spData.lpISP;
384 (*This->dp2->spData.lpCB->ShutdownEx)( &data );
386 else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
388 TRACE( "Calling obsolete SP Shutdown\n" );
389 (*This->dp2->spData.lpCB->Shutdown)();
392 /* Unload the SP (if it exists) */
393 if( This->dp2->hServiceProvider != 0 )
395 FreeLibrary( This->dp2->hServiceProvider );
398 /* Unload the Lobby Provider (if it exists) */
399 if( This->dp2->hDPLobbyProvider != 0 )
401 FreeLibrary( This->dp2->hDPLobbyProvider );
404 #if 0
405 DPQ_DELETEQ( This->dp2->players, players, lpPlayerList, cbDeletePlayerElem );
406 DPQ_DELETEQ( This->dp2->groups, groups, lpGroupList, cbDeleteGroupsElem );
407 #endif
409 /* FIXME: Need to delete receive and send msgs queue contents */
411 NS_DeleteSessionCache( This->dp2->lpNameServerData );
413 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
415 IDirectPlaySP_Release( This->dp2->spData.lpISP );
417 /* Delete the contents */
418 HeapFree( GetProcessHeap(), 0, This->dp2 );
420 return TRUE;
423 static BOOL DP_CreateDirectPlay3( LPVOID lpDP )
425 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;
427 This->dp3 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp3) ) );
428 if ( This->dp3 == NULL )
430 return FALSE;
433 return TRUE;
436 static BOOL DP_DestroyDirectPlay3( LPVOID lpDP )
438 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;
440 /* Delete the contents */
441 HeapFree( GetProcessHeap(), 0, This->dp3 );
443 return TRUE;
446 static BOOL DP_CreateDirectPlay4( LPVOID lpDP )
448 IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)lpDP;
450 This->dp4 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp4) ) );
451 if ( This->dp4 == NULL )
453 return FALSE;
456 return TRUE;
459 static BOOL DP_DestroyDirectPlay4( LPVOID lpDP )
461 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;
463 /* Delete the contents */
464 HeapFree( GetProcessHeap(), 0, This->dp4 );
466 return TRUE;
470 /* Create a new interface */
471 extern
472 HRESULT DP_CreateInterface
473 ( REFIID riid, LPVOID* ppvObj )
475 TRACE( " for %s\n", debugstr_guid( riid ) );
477 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
478 sizeof( IDirectPlay2Impl ) );
480 if( *ppvObj == NULL )
482 return DPERR_OUTOFMEMORY;
485 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
487 IDirectPlay2Impl *This = (IDirectPlay2Impl *)*ppvObj;
488 This->lpVtbl = &directPlay2WVT;
490 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
492 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)*ppvObj;
493 This->lpVtbl = &directPlay2AVT;
495 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
497 IDirectPlay3Impl *This = (IDirectPlay3Impl *)*ppvObj;
498 This->lpVtbl = &directPlay3WVT;
500 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
502 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)*ppvObj;
503 This->lpVtbl = &directPlay3AVT;
505 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
507 IDirectPlay4Impl *This = (IDirectPlay4Impl *)*ppvObj;
508 This->lpVtbl = &directPlay4WVT;
510 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
512 IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)*ppvObj;
513 This->lpVtbl = &directPlay4AVT;
515 else
517 /* Unsupported interface */
518 HeapFree( GetProcessHeap(), 0, *ppvObj );
519 *ppvObj = NULL;
521 return E_NOINTERFACE;
524 /* Initialize it */
525 if ( DP_CreateIUnknown( *ppvObj ) &&
526 DP_CreateDirectPlay2( *ppvObj ) &&
527 DP_CreateDirectPlay3( *ppvObj ) &&
528 DP_CreateDirectPlay4( *ppvObj )
531 IDirectPlayX_AddRef( (LPDIRECTPLAY2A)*ppvObj );
533 return S_OK;
536 /* Initialize failed, destroy it */
537 DP_DestroyDirectPlay4( *ppvObj );
538 DP_DestroyDirectPlay3( *ppvObj );
539 DP_DestroyDirectPlay2( *ppvObj );
540 DP_DestroyIUnknown( *ppvObj );
542 HeapFree( GetProcessHeap(), 0, *ppvObj );
544 *ppvObj = NULL;
545 return DPERR_NOMEMORY;
549 /* Direct Play methods */
551 /* Shared between all dplay types */
552 static HRESULT WINAPI DP_QueryInterface
553 ( LPDIRECTPLAY2 iface, REFIID riid, LPVOID* ppvObj )
555 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
556 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
558 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
559 sizeof( *This ) );
561 if( *ppvObj == NULL )
563 return DPERR_OUTOFMEMORY;
566 CopyMemory( *ppvObj, This, sizeof( *This ) );
567 (*(IDirectPlay2Impl**)ppvObj)->ulInterfaceRef = 0;
569 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
571 IDirectPlay2Impl *This = (IDirectPlay2Impl *)*ppvObj;
572 This->lpVtbl = &directPlay2WVT;
574 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
576 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)*ppvObj;
577 This->lpVtbl = &directPlay2AVT;
579 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
581 IDirectPlay3Impl *This = (IDirectPlay3Impl *)*ppvObj;
582 This->lpVtbl = &directPlay3WVT;
584 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
586 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)*ppvObj;
587 This->lpVtbl = &directPlay3AVT;
589 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
591 IDirectPlay4Impl *This = (IDirectPlay4Impl *)*ppvObj;
592 This->lpVtbl = &directPlay4WVT;
594 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
596 IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)*ppvObj;
597 This->lpVtbl = &directPlay4AVT;
599 else
601 /* Unsupported interface */
602 HeapFree( GetProcessHeap(), 0, *ppvObj );
603 *ppvObj = NULL;
605 return E_NOINTERFACE;
608 IDirectPlayX_AddRef( (LPDIRECTPLAY2)*ppvObj );
610 return S_OK;
613 /* Shared between all dplay types */
614 static ULONG WINAPI DP_AddRef
615 ( LPDIRECTPLAY3 iface )
617 ULONG ulInterfaceRefCount, ulObjRefCount;
618 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
620 ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
621 ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
623 TRACE( "ref count incremented to %u:%u for %p\n",
624 ulInterfaceRefCount, ulObjRefCount, This );
626 return ulObjRefCount;
629 static ULONG WINAPI DP_Release
630 ( LPDIRECTPLAY3 iface )
632 ULONG ulInterfaceRefCount, ulObjRefCount;
634 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
636 ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
637 ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
639 TRACE( "ref count decremented to %u:%u for %p\n",
640 ulInterfaceRefCount, ulObjRefCount, This );
642 /* Deallocate if this is the last reference to the object */
643 if( ulObjRefCount == 0 )
645 /* If we're destroying the object, this must be the last ref
646 of the last interface */
647 DP_DestroyDirectPlay4( This );
648 DP_DestroyDirectPlay3( This );
649 DP_DestroyDirectPlay2( This );
650 DP_DestroyIUnknown( This );
653 /* Deallocate the interface */
654 if( ulInterfaceRefCount == 0 )
656 HeapFree( GetProcessHeap(), 0, This );
659 return ulObjRefCount;
662 static inline DPID DP_NextObjectId(void)
664 return (DPID)InterlockedIncrement( &kludgePlayerGroupId );
667 /* *lplpReply will be non NULL iff there is something to reply */
668 HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpcMessageBody,
669 DWORD dwMessageBodySize, LPCVOID lpcMessageHeader,
670 WORD wCommandId, WORD wVersion,
671 LPVOID* lplpReply, LPDWORD lpdwMsgSize )
673 TRACE( "(%p)->(%p,0x%08x,%p,%u,%u)\n",
674 This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId,
675 wVersion );
677 switch( wCommandId )
679 /* Name server needs to handle this request */
680 case DPMSGCMD_ENUMSESSIONSREQUEST:
682 /* Reply expected */
683 NS_ReplyToEnumSessionsRequest( lpcMessageBody, lplpReply, lpdwMsgSize, This );
685 break;
688 /* Name server needs to handle this request */
689 case DPMSGCMD_ENUMSESSIONSREPLY:
691 /* No reply expected */
692 NS_AddRemoteComputerAsNameServer( lpcMessageHeader,
693 This->dp2->spData.dwSPHeaderSize,
694 lpcMessageBody,
695 This->dp2->lpNameServerData );
696 break;
699 case DPMSGCMD_REQUESTNEWPLAYERID:
701 LPCDPMSG_REQUESTNEWPLAYERID lpcMsg =
702 (LPCDPMSG_REQUESTNEWPLAYERID)lpcMessageBody;
704 LPDPMSG_NEWPLAYERIDREPLY lpReply;
706 *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
708 *lplpReply = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, *lpdwMsgSize );
710 FIXME( "Ignoring dwFlags 0x%08x in request msg\n",
711 lpcMsg->dwFlags );
713 /* Setup the reply */
714 lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) +
715 This->dp2->spData.dwSPHeaderSize );
717 lpReply->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
718 lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY;
719 lpReply->envelope.wVersion = DPMSGVER_DP6;
721 lpReply->dpidNewPlayerId = DP_NextObjectId();
723 TRACE( "Allocating new playerid 0x%08x from remote request\n",
724 lpReply->dpidNewPlayerId );
726 break;
729 case DPMSGCMD_GETNAMETABLEREPLY:
730 case DPMSGCMD_NEWPLAYERIDREPLY:
733 #if 0
734 if( wCommandId == DPMSGCMD_NEWPLAYERIDREPLY )
735 DebugBreak();
736 #endif
737 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
739 break;
742 #if 1
743 case DPMSGCMD_JUSTENVELOPE:
745 TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08x\n", lpcMessageHeader, ((const DWORD *)lpcMessageHeader)[1] );
746 NS_SetLocalAddr( This->dp2->lpNameServerData, lpcMessageHeader, 20 );
747 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
749 #endif
751 case DPMSGCMD_FORWARDADDPLAYER:
753 #if 0
754 DebugBreak();
755 #endif
756 #if 1
757 TRACE( "Sending message to self to get my addr\n" );
758 DP_MSG_ToSelf( This, 1 ); /* This is a hack right now */
759 #endif
760 break;
763 case DPMSGCMD_FORWARDADDPLAYERNACK:
765 DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
766 break;
769 default:
771 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
772 DebugBreak();
773 break;
777 /* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */
779 return DP_OK;
783 static HRESULT WINAPI DP_IF_AddPlayerToGroup
784 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
785 DPID idPlayer, BOOL bAnsi )
787 lpGroupData lpGData;
788 lpPlayerList lpPList;
789 lpPlayerList lpNewPList;
791 TRACE( "(%p)->(%p,0x%08x,0x%08x,%u)\n",
792 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
794 /* Find the group */
795 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
797 return DPERR_INVALIDGROUP;
800 /* Find the player */
801 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
803 return DPERR_INVALIDPLAYER;
806 /* Create a player list (ie "shortcut" ) */
807 lpNewPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewPList ) );
808 if( lpNewPList == NULL )
810 return DPERR_CANTADDPLAYER;
813 /* Add the shortcut */
814 lpPList->lpPData->uRef++;
815 lpNewPList->lpPData = lpPList->lpPData;
817 /* Add the player to the list of players for this group */
818 DPQ_INSERT(lpGData->players,lpNewPList,players);
820 /* Let the SP know that we've added a player to the group */
821 if( This->dp2->spData.lpCB->AddPlayerToGroup )
823 DPSP_ADDPLAYERTOGROUPDATA data;
825 TRACE( "Calling SP AddPlayerToGroup\n" );
827 data.idPlayer = idPlayer;
828 data.idGroup = idGroup;
829 data.lpISP = This->dp2->spData.lpISP;
831 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
834 /* Inform all other peers of the addition of player to the group. If there are
835 * no peers keep this event quiet.
836 * Also, if this event was the result of another machine sending it to us,
837 * don't bother rebroadcasting it.
839 if( ( lpMsgHdr == NULL ) &&
840 This->dp2->lpSessionDesc &&
841 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
843 DPMSG_ADDPLAYERTOGROUP msg;
844 msg.dwType = DPSYS_ADDPLAYERTOGROUP;
846 msg.dpIdGroup = idGroup;
847 msg.dpIdPlayer = idPlayer;
849 /* FIXME: Correct to just use send effectively? */
850 /* FIXME: Should size include data w/ message or just message "header" */
851 /* FIXME: Check return code */
852 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
855 return DP_OK;
858 static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
859 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
861 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
862 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, TRUE );
865 static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
866 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
868 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
869 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, FALSE );
872 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi )
874 HRESULT hr = DP_OK;
876 TRACE("(%p)->(%u)\n", This, bAnsi );
878 /* FIXME: Need to find a new host I assume (how?) */
879 /* FIXME: Need to destroy all local groups */
880 /* FIXME: Need to migrate all remotely visible players to the new host */
882 /* Invoke the SP callback to inform of session close */
883 if( This->dp2->spData.lpCB->CloseEx )
885 DPSP_CLOSEDATA data;
887 TRACE( "Calling SP CloseEx\n" );
889 data.lpISP = This->dp2->spData.lpISP;
891 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
894 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
896 TRACE( "Calling SP Close (obsolete interface)\n" );
898 hr = (*This->dp2->spData.lpCB->Close)();
901 return hr;
904 static HRESULT WINAPI DirectPlay2AImpl_Close
905 ( LPDIRECTPLAY2A iface )
907 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
908 return DP_IF_Close( This, TRUE );
911 static HRESULT WINAPI DirectPlay2WImpl_Close
912 ( LPDIRECTPLAY2 iface )
914 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
915 return DP_IF_Close( This, FALSE );
918 static
919 lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, LPDPID lpid,
920 LPDPNAME lpName, DWORD dwFlags,
921 DPID idParent, BOOL bAnsi )
923 lpGroupData lpGData;
925 /* Allocate the new space and add to end of high level group list */
926 lpGData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGData ) );
928 if( lpGData == NULL )
930 return NULL;
933 DPQ_INIT(lpGData->groups);
934 DPQ_INIT(lpGData->players);
936 /* Set the desired player ID - no sanity checking to see if it exists */
937 lpGData->dpid = *lpid;
939 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
941 /* FIXME: Should we check that the parent exists? */
942 lpGData->parent = idParent;
944 /* FIXME: Should we validate the dwFlags? */
945 lpGData->dwFlags = dwFlags;
947 TRACE( "Created group id 0x%08x\n", *lpid );
949 return lpGData;
952 /* This method assumes that all links to it are already deleted */
953 static void
954 DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid )
956 lpGroupList lpGList;
958 TRACE( "(%p)->(0x%08x)\n", This, dpid );
960 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
962 if( lpGList == NULL )
964 ERR( "DPID 0x%08x not found\n", dpid );
965 return;
968 if( --(lpGList->lpGData->uRef) )
970 FIXME( "Why is this not the last reference to group?\n" );
971 DebugBreak();
974 /* Delete player */
975 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
976 HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
978 /* Remove and Delete Player List object */
979 HeapFree( GetProcessHeap(), 0, lpGList );
983 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid )
985 lpGroupList lpGroups;
987 TRACE( "(%p)->(0x%08x)\n", This, dpid );
989 if( dpid == DPID_SYSTEM_GROUP )
991 return This->dp2->lpSysGroup;
993 else
995 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
998 if( lpGroups == NULL )
1000 return NULL;
1003 return lpGroups->lpGData;
1006 static HRESULT WINAPI DP_IF_CreateGroup
1007 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
1008 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
1009 DWORD dwFlags, BOOL bAnsi )
1011 lpGroupData lpGData;
1013 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1014 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
1015 dwFlags, bAnsi );
1017 /* If the name is not specified, we must provide one */
1018 if( DPID_UNKNOWN == *lpidGroup )
1020 /* If we are the name server, we decide on the group ids. If not, we
1021 * must ask for one before attempting a creation.
1023 if( This->dp2->bHostInterface )
1025 *lpidGroup = DP_NextObjectId();
1027 else
1029 *lpidGroup = DP_GetRemoteNextObjectId();
1033 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
1034 DPID_NOPARENT_GROUP, bAnsi );
1036 if( lpGData == NULL )
1038 return DPERR_CANTADDPLAYER; /* yes player not group */
1041 if( DPID_SYSTEM_GROUP == *lpidGroup )
1043 This->dp2->lpSysGroup = lpGData;
1044 TRACE( "Inserting system group\n" );
1046 else
1048 /* Insert into the system group */
1049 lpGroupList lpGroup = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGroup ) );
1050 lpGroup->lpGData = lpGData;
1052 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
1055 /* Something is now referencing this data */
1056 lpGData->uRef++;
1058 /* Set all the important stuff for the group */
1059 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
1061 /* FIXME: We should only create the system group if GetCaps returns
1062 * DPCAPS_GROUPOPTIMIZED.
1065 /* Let the SP know that we've created this group */
1066 if( This->dp2->spData.lpCB->CreateGroup )
1068 DPSP_CREATEGROUPDATA data;
1069 DWORD dwCreateFlags = 0;
1071 TRACE( "Calling SP CreateGroup\n" );
1073 if( *lpidGroup == DPID_NOPARENT_GROUP )
1074 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
1076 if( lpMsgHdr == NULL )
1077 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1079 if( dwFlags & DPGROUP_HIDDEN )
1080 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
1082 data.idGroup = *lpidGroup;
1083 data.dwFlags = dwCreateFlags;
1084 data.lpSPMessageHeader = lpMsgHdr;
1085 data.lpISP = This->dp2->spData.lpISP;
1087 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1090 /* Inform all other peers of the creation of a new group. If there are
1091 * no peers keep this event quiet.
1092 * Also if this message was sent to us, don't rebroadcast.
1094 if( ( lpMsgHdr == NULL ) &&
1095 This->dp2->lpSessionDesc &&
1096 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1098 DPMSG_CREATEPLAYERORGROUP msg;
1099 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1101 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1102 msg.dpId = *lpidGroup;
1103 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1104 msg.lpData = lpData;
1105 msg.dwDataSize = dwDataSize;
1106 msg.dpnName = *lpGroupName;
1107 msg.dpIdParent = DPID_NOPARENT_GROUP;
1108 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
1110 /* FIXME: Correct to just use send effectively? */
1111 /* FIXME: Should size include data w/ message or just message "header" */
1112 /* FIXME: Check return code */
1113 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
1114 0, 0, NULL, NULL, bAnsi );
1117 return DP_OK;
1120 static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
1121 ( LPDIRECTPLAY2A iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1122 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1124 *lpidGroup = DPID_UNKNOWN;
1126 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1127 lpGroupName, lpData, dwDataSize, dwFlags, TRUE );
1130 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
1131 ( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1132 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1134 *lpidGroup = DPID_UNKNOWN;
1136 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1137 lpGroupName, lpData, dwDataSize, dwFlags, FALSE );
1141 static void
1142 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
1143 LPVOID lpData, DWORD dwDataSize )
1145 /* Clear out the data with this player */
1146 if( dwFlags & DPSET_LOCAL )
1148 if ( lpGData->dwLocalDataSize != 0 )
1150 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
1151 lpGData->lpLocalData = NULL;
1152 lpGData->dwLocalDataSize = 0;
1155 else
1157 if( lpGData->dwRemoteDataSize != 0 )
1159 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
1160 lpGData->lpRemoteData = NULL;
1161 lpGData->dwRemoteDataSize = 0;
1165 /* Reallocate for new data */
1166 if( lpData != NULL )
1168 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1169 sizeof( dwDataSize ) );
1170 CopyMemory( lpNewData, lpData, dwDataSize );
1172 if( dwFlags & DPSET_LOCAL )
1174 lpGData->lpLocalData = lpData;
1175 lpGData->dwLocalDataSize = dwDataSize;
1177 else
1179 lpGData->lpRemoteData = lpNewData;
1180 lpGData->dwRemoteDataSize = dwDataSize;
1186 /* This function will just create the storage for the new player. */
1187 static
1188 lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid,
1189 LPDPNAME lpName, DWORD dwFlags,
1190 HANDLE hEvent, BOOL bAnsi )
1192 lpPlayerData lpPData;
1194 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
1196 /* Allocate the storage for the player and associate it with list element */
1197 lpPData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPData ) );
1198 if( lpPData == NULL )
1200 return NULL;
1203 /* Set the desired player ID */
1204 lpPData->dpid = *lpid;
1206 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
1208 lpPData->dwFlags = dwFlags;
1210 /* If we were given an event handle, duplicate it */
1211 if( hEvent != 0 )
1213 if( !DuplicateHandle( GetCurrentProcess(), hEvent,
1214 GetCurrentProcess(), &lpPData->hEvent,
1215 0, FALSE, DUPLICATE_SAME_ACCESS )
1218 /* FIXME: Memory leak */
1219 ERR( "Can't duplicate player msg handle %p\n", hEvent );
1223 /* Initialize the SP data section */
1224 lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData();
1226 TRACE( "Created player id 0x%08x\n", *lpid );
1228 return lpPData;
1231 /* Delete the contents of the DPNAME struct */
1232 static void
1233 DP_DeleteDPNameStruct( LPDPNAME lpDPName )
1235 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u1.lpszShortNameA );
1236 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u2.lpszLongNameA );
1239 /* This method assumes that all links to it are already deleted */
1240 static void
1241 DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid )
1243 lpPlayerList lpPList;
1245 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1247 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1249 if( lpPList == NULL )
1251 ERR( "DPID 0x%08x not found\n", dpid );
1252 return;
1255 /* Verify that this is the last reference to the data */
1256 if( --(lpPList->lpPData->uRef) )
1258 FIXME( "Why is this not the last reference to player?\n" );
1259 DebugBreak();
1262 /* Delete player */
1263 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1265 CloseHandle( lpPList->lpPData->hEvent );
1266 HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
1268 /* Delete Player List object */
1269 HeapFree( GetProcessHeap(), 0, lpPList );
1272 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid )
1274 lpPlayerList lpPlayers;
1276 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1278 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1280 return lpPlayers;
1283 /* Basic area for Dst must already be allocated */
1284 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi )
1286 if( lpSrc == NULL )
1288 ZeroMemory( lpDst, sizeof( *lpDst ) );
1289 lpDst->dwSize = sizeof( *lpDst );
1290 return TRUE;
1293 if( lpSrc->dwSize != sizeof( *lpSrc) )
1295 return FALSE;
1298 /* Delete any existing pointers */
1299 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1300 HeapFree( GetProcessHeap(), 0, lpDst->u2.lpszLongNameA );
1302 /* Copy as required */
1303 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1305 if( bAnsi )
1307 if( lpSrc->u1.lpszShortNameA )
1309 lpDst->u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), 0,
1310 strlen(lpSrc->u1.lpszShortNameA)+1 );
1311 strcpy( lpDst->u1.lpszShortNameA, lpSrc->u1.lpszShortNameA );
1313 if( lpSrc->u2.lpszLongNameA )
1315 lpDst->u2.lpszLongNameA = HeapAlloc( GetProcessHeap(), 0,
1316 strlen(lpSrc->u2.lpszLongNameA)+1 );
1317 strcpy( lpDst->u2.lpszLongNameA, lpSrc->u2.lpszLongNameA );
1320 else
1322 if( lpSrc->u1.lpszShortNameA )
1324 lpDst->u1.lpszShortName = HeapAlloc( GetProcessHeap(), 0,
1325 (strlenW(lpSrc->u1.lpszShortName)+1)*sizeof(WCHAR) );
1326 strcpyW( lpDst->u1.lpszShortName, lpSrc->u1.lpszShortName );
1328 if( lpSrc->u2.lpszLongNameA )
1330 lpDst->u2.lpszLongName = HeapAlloc( GetProcessHeap(), 0,
1331 (strlenW(lpSrc->u2.lpszLongName)+1)*sizeof(WCHAR) );
1332 strcpyW( lpDst->u2.lpszLongName, lpSrc->u2.lpszLongName );
1336 return TRUE;
1339 static void
1340 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
1341 LPVOID lpData, DWORD dwDataSize )
1343 /* Clear out the data with this player */
1344 if( dwFlags & DPSET_LOCAL )
1346 if ( lpPData->dwLocalDataSize != 0 )
1348 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
1349 lpPData->lpLocalData = NULL;
1350 lpPData->dwLocalDataSize = 0;
1353 else
1355 if( lpPData->dwRemoteDataSize != 0 )
1357 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
1358 lpPData->lpRemoteData = NULL;
1359 lpPData->dwRemoteDataSize = 0;
1363 /* Reallocate for new data */
1364 if( lpData != NULL )
1366 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1367 sizeof( dwDataSize ) );
1368 CopyMemory( lpNewData, lpData, dwDataSize );
1370 if( dwFlags & DPSET_LOCAL )
1372 lpPData->lpLocalData = lpData;
1373 lpPData->dwLocalDataSize = dwDataSize;
1375 else
1377 lpPData->lpRemoteData = lpNewData;
1378 lpPData->dwRemoteDataSize = dwDataSize;
1384 static HRESULT WINAPI DP_IF_CreatePlayer
1385 ( IDirectPlay2Impl* This,
1386 LPVOID lpMsgHdr, /* NULL for local creation, non NULL for remote creation */
1387 LPDPID lpidPlayer,
1388 LPDPNAME lpPlayerName,
1389 HANDLE hEvent,
1390 LPVOID lpData,
1391 DWORD dwDataSize,
1392 DWORD dwFlags,
1393 BOOL bAnsi )
1395 HRESULT hr = DP_OK;
1396 lpPlayerData lpPData;
1397 lpPlayerList lpPList;
1398 DWORD dwCreateFlags = 0;
1400 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1401 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1402 dwDataSize, dwFlags, bAnsi );
1404 if( dwFlags == 0 )
1406 dwFlags = DPPLAYER_SPECTATOR;
1409 if( lpidPlayer == NULL )
1411 return DPERR_INVALIDPARAMS;
1415 /* Determine the creation flags for the player. These will be passed
1416 * to the name server if requesting a player id and to the SP when
1417 * informing it of the player creation
1420 if( dwFlags & DPPLAYER_SERVERPLAYER )
1422 if( *lpidPlayer == DPID_SERVERPLAYER )
1424 /* Server player for the host interface */
1425 dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
1427 else if( *lpidPlayer == DPID_NAME_SERVER )
1429 /* Name server - master of everything */
1430 dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
1432 else
1434 /* Server player for a non host interface */
1435 dwCreateFlags |= DPLAYI_PLAYER_SYSPLAYER;
1439 if( lpMsgHdr == NULL )
1440 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1443 /* Verify we know how to handle all the flags */
1444 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1445 ( dwFlags & DPPLAYER_SPECTATOR )
1449 /* Assume non fatal failure */
1450 ERR( "unknown dwFlags = 0x%08x\n", dwFlags );
1453 /* If the name is not specified, we must provide one */
1454 if( *lpidPlayer == DPID_UNKNOWN )
1456 /* If we are the session master, we dish out the group/player ids */
1457 if( This->dp2->bHostInterface )
1459 *lpidPlayer = DP_NextObjectId();
1461 else
1463 hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer );
1465 if( FAILED(hr) )
1467 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1468 return hr;
1472 else
1474 /* FIXME: Would be nice to perhaps verify that we don't already have
1475 * this player.
1479 /* FIXME: Should we be storing these dwFlags or the creation ones? */
1480 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwFlags,
1481 hEvent, bAnsi );
1483 if( lpPData == NULL )
1485 return DPERR_CANTADDPLAYER;
1488 /* Create the list object and link it in */
1489 lpPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPList ) );
1490 if( lpPList == NULL )
1492 FIXME( "Memory leak\n" );
1493 return DPERR_CANTADDPLAYER;
1496 lpPData->uRef = 1;
1497 lpPList->lpPData = lpPData;
1499 /* Add the player to the system group */
1500 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1502 /* Update the information and send it to all players in the session */
1503 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
1505 /* Let the SP know that we've created this player */
1506 if( This->dp2->spData.lpCB->CreatePlayer )
1508 DPSP_CREATEPLAYERDATA data;
1510 data.idPlayer = *lpidPlayer;
1511 data.dwFlags = dwCreateFlags;
1512 data.lpSPMessageHeader = lpMsgHdr;
1513 data.lpISP = This->dp2->spData.lpISP;
1515 TRACE( "Calling SP CreatePlayer 0x%08x: dwFlags: 0x%08x lpMsgHdr: %p\n",
1516 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
1518 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1521 if( FAILED(hr) )
1523 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1524 return hr;
1527 /* Now let the SP know that this player is a member of the system group */
1528 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1530 DPSP_ADDPLAYERTOGROUPDATA data;
1532 data.idPlayer = *lpidPlayer;
1533 data.idGroup = DPID_SYSTEM_GROUP;
1534 data.lpISP = This->dp2->spData.lpISP;
1536 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1538 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1541 if( FAILED(hr) )
1543 ERR( "Failed to add player to sys group with sp: %s\n",
1544 DPLAYX_HresultToString(hr) );
1545 return hr;
1548 #if 1
1549 if( This->dp2->bHostInterface == FALSE )
1551 /* Let the name server know about the creation of this player */
1552 /* FIXME: Is this only to be done for the creation of a server player or
1553 * is this used for regular players? If only for server players, move
1554 * this call to DP_SecureOpen(...);
1556 #if 0
1557 TRACE( "Sending message to self to get my addr\n" );
1558 DP_MSG_ToSelf( This, *lpidPlayer ); /* This is a hack right now */
1559 #endif
1561 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
1563 #else
1564 /* Inform all other peers of the creation of a new player. If there are
1565 * no peers keep this quiet.
1566 * Also, if this was a remote event, no need to rebroadcast it.
1568 if( ( lpMsgHdr == NULL ) &&
1569 This->dp2->lpSessionDesc &&
1570 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1572 DPMSG_CREATEPLAYERORGROUP msg;
1573 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1575 msg.dwPlayerType = DPPLAYERTYPE_PLAYER;
1576 msg.dpId = *lpidPlayer;
1577 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */
1578 msg.lpData = lpData;
1579 msg.dwDataSize = dwDataSize;
1580 msg.dpnName = *lpPlayerName;
1581 msg.dpIdParent = DPID_NOPARENT_GROUP;
1582 msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
1584 /* FIXME: Correct to just use send effectively? */
1585 /* FIXME: Should size include data w/ message or just message "header" */
1586 /* FIXME: Check return code */
1587 hr = DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
1588 sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
1590 #endif
1592 return hr;
1595 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
1596 ( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1597 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1599 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1601 if( dwFlags & DPPLAYER_SERVERPLAYER )
1603 *lpidPlayer = DPID_SERVERPLAYER;
1605 else
1607 *lpidPlayer = DPID_UNKNOWN;
1610 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1611 lpData, dwDataSize, dwFlags, TRUE );
1614 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
1615 ( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1616 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1618 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1620 if( dwFlags & DPPLAYER_SERVERPLAYER )
1622 *lpidPlayer = DPID_SERVERPLAYER;
1624 else
1626 *lpidPlayer = DPID_UNKNOWN;
1629 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1630 lpData, dwDataSize, dwFlags, FALSE );
1633 static DPID DP_GetRemoteNextObjectId(void)
1635 FIXME( ":stub\n" );
1637 /* Hack solution */
1638 return DP_NextObjectId();
1641 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
1642 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
1643 DPID idPlayer, BOOL bAnsi )
1645 HRESULT hr = DP_OK;
1647 lpGroupData lpGData;
1648 lpPlayerList lpPList;
1650 TRACE( "(%p)->(%p,0x%08x,0x%08x,%u)\n",
1651 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
1653 /* Find the group */
1654 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1656 return DPERR_INVALIDGROUP;
1659 /* Find the player */
1660 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
1662 return DPERR_INVALIDPLAYER;
1665 /* Remove the player shortcut from the group */
1666 DPQ_REMOVE_ENTRY( lpGData->players, players, lpPData->dpid, ==, idPlayer, lpPList );
1668 if( lpPList == NULL )
1670 return DPERR_INVALIDPLAYER;
1673 /* One less reference */
1674 lpPList->lpPData->uRef--;
1676 /* Delete the Player List element */
1677 HeapFree( GetProcessHeap(), 0, lpPList );
1679 /* Inform the SP if they care */
1680 if( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1682 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1684 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1686 data.idPlayer = idPlayer;
1687 data.idGroup = idGroup;
1688 data.lpISP = This->dp2->spData.lpISP;
1690 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1693 /* Need to send a DELETEPLAYERFROMGROUP message */
1694 FIXME( "Need to send a message\n" );
1696 return hr;
1699 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
1700 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
1702 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1703 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, TRUE );
1706 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
1707 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
1709 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1710 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, FALSE );
1713 typedef struct _DPRGOPContext
1715 IDirectPlay3Impl* This;
1716 BOOL bAnsi;
1717 DPID idGroup;
1718 } DPRGOPContext, *lpDPRGOPContext;
1720 static BOOL CALLBACK
1721 cbRemoveGroupOrPlayer(
1722 DPID dpId,
1723 DWORD dwPlayerType,
1724 LPCDPNAME lpName,
1725 DWORD dwFlags,
1726 LPVOID lpContext )
1728 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1730 TRACE( "Removing element:0x%08x (type:0x%08x) from element:0x%08x\n",
1731 dpId, dwPlayerType, lpCtxt->idGroup );
1733 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1735 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt->This, lpCtxt->idGroup,
1736 dpId )
1740 ERR( "Unable to delete group 0x%08x from group 0x%08x\n",
1741 dpId, lpCtxt->idGroup );
1744 else
1746 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl*)lpCtxt->This,
1747 NULL, lpCtxt->idGroup,
1748 dpId, lpCtxt->bAnsi )
1752 ERR( "Unable to delete player 0x%08x from grp 0x%08x\n",
1753 dpId, lpCtxt->idGroup );
1757 return TRUE; /* Continue enumeration */
1760 static HRESULT WINAPI DP_IF_DestroyGroup
1761 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi )
1763 lpGroupData lpGData;
1764 DPRGOPContext context;
1766 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1767 This, lpMsgHdr, idGroup, bAnsi );
1769 /* Find the group */
1770 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1772 return DPERR_INVALIDPLAYER; /* yes player */
1775 context.This = (IDirectPlay3Impl*)This;
1776 context.bAnsi = bAnsi;
1777 context.idGroup = idGroup;
1779 /* Remove all players that this group has */
1780 DP_IF_EnumGroupPlayers( This, idGroup, NULL,
1781 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1783 /* Remove all links to groups that this group has since this is dp3 */
1784 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This, idGroup, NULL,
1785 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1787 /* Remove this group from the parent group - if it has one */
1788 if( ( idGroup != DPID_SYSTEM_GROUP ) &&
1789 ( lpGData->parent != DPID_SYSTEM_GROUP )
1792 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl*)This, lpGData->parent,
1793 idGroup );
1796 /* Now delete this group data and list from the system group */
1797 DP_DeleteGroup( This, idGroup );
1799 /* Let the SP know that we've destroyed this group */
1800 if( This->dp2->spData.lpCB->DeleteGroup )
1802 DPSP_DELETEGROUPDATA data;
1804 FIXME( "data.dwFlags is incorrect\n" );
1806 data.idGroup = idGroup;
1807 data.dwFlags = 0;
1808 data.lpISP = This->dp2->spData.lpISP;
1810 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1813 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1815 return DP_OK;
1818 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
1819 ( LPDIRECTPLAY2A iface, DPID idGroup )
1821 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1822 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
1825 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
1826 ( LPDIRECTPLAY2 iface, DPID idGroup )
1828 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1829 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
1832 typedef struct _DPFAGContext
1834 IDirectPlay2Impl* This;
1835 DPID idPlayer;
1836 BOOL bAnsi;
1837 } DPFAGContext, *lpDPFAGContext;
1839 static HRESULT WINAPI DP_IF_DestroyPlayer
1840 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi )
1842 DPFAGContext cbContext;
1844 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1845 This, lpMsgHdr, idPlayer, bAnsi );
1847 if( This->dp2->connectionInitialized == NO_PROVIDER )
1849 return DPERR_UNINITIALIZED;
1852 if( DP_FindPlayer( This, idPlayer ) == NULL )
1854 return DPERR_INVALIDPLAYER;
1857 /* FIXME: If the player is remote, we must be the host to delete this */
1859 cbContext.This = This;
1860 cbContext.idPlayer = idPlayer;
1861 cbContext.bAnsi = bAnsi;
1863 /* Find each group and call DeletePlayerFromGroup if the player is a
1864 member of the group */
1865 DP_IF_EnumGroups( This, NULL, cbDeletePlayerFromAllGroups,
1866 (LPVOID)&cbContext, DPENUMGROUPS_ALL, bAnsi );
1868 /* Now delete player and player list from the sys group */
1869 DP_DeletePlayer( This, idPlayer );
1871 /* Let the SP know that we've destroyed this group */
1872 if( This->dp2->spData.lpCB->DeletePlayer )
1874 DPSP_DELETEPLAYERDATA data;
1876 FIXME( "data.dwFlags is incorrect\n" );
1878 data.idPlayer = idPlayer;
1879 data.dwFlags = 0;
1880 data.lpISP = This->dp2->spData.lpISP;
1882 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
1885 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
1887 return DP_OK;
1890 static BOOL CALLBACK
1891 cbDeletePlayerFromAllGroups(
1892 DPID dpId,
1893 DWORD dwPlayerType,
1894 LPCDPNAME lpName,
1895 DWORD dwFlags,
1896 LPVOID lpContext )
1898 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
1900 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1902 DP_IF_DeletePlayerFromGroup( lpCtxt->This, NULL, dpId, lpCtxt->idPlayer,
1903 lpCtxt->bAnsi );
1905 /* Enumerate all groups in this group since this will normally only
1906 * be called for top level groups
1908 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)lpCtxt->This,
1909 dpId, NULL,
1910 cbDeletePlayerFromAllGroups,
1911 (LPVOID)lpContext, DPENUMGROUPS_ALL,
1912 lpCtxt->bAnsi );
1915 else
1917 ERR( "Group callback has dwPlayerType = 0x%08x\n", dwPlayerType );
1920 return TRUE;
1923 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
1924 ( LPDIRECTPLAY2A iface, DPID idPlayer )
1926 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1927 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
1930 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
1931 ( LPDIRECTPLAY2 iface, DPID idPlayer )
1933 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1934 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
1937 static HRESULT WINAPI DP_IF_EnumGroupPlayers
1938 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
1939 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1940 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1942 lpGroupData lpGData;
1943 lpPlayerList lpPList;
1945 FIXME("(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
1946 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
1947 lpContext, dwFlags, bAnsi );
1949 if( This->dp2->connectionInitialized == NO_PROVIDER )
1951 return DPERR_UNINITIALIZED;
1954 /* Find the group */
1955 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1957 return DPERR_INVALIDGROUP;
1960 if( DPQ_IS_EMPTY( lpGData->players ) )
1962 return DP_OK;
1965 lpPList = DPQ_FIRST( lpGData->players );
1967 /* Walk the players in this group */
1968 for( ;; )
1970 /* We do not enum the name server or app server as they are of no
1971 * concequence to the end user.
1973 if( ( lpPList->lpPData->dpid != DPID_NAME_SERVER ) &&
1974 ( lpPList->lpPData->dpid != DPID_SERVERPLAYER )
1978 /* FIXME: Need to add stuff for dwFlags checking */
1980 if( !lpEnumPlayersCallback2( lpPList->lpPData->dpid, DPPLAYERTYPE_PLAYER,
1981 &lpPList->lpPData->name,
1982 lpPList->lpPData->dwFlags,
1983 lpContext )
1986 /* User requested break */
1987 return DP_OK;
1991 if( DPQ_IS_ENDOFLIST( lpPList->players ) )
1993 break;
1996 lpPList = DPQ_NEXT( lpPList->players );
1999 return DP_OK;
2002 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
2003 ( LPDIRECTPLAY2A iface, DPID idGroup, LPGUID lpguidInstance,
2004 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2005 LPVOID lpContext, DWORD dwFlags )
2007 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2008 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2009 lpEnumPlayersCallback2, lpContext,
2010 dwFlags, TRUE );
2013 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
2014 ( LPDIRECTPLAY2 iface, DPID idGroup, LPGUID lpguidInstance,
2015 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2016 LPVOID lpContext, DWORD dwFlags )
2018 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2019 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2020 lpEnumPlayersCallback2, lpContext,
2021 dwFlags, FALSE );
2024 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2025 static HRESULT WINAPI DP_IF_EnumGroups
2026 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2027 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2028 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2030 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This,
2031 DPID_SYSTEM_GROUP, lpguidInstance,
2032 lpEnumPlayersCallback2, lpContext,
2033 dwFlags, bAnsi );
2036 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
2037 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2038 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2039 LPVOID lpContext, DWORD dwFlags )
2041 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2042 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2043 lpContext, dwFlags, TRUE );
2046 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
2047 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2048 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2049 LPVOID lpContext, DWORD dwFlags )
2051 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2052 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2053 lpContext, dwFlags, FALSE );
2056 static HRESULT WINAPI DP_IF_EnumPlayers
2057 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2058 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2059 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2061 return DP_IF_EnumGroupPlayers( This, DPID_SYSTEM_GROUP, lpguidInstance,
2062 lpEnumPlayersCallback2, lpContext,
2063 dwFlags, bAnsi );
2066 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
2067 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2068 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2069 LPVOID lpContext, DWORD dwFlags )
2071 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2072 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2073 lpContext, dwFlags, TRUE );
2076 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
2077 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2078 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2079 LPVOID lpContext, DWORD dwFlags )
2081 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2082 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2083 lpContext, dwFlags, FALSE );
2086 /* This function should call the registered callback function that the user
2087 passed into EnumSessions for each entry available.
2089 static void DP_InvokeEnumSessionCallbacks
2090 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2091 LPVOID lpNSInfo,
2092 DWORD dwTimeout,
2093 LPVOID lpContext )
2095 LPDPSESSIONDESC2 lpSessionDesc;
2097 FIXME( ": not checking for conditions\n" );
2099 /* Not sure if this should be pruning but it's convenient */
2100 NS_PruneSessionCache( lpNSInfo );
2102 NS_ResetSessionEnumeration( lpNSInfo );
2104 /* Enumerate all sessions */
2105 /* FIXME: Need to indicate ANSI */
2106 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2108 TRACE( "EnumSessionsCallback2 invoked\n" );
2109 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2111 return;
2115 /* Invoke one last time to indicate that there is no more to come */
2116 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2119 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2121 EnumSessionAsyncCallbackData* data = (EnumSessionAsyncCallbackData*)lpContext;
2122 HANDLE hSuicideRequest = data->hSuicideRequest;
2123 DWORD dwTimeout = data->dwTimeout;
2125 TRACE( "Thread started with timeout = 0x%08x\n", dwTimeout );
2127 for( ;; )
2129 HRESULT hr;
2131 /* Sleep up to dwTimeout waiting for request to terminate thread */
2132 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2134 TRACE( "Thread terminating on terminate request\n" );
2135 break;
2138 /* Now resend the enum request */
2139 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2140 data->dwEnumSessionFlags,
2141 data->lpSpData );
2143 if( FAILED(hr) )
2145 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2146 /* FIXME: Should we kill this thread? How to inform the main thread? */
2151 TRACE( "Thread terminating\n" );
2153 /* Clean up the thread data */
2154 CloseHandle( hSuicideRequest );
2155 HeapFree( GetProcessHeap(), 0, lpContext );
2157 /* FIXME: Need to have some notification to main app thread that this is
2158 * dead. It would serve two purposes. 1) allow sync on termination
2159 * so that we don't actually send something to ourselves when we
2160 * become name server (race condition) and 2) so that if we die
2161 * abnormally something else will be able to tell.
2164 return 1;
2167 static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
2169 /* Does a thread exist? If so we were doing an async enum session */
2170 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2172 TRACE( "Killing EnumSession thread %p\n",
2173 This->dp2->hEnumSessionThread );
2175 /* Request that the thread kill itself nicely */
2176 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2177 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2179 /* We no longer need to know about the thread */
2180 CloseHandle( This->dp2->hEnumSessionThread );
2182 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2186 static HRESULT WINAPI DP_IF_EnumSessions
2187 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2188 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2189 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2191 HRESULT hr = DP_OK;
2193 TRACE( "(%p)->(%p,0x%08x,%p,%p,0x%08x,%u)\n",
2194 This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags,
2195 bAnsi );
2197 /* Can't enumerate if the interface is already open */
2198 if( This->dp2->bConnectionOpen )
2200 return DPERR_GENERIC;
2203 #if 1
2204 /* The loading of a lobby provider _seems_ to require a backdoor loading
2205 * of the service provider to also associate with this DP object. This is
2206 * because the app doesn't seem to have to call EnumConnections and
2207 * InitializeConnection for the SP before calling this method. As such
2208 * we'll do their dirty work for them with a quick hack so as to always
2209 * load the TCP/IP service provider.
2211 * The correct solution would seem to involve creating a dialog box which
2212 * contains the possible SPs. These dialog boxes most likely follow SDK
2213 * examples.
2215 if( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
2217 LPVOID lpConnection;
2218 DWORD dwSize;
2220 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2222 if( !DP_BuildSPCompoundAddr( (LPGUID)&DPSPGUID_TCPIP, &lpConnection, &dwSize ) )
2224 ERR( "Can't build compound addr\n" );
2225 return DPERR_GENERIC;
2228 hr = DP_IF_InitializeConnection( (IDirectPlay3Impl*)This, lpConnection,
2229 0, bAnsi );
2230 if( FAILED(hr) )
2232 return hr;
2235 /* Free up the address buffer */
2236 HeapFree( GetProcessHeap(), 0, lpConnection );
2238 /* The SP is now initialized */
2239 This->dp2->bSPInitialized = TRUE;
2241 #endif
2244 /* Use the service provider default? */
2245 if( dwTimeout == 0 )
2247 DPCAPS spCaps;
2248 spCaps.dwSize = sizeof( spCaps );
2250 DP_IF_GetCaps( This, &spCaps, 0 );
2251 dwTimeout = spCaps.dwTimeout;
2253 /* The service provider doesn't provide one either! */
2254 if( dwTimeout == 0 )
2256 /* Provide the TCP/IP default */
2257 dwTimeout = DPMSG_WAIT_5_SECS;
2261 if( dwFlags & DPENUMSESSIONS_STOPASYNC )
2263 DP_KillEnumSessionThread( This );
2264 return hr;
2267 /* FIXME: Interface locking sucks in this method */
2268 if( ( dwFlags & DPENUMSESSIONS_ASYNC ) )
2270 /* Enumerate everything presently in the local session cache */
2271 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2272 This->dp2->lpNameServerData, dwTimeout,
2273 lpContext );
2276 /* See if we've already created a thread to service this interface */
2277 if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2279 DWORD dwThreadId;
2281 /* Send the first enum request inline since the user may cancel a dialog
2282 * if one is presented. Also, may also have a connecting return code.
2284 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2285 dwFlags, &This->dp2->spData );
2287 if( !FAILED(hr) )
2289 EnumSessionAsyncCallbackData* lpData
2290 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpData ) );
2291 /* FIXME: need to kill the thread on object deletion */
2292 lpData->lpSpData = &This->dp2->spData;
2294 CopyMemory( &lpData->requestGuid, &lpsd->guidApplication, sizeof(GUID) );
2295 lpData->dwEnumSessionFlags = dwFlags;
2296 lpData->dwTimeout = dwTimeout;
2298 This->dp2->hKillEnumSessionThreadEvent =
2299 CreateEventW( NULL, TRUE, FALSE, NULL );
2301 if( !DuplicateHandle( GetCurrentProcess(),
2302 This->dp2->hKillEnumSessionThreadEvent,
2303 GetCurrentProcess(),
2304 &lpData->hSuicideRequest,
2305 0, FALSE, DUPLICATE_SAME_ACCESS )
2308 ERR( "Can't duplicate thread killing handle\n" );
2311 TRACE( ": creating EnumSessionsRequest thread\n" );
2313 This->dp2->hEnumSessionThread = CreateThread( NULL,
2315 DP_EnumSessionsSendAsyncRequestThread,
2316 lpData,
2318 &dwThreadId );
2322 else
2324 /* Invalidate the session cache for the interface */
2325 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2327 /* Send the broadcast for session enumeration */
2328 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2329 dwFlags,
2330 &This->dp2->spData );
2333 SleepEx( dwTimeout, FALSE );
2335 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2336 This->dp2->lpNameServerData, dwTimeout,
2337 lpContext );
2340 return hr;
2343 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2344 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2345 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2346 LPVOID lpContext, DWORD dwFlags )
2348 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2349 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2350 lpContext, dwFlags, TRUE );
2353 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2354 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2355 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2356 LPVOID lpContext, DWORD dwFlags )
2358 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2359 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2360 lpContext, dwFlags, FALSE );
2363 static HRESULT WINAPI DP_IF_GetPlayerCaps
2364 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
2365 DWORD dwFlags )
2367 DPSP_GETCAPSDATA data;
2369 TRACE("(%p)->(0x%08x,%p,0x%08x)\n", This, idPlayer, lpDPCaps, dwFlags);
2371 /* Query the service provider */
2372 data.idPlayer = idPlayer;
2373 data.dwFlags = dwFlags;
2374 data.lpCaps = lpDPCaps;
2375 data.lpISP = This->dp2->spData.lpISP;
2377 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2380 static HRESULT WINAPI DP_IF_GetCaps
2381 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags )
2383 return DP_IF_GetPlayerCaps( This, DPID_ALLPLAYERS, lpDPCaps, dwFlags );
2386 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2387 ( LPDIRECTPLAY2A iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2389 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2390 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2393 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2394 ( LPDIRECTPLAY2 iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2396 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2397 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2400 static HRESULT WINAPI DP_IF_GetGroupData
2401 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2402 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2404 lpGroupData lpGData;
2405 DWORD dwRequiredBufferSize;
2406 LPVOID lpCopyDataFrom;
2408 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2409 This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi );
2411 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2413 return DPERR_INVALIDGROUP;
2416 /* How much buffer is required? */
2417 if( dwFlags & DPSET_LOCAL )
2419 dwRequiredBufferSize = lpGData->dwLocalDataSize;
2420 lpCopyDataFrom = lpGData->lpLocalData;
2422 else
2424 dwRequiredBufferSize = lpGData->dwRemoteDataSize;
2425 lpCopyDataFrom = lpGData->lpRemoteData;
2428 /* Is the user requesting to know how big a buffer is required? */
2429 if( ( lpData == NULL ) ||
2430 ( *lpdwDataSize < dwRequiredBufferSize )
2433 *lpdwDataSize = dwRequiredBufferSize;
2434 return DPERR_BUFFERTOOSMALL;
2437 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2439 return DP_OK;
2442 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2443 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2444 LPDWORD lpdwDataSize, DWORD dwFlags )
2446 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2447 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2448 dwFlags, TRUE );
2451 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2452 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2453 LPDWORD lpdwDataSize, DWORD dwFlags )
2455 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2456 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2457 dwFlags, FALSE );
2460 static HRESULT WINAPI DP_IF_GetGroupName
2461 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2462 LPDWORD lpdwDataSize, BOOL bAnsi )
2464 lpGroupData lpGData;
2465 LPDPNAME lpName = (LPDPNAME)lpData;
2466 DWORD dwRequiredDataSize;
2468 FIXME("(%p)->(0x%08x,%p,%p,%u) ANSI ignored\n",
2469 This, idGroup, lpData, lpdwDataSize, bAnsi );
2471 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2473 return DPERR_INVALIDGROUP;
2476 dwRequiredDataSize = lpGData->name.dwSize;
2478 if( lpGData->name.u1.lpszShortNameA )
2480 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
2483 if( lpGData->name.u2.lpszLongNameA )
2485 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
2488 if( ( lpData == NULL ) ||
2489 ( *lpdwDataSize < dwRequiredDataSize )
2492 *lpdwDataSize = dwRequiredDataSize;
2493 return DPERR_BUFFERTOOSMALL;
2496 /* Copy the structure */
2497 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2499 if( lpGData->name.u1.lpszShortNameA )
2501 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2502 lpGData->name.u1.lpszShortNameA );
2504 else
2506 lpName->u1.lpszShortNameA = NULL;
2509 if( lpGData->name.u1.lpszShortNameA )
2511 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2512 lpGData->name.u2.lpszLongNameA );
2514 else
2516 lpName->u2.lpszLongNameA = NULL;
2519 return DP_OK;
2522 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2523 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2524 LPDWORD lpdwDataSize )
2526 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2527 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2530 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2531 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2532 LPDWORD lpdwDataSize )
2534 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2535 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2538 static HRESULT WINAPI DP_IF_GetMessageCount
2539 ( IDirectPlay2Impl* This, DPID idPlayer,
2540 LPDWORD lpdwCount, BOOL bAnsi )
2542 FIXME("(%p)->(0x%08x,%p,%u): stub\n", This, idPlayer, lpdwCount, bAnsi );
2543 return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer,
2544 DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL,
2545 bAnsi );
2548 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2549 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDWORD lpdwCount )
2551 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2552 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, TRUE );
2555 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2556 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDWORD lpdwCount )
2558 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2559 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, FALSE );
2562 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2563 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2565 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2566 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2567 return DP_OK;
2570 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2571 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2573 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2574 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2575 return DP_OK;
2578 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2579 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2580 DWORD dwFlags )
2582 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2583 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2586 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2587 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2588 DWORD dwFlags )
2590 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2591 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2594 static HRESULT WINAPI DP_IF_GetPlayerData
2595 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2596 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2598 lpPlayerList lpPList;
2599 DWORD dwRequiredBufferSize;
2600 LPVOID lpCopyDataFrom;
2602 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2603 This, idPlayer, lpData, lpdwDataSize, dwFlags, bAnsi );
2605 if( This->dp2->connectionInitialized == NO_PROVIDER )
2607 return DPERR_UNINITIALIZED;
2610 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2612 return DPERR_INVALIDPLAYER;
2615 /* How much buffer is required? */
2616 if( dwFlags & DPSET_LOCAL )
2618 dwRequiredBufferSize = lpPList->lpPData->dwLocalDataSize;
2619 lpCopyDataFrom = lpPList->lpPData->lpLocalData;
2621 else
2623 dwRequiredBufferSize = lpPList->lpPData->dwRemoteDataSize;
2624 lpCopyDataFrom = lpPList->lpPData->lpRemoteData;
2627 /* Is the user requesting to know how big a buffer is required? */
2628 if( ( lpData == NULL ) ||
2629 ( *lpdwDataSize < dwRequiredBufferSize )
2632 *lpdwDataSize = dwRequiredBufferSize;
2633 return DPERR_BUFFERTOOSMALL;
2636 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2638 return DP_OK;
2641 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2642 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2643 LPDWORD lpdwDataSize, DWORD dwFlags )
2645 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2646 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2647 dwFlags, TRUE );
2650 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2651 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2652 LPDWORD lpdwDataSize, DWORD dwFlags )
2654 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2655 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2656 dwFlags, FALSE );
2659 static HRESULT WINAPI DP_IF_GetPlayerName
2660 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2661 LPDWORD lpdwDataSize, BOOL bAnsi )
2663 lpPlayerList lpPList;
2664 LPDPNAME lpName = (LPDPNAME)lpData;
2665 DWORD dwRequiredDataSize;
2667 FIXME( "(%p)->(0x%08x,%p,%p,%u): ANSI\n",
2668 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2670 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2672 return DPERR_INVALIDPLAYER;
2675 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
2677 if( lpPList->lpPData->name.u1.lpszShortNameA )
2679 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
2682 if( lpPList->lpPData->name.u2.lpszLongNameA )
2684 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
2687 if( ( lpData == NULL ) ||
2688 ( *lpdwDataSize < dwRequiredDataSize )
2691 *lpdwDataSize = dwRequiredDataSize;
2692 return DPERR_BUFFERTOOSMALL;
2695 /* Copy the structure */
2696 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
2698 if( lpPList->lpPData->name.u1.lpszShortNameA )
2700 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2701 lpPList->lpPData->name.u1.lpszShortNameA );
2703 else
2705 lpName->u1.lpszShortNameA = NULL;
2708 if( lpPList->lpPData->name.u1.lpszShortNameA )
2710 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2711 lpPList->lpPData->name.u2.lpszLongNameA );
2713 else
2715 lpName->u2.lpszLongNameA = NULL;
2718 return DP_OK;
2721 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2722 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2723 LPDWORD lpdwDataSize )
2725 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2726 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
2729 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2730 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2731 LPDWORD lpdwDataSize )
2733 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2734 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
2737 static HRESULT WINAPI DP_GetSessionDesc
2738 ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize,
2739 BOOL bAnsi )
2741 DWORD dwRequiredSize;
2743 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
2745 if( This->dp2->connectionInitialized == NO_PROVIDER )
2747 return DPERR_UNINITIALIZED;
2750 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
2752 return DPERR_INVALIDPARAMS;
2755 /* FIXME: Get from This->dp2->lpSessionDesc */
2756 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
2758 if ( ( lpData == NULL ) ||
2759 ( *lpdwDataSize < dwRequiredSize )
2762 *lpdwDataSize = dwRequiredSize;
2763 return DPERR_BUFFERTOOSMALL;
2766 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
2768 return DP_OK;
2771 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
2772 ( LPDIRECTPLAY2A iface, LPVOID lpData, LPDWORD lpdwDataSize )
2774 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2775 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2778 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
2779 ( LPDIRECTPLAY2 iface, LPVOID lpData, LPDWORD lpdwDataSize )
2781 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2782 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2785 /* Intended only for COM compatibility. Always returns an error. */
2786 static HRESULT WINAPI DirectPlay2AImpl_Initialize
2787 ( LPDIRECTPLAY2A iface, LPGUID lpGUID )
2789 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2790 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2791 return DPERR_ALREADYINITIALIZED;
2794 /* Intended only for COM compatibility. Always returns an error. */
2795 static HRESULT WINAPI DirectPlay2WImpl_Initialize
2796 ( LPDIRECTPLAY2 iface, LPGUID lpGUID )
2798 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2799 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2800 return DPERR_ALREADYINITIALIZED;
2804 static HRESULT WINAPI DP_SecureOpen
2805 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
2806 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
2807 BOOL bAnsi )
2809 HRESULT hr = DP_OK;
2811 FIXME( "(%p)->(%p,0x%08x,%p,%p): partial stub\n",
2812 This, lpsd, dwFlags, lpSecurity, lpCredentials );
2814 if( This->dp2->bConnectionOpen )
2816 TRACE( ": rejecting already open connection.\n" );
2817 return DPERR_ALREADYINITIALIZED;
2820 /* If we're enumerating, kill the thread */
2821 DP_KillEnumSessionThread( This );
2823 if( dwFlags & DPOPEN_CREATE )
2825 /* Rightoo - this computer is the host and the local computer needs to be
2826 the name server so that others can join this session */
2827 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
2829 This->dp2->bHostInterface = TRUE;
2831 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
2832 if( FAILED( hr ) )
2834 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
2835 return hr;
2839 /* Invoke the conditional callback for the service provider */
2840 if( This->dp2->spData.lpCB->Open )
2842 DPSP_OPENDATA data;
2844 FIXME( "Not all data fields are correct. Need new parameter\n" );
2846 data.bCreate = (dwFlags & DPOPEN_CREATE ) ? TRUE : FALSE;
2847 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
2848 : NS_GetNSAddr( This->dp2->lpNameServerData );
2849 data.lpISP = This->dp2->spData.lpISP;
2850 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) ? TRUE : FALSE;
2851 data.dwOpenFlags = dwFlags;
2852 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
2854 hr = (*This->dp2->spData.lpCB->Open)(&data);
2855 if( FAILED( hr ) )
2857 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
2858 return hr;
2863 /* Create the system group of which everything is a part of */
2864 DPID systemGroup = DPID_SYSTEM_GROUP;
2866 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
2867 NULL, 0, 0, TRUE );
2871 if( dwFlags & DPOPEN_JOIN )
2873 DPID dpidServerId = DPID_UNKNOWN;
2875 /* Create the server player for this interface. This way we can receive
2876 * messages for this session.
2878 /* FIXME: I suppose that we should be setting an event for a receive
2879 * type of thing. That way the messaging thread could know to wake
2880 * up. DPlay would then trigger the hEvent for the player the
2881 * message is directed to.
2883 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
2885 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
2888 else if( dwFlags & DPOPEN_CREATE )
2890 DPID dpidNameServerId = DPID_NAME_SERVER;
2892 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
2893 0, DPPLAYER_SERVERPLAYER, bAnsi );
2896 if( FAILED(hr) )
2898 ERR( "Couldn't create name server/system player: %s\n",
2899 DPLAYX_HresultToString(hr) );
2902 return hr;
2905 static HRESULT WINAPI DirectPlay2AImpl_Open
2906 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2908 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2909 TRACE("(%p)->(%p,0x%08x)\n", This, lpsd, dwFlags );
2910 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, TRUE );
2913 static HRESULT WINAPI DirectPlay2WImpl_Open
2914 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2916 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2917 TRACE("(%p)->(%p,0x%08x)\n", This, lpsd, dwFlags );
2918 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, FALSE );
2921 static HRESULT WINAPI DP_IF_Receive
2922 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
2923 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi )
2925 LPDPMSG lpMsg = NULL;
2927 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p,%u): stub\n",
2928 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
2930 if( This->dp2->connectionInitialized == NO_PROVIDER )
2932 return DPERR_UNINITIALIZED;
2935 if( dwFlags == 0 )
2937 dwFlags = DPRECEIVE_ALL;
2940 /* If the lpData is NULL, we must be peeking the message */
2941 if( ( lpData == NULL ) &&
2942 !( dwFlags & DPRECEIVE_PEEK )
2945 return DPERR_INVALIDPARAMS;
2948 if( dwFlags & DPRECEIVE_ALL )
2950 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
2952 if( !( dwFlags & DPRECEIVE_PEEK ) )
2954 FIXME( "Remove from queue\n" );
2957 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
2958 ( dwFlags & DPRECEIVE_FROMPLAYER )
2961 FIXME( "Find matching message 0x%08x\n", dwFlags );
2963 else
2965 ERR( "Hmmm..dwFlags 0x%08x\n", dwFlags );
2968 if( lpMsg == NULL )
2970 return DPERR_NOMESSAGES;
2973 /* Copy into the provided buffer */
2974 CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
2976 return DP_OK;
2979 static HRESULT WINAPI DirectPlay2AImpl_Receive
2980 ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo,
2981 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
2983 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2984 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
2985 lpData, lpdwDataSize, TRUE );
2988 static HRESULT WINAPI DirectPlay2WImpl_Receive
2989 ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo,
2990 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
2992 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2993 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
2994 lpData, lpdwDataSize, FALSE );
2997 static HRESULT WINAPI DirectPlay2AImpl_Send
2998 ( LPDIRECTPLAY2A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3000 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3001 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3002 0, 0, NULL, NULL, TRUE );
3005 static HRESULT WINAPI DirectPlay2WImpl_Send
3006 ( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3008 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3009 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3010 0, 0, NULL, NULL, FALSE );
3013 static HRESULT WINAPI DP_IF_SetGroupData
3014 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
3015 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3017 lpGroupData lpGData;
3019 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3020 This, idGroup, lpData, dwDataSize, dwFlags, bAnsi );
3022 /* Parameter check */
3023 if( ( lpData == NULL ) &&
3024 ( dwDataSize != 0 )
3027 return DPERR_INVALIDPARAMS;
3030 /* Find the pointer to the data for this player */
3031 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3033 return DPERR_INVALIDOBJECT;
3036 if( !(dwFlags & DPSET_LOCAL) )
3038 FIXME( "Was this group created by this interface?\n" );
3039 /* FIXME: If this is a remote update need to allow it but not
3040 * send a message.
3044 DP_SetGroupData( lpGData, dwFlags, lpData, dwDataSize );
3046 /* FIXME: Only send a message if this group is local to the session otherwise
3047 * it will have been rejected above
3049 if( !(dwFlags & DPSET_LOCAL) )
3051 FIXME( "Send msg?\n" );
3054 return DP_OK;
3057 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
3058 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
3059 DWORD dwDataSize, DWORD dwFlags )
3061 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3062 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, TRUE );
3065 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
3066 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
3067 DWORD dwDataSize, DWORD dwFlags )
3069 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3070 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, FALSE );
3073 static HRESULT WINAPI DP_IF_SetGroupName
3074 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
3075 DWORD dwFlags, BOOL bAnsi )
3077 lpGroupData lpGData;
3079 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n", This, idGroup,
3080 lpGroupName, dwFlags, bAnsi );
3082 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3084 return DPERR_INVALIDGROUP;
3087 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
3089 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3090 FIXME( "Message not sent and dwFlags ignored\n" );
3092 return DP_OK;
3095 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
3096 ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName,
3097 DWORD dwFlags )
3099 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3100 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
3103 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
3104 ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName,
3105 DWORD dwFlags )
3107 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3108 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
3111 static HRESULT WINAPI DP_IF_SetPlayerData
3112 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
3113 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3115 lpPlayerList lpPList;
3117 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3118 This, idPlayer, lpData, dwDataSize, dwFlags, bAnsi );
3120 /* Parameter check */
3121 if( ( lpData == NULL ) &&
3122 ( dwDataSize != 0 )
3125 return DPERR_INVALIDPARAMS;
3128 /* Find the pointer to the data for this player */
3129 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3131 return DPERR_INVALIDPLAYER;
3134 if( !(dwFlags & DPSET_LOCAL) )
3136 FIXME( "Was this group created by this interface?\n" );
3137 /* FIXME: If this is a remote update need to allow it but not
3138 * send a message.
3142 DP_SetPlayerData( lpPList->lpPData, dwFlags, lpData, dwDataSize );
3144 if( !(dwFlags & DPSET_LOCAL) )
3146 FIXME( "Send msg?\n" );
3149 return DP_OK;
3152 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3153 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
3154 DWORD dwDataSize, DWORD dwFlags )
3156 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3157 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3158 dwFlags, TRUE );
3161 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3162 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
3163 DWORD dwDataSize, DWORD dwFlags )
3165 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3166 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3167 dwFlags, FALSE );
3170 static HRESULT WINAPI DP_IF_SetPlayerName
3171 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
3172 DWORD dwFlags, BOOL bAnsi )
3174 lpPlayerList lpPList;
3176 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n",
3177 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3179 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3181 return DPERR_INVALIDGROUP;
3184 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3186 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3187 FIXME( "Message not sent and dwFlags ignored\n" );
3189 return DP_OK;
3192 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3193 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName,
3194 DWORD dwFlags )
3196 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3197 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3200 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3201 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName,
3202 DWORD dwFlags )
3204 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3205 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3208 static HRESULT WINAPI DP_SetSessionDesc
3209 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
3210 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3212 DWORD dwRequiredSize;
3213 LPDPSESSIONDESC2 lpTempSessDesc;
3215 TRACE( "(%p)->(%p,0x%08x,%u,%u)\n",
3216 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3218 if( This->dp2->connectionInitialized == NO_PROVIDER )
3220 return DPERR_UNINITIALIZED;
3223 if( dwFlags )
3225 return DPERR_INVALIDPARAMS;
3228 /* Only the host is allowed to update the session desc */
3229 if( !This->dp2->bHostInterface )
3231 return DPERR_ACCESSDENIED;
3234 /* FIXME: Copy into This->dp2->lpSessionDesc */
3235 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3236 lpTempSessDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize );
3238 if( lpTempSessDesc == NULL )
3240 return DPERR_OUTOFMEMORY;
3243 /* Free the old */
3244 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3246 This->dp2->lpSessionDesc = lpTempSessDesc;
3247 if( bInitial )
3249 /*Initializing session GUID*/
3250 CoCreateGuid( &(This->dp2->lpSessionDesc->guidInstance) );
3252 /* Set the new */
3253 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3255 /* If this is an external invocation of the interface, we should be
3256 * letting everyone know that things have changed. Otherwise this is
3257 * just an initialization and it doesn't need to be propagated.
3259 if( !bInitial )
3261 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3264 return DP_OK;
3267 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3268 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3270 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3271 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3274 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3275 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3277 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3278 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3281 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3282 DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3284 DWORD dwSize = 0;
3286 if( lpSessDesc == NULL )
3288 /* Hmmm..don't need any size? */
3289 ERR( "NULL lpSessDesc\n" );
3290 return dwSize;
3293 dwSize += sizeof( *lpSessDesc );
3295 if( bAnsi )
3297 if( lpSessDesc->u1.lpszSessionNameA )
3299 dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1;
3302 if( lpSessDesc->u2.lpszPasswordA )
3304 dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1;
3307 else /* UNICODE */
3309 if( lpSessDesc->u1.lpszSessionName )
3311 dwSize += sizeof( WCHAR ) *
3312 ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 );
3315 if( lpSessDesc->u2.lpszPassword )
3317 dwSize += sizeof( WCHAR ) *
3318 ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 );
3322 return dwSize;
3325 /* Assumes that contugous buffers are already allocated. */
3326 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3327 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3329 BYTE* lpStartOfFreeSpace;
3331 if( lpSessionDest == NULL )
3333 ERR( "NULL lpSessionDest\n" );
3334 return;
3337 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3339 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3341 if( bAnsi )
3343 if( lpSessionSrc->u1.lpszSessionNameA )
3345 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3346 lpSessionDest->u1.lpszSessionNameA );
3347 lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3348 lpStartOfFreeSpace +=
3349 lstrlenA( (LPSTR)lpSessionDest->u1.lpszSessionNameA ) + 1;
3352 if( lpSessionSrc->u2.lpszPasswordA )
3354 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3355 lpSessionDest->u2.lpszPasswordA );
3356 lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3357 lpStartOfFreeSpace +=
3358 lstrlenA( (LPSTR)lpSessionDest->u2.lpszPasswordA ) + 1;
3361 else /* UNICODE */
3363 if( lpSessionSrc->u1.lpszSessionName )
3365 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3366 lpSessionDest->u1.lpszSessionName );
3367 lpSessionDest->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3368 lpStartOfFreeSpace += sizeof(WCHAR) *
3369 ( lstrlenW( (LPWSTR)lpSessionDest->u1.lpszSessionName ) + 1 );
3372 if( lpSessionSrc->u2.lpszPassword )
3374 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3375 lpSessionDest->u2.lpszPassword );
3376 lpSessionDest->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3377 lpStartOfFreeSpace += sizeof(WCHAR) *
3378 ( lstrlenW( (LPWSTR)lpSessionDest->u2.lpszPassword ) + 1 );
3384 static HRESULT WINAPI DP_IF_AddGroupToGroup
3385 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3387 lpGroupData lpGParentData;
3388 lpGroupData lpGData;
3389 lpGroupList lpNewGList;
3391 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, idParentGroup, idGroup );
3393 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3395 return DPERR_INVALIDGROUP;
3398 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3400 return DPERR_INVALIDGROUP;
3403 /* Create a player list (ie "shortcut" ) */
3404 lpNewGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewGList ) );
3405 if( lpNewGList == NULL )
3407 return DPERR_CANTADDPLAYER;
3410 /* Add the shortcut */
3411 lpGData->uRef++;
3412 lpNewGList->lpGData = lpGData;
3414 /* Add the player to the list of players for this group */
3415 DPQ_INSERT( lpGData->groups, lpNewGList, groups );
3417 /* Send a ADDGROUPTOGROUP message */
3418 FIXME( "Not sending message\n" );
3420 return DP_OK;
3423 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3424 ( LPDIRECTPLAY3A iface, DPID idParentGroup, DPID idGroup )
3426 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3427 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3430 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3431 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3433 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3434 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3437 static HRESULT WINAPI DP_IF_CreateGroupInGroup
3438 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
3439 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
3440 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3442 lpGroupData lpGParentData;
3443 lpGroupList lpGList;
3444 lpGroupData lpGData;
3446 TRACE( "(%p)->(0x%08x,%p,%p,%p,0x%08x,0x%08x,%u)\n",
3447 This, idParentGroup, lpidGroup, lpGroupName, lpData,
3448 dwDataSize, dwFlags, bAnsi );
3450 /* Verify that the specified parent is valid */
3451 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This,
3452 idParentGroup ) ) == NULL
3455 return DPERR_INVALIDGROUP;
3458 lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName,
3459 dwFlags, idParentGroup, bAnsi );
3461 if( lpGData == NULL )
3463 return DPERR_CANTADDPLAYER; /* yes player not group */
3466 /* Something else is referencing this data */
3467 lpGData->uRef++;
3469 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
3471 /* The list has now been inserted into the interface group list. We now
3472 need to put a "shortcut" to this group in the parent group */
3473 lpGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGList ) );
3474 if( lpGList == NULL )
3476 FIXME( "Memory leak\n" );
3477 return DPERR_CANTADDPLAYER; /* yes player not group */
3480 lpGList->lpGData = lpGData;
3482 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
3484 /* Let the SP know that we've created this group */
3485 if( This->dp2->spData.lpCB->CreateGroup )
3487 DPSP_CREATEGROUPDATA data;
3489 TRACE( "Calling SP CreateGroup\n" );
3491 data.idGroup = *lpidGroup;
3492 data.dwFlags = dwFlags;
3493 data.lpSPMessageHeader = lpMsgHdr;
3494 data.lpISP = This->dp2->spData.lpISP;
3496 (*This->dp2->spData.lpCB->CreateGroup)( &data );
3499 /* Inform all other peers of the creation of a new group. If there are
3500 * no peers keep this quiet.
3502 if( This->dp2->lpSessionDesc &&
3503 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
3505 DPMSG_CREATEPLAYERORGROUP msg;
3507 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
3508 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
3509 msg.dpId = *lpidGroup;
3510 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
3511 msg.lpData = lpData;
3512 msg.dwDataSize = dwDataSize;
3513 msg.dpnName = *lpGroupName;
3515 /* FIXME: Correct to just use send effectively? */
3516 /* FIXME: Should size include data w/ message or just message "header" */
3517 /* FIXME: Check return code */
3518 DP_SendEx( (IDirectPlay2Impl*)This,
3519 DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
3520 0, 0, NULL, NULL, bAnsi );
3523 return DP_OK;
3526 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3527 ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup,
3528 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3529 DWORD dwFlags )
3531 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3533 *lpidGroup = DPID_UNKNOWN;
3535 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3536 lpGroupName, lpData, dwDataSize, dwFlags,
3537 TRUE );
3540 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3541 ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup,
3542 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3543 DWORD dwFlags )
3545 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3547 *lpidGroup = DPID_UNKNOWN;
3549 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3550 lpGroupName, lpData, dwDataSize,
3551 dwFlags, FALSE );
3554 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
3555 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3557 lpGroupList lpGList;
3558 lpGroupData lpGParentData;
3560 TRACE("(%p)->(0x%08x,0x%08x)\n", This, idParentGroup, idGroup );
3562 /* Is the parent group valid? */
3563 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3565 return DPERR_INVALIDGROUP;
3568 /* Remove the group from the parent group queue */
3569 DPQ_REMOVE_ENTRY( lpGParentData->groups, groups, lpGData->dpid, ==, idGroup, lpGList );
3571 if( lpGList == NULL )
3573 return DPERR_INVALIDGROUP;
3576 /* Decrement the ref count */
3577 lpGList->lpGData->uRef--;
3579 /* Free up the list item */
3580 HeapFree( GetProcessHeap(), 0, lpGList );
3582 /* Should send a DELETEGROUPFROMGROUP message */
3583 FIXME( "message not sent\n" );
3585 return DP_OK;
3588 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3589 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3591 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3592 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3595 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3596 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3598 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3599 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3602 static
3603 BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
3604 LPDWORD lpdwBufSize )
3606 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3607 HRESULT hr;
3609 dpCompoundAddress.dwDataSize = sizeof( GUID );
3610 memcpy( &dpCompoundAddress.guidDataType, &DPAID_ServiceProvider,
3611 sizeof( GUID ) ) ;
3612 dpCompoundAddress.lpData = lpcSpGuid;
3614 *lplpAddrBuf = NULL;
3615 *lpdwBufSize = 0;
3617 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3618 lpdwBufSize, TRUE );
3620 if( hr != DPERR_BUFFERTOOSMALL )
3622 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3623 return FALSE;
3626 /* Now allocate the buffer */
3627 *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3628 *lpdwBufSize );
3630 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3631 lpdwBufSize, TRUE );
3632 if( FAILED(hr) )
3634 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3635 return FALSE;
3638 return TRUE;
3641 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
3642 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3644 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3645 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3647 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
3648 if( dwFlags == 0 )
3650 dwFlags = DPCONNECTION_DIRECTPLAY;
3653 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
3654 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) )
3657 return DPERR_INVALIDFLAGS;
3660 if( !lpEnumCallback || !*lpEnumCallback )
3662 return DPERR_INVALIDPARAMS;
3665 /* Enumerate DirectPlay service providers */
3666 if( dwFlags & DPCONNECTION_DIRECTPLAY )
3668 HKEY hkResult;
3669 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3670 LPCSTR guidDataSubKey = "Guid";
3671 char subKeyName[51];
3672 DWORD dwIndex, sizeOfSubKeyName=50;
3673 FILETIME filetime;
3675 /* Need to loop over the service providers in the registry */
3676 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3677 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3679 /* Hmmm. Does this mean that there are no service providers? */
3680 ERR(": no service providers?\n");
3681 return DP_OK;
3685 /* Traverse all the service providers we have available */
3686 for( dwIndex=0;
3687 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3688 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3689 ++dwIndex, sizeOfSubKeyName=51 )
3692 HKEY hkServiceProvider;
3693 GUID serviceProviderGUID;
3694 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3695 char returnBuffer[51];
3696 WCHAR buff[51];
3697 DPNAME dpName;
3698 BOOL bBuildPass;
3700 LPVOID lpAddressBuffer = NULL;
3701 DWORD dwAddressBufferSize = 0;
3703 TRACE(" this time through: %s\n", subKeyName );
3705 /* Get a handle for this particular service provider */
3706 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3707 &hkServiceProvider ) != ERROR_SUCCESS )
3709 ERR(": what the heck is going on?\n" );
3710 continue;
3713 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3714 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
3715 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3717 ERR(": missing GUID registry data members\n" );
3718 continue;
3721 /* FIXME: Check return types to ensure we're interpreting data right */
3722 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3723 CLSIDFromString( buff, &serviceProviderGUID );
3724 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3726 /* Fill in the DPNAME struct for the service provider */
3727 dpName.dwSize = sizeof( dpName );
3728 dpName.dwFlags = 0;
3729 dpName.u1.lpszShortNameA = subKeyName;
3730 dpName.u2.lpszLongNameA = NULL;
3732 /* Create the compound address for the service provider.
3733 * NOTE: This is a gruesome architectural scar right now. DP
3734 * uses DPL and DPL uses DP. Nasty stuff. This may be why the
3735 * native dll just gets around this little bit by allocating an
3736 * 80 byte buffer which isn't even filled with a valid compound
3737 * address. Oh well. Creating a proper compound address is the
3738 * way to go anyways despite this method taking slightly more
3739 * heap space and realtime :) */
3741 bBuildPass = DP_BuildSPCompoundAddr( &serviceProviderGUID,
3742 &lpAddressBuffer,
3743 &dwAddressBufferSize );
3744 if( !bBuildPass )
3746 ERR( "Can't build compound addr\n" );
3747 return DPERR_GENERIC;
3750 /* The enumeration will return FALSE if we are not to continue */
3751 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3752 &dpName, DPCONNECTION_DIRECTPLAY, lpContext ) )
3754 return DP_OK;
3759 /* Enumerate DirectPlayLobby service providers */
3760 if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY )
3762 HKEY hkResult;
3763 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3764 LPCSTR guidDataSubKey = "Guid";
3765 char subKeyName[51];
3766 DWORD dwIndex, sizeOfSubKeyName=50;
3767 FILETIME filetime;
3769 /* Need to loop over the service providers in the registry */
3770 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3771 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3773 /* Hmmm. Does this mean that there are no service providers? */
3774 ERR(": no service providers?\n");
3775 return DP_OK;
3779 /* Traverse all the lobby providers we have available */
3780 for( dwIndex=0;
3781 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3782 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3783 ++dwIndex, sizeOfSubKeyName=51 )
3786 HKEY hkServiceProvider;
3787 GUID serviceProviderGUID;
3788 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3789 char returnBuffer[51];
3790 WCHAR buff[51];
3791 DPNAME dpName;
3792 HRESULT hr;
3794 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3795 LPVOID lpAddressBuffer = NULL;
3796 DWORD dwAddressBufferSize = 0;
3798 TRACE(" this time through: %s\n", subKeyName );
3800 /* Get a handle for this particular service provider */
3801 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3802 &hkServiceProvider ) != ERROR_SUCCESS )
3804 ERR(": what the heck is going on?\n" );
3805 continue;
3808 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3809 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
3810 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3812 ERR(": missing GUID registry data members\n" );
3813 continue;
3816 /* FIXME: Check return types to ensure we're interpreting data right */
3817 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3818 CLSIDFromString( buff, &serviceProviderGUID );
3819 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3821 /* Fill in the DPNAME struct for the service provider */
3822 dpName.dwSize = sizeof( dpName );
3823 dpName.dwFlags = 0;
3824 dpName.u1.lpszShortNameA = subKeyName;
3825 dpName.u2.lpszLongNameA = NULL;
3827 /* Create the compound address for the service provider.
3828 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
3829 nast stuff. This may be why the native dll just gets around this little bit by
3830 allocating an 80 byte buffer which isn't even a filled with a valid compound
3831 address. Oh well. Creating a proper compound address is the way to go anyways
3832 despite this method taking slightly more heap space and realtime :) */
3834 dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
3835 dpCompoundAddress.dwDataSize = sizeof( GUID );
3836 dpCompoundAddress.lpData = &serviceProviderGUID;
3838 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3839 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
3841 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3842 return hr;
3845 /* Now allocate the buffer */
3846 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
3848 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3849 &dwAddressBufferSize, TRUE ) ) != DP_OK )
3851 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3852 return hr;
3855 /* The enumeration will return FALSE if we are not to continue */
3856 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3857 &dpName, DPCONNECTION_DIRECTPLAYLOBBY, lpContext ) )
3859 return DP_OK;
3864 return DP_OK;
3867 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
3868 ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3870 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3871 FIXME("(%p)->(%p,%p,%p,0x%08x): stub\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3872 return DP_OK;
3875 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
3876 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
3877 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
3878 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
3880 lpGroupList lpGList;
3881 lpGroupData lpGData;
3883 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
3884 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
3885 lpContext, dwFlags, bAnsi );
3887 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3889 return DPERR_INVALIDGROUP;
3892 if( DPQ_IS_EMPTY( lpGData->groups ) )
3894 return DP_OK;
3897 lpGList = DPQ_FIRST( lpGData->groups );
3899 for( ;; )
3901 /* FIXME: Should check dwFlags for match here */
3903 if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP,
3904 &lpGList->lpGData->name, dwFlags,
3905 lpContext ) )
3907 return DP_OK; /* User requested break */
3910 if( DPQ_IS_ENDOFLIST( lpGList->groups ) )
3912 break;
3915 lpGList = DPQ_NEXT( lpGList->groups );
3919 return DP_OK;
3922 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
3923 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3924 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3925 DWORD dwFlags )
3927 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3928 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3929 lpEnumPlayersCallback2, lpContext, dwFlags,
3930 TRUE );
3933 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
3934 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3935 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3936 DWORD dwFlags )
3938 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3939 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3940 lpEnumPlayersCallback2, lpContext, dwFlags,
3941 FALSE );
3944 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
3945 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3947 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3948 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3949 return DP_OK;
3952 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
3953 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3955 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3956 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3957 return DP_OK;
3960 static BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
3961 REFGUID guidDataType,
3962 DWORD dwDataSize,
3963 LPCVOID lpData,
3964 LPVOID lpContext )
3966 /* Looking for the GUID of the provider to load */
3967 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
3968 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
3971 TRACE( "Found SP/LP (%s) %s (data size = 0x%08x)\n",
3972 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
3974 if( dwDataSize != sizeof( GUID ) )
3976 ERR( "Invalid sp/lp guid size 0x%08x\n", dwDataSize );
3979 memcpy( lpContext, lpData, dwDataSize );
3981 /* There shouldn't be more than 1 GUID/compound address */
3982 return FALSE;
3985 /* Still waiting for what we want */
3986 return TRUE;
3990 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
3991 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
3993 UINT i;
3994 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3995 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3996 LPCSTR guidDataSubKey = "Guid";
3997 LPCSTR majVerDataSubKey = "dwReserved1";
3998 LPCSTR minVerDataSubKey = "dwReserved2";
3999 LPCSTR pathSubKey = "Path";
4001 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
4003 /* FIXME: Cloned code with a quick hack. */
4004 for( i=0; i<2; i++ )
4006 HKEY hkResult;
4007 LPCSTR searchSubKey;
4008 char subKeyName[51];
4009 DWORD dwIndex, sizeOfSubKeyName=50;
4010 FILETIME filetime;
4012 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
4013 *lpbIsDpSp = (i == 0) ? TRUE : FALSE;
4016 /* Need to loop over the service providers in the registry */
4017 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4018 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4020 /* Hmmm. Does this mean that there are no service providers? */
4021 ERR(": no service providers?\n");
4022 return 0;
4025 /* Traverse all the service providers we have available */
4026 for( dwIndex=0;
4027 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4028 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4029 ++dwIndex, sizeOfSubKeyName=51 )
4032 HKEY hkServiceProvider;
4033 GUID serviceProviderGUID;
4034 DWORD returnType, sizeOfReturnBuffer = 255;
4035 char returnBuffer[256];
4036 WCHAR buff[51];
4037 DWORD dwTemp, len;
4039 TRACE(" this time through: %s\n", subKeyName );
4041 /* Get a handle for this particular service provider */
4042 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4043 &hkServiceProvider ) != ERROR_SUCCESS )
4045 ERR(": what the heck is going on?\n" );
4046 continue;
4049 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4050 NULL, &returnType, (LPBYTE)returnBuffer,
4051 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4053 ERR(": missing GUID registry data members\n" );
4054 continue;
4057 /* FIXME: Check return types to ensure we're interpreting data right */
4058 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4059 CLSIDFromString( buff, &serviceProviderGUID );
4060 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4062 /* Determine if this is the Service Provider that the user asked for */
4063 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
4065 continue;
4068 if( i == 0 ) /* DP SP */
4070 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
4071 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
4072 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
4075 sizeOfReturnBuffer = 255;
4077 /* Get dwReserved1 */
4078 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
4079 NULL, &returnType, (LPBYTE)returnBuffer,
4080 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4082 ERR(": missing dwReserved1 registry data members\n") ;
4083 continue;
4086 if( i == 0 )
4087 memcpy( &lpSpData->dwReserved1, returnBuffer, sizeof(lpSpData->dwReserved1) );
4089 sizeOfReturnBuffer = 255;
4091 /* Get dwReserved2 */
4092 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4093 NULL, &returnType, (LPBYTE)returnBuffer,
4094 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4096 ERR(": missing dwReserved1 registry data members\n") ;
4097 continue;
4100 if( i == 0 )
4101 memcpy( &lpSpData->dwReserved2, returnBuffer, sizeof(lpSpData->dwReserved2) );
4103 sizeOfReturnBuffer = 255;
4105 /* Get the path for this service provider */
4106 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
4107 NULL, NULL, (LPBYTE)returnBuffer,
4108 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
4110 ERR(": missing PATH registry data members: 0x%08x\n", dwTemp );
4111 continue;
4114 TRACE( "Loading %s\n", returnBuffer );
4115 return LoadLibraryA( returnBuffer );
4119 return 0;
4122 static
4123 HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider )
4125 HRESULT hr;
4126 LPDPSP_SPINIT SPInit;
4128 /* Initialize the service provider by calling SPInit */
4129 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4131 if( SPInit == NULL )
4133 ERR( "Service provider doesn't provide SPInit interface?\n" );
4134 FreeLibrary( hServiceProvider );
4135 return DPERR_UNAVAILABLE;
4138 TRACE( "Calling SPInit (DP SP entry point)\n" );
4140 hr = (*SPInit)( &This->dp2->spData );
4142 if( FAILED(hr) )
4144 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4145 FreeLibrary( hServiceProvider );
4146 return hr;
4149 /* FIXME: Need to verify the sanity of the returned callback table
4150 * using IsBadCodePtr */
4151 This->dp2->bSPInitialized = TRUE;
4153 /* This interface is now initialized as a DP object */
4154 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
4156 /* Store the handle of the module so that we can unload it later */
4157 This->dp2->hServiceProvider = hServiceProvider;
4159 return hr;
4162 static
4163 HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hLobbyProvider )
4165 HRESULT hr;
4166 LPSP_INIT DPLSPInit;
4168 /* Initialize the service provider by calling SPInit */
4169 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
4171 if( DPLSPInit == NULL )
4173 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4174 FreeLibrary( hLobbyProvider );
4175 return DPERR_UNAVAILABLE;
4178 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4180 hr = (*DPLSPInit)( &This->dp2->dplspData );
4182 if( FAILED(hr) )
4184 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4185 FreeLibrary( hLobbyProvider );
4186 return hr;
4189 /* FIXME: Need to verify the sanity of the returned callback table
4190 * using IsBadCodePtr */
4192 This->dp2->bDPLSPInitialized = TRUE;
4194 /* This interface is now initialized as a lobby object */
4195 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
4197 /* Store the handle of the module so that we can unload it later */
4198 This->dp2->hDPLobbyProvider = hLobbyProvider;
4200 return hr;
4203 static HRESULT WINAPI DP_IF_InitializeConnection
4204 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi )
4206 HMODULE hServiceProvider;
4207 HRESULT hr;
4208 GUID guidSP;
4209 const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
4210 BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4212 TRACE("(%p)->(%p,0x%08x,%u)\n", This, lpConnection, dwFlags, bAnsi );
4214 if( dwFlags != 0 )
4216 return DPERR_INVALIDFLAGS;
4219 /* Find out what the requested SP is and how large this buffer is */
4220 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
4221 dwAddrSize, &guidSP );
4223 if( FAILED(hr) )
4225 ERR( "Invalid compound address?\n" );
4226 return DPERR_UNAVAILABLE;
4229 /* Load the service provider */
4230 hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp );
4232 if( hServiceProvider == 0 )
4234 ERR( "Unable to load service provider %s\n", debugstr_guid(&guidSP) );
4235 return DPERR_UNAVAILABLE;
4238 if( bIsDpSp )
4240 /* Fill in what we can of the Service Provider required information.
4241 * The rest was be done in DP_LoadSP
4243 This->dp2->spData.lpAddress = lpConnection;
4244 This->dp2->spData.dwAddressSize = dwAddrSize;
4245 This->dp2->spData.lpGuid = &guidSP;
4247 hr = DP_InitializeDPSP( This, hServiceProvider );
4249 else
4251 This->dp2->dplspData.lpAddress = lpConnection;
4253 hr = DP_InitializeDPLSP( This, hServiceProvider );
4256 if( FAILED(hr) )
4258 return hr;
4261 return DP_OK;
4264 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4265 ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
4267 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4269 /* This may not be externally invoked once either an SP or LP is initialized */
4270 if( This->dp2->connectionInitialized != NO_PROVIDER )
4272 return DPERR_ALREADYINITIALIZED;
4275 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE );
4278 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4279 ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
4281 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4283 /* This may not be externally invoked once either an SP or LP is initialized */
4284 if( This->dp2->connectionInitialized != NO_PROVIDER )
4286 return DPERR_ALREADYINITIALIZED;
4289 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE );
4292 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4293 ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4294 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4296 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4297 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4300 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4301 ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4302 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4304 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4305 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4308 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4309 ( LPDIRECTPLAY3A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4311 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4312 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4313 return DP_OK;
4316 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4317 ( LPDIRECTPLAY3 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4319 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4320 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4321 return DP_OK;
4324 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4325 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4327 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4328 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4329 return DP_OK;
4332 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4333 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4335 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4336 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4337 return DP_OK;
4340 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4341 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup )
4343 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4344 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, dwFlags, idGroup );
4345 return DP_OK;
4348 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4349 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup )
4351 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4352 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, dwFlags, idGroup );
4353 return DP_OK;
4356 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4357 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDWORD lpdwFlags )
4359 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4360 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpdwFlags );
4361 return DP_OK;
4364 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4365 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDWORD lpdwFlags )
4367 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4368 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpdwFlags );
4369 return DP_OK;
4372 static HRESULT WINAPI DP_IF_GetGroupParent
4373 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
4374 BOOL bAnsi )
4376 lpGroupData lpGData;
4378 TRACE("(%p)->(0x%08x,%p,%u)\n", This, idGroup, lpidGroup, bAnsi );
4380 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4382 return DPERR_INVALIDGROUP;
4385 *lpidGroup = lpGData->dpid;
4387 return DP_OK;
4390 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4391 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
4393 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4394 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE );
4396 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4397 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
4399 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4400 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE );
4403 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4404 ( LPDIRECTPLAY3A iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4406 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4407 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4408 return DP_OK;
4411 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4412 ( LPDIRECTPLAY3 iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4414 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4415 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4416 return DP_OK;
4419 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4420 ( LPDIRECTPLAY3A iface, DPID idPlayer, LPDWORD lpdwFlags )
4422 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4423 FIXME("(%p)->(0x%08x,%p): stub\n", This, idPlayer, lpdwFlags );
4424 return DP_OK;
4427 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4428 ( LPDIRECTPLAY3 iface, DPID idPlayer, LPDWORD lpdwFlags )
4430 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4431 FIXME("(%p)->(0x%08x,%p): stub\n", This, idPlayer, lpdwFlags );
4432 return DP_OK;
4435 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4436 ( LPDIRECTPLAY4A iface, DPID idGroup, LPDPID lpidGroupOwner )
4438 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4439 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpidGroupOwner );
4440 return DP_OK;
4443 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4444 ( LPDIRECTPLAY4 iface, DPID idGroup, LPDPID lpidGroupOwner )
4446 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4447 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpidGroupOwner );
4448 return DP_OK;
4451 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4452 ( LPDIRECTPLAY4A iface, DPID idGroup , DPID idGroupOwner )
4454 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4455 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, idGroup, idGroupOwner );
4456 return DP_OK;
4459 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4460 ( LPDIRECTPLAY4 iface, DPID idGroup , DPID idGroupOwner )
4462 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4463 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, idGroup, idGroupOwner );
4464 return DP_OK;
4467 static HRESULT WINAPI DP_SendEx
4468 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4469 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4470 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi )
4472 lpPlayerList lpPList;
4473 lpGroupData lpGData;
4474 BOOL bValidDestination = FALSE;
4476 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,0x%08x,0x%08x,0x%08x,%p,%p,%u)"
4477 ": stub\n",
4478 This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority,
4479 dwTimeout, lpContext, lpdwMsgID, bAnsi );
4481 /* FIXME: Add parameter checking */
4482 /* FIXME: First call to this needs to acquire a message id which will be
4483 * used for multiple sends
4486 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4488 /* Verify that the message is being sent from a valid local player. The
4489 * from player may be anonymous DPID_UNKNOWN
4491 if( idFrom != DPID_UNKNOWN )
4493 if( ( lpPList = DP_FindPlayer( This, idFrom ) ) == NULL )
4495 WARN( "INFO: Invalid from player 0x%08x\n", idFrom );
4496 return DPERR_INVALIDPLAYER;
4500 /* Verify that the message is being sent to a valid player, group or to
4501 * everyone. If it's valid, send it to those players.
4503 if( idTo == DPID_ALLPLAYERS )
4505 bValidDestination = TRUE;
4507 /* See if SP has the ability to multicast. If so, use it */
4508 if( This->dp2->spData.lpCB->SendToGroupEx )
4510 FIXME( "Use group sendex to group 0\n" );
4512 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4514 FIXME( "Use obsolete group send to group 0\n" );
4516 else /* No multicast, multiplicate */
4518 /* Send to all players we know about */
4519 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4523 if( ( !bValidDestination ) &&
4524 ( DP_FindPlayer( This, idTo ) != NULL )
4527 bValidDestination = TRUE;
4529 /* Have the service provider send this message */
4530 /* FIXME: Could optimize for local interface sends */
4531 return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority,
4532 dwTimeout, lpContext, lpdwMsgID );
4535 if( ( !bValidDestination ) &&
4536 ( ( lpGData = DP_FindAnyGroup( This, idTo ) ) != NULL )
4539 bValidDestination = TRUE;
4541 /* See if SP has the ability to multicast. If so, use it */
4542 if( This->dp2->spData.lpCB->SendToGroupEx )
4544 FIXME( "Use group sendex\n" );
4546 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4548 FIXME( "Use obsolete group send to group\n" );
4550 else /* No multicast, multiplicate */
4552 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4555 #if 0
4556 if( bExpectReply )
4558 DWORD dwWaitReturn;
4560 This->dp2->hReplyEvent = CreateEventW( NULL, FALSE, FALSE, NULL );
4562 dwWaitReturn = WaitForSingleObject( hReplyEvent, dwTimeout );
4563 if( dwWaitReturn != WAIT_OBJECT_0 )
4565 ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
4568 #endif
4571 if( !bValidDestination )
4573 return DPERR_INVALIDPLAYER;
4575 else
4577 /* FIXME: Should return what the send returned */
4578 return DP_OK;
4583 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4584 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4585 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4586 LPVOID lpContext, LPDWORD lpdwMsgID )
4588 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4589 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4590 dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE );
4593 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4594 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4595 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4596 LPVOID lpContext, LPDWORD lpdwMsgID )
4598 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4599 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4600 dwPriority, dwTimeout, lpContext, lpdwMsgID, FALSE );
4603 static HRESULT WINAPI DP_SP_SendEx
4604 ( IDirectPlay2Impl* This, DWORD dwFlags,
4605 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4606 LPVOID lpContext, LPDWORD lpdwMsgID )
4608 LPDPMSG lpMElem;
4610 FIXME( ": stub\n" );
4612 /* FIXME: This queuing should only be for async messages */
4614 lpMElem = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpMElem ) );
4615 lpMElem->msg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
4617 CopyMemory( lpMElem->msg, lpData, dwDataSize );
4619 /* FIXME: Need to queue based on priority */
4620 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
4622 return DP_OK;
4625 static HRESULT WINAPI DP_IF_GetMessageQueue
4626 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4627 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi )
4629 HRESULT hr = DP_OK;
4631 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%p,%u): semi stub\n",
4632 This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi );
4634 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4635 /* FIXME: What about sends which are not immediate? */
4637 if( This->dp2->spData.lpCB->GetMessageQueue )
4639 DPSP_GETMESSAGEQUEUEDATA data;
4641 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4643 /* FIXME: None of this is documented :( */
4645 data.lpISP = This->dp2->spData.lpISP;
4646 data.dwFlags = dwFlags;
4647 data.idFrom = idFrom;
4648 data.idTo = idTo;
4649 data.lpdwNumMsgs = lpdwNumMsgs;
4650 data.lpdwNumBytes = lpdwNumBytes;
4652 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
4654 else
4656 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4659 return hr;
4662 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4663 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4664 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4666 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4667 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4668 lpdwNumBytes, TRUE );
4671 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4672 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4673 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4675 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4676 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4677 lpdwNumBytes, FALSE );
4680 static HRESULT WINAPI DP_IF_CancelMessage
4681 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
4682 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi )
4684 HRESULT hr = DP_OK;
4686 FIXME( "(%p)->(0x%08x,0x%08x,%u): semi stub\n",
4687 This, dwMsgID, dwFlags, bAnsi );
4689 if( This->dp2->spData.lpCB->Cancel )
4691 DPSP_CANCELDATA data;
4693 TRACE( "Calling SP Cancel\n" );
4695 /* FIXME: Undocumented callback */
4697 data.lpISP = This->dp2->spData.lpISP;
4698 data.dwFlags = dwFlags;
4699 data.lprglpvSPMsgID = NULL;
4700 data.cSPMsgID = dwMsgID;
4701 data.dwMinPriority = dwMinPriority;
4702 data.dwMaxPriority = dwMaxPriority;
4704 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
4706 else
4708 FIXME( "SP doesn't implement Cancel\n" );
4711 return hr;
4714 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
4715 ( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags )
4717 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4719 if( dwFlags != 0 )
4721 return DPERR_INVALIDFLAGS;
4724 if( dwMsgID == 0 )
4726 dwFlags |= DPCANCELSEND_ALL;
4729 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE );
4732 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
4733 ( LPDIRECTPLAY4 iface, DWORD dwMsgID, DWORD dwFlags )
4735 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4737 if( dwFlags != 0 )
4739 return DPERR_INVALIDFLAGS;
4742 if( dwMsgID == 0 )
4744 dwFlags |= DPCANCELSEND_ALL;
4747 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, FALSE );
4750 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
4751 ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4752 DWORD dwFlags )
4754 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4756 if( dwFlags != 0 )
4758 return DPERR_INVALIDFLAGS;
4761 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4762 dwMaxPriority, TRUE );
4765 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
4766 ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4767 DWORD dwFlags )
4769 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4771 if( dwFlags != 0 )
4773 return DPERR_INVALIDFLAGS;
4776 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4777 dwMaxPriority, FALSE );
4780 /* Note: Hack so we can reuse the old functions without compiler warnings */
4781 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4782 # define XCAST(fun) (typeof(directPlay2WVT.fun))
4783 #else
4784 # define XCAST(fun) (void*)
4785 #endif
4787 static const IDirectPlay2Vtbl directPlay2WVT =
4789 XCAST(QueryInterface)DP_QueryInterface,
4790 XCAST(AddRef)DP_AddRef,
4791 XCAST(Release)DP_Release,
4793 DirectPlay2WImpl_AddPlayerToGroup,
4794 DirectPlay2WImpl_Close,
4795 DirectPlay2WImpl_CreateGroup,
4796 DirectPlay2WImpl_CreatePlayer,
4797 DirectPlay2WImpl_DeletePlayerFromGroup,
4798 DirectPlay2WImpl_DestroyGroup,
4799 DirectPlay2WImpl_DestroyPlayer,
4800 DirectPlay2WImpl_EnumGroupPlayers,
4801 DirectPlay2WImpl_EnumGroups,
4802 DirectPlay2WImpl_EnumPlayers,
4803 DirectPlay2WImpl_EnumSessions,
4804 DirectPlay2WImpl_GetCaps,
4805 DirectPlay2WImpl_GetGroupData,
4806 DirectPlay2WImpl_GetGroupName,
4807 DirectPlay2WImpl_GetMessageCount,
4808 DirectPlay2WImpl_GetPlayerAddress,
4809 DirectPlay2WImpl_GetPlayerCaps,
4810 DirectPlay2WImpl_GetPlayerData,
4811 DirectPlay2WImpl_GetPlayerName,
4812 DirectPlay2WImpl_GetSessionDesc,
4813 DirectPlay2WImpl_Initialize,
4814 DirectPlay2WImpl_Open,
4815 DirectPlay2WImpl_Receive,
4816 DirectPlay2WImpl_Send,
4817 DirectPlay2WImpl_SetGroupData,
4818 DirectPlay2WImpl_SetGroupName,
4819 DirectPlay2WImpl_SetPlayerData,
4820 DirectPlay2WImpl_SetPlayerName,
4821 DirectPlay2WImpl_SetSessionDesc
4823 #undef XCAST
4825 /* Note: Hack so we can reuse the old functions without compiler warnings */
4826 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4827 # define XCAST(fun) (typeof(directPlay2AVT.fun))
4828 #else
4829 # define XCAST(fun) (void*)
4830 #endif
4832 static const IDirectPlay2Vtbl directPlay2AVT =
4834 XCAST(QueryInterface)DP_QueryInterface,
4835 XCAST(AddRef)DP_AddRef,
4836 XCAST(Release)DP_Release,
4838 DirectPlay2AImpl_AddPlayerToGroup,
4839 DirectPlay2AImpl_Close,
4840 DirectPlay2AImpl_CreateGroup,
4841 DirectPlay2AImpl_CreatePlayer,
4842 DirectPlay2AImpl_DeletePlayerFromGroup,
4843 DirectPlay2AImpl_DestroyGroup,
4844 DirectPlay2AImpl_DestroyPlayer,
4845 DirectPlay2AImpl_EnumGroupPlayers,
4846 DirectPlay2AImpl_EnumGroups,
4847 DirectPlay2AImpl_EnumPlayers,
4848 DirectPlay2AImpl_EnumSessions,
4849 DirectPlay2AImpl_GetCaps,
4850 DirectPlay2AImpl_GetGroupData,
4851 DirectPlay2AImpl_GetGroupName,
4852 DirectPlay2AImpl_GetMessageCount,
4853 DirectPlay2AImpl_GetPlayerAddress,
4854 DirectPlay2AImpl_GetPlayerCaps,
4855 DirectPlay2AImpl_GetPlayerData,
4856 DirectPlay2AImpl_GetPlayerName,
4857 DirectPlay2AImpl_GetSessionDesc,
4858 DirectPlay2AImpl_Initialize,
4859 DirectPlay2AImpl_Open,
4860 DirectPlay2AImpl_Receive,
4861 DirectPlay2AImpl_Send,
4862 DirectPlay2AImpl_SetGroupData,
4863 DirectPlay2AImpl_SetGroupName,
4864 DirectPlay2AImpl_SetPlayerData,
4865 DirectPlay2AImpl_SetPlayerName,
4866 DirectPlay2AImpl_SetSessionDesc
4868 #undef XCAST
4871 /* Note: Hack so we can reuse the old functions without compiler warnings */
4872 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4873 # define XCAST(fun) (typeof(directPlay3AVT.fun))
4874 #else
4875 # define XCAST(fun) (void*)
4876 #endif
4878 static const IDirectPlay3Vtbl directPlay3AVT =
4880 XCAST(QueryInterface)DP_QueryInterface,
4881 XCAST(AddRef)DP_AddRef,
4882 XCAST(Release)DP_Release,
4884 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
4885 XCAST(Close)DirectPlay2AImpl_Close,
4886 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
4887 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
4888 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
4889 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
4890 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
4891 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
4892 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
4893 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
4894 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
4895 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
4896 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
4897 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
4898 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
4899 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
4900 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
4901 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
4902 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
4903 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
4904 XCAST(Initialize)DirectPlay2AImpl_Initialize,
4905 XCAST(Open)DirectPlay2AImpl_Open,
4906 XCAST(Receive)DirectPlay2AImpl_Receive,
4907 XCAST(Send)DirectPlay2AImpl_Send,
4908 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
4909 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
4910 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
4911 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
4912 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
4914 DirectPlay3AImpl_AddGroupToGroup,
4915 DirectPlay3AImpl_CreateGroupInGroup,
4916 DirectPlay3AImpl_DeleteGroupFromGroup,
4917 DirectPlay3AImpl_EnumConnections,
4918 DirectPlay3AImpl_EnumGroupsInGroup,
4919 DirectPlay3AImpl_GetGroupConnectionSettings,
4920 DirectPlay3AImpl_InitializeConnection,
4921 DirectPlay3AImpl_SecureOpen,
4922 DirectPlay3AImpl_SendChatMessage,
4923 DirectPlay3AImpl_SetGroupConnectionSettings,
4924 DirectPlay3AImpl_StartSession,
4925 DirectPlay3AImpl_GetGroupFlags,
4926 DirectPlay3AImpl_GetGroupParent,
4927 DirectPlay3AImpl_GetPlayerAccount,
4928 DirectPlay3AImpl_GetPlayerFlags
4930 #undef XCAST
4932 /* Note: Hack so we can reuse the old functions without compiler warnings */
4933 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4934 # define XCAST(fun) (typeof(directPlay3WVT.fun))
4935 #else
4936 # define XCAST(fun) (void*)
4937 #endif
4938 static const IDirectPlay3Vtbl directPlay3WVT =
4940 XCAST(QueryInterface)DP_QueryInterface,
4941 XCAST(AddRef)DP_AddRef,
4942 XCAST(Release)DP_Release,
4944 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
4945 XCAST(Close)DirectPlay2WImpl_Close,
4946 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
4947 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
4948 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
4949 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
4950 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
4951 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
4952 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
4953 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
4954 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
4955 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
4956 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
4957 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
4958 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
4959 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
4960 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
4961 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
4962 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
4963 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
4964 XCAST(Initialize)DirectPlay2WImpl_Initialize,
4965 XCAST(Open)DirectPlay2WImpl_Open,
4966 XCAST(Receive)DirectPlay2WImpl_Receive,
4967 XCAST(Send)DirectPlay2WImpl_Send,
4968 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
4969 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
4970 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
4971 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
4972 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
4974 DirectPlay3WImpl_AddGroupToGroup,
4975 DirectPlay3WImpl_CreateGroupInGroup,
4976 DirectPlay3WImpl_DeleteGroupFromGroup,
4977 DirectPlay3WImpl_EnumConnections,
4978 DirectPlay3WImpl_EnumGroupsInGroup,
4979 DirectPlay3WImpl_GetGroupConnectionSettings,
4980 DirectPlay3WImpl_InitializeConnection,
4981 DirectPlay3WImpl_SecureOpen,
4982 DirectPlay3WImpl_SendChatMessage,
4983 DirectPlay3WImpl_SetGroupConnectionSettings,
4984 DirectPlay3WImpl_StartSession,
4985 DirectPlay3WImpl_GetGroupFlags,
4986 DirectPlay3WImpl_GetGroupParent,
4987 DirectPlay3WImpl_GetPlayerAccount,
4988 DirectPlay3WImpl_GetPlayerFlags
4990 #undef XCAST
4992 /* Note: Hack so we can reuse the old functions without compiler warnings */
4993 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4994 # define XCAST(fun) (typeof(directPlay4WVT.fun))
4995 #else
4996 # define XCAST(fun) (void*)
4997 #endif
4998 static const IDirectPlay4Vtbl directPlay4WVT =
5000 XCAST(QueryInterface)DP_QueryInterface,
5001 XCAST(AddRef)DP_AddRef,
5002 XCAST(Release)DP_Release,
5004 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
5005 XCAST(Close)DirectPlay2WImpl_Close,
5006 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
5007 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
5008 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
5009 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
5010 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5011 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5012 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5013 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5014 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5015 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5016 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5017 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5018 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5019 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5020 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5021 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5022 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5023 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5024 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5025 XCAST(Open)DirectPlay2WImpl_Open,
5026 XCAST(Receive)DirectPlay2WImpl_Receive,
5027 XCAST(Send)DirectPlay2WImpl_Send,
5028 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5029 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5030 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5031 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5032 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5034 XCAST(AddGroupToGroup)DirectPlay3WImpl_AddGroupToGroup,
5035 XCAST(CreateGroupInGroup)DirectPlay3WImpl_CreateGroupInGroup,
5036 XCAST(DeleteGroupFromGroup)DirectPlay3WImpl_DeleteGroupFromGroup,
5037 XCAST(EnumConnections)DirectPlay3WImpl_EnumConnections,
5038 XCAST(EnumGroupsInGroup)DirectPlay3WImpl_EnumGroupsInGroup,
5039 XCAST(GetGroupConnectionSettings)DirectPlay3WImpl_GetGroupConnectionSettings,
5040 XCAST(InitializeConnection)DirectPlay3WImpl_InitializeConnection,
5041 XCAST(SecureOpen)DirectPlay3WImpl_SecureOpen,
5042 XCAST(SendChatMessage)DirectPlay3WImpl_SendChatMessage,
5043 XCAST(SetGroupConnectionSettings)DirectPlay3WImpl_SetGroupConnectionSettings,
5044 XCAST(StartSession)DirectPlay3WImpl_StartSession,
5045 XCAST(GetGroupFlags)DirectPlay3WImpl_GetGroupFlags,
5046 XCAST(GetGroupParent)DirectPlay3WImpl_GetGroupParent,
5047 XCAST(GetPlayerAccount)DirectPlay3WImpl_GetPlayerAccount,
5048 XCAST(GetPlayerFlags)DirectPlay3WImpl_GetPlayerFlags,
5050 DirectPlay4WImpl_GetGroupOwner,
5051 DirectPlay4WImpl_SetGroupOwner,
5052 DirectPlay4WImpl_SendEx,
5053 DirectPlay4WImpl_GetMessageQueue,
5054 DirectPlay4WImpl_CancelMessage,
5055 DirectPlay4WImpl_CancelPriority
5057 #undef XCAST
5060 /* Note: Hack so we can reuse the old functions without compiler warnings */
5061 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5062 # define XCAST(fun) (typeof(directPlay4AVT.fun))
5063 #else
5064 # define XCAST(fun) (void*)
5065 #endif
5066 static const IDirectPlay4Vtbl directPlay4AVT =
5068 XCAST(QueryInterface)DP_QueryInterface,
5069 XCAST(AddRef)DP_AddRef,
5070 XCAST(Release)DP_Release,
5072 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
5073 XCAST(Close)DirectPlay2AImpl_Close,
5074 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
5075 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
5076 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
5077 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
5078 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
5079 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
5080 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
5081 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
5082 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
5083 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
5084 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
5085 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
5086 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5087 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5088 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5089 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5090 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5091 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5092 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5093 XCAST(Open)DirectPlay2AImpl_Open,
5094 XCAST(Receive)DirectPlay2AImpl_Receive,
5095 XCAST(Send)DirectPlay2AImpl_Send,
5096 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5097 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5098 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5099 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5100 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5102 XCAST(AddGroupToGroup)DirectPlay3AImpl_AddGroupToGroup,
5103 XCAST(CreateGroupInGroup)DirectPlay3AImpl_CreateGroupInGroup,
5104 XCAST(DeleteGroupFromGroup)DirectPlay3AImpl_DeleteGroupFromGroup,
5105 XCAST(EnumConnections)DirectPlay3AImpl_EnumConnections,
5106 XCAST(EnumGroupsInGroup)DirectPlay3AImpl_EnumGroupsInGroup,
5107 XCAST(GetGroupConnectionSettings)DirectPlay3AImpl_GetGroupConnectionSettings,
5108 XCAST(InitializeConnection)DirectPlay3AImpl_InitializeConnection,
5109 XCAST(SecureOpen)DirectPlay3AImpl_SecureOpen,
5110 XCAST(SendChatMessage)DirectPlay3AImpl_SendChatMessage,
5111 XCAST(SetGroupConnectionSettings)DirectPlay3AImpl_SetGroupConnectionSettings,
5112 XCAST(StartSession)DirectPlay3AImpl_StartSession,
5113 XCAST(GetGroupFlags)DirectPlay3AImpl_GetGroupFlags,
5114 XCAST(GetGroupParent)DirectPlay3AImpl_GetGroupParent,
5115 XCAST(GetPlayerAccount)DirectPlay3AImpl_GetPlayerAccount,
5116 XCAST(GetPlayerFlags)DirectPlay3AImpl_GetPlayerFlags,
5118 DirectPlay4AImpl_GetGroupOwner,
5119 DirectPlay4AImpl_SetGroupOwner,
5120 DirectPlay4AImpl_SendEx,
5121 DirectPlay4AImpl_GetMessageQueue,
5122 DirectPlay4AImpl_CancelMessage,
5123 DirectPlay4AImpl_CancelPriority
5125 #undef XCAST
5127 extern
5128 HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP,
5129 DPID idPlayer,
5130 LPVOID* lplpData )
5132 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5134 if( lpPlayer == NULL )
5136 return DPERR_INVALIDPLAYER;
5139 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
5141 return DP_OK;
5144 extern
5145 HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP,
5146 DPID idPlayer,
5147 LPVOID lpData )
5149 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5151 if( lpPlayer == NULL )
5153 return DPERR_INVALIDPLAYER;
5156 lpPlayer->lpPData->lpSPPlayerData = lpData;
5158 return DP_OK;
5161 /***************************************************************************
5162 * DirectPlayEnumerateAW
5164 * The pointer to the structure lpContext will be filled with the
5165 * appropriate data for each service offered by the OS. These services are
5166 * not necessarily available on this particular machine but are defined
5167 * as simple service providers under the "Service Providers" registry key.
5168 * This structure is then passed to lpEnumCallback for each of the different
5169 * services.
5171 * This API is useful only for applications written using DirectX3 or
5172 * worse. It is superseded by IDirectPlay3::EnumConnections which also
5173 * gives information on the actual connections.
5175 * defn of a service provider:
5176 * A dynamic-link library used by DirectPlay to communicate over a network.
5177 * The service provider contains all the network-specific code required
5178 * to send and receive messages. Online services and network operators can
5179 * supply service providers to use specialized hardware, protocols, communications
5180 * media, and network resources.
5183 static HRESULT DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA,
5184 LPDPENUMDPCALLBACKW lpEnumCallbackW,
5185 LPVOID lpContext)
5187 HKEY hkResult;
5188 static const WCHAR searchSubKey[] = {
5189 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
5190 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
5191 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
5192 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
5193 static const WCHAR guidKey[] = { 'G', 'u', 'i', 'd', 0 };
5194 static const WCHAR descW[] = { 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', 'W', 0 };
5196 DWORD dwIndex;
5197 FILETIME filetime;
5199 char *descriptionA = NULL;
5200 DWORD max_sizeOfDescriptionA = 0;
5201 WCHAR *descriptionW = NULL;
5202 DWORD max_sizeOfDescriptionW = 0;
5204 if (!lpEnumCallbackA && !lpEnumCallbackW)
5206 return DPERR_INVALIDPARAMS;
5209 /* Need to loop over the service providers in the registry */
5210 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, searchSubKey,
5211 0, KEY_READ, &hkResult) != ERROR_SUCCESS)
5213 /* Hmmm. Does this mean that there are no service providers? */
5214 ERR(": no service provider key in the registry - check your Wine installation !!!\n");
5215 return DPERR_GENERIC;
5218 /* Traverse all the service providers we have available */
5219 dwIndex = 0;
5220 while (1)
5222 WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */
5223 DWORD sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR);
5224 HKEY hkServiceProvider;
5225 GUID serviceProviderGUID;
5226 WCHAR guidKeyContent[(2 * 16) + 1 + 6 /* This corresponds to '{....-..-..-..-......}' */ ];
5227 DWORD sizeOfGuidKeyContent = sizeof(guidKeyContent);
5228 LONG ret_value;
5230 ret_value = RegEnumKeyExW(hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
5231 NULL, NULL, NULL, &filetime);
5232 if (ret_value == ERROR_NO_MORE_ITEMS)
5233 break;
5234 else if (ret_value != ERROR_SUCCESS)
5236 ERR(": could not enumerate on service provider key.\n");
5237 return DPERR_EXCEPTION;
5239 TRACE(" this time through sub-key %s.\n", debugstr_w(subKeyName));
5241 /* Open the key for this service provider */
5242 if (RegOpenKeyExW(hkResult, subKeyName, 0, KEY_READ, &hkServiceProvider) != ERROR_SUCCESS)
5244 ERR(": could not open registry key for service provider %s.\n", debugstr_w(subKeyName));
5245 continue;
5248 /* Get the GUID from the registry */
5249 if (RegQueryValueExW(hkServiceProvider, guidKey,
5250 NULL, NULL, (LPBYTE) guidKeyContent, &sizeOfGuidKeyContent) != ERROR_SUCCESS)
5252 ERR(": missing GUID registry data member for service provider %s.\n", debugstr_w(subKeyName));
5253 continue;
5255 if (sizeOfGuidKeyContent != sizeof(guidKeyContent))
5257 ERR(": invalid format for the GUID registry data member for service provider %s (%s).\n", debugstr_w(subKeyName), debugstr_w(guidKeyContent));
5258 continue;
5260 CLSIDFromString(guidKeyContent, &serviceProviderGUID );
5262 /* The enumeration will return FALSE if we are not to continue.
5264 * Note: on my windows box, major / minor version is 6 / 0 for all service providers
5265 * and have no relations to any of the two dwReserved1 and dwReserved2 keys.
5266 * I think that it simply means that they are in-line with DirectX 6.0
5268 if (lpEnumCallbackA)
5270 DWORD sizeOfDescription = 0;
5272 /* Note that this the the A case of this function, so use the A variant to get the description string */
5273 if (RegQueryValueExA(hkServiceProvider, "DescriptionA",
5274 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5276 ERR(": missing 'DescriptionA' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5277 continue;
5279 if (sizeOfDescription > max_sizeOfDescriptionA)
5281 HeapFree(GetProcessHeap(), 0, descriptionA);
5282 max_sizeOfDescriptionA = sizeOfDescription;
5283 descriptionA = HeapAlloc(GetProcessHeap(), 0, max_sizeOfDescriptionA);
5285 descriptionA = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5286 RegQueryValueExA(hkServiceProvider, "DescriptionA",
5287 NULL, NULL, (LPBYTE) descriptionA, &sizeOfDescription);
5289 if (!lpEnumCallbackA(&serviceProviderGUID, descriptionA, 6, 0, lpContext))
5290 goto end;
5292 else
5294 DWORD sizeOfDescription = 0;
5296 if (RegQueryValueExW(hkServiceProvider, descW,
5297 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5299 ERR(": missing 'DescriptionW' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5300 continue;
5302 if (sizeOfDescription > max_sizeOfDescriptionW)
5304 HeapFree(GetProcessHeap(), 0, descriptionW);
5305 max_sizeOfDescriptionW = sizeOfDescription;
5306 descriptionW = HeapAlloc(GetProcessHeap(), 0, max_sizeOfDescriptionW);
5308 descriptionW = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5309 RegQueryValueExW(hkServiceProvider, descW,
5310 NULL, NULL, (LPBYTE) descriptionW, &sizeOfDescription);
5312 if (!lpEnumCallbackW(&serviceProviderGUID, descriptionW, 6, 0, lpContext))
5313 goto end;
5316 dwIndex++;
5319 end:
5320 HeapFree(GetProcessHeap(), 0, descriptionA);
5321 HeapFree(GetProcessHeap(), 0, descriptionW);
5323 return DP_OK;
5326 /***************************************************************************
5327 * DirectPlayEnumerate [DPLAYX.9]
5328 * DirectPlayEnumerateA [DPLAYX.2]
5330 HRESULT WINAPI DirectPlayEnumerateA(LPDPENUMDPCALLBACKA lpEnumCallback, LPVOID lpContext )
5332 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5334 return DirectPlayEnumerateAW(lpEnumCallback, NULL, lpContext);
5337 /***************************************************************************
5338 * DirectPlayEnumerateW [DPLAYX.3]
5340 HRESULT WINAPI DirectPlayEnumerateW(LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5342 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5344 return DirectPlayEnumerateAW(NULL, lpEnumCallback, lpContext);
5347 typedef struct tagCreateEnum
5349 LPVOID lpConn;
5350 LPCGUID lpGuid;
5351 } CreateEnumData, *lpCreateEnumData;
5353 /* Find and copy the matching connection for the SP guid */
5354 static BOOL CALLBACK cbDPCreateEnumConnections(
5355 LPCGUID lpguidSP,
5356 LPVOID lpConnection,
5357 DWORD dwConnectionSize,
5358 LPCDPNAME lpName,
5359 DWORD dwFlags,
5360 LPVOID lpContext)
5362 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5364 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5366 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5368 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5369 dwConnectionSize );
5370 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5372 /* Found the record that we were looking for */
5373 return FALSE;
5376 /* Haven't found what were looking for yet */
5377 return TRUE;
5381 /***************************************************************************
5382 * DirectPlayCreate [DPLAYX.1]
5385 HRESULT WINAPI DirectPlayCreate
5386 ( LPGUID lpGUID, LPDIRECTPLAY2 *lplpDP, IUnknown *pUnk)
5388 HRESULT hr;
5389 LPDIRECTPLAY3A lpDP3A;
5390 CreateEnumData cbData;
5392 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5394 if( pUnk != NULL )
5396 return CLASS_E_NOAGGREGATION;
5399 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5400 give them an IDirectPlay2A object and hope that doesn't cause problems */
5401 if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
5403 return DPERR_UNAVAILABLE;
5406 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
5408 /* The GUID_NULL means don't bind a service provider. Just return the
5409 interface as is */
5410 return DP_OK;
5413 /* Bind the desired service provider since lpGUID is non NULL */
5414 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
5416 /* We're going to use a DP3 interface */
5417 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
5418 (LPVOID*)&lpDP3A );
5419 if( FAILED(hr) )
5421 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
5422 return hr;
5425 cbData.lpConn = NULL;
5426 cbData.lpGuid = lpGUID;
5428 /* We were given a service provider, find info about it... */
5429 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
5430 &cbData, DPCONNECTION_DIRECTPLAY );
5431 if( ( FAILED(hr) ) ||
5432 ( cbData.lpConn == NULL )
5435 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
5436 IDirectPlayX_Release( lpDP3A );
5437 return DPERR_UNAVAILABLE;
5440 /* Initialize the service provider */
5441 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
5442 if( FAILED(hr) )
5444 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
5445 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5446 IDirectPlayX_Release( lpDP3A );
5447 return hr;
5450 /* Release our version of the interface now that we're done with it */
5451 IDirectPlayX_Release( lpDP3A );
5452 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5454 return DP_OK;