dplayx: Removing useless test
[wine/gsoc_dplay.git] / dlls / dplayx / dplay.c
blobf31871f930e12202b9e291695fdb8918fb10ea8f
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 /* If the name is not specified, we must provide one */
1651 if( *lpidPlayer == DPID_UNKNOWN )
1653 /* If we are the session master, we dish out the group/player ids */
1654 if( This->dp2->bHostInterface )
1656 *lpidPlayer = DP_NextObjectId();
1658 else
1660 hr = DP_MSG_SendRequestPlayerId( This, dwFlags & 0x000000FF, lpidPlayer );
1662 if( FAILED(hr) )
1664 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1665 return hr;
1670 hr = DP_CreatePlayer( This, *lpidPlayer, lpPlayerName, dwFlags,
1671 lpData, dwDataSize, hEvent, bAnsi,
1672 &lpPData );
1673 if( FAILED(hr) )
1675 return hr;
1678 /* Let the SP know that we've created this player */
1679 if( This->dp2->spData.lpCB->CreatePlayer )
1681 DPSP_CREATEPLAYERDATA data;
1683 data.idPlayer = *lpidPlayer;
1684 data.dwFlags = dwFlags;
1685 data.lpSPMessageHeader = lpMsgHdr;
1686 data.lpISP = This->dp2->spData.lpISP;
1688 TRACE( "Calling SP CreatePlayer 0x%08x: dwFlags: 0x%08x lpMsgHdr: %p\n",
1689 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
1691 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1694 if( FAILED(hr) )
1696 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1697 return hr;
1700 /* Now let the SP know that this player is a member of the system group */
1701 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1703 DPSP_ADDPLAYERTOGROUPDATA data;
1705 data.idPlayer = *lpidPlayer;
1706 data.idGroup = DPID_SYSTEM_GROUP;
1707 data.lpISP = This->dp2->spData.lpISP;
1709 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1711 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1714 if( FAILED(hr) )
1716 ERR( "Failed to add player to sys group with sp: %s\n",
1717 DPLAYX_HresultToString(hr) );
1718 return hr;
1722 if ( ( ! This->dp2->bHostInterface ) && ( lpMsgHdr == NULL ) )
1724 if ( dwFlags & DPLAYI_PLAYER_SYSPLAYER )
1726 /* Let the name server know about the creation of this player,
1727 * and reeceive the name table */
1728 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
1730 else
1732 /* Inform all other peers of the creation of a new player.
1733 * Also, if this was a remote event, no need to rebroadcast it. */
1734 hr = DP_MSG_SendCreatePlayer( This, lpPData );
1738 return hr;
1741 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
1742 ( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1743 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1745 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1747 if( This->dp2->connectionInitialized == NO_PROVIDER )
1749 return DPERR_UNINITIALIZED;
1752 if( lpidPlayer == NULL || !This->dp2->bConnectionOpen )
1754 return DPERR_INVALIDPARAMS;
1757 if ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_NEWPLAYERSDISABLED )
1759 return DPERR_CANTCREATEPLAYER;
1762 if( dwFlags & DPPLAYER_SERVERPLAYER )
1764 *lpidPlayer = DPID_SERVERPLAYER;
1766 else
1768 *lpidPlayer = DPID_UNKNOWN;
1771 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1772 lpData, dwDataSize, dwFlags, TRUE );
1775 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
1776 ( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1777 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1779 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1781 if( This->dp2->connectionInitialized == NO_PROVIDER )
1783 return DPERR_UNINITIALIZED;
1786 if( lpidPlayer == NULL || !This->dp2->bConnectionOpen )
1788 return DPERR_INVALIDPARAMS;
1791 if ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_NEWPLAYERSDISABLED )
1793 return DPERR_CANTCREATEPLAYER;
1796 if( dwFlags & DPPLAYER_SERVERPLAYER )
1798 *lpidPlayer = DPID_SERVERPLAYER;
1800 else
1802 *lpidPlayer = DPID_UNKNOWN;
1805 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1806 lpData, dwDataSize, dwFlags, FALSE );
1809 static DPID DP_GetRemoteNextObjectId(void)
1811 FIXME( ":stub\n" );
1813 /* Hack solution */
1814 return DP_NextObjectId();
1817 static HRESULT DP_IF_DeletePlayerFromGroup
1818 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
1819 DPID idPlayer, BOOL bAnsi )
1821 HRESULT hr = DP_OK;
1823 lpGroupData lpGData;
1824 lpPlayerList lpPList;
1826 TRACE( "(%p)->(%p,0x%08x,0x%08x,%u)\n",
1827 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
1829 /* Find the group */
1830 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1832 return DPERR_INVALIDGROUP;
1835 /* Find the player */
1836 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
1838 return DPERR_INVALIDPLAYER;
1841 /* Remove the player shortcut from the group */
1842 DPQ_REMOVE_ENTRY( lpGData->players, players, lpPData->dpid, ==, idPlayer, lpPList );
1844 if( lpPList == NULL )
1846 return DPERR_INVALIDPLAYER;
1849 /* One less reference */
1850 lpPList->lpPData->uRef--;
1852 /* Delete the Player List element */
1853 HeapFree( GetProcessHeap(), 0, lpPList );
1855 /* Inform the SP if they care */
1856 if( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1858 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1860 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1862 data.idPlayer = idPlayer;
1863 data.idGroup = idGroup;
1864 data.lpISP = This->dp2->spData.lpISP;
1866 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1869 /* Need to send a DELETEPLAYERFROMGROUP message */
1870 FIXME( "Need to send a message\n" );
1872 return hr;
1875 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
1876 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
1878 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1879 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, TRUE );
1882 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
1883 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
1885 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1886 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, FALSE );
1889 typedef struct _DPRGOPContext
1891 IDirectPlay3Impl* This;
1892 BOOL bAnsi;
1893 DPID idGroup;
1894 } DPRGOPContext, *lpDPRGOPContext;
1896 static BOOL CALLBACK
1897 cbRemoveGroupOrPlayer(
1898 DPID dpId,
1899 DWORD dwPlayerType,
1900 LPCDPNAME lpName,
1901 DWORD dwFlags,
1902 LPVOID lpContext )
1904 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1906 TRACE( "Removing element:0x%08x (type:0x%08x) from element:0x%08x\n",
1907 dpId, dwPlayerType, lpCtxt->idGroup );
1909 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1911 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt->This, lpCtxt->idGroup,
1912 dpId )
1916 ERR( "Unable to delete group 0x%08x from group 0x%08x\n",
1917 dpId, lpCtxt->idGroup );
1920 else
1922 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl*)lpCtxt->This,
1923 NULL, lpCtxt->idGroup,
1924 dpId, lpCtxt->bAnsi )
1928 ERR( "Unable to delete player 0x%08x from grp 0x%08x\n",
1929 dpId, lpCtxt->idGroup );
1933 return TRUE; /* Continue enumeration */
1936 static HRESULT DP_IF_DestroyGroup
1937 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi )
1939 lpGroupData lpGData;
1940 DPRGOPContext context;
1942 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1943 This, lpMsgHdr, idGroup, bAnsi );
1945 /* Find the group */
1946 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1948 return DPERR_INVALIDPLAYER; /* yes player */
1951 context.This = (IDirectPlay3Impl*)This;
1952 context.bAnsi = bAnsi;
1953 context.idGroup = idGroup;
1955 /* Remove all players that this group has */
1956 DP_IF_EnumGroupPlayers( This, idGroup, NULL,
1957 cbRemoveGroupOrPlayer, &context, 0, bAnsi );
1959 /* Remove all links to groups that this group has since this is dp3 */
1960 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This, idGroup, NULL,
1961 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1963 /* Remove this group from the parent group - if it has one */
1964 if( ( idGroup != DPID_SYSTEM_GROUP ) &&
1965 ( lpGData->parent != DPID_SYSTEM_GROUP )
1968 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl*)This, lpGData->parent,
1969 idGroup );
1972 /* Now delete this group data and list from the system group */
1973 DP_DeleteGroup( This, idGroup );
1975 /* Let the SP know that we've destroyed this group */
1976 if( This->dp2->spData.lpCB->DeleteGroup )
1978 DPSP_DELETEGROUPDATA data;
1980 FIXME( "data.dwFlags is incorrect\n" );
1982 data.idGroup = idGroup;
1983 data.dwFlags = 0;
1984 data.lpISP = This->dp2->spData.lpISP;
1986 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1989 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1991 return DP_OK;
1994 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
1995 ( LPDIRECTPLAY2A iface, DPID idGroup )
1997 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1998 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
2001 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
2002 ( LPDIRECTPLAY2 iface, DPID idGroup )
2004 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2005 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
2008 typedef struct _DPFAGContext
2010 IDirectPlay2Impl* This;
2011 DPID idPlayer;
2012 BOOL bAnsi;
2013 } DPFAGContext, *lpDPFAGContext;
2015 static HRESULT DP_IF_DestroyPlayer
2016 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi )
2018 DPFAGContext cbContext;
2020 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
2021 This, lpMsgHdr, idPlayer, bAnsi );
2023 if( This->dp2->connectionInitialized == NO_PROVIDER )
2025 return DPERR_UNINITIALIZED;
2028 if( DP_FindPlayer( This, idPlayer ) == NULL )
2030 return DPERR_INVALIDPLAYER;
2033 /* FIXME: If the player is remote, we must be the host to delete this */
2035 cbContext.This = This;
2036 cbContext.idPlayer = idPlayer;
2037 cbContext.bAnsi = bAnsi;
2039 /* Find each group and call DeletePlayerFromGroup if the player is a
2040 member of the group */
2041 DP_IF_EnumGroups( This, NULL, cbDeletePlayerFromAllGroups,
2042 &cbContext, DPENUMGROUPS_ALL, bAnsi );
2044 /* Now delete player and player list from the sys group */
2045 DP_DeletePlayer( This, idPlayer );
2047 /* Let the SP know that we've destroyed this group */
2048 if( This->dp2->spData.lpCB->DeletePlayer )
2050 DPSP_DELETEPLAYERDATA data;
2052 FIXME( "data.dwFlags is incorrect\n" );
2054 data.idPlayer = idPlayer;
2055 data.dwFlags = 0;
2056 data.lpISP = This->dp2->spData.lpISP;
2058 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
2061 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
2063 return DP_OK;
2066 static BOOL CALLBACK
2067 cbDeletePlayerFromAllGroups(
2068 DPID dpId,
2069 DWORD dwPlayerType,
2070 LPCDPNAME lpName,
2071 DWORD dwFlags,
2072 LPVOID lpContext )
2074 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
2076 if( dwPlayerType == DPPLAYERTYPE_GROUP )
2078 DP_IF_DeletePlayerFromGroup( lpCtxt->This, NULL, dpId, lpCtxt->idPlayer,
2079 lpCtxt->bAnsi );
2081 /* Enumerate all groups in this group since this will normally only
2082 * be called for top level groups
2084 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)lpCtxt->This,
2085 dpId, NULL,
2086 cbDeletePlayerFromAllGroups,
2087 lpContext, DPENUMGROUPS_ALL,
2088 lpCtxt->bAnsi );
2091 else
2093 ERR( "Group callback has dwPlayerType = 0x%08x\n", dwPlayerType );
2096 return TRUE;
2099 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
2100 ( LPDIRECTPLAY2A iface, DPID idPlayer )
2102 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2103 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
2106 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
2107 ( LPDIRECTPLAY2 iface, DPID idPlayer )
2109 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2110 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
2113 static HRESULT DP_IF_EnumGroupPlayers
2114 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
2115 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2116 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2118 lpGroupData lpGData;
2119 lpPlayerList lpPList;
2121 FIXME("(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
2122 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
2123 lpContext, dwFlags, bAnsi );
2125 if( This->dp2->connectionInitialized == NO_PROVIDER )
2127 return DPERR_UNINITIALIZED;
2130 if( !This->dp2->bConnectionOpen )
2132 return DPERR_NOSESSIONS;
2135 if( ( lpEnumPlayersCallback2 == NULL ) ||
2136 ( ( dwFlags & DPENUMPLAYERS_SESSION ) && ( lpguidInstance == NULL ) ) )
2138 return DPERR_INVALIDPARAMS;
2141 /* Find the group */
2142 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2144 return DPERR_INVALIDGROUP;
2147 if( DPQ_IS_EMPTY( lpGData->players ) )
2149 return DP_OK;
2152 lpPList = DPQ_FIRST( lpGData->players );
2154 /* Walk the players in this group */
2155 for( ;; )
2157 /* We do not enum any system players as they are of no
2158 * consequence to the end user.
2160 if( lpPList->lpPData->dwFlags & DPLAYI_PLAYER_SYSPLAYER )
2163 /* FIXME: Need to add stuff for dwFlags checking */
2165 if( !lpEnumPlayersCallback2( lpPList->lpPData->dpid, DPPLAYERTYPE_PLAYER,
2166 &lpPList->lpPData->name,
2167 lpPList->lpPData->dwFlags,
2168 lpContext )
2171 /* User requested break */
2172 return DP_OK;
2176 if( DPQ_IS_ENDOFLIST( lpPList->players ) )
2178 break;
2181 lpPList = DPQ_NEXT( lpPList->players );
2184 return DP_OK;
2187 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
2188 ( LPDIRECTPLAY2A iface, DPID idGroup, LPGUID lpguidInstance,
2189 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2190 LPVOID lpContext, DWORD dwFlags )
2192 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2193 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2194 lpEnumPlayersCallback2, lpContext,
2195 dwFlags, TRUE );
2198 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
2199 ( LPDIRECTPLAY2 iface, DPID idGroup, LPGUID lpguidInstance,
2200 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2201 LPVOID lpContext, DWORD dwFlags )
2203 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2204 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2205 lpEnumPlayersCallback2, lpContext,
2206 dwFlags, FALSE );
2209 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2210 static HRESULT DP_IF_EnumGroups
2211 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2212 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2213 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2215 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This,
2216 DPID_SYSTEM_GROUP, lpguidInstance,
2217 lpEnumPlayersCallback2, lpContext,
2218 dwFlags, bAnsi );
2221 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
2222 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2223 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2224 LPVOID lpContext, DWORD dwFlags )
2226 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2227 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2228 lpContext, dwFlags, TRUE );
2231 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
2232 ( LPDIRECTPLAY2 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, FALSE );
2241 static HRESULT DP_IF_EnumPlayers
2242 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2243 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2244 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2246 return DP_IF_EnumGroupPlayers( This, DPID_SYSTEM_GROUP, lpguidInstance,
2247 lpEnumPlayersCallback2, lpContext,
2248 dwFlags, bAnsi );
2251 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
2252 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2253 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2254 LPVOID lpContext, DWORD dwFlags )
2256 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2257 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2258 lpContext, dwFlags, TRUE );
2261 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
2262 ( LPDIRECTPLAY2 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, FALSE );
2271 /* This function should call the registered callback function that the user
2272 passed into EnumSessions for each entry available.
2274 static void DP_InvokeEnumSessionCallbacks
2275 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2276 LPVOID lpNSInfo,
2277 DWORD dwTimeout,
2278 LPVOID lpContext )
2280 LPDPSESSIONDESC2 lpSessionDesc;
2282 FIXME( ": not checking for conditions\n" );
2284 /* Not sure if this should be pruning but it's convenient */
2285 NS_PruneSessionCache( lpNSInfo );
2287 NS_ResetSessionEnumeration( lpNSInfo );
2289 /* Enumerate all sessions */
2290 /* FIXME: Need to indicate ANSI */
2291 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2293 TRACE( "EnumSessionsCallback2 invoked\n" );
2294 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2296 return;
2300 /* Invoke one last time to indicate that there is no more to come */
2301 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2304 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2306 EnumSessionAsyncCallbackData* data = lpContext;
2307 HANDLE hSuicideRequest = data->hSuicideRequest;
2308 DWORD dwTimeout = data->dwTimeout;
2310 TRACE( "Thread started with timeout = 0x%08x\n", dwTimeout );
2312 for( ;; )
2314 HRESULT hr;
2316 /* Sleep up to dwTimeout waiting for request to terminate thread */
2317 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2319 TRACE( "Thread terminating on terminate request\n" );
2320 break;
2323 /* Now resend the enum request */
2324 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2325 data->dwEnumSessionFlags,
2326 data->lpSpData );
2328 if( FAILED(hr) )
2330 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2331 /* FIXME: Should we kill this thread? How to inform the main thread? */
2336 TRACE( "Thread terminating\n" );
2338 /* Clean up the thread data */
2339 CloseHandle( hSuicideRequest );
2340 HeapFree( GetProcessHeap(), 0, lpContext );
2342 /* FIXME: Need to have some notification to main app thread that this is
2343 * dead. It would serve two purposes. 1) allow sync on termination
2344 * so that we don't actually send something to ourselves when we
2345 * become name server (race condition) and 2) so that if we die
2346 * abnormally something else will be able to tell.
2349 return 1;
2352 static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
2354 /* Does a thread exist? If so we were doing an async enum session */
2355 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2357 TRACE( "Killing EnumSession thread %p\n",
2358 This->dp2->hEnumSessionThread );
2360 /* Request that the thread kill itself nicely */
2361 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2362 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2364 /* We no longer need to know about the thread */
2365 CloseHandle( This->dp2->hEnumSessionThread );
2367 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2371 static HRESULT DP_IF_EnumSessions
2372 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2373 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2374 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2376 HRESULT hr = DP_OK;
2378 TRACE( "(%p)->(%p,0x%08x,%p,%p,0x%08x,%u)\n",
2379 This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags,
2380 bAnsi );
2381 if( This->dp2->connectionInitialized == NO_PROVIDER )
2383 return DPERR_UNINITIALIZED;
2386 if( (lpsd == NULL) || (lpsd->dwSize != sizeof(DPSESSIONDESC2)) )
2388 return DPERR_INVALIDPARAMS;
2391 /* Can't enumerate if the session is already open */
2392 if( This->dp2->bConnectionOpen )
2394 return DPERR_GENERIC;
2397 #if 1
2398 /* The loading of a lobby provider _seems_ to require a backdoor loading
2399 * of the service provider to also associate with this DP object. This is
2400 * because the app doesn't seem to have to call EnumConnections and
2401 * InitializeConnection for the SP before calling this method. As such
2402 * we'll do their dirty work for them with a quick hack so as to always
2403 * load the TCP/IP service provider.
2405 * The correct solution would seem to involve creating a dialog box which
2406 * contains the possible SPs. These dialog boxes most likely follow SDK
2407 * examples.
2409 if( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
2411 LPVOID lpConnection;
2412 DWORD dwSize;
2414 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2416 if( !DP_BuildCompoundAddr( DPAID_ServiceProvider, (LPGUID)&DPSPGUID_TCPIP,
2417 &lpConnection, &dwSize ) )
2419 ERR( "Can't build compound addr\n" );
2420 return DPERR_GENERIC;
2423 hr = DP_IF_InitializeConnection( (IDirectPlay3Impl*)This, lpConnection,
2424 0, bAnsi );
2425 if( FAILED(hr) )
2427 return hr;
2430 /* Free up the address buffer */
2431 HeapFree( GetProcessHeap(), 0, lpConnection );
2433 /* The SP is now initialized */
2434 This->dp2->bSPInitialized = TRUE;
2436 #endif
2439 /* Use the service provider default? */
2440 if( dwTimeout == 0 )
2442 DPCAPS spCaps;
2443 spCaps.dwSize = sizeof( spCaps );
2445 DP_IF_GetCaps( This, &spCaps, 0 );
2446 dwTimeout = spCaps.dwTimeout;
2448 /* The service provider doesn't provide one either! */
2449 if( dwTimeout == 0 )
2451 /* Provide the TCP/IP default */
2452 dwTimeout = DPMSG_WAIT_5_SECS;
2456 if( dwFlags & DPENUMSESSIONS_STOPASYNC )
2458 DP_KillEnumSessionThread( This );
2459 return hr;
2462 if( ( dwFlags & DPENUMSESSIONS_ASYNC ) )
2464 /* Enumerate everything presently in the local session cache */
2465 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2466 This->dp2->lpNameServerData, dwTimeout,
2467 lpContext );
2469 if( This->dp2->dwEnumSessionLock != 0 )
2470 return DPERR_CONNECTING;
2472 /* See if we've already created a thread to service this interface */
2473 if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2475 DWORD dwThreadId;
2476 This->dp2->dwEnumSessionLock++;
2478 /* Send the first enum request inline since the user may cancel a dialog
2479 * if one is presented. Also, may also have a connecting return code.
2481 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2482 dwFlags, &This->dp2->spData );
2484 if( SUCCEEDED(hr) )
2486 EnumSessionAsyncCallbackData* lpData
2487 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpData ) );
2488 /* FIXME: need to kill the thread on object deletion */
2489 lpData->lpSpData = &This->dp2->spData;
2491 lpData->requestGuid = lpsd->guidApplication;
2492 lpData->dwEnumSessionFlags = dwFlags;
2493 lpData->dwTimeout = dwTimeout;
2495 This->dp2->hKillEnumSessionThreadEvent =
2496 CreateEventW( NULL, TRUE, FALSE, NULL );
2498 if( !DuplicateHandle( GetCurrentProcess(),
2499 This->dp2->hKillEnumSessionThreadEvent,
2500 GetCurrentProcess(),
2501 &lpData->hSuicideRequest,
2502 0, FALSE, DUPLICATE_SAME_ACCESS )
2505 ERR( "Can't duplicate thread killing handle\n" );
2508 TRACE( ": creating EnumSessionsRequest thread\n" );
2510 This->dp2->hEnumSessionThread = CreateThread( NULL,
2512 DP_EnumSessionsSendAsyncRequestThread,
2513 lpData,
2515 &dwThreadId );
2517 This->dp2->dwEnumSessionLock--;
2520 else
2522 /* Invalidate the session cache for the interface */
2523 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2525 /* Send the broadcast for session enumeration */
2526 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2527 dwFlags,
2528 &This->dp2->spData );
2531 SleepEx( dwTimeout, FALSE );
2533 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2534 This->dp2->lpNameServerData, dwTimeout,
2535 lpContext );
2538 return hr;
2541 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2542 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2543 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2544 LPVOID lpContext, DWORD dwFlags )
2546 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2547 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2548 lpContext, dwFlags, TRUE );
2551 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2552 ( LPDIRECTPLAY2 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, FALSE );
2561 static HRESULT DP_IF_GetPlayerCaps
2562 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
2563 DWORD dwFlags )
2565 DPSP_GETCAPSDATA data;
2567 TRACE("(%p)->(0x%08x,%p,0x%08x)\n", This, idPlayer, lpDPCaps, dwFlags);
2569 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2571 return DPERR_UNINITIALIZED;
2574 if ( lpDPCaps->dwSize != sizeof(DPCAPS) )
2576 return DPERR_INVALIDPARAMS;
2579 /* Query the service provider */
2580 data.idPlayer = idPlayer;
2581 data.dwFlags = dwFlags;
2582 data.lpCaps = lpDPCaps;
2583 data.lpISP = This->dp2->spData.lpISP;
2585 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2588 static HRESULT DP_IF_GetCaps
2589 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags )
2591 return DP_IF_GetPlayerCaps( This, DPID_ALLPLAYERS, lpDPCaps, dwFlags );
2594 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2595 ( LPDIRECTPLAY2A iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2597 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2598 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2601 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2602 ( LPDIRECTPLAY2 iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2604 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2605 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2608 static HRESULT DP_IF_GetGroupData
2609 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2610 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2612 lpGroupData lpGData;
2613 DWORD dwRequiredBufferSize;
2614 LPVOID lpCopyDataFrom;
2616 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2617 This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi );
2619 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2621 return DPERR_INVALIDGROUP;
2624 /* How much buffer is required? */
2625 if( dwFlags & DPSET_LOCAL )
2627 dwRequiredBufferSize = lpGData->dwLocalDataSize;
2628 lpCopyDataFrom = lpGData->lpLocalData;
2630 else
2632 dwRequiredBufferSize = lpGData->dwRemoteDataSize;
2633 lpCopyDataFrom = lpGData->lpRemoteData;
2636 /* Is the user requesting to know how big a buffer is required? */
2637 if( ( lpData == NULL ) ||
2638 ( *lpdwDataSize < dwRequiredBufferSize )
2641 *lpdwDataSize = dwRequiredBufferSize;
2642 return DPERR_BUFFERTOOSMALL;
2645 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2647 return DP_OK;
2650 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2651 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2652 LPDWORD lpdwDataSize, DWORD dwFlags )
2654 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2655 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2656 dwFlags, TRUE );
2659 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2660 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2661 LPDWORD lpdwDataSize, DWORD dwFlags )
2663 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2664 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2665 dwFlags, FALSE );
2668 static HRESULT DP_IF_GetGroupName
2669 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2670 LPDWORD lpdwDataSize, BOOL bAnsi )
2672 lpGroupData lpGData;
2673 LPDPNAME lpName = lpData;
2674 DWORD dwRequiredDataSize;
2676 FIXME("(%p)->(0x%08x,%p,%p,%u) ANSI ignored\n",
2677 This, idGroup, lpData, lpdwDataSize, bAnsi );
2679 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2681 return DPERR_INVALIDGROUP;
2684 dwRequiredDataSize = lpGData->name.dwSize;
2686 if( lpGData->name.u1.lpszShortNameA )
2688 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
2691 if( lpGData->name.u2.lpszLongNameA )
2693 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
2696 if( ( lpData == NULL ) ||
2697 ( *lpdwDataSize < dwRequiredDataSize )
2700 *lpdwDataSize = dwRequiredDataSize;
2701 return DPERR_BUFFERTOOSMALL;
2704 /* Copy the structure */
2705 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2707 if( lpGData->name.u1.lpszShortNameA )
2709 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2710 lpGData->name.u1.lpszShortNameA );
2712 else
2714 lpName->u1.lpszShortNameA = NULL;
2717 if( lpGData->name.u1.lpszShortNameA )
2719 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2720 lpGData->name.u2.lpszLongNameA );
2722 else
2724 lpName->u2.lpszLongNameA = NULL;
2727 return DP_OK;
2730 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2731 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2732 LPDWORD lpdwDataSize )
2734 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2735 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2738 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2739 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2740 LPDWORD lpdwDataSize )
2742 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2743 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2746 static HRESULT DP_IF_GetMessageCount
2747 ( IDirectPlay2Impl* This, DPID idPlayer,
2748 LPDWORD lpdwCount, BOOL bAnsi )
2750 FIXME("(%p)->(0x%08x,%p,%u): stub\n", This, idPlayer, lpdwCount, bAnsi );
2751 return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer,
2752 DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL,
2753 bAnsi );
2756 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2757 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDWORD lpdwCount )
2759 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2760 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, TRUE );
2763 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2764 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDWORD lpdwCount )
2766 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2767 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, FALSE );
2770 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2771 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2773 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2774 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2775 return DP_OK;
2778 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2779 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2781 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2782 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2783 return DP_OK;
2786 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2787 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2788 DWORD dwFlags )
2790 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2791 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2794 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2795 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2796 DWORD dwFlags )
2798 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2799 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2802 static HRESULT DP_IF_GetPlayerData
2803 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2804 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2806 lpPlayerList lpPList;
2807 DWORD dwRequiredBufferSize;
2808 LPVOID lpCopyDataFrom;
2810 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2811 This, idPlayer, lpData, lpdwDataSize, dwFlags, bAnsi );
2813 if( This->dp2->connectionInitialized == NO_PROVIDER )
2815 return DPERR_UNINITIALIZED;
2818 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2820 return DPERR_INVALIDPLAYER;
2823 if( lpdwDataSize == NULL )
2825 return DPERR_INVALIDPARAMS;
2828 /* How much buffer is required? */
2829 if( dwFlags & DPSET_LOCAL )
2831 dwRequiredBufferSize = lpPList->lpPData->dwLocalDataSize;
2832 lpCopyDataFrom = lpPList->lpPData->lpLocalData;
2834 else
2836 dwRequiredBufferSize = lpPList->lpPData->dwRemoteDataSize;
2837 lpCopyDataFrom = lpPList->lpPData->lpRemoteData;
2840 /* Is the user requesting to know how big a buffer is required? */
2841 if( ( lpData == NULL ) ||
2842 ( *lpdwDataSize < dwRequiredBufferSize )
2845 *lpdwDataSize = dwRequiredBufferSize;
2846 return DPERR_BUFFERTOOSMALL;
2849 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2851 return DP_OK;
2854 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2855 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2856 LPDWORD lpdwDataSize, DWORD dwFlags )
2858 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2859 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2860 dwFlags, TRUE );
2863 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2864 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2865 LPDWORD lpdwDataSize, DWORD dwFlags )
2867 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2868 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2869 dwFlags, FALSE );
2872 static HRESULT DP_IF_GetPlayerName
2873 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2874 LPDWORD lpdwDataSize, BOOL bAnsi )
2876 lpPlayerList lpPList;
2877 LPDPNAME lpName = lpData;
2878 DWORD dwRequiredDataSize;
2880 FIXME( "(%p)->(0x%08x,%p,%p,%u): ANSI\n",
2881 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2883 if( This->dp2->connectionInitialized == NO_PROVIDER )
2885 return DPERR_UNINITIALIZED;
2888 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2890 return DPERR_INVALIDPLAYER;
2893 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
2895 if( lpPList->lpPData->name.u1.lpszShortNameA )
2897 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
2900 if( lpPList->lpPData->name.u2.lpszLongNameA )
2902 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
2905 if( ( lpData == NULL ) ||
2906 ( *lpdwDataSize < dwRequiredDataSize )
2909 *lpdwDataSize = dwRequiredDataSize;
2910 return DPERR_BUFFERTOOSMALL;
2913 /* Copy the structure */
2914 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
2916 if( lpPList->lpPData->name.u1.lpszShortNameA )
2918 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2919 lpPList->lpPData->name.u1.lpszShortNameA );
2921 else
2923 lpName->u1.lpszShortNameA = NULL;
2926 if( lpPList->lpPData->name.u2.lpszLongNameA )
2928 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2929 lpPList->lpPData->name.u2.lpszLongNameA );
2931 else
2933 lpName->u2.lpszLongNameA = NULL;
2936 return DP_OK;
2939 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2940 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2941 LPDWORD lpdwDataSize )
2943 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2944 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
2947 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2948 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2949 LPDWORD lpdwDataSize )
2951 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2952 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
2955 static HRESULT DP_GetSessionDesc
2956 ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize,
2957 BOOL bAnsi )
2959 DWORD dwRequiredSize;
2961 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
2963 if( This->dp2->connectionInitialized == NO_PROVIDER )
2965 return DPERR_UNINITIALIZED;
2968 if( !This->dp2->bConnectionOpen )
2970 return DPERR_NOSESSIONS;
2973 if( ( lpdwDataSize == NULL ) || ( *lpdwDataSize >= MAXDWORD ) )
2975 return DPERR_INVALIDPARAMS;
2978 /* FIXME: Get from This->dp2->lpSessionDesc */
2979 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
2981 if ( ( lpData == NULL ) ||
2982 ( *lpdwDataSize < dwRequiredSize )
2985 *lpdwDataSize = dwRequiredSize;
2986 return DPERR_BUFFERTOOSMALL;
2989 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
2991 return DP_OK;
2994 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
2995 ( LPDIRECTPLAY2A iface, LPVOID lpData, LPDWORD lpdwDataSize )
2997 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2998 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
3001 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
3002 ( LPDIRECTPLAY2 iface, LPVOID lpData, LPDWORD lpdwDataSize )
3004 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3005 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
3008 /* Intended only for COM compatibility. Always returns an error. */
3009 static HRESULT WINAPI DirectPlay2AImpl_Initialize
3010 ( LPDIRECTPLAY2A iface, LPGUID lpGUID )
3012 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3013 TRACE("(%p)->(%p): stub\n", This, lpGUID );
3014 return DPERR_ALREADYINITIALIZED;
3017 /* Intended only for COM compatibility. Always returns an error. */
3018 static HRESULT WINAPI DirectPlay2WImpl_Initialize
3019 ( LPDIRECTPLAY2 iface, LPGUID lpGUID )
3021 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3022 TRACE("(%p)->(%p): stub\n", This, lpGUID );
3023 return DPERR_ALREADYINITIALIZED;
3027 static HRESULT DP_SecureOpen
3028 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
3029 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
3030 BOOL bAnsi )
3032 HRESULT hr = DP_OK;
3034 FIXME( "(%p)->(%p,0x%08x,%p,%p): partial stub\n",
3035 This, lpsd, dwFlags, lpSecurity, lpCredentials );
3037 if( ( lpsd == NULL ) ||
3038 ( lpsd->dwSize != sizeof(DPSESSIONDESC2) ) )
3040 return DPERR_INVALIDPARAMS;
3043 if( This->dp2->bConnectionOpen )
3045 TRACE( ": rejecting already open connection.\n" );
3046 return DPERR_ALREADYINITIALIZED;
3049 /* If we're enumerating, kill the thread */
3050 DP_KillEnumSessionThread( This );
3052 if( dwFlags & DPOPEN_JOIN )
3054 LPDPSESSIONDESC2 current = NULL;
3055 NS_ResetSessionEnumeration( This->dp2->lpNameServerData );
3056 while( ( current = NS_WalkSessions( This->dp2->lpNameServerData ) ) )
3058 if ( IsEqualGUID( &lpsd->guidInstance, &current->guidInstance ) )
3059 break;
3061 if ( current == NULL )
3062 return DPERR_NOSESSIONS;
3064 else if( dwFlags & DPOPEN_CREATE )
3066 /* Rightoo - this computer is the host and the local computer needs to be
3067 the name server so that others can join this session */
3068 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
3070 This->dp2->bHostInterface = TRUE;
3072 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
3073 if( FAILED( hr ) )
3075 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
3076 return hr;
3080 /* Invoke the conditional callback for the service provider */
3081 if( This->dp2->spData.lpCB->Open )
3083 DPSP_OPENDATA data;
3085 FIXME( "Not all data fields are correct. Need new parameter\n" );
3087 data.bCreate = (dwFlags & DPOPEN_CREATE ) ? TRUE : FALSE;
3088 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
3089 : NS_GetNSAddr( This->dp2->lpNameServerData );
3090 data.lpISP = This->dp2->spData.lpISP;
3091 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) ? TRUE : FALSE;
3092 data.dwOpenFlags = dwFlags;
3093 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
3095 hr = (*This->dp2->spData.lpCB->Open)(&data);
3096 if( FAILED( hr ) )
3098 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
3099 return hr;
3104 /* Create the system group of which everything is a part of */
3105 DPID systemGroup = DPID_SYSTEM_GROUP;
3107 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
3108 NULL, 0, 0, TRUE );
3112 if( dwFlags & DPOPEN_JOIN )
3114 DPID dpidServerId = DPID_UNKNOWN;
3116 /* Create the server player for this interface. This way we can receive
3117 * messages for this session.
3119 /* FIXME: I suppose that we should be setting an event for a receive
3120 * type of thing. That way the messaging thread could know to wake
3121 * up. DPlay would then trigger the hEvent for the player the
3122 * message is directed to.
3124 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
3126 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
3129 else if( dwFlags & DPOPEN_CREATE )
3131 DPID dpidNameServerId = DPID_NAME_SERVER;
3133 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
3134 0, DPPLAYER_SERVERPLAYER, bAnsi );
3137 if( FAILED(hr) )
3139 ERR( "Couldn't create name server/system player: %s\n",
3140 DPLAYX_HresultToString(hr) );
3142 else
3144 This->dp2->bConnectionOpen = TRUE;
3147 return hr;
3150 static HRESULT WINAPI DirectPlay2AImpl_Open
3151 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
3153 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3154 TRACE("(%p)->(%p,0x%08x)\n", This, lpsd, dwFlags );
3155 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, TRUE );
3158 static HRESULT WINAPI DirectPlay2WImpl_Open
3159 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
3161 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3162 TRACE("(%p)->(%p,0x%08x)\n", This, lpsd, dwFlags );
3163 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, FALSE );
3166 static HRESULT DP_IF_Receive
3167 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
3168 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi )
3170 LPDPMSG lpMsg = NULL;
3172 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p,%u): stub\n",
3173 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
3175 if( This->dp2->connectionInitialized == NO_PROVIDER )
3177 return DPERR_UNINITIALIZED;
3180 if ( ( lpdwDataSize == NULL ) ||
3181 ( ( dwFlags & DPRECEIVE_FROMPLAYER ) && ( lpidFrom == NULL ) ) ||
3182 ( ( dwFlags & DPRECEIVE_TOPLAYER ) && ( lpidTo == NULL ) ) )
3184 return DPERR_INVALIDPARAMS;
3187 if( dwFlags == 0 )
3189 dwFlags = DPRECEIVE_ALL;
3192 if( dwFlags & DPRECEIVE_ALL )
3194 lpMsg = DPQ_FIRST( This->dp2->receiveMsgs );
3196 else
3198 if ( (lpMsg = DPQ_FIRST( This->dp2->receiveMsgs )) )
3202 if ( ( ( dwFlags & DPRECEIVE_FROMPLAYER ) &&
3203 ( dwFlags & DPRECEIVE_TOPLAYER ) &&
3204 ( lpMsg->idFrom == *lpidFrom ) &&
3205 ( lpMsg->idTo == *lpidTo ) ) || /* From & To */
3206 ( ( dwFlags & DPRECEIVE_FROMPLAYER ) &&
3207 ( lpMsg->idFrom == *lpidFrom ) ) || /* From */
3208 ( ( dwFlags & DPRECEIVE_TOPLAYER ) &&
3209 ( lpMsg->idTo == *lpidTo ) ) ) /* To */
3211 break;
3214 while( (lpMsg = DPQ_NEXT( lpMsg->msgs )) );
3218 if( lpMsg == NULL )
3220 return DPERR_NOMESSAGES;
3223 /* Buffer size check */
3224 if ( ( lpData == NULL ) ||
3225 ( *lpdwDataSize < lpMsg->dwMsgSize ) )
3227 *lpdwDataSize = lpMsg->dwMsgSize;
3228 return DPERR_BUFFERTOOSMALL;
3231 /* Copy into the provided buffer */
3232 if (lpData) CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
3234 /* Set players */
3235 if ( lpidFrom )
3237 *lpidFrom = lpMsg->idFrom;
3239 if ( lpidTo )
3241 *lpidTo = lpMsg->idTo;
3244 /* Remove message from queue */
3245 if( !( dwFlags & DPRECEIVE_PEEK ) )
3247 HeapFree( GetProcessHeap(), 0, lpMsg->msg );
3248 DPQ_REMOVE( This->dp2->receiveMsgs, lpMsg, msgs );
3249 HeapFree( GetProcessHeap(), 0, lpMsg );
3252 return DP_OK;
3255 static HRESULT WINAPI DirectPlay2AImpl_Receive
3256 ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo,
3257 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
3259 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3260 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
3261 lpData, lpdwDataSize, TRUE );
3264 static HRESULT WINAPI DirectPlay2WImpl_Receive
3265 ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo,
3266 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
3268 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3269 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
3270 lpData, lpdwDataSize, FALSE );
3273 static HRESULT WINAPI DirectPlay2AImpl_Send
3274 ( LPDIRECTPLAY2A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3276 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3277 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3278 0, 0, NULL, NULL, TRUE );
3281 static HRESULT WINAPI DirectPlay2WImpl_Send
3282 ( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3284 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3285 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3286 0, 0, NULL, NULL, FALSE );
3289 static HRESULT DP_IF_SetGroupData
3290 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
3291 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3293 lpGroupData lpGData;
3295 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3296 This, idGroup, lpData, dwDataSize, dwFlags, bAnsi );
3298 /* Parameter check */
3299 if( ( lpData == NULL ) &&
3300 ( dwDataSize != 0 )
3303 return DPERR_INVALIDPARAMS;
3306 /* Find the pointer to the data for this player */
3307 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3309 return DPERR_INVALIDOBJECT;
3312 if( !(dwFlags & DPSET_LOCAL) )
3314 FIXME( "Was this group created by this interface?\n" );
3315 /* FIXME: If this is a remote update need to allow it but not
3316 * send a message.
3320 DP_SetGroupData( lpGData, dwFlags, lpData, dwDataSize );
3322 /* FIXME: Only send a message if this group is local to the session otherwise
3323 * it will have been rejected above
3325 if( !(dwFlags & DPSET_LOCAL) )
3327 FIXME( "Send msg?\n" );
3330 return DP_OK;
3333 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
3334 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
3335 DWORD dwDataSize, DWORD dwFlags )
3337 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3338 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, TRUE );
3341 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
3342 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
3343 DWORD dwDataSize, DWORD dwFlags )
3345 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3346 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, FALSE );
3349 static HRESULT DP_IF_SetGroupName
3350 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
3351 DWORD dwFlags, BOOL bAnsi )
3353 lpGroupData lpGData;
3355 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n", This, idGroup,
3356 lpGroupName, dwFlags, bAnsi );
3358 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3360 return DPERR_INVALIDGROUP;
3363 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
3365 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3366 FIXME( "Message not sent and dwFlags ignored\n" );
3368 return DP_OK;
3371 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
3372 ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName,
3373 DWORD dwFlags )
3375 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3376 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
3379 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
3380 ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName,
3381 DWORD dwFlags )
3383 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3384 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
3387 static HRESULT DP_IF_SetPlayerData
3388 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
3389 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3391 lpPlayerList lpPList;
3393 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3394 This, idPlayer, lpData, dwDataSize, dwFlags, bAnsi );
3396 if( This->dp2->connectionInitialized == NO_PROVIDER )
3398 return DPERR_UNINITIALIZED;
3401 /* Parameter check */
3402 if( ( ( lpData == NULL ) && ( dwDataSize != 0 ) ) ||
3403 ( dwDataSize >= MAXDWORD ) )
3405 return DPERR_INVALIDPARAMS;
3408 /* Find the pointer to the data for this player */
3409 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3411 return DPERR_INVALIDPLAYER;
3414 if( !(dwFlags & DPSET_LOCAL) )
3416 FIXME( "Was this group created by this interface?\n" );
3417 /* FIXME: If this is a remote update need to allow it but not
3418 * send a message.
3422 DP_SetPlayerData( lpPList->lpPData, dwFlags, lpData, dwDataSize );
3424 if( !(dwFlags & DPSET_LOCAL) )
3426 FIXME( "Send msg?\n" );
3429 return DP_OK;
3432 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3433 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
3434 DWORD dwDataSize, DWORD dwFlags )
3436 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3437 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3438 dwFlags, TRUE );
3441 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3442 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
3443 DWORD dwDataSize, DWORD dwFlags )
3445 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3446 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3447 dwFlags, FALSE );
3450 static HRESULT DP_IF_SetPlayerName
3451 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
3452 DWORD dwFlags, BOOL bAnsi )
3454 lpPlayerList lpPList;
3456 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n",
3457 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3459 if( This->dp2->connectionInitialized == NO_PROVIDER )
3461 return DPERR_UNINITIALIZED;
3464 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3466 return DPERR_INVALIDGROUP;
3469 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3471 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3472 FIXME( "Message not sent and dwFlags ignored\n" );
3474 return DP_OK;
3477 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3478 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName,
3479 DWORD dwFlags )
3481 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3482 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3485 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3486 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName,
3487 DWORD dwFlags )
3489 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3490 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3493 HRESULT DP_SetSessionDesc
3494 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
3495 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3497 DWORD dwRequiredSize;
3498 LPDPSESSIONDESC2 lpTempSessDesc;
3500 TRACE( "(%p)->(%p,0x%08x,%u,%u)\n",
3501 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3503 /* FIXME: Copy into This->dp2->lpSessionDesc */
3504 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3505 lpTempSessDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize );
3507 if( lpTempSessDesc == NULL )
3509 return DPERR_OUTOFMEMORY;
3512 /* Free the old */
3513 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3515 This->dp2->lpSessionDesc = lpTempSessDesc;
3516 /* Set the new */
3517 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3518 if( bInitial )
3520 /*Initializing session GUID*/
3521 CoCreateGuid( &(This->dp2->lpSessionDesc->guidInstance) );
3523 /* If this is an external invocation of the interface, we should be
3524 * letting everyone know that things have changed. Otherwise this is
3525 * just an initialization and it doesn't need to be propagated.
3527 if( !bInitial )
3529 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3532 return DP_OK;
3535 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3536 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3538 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3540 if( This->dp2->connectionInitialized == NO_PROVIDER )
3542 return DPERR_UNINITIALIZED;
3545 if( !This->dp2->bConnectionOpen )
3547 return DPERR_NOSESSIONS;
3550 if( dwFlags || (lpSessDesc == NULL) )
3552 return DPERR_INVALIDPARAMS;
3555 /* Illegal combinations of flags */
3556 if ( ( lpSessDesc->dwFlags & DPSESSION_MIGRATEHOST ) &&
3557 ( lpSessDesc->dwFlags & ( DPSESSION_CLIENTSERVER |
3558 DPSESSION_MULTICASTSERVER |
3559 DPSESSION_SECURESERVER ) ) )
3561 return DPERR_INVALIDFLAGS;
3564 /* Only the host is allowed to update the session desc */
3565 if( !This->dp2->bHostInterface )
3567 return DPERR_ACCESSDENIED;
3570 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3573 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3574 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3576 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3578 if( This->dp2->connectionInitialized == NO_PROVIDER )
3580 return DPERR_UNINITIALIZED;
3583 if( !This->dp2->bConnectionOpen )
3585 return DPERR_NOSESSIONS;
3588 if( dwFlags || (lpSessDesc == NULL) )
3590 return DPERR_INVALIDPARAMS;
3593 /* Illegal combinations of flags */
3594 if ( ( lpSessDesc->dwFlags & DPSESSION_MIGRATEHOST ) &&
3595 ( lpSessDesc->dwFlags & ( DPSESSION_CLIENTSERVER |
3596 DPSESSION_MULTICASTSERVER |
3597 DPSESSION_SECURESERVER ) ) )
3599 return DPERR_INVALIDFLAGS;
3602 /* Only the host is allowed to update the session desc */
3603 if( !This->dp2->bHostInterface )
3605 return DPERR_ACCESSDENIED;
3608 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3611 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3612 static DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3614 DWORD dwSize = 0;
3616 if( lpSessDesc == NULL )
3618 /* Hmmm..don't need any size? */
3619 ERR( "NULL lpSessDesc\n" );
3620 return dwSize;
3623 dwSize += sizeof( *lpSessDesc );
3625 if( bAnsi )
3627 if( lpSessDesc->u1.lpszSessionNameA )
3629 dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1;
3632 if( lpSessDesc->u2.lpszPasswordA )
3634 dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1;
3637 else /* UNICODE */
3639 if( lpSessDesc->u1.lpszSessionName )
3641 dwSize += sizeof( WCHAR ) *
3642 ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 );
3645 if( lpSessDesc->u2.lpszPassword )
3647 dwSize += sizeof( WCHAR ) *
3648 ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 );
3652 return dwSize;
3655 /* Assumes that contiguous buffers are already allocated. */
3656 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3657 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3659 BYTE* lpStartOfFreeSpace;
3661 if( lpSessionDest == NULL )
3663 ERR( "NULL lpSessionDest\n" );
3664 return;
3667 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3669 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3671 if( bAnsi )
3673 if( lpSessionSrc->u1.lpszSessionNameA )
3675 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3676 lpSessionDest->u1.lpszSessionNameA );
3677 lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3678 lpStartOfFreeSpace +=
3679 lstrlenA( lpSessionDest->u1.lpszSessionNameA ) + 1;
3682 if( lpSessionSrc->u2.lpszPasswordA )
3684 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3685 lpSessionDest->u2.lpszPasswordA );
3686 lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3687 lpStartOfFreeSpace +=
3688 lstrlenA( lpSessionDest->u2.lpszPasswordA ) + 1;
3691 else /* UNICODE */
3693 if( lpSessionSrc->u1.lpszSessionName )
3695 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3696 lpSessionDest->u1.lpszSessionName );
3697 lpSessionDest->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3698 lpStartOfFreeSpace += sizeof(WCHAR) *
3699 ( lstrlenW( lpSessionDest->u1.lpszSessionName ) + 1 );
3702 if( lpSessionSrc->u2.lpszPassword )
3704 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3705 lpSessionDest->u2.lpszPassword );
3706 lpSessionDest->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3707 lpStartOfFreeSpace += sizeof(WCHAR) *
3708 ( lstrlenW( lpSessionDest->u2.lpszPassword ) + 1 );
3714 static HRESULT DP_IF_AddGroupToGroup
3715 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3717 lpGroupData lpGData;
3718 lpGroupList lpNewGList;
3720 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, idParentGroup, idGroup );
3722 if( This->dp2->connectionInitialized == NO_PROVIDER )
3724 return DPERR_UNINITIALIZED;
3727 if( DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) == NULL )
3729 return DPERR_INVALIDGROUP;
3732 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3734 return DPERR_INVALIDGROUP;
3737 /* Create a player list (ie "shortcut" ) */
3738 lpNewGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewGList ) );
3739 if( lpNewGList == NULL )
3741 return DPERR_CANTADDPLAYER;
3744 /* Add the shortcut */
3745 lpGData->uRef++;
3746 lpNewGList->lpGData = lpGData;
3748 /* Add the player to the list of players for this group */
3749 DPQ_INSERT( lpGData->groups, lpNewGList, groups );
3751 /* Send a ADDGROUPTOGROUP message */
3752 FIXME( "Not sending message\n" );
3754 return DP_OK;
3757 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3758 ( LPDIRECTPLAY3A iface, DPID idParentGroup, DPID idGroup )
3760 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3761 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3764 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3765 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3767 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3768 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3771 static HRESULT DP_IF_CreateGroupInGroup
3772 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
3773 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
3774 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3776 lpGroupData lpGParentData;
3777 lpGroupList lpGList;
3778 lpGroupData lpGData;
3780 TRACE( "(%p)->(0x%08x,%p,%p,%p,0x%08x,0x%08x,%u)\n",
3781 This, idParentGroup, lpidGroup, lpGroupName, lpData,
3782 dwDataSize, dwFlags, bAnsi );
3784 /* Verify that the specified parent is valid */
3785 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This,
3786 idParentGroup ) ) == NULL
3789 return DPERR_INVALIDGROUP;
3792 lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName,
3793 dwFlags, idParentGroup, bAnsi );
3795 if( lpGData == NULL )
3797 return DPERR_CANTADDPLAYER; /* yes player not group */
3800 /* Something else is referencing this data */
3801 lpGData->uRef++;
3803 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
3805 /* The list has now been inserted into the interface group list. We now
3806 need to put a "shortcut" to this group in the parent group */
3807 lpGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGList ) );
3808 if( lpGList == NULL )
3810 FIXME( "Memory leak\n" );
3811 return DPERR_CANTADDPLAYER; /* yes player not group */
3814 lpGList->lpGData = lpGData;
3816 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
3818 /* Let the SP know that we've created this group */
3819 if( This->dp2->spData.lpCB->CreateGroup )
3821 DPSP_CREATEGROUPDATA data;
3823 TRACE( "Calling SP CreateGroup\n" );
3825 data.idGroup = *lpidGroup;
3826 data.dwFlags = dwFlags;
3827 data.lpSPMessageHeader = lpMsgHdr;
3828 data.lpISP = This->dp2->spData.lpISP;
3830 (*This->dp2->spData.lpCB->CreateGroup)( &data );
3833 /* Inform all other peers of the creation of a new group. If there are
3834 * no peers keep this quiet.
3836 if( This->dp2->lpSessionDesc &&
3837 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
3839 DPMSG_CREATEPLAYERORGROUP msg;
3841 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
3842 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
3843 msg.dpId = *lpidGroup;
3844 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
3845 msg.lpData = lpData;
3846 msg.dwDataSize = dwDataSize;
3847 msg.dpnName = *lpGroupName;
3849 /* FIXME: Correct to just use send effectively? */
3850 /* FIXME: Should size include data w/ message or just message "header" */
3851 /* FIXME: Check return code */
3852 DP_SendEx( (IDirectPlay2Impl*)This,
3853 DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
3854 0, 0, NULL, NULL, bAnsi );
3857 return DP_OK;
3860 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3861 ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup,
3862 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3863 DWORD dwFlags )
3865 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3867 if( This->dp2->connectionInitialized == NO_PROVIDER )
3869 return DPERR_UNINITIALIZED;
3872 if( lpidGroup == NULL ||
3873 !This->dp2->bConnectionOpen ||
3874 dwDataSize >= MAXDWORD ||
3875 ( lpData == NULL && dwDataSize != 0 ) )
3877 return DPERR_INVALIDPARAMS;
3880 *lpidGroup = DPID_UNKNOWN;
3882 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3883 lpGroupName, lpData, dwDataSize, dwFlags,
3884 TRUE );
3887 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3888 ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup,
3889 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3890 DWORD dwFlags )
3892 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3894 if( This->dp2->connectionInitialized == NO_PROVIDER )
3896 return DPERR_UNINITIALIZED;
3899 if( lpidGroup == NULL ||
3900 !This->dp2->bConnectionOpen ||
3901 dwDataSize >= MAXDWORD ||
3902 ( lpData == NULL && dwDataSize != 0 ) )
3904 return DPERR_INVALIDPARAMS;
3907 *lpidGroup = DPID_UNKNOWN;
3909 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3910 lpGroupName, lpData, dwDataSize,
3911 dwFlags, FALSE );
3914 static HRESULT DP_IF_DeleteGroupFromGroup
3915 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3917 lpGroupList lpGList;
3918 lpGroupData lpGParentData;
3920 TRACE("(%p)->(0x%08x,0x%08x)\n", This, idParentGroup, idGroup );
3922 /* Is the parent group valid? */
3923 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3925 return DPERR_INVALIDGROUP;
3928 /* Remove the group from the parent group queue */
3929 DPQ_REMOVE_ENTRY( lpGParentData->groups, groups, lpGData->dpid, ==, idGroup, lpGList );
3931 if( lpGList == NULL )
3933 return DPERR_INVALIDGROUP;
3936 /* Decrement the ref count */
3937 lpGList->lpGData->uRef--;
3939 /* Free up the list item */
3940 HeapFree( GetProcessHeap(), 0, lpGList );
3942 /* Should send a DELETEGROUPFROMGROUP message */
3943 FIXME( "message not sent\n" );
3945 return DP_OK;
3948 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3949 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3951 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3952 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3955 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3956 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3958 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3959 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3961 static BOOL DP_BuildCompoundAddr( GUID guidDataType,
3962 LPGUID lpcSpGuid,
3963 LPVOID* lplpAddrBuf,
3964 LPDWORD lpdwBufSize )
3966 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3967 HRESULT hr;
3969 dpCompoundAddress.dwDataSize = sizeof( GUID );
3970 dpCompoundAddress.guidDataType = guidDataType;
3971 dpCompoundAddress.lpData = lpcSpGuid;
3973 *lplpAddrBuf = NULL;
3974 *lpdwBufSize = 0;
3976 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3977 lpdwBufSize, TRUE );
3979 if( hr != DPERR_BUFFERTOOSMALL )
3981 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3982 return FALSE;
3985 /* Now allocate the buffer */
3986 *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3987 *lpdwBufSize );
3989 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3990 lpdwBufSize, TRUE );
3991 if( FAILED(hr) )
3993 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3994 return FALSE;
3997 return TRUE;
4000 static HRESULT WINAPI DP_IF_EnumConnections
4001 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication,
4002 LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext,
4003 DWORD dwFlags, BOOL bAnsi )
4005 HKEY hkResult;
4006 WCHAR searchSubKeySP[] = {
4007 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
4008 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
4009 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
4010 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
4011 WCHAR searchSubKeyLP[] = {
4012 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
4013 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
4014 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
4015 'L', 'o', 'b', 'b', 'y', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
4016 WCHAR guidDataSubKey[] = { 'G', 'u', 'i', 'd', 0 };
4017 WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */
4018 DWORD dwIndex, sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR);
4019 FILETIME filetime;
4021 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
4022 if( dwFlags == 0 )
4024 dwFlags = DPCONNECTION_DIRECTPLAY;
4027 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
4028 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) ) )
4030 return DPERR_INVALIDFLAGS;
4033 if( !lpEnumCallback )
4035 return DPERR_INVALIDPARAMS;
4039 /* Need to loop over the service providers in the registry */
4040 if( RegOpenKeyExW( HKEY_LOCAL_MACHINE,
4041 ( dwFlags & DPCONNECTION_DIRECTPLAY ) ? searchSubKeySP
4042 : searchSubKeyLP,
4043 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4045 /* Hmmm. Does this mean that there are no service providers? */
4046 ERR(": no service providers?\n");
4047 return DP_OK;
4051 /* Traverse all the service providers we have available */
4052 for( dwIndex=0;
4053 RegEnumKeyExW( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4054 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4055 ++dwIndex, sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR) )
4057 HKEY hkServiceProvider;
4058 GUID serviceProviderGUID;
4059 WCHAR guidKeyContent[39];
4060 DWORD sizeOfReturnBuffer = sizeof(guidKeyContent);
4061 DPNAME dpName;
4062 BOOL continueEnumeration = TRUE;
4064 LPVOID lpAddressBuffer = NULL;
4065 DWORD dwAddressBufferSize = 0;
4068 TRACE(" this time through: %s\n", debugstr_w(subKeyName) );
4070 /* Get a handle for this particular service provider */
4071 if( RegOpenKeyExW( hkResult, subKeyName, 0, KEY_READ,
4072 &hkServiceProvider ) != ERROR_SUCCESS )
4074 ERR(": what the heck is going on?\n" );
4075 continue;
4078 if( RegQueryValueExW( hkServiceProvider, guidDataSubKey,
4079 NULL, NULL, (LPBYTE)guidKeyContent,
4080 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4082 ERR(": missing GUID registry data members\n" );
4083 RegCloseKey(hkServiceProvider);
4084 continue;
4086 RegCloseKey(hkServiceProvider);
4088 CLSIDFromString( guidKeyContent, &serviceProviderGUID );
4090 /* Fill in the DPNAME struct for the service provider */
4091 dpName.dwSize = sizeof( dpName );
4092 dpName.dwFlags = 0;
4093 if ( bAnsi )
4095 dpName.u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4096 sizeOfSubKeyName+1 );
4097 WideCharToMultiByte( CP_ACP, 0, subKeyName,
4098 -1, dpName.u1.lpszShortNameA, -1, 0, 0);
4099 dpName.u2.lpszLongNameA = NULL;
4101 else
4103 dpName.u1.lpszShortName = subKeyName;
4104 dpName.u2.lpszLongName = NULL;
4107 /* Create the compound address for the service provider.
4108 * NOTE: This is a gruesome architectural scar right now. DP
4109 * uses DPL and DPL uses DP. Nasty stuff. This may be why the
4110 * native dll just gets around this little bit by allocating an
4111 * 80 byte buffer which isn't even filled with a valid compound
4112 * address. Oh well. Creating a proper compound address is the
4113 * way to go anyways despite this method taking slightly more
4114 * heap space and realtime :) */
4116 if ( DP_BuildCompoundAddr( ( ( dwFlags & DPCONNECTION_DIRECTPLAY )
4117 ? DPAID_ServiceProvider
4118 : DPAID_LobbyProvider ),
4119 &serviceProviderGUID,
4120 &lpAddressBuffer,
4121 &dwAddressBufferSize ) )
4123 /* The enumeration will return FALSE if we are not to continue */
4124 continueEnumeration = lpEnumCallback( &serviceProviderGUID, lpAddressBuffer,
4125 dwAddressBufferSize, &dpName,
4126 dwFlags, lpContext );
4128 else
4130 ERR( "Couldn't build compound address\n" );
4133 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
4134 if ( bAnsi )
4135 HeapFree( GetProcessHeap(), 0, dpName.u1.lpszShortNameA );
4137 if (!continueEnumeration)
4138 return DP_OK;
4141 return DP_OK;
4144 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
4145 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
4147 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4148 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
4149 return DP_IF_EnumConnections( iface, lpguidApplication, lpEnumCallback, lpContext, dwFlags, TRUE );
4152 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
4153 ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
4155 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4156 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
4157 return DP_IF_EnumConnections( iface, lpguidApplication, lpEnumCallback, lpContext, dwFlags, FALSE );
4160 static HRESULT DP_IF_EnumGroupsInGroup
4161 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
4162 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
4163 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
4165 lpGroupList lpGList;
4166 lpGroupData lpGData;
4168 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
4169 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
4170 lpContext, dwFlags, bAnsi );
4172 if( This->dp2->connectionInitialized == NO_PROVIDER )
4174 return DPERR_UNINITIALIZED;
4177 if( !This->dp2->bConnectionOpen )
4179 return DPERR_NOSESSIONS;
4182 if( ( lpEnumPlayersCallback2 == NULL ) ||
4183 ( ( dwFlags & DPENUMGROUPS_SESSION ) && ( lpguidInstance == NULL ) ) )
4185 return DPERR_INVALIDPARAMS;
4188 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4190 return DPERR_INVALIDGROUP;
4193 if( DPQ_IS_EMPTY( lpGData->groups ) )
4195 return DP_OK;
4198 lpGList = DPQ_FIRST( lpGData->groups );
4200 for( ;; )
4202 /* FIXME: Should check dwFlags for match here */
4204 if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP,
4205 &lpGList->lpGData->name, dwFlags,
4206 lpContext ) )
4208 return DP_OK; /* User requested break */
4211 if( DPQ_IS_ENDOFLIST( lpGList->groups ) )
4213 break;
4216 lpGList = DPQ_NEXT( lpGList->groups );
4220 return DP_OK;
4223 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
4224 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
4225 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
4226 DWORD dwFlags )
4228 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4229 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
4230 lpEnumPlayersCallback2, lpContext, dwFlags,
4231 TRUE );
4234 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
4235 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
4236 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
4237 DWORD dwFlags )
4239 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4240 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
4241 lpEnumPlayersCallback2, lpContext, dwFlags,
4242 FALSE );
4245 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
4246 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
4248 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4249 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
4250 return DP_OK;
4253 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
4254 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
4256 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4257 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
4258 return DP_OK;
4261 static BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
4262 REFGUID guidDataType,
4263 DWORD dwDataSize,
4264 LPCVOID lpData,
4265 LPVOID lpContext )
4267 /* Looking for the GUID of the provider to load */
4268 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
4269 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
4272 TRACE( "Found SP/LP (%s) %s (data size = 0x%08x)\n",
4273 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
4275 if( dwDataSize != sizeof( GUID ) )
4277 ERR( "Invalid sp/lp guid size 0x%08x\n", dwDataSize );
4280 memcpy( lpContext, lpData, dwDataSize );
4282 /* There shouldn't be more than 1 GUID/compound address */
4283 return FALSE;
4286 /* Still waiting for what we want */
4287 return TRUE;
4291 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
4292 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
4294 UINT i;
4295 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4296 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
4297 LPCSTR guidDataSubKey = "Guid";
4298 LPCSTR majVerDataSubKey = "dwReserved1";
4299 LPCSTR minVerDataSubKey = "dwReserved2";
4300 LPCSTR pathSubKey = "Path";
4302 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
4304 /* FIXME: Cloned code with a quick hack. */
4305 for( i=0; i<2; i++ )
4307 HKEY hkResult;
4308 LPCSTR searchSubKey;
4309 char subKeyName[51];
4310 DWORD dwIndex, sizeOfSubKeyName=50;
4311 FILETIME filetime;
4313 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
4314 *lpbIsDpSp = (i == 0) ? TRUE : FALSE;
4317 /* Need to loop over the service providers in the registry */
4318 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4319 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4321 /* Hmmm. Does this mean that there are no service providers? */
4322 ERR(": no service providers?\n");
4323 return 0;
4326 /* Traverse all the service providers we have available */
4327 for( dwIndex=0;
4328 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4329 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4330 ++dwIndex, sizeOfSubKeyName=51 )
4333 HKEY hkServiceProvider;
4334 GUID serviceProviderGUID;
4335 DWORD returnType, sizeOfReturnBuffer = 255;
4336 char returnBuffer[256];
4337 WCHAR buff[51];
4338 DWORD dwTemp, len;
4340 TRACE(" this time through: %s\n", subKeyName );
4342 /* Get a handle for this particular service provider */
4343 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4344 &hkServiceProvider ) != ERROR_SUCCESS )
4346 ERR(": what the heck is going on?\n" );
4347 continue;
4350 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4351 NULL, &returnType, (LPBYTE)returnBuffer,
4352 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4354 ERR(": missing GUID registry data members\n" );
4355 continue;
4358 /* FIXME: Check return types to ensure we're interpreting data right */
4359 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4360 CLSIDFromString( buff, &serviceProviderGUID );
4361 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4363 /* Determine if this is the Service Provider that the user asked for */
4364 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
4366 continue;
4369 if( i == 0 ) /* DP SP */
4371 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
4372 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
4373 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
4376 sizeOfReturnBuffer = 255;
4378 /* Get dwReserved1 */
4379 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
4380 NULL, &returnType, (LPBYTE)returnBuffer,
4381 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4383 ERR(": missing dwReserved1 registry data members\n") ;
4384 continue;
4387 if( i == 0 )
4388 memcpy( &lpSpData->dwReserved1, returnBuffer, sizeof(lpSpData->dwReserved1) );
4390 sizeOfReturnBuffer = 255;
4392 /* Get dwReserved2 */
4393 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4394 NULL, &returnType, (LPBYTE)returnBuffer,
4395 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4397 ERR(": missing dwReserved1 registry data members\n") ;
4398 continue;
4401 if( i == 0 )
4402 memcpy( &lpSpData->dwReserved2, returnBuffer, sizeof(lpSpData->dwReserved2) );
4404 sizeOfReturnBuffer = 255;
4406 /* Get the path for this service provider */
4407 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
4408 NULL, NULL, (LPBYTE)returnBuffer,
4409 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
4411 ERR(": missing PATH registry data members: 0x%08x\n", dwTemp );
4412 continue;
4415 TRACE( "Loading %s\n", returnBuffer );
4416 return LoadLibraryA( returnBuffer );
4420 return 0;
4423 static
4424 HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider )
4426 HRESULT hr;
4427 LPDPSP_SPINIT SPInit;
4429 /* Initialize the service provider by calling SPInit */
4430 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4432 if( SPInit == NULL )
4434 ERR( "Service provider doesn't provide SPInit interface?\n" );
4435 FreeLibrary( hServiceProvider );
4436 return DPERR_UNAVAILABLE;
4439 TRACE( "Calling SPInit (DP SP entry point)\n" );
4441 hr = (*SPInit)( &This->dp2->spData );
4443 if( FAILED(hr) )
4445 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4446 FreeLibrary( hServiceProvider );
4447 return hr;
4450 /* FIXME: Need to verify the sanity of the returned callback table
4451 * using IsBadCodePtr */
4452 This->dp2->bSPInitialized = TRUE;
4454 /* This interface is now initialized as a DP object */
4455 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
4457 /* Store the handle of the module so that we can unload it later */
4458 This->dp2->hServiceProvider = hServiceProvider;
4460 return hr;
4463 static
4464 HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hLobbyProvider )
4466 HRESULT hr;
4467 LPSP_INIT DPLSPInit;
4469 /* Initialize the service provider by calling SPInit */
4470 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
4472 if( DPLSPInit == NULL )
4474 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4475 FreeLibrary( hLobbyProvider );
4476 return DPERR_UNAVAILABLE;
4479 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4481 hr = (*DPLSPInit)( &This->dp2->dplspData );
4483 if( FAILED(hr) )
4485 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4486 FreeLibrary( hLobbyProvider );
4487 return hr;
4490 /* FIXME: Need to verify the sanity of the returned callback table
4491 * using IsBadCodePtr */
4493 This->dp2->bDPLSPInitialized = TRUE;
4495 /* This interface is now initialized as a lobby object */
4496 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
4498 /* Store the handle of the module so that we can unload it later */
4499 This->dp2->hDPLobbyProvider = hLobbyProvider;
4501 return hr;
4504 static HRESULT DP_IF_InitializeConnection
4505 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi )
4507 HMODULE hServiceProvider;
4508 HRESULT hr;
4509 GUID guidSP;
4510 const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
4511 BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4513 TRACE("(%p)->(%p,0x%08x,%u)\n", This, lpConnection, dwFlags, bAnsi );
4515 if ( lpConnection == NULL )
4517 return DPERR_INVALIDPARAMS;
4520 if( dwFlags != 0 )
4522 return DPERR_INVALIDFLAGS;
4525 if( This->dp2->connectionInitialized != NO_PROVIDER )
4527 return DPERR_ALREADYINITIALIZED;
4530 /* Find out what the requested SP is and how large this buffer is */
4531 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
4532 dwAddrSize, &guidSP );
4534 if( FAILED(hr) )
4536 ERR( "Invalid compound address?\n" );
4537 return DPERR_UNAVAILABLE;
4540 /* Load the service provider */
4541 hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp );
4543 if( hServiceProvider == 0 )
4545 ERR( "Unable to load service provider %s\n", debugstr_guid(&guidSP) );
4546 return DPERR_UNAVAILABLE;
4549 if( bIsDpSp )
4551 /* Fill in what we can of the Service Provider required information.
4552 * The rest was be done in DP_LoadSP
4554 This->dp2->spData.lpAddress = lpConnection;
4555 This->dp2->spData.dwAddressSize = dwAddrSize;
4556 This->dp2->spData.lpGuid = &guidSP;
4558 hr = DP_InitializeDPSP( This, hServiceProvider );
4560 else
4562 This->dp2->dplspData.lpAddress = lpConnection;
4564 hr = DP_InitializeDPLSP( This, hServiceProvider );
4567 if( FAILED(hr) )
4569 return hr;
4572 return DP_OK;
4575 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4576 ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
4578 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4579 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE );
4582 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4583 ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
4585 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4586 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE );
4589 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4590 ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4591 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4593 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4594 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4597 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4598 ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4599 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4601 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4602 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4605 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4606 ( LPDIRECTPLAY3A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4608 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4609 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4610 return DP_OK;
4613 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4614 ( LPDIRECTPLAY3 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4616 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4617 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4618 return DP_OK;
4621 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4622 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4624 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4625 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4626 return DP_OK;
4629 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4630 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4632 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4633 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4634 return DP_OK;
4637 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4638 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup )
4640 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4641 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, dwFlags, idGroup );
4642 return DP_OK;
4645 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4646 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup )
4648 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4649 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, dwFlags, idGroup );
4650 return DP_OK;
4653 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4654 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDWORD lpdwFlags )
4656 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4657 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpdwFlags );
4658 return DP_OK;
4661 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4662 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDWORD lpdwFlags )
4664 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4665 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpdwFlags );
4666 return DP_OK;
4669 static HRESULT DP_IF_GetGroupParent
4670 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
4671 BOOL bAnsi )
4673 lpGroupData lpGData;
4675 TRACE("(%p)->(0x%08x,%p,%u)\n", This, idGroup, lpidGroup, bAnsi );
4677 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4679 return DPERR_INVALIDGROUP;
4682 *lpidGroup = lpGData->dpid;
4684 return DP_OK;
4687 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4688 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
4690 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4691 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE );
4693 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4694 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
4696 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4697 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE );
4700 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4701 ( LPDIRECTPLAY3A iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4703 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4704 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4705 return DP_OK;
4708 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4709 ( LPDIRECTPLAY3 iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4711 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4712 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4713 return DP_OK;
4716 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4717 ( LPDIRECTPLAY3A iface, DPID idPlayer, LPDWORD lpdwFlags )
4719 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4720 FIXME("(%p)->(0x%08x,%p): stub\n", This, idPlayer, lpdwFlags );
4721 return DP_OK;
4724 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4725 ( LPDIRECTPLAY3 iface, DPID idPlayer, LPDWORD lpdwFlags )
4727 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4728 FIXME("(%p)->(0x%08x,%p): stub\n", This, idPlayer, lpdwFlags );
4729 return DP_OK;
4732 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4733 ( LPDIRECTPLAY4A iface, DPID idGroup, LPDPID lpidGroupOwner )
4735 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4736 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpidGroupOwner );
4737 return DP_OK;
4740 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4741 ( LPDIRECTPLAY4 iface, DPID idGroup, LPDPID lpidGroupOwner )
4743 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4744 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpidGroupOwner );
4745 return DP_OK;
4748 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4749 ( LPDIRECTPLAY4A iface, DPID idGroup , DPID idGroupOwner )
4751 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4752 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, idGroup, idGroupOwner );
4753 return DP_OK;
4756 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4757 ( LPDIRECTPLAY4 iface, DPID idGroup , DPID idGroupOwner )
4759 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4760 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, idGroup, idGroupOwner );
4761 return DP_OK;
4764 static HRESULT DP_SendEx
4765 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4766 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4767 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi )
4769 lpGroupData lpGData;
4770 BOOL bSendToGroup;
4772 TRACE( "(%p)->(0x%08x,0x%08x,0x%08x,%p,0x%08x,0x%08x,0x%08x,%p,%p,%u)\n",
4773 This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority,
4774 dwTimeout, lpContext, lpdwMsgID, bAnsi );
4776 if( This->dp2->connectionInitialized == NO_PROVIDER )
4778 return DPERR_UNINITIALIZED;
4781 /* FIXME: Add parameter checking */
4782 /* FIXME: First call to this needs to acquire a message id which will be
4783 * used for multiple sends
4786 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4788 /* Check idFrom points to a valid player */
4789 if ( DP_FindPlayer( This, idFrom ) == NULL )
4791 ERR( "Invalid from player 0x%08x\n", idFrom );
4792 return DPERR_INVALIDPLAYER;
4795 /* Check idTo: it can be a player or a group */
4796 if( idTo == DPID_ALLPLAYERS )
4798 bSendToGroup = TRUE;
4799 lpGData = This->dp2->lpSysGroup;
4801 else if ( DP_FindPlayer( This, idTo ) )
4803 bSendToGroup = FALSE;
4805 else if ( ( lpGData = DP_FindAnyGroup( This, idTo ) ) )
4807 bSendToGroup = TRUE;
4809 else
4811 return DPERR_INVALIDPLAYER;
4814 if ( bSendToGroup )
4816 #if 0
4817 DPSP_SENDTOGROUPEXDATA data;
4819 data.lpISP = This->dp2->spData.lpISP;
4820 data.dwFlags = dwFlags;
4821 data.idGroupTo = idTo;
4822 data.idPlayerFrom = idFrom;
4823 data.lpSendBuffers = lpData;
4824 data.cBuffers = NULL;
4825 data.dwMessageSize = dwDataSize;
4826 data.dwPriority = dwPriority;
4827 data.dwTimeout = dwTimeout;
4828 data.lpDPContext = lpContext;
4829 data.lpdwSPMsgID = lpdwMsgID;
4831 return (*This->dp2->spData.lpCB->SendToGroupEx)( &data );
4832 #endif
4833 DPSP_SENDDATA data;
4834 lpPlayerList lpPList;
4836 data.dwFlags = dwFlags;
4837 data.idPlayerFrom = idFrom;
4838 data.lpMessage = lpData;
4839 data.dwMessageSize = dwDataSize;
4840 data.bSystemMessage = FALSE;
4841 data.lpISP = This->dp2->spData.lpISP;
4843 if ( (lpPList = DPQ_FIRST( lpGData->players )) )
4847 if ( ~lpPList->lpPData->dwFlags & DPLAYI_PLAYER_PLAYERLOCAL )
4849 data.idPlayerTo = lpPList->lpPData->dpid;
4850 (*This->dp2->spData.lpCB->Send)( &data );
4853 while( (lpPList = DPQ_NEXT( lpPList->players )) );
4856 else
4858 DPSP_SENDDATA data;
4860 data.dwFlags = dwFlags;
4861 data.idPlayerFrom = idFrom;
4862 data.idPlayerTo = idTo;
4863 data.lpMessage = lpData;
4864 data.dwMessageSize = dwDataSize;
4865 data.bSystemMessage = FALSE;
4866 data.lpISP = This->dp2->spData.lpISP;
4868 return (*This->dp2->spData.lpCB->Send)( &data );
4871 /* Have the service provider send this message */
4872 /*wat?
4873 return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority,
4874 dwTimeout, lpContext, lpdwMsgID );*/
4876 return DP_OK;
4880 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4881 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4882 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4883 LPVOID lpContext, LPDWORD lpdwMsgID )
4885 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4886 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4887 dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE );
4890 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4891 ( LPDIRECTPLAY4 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, FALSE );
4900 static HRESULT DP_SP_SendEx
4901 ( IDirectPlay2Impl* This, DWORD dwFlags,
4902 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4903 LPVOID lpContext, LPDWORD lpdwMsgID )
4905 LPDPMSG lpMElem;
4907 FIXME( ": stub\n" );
4909 /* FIXME: This queuing should only be for async messages */
4911 lpMElem = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpMElem ) );
4912 lpMElem->msg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
4914 CopyMemory( lpMElem->msg, lpData, dwDataSize );
4916 /* FIXME: Need to queue based on priority */
4917 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
4919 return DP_OK;
4922 static HRESULT DP_IF_GetMessageQueue
4923 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4924 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi )
4926 HRESULT hr = DP_OK;
4928 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%p,%u): semi stub\n",
4929 This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi );
4931 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4932 /* FIXME: What about sends which are not immediate? */
4934 if( This->dp2->spData.lpCB->GetMessageQueue )
4936 DPSP_GETMESSAGEQUEUEDATA data;
4938 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4940 /* FIXME: None of this is documented :( */
4942 data.lpISP = This->dp2->spData.lpISP;
4943 data.dwFlags = dwFlags;
4944 data.idFrom = idFrom;
4945 data.idTo = idTo;
4946 data.lpdwNumMsgs = lpdwNumMsgs;
4947 data.lpdwNumBytes = lpdwNumBytes;
4949 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
4951 else
4953 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4956 return hr;
4959 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4960 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4961 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4963 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4964 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4965 lpdwNumBytes, TRUE );
4968 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4969 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4970 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4972 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4973 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4974 lpdwNumBytes, FALSE );
4977 static HRESULT DP_IF_CancelMessage
4978 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
4979 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi )
4981 HRESULT hr = DP_OK;
4983 FIXME( "(%p)->(0x%08x,0x%08x,%u): semi stub\n",
4984 This, dwMsgID, dwFlags, bAnsi );
4986 if( This->dp2->spData.lpCB->Cancel )
4988 DPSP_CANCELDATA data;
4990 TRACE( "Calling SP Cancel\n" );
4992 /* FIXME: Undocumented callback */
4994 data.lpISP = This->dp2->spData.lpISP;
4995 data.dwFlags = dwFlags;
4996 data.lprglpvSPMsgID = NULL;
4997 data.cSPMsgID = dwMsgID;
4998 data.dwMinPriority = dwMinPriority;
4999 data.dwMaxPriority = dwMaxPriority;
5001 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
5003 else
5005 FIXME( "SP doesn't implement Cancel\n" );
5008 return hr;
5011 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
5012 ( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags )
5014 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
5016 if( dwFlags != 0 )
5018 return DPERR_INVALIDFLAGS;
5021 if( dwMsgID == 0 )
5023 dwFlags |= DPCANCELSEND_ALL;
5026 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE );
5029 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
5030 ( LPDIRECTPLAY4 iface, DWORD dwMsgID, DWORD dwFlags )
5032 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
5034 if( dwFlags != 0 )
5036 return DPERR_INVALIDFLAGS;
5039 if( dwMsgID == 0 )
5041 dwFlags |= DPCANCELSEND_ALL;
5044 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, FALSE );
5047 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
5048 ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority,
5049 DWORD dwFlags )
5051 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
5053 if( dwFlags != 0 )
5055 return DPERR_INVALIDFLAGS;
5058 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
5059 dwMaxPriority, TRUE );
5062 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
5063 ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority,
5064 DWORD dwFlags )
5066 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
5068 if( dwFlags != 0 )
5070 return DPERR_INVALIDFLAGS;
5073 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
5074 dwMaxPriority, FALSE );
5077 /* Note: Hack so we can reuse the old functions without compiler warnings */
5078 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5079 # define XCAST(fun) (typeof(directPlay2WVT.fun))
5080 #else
5081 # define XCAST(fun) (void*)
5082 #endif
5084 static const IDirectPlay2Vtbl directPlay2WVT =
5086 XCAST(QueryInterface)DP_QueryInterface,
5087 XCAST(AddRef)DP_AddRef,
5088 XCAST(Release)DP_Release,
5090 DirectPlay2WImpl_AddPlayerToGroup,
5091 DirectPlay2WImpl_Close,
5092 DirectPlay2WImpl_CreateGroup,
5093 DirectPlay2WImpl_CreatePlayer,
5094 DirectPlay2WImpl_DeletePlayerFromGroup,
5095 DirectPlay2WImpl_DestroyGroup,
5096 DirectPlay2WImpl_DestroyPlayer,
5097 DirectPlay2WImpl_EnumGroupPlayers,
5098 DirectPlay2WImpl_EnumGroups,
5099 DirectPlay2WImpl_EnumPlayers,
5100 DirectPlay2WImpl_EnumSessions,
5101 DirectPlay2WImpl_GetCaps,
5102 DirectPlay2WImpl_GetGroupData,
5103 DirectPlay2WImpl_GetGroupName,
5104 DirectPlay2WImpl_GetMessageCount,
5105 DirectPlay2WImpl_GetPlayerAddress,
5106 DirectPlay2WImpl_GetPlayerCaps,
5107 DirectPlay2WImpl_GetPlayerData,
5108 DirectPlay2WImpl_GetPlayerName,
5109 DirectPlay2WImpl_GetSessionDesc,
5110 DirectPlay2WImpl_Initialize,
5111 DirectPlay2WImpl_Open,
5112 DirectPlay2WImpl_Receive,
5113 DirectPlay2WImpl_Send,
5114 DirectPlay2WImpl_SetGroupData,
5115 DirectPlay2WImpl_SetGroupName,
5116 DirectPlay2WImpl_SetPlayerData,
5117 DirectPlay2WImpl_SetPlayerName,
5118 DirectPlay2WImpl_SetSessionDesc
5120 #undef XCAST
5122 /* Note: Hack so we can reuse the old functions without compiler warnings */
5123 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5124 # define XCAST(fun) (typeof(directPlay2AVT.fun))
5125 #else
5126 # define XCAST(fun) (void*)
5127 #endif
5129 static const IDirectPlay2Vtbl directPlay2AVT =
5131 XCAST(QueryInterface)DP_QueryInterface,
5132 XCAST(AddRef)DP_AddRef,
5133 XCAST(Release)DP_Release,
5135 DirectPlay2AImpl_AddPlayerToGroup,
5136 DirectPlay2AImpl_Close,
5137 DirectPlay2AImpl_CreateGroup,
5138 DirectPlay2AImpl_CreatePlayer,
5139 DirectPlay2AImpl_DeletePlayerFromGroup,
5140 DirectPlay2AImpl_DestroyGroup,
5141 DirectPlay2AImpl_DestroyPlayer,
5142 DirectPlay2AImpl_EnumGroupPlayers,
5143 DirectPlay2AImpl_EnumGroups,
5144 DirectPlay2AImpl_EnumPlayers,
5145 DirectPlay2AImpl_EnumSessions,
5146 DirectPlay2AImpl_GetCaps,
5147 DirectPlay2AImpl_GetGroupData,
5148 DirectPlay2AImpl_GetGroupName,
5149 DirectPlay2AImpl_GetMessageCount,
5150 DirectPlay2AImpl_GetPlayerAddress,
5151 DirectPlay2AImpl_GetPlayerCaps,
5152 DirectPlay2AImpl_GetPlayerData,
5153 DirectPlay2AImpl_GetPlayerName,
5154 DirectPlay2AImpl_GetSessionDesc,
5155 DirectPlay2AImpl_Initialize,
5156 DirectPlay2AImpl_Open,
5157 DirectPlay2AImpl_Receive,
5158 DirectPlay2AImpl_Send,
5159 DirectPlay2AImpl_SetGroupData,
5160 DirectPlay2AImpl_SetGroupName,
5161 DirectPlay2AImpl_SetPlayerData,
5162 DirectPlay2AImpl_SetPlayerName,
5163 DirectPlay2AImpl_SetSessionDesc
5165 #undef XCAST
5168 /* Note: Hack so we can reuse the old functions without compiler warnings */
5169 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5170 # define XCAST(fun) (typeof(directPlay3AVT.fun))
5171 #else
5172 # define XCAST(fun) (void*)
5173 #endif
5175 static const IDirectPlay3Vtbl directPlay3AVT =
5177 XCAST(QueryInterface)DP_QueryInterface,
5178 XCAST(AddRef)DP_AddRef,
5179 XCAST(Release)DP_Release,
5181 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
5182 XCAST(Close)DirectPlay2AImpl_Close,
5183 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
5184 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
5185 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
5186 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
5187 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
5188 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
5189 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
5190 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
5191 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
5192 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
5193 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
5194 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
5195 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5196 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5197 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5198 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5199 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5200 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5201 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5202 XCAST(Open)DirectPlay2AImpl_Open,
5203 XCAST(Receive)DirectPlay2AImpl_Receive,
5204 XCAST(Send)DirectPlay2AImpl_Send,
5205 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5206 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5207 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5208 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5209 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5211 DirectPlay3AImpl_AddGroupToGroup,
5212 DirectPlay3AImpl_CreateGroupInGroup,
5213 DirectPlay3AImpl_DeleteGroupFromGroup,
5214 DirectPlay3AImpl_EnumConnections,
5215 DirectPlay3AImpl_EnumGroupsInGroup,
5216 DirectPlay3AImpl_GetGroupConnectionSettings,
5217 DirectPlay3AImpl_InitializeConnection,
5218 DirectPlay3AImpl_SecureOpen,
5219 DirectPlay3AImpl_SendChatMessage,
5220 DirectPlay3AImpl_SetGroupConnectionSettings,
5221 DirectPlay3AImpl_StartSession,
5222 DirectPlay3AImpl_GetGroupFlags,
5223 DirectPlay3AImpl_GetGroupParent,
5224 DirectPlay3AImpl_GetPlayerAccount,
5225 DirectPlay3AImpl_GetPlayerFlags
5227 #undef XCAST
5229 /* Note: Hack so we can reuse the old functions without compiler warnings */
5230 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5231 # define XCAST(fun) (typeof(directPlay3WVT.fun))
5232 #else
5233 # define XCAST(fun) (void*)
5234 #endif
5235 static const IDirectPlay3Vtbl directPlay3WVT =
5237 XCAST(QueryInterface)DP_QueryInterface,
5238 XCAST(AddRef)DP_AddRef,
5239 XCAST(Release)DP_Release,
5241 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
5242 XCAST(Close)DirectPlay2WImpl_Close,
5243 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
5244 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
5245 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
5246 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
5247 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5248 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5249 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5250 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5251 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5252 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5253 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5254 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5255 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5256 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5257 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5258 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5259 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5260 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5261 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5262 XCAST(Open)DirectPlay2WImpl_Open,
5263 XCAST(Receive)DirectPlay2WImpl_Receive,
5264 XCAST(Send)DirectPlay2WImpl_Send,
5265 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5266 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5267 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5268 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5269 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5271 DirectPlay3WImpl_AddGroupToGroup,
5272 DirectPlay3WImpl_CreateGroupInGroup,
5273 DirectPlay3WImpl_DeleteGroupFromGroup,
5274 DirectPlay3WImpl_EnumConnections,
5275 DirectPlay3WImpl_EnumGroupsInGroup,
5276 DirectPlay3WImpl_GetGroupConnectionSettings,
5277 DirectPlay3WImpl_InitializeConnection,
5278 DirectPlay3WImpl_SecureOpen,
5279 DirectPlay3WImpl_SendChatMessage,
5280 DirectPlay3WImpl_SetGroupConnectionSettings,
5281 DirectPlay3WImpl_StartSession,
5282 DirectPlay3WImpl_GetGroupFlags,
5283 DirectPlay3WImpl_GetGroupParent,
5284 DirectPlay3WImpl_GetPlayerAccount,
5285 DirectPlay3WImpl_GetPlayerFlags
5287 #undef XCAST
5289 /* Note: Hack so we can reuse the old functions without compiler warnings */
5290 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5291 # define XCAST(fun) (typeof(directPlay4WVT.fun))
5292 #else
5293 # define XCAST(fun) (void*)
5294 #endif
5295 static const IDirectPlay4Vtbl directPlay4WVT =
5297 XCAST(QueryInterface)DP_QueryInterface,
5298 XCAST(AddRef)DP_AddRef,
5299 XCAST(Release)DP_Release,
5301 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
5302 XCAST(Close)DirectPlay2WImpl_Close,
5303 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
5304 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
5305 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
5306 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
5307 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5308 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5309 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5310 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5311 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5312 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5313 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5314 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5315 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5316 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5317 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5318 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5319 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5320 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5321 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5322 XCAST(Open)DirectPlay2WImpl_Open,
5323 XCAST(Receive)DirectPlay2WImpl_Receive,
5324 XCAST(Send)DirectPlay2WImpl_Send,
5325 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5326 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5327 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5328 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5329 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5331 XCAST(AddGroupToGroup)DirectPlay3WImpl_AddGroupToGroup,
5332 XCAST(CreateGroupInGroup)DirectPlay3WImpl_CreateGroupInGroup,
5333 XCAST(DeleteGroupFromGroup)DirectPlay3WImpl_DeleteGroupFromGroup,
5334 XCAST(EnumConnections)DirectPlay3WImpl_EnumConnections,
5335 XCAST(EnumGroupsInGroup)DirectPlay3WImpl_EnumGroupsInGroup,
5336 XCAST(GetGroupConnectionSettings)DirectPlay3WImpl_GetGroupConnectionSettings,
5337 XCAST(InitializeConnection)DirectPlay3WImpl_InitializeConnection,
5338 XCAST(SecureOpen)DirectPlay3WImpl_SecureOpen,
5339 XCAST(SendChatMessage)DirectPlay3WImpl_SendChatMessage,
5340 XCAST(SetGroupConnectionSettings)DirectPlay3WImpl_SetGroupConnectionSettings,
5341 XCAST(StartSession)DirectPlay3WImpl_StartSession,
5342 XCAST(GetGroupFlags)DirectPlay3WImpl_GetGroupFlags,
5343 XCAST(GetGroupParent)DirectPlay3WImpl_GetGroupParent,
5344 XCAST(GetPlayerAccount)DirectPlay3WImpl_GetPlayerAccount,
5345 XCAST(GetPlayerFlags)DirectPlay3WImpl_GetPlayerFlags,
5347 DirectPlay4WImpl_GetGroupOwner,
5348 DirectPlay4WImpl_SetGroupOwner,
5349 DirectPlay4WImpl_SendEx,
5350 DirectPlay4WImpl_GetMessageQueue,
5351 DirectPlay4WImpl_CancelMessage,
5352 DirectPlay4WImpl_CancelPriority
5354 #undef XCAST
5357 /* Note: Hack so we can reuse the old functions without compiler warnings */
5358 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5359 # define XCAST(fun) (typeof(directPlay4AVT.fun))
5360 #else
5361 # define XCAST(fun) (void*)
5362 #endif
5363 static const IDirectPlay4Vtbl directPlay4AVT =
5365 XCAST(QueryInterface)DP_QueryInterface,
5366 XCAST(AddRef)DP_AddRef,
5367 XCAST(Release)DP_Release,
5369 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
5370 XCAST(Close)DirectPlay2AImpl_Close,
5371 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
5372 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
5373 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
5374 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
5375 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
5376 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
5377 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
5378 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
5379 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
5380 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
5381 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
5382 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
5383 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5384 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5385 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5386 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5387 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5388 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5389 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5390 XCAST(Open)DirectPlay2AImpl_Open,
5391 XCAST(Receive)DirectPlay2AImpl_Receive,
5392 XCAST(Send)DirectPlay2AImpl_Send,
5393 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5394 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5395 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5396 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5397 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5399 XCAST(AddGroupToGroup)DirectPlay3AImpl_AddGroupToGroup,
5400 XCAST(CreateGroupInGroup)DirectPlay3AImpl_CreateGroupInGroup,
5401 XCAST(DeleteGroupFromGroup)DirectPlay3AImpl_DeleteGroupFromGroup,
5402 XCAST(EnumConnections)DirectPlay3AImpl_EnumConnections,
5403 XCAST(EnumGroupsInGroup)DirectPlay3AImpl_EnumGroupsInGroup,
5404 XCAST(GetGroupConnectionSettings)DirectPlay3AImpl_GetGroupConnectionSettings,
5405 XCAST(InitializeConnection)DirectPlay3AImpl_InitializeConnection,
5406 XCAST(SecureOpen)DirectPlay3AImpl_SecureOpen,
5407 XCAST(SendChatMessage)DirectPlay3AImpl_SendChatMessage,
5408 XCAST(SetGroupConnectionSettings)DirectPlay3AImpl_SetGroupConnectionSettings,
5409 XCAST(StartSession)DirectPlay3AImpl_StartSession,
5410 XCAST(GetGroupFlags)DirectPlay3AImpl_GetGroupFlags,
5411 XCAST(GetGroupParent)DirectPlay3AImpl_GetGroupParent,
5412 XCAST(GetPlayerAccount)DirectPlay3AImpl_GetPlayerAccount,
5413 XCAST(GetPlayerFlags)DirectPlay3AImpl_GetPlayerFlags,
5415 DirectPlay4AImpl_GetGroupOwner,
5416 DirectPlay4AImpl_SetGroupOwner,
5417 DirectPlay4AImpl_SendEx,
5418 DirectPlay4AImpl_GetMessageQueue,
5419 DirectPlay4AImpl_CancelMessage,
5420 DirectPlay4AImpl_CancelPriority
5422 #undef XCAST
5424 HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP,
5425 DPID idPlayer,
5426 LPVOID* lplpData )
5428 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5430 if( lpPlayer == NULL )
5432 return DPERR_INVALIDPLAYER;
5435 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
5437 return DP_OK;
5440 HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP,
5441 DPID idPlayer,
5442 LPVOID lpData )
5444 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5446 if( lpPlayer == NULL )
5448 return DPERR_INVALIDPLAYER;
5451 lpPlayer->lpPData->lpSPPlayerData = lpData;
5453 return DP_OK;
5456 /***************************************************************************
5457 * DirectPlayEnumerateAW
5459 * The pointer to the structure lpContext will be filled with the
5460 * appropriate data for each service offered by the OS. These services are
5461 * not necessarily available on this particular machine but are defined
5462 * as simple service providers under the "Service Providers" registry key.
5463 * This structure is then passed to lpEnumCallback for each of the different
5464 * services.
5466 * This API is useful only for applications written using DirectX3 or
5467 * worse. It is superseded by IDirectPlay3::EnumConnections which also
5468 * gives information on the actual connections.
5470 * defn of a service provider:
5471 * A dynamic-link library used by DirectPlay to communicate over a network.
5472 * The service provider contains all the network-specific code required
5473 * to send and receive messages. Online services and network operators can
5474 * supply service providers to use specialized hardware, protocols, communications
5475 * media, and network resources.
5478 static HRESULT DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA,
5479 LPDPENUMDPCALLBACKW lpEnumCallbackW,
5480 LPVOID lpContext)
5482 HKEY hkResult;
5483 static const WCHAR searchSubKey[] = {
5484 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
5485 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
5486 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
5487 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
5488 static const WCHAR guidKey[] = { 'G', 'u', 'i', 'd', 0 };
5489 static const WCHAR descW[] = { 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', 'W', 0 };
5491 DWORD dwIndex;
5492 FILETIME filetime;
5494 char *descriptionA = NULL;
5495 DWORD max_sizeOfDescriptionA = 0;
5496 WCHAR *descriptionW = NULL;
5497 DWORD max_sizeOfDescriptionW = 0;
5499 if (!lpEnumCallbackA && !lpEnumCallbackW)
5501 return DPERR_INVALIDPARAMS;
5504 /* Need to loop over the service providers in the registry */
5505 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, searchSubKey,
5506 0, KEY_READ, &hkResult) != ERROR_SUCCESS)
5508 /* Hmmm. Does this mean that there are no service providers? */
5509 ERR(": no service provider key in the registry - check your Wine installation !!!\n");
5510 return DPERR_GENERIC;
5513 /* Traverse all the service providers we have available */
5514 dwIndex = 0;
5515 while (1)
5517 WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */
5518 DWORD sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR);
5519 HKEY hkServiceProvider;
5520 GUID serviceProviderGUID;
5521 WCHAR guidKeyContent[(2 * 16) + 1 + 6 /* This corresponds to '{....-..-..-..-......}' */ ];
5522 DWORD sizeOfGuidKeyContent = sizeof(guidKeyContent);
5523 LONG ret_value;
5525 ret_value = RegEnumKeyExW(hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
5526 NULL, NULL, NULL, &filetime);
5527 if (ret_value == ERROR_NO_MORE_ITEMS)
5528 break;
5529 else if (ret_value != ERROR_SUCCESS)
5531 ERR(": could not enumerate on service provider key.\n");
5532 return DPERR_EXCEPTION;
5534 TRACE(" this time through sub-key %s.\n", debugstr_w(subKeyName));
5536 /* Open the key for this service provider */
5537 if (RegOpenKeyExW(hkResult, subKeyName, 0, KEY_READ, &hkServiceProvider) != ERROR_SUCCESS)
5539 ERR(": could not open registry key for service provider %s.\n", debugstr_w(subKeyName));
5540 continue;
5543 /* Get the GUID from the registry */
5544 if (RegQueryValueExW(hkServiceProvider, guidKey,
5545 NULL, NULL, (LPBYTE) guidKeyContent, &sizeOfGuidKeyContent) != ERROR_SUCCESS)
5547 ERR(": missing GUID registry data member for service provider %s.\n", debugstr_w(subKeyName));
5548 continue;
5550 if (sizeOfGuidKeyContent != sizeof(guidKeyContent))
5552 ERR(": invalid format for the GUID registry data member for service provider %s (%s).\n", debugstr_w(subKeyName), debugstr_w(guidKeyContent));
5553 continue;
5555 CLSIDFromString(guidKeyContent, &serviceProviderGUID );
5557 /* The enumeration will return FALSE if we are not to continue.
5559 * Note: on my windows box, major / minor version is 6 / 0 for all service providers
5560 * and have no relation to any of the two dwReserved1 and dwReserved2 keys.
5561 * I think that it simply means that they are in-line with DirectX 6.0
5563 if (lpEnumCallbackA)
5565 DWORD sizeOfDescription = 0;
5567 /* Note that this is the A case of this function, so use the A variant to get the description string */
5568 if (RegQueryValueExA(hkServiceProvider, "DescriptionA",
5569 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5571 ERR(": missing 'DescriptionA' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5572 continue;
5574 if (sizeOfDescription > max_sizeOfDescriptionA)
5576 HeapFree(GetProcessHeap(), 0, descriptionA);
5577 max_sizeOfDescriptionA = sizeOfDescription;
5579 descriptionA = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5580 RegQueryValueExA(hkServiceProvider, "DescriptionA",
5581 NULL, NULL, (LPBYTE) descriptionA, &sizeOfDescription);
5583 if (!lpEnumCallbackA(&serviceProviderGUID, descriptionA, 6, 0, lpContext))
5584 goto end;
5586 else
5588 DWORD sizeOfDescription = 0;
5590 if (RegQueryValueExW(hkServiceProvider, descW,
5591 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5593 ERR(": missing 'DescriptionW' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5594 continue;
5596 if (sizeOfDescription > max_sizeOfDescriptionW)
5598 HeapFree(GetProcessHeap(), 0, descriptionW);
5599 max_sizeOfDescriptionW = sizeOfDescription;
5601 descriptionW = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5602 RegQueryValueExW(hkServiceProvider, descW,
5603 NULL, NULL, (LPBYTE) descriptionW, &sizeOfDescription);
5605 if (!lpEnumCallbackW(&serviceProviderGUID, descriptionW, 6, 0, lpContext))
5606 goto end;
5609 dwIndex++;
5612 end:
5613 HeapFree(GetProcessHeap(), 0, descriptionA);
5614 HeapFree(GetProcessHeap(), 0, descriptionW);
5616 return DP_OK;
5619 /***************************************************************************
5620 * DirectPlayEnumerate [DPLAYX.9]
5621 * DirectPlayEnumerateA [DPLAYX.2]
5623 HRESULT WINAPI DirectPlayEnumerateA(LPDPENUMDPCALLBACKA lpEnumCallback, LPVOID lpContext )
5625 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5627 return DirectPlayEnumerateAW(lpEnumCallback, NULL, lpContext);
5630 /***************************************************************************
5631 * DirectPlayEnumerateW [DPLAYX.3]
5633 HRESULT WINAPI DirectPlayEnumerateW(LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5635 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5637 return DirectPlayEnumerateAW(NULL, lpEnumCallback, lpContext);
5640 typedef struct tagCreateEnum
5642 LPVOID lpConn;
5643 LPCGUID lpGuid;
5644 } CreateEnumData, *lpCreateEnumData;
5646 /* Find and copy the matching connection for the SP guid */
5647 static BOOL CALLBACK cbDPCreateEnumConnections(
5648 LPCGUID lpguidSP,
5649 LPVOID lpConnection,
5650 DWORD dwConnectionSize,
5651 LPCDPNAME lpName,
5652 DWORD dwFlags,
5653 LPVOID lpContext)
5655 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5657 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5659 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5661 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5662 dwConnectionSize );
5663 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5665 /* Found the record that we were looking for */
5666 return FALSE;
5669 /* Haven't found what were looking for yet */
5670 return TRUE;
5674 /***************************************************************************
5675 * DirectPlayCreate [DPLAYX.1]
5678 HRESULT WINAPI DirectPlayCreate
5679 ( LPGUID lpGUID, LPDIRECTPLAY *lplpDP, IUnknown *pUnk )
5681 HRESULT hr;
5682 LPDIRECTPLAY3A lpDP3A;
5683 CreateEnumData cbData;
5685 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5687 if( pUnk != NULL )
5689 return CLASS_E_NOAGGREGATION;
5692 if( (lplpDP == NULL) || (lpGUID == NULL) )
5694 return DPERR_INVALIDPARAMS;
5698 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5699 give them an IDirectPlay2A object and hope that doesn't cause problems */
5700 if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
5702 return DPERR_UNAVAILABLE;
5705 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
5707 /* The GUID_NULL means don't bind a service provider. Just return the
5708 interface as is */
5709 return DP_OK;
5712 /* Bind the desired service provider since lpGUID is non NULL */
5713 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
5715 /* We're going to use a DP3 interface */
5716 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
5717 (LPVOID*)&lpDP3A );
5718 if( FAILED(hr) )
5720 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
5721 return hr;
5724 cbData.lpConn = NULL;
5725 cbData.lpGuid = lpGUID;
5727 /* We were given a service provider, find info about it... */
5728 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
5729 &cbData, DPCONNECTION_DIRECTPLAY );
5730 if( ( FAILED(hr) ) ||
5731 ( cbData.lpConn == NULL )
5734 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
5735 IDirectPlayX_Release( lpDP3A );
5736 return DPERR_UNAVAILABLE;
5739 /* Initialize the service provider */
5740 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
5741 if( FAILED(hr) )
5743 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
5744 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5745 IDirectPlayX_Release( lpDP3A );
5746 return hr;
5749 /* Release our version of the interface now that we're done with it */
5750 IDirectPlayX_Release( lpDP3A );
5751 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5753 return DP_OK;