mscms: Fix some wine_todo for GetStandardColorSpaceProfile().
[wine.git] / dlls / dplayx / dplay.c
blobc847987def5a674bbdc9c1d8c086bc40d1f7e24d
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "config.h"
21 #include "wine/port.h"
23 #include <stdarg.h>
24 #include <string.h>
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
28 #include "windef.h"
29 #include "winerror.h"
30 #include "winbase.h"
31 #include "winnt.h"
32 #include "winreg.h"
33 #include "winnls.h"
34 #include "wine/unicode.h"
35 #include "wine/debug.h"
37 #include "dpinit.h"
38 #include "dplayx_global.h"
39 #include "name_server.h"
40 #include "dplayx_queue.h"
41 #include "dplaysp.h"
42 #include "dplay_global.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(dplay);
46 /* FIXME: Should this be externed? */
47 extern HRESULT DPL_CreateCompoundAddress
48 ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
49 LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
52 /* Local function prototypes */
53 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid );
54 static lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* iface, LPDPID lpid,
55 LPDPNAME lpName, DWORD dwFlags,
56 HANDLE hEvent, BOOL bAnsi );
57 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi );
58 static void DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
59 LPVOID lpData, DWORD dwDataSize );
61 static lpGroupData DP_CreateGroup( IDirectPlay2AImpl* iface, LPDPID lpid,
62 LPDPNAME lpName, DWORD dwFlags,
63 DPID idParent, BOOL bAnsi );
64 static void DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
65 LPVOID lpData, DWORD dwDataSize );
66 static void DP_DeleteDPNameStruct( LPDPNAME lpDPName );
67 static void DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid );
68 static BOOL CALLBACK cbDeletePlayerFromAllGroups( DPID dpId,
69 DWORD dwPlayerType,
70 LPCDPNAME lpName,
71 DWORD dwFlags,
72 LPVOID lpContext );
73 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid );
74 static BOOL CALLBACK cbRemoveGroupOrPlayer( DPID dpId, DWORD dwPlayerType,
75 LPCDPNAME lpName, DWORD dwFlags,
76 LPVOID lpContext );
77 static void DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid );
79 /* Forward declarations of virtual tables */
80 static const IDirectPlay2Vtbl directPlay2AVT;
81 static const IDirectPlay3Vtbl directPlay3AVT;
82 static const IDirectPlay4Vtbl directPlay4AVT;
84 static const IDirectPlay2Vtbl directPlay2WVT;
85 static const IDirectPlay3Vtbl directPlay3WVT;
86 static const IDirectPlay4Vtbl directPlay4WVT;
88 /* Helper methods for player/group interfaces */
89 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
90 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
91 DPID idPlayer, BOOL bAnsi );
92 static HRESULT WINAPI DP_IF_CreatePlayer
93 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, LPDPID lpidPlayer,
94 LPDPNAME lpPlayerName, HANDLE hEvent, LPVOID lpData,
95 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
96 static HRESULT WINAPI DP_IF_DestroyGroup
97 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi );
98 static HRESULT WINAPI DP_IF_DestroyPlayer
99 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi );
100 static HRESULT WINAPI DP_IF_EnumGroupPlayers
101 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
102 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
103 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
104 static HRESULT WINAPI DP_IF_EnumGroups
105 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
106 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
107 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
108 static HRESULT WINAPI DP_IF_EnumPlayers
109 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
110 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
111 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
112 static HRESULT WINAPI DP_IF_GetGroupData
113 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
114 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
115 static HRESULT WINAPI DP_IF_GetGroupName
116 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
117 LPDWORD lpdwDataSize, BOOL bAnsi );
118 static HRESULT WINAPI DP_IF_GetPlayerData
119 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
120 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
121 static HRESULT WINAPI DP_IF_GetPlayerName
122 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
123 LPDWORD lpdwDataSize, BOOL bAnsi );
124 static HRESULT WINAPI DP_IF_SetGroupName
125 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
126 DWORD dwFlags, BOOL bAnsi );
127 static HRESULT WINAPI DP_IF_SetPlayerData
128 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
129 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
130 static HRESULT WINAPI DP_IF_SetPlayerName
131 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
132 DWORD dwFlags, BOOL bAnsi );
133 static HRESULT WINAPI DP_IF_AddGroupToGroup
134 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
135 static HRESULT WINAPI DP_IF_CreateGroup
136 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
137 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
138 DWORD dwFlags, BOOL bAnsi );
139 static HRESULT WINAPI DP_IF_CreateGroupInGroup
140 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
141 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
142 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
143 static HRESULT WINAPI DP_IF_AddPlayerToGroup
144 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
145 DPID idPlayer, BOOL bAnsi );
146 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
147 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
148 static HRESULT WINAPI DP_SetSessionDesc
149 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
150 DWORD dwFlags, BOOL bInitial, BOOL bAnsi );
151 static HRESULT WINAPI DP_SecureOpen
152 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
153 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
154 BOOL bAnsi );
155 static HRESULT WINAPI DP_SendEx
156 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
157 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
158 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi );
159 static HRESULT WINAPI DP_IF_Receive
160 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
161 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi );
162 static HRESULT WINAPI DP_IF_GetMessageQueue
163 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
164 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi );
165 static HRESULT WINAPI DP_SP_SendEx
166 ( IDirectPlay2Impl* This, DWORD dwFlags,
167 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
168 LPVOID lpContext, LPDWORD lpdwMsgID );
169 static HRESULT WINAPI DP_IF_SetGroupData
170 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
171 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
172 static HRESULT WINAPI DP_IF_GetPlayerCaps
173 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
174 DWORD dwFlags );
175 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi );
176 static HRESULT WINAPI DP_IF_CancelMessage
177 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
178 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi );
179 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
180 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
181 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
182 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
183 static HRESULT WINAPI DP_IF_GetGroupParent
184 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
185 BOOL bAnsi );
186 static HRESULT WINAPI DP_IF_GetCaps
187 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags );
188 static HRESULT WINAPI DP_IF_EnumSessions
189 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
190 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
191 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
192 static HRESULT WINAPI DP_IF_InitializeConnection
193 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi );
194 static BOOL CALLBACK cbDPCreateEnumConnections( LPCGUID lpguidSP,
195 LPVOID lpConnection, DWORD dwConnectionSize, LPCDPNAME lpName,
196 DWORD dwFlags, LPVOID lpContext );
197 static BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
198 LPDWORD lpdwBufSize );
202 static inline DPID DP_NextObjectId(void);
203 static DPID DP_GetRemoteNextObjectId(void);
206 static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc,
207 LPCDPSESSIONDESC2 srcSessDesc, BOOL bAnsi );
210 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp );
211 static HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider );
212 static HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hServiceProvider );
219 #define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */
220 #define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported
221 we don't have to change much */
222 #define DPID_NAME_SERVER 0x19a9d65b /* Don't ask me why */
224 /* Strip out dwFlag values which cannot be sent in the CREATEGROUP msg */
225 #define DPMSG_CREATEGROUP_DWFLAGS(x) ( (x) & DPGROUP_HIDDEN )
227 /* Strip out all dwFlags values for CREATEPLAYER msg */
228 #define DPMSG_CREATEPLAYER_DWFLAGS(x) 0
230 static LONG kludgePlayerGroupId = 1000;
232 /* ------------------------------------------------------------------ */
235 static BOOL DP_CreateIUnknown( LPVOID lpDP )
237 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;
239 This->unk = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->unk) ) );
240 if ( This->unk == NULL )
242 return FALSE;
245 InitializeCriticalSection( &This->unk->DP_lock );
247 return TRUE;
250 static BOOL DP_DestroyIUnknown( LPVOID lpDP )
252 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;
254 DeleteCriticalSection( &This->unk->DP_lock );
255 HeapFree( GetProcessHeap(), 0, This->unk );
257 return TRUE;
260 static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
262 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;
264 This->dp2 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp2) ) );
265 if ( This->dp2 == NULL )
267 return FALSE;
270 This->dp2->bConnectionOpen = FALSE;
272 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
274 This->dp2->bHostInterface = FALSE;
276 DPQ_INIT(This->dp2->receiveMsgs);
277 DPQ_INIT(This->dp2->sendMsgs);
278 DPQ_INIT(This->dp2->replysExpected);
280 if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
282 /* FIXME: Memory leak */
283 return FALSE;
286 /* Provide an initial session desc with nothing in it */
287 This->dp2->lpSessionDesc = HeapAlloc( GetProcessHeap(),
288 HEAP_ZERO_MEMORY,
289 sizeof( *This->dp2->lpSessionDesc ) );
290 if( This->dp2->lpSessionDesc == NULL )
292 /* FIXME: Memory leak */
293 return FALSE;
295 This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc );
297 /* We are emulating a dp 6 implementation */
298 This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION;
300 This->dp2->spData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
301 sizeof( *This->dp2->spData.lpCB ) );
302 This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB );
303 This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION;
305 /* This is the pointer to the service provider */
306 if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP,
307 (LPVOID*)&This->dp2->spData.lpISP, This ) )
310 /* FIXME: Memory leak */
311 return FALSE;
314 /* Setup lobby provider information */
315 This->dp2->dplspData.dwSPVersion = DPSP_MAJORVERSION;
316 This->dp2->dplspData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
317 sizeof( *This->dp2->dplspData.lpCB ) );
318 This->dp2->dplspData.lpCB->dwSize = sizeof( *This->dp2->dplspData.lpCB );
320 if( FAILED( DPLSP_CreateInterface( &IID_IDPLobbySP,
321 (LPVOID*)&This->dp2->dplspData.lpISP, This ) )
324 /* FIXME: Memory leak */
325 return FALSE;
328 return TRUE;
331 /* Definition of the global function in dplayx_queue.h. #
332 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
333 DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
335 HeapFree( GetProcessHeap(), 0, elem );
338 /* Function to delete the list of groups with this interface. Needs to
339 * delete the group and player lists associated with this group as well
340 * as the group data associated with this group. It should not delete
341 * player data as that is shared with the top player list and will be
342 * deleted with that.
344 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList );
345 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList )
347 DPQ_DELETEQ( elem->lpGData->groups, groups,
348 lpGroupList, cbDeleteElemFromHeap );
349 DPQ_DELETEQ( elem->lpGData->players, players,
350 lpPlayerList, cbDeleteElemFromHeap );
351 HeapFree( GetProcessHeap(), 0, elem->lpGData );
352 HeapFree( GetProcessHeap(), 0, elem );
355 /* Function to delete the list of players with this interface. Needs to
356 * delete the player data for all players as well.
358 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList );
359 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList )
361 HeapFree( GetProcessHeap(), 0, elem->lpPData );
362 HeapFree( GetProcessHeap(), 0, elem );
365 static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
367 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;
369 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
371 TerminateThread( This->dp2->hEnumSessionThread, 0 );
372 CloseHandle( This->dp2->hEnumSessionThread );
375 /* Finish with the SP - have it shutdown */
376 if( This->dp2->spData.lpCB->ShutdownEx )
378 DPSP_SHUTDOWNDATA data;
380 TRACE( "Calling SP ShutdownEx\n" );
382 data.lpISP = This->dp2->spData.lpISP;
384 (*This->dp2->spData.lpCB->ShutdownEx)( &data );
386 else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
388 TRACE( "Calling obsolete SP Shutdown\n" );
389 (*This->dp2->spData.lpCB->Shutdown)();
392 /* Unload the SP (if it exists) */
393 if( This->dp2->hServiceProvider != 0 )
395 FreeLibrary( This->dp2->hServiceProvider );
398 /* Unload the Lobby Provider (if it exists) */
399 if( This->dp2->hDPLobbyProvider != 0 )
401 FreeLibrary( This->dp2->hDPLobbyProvider );
404 #if 0
405 DPQ_DELETEQ( This->dp2->players, players, lpPlayerList, cbDeletePlayerElem );
406 DPQ_DELETEQ( This->dp2->groups, groups, lpGroupList, cbDeleteGroupsElem );
407 #endif
409 /* FIXME: Need to delete receive and send msgs queue contents */
411 NS_DeleteSessionCache( This->dp2->lpNameServerData );
413 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
415 IDirectPlaySP_Release( This->dp2->spData.lpISP );
417 /* Delete the contents */
418 HeapFree( GetProcessHeap(), 0, This->dp2 );
420 return TRUE;
423 static BOOL DP_CreateDirectPlay3( LPVOID lpDP )
425 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;
427 This->dp3 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp3) ) );
428 if ( This->dp3 == NULL )
430 return FALSE;
433 return TRUE;
436 static BOOL DP_DestroyDirectPlay3( LPVOID lpDP )
438 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;
440 /* Delete the contents */
441 HeapFree( GetProcessHeap(), 0, This->dp3 );
443 return TRUE;
446 static BOOL DP_CreateDirectPlay4( LPVOID lpDP )
448 IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)lpDP;
450 This->dp4 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp4) ) );
451 if ( This->dp4 == NULL )
453 return FALSE;
456 return TRUE;
459 static BOOL DP_DestroyDirectPlay4( LPVOID lpDP )
461 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;
463 /* Delete the contents */
464 HeapFree( GetProcessHeap(), 0, This->dp4 );
466 return TRUE;
470 /* Create a new interface */
471 extern
472 HRESULT DP_CreateInterface
473 ( REFIID riid, LPVOID* ppvObj )
475 TRACE( " for %s\n", debugstr_guid( riid ) );
477 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
478 sizeof( IDirectPlay2Impl ) );
480 if( *ppvObj == NULL )
482 return DPERR_OUTOFMEMORY;
485 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
487 IDirectPlay2Impl *This = (IDirectPlay2Impl *)*ppvObj;
488 This->lpVtbl = &directPlay2WVT;
490 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
492 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)*ppvObj;
493 This->lpVtbl = &directPlay2AVT;
495 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
497 IDirectPlay3Impl *This = (IDirectPlay3Impl *)*ppvObj;
498 This->lpVtbl = &directPlay3WVT;
500 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
502 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)*ppvObj;
503 This->lpVtbl = &directPlay3AVT;
505 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
507 IDirectPlay4Impl *This = (IDirectPlay4Impl *)*ppvObj;
508 This->lpVtbl = &directPlay4WVT;
510 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
512 IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)*ppvObj;
513 This->lpVtbl = &directPlay4AVT;
515 else
517 /* Unsupported interface */
518 HeapFree( GetProcessHeap(), 0, *ppvObj );
519 *ppvObj = NULL;
521 return E_NOINTERFACE;
524 /* Initialize it */
525 if ( DP_CreateIUnknown( *ppvObj ) &&
526 DP_CreateDirectPlay2( *ppvObj ) &&
527 DP_CreateDirectPlay3( *ppvObj ) &&
528 DP_CreateDirectPlay4( *ppvObj )
531 IDirectPlayX_AddRef( (LPDIRECTPLAY2A)*ppvObj );
533 return S_OK;
536 /* Initialize failed, destroy it */
537 DP_DestroyDirectPlay4( *ppvObj );
538 DP_DestroyDirectPlay3( *ppvObj );
539 DP_DestroyDirectPlay2( *ppvObj );
540 DP_DestroyIUnknown( *ppvObj );
542 HeapFree( GetProcessHeap(), 0, *ppvObj );
544 *ppvObj = NULL;
545 return DPERR_NOMEMORY;
549 /* Direct Play methods */
551 /* Shared between all dplay types */
552 static HRESULT WINAPI DP_QueryInterface
553 ( LPDIRECTPLAY2 iface, REFIID riid, LPVOID* ppvObj )
555 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
556 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
558 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
559 sizeof( *This ) );
561 if( *ppvObj == NULL )
563 return DPERR_OUTOFMEMORY;
566 CopyMemory( *ppvObj, This, sizeof( *This ) );
567 (*(IDirectPlay2Impl**)ppvObj)->ulInterfaceRef = 0;
569 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
571 IDirectPlay2Impl *This = (IDirectPlay2Impl *)*ppvObj;
572 This->lpVtbl = &directPlay2WVT;
574 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
576 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)*ppvObj;
577 This->lpVtbl = &directPlay2AVT;
579 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
581 IDirectPlay3Impl *This = (IDirectPlay3Impl *)*ppvObj;
582 This->lpVtbl = &directPlay3WVT;
584 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
586 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)*ppvObj;
587 This->lpVtbl = &directPlay3AVT;
589 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
591 IDirectPlay4Impl *This = (IDirectPlay4Impl *)*ppvObj;
592 This->lpVtbl = &directPlay4WVT;
594 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
596 IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)*ppvObj;
597 This->lpVtbl = &directPlay4AVT;
599 else
601 /* Unsupported interface */
602 HeapFree( GetProcessHeap(), 0, *ppvObj );
603 *ppvObj = NULL;
605 return E_NOINTERFACE;
608 IDirectPlayX_AddRef( (LPDIRECTPLAY2)*ppvObj );
610 return S_OK;
613 /* Shared between all dplay types */
614 static ULONG WINAPI DP_AddRef
615 ( LPDIRECTPLAY3 iface )
617 ULONG ulInterfaceRefCount, ulObjRefCount;
618 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
620 ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
621 ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
623 TRACE( "ref count incremented to %lu:%lu for %p\n",
624 ulInterfaceRefCount, ulObjRefCount, This );
626 return ulObjRefCount;
629 static ULONG WINAPI DP_Release
630 ( LPDIRECTPLAY3 iface )
632 ULONG ulInterfaceRefCount, ulObjRefCount;
634 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
636 ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
637 ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
639 TRACE( "ref count decremented to %lu:%lu for %p\n",
640 ulInterfaceRefCount, ulObjRefCount, This );
642 /* Deallocate if this is the last reference to the object */
643 if( ulObjRefCount == 0 )
645 /* If we're destroying the object, this must be the last ref
646 of the last interface */
647 DP_DestroyDirectPlay4( This );
648 DP_DestroyDirectPlay3( This );
649 DP_DestroyDirectPlay2( This );
650 DP_DestroyIUnknown( This );
653 /* Deallocate the interface */
654 if( ulInterfaceRefCount == 0 )
656 HeapFree( GetProcessHeap(), 0, This );
659 return ulObjRefCount;
662 static inline DPID DP_NextObjectId(void)
664 return (DPID)InterlockedIncrement( &kludgePlayerGroupId );
667 /* *lplpReply will be non NULL iff there is something to reply */
668 HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpcMessageBody,
669 DWORD dwMessageBodySize, LPCVOID lpcMessageHeader,
670 WORD wCommandId, WORD wVersion,
671 LPVOID* lplpReply, LPDWORD lpdwMsgSize )
673 TRACE( "(%p)->(%p,0x%08lx,%p,%u,%u)\n",
674 This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId,
675 wVersion );
677 switch( wCommandId )
679 /* Name server needs to handle this request */
680 case DPMSGCMD_ENUMSESSIONSREQUEST:
682 /* Reply expected */
683 NS_ReplyToEnumSessionsRequest( lpcMessageBody, lplpReply, lpdwMsgSize, This );
685 break;
688 /* Name server needs to handle this request */
689 case DPMSGCMD_ENUMSESSIONSREPLY:
691 /* No reply expected */
692 NS_AddRemoteComputerAsNameServer( lpcMessageHeader,
693 This->dp2->spData.dwSPHeaderSize,
694 (LPDPMSG_ENUMSESSIONSREPLY)lpcMessageBody,
695 This->dp2->lpNameServerData );
696 break;
699 case DPMSGCMD_REQUESTNEWPLAYERID:
701 LPCDPMSG_REQUESTNEWPLAYERID lpcMsg =
702 (LPCDPMSG_REQUESTNEWPLAYERID)lpcMessageBody;
704 LPDPMSG_NEWPLAYERIDREPLY lpReply;
706 *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
708 *lplpReply = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, *lpdwMsgSize );
710 FIXME( "Ignoring dwFlags 0x%08lx in request msg\n",
711 lpcMsg->dwFlags );
713 /* Setup the reply */
714 lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) +
715 This->dp2->spData.dwSPHeaderSize );
717 lpReply->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
718 lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY;
719 lpReply->envelope.wVersion = DPMSGVER_DP6;
721 lpReply->dpidNewPlayerId = DP_NextObjectId();
723 TRACE( "Allocating new playerid 0x%08lx from remote request\n",
724 lpReply->dpidNewPlayerId );
726 break;
729 case DPMSGCMD_GETNAMETABLEREPLY:
730 case DPMSGCMD_NEWPLAYERIDREPLY:
733 #if 0
734 if( wCommandId == DPMSGCMD_NEWPLAYERIDREPLY )
735 DebugBreak();
736 #endif
737 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
739 break;
742 #if 1
743 case DPMSGCMD_JUSTENVELOPE:
745 TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08lx\n", lpcMessageHeader, ((LPDWORD)lpcMessageHeader)[1] );
746 NS_SetLocalAddr( This->dp2->lpNameServerData, lpcMessageHeader, 20 );
747 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
749 #endif
751 case DPMSGCMD_FORWARDADDPLAYER:
753 #if 0
754 DebugBreak();
755 #endif
756 #if 1
757 TRACE( "Sending message to self to get my addr\n" );
758 DP_MSG_ToSelf( This, 1 ); /* This is a hack right now */
759 #endif
760 break;
763 case DPMSGCMD_FORWARDADDPLAYERNACK:
765 DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
766 break;
769 default:
771 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
772 DebugBreak();
773 break;
777 /* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */
779 return DP_OK;
783 static HRESULT WINAPI DP_IF_AddPlayerToGroup
784 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
785 DPID idPlayer, BOOL bAnsi )
787 lpGroupData lpGData;
788 lpPlayerList lpPList;
789 lpPlayerList lpNewPList;
791 TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
792 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
794 /* Find the group */
795 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
797 return DPERR_INVALIDGROUP;
800 /* Find the player */
801 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
803 return DPERR_INVALIDPLAYER;
806 /* Create a player list (ie "shortcut" ) */
807 lpNewPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewPList ) );
808 if( lpNewPList == NULL )
810 return DPERR_CANTADDPLAYER;
813 /* Add the shortcut */
814 lpPList->lpPData->uRef++;
815 lpNewPList->lpPData = lpPList->lpPData;
817 /* Add the player to the list of players for this group */
818 DPQ_INSERT(lpGData->players,lpNewPList,players);
820 /* Let the SP know that we've added a player to the group */
821 if( This->dp2->spData.lpCB->AddPlayerToGroup )
823 DPSP_ADDPLAYERTOGROUPDATA data;
825 TRACE( "Calling SP AddPlayerToGroup\n" );
827 data.idPlayer = idPlayer;
828 data.idGroup = idGroup;
829 data.lpISP = This->dp2->spData.lpISP;
831 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
834 /* Inform all other peers of the addition of player to the group. If there are
835 * no peers keep this event quiet.
836 * Also, if this event was the result of another machine sending it to us,
837 * don't bother rebroadcasting it.
839 if( ( lpMsgHdr == NULL ) &&
840 This->dp2->lpSessionDesc &&
841 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
843 DPMSG_ADDPLAYERTOGROUP msg;
844 msg.dwType = DPSYS_ADDPLAYERTOGROUP;
846 msg.dpIdGroup = idGroup;
847 msg.dpIdPlayer = idPlayer;
849 /* FIXME: Correct to just use send effectively? */
850 /* FIXME: Should size include data w/ message or just message "header" */
851 /* FIXME: Check return code */
852 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
855 return DP_OK;
858 static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
859 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
861 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
862 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, TRUE );
865 static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
866 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
868 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
869 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, FALSE );
872 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi )
874 HRESULT hr = DP_OK;
876 TRACE("(%p)->(%u)\n", This, bAnsi );
878 /* FIXME: Need to find a new host I assume (how?) */
879 /* FIXME: Need to destroy all local groups */
880 /* FIXME: Need to migrate all remotely visible players to the new host */
882 /* Invoke the SP callback to inform of session close */
883 if( This->dp2->spData.lpCB->CloseEx )
885 DPSP_CLOSEDATA data;
887 TRACE( "Calling SP CloseEx\n" );
889 data.lpISP = This->dp2->spData.lpISP;
891 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
894 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
896 TRACE( "Calling SP Close (obsolete interface)\n" );
898 hr = (*This->dp2->spData.lpCB->Close)();
901 return hr;
904 static HRESULT WINAPI DirectPlay2AImpl_Close
905 ( LPDIRECTPLAY2A iface )
907 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
908 return DP_IF_Close( This, TRUE );
911 static HRESULT WINAPI DirectPlay2WImpl_Close
912 ( LPDIRECTPLAY2 iface )
914 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
915 return DP_IF_Close( This, FALSE );
918 static
919 lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, LPDPID lpid,
920 LPDPNAME lpName, DWORD dwFlags,
921 DPID idParent, BOOL bAnsi )
923 lpGroupData lpGData;
925 /* Allocate the new space and add to end of high level group list */
926 lpGData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGData ) );
928 if( lpGData == NULL )
930 return NULL;
933 DPQ_INIT(lpGData->groups);
934 DPQ_INIT(lpGData->players);
936 /* Set the desired player ID - no sanity checking to see if it exists */
937 lpGData->dpid = *lpid;
939 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
941 /* FIXME: Should we check that the parent exists? */
942 lpGData->parent = idParent;
944 /* FIXME: Should we validate the dwFlags? */
945 lpGData->dwFlags = dwFlags;
947 TRACE( "Created group id 0x%08lx\n", *lpid );
949 return lpGData;
952 /* This method assumes that all links to it are already deleted */
953 static void
954 DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid )
956 lpGroupList lpGList;
958 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
960 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
962 if( lpGList == NULL )
964 ERR( "DPID 0x%08lx not found\n", dpid );
965 return;
968 if( --(lpGList->lpGData->uRef) )
970 FIXME( "Why is this not the last reference to group?\n" );
971 DebugBreak();
974 /* Delete player */
975 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
976 HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
978 /* Remove and Delete Player List object */
979 HeapFree( GetProcessHeap(), 0, lpGList );
983 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid )
985 lpGroupList lpGroups;
987 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
989 if( dpid == DPID_SYSTEM_GROUP )
991 return This->dp2->lpSysGroup;
993 else
995 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
998 if( lpGroups == NULL )
1000 return NULL;
1003 return lpGroups->lpGData;
1006 static HRESULT WINAPI DP_IF_CreateGroup
1007 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
1008 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
1009 DWORD dwFlags, BOOL bAnsi )
1011 lpGroupData lpGData;
1013 TRACE( "(%p)->(%p,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
1014 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
1015 dwFlags, bAnsi );
1017 /* If the name is not specified, we must provide one */
1018 if( DPID_UNKNOWN == *lpidGroup )
1020 /* If we are the name server, we decide on the group ids. If not, we
1021 * must ask for one before attempting a creation.
1023 if( This->dp2->bHostInterface )
1025 *lpidGroup = DP_NextObjectId();
1027 else
1029 *lpidGroup = DP_GetRemoteNextObjectId();
1033 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
1034 DPID_NOPARENT_GROUP, bAnsi );
1036 if( lpGData == NULL )
1038 return DPERR_CANTADDPLAYER; /* yes player not group */
1041 if( DPID_SYSTEM_GROUP == *lpidGroup )
1043 This->dp2->lpSysGroup = lpGData;
1044 TRACE( "Inserting system group\n" );
1046 else
1048 /* Insert into the system group */
1049 lpGroupList lpGroup = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGroup ) );
1050 lpGroup->lpGData = lpGData;
1052 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
1055 /* Something is now referencing this data */
1056 lpGData->uRef++;
1058 /* Set all the important stuff for the group */
1059 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
1061 /* FIXME: We should only create the system group if GetCaps returns
1062 * DPCAPS_GROUPOPTIMIZED.
1065 /* Let the SP know that we've created this group */
1066 if( This->dp2->spData.lpCB->CreateGroup )
1068 DPSP_CREATEGROUPDATA data;
1069 DWORD dwCreateFlags = 0;
1071 TRACE( "Calling SP CreateGroup\n" );
1073 if( *lpidGroup == DPID_NOPARENT_GROUP )
1074 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
1076 if( lpMsgHdr == NULL )
1077 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1079 if( dwFlags & DPGROUP_HIDDEN )
1080 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
1082 data.idGroup = *lpidGroup;
1083 data.dwFlags = dwCreateFlags;
1084 data.lpSPMessageHeader = lpMsgHdr;
1085 data.lpISP = This->dp2->spData.lpISP;
1087 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1090 /* Inform all other peers of the creation of a new group. If there are
1091 * no peers keep this event quiet.
1092 * Also if this message was sent to us, don't rebroadcast.
1094 if( ( lpMsgHdr == NULL ) &&
1095 This->dp2->lpSessionDesc &&
1096 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1098 DPMSG_CREATEPLAYERORGROUP msg;
1099 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1101 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1102 msg.dpId = *lpidGroup;
1103 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1104 msg.lpData = lpData;
1105 msg.dwDataSize = dwDataSize;
1106 msg.dpnName = *lpGroupName;
1107 msg.dpIdParent = DPID_NOPARENT_GROUP;
1108 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
1110 /* FIXME: Correct to just use send effectively? */
1111 /* FIXME: Should size include data w/ message or just message "header" */
1112 /* FIXME: Check return code */
1113 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
1114 0, 0, NULL, NULL, bAnsi );
1117 return DP_OK;
1120 static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
1121 ( LPDIRECTPLAY2A iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1122 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1124 *lpidGroup = DPID_UNKNOWN;
1126 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1127 lpGroupName, lpData, dwDataSize, dwFlags, TRUE );
1130 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
1131 ( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1132 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1134 *lpidGroup = DPID_UNKNOWN;
1136 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1137 lpGroupName, lpData, dwDataSize, dwFlags, FALSE );
1141 static void
1142 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
1143 LPVOID lpData, DWORD dwDataSize )
1145 /* Clear out the data with this player */
1146 if( dwFlags & DPSET_LOCAL )
1148 if ( lpGData->dwLocalDataSize != 0 )
1150 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
1151 lpGData->lpLocalData = NULL;
1152 lpGData->dwLocalDataSize = 0;
1155 else
1157 if( lpGData->dwRemoteDataSize != 0 )
1159 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
1160 lpGData->lpRemoteData = NULL;
1161 lpGData->dwRemoteDataSize = 0;
1165 /* Reallocate for new data */
1166 if( lpData != NULL )
1168 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1169 sizeof( dwDataSize ) );
1170 CopyMemory( lpNewData, lpData, dwDataSize );
1172 if( dwFlags & DPSET_LOCAL )
1174 lpGData->lpLocalData = lpData;
1175 lpGData->dwLocalDataSize = dwDataSize;
1177 else
1179 lpGData->lpRemoteData = lpNewData;
1180 lpGData->dwRemoteDataSize = dwDataSize;
1186 /* This function will just create the storage for the new player. */
1187 static
1188 lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid,
1189 LPDPNAME lpName, DWORD dwFlags,
1190 HANDLE hEvent, BOOL bAnsi )
1192 lpPlayerData lpPData;
1194 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
1196 /* Allocate the storage for the player and associate it with list element */
1197 lpPData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPData ) );
1198 if( lpPData == NULL )
1200 return NULL;
1203 /* Set the desired player ID */
1204 lpPData->dpid = *lpid;
1206 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
1208 lpPData->dwFlags = dwFlags;
1210 /* If we were given an event handle, duplicate it */
1211 if( hEvent != 0 )
1213 if( !DuplicateHandle( GetCurrentProcess(), hEvent,
1214 GetCurrentProcess(), &lpPData->hEvent,
1215 0, FALSE, DUPLICATE_SAME_ACCESS )
1218 /* FIXME: Memory leak */
1219 ERR( "Can't duplicate player msg handle %p\n", hEvent );
1223 /* Initialize the SP data section */
1224 lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData();
1226 TRACE( "Created player id 0x%08lx\n", *lpid );
1228 return lpPData;
1231 /* Delete the contents of the DPNAME struct */
1232 static void
1233 DP_DeleteDPNameStruct( LPDPNAME lpDPName )
1235 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u1.lpszShortNameA );
1236 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u2.lpszLongNameA );
1239 /* This method assumes that all links to it are already deleted */
1240 static void
1241 DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid )
1243 lpPlayerList lpPList;
1245 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
1247 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1249 if( lpPList == NULL )
1251 ERR( "DPID 0x%08lx not found\n", dpid );
1252 return;
1255 /* Verify that this is the last reference to the data */
1256 if( --(lpPList->lpPData->uRef) )
1258 FIXME( "Why is this not the last reference to player?\n" );
1259 DebugBreak();
1262 /* Delete player */
1263 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1265 CloseHandle( lpPList->lpPData->hEvent );
1266 HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
1268 /* Delete Player List object */
1269 HeapFree( GetProcessHeap(), 0, lpPList );
1272 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid )
1274 lpPlayerList lpPlayers;
1276 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
1278 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1280 return lpPlayers;
1283 /* Basic area for Dst must already be allocated */
1284 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi )
1286 if( lpSrc == NULL )
1288 ZeroMemory( lpDst, sizeof( *lpDst ) );
1289 lpDst->dwSize = sizeof( *lpDst );
1290 return TRUE;
1293 if( lpSrc->dwSize != sizeof( *lpSrc) )
1295 return FALSE;
1298 /* Delete any existing pointers */
1299 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1300 HeapFree( GetProcessHeap(), 0, lpDst->u2.lpszLongNameA );
1302 /* Copy as required */
1303 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1305 if( bAnsi )
1307 if( lpSrc->u1.lpszShortNameA )
1309 lpDst->u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), 0,
1310 strlen(lpSrc->u1.lpszShortNameA)+1 );
1311 strcpy( lpDst->u1.lpszShortNameA, lpSrc->u1.lpszShortNameA );
1313 if( lpSrc->u2.lpszLongNameA )
1315 lpDst->u2.lpszLongNameA = HeapAlloc( GetProcessHeap(), 0,
1316 strlen(lpSrc->u2.lpszLongNameA)+1 );
1317 strcpy( lpDst->u2.lpszLongNameA, lpSrc->u2.lpszLongNameA );
1320 else
1322 if( lpSrc->u1.lpszShortNameA )
1324 lpDst->u1.lpszShortName = HeapAlloc( GetProcessHeap(), 0,
1325 (strlenW(lpSrc->u1.lpszShortName)+1)*sizeof(WCHAR) );
1326 strcpyW( lpDst->u1.lpszShortName, lpSrc->u1.lpszShortName );
1328 if( lpSrc->u2.lpszLongNameA )
1330 lpDst->u2.lpszLongName = HeapAlloc( GetProcessHeap(), 0,
1331 (strlenW(lpSrc->u2.lpszLongName)+1)*sizeof(WCHAR) );
1332 strcpyW( lpDst->u2.lpszLongName, lpSrc->u2.lpszLongName );
1336 return TRUE;
1339 static void
1340 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
1341 LPVOID lpData, DWORD dwDataSize )
1343 /* Clear out the data with this player */
1344 if( dwFlags & DPSET_LOCAL )
1346 if ( lpPData->dwLocalDataSize != 0 )
1348 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
1349 lpPData->lpLocalData = NULL;
1350 lpPData->dwLocalDataSize = 0;
1353 else
1355 if( lpPData->dwRemoteDataSize != 0 )
1357 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
1358 lpPData->lpRemoteData = NULL;
1359 lpPData->dwRemoteDataSize = 0;
1363 /* Reallocate for new data */
1364 if( lpData != NULL )
1366 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1367 sizeof( dwDataSize ) );
1368 CopyMemory( lpNewData, lpData, dwDataSize );
1370 if( dwFlags & DPSET_LOCAL )
1372 lpPData->lpLocalData = lpData;
1373 lpPData->dwLocalDataSize = dwDataSize;
1375 else
1377 lpPData->lpRemoteData = lpNewData;
1378 lpPData->dwRemoteDataSize = dwDataSize;
1384 static HRESULT WINAPI DP_IF_CreatePlayer
1385 ( IDirectPlay2Impl* This,
1386 LPVOID lpMsgHdr, /* NULL for local creation, non NULL for remote creation */
1387 LPDPID lpidPlayer,
1388 LPDPNAME lpPlayerName,
1389 HANDLE hEvent,
1390 LPVOID lpData,
1391 DWORD dwDataSize,
1392 DWORD dwFlags,
1393 BOOL bAnsi )
1395 HRESULT hr = DP_OK;
1396 lpPlayerData lpPData;
1397 lpPlayerList lpPList;
1398 DWORD dwCreateFlags = 0;
1400 TRACE( "(%p)->(%p,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
1401 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1402 dwDataSize, dwFlags, bAnsi );
1404 if( dwFlags == 0 )
1406 dwFlags = DPPLAYER_SPECTATOR;
1409 if( lpidPlayer == NULL )
1411 return DPERR_INVALIDPARAMS;
1415 /* Determine the creation flags for the player. These will be passed
1416 * to the name server if requesting a player id and to the SP when
1417 * informing it of the player creation
1420 if( dwFlags & DPPLAYER_SERVERPLAYER )
1422 if( *lpidPlayer == DPID_SERVERPLAYER )
1424 /* Server player for the host interface */
1425 dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
1427 else if( *lpidPlayer == DPID_NAME_SERVER )
1429 /* Name server - master of everything */
1430 dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
1432 else
1434 /* Server player for a non host interface */
1435 dwCreateFlags |= DPLAYI_PLAYER_SYSPLAYER;
1439 if( lpMsgHdr == NULL )
1440 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1443 /* Verify we know how to handle all the flags */
1444 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1445 ( dwFlags & DPPLAYER_SPECTATOR )
1449 /* Assume non fatal failure */
1450 ERR( "unknown dwFlags = 0x%08lx\n", dwFlags );
1453 /* If the name is not specified, we must provide one */
1454 if( *lpidPlayer == DPID_UNKNOWN )
1456 /* If we are the session master, we dish out the group/player ids */
1457 if( This->dp2->bHostInterface )
1459 *lpidPlayer = DP_NextObjectId();
1461 else
1463 hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer );
1465 if( FAILED(hr) )
1467 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1468 return hr;
1472 else
1474 /* FIXME: Would be nice to perhaps verify that we don't already have
1475 * this player.
1479 /* FIXME: Should we be storing these dwFlags or the creation ones? */
1480 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwFlags,
1481 hEvent, bAnsi );
1483 if( lpPData == NULL )
1485 return DPERR_CANTADDPLAYER;
1488 /* Create the list object and link it in */
1489 lpPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPList ) );
1490 if( lpPList == NULL )
1492 FIXME( "Memory leak\n" );
1493 return DPERR_CANTADDPLAYER;
1496 lpPData->uRef = 1;
1497 lpPList->lpPData = lpPData;
1499 /* Add the player to the system group */
1500 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1502 /* Update the information and send it to all players in the session */
1503 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
1505 /* Let the SP know that we've created this player */
1506 if( This->dp2->spData.lpCB->CreatePlayer )
1508 DPSP_CREATEPLAYERDATA data;
1510 data.idPlayer = *lpidPlayer;
1511 data.dwFlags = dwCreateFlags;
1512 data.lpSPMessageHeader = lpMsgHdr;
1513 data.lpISP = This->dp2->spData.lpISP;
1515 TRACE( "Calling SP CreatePlayer 0x%08lx: dwFlags: 0x%08lx lpMsgHdr: %p\n",
1516 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
1518 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1521 if( FAILED(hr) )
1523 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1524 return hr;
1527 /* Now let the SP know that this player is a member of the system group */
1528 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1530 DPSP_ADDPLAYERTOGROUPDATA data;
1532 data.idPlayer = *lpidPlayer;
1533 data.idGroup = DPID_SYSTEM_GROUP;
1534 data.lpISP = This->dp2->spData.lpISP;
1536 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1538 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1541 if( FAILED(hr) )
1543 ERR( "Failed to add player to sys group with sp: %s\n",
1544 DPLAYX_HresultToString(hr) );
1545 return hr;
1548 #if 1
1549 if( This->dp2->bHostInterface == FALSE )
1551 /* Let the name server know about the creation of this player */
1552 /* FIXME: Is this only to be done for the creation of a server player or
1553 * is this used for regular players? If only for server players, move
1554 * this call to DP_SecureOpen(...);
1556 #if 0
1557 TRACE( "Sending message to self to get my addr\n" );
1558 DP_MSG_ToSelf( This, *lpidPlayer ); /* This is a hack right now */
1559 #endif
1561 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
1563 #else
1564 /* Inform all other peers of the creation of a new player. If there are
1565 * no peers keep this quiet.
1566 * Also, if this was a remote event, no need to rebroadcast it.
1568 if( ( lpMsgHdr == NULL ) &&
1569 This->dp2->lpSessionDesc &&
1570 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1572 DPMSG_CREATEPLAYERORGROUP msg;
1573 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1575 msg.dwPlayerType = DPPLAYERTYPE_PLAYER;
1576 msg.dpId = *lpidPlayer;
1577 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */
1578 msg.lpData = lpData;
1579 msg.dwDataSize = dwDataSize;
1580 msg.dpnName = *lpPlayerName;
1581 msg.dpIdParent = DPID_NOPARENT_GROUP;
1582 msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
1584 /* FIXME: Correct to just use send effectively? */
1585 /* FIXME: Should size include data w/ message or just message "header" */
1586 /* FIXME: Check return code */
1587 hr = DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
1588 sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
1590 #endif
1592 return hr;
1595 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
1596 ( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1597 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1599 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1601 if( dwFlags & DPPLAYER_SERVERPLAYER )
1603 *lpidPlayer = DPID_SERVERPLAYER;
1605 else
1607 *lpidPlayer = DPID_UNKNOWN;
1610 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1611 lpData, dwDataSize, dwFlags, TRUE );
1614 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
1615 ( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1616 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1618 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1620 if( dwFlags & DPPLAYER_SERVERPLAYER )
1622 *lpidPlayer = DPID_SERVERPLAYER;
1624 else
1626 *lpidPlayer = DPID_UNKNOWN;
1629 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1630 lpData, dwDataSize, dwFlags, FALSE );
1633 static DPID DP_GetRemoteNextObjectId(void)
1635 FIXME( ":stub\n" );
1637 /* Hack solution */
1638 return DP_NextObjectId();
1641 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
1642 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
1643 DPID idPlayer, BOOL bAnsi )
1645 HRESULT hr = DP_OK;
1647 lpGroupData lpGData;
1648 lpPlayerList lpPList;
1650 TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
1651 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
1653 /* Find the group */
1654 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1656 return DPERR_INVALIDGROUP;
1659 /* Find the player */
1660 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
1662 return DPERR_INVALIDPLAYER;
1665 /* Remove the player shortcut from the group */
1666 DPQ_REMOVE_ENTRY( lpGData->players, players, lpPData->dpid, ==, idPlayer, lpPList );
1668 if( lpPList == NULL )
1670 return DPERR_INVALIDPLAYER;
1673 /* One less reference */
1674 lpPList->lpPData->uRef--;
1676 /* Delete the Player List element */
1677 HeapFree( GetProcessHeap(), 0, lpPList );
1679 /* Inform the SP if they care */
1680 if( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1682 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1684 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1686 data.idPlayer = idPlayer;
1687 data.idGroup = idGroup;
1688 data.lpISP = This->dp2->spData.lpISP;
1690 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1693 /* Need to send a DELETEPLAYERFROMGROUP message */
1694 FIXME( "Need to send a message\n" );
1696 return hr;
1699 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
1700 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
1702 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1703 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, TRUE );
1706 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
1707 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
1709 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1710 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, FALSE );
1713 typedef struct _DPRGOPContext
1715 IDirectPlay3Impl* This;
1716 BOOL bAnsi;
1717 DPID idGroup;
1718 } DPRGOPContext, *lpDPRGOPContext;
1720 static BOOL CALLBACK
1721 cbRemoveGroupOrPlayer(
1722 DPID dpId,
1723 DWORD dwPlayerType,
1724 LPCDPNAME lpName,
1725 DWORD dwFlags,
1726 LPVOID lpContext )
1728 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1730 TRACE( "Removing element:0x%08lx (type:0x%08lx) from element:0x%08lx\n",
1731 dpId, dwPlayerType, lpCtxt->idGroup );
1733 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1735 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt->This, lpCtxt->idGroup,
1736 dpId )
1740 ERR( "Unable to delete group 0x%08lx from group 0x%08lx\n",
1741 dpId, lpCtxt->idGroup );
1744 else
1746 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl*)lpCtxt->This,
1747 NULL, lpCtxt->idGroup,
1748 dpId, lpCtxt->bAnsi )
1752 ERR( "Unable to delete player 0x%08lx from grp 0x%08lx\n",
1753 dpId, lpCtxt->idGroup );
1757 return TRUE; /* Continue enumeration */
1760 static HRESULT WINAPI DP_IF_DestroyGroup
1761 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi )
1763 lpGroupData lpGData;
1764 DPRGOPContext context;
1766 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
1767 This, lpMsgHdr, idGroup, bAnsi );
1769 /* Find the group */
1770 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1772 return DPERR_INVALIDPLAYER; /* yes player */
1775 context.This = (IDirectPlay3Impl*)This;
1776 context.bAnsi = bAnsi;
1777 context.idGroup = idGroup;
1779 /* Remove all players that this group has */
1780 DP_IF_EnumGroupPlayers( This, idGroup, NULL,
1781 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1783 /* Remove all links to groups that this group has since this is dp3 */
1784 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This, idGroup, NULL,
1785 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1787 /* Remove this group from the parent group - if it has one */
1788 if( ( idGroup != DPID_SYSTEM_GROUP ) &&
1789 ( lpGData->parent != DPID_SYSTEM_GROUP )
1792 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl*)This, lpGData->parent,
1793 idGroup );
1796 /* Now delete this group data and list from the system group */
1797 DP_DeleteGroup( This, idGroup );
1799 /* Let the SP know that we've destroyed this group */
1800 if( This->dp2->spData.lpCB->DeleteGroup )
1802 DPSP_DELETEGROUPDATA data;
1804 FIXME( "data.dwFlags is incorrect\n" );
1806 data.idGroup = idGroup;
1807 data.dwFlags = 0;
1808 data.lpISP = This->dp2->spData.lpISP;
1810 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1813 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1815 return DP_OK;
1818 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
1819 ( LPDIRECTPLAY2A iface, DPID idGroup )
1821 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1822 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
1825 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
1826 ( LPDIRECTPLAY2 iface, DPID idGroup )
1828 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1829 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
1832 typedef struct _DPFAGContext
1834 IDirectPlay2Impl* This;
1835 DPID idPlayer;
1836 BOOL bAnsi;
1837 } DPFAGContext, *lpDPFAGContext;
1839 static HRESULT WINAPI DP_IF_DestroyPlayer
1840 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi )
1842 DPFAGContext cbContext;
1844 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
1845 This, lpMsgHdr, idPlayer, bAnsi );
1847 if( This->dp2->connectionInitialized == NO_PROVIDER )
1849 return DPERR_UNINITIALIZED;
1852 if( DP_FindPlayer( This, idPlayer ) == NULL )
1854 return DPERR_INVALIDPLAYER;
1857 /* FIXME: If the player is remote, we must be the host to delete this */
1859 cbContext.This = This;
1860 cbContext.idPlayer = idPlayer;
1861 cbContext.bAnsi = bAnsi;
1863 /* Find each group and call DeletePlayerFromGroup if the player is a
1864 member of the group */
1865 DP_IF_EnumGroups( This, NULL, cbDeletePlayerFromAllGroups,
1866 (LPVOID)&cbContext, DPENUMGROUPS_ALL, bAnsi );
1868 /* Now delete player and player list from the sys group */
1869 DP_DeletePlayer( This, idPlayer );
1871 /* Let the SP know that we've destroyed this group */
1872 if( This->dp2->spData.lpCB->DeletePlayer )
1874 DPSP_DELETEPLAYERDATA data;
1876 FIXME( "data.dwFlags is incorrect\n" );
1878 data.idPlayer = idPlayer;
1879 data.dwFlags = 0;
1880 data.lpISP = This->dp2->spData.lpISP;
1882 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
1885 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
1887 return DP_OK;
1890 static BOOL CALLBACK
1891 cbDeletePlayerFromAllGroups(
1892 DPID dpId,
1893 DWORD dwPlayerType,
1894 LPCDPNAME lpName,
1895 DWORD dwFlags,
1896 LPVOID lpContext )
1898 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
1900 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1902 DP_IF_DeletePlayerFromGroup( lpCtxt->This, NULL, dpId, lpCtxt->idPlayer,
1903 lpCtxt->bAnsi );
1905 /* Enumerate all groups in this group since this will normally only
1906 * be called for top level groups
1908 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)lpCtxt->This,
1909 dpId, NULL,
1910 cbDeletePlayerFromAllGroups,
1911 (LPVOID)lpContext, DPENUMGROUPS_ALL,
1912 lpCtxt->bAnsi );
1915 else
1917 ERR( "Group callback has dwPlayerType = 0x%08lx\n", dwPlayerType );
1920 return TRUE;
1923 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
1924 ( LPDIRECTPLAY2A iface, DPID idPlayer )
1926 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1927 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
1930 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
1931 ( LPDIRECTPLAY2 iface, DPID idPlayer )
1933 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1934 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
1937 static HRESULT WINAPI DP_IF_EnumGroupPlayers
1938 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
1939 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1940 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1942 lpGroupData lpGData;
1943 lpPlayerList lpPList;
1945 FIXME("(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
1946 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
1947 lpContext, dwFlags, bAnsi );
1949 if( This->dp2->connectionInitialized == NO_PROVIDER )
1951 return DPERR_UNINITIALIZED;
1954 /* Find the group */
1955 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1957 return DPERR_INVALIDGROUP;
1960 if( DPQ_IS_EMPTY( lpGData->players ) )
1962 return DP_OK;
1965 lpPList = DPQ_FIRST( lpGData->players );
1967 /* Walk the players in this group */
1968 for( ;; )
1970 /* We do not enum the name server or app server as they are of no
1971 * concequence to the end user.
1973 if( ( lpPList->lpPData->dpid != DPID_NAME_SERVER ) &&
1974 ( lpPList->lpPData->dpid != DPID_SERVERPLAYER )
1978 /* FIXME: Need to add stuff for dwFlags checking */
1980 if( !lpEnumPlayersCallback2( lpPList->lpPData->dpid, DPPLAYERTYPE_PLAYER,
1981 &lpPList->lpPData->name,
1982 lpPList->lpPData->dwFlags,
1983 lpContext )
1986 /* User requested break */
1987 return DP_OK;
1991 if( DPQ_IS_ENDOFLIST( lpPList->players ) )
1993 break;
1996 lpPList = DPQ_NEXT( lpPList->players );
1999 return DP_OK;
2002 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
2003 ( LPDIRECTPLAY2A iface, DPID idGroup, LPGUID lpguidInstance,
2004 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2005 LPVOID lpContext, DWORD dwFlags )
2007 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2008 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2009 lpEnumPlayersCallback2, lpContext,
2010 dwFlags, TRUE );
2013 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
2014 ( LPDIRECTPLAY2 iface, DPID idGroup, LPGUID lpguidInstance,
2015 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2016 LPVOID lpContext, DWORD dwFlags )
2018 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2019 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2020 lpEnumPlayersCallback2, lpContext,
2021 dwFlags, FALSE );
2024 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2025 static HRESULT WINAPI DP_IF_EnumGroups
2026 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2027 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2028 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2030 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This,
2031 DPID_SYSTEM_GROUP, lpguidInstance,
2032 lpEnumPlayersCallback2, lpContext,
2033 dwFlags, bAnsi );
2036 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
2037 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2038 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2039 LPVOID lpContext, DWORD dwFlags )
2041 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2042 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2043 lpContext, dwFlags, TRUE );
2046 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
2047 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2048 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2049 LPVOID lpContext, DWORD dwFlags )
2051 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2052 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2053 lpContext, dwFlags, FALSE );
2056 static HRESULT WINAPI DP_IF_EnumPlayers
2057 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2058 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2059 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2061 return DP_IF_EnumGroupPlayers( This, DPID_SYSTEM_GROUP, lpguidInstance,
2062 lpEnumPlayersCallback2, lpContext,
2063 dwFlags, bAnsi );
2066 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
2067 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2068 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2069 LPVOID lpContext, DWORD dwFlags )
2071 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2072 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2073 lpContext, dwFlags, TRUE );
2076 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
2077 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2078 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2079 LPVOID lpContext, DWORD dwFlags )
2081 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2082 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2083 lpContext, dwFlags, FALSE );
2086 /* This function should call the registered callback function that the user
2087 passed into EnumSessions for each entry available.
2089 static void DP_InvokeEnumSessionCallbacks
2090 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2091 LPVOID lpNSInfo,
2092 DWORD dwTimeout,
2093 LPVOID lpContext )
2095 LPDPSESSIONDESC2 lpSessionDesc;
2097 FIXME( ": not checking for conditions\n" );
2099 /* Not sure if this should be pruning but it's convenient */
2100 NS_PruneSessionCache( lpNSInfo );
2102 NS_ResetSessionEnumeration( lpNSInfo );
2104 /* Enumerate all sessions */
2105 /* FIXME: Need to indicate ANSI */
2106 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2108 TRACE( "EnumSessionsCallback2 invoked\n" );
2109 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2111 return;
2115 /* Invoke one last time to indicate that there is no more to come */
2116 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2119 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2121 EnumSessionAsyncCallbackData* data = (EnumSessionAsyncCallbackData*)lpContext;
2122 HANDLE hSuicideRequest = data->hSuicideRequest;
2123 DWORD dwTimeout = data->dwTimeout;
2125 TRACE( "Thread started with timeout = 0x%08lx\n", dwTimeout );
2127 for( ;; )
2129 HRESULT hr;
2131 /* Sleep up to dwTimeout waiting for request to terminate thread */
2132 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2134 TRACE( "Thread terminating on terminate request\n" );
2135 break;
2138 /* Now resend the enum request */
2139 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2140 data->dwEnumSessionFlags,
2141 data->lpSpData );
2143 if( FAILED(hr) )
2145 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2146 /* FIXME: Should we kill this thread? How to inform the main thread? */
2151 TRACE( "Thread terminating\n" );
2153 /* Clean up the thread data */
2154 CloseHandle( hSuicideRequest );
2155 HeapFree( GetProcessHeap(), 0, lpContext );
2157 /* FIXME: Need to have some notification to main app thread that this is
2158 * dead. It would serve two purposes. 1) allow sync on termination
2159 * so that we don't actually send something to ourselves when we
2160 * become name server (race condition) and 2) so that if we die
2161 * abnormally something else will be able to tell.
2164 return 1;
2167 static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
2169 /* Does a thread exist? If so we were doing an async enum session */
2170 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2172 TRACE( "Killing EnumSession thread %p\n",
2173 This->dp2->hEnumSessionThread );
2175 /* Request that the thread kill itself nicely */
2176 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2177 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2179 /* We no longer need to know about the thread */
2180 CloseHandle( This->dp2->hEnumSessionThread );
2182 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2186 static HRESULT WINAPI DP_IF_EnumSessions
2187 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2188 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2189 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2191 HRESULT hr = DP_OK;
2193 TRACE( "(%p)->(%p,0x%08lx,%p,%p,0x%08lx,%u)\n",
2194 This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags,
2195 bAnsi );
2197 /* Can't enumerate if the interface is already open */
2198 if( This->dp2->bConnectionOpen )
2200 return DPERR_GENERIC;
2203 #if 1
2204 /* The loading of a lobby provider _seems_ to require a backdoor loading
2205 * of the service provider to also associate with this DP object. This is
2206 * because the app doesn't seem to have to call EnumConnections and
2207 * InitializeConnection for the SP before calling this method. As such
2208 * we'll do their dirty work for them with a quick hack so as to always
2209 * load the TCP/IP service provider.
2211 * The correct solution would seem to involve creating a dialog box which
2212 * contains the possible SPs. These dialog boxes most likely follow SDK
2213 * examples.
2215 if( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
2217 LPVOID lpConnection;
2218 DWORD dwSize;
2220 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2222 if( !DP_BuildSPCompoundAddr( (LPGUID)&DPSPGUID_TCPIP, &lpConnection, &dwSize ) )
2224 ERR( "Can't build compound addr\n" );
2225 return DPERR_GENERIC;
2228 hr = DP_IF_InitializeConnection( (IDirectPlay3Impl*)This, lpConnection,
2229 0, bAnsi );
2230 if( FAILED(hr) )
2232 return hr;
2235 /* Free up the address buffer */
2236 HeapFree( GetProcessHeap(), 0, lpConnection );
2238 /* The SP is now initialized */
2239 This->dp2->bSPInitialized = TRUE;
2241 #endif
2244 /* Use the service provider default? */
2245 if( dwTimeout == 0 )
2247 DPCAPS spCaps;
2248 spCaps.dwSize = sizeof( spCaps );
2250 DP_IF_GetCaps( This, &spCaps, 0 );
2251 dwTimeout = spCaps.dwTimeout;
2253 /* The service provider doesn't provide one either! */
2254 if( dwTimeout == 0 )
2256 /* Provide the TCP/IP default */
2257 dwTimeout = DPMSG_WAIT_5_SECS;
2261 if( dwFlags & DPENUMSESSIONS_STOPASYNC )
2263 DP_KillEnumSessionThread( This );
2264 return hr;
2267 /* FIXME: Interface locking sucks in this method */
2268 if( ( dwFlags & DPENUMSESSIONS_ASYNC ) )
2270 /* Enumerate everything presently in the local session cache */
2271 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2272 This->dp2->lpNameServerData, dwTimeout,
2273 lpContext );
2276 /* See if we've already created a thread to service this interface */
2277 if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2279 DWORD dwThreadId;
2281 /* Send the first enum request inline since the user may cancel a dialog
2282 * if one is presented. Also, may also have a connecting return code.
2284 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2285 dwFlags, &This->dp2->spData );
2287 if( !FAILED(hr) )
2289 EnumSessionAsyncCallbackData* lpData
2290 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpData ) );
2291 /* FIXME: need to kill the thread on object deletion */
2292 lpData->lpSpData = &This->dp2->spData;
2294 CopyMemory( &lpData->requestGuid, &lpsd->guidApplication, sizeof(GUID) );
2295 lpData->dwEnumSessionFlags = dwFlags;
2296 lpData->dwTimeout = dwTimeout;
2298 This->dp2->hKillEnumSessionThreadEvent =
2299 CreateEventW( NULL, TRUE, FALSE, NULL );
2301 if( !DuplicateHandle( GetCurrentProcess(),
2302 This->dp2->hKillEnumSessionThreadEvent,
2303 GetCurrentProcess(),
2304 &lpData->hSuicideRequest,
2305 0, FALSE, DUPLICATE_SAME_ACCESS )
2308 ERR( "Can't duplicate thread killing handle\n" );
2311 TRACE( ": creating EnumSessionsRequest thread\n" );
2313 This->dp2->hEnumSessionThread = CreateThread( NULL,
2315 DP_EnumSessionsSendAsyncRequestThread,
2316 lpData,
2318 &dwThreadId );
2322 else
2324 /* Invalidate the session cache for the interface */
2325 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2327 /* Send the broadcast for session enumeration */
2328 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2329 dwFlags,
2330 &This->dp2->spData );
2333 SleepEx( dwTimeout, FALSE );
2335 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2336 This->dp2->lpNameServerData, dwTimeout,
2337 lpContext );
2340 return hr;
2343 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2344 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2345 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2346 LPVOID lpContext, DWORD dwFlags )
2348 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2349 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2350 lpContext, dwFlags, TRUE );
2353 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2354 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2355 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2356 LPVOID lpContext, DWORD dwFlags )
2358 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2359 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2360 lpContext, dwFlags, FALSE );
2363 static HRESULT WINAPI DP_IF_GetPlayerCaps
2364 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
2365 DWORD dwFlags )
2367 DPSP_GETCAPSDATA data;
2369 TRACE("(%p)->(0x%08lx,%p,0x%08lx)\n", This, idPlayer, lpDPCaps, dwFlags);
2371 /* Query the service provider */
2372 data.idPlayer = idPlayer;
2373 data.dwFlags = dwFlags;
2374 data.lpCaps = lpDPCaps;
2375 data.lpISP = This->dp2->spData.lpISP;
2377 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2380 static HRESULT WINAPI DP_IF_GetCaps
2381 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags )
2383 return DP_IF_GetPlayerCaps( This, DPID_ALLPLAYERS, lpDPCaps, dwFlags );
2386 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2387 ( LPDIRECTPLAY2A iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2389 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2390 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2393 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2394 ( LPDIRECTPLAY2 iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2396 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2397 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2400 static HRESULT WINAPI DP_IF_GetGroupData
2401 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2402 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2404 lpGroupData lpGData;
2405 DWORD dwRequiredBufferSize;
2406 LPVOID lpCopyDataFrom;
2408 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
2409 This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi );
2411 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2413 return DPERR_INVALIDGROUP;
2416 /* How much buffer is required? */
2417 if( dwFlags & DPSET_LOCAL )
2419 dwRequiredBufferSize = lpGData->dwLocalDataSize;
2420 lpCopyDataFrom = lpGData->lpLocalData;
2422 else
2424 dwRequiredBufferSize = lpGData->dwRemoteDataSize;
2425 lpCopyDataFrom = lpGData->lpRemoteData;
2428 /* Is the user requesting to know how big a buffer is required? */
2429 if( ( lpData == NULL ) ||
2430 ( *lpdwDataSize < dwRequiredBufferSize )
2433 *lpdwDataSize = dwRequiredBufferSize;
2434 return DPERR_BUFFERTOOSMALL;
2437 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2439 return DP_OK;
2442 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2443 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2444 LPDWORD lpdwDataSize, DWORD dwFlags )
2446 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2447 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2448 dwFlags, TRUE );
2451 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2452 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2453 LPDWORD lpdwDataSize, DWORD dwFlags )
2455 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2456 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2457 dwFlags, FALSE );
2460 static HRESULT WINAPI DP_IF_GetGroupName
2461 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2462 LPDWORD lpdwDataSize, BOOL bAnsi )
2464 lpGroupData lpGData;
2465 LPDPNAME lpName = (LPDPNAME)lpData;
2466 DWORD dwRequiredDataSize;
2468 FIXME("(%p)->(0x%08lx,%p,%p,%u) ANSI ignored\n",
2469 This, idGroup, lpData, lpdwDataSize, bAnsi );
2471 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2473 return DPERR_INVALIDGROUP;
2476 dwRequiredDataSize = lpGData->name.dwSize;
2478 if( lpGData->name.u1.lpszShortNameA )
2480 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
2483 if( lpGData->name.u2.lpszLongNameA )
2485 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
2488 if( ( lpData == NULL ) ||
2489 ( *lpdwDataSize < dwRequiredDataSize )
2492 *lpdwDataSize = dwRequiredDataSize;
2493 return DPERR_BUFFERTOOSMALL;
2496 /* Copy the structure */
2497 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2499 if( lpGData->name.u1.lpszShortNameA )
2501 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2502 lpGData->name.u1.lpszShortNameA );
2504 else
2506 lpName->u1.lpszShortNameA = NULL;
2509 if( lpGData->name.u1.lpszShortNameA )
2511 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2512 lpGData->name.u2.lpszLongNameA );
2514 else
2516 lpName->u2.lpszLongNameA = NULL;
2519 return DP_OK;
2522 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2523 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2524 LPDWORD lpdwDataSize )
2526 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2527 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2530 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2531 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2532 LPDWORD lpdwDataSize )
2534 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2535 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2538 static HRESULT WINAPI DP_IF_GetMessageCount
2539 ( IDirectPlay2Impl* This, DPID idPlayer,
2540 LPDWORD lpdwCount, BOOL bAnsi )
2542 FIXME("(%p)->(0x%08lx,%p,%u): stub\n", This, idPlayer, lpdwCount, bAnsi );
2543 return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer,
2544 DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL,
2545 bAnsi );
2548 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2549 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDWORD lpdwCount )
2551 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2552 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, TRUE );
2555 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2556 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDWORD lpdwCount )
2558 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2559 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, FALSE );
2562 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2563 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2565 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2566 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2567 return DP_OK;
2570 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2571 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2573 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2574 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2575 return DP_OK;
2578 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2579 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2580 DWORD dwFlags )
2582 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2583 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2586 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2587 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2588 DWORD dwFlags )
2590 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2591 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2594 static HRESULT WINAPI DP_IF_GetPlayerData
2595 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2596 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2598 lpPlayerList lpPList;
2599 DWORD dwRequiredBufferSize;
2600 LPVOID lpCopyDataFrom;
2602 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
2603 This, idPlayer, lpData, lpdwDataSize, dwFlags, bAnsi );
2605 if( This->dp2->connectionInitialized == NO_PROVIDER )
2607 return DPERR_UNINITIALIZED;
2610 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2612 return DPERR_INVALIDPLAYER;
2615 /* How much buffer is required? */
2616 if( dwFlags & DPSET_LOCAL )
2618 dwRequiredBufferSize = lpPList->lpPData->dwLocalDataSize;
2619 lpCopyDataFrom = lpPList->lpPData->lpLocalData;
2621 else
2623 dwRequiredBufferSize = lpPList->lpPData->dwRemoteDataSize;
2624 lpCopyDataFrom = lpPList->lpPData->lpRemoteData;
2627 /* Is the user requesting to know how big a buffer is required? */
2628 if( ( lpData == NULL ) ||
2629 ( *lpdwDataSize < dwRequiredBufferSize )
2632 *lpdwDataSize = dwRequiredBufferSize;
2633 return DPERR_BUFFERTOOSMALL;
2636 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2638 return DP_OK;
2641 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2642 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2643 LPDWORD lpdwDataSize, DWORD dwFlags )
2645 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2646 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2647 dwFlags, TRUE );
2650 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2651 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2652 LPDWORD lpdwDataSize, DWORD dwFlags )
2654 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2655 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2656 dwFlags, FALSE );
2659 static HRESULT WINAPI DP_IF_GetPlayerName
2660 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2661 LPDWORD lpdwDataSize, BOOL bAnsi )
2663 lpPlayerList lpPList;
2664 LPDPNAME lpName = (LPDPNAME)lpData;
2665 DWORD dwRequiredDataSize;
2667 FIXME( "(%p)->(0x%08lx,%p,%p,%u): ANSI\n",
2668 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2670 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2672 return DPERR_INVALIDPLAYER;
2675 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
2677 if( lpPList->lpPData->name.u1.lpszShortNameA )
2679 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
2682 if( lpPList->lpPData->name.u2.lpszLongNameA )
2684 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
2687 if( ( lpData == NULL ) ||
2688 ( *lpdwDataSize < dwRequiredDataSize )
2691 *lpdwDataSize = dwRequiredDataSize;
2692 return DPERR_BUFFERTOOSMALL;
2695 /* Copy the structure */
2696 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
2698 if( lpPList->lpPData->name.u1.lpszShortNameA )
2700 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2701 lpPList->lpPData->name.u1.lpszShortNameA );
2703 else
2705 lpName->u1.lpszShortNameA = NULL;
2708 if( lpPList->lpPData->name.u1.lpszShortNameA )
2710 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2711 lpPList->lpPData->name.u2.lpszLongNameA );
2713 else
2715 lpName->u2.lpszLongNameA = NULL;
2718 return DP_OK;
2721 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2722 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2723 LPDWORD lpdwDataSize )
2725 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2726 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
2729 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2730 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2731 LPDWORD lpdwDataSize )
2733 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2734 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
2737 static HRESULT WINAPI DP_GetSessionDesc
2738 ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize,
2739 BOOL bAnsi )
2741 DWORD dwRequiredSize;
2743 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
2745 if( This->dp2->connectionInitialized == NO_PROVIDER )
2747 return DPERR_UNINITIALIZED;
2750 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
2752 return DPERR_INVALIDPARAMS;
2755 /* FIXME: Get from This->dp2->lpSessionDesc */
2756 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
2758 if ( ( lpData == NULL ) ||
2759 ( *lpdwDataSize < dwRequiredSize )
2762 *lpdwDataSize = dwRequiredSize;
2763 return DPERR_BUFFERTOOSMALL;
2766 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
2768 return DP_OK;
2771 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
2772 ( LPDIRECTPLAY2A iface, LPVOID lpData, LPDWORD lpdwDataSize )
2774 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2775 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2778 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
2779 ( LPDIRECTPLAY2 iface, LPVOID lpData, LPDWORD lpdwDataSize )
2781 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2782 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2785 /* Intended only for COM compatibility. Always returns an error. */
2786 static HRESULT WINAPI DirectPlay2AImpl_Initialize
2787 ( LPDIRECTPLAY2A iface, LPGUID lpGUID )
2789 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2790 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2791 return DPERR_ALREADYINITIALIZED;
2794 /* Intended only for COM compatibility. Always returns an error. */
2795 static HRESULT WINAPI DirectPlay2WImpl_Initialize
2796 ( LPDIRECTPLAY2 iface, LPGUID lpGUID )
2798 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2799 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2800 return DPERR_ALREADYINITIALIZED;
2804 static HRESULT WINAPI DP_SecureOpen
2805 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
2806 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
2807 BOOL bAnsi )
2809 HRESULT hr = DP_OK;
2811 FIXME( "(%p)->(%p,0x%08lx,%p,%p): partial stub\n",
2812 This, lpsd, dwFlags, lpSecurity, lpCredentials );
2814 if( This->dp2->bConnectionOpen )
2816 TRACE( ": rejecting already open connection.\n" );
2817 return DPERR_ALREADYINITIALIZED;
2820 /* If we're enumerating, kill the thread */
2821 DP_KillEnumSessionThread( This );
2823 if( dwFlags & DPOPEN_CREATE )
2825 /* Rightoo - this computer is the host and the local computer needs to be
2826 the name server so that others can join this session */
2827 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
2829 This->dp2->bHostInterface = TRUE;
2831 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
2832 if( FAILED( hr ) )
2834 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
2835 return hr;
2839 /* Invoke the conditional callback for the service provider */
2840 if( This->dp2->spData.lpCB->Open )
2842 DPSP_OPENDATA data;
2844 FIXME( "Not all data fields are correct. Need new parameter\n" );
2846 data.bCreate = (dwFlags & DPOPEN_CREATE ) ? TRUE : FALSE;
2847 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
2848 : NS_GetNSAddr( This->dp2->lpNameServerData );
2849 data.lpISP = This->dp2->spData.lpISP;
2850 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) ? TRUE : FALSE;
2851 data.dwOpenFlags = dwFlags;
2852 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
2854 hr = (*This->dp2->spData.lpCB->Open)(&data);
2855 if( FAILED( hr ) )
2857 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
2858 return hr;
2863 /* Create the system group of which everything is a part of */
2864 DPID systemGroup = DPID_SYSTEM_GROUP;
2866 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
2867 NULL, 0, 0, TRUE );
2871 if( dwFlags & DPOPEN_JOIN )
2873 DPID dpidServerId = DPID_UNKNOWN;
2875 /* Create the server player for this interface. This way we can receive
2876 * messages for this session.
2878 /* FIXME: I suppose that we should be setting an event for a receive
2879 * type of thing. That way the messaging thread could know to wake
2880 * up. DPlay would then trigger the hEvent for the player the
2881 * message is directed to.
2883 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
2885 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
2888 else if( dwFlags & DPOPEN_CREATE )
2890 DPID dpidNameServerId = DPID_NAME_SERVER;
2892 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
2893 0, DPPLAYER_SERVERPLAYER, bAnsi );
2896 if( FAILED(hr) )
2898 ERR( "Couldn't create name server/system player: %s\n",
2899 DPLAYX_HresultToString(hr) );
2902 return hr;
2905 static HRESULT WINAPI DirectPlay2AImpl_Open
2906 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2908 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2909 TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags );
2910 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, TRUE );
2913 static HRESULT WINAPI DirectPlay2WImpl_Open
2914 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2916 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2917 TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags );
2918 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, FALSE );
2921 static HRESULT WINAPI DP_IF_Receive
2922 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
2923 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi )
2925 LPDPMSG lpMsg = NULL;
2927 FIXME( "(%p)->(%p,%p,0x%08lx,%p,%p,%u): stub\n",
2928 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
2930 if( This->dp2->connectionInitialized == NO_PROVIDER )
2932 return DPERR_UNINITIALIZED;
2935 if( dwFlags == 0 )
2937 dwFlags = DPRECEIVE_ALL;
2940 /* If the lpData is NULL, we must be peeking the message */
2941 if( ( lpData == NULL ) &&
2942 !( dwFlags & DPRECEIVE_PEEK )
2945 return DPERR_INVALIDPARAMS;
2948 if( dwFlags & DPRECEIVE_ALL )
2950 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
2952 if( !( dwFlags & DPRECEIVE_PEEK ) )
2954 FIXME( "Remove from queue\n" );
2957 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
2958 ( dwFlags & DPRECEIVE_FROMPLAYER )
2961 FIXME( "Find matching message 0x%08lx\n", dwFlags );
2963 else
2965 ERR( "Hmmm..dwFlags 0x%08lx\n", dwFlags );
2968 if( lpMsg == NULL )
2970 return DPERR_NOMESSAGES;
2973 /* Copy into the provided buffer */
2974 CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
2976 return DP_OK;
2979 static HRESULT WINAPI DirectPlay2AImpl_Receive
2980 ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo,
2981 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
2983 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2984 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
2985 lpData, lpdwDataSize, TRUE );
2988 static HRESULT WINAPI DirectPlay2WImpl_Receive
2989 ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo,
2990 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
2992 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2993 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
2994 lpData, lpdwDataSize, FALSE );
2997 static HRESULT WINAPI DirectPlay2AImpl_Send
2998 ( LPDIRECTPLAY2A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3000 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3001 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3002 0, 0, NULL, NULL, TRUE );
3005 static HRESULT WINAPI DirectPlay2WImpl_Send
3006 ( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3008 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3009 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3010 0, 0, NULL, NULL, FALSE );
3013 static HRESULT WINAPI DP_IF_SetGroupData
3014 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
3015 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3017 lpGroupData lpGData;
3019 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
3020 This, idGroup, lpData, dwDataSize, dwFlags, bAnsi );
3022 /* Parameter check */
3023 if( ( lpData == NULL ) &&
3024 ( dwDataSize != 0 )
3027 return DPERR_INVALIDPARAMS;
3030 /* Find the pointer to the data for this player */
3031 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3033 return DPERR_INVALIDOBJECT;
3036 if( !(dwFlags & DPSET_LOCAL) )
3038 FIXME( "Was this group created by this interface?\n" );
3039 /* FIXME: If this is a remote update need to allow it but not
3040 * send a message.
3044 DP_SetGroupData( lpGData, dwFlags, lpData, dwDataSize );
3046 /* FIXME: Only send a message if this group is local to the session otherwise
3047 * it will have been rejected above
3049 if( !(dwFlags & DPSET_LOCAL) )
3051 FIXME( "Send msg?\n" );
3054 return DP_OK;
3057 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
3058 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
3059 DWORD dwDataSize, DWORD dwFlags )
3061 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3062 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, TRUE );
3065 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
3066 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
3067 DWORD dwDataSize, DWORD dwFlags )
3069 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3070 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, FALSE );
3073 static HRESULT WINAPI DP_IF_SetGroupName
3074 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
3075 DWORD dwFlags, BOOL bAnsi )
3077 lpGroupData lpGData;
3079 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n", This, idGroup,
3080 lpGroupName, dwFlags, bAnsi );
3082 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3084 return DPERR_INVALIDGROUP;
3087 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
3089 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3090 FIXME( "Message not sent and dwFlags ignored\n" );
3092 return DP_OK;
3095 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
3096 ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName,
3097 DWORD dwFlags )
3099 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3100 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
3103 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
3104 ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName,
3105 DWORD dwFlags )
3107 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3108 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
3111 static HRESULT WINAPI DP_IF_SetPlayerData
3112 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
3113 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3115 lpPlayerList lpPList;
3117 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
3118 This, idPlayer, lpData, dwDataSize, dwFlags, bAnsi );
3120 /* Parameter check */
3121 if( ( lpData == NULL ) &&
3122 ( dwDataSize != 0 )
3125 return DPERR_INVALIDPARAMS;
3128 /* Find the pointer to the data for this player */
3129 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3131 return DPERR_INVALIDPLAYER;
3134 if( !(dwFlags & DPSET_LOCAL) )
3136 FIXME( "Was this group created by this interface?\n" );
3137 /* FIXME: If this is a remote update need to allow it but not
3138 * send a message.
3142 DP_SetPlayerData( lpPList->lpPData, dwFlags, lpData, dwDataSize );
3144 if( !(dwFlags & DPSET_LOCAL) )
3146 FIXME( "Send msg?\n" );
3149 return DP_OK;
3152 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3153 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
3154 DWORD dwDataSize, DWORD dwFlags )
3156 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3157 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3158 dwFlags, TRUE );
3161 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3162 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
3163 DWORD dwDataSize, DWORD dwFlags )
3165 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3166 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3167 dwFlags, FALSE );
3170 static HRESULT WINAPI DP_IF_SetPlayerName
3171 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
3172 DWORD dwFlags, BOOL bAnsi )
3174 lpPlayerList lpPList;
3176 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n",
3177 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3179 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3181 return DPERR_INVALIDGROUP;
3184 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3186 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3187 FIXME( "Message not sent and dwFlags ignored\n" );
3189 return DP_OK;
3192 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3193 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName,
3194 DWORD dwFlags )
3196 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3197 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3200 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3201 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName,
3202 DWORD dwFlags )
3204 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3205 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3208 static HRESULT WINAPI DP_SetSessionDesc
3209 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
3210 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3212 DWORD dwRequiredSize;
3213 LPDPSESSIONDESC2 lpTempSessDesc;
3215 TRACE( "(%p)->(%p,0x%08lx,%u,%u)\n",
3216 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3218 if( This->dp2->connectionInitialized == NO_PROVIDER )
3220 return DPERR_UNINITIALIZED;
3223 if( dwFlags )
3225 return DPERR_INVALIDPARAMS;
3228 /* Only the host is allowed to update the session desc */
3229 if( !This->dp2->bHostInterface )
3231 return DPERR_ACCESSDENIED;
3234 /* FIXME: Copy into This->dp2->lpSessionDesc */
3235 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3236 lpTempSessDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize );
3238 if( lpTempSessDesc == NULL )
3240 return DPERR_OUTOFMEMORY;
3243 /* Free the old */
3244 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3246 This->dp2->lpSessionDesc = lpTempSessDesc;
3248 /* Set the new */
3249 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3251 /* If this is an external invocation of the interface, we should be
3252 * letting everyone know that things have changed. Otherwise this is
3253 * just an initialization and it doesn't need to be propagated.
3255 if( !bInitial )
3257 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3260 return DP_OK;
3263 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3264 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3266 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3267 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3270 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3271 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3273 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3274 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3277 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3278 DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3280 DWORD dwSize = 0;
3282 if( lpSessDesc == NULL )
3284 /* Hmmm..don't need any size? */
3285 ERR( "NULL lpSessDesc\n" );
3286 return dwSize;
3289 dwSize += sizeof( *lpSessDesc );
3291 if( bAnsi )
3293 if( lpSessDesc->u1.lpszSessionNameA )
3295 dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1;
3298 if( lpSessDesc->u2.lpszPasswordA )
3300 dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1;
3303 else /* UNICODE */
3305 if( lpSessDesc->u1.lpszSessionName )
3307 dwSize += sizeof( WCHAR ) *
3308 ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 );
3311 if( lpSessDesc->u2.lpszPassword )
3313 dwSize += sizeof( WCHAR ) *
3314 ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 );
3318 return dwSize;
3321 /* Assumes that contugous buffers are already allocated. */
3322 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3323 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3325 BYTE* lpStartOfFreeSpace;
3327 if( lpSessionDest == NULL )
3329 ERR( "NULL lpSessionDest\n" );
3330 return;
3333 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3335 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3337 if( bAnsi )
3339 if( lpSessionSrc->u1.lpszSessionNameA )
3341 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3342 lpSessionDest->u1.lpszSessionNameA );
3343 lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3344 lpStartOfFreeSpace +=
3345 lstrlenA( (LPSTR)lpSessionDest->u1.lpszSessionNameA ) + 1;
3348 if( lpSessionSrc->u2.lpszPasswordA )
3350 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3351 lpSessionDest->u2.lpszPasswordA );
3352 lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3353 lpStartOfFreeSpace +=
3354 lstrlenA( (LPSTR)lpSessionDest->u2.lpszPasswordA ) + 1;
3357 else /* UNICODE */
3359 if( lpSessionSrc->u1.lpszSessionName )
3361 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3362 lpSessionDest->u1.lpszSessionName );
3363 lpSessionDest->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3364 lpStartOfFreeSpace += sizeof(WCHAR) *
3365 ( lstrlenW( (LPWSTR)lpSessionDest->u1.lpszSessionName ) + 1 );
3368 if( lpSessionSrc->u2.lpszPassword )
3370 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3371 lpSessionDest->u2.lpszPassword );
3372 lpSessionDest->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3373 lpStartOfFreeSpace += sizeof(WCHAR) *
3374 ( lstrlenW( (LPWSTR)lpSessionDest->u2.lpszPassword ) + 1 );
3380 static HRESULT WINAPI DP_IF_AddGroupToGroup
3381 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3383 lpGroupData lpGParentData;
3384 lpGroupData lpGData;
3385 lpGroupList lpNewGList;
3387 TRACE( "(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup );
3389 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3391 return DPERR_INVALIDGROUP;
3394 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3396 return DPERR_INVALIDGROUP;
3399 /* Create a player list (ie "shortcut" ) */
3400 lpNewGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewGList ) );
3401 if( lpNewGList == NULL )
3403 return DPERR_CANTADDPLAYER;
3406 /* Add the shortcut */
3407 lpGData->uRef++;
3408 lpNewGList->lpGData = lpGData;
3410 /* Add the player to the list of players for this group */
3411 DPQ_INSERT( lpGData->groups, lpNewGList, groups );
3413 /* Send a ADDGROUPTOGROUP message */
3414 FIXME( "Not sending message\n" );
3416 return DP_OK;
3419 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3420 ( LPDIRECTPLAY3A iface, DPID idParentGroup, DPID idGroup )
3422 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3423 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3426 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3427 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3429 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3430 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3433 static HRESULT WINAPI DP_IF_CreateGroupInGroup
3434 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
3435 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
3436 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3438 lpGroupData lpGParentData;
3439 lpGroupList lpGList;
3440 lpGroupData lpGData;
3442 TRACE( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
3443 This, idParentGroup, lpidGroup, lpGroupName, lpData,
3444 dwDataSize, dwFlags, bAnsi );
3446 /* Verify that the specified parent is valid */
3447 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This,
3448 idParentGroup ) ) == NULL
3451 return DPERR_INVALIDGROUP;
3454 lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName,
3455 dwFlags, idParentGroup, bAnsi );
3457 if( lpGData == NULL )
3459 return DPERR_CANTADDPLAYER; /* yes player not group */
3462 /* Something else is referencing this data */
3463 lpGData->uRef++;
3465 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
3467 /* The list has now been inserted into the interface group list. We now
3468 need to put a "shortcut" to this group in the parent group */
3469 lpGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGList ) );
3470 if( lpGList == NULL )
3472 FIXME( "Memory leak\n" );
3473 return DPERR_CANTADDPLAYER; /* yes player not group */
3476 lpGList->lpGData = lpGData;
3478 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
3480 /* Let the SP know that we've created this group */
3481 if( This->dp2->spData.lpCB->CreateGroup )
3483 DPSP_CREATEGROUPDATA data;
3485 TRACE( "Calling SP CreateGroup\n" );
3487 data.idGroup = *lpidGroup;
3488 data.dwFlags = dwFlags;
3489 data.lpSPMessageHeader = lpMsgHdr;
3490 data.lpISP = This->dp2->spData.lpISP;
3492 (*This->dp2->spData.lpCB->CreateGroup)( &data );
3495 /* Inform all other peers of the creation of a new group. If there are
3496 * no peers keep this quiet.
3498 if( This->dp2->lpSessionDesc &&
3499 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
3501 DPMSG_CREATEPLAYERORGROUP msg;
3503 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
3504 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
3505 msg.dpId = *lpidGroup;
3506 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
3507 msg.lpData = lpData;
3508 msg.dwDataSize = dwDataSize;
3509 msg.dpnName = *lpGroupName;
3511 /* FIXME: Correct to just use send effectively? */
3512 /* FIXME: Should size include data w/ message or just message "header" */
3513 /* FIXME: Check return code */
3514 DP_SendEx( (IDirectPlay2Impl*)This,
3515 DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
3516 0, 0, NULL, NULL, bAnsi );
3519 return DP_OK;
3522 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3523 ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup,
3524 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3525 DWORD dwFlags )
3527 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3529 *lpidGroup = DPID_UNKNOWN;
3531 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3532 lpGroupName, lpData, dwDataSize, dwFlags,
3533 TRUE );
3536 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3537 ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup,
3538 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3539 DWORD dwFlags )
3541 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3543 *lpidGroup = DPID_UNKNOWN;
3545 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3546 lpGroupName, lpData, dwDataSize,
3547 dwFlags, FALSE );
3550 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
3551 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3553 lpGroupList lpGList;
3554 lpGroupData lpGParentData;
3556 TRACE("(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup );
3558 /* Is the parent group valid? */
3559 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3561 return DPERR_INVALIDGROUP;
3564 /* Remove the group from the parent group queue */
3565 DPQ_REMOVE_ENTRY( lpGParentData->groups, groups, lpGData->dpid, ==, idGroup, lpGList );
3567 if( lpGList == NULL )
3569 return DPERR_INVALIDGROUP;
3572 /* Decrement the ref count */
3573 lpGList->lpGData->uRef--;
3575 /* Free up the list item */
3576 HeapFree( GetProcessHeap(), 0, lpGList );
3578 /* Should send a DELETEGROUPFROMGROUP message */
3579 FIXME( "message not sent\n" );
3581 return DP_OK;
3584 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3585 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3587 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3588 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3591 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3592 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3594 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3595 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3598 static
3599 BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
3600 LPDWORD lpdwBufSize )
3602 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3603 HRESULT hr;
3605 dpCompoundAddress.dwDataSize = sizeof( GUID );
3606 memcpy( &dpCompoundAddress.guidDataType, &DPAID_ServiceProvider,
3607 sizeof( GUID ) ) ;
3608 dpCompoundAddress.lpData = lpcSpGuid;
3610 *lplpAddrBuf = NULL;
3611 *lpdwBufSize = 0;
3613 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3614 lpdwBufSize, TRUE );
3616 if( hr != DPERR_BUFFERTOOSMALL )
3618 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3619 return FALSE;
3622 /* Now allocate the buffer */
3623 *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3624 *lpdwBufSize );
3626 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3627 lpdwBufSize, TRUE );
3628 if( FAILED(hr) )
3630 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3631 return FALSE;
3634 return TRUE;
3637 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
3638 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3640 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3641 TRACE("(%p)->(%p,%p,%p,0x%08lx)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3643 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
3644 if( dwFlags == 0 )
3646 dwFlags = DPCONNECTION_DIRECTPLAY;
3649 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
3650 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) )
3653 return DPERR_INVALIDFLAGS;
3656 if( !lpEnumCallback || !*lpEnumCallback )
3658 return DPERR_INVALIDPARAMS;
3661 /* Enumerate DirectPlay service providers */
3662 if( dwFlags & DPCONNECTION_DIRECTPLAY )
3664 HKEY hkResult;
3665 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3666 LPCSTR guidDataSubKey = "Guid";
3667 char subKeyName[51];
3668 DWORD dwIndex, sizeOfSubKeyName=50;
3669 FILETIME filetime;
3671 /* Need to loop over the service providers in the registry */
3672 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3673 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3675 /* Hmmm. Does this mean that there are no service providers? */
3676 ERR(": no service providers?\n");
3677 return DP_OK;
3681 /* Traverse all the service providers we have available */
3682 for( dwIndex=0;
3683 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3684 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3685 ++dwIndex, sizeOfSubKeyName=51 )
3688 HKEY hkServiceProvider;
3689 GUID serviceProviderGUID;
3690 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3691 char returnBuffer[51];
3692 WCHAR buff[51];
3693 DPNAME dpName;
3694 BOOL bBuildPass;
3696 LPVOID lpAddressBuffer = NULL;
3697 DWORD dwAddressBufferSize = 0;
3699 TRACE(" this time through: %s\n", subKeyName );
3701 /* Get a handle for this particular service provider */
3702 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3703 &hkServiceProvider ) != ERROR_SUCCESS )
3705 ERR(": what the heck is going on?\n" );
3706 continue;
3709 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3710 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
3711 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3713 ERR(": missing GUID registry data members\n" );
3714 continue;
3717 /* FIXME: Check return types to ensure we're interpreting data right */
3718 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3719 CLSIDFromString( buff, &serviceProviderGUID );
3720 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3722 /* Fill in the DPNAME struct for the service provider */
3723 dpName.dwSize = sizeof( dpName );
3724 dpName.dwFlags = 0;
3725 dpName.u1.lpszShortNameA = subKeyName;
3726 dpName.u2.lpszLongNameA = NULL;
3728 /* Create the compound address for the service provider.
3729 * NOTE: This is a gruesome architectural scar right now. DP
3730 * uses DPL and DPL uses DP. Nasty stuff. This may be why the
3731 * native dll just gets around this little bit by allocating an
3732 * 80 byte buffer which isn't even filled with a valid compound
3733 * address. Oh well. Creating a proper compound address is the
3734 * way to go anyways despite this method taking slightly more
3735 * heap space and realtime :) */
3737 bBuildPass = DP_BuildSPCompoundAddr( &serviceProviderGUID,
3738 &lpAddressBuffer,
3739 &dwAddressBufferSize );
3740 if( !bBuildPass )
3742 ERR( "Can't build compound addr\n" );
3743 return DPERR_GENERIC;
3746 /* The enumeration will return FALSE if we are not to continue */
3747 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3748 &dpName, DPCONNECTION_DIRECTPLAY, lpContext ) )
3750 return DP_OK;
3755 /* Enumerate DirectPlayLobby service providers */
3756 if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY )
3758 HKEY hkResult;
3759 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3760 LPCSTR guidDataSubKey = "Guid";
3761 char subKeyName[51];
3762 DWORD dwIndex, sizeOfSubKeyName=50;
3763 FILETIME filetime;
3765 /* Need to loop over the service providers in the registry */
3766 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3767 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3769 /* Hmmm. Does this mean that there are no service providers? */
3770 ERR(": no service providers?\n");
3771 return DP_OK;
3775 /* Traverse all the lobby providers we have available */
3776 for( dwIndex=0;
3777 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3778 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3779 ++dwIndex, sizeOfSubKeyName=51 )
3782 HKEY hkServiceProvider;
3783 GUID serviceProviderGUID;
3784 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3785 char returnBuffer[51];
3786 WCHAR buff[51];
3787 DPNAME dpName;
3788 HRESULT hr;
3790 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3791 LPVOID lpAddressBuffer = NULL;
3792 DWORD dwAddressBufferSize = 0;
3794 TRACE(" this time through: %s\n", subKeyName );
3796 /* Get a handle for this particular service provider */
3797 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3798 &hkServiceProvider ) != ERROR_SUCCESS )
3800 ERR(": what the heck is going on?\n" );
3801 continue;
3804 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3805 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
3806 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3808 ERR(": missing GUID registry data members\n" );
3809 continue;
3812 /* FIXME: Check return types to ensure we're interpreting data right */
3813 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3814 CLSIDFromString( buff, &serviceProviderGUID );
3815 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3817 /* Fill in the DPNAME struct for the service provider */
3818 dpName.dwSize = sizeof( dpName );
3819 dpName.dwFlags = 0;
3820 dpName.u1.lpszShortNameA = subKeyName;
3821 dpName.u2.lpszLongNameA = NULL;
3823 /* Create the compound address for the service provider.
3824 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
3825 nast stuff. This may be why the native dll just gets around this little bit by
3826 allocating an 80 byte buffer which isn't even a filled with a valid compound
3827 address. Oh well. Creating a proper compound address is the way to go anyways
3828 despite this method taking slightly more heap space and realtime :) */
3830 dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
3831 dpCompoundAddress.dwDataSize = sizeof( GUID );
3832 dpCompoundAddress.lpData = &serviceProviderGUID;
3834 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3835 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
3837 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3838 return hr;
3841 /* Now allocate the buffer */
3842 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
3844 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3845 &dwAddressBufferSize, TRUE ) ) != DP_OK )
3847 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3848 return hr;
3851 /* The enumeration will return FALSE if we are not to continue */
3852 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3853 &dpName, DPCONNECTION_DIRECTPLAYLOBBY, lpContext ) )
3855 return DP_OK;
3860 return DP_OK;
3863 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
3864 ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3866 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3867 FIXME("(%p)->(%p,%p,%p,0x%08lx): stub\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3868 return DP_OK;
3871 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
3872 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
3873 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
3874 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
3876 lpGroupList lpGList;
3877 lpGroupData lpGData;
3879 FIXME( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
3880 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
3881 lpContext, dwFlags, bAnsi );
3883 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3885 return DPERR_INVALIDGROUP;
3888 if( DPQ_IS_EMPTY( lpGData->groups ) )
3890 return DP_OK;
3893 lpGList = DPQ_FIRST( lpGData->groups );
3895 for( ;; )
3897 /* FIXME: Should check dwFlags for match here */
3899 if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP,
3900 &lpGList->lpGData->name, dwFlags,
3901 lpContext ) )
3903 return DP_OK; /* User requested break */
3906 if( DPQ_IS_ENDOFLIST( lpGList->groups ) )
3908 break;
3911 lpGList = DPQ_NEXT( lpGList->groups );
3915 return DP_OK;
3918 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
3919 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3920 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3921 DWORD dwFlags )
3923 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3924 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3925 lpEnumPlayersCallback2, lpContext, dwFlags,
3926 TRUE );
3929 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
3930 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3931 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3932 DWORD dwFlags )
3934 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3935 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3936 lpEnumPlayersCallback2, lpContext, dwFlags,
3937 FALSE );
3940 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
3941 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3943 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3944 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3945 return DP_OK;
3948 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
3949 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3951 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3952 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3953 return DP_OK;
3956 static BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
3957 REFGUID guidDataType,
3958 DWORD dwDataSize,
3959 LPCVOID lpData,
3960 LPVOID lpContext )
3962 /* Looking for the GUID of the provider to load */
3963 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
3964 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
3967 TRACE( "Found SP/LP (%s) %s (data size = 0x%08lx)\n",
3968 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
3970 if( dwDataSize != sizeof( GUID ) )
3972 ERR( "Invalid sp/lp guid size 0x%08lx\n", dwDataSize );
3975 memcpy( lpContext, lpData, dwDataSize );
3977 /* There shouldn't be more than 1 GUID/compound address */
3978 return FALSE;
3981 /* Still waiting for what we want */
3982 return TRUE;
3986 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
3987 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
3989 UINT i;
3990 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3991 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3992 LPCSTR guidDataSubKey = "Guid";
3993 LPCSTR majVerDataSubKey = "dwReserved1";
3994 LPCSTR minVerDataSubKey = "dwReserved2";
3995 LPCSTR pathSubKey = "Path";
3997 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
3999 /* FIXME: Cloned code with a quick hack. */
4000 for( i=0; i<2; i++ )
4002 HKEY hkResult;
4003 LPCSTR searchSubKey;
4004 char subKeyName[51];
4005 DWORD dwIndex, sizeOfSubKeyName=50;
4006 FILETIME filetime;
4008 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
4009 *lpbIsDpSp = (i == 0) ? TRUE : FALSE;
4012 /* Need to loop over the service providers in the registry */
4013 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4014 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4016 /* Hmmm. Does this mean that there are no service providers? */
4017 ERR(": no service providers?\n");
4018 return 0;
4021 /* Traverse all the service providers we have available */
4022 for( dwIndex=0;
4023 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4024 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4025 ++dwIndex, sizeOfSubKeyName=51 )
4028 HKEY hkServiceProvider;
4029 GUID serviceProviderGUID;
4030 DWORD returnType, sizeOfReturnBuffer = 255;
4031 char returnBuffer[256];
4032 WCHAR buff[51];
4033 DWORD dwTemp, len;
4035 TRACE(" this time through: %s\n", subKeyName );
4037 /* Get a handle for this particular service provider */
4038 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4039 &hkServiceProvider ) != ERROR_SUCCESS )
4041 ERR(": what the heck is going on?\n" );
4042 continue;
4045 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4046 NULL, &returnType, (LPBYTE)returnBuffer,
4047 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4049 ERR(": missing GUID registry data members\n" );
4050 continue;
4053 /* FIXME: Check return types to ensure we're interpreting data right */
4054 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4055 CLSIDFromString( buff, &serviceProviderGUID );
4056 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4058 /* Determine if this is the Service Provider that the user asked for */
4059 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
4061 continue;
4064 if( i == 0 ) /* DP SP */
4066 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
4067 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
4068 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
4071 sizeOfReturnBuffer = 255;
4073 /* Get dwReserved1 */
4074 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
4075 NULL, &returnType, (LPBYTE)returnBuffer,
4076 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4078 ERR(": missing dwReserved1 registry data members\n") ;
4079 continue;
4082 if( i == 0 )
4083 memcpy( &lpSpData->dwReserved1, returnBuffer, sizeof(lpSpData->dwReserved1) );
4085 sizeOfReturnBuffer = 255;
4087 /* Get dwReserved2 */
4088 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4089 NULL, &returnType, (LPBYTE)returnBuffer,
4090 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4092 ERR(": missing dwReserved1 registry data members\n") ;
4093 continue;
4096 if( i == 0 )
4097 memcpy( &lpSpData->dwReserved2, returnBuffer, sizeof(lpSpData->dwReserved2) );
4099 sizeOfReturnBuffer = 255;
4101 /* Get the path for this service provider */
4102 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
4103 NULL, NULL, (LPBYTE)returnBuffer,
4104 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
4106 ERR(": missing PATH registry data members: 0x%08lx\n", dwTemp );
4107 continue;
4110 TRACE( "Loading %s\n", returnBuffer );
4111 return LoadLibraryA( returnBuffer );
4115 return 0;
4118 static
4119 HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider )
4121 HRESULT hr;
4122 LPDPSP_SPINIT SPInit;
4124 /* Initialize the service provider by calling SPInit */
4125 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4127 if( SPInit == NULL )
4129 ERR( "Service provider doesn't provide SPInit interface?\n" );
4130 FreeLibrary( hServiceProvider );
4131 return DPERR_UNAVAILABLE;
4134 TRACE( "Calling SPInit (DP SP entry point)\n" );
4136 hr = (*SPInit)( &This->dp2->spData );
4138 if( FAILED(hr) )
4140 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4141 FreeLibrary( hServiceProvider );
4142 return hr;
4145 /* FIXME: Need to verify the sanity of the returned callback table
4146 * using IsBadCodePtr */
4147 This->dp2->bSPInitialized = TRUE;
4149 /* This interface is now initialized as a DP object */
4150 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
4152 /* Store the handle of the module so that we can unload it later */
4153 This->dp2->hServiceProvider = hServiceProvider;
4155 return hr;
4158 static
4159 HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hLobbyProvider )
4161 HRESULT hr;
4162 LPSP_INIT DPLSPInit;
4164 /* Initialize the service provider by calling SPInit */
4165 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
4167 if( DPLSPInit == NULL )
4169 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4170 FreeLibrary( hLobbyProvider );
4171 return DPERR_UNAVAILABLE;
4174 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4176 hr = (*DPLSPInit)( &This->dp2->dplspData );
4178 if( FAILED(hr) )
4180 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4181 FreeLibrary( hLobbyProvider );
4182 return hr;
4185 /* FIXME: Need to verify the sanity of the returned callback table
4186 * using IsBadCodePtr */
4188 This->dp2->bDPLSPInitialized = TRUE;
4190 /* This interface is now initialized as a lobby object */
4191 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
4193 /* Store the handle of the module so that we can unload it later */
4194 This->dp2->hDPLobbyProvider = hLobbyProvider;
4196 return hr;
4199 static HRESULT WINAPI DP_IF_InitializeConnection
4200 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi )
4202 HMODULE hServiceProvider;
4203 HRESULT hr;
4204 GUID guidSP;
4205 const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
4206 BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4208 TRACE("(%p)->(%p,0x%08lx,%u)\n", This, lpConnection, dwFlags, bAnsi );
4210 if( dwFlags != 0 )
4212 return DPERR_INVALIDFLAGS;
4215 /* Find out what the requested SP is and how large this buffer is */
4216 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
4217 dwAddrSize, &guidSP );
4219 if( FAILED(hr) )
4221 ERR( "Invalid compound address?\n" );
4222 return DPERR_UNAVAILABLE;
4225 /* Load the service provider */
4226 hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp );
4228 if( hServiceProvider == 0 )
4230 ERR( "Unable to load service provider\n" );
4231 return DPERR_UNAVAILABLE;
4234 if( bIsDpSp )
4236 /* Fill in what we can of the Service Provider required information.
4237 * The rest was be done in DP_LoadSP
4239 This->dp2->spData.lpAddress = lpConnection;
4240 This->dp2->spData.dwAddressSize = dwAddrSize;
4241 This->dp2->spData.lpGuid = &guidSP;
4243 hr = DP_InitializeDPSP( This, hServiceProvider );
4245 else
4247 This->dp2->dplspData.lpAddress = lpConnection;
4249 hr = DP_InitializeDPLSP( This, hServiceProvider );
4252 if( FAILED(hr) )
4254 return hr;
4257 return DP_OK;
4260 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4261 ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
4263 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4265 /* This may not be externally invoked once either an SP or LP is initialized */
4266 if( This->dp2->connectionInitialized != NO_PROVIDER )
4268 return DPERR_ALREADYINITIALIZED;
4271 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE );
4274 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4275 ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
4277 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4279 /* This may not be externally invoked once either an SP or LP is initialized */
4280 if( This->dp2->connectionInitialized != NO_PROVIDER )
4282 return DPERR_ALREADYINITIALIZED;
4285 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE );
4288 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4289 ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4290 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4292 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4293 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4296 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4297 ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4298 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4300 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4301 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4304 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4305 ( LPDIRECTPLAY3A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4307 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4308 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4309 return DP_OK;
4312 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4313 ( LPDIRECTPLAY3 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4315 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4316 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4317 return DP_OK;
4320 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4321 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4323 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4324 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4325 return DP_OK;
4328 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4329 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4331 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4332 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4333 return DP_OK;
4336 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4337 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup )
4339 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4340 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
4341 return DP_OK;
4344 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4345 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup )
4347 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4348 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
4349 return DP_OK;
4352 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4353 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDWORD lpdwFlags )
4355 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4356 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
4357 return DP_OK;
4360 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4361 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDWORD lpdwFlags )
4363 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4364 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
4365 return DP_OK;
4368 static HRESULT WINAPI DP_IF_GetGroupParent
4369 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
4370 BOOL bAnsi )
4372 lpGroupData lpGData;
4374 TRACE("(%p)->(0x%08lx,%p,%u)\n", This, idGroup, lpidGroup, bAnsi );
4376 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4378 return DPERR_INVALIDGROUP;
4381 *lpidGroup = lpGData->dpid;
4383 return DP_OK;
4386 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4387 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
4389 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4390 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE );
4392 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4393 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
4395 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4396 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE );
4399 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4400 ( LPDIRECTPLAY3A iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4402 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4403 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4404 return DP_OK;
4407 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4408 ( LPDIRECTPLAY3 iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4410 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4411 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4412 return DP_OK;
4415 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4416 ( LPDIRECTPLAY3A iface, DPID idPlayer, LPDWORD lpdwFlags )
4418 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4419 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
4420 return DP_OK;
4423 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4424 ( LPDIRECTPLAY3 iface, DPID idPlayer, LPDWORD lpdwFlags )
4426 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4427 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
4428 return DP_OK;
4431 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4432 ( LPDIRECTPLAY4A iface, DPID idGroup, LPDPID lpidGroupOwner )
4434 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4435 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
4436 return DP_OK;
4439 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4440 ( LPDIRECTPLAY4 iface, DPID idGroup, LPDPID lpidGroupOwner )
4442 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4443 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
4444 return DP_OK;
4447 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4448 ( LPDIRECTPLAY4A iface, DPID idGroup , DPID idGroupOwner )
4450 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4451 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
4452 return DP_OK;
4455 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4456 ( LPDIRECTPLAY4 iface, DPID idGroup , DPID idGroupOwner )
4458 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4459 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
4460 return DP_OK;
4463 static HRESULT WINAPI DP_SendEx
4464 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4465 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4466 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi )
4468 lpPlayerList lpPList;
4469 lpGroupData lpGData;
4470 BOOL bValidDestination = FALSE;
4472 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx,0x%08lx,0x%08lx,%p,%p,%u)"
4473 ": stub\n",
4474 This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority,
4475 dwTimeout, lpContext, lpdwMsgID, bAnsi );
4477 /* FIXME: Add parameter checking */
4478 /* FIXME: First call to this needs to aquire a message id which will be
4479 * used for multiple sends
4482 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4484 /* Verify that the message is being sent from a valid local player. The
4485 * from player may be anonymous DPID_UNKNOWN
4487 if( idFrom != DPID_UNKNOWN )
4489 if( ( lpPList = DP_FindPlayer( This, idFrom ) ) == NULL )
4491 WARN( "INFO: Invalid from player 0x%08lx\n", idFrom );
4492 return DPERR_INVALIDPLAYER;
4496 /* Verify that the message is being sent to a valid player, group or to
4497 * everyone. If it's valid, send it to those players.
4499 if( idTo == DPID_ALLPLAYERS )
4501 bValidDestination = TRUE;
4503 /* See if SP has the ability to multicast. If so, use it */
4504 if( This->dp2->spData.lpCB->SendToGroupEx )
4506 FIXME( "Use group sendex to group 0\n" );
4508 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4510 FIXME( "Use obsolete group send to group 0\n" );
4512 else /* No multicast, multiplicate */
4514 /* Send to all players we know about */
4515 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4519 if( ( !bValidDestination ) &&
4520 ( DP_FindPlayer( This, idTo ) != NULL )
4523 bValidDestination = TRUE;
4525 /* Have the service provider send this message */
4526 /* FIXME: Could optimize for local interface sends */
4527 return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority,
4528 dwTimeout, lpContext, lpdwMsgID );
4531 if( ( !bValidDestination ) &&
4532 ( ( lpGData = DP_FindAnyGroup( This, idTo ) ) != NULL )
4535 bValidDestination = TRUE;
4537 /* See if SP has the ability to multicast. If so, use it */
4538 if( This->dp2->spData.lpCB->SendToGroupEx )
4540 FIXME( "Use group sendex\n" );
4542 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4544 FIXME( "Use obsolete group send to group\n" );
4546 else /* No multicast, multiplicate */
4548 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4551 #if 0
4552 if( bExpectReply )
4554 DWORD dwWaitReturn;
4556 This->dp2->hReplyEvent = CreateEventW( NULL, FALSE, FALSE, NULL );
4558 dwWaitReturn = WaitForSingleObject( hReplyEvent, dwTimeout );
4559 if( dwWaitReturn != WAIT_OBJECT_0 )
4561 ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
4564 #endif
4567 if( !bValidDestination )
4569 return DPERR_INVALIDPLAYER;
4571 else
4573 /* FIXME: Should return what the send returned */
4574 return DP_OK;
4579 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4580 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4581 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4582 LPVOID lpContext, LPDWORD lpdwMsgID )
4584 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4585 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4586 dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE );
4589 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4590 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4591 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4592 LPVOID lpContext, LPDWORD lpdwMsgID )
4594 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4595 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4596 dwPriority, dwTimeout, lpContext, lpdwMsgID, FALSE );
4599 static HRESULT WINAPI DP_SP_SendEx
4600 ( IDirectPlay2Impl* This, DWORD dwFlags,
4601 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4602 LPVOID lpContext, LPDWORD lpdwMsgID )
4604 LPDPMSG lpMElem;
4606 FIXME( ": stub\n" );
4608 /* FIXME: This queuing should only be for async messages */
4610 lpMElem = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpMElem ) );
4611 lpMElem->msg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
4613 CopyMemory( lpMElem->msg, lpData, dwDataSize );
4615 /* FIXME: Need to queue based on priority */
4616 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
4618 return DP_OK;
4621 static HRESULT WINAPI DP_IF_GetMessageQueue
4622 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4623 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi )
4625 HRESULT hr = DP_OK;
4627 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,%p,%u): semi stub\n",
4628 This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi );
4630 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4631 /* FIXME: What about sends which are not immediate? */
4633 if( This->dp2->spData.lpCB->GetMessageQueue )
4635 DPSP_GETMESSAGEQUEUEDATA data;
4637 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4639 /* FIXME: None of this is documented :( */
4641 data.lpISP = This->dp2->spData.lpISP;
4642 data.dwFlags = dwFlags;
4643 data.idFrom = idFrom;
4644 data.idTo = idTo;
4645 data.lpdwNumMsgs = lpdwNumMsgs;
4646 data.lpdwNumBytes = lpdwNumBytes;
4648 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
4650 else
4652 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4655 return hr;
4658 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4659 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4660 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4662 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4663 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4664 lpdwNumBytes, TRUE );
4667 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4668 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4669 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4671 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4672 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4673 lpdwNumBytes, FALSE );
4676 static HRESULT WINAPI DP_IF_CancelMessage
4677 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
4678 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi )
4680 HRESULT hr = DP_OK;
4682 FIXME( "(%p)->(0x%08lx,0x%08lx,%u): semi stub\n",
4683 This, dwMsgID, dwFlags, bAnsi );
4685 if( This->dp2->spData.lpCB->Cancel )
4687 DPSP_CANCELDATA data;
4689 TRACE( "Calling SP Cancel\n" );
4691 /* FIXME: Undocumented callback */
4693 data.lpISP = This->dp2->spData.lpISP;
4694 data.dwFlags = dwFlags;
4695 data.lprglpvSPMsgID = NULL;
4696 data.cSPMsgID = dwMsgID;
4697 data.dwMinPriority = dwMinPriority;
4698 data.dwMaxPriority = dwMaxPriority;
4700 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
4702 else
4704 FIXME( "SP doesn't implement Cancel\n" );
4707 return hr;
4710 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
4711 ( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags )
4713 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4715 if( dwFlags != 0 )
4717 return DPERR_INVALIDFLAGS;
4720 if( dwMsgID == 0 )
4722 dwFlags |= DPCANCELSEND_ALL;
4725 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE );
4728 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
4729 ( LPDIRECTPLAY4 iface, DWORD dwMsgID, DWORD dwFlags )
4731 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4733 if( dwFlags != 0 )
4735 return DPERR_INVALIDFLAGS;
4738 if( dwMsgID == 0 )
4740 dwFlags |= DPCANCELSEND_ALL;
4743 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, FALSE );
4746 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
4747 ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4748 DWORD dwFlags )
4750 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4752 if( dwFlags != 0 )
4754 return DPERR_INVALIDFLAGS;
4757 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4758 dwMaxPriority, TRUE );
4761 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
4762 ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4763 DWORD dwFlags )
4765 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4767 if( dwFlags != 0 )
4769 return DPERR_INVALIDFLAGS;
4772 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4773 dwMaxPriority, FALSE );
4776 /* Note: Hack so we can reuse the old functions without compiler warnings */
4777 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4778 # define XCAST(fun) (typeof(directPlay2WVT.fun))
4779 #else
4780 # define XCAST(fun) (void*)
4781 #endif
4783 static const IDirectPlay2Vtbl directPlay2WVT =
4785 XCAST(QueryInterface)DP_QueryInterface,
4786 XCAST(AddRef)DP_AddRef,
4787 XCAST(Release)DP_Release,
4789 DirectPlay2WImpl_AddPlayerToGroup,
4790 DirectPlay2WImpl_Close,
4791 DirectPlay2WImpl_CreateGroup,
4792 DirectPlay2WImpl_CreatePlayer,
4793 DirectPlay2WImpl_DeletePlayerFromGroup,
4794 DirectPlay2WImpl_DestroyGroup,
4795 DirectPlay2WImpl_DestroyPlayer,
4796 DirectPlay2WImpl_EnumGroupPlayers,
4797 DirectPlay2WImpl_EnumGroups,
4798 DirectPlay2WImpl_EnumPlayers,
4799 DirectPlay2WImpl_EnumSessions,
4800 DirectPlay2WImpl_GetCaps,
4801 DirectPlay2WImpl_GetGroupData,
4802 DirectPlay2WImpl_GetGroupName,
4803 DirectPlay2WImpl_GetMessageCount,
4804 DirectPlay2WImpl_GetPlayerAddress,
4805 DirectPlay2WImpl_GetPlayerCaps,
4806 DirectPlay2WImpl_GetPlayerData,
4807 DirectPlay2WImpl_GetPlayerName,
4808 DirectPlay2WImpl_GetSessionDesc,
4809 DirectPlay2WImpl_Initialize,
4810 DirectPlay2WImpl_Open,
4811 DirectPlay2WImpl_Receive,
4812 DirectPlay2WImpl_Send,
4813 DirectPlay2WImpl_SetGroupData,
4814 DirectPlay2WImpl_SetGroupName,
4815 DirectPlay2WImpl_SetPlayerData,
4816 DirectPlay2WImpl_SetPlayerName,
4817 DirectPlay2WImpl_SetSessionDesc
4819 #undef XCAST
4821 /* Note: Hack so we can reuse the old functions without compiler warnings */
4822 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4823 # define XCAST(fun) (typeof(directPlay2AVT.fun))
4824 #else
4825 # define XCAST(fun) (void*)
4826 #endif
4828 static const IDirectPlay2Vtbl directPlay2AVT =
4830 XCAST(QueryInterface)DP_QueryInterface,
4831 XCAST(AddRef)DP_AddRef,
4832 XCAST(Release)DP_Release,
4834 DirectPlay2AImpl_AddPlayerToGroup,
4835 DirectPlay2AImpl_Close,
4836 DirectPlay2AImpl_CreateGroup,
4837 DirectPlay2AImpl_CreatePlayer,
4838 DirectPlay2AImpl_DeletePlayerFromGroup,
4839 DirectPlay2AImpl_DestroyGroup,
4840 DirectPlay2AImpl_DestroyPlayer,
4841 DirectPlay2AImpl_EnumGroupPlayers,
4842 DirectPlay2AImpl_EnumGroups,
4843 DirectPlay2AImpl_EnumPlayers,
4844 DirectPlay2AImpl_EnumSessions,
4845 DirectPlay2AImpl_GetCaps,
4846 DirectPlay2AImpl_GetGroupData,
4847 DirectPlay2AImpl_GetGroupName,
4848 DirectPlay2AImpl_GetMessageCount,
4849 DirectPlay2AImpl_GetPlayerAddress,
4850 DirectPlay2AImpl_GetPlayerCaps,
4851 DirectPlay2AImpl_GetPlayerData,
4852 DirectPlay2AImpl_GetPlayerName,
4853 DirectPlay2AImpl_GetSessionDesc,
4854 DirectPlay2AImpl_Initialize,
4855 DirectPlay2AImpl_Open,
4856 DirectPlay2AImpl_Receive,
4857 DirectPlay2AImpl_Send,
4858 DirectPlay2AImpl_SetGroupData,
4859 DirectPlay2AImpl_SetGroupName,
4860 DirectPlay2AImpl_SetPlayerData,
4861 DirectPlay2AImpl_SetPlayerName,
4862 DirectPlay2AImpl_SetSessionDesc
4864 #undef XCAST
4867 /* Note: Hack so we can reuse the old functions without compiler warnings */
4868 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4869 # define XCAST(fun) (typeof(directPlay3AVT.fun))
4870 #else
4871 # define XCAST(fun) (void*)
4872 #endif
4874 static const IDirectPlay3Vtbl directPlay3AVT =
4876 XCAST(QueryInterface)DP_QueryInterface,
4877 XCAST(AddRef)DP_AddRef,
4878 XCAST(Release)DP_Release,
4880 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
4881 XCAST(Close)DirectPlay2AImpl_Close,
4882 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
4883 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
4884 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
4885 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
4886 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
4887 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
4888 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
4889 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
4890 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
4891 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
4892 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
4893 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
4894 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
4895 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
4896 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
4897 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
4898 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
4899 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
4900 XCAST(Initialize)DirectPlay2AImpl_Initialize,
4901 XCAST(Open)DirectPlay2AImpl_Open,
4902 XCAST(Receive)DirectPlay2AImpl_Receive,
4903 XCAST(Send)DirectPlay2AImpl_Send,
4904 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
4905 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
4906 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
4907 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
4908 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
4910 DirectPlay3AImpl_AddGroupToGroup,
4911 DirectPlay3AImpl_CreateGroupInGroup,
4912 DirectPlay3AImpl_DeleteGroupFromGroup,
4913 DirectPlay3AImpl_EnumConnections,
4914 DirectPlay3AImpl_EnumGroupsInGroup,
4915 DirectPlay3AImpl_GetGroupConnectionSettings,
4916 DirectPlay3AImpl_InitializeConnection,
4917 DirectPlay3AImpl_SecureOpen,
4918 DirectPlay3AImpl_SendChatMessage,
4919 DirectPlay3AImpl_SetGroupConnectionSettings,
4920 DirectPlay3AImpl_StartSession,
4921 DirectPlay3AImpl_GetGroupFlags,
4922 DirectPlay3AImpl_GetGroupParent,
4923 DirectPlay3AImpl_GetPlayerAccount,
4924 DirectPlay3AImpl_GetPlayerFlags
4926 #undef XCAST
4928 /* Note: Hack so we can reuse the old functions without compiler warnings */
4929 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4930 # define XCAST(fun) (typeof(directPlay3WVT.fun))
4931 #else
4932 # define XCAST(fun) (void*)
4933 #endif
4934 static const IDirectPlay3Vtbl directPlay3WVT =
4936 XCAST(QueryInterface)DP_QueryInterface,
4937 XCAST(AddRef)DP_AddRef,
4938 XCAST(Release)DP_Release,
4940 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
4941 XCAST(Close)DirectPlay2WImpl_Close,
4942 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
4943 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
4944 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
4945 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
4946 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
4947 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
4948 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
4949 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
4950 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
4951 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
4952 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
4953 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
4954 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
4955 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
4956 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
4957 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
4958 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
4959 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
4960 XCAST(Initialize)DirectPlay2WImpl_Initialize,
4961 XCAST(Open)DirectPlay2WImpl_Open,
4962 XCAST(Receive)DirectPlay2WImpl_Receive,
4963 XCAST(Send)DirectPlay2WImpl_Send,
4964 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
4965 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
4966 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
4967 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
4968 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
4970 DirectPlay3WImpl_AddGroupToGroup,
4971 DirectPlay3WImpl_CreateGroupInGroup,
4972 DirectPlay3WImpl_DeleteGroupFromGroup,
4973 DirectPlay3WImpl_EnumConnections,
4974 DirectPlay3WImpl_EnumGroupsInGroup,
4975 DirectPlay3WImpl_GetGroupConnectionSettings,
4976 DirectPlay3WImpl_InitializeConnection,
4977 DirectPlay3WImpl_SecureOpen,
4978 DirectPlay3WImpl_SendChatMessage,
4979 DirectPlay3WImpl_SetGroupConnectionSettings,
4980 DirectPlay3WImpl_StartSession,
4981 DirectPlay3WImpl_GetGroupFlags,
4982 DirectPlay3WImpl_GetGroupParent,
4983 DirectPlay3WImpl_GetPlayerAccount,
4984 DirectPlay3WImpl_GetPlayerFlags
4986 #undef XCAST
4988 /* Note: Hack so we can reuse the old functions without compiler warnings */
4989 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4990 # define XCAST(fun) (typeof(directPlay4WVT.fun))
4991 #else
4992 # define XCAST(fun) (void*)
4993 #endif
4994 static const IDirectPlay4Vtbl directPlay4WVT =
4996 XCAST(QueryInterface)DP_QueryInterface,
4997 XCAST(AddRef)DP_AddRef,
4998 XCAST(Release)DP_Release,
5000 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
5001 XCAST(Close)DirectPlay2WImpl_Close,
5002 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
5003 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
5004 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
5005 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
5006 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5007 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5008 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5009 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5010 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5011 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5012 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5013 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5014 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5015 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5016 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5017 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5018 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5019 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5020 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5021 XCAST(Open)DirectPlay2WImpl_Open,
5022 XCAST(Receive)DirectPlay2WImpl_Receive,
5023 XCAST(Send)DirectPlay2WImpl_Send,
5024 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5025 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5026 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5027 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5028 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5030 XCAST(AddGroupToGroup)DirectPlay3WImpl_AddGroupToGroup,
5031 XCAST(CreateGroupInGroup)DirectPlay3WImpl_CreateGroupInGroup,
5032 XCAST(DeleteGroupFromGroup)DirectPlay3WImpl_DeleteGroupFromGroup,
5033 XCAST(EnumConnections)DirectPlay3WImpl_EnumConnections,
5034 XCAST(EnumGroupsInGroup)DirectPlay3WImpl_EnumGroupsInGroup,
5035 XCAST(GetGroupConnectionSettings)DirectPlay3WImpl_GetGroupConnectionSettings,
5036 XCAST(InitializeConnection)DirectPlay3WImpl_InitializeConnection,
5037 XCAST(SecureOpen)DirectPlay3WImpl_SecureOpen,
5038 XCAST(SendChatMessage)DirectPlay3WImpl_SendChatMessage,
5039 XCAST(SetGroupConnectionSettings)DirectPlay3WImpl_SetGroupConnectionSettings,
5040 XCAST(StartSession)DirectPlay3WImpl_StartSession,
5041 XCAST(GetGroupFlags)DirectPlay3WImpl_GetGroupFlags,
5042 XCAST(GetGroupParent)DirectPlay3WImpl_GetGroupParent,
5043 XCAST(GetPlayerAccount)DirectPlay3WImpl_GetPlayerAccount,
5044 XCAST(GetPlayerFlags)DirectPlay3WImpl_GetPlayerFlags,
5046 DirectPlay4WImpl_GetGroupOwner,
5047 DirectPlay4WImpl_SetGroupOwner,
5048 DirectPlay4WImpl_SendEx,
5049 DirectPlay4WImpl_GetMessageQueue,
5050 DirectPlay4WImpl_CancelMessage,
5051 DirectPlay4WImpl_CancelPriority
5053 #undef XCAST
5056 /* Note: Hack so we can reuse the old functions without compiler warnings */
5057 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5058 # define XCAST(fun) (typeof(directPlay4AVT.fun))
5059 #else
5060 # define XCAST(fun) (void*)
5061 #endif
5062 static const IDirectPlay4Vtbl directPlay4AVT =
5064 XCAST(QueryInterface)DP_QueryInterface,
5065 XCAST(AddRef)DP_AddRef,
5066 XCAST(Release)DP_Release,
5068 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
5069 XCAST(Close)DirectPlay2AImpl_Close,
5070 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
5071 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
5072 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
5073 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
5074 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
5075 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
5076 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
5077 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
5078 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
5079 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
5080 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
5081 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
5082 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5083 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5084 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5085 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5086 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5087 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5088 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5089 XCAST(Open)DirectPlay2AImpl_Open,
5090 XCAST(Receive)DirectPlay2AImpl_Receive,
5091 XCAST(Send)DirectPlay2AImpl_Send,
5092 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5093 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5094 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5095 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5096 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5098 XCAST(AddGroupToGroup)DirectPlay3AImpl_AddGroupToGroup,
5099 XCAST(CreateGroupInGroup)DirectPlay3AImpl_CreateGroupInGroup,
5100 XCAST(DeleteGroupFromGroup)DirectPlay3AImpl_DeleteGroupFromGroup,
5101 XCAST(EnumConnections)DirectPlay3AImpl_EnumConnections,
5102 XCAST(EnumGroupsInGroup)DirectPlay3AImpl_EnumGroupsInGroup,
5103 XCAST(GetGroupConnectionSettings)DirectPlay3AImpl_GetGroupConnectionSettings,
5104 XCAST(InitializeConnection)DirectPlay3AImpl_InitializeConnection,
5105 XCAST(SecureOpen)DirectPlay3AImpl_SecureOpen,
5106 XCAST(SendChatMessage)DirectPlay3AImpl_SendChatMessage,
5107 XCAST(SetGroupConnectionSettings)DirectPlay3AImpl_SetGroupConnectionSettings,
5108 XCAST(StartSession)DirectPlay3AImpl_StartSession,
5109 XCAST(GetGroupFlags)DirectPlay3AImpl_GetGroupFlags,
5110 XCAST(GetGroupParent)DirectPlay3AImpl_GetGroupParent,
5111 XCAST(GetPlayerAccount)DirectPlay3AImpl_GetPlayerAccount,
5112 XCAST(GetPlayerFlags)DirectPlay3AImpl_GetPlayerFlags,
5114 DirectPlay4AImpl_GetGroupOwner,
5115 DirectPlay4AImpl_SetGroupOwner,
5116 DirectPlay4AImpl_SendEx,
5117 DirectPlay4AImpl_GetMessageQueue,
5118 DirectPlay4AImpl_CancelMessage,
5119 DirectPlay4AImpl_CancelPriority
5121 #undef XCAST
5123 extern
5124 HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP,
5125 DPID idPlayer,
5126 LPVOID* lplpData )
5128 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5130 if( lpPlayer == NULL )
5132 return DPERR_INVALIDPLAYER;
5135 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
5137 return DP_OK;
5140 extern
5141 HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP,
5142 DPID idPlayer,
5143 LPVOID lpData )
5145 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5147 if( lpPlayer == NULL )
5149 return DPERR_INVALIDPLAYER;
5152 lpPlayer->lpPData->lpSPPlayerData = lpData;
5154 return DP_OK;
5157 /***************************************************************************
5158 * DirectPlayEnumerateAW
5160 * The pointer to the structure lpContext will be filled with the
5161 * appropriate data for each service offered by the OS. These services are
5162 * not necessarily available on this particular machine but are defined
5163 * as simple service providers under the "Service Providers" registry key.
5164 * This structure is then passed to lpEnumCallback for each of the different
5165 * services.
5167 * This API is useful only for applications written using DirectX3 or
5168 * worse. It is superseded by IDirectPlay3::EnumConnections which also
5169 * gives information on the actual connections.
5171 * defn of a service provider:
5172 * A dynamic-link library used by DirectPlay to communicate over a network.
5173 * The service provider contains all the network-specific code required
5174 * to send and receive messages. Online services and network operators can
5175 * supply service providers to use specialized hardware, protocols, communications
5176 * media, and network resources.
5179 static HRESULT DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA,
5180 LPDPENUMDPCALLBACKW lpEnumCallbackW,
5181 LPVOID lpContext)
5183 HKEY hkResult;
5184 static const WCHAR searchSubKey[] = {
5185 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
5186 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
5187 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
5188 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
5189 static const WCHAR guidKey[] = { 'G', 'u', 'i', 'd', 0 };
5190 static const WCHAR descW[] = { 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', 'W', 0 };
5192 DWORD dwIndex;
5193 FILETIME filetime;
5195 char *descriptionA = NULL;
5196 DWORD max_sizeOfDescriptionA = 0;
5197 WCHAR *descriptionW = NULL;
5198 DWORD max_sizeOfDescriptionW = 0;
5200 if (!lpEnumCallbackA && !lpEnumCallbackW)
5202 return DPERR_INVALIDPARAMS;
5205 /* Need to loop over the service providers in the registry */
5206 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, searchSubKey,
5207 0, KEY_READ, &hkResult) != ERROR_SUCCESS)
5209 /* Hmmm. Does this mean that there are no service providers? */
5210 ERR(": no service provider key in the registry - check your Wine installation !!!\n");
5211 return DPERR_GENERIC;
5214 /* Traverse all the service providers we have available */
5215 dwIndex = 0;
5216 while (1)
5218 WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */
5219 DWORD sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR);
5220 HKEY hkServiceProvider;
5221 GUID serviceProviderGUID;
5222 WCHAR guidKeyContent[(2 * 16) + 1 + 6 /* This corresponds to '{....-..-..-..-......}' */ ];
5223 DWORD sizeOfGuidKeyContent = sizeof(guidKeyContent);
5224 LONG ret_value;
5226 ret_value = RegEnumKeyExW(hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
5227 NULL, NULL, NULL, &filetime);
5228 if (ret_value == ERROR_NO_MORE_ITEMS)
5229 break;
5230 else if (ret_value != ERROR_SUCCESS)
5232 ERR(": could not enumerate on service provider key.\n");
5233 return DPERR_EXCEPTION;
5235 TRACE(" this time through sub-key %s.\n", debugstr_w(subKeyName));
5237 /* Open the key for this service provider */
5238 if (RegOpenKeyExW(hkResult, subKeyName, 0, KEY_READ, &hkServiceProvider) != ERROR_SUCCESS)
5240 ERR(": could not open registry key for service provider %s.\n", debugstr_w(subKeyName));
5241 continue;
5244 /* Get the GUID from the registry */
5245 if (RegQueryValueExW(hkServiceProvider, guidKey,
5246 NULL, NULL, (LPBYTE) guidKeyContent, &sizeOfGuidKeyContent) != ERROR_SUCCESS)
5248 ERR(": missing GUID registry data member for service provider %s.\n", debugstr_w(subKeyName));
5249 continue;
5251 if (sizeOfGuidKeyContent != sizeof(guidKeyContent))
5253 ERR(": invalid format for the GUID registry data member for service provider %s (%s).\n", debugstr_w(subKeyName), debugstr_w(guidKeyContent));
5254 continue;
5256 CLSIDFromString(guidKeyContent, &serviceProviderGUID );
5258 /* The enumeration will return FALSE if we are not to continue.
5260 * Note: on my windows box, major / minor version is 6 / 0 for all service providers
5261 * and have no relations to any of the two dwReserved1 and dwReserved2 keys.
5262 * I think that it simply means that they are in-line with DirectX 6.0
5264 if (lpEnumCallbackA)
5266 DWORD sizeOfDescription = 0;
5268 /* Note that this the the A case of this function, so use the A variant to get the description string */
5269 if (RegQueryValueExA(hkServiceProvider, "DescriptionA",
5270 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5272 ERR(": missing 'DescriptionA' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5273 continue;
5275 if (sizeOfDescription > max_sizeOfDescriptionA)
5277 HeapFree(GetProcessHeap(), 0, descriptionA);
5278 max_sizeOfDescriptionA = sizeOfDescription;
5279 descriptionA = HeapAlloc(GetProcessHeap(), 0, max_sizeOfDescriptionA);
5281 descriptionA = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5282 RegQueryValueExA(hkServiceProvider, "DescriptionA",
5283 NULL, NULL, (LPBYTE) descriptionA, &sizeOfDescription);
5285 if (!lpEnumCallbackA(&serviceProviderGUID, descriptionA, 6, 0, lpContext))
5286 goto end;
5288 else
5290 DWORD sizeOfDescription = 0;
5292 if (RegQueryValueExW(hkServiceProvider, descW,
5293 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5295 ERR(": missing 'DescriptionW' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5296 continue;
5298 if (sizeOfDescription > max_sizeOfDescriptionW)
5300 HeapFree(GetProcessHeap(), 0, descriptionW);
5301 max_sizeOfDescriptionW = sizeOfDescription;
5302 descriptionW = HeapAlloc(GetProcessHeap(), 0, max_sizeOfDescriptionW);
5304 descriptionW = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5305 RegQueryValueExW(hkServiceProvider, descW,
5306 NULL, NULL, (LPBYTE) descriptionW, &sizeOfDescription);
5308 if (!lpEnumCallbackW(&serviceProviderGUID, descriptionW, 6, 0, lpContext))
5309 goto end;
5312 dwIndex++;
5315 end:
5316 HeapFree(GetProcessHeap(), 0, descriptionA);
5317 HeapFree(GetProcessHeap(), 0, descriptionW);
5319 return DP_OK;
5322 /***************************************************************************
5323 * DirectPlayEnumerate [DPLAYX.9]
5324 * DirectPlayEnumerateA [DPLAYX.2]
5326 HRESULT WINAPI DirectPlayEnumerateA(LPDPENUMDPCALLBACKA lpEnumCallback, LPVOID lpContext )
5328 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5330 return DirectPlayEnumerateAW(lpEnumCallback, NULL, lpContext);
5333 /***************************************************************************
5334 * DirectPlayEnumerateW [DPLAYX.3]
5336 HRESULT WINAPI DirectPlayEnumerateW(LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5338 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5340 return DirectPlayEnumerateAW(NULL, lpEnumCallback, lpContext);
5343 typedef struct tagCreateEnum
5345 LPVOID lpConn;
5346 LPCGUID lpGuid;
5347 } CreateEnumData, *lpCreateEnumData;
5349 /* Find and copy the matching connection for the SP guid */
5350 static BOOL CALLBACK cbDPCreateEnumConnections(
5351 LPCGUID lpguidSP,
5352 LPVOID lpConnection,
5353 DWORD dwConnectionSize,
5354 LPCDPNAME lpName,
5355 DWORD dwFlags,
5356 LPVOID lpContext)
5358 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5360 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5362 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5364 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5365 dwConnectionSize );
5366 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5368 /* Found the record that we were looking for */
5369 return FALSE;
5372 /* Haven't found what were looking for yet */
5373 return TRUE;
5377 /***************************************************************************
5378 * DirectPlayCreate [DPLAYX.1]
5381 HRESULT WINAPI DirectPlayCreate
5382 ( LPGUID lpGUID, LPDIRECTPLAY2 *lplpDP, IUnknown *pUnk)
5384 HRESULT hr;
5385 LPDIRECTPLAY3A lpDP3A;
5386 CreateEnumData cbData;
5388 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5390 if( pUnk != NULL )
5392 return CLASS_E_NOAGGREGATION;
5395 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5396 give them an IDirectPlay2A object and hope that doesn't cause problems */
5397 if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
5399 return DPERR_UNAVAILABLE;
5402 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
5404 /* The GUID_NULL means don't bind a service provider. Just return the
5405 interface as is */
5406 return DP_OK;
5409 /* Bind the desired service provider since lpGUID is non NULL */
5410 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
5412 /* We're going to use a DP3 interface */
5413 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
5414 (LPVOID*)&lpDP3A );
5415 if( FAILED(hr) )
5417 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
5418 return hr;
5421 cbData.lpConn = NULL;
5422 cbData.lpGuid = lpGUID;
5424 /* We were given a service provider, find info about it... */
5425 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
5426 &cbData, DPCONNECTION_DIRECTPLAY );
5427 if( ( FAILED(hr) ) ||
5428 ( cbData.lpConn == NULL )
5431 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
5432 IDirectPlayX_Release( lpDP3A );
5433 return DPERR_UNAVAILABLE;
5436 /* Initialize the service provider */
5437 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
5438 if( FAILED(hr) )
5440 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
5441 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5442 IDirectPlayX_Release( lpDP3A );
5443 return hr;
5446 /* Release our version of the interface now that we're done with it */
5447 IDirectPlayX_Release( lpDP3A );
5448 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5450 return DP_OK;