mshtml: Added DIID_DispHTMLDocument to QueryInterface.
[wine/testsucceed.git] / dlls / dplayx / dplay.c
blobd446f51897558ab0bdaa64723ac016608448ee20
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 );
246 This->unk->DP_lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectPlay2AImpl*->DirectPlayIUnknownData*->DP_lock");
248 return TRUE;
251 static BOOL DP_DestroyIUnknown( LPVOID lpDP )
253 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;
255 This->unk->DP_lock.DebugInfo->Spare[0] = 0;
256 DeleteCriticalSection( &This->unk->DP_lock );
257 HeapFree( GetProcessHeap(), 0, This->unk );
259 return TRUE;
262 static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
264 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;
266 This->dp2 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp2) ) );
267 if ( This->dp2 == NULL )
269 return FALSE;
272 This->dp2->bConnectionOpen = FALSE;
274 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
276 This->dp2->bHostInterface = FALSE;
278 DPQ_INIT(This->dp2->receiveMsgs);
279 DPQ_INIT(This->dp2->sendMsgs);
280 DPQ_INIT(This->dp2->replysExpected);
282 if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
284 /* FIXME: Memory leak */
285 return FALSE;
288 /* Provide an initial session desc with nothing in it */
289 This->dp2->lpSessionDesc = HeapAlloc( GetProcessHeap(),
290 HEAP_ZERO_MEMORY,
291 sizeof( *This->dp2->lpSessionDesc ) );
292 if( This->dp2->lpSessionDesc == NULL )
294 /* FIXME: Memory leak */
295 return FALSE;
297 This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc );
299 /* We are emulating a dp 6 implementation */
300 This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION;
302 This->dp2->spData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
303 sizeof( *This->dp2->spData.lpCB ) );
304 This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB );
305 This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION;
307 /* This is the pointer to the service provider */
308 if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP,
309 (LPVOID*)&This->dp2->spData.lpISP, This ) )
312 /* FIXME: Memory leak */
313 return FALSE;
316 /* Setup lobby provider information */
317 This->dp2->dplspData.dwSPVersion = DPSP_MAJORVERSION;
318 This->dp2->dplspData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
319 sizeof( *This->dp2->dplspData.lpCB ) );
320 This->dp2->dplspData.lpCB->dwSize = sizeof( *This->dp2->dplspData.lpCB );
322 if( FAILED( DPLSP_CreateInterface( &IID_IDPLobbySP,
323 (LPVOID*)&This->dp2->dplspData.lpISP, This ) )
326 /* FIXME: Memory leak */
327 return FALSE;
330 return TRUE;
333 /* Definition of the global function in dplayx_queue.h. #
334 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
335 DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
337 HeapFree( GetProcessHeap(), 0, elem );
340 /* Function to delete the list of groups with this interface. Needs to
341 * delete the group and player lists associated with this group as well
342 * as the group data associated with this group. It should not delete
343 * player data as that is shared with the top player list and will be
344 * deleted with that.
346 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList );
347 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList )
349 DPQ_DELETEQ( elem->lpGData->groups, groups,
350 lpGroupList, cbDeleteElemFromHeap );
351 DPQ_DELETEQ( elem->lpGData->players, players,
352 lpPlayerList, cbDeleteElemFromHeap );
353 HeapFree( GetProcessHeap(), 0, elem->lpGData );
354 HeapFree( GetProcessHeap(), 0, elem );
357 /* Function to delete the list of players with this interface. Needs to
358 * delete the player data for all players as well.
360 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList );
361 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList )
363 HeapFree( GetProcessHeap(), 0, elem->lpPData );
364 HeapFree( GetProcessHeap(), 0, elem );
367 static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
369 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;
371 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
373 TerminateThread( This->dp2->hEnumSessionThread, 0 );
374 CloseHandle( This->dp2->hEnumSessionThread );
377 /* Finish with the SP - have it shutdown */
378 if( This->dp2->spData.lpCB->ShutdownEx )
380 DPSP_SHUTDOWNDATA data;
382 TRACE( "Calling SP ShutdownEx\n" );
384 data.lpISP = This->dp2->spData.lpISP;
386 (*This->dp2->spData.lpCB->ShutdownEx)( &data );
388 else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
390 TRACE( "Calling obsolete SP Shutdown\n" );
391 (*This->dp2->spData.lpCB->Shutdown)();
394 /* Unload the SP (if it exists) */
395 if( This->dp2->hServiceProvider != 0 )
397 FreeLibrary( This->dp2->hServiceProvider );
400 /* Unload the Lobby Provider (if it exists) */
401 if( This->dp2->hDPLobbyProvider != 0 )
403 FreeLibrary( This->dp2->hDPLobbyProvider );
406 #if 0
407 DPQ_DELETEQ( This->dp2->players, players, lpPlayerList, cbDeletePlayerElem );
408 DPQ_DELETEQ( This->dp2->groups, groups, lpGroupList, cbDeleteGroupsElem );
409 #endif
411 /* FIXME: Need to delete receive and send msgs queue contents */
413 NS_DeleteSessionCache( This->dp2->lpNameServerData );
415 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
417 IDirectPlaySP_Release( This->dp2->spData.lpISP );
419 /* Delete the contents */
420 HeapFree( GetProcessHeap(), 0, This->dp2 );
422 return TRUE;
425 static BOOL DP_CreateDirectPlay3( LPVOID lpDP )
427 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;
429 This->dp3 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp3) ) );
430 if ( This->dp3 == NULL )
432 return FALSE;
435 return TRUE;
438 static BOOL DP_DestroyDirectPlay3( LPVOID lpDP )
440 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;
442 /* Delete the contents */
443 HeapFree( GetProcessHeap(), 0, This->dp3 );
445 return TRUE;
448 static BOOL DP_CreateDirectPlay4( LPVOID lpDP )
450 IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)lpDP;
452 This->dp4 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp4) ) );
453 if ( This->dp4 == NULL )
455 return FALSE;
458 return TRUE;
461 static BOOL DP_DestroyDirectPlay4( LPVOID lpDP )
463 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;
465 /* Delete the contents */
466 HeapFree( GetProcessHeap(), 0, This->dp4 );
468 return TRUE;
472 /* Create a new interface */
473 extern
474 HRESULT DP_CreateInterface
475 ( REFIID riid, LPVOID* ppvObj )
477 TRACE( " for %s\n", debugstr_guid( riid ) );
479 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
480 sizeof( IDirectPlay2Impl ) );
482 if( *ppvObj == NULL )
484 return DPERR_OUTOFMEMORY;
487 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
489 IDirectPlay2Impl *This = (IDirectPlay2Impl *)*ppvObj;
490 This->lpVtbl = &directPlay2WVT;
492 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
494 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)*ppvObj;
495 This->lpVtbl = &directPlay2AVT;
497 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
499 IDirectPlay3Impl *This = (IDirectPlay3Impl *)*ppvObj;
500 This->lpVtbl = &directPlay3WVT;
502 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
504 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)*ppvObj;
505 This->lpVtbl = &directPlay3AVT;
507 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
509 IDirectPlay4Impl *This = (IDirectPlay4Impl *)*ppvObj;
510 This->lpVtbl = &directPlay4WVT;
512 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
514 IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)*ppvObj;
515 This->lpVtbl = &directPlay4AVT;
517 else
519 /* Unsupported interface */
520 HeapFree( GetProcessHeap(), 0, *ppvObj );
521 *ppvObj = NULL;
523 return E_NOINTERFACE;
526 /* Initialize it */
527 if ( DP_CreateIUnknown( *ppvObj ) &&
528 DP_CreateDirectPlay2( *ppvObj ) &&
529 DP_CreateDirectPlay3( *ppvObj ) &&
530 DP_CreateDirectPlay4( *ppvObj )
533 IDirectPlayX_AddRef( (LPDIRECTPLAY2A)*ppvObj );
535 return S_OK;
538 /* Initialize failed, destroy it */
539 DP_DestroyDirectPlay4( *ppvObj );
540 DP_DestroyDirectPlay3( *ppvObj );
541 DP_DestroyDirectPlay2( *ppvObj );
542 DP_DestroyIUnknown( *ppvObj );
544 HeapFree( GetProcessHeap(), 0, *ppvObj );
546 *ppvObj = NULL;
547 return DPERR_NOMEMORY;
551 /* Direct Play methods */
553 /* Shared between all dplay types */
554 static HRESULT WINAPI DP_QueryInterface
555 ( LPDIRECTPLAY2 iface, REFIID riid, LPVOID* ppvObj )
557 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
558 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
560 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
561 sizeof( *This ) );
563 if( *ppvObj == NULL )
565 return DPERR_OUTOFMEMORY;
568 CopyMemory( *ppvObj, This, sizeof( *This ) );
569 (*(IDirectPlay2Impl**)ppvObj)->ulInterfaceRef = 0;
571 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
573 IDirectPlay2Impl *This = (IDirectPlay2Impl *)*ppvObj;
574 This->lpVtbl = &directPlay2WVT;
576 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
578 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)*ppvObj;
579 This->lpVtbl = &directPlay2AVT;
581 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
583 IDirectPlay3Impl *This = (IDirectPlay3Impl *)*ppvObj;
584 This->lpVtbl = &directPlay3WVT;
586 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
588 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)*ppvObj;
589 This->lpVtbl = &directPlay3AVT;
591 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
593 IDirectPlay4Impl *This = (IDirectPlay4Impl *)*ppvObj;
594 This->lpVtbl = &directPlay4WVT;
596 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
598 IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)*ppvObj;
599 This->lpVtbl = &directPlay4AVT;
601 else
603 /* Unsupported interface */
604 HeapFree( GetProcessHeap(), 0, *ppvObj );
605 *ppvObj = NULL;
607 return E_NOINTERFACE;
610 IDirectPlayX_AddRef( (LPDIRECTPLAY2)*ppvObj );
612 return S_OK;
615 /* Shared between all dplay types */
616 static ULONG WINAPI DP_AddRef
617 ( LPDIRECTPLAY3 iface )
619 ULONG ulInterfaceRefCount, ulObjRefCount;
620 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
622 ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
623 ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
625 TRACE( "ref count incremented to %u:%u for %p\n",
626 ulInterfaceRefCount, ulObjRefCount, This );
628 return ulObjRefCount;
631 static ULONG WINAPI DP_Release
632 ( LPDIRECTPLAY3 iface )
634 ULONG ulInterfaceRefCount, ulObjRefCount;
636 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
638 ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
639 ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
641 TRACE( "ref count decremented to %u:%u for %p\n",
642 ulInterfaceRefCount, ulObjRefCount, This );
644 /* Deallocate if this is the last reference to the object */
645 if( ulObjRefCount == 0 )
647 /* If we're destroying the object, this must be the last ref
648 of the last interface */
649 DP_DestroyDirectPlay4( This );
650 DP_DestroyDirectPlay3( This );
651 DP_DestroyDirectPlay2( This );
652 DP_DestroyIUnknown( This );
655 /* Deallocate the interface */
656 if( ulInterfaceRefCount == 0 )
658 HeapFree( GetProcessHeap(), 0, This );
661 return ulObjRefCount;
664 static inline DPID DP_NextObjectId(void)
666 return (DPID)InterlockedIncrement( &kludgePlayerGroupId );
669 /* *lplpReply will be non NULL iff there is something to reply */
670 HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpcMessageBody,
671 DWORD dwMessageBodySize, LPCVOID lpcMessageHeader,
672 WORD wCommandId, WORD wVersion,
673 LPVOID* lplpReply, LPDWORD lpdwMsgSize )
675 TRACE( "(%p)->(%p,0x%08x,%p,%u,%u)\n",
676 This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId,
677 wVersion );
679 switch( wCommandId )
681 /* Name server needs to handle this request */
682 case DPMSGCMD_ENUMSESSIONSREQUEST:
684 /* Reply expected */
685 NS_ReplyToEnumSessionsRequest( lpcMessageBody, lplpReply, lpdwMsgSize, This );
687 break;
690 /* Name server needs to handle this request */
691 case DPMSGCMD_ENUMSESSIONSREPLY:
693 /* No reply expected */
694 NS_AddRemoteComputerAsNameServer( lpcMessageHeader,
695 This->dp2->spData.dwSPHeaderSize,
696 lpcMessageBody,
697 This->dp2->lpNameServerData );
698 break;
701 case DPMSGCMD_REQUESTNEWPLAYERID:
703 LPCDPMSG_REQUESTNEWPLAYERID lpcMsg =
704 (LPCDPMSG_REQUESTNEWPLAYERID)lpcMessageBody;
706 LPDPMSG_NEWPLAYERIDREPLY lpReply;
708 *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
710 *lplpReply = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, *lpdwMsgSize );
712 FIXME( "Ignoring dwFlags 0x%08x in request msg\n",
713 lpcMsg->dwFlags );
715 /* Setup the reply */
716 lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) +
717 This->dp2->spData.dwSPHeaderSize );
719 lpReply->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
720 lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY;
721 lpReply->envelope.wVersion = DPMSGVER_DP6;
723 lpReply->dpidNewPlayerId = DP_NextObjectId();
725 TRACE( "Allocating new playerid 0x%08x from remote request\n",
726 lpReply->dpidNewPlayerId );
728 break;
731 case DPMSGCMD_GETNAMETABLEREPLY:
732 case DPMSGCMD_NEWPLAYERIDREPLY:
735 #if 0
736 if( wCommandId == DPMSGCMD_NEWPLAYERIDREPLY )
737 DebugBreak();
738 #endif
739 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
741 break;
744 #if 1
745 case DPMSGCMD_JUSTENVELOPE:
747 TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08x\n", lpcMessageHeader, ((const DWORD *)lpcMessageHeader)[1] );
748 NS_SetLocalAddr( This->dp2->lpNameServerData, lpcMessageHeader, 20 );
749 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
751 #endif
753 case DPMSGCMD_FORWARDADDPLAYER:
755 #if 0
756 DebugBreak();
757 #endif
758 #if 1
759 TRACE( "Sending message to self to get my addr\n" );
760 DP_MSG_ToSelf( This, 1 ); /* This is a hack right now */
761 #endif
762 break;
765 case DPMSGCMD_FORWARDADDPLAYERNACK:
767 DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
768 break;
771 default:
773 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
774 DebugBreak();
775 break;
779 /* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */
781 return DP_OK;
785 static HRESULT WINAPI DP_IF_AddPlayerToGroup
786 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
787 DPID idPlayer, BOOL bAnsi )
789 lpGroupData lpGData;
790 lpPlayerList lpPList;
791 lpPlayerList lpNewPList;
793 TRACE( "(%p)->(%p,0x%08x,0x%08x,%u)\n",
794 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
796 /* Find the group */
797 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
799 return DPERR_INVALIDGROUP;
802 /* Find the player */
803 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
805 return DPERR_INVALIDPLAYER;
808 /* Create a player list (ie "shortcut" ) */
809 lpNewPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewPList ) );
810 if( lpNewPList == NULL )
812 return DPERR_CANTADDPLAYER;
815 /* Add the shortcut */
816 lpPList->lpPData->uRef++;
817 lpNewPList->lpPData = lpPList->lpPData;
819 /* Add the player to the list of players for this group */
820 DPQ_INSERT(lpGData->players,lpNewPList,players);
822 /* Let the SP know that we've added a player to the group */
823 if( This->dp2->spData.lpCB->AddPlayerToGroup )
825 DPSP_ADDPLAYERTOGROUPDATA data;
827 TRACE( "Calling SP AddPlayerToGroup\n" );
829 data.idPlayer = idPlayer;
830 data.idGroup = idGroup;
831 data.lpISP = This->dp2->spData.lpISP;
833 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
836 /* Inform all other peers of the addition of player to the group. If there are
837 * no peers keep this event quiet.
838 * Also, if this event was the result of another machine sending it to us,
839 * don't bother rebroadcasting it.
841 if( ( lpMsgHdr == NULL ) &&
842 This->dp2->lpSessionDesc &&
843 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
845 DPMSG_ADDPLAYERTOGROUP msg;
846 msg.dwType = DPSYS_ADDPLAYERTOGROUP;
848 msg.dpIdGroup = idGroup;
849 msg.dpIdPlayer = idPlayer;
851 /* FIXME: Correct to just use send effectively? */
852 /* FIXME: Should size include data w/ message or just message "header" */
853 /* FIXME: Check return code */
854 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
857 return DP_OK;
860 static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
861 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
863 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
864 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, TRUE );
867 static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
868 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
870 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
871 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, FALSE );
874 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi )
876 HRESULT hr = DP_OK;
878 TRACE("(%p)->(%u)\n", This, bAnsi );
880 /* FIXME: Need to find a new host I assume (how?) */
881 /* FIXME: Need to destroy all local groups */
882 /* FIXME: Need to migrate all remotely visible players to the new host */
884 /* Invoke the SP callback to inform of session close */
885 if( This->dp2->spData.lpCB->CloseEx )
887 DPSP_CLOSEDATA data;
889 TRACE( "Calling SP CloseEx\n" );
891 data.lpISP = This->dp2->spData.lpISP;
893 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
896 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
898 TRACE( "Calling SP Close (obsolete interface)\n" );
900 hr = (*This->dp2->spData.lpCB->Close)();
903 return hr;
906 static HRESULT WINAPI DirectPlay2AImpl_Close
907 ( LPDIRECTPLAY2A iface )
909 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
910 return DP_IF_Close( This, TRUE );
913 static HRESULT WINAPI DirectPlay2WImpl_Close
914 ( LPDIRECTPLAY2 iface )
916 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
917 return DP_IF_Close( This, FALSE );
920 static
921 lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, LPDPID lpid,
922 LPDPNAME lpName, DWORD dwFlags,
923 DPID idParent, BOOL bAnsi )
925 lpGroupData lpGData;
927 /* Allocate the new space and add to end of high level group list */
928 lpGData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGData ) );
930 if( lpGData == NULL )
932 return NULL;
935 DPQ_INIT(lpGData->groups);
936 DPQ_INIT(lpGData->players);
938 /* Set the desired player ID - no sanity checking to see if it exists */
939 lpGData->dpid = *lpid;
941 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
943 /* FIXME: Should we check that the parent exists? */
944 lpGData->parent = idParent;
946 /* FIXME: Should we validate the dwFlags? */
947 lpGData->dwFlags = dwFlags;
949 TRACE( "Created group id 0x%08x\n", *lpid );
951 return lpGData;
954 /* This method assumes that all links to it are already deleted */
955 static void
956 DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid )
958 lpGroupList lpGList;
960 TRACE( "(%p)->(0x%08x)\n", This, dpid );
962 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
964 if( lpGList == NULL )
966 ERR( "DPID 0x%08x not found\n", dpid );
967 return;
970 if( --(lpGList->lpGData->uRef) )
972 FIXME( "Why is this not the last reference to group?\n" );
973 DebugBreak();
976 /* Delete player */
977 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
978 HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
980 /* Remove and Delete Player List object */
981 HeapFree( GetProcessHeap(), 0, lpGList );
985 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid )
987 lpGroupList lpGroups;
989 TRACE( "(%p)->(0x%08x)\n", This, dpid );
991 if( dpid == DPID_SYSTEM_GROUP )
993 return This->dp2->lpSysGroup;
995 else
997 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
1000 if( lpGroups == NULL )
1002 return NULL;
1005 return lpGroups->lpGData;
1008 static HRESULT WINAPI DP_IF_CreateGroup
1009 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
1010 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
1011 DWORD dwFlags, BOOL bAnsi )
1013 lpGroupData lpGData;
1015 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1016 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
1017 dwFlags, bAnsi );
1019 /* If the name is not specified, we must provide one */
1020 if( DPID_UNKNOWN == *lpidGroup )
1022 /* If we are the name server, we decide on the group ids. If not, we
1023 * must ask for one before attempting a creation.
1025 if( This->dp2->bHostInterface )
1027 *lpidGroup = DP_NextObjectId();
1029 else
1031 *lpidGroup = DP_GetRemoteNextObjectId();
1035 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
1036 DPID_NOPARENT_GROUP, bAnsi );
1038 if( lpGData == NULL )
1040 return DPERR_CANTADDPLAYER; /* yes player not group */
1043 if( DPID_SYSTEM_GROUP == *lpidGroup )
1045 This->dp2->lpSysGroup = lpGData;
1046 TRACE( "Inserting system group\n" );
1048 else
1050 /* Insert into the system group */
1051 lpGroupList lpGroup = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGroup ) );
1052 lpGroup->lpGData = lpGData;
1054 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
1057 /* Something is now referencing this data */
1058 lpGData->uRef++;
1060 /* Set all the important stuff for the group */
1061 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
1063 /* FIXME: We should only create the system group if GetCaps returns
1064 * DPCAPS_GROUPOPTIMIZED.
1067 /* Let the SP know that we've created this group */
1068 if( This->dp2->spData.lpCB->CreateGroup )
1070 DPSP_CREATEGROUPDATA data;
1071 DWORD dwCreateFlags = 0;
1073 TRACE( "Calling SP CreateGroup\n" );
1075 if( *lpidGroup == DPID_NOPARENT_GROUP )
1076 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
1078 if( lpMsgHdr == NULL )
1079 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1081 if( dwFlags & DPGROUP_HIDDEN )
1082 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
1084 data.idGroup = *lpidGroup;
1085 data.dwFlags = dwCreateFlags;
1086 data.lpSPMessageHeader = lpMsgHdr;
1087 data.lpISP = This->dp2->spData.lpISP;
1089 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1092 /* Inform all other peers of the creation of a new group. If there are
1093 * no peers keep this event quiet.
1094 * Also if this message was sent to us, don't rebroadcast.
1096 if( ( lpMsgHdr == NULL ) &&
1097 This->dp2->lpSessionDesc &&
1098 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1100 DPMSG_CREATEPLAYERORGROUP msg;
1101 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1103 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1104 msg.dpId = *lpidGroup;
1105 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1106 msg.lpData = lpData;
1107 msg.dwDataSize = dwDataSize;
1108 msg.dpnName = *lpGroupName;
1109 msg.dpIdParent = DPID_NOPARENT_GROUP;
1110 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
1112 /* FIXME: Correct to just use send effectively? */
1113 /* FIXME: Should size include data w/ message or just message "header" */
1114 /* FIXME: Check return code */
1115 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
1116 0, 0, NULL, NULL, bAnsi );
1119 return DP_OK;
1122 static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
1123 ( LPDIRECTPLAY2A iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1124 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1126 *lpidGroup = DPID_UNKNOWN;
1128 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1129 lpGroupName, lpData, dwDataSize, dwFlags, TRUE );
1132 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
1133 ( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1134 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1136 *lpidGroup = DPID_UNKNOWN;
1138 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1139 lpGroupName, lpData, dwDataSize, dwFlags, FALSE );
1143 static void
1144 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
1145 LPVOID lpData, DWORD dwDataSize )
1147 /* Clear out the data with this player */
1148 if( dwFlags & DPSET_LOCAL )
1150 if ( lpGData->dwLocalDataSize != 0 )
1152 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
1153 lpGData->lpLocalData = NULL;
1154 lpGData->dwLocalDataSize = 0;
1157 else
1159 if( lpGData->dwRemoteDataSize != 0 )
1161 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
1162 lpGData->lpRemoteData = NULL;
1163 lpGData->dwRemoteDataSize = 0;
1167 /* Reallocate for new data */
1168 if( lpData != NULL )
1170 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1171 sizeof( dwDataSize ) );
1172 CopyMemory( lpNewData, lpData, dwDataSize );
1174 if( dwFlags & DPSET_LOCAL )
1176 lpGData->lpLocalData = lpData;
1177 lpGData->dwLocalDataSize = dwDataSize;
1179 else
1181 lpGData->lpRemoteData = lpNewData;
1182 lpGData->dwRemoteDataSize = dwDataSize;
1188 /* This function will just create the storage for the new player. */
1189 static
1190 lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid,
1191 LPDPNAME lpName, DWORD dwFlags,
1192 HANDLE hEvent, BOOL bAnsi )
1194 lpPlayerData lpPData;
1196 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
1198 /* Allocate the storage for the player and associate it with list element */
1199 lpPData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPData ) );
1200 if( lpPData == NULL )
1202 return NULL;
1205 /* Set the desired player ID */
1206 lpPData->dpid = *lpid;
1208 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
1210 lpPData->dwFlags = dwFlags;
1212 /* If we were given an event handle, duplicate it */
1213 if( hEvent != 0 )
1215 if( !DuplicateHandle( GetCurrentProcess(), hEvent,
1216 GetCurrentProcess(), &lpPData->hEvent,
1217 0, FALSE, DUPLICATE_SAME_ACCESS )
1220 /* FIXME: Memory leak */
1221 ERR( "Can't duplicate player msg handle %p\n", hEvent );
1225 /* Initialize the SP data section */
1226 lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData();
1228 TRACE( "Created player id 0x%08x\n", *lpid );
1230 if( ~dwFlags & DPLAYI_PLAYER_SYSPLAYER )
1231 This->dp2->lpSessionDesc->dwCurrentPlayers++;
1233 return lpPData;
1236 /* Delete the contents of the DPNAME struct */
1237 static void
1238 DP_DeleteDPNameStruct( LPDPNAME lpDPName )
1240 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u1.lpszShortNameA );
1241 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u2.lpszLongNameA );
1244 /* This method assumes that all links to it are already deleted */
1245 static void
1246 DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid )
1248 lpPlayerList lpPList;
1250 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1252 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1254 if( lpPList == NULL )
1256 ERR( "DPID 0x%08x not found\n", dpid );
1257 return;
1260 /* Verify that this is the last reference to the data */
1261 if( --(lpPList->lpPData->uRef) )
1263 FIXME( "Why is this not the last reference to player?\n" );
1264 DebugBreak();
1267 /* Delete player */
1268 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1270 CloseHandle( lpPList->lpPData->hEvent );
1271 HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
1273 /* Delete Player List object */
1274 HeapFree( GetProcessHeap(), 0, lpPList );
1277 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid )
1279 lpPlayerList lpPlayers;
1281 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1283 if(This->dp2->lpSysGroup == NULL)
1284 return NULL;
1286 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1288 return lpPlayers;
1291 /* Basic area for Dst must already be allocated */
1292 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi )
1294 if( lpSrc == NULL )
1296 ZeroMemory( lpDst, sizeof( *lpDst ) );
1297 lpDst->dwSize = sizeof( *lpDst );
1298 return TRUE;
1301 if( lpSrc->dwSize != sizeof( *lpSrc) )
1303 return FALSE;
1306 /* Delete any existing pointers */
1307 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1308 HeapFree( GetProcessHeap(), 0, lpDst->u2.lpszLongNameA );
1310 /* Copy as required */
1311 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1313 if( bAnsi )
1315 if( lpSrc->u1.lpszShortNameA )
1317 lpDst->u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), 0,
1318 strlen(lpSrc->u1.lpszShortNameA)+1 );
1319 strcpy( lpDst->u1.lpszShortNameA, lpSrc->u1.lpszShortNameA );
1321 if( lpSrc->u2.lpszLongNameA )
1323 lpDst->u2.lpszLongNameA = HeapAlloc( GetProcessHeap(), 0,
1324 strlen(lpSrc->u2.lpszLongNameA)+1 );
1325 strcpy( lpDst->u2.lpszLongNameA, lpSrc->u2.lpszLongNameA );
1328 else
1330 if( lpSrc->u1.lpszShortNameA )
1332 lpDst->u1.lpszShortName = HeapAlloc( GetProcessHeap(), 0,
1333 (strlenW(lpSrc->u1.lpszShortName)+1)*sizeof(WCHAR) );
1334 strcpyW( lpDst->u1.lpszShortName, lpSrc->u1.lpszShortName );
1336 if( lpSrc->u2.lpszLongNameA )
1338 lpDst->u2.lpszLongName = HeapAlloc( GetProcessHeap(), 0,
1339 (strlenW(lpSrc->u2.lpszLongName)+1)*sizeof(WCHAR) );
1340 strcpyW( lpDst->u2.lpszLongName, lpSrc->u2.lpszLongName );
1344 return TRUE;
1347 static void
1348 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
1349 LPVOID lpData, DWORD dwDataSize )
1351 /* Clear out the data with this player */
1352 if( dwFlags & DPSET_LOCAL )
1354 if ( lpPData->dwLocalDataSize != 0 )
1356 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
1357 lpPData->lpLocalData = NULL;
1358 lpPData->dwLocalDataSize = 0;
1361 else
1363 if( lpPData->dwRemoteDataSize != 0 )
1365 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
1366 lpPData->lpRemoteData = NULL;
1367 lpPData->dwRemoteDataSize = 0;
1371 /* Reallocate for new data */
1372 if( lpData != NULL )
1374 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1375 sizeof( dwDataSize ) );
1376 CopyMemory( lpNewData, lpData, dwDataSize );
1378 if( dwFlags & DPSET_LOCAL )
1380 lpPData->lpLocalData = lpData;
1381 lpPData->dwLocalDataSize = dwDataSize;
1383 else
1385 lpPData->lpRemoteData = lpNewData;
1386 lpPData->dwRemoteDataSize = dwDataSize;
1392 static HRESULT WINAPI DP_IF_CreatePlayer
1393 ( IDirectPlay2Impl* This,
1394 LPVOID lpMsgHdr, /* NULL for local creation, non NULL for remote creation */
1395 LPDPID lpidPlayer,
1396 LPDPNAME lpPlayerName,
1397 HANDLE hEvent,
1398 LPVOID lpData,
1399 DWORD dwDataSize,
1400 DWORD dwFlags,
1401 BOOL bAnsi )
1403 HRESULT hr = DP_OK;
1404 lpPlayerData lpPData;
1405 lpPlayerList lpPList;
1406 DWORD dwCreateFlags = 0;
1408 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1409 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1410 dwDataSize, dwFlags, bAnsi );
1412 if( dwFlags == 0 )
1414 dwFlags = DPPLAYER_SPECTATOR;
1417 if( lpidPlayer == NULL )
1419 return DPERR_INVALIDPARAMS;
1423 /* Determine the creation flags for the player. These will be passed
1424 * to the name server if requesting a player id and to the SP when
1425 * informing it of the player creation
1428 if( dwFlags & DPPLAYER_SERVERPLAYER )
1430 if( *lpidPlayer == DPID_SERVERPLAYER )
1432 /* Server player for the host interface */
1433 dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
1435 else if( *lpidPlayer == DPID_NAME_SERVER )
1437 /* Name server - master of everything */
1438 dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
1440 else
1442 /* Server player for a non host interface */
1443 dwCreateFlags |= DPLAYI_PLAYER_SYSPLAYER;
1447 if( lpMsgHdr == NULL )
1448 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1451 /* Verify we know how to handle all the flags */
1452 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1453 ( dwFlags & DPPLAYER_SPECTATOR )
1457 /* Assume non fatal failure */
1458 ERR( "unknown dwFlags = 0x%08x\n", dwFlags );
1461 /* If the name is not specified, we must provide one */
1462 if( *lpidPlayer == DPID_UNKNOWN )
1464 /* If we are the session master, we dish out the group/player ids */
1465 if( This->dp2->bHostInterface )
1467 *lpidPlayer = DP_NextObjectId();
1469 else
1471 hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer );
1473 if( FAILED(hr) )
1475 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1476 return hr;
1480 else
1482 /* FIXME: Would be nice to perhaps verify that we don't already have
1483 * this player.
1487 /* We pass creation flags, so we can distinguish sysplayers and not count them in the current
1488 player total */
1489 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwCreateFlags,
1490 hEvent, bAnsi );
1492 if( lpPData == NULL )
1494 return DPERR_CANTADDPLAYER;
1497 /* Create the list object and link it in */
1498 lpPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPList ) );
1499 if( lpPList == NULL )
1501 FIXME( "Memory leak\n" );
1502 return DPERR_CANTADDPLAYER;
1505 lpPData->uRef = 1;
1506 lpPList->lpPData = lpPData;
1508 /* Add the player to the system group */
1509 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1511 /* Update the information and send it to all players in the session */
1512 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
1514 /* Let the SP know that we've created this player */
1515 if( This->dp2->spData.lpCB->CreatePlayer )
1517 DPSP_CREATEPLAYERDATA data;
1519 data.idPlayer = *lpidPlayer;
1520 data.dwFlags = dwCreateFlags;
1521 data.lpSPMessageHeader = lpMsgHdr;
1522 data.lpISP = This->dp2->spData.lpISP;
1524 TRACE( "Calling SP CreatePlayer 0x%08x: dwFlags: 0x%08x lpMsgHdr: %p\n",
1525 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
1527 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1530 if( FAILED(hr) )
1532 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1533 return hr;
1536 /* Now let the SP know that this player is a member of the system group */
1537 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1539 DPSP_ADDPLAYERTOGROUPDATA data;
1541 data.idPlayer = *lpidPlayer;
1542 data.idGroup = DPID_SYSTEM_GROUP;
1543 data.lpISP = This->dp2->spData.lpISP;
1545 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1547 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1550 if( FAILED(hr) )
1552 ERR( "Failed to add player to sys group with sp: %s\n",
1553 DPLAYX_HresultToString(hr) );
1554 return hr;
1557 #if 1
1558 if( This->dp2->bHostInterface == FALSE )
1560 /* Let the name server know about the creation of this player */
1561 /* FIXME: Is this only to be done for the creation of a server player or
1562 * is this used for regular players? If only for server players, move
1563 * this call to DP_SecureOpen(...);
1565 #if 0
1566 TRACE( "Sending message to self to get my addr\n" );
1567 DP_MSG_ToSelf( This, *lpidPlayer ); /* This is a hack right now */
1568 #endif
1570 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
1572 #else
1573 /* Inform all other peers of the creation of a new player. If there are
1574 * no peers keep this quiet.
1575 * Also, if this was a remote event, no need to rebroadcast it.
1577 if( ( lpMsgHdr == NULL ) &&
1578 This->dp2->lpSessionDesc &&
1579 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1581 DPMSG_CREATEPLAYERORGROUP msg;
1582 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1584 msg.dwPlayerType = DPPLAYERTYPE_PLAYER;
1585 msg.dpId = *lpidPlayer;
1586 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */
1587 msg.lpData = lpData;
1588 msg.dwDataSize = dwDataSize;
1589 msg.dpnName = *lpPlayerName;
1590 msg.dpIdParent = DPID_NOPARENT_GROUP;
1591 msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
1593 /* FIXME: Correct to just use send effectively? */
1594 /* FIXME: Should size include data w/ message or just message "header" */
1595 /* FIXME: Check return code */
1596 hr = DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
1597 sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
1599 #endif
1601 return hr;
1604 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
1605 ( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1606 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1608 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1610 if( dwFlags & DPPLAYER_SERVERPLAYER )
1612 *lpidPlayer = DPID_SERVERPLAYER;
1614 else
1616 *lpidPlayer = DPID_UNKNOWN;
1619 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1620 lpData, dwDataSize, dwFlags, TRUE );
1623 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
1624 ( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1625 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1627 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1629 if( dwFlags & DPPLAYER_SERVERPLAYER )
1631 *lpidPlayer = DPID_SERVERPLAYER;
1633 else
1635 *lpidPlayer = DPID_UNKNOWN;
1638 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1639 lpData, dwDataSize, dwFlags, FALSE );
1642 static DPID DP_GetRemoteNextObjectId(void)
1644 FIXME( ":stub\n" );
1646 /* Hack solution */
1647 return DP_NextObjectId();
1650 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
1651 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
1652 DPID idPlayer, BOOL bAnsi )
1654 HRESULT hr = DP_OK;
1656 lpGroupData lpGData;
1657 lpPlayerList lpPList;
1659 TRACE( "(%p)->(%p,0x%08x,0x%08x,%u)\n",
1660 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
1662 /* Find the group */
1663 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1665 return DPERR_INVALIDGROUP;
1668 /* Find the player */
1669 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
1671 return DPERR_INVALIDPLAYER;
1674 /* Remove the player shortcut from the group */
1675 DPQ_REMOVE_ENTRY( lpGData->players, players, lpPData->dpid, ==, idPlayer, lpPList );
1677 if( lpPList == NULL )
1679 return DPERR_INVALIDPLAYER;
1682 /* One less reference */
1683 lpPList->lpPData->uRef--;
1685 /* Delete the Player List element */
1686 HeapFree( GetProcessHeap(), 0, lpPList );
1688 /* Inform the SP if they care */
1689 if( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1691 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1693 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1695 data.idPlayer = idPlayer;
1696 data.idGroup = idGroup;
1697 data.lpISP = This->dp2->spData.lpISP;
1699 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1702 /* Need to send a DELETEPLAYERFROMGROUP message */
1703 FIXME( "Need to send a message\n" );
1705 return hr;
1708 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
1709 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
1711 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1712 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, TRUE );
1715 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
1716 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
1718 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1719 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, FALSE );
1722 typedef struct _DPRGOPContext
1724 IDirectPlay3Impl* This;
1725 BOOL bAnsi;
1726 DPID idGroup;
1727 } DPRGOPContext, *lpDPRGOPContext;
1729 static BOOL CALLBACK
1730 cbRemoveGroupOrPlayer(
1731 DPID dpId,
1732 DWORD dwPlayerType,
1733 LPCDPNAME lpName,
1734 DWORD dwFlags,
1735 LPVOID lpContext )
1737 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1739 TRACE( "Removing element:0x%08x (type:0x%08x) from element:0x%08x\n",
1740 dpId, dwPlayerType, lpCtxt->idGroup );
1742 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1744 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt->This, lpCtxt->idGroup,
1745 dpId )
1749 ERR( "Unable to delete group 0x%08x from group 0x%08x\n",
1750 dpId, lpCtxt->idGroup );
1753 else
1755 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl*)lpCtxt->This,
1756 NULL, lpCtxt->idGroup,
1757 dpId, lpCtxt->bAnsi )
1761 ERR( "Unable to delete player 0x%08x from grp 0x%08x\n",
1762 dpId, lpCtxt->idGroup );
1766 return TRUE; /* Continue enumeration */
1769 static HRESULT WINAPI DP_IF_DestroyGroup
1770 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi )
1772 lpGroupData lpGData;
1773 DPRGOPContext context;
1775 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1776 This, lpMsgHdr, idGroup, bAnsi );
1778 /* Find the group */
1779 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1781 return DPERR_INVALIDPLAYER; /* yes player */
1784 context.This = (IDirectPlay3Impl*)This;
1785 context.bAnsi = bAnsi;
1786 context.idGroup = idGroup;
1788 /* Remove all players that this group has */
1789 DP_IF_EnumGroupPlayers( This, idGroup, NULL,
1790 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1792 /* Remove all links to groups that this group has since this is dp3 */
1793 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This, idGroup, NULL,
1794 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1796 /* Remove this group from the parent group - if it has one */
1797 if( ( idGroup != DPID_SYSTEM_GROUP ) &&
1798 ( lpGData->parent != DPID_SYSTEM_GROUP )
1801 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl*)This, lpGData->parent,
1802 idGroup );
1805 /* Now delete this group data and list from the system group */
1806 DP_DeleteGroup( This, idGroup );
1808 /* Let the SP know that we've destroyed this group */
1809 if( This->dp2->spData.lpCB->DeleteGroup )
1811 DPSP_DELETEGROUPDATA data;
1813 FIXME( "data.dwFlags is incorrect\n" );
1815 data.idGroup = idGroup;
1816 data.dwFlags = 0;
1817 data.lpISP = This->dp2->spData.lpISP;
1819 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1822 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1824 return DP_OK;
1827 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
1828 ( LPDIRECTPLAY2A iface, DPID idGroup )
1830 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1831 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
1834 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
1835 ( LPDIRECTPLAY2 iface, DPID idGroup )
1837 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1838 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
1841 typedef struct _DPFAGContext
1843 IDirectPlay2Impl* This;
1844 DPID idPlayer;
1845 BOOL bAnsi;
1846 } DPFAGContext, *lpDPFAGContext;
1848 static HRESULT WINAPI DP_IF_DestroyPlayer
1849 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi )
1851 DPFAGContext cbContext;
1853 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1854 This, lpMsgHdr, idPlayer, bAnsi );
1856 if( This->dp2->connectionInitialized == NO_PROVIDER )
1858 return DPERR_UNINITIALIZED;
1861 if( DP_FindPlayer( This, idPlayer ) == NULL )
1863 return DPERR_INVALIDPLAYER;
1866 /* FIXME: If the player is remote, we must be the host to delete this */
1868 cbContext.This = This;
1869 cbContext.idPlayer = idPlayer;
1870 cbContext.bAnsi = bAnsi;
1872 /* Find each group and call DeletePlayerFromGroup if the player is a
1873 member of the group */
1874 DP_IF_EnumGroups( This, NULL, cbDeletePlayerFromAllGroups,
1875 (LPVOID)&cbContext, DPENUMGROUPS_ALL, bAnsi );
1877 /* Now delete player and player list from the sys group */
1878 DP_DeletePlayer( This, idPlayer );
1880 /* Let the SP know that we've destroyed this group */
1881 if( This->dp2->spData.lpCB->DeletePlayer )
1883 DPSP_DELETEPLAYERDATA data;
1885 FIXME( "data.dwFlags is incorrect\n" );
1887 data.idPlayer = idPlayer;
1888 data.dwFlags = 0;
1889 data.lpISP = This->dp2->spData.lpISP;
1891 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
1894 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
1896 return DP_OK;
1899 static BOOL CALLBACK
1900 cbDeletePlayerFromAllGroups(
1901 DPID dpId,
1902 DWORD dwPlayerType,
1903 LPCDPNAME lpName,
1904 DWORD dwFlags,
1905 LPVOID lpContext )
1907 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
1909 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1911 DP_IF_DeletePlayerFromGroup( lpCtxt->This, NULL, dpId, lpCtxt->idPlayer,
1912 lpCtxt->bAnsi );
1914 /* Enumerate all groups in this group since this will normally only
1915 * be called for top level groups
1917 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)lpCtxt->This,
1918 dpId, NULL,
1919 cbDeletePlayerFromAllGroups,
1920 (LPVOID)lpContext, DPENUMGROUPS_ALL,
1921 lpCtxt->bAnsi );
1924 else
1926 ERR( "Group callback has dwPlayerType = 0x%08x\n", dwPlayerType );
1929 return TRUE;
1932 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
1933 ( LPDIRECTPLAY2A iface, DPID idPlayer )
1935 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1936 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
1939 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
1940 ( LPDIRECTPLAY2 iface, DPID idPlayer )
1942 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1943 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
1946 static HRESULT WINAPI DP_IF_EnumGroupPlayers
1947 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
1948 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1949 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1951 lpGroupData lpGData;
1952 lpPlayerList lpPList;
1954 FIXME("(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
1955 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
1956 lpContext, dwFlags, bAnsi );
1958 if( This->dp2->connectionInitialized == NO_PROVIDER )
1960 return DPERR_UNINITIALIZED;
1963 /* Find the group */
1964 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1966 return DPERR_INVALIDGROUP;
1969 if( DPQ_IS_EMPTY( lpGData->players ) )
1971 return DP_OK;
1974 lpPList = DPQ_FIRST( lpGData->players );
1976 /* Walk the players in this group */
1977 for( ;; )
1979 /* We do not enum the name server or app server as they are of no
1980 * concequence to the end user.
1982 if( ( lpPList->lpPData->dpid != DPID_NAME_SERVER ) &&
1983 ( lpPList->lpPData->dpid != DPID_SERVERPLAYER )
1987 /* FIXME: Need to add stuff for dwFlags checking */
1989 if( !lpEnumPlayersCallback2( lpPList->lpPData->dpid, DPPLAYERTYPE_PLAYER,
1990 &lpPList->lpPData->name,
1991 lpPList->lpPData->dwFlags,
1992 lpContext )
1995 /* User requested break */
1996 return DP_OK;
2000 if( DPQ_IS_ENDOFLIST( lpPList->players ) )
2002 break;
2005 lpPList = DPQ_NEXT( lpPList->players );
2008 return DP_OK;
2011 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
2012 ( LPDIRECTPLAY2A iface, DPID idGroup, LPGUID lpguidInstance,
2013 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2014 LPVOID lpContext, DWORD dwFlags )
2016 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2017 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2018 lpEnumPlayersCallback2, lpContext,
2019 dwFlags, TRUE );
2022 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
2023 ( LPDIRECTPLAY2 iface, DPID idGroup, LPGUID lpguidInstance,
2024 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2025 LPVOID lpContext, DWORD dwFlags )
2027 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2028 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2029 lpEnumPlayersCallback2, lpContext,
2030 dwFlags, FALSE );
2033 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2034 static HRESULT WINAPI DP_IF_EnumGroups
2035 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2036 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2037 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2039 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This,
2040 DPID_SYSTEM_GROUP, lpguidInstance,
2041 lpEnumPlayersCallback2, lpContext,
2042 dwFlags, bAnsi );
2045 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
2046 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2047 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2048 LPVOID lpContext, DWORD dwFlags )
2050 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2051 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2052 lpContext, dwFlags, TRUE );
2055 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
2056 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2057 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2058 LPVOID lpContext, DWORD dwFlags )
2060 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2061 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2062 lpContext, dwFlags, FALSE );
2065 static HRESULT WINAPI DP_IF_EnumPlayers
2066 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2067 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2068 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2070 return DP_IF_EnumGroupPlayers( This, DPID_SYSTEM_GROUP, lpguidInstance,
2071 lpEnumPlayersCallback2, lpContext,
2072 dwFlags, bAnsi );
2075 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
2076 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2077 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2078 LPVOID lpContext, DWORD dwFlags )
2080 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2081 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2082 lpContext, dwFlags, TRUE );
2085 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
2086 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2087 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2088 LPVOID lpContext, DWORD dwFlags )
2090 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2091 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2092 lpContext, dwFlags, FALSE );
2095 /* This function should call the registered callback function that the user
2096 passed into EnumSessions for each entry available.
2098 static void DP_InvokeEnumSessionCallbacks
2099 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2100 LPVOID lpNSInfo,
2101 DWORD dwTimeout,
2102 LPVOID lpContext )
2104 LPDPSESSIONDESC2 lpSessionDesc;
2106 FIXME( ": not checking for conditions\n" );
2108 /* Not sure if this should be pruning but it's convenient */
2109 NS_PruneSessionCache( lpNSInfo );
2111 NS_ResetSessionEnumeration( lpNSInfo );
2113 /* Enumerate all sessions */
2114 /* FIXME: Need to indicate ANSI */
2115 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2117 TRACE( "EnumSessionsCallback2 invoked\n" );
2118 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2120 return;
2124 /* Invoke one last time to indicate that there is no more to come */
2125 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2128 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2130 EnumSessionAsyncCallbackData* data = (EnumSessionAsyncCallbackData*)lpContext;
2131 HANDLE hSuicideRequest = data->hSuicideRequest;
2132 DWORD dwTimeout = data->dwTimeout;
2134 TRACE( "Thread started with timeout = 0x%08x\n", dwTimeout );
2136 for( ;; )
2138 HRESULT hr;
2140 /* Sleep up to dwTimeout waiting for request to terminate thread */
2141 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2143 TRACE( "Thread terminating on terminate request\n" );
2144 break;
2147 /* Now resend the enum request */
2148 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2149 data->dwEnumSessionFlags,
2150 data->lpSpData );
2152 if( FAILED(hr) )
2154 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2155 /* FIXME: Should we kill this thread? How to inform the main thread? */
2160 TRACE( "Thread terminating\n" );
2162 /* Clean up the thread data */
2163 CloseHandle( hSuicideRequest );
2164 HeapFree( GetProcessHeap(), 0, lpContext );
2166 /* FIXME: Need to have some notification to main app thread that this is
2167 * dead. It would serve two purposes. 1) allow sync on termination
2168 * so that we don't actually send something to ourselves when we
2169 * become name server (race condition) and 2) so that if we die
2170 * abnormally something else will be able to tell.
2173 return 1;
2176 static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
2178 /* Does a thread exist? If so we were doing an async enum session */
2179 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2181 TRACE( "Killing EnumSession thread %p\n",
2182 This->dp2->hEnumSessionThread );
2184 /* Request that the thread kill itself nicely */
2185 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2186 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2188 /* We no longer need to know about the thread */
2189 CloseHandle( This->dp2->hEnumSessionThread );
2191 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2195 static HRESULT WINAPI DP_IF_EnumSessions
2196 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2197 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2198 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2200 HRESULT hr = DP_OK;
2202 TRACE( "(%p)->(%p,0x%08x,%p,%p,0x%08x,%u)\n",
2203 This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags,
2204 bAnsi );
2206 /* Can't enumerate if the interface is already open */
2207 if( This->dp2->bConnectionOpen )
2209 return DPERR_GENERIC;
2212 #if 1
2213 /* The loading of a lobby provider _seems_ to require a backdoor loading
2214 * of the service provider to also associate with this DP object. This is
2215 * because the app doesn't seem to have to call EnumConnections and
2216 * InitializeConnection for the SP before calling this method. As such
2217 * we'll do their dirty work for them with a quick hack so as to always
2218 * load the TCP/IP service provider.
2220 * The correct solution would seem to involve creating a dialog box which
2221 * contains the possible SPs. These dialog boxes most likely follow SDK
2222 * examples.
2224 if( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
2226 LPVOID lpConnection;
2227 DWORD dwSize;
2229 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2231 if( !DP_BuildSPCompoundAddr( (LPGUID)&DPSPGUID_TCPIP, &lpConnection, &dwSize ) )
2233 ERR( "Can't build compound addr\n" );
2234 return DPERR_GENERIC;
2237 hr = DP_IF_InitializeConnection( (IDirectPlay3Impl*)This, lpConnection,
2238 0, bAnsi );
2239 if( FAILED(hr) )
2241 return hr;
2244 /* Free up the address buffer */
2245 HeapFree( GetProcessHeap(), 0, lpConnection );
2247 /* The SP is now initialized */
2248 This->dp2->bSPInitialized = TRUE;
2250 #endif
2253 /* Use the service provider default? */
2254 if( dwTimeout == 0 )
2256 DPCAPS spCaps;
2257 spCaps.dwSize = sizeof( spCaps );
2259 DP_IF_GetCaps( This, &spCaps, 0 );
2260 dwTimeout = spCaps.dwTimeout;
2262 /* The service provider doesn't provide one either! */
2263 if( dwTimeout == 0 )
2265 /* Provide the TCP/IP default */
2266 dwTimeout = DPMSG_WAIT_5_SECS;
2270 if( dwFlags & DPENUMSESSIONS_STOPASYNC )
2272 DP_KillEnumSessionThread( This );
2273 return hr;
2276 /* FIXME: Interface locking sucks in this method */
2277 if( ( dwFlags & DPENUMSESSIONS_ASYNC ) )
2279 /* Enumerate everything presently in the local session cache */
2280 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2281 This->dp2->lpNameServerData, dwTimeout,
2282 lpContext );
2285 /* See if we've already created a thread to service this interface */
2286 if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2288 DWORD dwThreadId;
2290 /* Send the first enum request inline since the user may cancel a dialog
2291 * if one is presented. Also, may also have a connecting return code.
2293 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2294 dwFlags, &This->dp2->spData );
2296 if( !FAILED(hr) )
2298 EnumSessionAsyncCallbackData* lpData
2299 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpData ) );
2300 /* FIXME: need to kill the thread on object deletion */
2301 lpData->lpSpData = &This->dp2->spData;
2303 CopyMemory( &lpData->requestGuid, &lpsd->guidApplication, sizeof(GUID) );
2304 lpData->dwEnumSessionFlags = dwFlags;
2305 lpData->dwTimeout = dwTimeout;
2307 This->dp2->hKillEnumSessionThreadEvent =
2308 CreateEventW( NULL, TRUE, FALSE, NULL );
2310 if( !DuplicateHandle( GetCurrentProcess(),
2311 This->dp2->hKillEnumSessionThreadEvent,
2312 GetCurrentProcess(),
2313 &lpData->hSuicideRequest,
2314 0, FALSE, DUPLICATE_SAME_ACCESS )
2317 ERR( "Can't duplicate thread killing handle\n" );
2320 TRACE( ": creating EnumSessionsRequest thread\n" );
2322 This->dp2->hEnumSessionThread = CreateThread( NULL,
2324 DP_EnumSessionsSendAsyncRequestThread,
2325 lpData,
2327 &dwThreadId );
2331 else
2333 /* Invalidate the session cache for the interface */
2334 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2336 /* Send the broadcast for session enumeration */
2337 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2338 dwFlags,
2339 &This->dp2->spData );
2342 SleepEx( dwTimeout, FALSE );
2344 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2345 This->dp2->lpNameServerData, dwTimeout,
2346 lpContext );
2349 return hr;
2352 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2353 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2354 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2355 LPVOID lpContext, DWORD dwFlags )
2357 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2358 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2359 lpContext, dwFlags, TRUE );
2362 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2363 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2364 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2365 LPVOID lpContext, DWORD dwFlags )
2367 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2368 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2369 lpContext, dwFlags, FALSE );
2372 static HRESULT WINAPI DP_IF_GetPlayerCaps
2373 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
2374 DWORD dwFlags )
2376 DPSP_GETCAPSDATA data;
2378 TRACE("(%p)->(0x%08x,%p,0x%08x)\n", This, idPlayer, lpDPCaps, dwFlags);
2380 /* Query the service provider */
2381 data.idPlayer = idPlayer;
2382 data.dwFlags = dwFlags;
2383 data.lpCaps = lpDPCaps;
2384 data.lpISP = This->dp2->spData.lpISP;
2386 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2389 static HRESULT WINAPI DP_IF_GetCaps
2390 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags )
2392 return DP_IF_GetPlayerCaps( This, DPID_ALLPLAYERS, lpDPCaps, dwFlags );
2395 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2396 ( LPDIRECTPLAY2A iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2398 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2399 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2402 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2403 ( LPDIRECTPLAY2 iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2405 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2406 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2409 static HRESULT WINAPI DP_IF_GetGroupData
2410 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2411 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2413 lpGroupData lpGData;
2414 DWORD dwRequiredBufferSize;
2415 LPVOID lpCopyDataFrom;
2417 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2418 This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi );
2420 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2422 return DPERR_INVALIDGROUP;
2425 /* How much buffer is required? */
2426 if( dwFlags & DPSET_LOCAL )
2428 dwRequiredBufferSize = lpGData->dwLocalDataSize;
2429 lpCopyDataFrom = lpGData->lpLocalData;
2431 else
2433 dwRequiredBufferSize = lpGData->dwRemoteDataSize;
2434 lpCopyDataFrom = lpGData->lpRemoteData;
2437 /* Is the user requesting to know how big a buffer is required? */
2438 if( ( lpData == NULL ) ||
2439 ( *lpdwDataSize < dwRequiredBufferSize )
2442 *lpdwDataSize = dwRequiredBufferSize;
2443 return DPERR_BUFFERTOOSMALL;
2446 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2448 return DP_OK;
2451 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2452 ( LPDIRECTPLAY2A 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, TRUE );
2460 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2461 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2462 LPDWORD lpdwDataSize, DWORD dwFlags )
2464 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2465 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2466 dwFlags, FALSE );
2469 static HRESULT WINAPI DP_IF_GetGroupName
2470 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2471 LPDWORD lpdwDataSize, BOOL bAnsi )
2473 lpGroupData lpGData;
2474 LPDPNAME lpName = (LPDPNAME)lpData;
2475 DWORD dwRequiredDataSize;
2477 FIXME("(%p)->(0x%08x,%p,%p,%u) ANSI ignored\n",
2478 This, idGroup, lpData, lpdwDataSize, bAnsi );
2480 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2482 return DPERR_INVALIDGROUP;
2485 dwRequiredDataSize = lpGData->name.dwSize;
2487 if( lpGData->name.u1.lpszShortNameA )
2489 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
2492 if( lpGData->name.u2.lpszLongNameA )
2494 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
2497 if( ( lpData == NULL ) ||
2498 ( *lpdwDataSize < dwRequiredDataSize )
2501 *lpdwDataSize = dwRequiredDataSize;
2502 return DPERR_BUFFERTOOSMALL;
2505 /* Copy the structure */
2506 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2508 if( lpGData->name.u1.lpszShortNameA )
2510 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2511 lpGData->name.u1.lpszShortNameA );
2513 else
2515 lpName->u1.lpszShortNameA = NULL;
2518 if( lpGData->name.u1.lpszShortNameA )
2520 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2521 lpGData->name.u2.lpszLongNameA );
2523 else
2525 lpName->u2.lpszLongNameA = NULL;
2528 return DP_OK;
2531 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2532 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2533 LPDWORD lpdwDataSize )
2535 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2536 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2539 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2540 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2541 LPDWORD lpdwDataSize )
2543 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2544 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2547 static HRESULT WINAPI DP_IF_GetMessageCount
2548 ( IDirectPlay2Impl* This, DPID idPlayer,
2549 LPDWORD lpdwCount, BOOL bAnsi )
2551 FIXME("(%p)->(0x%08x,%p,%u): stub\n", This, idPlayer, lpdwCount, bAnsi );
2552 return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer,
2553 DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL,
2554 bAnsi );
2557 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2558 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDWORD lpdwCount )
2560 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2561 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, TRUE );
2564 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2565 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDWORD lpdwCount )
2567 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2568 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, FALSE );
2571 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2572 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2574 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2575 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2576 return DP_OK;
2579 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2580 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2582 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2583 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2584 return DP_OK;
2587 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2588 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2589 DWORD dwFlags )
2591 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2592 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2595 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2596 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2597 DWORD dwFlags )
2599 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2600 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2603 static HRESULT WINAPI DP_IF_GetPlayerData
2604 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2605 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2607 lpPlayerList lpPList;
2608 DWORD dwRequiredBufferSize;
2609 LPVOID lpCopyDataFrom;
2611 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2612 This, idPlayer, lpData, lpdwDataSize, dwFlags, bAnsi );
2614 if( This->dp2->connectionInitialized == NO_PROVIDER )
2616 return DPERR_UNINITIALIZED;
2619 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2621 return DPERR_INVALIDPLAYER;
2624 /* How much buffer is required? */
2625 if( dwFlags & DPSET_LOCAL )
2627 dwRequiredBufferSize = lpPList->lpPData->dwLocalDataSize;
2628 lpCopyDataFrom = lpPList->lpPData->lpLocalData;
2630 else
2632 dwRequiredBufferSize = lpPList->lpPData->dwRemoteDataSize;
2633 lpCopyDataFrom = lpPList->lpPData->lpRemoteData;
2636 /* Is the user requesting to know how big a buffer is required? */
2637 if( ( lpData == NULL ) ||
2638 ( *lpdwDataSize < dwRequiredBufferSize )
2641 *lpdwDataSize = dwRequiredBufferSize;
2642 return DPERR_BUFFERTOOSMALL;
2645 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2647 return DP_OK;
2650 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2651 ( LPDIRECTPLAY2A 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, TRUE );
2659 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2660 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2661 LPDWORD lpdwDataSize, DWORD dwFlags )
2663 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2664 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2665 dwFlags, FALSE );
2668 static HRESULT WINAPI DP_IF_GetPlayerName
2669 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2670 LPDWORD lpdwDataSize, BOOL bAnsi )
2672 lpPlayerList lpPList;
2673 LPDPNAME lpName = (LPDPNAME)lpData;
2674 DWORD dwRequiredDataSize;
2676 FIXME( "(%p)->(0x%08x,%p,%p,%u): ANSI\n",
2677 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2679 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2681 return DPERR_INVALIDPLAYER;
2684 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
2686 if( lpPList->lpPData->name.u1.lpszShortNameA )
2688 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
2691 if( lpPList->lpPData->name.u2.lpszLongNameA )
2693 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
2696 if( ( lpData == NULL ) ||
2697 ( *lpdwDataSize < dwRequiredDataSize )
2700 *lpdwDataSize = dwRequiredDataSize;
2701 return DPERR_BUFFERTOOSMALL;
2704 /* Copy the structure */
2705 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
2707 if( lpPList->lpPData->name.u1.lpszShortNameA )
2709 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2710 lpPList->lpPData->name.u1.lpszShortNameA );
2712 else
2714 lpName->u1.lpszShortNameA = NULL;
2717 if( lpPList->lpPData->name.u1.lpszShortNameA )
2719 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2720 lpPList->lpPData->name.u2.lpszLongNameA );
2722 else
2724 lpName->u2.lpszLongNameA = NULL;
2727 return DP_OK;
2730 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2731 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2732 LPDWORD lpdwDataSize )
2734 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2735 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
2738 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2739 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2740 LPDWORD lpdwDataSize )
2742 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2743 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
2746 static HRESULT WINAPI DP_GetSessionDesc
2747 ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize,
2748 BOOL bAnsi )
2750 DWORD dwRequiredSize;
2752 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
2754 if( This->dp2->connectionInitialized == NO_PROVIDER )
2756 return DPERR_UNINITIALIZED;
2759 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
2761 return DPERR_INVALIDPARAMS;
2764 /* FIXME: Get from This->dp2->lpSessionDesc */
2765 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
2767 if ( ( lpData == NULL ) ||
2768 ( *lpdwDataSize < dwRequiredSize )
2771 *lpdwDataSize = dwRequiredSize;
2772 return DPERR_BUFFERTOOSMALL;
2775 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
2777 return DP_OK;
2780 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
2781 ( LPDIRECTPLAY2A iface, LPVOID lpData, LPDWORD lpdwDataSize )
2783 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2784 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2787 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
2788 ( LPDIRECTPLAY2 iface, LPVOID lpData, LPDWORD lpdwDataSize )
2790 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2791 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2794 /* Intended only for COM compatibility. Always returns an error. */
2795 static HRESULT WINAPI DirectPlay2AImpl_Initialize
2796 ( LPDIRECTPLAY2A iface, LPGUID lpGUID )
2798 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2799 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2800 return DPERR_ALREADYINITIALIZED;
2803 /* Intended only for COM compatibility. Always returns an error. */
2804 static HRESULT WINAPI DirectPlay2WImpl_Initialize
2805 ( LPDIRECTPLAY2 iface, LPGUID lpGUID )
2807 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2808 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2809 return DPERR_ALREADYINITIALIZED;
2813 static HRESULT WINAPI DP_SecureOpen
2814 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
2815 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
2816 BOOL bAnsi )
2818 HRESULT hr = DP_OK;
2820 FIXME( "(%p)->(%p,0x%08x,%p,%p): partial stub\n",
2821 This, lpsd, dwFlags, lpSecurity, lpCredentials );
2823 if( This->dp2->bConnectionOpen )
2825 TRACE( ": rejecting already open connection.\n" );
2826 return DPERR_ALREADYINITIALIZED;
2829 /* If we're enumerating, kill the thread */
2830 DP_KillEnumSessionThread( This );
2832 if( dwFlags & DPOPEN_CREATE )
2834 /* Rightoo - this computer is the host and the local computer needs to be
2835 the name server so that others can join this session */
2836 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
2838 This->dp2->bHostInterface = TRUE;
2840 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
2841 if( FAILED( hr ) )
2843 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
2844 return hr;
2848 /* Invoke the conditional callback for the service provider */
2849 if( This->dp2->spData.lpCB->Open )
2851 DPSP_OPENDATA data;
2853 FIXME( "Not all data fields are correct. Need new parameter\n" );
2855 data.bCreate = (dwFlags & DPOPEN_CREATE ) ? TRUE : FALSE;
2856 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
2857 : NS_GetNSAddr( This->dp2->lpNameServerData );
2858 data.lpISP = This->dp2->spData.lpISP;
2859 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) ? TRUE : FALSE;
2860 data.dwOpenFlags = dwFlags;
2861 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
2863 hr = (*This->dp2->spData.lpCB->Open)(&data);
2864 if( FAILED( hr ) )
2866 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
2867 return hr;
2872 /* Create the system group of which everything is a part of */
2873 DPID systemGroup = DPID_SYSTEM_GROUP;
2875 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
2876 NULL, 0, 0, TRUE );
2880 if( dwFlags & DPOPEN_JOIN )
2882 DPID dpidServerId = DPID_UNKNOWN;
2884 /* Create the server player for this interface. This way we can receive
2885 * messages for this session.
2887 /* FIXME: I suppose that we should be setting an event for a receive
2888 * type of thing. That way the messaging thread could know to wake
2889 * up. DPlay would then trigger the hEvent for the player the
2890 * message is directed to.
2892 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
2894 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
2897 else if( dwFlags & DPOPEN_CREATE )
2899 DPID dpidNameServerId = DPID_NAME_SERVER;
2901 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
2902 0, DPPLAYER_SERVERPLAYER, bAnsi );
2905 if( FAILED(hr) )
2907 ERR( "Couldn't create name server/system player: %s\n",
2908 DPLAYX_HresultToString(hr) );
2911 return hr;
2914 static HRESULT WINAPI DirectPlay2AImpl_Open
2915 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2917 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2918 TRACE("(%p)->(%p,0x%08x)\n", This, lpsd, dwFlags );
2919 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, TRUE );
2922 static HRESULT WINAPI DirectPlay2WImpl_Open
2923 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2925 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2926 TRACE("(%p)->(%p,0x%08x)\n", This, lpsd, dwFlags );
2927 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, FALSE );
2930 static HRESULT WINAPI DP_IF_Receive
2931 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
2932 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi )
2934 LPDPMSG lpMsg = NULL;
2936 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p,%u): stub\n",
2937 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
2939 if( This->dp2->connectionInitialized == NO_PROVIDER )
2941 return DPERR_UNINITIALIZED;
2944 if( dwFlags == 0 )
2946 dwFlags = DPRECEIVE_ALL;
2949 /* If the lpData is NULL, we must be peeking the message */
2950 if( ( lpData == NULL ) &&
2951 !( dwFlags & DPRECEIVE_PEEK )
2954 return DPERR_INVALIDPARAMS;
2957 if( dwFlags & DPRECEIVE_ALL )
2959 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
2961 if( !( dwFlags & DPRECEIVE_PEEK ) )
2963 FIXME( "Remove from queue\n" );
2966 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
2967 ( dwFlags & DPRECEIVE_FROMPLAYER )
2970 FIXME( "Find matching message 0x%08x\n", dwFlags );
2972 else
2974 ERR( "Hmmm..dwFlags 0x%08x\n", dwFlags );
2977 if( lpMsg == NULL )
2979 return DPERR_NOMESSAGES;
2982 /* Copy into the provided buffer */
2983 CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
2985 return DP_OK;
2988 static HRESULT WINAPI DirectPlay2AImpl_Receive
2989 ( LPDIRECTPLAY2A 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, TRUE );
2997 static HRESULT WINAPI DirectPlay2WImpl_Receive
2998 ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo,
2999 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
3001 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3002 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
3003 lpData, lpdwDataSize, FALSE );
3006 static HRESULT WINAPI DirectPlay2AImpl_Send
3007 ( LPDIRECTPLAY2A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3009 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3010 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3011 0, 0, NULL, NULL, TRUE );
3014 static HRESULT WINAPI DirectPlay2WImpl_Send
3015 ( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3017 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3018 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3019 0, 0, NULL, NULL, FALSE );
3022 static HRESULT WINAPI DP_IF_SetGroupData
3023 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
3024 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3026 lpGroupData lpGData;
3028 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3029 This, idGroup, lpData, dwDataSize, dwFlags, bAnsi );
3031 /* Parameter check */
3032 if( ( lpData == NULL ) &&
3033 ( dwDataSize != 0 )
3036 return DPERR_INVALIDPARAMS;
3039 /* Find the pointer to the data for this player */
3040 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3042 return DPERR_INVALIDOBJECT;
3045 if( !(dwFlags & DPSET_LOCAL) )
3047 FIXME( "Was this group created by this interface?\n" );
3048 /* FIXME: If this is a remote update need to allow it but not
3049 * send a message.
3053 DP_SetGroupData( lpGData, dwFlags, lpData, dwDataSize );
3055 /* FIXME: Only send a message if this group is local to the session otherwise
3056 * it will have been rejected above
3058 if( !(dwFlags & DPSET_LOCAL) )
3060 FIXME( "Send msg?\n" );
3063 return DP_OK;
3066 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
3067 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
3068 DWORD dwDataSize, DWORD dwFlags )
3070 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3071 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, TRUE );
3074 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
3075 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
3076 DWORD dwDataSize, DWORD dwFlags )
3078 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3079 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, FALSE );
3082 static HRESULT WINAPI DP_IF_SetGroupName
3083 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
3084 DWORD dwFlags, BOOL bAnsi )
3086 lpGroupData lpGData;
3088 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n", This, idGroup,
3089 lpGroupName, dwFlags, bAnsi );
3091 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3093 return DPERR_INVALIDGROUP;
3096 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
3098 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3099 FIXME( "Message not sent and dwFlags ignored\n" );
3101 return DP_OK;
3104 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
3105 ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName,
3106 DWORD dwFlags )
3108 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3109 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
3112 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
3113 ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName,
3114 DWORD dwFlags )
3116 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3117 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
3120 static HRESULT WINAPI DP_IF_SetPlayerData
3121 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
3122 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3124 lpPlayerList lpPList;
3126 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3127 This, idPlayer, lpData, dwDataSize, dwFlags, bAnsi );
3129 /* Parameter check */
3130 if( ( lpData == NULL ) &&
3131 ( dwDataSize != 0 )
3134 return DPERR_INVALIDPARAMS;
3137 /* Find the pointer to the data for this player */
3138 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3140 return DPERR_INVALIDPLAYER;
3143 if( !(dwFlags & DPSET_LOCAL) )
3145 FIXME( "Was this group created by this interface?\n" );
3146 /* FIXME: If this is a remote update need to allow it but not
3147 * send a message.
3151 DP_SetPlayerData( lpPList->lpPData, dwFlags, lpData, dwDataSize );
3153 if( !(dwFlags & DPSET_LOCAL) )
3155 FIXME( "Send msg?\n" );
3158 return DP_OK;
3161 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3162 ( LPDIRECTPLAY2A 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, TRUE );
3170 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3171 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
3172 DWORD dwDataSize, DWORD dwFlags )
3174 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3175 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3176 dwFlags, FALSE );
3179 static HRESULT WINAPI DP_IF_SetPlayerName
3180 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
3181 DWORD dwFlags, BOOL bAnsi )
3183 lpPlayerList lpPList;
3185 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n",
3186 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3188 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3190 return DPERR_INVALIDGROUP;
3193 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3195 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3196 FIXME( "Message not sent and dwFlags ignored\n" );
3198 return DP_OK;
3201 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3202 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName,
3203 DWORD dwFlags )
3205 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3206 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3209 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3210 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName,
3211 DWORD dwFlags )
3213 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3214 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3217 static HRESULT WINAPI DP_SetSessionDesc
3218 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
3219 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3221 DWORD dwRequiredSize;
3222 LPDPSESSIONDESC2 lpTempSessDesc;
3224 TRACE( "(%p)->(%p,0x%08x,%u,%u)\n",
3225 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3227 if( This->dp2->connectionInitialized == NO_PROVIDER )
3229 return DPERR_UNINITIALIZED;
3232 if( dwFlags )
3234 return DPERR_INVALIDPARAMS;
3237 /* Only the host is allowed to update the session desc */
3238 if( !This->dp2->bHostInterface )
3240 return DPERR_ACCESSDENIED;
3243 /* FIXME: Copy into This->dp2->lpSessionDesc */
3244 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3245 lpTempSessDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize );
3247 if( lpTempSessDesc == NULL )
3249 return DPERR_OUTOFMEMORY;
3252 /* Free the old */
3253 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3255 This->dp2->lpSessionDesc = lpTempSessDesc;
3256 /* Set the new */
3257 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3258 if( bInitial )
3260 /*Initializing session GUID*/
3261 CoCreateGuid( &(This->dp2->lpSessionDesc->guidInstance) );
3263 /* If this is an external invocation of the interface, we should be
3264 * letting everyone know that things have changed. Otherwise this is
3265 * just an initialization and it doesn't need to be propagated.
3267 if( !bInitial )
3269 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3272 return DP_OK;
3275 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3276 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3278 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3279 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3282 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3283 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3285 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3286 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3289 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3290 DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3292 DWORD dwSize = 0;
3294 if( lpSessDesc == NULL )
3296 /* Hmmm..don't need any size? */
3297 ERR( "NULL lpSessDesc\n" );
3298 return dwSize;
3301 dwSize += sizeof( *lpSessDesc );
3303 if( bAnsi )
3305 if( lpSessDesc->u1.lpszSessionNameA )
3307 dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1;
3310 if( lpSessDesc->u2.lpszPasswordA )
3312 dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1;
3315 else /* UNICODE */
3317 if( lpSessDesc->u1.lpszSessionName )
3319 dwSize += sizeof( WCHAR ) *
3320 ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 );
3323 if( lpSessDesc->u2.lpszPassword )
3325 dwSize += sizeof( WCHAR ) *
3326 ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 );
3330 return dwSize;
3333 /* Assumes that contugous buffers are already allocated. */
3334 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3335 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3337 BYTE* lpStartOfFreeSpace;
3339 if( lpSessionDest == NULL )
3341 ERR( "NULL lpSessionDest\n" );
3342 return;
3345 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3347 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3349 if( bAnsi )
3351 if( lpSessionSrc->u1.lpszSessionNameA )
3353 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3354 lpSessionDest->u1.lpszSessionNameA );
3355 lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3356 lpStartOfFreeSpace +=
3357 lstrlenA( (LPSTR)lpSessionDest->u1.lpszSessionNameA ) + 1;
3360 if( lpSessionSrc->u2.lpszPasswordA )
3362 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3363 lpSessionDest->u2.lpszPasswordA );
3364 lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3365 lpStartOfFreeSpace +=
3366 lstrlenA( (LPSTR)lpSessionDest->u2.lpszPasswordA ) + 1;
3369 else /* UNICODE */
3371 if( lpSessionSrc->u1.lpszSessionName )
3373 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3374 lpSessionDest->u1.lpszSessionName );
3375 lpSessionDest->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3376 lpStartOfFreeSpace += sizeof(WCHAR) *
3377 ( lstrlenW( (LPWSTR)lpSessionDest->u1.lpszSessionName ) + 1 );
3380 if( lpSessionSrc->u2.lpszPassword )
3382 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3383 lpSessionDest->u2.lpszPassword );
3384 lpSessionDest->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3385 lpStartOfFreeSpace += sizeof(WCHAR) *
3386 ( lstrlenW( (LPWSTR)lpSessionDest->u2.lpszPassword ) + 1 );
3392 static HRESULT WINAPI DP_IF_AddGroupToGroup
3393 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3395 lpGroupData lpGParentData;
3396 lpGroupData lpGData;
3397 lpGroupList lpNewGList;
3399 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, idParentGroup, idGroup );
3401 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3403 return DPERR_INVALIDGROUP;
3406 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3408 return DPERR_INVALIDGROUP;
3411 /* Create a player list (ie "shortcut" ) */
3412 lpNewGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewGList ) );
3413 if( lpNewGList == NULL )
3415 return DPERR_CANTADDPLAYER;
3418 /* Add the shortcut */
3419 lpGData->uRef++;
3420 lpNewGList->lpGData = lpGData;
3422 /* Add the player to the list of players for this group */
3423 DPQ_INSERT( lpGData->groups, lpNewGList, groups );
3425 /* Send a ADDGROUPTOGROUP message */
3426 FIXME( "Not sending message\n" );
3428 return DP_OK;
3431 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3432 ( LPDIRECTPLAY3A iface, DPID idParentGroup, DPID idGroup )
3434 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3435 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3438 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3439 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3441 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3442 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3445 static HRESULT WINAPI DP_IF_CreateGroupInGroup
3446 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
3447 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
3448 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3450 lpGroupData lpGParentData;
3451 lpGroupList lpGList;
3452 lpGroupData lpGData;
3454 TRACE( "(%p)->(0x%08x,%p,%p,%p,0x%08x,0x%08x,%u)\n",
3455 This, idParentGroup, lpidGroup, lpGroupName, lpData,
3456 dwDataSize, dwFlags, bAnsi );
3458 /* Verify that the specified parent is valid */
3459 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This,
3460 idParentGroup ) ) == NULL
3463 return DPERR_INVALIDGROUP;
3466 lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName,
3467 dwFlags, idParentGroup, bAnsi );
3469 if( lpGData == NULL )
3471 return DPERR_CANTADDPLAYER; /* yes player not group */
3474 /* Something else is referencing this data */
3475 lpGData->uRef++;
3477 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
3479 /* The list has now been inserted into the interface group list. We now
3480 need to put a "shortcut" to this group in the parent group */
3481 lpGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGList ) );
3482 if( lpGList == NULL )
3484 FIXME( "Memory leak\n" );
3485 return DPERR_CANTADDPLAYER; /* yes player not group */
3488 lpGList->lpGData = lpGData;
3490 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
3492 /* Let the SP know that we've created this group */
3493 if( This->dp2->spData.lpCB->CreateGroup )
3495 DPSP_CREATEGROUPDATA data;
3497 TRACE( "Calling SP CreateGroup\n" );
3499 data.idGroup = *lpidGroup;
3500 data.dwFlags = dwFlags;
3501 data.lpSPMessageHeader = lpMsgHdr;
3502 data.lpISP = This->dp2->spData.lpISP;
3504 (*This->dp2->spData.lpCB->CreateGroup)( &data );
3507 /* Inform all other peers of the creation of a new group. If there are
3508 * no peers keep this quiet.
3510 if( This->dp2->lpSessionDesc &&
3511 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
3513 DPMSG_CREATEPLAYERORGROUP msg;
3515 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
3516 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
3517 msg.dpId = *lpidGroup;
3518 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
3519 msg.lpData = lpData;
3520 msg.dwDataSize = dwDataSize;
3521 msg.dpnName = *lpGroupName;
3523 /* FIXME: Correct to just use send effectively? */
3524 /* FIXME: Should size include data w/ message or just message "header" */
3525 /* FIXME: Check return code */
3526 DP_SendEx( (IDirectPlay2Impl*)This,
3527 DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
3528 0, 0, NULL, NULL, bAnsi );
3531 return DP_OK;
3534 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3535 ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup,
3536 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3537 DWORD dwFlags )
3539 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3541 *lpidGroup = DPID_UNKNOWN;
3543 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3544 lpGroupName, lpData, dwDataSize, dwFlags,
3545 TRUE );
3548 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3549 ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup,
3550 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3551 DWORD dwFlags )
3553 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3555 *lpidGroup = DPID_UNKNOWN;
3557 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3558 lpGroupName, lpData, dwDataSize,
3559 dwFlags, FALSE );
3562 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
3563 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3565 lpGroupList lpGList;
3566 lpGroupData lpGParentData;
3568 TRACE("(%p)->(0x%08x,0x%08x)\n", This, idParentGroup, idGroup );
3570 /* Is the parent group valid? */
3571 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3573 return DPERR_INVALIDGROUP;
3576 /* Remove the group from the parent group queue */
3577 DPQ_REMOVE_ENTRY( lpGParentData->groups, groups, lpGData->dpid, ==, idGroup, lpGList );
3579 if( lpGList == NULL )
3581 return DPERR_INVALIDGROUP;
3584 /* Decrement the ref count */
3585 lpGList->lpGData->uRef--;
3587 /* Free up the list item */
3588 HeapFree( GetProcessHeap(), 0, lpGList );
3590 /* Should send a DELETEGROUPFROMGROUP message */
3591 FIXME( "message not sent\n" );
3593 return DP_OK;
3596 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3597 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3599 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3600 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3603 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3604 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3606 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3607 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3610 static
3611 BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
3612 LPDWORD lpdwBufSize )
3614 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3615 HRESULT hr;
3617 dpCompoundAddress.dwDataSize = sizeof( GUID );
3618 memcpy( &dpCompoundAddress.guidDataType, &DPAID_ServiceProvider,
3619 sizeof( GUID ) ) ;
3620 dpCompoundAddress.lpData = lpcSpGuid;
3622 *lplpAddrBuf = NULL;
3623 *lpdwBufSize = 0;
3625 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3626 lpdwBufSize, TRUE );
3628 if( hr != DPERR_BUFFERTOOSMALL )
3630 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3631 return FALSE;
3634 /* Now allocate the buffer */
3635 *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3636 *lpdwBufSize );
3638 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3639 lpdwBufSize, TRUE );
3640 if( FAILED(hr) )
3642 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3643 return FALSE;
3646 return TRUE;
3649 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
3650 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3652 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3653 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3655 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
3656 if( dwFlags == 0 )
3658 dwFlags = DPCONNECTION_DIRECTPLAY;
3661 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
3662 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) )
3665 return DPERR_INVALIDFLAGS;
3668 if( !lpEnumCallback || !*lpEnumCallback )
3670 return DPERR_INVALIDPARAMS;
3673 /* Enumerate DirectPlay service providers */
3674 if( dwFlags & DPCONNECTION_DIRECTPLAY )
3676 HKEY hkResult;
3677 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3678 LPCSTR guidDataSubKey = "Guid";
3679 char subKeyName[51];
3680 DWORD dwIndex, sizeOfSubKeyName=50;
3681 FILETIME filetime;
3683 /* Need to loop over the service providers in the registry */
3684 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3685 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3687 /* Hmmm. Does this mean that there are no service providers? */
3688 ERR(": no service providers?\n");
3689 return DP_OK;
3693 /* Traverse all the service providers we have available */
3694 for( dwIndex=0;
3695 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3696 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3697 ++dwIndex, sizeOfSubKeyName=51 )
3700 HKEY hkServiceProvider;
3701 GUID serviceProviderGUID;
3702 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3703 char returnBuffer[51];
3704 WCHAR buff[51];
3705 DPNAME dpName;
3706 BOOL bBuildPass;
3708 LPVOID lpAddressBuffer = NULL;
3709 DWORD dwAddressBufferSize = 0;
3711 TRACE(" this time through: %s\n", subKeyName );
3713 /* Get a handle for this particular service provider */
3714 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3715 &hkServiceProvider ) != ERROR_SUCCESS )
3717 ERR(": what the heck is going on?\n" );
3718 continue;
3721 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3722 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
3723 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3725 ERR(": missing GUID registry data members\n" );
3726 continue;
3729 /* FIXME: Check return types to ensure we're interpreting data right */
3730 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3731 CLSIDFromString( buff, &serviceProviderGUID );
3732 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3734 /* Fill in the DPNAME struct for the service provider */
3735 dpName.dwSize = sizeof( dpName );
3736 dpName.dwFlags = 0;
3737 dpName.u1.lpszShortNameA = subKeyName;
3738 dpName.u2.lpszLongNameA = NULL;
3740 /* Create the compound address for the service provider.
3741 * NOTE: This is a gruesome architectural scar right now. DP
3742 * uses DPL and DPL uses DP. Nasty stuff. This may be why the
3743 * native dll just gets around this little bit by allocating an
3744 * 80 byte buffer which isn't even filled with a valid compound
3745 * address. Oh well. Creating a proper compound address is the
3746 * way to go anyways despite this method taking slightly more
3747 * heap space and realtime :) */
3749 bBuildPass = DP_BuildSPCompoundAddr( &serviceProviderGUID,
3750 &lpAddressBuffer,
3751 &dwAddressBufferSize );
3752 if( !bBuildPass )
3754 ERR( "Can't build compound addr\n" );
3755 return DPERR_GENERIC;
3758 /* The enumeration will return FALSE if we are not to continue */
3759 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3760 &dpName, DPCONNECTION_DIRECTPLAY, lpContext ) )
3762 return DP_OK;
3767 /* Enumerate DirectPlayLobby service providers */
3768 if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY )
3770 HKEY hkResult;
3771 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3772 LPCSTR guidDataSubKey = "Guid";
3773 char subKeyName[51];
3774 DWORD dwIndex, sizeOfSubKeyName=50;
3775 FILETIME filetime;
3777 /* Need to loop over the service providers in the registry */
3778 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3779 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3781 /* Hmmm. Does this mean that there are no service providers? */
3782 ERR(": no service providers?\n");
3783 return DP_OK;
3787 /* Traverse all the lobby providers we have available */
3788 for( dwIndex=0;
3789 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3790 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3791 ++dwIndex, sizeOfSubKeyName=51 )
3794 HKEY hkServiceProvider;
3795 GUID serviceProviderGUID;
3796 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3797 char returnBuffer[51];
3798 WCHAR buff[51];
3799 DPNAME dpName;
3800 HRESULT hr;
3802 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3803 LPVOID lpAddressBuffer = NULL;
3804 DWORD dwAddressBufferSize = 0;
3806 TRACE(" this time through: %s\n", subKeyName );
3808 /* Get a handle for this particular service provider */
3809 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3810 &hkServiceProvider ) != ERROR_SUCCESS )
3812 ERR(": what the heck is going on?\n" );
3813 continue;
3816 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3817 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
3818 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3820 ERR(": missing GUID registry data members\n" );
3821 continue;
3824 /* FIXME: Check return types to ensure we're interpreting data right */
3825 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3826 CLSIDFromString( buff, &serviceProviderGUID );
3827 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3829 /* Fill in the DPNAME struct for the service provider */
3830 dpName.dwSize = sizeof( dpName );
3831 dpName.dwFlags = 0;
3832 dpName.u1.lpszShortNameA = subKeyName;
3833 dpName.u2.lpszLongNameA = NULL;
3835 /* Create the compound address for the service provider.
3836 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
3837 nast stuff. This may be why the native dll just gets around this little bit by
3838 allocating an 80 byte buffer which isn't even a filled with a valid compound
3839 address. Oh well. Creating a proper compound address is the way to go anyways
3840 despite this method taking slightly more heap space and realtime :) */
3842 dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
3843 dpCompoundAddress.dwDataSize = sizeof( GUID );
3844 dpCompoundAddress.lpData = &serviceProviderGUID;
3846 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3847 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
3849 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3850 return hr;
3853 /* Now allocate the buffer */
3854 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
3856 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3857 &dwAddressBufferSize, TRUE ) ) != DP_OK )
3859 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3860 return hr;
3863 /* The enumeration will return FALSE if we are not to continue */
3864 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3865 &dpName, DPCONNECTION_DIRECTPLAYLOBBY, lpContext ) )
3867 return DP_OK;
3872 return DP_OK;
3875 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
3876 ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3878 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3879 FIXME("(%p)->(%p,%p,%p,0x%08x): stub\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3880 return DP_OK;
3883 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
3884 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
3885 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
3886 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
3888 lpGroupList lpGList;
3889 lpGroupData lpGData;
3891 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
3892 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
3893 lpContext, dwFlags, bAnsi );
3895 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3897 return DPERR_INVALIDGROUP;
3900 if( DPQ_IS_EMPTY( lpGData->groups ) )
3902 return DP_OK;
3905 lpGList = DPQ_FIRST( lpGData->groups );
3907 for( ;; )
3909 /* FIXME: Should check dwFlags for match here */
3911 if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP,
3912 &lpGList->lpGData->name, dwFlags,
3913 lpContext ) )
3915 return DP_OK; /* User requested break */
3918 if( DPQ_IS_ENDOFLIST( lpGList->groups ) )
3920 break;
3923 lpGList = DPQ_NEXT( lpGList->groups );
3927 return DP_OK;
3930 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
3931 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3932 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3933 DWORD dwFlags )
3935 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3936 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3937 lpEnumPlayersCallback2, lpContext, dwFlags,
3938 TRUE );
3941 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
3942 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3943 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3944 DWORD dwFlags )
3946 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3947 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3948 lpEnumPlayersCallback2, lpContext, dwFlags,
3949 FALSE );
3952 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
3953 ( LPDIRECTPLAY3A 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 HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
3961 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3963 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3964 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3965 return DP_OK;
3968 static BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
3969 REFGUID guidDataType,
3970 DWORD dwDataSize,
3971 LPCVOID lpData,
3972 LPVOID lpContext )
3974 /* Looking for the GUID of the provider to load */
3975 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
3976 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
3979 TRACE( "Found SP/LP (%s) %s (data size = 0x%08x)\n",
3980 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
3982 if( dwDataSize != sizeof( GUID ) )
3984 ERR( "Invalid sp/lp guid size 0x%08x\n", dwDataSize );
3987 memcpy( lpContext, lpData, dwDataSize );
3989 /* There shouldn't be more than 1 GUID/compound address */
3990 return FALSE;
3993 /* Still waiting for what we want */
3994 return TRUE;
3998 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
3999 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
4001 UINT i;
4002 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4003 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
4004 LPCSTR guidDataSubKey = "Guid";
4005 LPCSTR majVerDataSubKey = "dwReserved1";
4006 LPCSTR minVerDataSubKey = "dwReserved2";
4007 LPCSTR pathSubKey = "Path";
4009 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
4011 /* FIXME: Cloned code with a quick hack. */
4012 for( i=0; i<2; i++ )
4014 HKEY hkResult;
4015 LPCSTR searchSubKey;
4016 char subKeyName[51];
4017 DWORD dwIndex, sizeOfSubKeyName=50;
4018 FILETIME filetime;
4020 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
4021 *lpbIsDpSp = (i == 0) ? TRUE : FALSE;
4024 /* Need to loop over the service providers in the registry */
4025 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4026 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4028 /* Hmmm. Does this mean that there are no service providers? */
4029 ERR(": no service providers?\n");
4030 return 0;
4033 /* Traverse all the service providers we have available */
4034 for( dwIndex=0;
4035 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4036 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4037 ++dwIndex, sizeOfSubKeyName=51 )
4040 HKEY hkServiceProvider;
4041 GUID serviceProviderGUID;
4042 DWORD returnType, sizeOfReturnBuffer = 255;
4043 char returnBuffer[256];
4044 WCHAR buff[51];
4045 DWORD dwTemp, len;
4047 TRACE(" this time through: %s\n", subKeyName );
4049 /* Get a handle for this particular service provider */
4050 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4051 &hkServiceProvider ) != ERROR_SUCCESS )
4053 ERR(": what the heck is going on?\n" );
4054 continue;
4057 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4058 NULL, &returnType, (LPBYTE)returnBuffer,
4059 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4061 ERR(": missing GUID registry data members\n" );
4062 continue;
4065 /* FIXME: Check return types to ensure we're interpreting data right */
4066 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4067 CLSIDFromString( buff, &serviceProviderGUID );
4068 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4070 /* Determine if this is the Service Provider that the user asked for */
4071 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
4073 continue;
4076 if( i == 0 ) /* DP SP */
4078 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
4079 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
4080 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
4083 sizeOfReturnBuffer = 255;
4085 /* Get dwReserved1 */
4086 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
4087 NULL, &returnType, (LPBYTE)returnBuffer,
4088 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4090 ERR(": missing dwReserved1 registry data members\n") ;
4091 continue;
4094 if( i == 0 )
4095 memcpy( &lpSpData->dwReserved1, returnBuffer, sizeof(lpSpData->dwReserved1) );
4097 sizeOfReturnBuffer = 255;
4099 /* Get dwReserved2 */
4100 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4101 NULL, &returnType, (LPBYTE)returnBuffer,
4102 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4104 ERR(": missing dwReserved1 registry data members\n") ;
4105 continue;
4108 if( i == 0 )
4109 memcpy( &lpSpData->dwReserved2, returnBuffer, sizeof(lpSpData->dwReserved2) );
4111 sizeOfReturnBuffer = 255;
4113 /* Get the path for this service provider */
4114 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
4115 NULL, NULL, (LPBYTE)returnBuffer,
4116 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
4118 ERR(": missing PATH registry data members: 0x%08x\n", dwTemp );
4119 continue;
4122 TRACE( "Loading %s\n", returnBuffer );
4123 return LoadLibraryA( returnBuffer );
4127 return 0;
4130 static
4131 HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider )
4133 HRESULT hr;
4134 LPDPSP_SPINIT SPInit;
4136 /* Initialize the service provider by calling SPInit */
4137 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4139 if( SPInit == NULL )
4141 ERR( "Service provider doesn't provide SPInit interface?\n" );
4142 FreeLibrary( hServiceProvider );
4143 return DPERR_UNAVAILABLE;
4146 TRACE( "Calling SPInit (DP SP entry point)\n" );
4148 hr = (*SPInit)( &This->dp2->spData );
4150 if( FAILED(hr) )
4152 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4153 FreeLibrary( hServiceProvider );
4154 return hr;
4157 /* FIXME: Need to verify the sanity of the returned callback table
4158 * using IsBadCodePtr */
4159 This->dp2->bSPInitialized = TRUE;
4161 /* This interface is now initialized as a DP object */
4162 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
4164 /* Store the handle of the module so that we can unload it later */
4165 This->dp2->hServiceProvider = hServiceProvider;
4167 return hr;
4170 static
4171 HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hLobbyProvider )
4173 HRESULT hr;
4174 LPSP_INIT DPLSPInit;
4176 /* Initialize the service provider by calling SPInit */
4177 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
4179 if( DPLSPInit == NULL )
4181 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4182 FreeLibrary( hLobbyProvider );
4183 return DPERR_UNAVAILABLE;
4186 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4188 hr = (*DPLSPInit)( &This->dp2->dplspData );
4190 if( FAILED(hr) )
4192 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4193 FreeLibrary( hLobbyProvider );
4194 return hr;
4197 /* FIXME: Need to verify the sanity of the returned callback table
4198 * using IsBadCodePtr */
4200 This->dp2->bDPLSPInitialized = TRUE;
4202 /* This interface is now initialized as a lobby object */
4203 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
4205 /* Store the handle of the module so that we can unload it later */
4206 This->dp2->hDPLobbyProvider = hLobbyProvider;
4208 return hr;
4211 static HRESULT WINAPI DP_IF_InitializeConnection
4212 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi )
4214 HMODULE hServiceProvider;
4215 HRESULT hr;
4216 GUID guidSP;
4217 const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
4218 BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4220 TRACE("(%p)->(%p,0x%08x,%u)\n", This, lpConnection, dwFlags, bAnsi );
4222 if( dwFlags != 0 )
4224 return DPERR_INVALIDFLAGS;
4227 /* Find out what the requested SP is and how large this buffer is */
4228 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
4229 dwAddrSize, &guidSP );
4231 if( FAILED(hr) )
4233 ERR( "Invalid compound address?\n" );
4234 return DPERR_UNAVAILABLE;
4237 /* Load the service provider */
4238 hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp );
4240 if( hServiceProvider == 0 )
4242 ERR( "Unable to load service provider %s\n", debugstr_guid(&guidSP) );
4243 return DPERR_UNAVAILABLE;
4246 if( bIsDpSp )
4248 /* Fill in what we can of the Service Provider required information.
4249 * The rest was be done in DP_LoadSP
4251 This->dp2->spData.lpAddress = lpConnection;
4252 This->dp2->spData.dwAddressSize = dwAddrSize;
4253 This->dp2->spData.lpGuid = &guidSP;
4255 hr = DP_InitializeDPSP( This, hServiceProvider );
4257 else
4259 This->dp2->dplspData.lpAddress = lpConnection;
4261 hr = DP_InitializeDPLSP( This, hServiceProvider );
4264 if( FAILED(hr) )
4266 return hr;
4269 return DP_OK;
4272 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4273 ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
4275 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4277 /* This may not be externally invoked once either an SP or LP is initialized */
4278 if( This->dp2->connectionInitialized != NO_PROVIDER )
4280 return DPERR_ALREADYINITIALIZED;
4283 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE );
4286 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4287 ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
4289 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4291 /* This may not be externally invoked once either an SP or LP is initialized */
4292 if( This->dp2->connectionInitialized != NO_PROVIDER )
4294 return DPERR_ALREADYINITIALIZED;
4297 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE );
4300 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4301 ( LPDIRECTPLAY3A 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, TRUE );
4308 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4309 ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4310 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4312 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4313 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4316 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4317 ( LPDIRECTPLAY3A 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 DirectPlay3WImpl_SendChatMessage
4325 ( LPDIRECTPLAY3 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4327 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4328 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4329 return DP_OK;
4332 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4333 ( LPDIRECTPLAY3A 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 DirectPlay3WImpl_SetGroupConnectionSettings
4341 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4343 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4344 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4345 return DP_OK;
4348 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4349 ( LPDIRECTPLAY3A 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 DirectPlay3WImpl_StartSession
4357 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup )
4359 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4360 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, dwFlags, idGroup );
4361 return DP_OK;
4364 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4365 ( LPDIRECTPLAY3A 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 DirectPlay3WImpl_GetGroupFlags
4373 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDWORD lpdwFlags )
4375 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4376 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpdwFlags );
4377 return DP_OK;
4380 static HRESULT WINAPI DP_IF_GetGroupParent
4381 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
4382 BOOL bAnsi )
4384 lpGroupData lpGData;
4386 TRACE("(%p)->(0x%08x,%p,%u)\n", This, idGroup, lpidGroup, bAnsi );
4388 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4390 return DPERR_INVALIDGROUP;
4393 *lpidGroup = lpGData->dpid;
4395 return DP_OK;
4398 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4399 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
4401 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4402 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE );
4404 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4405 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
4407 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4408 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE );
4411 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4412 ( LPDIRECTPLAY3A 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 DirectPlay3WImpl_GetPlayerAccount
4420 ( LPDIRECTPLAY3 iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4422 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4423 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4424 return DP_OK;
4427 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4428 ( LPDIRECTPLAY3A 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 DirectPlay3WImpl_GetPlayerFlags
4436 ( LPDIRECTPLAY3 iface, DPID idPlayer, LPDWORD lpdwFlags )
4438 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4439 FIXME("(%p)->(0x%08x,%p): stub\n", This, idPlayer, lpdwFlags );
4440 return DP_OK;
4443 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4444 ( LPDIRECTPLAY4A 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 DirectPlay4WImpl_GetGroupOwner
4452 ( LPDIRECTPLAY4 iface, DPID idGroup, LPDPID lpidGroupOwner )
4454 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4455 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpidGroupOwner );
4456 return DP_OK;
4459 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4460 ( LPDIRECTPLAY4A 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 DirectPlay4WImpl_SetGroupOwner
4468 ( LPDIRECTPLAY4 iface, DPID idGroup , DPID idGroupOwner )
4470 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4471 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, idGroup, idGroupOwner );
4472 return DP_OK;
4475 static HRESULT WINAPI DP_SendEx
4476 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4477 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4478 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi )
4480 lpPlayerList lpPList;
4481 lpGroupData lpGData;
4482 BOOL bValidDestination = FALSE;
4484 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,0x%08x,0x%08x,0x%08x,%p,%p,%u)"
4485 ": stub\n",
4486 This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority,
4487 dwTimeout, lpContext, lpdwMsgID, bAnsi );
4489 /* FIXME: Add parameter checking */
4490 /* FIXME: First call to this needs to acquire a message id which will be
4491 * used for multiple sends
4494 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4496 /* Verify that the message is being sent from a valid local player. The
4497 * from player may be anonymous DPID_UNKNOWN
4499 if( idFrom != DPID_UNKNOWN )
4501 if( ( lpPList = DP_FindPlayer( This, idFrom ) ) == NULL )
4503 WARN( "INFO: Invalid from player 0x%08x\n", idFrom );
4504 return DPERR_INVALIDPLAYER;
4508 /* Verify that the message is being sent to a valid player, group or to
4509 * everyone. If it's valid, send it to those players.
4511 if( idTo == DPID_ALLPLAYERS )
4513 bValidDestination = TRUE;
4515 /* See if SP has the ability to multicast. If so, use it */
4516 if( This->dp2->spData.lpCB->SendToGroupEx )
4518 FIXME( "Use group sendex to group 0\n" );
4520 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4522 FIXME( "Use obsolete group send to group 0\n" );
4524 else /* No multicast, multiplicate */
4526 /* Send to all players we know about */
4527 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4531 if( ( !bValidDestination ) &&
4532 ( DP_FindPlayer( This, idTo ) != NULL )
4535 bValidDestination = TRUE;
4537 /* Have the service provider send this message */
4538 /* FIXME: Could optimize for local interface sends */
4539 return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority,
4540 dwTimeout, lpContext, lpdwMsgID );
4543 if( ( !bValidDestination ) &&
4544 ( ( lpGData = DP_FindAnyGroup( This, idTo ) ) != NULL )
4547 bValidDestination = TRUE;
4549 /* See if SP has the ability to multicast. If so, use it */
4550 if( This->dp2->spData.lpCB->SendToGroupEx )
4552 FIXME( "Use group sendex\n" );
4554 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4556 FIXME( "Use obsolete group send to group\n" );
4558 else /* No multicast, multiplicate */
4560 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4563 #if 0
4564 if( bExpectReply )
4566 DWORD dwWaitReturn;
4568 This->dp2->hReplyEvent = CreateEventW( NULL, FALSE, FALSE, NULL );
4570 dwWaitReturn = WaitForSingleObject( hReplyEvent, dwTimeout );
4571 if( dwWaitReturn != WAIT_OBJECT_0 )
4573 ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
4576 #endif
4579 if( !bValidDestination )
4581 return DPERR_INVALIDPLAYER;
4583 else
4585 /* FIXME: Should return what the send returned */
4586 return DP_OK;
4591 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4592 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4593 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4594 LPVOID lpContext, LPDWORD lpdwMsgID )
4596 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4597 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4598 dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE );
4601 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4602 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4603 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4604 LPVOID lpContext, LPDWORD lpdwMsgID )
4606 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4607 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4608 dwPriority, dwTimeout, lpContext, lpdwMsgID, FALSE );
4611 static HRESULT WINAPI DP_SP_SendEx
4612 ( IDirectPlay2Impl* This, DWORD dwFlags,
4613 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4614 LPVOID lpContext, LPDWORD lpdwMsgID )
4616 LPDPMSG lpMElem;
4618 FIXME( ": stub\n" );
4620 /* FIXME: This queuing should only be for async messages */
4622 lpMElem = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpMElem ) );
4623 lpMElem->msg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
4625 CopyMemory( lpMElem->msg, lpData, dwDataSize );
4627 /* FIXME: Need to queue based on priority */
4628 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
4630 return DP_OK;
4633 static HRESULT WINAPI DP_IF_GetMessageQueue
4634 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4635 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi )
4637 HRESULT hr = DP_OK;
4639 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%p,%u): semi stub\n",
4640 This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi );
4642 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4643 /* FIXME: What about sends which are not immediate? */
4645 if( This->dp2->spData.lpCB->GetMessageQueue )
4647 DPSP_GETMESSAGEQUEUEDATA data;
4649 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4651 /* FIXME: None of this is documented :( */
4653 data.lpISP = This->dp2->spData.lpISP;
4654 data.dwFlags = dwFlags;
4655 data.idFrom = idFrom;
4656 data.idTo = idTo;
4657 data.lpdwNumMsgs = lpdwNumMsgs;
4658 data.lpdwNumBytes = lpdwNumBytes;
4660 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
4662 else
4664 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4667 return hr;
4670 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4671 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4672 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4674 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4675 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4676 lpdwNumBytes, TRUE );
4679 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4680 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4681 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4683 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4684 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4685 lpdwNumBytes, FALSE );
4688 static HRESULT WINAPI DP_IF_CancelMessage
4689 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
4690 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi )
4692 HRESULT hr = DP_OK;
4694 FIXME( "(%p)->(0x%08x,0x%08x,%u): semi stub\n",
4695 This, dwMsgID, dwFlags, bAnsi );
4697 if( This->dp2->spData.lpCB->Cancel )
4699 DPSP_CANCELDATA data;
4701 TRACE( "Calling SP Cancel\n" );
4703 /* FIXME: Undocumented callback */
4705 data.lpISP = This->dp2->spData.lpISP;
4706 data.dwFlags = dwFlags;
4707 data.lprglpvSPMsgID = NULL;
4708 data.cSPMsgID = dwMsgID;
4709 data.dwMinPriority = dwMinPriority;
4710 data.dwMaxPriority = dwMaxPriority;
4712 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
4714 else
4716 FIXME( "SP doesn't implement Cancel\n" );
4719 return hr;
4722 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
4723 ( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags )
4725 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4727 if( dwFlags != 0 )
4729 return DPERR_INVALIDFLAGS;
4732 if( dwMsgID == 0 )
4734 dwFlags |= DPCANCELSEND_ALL;
4737 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE );
4740 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
4741 ( LPDIRECTPLAY4 iface, DWORD dwMsgID, DWORD dwFlags )
4743 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4745 if( dwFlags != 0 )
4747 return DPERR_INVALIDFLAGS;
4750 if( dwMsgID == 0 )
4752 dwFlags |= DPCANCELSEND_ALL;
4755 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, FALSE );
4758 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
4759 ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4760 DWORD dwFlags )
4762 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4764 if( dwFlags != 0 )
4766 return DPERR_INVALIDFLAGS;
4769 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4770 dwMaxPriority, TRUE );
4773 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
4774 ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4775 DWORD dwFlags )
4777 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4779 if( dwFlags != 0 )
4781 return DPERR_INVALIDFLAGS;
4784 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4785 dwMaxPriority, FALSE );
4788 /* Note: Hack so we can reuse the old functions without compiler warnings */
4789 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4790 # define XCAST(fun) (typeof(directPlay2WVT.fun))
4791 #else
4792 # define XCAST(fun) (void*)
4793 #endif
4795 static const IDirectPlay2Vtbl directPlay2WVT =
4797 XCAST(QueryInterface)DP_QueryInterface,
4798 XCAST(AddRef)DP_AddRef,
4799 XCAST(Release)DP_Release,
4801 DirectPlay2WImpl_AddPlayerToGroup,
4802 DirectPlay2WImpl_Close,
4803 DirectPlay2WImpl_CreateGroup,
4804 DirectPlay2WImpl_CreatePlayer,
4805 DirectPlay2WImpl_DeletePlayerFromGroup,
4806 DirectPlay2WImpl_DestroyGroup,
4807 DirectPlay2WImpl_DestroyPlayer,
4808 DirectPlay2WImpl_EnumGroupPlayers,
4809 DirectPlay2WImpl_EnumGroups,
4810 DirectPlay2WImpl_EnumPlayers,
4811 DirectPlay2WImpl_EnumSessions,
4812 DirectPlay2WImpl_GetCaps,
4813 DirectPlay2WImpl_GetGroupData,
4814 DirectPlay2WImpl_GetGroupName,
4815 DirectPlay2WImpl_GetMessageCount,
4816 DirectPlay2WImpl_GetPlayerAddress,
4817 DirectPlay2WImpl_GetPlayerCaps,
4818 DirectPlay2WImpl_GetPlayerData,
4819 DirectPlay2WImpl_GetPlayerName,
4820 DirectPlay2WImpl_GetSessionDesc,
4821 DirectPlay2WImpl_Initialize,
4822 DirectPlay2WImpl_Open,
4823 DirectPlay2WImpl_Receive,
4824 DirectPlay2WImpl_Send,
4825 DirectPlay2WImpl_SetGroupData,
4826 DirectPlay2WImpl_SetGroupName,
4827 DirectPlay2WImpl_SetPlayerData,
4828 DirectPlay2WImpl_SetPlayerName,
4829 DirectPlay2WImpl_SetSessionDesc
4831 #undef XCAST
4833 /* Note: Hack so we can reuse the old functions without compiler warnings */
4834 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4835 # define XCAST(fun) (typeof(directPlay2AVT.fun))
4836 #else
4837 # define XCAST(fun) (void*)
4838 #endif
4840 static const IDirectPlay2Vtbl directPlay2AVT =
4842 XCAST(QueryInterface)DP_QueryInterface,
4843 XCAST(AddRef)DP_AddRef,
4844 XCAST(Release)DP_Release,
4846 DirectPlay2AImpl_AddPlayerToGroup,
4847 DirectPlay2AImpl_Close,
4848 DirectPlay2AImpl_CreateGroup,
4849 DirectPlay2AImpl_CreatePlayer,
4850 DirectPlay2AImpl_DeletePlayerFromGroup,
4851 DirectPlay2AImpl_DestroyGroup,
4852 DirectPlay2AImpl_DestroyPlayer,
4853 DirectPlay2AImpl_EnumGroupPlayers,
4854 DirectPlay2AImpl_EnumGroups,
4855 DirectPlay2AImpl_EnumPlayers,
4856 DirectPlay2AImpl_EnumSessions,
4857 DirectPlay2AImpl_GetCaps,
4858 DirectPlay2AImpl_GetGroupData,
4859 DirectPlay2AImpl_GetGroupName,
4860 DirectPlay2AImpl_GetMessageCount,
4861 DirectPlay2AImpl_GetPlayerAddress,
4862 DirectPlay2AImpl_GetPlayerCaps,
4863 DirectPlay2AImpl_GetPlayerData,
4864 DirectPlay2AImpl_GetPlayerName,
4865 DirectPlay2AImpl_GetSessionDesc,
4866 DirectPlay2AImpl_Initialize,
4867 DirectPlay2AImpl_Open,
4868 DirectPlay2AImpl_Receive,
4869 DirectPlay2AImpl_Send,
4870 DirectPlay2AImpl_SetGroupData,
4871 DirectPlay2AImpl_SetGroupName,
4872 DirectPlay2AImpl_SetPlayerData,
4873 DirectPlay2AImpl_SetPlayerName,
4874 DirectPlay2AImpl_SetSessionDesc
4876 #undef XCAST
4879 /* Note: Hack so we can reuse the old functions without compiler warnings */
4880 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4881 # define XCAST(fun) (typeof(directPlay3AVT.fun))
4882 #else
4883 # define XCAST(fun) (void*)
4884 #endif
4886 static const IDirectPlay3Vtbl directPlay3AVT =
4888 XCAST(QueryInterface)DP_QueryInterface,
4889 XCAST(AddRef)DP_AddRef,
4890 XCAST(Release)DP_Release,
4892 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
4893 XCAST(Close)DirectPlay2AImpl_Close,
4894 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
4895 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
4896 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
4897 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
4898 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
4899 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
4900 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
4901 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
4902 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
4903 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
4904 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
4905 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
4906 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
4907 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
4908 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
4909 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
4910 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
4911 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
4912 XCAST(Initialize)DirectPlay2AImpl_Initialize,
4913 XCAST(Open)DirectPlay2AImpl_Open,
4914 XCAST(Receive)DirectPlay2AImpl_Receive,
4915 XCAST(Send)DirectPlay2AImpl_Send,
4916 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
4917 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
4918 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
4919 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
4920 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
4922 DirectPlay3AImpl_AddGroupToGroup,
4923 DirectPlay3AImpl_CreateGroupInGroup,
4924 DirectPlay3AImpl_DeleteGroupFromGroup,
4925 DirectPlay3AImpl_EnumConnections,
4926 DirectPlay3AImpl_EnumGroupsInGroup,
4927 DirectPlay3AImpl_GetGroupConnectionSettings,
4928 DirectPlay3AImpl_InitializeConnection,
4929 DirectPlay3AImpl_SecureOpen,
4930 DirectPlay3AImpl_SendChatMessage,
4931 DirectPlay3AImpl_SetGroupConnectionSettings,
4932 DirectPlay3AImpl_StartSession,
4933 DirectPlay3AImpl_GetGroupFlags,
4934 DirectPlay3AImpl_GetGroupParent,
4935 DirectPlay3AImpl_GetPlayerAccount,
4936 DirectPlay3AImpl_GetPlayerFlags
4938 #undef XCAST
4940 /* Note: Hack so we can reuse the old functions without compiler warnings */
4941 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4942 # define XCAST(fun) (typeof(directPlay3WVT.fun))
4943 #else
4944 # define XCAST(fun) (void*)
4945 #endif
4946 static const IDirectPlay3Vtbl directPlay3WVT =
4948 XCAST(QueryInterface)DP_QueryInterface,
4949 XCAST(AddRef)DP_AddRef,
4950 XCAST(Release)DP_Release,
4952 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
4953 XCAST(Close)DirectPlay2WImpl_Close,
4954 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
4955 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
4956 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
4957 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
4958 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
4959 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
4960 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
4961 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
4962 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
4963 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
4964 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
4965 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
4966 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
4967 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
4968 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
4969 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
4970 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
4971 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
4972 XCAST(Initialize)DirectPlay2WImpl_Initialize,
4973 XCAST(Open)DirectPlay2WImpl_Open,
4974 XCAST(Receive)DirectPlay2WImpl_Receive,
4975 XCAST(Send)DirectPlay2WImpl_Send,
4976 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
4977 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
4978 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
4979 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
4980 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
4982 DirectPlay3WImpl_AddGroupToGroup,
4983 DirectPlay3WImpl_CreateGroupInGroup,
4984 DirectPlay3WImpl_DeleteGroupFromGroup,
4985 DirectPlay3WImpl_EnumConnections,
4986 DirectPlay3WImpl_EnumGroupsInGroup,
4987 DirectPlay3WImpl_GetGroupConnectionSettings,
4988 DirectPlay3WImpl_InitializeConnection,
4989 DirectPlay3WImpl_SecureOpen,
4990 DirectPlay3WImpl_SendChatMessage,
4991 DirectPlay3WImpl_SetGroupConnectionSettings,
4992 DirectPlay3WImpl_StartSession,
4993 DirectPlay3WImpl_GetGroupFlags,
4994 DirectPlay3WImpl_GetGroupParent,
4995 DirectPlay3WImpl_GetPlayerAccount,
4996 DirectPlay3WImpl_GetPlayerFlags
4998 #undef XCAST
5000 /* Note: Hack so we can reuse the old functions without compiler warnings */
5001 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5002 # define XCAST(fun) (typeof(directPlay4WVT.fun))
5003 #else
5004 # define XCAST(fun) (void*)
5005 #endif
5006 static const IDirectPlay4Vtbl directPlay4WVT =
5008 XCAST(QueryInterface)DP_QueryInterface,
5009 XCAST(AddRef)DP_AddRef,
5010 XCAST(Release)DP_Release,
5012 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
5013 XCAST(Close)DirectPlay2WImpl_Close,
5014 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
5015 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
5016 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
5017 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
5018 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5019 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5020 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5021 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5022 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5023 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5024 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5025 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5026 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5027 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5028 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5029 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5030 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5031 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5032 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5033 XCAST(Open)DirectPlay2WImpl_Open,
5034 XCAST(Receive)DirectPlay2WImpl_Receive,
5035 XCAST(Send)DirectPlay2WImpl_Send,
5036 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5037 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5038 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5039 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5040 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5042 XCAST(AddGroupToGroup)DirectPlay3WImpl_AddGroupToGroup,
5043 XCAST(CreateGroupInGroup)DirectPlay3WImpl_CreateGroupInGroup,
5044 XCAST(DeleteGroupFromGroup)DirectPlay3WImpl_DeleteGroupFromGroup,
5045 XCAST(EnumConnections)DirectPlay3WImpl_EnumConnections,
5046 XCAST(EnumGroupsInGroup)DirectPlay3WImpl_EnumGroupsInGroup,
5047 XCAST(GetGroupConnectionSettings)DirectPlay3WImpl_GetGroupConnectionSettings,
5048 XCAST(InitializeConnection)DirectPlay3WImpl_InitializeConnection,
5049 XCAST(SecureOpen)DirectPlay3WImpl_SecureOpen,
5050 XCAST(SendChatMessage)DirectPlay3WImpl_SendChatMessage,
5051 XCAST(SetGroupConnectionSettings)DirectPlay3WImpl_SetGroupConnectionSettings,
5052 XCAST(StartSession)DirectPlay3WImpl_StartSession,
5053 XCAST(GetGroupFlags)DirectPlay3WImpl_GetGroupFlags,
5054 XCAST(GetGroupParent)DirectPlay3WImpl_GetGroupParent,
5055 XCAST(GetPlayerAccount)DirectPlay3WImpl_GetPlayerAccount,
5056 XCAST(GetPlayerFlags)DirectPlay3WImpl_GetPlayerFlags,
5058 DirectPlay4WImpl_GetGroupOwner,
5059 DirectPlay4WImpl_SetGroupOwner,
5060 DirectPlay4WImpl_SendEx,
5061 DirectPlay4WImpl_GetMessageQueue,
5062 DirectPlay4WImpl_CancelMessage,
5063 DirectPlay4WImpl_CancelPriority
5065 #undef XCAST
5068 /* Note: Hack so we can reuse the old functions without compiler warnings */
5069 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5070 # define XCAST(fun) (typeof(directPlay4AVT.fun))
5071 #else
5072 # define XCAST(fun) (void*)
5073 #endif
5074 static const IDirectPlay4Vtbl directPlay4AVT =
5076 XCAST(QueryInterface)DP_QueryInterface,
5077 XCAST(AddRef)DP_AddRef,
5078 XCAST(Release)DP_Release,
5080 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
5081 XCAST(Close)DirectPlay2AImpl_Close,
5082 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
5083 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
5084 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
5085 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
5086 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
5087 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
5088 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
5089 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
5090 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
5091 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
5092 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
5093 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
5094 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5095 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5096 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5097 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5098 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5099 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5100 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5101 XCAST(Open)DirectPlay2AImpl_Open,
5102 XCAST(Receive)DirectPlay2AImpl_Receive,
5103 XCAST(Send)DirectPlay2AImpl_Send,
5104 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5105 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5106 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5107 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5108 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5110 XCAST(AddGroupToGroup)DirectPlay3AImpl_AddGroupToGroup,
5111 XCAST(CreateGroupInGroup)DirectPlay3AImpl_CreateGroupInGroup,
5112 XCAST(DeleteGroupFromGroup)DirectPlay3AImpl_DeleteGroupFromGroup,
5113 XCAST(EnumConnections)DirectPlay3AImpl_EnumConnections,
5114 XCAST(EnumGroupsInGroup)DirectPlay3AImpl_EnumGroupsInGroup,
5115 XCAST(GetGroupConnectionSettings)DirectPlay3AImpl_GetGroupConnectionSettings,
5116 XCAST(InitializeConnection)DirectPlay3AImpl_InitializeConnection,
5117 XCAST(SecureOpen)DirectPlay3AImpl_SecureOpen,
5118 XCAST(SendChatMessage)DirectPlay3AImpl_SendChatMessage,
5119 XCAST(SetGroupConnectionSettings)DirectPlay3AImpl_SetGroupConnectionSettings,
5120 XCAST(StartSession)DirectPlay3AImpl_StartSession,
5121 XCAST(GetGroupFlags)DirectPlay3AImpl_GetGroupFlags,
5122 XCAST(GetGroupParent)DirectPlay3AImpl_GetGroupParent,
5123 XCAST(GetPlayerAccount)DirectPlay3AImpl_GetPlayerAccount,
5124 XCAST(GetPlayerFlags)DirectPlay3AImpl_GetPlayerFlags,
5126 DirectPlay4AImpl_GetGroupOwner,
5127 DirectPlay4AImpl_SetGroupOwner,
5128 DirectPlay4AImpl_SendEx,
5129 DirectPlay4AImpl_GetMessageQueue,
5130 DirectPlay4AImpl_CancelMessage,
5131 DirectPlay4AImpl_CancelPriority
5133 #undef XCAST
5135 extern
5136 HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP,
5137 DPID idPlayer,
5138 LPVOID* lplpData )
5140 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5142 if( lpPlayer == NULL )
5144 return DPERR_INVALIDPLAYER;
5147 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
5149 return DP_OK;
5152 extern
5153 HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP,
5154 DPID idPlayer,
5155 LPVOID lpData )
5157 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5159 if( lpPlayer == NULL )
5161 return DPERR_INVALIDPLAYER;
5164 lpPlayer->lpPData->lpSPPlayerData = lpData;
5166 return DP_OK;
5169 /***************************************************************************
5170 * DirectPlayEnumerateAW
5172 * The pointer to the structure lpContext will be filled with the
5173 * appropriate data for each service offered by the OS. These services are
5174 * not necessarily available on this particular machine but are defined
5175 * as simple service providers under the "Service Providers" registry key.
5176 * This structure is then passed to lpEnumCallback for each of the different
5177 * services.
5179 * This API is useful only for applications written using DirectX3 or
5180 * worse. It is superseded by IDirectPlay3::EnumConnections which also
5181 * gives information on the actual connections.
5183 * defn of a service provider:
5184 * A dynamic-link library used by DirectPlay to communicate over a network.
5185 * The service provider contains all the network-specific code required
5186 * to send and receive messages. Online services and network operators can
5187 * supply service providers to use specialized hardware, protocols, communications
5188 * media, and network resources.
5191 static HRESULT DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA,
5192 LPDPENUMDPCALLBACKW lpEnumCallbackW,
5193 LPVOID lpContext)
5195 HKEY hkResult;
5196 static const WCHAR searchSubKey[] = {
5197 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
5198 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
5199 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
5200 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
5201 static const WCHAR guidKey[] = { 'G', 'u', 'i', 'd', 0 };
5202 static const WCHAR descW[] = { 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', 'W', 0 };
5204 DWORD dwIndex;
5205 FILETIME filetime;
5207 char *descriptionA = NULL;
5208 DWORD max_sizeOfDescriptionA = 0;
5209 WCHAR *descriptionW = NULL;
5210 DWORD max_sizeOfDescriptionW = 0;
5212 if (!lpEnumCallbackA && !lpEnumCallbackW)
5214 return DPERR_INVALIDPARAMS;
5217 /* Need to loop over the service providers in the registry */
5218 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, searchSubKey,
5219 0, KEY_READ, &hkResult) != ERROR_SUCCESS)
5221 /* Hmmm. Does this mean that there are no service providers? */
5222 ERR(": no service provider key in the registry - check your Wine installation !!!\n");
5223 return DPERR_GENERIC;
5226 /* Traverse all the service providers we have available */
5227 dwIndex = 0;
5228 while (1)
5230 WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */
5231 DWORD sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR);
5232 HKEY hkServiceProvider;
5233 GUID serviceProviderGUID;
5234 WCHAR guidKeyContent[(2 * 16) + 1 + 6 /* This corresponds to '{....-..-..-..-......}' */ ];
5235 DWORD sizeOfGuidKeyContent = sizeof(guidKeyContent);
5236 LONG ret_value;
5238 ret_value = RegEnumKeyExW(hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
5239 NULL, NULL, NULL, &filetime);
5240 if (ret_value == ERROR_NO_MORE_ITEMS)
5241 break;
5242 else if (ret_value != ERROR_SUCCESS)
5244 ERR(": could not enumerate on service provider key.\n");
5245 return DPERR_EXCEPTION;
5247 TRACE(" this time through sub-key %s.\n", debugstr_w(subKeyName));
5249 /* Open the key for this service provider */
5250 if (RegOpenKeyExW(hkResult, subKeyName, 0, KEY_READ, &hkServiceProvider) != ERROR_SUCCESS)
5252 ERR(": could not open registry key for service provider %s.\n", debugstr_w(subKeyName));
5253 continue;
5256 /* Get the GUID from the registry */
5257 if (RegQueryValueExW(hkServiceProvider, guidKey,
5258 NULL, NULL, (LPBYTE) guidKeyContent, &sizeOfGuidKeyContent) != ERROR_SUCCESS)
5260 ERR(": missing GUID registry data member for service provider %s.\n", debugstr_w(subKeyName));
5261 continue;
5263 if (sizeOfGuidKeyContent != sizeof(guidKeyContent))
5265 ERR(": invalid format for the GUID registry data member for service provider %s (%s).\n", debugstr_w(subKeyName), debugstr_w(guidKeyContent));
5266 continue;
5268 CLSIDFromString(guidKeyContent, &serviceProviderGUID );
5270 /* The enumeration will return FALSE if we are not to continue.
5272 * Note: on my windows box, major / minor version is 6 / 0 for all service providers
5273 * and have no relations to any of the two dwReserved1 and dwReserved2 keys.
5274 * I think that it simply means that they are in-line with DirectX 6.0
5276 if (lpEnumCallbackA)
5278 DWORD sizeOfDescription = 0;
5280 /* Note that this the the A case of this function, so use the A variant to get the description string */
5281 if (RegQueryValueExA(hkServiceProvider, "DescriptionA",
5282 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5284 ERR(": missing 'DescriptionA' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5285 continue;
5287 if (sizeOfDescription > max_sizeOfDescriptionA)
5289 HeapFree(GetProcessHeap(), 0, descriptionA);
5290 max_sizeOfDescriptionA = sizeOfDescription;
5291 descriptionA = HeapAlloc(GetProcessHeap(), 0, max_sizeOfDescriptionA);
5293 descriptionA = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5294 RegQueryValueExA(hkServiceProvider, "DescriptionA",
5295 NULL, NULL, (LPBYTE) descriptionA, &sizeOfDescription);
5297 if (!lpEnumCallbackA(&serviceProviderGUID, descriptionA, 6, 0, lpContext))
5298 goto end;
5300 else
5302 DWORD sizeOfDescription = 0;
5304 if (RegQueryValueExW(hkServiceProvider, descW,
5305 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5307 ERR(": missing 'DescriptionW' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5308 continue;
5310 if (sizeOfDescription > max_sizeOfDescriptionW)
5312 HeapFree(GetProcessHeap(), 0, descriptionW);
5313 max_sizeOfDescriptionW = sizeOfDescription;
5314 descriptionW = HeapAlloc(GetProcessHeap(), 0, max_sizeOfDescriptionW);
5316 descriptionW = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5317 RegQueryValueExW(hkServiceProvider, descW,
5318 NULL, NULL, (LPBYTE) descriptionW, &sizeOfDescription);
5320 if (!lpEnumCallbackW(&serviceProviderGUID, descriptionW, 6, 0, lpContext))
5321 goto end;
5324 dwIndex++;
5327 end:
5328 HeapFree(GetProcessHeap(), 0, descriptionA);
5329 HeapFree(GetProcessHeap(), 0, descriptionW);
5331 return DP_OK;
5334 /***************************************************************************
5335 * DirectPlayEnumerate [DPLAYX.9]
5336 * DirectPlayEnumerateA [DPLAYX.2]
5338 HRESULT WINAPI DirectPlayEnumerateA(LPDPENUMDPCALLBACKA lpEnumCallback, LPVOID lpContext )
5340 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5342 return DirectPlayEnumerateAW(lpEnumCallback, NULL, lpContext);
5345 /***************************************************************************
5346 * DirectPlayEnumerateW [DPLAYX.3]
5348 HRESULT WINAPI DirectPlayEnumerateW(LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5350 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5352 return DirectPlayEnumerateAW(NULL, lpEnumCallback, lpContext);
5355 typedef struct tagCreateEnum
5357 LPVOID lpConn;
5358 LPCGUID lpGuid;
5359 } CreateEnumData, *lpCreateEnumData;
5361 /* Find and copy the matching connection for the SP guid */
5362 static BOOL CALLBACK cbDPCreateEnumConnections(
5363 LPCGUID lpguidSP,
5364 LPVOID lpConnection,
5365 DWORD dwConnectionSize,
5366 LPCDPNAME lpName,
5367 DWORD dwFlags,
5368 LPVOID lpContext)
5370 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5372 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5374 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5376 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5377 dwConnectionSize );
5378 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5380 /* Found the record that we were looking for */
5381 return FALSE;
5384 /* Haven't found what were looking for yet */
5385 return TRUE;
5389 /***************************************************************************
5390 * DirectPlayCreate [DPLAYX.1]
5393 HRESULT WINAPI DirectPlayCreate
5394 ( LPGUID lpGUID, LPDIRECTPLAY2 *lplpDP, IUnknown *pUnk)
5396 HRESULT hr;
5397 LPDIRECTPLAY3A lpDP3A;
5398 CreateEnumData cbData;
5400 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5402 if( pUnk != NULL )
5404 return CLASS_E_NOAGGREGATION;
5407 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5408 give them an IDirectPlay2A object and hope that doesn't cause problems */
5409 if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
5411 return DPERR_UNAVAILABLE;
5414 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
5416 /* The GUID_NULL means don't bind a service provider. Just return the
5417 interface as is */
5418 return DP_OK;
5421 /* Bind the desired service provider since lpGUID is non NULL */
5422 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
5424 /* We're going to use a DP3 interface */
5425 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
5426 (LPVOID*)&lpDP3A );
5427 if( FAILED(hr) )
5429 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
5430 return hr;
5433 cbData.lpConn = NULL;
5434 cbData.lpGuid = lpGUID;
5436 /* We were given a service provider, find info about it... */
5437 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
5438 &cbData, DPCONNECTION_DIRECTPLAY );
5439 if( ( FAILED(hr) ) ||
5440 ( cbData.lpConn == NULL )
5443 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
5444 IDirectPlayX_Release( lpDP3A );
5445 return DPERR_UNAVAILABLE;
5448 /* Initialize the service provider */
5449 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
5450 if( FAILED(hr) )
5452 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
5453 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5454 IDirectPlayX_Release( lpDP3A );
5455 return hr;
5458 /* Release our version of the interface now that we're done with it */
5459 IDirectPlayX_Release( lpDP3A );
5460 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5462 return DP_OK;