dplayx: Adjust GetCaps behaviour to documentation
[wine/gsoc_dplay.git] / dlls / dplayx / dplay.c
blob6246b4878a556f657390bfeddc8f998f2cc22990
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 HRESULT hr;
2566 DPSP_GETCAPSDATA data;
2568 TRACE("(%p)->(0x%08x,%p,0x%08x)\n", This, idPlayer, lpDPCaps, dwFlags);
2570 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2572 return DPERR_UNINITIALIZED;
2575 if ( lpDPCaps->dwSize != sizeof(DPCAPS) )
2577 return DPERR_INVALIDPARAMS;
2580 /* Query the service provider */
2581 data.idPlayer = idPlayer;
2582 data.dwFlags = dwFlags;
2583 data.lpCaps = lpDPCaps;
2584 data.lpISP = This->dp2->spData.lpISP;
2586 hr = (*This->dp2->spData.lpCB->GetCaps)( &data );
2588 /* Substract size of DirectPlay header */
2589 data.lpCaps->dwMaxBufferSize -= sizeof(DPSP_MSG_ENVELOPE);
2591 return hr;
2594 static HRESULT DP_IF_GetCaps
2595 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags )
2597 return DP_IF_GetPlayerCaps( This, DPID_ALLPLAYERS, lpDPCaps, dwFlags );
2600 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2601 ( LPDIRECTPLAY2A iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2603 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2604 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2607 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2608 ( LPDIRECTPLAY2 iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2610 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2611 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2614 static HRESULT DP_IF_GetGroupData
2615 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2616 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2618 lpGroupData lpGData;
2619 DWORD dwRequiredBufferSize;
2620 LPVOID lpCopyDataFrom;
2622 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2623 This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi );
2625 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2627 return DPERR_INVALIDGROUP;
2630 /* How much buffer is required? */
2631 if( dwFlags & DPSET_LOCAL )
2633 dwRequiredBufferSize = lpGData->dwLocalDataSize;
2634 lpCopyDataFrom = lpGData->lpLocalData;
2636 else
2638 dwRequiredBufferSize = lpGData->dwRemoteDataSize;
2639 lpCopyDataFrom = lpGData->lpRemoteData;
2642 /* Is the user requesting to know how big a buffer is required? */
2643 if( ( lpData == NULL ) ||
2644 ( *lpdwDataSize < dwRequiredBufferSize )
2647 *lpdwDataSize = dwRequiredBufferSize;
2648 return DPERR_BUFFERTOOSMALL;
2651 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2653 return DP_OK;
2656 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2657 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2658 LPDWORD lpdwDataSize, DWORD dwFlags )
2660 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2661 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2662 dwFlags, TRUE );
2665 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2666 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2667 LPDWORD lpdwDataSize, DWORD dwFlags )
2669 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2670 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2671 dwFlags, FALSE );
2674 static HRESULT DP_IF_GetGroupName
2675 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2676 LPDWORD lpdwDataSize, BOOL bAnsi )
2678 lpGroupData lpGData;
2679 LPDPNAME lpName = lpData;
2680 DWORD dwRequiredDataSize;
2682 FIXME("(%p)->(0x%08x,%p,%p,%u) ANSI ignored\n",
2683 This, idGroup, lpData, lpdwDataSize, bAnsi );
2685 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2687 return DPERR_INVALIDGROUP;
2690 dwRequiredDataSize = lpGData->name.dwSize;
2692 if( lpGData->name.u1.lpszShortNameA )
2694 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
2697 if( lpGData->name.u2.lpszLongNameA )
2699 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
2702 if( ( lpData == NULL ) ||
2703 ( *lpdwDataSize < dwRequiredDataSize )
2706 *lpdwDataSize = dwRequiredDataSize;
2707 return DPERR_BUFFERTOOSMALL;
2710 /* Copy the structure */
2711 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2713 if( lpGData->name.u1.lpszShortNameA )
2715 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2716 lpGData->name.u1.lpszShortNameA );
2718 else
2720 lpName->u1.lpszShortNameA = NULL;
2723 if( lpGData->name.u1.lpszShortNameA )
2725 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2726 lpGData->name.u2.lpszLongNameA );
2728 else
2730 lpName->u2.lpszLongNameA = NULL;
2733 return DP_OK;
2736 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2737 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2738 LPDWORD lpdwDataSize )
2740 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2741 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2744 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2745 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2746 LPDWORD lpdwDataSize )
2748 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2749 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2752 static HRESULT DP_IF_GetMessageCount
2753 ( IDirectPlay2Impl* This, DPID idPlayer,
2754 LPDWORD lpdwCount, BOOL bAnsi )
2756 FIXME("(%p)->(0x%08x,%p,%u): stub\n", This, idPlayer, lpdwCount, bAnsi );
2757 return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer,
2758 DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL,
2759 bAnsi );
2762 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2763 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDWORD lpdwCount )
2765 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2766 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, TRUE );
2769 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2770 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDWORD lpdwCount )
2772 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2773 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, FALSE );
2776 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2777 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2779 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2780 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2781 return DP_OK;
2784 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2785 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2787 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2788 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2789 return DP_OK;
2792 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2793 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2794 DWORD dwFlags )
2796 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2797 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2800 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2801 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2802 DWORD dwFlags )
2804 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2805 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2808 static HRESULT DP_IF_GetPlayerData
2809 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2810 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2812 lpPlayerList lpPList;
2813 DWORD dwRequiredBufferSize;
2814 LPVOID lpCopyDataFrom;
2816 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2817 This, idPlayer, lpData, lpdwDataSize, dwFlags, bAnsi );
2819 if( This->dp2->connectionInitialized == NO_PROVIDER )
2821 return DPERR_UNINITIALIZED;
2824 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2826 return DPERR_INVALIDPLAYER;
2829 if( lpdwDataSize == NULL )
2831 return DPERR_INVALIDPARAMS;
2834 /* How much buffer is required? */
2835 if( dwFlags & DPSET_LOCAL )
2837 dwRequiredBufferSize = lpPList->lpPData->dwLocalDataSize;
2838 lpCopyDataFrom = lpPList->lpPData->lpLocalData;
2840 else
2842 dwRequiredBufferSize = lpPList->lpPData->dwRemoteDataSize;
2843 lpCopyDataFrom = lpPList->lpPData->lpRemoteData;
2846 /* Is the user requesting to know how big a buffer is required? */
2847 if( ( lpData == NULL ) ||
2848 ( *lpdwDataSize < dwRequiredBufferSize )
2851 *lpdwDataSize = dwRequiredBufferSize;
2852 return DPERR_BUFFERTOOSMALL;
2855 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2857 return DP_OK;
2860 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2861 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2862 LPDWORD lpdwDataSize, DWORD dwFlags )
2864 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2865 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2866 dwFlags, TRUE );
2869 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2870 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2871 LPDWORD lpdwDataSize, DWORD dwFlags )
2873 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2874 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2875 dwFlags, FALSE );
2878 static HRESULT DP_IF_GetPlayerName
2879 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2880 LPDWORD lpdwDataSize, BOOL bAnsi )
2882 lpPlayerList lpPList;
2883 LPDPNAME lpName = lpData;
2884 DWORD dwRequiredDataSize;
2886 FIXME( "(%p)->(0x%08x,%p,%p,%u): ANSI\n",
2887 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2889 if( This->dp2->connectionInitialized == NO_PROVIDER )
2891 return DPERR_UNINITIALIZED;
2894 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2896 return DPERR_INVALIDPLAYER;
2899 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
2901 if( lpPList->lpPData->name.u1.lpszShortNameA )
2903 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
2906 if( lpPList->lpPData->name.u2.lpszLongNameA )
2908 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
2911 if( ( lpData == NULL ) ||
2912 ( *lpdwDataSize < dwRequiredDataSize )
2915 *lpdwDataSize = dwRequiredDataSize;
2916 return DPERR_BUFFERTOOSMALL;
2919 /* Copy the structure */
2920 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
2922 if( lpPList->lpPData->name.u1.lpszShortNameA )
2924 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2925 lpPList->lpPData->name.u1.lpszShortNameA );
2927 else
2929 lpName->u1.lpszShortNameA = NULL;
2932 if( lpPList->lpPData->name.u2.lpszLongNameA )
2934 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2935 lpPList->lpPData->name.u2.lpszLongNameA );
2937 else
2939 lpName->u2.lpszLongNameA = NULL;
2942 return DP_OK;
2945 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2946 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2947 LPDWORD lpdwDataSize )
2949 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2950 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
2953 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2954 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2955 LPDWORD lpdwDataSize )
2957 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2958 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
2961 static HRESULT DP_GetSessionDesc
2962 ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize,
2963 BOOL bAnsi )
2965 DWORD dwRequiredSize;
2967 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
2969 if( This->dp2->connectionInitialized == NO_PROVIDER )
2971 return DPERR_UNINITIALIZED;
2974 if( !This->dp2->bConnectionOpen )
2976 return DPERR_NOSESSIONS;
2979 if( ( lpdwDataSize == NULL ) || ( *lpdwDataSize >= MAXDWORD ) )
2981 return DPERR_INVALIDPARAMS;
2984 /* FIXME: Get from This->dp2->lpSessionDesc */
2985 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
2987 if ( ( lpData == NULL ) ||
2988 ( *lpdwDataSize < dwRequiredSize )
2991 *lpdwDataSize = dwRequiredSize;
2992 return DPERR_BUFFERTOOSMALL;
2995 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
2997 return DP_OK;
3000 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
3001 ( LPDIRECTPLAY2A iface, LPVOID lpData, LPDWORD lpdwDataSize )
3003 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3004 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
3007 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
3008 ( LPDIRECTPLAY2 iface, LPVOID lpData, LPDWORD lpdwDataSize )
3010 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3011 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
3014 /* Intended only for COM compatibility. Always returns an error. */
3015 static HRESULT WINAPI DirectPlay2AImpl_Initialize
3016 ( LPDIRECTPLAY2A iface, LPGUID lpGUID )
3018 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3019 TRACE("(%p)->(%p): stub\n", This, lpGUID );
3020 return DPERR_ALREADYINITIALIZED;
3023 /* Intended only for COM compatibility. Always returns an error. */
3024 static HRESULT WINAPI DirectPlay2WImpl_Initialize
3025 ( LPDIRECTPLAY2 iface, LPGUID lpGUID )
3027 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3028 TRACE("(%p)->(%p): stub\n", This, lpGUID );
3029 return DPERR_ALREADYINITIALIZED;
3033 static HRESULT DP_SecureOpen
3034 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
3035 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
3036 BOOL bAnsi )
3038 HRESULT hr = DP_OK;
3040 FIXME( "(%p)->(%p,0x%08x,%p,%p): partial stub\n",
3041 This, lpsd, dwFlags, lpSecurity, lpCredentials );
3043 if( ( lpsd == NULL ) ||
3044 ( lpsd->dwSize != sizeof(DPSESSIONDESC2) ) )
3046 return DPERR_INVALIDPARAMS;
3049 if( This->dp2->bConnectionOpen )
3051 TRACE( ": rejecting already open connection.\n" );
3052 return DPERR_ALREADYINITIALIZED;
3055 /* If we're enumerating, kill the thread */
3056 DP_KillEnumSessionThread( This );
3058 if( dwFlags & DPOPEN_JOIN )
3060 LPDPSESSIONDESC2 current = NULL;
3061 NS_ResetSessionEnumeration( This->dp2->lpNameServerData );
3062 while( ( current = NS_WalkSessions( This->dp2->lpNameServerData ) ) )
3064 if ( IsEqualGUID( &lpsd->guidInstance, &current->guidInstance ) )
3065 break;
3067 if ( current == NULL )
3068 return DPERR_NOSESSIONS;
3070 else if( dwFlags & DPOPEN_CREATE )
3072 /* Rightoo - this computer is the host and the local computer needs to be
3073 the name server so that others can join this session */
3074 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
3076 This->dp2->bHostInterface = TRUE;
3078 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
3079 if( FAILED( hr ) )
3081 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
3082 return hr;
3086 /* Invoke the conditional callback for the service provider */
3087 if( This->dp2->spData.lpCB->Open )
3089 DPSP_OPENDATA data;
3091 FIXME( "Not all data fields are correct. Need new parameter\n" );
3093 data.bCreate = (dwFlags & DPOPEN_CREATE ) ? TRUE : FALSE;
3094 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
3095 : NS_GetNSAddr( This->dp2->lpNameServerData );
3096 data.lpISP = This->dp2->spData.lpISP;
3097 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) ? TRUE : FALSE;
3098 data.dwOpenFlags = dwFlags;
3099 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
3101 hr = (*This->dp2->spData.lpCB->Open)(&data);
3102 if( FAILED( hr ) )
3104 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
3105 return hr;
3110 /* Create the system group of which everything is a part of */
3111 DPID systemGroup = DPID_SYSTEM_GROUP;
3113 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
3114 NULL, 0, 0, TRUE );
3118 if( dwFlags & DPOPEN_JOIN )
3120 DPID dpidServerId = DPID_UNKNOWN;
3122 /* Create the server player for this interface. This way we can receive
3123 * messages for this session.
3125 /* FIXME: I suppose that we should be setting an event for a receive
3126 * type of thing. That way the messaging thread could know to wake
3127 * up. DPlay would then trigger the hEvent for the player the
3128 * message is directed to.
3130 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
3132 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
3135 else if( dwFlags & DPOPEN_CREATE )
3137 DPID dpidNameServerId = DPID_NAME_SERVER;
3139 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
3140 0, DPPLAYER_SERVERPLAYER, bAnsi );
3143 if( FAILED(hr) )
3145 ERR( "Couldn't create name server/system player: %s\n",
3146 DPLAYX_HresultToString(hr) );
3148 else
3150 This->dp2->bConnectionOpen = TRUE;
3153 return hr;
3156 static HRESULT WINAPI DirectPlay2AImpl_Open
3157 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
3159 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3160 TRACE("(%p)->(%p,0x%08x)\n", This, lpsd, dwFlags );
3161 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, TRUE );
3164 static HRESULT WINAPI DirectPlay2WImpl_Open
3165 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
3167 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3168 TRACE("(%p)->(%p,0x%08x)\n", This, lpsd, dwFlags );
3169 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, FALSE );
3172 static HRESULT DP_IF_Receive
3173 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
3174 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi )
3176 LPDPMSG lpMsg = NULL;
3178 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p,%u): stub\n",
3179 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
3181 if( This->dp2->connectionInitialized == NO_PROVIDER )
3183 return DPERR_UNINITIALIZED;
3186 if ( ( lpdwDataSize == NULL ) ||
3187 ( ( dwFlags & DPRECEIVE_FROMPLAYER ) && ( lpidFrom == NULL ) ) ||
3188 ( ( dwFlags & DPRECEIVE_TOPLAYER ) && ( lpidTo == NULL ) ) )
3190 return DPERR_INVALIDPARAMS;
3193 if( dwFlags == 0 )
3195 dwFlags = DPRECEIVE_ALL;
3198 if( dwFlags & DPRECEIVE_ALL )
3200 lpMsg = DPQ_FIRST( This->dp2->receiveMsgs );
3202 else
3204 if ( (lpMsg = DPQ_FIRST( This->dp2->receiveMsgs )) )
3208 if ( ( ( dwFlags & DPRECEIVE_FROMPLAYER ) &&
3209 ( dwFlags & DPRECEIVE_TOPLAYER ) &&
3210 ( lpMsg->idFrom == *lpidFrom ) &&
3211 ( lpMsg->idTo == *lpidTo ) ) || /* From & To */
3212 ( ( dwFlags & DPRECEIVE_FROMPLAYER ) &&
3213 ( lpMsg->idFrom == *lpidFrom ) ) || /* From */
3214 ( ( dwFlags & DPRECEIVE_TOPLAYER ) &&
3215 ( lpMsg->idTo == *lpidTo ) ) ) /* To */
3217 break;
3220 while( (lpMsg = DPQ_NEXT( lpMsg->msgs )) );
3224 if( lpMsg == NULL )
3226 return DPERR_NOMESSAGES;
3229 /* Buffer size check */
3230 if ( ( lpData == NULL ) ||
3231 ( *lpdwDataSize < lpMsg->dwMsgSize ) )
3233 *lpdwDataSize = lpMsg->dwMsgSize;
3234 return DPERR_BUFFERTOOSMALL;
3237 /* Copy into the provided buffer */
3238 if (lpData) CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
3240 /* Set players */
3241 if ( lpidFrom )
3243 *lpidFrom = lpMsg->idFrom;
3245 if ( lpidTo )
3247 *lpidTo = lpMsg->idTo;
3250 /* Remove message from queue */
3251 if( !( dwFlags & DPRECEIVE_PEEK ) )
3253 HeapFree( GetProcessHeap(), 0, lpMsg->msg );
3254 DPQ_REMOVE( This->dp2->receiveMsgs, lpMsg, msgs );
3255 HeapFree( GetProcessHeap(), 0, lpMsg );
3258 return DP_OK;
3261 static HRESULT WINAPI DirectPlay2AImpl_Receive
3262 ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo,
3263 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
3265 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3266 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
3267 lpData, lpdwDataSize, TRUE );
3270 static HRESULT WINAPI DirectPlay2WImpl_Receive
3271 ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo,
3272 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
3274 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3275 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
3276 lpData, lpdwDataSize, FALSE );
3279 static HRESULT WINAPI DirectPlay2AImpl_Send
3280 ( LPDIRECTPLAY2A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3282 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3283 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3284 0, 0, NULL, NULL, TRUE );
3287 static HRESULT WINAPI DirectPlay2WImpl_Send
3288 ( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3290 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3291 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3292 0, 0, NULL, NULL, FALSE );
3295 static HRESULT DP_IF_SetGroupData
3296 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
3297 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3299 lpGroupData lpGData;
3301 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3302 This, idGroup, lpData, dwDataSize, dwFlags, bAnsi );
3304 /* Parameter check */
3305 if( ( lpData == NULL ) &&
3306 ( dwDataSize != 0 )
3309 return DPERR_INVALIDPARAMS;
3312 /* Find the pointer to the data for this player */
3313 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3315 return DPERR_INVALIDOBJECT;
3318 if( !(dwFlags & DPSET_LOCAL) )
3320 FIXME( "Was this group created by this interface?\n" );
3321 /* FIXME: If this is a remote update need to allow it but not
3322 * send a message.
3326 DP_SetGroupData( lpGData, dwFlags, lpData, dwDataSize );
3328 /* FIXME: Only send a message if this group is local to the session otherwise
3329 * it will have been rejected above
3331 if( !(dwFlags & DPSET_LOCAL) )
3333 FIXME( "Send msg?\n" );
3336 return DP_OK;
3339 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
3340 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
3341 DWORD dwDataSize, DWORD dwFlags )
3343 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3344 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, TRUE );
3347 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
3348 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
3349 DWORD dwDataSize, DWORD dwFlags )
3351 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3352 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, FALSE );
3355 static HRESULT DP_IF_SetGroupName
3356 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
3357 DWORD dwFlags, BOOL bAnsi )
3359 lpGroupData lpGData;
3361 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n", This, idGroup,
3362 lpGroupName, dwFlags, bAnsi );
3364 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3366 return DPERR_INVALIDGROUP;
3369 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
3371 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3372 FIXME( "Message not sent and dwFlags ignored\n" );
3374 return DP_OK;
3377 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
3378 ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName,
3379 DWORD dwFlags )
3381 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3382 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
3385 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
3386 ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName,
3387 DWORD dwFlags )
3389 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3390 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
3393 static HRESULT DP_IF_SetPlayerData
3394 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
3395 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3397 lpPlayerList lpPList;
3399 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3400 This, idPlayer, lpData, dwDataSize, dwFlags, bAnsi );
3402 if( This->dp2->connectionInitialized == NO_PROVIDER )
3404 return DPERR_UNINITIALIZED;
3407 /* Parameter check */
3408 if( ( ( lpData == NULL ) && ( dwDataSize != 0 ) ) ||
3409 ( dwDataSize >= MAXDWORD ) )
3411 return DPERR_INVALIDPARAMS;
3414 /* Find the pointer to the data for this player */
3415 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3417 return DPERR_INVALIDPLAYER;
3420 if( !(dwFlags & DPSET_LOCAL) )
3422 FIXME( "Was this group created by this interface?\n" );
3423 /* FIXME: If this is a remote update need to allow it but not
3424 * send a message.
3428 DP_SetPlayerData( lpPList->lpPData, dwFlags, lpData, dwDataSize );
3430 if( !(dwFlags & DPSET_LOCAL) )
3432 FIXME( "Send msg?\n" );
3435 return DP_OK;
3438 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3439 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
3440 DWORD dwDataSize, DWORD dwFlags )
3442 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3443 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3444 dwFlags, TRUE );
3447 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3448 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
3449 DWORD dwDataSize, DWORD dwFlags )
3451 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3452 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3453 dwFlags, FALSE );
3456 static HRESULT DP_IF_SetPlayerName
3457 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
3458 DWORD dwFlags, BOOL bAnsi )
3460 lpPlayerList lpPList;
3462 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n",
3463 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3465 if( This->dp2->connectionInitialized == NO_PROVIDER )
3467 return DPERR_UNINITIALIZED;
3470 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3472 return DPERR_INVALIDGROUP;
3475 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3477 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3478 FIXME( "Message not sent and dwFlags ignored\n" );
3480 return DP_OK;
3483 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3484 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName,
3485 DWORD dwFlags )
3487 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3488 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3491 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3492 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName,
3493 DWORD dwFlags )
3495 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3496 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3499 HRESULT DP_SetSessionDesc
3500 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
3501 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3503 DWORD dwRequiredSize;
3504 LPDPSESSIONDESC2 lpTempSessDesc;
3506 TRACE( "(%p)->(%p,0x%08x,%u,%u)\n",
3507 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3509 /* FIXME: Copy into This->dp2->lpSessionDesc */
3510 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3511 lpTempSessDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize );
3513 if( lpTempSessDesc == NULL )
3515 return DPERR_OUTOFMEMORY;
3518 /* Free the old */
3519 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3521 This->dp2->lpSessionDesc = lpTempSessDesc;
3522 /* Set the new */
3523 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3524 if( bInitial )
3526 /*Initializing session GUID*/
3527 CoCreateGuid( &(This->dp2->lpSessionDesc->guidInstance) );
3529 /* If this is an external invocation of the interface, we should be
3530 * letting everyone know that things have changed. Otherwise this is
3531 * just an initialization and it doesn't need to be propagated.
3533 if( !bInitial )
3535 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3538 return DP_OK;
3541 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3542 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3544 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3546 if( This->dp2->connectionInitialized == NO_PROVIDER )
3548 return DPERR_UNINITIALIZED;
3551 if( !This->dp2->bConnectionOpen )
3553 return DPERR_NOSESSIONS;
3556 if( dwFlags || (lpSessDesc == NULL) )
3558 return DPERR_INVALIDPARAMS;
3561 /* Illegal combinations of flags */
3562 if ( ( lpSessDesc->dwFlags & DPSESSION_MIGRATEHOST ) &&
3563 ( lpSessDesc->dwFlags & ( DPSESSION_CLIENTSERVER |
3564 DPSESSION_MULTICASTSERVER |
3565 DPSESSION_SECURESERVER ) ) )
3567 return DPERR_INVALIDFLAGS;
3570 /* Only the host is allowed to update the session desc */
3571 if( !This->dp2->bHostInterface )
3573 return DPERR_ACCESSDENIED;
3576 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3579 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3580 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3582 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3584 if( This->dp2->connectionInitialized == NO_PROVIDER )
3586 return DPERR_UNINITIALIZED;
3589 if( !This->dp2->bConnectionOpen )
3591 return DPERR_NOSESSIONS;
3594 if( dwFlags || (lpSessDesc == NULL) )
3596 return DPERR_INVALIDPARAMS;
3599 /* Illegal combinations of flags */
3600 if ( ( lpSessDesc->dwFlags & DPSESSION_MIGRATEHOST ) &&
3601 ( lpSessDesc->dwFlags & ( DPSESSION_CLIENTSERVER |
3602 DPSESSION_MULTICASTSERVER |
3603 DPSESSION_SECURESERVER ) ) )
3605 return DPERR_INVALIDFLAGS;
3608 /* Only the host is allowed to update the session desc */
3609 if( !This->dp2->bHostInterface )
3611 return DPERR_ACCESSDENIED;
3614 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3617 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3618 static DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3620 DWORD dwSize = 0;
3622 if( lpSessDesc == NULL )
3624 /* Hmmm..don't need any size? */
3625 ERR( "NULL lpSessDesc\n" );
3626 return dwSize;
3629 dwSize += sizeof( *lpSessDesc );
3631 if( bAnsi )
3633 if( lpSessDesc->u1.lpszSessionNameA )
3635 dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1;
3638 if( lpSessDesc->u2.lpszPasswordA )
3640 dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1;
3643 else /* UNICODE */
3645 if( lpSessDesc->u1.lpszSessionName )
3647 dwSize += sizeof( WCHAR ) *
3648 ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 );
3651 if( lpSessDesc->u2.lpszPassword )
3653 dwSize += sizeof( WCHAR ) *
3654 ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 );
3658 return dwSize;
3661 /* Assumes that contiguous buffers are already allocated. */
3662 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3663 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3665 BYTE* lpStartOfFreeSpace;
3667 if( lpSessionDest == NULL )
3669 ERR( "NULL lpSessionDest\n" );
3670 return;
3673 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3675 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3677 if( bAnsi )
3679 if( lpSessionSrc->u1.lpszSessionNameA )
3681 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3682 lpSessionDest->u1.lpszSessionNameA );
3683 lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3684 lpStartOfFreeSpace +=
3685 lstrlenA( lpSessionDest->u1.lpszSessionNameA ) + 1;
3688 if( lpSessionSrc->u2.lpszPasswordA )
3690 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3691 lpSessionDest->u2.lpszPasswordA );
3692 lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3693 lpStartOfFreeSpace +=
3694 lstrlenA( lpSessionDest->u2.lpszPasswordA ) + 1;
3697 else /* UNICODE */
3699 if( lpSessionSrc->u1.lpszSessionName )
3701 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3702 lpSessionDest->u1.lpszSessionName );
3703 lpSessionDest->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3704 lpStartOfFreeSpace += sizeof(WCHAR) *
3705 ( lstrlenW( lpSessionDest->u1.lpszSessionName ) + 1 );
3708 if( lpSessionSrc->u2.lpszPassword )
3710 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3711 lpSessionDest->u2.lpszPassword );
3712 lpSessionDest->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3713 lpStartOfFreeSpace += sizeof(WCHAR) *
3714 ( lstrlenW( lpSessionDest->u2.lpszPassword ) + 1 );
3720 static HRESULT DP_IF_AddGroupToGroup
3721 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3723 lpGroupData lpGData;
3724 lpGroupList lpNewGList;
3726 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, idParentGroup, idGroup );
3728 if( This->dp2->connectionInitialized == NO_PROVIDER )
3730 return DPERR_UNINITIALIZED;
3733 if( DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) == NULL )
3735 return DPERR_INVALIDGROUP;
3738 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3740 return DPERR_INVALIDGROUP;
3743 /* Create a player list (ie "shortcut" ) */
3744 lpNewGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewGList ) );
3745 if( lpNewGList == NULL )
3747 return DPERR_CANTADDPLAYER;
3750 /* Add the shortcut */
3751 lpGData->uRef++;
3752 lpNewGList->lpGData = lpGData;
3754 /* Add the player to the list of players for this group */
3755 DPQ_INSERT( lpGData->groups, lpNewGList, groups );
3757 /* Send a ADDGROUPTOGROUP message */
3758 FIXME( "Not sending message\n" );
3760 return DP_OK;
3763 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3764 ( LPDIRECTPLAY3A iface, DPID idParentGroup, DPID idGroup )
3766 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3767 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3770 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3771 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3773 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3774 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3777 static HRESULT DP_IF_CreateGroupInGroup
3778 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
3779 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
3780 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3782 lpGroupData lpGParentData;
3783 lpGroupList lpGList;
3784 lpGroupData lpGData;
3786 TRACE( "(%p)->(0x%08x,%p,%p,%p,0x%08x,0x%08x,%u)\n",
3787 This, idParentGroup, lpidGroup, lpGroupName, lpData,
3788 dwDataSize, dwFlags, bAnsi );
3790 /* Verify that the specified parent is valid */
3791 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This,
3792 idParentGroup ) ) == NULL
3795 return DPERR_INVALIDGROUP;
3798 lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName,
3799 dwFlags, idParentGroup, bAnsi );
3801 if( lpGData == NULL )
3803 return DPERR_CANTADDPLAYER; /* yes player not group */
3806 /* Something else is referencing this data */
3807 lpGData->uRef++;
3809 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
3811 /* The list has now been inserted into the interface group list. We now
3812 need to put a "shortcut" to this group in the parent group */
3813 lpGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGList ) );
3814 if( lpGList == NULL )
3816 FIXME( "Memory leak\n" );
3817 return DPERR_CANTADDPLAYER; /* yes player not group */
3820 lpGList->lpGData = lpGData;
3822 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
3824 /* Let the SP know that we've created this group */
3825 if( This->dp2->spData.lpCB->CreateGroup )
3827 DPSP_CREATEGROUPDATA data;
3829 TRACE( "Calling SP CreateGroup\n" );
3831 data.idGroup = *lpidGroup;
3832 data.dwFlags = dwFlags;
3833 data.lpSPMessageHeader = lpMsgHdr;
3834 data.lpISP = This->dp2->spData.lpISP;
3836 (*This->dp2->spData.lpCB->CreateGroup)( &data );
3839 /* Inform all other peers of the creation of a new group. If there are
3840 * no peers keep this quiet.
3842 if( This->dp2->lpSessionDesc &&
3843 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
3845 DPMSG_CREATEPLAYERORGROUP msg;
3847 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
3848 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
3849 msg.dpId = *lpidGroup;
3850 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
3851 msg.lpData = lpData;
3852 msg.dwDataSize = dwDataSize;
3853 msg.dpnName = *lpGroupName;
3855 /* FIXME: Correct to just use send effectively? */
3856 /* FIXME: Should size include data w/ message or just message "header" */
3857 /* FIXME: Check return code */
3858 DP_SendEx( (IDirectPlay2Impl*)This,
3859 DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
3860 0, 0, NULL, NULL, bAnsi );
3863 return DP_OK;
3866 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3867 ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup,
3868 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3869 DWORD dwFlags )
3871 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3873 if( This->dp2->connectionInitialized == NO_PROVIDER )
3875 return DPERR_UNINITIALIZED;
3878 if( lpidGroup == NULL ||
3879 !This->dp2->bConnectionOpen ||
3880 dwDataSize >= MAXDWORD ||
3881 ( lpData == NULL && dwDataSize != 0 ) )
3883 return DPERR_INVALIDPARAMS;
3886 *lpidGroup = DPID_UNKNOWN;
3888 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3889 lpGroupName, lpData, dwDataSize, dwFlags,
3890 TRUE );
3893 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3894 ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup,
3895 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3896 DWORD dwFlags )
3898 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3900 if( This->dp2->connectionInitialized == NO_PROVIDER )
3902 return DPERR_UNINITIALIZED;
3905 if( lpidGroup == NULL ||
3906 !This->dp2->bConnectionOpen ||
3907 dwDataSize >= MAXDWORD ||
3908 ( lpData == NULL && dwDataSize != 0 ) )
3910 return DPERR_INVALIDPARAMS;
3913 *lpidGroup = DPID_UNKNOWN;
3915 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3916 lpGroupName, lpData, dwDataSize,
3917 dwFlags, FALSE );
3920 static HRESULT DP_IF_DeleteGroupFromGroup
3921 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3923 lpGroupList lpGList;
3924 lpGroupData lpGParentData;
3926 TRACE("(%p)->(0x%08x,0x%08x)\n", This, idParentGroup, idGroup );
3928 /* Is the parent group valid? */
3929 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3931 return DPERR_INVALIDGROUP;
3934 /* Remove the group from the parent group queue */
3935 DPQ_REMOVE_ENTRY( lpGParentData->groups, groups, lpGData->dpid, ==, idGroup, lpGList );
3937 if( lpGList == NULL )
3939 return DPERR_INVALIDGROUP;
3942 /* Decrement the ref count */
3943 lpGList->lpGData->uRef--;
3945 /* Free up the list item */
3946 HeapFree( GetProcessHeap(), 0, lpGList );
3948 /* Should send a DELETEGROUPFROMGROUP message */
3949 FIXME( "message not sent\n" );
3951 return DP_OK;
3954 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3955 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3957 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3958 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3961 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3962 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3964 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3965 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3967 static BOOL DP_BuildCompoundAddr( GUID guidDataType,
3968 LPGUID lpcSpGuid,
3969 LPVOID* lplpAddrBuf,
3970 LPDWORD lpdwBufSize )
3972 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3973 HRESULT hr;
3975 dpCompoundAddress.dwDataSize = sizeof( GUID );
3976 dpCompoundAddress.guidDataType = guidDataType;
3977 dpCompoundAddress.lpData = lpcSpGuid;
3979 *lplpAddrBuf = NULL;
3980 *lpdwBufSize = 0;
3982 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3983 lpdwBufSize, TRUE );
3985 if( hr != DPERR_BUFFERTOOSMALL )
3987 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3988 return FALSE;
3991 /* Now allocate the buffer */
3992 *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3993 *lpdwBufSize );
3995 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3996 lpdwBufSize, TRUE );
3997 if( FAILED(hr) )
3999 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
4000 return FALSE;
4003 return TRUE;
4006 static HRESULT WINAPI DP_IF_EnumConnections
4007 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication,
4008 LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext,
4009 DWORD dwFlags, BOOL bAnsi )
4011 HKEY hkResult;
4012 WCHAR searchSubKeySP[] = {
4013 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
4014 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
4015 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
4016 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
4017 WCHAR searchSubKeyLP[] = {
4018 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
4019 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
4020 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
4021 'L', 'o', 'b', 'b', 'y', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
4022 WCHAR guidDataSubKey[] = { 'G', 'u', 'i', 'd', 0 };
4023 WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */
4024 DWORD dwIndex, sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR);
4025 FILETIME filetime;
4027 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
4028 if( dwFlags == 0 )
4030 dwFlags = DPCONNECTION_DIRECTPLAY;
4033 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
4034 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) ) )
4036 return DPERR_INVALIDFLAGS;
4039 if( !lpEnumCallback )
4041 return DPERR_INVALIDPARAMS;
4045 /* Need to loop over the service providers in the registry */
4046 if( RegOpenKeyExW( HKEY_LOCAL_MACHINE,
4047 ( dwFlags & DPCONNECTION_DIRECTPLAY ) ? searchSubKeySP
4048 : searchSubKeyLP,
4049 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4051 /* Hmmm. Does this mean that there are no service providers? */
4052 ERR(": no service providers?\n");
4053 return DP_OK;
4057 /* Traverse all the service providers we have available */
4058 for( dwIndex=0;
4059 RegEnumKeyExW( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4060 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4061 ++dwIndex, sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR) )
4063 HKEY hkServiceProvider;
4064 GUID serviceProviderGUID;
4065 WCHAR guidKeyContent[39];
4066 DWORD sizeOfReturnBuffer = sizeof(guidKeyContent);
4067 DPNAME dpName;
4068 BOOL continueEnumeration = TRUE;
4070 LPVOID lpAddressBuffer = NULL;
4071 DWORD dwAddressBufferSize = 0;
4074 TRACE(" this time through: %s\n", debugstr_w(subKeyName) );
4076 /* Get a handle for this particular service provider */
4077 if( RegOpenKeyExW( hkResult, subKeyName, 0, KEY_READ,
4078 &hkServiceProvider ) != ERROR_SUCCESS )
4080 ERR(": what the heck is going on?\n" );
4081 continue;
4084 if( RegQueryValueExW( hkServiceProvider, guidDataSubKey,
4085 NULL, NULL, (LPBYTE)guidKeyContent,
4086 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4088 ERR(": missing GUID registry data members\n" );
4089 RegCloseKey(hkServiceProvider);
4090 continue;
4092 RegCloseKey(hkServiceProvider);
4094 CLSIDFromString( guidKeyContent, &serviceProviderGUID );
4096 /* Fill in the DPNAME struct for the service provider */
4097 dpName.dwSize = sizeof( dpName );
4098 dpName.dwFlags = 0;
4099 if ( bAnsi )
4101 dpName.u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4102 sizeOfSubKeyName+1 );
4103 WideCharToMultiByte( CP_ACP, 0, subKeyName,
4104 -1, dpName.u1.lpszShortNameA, -1, 0, 0);
4105 dpName.u2.lpszLongNameA = NULL;
4107 else
4109 dpName.u1.lpszShortName = subKeyName;
4110 dpName.u2.lpszLongName = NULL;
4113 /* Create the compound address for the service provider.
4114 * NOTE: This is a gruesome architectural scar right now. DP
4115 * uses DPL and DPL uses DP. Nasty stuff. This may be why the
4116 * native dll just gets around this little bit by allocating an
4117 * 80 byte buffer which isn't even filled with a valid compound
4118 * address. Oh well. Creating a proper compound address is the
4119 * way to go anyways despite this method taking slightly more
4120 * heap space and realtime :) */
4122 if ( DP_BuildCompoundAddr( ( ( dwFlags & DPCONNECTION_DIRECTPLAY )
4123 ? DPAID_ServiceProvider
4124 : DPAID_LobbyProvider ),
4125 &serviceProviderGUID,
4126 &lpAddressBuffer,
4127 &dwAddressBufferSize ) )
4129 /* The enumeration will return FALSE if we are not to continue */
4130 continueEnumeration = lpEnumCallback( &serviceProviderGUID, lpAddressBuffer,
4131 dwAddressBufferSize, &dpName,
4132 dwFlags, lpContext );
4134 else
4136 ERR( "Couldn't build compound address\n" );
4139 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
4140 if ( bAnsi )
4141 HeapFree( GetProcessHeap(), 0, dpName.u1.lpszShortNameA );
4143 if (!continueEnumeration)
4144 return DP_OK;
4147 return DP_OK;
4150 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
4151 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
4153 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4154 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
4155 return DP_IF_EnumConnections( iface, lpguidApplication, lpEnumCallback, lpContext, dwFlags, TRUE );
4158 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
4159 ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
4161 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4162 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
4163 return DP_IF_EnumConnections( iface, lpguidApplication, lpEnumCallback, lpContext, dwFlags, FALSE );
4166 static HRESULT DP_IF_EnumGroupsInGroup
4167 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
4168 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
4169 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
4171 lpGroupList lpGList;
4172 lpGroupData lpGData;
4174 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
4175 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
4176 lpContext, dwFlags, bAnsi );
4178 if( This->dp2->connectionInitialized == NO_PROVIDER )
4180 return DPERR_UNINITIALIZED;
4183 if( !This->dp2->bConnectionOpen )
4185 return DPERR_NOSESSIONS;
4188 if( ( lpEnumPlayersCallback2 == NULL ) ||
4189 ( ( dwFlags & DPENUMGROUPS_SESSION ) && ( lpguidInstance == NULL ) ) )
4191 return DPERR_INVALIDPARAMS;
4194 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4196 return DPERR_INVALIDGROUP;
4199 if( DPQ_IS_EMPTY( lpGData->groups ) )
4201 return DP_OK;
4204 lpGList = DPQ_FIRST( lpGData->groups );
4206 for( ;; )
4208 /* FIXME: Should check dwFlags for match here */
4210 if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP,
4211 &lpGList->lpGData->name, dwFlags,
4212 lpContext ) )
4214 return DP_OK; /* User requested break */
4217 if( DPQ_IS_ENDOFLIST( lpGList->groups ) )
4219 break;
4222 lpGList = DPQ_NEXT( lpGList->groups );
4226 return DP_OK;
4229 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
4230 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
4231 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
4232 DWORD dwFlags )
4234 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4235 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
4236 lpEnumPlayersCallback2, lpContext, dwFlags,
4237 TRUE );
4240 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
4241 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
4242 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
4243 DWORD dwFlags )
4245 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4246 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
4247 lpEnumPlayersCallback2, lpContext, dwFlags,
4248 FALSE );
4251 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
4252 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
4254 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4255 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
4256 return DP_OK;
4259 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
4260 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
4262 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4263 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
4264 return DP_OK;
4267 static BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
4268 REFGUID guidDataType,
4269 DWORD dwDataSize,
4270 LPCVOID lpData,
4271 LPVOID lpContext )
4273 /* Looking for the GUID of the provider to load */
4274 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
4275 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
4278 TRACE( "Found SP/LP (%s) %s (data size = 0x%08x)\n",
4279 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
4281 if( dwDataSize != sizeof( GUID ) )
4283 ERR( "Invalid sp/lp guid size 0x%08x\n", dwDataSize );
4286 memcpy( lpContext, lpData, dwDataSize );
4288 /* There shouldn't be more than 1 GUID/compound address */
4289 return FALSE;
4292 /* Still waiting for what we want */
4293 return TRUE;
4297 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
4298 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
4300 UINT i;
4301 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4302 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
4303 LPCSTR guidDataSubKey = "Guid";
4304 LPCSTR majVerDataSubKey = "dwReserved1";
4305 LPCSTR minVerDataSubKey = "dwReserved2";
4306 LPCSTR pathSubKey = "Path";
4308 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
4310 /* FIXME: Cloned code with a quick hack. */
4311 for( i=0; i<2; i++ )
4313 HKEY hkResult;
4314 LPCSTR searchSubKey;
4315 char subKeyName[51];
4316 DWORD dwIndex, sizeOfSubKeyName=50;
4317 FILETIME filetime;
4319 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
4320 *lpbIsDpSp = (i == 0) ? TRUE : FALSE;
4323 /* Need to loop over the service providers in the registry */
4324 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4325 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4327 /* Hmmm. Does this mean that there are no service providers? */
4328 ERR(": no service providers?\n");
4329 return 0;
4332 /* Traverse all the service providers we have available */
4333 for( dwIndex=0;
4334 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4335 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4336 ++dwIndex, sizeOfSubKeyName=51 )
4339 HKEY hkServiceProvider;
4340 GUID serviceProviderGUID;
4341 DWORD returnType, sizeOfReturnBuffer = 255;
4342 char returnBuffer[256];
4343 WCHAR buff[51];
4344 DWORD dwTemp, len;
4346 TRACE(" this time through: %s\n", subKeyName );
4348 /* Get a handle for this particular service provider */
4349 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4350 &hkServiceProvider ) != ERROR_SUCCESS )
4352 ERR(": what the heck is going on?\n" );
4353 continue;
4356 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4357 NULL, &returnType, (LPBYTE)returnBuffer,
4358 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4360 ERR(": missing GUID registry data members\n" );
4361 continue;
4364 /* FIXME: Check return types to ensure we're interpreting data right */
4365 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4366 CLSIDFromString( buff, &serviceProviderGUID );
4367 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4369 /* Determine if this is the Service Provider that the user asked for */
4370 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
4372 continue;
4375 if( i == 0 ) /* DP SP */
4377 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
4378 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
4379 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
4382 sizeOfReturnBuffer = 255;
4384 /* Get dwReserved1 */
4385 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
4386 NULL, &returnType, (LPBYTE)returnBuffer,
4387 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4389 ERR(": missing dwReserved1 registry data members\n") ;
4390 continue;
4393 if( i == 0 )
4394 memcpy( &lpSpData->dwReserved1, returnBuffer, sizeof(lpSpData->dwReserved1) );
4396 sizeOfReturnBuffer = 255;
4398 /* Get dwReserved2 */
4399 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4400 NULL, &returnType, (LPBYTE)returnBuffer,
4401 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4403 ERR(": missing dwReserved1 registry data members\n") ;
4404 continue;
4407 if( i == 0 )
4408 memcpy( &lpSpData->dwReserved2, returnBuffer, sizeof(lpSpData->dwReserved2) );
4410 sizeOfReturnBuffer = 255;
4412 /* Get the path for this service provider */
4413 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
4414 NULL, NULL, (LPBYTE)returnBuffer,
4415 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
4417 ERR(": missing PATH registry data members: 0x%08x\n", dwTemp );
4418 continue;
4421 TRACE( "Loading %s\n", returnBuffer );
4422 return LoadLibraryA( returnBuffer );
4426 return 0;
4429 static
4430 HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider )
4432 HRESULT hr;
4433 LPDPSP_SPINIT SPInit;
4435 /* Initialize the service provider by calling SPInit */
4436 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4438 if( SPInit == NULL )
4440 ERR( "Service provider doesn't provide SPInit interface?\n" );
4441 FreeLibrary( hServiceProvider );
4442 return DPERR_UNAVAILABLE;
4445 TRACE( "Calling SPInit (DP SP entry point)\n" );
4447 hr = (*SPInit)( &This->dp2->spData );
4449 if( FAILED(hr) )
4451 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4452 FreeLibrary( hServiceProvider );
4453 return hr;
4456 /* FIXME: Need to verify the sanity of the returned callback table
4457 * using IsBadCodePtr */
4458 This->dp2->bSPInitialized = TRUE;
4460 /* This interface is now initialized as a DP object */
4461 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
4463 /* Store the handle of the module so that we can unload it later */
4464 This->dp2->hServiceProvider = hServiceProvider;
4466 return hr;
4469 static
4470 HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hLobbyProvider )
4472 HRESULT hr;
4473 LPSP_INIT DPLSPInit;
4475 /* Initialize the service provider by calling SPInit */
4476 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
4478 if( DPLSPInit == NULL )
4480 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4481 FreeLibrary( hLobbyProvider );
4482 return DPERR_UNAVAILABLE;
4485 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4487 hr = (*DPLSPInit)( &This->dp2->dplspData );
4489 if( FAILED(hr) )
4491 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4492 FreeLibrary( hLobbyProvider );
4493 return hr;
4496 /* FIXME: Need to verify the sanity of the returned callback table
4497 * using IsBadCodePtr */
4499 This->dp2->bDPLSPInitialized = TRUE;
4501 /* This interface is now initialized as a lobby object */
4502 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
4504 /* Store the handle of the module so that we can unload it later */
4505 This->dp2->hDPLobbyProvider = hLobbyProvider;
4507 return hr;
4510 static HRESULT DP_IF_InitializeConnection
4511 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi )
4513 HMODULE hServiceProvider;
4514 HRESULT hr;
4515 GUID guidSP;
4516 const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
4517 BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4519 TRACE("(%p)->(%p,0x%08x,%u)\n", This, lpConnection, dwFlags, bAnsi );
4521 if ( lpConnection == NULL )
4523 return DPERR_INVALIDPARAMS;
4526 if( dwFlags != 0 )
4528 return DPERR_INVALIDFLAGS;
4531 if( This->dp2->connectionInitialized != NO_PROVIDER )
4533 return DPERR_ALREADYINITIALIZED;
4536 /* Find out what the requested SP is and how large this buffer is */
4537 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
4538 dwAddrSize, &guidSP );
4540 if( FAILED(hr) )
4542 ERR( "Invalid compound address?\n" );
4543 return DPERR_UNAVAILABLE;
4546 /* Load the service provider */
4547 hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp );
4549 if( hServiceProvider == 0 )
4551 ERR( "Unable to load service provider %s\n", debugstr_guid(&guidSP) );
4552 return DPERR_UNAVAILABLE;
4555 if( bIsDpSp )
4557 /* Fill in what we can of the Service Provider required information.
4558 * The rest was be done in DP_LoadSP
4560 This->dp2->spData.lpAddress = lpConnection;
4561 This->dp2->spData.dwAddressSize = dwAddrSize;
4562 This->dp2->spData.lpGuid = &guidSP;
4564 hr = DP_InitializeDPSP( This, hServiceProvider );
4566 else
4568 This->dp2->dplspData.lpAddress = lpConnection;
4570 hr = DP_InitializeDPLSP( This, hServiceProvider );
4573 if( FAILED(hr) )
4575 return hr;
4578 return DP_OK;
4581 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4582 ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
4584 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4585 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE );
4588 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4589 ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
4591 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4592 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE );
4595 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4596 ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4597 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4599 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4600 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4603 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4604 ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4605 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4607 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4608 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4611 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4612 ( LPDIRECTPLAY3A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4614 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4615 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4616 return DP_OK;
4619 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4620 ( LPDIRECTPLAY3 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4622 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4623 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4624 return DP_OK;
4627 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4628 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4630 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4631 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4632 return DP_OK;
4635 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4636 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4638 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4639 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4640 return DP_OK;
4643 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4644 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup )
4646 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4647 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, dwFlags, idGroup );
4648 return DP_OK;
4651 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4652 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup )
4654 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4655 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, dwFlags, idGroup );
4656 return DP_OK;
4659 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4660 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDWORD lpdwFlags )
4662 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4663 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpdwFlags );
4664 return DP_OK;
4667 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4668 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDWORD lpdwFlags )
4670 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4671 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpdwFlags );
4672 return DP_OK;
4675 static HRESULT DP_IF_GetGroupParent
4676 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
4677 BOOL bAnsi )
4679 lpGroupData lpGData;
4681 TRACE("(%p)->(0x%08x,%p,%u)\n", This, idGroup, lpidGroup, bAnsi );
4683 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4685 return DPERR_INVALIDGROUP;
4688 *lpidGroup = lpGData->dpid;
4690 return DP_OK;
4693 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4694 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
4696 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4697 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE );
4699 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4700 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
4702 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4703 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE );
4706 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4707 ( LPDIRECTPLAY3A iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4709 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4710 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4711 return DP_OK;
4714 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4715 ( LPDIRECTPLAY3 iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4717 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4718 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4719 return DP_OK;
4722 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4723 ( LPDIRECTPLAY3A iface, DPID idPlayer, LPDWORD lpdwFlags )
4725 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4726 FIXME("(%p)->(0x%08x,%p): stub\n", This, idPlayer, lpdwFlags );
4727 return DP_OK;
4730 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4731 ( LPDIRECTPLAY3 iface, DPID idPlayer, LPDWORD lpdwFlags )
4733 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4734 FIXME("(%p)->(0x%08x,%p): stub\n", This, idPlayer, lpdwFlags );
4735 return DP_OK;
4738 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4739 ( LPDIRECTPLAY4A iface, DPID idGroup, LPDPID lpidGroupOwner )
4741 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4742 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpidGroupOwner );
4743 return DP_OK;
4746 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4747 ( LPDIRECTPLAY4 iface, DPID idGroup, LPDPID lpidGroupOwner )
4749 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4750 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpidGroupOwner );
4751 return DP_OK;
4754 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4755 ( LPDIRECTPLAY4A iface, DPID idGroup , DPID idGroupOwner )
4757 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4758 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, idGroup, idGroupOwner );
4759 return DP_OK;
4762 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4763 ( LPDIRECTPLAY4 iface, DPID idGroup , DPID idGroupOwner )
4765 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4766 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, idGroup, idGroupOwner );
4767 return DP_OK;
4770 static HRESULT DP_SendEx
4771 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4772 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4773 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi )
4775 lpGroupData lpGData;
4776 BOOL bSendToGroup;
4778 TRACE( "(%p)->(0x%08x,0x%08x,0x%08x,%p,0x%08x,0x%08x,0x%08x,%p,%p,%u)\n",
4779 This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority,
4780 dwTimeout, lpContext, lpdwMsgID, bAnsi );
4782 if( This->dp2->connectionInitialized == NO_PROVIDER )
4784 return DPERR_UNINITIALIZED;
4787 /* FIXME: Add parameter checking */
4788 /* FIXME: First call to this needs to acquire a message id which will be
4789 * used for multiple sends
4792 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4794 /* Check idFrom points to a valid player */
4795 if ( DP_FindPlayer( This, idFrom ) == NULL )
4797 ERR( "Invalid from player 0x%08x\n", idFrom );
4798 return DPERR_INVALIDPLAYER;
4801 /* Check idTo: it can be a player or a group */
4802 if( idTo == DPID_ALLPLAYERS )
4804 bSendToGroup = TRUE;
4805 lpGData = This->dp2->lpSysGroup;
4807 else if ( DP_FindPlayer( This, idTo ) )
4809 bSendToGroup = FALSE;
4811 else if ( ( lpGData = DP_FindAnyGroup( This, idTo ) ) )
4813 bSendToGroup = TRUE;
4815 else
4817 return DPERR_INVALIDPLAYER;
4820 if ( bSendToGroup )
4822 #if 0
4823 DPSP_SENDTOGROUPEXDATA data;
4825 data.lpISP = This->dp2->spData.lpISP;
4826 data.dwFlags = dwFlags;
4827 data.idGroupTo = idTo;
4828 data.idPlayerFrom = idFrom;
4829 data.lpSendBuffers = lpData;
4830 data.cBuffers = NULL;
4831 data.dwMessageSize = dwDataSize;
4832 data.dwPriority = dwPriority;
4833 data.dwTimeout = dwTimeout;
4834 data.lpDPContext = lpContext;
4835 data.lpdwSPMsgID = lpdwMsgID;
4837 return (*This->dp2->spData.lpCB->SendToGroupEx)( &data );
4838 #endif
4839 DPSP_SENDDATA data;
4840 lpPlayerList lpPList;
4842 data.dwFlags = dwFlags;
4843 data.idPlayerFrom = idFrom;
4844 data.lpMessage = lpData;
4845 data.dwMessageSize = dwDataSize;
4846 data.bSystemMessage = FALSE;
4847 data.lpISP = This->dp2->spData.lpISP;
4849 if ( (lpPList = DPQ_FIRST( lpGData->players )) )
4853 if ( ~lpPList->lpPData->dwFlags & DPLAYI_PLAYER_PLAYERLOCAL )
4855 data.idPlayerTo = lpPList->lpPData->dpid;
4856 (*This->dp2->spData.lpCB->Send)( &data );
4859 while( (lpPList = DPQ_NEXT( lpPList->players )) );
4862 else
4864 DPSP_SENDDATA data;
4866 data.dwFlags = dwFlags;
4867 data.idPlayerFrom = idFrom;
4868 data.idPlayerTo = idTo;
4869 data.lpMessage = lpData;
4870 data.dwMessageSize = dwDataSize;
4871 data.bSystemMessage = FALSE;
4872 data.lpISP = This->dp2->spData.lpISP;
4874 return (*This->dp2->spData.lpCB->Send)( &data );
4877 /* Have the service provider send this message */
4878 /*wat?
4879 return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority,
4880 dwTimeout, lpContext, lpdwMsgID );*/
4882 return DP_OK;
4886 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4887 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4888 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4889 LPVOID lpContext, LPDWORD lpdwMsgID )
4891 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4892 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4893 dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE );
4896 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4897 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4898 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4899 LPVOID lpContext, LPDWORD lpdwMsgID )
4901 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4902 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4903 dwPriority, dwTimeout, lpContext, lpdwMsgID, FALSE );
4906 static HRESULT DP_SP_SendEx
4907 ( IDirectPlay2Impl* This, DWORD dwFlags,
4908 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4909 LPVOID lpContext, LPDWORD lpdwMsgID )
4911 LPDPMSG lpMElem;
4913 FIXME( ": stub\n" );
4915 /* FIXME: This queuing should only be for async messages */
4917 lpMElem = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpMElem ) );
4918 lpMElem->msg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
4920 CopyMemory( lpMElem->msg, lpData, dwDataSize );
4922 /* FIXME: Need to queue based on priority */
4923 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
4925 return DP_OK;
4928 static HRESULT DP_IF_GetMessageQueue
4929 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4930 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi )
4932 HRESULT hr = DP_OK;
4934 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%p,%u): semi stub\n",
4935 This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi );
4937 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4938 /* FIXME: What about sends which are not immediate? */
4940 if( This->dp2->spData.lpCB->GetMessageQueue )
4942 DPSP_GETMESSAGEQUEUEDATA data;
4944 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4946 /* FIXME: None of this is documented :( */
4948 data.lpISP = This->dp2->spData.lpISP;
4949 data.dwFlags = dwFlags;
4950 data.idFrom = idFrom;
4951 data.idTo = idTo;
4952 data.lpdwNumMsgs = lpdwNumMsgs;
4953 data.lpdwNumBytes = lpdwNumBytes;
4955 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
4957 else
4959 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4962 return hr;
4965 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4966 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4967 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4969 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4970 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4971 lpdwNumBytes, TRUE );
4974 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4975 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4976 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4978 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4979 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4980 lpdwNumBytes, FALSE );
4983 static HRESULT DP_IF_CancelMessage
4984 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
4985 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi )
4987 HRESULT hr = DP_OK;
4989 FIXME( "(%p)->(0x%08x,0x%08x,%u): semi stub\n",
4990 This, dwMsgID, dwFlags, bAnsi );
4992 if( This->dp2->spData.lpCB->Cancel )
4994 DPSP_CANCELDATA data;
4996 TRACE( "Calling SP Cancel\n" );
4998 /* FIXME: Undocumented callback */
5000 data.lpISP = This->dp2->spData.lpISP;
5001 data.dwFlags = dwFlags;
5002 data.lprglpvSPMsgID = NULL;
5003 data.cSPMsgID = dwMsgID;
5004 data.dwMinPriority = dwMinPriority;
5005 data.dwMaxPriority = dwMaxPriority;
5007 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
5009 else
5011 FIXME( "SP doesn't implement Cancel\n" );
5014 return hr;
5017 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
5018 ( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags )
5020 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
5022 if( dwFlags != 0 )
5024 return DPERR_INVALIDFLAGS;
5027 if( dwMsgID == 0 )
5029 dwFlags |= DPCANCELSEND_ALL;
5032 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE );
5035 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
5036 ( LPDIRECTPLAY4 iface, DWORD dwMsgID, DWORD dwFlags )
5038 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
5040 if( dwFlags != 0 )
5042 return DPERR_INVALIDFLAGS;
5045 if( dwMsgID == 0 )
5047 dwFlags |= DPCANCELSEND_ALL;
5050 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, FALSE );
5053 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
5054 ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority,
5055 DWORD dwFlags )
5057 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
5059 if( dwFlags != 0 )
5061 return DPERR_INVALIDFLAGS;
5064 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
5065 dwMaxPriority, TRUE );
5068 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
5069 ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority,
5070 DWORD dwFlags )
5072 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
5074 if( dwFlags != 0 )
5076 return DPERR_INVALIDFLAGS;
5079 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
5080 dwMaxPriority, FALSE );
5083 /* Note: Hack so we can reuse the old functions without compiler warnings */
5084 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5085 # define XCAST(fun) (typeof(directPlay2WVT.fun))
5086 #else
5087 # define XCAST(fun) (void*)
5088 #endif
5090 static const IDirectPlay2Vtbl directPlay2WVT =
5092 XCAST(QueryInterface)DP_QueryInterface,
5093 XCAST(AddRef)DP_AddRef,
5094 XCAST(Release)DP_Release,
5096 DirectPlay2WImpl_AddPlayerToGroup,
5097 DirectPlay2WImpl_Close,
5098 DirectPlay2WImpl_CreateGroup,
5099 DirectPlay2WImpl_CreatePlayer,
5100 DirectPlay2WImpl_DeletePlayerFromGroup,
5101 DirectPlay2WImpl_DestroyGroup,
5102 DirectPlay2WImpl_DestroyPlayer,
5103 DirectPlay2WImpl_EnumGroupPlayers,
5104 DirectPlay2WImpl_EnumGroups,
5105 DirectPlay2WImpl_EnumPlayers,
5106 DirectPlay2WImpl_EnumSessions,
5107 DirectPlay2WImpl_GetCaps,
5108 DirectPlay2WImpl_GetGroupData,
5109 DirectPlay2WImpl_GetGroupName,
5110 DirectPlay2WImpl_GetMessageCount,
5111 DirectPlay2WImpl_GetPlayerAddress,
5112 DirectPlay2WImpl_GetPlayerCaps,
5113 DirectPlay2WImpl_GetPlayerData,
5114 DirectPlay2WImpl_GetPlayerName,
5115 DirectPlay2WImpl_GetSessionDesc,
5116 DirectPlay2WImpl_Initialize,
5117 DirectPlay2WImpl_Open,
5118 DirectPlay2WImpl_Receive,
5119 DirectPlay2WImpl_Send,
5120 DirectPlay2WImpl_SetGroupData,
5121 DirectPlay2WImpl_SetGroupName,
5122 DirectPlay2WImpl_SetPlayerData,
5123 DirectPlay2WImpl_SetPlayerName,
5124 DirectPlay2WImpl_SetSessionDesc
5126 #undef XCAST
5128 /* Note: Hack so we can reuse the old functions without compiler warnings */
5129 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5130 # define XCAST(fun) (typeof(directPlay2AVT.fun))
5131 #else
5132 # define XCAST(fun) (void*)
5133 #endif
5135 static const IDirectPlay2Vtbl directPlay2AVT =
5137 XCAST(QueryInterface)DP_QueryInterface,
5138 XCAST(AddRef)DP_AddRef,
5139 XCAST(Release)DP_Release,
5141 DirectPlay2AImpl_AddPlayerToGroup,
5142 DirectPlay2AImpl_Close,
5143 DirectPlay2AImpl_CreateGroup,
5144 DirectPlay2AImpl_CreatePlayer,
5145 DirectPlay2AImpl_DeletePlayerFromGroup,
5146 DirectPlay2AImpl_DestroyGroup,
5147 DirectPlay2AImpl_DestroyPlayer,
5148 DirectPlay2AImpl_EnumGroupPlayers,
5149 DirectPlay2AImpl_EnumGroups,
5150 DirectPlay2AImpl_EnumPlayers,
5151 DirectPlay2AImpl_EnumSessions,
5152 DirectPlay2AImpl_GetCaps,
5153 DirectPlay2AImpl_GetGroupData,
5154 DirectPlay2AImpl_GetGroupName,
5155 DirectPlay2AImpl_GetMessageCount,
5156 DirectPlay2AImpl_GetPlayerAddress,
5157 DirectPlay2AImpl_GetPlayerCaps,
5158 DirectPlay2AImpl_GetPlayerData,
5159 DirectPlay2AImpl_GetPlayerName,
5160 DirectPlay2AImpl_GetSessionDesc,
5161 DirectPlay2AImpl_Initialize,
5162 DirectPlay2AImpl_Open,
5163 DirectPlay2AImpl_Receive,
5164 DirectPlay2AImpl_Send,
5165 DirectPlay2AImpl_SetGroupData,
5166 DirectPlay2AImpl_SetGroupName,
5167 DirectPlay2AImpl_SetPlayerData,
5168 DirectPlay2AImpl_SetPlayerName,
5169 DirectPlay2AImpl_SetSessionDesc
5171 #undef XCAST
5174 /* Note: Hack so we can reuse the old functions without compiler warnings */
5175 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5176 # define XCAST(fun) (typeof(directPlay3AVT.fun))
5177 #else
5178 # define XCAST(fun) (void*)
5179 #endif
5181 static const IDirectPlay3Vtbl directPlay3AVT =
5183 XCAST(QueryInterface)DP_QueryInterface,
5184 XCAST(AddRef)DP_AddRef,
5185 XCAST(Release)DP_Release,
5187 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
5188 XCAST(Close)DirectPlay2AImpl_Close,
5189 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
5190 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
5191 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
5192 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
5193 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
5194 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
5195 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
5196 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
5197 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
5198 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
5199 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
5200 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
5201 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5202 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5203 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5204 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5205 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5206 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5207 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5208 XCAST(Open)DirectPlay2AImpl_Open,
5209 XCAST(Receive)DirectPlay2AImpl_Receive,
5210 XCAST(Send)DirectPlay2AImpl_Send,
5211 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5212 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5213 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5214 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5215 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5217 DirectPlay3AImpl_AddGroupToGroup,
5218 DirectPlay3AImpl_CreateGroupInGroup,
5219 DirectPlay3AImpl_DeleteGroupFromGroup,
5220 DirectPlay3AImpl_EnumConnections,
5221 DirectPlay3AImpl_EnumGroupsInGroup,
5222 DirectPlay3AImpl_GetGroupConnectionSettings,
5223 DirectPlay3AImpl_InitializeConnection,
5224 DirectPlay3AImpl_SecureOpen,
5225 DirectPlay3AImpl_SendChatMessage,
5226 DirectPlay3AImpl_SetGroupConnectionSettings,
5227 DirectPlay3AImpl_StartSession,
5228 DirectPlay3AImpl_GetGroupFlags,
5229 DirectPlay3AImpl_GetGroupParent,
5230 DirectPlay3AImpl_GetPlayerAccount,
5231 DirectPlay3AImpl_GetPlayerFlags
5233 #undef XCAST
5235 /* Note: Hack so we can reuse the old functions without compiler warnings */
5236 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5237 # define XCAST(fun) (typeof(directPlay3WVT.fun))
5238 #else
5239 # define XCAST(fun) (void*)
5240 #endif
5241 static const IDirectPlay3Vtbl directPlay3WVT =
5243 XCAST(QueryInterface)DP_QueryInterface,
5244 XCAST(AddRef)DP_AddRef,
5245 XCAST(Release)DP_Release,
5247 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
5248 XCAST(Close)DirectPlay2WImpl_Close,
5249 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
5250 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
5251 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
5252 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
5253 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5254 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5255 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5256 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5257 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5258 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5259 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5260 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5261 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5262 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5263 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5264 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5265 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5266 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5267 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5268 XCAST(Open)DirectPlay2WImpl_Open,
5269 XCAST(Receive)DirectPlay2WImpl_Receive,
5270 XCAST(Send)DirectPlay2WImpl_Send,
5271 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5272 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5273 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5274 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5275 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5277 DirectPlay3WImpl_AddGroupToGroup,
5278 DirectPlay3WImpl_CreateGroupInGroup,
5279 DirectPlay3WImpl_DeleteGroupFromGroup,
5280 DirectPlay3WImpl_EnumConnections,
5281 DirectPlay3WImpl_EnumGroupsInGroup,
5282 DirectPlay3WImpl_GetGroupConnectionSettings,
5283 DirectPlay3WImpl_InitializeConnection,
5284 DirectPlay3WImpl_SecureOpen,
5285 DirectPlay3WImpl_SendChatMessage,
5286 DirectPlay3WImpl_SetGroupConnectionSettings,
5287 DirectPlay3WImpl_StartSession,
5288 DirectPlay3WImpl_GetGroupFlags,
5289 DirectPlay3WImpl_GetGroupParent,
5290 DirectPlay3WImpl_GetPlayerAccount,
5291 DirectPlay3WImpl_GetPlayerFlags
5293 #undef XCAST
5295 /* Note: Hack so we can reuse the old functions without compiler warnings */
5296 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5297 # define XCAST(fun) (typeof(directPlay4WVT.fun))
5298 #else
5299 # define XCAST(fun) (void*)
5300 #endif
5301 static const IDirectPlay4Vtbl directPlay4WVT =
5303 XCAST(QueryInterface)DP_QueryInterface,
5304 XCAST(AddRef)DP_AddRef,
5305 XCAST(Release)DP_Release,
5307 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
5308 XCAST(Close)DirectPlay2WImpl_Close,
5309 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
5310 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
5311 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
5312 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
5313 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5314 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5315 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5316 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5317 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5318 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5319 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5320 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5321 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5322 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5323 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5324 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5325 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5326 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5327 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5328 XCAST(Open)DirectPlay2WImpl_Open,
5329 XCAST(Receive)DirectPlay2WImpl_Receive,
5330 XCAST(Send)DirectPlay2WImpl_Send,
5331 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5332 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5333 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5334 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5335 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5337 XCAST(AddGroupToGroup)DirectPlay3WImpl_AddGroupToGroup,
5338 XCAST(CreateGroupInGroup)DirectPlay3WImpl_CreateGroupInGroup,
5339 XCAST(DeleteGroupFromGroup)DirectPlay3WImpl_DeleteGroupFromGroup,
5340 XCAST(EnumConnections)DirectPlay3WImpl_EnumConnections,
5341 XCAST(EnumGroupsInGroup)DirectPlay3WImpl_EnumGroupsInGroup,
5342 XCAST(GetGroupConnectionSettings)DirectPlay3WImpl_GetGroupConnectionSettings,
5343 XCAST(InitializeConnection)DirectPlay3WImpl_InitializeConnection,
5344 XCAST(SecureOpen)DirectPlay3WImpl_SecureOpen,
5345 XCAST(SendChatMessage)DirectPlay3WImpl_SendChatMessage,
5346 XCAST(SetGroupConnectionSettings)DirectPlay3WImpl_SetGroupConnectionSettings,
5347 XCAST(StartSession)DirectPlay3WImpl_StartSession,
5348 XCAST(GetGroupFlags)DirectPlay3WImpl_GetGroupFlags,
5349 XCAST(GetGroupParent)DirectPlay3WImpl_GetGroupParent,
5350 XCAST(GetPlayerAccount)DirectPlay3WImpl_GetPlayerAccount,
5351 XCAST(GetPlayerFlags)DirectPlay3WImpl_GetPlayerFlags,
5353 DirectPlay4WImpl_GetGroupOwner,
5354 DirectPlay4WImpl_SetGroupOwner,
5355 DirectPlay4WImpl_SendEx,
5356 DirectPlay4WImpl_GetMessageQueue,
5357 DirectPlay4WImpl_CancelMessage,
5358 DirectPlay4WImpl_CancelPriority
5360 #undef XCAST
5363 /* Note: Hack so we can reuse the old functions without compiler warnings */
5364 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5365 # define XCAST(fun) (typeof(directPlay4AVT.fun))
5366 #else
5367 # define XCAST(fun) (void*)
5368 #endif
5369 static const IDirectPlay4Vtbl directPlay4AVT =
5371 XCAST(QueryInterface)DP_QueryInterface,
5372 XCAST(AddRef)DP_AddRef,
5373 XCAST(Release)DP_Release,
5375 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
5376 XCAST(Close)DirectPlay2AImpl_Close,
5377 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
5378 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
5379 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
5380 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
5381 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
5382 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
5383 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
5384 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
5385 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
5386 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
5387 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
5388 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
5389 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5390 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5391 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5392 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5393 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5394 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5395 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5396 XCAST(Open)DirectPlay2AImpl_Open,
5397 XCAST(Receive)DirectPlay2AImpl_Receive,
5398 XCAST(Send)DirectPlay2AImpl_Send,
5399 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5400 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5401 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5402 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5403 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5405 XCAST(AddGroupToGroup)DirectPlay3AImpl_AddGroupToGroup,
5406 XCAST(CreateGroupInGroup)DirectPlay3AImpl_CreateGroupInGroup,
5407 XCAST(DeleteGroupFromGroup)DirectPlay3AImpl_DeleteGroupFromGroup,
5408 XCAST(EnumConnections)DirectPlay3AImpl_EnumConnections,
5409 XCAST(EnumGroupsInGroup)DirectPlay3AImpl_EnumGroupsInGroup,
5410 XCAST(GetGroupConnectionSettings)DirectPlay3AImpl_GetGroupConnectionSettings,
5411 XCAST(InitializeConnection)DirectPlay3AImpl_InitializeConnection,
5412 XCAST(SecureOpen)DirectPlay3AImpl_SecureOpen,
5413 XCAST(SendChatMessage)DirectPlay3AImpl_SendChatMessage,
5414 XCAST(SetGroupConnectionSettings)DirectPlay3AImpl_SetGroupConnectionSettings,
5415 XCAST(StartSession)DirectPlay3AImpl_StartSession,
5416 XCAST(GetGroupFlags)DirectPlay3AImpl_GetGroupFlags,
5417 XCAST(GetGroupParent)DirectPlay3AImpl_GetGroupParent,
5418 XCAST(GetPlayerAccount)DirectPlay3AImpl_GetPlayerAccount,
5419 XCAST(GetPlayerFlags)DirectPlay3AImpl_GetPlayerFlags,
5421 DirectPlay4AImpl_GetGroupOwner,
5422 DirectPlay4AImpl_SetGroupOwner,
5423 DirectPlay4AImpl_SendEx,
5424 DirectPlay4AImpl_GetMessageQueue,
5425 DirectPlay4AImpl_CancelMessage,
5426 DirectPlay4AImpl_CancelPriority
5428 #undef XCAST
5430 HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP,
5431 DPID idPlayer,
5432 LPVOID* lplpData )
5434 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5436 if( lpPlayer == NULL )
5438 return DPERR_INVALIDPLAYER;
5441 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
5443 return DP_OK;
5446 HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP,
5447 DPID idPlayer,
5448 LPVOID lpData )
5450 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5452 if( lpPlayer == NULL )
5454 return DPERR_INVALIDPLAYER;
5457 lpPlayer->lpPData->lpSPPlayerData = lpData;
5459 return DP_OK;
5462 /***************************************************************************
5463 * DirectPlayEnumerateAW
5465 * The pointer to the structure lpContext will be filled with the
5466 * appropriate data for each service offered by the OS. These services are
5467 * not necessarily available on this particular machine but are defined
5468 * as simple service providers under the "Service Providers" registry key.
5469 * This structure is then passed to lpEnumCallback for each of the different
5470 * services.
5472 * This API is useful only for applications written using DirectX3 or
5473 * worse. It is superseded by IDirectPlay3::EnumConnections which also
5474 * gives information on the actual connections.
5476 * defn of a service provider:
5477 * A dynamic-link library used by DirectPlay to communicate over a network.
5478 * The service provider contains all the network-specific code required
5479 * to send and receive messages. Online services and network operators can
5480 * supply service providers to use specialized hardware, protocols, communications
5481 * media, and network resources.
5484 static HRESULT DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA,
5485 LPDPENUMDPCALLBACKW lpEnumCallbackW,
5486 LPVOID lpContext)
5488 HKEY hkResult;
5489 static const WCHAR searchSubKey[] = {
5490 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
5491 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
5492 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
5493 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
5494 static const WCHAR guidKey[] = { 'G', 'u', 'i', 'd', 0 };
5495 static const WCHAR descW[] = { 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', 'W', 0 };
5497 DWORD dwIndex;
5498 FILETIME filetime;
5500 char *descriptionA = NULL;
5501 DWORD max_sizeOfDescriptionA = 0;
5502 WCHAR *descriptionW = NULL;
5503 DWORD max_sizeOfDescriptionW = 0;
5505 if (!lpEnumCallbackA && !lpEnumCallbackW)
5507 return DPERR_INVALIDPARAMS;
5510 /* Need to loop over the service providers in the registry */
5511 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, searchSubKey,
5512 0, KEY_READ, &hkResult) != ERROR_SUCCESS)
5514 /* Hmmm. Does this mean that there are no service providers? */
5515 ERR(": no service provider key in the registry - check your Wine installation !!!\n");
5516 return DPERR_GENERIC;
5519 /* Traverse all the service providers we have available */
5520 dwIndex = 0;
5521 while (1)
5523 WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */
5524 DWORD sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR);
5525 HKEY hkServiceProvider;
5526 GUID serviceProviderGUID;
5527 WCHAR guidKeyContent[(2 * 16) + 1 + 6 /* This corresponds to '{....-..-..-..-......}' */ ];
5528 DWORD sizeOfGuidKeyContent = sizeof(guidKeyContent);
5529 LONG ret_value;
5531 ret_value = RegEnumKeyExW(hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
5532 NULL, NULL, NULL, &filetime);
5533 if (ret_value == ERROR_NO_MORE_ITEMS)
5534 break;
5535 else if (ret_value != ERROR_SUCCESS)
5537 ERR(": could not enumerate on service provider key.\n");
5538 return DPERR_EXCEPTION;
5540 TRACE(" this time through sub-key %s.\n", debugstr_w(subKeyName));
5542 /* Open the key for this service provider */
5543 if (RegOpenKeyExW(hkResult, subKeyName, 0, KEY_READ, &hkServiceProvider) != ERROR_SUCCESS)
5545 ERR(": could not open registry key for service provider %s.\n", debugstr_w(subKeyName));
5546 continue;
5549 /* Get the GUID from the registry */
5550 if (RegQueryValueExW(hkServiceProvider, guidKey,
5551 NULL, NULL, (LPBYTE) guidKeyContent, &sizeOfGuidKeyContent) != ERROR_SUCCESS)
5553 ERR(": missing GUID registry data member for service provider %s.\n", debugstr_w(subKeyName));
5554 continue;
5556 if (sizeOfGuidKeyContent != sizeof(guidKeyContent))
5558 ERR(": invalid format for the GUID registry data member for service provider %s (%s).\n", debugstr_w(subKeyName), debugstr_w(guidKeyContent));
5559 continue;
5561 CLSIDFromString(guidKeyContent, &serviceProviderGUID );
5563 /* The enumeration will return FALSE if we are not to continue.
5565 * Note: on my windows box, major / minor version is 6 / 0 for all service providers
5566 * and have no relation to any of the two dwReserved1 and dwReserved2 keys.
5567 * I think that it simply means that they are in-line with DirectX 6.0
5569 if (lpEnumCallbackA)
5571 DWORD sizeOfDescription = 0;
5573 /* Note that this is the A case of this function, so use the A variant to get the description string */
5574 if (RegQueryValueExA(hkServiceProvider, "DescriptionA",
5575 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5577 ERR(": missing 'DescriptionA' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5578 continue;
5580 if (sizeOfDescription > max_sizeOfDescriptionA)
5582 HeapFree(GetProcessHeap(), 0, descriptionA);
5583 max_sizeOfDescriptionA = sizeOfDescription;
5585 descriptionA = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5586 RegQueryValueExA(hkServiceProvider, "DescriptionA",
5587 NULL, NULL, (LPBYTE) descriptionA, &sizeOfDescription);
5589 if (!lpEnumCallbackA(&serviceProviderGUID, descriptionA, 6, 0, lpContext))
5590 goto end;
5592 else
5594 DWORD sizeOfDescription = 0;
5596 if (RegQueryValueExW(hkServiceProvider, descW,
5597 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5599 ERR(": missing 'DescriptionW' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5600 continue;
5602 if (sizeOfDescription > max_sizeOfDescriptionW)
5604 HeapFree(GetProcessHeap(), 0, descriptionW);
5605 max_sizeOfDescriptionW = sizeOfDescription;
5607 descriptionW = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5608 RegQueryValueExW(hkServiceProvider, descW,
5609 NULL, NULL, (LPBYTE) descriptionW, &sizeOfDescription);
5611 if (!lpEnumCallbackW(&serviceProviderGUID, descriptionW, 6, 0, lpContext))
5612 goto end;
5615 dwIndex++;
5618 end:
5619 HeapFree(GetProcessHeap(), 0, descriptionA);
5620 HeapFree(GetProcessHeap(), 0, descriptionW);
5622 return DP_OK;
5625 /***************************************************************************
5626 * DirectPlayEnumerate [DPLAYX.9]
5627 * DirectPlayEnumerateA [DPLAYX.2]
5629 HRESULT WINAPI DirectPlayEnumerateA(LPDPENUMDPCALLBACKA lpEnumCallback, LPVOID lpContext )
5631 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5633 return DirectPlayEnumerateAW(lpEnumCallback, NULL, lpContext);
5636 /***************************************************************************
5637 * DirectPlayEnumerateW [DPLAYX.3]
5639 HRESULT WINAPI DirectPlayEnumerateW(LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5641 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5643 return DirectPlayEnumerateAW(NULL, lpEnumCallback, lpContext);
5646 typedef struct tagCreateEnum
5648 LPVOID lpConn;
5649 LPCGUID lpGuid;
5650 } CreateEnumData, *lpCreateEnumData;
5652 /* Find and copy the matching connection for the SP guid */
5653 static BOOL CALLBACK cbDPCreateEnumConnections(
5654 LPCGUID lpguidSP,
5655 LPVOID lpConnection,
5656 DWORD dwConnectionSize,
5657 LPCDPNAME lpName,
5658 DWORD dwFlags,
5659 LPVOID lpContext)
5661 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5663 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5665 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5667 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5668 dwConnectionSize );
5669 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5671 /* Found the record that we were looking for */
5672 return FALSE;
5675 /* Haven't found what were looking for yet */
5676 return TRUE;
5680 /***************************************************************************
5681 * DirectPlayCreate [DPLAYX.1]
5684 HRESULT WINAPI DirectPlayCreate
5685 ( LPGUID lpGUID, LPDIRECTPLAY *lplpDP, IUnknown *pUnk )
5687 HRESULT hr;
5688 LPDIRECTPLAY3A lpDP3A;
5689 CreateEnumData cbData;
5691 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5693 if( pUnk != NULL )
5695 return CLASS_E_NOAGGREGATION;
5698 if( (lplpDP == NULL) || (lpGUID == NULL) )
5700 return DPERR_INVALIDPARAMS;
5704 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5705 give them an IDirectPlay2A object and hope that doesn't cause problems */
5706 if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
5708 return DPERR_UNAVAILABLE;
5711 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
5713 /* The GUID_NULL means don't bind a service provider. Just return the
5714 interface as is */
5715 return DP_OK;
5718 /* Bind the desired service provider since lpGUID is non NULL */
5719 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
5721 /* We're going to use a DP3 interface */
5722 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
5723 (LPVOID*)&lpDP3A );
5724 if( FAILED(hr) )
5726 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
5727 return hr;
5730 cbData.lpConn = NULL;
5731 cbData.lpGuid = lpGUID;
5733 /* We were given a service provider, find info about it... */
5734 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
5735 &cbData, DPCONNECTION_DIRECTPLAY );
5736 if( ( FAILED(hr) ) ||
5737 ( cbData.lpConn == NULL )
5740 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
5741 IDirectPlayX_Release( lpDP3A );
5742 return DPERR_UNAVAILABLE;
5745 /* Initialize the service provider */
5746 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
5747 if( FAILED(hr) )
5749 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
5750 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5751 IDirectPlayX_Release( lpDP3A );
5752 return hr;
5755 /* Release our version of the interface now that we're done with it */
5756 IDirectPlayX_Release( lpDP3A );
5757 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5759 return DP_OK;