dplayx: System players are the ones who must not be listed
[wine/gsoc_dplay.git] / dlls / dplayx / dplay.c
blobbf49d8f9ecb3dfe0b8789e35257014ab17e80171
1 /* Direct Play 2,3,4 Implementation
3 * Copyright 1998,1999,2000,2001 - Peter Hunnisett
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "config.h"
21 #include "wine/port.h"
23 #include <stdarg.h>
24 #include <string.h>
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
28 #include "windef.h"
29 #include "winerror.h"
30 #include "winbase.h"
31 #include "winnt.h"
32 #include "winreg.h"
33 #include "winnls.h"
34 #include "wine/unicode.h"
35 #include "wine/debug.h"
37 #include "dpinit.h"
38 #include "dplayx_global.h"
39 #include "name_server.h"
40 #include "dplayx_queue.h"
41 #include "wine/dplaysp.h"
42 #include "dplay_global.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(dplay);
46 /* FIXME: Should this be externed? */
47 extern HRESULT DPL_CreateCompoundAddress
48 ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
49 LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
52 /* Local function prototypes */
53 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, const DPNAME *lpSrc, BOOL bAnsi );
54 static void DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
55 LPVOID lpData, DWORD dwDataSize );
57 static lpGroupData DP_CreateGroup( IDirectPlay2AImpl* iface, const DPID *lpid,
58 const DPNAME *lpName, DWORD dwFlags,
59 DPID idParent, BOOL bAnsi );
60 static void DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
61 LPVOID lpData, DWORD dwDataSize );
62 static void DP_DeleteDPNameStruct( LPDPNAME lpDPName );
63 static void DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid );
64 static BOOL CALLBACK cbDeletePlayerFromAllGroups( DPID dpId,
65 DWORD dwPlayerType,
66 LPCDPNAME lpName,
67 DWORD dwFlags,
68 LPVOID lpContext );
69 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid );
70 static BOOL CALLBACK cbRemoveGroupOrPlayer( DPID dpId, DWORD dwPlayerType,
71 LPCDPNAME lpName, DWORD dwFlags,
72 LPVOID lpContext );
73 static void DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid );
75 /* Forward declarations of virtual tables */
76 static const IDirectPlay2Vtbl directPlay2AVT;
77 static const IDirectPlay3Vtbl directPlay3AVT;
78 static const IDirectPlay4Vtbl directPlay4AVT;
80 static const IDirectPlay2Vtbl directPlay2WVT;
81 static const IDirectPlay3Vtbl directPlay3WVT;
82 static const IDirectPlay4Vtbl directPlay4WVT;
84 /* Helper methods for player/group interfaces */
85 static HRESULT DP_IF_DeletePlayerFromGroup
86 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
87 DPID idPlayer, BOOL bAnsi );
88 static HRESULT DP_IF_CreatePlayer
89 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, LPDPID lpidPlayer,
90 LPDPNAME lpPlayerName, HANDLE hEvent, LPVOID lpData,
91 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
92 static HRESULT DP_IF_DestroyGroup
93 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi );
94 static HRESULT DP_IF_DestroyPlayer
95 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi );
96 static HRESULT DP_IF_EnumGroupPlayers
97 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
98 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
99 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
100 static HRESULT DP_IF_EnumGroups
101 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
102 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
103 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
104 static HRESULT DP_IF_EnumPlayers
105 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
106 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
107 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
108 static HRESULT DP_IF_GetGroupData
109 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
110 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
111 static HRESULT DP_IF_GetGroupName
112 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
113 LPDWORD lpdwDataSize, BOOL bAnsi );
114 static HRESULT DP_IF_GetPlayerData
115 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
116 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
117 static HRESULT DP_IF_GetPlayerName
118 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
119 LPDWORD lpdwDataSize, BOOL bAnsi );
120 static HRESULT DP_IF_SetGroupName
121 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
122 DWORD dwFlags, BOOL bAnsi );
123 static HRESULT DP_IF_SetPlayerData
124 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
125 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
126 static HRESULT DP_IF_SetPlayerName
127 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
128 DWORD dwFlags, BOOL bAnsi );
129 static HRESULT DP_IF_AddGroupToGroup
130 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
131 static HRESULT DP_IF_CreateGroup
132 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
133 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
134 DWORD dwFlags, BOOL bAnsi );
135 static HRESULT DP_IF_CreateGroupInGroup
136 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
137 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
138 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
139 static HRESULT DP_IF_AddPlayerToGroup
140 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
141 DPID idPlayer, BOOL bAnsi );
142 static HRESULT DP_IF_DeleteGroupFromGroup
143 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
144 static HRESULT DP_SecureOpen
145 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
146 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
147 BOOL bAnsi );
148 static HRESULT DP_SendEx
149 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
150 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
151 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi );
152 static HRESULT DP_IF_Receive
153 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
154 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi );
155 static HRESULT DP_IF_GetMessageQueue
156 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
157 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi );
158 static HRESULT DP_SP_SendEx
159 ( IDirectPlay2Impl* This, DWORD dwFlags,
160 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
161 LPVOID lpContext, LPDWORD lpdwMsgID );
162 static HRESULT DP_IF_SetGroupData
163 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
164 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
165 static HRESULT DP_IF_GetPlayerCaps
166 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
167 DWORD dwFlags );
168 static HRESULT DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi );
169 static HRESULT DP_IF_CancelMessage
170 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
171 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi );
172 static HRESULT DP_IF_EnumGroupsInGroup
173 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
174 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
175 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
176 static HRESULT DP_IF_GetGroupParent
177 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
178 BOOL bAnsi );
179 static HRESULT DP_IF_GetCaps
180 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags );
181 static HRESULT DP_IF_EnumSessions
182 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
183 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
184 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
185 static HRESULT DP_IF_InitializeConnection
186 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi );
187 static BOOL CALLBACK cbDPCreateEnumConnections( LPCGUID lpguidSP,
188 LPVOID lpConnection, DWORD dwConnectionSize, LPCDPNAME lpName,
189 DWORD dwFlags, LPVOID lpContext );
190 static BOOL DP_BuildCompoundAddr( GUID guidDataType, LPGUID lpcSpGuid,
191 LPVOID* lplpAddrBuf, LPDWORD lpdwBufSize );
195 static inline DPID DP_NextObjectId(void);
196 static DPID DP_GetRemoteNextObjectId(void);
198 static DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi );
199 static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc,
200 LPCDPSESSIONDESC2 srcSessDesc, BOOL bAnsi );
203 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp );
204 static HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider );
205 static HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hServiceProvider );
212 #define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */
213 #define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported
214 we don't have to change much */
215 #define DPID_NAME_SERVER 0x19a9d65b /* Don't ask me why */
217 /* Strip out dwFlag values which cannot be sent in the CREATEGROUP msg */
218 #define DPMSG_CREATEGROUP_DWFLAGS(x) ( (x) & DPGROUP_HIDDEN )
220 /* Strip out all dwFlags values for CREATEPLAYER msg */
221 #define DPMSG_CREATEPLAYER_DWFLAGS(x) 0
223 static LONG kludgePlayerGroupId = 1000;
225 /* ------------------------------------------------------------------ */
228 static BOOL DP_CreateIUnknown( LPVOID lpDP )
230 IDirectPlay2AImpl *This = lpDP;
232 This->unk = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->unk) ) );
233 if ( This->unk == NULL )
235 return FALSE;
238 InitializeCriticalSection( &This->unk->DP_lock );
239 This->unk->DP_lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectPlay2AImpl*->DirectPlayIUnknownData*->DP_lock");
241 return TRUE;
244 static BOOL DP_DestroyIUnknown( LPVOID lpDP )
246 IDirectPlay2AImpl *This = lpDP;
248 This->unk->DP_lock.DebugInfo->Spare[0] = 0;
249 DeleteCriticalSection( &This->unk->DP_lock );
250 HeapFree( GetProcessHeap(), 0, This->unk );
252 return TRUE;
255 static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
257 IDirectPlay2AImpl *This = lpDP;
259 This->dp2 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp2) ) );
260 if ( This->dp2 == NULL )
262 return FALSE;
265 This->dp2->bConnectionOpen = FALSE;
267 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
268 This->dp2->dwEnumSessionLock = 0;
270 This->dp2->bHostInterface = FALSE;
272 DPQ_INIT(This->dp2->receiveMsgs);
273 DPQ_INIT(This->dp2->sendMsgs);
274 DPQ_INIT(This->dp2->replysExpected);
276 if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
278 /* FIXME: Memory leak */
279 return FALSE;
282 /* Provide an initial session desc with nothing in it */
283 This->dp2->lpSessionDesc = HeapAlloc( GetProcessHeap(),
284 HEAP_ZERO_MEMORY,
285 sizeof( *This->dp2->lpSessionDesc ) );
286 if( This->dp2->lpSessionDesc == NULL )
288 /* FIXME: Memory leak */
289 return FALSE;
291 This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc );
293 /* We are emulating a dp 6 implementation */
294 This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION;
296 This->dp2->spData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
297 sizeof( *This->dp2->spData.lpCB ) );
298 This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB );
299 This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION;
301 /* This is the pointer to the service provider */
302 if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP,
303 (LPVOID*)&This->dp2->spData.lpISP, This ) )
306 /* FIXME: Memory leak */
307 return FALSE;
310 /* Setup lobby provider information */
311 This->dp2->dplspData.dwSPVersion = DPSP_MAJORVERSION;
312 This->dp2->dplspData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
313 sizeof( *This->dp2->dplspData.lpCB ) );
314 This->dp2->dplspData.lpCB->dwSize = sizeof( *This->dp2->dplspData.lpCB );
316 if( FAILED( DPLSP_CreateInterface( &IID_IDPLobbySP,
317 (LPVOID*)&This->dp2->dplspData.lpISP, This ) )
320 /* FIXME: Memory leak */
321 return FALSE;
324 return TRUE;
327 /* Definition of the global function in dplayx_queue.h. #
328 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
329 DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
331 HeapFree( GetProcessHeap(), 0, elem );
334 static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
336 IDirectPlay2AImpl *This = lpDP;
338 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
340 TerminateThread( This->dp2->hEnumSessionThread, 0 );
341 CloseHandle( This->dp2->hEnumSessionThread );
344 /* Finish with the SP - have it shutdown */
345 if( This->dp2->spData.lpCB->ShutdownEx )
347 DPSP_SHUTDOWNDATA data;
349 TRACE( "Calling SP ShutdownEx\n" );
351 data.lpISP = This->dp2->spData.lpISP;
353 (*This->dp2->spData.lpCB->ShutdownEx)( &data );
355 else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
357 TRACE( "Calling obsolete SP Shutdown\n" );
358 (*This->dp2->spData.lpCB->Shutdown)();
361 /* Unload the SP (if it exists) */
362 if( This->dp2->hServiceProvider != 0 )
364 FreeLibrary( This->dp2->hServiceProvider );
367 /* Unload the Lobby Provider (if it exists) */
368 if( This->dp2->hDPLobbyProvider != 0 )
370 FreeLibrary( This->dp2->hDPLobbyProvider );
373 /* FIXME: Need to delete receive and send msgs queue contents */
375 NS_DeleteSessionCache( This->dp2->lpNameServerData );
377 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
379 IDirectPlaySP_Release( This->dp2->spData.lpISP );
381 /* Delete the contents */
382 HeapFree( GetProcessHeap(), 0, This->dp2 );
384 return TRUE;
387 static BOOL DP_CreateDirectPlay3( LPVOID lpDP )
389 IDirectPlay3AImpl *This = lpDP;
391 This->dp3 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp3) ) );
392 if ( This->dp3 == NULL )
394 return FALSE;
397 return TRUE;
400 static BOOL DP_DestroyDirectPlay3( LPVOID lpDP )
402 IDirectPlay3AImpl *This = lpDP;
404 /* Delete the contents */
405 HeapFree( GetProcessHeap(), 0, This->dp3 );
407 return TRUE;
410 static BOOL DP_CreateDirectPlay4( LPVOID lpDP )
412 IDirectPlay4AImpl *This = lpDP;
414 This->dp4 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp4) ) );
415 if ( This->dp4 == NULL )
417 return FALSE;
420 return TRUE;
423 static BOOL DP_DestroyDirectPlay4( LPVOID lpDP )
425 IDirectPlay3AImpl *This = lpDP;
427 /* Delete the contents */
428 HeapFree( GetProcessHeap(), 0, This->dp4 );
430 return TRUE;
434 /* Create a new interface */
435 HRESULT DP_CreateInterface
436 ( REFIID riid, LPVOID* ppvObj )
438 TRACE( " for %s\n", debugstr_guid( riid ) );
440 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
441 sizeof( IDirectPlay2Impl ) );
443 if( *ppvObj == NULL )
445 return DPERR_OUTOFMEMORY;
448 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
450 IDirectPlay2Impl *This = *ppvObj;
451 This->lpVtbl = &directPlay2WVT;
453 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
455 IDirectPlay2AImpl *This = *ppvObj;
456 This->lpVtbl = &directPlay2AVT;
458 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
460 IDirectPlay3Impl *This = *ppvObj;
461 This->lpVtbl = &directPlay3WVT;
463 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
465 IDirectPlay3AImpl *This = *ppvObj;
466 This->lpVtbl = &directPlay3AVT;
468 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
470 IDirectPlay4Impl *This = *ppvObj;
471 This->lpVtbl = &directPlay4WVT;
473 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
475 IDirectPlay4AImpl *This = *ppvObj;
476 This->lpVtbl = &directPlay4AVT;
478 else
480 /* Unsupported interface */
481 HeapFree( GetProcessHeap(), 0, *ppvObj );
482 *ppvObj = NULL;
484 return E_NOINTERFACE;
487 /* Initialize it */
488 if ( DP_CreateIUnknown( *ppvObj ) &&
489 DP_CreateDirectPlay2( *ppvObj ) &&
490 DP_CreateDirectPlay3( *ppvObj ) &&
491 DP_CreateDirectPlay4( *ppvObj )
494 IDirectPlayX_AddRef( (LPDIRECTPLAY2A)*ppvObj );
496 return S_OK;
499 /* Initialize failed, destroy it */
500 DP_DestroyDirectPlay4( *ppvObj );
501 DP_DestroyDirectPlay3( *ppvObj );
502 DP_DestroyDirectPlay2( *ppvObj );
503 DP_DestroyIUnknown( *ppvObj );
505 HeapFree( GetProcessHeap(), 0, *ppvObj );
507 *ppvObj = NULL;
508 return DPERR_NOMEMORY;
512 /* Direct Play methods */
514 /* Shared between all dplay types */
515 static HRESULT WINAPI DP_QueryInterface
516 ( LPDIRECTPLAY2 iface, REFIID riid, LPVOID* ppvObj )
518 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
519 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
521 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
522 sizeof( *This ) );
524 if( *ppvObj == NULL )
526 return DPERR_OUTOFMEMORY;
529 CopyMemory( *ppvObj, This, sizeof( *This ) );
530 (*(IDirectPlay2Impl**)ppvObj)->ulInterfaceRef = 0;
532 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
534 IDirectPlay2Impl *This = *ppvObj;
535 This->lpVtbl = &directPlay2WVT;
537 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
539 IDirectPlay2AImpl *This = *ppvObj;
540 This->lpVtbl = &directPlay2AVT;
542 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
544 IDirectPlay3Impl *This = *ppvObj;
545 This->lpVtbl = &directPlay3WVT;
547 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
549 IDirectPlay3AImpl *This = *ppvObj;
550 This->lpVtbl = &directPlay3AVT;
552 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
554 IDirectPlay4Impl *This = *ppvObj;
555 This->lpVtbl = &directPlay4WVT;
557 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
559 IDirectPlay4AImpl *This = *ppvObj;
560 This->lpVtbl = &directPlay4AVT;
562 else
564 /* Unsupported interface */
565 HeapFree( GetProcessHeap(), 0, *ppvObj );
566 *ppvObj = NULL;
568 return E_NOINTERFACE;
571 IDirectPlayX_AddRef( (LPDIRECTPLAY2)*ppvObj );
573 return S_OK;
576 /* Shared between all dplay types */
577 static ULONG WINAPI DP_AddRef
578 ( LPDIRECTPLAY3 iface )
580 ULONG ulInterfaceRefCount, ulObjRefCount;
581 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
583 ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
584 ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
586 TRACE( "ref count incremented to %u:%u for %p\n",
587 ulInterfaceRefCount, ulObjRefCount, This );
589 return ulObjRefCount;
592 static ULONG WINAPI DP_Release
593 ( LPDIRECTPLAY3 iface )
595 ULONG ulInterfaceRefCount, ulObjRefCount;
597 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
599 ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
600 ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
602 TRACE( "ref count decremented to %u:%u for %p\n",
603 ulInterfaceRefCount, ulObjRefCount, This );
605 /* Deallocate if this is the last reference to the object */
606 if( ulObjRefCount == 0 )
608 /* If we're destroying the object, this must be the last ref
609 of the last interface */
610 DP_DestroyDirectPlay4( This );
611 DP_DestroyDirectPlay3( This );
612 DP_DestroyDirectPlay2( This );
613 DP_DestroyIUnknown( This );
616 /* Deallocate the interface */
617 if( ulInterfaceRefCount == 0 )
619 HeapFree( GetProcessHeap(), 0, This );
622 return ulObjRefCount;
625 static inline DPID DP_NextObjectId(void)
627 return (DPID)InterlockedIncrement( &kludgePlayerGroupId );
630 /* *lplpReply will be non NULL iff there is something to reply */
631 HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpcMessageBody,
632 DWORD dwMessageBodySize, LPCVOID lpcMessageHeader,
633 WORD wCommandId, WORD wVersion,
634 LPVOID* lplpReply, LPDWORD lpdwMsgSize )
636 TRACE( "(%p)->(%p,0x%08x,%p,0x%x,%u)\n",
637 This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId,
638 wVersion );
640 switch( wCommandId )
642 /* Name server needs to handle this request */
643 case DPMSGCMD_ENUMSESSIONS:
645 /* Reply expected */
646 NS_ReplyToEnumSessionsRequest( lpcMessageBody, lplpReply, lpdwMsgSize, This );
648 break;
651 /* Name server needs to handle this request */
652 case DPMSGCMD_ENUMSESSIONSREPLY:
654 /* No reply expected */
655 NS_AddRemoteComputerAsNameServer( lpcMessageHeader,
656 This->dp2->spData.dwSPHeaderSize,
657 lpcMessageBody,
658 This->dp2->lpNameServerData );
659 break;
662 case DPMSGCMD_REQUESTPLAYERID:
664 LPDPSP_MSG_REQUESTPLAYERID lpcMsg = lpcMessageBody;
665 LPDPSP_MSG_REQUESTPLAYERREPLY lpReply;
667 *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
669 *lplpReply = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, *lpdwMsgSize );
671 lpReply = (LPDPSP_MSG_REQUESTPLAYERREPLY)( (LPBYTE)(*lplpReply) +
672 This->dp2->spData.dwSPHeaderSize );
674 lpReply->envelope.dwMagic = DPMSG_SIGNATURE;
675 lpReply->envelope.wCommandId = DPMSGCMD_REQUESTPLAYERREPLY;
676 lpReply->envelope.wVersion = DX61AVERSION;
678 if ( lpcMsg->Flags & DPLAYI_PLAYER_SYSPLAYER )
680 /* Request to join the game */
682 if ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_SECURESERVER )
684 FIXME( "Fill lpReply->SecDesc with Game->SSPIProvider\n" );
686 FIXME( "Fill lpReply->CAPIProvider with Game->CAPIProvider\n" );
687 FIXME( "Fill lpReply->SecDesc->dwEncryptionAlgorithm with Game->EncryptionAlgorithm\n" );
689 /* Player is not local anymore */
690 lpcMsg->Flags ^= DPLAYI_PLAYER_PLAYERLOCAL;
692 lpReply->ID = DP_NextObjectId();
693 lpReply->Result = DP_IF_CreatePlayer( This, lpcMessageHeader,
694 &lpReply->ID, NULL, 0, NULL, 0,
695 lpcMsg->Flags, TRUE/*TODO*/ );
696 lpReply->Result = S_OK;
698 else
700 /* Request to to add a normal player from an
701 * existing member of the session */
703 if ( ( This->dp2->lpSessionDesc->dwCurrentPlayers
704 == This->dp2->lpSessionDesc->dwMaxPlayers ) ||
705 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_NEWPLAYERSDISABLED ) )
707 lpReply->Result = DPERR_NONEWPLAYERS;
709 else
711 lpReply->ID = DP_NextObjectId();
712 lpReply->Result = S_OK;
716 break;
719 case DPMSGCMD_CREATEPLAYER:
721 LPDPSP_MSG_CREATEPLAYER lpcMsg = lpcMessageBody;
722 LPDPLAYI_PACKEDPLAYER lpPackedPlayer =
723 (LPDPLAYI_PACKEDPLAYER)(((LPBYTE) lpcMsg) + lpcMsg->CreateOffset);
724 PACKEDPLAYERDATA packedPlayerData;
726 DP_MSG_ParsePackedPlayer( This,
727 (LPBYTE) lpPackedPlayer,
728 &packedPlayerData,
729 FALSE,
730 TRUE/*TODO*/ );
732 return DP_CreatePlayer( This, lpPackedPlayer->PlayerID,
733 &packedPlayerData.name,
734 lpPackedPlayer->Flags,
735 packedPlayerData.lpPlayerData,
736 packedPlayerData.dwPlayerDataSize,
737 NULL, TRUE/*TODO*/, NULL );
739 /* TODO send msg to upper layer */
740 break;
743 case DPMSGCMD_PACKET:
745 LPCDPSP_MSG_PACKET lpcMsg = lpcMessageBody;
746 LPDPSP_MSG_ENVELOPE packetData;
748 /* TODO: We have to wait for all the messages in the sequence and
749 * assemble them in a bigger message. */
750 if ( lpcMsg->TotalPackets > 1 )
752 FIXME( "TODO: Message belongs to a sequence of %d, implement assembly\n",
753 lpcMsg->TotalPackets );
754 return DPERR_GENERIC;
757 /* For now, for simplicity we'll just decapsulate the embedded
758 * message and work with it. */
759 packetData = (LPVOID)(lpcMsg + 1);
761 TRACE( "Processing embedded message with envelope (0x%08x, 0x%08x, %d)\n",
762 packetData->dwMagic, packetData->wCommandId, packetData->wVersion );
764 return DP_HandleMessage( This,
765 packetData,
766 lpcMsg->DataSize,
767 lpcMessageHeader,
768 packetData->wCommandId,
769 packetData->wVersion,
770 lplpReply, lpdwMsgSize );
771 break;
774 case DPMSGCMD_REQUESTPLAYERREPLY:
776 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageHeader,
777 lpcMessageBody, dwMessageBodySize );
778 break;
781 case DPMSGCMD_ADDFORWARDREQUEST:
783 /*LPCDPSP_MSG_ADDFORWARDREQUEST lpcMsg =
784 (LPCDPSP_MSG_ADDFORWARDREQUEST) lpcMessageBody;*/
786 /* TODO: Send ADDFORWARD messages to all the players to populate
787 * their name tables.
788 * Start NametablePopulation timer and wait for ADDFORWARDACKs */
789 FIXME( "Spread name table population messages\n" );
791 /* TODO remember to set local addr somewhere */
792 /* call NS_SetLocalAddr with a SOCKADDR_IN */
794 FIXME( "This should happen after we received all the DPMSGCMD_ADDFORWARDACKs\n" );
795 DP_MSG_ReplyToEnumPlayersRequest( This, lplpReply, lpdwMsgSize );
797 break;
800 case DPMSGCMD_ADDFORWARDREPLY:
802 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageHeader,
803 lpcMessageBody, dwMessageBodySize );
804 break;
807 case DPMSGCMD_ENUMPLAYERSREPLY:
808 case DPMSGCMD_SUPERENUMPLAYERSREPLY:
810 /* If we're joining a session, when we receive this
811 * command we were waiting for a ADDFORWARDREPLY */
812 if ( !DP_MSG_ReplyReceived( This, DPMSGCMD_ADDFORWARDREPLY,
813 lpcMessageHeader, lpcMessageBody,
814 dwMessageBodySize ) )
816 /* If we were not joining a session, check if we are
817 * waiting for an enumeration of players or groups */
818 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageHeader,
819 lpcMessageBody, dwMessageBodySize );
821 break;
824 case DPMSGCMD_ADDFORWARDACK:
826 /* When we receive an ADDFORWARDACK for each of the ADDFORWARDs
827 * we've sent, send a SUPERENUMPLAYERSREPLY back to the peer
828 * that sent the ADDFORWARDREQUEST */
829 /* TODO: We'll skip this for now and just send the SUPERENUMPLAYERSREPLY
830 * right away when we get a ADDFORWARDREQUEST */
831 break;
834 default:
836 FIXME( "Unknown wCommandId 0x%08x. Ignoring message\n", wCommandId );
837 return DPERR_GENERIC;
841 return DP_OK;
845 static HRESULT DP_IF_AddPlayerToGroup
846 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
847 DPID idPlayer, BOOL bAnsi )
849 lpGroupData lpGData;
850 lpPlayerList lpPList;
851 lpPlayerList lpNewPList;
853 TRACE( "(%p)->(%p,0x%08x,0x%08x,%u)\n",
854 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
856 if( This->dp2->connectionInitialized == NO_PROVIDER )
858 return DPERR_UNINITIALIZED;
861 /* Find the group */
862 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
864 return DPERR_INVALIDGROUP;
867 /* Find the player */
868 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
870 return DPERR_INVALIDPLAYER;
873 /* Create a player list (ie "shortcut" ) */
874 lpNewPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewPList ) );
875 if( lpNewPList == NULL )
877 return DPERR_CANTADDPLAYER;
880 /* Add the shortcut */
881 lpPList->lpPData->uRef++;
882 lpNewPList->lpPData = lpPList->lpPData;
884 /* Add the player to the list of players for this group */
885 DPQ_INSERT(lpGData->players,lpNewPList,players);
887 /* Let the SP know that we've added a player to the group */
888 if( This->dp2->spData.lpCB->AddPlayerToGroup )
890 DPSP_ADDPLAYERTOGROUPDATA data;
892 TRACE( "Calling SP AddPlayerToGroup\n" );
894 data.idPlayer = idPlayer;
895 data.idGroup = idGroup;
896 data.lpISP = This->dp2->spData.lpISP;
898 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
901 /* Inform all other peers of the addition of player to the group. If there are
902 * no peers keep this event quiet.
903 * Also, if this event was the result of another machine sending it to us,
904 * don't bother rebroadcasting it.
906 if( ( lpMsgHdr == NULL ) &&
907 This->dp2->lpSessionDesc &&
908 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
910 DPMSG_ADDPLAYERTOGROUP msg;
911 msg.dwType = DPSYS_ADDPLAYERTOGROUP;
913 msg.dpIdGroup = idGroup;
914 msg.dpIdPlayer = idPlayer;
916 /* FIXME: Correct to just use send effectively? */
917 /* FIXME: Should size include data w/ message or just message "header" */
918 /* FIXME: Check return code */
919 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
922 return DP_OK;
925 static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
926 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
928 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
929 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, TRUE );
932 static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
933 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
935 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
936 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, FALSE );
939 static HRESULT DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi )
941 HRESULT hr = DP_OK;
943 TRACE("(%p)->(%u)\n", This, bAnsi );
945 /* FIXME: Need to find a new host I assume (how?) */
946 /* FIXME: Need to destroy all local groups */
947 /* FIXME: Need to migrate all remotely visible players to the new host */
949 /* Invoke the SP callback to inform of session close */
950 if( This->dp2->spData.lpCB->CloseEx )
952 DPSP_CLOSEDATA data;
954 TRACE( "Calling SP CloseEx\n" );
956 data.lpISP = This->dp2->spData.lpISP;
958 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
961 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
963 TRACE( "Calling SP Close (obsolete interface)\n" );
965 hr = (*This->dp2->spData.lpCB->Close)();
968 if ( !FAILED(hr) )
970 This->dp2->bConnectionOpen = FALSE;
973 return hr;
976 static HRESULT WINAPI DirectPlay2AImpl_Close
977 ( LPDIRECTPLAY2A iface )
979 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
980 return DP_IF_Close( This, TRUE );
983 static HRESULT WINAPI DirectPlay2WImpl_Close
984 ( LPDIRECTPLAY2 iface )
986 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
987 return DP_IF_Close( This, FALSE );
990 static
991 lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, const DPID *lpid,
992 const DPNAME *lpName, DWORD dwFlags,
993 DPID idParent, BOOL bAnsi )
995 lpGroupData lpGData;
997 /* Allocate the new space and add to end of high level group list */
998 lpGData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGData ) );
1000 if( lpGData == NULL )
1002 return NULL;
1005 DPQ_INIT(lpGData->groups);
1006 DPQ_INIT(lpGData->players);
1008 /* Set the desired player ID - no sanity checking to see if it exists */
1009 lpGData->dpid = *lpid;
1011 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
1013 /* FIXME: Should we check that the parent exists? */
1014 lpGData->parent = idParent;
1016 /* FIXME: Should we validate the dwFlags? */
1017 lpGData->dwFlags = dwFlags;
1019 TRACE( "Created group id 0x%08x\n", *lpid );
1021 return lpGData;
1024 /* This method assumes that all links to it are already deleted */
1025 static void
1026 DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid )
1028 lpGroupList lpGList;
1030 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1032 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
1034 if( lpGList == NULL )
1036 ERR( "DPID 0x%08x not found\n", dpid );
1037 return;
1040 if( --(lpGList->lpGData->uRef) )
1042 FIXME( "Why is this not the last reference to group?\n" );
1043 DebugBreak();
1046 /* Delete player */
1047 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
1048 HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
1050 /* Remove and Delete Player List object */
1051 HeapFree( GetProcessHeap(), 0, lpGList );
1055 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid )
1057 lpGroupList lpGroups;
1059 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1061 if( dpid == DPID_SYSTEM_GROUP )
1063 return This->dp2->lpSysGroup;
1065 else
1067 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
1070 if( lpGroups == NULL )
1072 return NULL;
1075 return lpGroups->lpGData;
1078 static HRESULT DP_IF_CreateGroup
1079 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
1080 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
1081 DWORD dwFlags, BOOL bAnsi )
1083 lpGroupData lpGData;
1085 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1086 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
1087 dwFlags, bAnsi );
1089 /* If the name is not specified, we must provide one */
1090 if( DPID_UNKNOWN == *lpidGroup )
1092 /* If we are the name server, we decide on the group ids. If not, we
1093 * must ask for one before attempting a creation.
1095 if( This->dp2->bHostInterface )
1097 *lpidGroup = DP_NextObjectId();
1099 else
1101 *lpidGroup = DP_GetRemoteNextObjectId();
1105 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
1106 DPID_NOPARENT_GROUP, bAnsi );
1108 if( lpGData == NULL )
1110 return DPERR_CANTADDPLAYER; /* yes player not group */
1113 if( DPID_SYSTEM_GROUP == *lpidGroup )
1115 This->dp2->lpSysGroup = lpGData;
1116 TRACE( "Inserting system group\n" );
1118 else
1120 /* Insert into the system group */
1121 lpGroupList lpGroup = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGroup ) );
1122 lpGroup->lpGData = lpGData;
1124 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
1127 /* Something is now referencing this data */
1128 lpGData->uRef++;
1130 /* Set all the important stuff for the group */
1131 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
1133 /* FIXME: We should only create the system group if GetCaps returns
1134 * DPCAPS_GROUPOPTIMIZED.
1137 /* Let the SP know that we've created this group */
1138 if( This->dp2->spData.lpCB->CreateGroup )
1140 DPSP_CREATEGROUPDATA data;
1141 DWORD dwCreateFlags = 0;
1143 TRACE( "Calling SP CreateGroup\n" );
1145 if( *lpidGroup == DPID_NOPARENT_GROUP )
1146 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
1148 if( lpMsgHdr == NULL )
1149 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1151 if( dwFlags & DPGROUP_HIDDEN )
1152 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
1154 data.idGroup = *lpidGroup;
1155 data.dwFlags = dwCreateFlags;
1156 data.lpSPMessageHeader = lpMsgHdr;
1157 data.lpISP = This->dp2->spData.lpISP;
1159 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1162 /* Inform all other peers of the creation of a new group. If there are
1163 * no peers keep this event quiet.
1164 * Also if this message was sent to us, don't rebroadcast.
1166 if( ( lpMsgHdr == NULL ) &&
1167 This->dp2->lpSessionDesc &&
1168 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1170 DPMSG_CREATEPLAYERORGROUP msg;
1171 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1173 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1174 msg.dpId = *lpidGroup;
1175 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1176 msg.lpData = lpData;
1177 msg.dwDataSize = dwDataSize;
1178 msg.dpnName = *lpGroupName;
1179 msg.dpIdParent = DPID_NOPARENT_GROUP;
1180 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
1182 /* FIXME: Correct to just use send effectively? */
1183 /* FIXME: Should size include data w/ message or just message "header" */
1184 /* FIXME: Check return code */
1185 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
1186 0, 0, NULL, NULL, bAnsi );
1189 return DP_OK;
1192 static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
1193 ( LPDIRECTPLAY2A iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1194 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1196 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1198 if( This->dp2->connectionInitialized == NO_PROVIDER )
1200 return DPERR_UNINITIALIZED;
1203 if( lpidGroup == NULL ||
1204 !This->dp2->bConnectionOpen ||
1205 dwDataSize >= MAXDWORD ||
1206 ( lpData == NULL && dwDataSize != 0 ) )
1208 return DPERR_INVALIDPARAMS;
1211 *lpidGroup = DPID_UNKNOWN;
1213 return DP_IF_CreateGroup( This, NULL, lpidGroup,
1214 lpGroupName, lpData, dwDataSize, dwFlags, TRUE );
1217 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
1218 ( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1219 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1221 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1223 if( This->dp2->connectionInitialized == NO_PROVIDER )
1225 return DPERR_UNINITIALIZED;
1228 if( lpidGroup == NULL ||
1229 !This->dp2->bConnectionOpen ||
1230 dwDataSize >= MAXDWORD ||
1231 ( lpData == NULL && dwDataSize != 0 ) )
1233 return DPERR_INVALIDPARAMS;
1236 *lpidGroup = DPID_UNKNOWN;
1238 return DP_IF_CreateGroup( This, NULL, lpidGroup,
1239 lpGroupName, lpData, dwDataSize, dwFlags, FALSE );
1243 static void
1244 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
1245 LPVOID lpData, DWORD dwDataSize )
1247 /* Clear out the data with this player */
1248 if( dwFlags & DPSET_LOCAL )
1250 if ( lpGData->dwLocalDataSize != 0 )
1252 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
1253 lpGData->lpLocalData = NULL;
1254 lpGData->dwLocalDataSize = 0;
1257 else
1259 if( lpGData->dwRemoteDataSize != 0 )
1261 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
1262 lpGData->lpRemoteData = NULL;
1263 lpGData->dwRemoteDataSize = 0;
1267 /* Reallocate for new data */
1268 if( lpData != NULL )
1270 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1271 sizeof( dwDataSize ) );
1272 CopyMemory( lpNewData, lpData, dwDataSize );
1274 if( dwFlags & DPSET_LOCAL )
1276 lpGData->lpLocalData = lpData;
1277 lpGData->dwLocalDataSize = dwDataSize;
1279 else
1281 lpGData->lpRemoteData = lpNewData;
1282 lpGData->dwRemoteDataSize = dwDataSize;
1289 HRESULT DP_CreatePlayer( IDirectPlay2Impl* This, DPID idPlayer,
1290 LPDPNAME lpName, DWORD dwFlags,
1291 LPVOID lpData, DWORD dwDataSize,
1292 HANDLE hEvent, BOOL bAnsi,
1293 lpPlayerData* lplpPlayer )
1295 /* Create the storage for a new player and insert
1296 * it in the list of players. */
1298 lpPlayerList lpPList = NULL;
1299 lpPlayerData lpPlayer;
1300 HRESULT hr;
1302 TRACE( "(%p)->(0x%08x,%p,0x%08x,%p,%d,%p,%u,%p)\n",
1303 This, idPlayer, lpName, dwFlags, lpData,
1304 dwDataSize, hEvent, bAnsi, lplpPlayer );
1306 /* Verify that we don't already have this player */
1307 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players,
1308 lpPData->dpid, ==, idPlayer, lpPList );
1309 if ( lpPList != NULL )
1311 hr = DPERR_CANTCREATEPLAYER;
1312 goto end;
1315 /* Allocate the storage for the player and associate it with list element */
1316 lpPlayer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPlayer ) );
1317 if( lpPlayer == NULL )
1319 hr = DPERR_CANTCREATEPLAYER;
1320 goto end;
1323 if ( lplpPlayer != NULL )
1325 *lplpPlayer = lpPlayer;
1328 lpPlayer->dpid = idPlayer;
1329 lpPlayer->dwFlags = dwFlags;
1331 DP_CopyDPNAMEStruct( &lpPlayer->name, lpName, bAnsi );
1333 /* If we were given an event handle, duplicate it */
1334 if( hEvent != 0 )
1336 if( !DuplicateHandle( GetCurrentProcess(), hEvent,
1337 GetCurrentProcess(), &lpPlayer->hEvent,
1338 0, FALSE, DUPLICATE_SAME_ACCESS ) )
1340 ERR( "Can't duplicate player msg handle %p\n", hEvent );
1341 hr = DPERR_CANTCREATEPLAYER;
1342 goto end;
1346 /* Set player data */
1347 if ( lpData != NULL )
1349 DP_SetPlayerData( lpPlayer, DPSET_REMOTE, lpData, dwDataSize );
1352 /* Initialize the SP data section */
1353 lpPlayer->lpSPPlayerData = DPSP_CreateSPPlayerData();
1355 if( ~dwFlags & DPLAYI_PLAYER_SYSPLAYER )
1357 This->dp2->lpSessionDesc->dwCurrentPlayers++;
1360 /* Create the list object and link it in */
1361 lpPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPList ) );
1362 if( lpPList == NULL )
1364 hr = DPERR_CANTADDPLAYER;
1365 goto end;
1368 lpPlayer->uRef = 1;
1369 lpPList->lpPData = lpPlayer;
1371 /* Add the player to the system group */
1372 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1374 /* Quick hack */
1375 if ( ~dwFlags & DPLAYI_PLAYER_PLAYERLOCAL ) {
1376 lpPlayerList lpPList;
1377 LPDPMSG lpMsg =
1378 HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct DPMSG) );
1379 LPDPMSG_CREATEPLAYERORGROUP msg =
1380 HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DPMSG_CREATEPLAYERORGROUP) );
1382 msg->dwType = DPSYS_CREATEPLAYERORGROUP;
1383 msg->dwPlayerType = DPPLAYERTYPE_PLAYER;
1384 msg->dpId = idPlayer;
1385 msg->dwCurrentPlayers = This->dp2->lpSessionDesc->dwCurrentPlayers;
1386 msg->lpData = NULL;/*TODO*/
1387 msg->dwDataSize = 0;/*TODO*/
1388 msg->dpIdParent = DPID_NOPARENT_GROUP;
1389 msg->dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
1390 if ( lpName )
1392 msg->dpnName = *lpName;
1395 lpMsg->msg = (LPDPMSG_GENERIC) msg;
1396 lpMsg->dwMsgSize = sizeof(LPDPMSG_CREATEPLAYERORGROUP);
1397 DPQ_INSERT( This->dp2->receiveMsgs, lpMsg, msgs );
1399 if ( (lpPList = DPQ_FIRST( This->dp2->lpSysGroup->players )) )
1403 if ( ( lpPList->lpPData->dwFlags & DPLAYI_PLAYER_PLAYERLOCAL ) &&
1404 lpPList->lpPData->hEvent )
1406 SetEvent( lpPList->lpPData->hEvent );
1409 while( (lpPList = DPQ_NEXT( lpPList->players )) );
1413 end:
1414 if ( FAILED(hr) )
1416 DP_DeletePlayer( This, idPlayer );
1418 return hr;
1421 /* Delete the contents of the DPNAME struct */
1422 static void
1423 DP_DeleteDPNameStruct( LPDPNAME lpDPName )
1425 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u1.lpszShortNameA );
1426 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u2.lpszLongNameA );
1429 /* This method assumes that all links to it are already deleted */
1430 static void
1431 DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid )
1433 lpPlayerList lpPList;
1435 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1437 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1439 if( lpPList == NULL )
1441 ERR( "DPID 0x%08x not found\n", dpid );
1442 return;
1445 /* Verify that this is the last reference to the data */
1446 if( --(lpPList->lpPData->uRef) )
1448 FIXME( "Why is this not the last reference to player?\n" );
1449 DebugBreak();
1452 /* Delete player */
1453 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1455 CloseHandle( lpPList->lpPData->hEvent );
1456 HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
1458 /* Delete Player List object */
1459 HeapFree( GetProcessHeap(), 0, lpPList );
1462 lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid )
1464 lpPlayerList lpPlayers;
1466 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1468 if(This->dp2->lpSysGroup == NULL)
1469 return NULL;
1471 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1473 return lpPlayers;
1476 /* Basic area for Dst must already be allocated */
1477 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, const DPNAME *lpSrc, BOOL bAnsi )
1479 if( lpSrc == NULL )
1481 ZeroMemory( lpDst, sizeof( *lpDst ) );
1482 lpDst->dwSize = sizeof( *lpDst );
1483 return TRUE;
1486 if( lpSrc->dwSize != sizeof( *lpSrc) )
1488 return FALSE;
1491 /* Delete any existing pointers */
1492 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1493 HeapFree( GetProcessHeap(), 0, lpDst->u2.lpszLongNameA );
1495 /* Copy as required */
1496 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1498 if( bAnsi )
1500 if( lpSrc->u1.lpszShortNameA )
1502 lpDst->u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), 0,
1503 strlen(lpSrc->u1.lpszShortNameA)+1 );
1504 strcpy( lpDst->u1.lpszShortNameA, lpSrc->u1.lpszShortNameA );
1506 else
1508 lpDst->u1.lpszShortNameA = NULL;
1510 if( lpSrc->u2.lpszLongNameA )
1512 lpDst->u2.lpszLongNameA = HeapAlloc( GetProcessHeap(), 0,
1513 strlen(lpSrc->u2.lpszLongNameA)+1 );
1514 strcpy( lpDst->u2.lpszLongNameA, lpSrc->u2.lpszLongNameA );
1516 else
1518 lpDst->u2.lpszLongNameA = NULL;
1521 else
1523 if( lpSrc->u1.lpszShortNameA )
1525 lpDst->u1.lpszShortName = HeapAlloc( GetProcessHeap(), 0,
1526 (strlenW(lpSrc->u1.lpszShortName)+1)*sizeof(WCHAR) );
1527 strcpyW( lpDst->u1.lpszShortName, lpSrc->u1.lpszShortName );
1529 else
1531 lpDst->u1.lpszShortNameA = NULL;
1533 if( lpSrc->u2.lpszLongNameA )
1535 lpDst->u2.lpszLongName = HeapAlloc( GetProcessHeap(), 0,
1536 (strlenW(lpSrc->u2.lpszLongName)+1)*sizeof(WCHAR) );
1537 strcpyW( lpDst->u2.lpszLongName, lpSrc->u2.lpszLongName );
1539 else
1541 lpDst->u2.lpszLongNameA = NULL;
1545 return TRUE;
1548 static void
1549 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
1550 LPVOID lpData, DWORD dwDataSize )
1552 /* Clear out the data with this player */
1553 if( dwFlags & DPSET_LOCAL )
1555 if ( lpPData->dwLocalDataSize != 0 )
1557 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
1558 lpPData->lpLocalData = NULL;
1559 lpPData->dwLocalDataSize = 0;
1562 else
1564 if( lpPData->dwRemoteDataSize != 0 )
1566 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
1567 lpPData->lpRemoteData = NULL;
1568 lpPData->dwRemoteDataSize = 0;
1572 /* Reallocate for new data */
1573 if( lpData != NULL )
1575 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1576 sizeof( dwDataSize ) );
1577 CopyMemory( lpNewData, lpData, dwDataSize );
1579 if( dwFlags & DPSET_LOCAL )
1581 lpPData->lpLocalData = lpData;
1582 lpPData->dwLocalDataSize = dwDataSize;
1584 else
1586 lpPData->lpRemoteData = lpNewData;
1587 lpPData->dwRemoteDataSize = dwDataSize;
1593 static HRESULT DP_IF_CreatePlayer
1594 ( IDirectPlay2Impl* This,
1595 LPVOID lpMsgHdr, /* NULL for local creation, non NULL for remote creation */
1596 LPDPID lpidPlayer,
1597 LPDPNAME lpPlayerName,
1598 HANDLE hEvent,
1599 LPVOID lpData,
1600 DWORD dwDataSize,
1601 DWORD dwFlags,
1602 BOOL bAnsi )
1604 HRESULT hr = DP_OK;
1605 lpPlayerData lpPData;
1607 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1608 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1609 dwDataSize, dwFlags, bAnsi );
1611 if( dwFlags == 0 )
1613 dwFlags = DPPLAYER_SPECTATOR;
1616 if( lpidPlayer == NULL )
1618 return DPERR_INVALIDPARAMS;
1622 /* Determine the creation flags for the player. These will be passed
1623 * to the name server if requesting a player id and to the SP when
1624 * informing it of the player creation
1627 if( dwFlags & DPPLAYER_SERVERPLAYER )
1629 if( *lpidPlayer == DPID_SERVERPLAYER )
1631 /* Server player for the host interface */
1632 dwFlags |= DPLAYI_PLAYER_APPSERVER;
1634 else if( *lpidPlayer == DPID_NAME_SERVER )
1636 /* Name server - master of everything */
1637 dwFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
1639 else
1641 /* Server player for a non host interface */
1642 dwFlags |= DPLAYI_PLAYER_SYSPLAYER;
1646 if( lpMsgHdr == NULL )
1647 dwFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1650 /* Verify we know how to handle all the flags */
1651 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1652 ( dwFlags & DPPLAYER_SPECTATOR )
1656 /* Assume non fatal failure */
1657 ERR( "unknown dwFlags = 0x%08x\n", dwFlags );
1660 /* If the name is not specified, we must provide one */
1661 if( *lpidPlayer == DPID_UNKNOWN )
1663 /* If we are the session master, we dish out the group/player ids */
1664 if( This->dp2->bHostInterface )
1666 *lpidPlayer = DP_NextObjectId();
1668 else
1670 hr = DP_MSG_SendRequestPlayerId( This, dwFlags & 0x000000FF, lpidPlayer );
1672 if( FAILED(hr) )
1674 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1675 return hr;
1680 hr = DP_CreatePlayer( This, *lpidPlayer, lpPlayerName, dwFlags,
1681 lpData, dwDataSize, hEvent, bAnsi,
1682 &lpPData );
1683 if( FAILED(hr) )
1685 return hr;
1688 /* Let the SP know that we've created this player */
1689 if( This->dp2->spData.lpCB->CreatePlayer )
1691 DPSP_CREATEPLAYERDATA data;
1693 data.idPlayer = *lpidPlayer;
1694 data.dwFlags = dwFlags;
1695 data.lpSPMessageHeader = lpMsgHdr;
1696 data.lpISP = This->dp2->spData.lpISP;
1698 TRACE( "Calling SP CreatePlayer 0x%08x: dwFlags: 0x%08x lpMsgHdr: %p\n",
1699 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
1701 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1704 if( FAILED(hr) )
1706 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1707 return hr;
1710 /* Now let the SP know that this player is a member of the system group */
1711 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1713 DPSP_ADDPLAYERTOGROUPDATA data;
1715 data.idPlayer = *lpidPlayer;
1716 data.idGroup = DPID_SYSTEM_GROUP;
1717 data.lpISP = This->dp2->spData.lpISP;
1719 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1721 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1724 if( FAILED(hr) )
1726 ERR( "Failed to add player to sys group with sp: %s\n",
1727 DPLAYX_HresultToString(hr) );
1728 return hr;
1732 if ( ( ! This->dp2->bHostInterface ) && ( lpMsgHdr == NULL ) )
1734 if ( dwFlags & DPLAYI_PLAYER_SYSPLAYER )
1736 /* Let the name server know about the creation of this player,
1737 * and reeceive the name table */
1738 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
1740 else
1742 /* Inform all other peers of the creation of a new player.
1743 * Also, if this was a remote event, no need to rebroadcast it. */
1744 hr = DP_MSG_SendCreatePlayer( This, lpPData );
1748 return hr;
1751 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
1752 ( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1753 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1755 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1757 if( This->dp2->connectionInitialized == NO_PROVIDER )
1759 return DPERR_UNINITIALIZED;
1762 if( lpidPlayer == NULL || !This->dp2->bConnectionOpen )
1764 return DPERR_INVALIDPARAMS;
1767 if ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_NEWPLAYERSDISABLED )
1769 return DPERR_CANTCREATEPLAYER;
1772 if( dwFlags & DPPLAYER_SERVERPLAYER )
1774 *lpidPlayer = DPID_SERVERPLAYER;
1776 else
1778 *lpidPlayer = DPID_UNKNOWN;
1781 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1782 lpData, dwDataSize, dwFlags, TRUE );
1785 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
1786 ( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1787 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1789 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1791 if( This->dp2->connectionInitialized == NO_PROVIDER )
1793 return DPERR_UNINITIALIZED;
1796 if( lpidPlayer == NULL || !This->dp2->bConnectionOpen )
1798 return DPERR_INVALIDPARAMS;
1801 if ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_NEWPLAYERSDISABLED )
1803 return DPERR_CANTCREATEPLAYER;
1806 if( dwFlags & DPPLAYER_SERVERPLAYER )
1808 *lpidPlayer = DPID_SERVERPLAYER;
1810 else
1812 *lpidPlayer = DPID_UNKNOWN;
1815 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1816 lpData, dwDataSize, dwFlags, FALSE );
1819 static DPID DP_GetRemoteNextObjectId(void)
1821 FIXME( ":stub\n" );
1823 /* Hack solution */
1824 return DP_NextObjectId();
1827 static HRESULT DP_IF_DeletePlayerFromGroup
1828 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
1829 DPID idPlayer, BOOL bAnsi )
1831 HRESULT hr = DP_OK;
1833 lpGroupData lpGData;
1834 lpPlayerList lpPList;
1836 TRACE( "(%p)->(%p,0x%08x,0x%08x,%u)\n",
1837 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
1839 /* Find the group */
1840 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1842 return DPERR_INVALIDGROUP;
1845 /* Find the player */
1846 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
1848 return DPERR_INVALIDPLAYER;
1851 /* Remove the player shortcut from the group */
1852 DPQ_REMOVE_ENTRY( lpGData->players, players, lpPData->dpid, ==, idPlayer, lpPList );
1854 if( lpPList == NULL )
1856 return DPERR_INVALIDPLAYER;
1859 /* One less reference */
1860 lpPList->lpPData->uRef--;
1862 /* Delete the Player List element */
1863 HeapFree( GetProcessHeap(), 0, lpPList );
1865 /* Inform the SP if they care */
1866 if( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1868 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1870 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1872 data.idPlayer = idPlayer;
1873 data.idGroup = idGroup;
1874 data.lpISP = This->dp2->spData.lpISP;
1876 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1879 /* Need to send a DELETEPLAYERFROMGROUP message */
1880 FIXME( "Need to send a message\n" );
1882 return hr;
1885 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
1886 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
1888 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1889 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, TRUE );
1892 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
1893 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
1895 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1896 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, FALSE );
1899 typedef struct _DPRGOPContext
1901 IDirectPlay3Impl* This;
1902 BOOL bAnsi;
1903 DPID idGroup;
1904 } DPRGOPContext, *lpDPRGOPContext;
1906 static BOOL CALLBACK
1907 cbRemoveGroupOrPlayer(
1908 DPID dpId,
1909 DWORD dwPlayerType,
1910 LPCDPNAME lpName,
1911 DWORD dwFlags,
1912 LPVOID lpContext )
1914 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1916 TRACE( "Removing element:0x%08x (type:0x%08x) from element:0x%08x\n",
1917 dpId, dwPlayerType, lpCtxt->idGroup );
1919 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1921 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt->This, lpCtxt->idGroup,
1922 dpId )
1926 ERR( "Unable to delete group 0x%08x from group 0x%08x\n",
1927 dpId, lpCtxt->idGroup );
1930 else
1932 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl*)lpCtxt->This,
1933 NULL, lpCtxt->idGroup,
1934 dpId, lpCtxt->bAnsi )
1938 ERR( "Unable to delete player 0x%08x from grp 0x%08x\n",
1939 dpId, lpCtxt->idGroup );
1943 return TRUE; /* Continue enumeration */
1946 static HRESULT DP_IF_DestroyGroup
1947 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi )
1949 lpGroupData lpGData;
1950 DPRGOPContext context;
1952 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1953 This, lpMsgHdr, idGroup, bAnsi );
1955 /* Find the group */
1956 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1958 return DPERR_INVALIDPLAYER; /* yes player */
1961 context.This = (IDirectPlay3Impl*)This;
1962 context.bAnsi = bAnsi;
1963 context.idGroup = idGroup;
1965 /* Remove all players that this group has */
1966 DP_IF_EnumGroupPlayers( This, idGroup, NULL,
1967 cbRemoveGroupOrPlayer, &context, 0, bAnsi );
1969 /* Remove all links to groups that this group has since this is dp3 */
1970 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This, idGroup, NULL,
1971 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1973 /* Remove this group from the parent group - if it has one */
1974 if( ( idGroup != DPID_SYSTEM_GROUP ) &&
1975 ( lpGData->parent != DPID_SYSTEM_GROUP )
1978 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl*)This, lpGData->parent,
1979 idGroup );
1982 /* Now delete this group data and list from the system group */
1983 DP_DeleteGroup( This, idGroup );
1985 /* Let the SP know that we've destroyed this group */
1986 if( This->dp2->spData.lpCB->DeleteGroup )
1988 DPSP_DELETEGROUPDATA data;
1990 FIXME( "data.dwFlags is incorrect\n" );
1992 data.idGroup = idGroup;
1993 data.dwFlags = 0;
1994 data.lpISP = This->dp2->spData.lpISP;
1996 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1999 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
2001 return DP_OK;
2004 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
2005 ( LPDIRECTPLAY2A iface, DPID idGroup )
2007 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2008 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
2011 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
2012 ( LPDIRECTPLAY2 iface, DPID idGroup )
2014 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2015 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
2018 typedef struct _DPFAGContext
2020 IDirectPlay2Impl* This;
2021 DPID idPlayer;
2022 BOOL bAnsi;
2023 } DPFAGContext, *lpDPFAGContext;
2025 static HRESULT DP_IF_DestroyPlayer
2026 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi )
2028 DPFAGContext cbContext;
2030 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
2031 This, lpMsgHdr, idPlayer, bAnsi );
2033 if( This->dp2->connectionInitialized == NO_PROVIDER )
2035 return DPERR_UNINITIALIZED;
2038 if( DP_FindPlayer( This, idPlayer ) == NULL )
2040 return DPERR_INVALIDPLAYER;
2043 /* FIXME: If the player is remote, we must be the host to delete this */
2045 cbContext.This = This;
2046 cbContext.idPlayer = idPlayer;
2047 cbContext.bAnsi = bAnsi;
2049 /* Find each group and call DeletePlayerFromGroup if the player is a
2050 member of the group */
2051 DP_IF_EnumGroups( This, NULL, cbDeletePlayerFromAllGroups,
2052 &cbContext, DPENUMGROUPS_ALL, bAnsi );
2054 /* Now delete player and player list from the sys group */
2055 DP_DeletePlayer( This, idPlayer );
2057 /* Let the SP know that we've destroyed this group */
2058 if( This->dp2->spData.lpCB->DeletePlayer )
2060 DPSP_DELETEPLAYERDATA data;
2062 FIXME( "data.dwFlags is incorrect\n" );
2064 data.idPlayer = idPlayer;
2065 data.dwFlags = 0;
2066 data.lpISP = This->dp2->spData.lpISP;
2068 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
2071 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
2073 return DP_OK;
2076 static BOOL CALLBACK
2077 cbDeletePlayerFromAllGroups(
2078 DPID dpId,
2079 DWORD dwPlayerType,
2080 LPCDPNAME lpName,
2081 DWORD dwFlags,
2082 LPVOID lpContext )
2084 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
2086 if( dwPlayerType == DPPLAYERTYPE_GROUP )
2088 DP_IF_DeletePlayerFromGroup( lpCtxt->This, NULL, dpId, lpCtxt->idPlayer,
2089 lpCtxt->bAnsi );
2091 /* Enumerate all groups in this group since this will normally only
2092 * be called for top level groups
2094 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)lpCtxt->This,
2095 dpId, NULL,
2096 cbDeletePlayerFromAllGroups,
2097 lpContext, DPENUMGROUPS_ALL,
2098 lpCtxt->bAnsi );
2101 else
2103 ERR( "Group callback has dwPlayerType = 0x%08x\n", dwPlayerType );
2106 return TRUE;
2109 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
2110 ( LPDIRECTPLAY2A iface, DPID idPlayer )
2112 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2113 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
2116 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
2117 ( LPDIRECTPLAY2 iface, DPID idPlayer )
2119 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2120 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
2123 static HRESULT DP_IF_EnumGroupPlayers
2124 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
2125 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2126 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2128 lpGroupData lpGData;
2129 lpPlayerList lpPList;
2131 FIXME("(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
2132 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
2133 lpContext, dwFlags, bAnsi );
2135 if( This->dp2->connectionInitialized == NO_PROVIDER )
2137 return DPERR_UNINITIALIZED;
2140 if( !This->dp2->bConnectionOpen )
2142 return DPERR_NOSESSIONS;
2145 if( ( lpEnumPlayersCallback2 == NULL ) ||
2146 ( ( dwFlags & DPENUMPLAYERS_SESSION ) && ( lpguidInstance == NULL ) ) )
2148 return DPERR_INVALIDPARAMS;
2151 /* Find the group */
2152 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2154 return DPERR_INVALIDGROUP;
2157 if( DPQ_IS_EMPTY( lpGData->players ) )
2159 return DP_OK;
2162 lpPList = DPQ_FIRST( lpGData->players );
2164 /* Walk the players in this group */
2165 for( ;; )
2167 /* We do not enum any system players as they are of no
2168 * consequence to the end user.
2170 if( lpPList->lpPData->dwFlags & DPLAYI_PLAYER_SYSPLAYER )
2173 /* FIXME: Need to add stuff for dwFlags checking */
2175 if( !lpEnumPlayersCallback2( lpPList->lpPData->dpid, DPPLAYERTYPE_PLAYER,
2176 &lpPList->lpPData->name,
2177 lpPList->lpPData->dwFlags,
2178 lpContext )
2181 /* User requested break */
2182 return DP_OK;
2186 if( DPQ_IS_ENDOFLIST( lpPList->players ) )
2188 break;
2191 lpPList = DPQ_NEXT( lpPList->players );
2194 return DP_OK;
2197 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
2198 ( LPDIRECTPLAY2A iface, DPID idGroup, LPGUID lpguidInstance,
2199 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2200 LPVOID lpContext, DWORD dwFlags )
2202 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2203 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2204 lpEnumPlayersCallback2, lpContext,
2205 dwFlags, TRUE );
2208 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
2209 ( LPDIRECTPLAY2 iface, DPID idGroup, LPGUID lpguidInstance,
2210 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2211 LPVOID lpContext, DWORD dwFlags )
2213 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2214 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2215 lpEnumPlayersCallback2, lpContext,
2216 dwFlags, FALSE );
2219 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2220 static HRESULT DP_IF_EnumGroups
2221 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2222 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2223 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2225 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This,
2226 DPID_SYSTEM_GROUP, lpguidInstance,
2227 lpEnumPlayersCallback2, lpContext,
2228 dwFlags, bAnsi );
2231 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
2232 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2233 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2234 LPVOID lpContext, DWORD dwFlags )
2236 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2237 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2238 lpContext, dwFlags, TRUE );
2241 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
2242 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2243 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2244 LPVOID lpContext, DWORD dwFlags )
2246 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2247 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2248 lpContext, dwFlags, FALSE );
2251 static HRESULT DP_IF_EnumPlayers
2252 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2253 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2254 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2256 return DP_IF_EnumGroupPlayers( This, DPID_SYSTEM_GROUP, lpguidInstance,
2257 lpEnumPlayersCallback2, lpContext,
2258 dwFlags, bAnsi );
2261 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
2262 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2263 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2264 LPVOID lpContext, DWORD dwFlags )
2266 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2267 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2268 lpContext, dwFlags, TRUE );
2271 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
2272 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2273 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2274 LPVOID lpContext, DWORD dwFlags )
2276 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2277 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2278 lpContext, dwFlags, FALSE );
2281 /* This function should call the registered callback function that the user
2282 passed into EnumSessions for each entry available.
2284 static void DP_InvokeEnumSessionCallbacks
2285 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2286 LPVOID lpNSInfo,
2287 DWORD dwTimeout,
2288 LPVOID lpContext )
2290 LPDPSESSIONDESC2 lpSessionDesc;
2292 FIXME( ": not checking for conditions\n" );
2294 /* Not sure if this should be pruning but it's convenient */
2295 NS_PruneSessionCache( lpNSInfo );
2297 NS_ResetSessionEnumeration( lpNSInfo );
2299 /* Enumerate all sessions */
2300 /* FIXME: Need to indicate ANSI */
2301 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2303 TRACE( "EnumSessionsCallback2 invoked\n" );
2304 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2306 return;
2310 /* Invoke one last time to indicate that there is no more to come */
2311 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2314 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2316 EnumSessionAsyncCallbackData* data = lpContext;
2317 HANDLE hSuicideRequest = data->hSuicideRequest;
2318 DWORD dwTimeout = data->dwTimeout;
2320 TRACE( "Thread started with timeout = 0x%08x\n", dwTimeout );
2322 for( ;; )
2324 HRESULT hr;
2326 /* Sleep up to dwTimeout waiting for request to terminate thread */
2327 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2329 TRACE( "Thread terminating on terminate request\n" );
2330 break;
2333 /* Now resend the enum request */
2334 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2335 data->dwEnumSessionFlags,
2336 data->lpSpData );
2338 if( FAILED(hr) )
2340 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2341 /* FIXME: Should we kill this thread? How to inform the main thread? */
2346 TRACE( "Thread terminating\n" );
2348 /* Clean up the thread data */
2349 CloseHandle( hSuicideRequest );
2350 HeapFree( GetProcessHeap(), 0, lpContext );
2352 /* FIXME: Need to have some notification to main app thread that this is
2353 * dead. It would serve two purposes. 1) allow sync on termination
2354 * so that we don't actually send something to ourselves when we
2355 * become name server (race condition) and 2) so that if we die
2356 * abnormally something else will be able to tell.
2359 return 1;
2362 static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
2364 /* Does a thread exist? If so we were doing an async enum session */
2365 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2367 TRACE( "Killing EnumSession thread %p\n",
2368 This->dp2->hEnumSessionThread );
2370 /* Request that the thread kill itself nicely */
2371 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2372 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2374 /* We no longer need to know about the thread */
2375 CloseHandle( This->dp2->hEnumSessionThread );
2377 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2381 static HRESULT DP_IF_EnumSessions
2382 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2383 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2384 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2386 HRESULT hr = DP_OK;
2388 TRACE( "(%p)->(%p,0x%08x,%p,%p,0x%08x,%u)\n",
2389 This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags,
2390 bAnsi );
2391 if( This->dp2->connectionInitialized == NO_PROVIDER )
2393 return DPERR_UNINITIALIZED;
2396 if( (lpsd == NULL) || (lpsd->dwSize != sizeof(DPSESSIONDESC2)) )
2398 return DPERR_INVALIDPARAMS;
2401 /* Can't enumerate if the session is already open */
2402 if( This->dp2->bConnectionOpen )
2404 return DPERR_GENERIC;
2407 #if 1
2408 /* The loading of a lobby provider _seems_ to require a backdoor loading
2409 * of the service provider to also associate with this DP object. This is
2410 * because the app doesn't seem to have to call EnumConnections and
2411 * InitializeConnection for the SP before calling this method. As such
2412 * we'll do their dirty work for them with a quick hack so as to always
2413 * load the TCP/IP service provider.
2415 * The correct solution would seem to involve creating a dialog box which
2416 * contains the possible SPs. These dialog boxes most likely follow SDK
2417 * examples.
2419 if( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
2421 LPVOID lpConnection;
2422 DWORD dwSize;
2424 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2426 if( !DP_BuildCompoundAddr( DPAID_ServiceProvider, (LPGUID)&DPSPGUID_TCPIP,
2427 &lpConnection, &dwSize ) )
2429 ERR( "Can't build compound addr\n" );
2430 return DPERR_GENERIC;
2433 hr = DP_IF_InitializeConnection( (IDirectPlay3Impl*)This, lpConnection,
2434 0, bAnsi );
2435 if( FAILED(hr) )
2437 return hr;
2440 /* Free up the address buffer */
2441 HeapFree( GetProcessHeap(), 0, lpConnection );
2443 /* The SP is now initialized */
2444 This->dp2->bSPInitialized = TRUE;
2446 #endif
2449 /* Use the service provider default? */
2450 if( dwTimeout == 0 )
2452 DPCAPS spCaps;
2453 spCaps.dwSize = sizeof( spCaps );
2455 DP_IF_GetCaps( This, &spCaps, 0 );
2456 dwTimeout = spCaps.dwTimeout;
2458 /* The service provider doesn't provide one either! */
2459 if( dwTimeout == 0 )
2461 /* Provide the TCP/IP default */
2462 dwTimeout = DPMSG_WAIT_5_SECS;
2466 if( dwFlags & DPENUMSESSIONS_STOPASYNC )
2468 DP_KillEnumSessionThread( This );
2469 return hr;
2472 if( ( dwFlags & DPENUMSESSIONS_ASYNC ) )
2474 /* Enumerate everything presently in the local session cache */
2475 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2476 This->dp2->lpNameServerData, dwTimeout,
2477 lpContext );
2479 if( This->dp2->dwEnumSessionLock != 0 )
2480 return DPERR_CONNECTING;
2482 /* See if we've already created a thread to service this interface */
2483 if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2485 DWORD dwThreadId;
2486 This->dp2->dwEnumSessionLock++;
2488 /* Send the first enum request inline since the user may cancel a dialog
2489 * if one is presented. Also, may also have a connecting return code.
2491 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2492 dwFlags, &This->dp2->spData );
2494 if( SUCCEEDED(hr) )
2496 EnumSessionAsyncCallbackData* lpData
2497 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpData ) );
2498 /* FIXME: need to kill the thread on object deletion */
2499 lpData->lpSpData = &This->dp2->spData;
2501 lpData->requestGuid = lpsd->guidApplication;
2502 lpData->dwEnumSessionFlags = dwFlags;
2503 lpData->dwTimeout = dwTimeout;
2505 This->dp2->hKillEnumSessionThreadEvent =
2506 CreateEventW( NULL, TRUE, FALSE, NULL );
2508 if( !DuplicateHandle( GetCurrentProcess(),
2509 This->dp2->hKillEnumSessionThreadEvent,
2510 GetCurrentProcess(),
2511 &lpData->hSuicideRequest,
2512 0, FALSE, DUPLICATE_SAME_ACCESS )
2515 ERR( "Can't duplicate thread killing handle\n" );
2518 TRACE( ": creating EnumSessionsRequest thread\n" );
2520 This->dp2->hEnumSessionThread = CreateThread( NULL,
2522 DP_EnumSessionsSendAsyncRequestThread,
2523 lpData,
2525 &dwThreadId );
2527 This->dp2->dwEnumSessionLock--;
2530 else
2532 /* Invalidate the session cache for the interface */
2533 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2535 /* Send the broadcast for session enumeration */
2536 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2537 dwFlags,
2538 &This->dp2->spData );
2541 SleepEx( dwTimeout, FALSE );
2543 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2544 This->dp2->lpNameServerData, dwTimeout,
2545 lpContext );
2548 return hr;
2551 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2552 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2553 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2554 LPVOID lpContext, DWORD dwFlags )
2556 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2557 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2558 lpContext, dwFlags, TRUE );
2561 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2562 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2563 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2564 LPVOID lpContext, DWORD dwFlags )
2566 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2567 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2568 lpContext, dwFlags, FALSE );
2571 static HRESULT DP_IF_GetPlayerCaps
2572 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
2573 DWORD dwFlags )
2575 DPSP_GETCAPSDATA data;
2577 TRACE("(%p)->(0x%08x,%p,0x%08x)\n", This, idPlayer, lpDPCaps, dwFlags);
2579 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2581 return DPERR_UNINITIALIZED;
2584 if ( lpDPCaps->dwSize != sizeof(DPCAPS) )
2586 return DPERR_INVALIDPARAMS;
2589 /* Query the service provider */
2590 data.idPlayer = idPlayer;
2591 data.dwFlags = dwFlags;
2592 data.lpCaps = lpDPCaps;
2593 data.lpISP = This->dp2->spData.lpISP;
2595 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2598 static HRESULT DP_IF_GetCaps
2599 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags )
2601 return DP_IF_GetPlayerCaps( This, DPID_ALLPLAYERS, lpDPCaps, dwFlags );
2604 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2605 ( LPDIRECTPLAY2A iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2607 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2608 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2611 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2612 ( LPDIRECTPLAY2 iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2614 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2615 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2618 static HRESULT DP_IF_GetGroupData
2619 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2620 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2622 lpGroupData lpGData;
2623 DWORD dwRequiredBufferSize;
2624 LPVOID lpCopyDataFrom;
2626 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2627 This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi );
2629 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2631 return DPERR_INVALIDGROUP;
2634 /* How much buffer is required? */
2635 if( dwFlags & DPSET_LOCAL )
2637 dwRequiredBufferSize = lpGData->dwLocalDataSize;
2638 lpCopyDataFrom = lpGData->lpLocalData;
2640 else
2642 dwRequiredBufferSize = lpGData->dwRemoteDataSize;
2643 lpCopyDataFrom = lpGData->lpRemoteData;
2646 /* Is the user requesting to know how big a buffer is required? */
2647 if( ( lpData == NULL ) ||
2648 ( *lpdwDataSize < dwRequiredBufferSize )
2651 *lpdwDataSize = dwRequiredBufferSize;
2652 return DPERR_BUFFERTOOSMALL;
2655 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2657 return DP_OK;
2660 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2661 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2662 LPDWORD lpdwDataSize, DWORD dwFlags )
2664 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2665 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2666 dwFlags, TRUE );
2669 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2670 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2671 LPDWORD lpdwDataSize, DWORD dwFlags )
2673 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2674 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2675 dwFlags, FALSE );
2678 static HRESULT DP_IF_GetGroupName
2679 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2680 LPDWORD lpdwDataSize, BOOL bAnsi )
2682 lpGroupData lpGData;
2683 LPDPNAME lpName = lpData;
2684 DWORD dwRequiredDataSize;
2686 FIXME("(%p)->(0x%08x,%p,%p,%u) ANSI ignored\n",
2687 This, idGroup, lpData, lpdwDataSize, bAnsi );
2689 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2691 return DPERR_INVALIDGROUP;
2694 dwRequiredDataSize = lpGData->name.dwSize;
2696 if( lpGData->name.u1.lpszShortNameA )
2698 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
2701 if( lpGData->name.u2.lpszLongNameA )
2703 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
2706 if( ( lpData == NULL ) ||
2707 ( *lpdwDataSize < dwRequiredDataSize )
2710 *lpdwDataSize = dwRequiredDataSize;
2711 return DPERR_BUFFERTOOSMALL;
2714 /* Copy the structure */
2715 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2717 if( lpGData->name.u1.lpszShortNameA )
2719 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2720 lpGData->name.u1.lpszShortNameA );
2722 else
2724 lpName->u1.lpszShortNameA = NULL;
2727 if( lpGData->name.u1.lpszShortNameA )
2729 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2730 lpGData->name.u2.lpszLongNameA );
2732 else
2734 lpName->u2.lpszLongNameA = NULL;
2737 return DP_OK;
2740 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2741 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2742 LPDWORD lpdwDataSize )
2744 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2745 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2748 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2749 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2750 LPDWORD lpdwDataSize )
2752 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2753 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2756 static HRESULT DP_IF_GetMessageCount
2757 ( IDirectPlay2Impl* This, DPID idPlayer,
2758 LPDWORD lpdwCount, BOOL bAnsi )
2760 FIXME("(%p)->(0x%08x,%p,%u): stub\n", This, idPlayer, lpdwCount, bAnsi );
2761 return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer,
2762 DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL,
2763 bAnsi );
2766 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2767 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDWORD lpdwCount )
2769 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2770 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, TRUE );
2773 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2774 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDWORD lpdwCount )
2776 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2777 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, FALSE );
2780 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2781 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2783 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2784 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2785 return DP_OK;
2788 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2789 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2791 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2792 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2793 return DP_OK;
2796 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2797 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2798 DWORD dwFlags )
2800 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2801 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2804 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2805 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2806 DWORD dwFlags )
2808 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2809 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2812 static HRESULT DP_IF_GetPlayerData
2813 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2814 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2816 lpPlayerList lpPList;
2817 DWORD dwRequiredBufferSize;
2818 LPVOID lpCopyDataFrom;
2820 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2821 This, idPlayer, lpData, lpdwDataSize, dwFlags, bAnsi );
2823 if( This->dp2->connectionInitialized == NO_PROVIDER )
2825 return DPERR_UNINITIALIZED;
2828 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2830 return DPERR_INVALIDPLAYER;
2833 if( lpdwDataSize == NULL )
2835 return DPERR_INVALIDPARAMS;
2838 /* How much buffer is required? */
2839 if( dwFlags & DPSET_LOCAL )
2841 dwRequiredBufferSize = lpPList->lpPData->dwLocalDataSize;
2842 lpCopyDataFrom = lpPList->lpPData->lpLocalData;
2844 else
2846 dwRequiredBufferSize = lpPList->lpPData->dwRemoteDataSize;
2847 lpCopyDataFrom = lpPList->lpPData->lpRemoteData;
2850 /* Is the user requesting to know how big a buffer is required? */
2851 if( ( lpData == NULL ) ||
2852 ( *lpdwDataSize < dwRequiredBufferSize )
2855 *lpdwDataSize = dwRequiredBufferSize;
2856 return DPERR_BUFFERTOOSMALL;
2859 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2861 return DP_OK;
2864 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2865 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2866 LPDWORD lpdwDataSize, DWORD dwFlags )
2868 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2869 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2870 dwFlags, TRUE );
2873 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2874 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2875 LPDWORD lpdwDataSize, DWORD dwFlags )
2877 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2878 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2879 dwFlags, FALSE );
2882 static HRESULT DP_IF_GetPlayerName
2883 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2884 LPDWORD lpdwDataSize, BOOL bAnsi )
2886 lpPlayerList lpPList;
2887 LPDPNAME lpName = lpData;
2888 DWORD dwRequiredDataSize;
2890 FIXME( "(%p)->(0x%08x,%p,%p,%u): ANSI\n",
2891 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2893 if( This->dp2->connectionInitialized == NO_PROVIDER )
2895 return DPERR_UNINITIALIZED;
2898 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2900 return DPERR_INVALIDPLAYER;
2903 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
2905 if( lpPList->lpPData->name.u1.lpszShortNameA )
2907 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
2910 if( lpPList->lpPData->name.u2.lpszLongNameA )
2912 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
2915 if( ( lpData == NULL ) ||
2916 ( *lpdwDataSize < dwRequiredDataSize )
2919 *lpdwDataSize = dwRequiredDataSize;
2920 return DPERR_BUFFERTOOSMALL;
2923 /* Copy the structure */
2924 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
2926 if( lpPList->lpPData->name.u1.lpszShortNameA )
2928 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2929 lpPList->lpPData->name.u1.lpszShortNameA );
2931 else
2933 lpName->u1.lpszShortNameA = NULL;
2936 if( lpPList->lpPData->name.u2.lpszLongNameA )
2938 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2939 lpPList->lpPData->name.u2.lpszLongNameA );
2941 else
2943 lpName->u2.lpszLongNameA = NULL;
2946 return DP_OK;
2949 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2950 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2951 LPDWORD lpdwDataSize )
2953 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2954 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
2957 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2958 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2959 LPDWORD lpdwDataSize )
2961 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2962 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
2965 static HRESULT DP_GetSessionDesc
2966 ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize,
2967 BOOL bAnsi )
2969 DWORD dwRequiredSize;
2971 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
2973 if( This->dp2->connectionInitialized == NO_PROVIDER )
2975 return DPERR_UNINITIALIZED;
2978 if( !This->dp2->bConnectionOpen )
2980 return DPERR_NOSESSIONS;
2983 if( ( lpdwDataSize == NULL ) || ( *lpdwDataSize >= MAXDWORD ) )
2985 return DPERR_INVALIDPARAMS;
2988 /* FIXME: Get from This->dp2->lpSessionDesc */
2989 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
2991 if ( ( lpData == NULL ) ||
2992 ( *lpdwDataSize < dwRequiredSize )
2995 *lpdwDataSize = dwRequiredSize;
2996 return DPERR_BUFFERTOOSMALL;
2999 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
3001 return DP_OK;
3004 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
3005 ( LPDIRECTPLAY2A iface, LPVOID lpData, LPDWORD lpdwDataSize )
3007 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3008 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
3011 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
3012 ( LPDIRECTPLAY2 iface, LPVOID lpData, LPDWORD lpdwDataSize )
3014 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3015 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
3018 /* Intended only for COM compatibility. Always returns an error. */
3019 static HRESULT WINAPI DirectPlay2AImpl_Initialize
3020 ( LPDIRECTPLAY2A iface, LPGUID lpGUID )
3022 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3023 TRACE("(%p)->(%p): stub\n", This, lpGUID );
3024 return DPERR_ALREADYINITIALIZED;
3027 /* Intended only for COM compatibility. Always returns an error. */
3028 static HRESULT WINAPI DirectPlay2WImpl_Initialize
3029 ( LPDIRECTPLAY2 iface, LPGUID lpGUID )
3031 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3032 TRACE("(%p)->(%p): stub\n", This, lpGUID );
3033 return DPERR_ALREADYINITIALIZED;
3037 static HRESULT DP_SecureOpen
3038 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
3039 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
3040 BOOL bAnsi )
3042 HRESULT hr = DP_OK;
3044 FIXME( "(%p)->(%p,0x%08x,%p,%p): partial stub\n",
3045 This, lpsd, dwFlags, lpSecurity, lpCredentials );
3047 if( ( lpsd == NULL ) ||
3048 ( lpsd->dwSize != sizeof(DPSESSIONDESC2) ) )
3050 return DPERR_INVALIDPARAMS;
3053 if( This->dp2->bConnectionOpen )
3055 TRACE( ": rejecting already open connection.\n" );
3056 return DPERR_ALREADYINITIALIZED;
3059 /* If we're enumerating, kill the thread */
3060 DP_KillEnumSessionThread( This );
3062 if( dwFlags & DPOPEN_JOIN )
3064 LPDPSESSIONDESC2 current = NULL;
3065 NS_ResetSessionEnumeration( This->dp2->lpNameServerData );
3066 while( ( current = NS_WalkSessions( This->dp2->lpNameServerData ) ) )
3068 if ( IsEqualGUID( &lpsd->guidInstance, &current->guidInstance ) )
3069 break;
3071 if ( current == NULL )
3072 return DPERR_NOSESSIONS;
3074 else if( dwFlags & DPOPEN_CREATE )
3076 /* Rightoo - this computer is the host and the local computer needs to be
3077 the name server so that others can join this session */
3078 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
3080 This->dp2->bHostInterface = TRUE;
3082 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
3083 if( FAILED( hr ) )
3085 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
3086 return hr;
3090 /* Invoke the conditional callback for the service provider */
3091 if( This->dp2->spData.lpCB->Open )
3093 DPSP_OPENDATA data;
3095 FIXME( "Not all data fields are correct. Need new parameter\n" );
3097 data.bCreate = (dwFlags & DPOPEN_CREATE ) ? TRUE : FALSE;
3098 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
3099 : NS_GetNSAddr( This->dp2->lpNameServerData );
3100 data.lpISP = This->dp2->spData.lpISP;
3101 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) ? TRUE : FALSE;
3102 data.dwOpenFlags = dwFlags;
3103 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
3105 hr = (*This->dp2->spData.lpCB->Open)(&data);
3106 if( FAILED( hr ) )
3108 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
3109 return hr;
3114 /* Create the system group of which everything is a part of */
3115 DPID systemGroup = DPID_SYSTEM_GROUP;
3117 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
3118 NULL, 0, 0, TRUE );
3122 if( dwFlags & DPOPEN_JOIN )
3124 DPID dpidServerId = DPID_UNKNOWN;
3126 /* Create the server player for this interface. This way we can receive
3127 * messages for this session.
3129 /* FIXME: I suppose that we should be setting an event for a receive
3130 * type of thing. That way the messaging thread could know to wake
3131 * up. DPlay would then trigger the hEvent for the player the
3132 * message is directed to.
3134 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
3136 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
3139 else if( dwFlags & DPOPEN_CREATE )
3141 DPID dpidNameServerId = DPID_NAME_SERVER;
3143 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
3144 0, DPPLAYER_SERVERPLAYER, bAnsi );
3147 if( FAILED(hr) )
3149 ERR( "Couldn't create name server/system player: %s\n",
3150 DPLAYX_HresultToString(hr) );
3152 else
3154 This->dp2->bConnectionOpen = TRUE;
3157 return hr;
3160 static HRESULT WINAPI DirectPlay2AImpl_Open
3161 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
3163 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3164 TRACE("(%p)->(%p,0x%08x)\n", This, lpsd, dwFlags );
3165 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, TRUE );
3168 static HRESULT WINAPI DirectPlay2WImpl_Open
3169 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
3171 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3172 TRACE("(%p)->(%p,0x%08x)\n", This, lpsd, dwFlags );
3173 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, FALSE );
3176 static HRESULT DP_IF_Receive
3177 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
3178 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi )
3180 LPDPMSG lpMsg = NULL;
3182 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p,%u): stub\n",
3183 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
3185 if( This->dp2->connectionInitialized == NO_PROVIDER )
3187 return DPERR_UNINITIALIZED;
3190 if ( ( lpdwDataSize == NULL ) ||
3191 ( ( dwFlags & DPRECEIVE_FROMPLAYER ) && ( lpidFrom == NULL ) ) ||
3192 ( ( dwFlags & DPRECEIVE_TOPLAYER ) && ( lpidTo == NULL ) ) )
3194 return DPERR_INVALIDPARAMS;
3197 if( dwFlags == 0 )
3199 dwFlags = DPRECEIVE_ALL;
3202 if( dwFlags & DPRECEIVE_ALL )
3204 lpMsg = DPQ_FIRST( This->dp2->receiveMsgs );
3206 else
3208 if ( (lpMsg = DPQ_FIRST( This->dp2->receiveMsgs )) )
3212 if ( ( ( dwFlags & DPRECEIVE_FROMPLAYER ) &&
3213 ( dwFlags & DPRECEIVE_TOPLAYER ) &&
3214 ( lpMsg->idFrom == *lpidFrom ) &&
3215 ( lpMsg->idTo == *lpidTo ) ) || /* From & To */
3216 ( ( dwFlags & DPRECEIVE_FROMPLAYER ) &&
3217 ( lpMsg->idFrom == *lpidFrom ) ) || /* From */
3218 ( ( dwFlags & DPRECEIVE_TOPLAYER ) &&
3219 ( lpMsg->idTo == *lpidTo ) ) ) /* To */
3221 break;
3224 while( (lpMsg = DPQ_NEXT( lpMsg->msgs )) );
3228 if( lpMsg == NULL )
3230 return DPERR_NOMESSAGES;
3233 /* Buffer size check */
3234 if ( ( lpData == NULL ) ||
3235 ( *lpdwDataSize < lpMsg->dwMsgSize ) )
3237 *lpdwDataSize = lpMsg->dwMsgSize;
3238 return DPERR_BUFFERTOOSMALL;
3241 /* Copy into the provided buffer */
3242 if (lpData) CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
3244 /* Set players */
3245 if ( lpidFrom )
3247 *lpidFrom = lpMsg->idFrom;
3249 if ( lpidTo )
3251 *lpidTo = lpMsg->idTo;
3254 /* Remove message from queue */
3255 if( !( dwFlags & DPRECEIVE_PEEK ) )
3257 HeapFree( GetProcessHeap(), 0, lpMsg->msg );
3258 DPQ_REMOVE( This->dp2->receiveMsgs, lpMsg, msgs );
3259 HeapFree( GetProcessHeap(), 0, lpMsg );
3262 return DP_OK;
3265 static HRESULT WINAPI DirectPlay2AImpl_Receive
3266 ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo,
3267 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
3269 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3270 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
3271 lpData, lpdwDataSize, TRUE );
3274 static HRESULT WINAPI DirectPlay2WImpl_Receive
3275 ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo,
3276 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
3278 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3279 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
3280 lpData, lpdwDataSize, FALSE );
3283 static HRESULT WINAPI DirectPlay2AImpl_Send
3284 ( LPDIRECTPLAY2A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3286 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3287 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3288 0, 0, NULL, NULL, TRUE );
3291 static HRESULT WINAPI DirectPlay2WImpl_Send
3292 ( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3294 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3295 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3296 0, 0, NULL, NULL, FALSE );
3299 static HRESULT DP_IF_SetGroupData
3300 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
3301 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3303 lpGroupData lpGData;
3305 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3306 This, idGroup, lpData, dwDataSize, dwFlags, bAnsi );
3308 /* Parameter check */
3309 if( ( lpData == NULL ) &&
3310 ( dwDataSize != 0 )
3313 return DPERR_INVALIDPARAMS;
3316 /* Find the pointer to the data for this player */
3317 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3319 return DPERR_INVALIDOBJECT;
3322 if( !(dwFlags & DPSET_LOCAL) )
3324 FIXME( "Was this group created by this interface?\n" );
3325 /* FIXME: If this is a remote update need to allow it but not
3326 * send a message.
3330 DP_SetGroupData( lpGData, dwFlags, lpData, dwDataSize );
3332 /* FIXME: Only send a message if this group is local to the session otherwise
3333 * it will have been rejected above
3335 if( !(dwFlags & DPSET_LOCAL) )
3337 FIXME( "Send msg?\n" );
3340 return DP_OK;
3343 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
3344 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
3345 DWORD dwDataSize, DWORD dwFlags )
3347 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3348 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, TRUE );
3351 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
3352 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
3353 DWORD dwDataSize, DWORD dwFlags )
3355 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3356 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, FALSE );
3359 static HRESULT DP_IF_SetGroupName
3360 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
3361 DWORD dwFlags, BOOL bAnsi )
3363 lpGroupData lpGData;
3365 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n", This, idGroup,
3366 lpGroupName, dwFlags, bAnsi );
3368 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3370 return DPERR_INVALIDGROUP;
3373 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
3375 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3376 FIXME( "Message not sent and dwFlags ignored\n" );
3378 return DP_OK;
3381 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
3382 ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName,
3383 DWORD dwFlags )
3385 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3386 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
3389 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
3390 ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName,
3391 DWORD dwFlags )
3393 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3394 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
3397 static HRESULT DP_IF_SetPlayerData
3398 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
3399 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3401 lpPlayerList lpPList;
3403 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3404 This, idPlayer, lpData, dwDataSize, dwFlags, bAnsi );
3406 if( This->dp2->connectionInitialized == NO_PROVIDER )
3408 return DPERR_UNINITIALIZED;
3411 /* Parameter check */
3412 if( ( ( lpData == NULL ) && ( dwDataSize != 0 ) ) ||
3413 ( dwDataSize >= MAXDWORD ) )
3415 return DPERR_INVALIDPARAMS;
3418 /* Find the pointer to the data for this player */
3419 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3421 return DPERR_INVALIDPLAYER;
3424 if( !(dwFlags & DPSET_LOCAL) )
3426 FIXME( "Was this group created by this interface?\n" );
3427 /* FIXME: If this is a remote update need to allow it but not
3428 * send a message.
3432 DP_SetPlayerData( lpPList->lpPData, dwFlags, lpData, dwDataSize );
3434 if( !(dwFlags & DPSET_LOCAL) )
3436 FIXME( "Send msg?\n" );
3439 return DP_OK;
3442 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3443 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
3444 DWORD dwDataSize, DWORD dwFlags )
3446 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3447 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3448 dwFlags, TRUE );
3451 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3452 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
3453 DWORD dwDataSize, DWORD dwFlags )
3455 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3456 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3457 dwFlags, FALSE );
3460 static HRESULT DP_IF_SetPlayerName
3461 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
3462 DWORD dwFlags, BOOL bAnsi )
3464 lpPlayerList lpPList;
3466 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n",
3467 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3469 if( This->dp2->connectionInitialized == NO_PROVIDER )
3471 return DPERR_UNINITIALIZED;
3474 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3476 return DPERR_INVALIDGROUP;
3479 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3481 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3482 FIXME( "Message not sent and dwFlags ignored\n" );
3484 return DP_OK;
3487 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3488 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName,
3489 DWORD dwFlags )
3491 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3492 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3495 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3496 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName,
3497 DWORD dwFlags )
3499 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3500 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3503 HRESULT DP_SetSessionDesc
3504 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
3505 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3507 DWORD dwRequiredSize;
3508 LPDPSESSIONDESC2 lpTempSessDesc;
3510 TRACE( "(%p)->(%p,0x%08x,%u,%u)\n",
3511 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3513 /* FIXME: Copy into This->dp2->lpSessionDesc */
3514 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3515 lpTempSessDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize );
3517 if( lpTempSessDesc == NULL )
3519 return DPERR_OUTOFMEMORY;
3522 /* Free the old */
3523 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3525 This->dp2->lpSessionDesc = lpTempSessDesc;
3526 /* Set the new */
3527 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3528 if( bInitial )
3530 /*Initializing session GUID*/
3531 CoCreateGuid( &(This->dp2->lpSessionDesc->guidInstance) );
3533 /* If this is an external invocation of the interface, we should be
3534 * letting everyone know that things have changed. Otherwise this is
3535 * just an initialization and it doesn't need to be propagated.
3537 if( !bInitial )
3539 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3542 return DP_OK;
3545 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3546 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3548 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3550 if( This->dp2->connectionInitialized == NO_PROVIDER )
3552 return DPERR_UNINITIALIZED;
3555 if( !This->dp2->bConnectionOpen )
3557 return DPERR_NOSESSIONS;
3560 if( dwFlags || (lpSessDesc == NULL) )
3562 return DPERR_INVALIDPARAMS;
3565 /* Illegal combinations of flags */
3566 if ( ( lpSessDesc->dwFlags & DPSESSION_MIGRATEHOST ) &&
3567 ( lpSessDesc->dwFlags & ( DPSESSION_CLIENTSERVER |
3568 DPSESSION_MULTICASTSERVER |
3569 DPSESSION_SECURESERVER ) ) )
3571 return DPERR_INVALIDFLAGS;
3574 /* Only the host is allowed to update the session desc */
3575 if( !This->dp2->bHostInterface )
3577 return DPERR_ACCESSDENIED;
3580 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3583 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3584 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3586 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3588 if( This->dp2->connectionInitialized == NO_PROVIDER )
3590 return DPERR_UNINITIALIZED;
3593 if( !This->dp2->bConnectionOpen )
3595 return DPERR_NOSESSIONS;
3598 if( dwFlags || (lpSessDesc == NULL) )
3600 return DPERR_INVALIDPARAMS;
3603 /* Illegal combinations of flags */
3604 if ( ( lpSessDesc->dwFlags & DPSESSION_MIGRATEHOST ) &&
3605 ( lpSessDesc->dwFlags & ( DPSESSION_CLIENTSERVER |
3606 DPSESSION_MULTICASTSERVER |
3607 DPSESSION_SECURESERVER ) ) )
3609 return DPERR_INVALIDFLAGS;
3612 /* Only the host is allowed to update the session desc */
3613 if( !This->dp2->bHostInterface )
3615 return DPERR_ACCESSDENIED;
3618 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3621 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3622 static DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3624 DWORD dwSize = 0;
3626 if( lpSessDesc == NULL )
3628 /* Hmmm..don't need any size? */
3629 ERR( "NULL lpSessDesc\n" );
3630 return dwSize;
3633 dwSize += sizeof( *lpSessDesc );
3635 if( bAnsi )
3637 if( lpSessDesc->u1.lpszSessionNameA )
3639 dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1;
3642 if( lpSessDesc->u2.lpszPasswordA )
3644 dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1;
3647 else /* UNICODE */
3649 if( lpSessDesc->u1.lpszSessionName )
3651 dwSize += sizeof( WCHAR ) *
3652 ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 );
3655 if( lpSessDesc->u2.lpszPassword )
3657 dwSize += sizeof( WCHAR ) *
3658 ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 );
3662 return dwSize;
3665 /* Assumes that contiguous buffers are already allocated. */
3666 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3667 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3669 BYTE* lpStartOfFreeSpace;
3671 if( lpSessionDest == NULL )
3673 ERR( "NULL lpSessionDest\n" );
3674 return;
3677 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3679 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3681 if( bAnsi )
3683 if( lpSessionSrc->u1.lpszSessionNameA )
3685 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3686 lpSessionDest->u1.lpszSessionNameA );
3687 lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3688 lpStartOfFreeSpace +=
3689 lstrlenA( lpSessionDest->u1.lpszSessionNameA ) + 1;
3692 if( lpSessionSrc->u2.lpszPasswordA )
3694 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3695 lpSessionDest->u2.lpszPasswordA );
3696 lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3697 lpStartOfFreeSpace +=
3698 lstrlenA( lpSessionDest->u2.lpszPasswordA ) + 1;
3701 else /* UNICODE */
3703 if( lpSessionSrc->u1.lpszSessionName )
3705 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3706 lpSessionDest->u1.lpszSessionName );
3707 lpSessionDest->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3708 lpStartOfFreeSpace += sizeof(WCHAR) *
3709 ( lstrlenW( lpSessionDest->u1.lpszSessionName ) + 1 );
3712 if( lpSessionSrc->u2.lpszPassword )
3714 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3715 lpSessionDest->u2.lpszPassword );
3716 lpSessionDest->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3717 lpStartOfFreeSpace += sizeof(WCHAR) *
3718 ( lstrlenW( lpSessionDest->u2.lpszPassword ) + 1 );
3724 static HRESULT DP_IF_AddGroupToGroup
3725 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3727 lpGroupData lpGData;
3728 lpGroupList lpNewGList;
3730 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, idParentGroup, idGroup );
3732 if( This->dp2->connectionInitialized == NO_PROVIDER )
3734 return DPERR_UNINITIALIZED;
3737 if( DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) == NULL )
3739 return DPERR_INVALIDGROUP;
3742 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3744 return DPERR_INVALIDGROUP;
3747 /* Create a player list (ie "shortcut" ) */
3748 lpNewGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewGList ) );
3749 if( lpNewGList == NULL )
3751 return DPERR_CANTADDPLAYER;
3754 /* Add the shortcut */
3755 lpGData->uRef++;
3756 lpNewGList->lpGData = lpGData;
3758 /* Add the player to the list of players for this group */
3759 DPQ_INSERT( lpGData->groups, lpNewGList, groups );
3761 /* Send a ADDGROUPTOGROUP message */
3762 FIXME( "Not sending message\n" );
3764 return DP_OK;
3767 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3768 ( LPDIRECTPLAY3A iface, DPID idParentGroup, DPID idGroup )
3770 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3771 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3774 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3775 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3777 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3778 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3781 static HRESULT DP_IF_CreateGroupInGroup
3782 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
3783 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
3784 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3786 lpGroupData lpGParentData;
3787 lpGroupList lpGList;
3788 lpGroupData lpGData;
3790 TRACE( "(%p)->(0x%08x,%p,%p,%p,0x%08x,0x%08x,%u)\n",
3791 This, idParentGroup, lpidGroup, lpGroupName, lpData,
3792 dwDataSize, dwFlags, bAnsi );
3794 /* Verify that the specified parent is valid */
3795 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This,
3796 idParentGroup ) ) == NULL
3799 return DPERR_INVALIDGROUP;
3802 lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName,
3803 dwFlags, idParentGroup, bAnsi );
3805 if( lpGData == NULL )
3807 return DPERR_CANTADDPLAYER; /* yes player not group */
3810 /* Something else is referencing this data */
3811 lpGData->uRef++;
3813 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
3815 /* The list has now been inserted into the interface group list. We now
3816 need to put a "shortcut" to this group in the parent group */
3817 lpGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGList ) );
3818 if( lpGList == NULL )
3820 FIXME( "Memory leak\n" );
3821 return DPERR_CANTADDPLAYER; /* yes player not group */
3824 lpGList->lpGData = lpGData;
3826 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
3828 /* Let the SP know that we've created this group */
3829 if( This->dp2->spData.lpCB->CreateGroup )
3831 DPSP_CREATEGROUPDATA data;
3833 TRACE( "Calling SP CreateGroup\n" );
3835 data.idGroup = *lpidGroup;
3836 data.dwFlags = dwFlags;
3837 data.lpSPMessageHeader = lpMsgHdr;
3838 data.lpISP = This->dp2->spData.lpISP;
3840 (*This->dp2->spData.lpCB->CreateGroup)( &data );
3843 /* Inform all other peers of the creation of a new group. If there are
3844 * no peers keep this quiet.
3846 if( This->dp2->lpSessionDesc &&
3847 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
3849 DPMSG_CREATEPLAYERORGROUP msg;
3851 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
3852 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
3853 msg.dpId = *lpidGroup;
3854 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
3855 msg.lpData = lpData;
3856 msg.dwDataSize = dwDataSize;
3857 msg.dpnName = *lpGroupName;
3859 /* FIXME: Correct to just use send effectively? */
3860 /* FIXME: Should size include data w/ message or just message "header" */
3861 /* FIXME: Check return code */
3862 DP_SendEx( (IDirectPlay2Impl*)This,
3863 DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
3864 0, 0, NULL, NULL, bAnsi );
3867 return DP_OK;
3870 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3871 ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup,
3872 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3873 DWORD dwFlags )
3875 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3877 if( This->dp2->connectionInitialized == NO_PROVIDER )
3879 return DPERR_UNINITIALIZED;
3882 if( lpidGroup == NULL ||
3883 !This->dp2->bConnectionOpen ||
3884 dwDataSize >= MAXDWORD ||
3885 ( lpData == NULL && dwDataSize != 0 ) )
3887 return DPERR_INVALIDPARAMS;
3890 *lpidGroup = DPID_UNKNOWN;
3892 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3893 lpGroupName, lpData, dwDataSize, dwFlags,
3894 TRUE );
3897 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3898 ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup,
3899 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3900 DWORD dwFlags )
3902 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3904 if( This->dp2->connectionInitialized == NO_PROVIDER )
3906 return DPERR_UNINITIALIZED;
3909 if( lpidGroup == NULL ||
3910 !This->dp2->bConnectionOpen ||
3911 dwDataSize >= MAXDWORD ||
3912 ( lpData == NULL && dwDataSize != 0 ) )
3914 return DPERR_INVALIDPARAMS;
3917 *lpidGroup = DPID_UNKNOWN;
3919 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3920 lpGroupName, lpData, dwDataSize,
3921 dwFlags, FALSE );
3924 static HRESULT DP_IF_DeleteGroupFromGroup
3925 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3927 lpGroupList lpGList;
3928 lpGroupData lpGParentData;
3930 TRACE("(%p)->(0x%08x,0x%08x)\n", This, idParentGroup, idGroup );
3932 /* Is the parent group valid? */
3933 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3935 return DPERR_INVALIDGROUP;
3938 /* Remove the group from the parent group queue */
3939 DPQ_REMOVE_ENTRY( lpGParentData->groups, groups, lpGData->dpid, ==, idGroup, lpGList );
3941 if( lpGList == NULL )
3943 return DPERR_INVALIDGROUP;
3946 /* Decrement the ref count */
3947 lpGList->lpGData->uRef--;
3949 /* Free up the list item */
3950 HeapFree( GetProcessHeap(), 0, lpGList );
3952 /* Should send a DELETEGROUPFROMGROUP message */
3953 FIXME( "message not sent\n" );
3955 return DP_OK;
3958 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3959 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3961 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3962 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3965 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3966 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3968 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3969 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3971 static BOOL DP_BuildCompoundAddr( GUID guidDataType,
3972 LPGUID lpcSpGuid,
3973 LPVOID* lplpAddrBuf,
3974 LPDWORD lpdwBufSize )
3976 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3977 HRESULT hr;
3979 dpCompoundAddress.dwDataSize = sizeof( GUID );
3980 dpCompoundAddress.guidDataType = guidDataType;
3981 dpCompoundAddress.lpData = lpcSpGuid;
3983 *lplpAddrBuf = NULL;
3984 *lpdwBufSize = 0;
3986 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3987 lpdwBufSize, TRUE );
3989 if( hr != DPERR_BUFFERTOOSMALL )
3991 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3992 return FALSE;
3995 /* Now allocate the buffer */
3996 *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3997 *lpdwBufSize );
3999 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
4000 lpdwBufSize, TRUE );
4001 if( FAILED(hr) )
4003 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
4004 return FALSE;
4007 return TRUE;
4010 static HRESULT WINAPI DP_IF_EnumConnections
4011 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication,
4012 LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext,
4013 DWORD dwFlags, BOOL bAnsi )
4015 HKEY hkResult;
4016 WCHAR searchSubKeySP[] = {
4017 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
4018 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
4019 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
4020 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
4021 WCHAR searchSubKeyLP[] = {
4022 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
4023 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
4024 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
4025 'L', 'o', 'b', 'b', 'y', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
4026 WCHAR guidDataSubKey[] = { 'G', 'u', 'i', 'd', 0 };
4027 WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */
4028 DWORD dwIndex, sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR);
4029 FILETIME filetime;
4031 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
4032 if( dwFlags == 0 )
4034 dwFlags = DPCONNECTION_DIRECTPLAY;
4037 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
4038 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) ) )
4040 return DPERR_INVALIDFLAGS;
4043 if( !lpEnumCallback )
4045 return DPERR_INVALIDPARAMS;
4049 /* Need to loop over the service providers in the registry */
4050 if( RegOpenKeyExW( HKEY_LOCAL_MACHINE,
4051 ( dwFlags & DPCONNECTION_DIRECTPLAY ) ? searchSubKeySP
4052 : searchSubKeyLP,
4053 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4055 /* Hmmm. Does this mean that there are no service providers? */
4056 ERR(": no service providers?\n");
4057 return DP_OK;
4061 /* Traverse all the service providers we have available */
4062 for( dwIndex=0;
4063 RegEnumKeyExW( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4064 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4065 ++dwIndex, sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR) )
4067 HKEY hkServiceProvider;
4068 GUID serviceProviderGUID;
4069 WCHAR guidKeyContent[39];
4070 DWORD sizeOfReturnBuffer = sizeof(guidKeyContent);
4071 DPNAME dpName;
4072 BOOL continueEnumeration = TRUE;
4074 LPVOID lpAddressBuffer = NULL;
4075 DWORD dwAddressBufferSize = 0;
4078 TRACE(" this time through: %s\n", debugstr_w(subKeyName) );
4080 /* Get a handle for this particular service provider */
4081 if( RegOpenKeyExW( hkResult, subKeyName, 0, KEY_READ,
4082 &hkServiceProvider ) != ERROR_SUCCESS )
4084 ERR(": what the heck is going on?\n" );
4085 continue;
4088 if( RegQueryValueExW( hkServiceProvider, guidDataSubKey,
4089 NULL, NULL, (LPBYTE)guidKeyContent,
4090 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4092 ERR(": missing GUID registry data members\n" );
4093 RegCloseKey(hkServiceProvider);
4094 continue;
4096 RegCloseKey(hkServiceProvider);
4098 CLSIDFromString( guidKeyContent, &serviceProviderGUID );
4100 /* Fill in the DPNAME struct for the service provider */
4101 dpName.dwSize = sizeof( dpName );
4102 dpName.dwFlags = 0;
4103 if ( bAnsi )
4105 dpName.u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4106 sizeOfSubKeyName+1 );
4107 WideCharToMultiByte( CP_ACP, 0, subKeyName,
4108 -1, dpName.u1.lpszShortNameA, -1, 0, 0);
4109 dpName.u2.lpszLongNameA = NULL;
4111 else
4113 dpName.u1.lpszShortName = subKeyName;
4114 dpName.u2.lpszLongName = NULL;
4117 /* Create the compound address for the service provider.
4118 * NOTE: This is a gruesome architectural scar right now. DP
4119 * uses DPL and DPL uses DP. Nasty stuff. This may be why the
4120 * native dll just gets around this little bit by allocating an
4121 * 80 byte buffer which isn't even filled with a valid compound
4122 * address. Oh well. Creating a proper compound address is the
4123 * way to go anyways despite this method taking slightly more
4124 * heap space and realtime :) */
4126 if ( DP_BuildCompoundAddr( ( ( dwFlags & DPCONNECTION_DIRECTPLAY )
4127 ? DPAID_ServiceProvider
4128 : DPAID_LobbyProvider ),
4129 &serviceProviderGUID,
4130 &lpAddressBuffer,
4131 &dwAddressBufferSize ) )
4133 /* The enumeration will return FALSE if we are not to continue */
4134 continueEnumeration = lpEnumCallback( &serviceProviderGUID, lpAddressBuffer,
4135 dwAddressBufferSize, &dpName,
4136 dwFlags, lpContext );
4138 else
4140 ERR( "Couldn't build compound address\n" );
4143 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
4144 if ( bAnsi )
4145 HeapFree( GetProcessHeap(), 0, dpName.u1.lpszShortNameA );
4147 if (!continueEnumeration)
4148 return DP_OK;
4151 return DP_OK;
4154 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
4155 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
4157 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4158 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
4159 return DP_IF_EnumConnections( iface, lpguidApplication, lpEnumCallback, lpContext, dwFlags, TRUE );
4162 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
4163 ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
4165 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4166 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
4167 return DP_IF_EnumConnections( iface, lpguidApplication, lpEnumCallback, lpContext, dwFlags, FALSE );
4170 static HRESULT DP_IF_EnumGroupsInGroup
4171 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
4172 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
4173 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
4175 lpGroupList lpGList;
4176 lpGroupData lpGData;
4178 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
4179 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
4180 lpContext, dwFlags, bAnsi );
4182 if( This->dp2->connectionInitialized == NO_PROVIDER )
4184 return DPERR_UNINITIALIZED;
4187 if( !This->dp2->bConnectionOpen )
4189 return DPERR_NOSESSIONS;
4192 if( ( lpEnumPlayersCallback2 == NULL ) ||
4193 ( ( dwFlags & DPENUMGROUPS_SESSION ) && ( lpguidInstance == NULL ) ) )
4195 return DPERR_INVALIDPARAMS;
4198 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4200 return DPERR_INVALIDGROUP;
4203 if( DPQ_IS_EMPTY( lpGData->groups ) )
4205 return DP_OK;
4208 lpGList = DPQ_FIRST( lpGData->groups );
4210 for( ;; )
4212 /* FIXME: Should check dwFlags for match here */
4214 if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP,
4215 &lpGList->lpGData->name, dwFlags,
4216 lpContext ) )
4218 return DP_OK; /* User requested break */
4221 if( DPQ_IS_ENDOFLIST( lpGList->groups ) )
4223 break;
4226 lpGList = DPQ_NEXT( lpGList->groups );
4230 return DP_OK;
4233 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
4234 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
4235 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
4236 DWORD dwFlags )
4238 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4239 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
4240 lpEnumPlayersCallback2, lpContext, dwFlags,
4241 TRUE );
4244 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
4245 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
4246 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
4247 DWORD dwFlags )
4249 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4250 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
4251 lpEnumPlayersCallback2, lpContext, dwFlags,
4252 FALSE );
4255 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
4256 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
4258 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4259 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
4260 return DP_OK;
4263 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
4264 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
4266 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4267 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
4268 return DP_OK;
4271 static BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
4272 REFGUID guidDataType,
4273 DWORD dwDataSize,
4274 LPCVOID lpData,
4275 LPVOID lpContext )
4277 /* Looking for the GUID of the provider to load */
4278 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
4279 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
4282 TRACE( "Found SP/LP (%s) %s (data size = 0x%08x)\n",
4283 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
4285 if( dwDataSize != sizeof( GUID ) )
4287 ERR( "Invalid sp/lp guid size 0x%08x\n", dwDataSize );
4290 memcpy( lpContext, lpData, dwDataSize );
4292 /* There shouldn't be more than 1 GUID/compound address */
4293 return FALSE;
4296 /* Still waiting for what we want */
4297 return TRUE;
4301 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
4302 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
4304 UINT i;
4305 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4306 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
4307 LPCSTR guidDataSubKey = "Guid";
4308 LPCSTR majVerDataSubKey = "dwReserved1";
4309 LPCSTR minVerDataSubKey = "dwReserved2";
4310 LPCSTR pathSubKey = "Path";
4312 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
4314 /* FIXME: Cloned code with a quick hack. */
4315 for( i=0; i<2; i++ )
4317 HKEY hkResult;
4318 LPCSTR searchSubKey;
4319 char subKeyName[51];
4320 DWORD dwIndex, sizeOfSubKeyName=50;
4321 FILETIME filetime;
4323 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
4324 *lpbIsDpSp = (i == 0) ? TRUE : FALSE;
4327 /* Need to loop over the service providers in the registry */
4328 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4329 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4331 /* Hmmm. Does this mean that there are no service providers? */
4332 ERR(": no service providers?\n");
4333 return 0;
4336 /* Traverse all the service providers we have available */
4337 for( dwIndex=0;
4338 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4339 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4340 ++dwIndex, sizeOfSubKeyName=51 )
4343 HKEY hkServiceProvider;
4344 GUID serviceProviderGUID;
4345 DWORD returnType, sizeOfReturnBuffer = 255;
4346 char returnBuffer[256];
4347 WCHAR buff[51];
4348 DWORD dwTemp, len;
4350 TRACE(" this time through: %s\n", subKeyName );
4352 /* Get a handle for this particular service provider */
4353 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4354 &hkServiceProvider ) != ERROR_SUCCESS )
4356 ERR(": what the heck is going on?\n" );
4357 continue;
4360 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4361 NULL, &returnType, (LPBYTE)returnBuffer,
4362 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4364 ERR(": missing GUID registry data members\n" );
4365 continue;
4368 /* FIXME: Check return types to ensure we're interpreting data right */
4369 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4370 CLSIDFromString( buff, &serviceProviderGUID );
4371 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4373 /* Determine if this is the Service Provider that the user asked for */
4374 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
4376 continue;
4379 if( i == 0 ) /* DP SP */
4381 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
4382 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
4383 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
4386 sizeOfReturnBuffer = 255;
4388 /* Get dwReserved1 */
4389 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
4390 NULL, &returnType, (LPBYTE)returnBuffer,
4391 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4393 ERR(": missing dwReserved1 registry data members\n") ;
4394 continue;
4397 if( i == 0 )
4398 memcpy( &lpSpData->dwReserved1, returnBuffer, sizeof(lpSpData->dwReserved1) );
4400 sizeOfReturnBuffer = 255;
4402 /* Get dwReserved2 */
4403 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4404 NULL, &returnType, (LPBYTE)returnBuffer,
4405 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4407 ERR(": missing dwReserved1 registry data members\n") ;
4408 continue;
4411 if( i == 0 )
4412 memcpy( &lpSpData->dwReserved2, returnBuffer, sizeof(lpSpData->dwReserved2) );
4414 sizeOfReturnBuffer = 255;
4416 /* Get the path for this service provider */
4417 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
4418 NULL, NULL, (LPBYTE)returnBuffer,
4419 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
4421 ERR(": missing PATH registry data members: 0x%08x\n", dwTemp );
4422 continue;
4425 TRACE( "Loading %s\n", returnBuffer );
4426 return LoadLibraryA( returnBuffer );
4430 return 0;
4433 static
4434 HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider )
4436 HRESULT hr;
4437 LPDPSP_SPINIT SPInit;
4439 /* Initialize the service provider by calling SPInit */
4440 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4442 if( SPInit == NULL )
4444 ERR( "Service provider doesn't provide SPInit interface?\n" );
4445 FreeLibrary( hServiceProvider );
4446 return DPERR_UNAVAILABLE;
4449 TRACE( "Calling SPInit (DP SP entry point)\n" );
4451 hr = (*SPInit)( &This->dp2->spData );
4453 if( FAILED(hr) )
4455 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4456 FreeLibrary( hServiceProvider );
4457 return hr;
4460 /* FIXME: Need to verify the sanity of the returned callback table
4461 * using IsBadCodePtr */
4462 This->dp2->bSPInitialized = TRUE;
4464 /* This interface is now initialized as a DP object */
4465 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
4467 /* Store the handle of the module so that we can unload it later */
4468 This->dp2->hServiceProvider = hServiceProvider;
4470 return hr;
4473 static
4474 HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hLobbyProvider )
4476 HRESULT hr;
4477 LPSP_INIT DPLSPInit;
4479 /* Initialize the service provider by calling SPInit */
4480 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
4482 if( DPLSPInit == NULL )
4484 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4485 FreeLibrary( hLobbyProvider );
4486 return DPERR_UNAVAILABLE;
4489 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4491 hr = (*DPLSPInit)( &This->dp2->dplspData );
4493 if( FAILED(hr) )
4495 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4496 FreeLibrary( hLobbyProvider );
4497 return hr;
4500 /* FIXME: Need to verify the sanity of the returned callback table
4501 * using IsBadCodePtr */
4503 This->dp2->bDPLSPInitialized = TRUE;
4505 /* This interface is now initialized as a lobby object */
4506 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
4508 /* Store the handle of the module so that we can unload it later */
4509 This->dp2->hDPLobbyProvider = hLobbyProvider;
4511 return hr;
4514 static HRESULT DP_IF_InitializeConnection
4515 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi )
4517 HMODULE hServiceProvider;
4518 HRESULT hr;
4519 GUID guidSP;
4520 const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
4521 BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4523 TRACE("(%p)->(%p,0x%08x,%u)\n", This, lpConnection, dwFlags, bAnsi );
4525 if ( lpConnection == NULL )
4527 return DPERR_INVALIDPARAMS;
4530 if( dwFlags != 0 )
4532 return DPERR_INVALIDFLAGS;
4535 if( This->dp2->connectionInitialized != NO_PROVIDER )
4537 return DPERR_ALREADYINITIALIZED;
4540 /* Find out what the requested SP is and how large this buffer is */
4541 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
4542 dwAddrSize, &guidSP );
4544 if( FAILED(hr) )
4546 ERR( "Invalid compound address?\n" );
4547 return DPERR_UNAVAILABLE;
4550 /* Load the service provider */
4551 hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp );
4553 if( hServiceProvider == 0 )
4555 ERR( "Unable to load service provider %s\n", debugstr_guid(&guidSP) );
4556 return DPERR_UNAVAILABLE;
4559 if( bIsDpSp )
4561 /* Fill in what we can of the Service Provider required information.
4562 * The rest was be done in DP_LoadSP
4564 This->dp2->spData.lpAddress = lpConnection;
4565 This->dp2->spData.dwAddressSize = dwAddrSize;
4566 This->dp2->spData.lpGuid = &guidSP;
4568 hr = DP_InitializeDPSP( This, hServiceProvider );
4570 else
4572 This->dp2->dplspData.lpAddress = lpConnection;
4574 hr = DP_InitializeDPLSP( This, hServiceProvider );
4577 if( FAILED(hr) )
4579 return hr;
4582 return DP_OK;
4585 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4586 ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
4588 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4589 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE );
4592 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4593 ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
4595 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4596 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE );
4599 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4600 ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4601 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4603 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4604 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4607 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4608 ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4609 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4611 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4612 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4615 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4616 ( LPDIRECTPLAY3A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4618 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4619 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4620 return DP_OK;
4623 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4624 ( LPDIRECTPLAY3 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4626 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4627 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4628 return DP_OK;
4631 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4632 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4634 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4635 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4636 return DP_OK;
4639 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4640 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4642 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4643 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4644 return DP_OK;
4647 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4648 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup )
4650 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4651 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, dwFlags, idGroup );
4652 return DP_OK;
4655 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4656 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup )
4658 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4659 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, dwFlags, idGroup );
4660 return DP_OK;
4663 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4664 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDWORD lpdwFlags )
4666 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4667 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpdwFlags );
4668 return DP_OK;
4671 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4672 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDWORD lpdwFlags )
4674 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4675 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpdwFlags );
4676 return DP_OK;
4679 static HRESULT DP_IF_GetGroupParent
4680 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
4681 BOOL bAnsi )
4683 lpGroupData lpGData;
4685 TRACE("(%p)->(0x%08x,%p,%u)\n", This, idGroup, lpidGroup, bAnsi );
4687 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4689 return DPERR_INVALIDGROUP;
4692 *lpidGroup = lpGData->dpid;
4694 return DP_OK;
4697 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4698 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
4700 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4701 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE );
4703 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4704 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
4706 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4707 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE );
4710 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4711 ( LPDIRECTPLAY3A iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4713 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4714 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4715 return DP_OK;
4718 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4719 ( LPDIRECTPLAY3 iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4721 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4722 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4723 return DP_OK;
4726 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4727 ( LPDIRECTPLAY3A iface, DPID idPlayer, LPDWORD lpdwFlags )
4729 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4730 FIXME("(%p)->(0x%08x,%p): stub\n", This, idPlayer, lpdwFlags );
4731 return DP_OK;
4734 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4735 ( LPDIRECTPLAY3 iface, DPID idPlayer, LPDWORD lpdwFlags )
4737 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4738 FIXME("(%p)->(0x%08x,%p): stub\n", This, idPlayer, lpdwFlags );
4739 return DP_OK;
4742 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4743 ( LPDIRECTPLAY4A iface, DPID idGroup, LPDPID lpidGroupOwner )
4745 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4746 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpidGroupOwner );
4747 return DP_OK;
4750 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4751 ( LPDIRECTPLAY4 iface, DPID idGroup, LPDPID lpidGroupOwner )
4753 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4754 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpidGroupOwner );
4755 return DP_OK;
4758 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4759 ( LPDIRECTPLAY4A iface, DPID idGroup , DPID idGroupOwner )
4761 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4762 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, idGroup, idGroupOwner );
4763 return DP_OK;
4766 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4767 ( LPDIRECTPLAY4 iface, DPID idGroup , DPID idGroupOwner )
4769 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4770 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, idGroup, idGroupOwner );
4771 return DP_OK;
4774 static HRESULT DP_SendEx
4775 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4776 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4777 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi )
4779 lpGroupData lpGData;
4780 BOOL bSendToGroup;
4782 TRACE( "(%p)->(0x%08x,0x%08x,0x%08x,%p,0x%08x,0x%08x,0x%08x,%p,%p,%u)\n",
4783 This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority,
4784 dwTimeout, lpContext, lpdwMsgID, bAnsi );
4786 if( This->dp2->connectionInitialized == NO_PROVIDER )
4788 return DPERR_UNINITIALIZED;
4791 /* FIXME: Add parameter checking */
4792 /* FIXME: First call to this needs to acquire a message id which will be
4793 * used for multiple sends
4796 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4798 /* Check idFrom points to a valid player */
4799 if ( DP_FindPlayer( This, idFrom ) == NULL )
4801 ERR( "Invalid from player 0x%08x\n", idFrom );
4802 return DPERR_INVALIDPLAYER;
4805 /* Check idTo: it can be a player or a group */
4806 if( idTo == DPID_ALLPLAYERS )
4808 bSendToGroup = TRUE;
4809 lpGData = This->dp2->lpSysGroup;
4811 else if ( DP_FindPlayer( This, idTo ) )
4813 bSendToGroup = FALSE;
4815 else if ( ( lpGData = DP_FindAnyGroup( This, idTo ) ) )
4817 bSendToGroup = TRUE;
4819 else
4821 return DPERR_INVALIDPLAYER;
4824 if ( bSendToGroup )
4826 #if 0
4827 DPSP_SENDTOGROUPEXDATA data;
4829 data.lpISP = This->dp2->spData.lpISP;
4830 data.dwFlags = dwFlags;
4831 data.idGroupTo = idTo;
4832 data.idPlayerFrom = idFrom;
4833 data.lpSendBuffers = lpData;
4834 data.cBuffers = NULL;
4835 data.dwMessageSize = dwDataSize;
4836 data.dwPriority = dwPriority;
4837 data.dwTimeout = dwTimeout;
4838 data.lpDPContext = lpContext;
4839 data.lpdwSPMsgID = lpdwMsgID;
4841 return (*This->dp2->spData.lpCB->SendToGroupEx)( &data );
4842 #endif
4843 DPSP_SENDDATA data;
4844 lpPlayerList lpPList;
4846 data.dwFlags = dwFlags;
4847 data.idPlayerFrom = idFrom;
4848 data.lpMessage = lpData;
4849 data.dwMessageSize = dwDataSize;
4850 data.bSystemMessage = FALSE;
4851 data.lpISP = This->dp2->spData.lpISP;
4853 if ( (lpPList = DPQ_FIRST( lpGData->players )) )
4857 if ( ~lpPList->lpPData->dwFlags & DPLAYI_PLAYER_PLAYERLOCAL )
4859 data.idPlayerTo = lpPList->lpPData->dpid;
4860 (*This->dp2->spData.lpCB->Send)( &data );
4863 while( (lpPList = DPQ_NEXT( lpPList->players )) );
4866 else
4868 DPSP_SENDDATA data;
4870 data.dwFlags = dwFlags;
4871 data.idPlayerFrom = idFrom;
4872 data.idPlayerTo = idTo;
4873 data.lpMessage = lpData;
4874 data.dwMessageSize = dwDataSize;
4875 data.bSystemMessage = FALSE;
4876 data.lpISP = This->dp2->spData.lpISP;
4878 return (*This->dp2->spData.lpCB->Send)( &data );
4881 /* Have the service provider send this message */
4882 /*wat?
4883 return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority,
4884 dwTimeout, lpContext, lpdwMsgID );*/
4886 return DP_OK;
4890 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4891 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4892 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4893 LPVOID lpContext, LPDWORD lpdwMsgID )
4895 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4896 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4897 dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE );
4900 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4901 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4902 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4903 LPVOID lpContext, LPDWORD lpdwMsgID )
4905 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4906 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4907 dwPriority, dwTimeout, lpContext, lpdwMsgID, FALSE );
4910 static HRESULT DP_SP_SendEx
4911 ( IDirectPlay2Impl* This, DWORD dwFlags,
4912 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4913 LPVOID lpContext, LPDWORD lpdwMsgID )
4915 LPDPMSG lpMElem;
4917 FIXME( ": stub\n" );
4919 /* FIXME: This queuing should only be for async messages */
4921 lpMElem = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpMElem ) );
4922 lpMElem->msg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
4924 CopyMemory( lpMElem->msg, lpData, dwDataSize );
4926 /* FIXME: Need to queue based on priority */
4927 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
4929 return DP_OK;
4932 static HRESULT DP_IF_GetMessageQueue
4933 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4934 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi )
4936 HRESULT hr = DP_OK;
4938 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%p,%u): semi stub\n",
4939 This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi );
4941 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4942 /* FIXME: What about sends which are not immediate? */
4944 if( This->dp2->spData.lpCB->GetMessageQueue )
4946 DPSP_GETMESSAGEQUEUEDATA data;
4948 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4950 /* FIXME: None of this is documented :( */
4952 data.lpISP = This->dp2->spData.lpISP;
4953 data.dwFlags = dwFlags;
4954 data.idFrom = idFrom;
4955 data.idTo = idTo;
4956 data.lpdwNumMsgs = lpdwNumMsgs;
4957 data.lpdwNumBytes = lpdwNumBytes;
4959 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
4961 else
4963 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4966 return hr;
4969 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4970 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4971 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4973 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4974 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4975 lpdwNumBytes, TRUE );
4978 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4979 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4980 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4982 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4983 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4984 lpdwNumBytes, FALSE );
4987 static HRESULT DP_IF_CancelMessage
4988 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
4989 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi )
4991 HRESULT hr = DP_OK;
4993 FIXME( "(%p)->(0x%08x,0x%08x,%u): semi stub\n",
4994 This, dwMsgID, dwFlags, bAnsi );
4996 if( This->dp2->spData.lpCB->Cancel )
4998 DPSP_CANCELDATA data;
5000 TRACE( "Calling SP Cancel\n" );
5002 /* FIXME: Undocumented callback */
5004 data.lpISP = This->dp2->spData.lpISP;
5005 data.dwFlags = dwFlags;
5006 data.lprglpvSPMsgID = NULL;
5007 data.cSPMsgID = dwMsgID;
5008 data.dwMinPriority = dwMinPriority;
5009 data.dwMaxPriority = dwMaxPriority;
5011 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
5013 else
5015 FIXME( "SP doesn't implement Cancel\n" );
5018 return hr;
5021 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
5022 ( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags )
5024 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
5026 if( dwFlags != 0 )
5028 return DPERR_INVALIDFLAGS;
5031 if( dwMsgID == 0 )
5033 dwFlags |= DPCANCELSEND_ALL;
5036 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE );
5039 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
5040 ( LPDIRECTPLAY4 iface, DWORD dwMsgID, DWORD dwFlags )
5042 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
5044 if( dwFlags != 0 )
5046 return DPERR_INVALIDFLAGS;
5049 if( dwMsgID == 0 )
5051 dwFlags |= DPCANCELSEND_ALL;
5054 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, FALSE );
5057 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
5058 ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority,
5059 DWORD dwFlags )
5061 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
5063 if( dwFlags != 0 )
5065 return DPERR_INVALIDFLAGS;
5068 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
5069 dwMaxPriority, TRUE );
5072 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
5073 ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority,
5074 DWORD dwFlags )
5076 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
5078 if( dwFlags != 0 )
5080 return DPERR_INVALIDFLAGS;
5083 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
5084 dwMaxPriority, FALSE );
5087 /* Note: Hack so we can reuse the old functions without compiler warnings */
5088 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5089 # define XCAST(fun) (typeof(directPlay2WVT.fun))
5090 #else
5091 # define XCAST(fun) (void*)
5092 #endif
5094 static const IDirectPlay2Vtbl directPlay2WVT =
5096 XCAST(QueryInterface)DP_QueryInterface,
5097 XCAST(AddRef)DP_AddRef,
5098 XCAST(Release)DP_Release,
5100 DirectPlay2WImpl_AddPlayerToGroup,
5101 DirectPlay2WImpl_Close,
5102 DirectPlay2WImpl_CreateGroup,
5103 DirectPlay2WImpl_CreatePlayer,
5104 DirectPlay2WImpl_DeletePlayerFromGroup,
5105 DirectPlay2WImpl_DestroyGroup,
5106 DirectPlay2WImpl_DestroyPlayer,
5107 DirectPlay2WImpl_EnumGroupPlayers,
5108 DirectPlay2WImpl_EnumGroups,
5109 DirectPlay2WImpl_EnumPlayers,
5110 DirectPlay2WImpl_EnumSessions,
5111 DirectPlay2WImpl_GetCaps,
5112 DirectPlay2WImpl_GetGroupData,
5113 DirectPlay2WImpl_GetGroupName,
5114 DirectPlay2WImpl_GetMessageCount,
5115 DirectPlay2WImpl_GetPlayerAddress,
5116 DirectPlay2WImpl_GetPlayerCaps,
5117 DirectPlay2WImpl_GetPlayerData,
5118 DirectPlay2WImpl_GetPlayerName,
5119 DirectPlay2WImpl_GetSessionDesc,
5120 DirectPlay2WImpl_Initialize,
5121 DirectPlay2WImpl_Open,
5122 DirectPlay2WImpl_Receive,
5123 DirectPlay2WImpl_Send,
5124 DirectPlay2WImpl_SetGroupData,
5125 DirectPlay2WImpl_SetGroupName,
5126 DirectPlay2WImpl_SetPlayerData,
5127 DirectPlay2WImpl_SetPlayerName,
5128 DirectPlay2WImpl_SetSessionDesc
5130 #undef XCAST
5132 /* Note: Hack so we can reuse the old functions without compiler warnings */
5133 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5134 # define XCAST(fun) (typeof(directPlay2AVT.fun))
5135 #else
5136 # define XCAST(fun) (void*)
5137 #endif
5139 static const IDirectPlay2Vtbl directPlay2AVT =
5141 XCAST(QueryInterface)DP_QueryInterface,
5142 XCAST(AddRef)DP_AddRef,
5143 XCAST(Release)DP_Release,
5145 DirectPlay2AImpl_AddPlayerToGroup,
5146 DirectPlay2AImpl_Close,
5147 DirectPlay2AImpl_CreateGroup,
5148 DirectPlay2AImpl_CreatePlayer,
5149 DirectPlay2AImpl_DeletePlayerFromGroup,
5150 DirectPlay2AImpl_DestroyGroup,
5151 DirectPlay2AImpl_DestroyPlayer,
5152 DirectPlay2AImpl_EnumGroupPlayers,
5153 DirectPlay2AImpl_EnumGroups,
5154 DirectPlay2AImpl_EnumPlayers,
5155 DirectPlay2AImpl_EnumSessions,
5156 DirectPlay2AImpl_GetCaps,
5157 DirectPlay2AImpl_GetGroupData,
5158 DirectPlay2AImpl_GetGroupName,
5159 DirectPlay2AImpl_GetMessageCount,
5160 DirectPlay2AImpl_GetPlayerAddress,
5161 DirectPlay2AImpl_GetPlayerCaps,
5162 DirectPlay2AImpl_GetPlayerData,
5163 DirectPlay2AImpl_GetPlayerName,
5164 DirectPlay2AImpl_GetSessionDesc,
5165 DirectPlay2AImpl_Initialize,
5166 DirectPlay2AImpl_Open,
5167 DirectPlay2AImpl_Receive,
5168 DirectPlay2AImpl_Send,
5169 DirectPlay2AImpl_SetGroupData,
5170 DirectPlay2AImpl_SetGroupName,
5171 DirectPlay2AImpl_SetPlayerData,
5172 DirectPlay2AImpl_SetPlayerName,
5173 DirectPlay2AImpl_SetSessionDesc
5175 #undef XCAST
5178 /* Note: Hack so we can reuse the old functions without compiler warnings */
5179 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5180 # define XCAST(fun) (typeof(directPlay3AVT.fun))
5181 #else
5182 # define XCAST(fun) (void*)
5183 #endif
5185 static const IDirectPlay3Vtbl directPlay3AVT =
5187 XCAST(QueryInterface)DP_QueryInterface,
5188 XCAST(AddRef)DP_AddRef,
5189 XCAST(Release)DP_Release,
5191 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
5192 XCAST(Close)DirectPlay2AImpl_Close,
5193 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
5194 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
5195 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
5196 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
5197 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
5198 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
5199 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
5200 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
5201 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
5202 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
5203 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
5204 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
5205 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5206 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5207 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5208 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5209 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5210 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5211 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5212 XCAST(Open)DirectPlay2AImpl_Open,
5213 XCAST(Receive)DirectPlay2AImpl_Receive,
5214 XCAST(Send)DirectPlay2AImpl_Send,
5215 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5216 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5217 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5218 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5219 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5221 DirectPlay3AImpl_AddGroupToGroup,
5222 DirectPlay3AImpl_CreateGroupInGroup,
5223 DirectPlay3AImpl_DeleteGroupFromGroup,
5224 DirectPlay3AImpl_EnumConnections,
5225 DirectPlay3AImpl_EnumGroupsInGroup,
5226 DirectPlay3AImpl_GetGroupConnectionSettings,
5227 DirectPlay3AImpl_InitializeConnection,
5228 DirectPlay3AImpl_SecureOpen,
5229 DirectPlay3AImpl_SendChatMessage,
5230 DirectPlay3AImpl_SetGroupConnectionSettings,
5231 DirectPlay3AImpl_StartSession,
5232 DirectPlay3AImpl_GetGroupFlags,
5233 DirectPlay3AImpl_GetGroupParent,
5234 DirectPlay3AImpl_GetPlayerAccount,
5235 DirectPlay3AImpl_GetPlayerFlags
5237 #undef XCAST
5239 /* Note: Hack so we can reuse the old functions without compiler warnings */
5240 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5241 # define XCAST(fun) (typeof(directPlay3WVT.fun))
5242 #else
5243 # define XCAST(fun) (void*)
5244 #endif
5245 static const IDirectPlay3Vtbl directPlay3WVT =
5247 XCAST(QueryInterface)DP_QueryInterface,
5248 XCAST(AddRef)DP_AddRef,
5249 XCAST(Release)DP_Release,
5251 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
5252 XCAST(Close)DirectPlay2WImpl_Close,
5253 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
5254 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
5255 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
5256 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
5257 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5258 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5259 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5260 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5261 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5262 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5263 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5264 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5265 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5266 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5267 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5268 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5269 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5270 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5271 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5272 XCAST(Open)DirectPlay2WImpl_Open,
5273 XCAST(Receive)DirectPlay2WImpl_Receive,
5274 XCAST(Send)DirectPlay2WImpl_Send,
5275 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5276 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5277 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5278 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5279 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5281 DirectPlay3WImpl_AddGroupToGroup,
5282 DirectPlay3WImpl_CreateGroupInGroup,
5283 DirectPlay3WImpl_DeleteGroupFromGroup,
5284 DirectPlay3WImpl_EnumConnections,
5285 DirectPlay3WImpl_EnumGroupsInGroup,
5286 DirectPlay3WImpl_GetGroupConnectionSettings,
5287 DirectPlay3WImpl_InitializeConnection,
5288 DirectPlay3WImpl_SecureOpen,
5289 DirectPlay3WImpl_SendChatMessage,
5290 DirectPlay3WImpl_SetGroupConnectionSettings,
5291 DirectPlay3WImpl_StartSession,
5292 DirectPlay3WImpl_GetGroupFlags,
5293 DirectPlay3WImpl_GetGroupParent,
5294 DirectPlay3WImpl_GetPlayerAccount,
5295 DirectPlay3WImpl_GetPlayerFlags
5297 #undef XCAST
5299 /* Note: Hack so we can reuse the old functions without compiler warnings */
5300 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5301 # define XCAST(fun) (typeof(directPlay4WVT.fun))
5302 #else
5303 # define XCAST(fun) (void*)
5304 #endif
5305 static const IDirectPlay4Vtbl directPlay4WVT =
5307 XCAST(QueryInterface)DP_QueryInterface,
5308 XCAST(AddRef)DP_AddRef,
5309 XCAST(Release)DP_Release,
5311 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
5312 XCAST(Close)DirectPlay2WImpl_Close,
5313 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
5314 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
5315 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
5316 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
5317 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5318 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5319 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5320 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5321 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5322 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5323 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5324 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5325 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5326 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5327 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5328 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5329 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5330 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5331 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5332 XCAST(Open)DirectPlay2WImpl_Open,
5333 XCAST(Receive)DirectPlay2WImpl_Receive,
5334 XCAST(Send)DirectPlay2WImpl_Send,
5335 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5336 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5337 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5338 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5339 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5341 XCAST(AddGroupToGroup)DirectPlay3WImpl_AddGroupToGroup,
5342 XCAST(CreateGroupInGroup)DirectPlay3WImpl_CreateGroupInGroup,
5343 XCAST(DeleteGroupFromGroup)DirectPlay3WImpl_DeleteGroupFromGroup,
5344 XCAST(EnumConnections)DirectPlay3WImpl_EnumConnections,
5345 XCAST(EnumGroupsInGroup)DirectPlay3WImpl_EnumGroupsInGroup,
5346 XCAST(GetGroupConnectionSettings)DirectPlay3WImpl_GetGroupConnectionSettings,
5347 XCAST(InitializeConnection)DirectPlay3WImpl_InitializeConnection,
5348 XCAST(SecureOpen)DirectPlay3WImpl_SecureOpen,
5349 XCAST(SendChatMessage)DirectPlay3WImpl_SendChatMessage,
5350 XCAST(SetGroupConnectionSettings)DirectPlay3WImpl_SetGroupConnectionSettings,
5351 XCAST(StartSession)DirectPlay3WImpl_StartSession,
5352 XCAST(GetGroupFlags)DirectPlay3WImpl_GetGroupFlags,
5353 XCAST(GetGroupParent)DirectPlay3WImpl_GetGroupParent,
5354 XCAST(GetPlayerAccount)DirectPlay3WImpl_GetPlayerAccount,
5355 XCAST(GetPlayerFlags)DirectPlay3WImpl_GetPlayerFlags,
5357 DirectPlay4WImpl_GetGroupOwner,
5358 DirectPlay4WImpl_SetGroupOwner,
5359 DirectPlay4WImpl_SendEx,
5360 DirectPlay4WImpl_GetMessageQueue,
5361 DirectPlay4WImpl_CancelMessage,
5362 DirectPlay4WImpl_CancelPriority
5364 #undef XCAST
5367 /* Note: Hack so we can reuse the old functions without compiler warnings */
5368 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5369 # define XCAST(fun) (typeof(directPlay4AVT.fun))
5370 #else
5371 # define XCAST(fun) (void*)
5372 #endif
5373 static const IDirectPlay4Vtbl directPlay4AVT =
5375 XCAST(QueryInterface)DP_QueryInterface,
5376 XCAST(AddRef)DP_AddRef,
5377 XCAST(Release)DP_Release,
5379 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
5380 XCAST(Close)DirectPlay2AImpl_Close,
5381 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
5382 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
5383 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
5384 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
5385 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
5386 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
5387 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
5388 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
5389 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
5390 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
5391 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
5392 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
5393 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5394 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5395 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5396 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5397 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5398 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5399 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5400 XCAST(Open)DirectPlay2AImpl_Open,
5401 XCAST(Receive)DirectPlay2AImpl_Receive,
5402 XCAST(Send)DirectPlay2AImpl_Send,
5403 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5404 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5405 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5406 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5407 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5409 XCAST(AddGroupToGroup)DirectPlay3AImpl_AddGroupToGroup,
5410 XCAST(CreateGroupInGroup)DirectPlay3AImpl_CreateGroupInGroup,
5411 XCAST(DeleteGroupFromGroup)DirectPlay3AImpl_DeleteGroupFromGroup,
5412 XCAST(EnumConnections)DirectPlay3AImpl_EnumConnections,
5413 XCAST(EnumGroupsInGroup)DirectPlay3AImpl_EnumGroupsInGroup,
5414 XCAST(GetGroupConnectionSettings)DirectPlay3AImpl_GetGroupConnectionSettings,
5415 XCAST(InitializeConnection)DirectPlay3AImpl_InitializeConnection,
5416 XCAST(SecureOpen)DirectPlay3AImpl_SecureOpen,
5417 XCAST(SendChatMessage)DirectPlay3AImpl_SendChatMessage,
5418 XCAST(SetGroupConnectionSettings)DirectPlay3AImpl_SetGroupConnectionSettings,
5419 XCAST(StartSession)DirectPlay3AImpl_StartSession,
5420 XCAST(GetGroupFlags)DirectPlay3AImpl_GetGroupFlags,
5421 XCAST(GetGroupParent)DirectPlay3AImpl_GetGroupParent,
5422 XCAST(GetPlayerAccount)DirectPlay3AImpl_GetPlayerAccount,
5423 XCAST(GetPlayerFlags)DirectPlay3AImpl_GetPlayerFlags,
5425 DirectPlay4AImpl_GetGroupOwner,
5426 DirectPlay4AImpl_SetGroupOwner,
5427 DirectPlay4AImpl_SendEx,
5428 DirectPlay4AImpl_GetMessageQueue,
5429 DirectPlay4AImpl_CancelMessage,
5430 DirectPlay4AImpl_CancelPriority
5432 #undef XCAST
5434 HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP,
5435 DPID idPlayer,
5436 LPVOID* lplpData )
5438 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5440 if( lpPlayer == NULL )
5442 return DPERR_INVALIDPLAYER;
5445 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
5447 return DP_OK;
5450 HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP,
5451 DPID idPlayer,
5452 LPVOID lpData )
5454 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5456 if( lpPlayer == NULL )
5458 return DPERR_INVALIDPLAYER;
5461 lpPlayer->lpPData->lpSPPlayerData = lpData;
5463 return DP_OK;
5466 /***************************************************************************
5467 * DirectPlayEnumerateAW
5469 * The pointer to the structure lpContext will be filled with the
5470 * appropriate data for each service offered by the OS. These services are
5471 * not necessarily available on this particular machine but are defined
5472 * as simple service providers under the "Service Providers" registry key.
5473 * This structure is then passed to lpEnumCallback for each of the different
5474 * services.
5476 * This API is useful only for applications written using DirectX3 or
5477 * worse. It is superseded by IDirectPlay3::EnumConnections which also
5478 * gives information on the actual connections.
5480 * defn of a service provider:
5481 * A dynamic-link library used by DirectPlay to communicate over a network.
5482 * The service provider contains all the network-specific code required
5483 * to send and receive messages. Online services and network operators can
5484 * supply service providers to use specialized hardware, protocols, communications
5485 * media, and network resources.
5488 static HRESULT DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA,
5489 LPDPENUMDPCALLBACKW lpEnumCallbackW,
5490 LPVOID lpContext)
5492 HKEY hkResult;
5493 static const WCHAR searchSubKey[] = {
5494 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
5495 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
5496 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
5497 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
5498 static const WCHAR guidKey[] = { 'G', 'u', 'i', 'd', 0 };
5499 static const WCHAR descW[] = { 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', 'W', 0 };
5501 DWORD dwIndex;
5502 FILETIME filetime;
5504 char *descriptionA = NULL;
5505 DWORD max_sizeOfDescriptionA = 0;
5506 WCHAR *descriptionW = NULL;
5507 DWORD max_sizeOfDescriptionW = 0;
5509 if (!lpEnumCallbackA && !lpEnumCallbackW)
5511 return DPERR_INVALIDPARAMS;
5514 /* Need to loop over the service providers in the registry */
5515 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, searchSubKey,
5516 0, KEY_READ, &hkResult) != ERROR_SUCCESS)
5518 /* Hmmm. Does this mean that there are no service providers? */
5519 ERR(": no service provider key in the registry - check your Wine installation !!!\n");
5520 return DPERR_GENERIC;
5523 /* Traverse all the service providers we have available */
5524 dwIndex = 0;
5525 while (1)
5527 WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */
5528 DWORD sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR);
5529 HKEY hkServiceProvider;
5530 GUID serviceProviderGUID;
5531 WCHAR guidKeyContent[(2 * 16) + 1 + 6 /* This corresponds to '{....-..-..-..-......}' */ ];
5532 DWORD sizeOfGuidKeyContent = sizeof(guidKeyContent);
5533 LONG ret_value;
5535 ret_value = RegEnumKeyExW(hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
5536 NULL, NULL, NULL, &filetime);
5537 if (ret_value == ERROR_NO_MORE_ITEMS)
5538 break;
5539 else if (ret_value != ERROR_SUCCESS)
5541 ERR(": could not enumerate on service provider key.\n");
5542 return DPERR_EXCEPTION;
5544 TRACE(" this time through sub-key %s.\n", debugstr_w(subKeyName));
5546 /* Open the key for this service provider */
5547 if (RegOpenKeyExW(hkResult, subKeyName, 0, KEY_READ, &hkServiceProvider) != ERROR_SUCCESS)
5549 ERR(": could not open registry key for service provider %s.\n", debugstr_w(subKeyName));
5550 continue;
5553 /* Get the GUID from the registry */
5554 if (RegQueryValueExW(hkServiceProvider, guidKey,
5555 NULL, NULL, (LPBYTE) guidKeyContent, &sizeOfGuidKeyContent) != ERROR_SUCCESS)
5557 ERR(": missing GUID registry data member for service provider %s.\n", debugstr_w(subKeyName));
5558 continue;
5560 if (sizeOfGuidKeyContent != sizeof(guidKeyContent))
5562 ERR(": invalid format for the GUID registry data member for service provider %s (%s).\n", debugstr_w(subKeyName), debugstr_w(guidKeyContent));
5563 continue;
5565 CLSIDFromString(guidKeyContent, &serviceProviderGUID );
5567 /* The enumeration will return FALSE if we are not to continue.
5569 * Note: on my windows box, major / minor version is 6 / 0 for all service providers
5570 * and have no relation to any of the two dwReserved1 and dwReserved2 keys.
5571 * I think that it simply means that they are in-line with DirectX 6.0
5573 if (lpEnumCallbackA)
5575 DWORD sizeOfDescription = 0;
5577 /* Note that this is the A case of this function, so use the A variant to get the description string */
5578 if (RegQueryValueExA(hkServiceProvider, "DescriptionA",
5579 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5581 ERR(": missing 'DescriptionA' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5582 continue;
5584 if (sizeOfDescription > max_sizeOfDescriptionA)
5586 HeapFree(GetProcessHeap(), 0, descriptionA);
5587 max_sizeOfDescriptionA = sizeOfDescription;
5589 descriptionA = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5590 RegQueryValueExA(hkServiceProvider, "DescriptionA",
5591 NULL, NULL, (LPBYTE) descriptionA, &sizeOfDescription);
5593 if (!lpEnumCallbackA(&serviceProviderGUID, descriptionA, 6, 0, lpContext))
5594 goto end;
5596 else
5598 DWORD sizeOfDescription = 0;
5600 if (RegQueryValueExW(hkServiceProvider, descW,
5601 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5603 ERR(": missing 'DescriptionW' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5604 continue;
5606 if (sizeOfDescription > max_sizeOfDescriptionW)
5608 HeapFree(GetProcessHeap(), 0, descriptionW);
5609 max_sizeOfDescriptionW = sizeOfDescription;
5611 descriptionW = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5612 RegQueryValueExW(hkServiceProvider, descW,
5613 NULL, NULL, (LPBYTE) descriptionW, &sizeOfDescription);
5615 if (!lpEnumCallbackW(&serviceProviderGUID, descriptionW, 6, 0, lpContext))
5616 goto end;
5619 dwIndex++;
5622 end:
5623 HeapFree(GetProcessHeap(), 0, descriptionA);
5624 HeapFree(GetProcessHeap(), 0, descriptionW);
5626 return DP_OK;
5629 /***************************************************************************
5630 * DirectPlayEnumerate [DPLAYX.9]
5631 * DirectPlayEnumerateA [DPLAYX.2]
5633 HRESULT WINAPI DirectPlayEnumerateA(LPDPENUMDPCALLBACKA lpEnumCallback, LPVOID lpContext )
5635 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5637 return DirectPlayEnumerateAW(lpEnumCallback, NULL, lpContext);
5640 /***************************************************************************
5641 * DirectPlayEnumerateW [DPLAYX.3]
5643 HRESULT WINAPI DirectPlayEnumerateW(LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5645 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5647 return DirectPlayEnumerateAW(NULL, lpEnumCallback, lpContext);
5650 typedef struct tagCreateEnum
5652 LPVOID lpConn;
5653 LPCGUID lpGuid;
5654 } CreateEnumData, *lpCreateEnumData;
5656 /* Find and copy the matching connection for the SP guid */
5657 static BOOL CALLBACK cbDPCreateEnumConnections(
5658 LPCGUID lpguidSP,
5659 LPVOID lpConnection,
5660 DWORD dwConnectionSize,
5661 LPCDPNAME lpName,
5662 DWORD dwFlags,
5663 LPVOID lpContext)
5665 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5667 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5669 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5671 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5672 dwConnectionSize );
5673 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5675 /* Found the record that we were looking for */
5676 return FALSE;
5679 /* Haven't found what were looking for yet */
5680 return TRUE;
5684 /***************************************************************************
5685 * DirectPlayCreate [DPLAYX.1]
5688 HRESULT WINAPI DirectPlayCreate
5689 ( LPGUID lpGUID, LPDIRECTPLAY *lplpDP, IUnknown *pUnk )
5691 HRESULT hr;
5692 LPDIRECTPLAY3A lpDP3A;
5693 CreateEnumData cbData;
5695 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5697 if( pUnk != NULL )
5699 return CLASS_E_NOAGGREGATION;
5702 if( (lplpDP == NULL) || (lpGUID == NULL) )
5704 return DPERR_INVALIDPARAMS;
5708 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5709 give them an IDirectPlay2A object and hope that doesn't cause problems */
5710 if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
5712 return DPERR_UNAVAILABLE;
5715 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
5717 /* The GUID_NULL means don't bind a service provider. Just return the
5718 interface as is */
5719 return DP_OK;
5722 /* Bind the desired service provider since lpGUID is non NULL */
5723 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
5725 /* We're going to use a DP3 interface */
5726 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
5727 (LPVOID*)&lpDP3A );
5728 if( FAILED(hr) )
5730 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
5731 return hr;
5734 cbData.lpConn = NULL;
5735 cbData.lpGuid = lpGUID;
5737 /* We were given a service provider, find info about it... */
5738 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
5739 &cbData, DPCONNECTION_DIRECTPLAY );
5740 if( ( FAILED(hr) ) ||
5741 ( cbData.lpConn == NULL )
5744 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
5745 IDirectPlayX_Release( lpDP3A );
5746 return DPERR_UNAVAILABLE;
5749 /* Initialize the service provider */
5750 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
5751 if( FAILED(hr) )
5753 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
5754 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5755 IDirectPlayX_Release( lpDP3A );
5756 return hr;
5759 /* Release our version of the interface now that we're done with it */
5760 IDirectPlayX_Release( lpDP3A );
5761 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5763 return DP_OK;