dplayx: Code to send CreatePlayer messages
[wine/gsoc_dplay.git] / dlls / dplayx / dplay.c
blob09fb759e7dd8486bc165c28b66f9187506172036
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_PACKET:
721 LPCDPSP_MSG_PACKET lpcMsg = lpcMessageBody;
722 LPDPSP_MSG_ENVELOPE packetData;
724 /* TODO: We have to wait for all the messages in the sequence and
725 * assemble them in a bigger message. */
726 if ( lpcMsg->TotalPackets > 1 )
728 FIXME( "TODO: Message belongs to a sequence of %d, implement assembly\n",
729 lpcMsg->TotalPackets );
730 return DPERR_GENERIC;
733 /* For now, for simplicity we'll just decapsulate the embedded
734 * message and work with it. */
735 packetData = (LPVOID)(lpcMsg + 1);
737 TRACE( "Processing embedded message with envelope (0x%08x, 0x%08x, %d)\n",
738 packetData->dwMagic, packetData->wCommandId, packetData->wVersion );
740 return DP_HandleMessage( This,
741 packetData,
742 lpcMsg->DataSize,
743 lpcMessageHeader,
744 packetData->wCommandId,
745 packetData->wVersion,
746 lplpReply, lpdwMsgSize );
747 break;
750 case DPMSGCMD_REQUESTPLAYERREPLY:
752 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageHeader,
753 lpcMessageBody, dwMessageBodySize );
754 break;
757 case DPMSGCMD_ADDFORWARDREQUEST:
759 /*LPCDPSP_MSG_ADDFORWARDREQUEST lpcMsg =
760 (LPCDPSP_MSG_ADDFORWARDREQUEST) lpcMessageBody;*/
762 /* TODO: Send ADDFORWARD messages to all the players to populate
763 * their name tables.
764 * Start NametablePopulation timer and wait for ADDFORWARDACKs */
765 FIXME( "Spread name table population messages\n" );
767 /* TODO remember to set local addr somewhere */
768 /* call NS_SetLocalAddr with a SOCKADDR_IN */
770 FIXME( "This should happen after we received all the DPMSGCMD_ADDFORWARDACKs\n" );
771 DP_MSG_ReplyToEnumPlayersRequest( This, lplpReply, lpdwMsgSize );
773 break;
776 case DPMSGCMD_ADDFORWARDREPLY:
778 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageHeader,
779 lpcMessageBody, dwMessageBodySize );
780 break;
783 case DPMSGCMD_ENUMPLAYERSREPLY:
784 case DPMSGCMD_SUPERENUMPLAYERSREPLY:
786 /* If we're joining a session, when we receive this
787 * command we were waiting for a ADDFORWARDREPLY */
788 if ( !DP_MSG_ReplyReceived( This, DPMSGCMD_ADDFORWARDREPLY,
789 lpcMessageHeader, lpcMessageBody,
790 dwMessageBodySize ) )
792 /* If we were not joining a session, check if we are
793 * waiting for an enumeration of players or groups */
794 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageHeader,
795 lpcMessageBody, dwMessageBodySize );
797 break;
800 case DPMSGCMD_ADDFORWARDACK:
802 /* When we receive an ADDFORWARDACK for each of the ADDFORWARDs
803 * we've sent, send a SUPERENUMPLAYERSREPLY back to the peer
804 * that sent the ADDFORWARDREQUEST */
805 /* TODO: We'll skip this for now and just send the SUPERENUMPLAYERSREPLY
806 * right away when we get a ADDFORWARDREQUEST */
807 break;
810 default:
812 FIXME( "Unknown wCommandId 0x%08x. Ignoring message\n", wCommandId );
813 return DPERR_GENERIC;
817 return DP_OK;
821 static HRESULT DP_IF_AddPlayerToGroup
822 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
823 DPID idPlayer, BOOL bAnsi )
825 lpGroupData lpGData;
826 lpPlayerList lpPList;
827 lpPlayerList lpNewPList;
829 TRACE( "(%p)->(%p,0x%08x,0x%08x,%u)\n",
830 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
832 if( This->dp2->connectionInitialized == NO_PROVIDER )
834 return DPERR_UNINITIALIZED;
837 /* Find the group */
838 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
840 return DPERR_INVALIDGROUP;
843 /* Find the player */
844 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
846 return DPERR_INVALIDPLAYER;
849 /* Create a player list (ie "shortcut" ) */
850 lpNewPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewPList ) );
851 if( lpNewPList == NULL )
853 return DPERR_CANTADDPLAYER;
856 /* Add the shortcut */
857 lpPList->lpPData->uRef++;
858 lpNewPList->lpPData = lpPList->lpPData;
860 /* Add the player to the list of players for this group */
861 DPQ_INSERT(lpGData->players,lpNewPList,players);
863 /* Let the SP know that we've added a player to the group */
864 if( This->dp2->spData.lpCB->AddPlayerToGroup )
866 DPSP_ADDPLAYERTOGROUPDATA data;
868 TRACE( "Calling SP AddPlayerToGroup\n" );
870 data.idPlayer = idPlayer;
871 data.idGroup = idGroup;
872 data.lpISP = This->dp2->spData.lpISP;
874 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
877 /* Inform all other peers of the addition of player to the group. If there are
878 * no peers keep this event quiet.
879 * Also, if this event was the result of another machine sending it to us,
880 * don't bother rebroadcasting it.
882 if( ( lpMsgHdr == NULL ) &&
883 This->dp2->lpSessionDesc &&
884 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
886 DPMSG_ADDPLAYERTOGROUP msg;
887 msg.dwType = DPSYS_ADDPLAYERTOGROUP;
889 msg.dpIdGroup = idGroup;
890 msg.dpIdPlayer = idPlayer;
892 /* FIXME: Correct to just use send effectively? */
893 /* FIXME: Should size include data w/ message or just message "header" */
894 /* FIXME: Check return code */
895 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
898 return DP_OK;
901 static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
902 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
904 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
905 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, TRUE );
908 static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
909 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
911 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
912 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, FALSE );
915 static HRESULT DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi )
917 HRESULT hr = DP_OK;
919 TRACE("(%p)->(%u)\n", This, bAnsi );
921 /* FIXME: Need to find a new host I assume (how?) */
922 /* FIXME: Need to destroy all local groups */
923 /* FIXME: Need to migrate all remotely visible players to the new host */
925 /* Invoke the SP callback to inform of session close */
926 if( This->dp2->spData.lpCB->CloseEx )
928 DPSP_CLOSEDATA data;
930 TRACE( "Calling SP CloseEx\n" );
932 data.lpISP = This->dp2->spData.lpISP;
934 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
937 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
939 TRACE( "Calling SP Close (obsolete interface)\n" );
941 hr = (*This->dp2->spData.lpCB->Close)();
944 if ( !FAILED(hr) )
946 This->dp2->bConnectionOpen = FALSE;
949 return hr;
952 static HRESULT WINAPI DirectPlay2AImpl_Close
953 ( LPDIRECTPLAY2A iface )
955 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
956 return DP_IF_Close( This, TRUE );
959 static HRESULT WINAPI DirectPlay2WImpl_Close
960 ( LPDIRECTPLAY2 iface )
962 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
963 return DP_IF_Close( This, FALSE );
966 static
967 lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, const DPID *lpid,
968 const DPNAME *lpName, DWORD dwFlags,
969 DPID idParent, BOOL bAnsi )
971 lpGroupData lpGData;
973 /* Allocate the new space and add to end of high level group list */
974 lpGData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGData ) );
976 if( lpGData == NULL )
978 return NULL;
981 DPQ_INIT(lpGData->groups);
982 DPQ_INIT(lpGData->players);
984 /* Set the desired player ID - no sanity checking to see if it exists */
985 lpGData->dpid = *lpid;
987 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
989 /* FIXME: Should we check that the parent exists? */
990 lpGData->parent = idParent;
992 /* FIXME: Should we validate the dwFlags? */
993 lpGData->dwFlags = dwFlags;
995 TRACE( "Created group id 0x%08x\n", *lpid );
997 return lpGData;
1000 /* This method assumes that all links to it are already deleted */
1001 static void
1002 DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid )
1004 lpGroupList lpGList;
1006 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1008 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
1010 if( lpGList == NULL )
1012 ERR( "DPID 0x%08x not found\n", dpid );
1013 return;
1016 if( --(lpGList->lpGData->uRef) )
1018 FIXME( "Why is this not the last reference to group?\n" );
1019 DebugBreak();
1022 /* Delete player */
1023 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
1024 HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
1026 /* Remove and Delete Player List object */
1027 HeapFree( GetProcessHeap(), 0, lpGList );
1031 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid )
1033 lpGroupList lpGroups;
1035 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1037 if( dpid == DPID_SYSTEM_GROUP )
1039 return This->dp2->lpSysGroup;
1041 else
1043 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
1046 if( lpGroups == NULL )
1048 return NULL;
1051 return lpGroups->lpGData;
1054 static HRESULT DP_IF_CreateGroup
1055 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
1056 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
1057 DWORD dwFlags, BOOL bAnsi )
1059 lpGroupData lpGData;
1061 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1062 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
1063 dwFlags, bAnsi );
1065 /* If the name is not specified, we must provide one */
1066 if( DPID_UNKNOWN == *lpidGroup )
1068 /* If we are the name server, we decide on the group ids. If not, we
1069 * must ask for one before attempting a creation.
1071 if( This->dp2->bHostInterface )
1073 *lpidGroup = DP_NextObjectId();
1075 else
1077 *lpidGroup = DP_GetRemoteNextObjectId();
1081 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
1082 DPID_NOPARENT_GROUP, bAnsi );
1084 if( lpGData == NULL )
1086 return DPERR_CANTADDPLAYER; /* yes player not group */
1089 if( DPID_SYSTEM_GROUP == *lpidGroup )
1091 This->dp2->lpSysGroup = lpGData;
1092 TRACE( "Inserting system group\n" );
1094 else
1096 /* Insert into the system group */
1097 lpGroupList lpGroup = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGroup ) );
1098 lpGroup->lpGData = lpGData;
1100 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
1103 /* Something is now referencing this data */
1104 lpGData->uRef++;
1106 /* Set all the important stuff for the group */
1107 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
1109 /* FIXME: We should only create the system group if GetCaps returns
1110 * DPCAPS_GROUPOPTIMIZED.
1113 /* Let the SP know that we've created this group */
1114 if( This->dp2->spData.lpCB->CreateGroup )
1116 DPSP_CREATEGROUPDATA data;
1117 DWORD dwCreateFlags = 0;
1119 TRACE( "Calling SP CreateGroup\n" );
1121 if( *lpidGroup == DPID_NOPARENT_GROUP )
1122 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
1124 if( lpMsgHdr == NULL )
1125 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1127 if( dwFlags & DPGROUP_HIDDEN )
1128 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
1130 data.idGroup = *lpidGroup;
1131 data.dwFlags = dwCreateFlags;
1132 data.lpSPMessageHeader = lpMsgHdr;
1133 data.lpISP = This->dp2->spData.lpISP;
1135 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1138 /* Inform all other peers of the creation of a new group. If there are
1139 * no peers keep this event quiet.
1140 * Also if this message was sent to us, don't rebroadcast.
1142 if( ( lpMsgHdr == NULL ) &&
1143 This->dp2->lpSessionDesc &&
1144 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1146 DPMSG_CREATEPLAYERORGROUP msg;
1147 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1149 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1150 msg.dpId = *lpidGroup;
1151 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1152 msg.lpData = lpData;
1153 msg.dwDataSize = dwDataSize;
1154 msg.dpnName = *lpGroupName;
1155 msg.dpIdParent = DPID_NOPARENT_GROUP;
1156 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
1158 /* FIXME: Correct to just use send effectively? */
1159 /* FIXME: Should size include data w/ message or just message "header" */
1160 /* FIXME: Check return code */
1161 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
1162 0, 0, NULL, NULL, bAnsi );
1165 return DP_OK;
1168 static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
1169 ( LPDIRECTPLAY2A iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1170 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1172 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1174 if( This->dp2->connectionInitialized == NO_PROVIDER )
1176 return DPERR_UNINITIALIZED;
1179 if( lpidGroup == NULL ||
1180 !This->dp2->bConnectionOpen ||
1181 dwDataSize >= MAXDWORD ||
1182 ( lpData == NULL && dwDataSize != 0 ) )
1184 return DPERR_INVALIDPARAMS;
1187 *lpidGroup = DPID_UNKNOWN;
1189 return DP_IF_CreateGroup( This, NULL, lpidGroup,
1190 lpGroupName, lpData, dwDataSize, dwFlags, TRUE );
1193 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
1194 ( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1195 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1197 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1199 if( This->dp2->connectionInitialized == NO_PROVIDER )
1201 return DPERR_UNINITIALIZED;
1204 if( lpidGroup == NULL ||
1205 !This->dp2->bConnectionOpen ||
1206 dwDataSize >= MAXDWORD ||
1207 ( lpData == NULL && dwDataSize != 0 ) )
1209 return DPERR_INVALIDPARAMS;
1212 *lpidGroup = DPID_UNKNOWN;
1214 return DP_IF_CreateGroup( This, NULL, lpidGroup,
1215 lpGroupName, lpData, dwDataSize, dwFlags, FALSE );
1219 static void
1220 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
1221 LPVOID lpData, DWORD dwDataSize )
1223 /* Clear out the data with this player */
1224 if( dwFlags & DPSET_LOCAL )
1226 if ( lpGData->dwLocalDataSize != 0 )
1228 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
1229 lpGData->lpLocalData = NULL;
1230 lpGData->dwLocalDataSize = 0;
1233 else
1235 if( lpGData->dwRemoteDataSize != 0 )
1237 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
1238 lpGData->lpRemoteData = NULL;
1239 lpGData->dwRemoteDataSize = 0;
1243 /* Reallocate for new data */
1244 if( lpData != NULL )
1246 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1247 sizeof( dwDataSize ) );
1248 CopyMemory( lpNewData, lpData, dwDataSize );
1250 if( dwFlags & DPSET_LOCAL )
1252 lpGData->lpLocalData = lpData;
1253 lpGData->dwLocalDataSize = dwDataSize;
1255 else
1257 lpGData->lpRemoteData = lpNewData;
1258 lpGData->dwRemoteDataSize = dwDataSize;
1265 HRESULT DP_CreatePlayer( IDirectPlay2Impl* This, DPID idPlayer,
1266 LPDPNAME lpName, DWORD dwFlags,
1267 LPVOID lpData, DWORD dwDataSize,
1268 HANDLE hEvent, BOOL bAnsi,
1269 lpPlayerData* lplpPlayer )
1271 /* Create the storage for a new player and insert
1272 * it in the list of players. */
1274 lpPlayerList lpPList = NULL;
1275 lpPlayerData lpPlayer;
1276 HRESULT hr;
1278 TRACE( "(%p)->(0x%08x,%p,0x%08x,%p,%d,%p,%u,%p)\n",
1279 This, idPlayer, lpName, dwFlags, lpData,
1280 dwDataSize, hEvent, bAnsi, lplpPlayer );
1282 /* Verify that we don't already have this player */
1283 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players,
1284 lpPData->dpid, ==, idPlayer, lpPList );
1285 if ( lpPList != NULL )
1287 hr = DPERR_CANTCREATEPLAYER;
1288 goto end;
1291 /* Allocate the storage for the player and associate it with list element */
1292 lpPlayer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPlayer ) );
1293 if( lpPlayer == NULL )
1295 hr = DPERR_CANTCREATEPLAYER;
1296 goto end;
1299 if ( lplpPlayer != NULL )
1301 *lplpPlayer = lpPlayer;
1304 lpPlayer->dpid = idPlayer;
1305 lpPlayer->dwFlags = dwFlags;
1307 DP_CopyDPNAMEStruct( &lpPlayer->name, lpName, bAnsi );
1309 /* If we were given an event handle, duplicate it */
1310 if( hEvent != 0 )
1312 if( !DuplicateHandle( GetCurrentProcess(), hEvent,
1313 GetCurrentProcess(), &lpPlayer->hEvent,
1314 0, FALSE, DUPLICATE_SAME_ACCESS ) )
1316 ERR( "Can't duplicate player msg handle %p\n", hEvent );
1317 hr = DPERR_CANTCREATEPLAYER;
1318 goto end;
1322 /* Set player data */
1323 if ( lpData != NULL )
1325 DP_SetPlayerData( lpPlayer, DPSET_REMOTE, lpData, dwDataSize );
1328 /* Initialize the SP data section */
1329 lpPlayer->lpSPPlayerData = DPSP_CreateSPPlayerData();
1331 if( ~dwFlags & DPLAYI_PLAYER_SYSPLAYER )
1333 This->dp2->lpSessionDesc->dwCurrentPlayers++;
1336 /* Create the list object and link it in */
1337 lpPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPList ) );
1338 if( lpPList == NULL )
1340 hr = DPERR_CANTADDPLAYER;
1341 goto end;
1344 lpPlayer->uRef = 1;
1345 lpPList->lpPData = lpPlayer;
1347 /* Add the player to the system group */
1348 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1350 /* Quick hack */
1351 if ( ~dwFlags & DPLAYI_PLAYER_PLAYERLOCAL ) {
1352 lpPlayerList lpPList;
1353 LPDPMSG lpMsg =
1354 HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct DPMSG) );
1355 LPDPMSG_CREATEPLAYERORGROUP msg =
1356 HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DPMSG_CREATEPLAYERORGROUP) );
1358 msg->dwType = DPSYS_CREATEPLAYERORGROUP;
1359 msg->dwPlayerType = DPPLAYERTYPE_PLAYER;
1360 msg->dpId = idPlayer;
1361 msg->dwCurrentPlayers = This->dp2->lpSessionDesc->dwCurrentPlayers;
1362 msg->lpData = NULL;/*TODO*/
1363 msg->dwDataSize = 0;/*TODO*/
1364 msg->dpIdParent = DPID_NOPARENT_GROUP;
1365 msg->dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
1366 if ( lpName )
1368 msg->dpnName = *lpName;
1371 lpMsg->msg = (LPDPMSG_GENERIC) msg;
1372 lpMsg->dwMsgSize = sizeof(LPDPMSG_CREATEPLAYERORGROUP);
1373 DPQ_INSERT( This->dp2->receiveMsgs, lpMsg, msgs );
1375 if ( (lpPList = DPQ_FIRST( This->dp2->lpSysGroup->players )) )
1379 if ( ( lpPList->lpPData->dwFlags & DPLAYI_PLAYER_PLAYERLOCAL ) &&
1380 lpPList->lpPData->hEvent )
1382 SetEvent( lpPList->lpPData->hEvent );
1385 while( (lpPList = DPQ_NEXT( lpPList->players )) );
1389 end:
1390 if ( FAILED(hr) )
1392 DP_DeletePlayer( This, idPlayer );
1394 return hr;
1397 /* Delete the contents of the DPNAME struct */
1398 static void
1399 DP_DeleteDPNameStruct( LPDPNAME lpDPName )
1401 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u1.lpszShortNameA );
1402 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u2.lpszLongNameA );
1405 /* This method assumes that all links to it are already deleted */
1406 static void
1407 DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid )
1409 lpPlayerList lpPList;
1411 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1413 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1415 if( lpPList == NULL )
1417 ERR( "DPID 0x%08x not found\n", dpid );
1418 return;
1421 /* Verify that this is the last reference to the data */
1422 if( --(lpPList->lpPData->uRef) )
1424 FIXME( "Why is this not the last reference to player?\n" );
1425 DebugBreak();
1428 /* Delete player */
1429 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1431 CloseHandle( lpPList->lpPData->hEvent );
1432 HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
1434 /* Delete Player List object */
1435 HeapFree( GetProcessHeap(), 0, lpPList );
1438 lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid )
1440 lpPlayerList lpPlayers;
1442 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1444 if(This->dp2->lpSysGroup == NULL)
1445 return NULL;
1447 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1449 return lpPlayers;
1452 /* Basic area for Dst must already be allocated */
1453 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, const DPNAME *lpSrc, BOOL bAnsi )
1455 if( lpSrc == NULL )
1457 ZeroMemory( lpDst, sizeof( *lpDst ) );
1458 lpDst->dwSize = sizeof( *lpDst );
1459 return TRUE;
1462 if( lpSrc->dwSize != sizeof( *lpSrc) )
1464 return FALSE;
1467 /* Delete any existing pointers */
1468 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1469 HeapFree( GetProcessHeap(), 0, lpDst->u2.lpszLongNameA );
1471 /* Copy as required */
1472 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1474 if( bAnsi )
1476 if( lpSrc->u1.lpszShortNameA )
1478 lpDst->u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), 0,
1479 strlen(lpSrc->u1.lpszShortNameA)+1 );
1480 strcpy( lpDst->u1.lpszShortNameA, lpSrc->u1.lpszShortNameA );
1482 else
1484 lpDst->u1.lpszShortNameA = NULL;
1486 if( lpSrc->u2.lpszLongNameA )
1488 lpDst->u2.lpszLongNameA = HeapAlloc( GetProcessHeap(), 0,
1489 strlen(lpSrc->u2.lpszLongNameA)+1 );
1490 strcpy( lpDst->u2.lpszLongNameA, lpSrc->u2.lpszLongNameA );
1492 else
1494 lpDst->u2.lpszLongNameA = NULL;
1497 else
1499 if( lpSrc->u1.lpszShortNameA )
1501 lpDst->u1.lpszShortName = HeapAlloc( GetProcessHeap(), 0,
1502 (strlenW(lpSrc->u1.lpszShortName)+1)*sizeof(WCHAR) );
1503 strcpyW( lpDst->u1.lpszShortName, lpSrc->u1.lpszShortName );
1505 else
1507 lpDst->u1.lpszShortNameA = NULL;
1509 if( lpSrc->u2.lpszLongNameA )
1511 lpDst->u2.lpszLongName = HeapAlloc( GetProcessHeap(), 0,
1512 (strlenW(lpSrc->u2.lpszLongName)+1)*sizeof(WCHAR) );
1513 strcpyW( lpDst->u2.lpszLongName, lpSrc->u2.lpszLongName );
1515 else
1517 lpDst->u2.lpszLongNameA = NULL;
1521 return TRUE;
1524 static void
1525 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
1526 LPVOID lpData, DWORD dwDataSize )
1528 /* Clear out the data with this player */
1529 if( dwFlags & DPSET_LOCAL )
1531 if ( lpPData->dwLocalDataSize != 0 )
1533 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
1534 lpPData->lpLocalData = NULL;
1535 lpPData->dwLocalDataSize = 0;
1538 else
1540 if( lpPData->dwRemoteDataSize != 0 )
1542 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
1543 lpPData->lpRemoteData = NULL;
1544 lpPData->dwRemoteDataSize = 0;
1548 /* Reallocate for new data */
1549 if( lpData != NULL )
1551 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1552 sizeof( dwDataSize ) );
1553 CopyMemory( lpNewData, lpData, dwDataSize );
1555 if( dwFlags & DPSET_LOCAL )
1557 lpPData->lpLocalData = lpData;
1558 lpPData->dwLocalDataSize = dwDataSize;
1560 else
1562 lpPData->lpRemoteData = lpNewData;
1563 lpPData->dwRemoteDataSize = dwDataSize;
1569 static HRESULT DP_IF_CreatePlayer
1570 ( IDirectPlay2Impl* This,
1571 LPVOID lpMsgHdr, /* NULL for local creation, non NULL for remote creation */
1572 LPDPID lpidPlayer,
1573 LPDPNAME lpPlayerName,
1574 HANDLE hEvent,
1575 LPVOID lpData,
1576 DWORD dwDataSize,
1577 DWORD dwFlags,
1578 BOOL bAnsi )
1580 HRESULT hr = DP_OK;
1581 lpPlayerData lpPData;
1583 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1584 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1585 dwDataSize, dwFlags, bAnsi );
1587 if( dwFlags == 0 )
1589 dwFlags = DPPLAYER_SPECTATOR;
1592 if( lpidPlayer == NULL )
1594 return DPERR_INVALIDPARAMS;
1598 /* Determine the creation flags for the player. These will be passed
1599 * to the name server if requesting a player id and to the SP when
1600 * informing it of the player creation
1603 if( dwFlags & DPPLAYER_SERVERPLAYER )
1605 if( *lpidPlayer == DPID_SERVERPLAYER )
1607 /* Server player for the host interface */
1608 dwFlags |= DPLAYI_PLAYER_APPSERVER;
1610 else if( *lpidPlayer == DPID_NAME_SERVER )
1612 /* Name server - master of everything */
1613 dwFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
1615 else
1617 /* Server player for a non host interface */
1618 dwFlags |= DPLAYI_PLAYER_SYSPLAYER;
1622 if( lpMsgHdr == NULL )
1623 dwFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1626 /* Verify we know how to handle all the flags */
1627 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1628 ( dwFlags & DPPLAYER_SPECTATOR )
1632 /* Assume non fatal failure */
1633 ERR( "unknown dwFlags = 0x%08x\n", dwFlags );
1636 /* If the name is not specified, we must provide one */
1637 if( *lpidPlayer == DPID_UNKNOWN )
1639 /* If we are the session master, we dish out the group/player ids */
1640 if( This->dp2->bHostInterface )
1642 *lpidPlayer = DP_NextObjectId();
1644 else
1646 hr = DP_MSG_SendRequestPlayerId( This, dwFlags & 0x000000FF, lpidPlayer );
1648 if( FAILED(hr) )
1650 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1651 return hr;
1656 hr = DP_CreatePlayer( This, *lpidPlayer, lpPlayerName, dwFlags,
1657 lpData, dwDataSize, hEvent, bAnsi,
1658 &lpPData );
1659 if( FAILED(hr) )
1661 return hr;
1664 /* Let the SP know that we've created this player */
1665 if( This->dp2->spData.lpCB->CreatePlayer )
1667 DPSP_CREATEPLAYERDATA data;
1669 data.idPlayer = *lpidPlayer;
1670 data.dwFlags = dwFlags;
1671 data.lpSPMessageHeader = lpMsgHdr;
1672 data.lpISP = This->dp2->spData.lpISP;
1674 TRACE( "Calling SP CreatePlayer 0x%08x: dwFlags: 0x%08x lpMsgHdr: %p\n",
1675 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
1677 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1680 if( FAILED(hr) )
1682 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1683 return hr;
1686 /* Now let the SP know that this player is a member of the system group */
1687 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1689 DPSP_ADDPLAYERTOGROUPDATA data;
1691 data.idPlayer = *lpidPlayer;
1692 data.idGroup = DPID_SYSTEM_GROUP;
1693 data.lpISP = This->dp2->spData.lpISP;
1695 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1697 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1700 if( FAILED(hr) )
1702 ERR( "Failed to add player to sys group with sp: %s\n",
1703 DPLAYX_HresultToString(hr) );
1704 return hr;
1708 if ( ( ! This->dp2->bHostInterface ) && ( lpMsgHdr == NULL ) )
1710 if ( dwFlags & DPLAYI_PLAYER_SYSPLAYER )
1712 /* Let the name server know about the creation of this player,
1713 * and reeceive the name table */
1714 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
1716 else
1718 /* Inform all other peers of the creation of a new player.
1719 * Also, if this was a remote event, no need to rebroadcast it. */
1720 hr = DP_MSG_SendCreatePlayer( This, lpPData );
1724 return hr;
1727 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
1728 ( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1729 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1731 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1733 if( This->dp2->connectionInitialized == NO_PROVIDER )
1735 return DPERR_UNINITIALIZED;
1738 if( lpidPlayer == NULL || !This->dp2->bConnectionOpen )
1740 return DPERR_INVALIDPARAMS;
1743 if ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_NEWPLAYERSDISABLED )
1745 return DPERR_CANTCREATEPLAYER;
1748 if( dwFlags & DPPLAYER_SERVERPLAYER )
1750 *lpidPlayer = DPID_SERVERPLAYER;
1752 else
1754 *lpidPlayer = DPID_UNKNOWN;
1757 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1758 lpData, dwDataSize, dwFlags, TRUE );
1761 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
1762 ( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1763 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1765 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1767 if( This->dp2->connectionInitialized == NO_PROVIDER )
1769 return DPERR_UNINITIALIZED;
1772 if( lpidPlayer == NULL || !This->dp2->bConnectionOpen )
1774 return DPERR_INVALIDPARAMS;
1777 if ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_NEWPLAYERSDISABLED )
1779 return DPERR_CANTCREATEPLAYER;
1782 if( dwFlags & DPPLAYER_SERVERPLAYER )
1784 *lpidPlayer = DPID_SERVERPLAYER;
1786 else
1788 *lpidPlayer = DPID_UNKNOWN;
1791 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1792 lpData, dwDataSize, dwFlags, FALSE );
1795 static DPID DP_GetRemoteNextObjectId(void)
1797 FIXME( ":stub\n" );
1799 /* Hack solution */
1800 return DP_NextObjectId();
1803 static HRESULT DP_IF_DeletePlayerFromGroup
1804 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
1805 DPID idPlayer, BOOL bAnsi )
1807 HRESULT hr = DP_OK;
1809 lpGroupData lpGData;
1810 lpPlayerList lpPList;
1812 TRACE( "(%p)->(%p,0x%08x,0x%08x,%u)\n",
1813 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
1815 /* Find the group */
1816 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1818 return DPERR_INVALIDGROUP;
1821 /* Find the player */
1822 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
1824 return DPERR_INVALIDPLAYER;
1827 /* Remove the player shortcut from the group */
1828 DPQ_REMOVE_ENTRY( lpGData->players, players, lpPData->dpid, ==, idPlayer, lpPList );
1830 if( lpPList == NULL )
1832 return DPERR_INVALIDPLAYER;
1835 /* One less reference */
1836 lpPList->lpPData->uRef--;
1838 /* Delete the Player List element */
1839 HeapFree( GetProcessHeap(), 0, lpPList );
1841 /* Inform the SP if they care */
1842 if( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1844 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1846 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1848 data.idPlayer = idPlayer;
1849 data.idGroup = idGroup;
1850 data.lpISP = This->dp2->spData.lpISP;
1852 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1855 /* Need to send a DELETEPLAYERFROMGROUP message */
1856 FIXME( "Need to send a message\n" );
1858 return hr;
1861 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
1862 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
1864 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1865 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, TRUE );
1868 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
1869 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
1871 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1872 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, FALSE );
1875 typedef struct _DPRGOPContext
1877 IDirectPlay3Impl* This;
1878 BOOL bAnsi;
1879 DPID idGroup;
1880 } DPRGOPContext, *lpDPRGOPContext;
1882 static BOOL CALLBACK
1883 cbRemoveGroupOrPlayer(
1884 DPID dpId,
1885 DWORD dwPlayerType,
1886 LPCDPNAME lpName,
1887 DWORD dwFlags,
1888 LPVOID lpContext )
1890 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1892 TRACE( "Removing element:0x%08x (type:0x%08x) from element:0x%08x\n",
1893 dpId, dwPlayerType, lpCtxt->idGroup );
1895 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1897 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt->This, lpCtxt->idGroup,
1898 dpId )
1902 ERR( "Unable to delete group 0x%08x from group 0x%08x\n",
1903 dpId, lpCtxt->idGroup );
1906 else
1908 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl*)lpCtxt->This,
1909 NULL, lpCtxt->idGroup,
1910 dpId, lpCtxt->bAnsi )
1914 ERR( "Unable to delete player 0x%08x from grp 0x%08x\n",
1915 dpId, lpCtxt->idGroup );
1919 return TRUE; /* Continue enumeration */
1922 static HRESULT DP_IF_DestroyGroup
1923 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi )
1925 lpGroupData lpGData;
1926 DPRGOPContext context;
1928 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1929 This, lpMsgHdr, idGroup, bAnsi );
1931 /* Find the group */
1932 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1934 return DPERR_INVALIDPLAYER; /* yes player */
1937 context.This = (IDirectPlay3Impl*)This;
1938 context.bAnsi = bAnsi;
1939 context.idGroup = idGroup;
1941 /* Remove all players that this group has */
1942 DP_IF_EnumGroupPlayers( This, idGroup, NULL,
1943 cbRemoveGroupOrPlayer, &context, 0, bAnsi );
1945 /* Remove all links to groups that this group has since this is dp3 */
1946 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This, idGroup, NULL,
1947 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1949 /* Remove this group from the parent group - if it has one */
1950 if( ( idGroup != DPID_SYSTEM_GROUP ) &&
1951 ( lpGData->parent != DPID_SYSTEM_GROUP )
1954 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl*)This, lpGData->parent,
1955 idGroup );
1958 /* Now delete this group data and list from the system group */
1959 DP_DeleteGroup( This, idGroup );
1961 /* Let the SP know that we've destroyed this group */
1962 if( This->dp2->spData.lpCB->DeleteGroup )
1964 DPSP_DELETEGROUPDATA data;
1966 FIXME( "data.dwFlags is incorrect\n" );
1968 data.idGroup = idGroup;
1969 data.dwFlags = 0;
1970 data.lpISP = This->dp2->spData.lpISP;
1972 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1975 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1977 return DP_OK;
1980 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
1981 ( LPDIRECTPLAY2A iface, DPID idGroup )
1983 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1984 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
1987 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
1988 ( LPDIRECTPLAY2 iface, DPID idGroup )
1990 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1991 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
1994 typedef struct _DPFAGContext
1996 IDirectPlay2Impl* This;
1997 DPID idPlayer;
1998 BOOL bAnsi;
1999 } DPFAGContext, *lpDPFAGContext;
2001 static HRESULT DP_IF_DestroyPlayer
2002 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi )
2004 DPFAGContext cbContext;
2006 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
2007 This, lpMsgHdr, idPlayer, bAnsi );
2009 if( This->dp2->connectionInitialized == NO_PROVIDER )
2011 return DPERR_UNINITIALIZED;
2014 if( DP_FindPlayer( This, idPlayer ) == NULL )
2016 return DPERR_INVALIDPLAYER;
2019 /* FIXME: If the player is remote, we must be the host to delete this */
2021 cbContext.This = This;
2022 cbContext.idPlayer = idPlayer;
2023 cbContext.bAnsi = bAnsi;
2025 /* Find each group and call DeletePlayerFromGroup if the player is a
2026 member of the group */
2027 DP_IF_EnumGroups( This, NULL, cbDeletePlayerFromAllGroups,
2028 &cbContext, DPENUMGROUPS_ALL, bAnsi );
2030 /* Now delete player and player list from the sys group */
2031 DP_DeletePlayer( This, idPlayer );
2033 /* Let the SP know that we've destroyed this group */
2034 if( This->dp2->spData.lpCB->DeletePlayer )
2036 DPSP_DELETEPLAYERDATA data;
2038 FIXME( "data.dwFlags is incorrect\n" );
2040 data.idPlayer = idPlayer;
2041 data.dwFlags = 0;
2042 data.lpISP = This->dp2->spData.lpISP;
2044 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
2047 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
2049 return DP_OK;
2052 static BOOL CALLBACK
2053 cbDeletePlayerFromAllGroups(
2054 DPID dpId,
2055 DWORD dwPlayerType,
2056 LPCDPNAME lpName,
2057 DWORD dwFlags,
2058 LPVOID lpContext )
2060 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
2062 if( dwPlayerType == DPPLAYERTYPE_GROUP )
2064 DP_IF_DeletePlayerFromGroup( lpCtxt->This, NULL, dpId, lpCtxt->idPlayer,
2065 lpCtxt->bAnsi );
2067 /* Enumerate all groups in this group since this will normally only
2068 * be called for top level groups
2070 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)lpCtxt->This,
2071 dpId, NULL,
2072 cbDeletePlayerFromAllGroups,
2073 lpContext, DPENUMGROUPS_ALL,
2074 lpCtxt->bAnsi );
2077 else
2079 ERR( "Group callback has dwPlayerType = 0x%08x\n", dwPlayerType );
2082 return TRUE;
2085 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
2086 ( LPDIRECTPLAY2A iface, DPID idPlayer )
2088 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2089 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
2092 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
2093 ( LPDIRECTPLAY2 iface, DPID idPlayer )
2095 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2096 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
2099 static HRESULT DP_IF_EnumGroupPlayers
2100 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
2101 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2102 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2104 lpGroupData lpGData;
2105 lpPlayerList lpPList;
2107 FIXME("(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
2108 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
2109 lpContext, dwFlags, bAnsi );
2111 if( This->dp2->connectionInitialized == NO_PROVIDER )
2113 return DPERR_UNINITIALIZED;
2116 if( !This->dp2->bConnectionOpen )
2118 return DPERR_NOSESSIONS;
2121 if( ( lpEnumPlayersCallback2 == NULL ) ||
2122 ( ( dwFlags & DPENUMPLAYERS_SESSION ) && ( lpguidInstance == NULL ) ) )
2124 return DPERR_INVALIDPARAMS;
2127 /* Find the group */
2128 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2130 return DPERR_INVALIDGROUP;
2133 if( DPQ_IS_EMPTY( lpGData->players ) )
2135 return DP_OK;
2138 lpPList = DPQ_FIRST( lpGData->players );
2140 /* Walk the players in this group */
2141 for( ;; )
2143 /* We do not enum the name server or app server as they are of no
2144 * consequence to the end user.
2146 if( ( lpPList->lpPData->dpid != DPID_NAME_SERVER ) &&
2147 ( lpPList->lpPData->dpid != DPID_SERVERPLAYER )
2151 /* FIXME: Need to add stuff for dwFlags checking */
2153 if( !lpEnumPlayersCallback2( lpPList->lpPData->dpid, DPPLAYERTYPE_PLAYER,
2154 &lpPList->lpPData->name,
2155 lpPList->lpPData->dwFlags,
2156 lpContext )
2159 /* User requested break */
2160 return DP_OK;
2164 if( DPQ_IS_ENDOFLIST( lpPList->players ) )
2166 break;
2169 lpPList = DPQ_NEXT( lpPList->players );
2172 return DP_OK;
2175 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
2176 ( LPDIRECTPLAY2A iface, DPID idGroup, LPGUID lpguidInstance,
2177 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2178 LPVOID lpContext, DWORD dwFlags )
2180 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2181 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2182 lpEnumPlayersCallback2, lpContext,
2183 dwFlags, TRUE );
2186 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
2187 ( LPDIRECTPLAY2 iface, DPID idGroup, LPGUID lpguidInstance,
2188 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2189 LPVOID lpContext, DWORD dwFlags )
2191 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2192 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2193 lpEnumPlayersCallback2, lpContext,
2194 dwFlags, FALSE );
2197 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2198 static HRESULT DP_IF_EnumGroups
2199 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2200 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2201 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2203 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This,
2204 DPID_SYSTEM_GROUP, lpguidInstance,
2205 lpEnumPlayersCallback2, lpContext,
2206 dwFlags, bAnsi );
2209 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
2210 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2211 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2212 LPVOID lpContext, DWORD dwFlags )
2214 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2215 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2216 lpContext, dwFlags, TRUE );
2219 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
2220 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2221 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2222 LPVOID lpContext, DWORD dwFlags )
2224 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2225 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2226 lpContext, dwFlags, FALSE );
2229 static HRESULT DP_IF_EnumPlayers
2230 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2231 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2232 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2234 return DP_IF_EnumGroupPlayers( This, DPID_SYSTEM_GROUP, lpguidInstance,
2235 lpEnumPlayersCallback2, lpContext,
2236 dwFlags, bAnsi );
2239 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
2240 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2241 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2242 LPVOID lpContext, DWORD dwFlags )
2244 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2245 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2246 lpContext, dwFlags, TRUE );
2249 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
2250 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2251 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2252 LPVOID lpContext, DWORD dwFlags )
2254 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2255 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2256 lpContext, dwFlags, FALSE );
2259 /* This function should call the registered callback function that the user
2260 passed into EnumSessions for each entry available.
2262 static void DP_InvokeEnumSessionCallbacks
2263 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2264 LPVOID lpNSInfo,
2265 DWORD dwTimeout,
2266 LPVOID lpContext )
2268 LPDPSESSIONDESC2 lpSessionDesc;
2270 FIXME( ": not checking for conditions\n" );
2272 /* Not sure if this should be pruning but it's convenient */
2273 NS_PruneSessionCache( lpNSInfo );
2275 NS_ResetSessionEnumeration( lpNSInfo );
2277 /* Enumerate all sessions */
2278 /* FIXME: Need to indicate ANSI */
2279 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2281 TRACE( "EnumSessionsCallback2 invoked\n" );
2282 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2284 return;
2288 /* Invoke one last time to indicate that there is no more to come */
2289 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2292 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2294 EnumSessionAsyncCallbackData* data = lpContext;
2295 HANDLE hSuicideRequest = data->hSuicideRequest;
2296 DWORD dwTimeout = data->dwTimeout;
2298 TRACE( "Thread started with timeout = 0x%08x\n", dwTimeout );
2300 for( ;; )
2302 HRESULT hr;
2304 /* Sleep up to dwTimeout waiting for request to terminate thread */
2305 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2307 TRACE( "Thread terminating on terminate request\n" );
2308 break;
2311 /* Now resend the enum request */
2312 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2313 data->dwEnumSessionFlags,
2314 data->lpSpData );
2316 if( FAILED(hr) )
2318 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2319 /* FIXME: Should we kill this thread? How to inform the main thread? */
2324 TRACE( "Thread terminating\n" );
2326 /* Clean up the thread data */
2327 CloseHandle( hSuicideRequest );
2328 HeapFree( GetProcessHeap(), 0, lpContext );
2330 /* FIXME: Need to have some notification to main app thread that this is
2331 * dead. It would serve two purposes. 1) allow sync on termination
2332 * so that we don't actually send something to ourselves when we
2333 * become name server (race condition) and 2) so that if we die
2334 * abnormally something else will be able to tell.
2337 return 1;
2340 static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
2342 /* Does a thread exist? If so we were doing an async enum session */
2343 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2345 TRACE( "Killing EnumSession thread %p\n",
2346 This->dp2->hEnumSessionThread );
2348 /* Request that the thread kill itself nicely */
2349 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2350 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2352 /* We no longer need to know about the thread */
2353 CloseHandle( This->dp2->hEnumSessionThread );
2355 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2359 static HRESULT DP_IF_EnumSessions
2360 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2361 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2362 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2364 HRESULT hr = DP_OK;
2366 TRACE( "(%p)->(%p,0x%08x,%p,%p,0x%08x,%u)\n",
2367 This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags,
2368 bAnsi );
2369 if( This->dp2->connectionInitialized == NO_PROVIDER )
2371 return DPERR_UNINITIALIZED;
2374 if( (lpsd == NULL) || (lpsd->dwSize != sizeof(DPSESSIONDESC2)) )
2376 return DPERR_INVALIDPARAMS;
2379 /* Can't enumerate if the session is already open */
2380 if( This->dp2->bConnectionOpen )
2382 return DPERR_GENERIC;
2385 #if 1
2386 /* The loading of a lobby provider _seems_ to require a backdoor loading
2387 * of the service provider to also associate with this DP object. This is
2388 * because the app doesn't seem to have to call EnumConnections and
2389 * InitializeConnection for the SP before calling this method. As such
2390 * we'll do their dirty work for them with a quick hack so as to always
2391 * load the TCP/IP service provider.
2393 * The correct solution would seem to involve creating a dialog box which
2394 * contains the possible SPs. These dialog boxes most likely follow SDK
2395 * examples.
2397 if( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
2399 LPVOID lpConnection;
2400 DWORD dwSize;
2402 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2404 if( !DP_BuildCompoundAddr( DPAID_ServiceProvider, (LPGUID)&DPSPGUID_TCPIP,
2405 &lpConnection, &dwSize ) )
2407 ERR( "Can't build compound addr\n" );
2408 return DPERR_GENERIC;
2411 hr = DP_IF_InitializeConnection( (IDirectPlay3Impl*)This, lpConnection,
2412 0, bAnsi );
2413 if( FAILED(hr) )
2415 return hr;
2418 /* Free up the address buffer */
2419 HeapFree( GetProcessHeap(), 0, lpConnection );
2421 /* The SP is now initialized */
2422 This->dp2->bSPInitialized = TRUE;
2424 #endif
2427 /* Use the service provider default? */
2428 if( dwTimeout == 0 )
2430 DPCAPS spCaps;
2431 spCaps.dwSize = sizeof( spCaps );
2433 DP_IF_GetCaps( This, &spCaps, 0 );
2434 dwTimeout = spCaps.dwTimeout;
2436 /* The service provider doesn't provide one either! */
2437 if( dwTimeout == 0 )
2439 /* Provide the TCP/IP default */
2440 dwTimeout = DPMSG_WAIT_5_SECS;
2444 if( dwFlags & DPENUMSESSIONS_STOPASYNC )
2446 DP_KillEnumSessionThread( This );
2447 return hr;
2450 if( ( dwFlags & DPENUMSESSIONS_ASYNC ) )
2452 /* Enumerate everything presently in the local session cache */
2453 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2454 This->dp2->lpNameServerData, dwTimeout,
2455 lpContext );
2457 if( This->dp2->dwEnumSessionLock != 0 )
2458 return DPERR_CONNECTING;
2460 /* See if we've already created a thread to service this interface */
2461 if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2463 DWORD dwThreadId;
2464 This->dp2->dwEnumSessionLock++;
2466 /* Send the first enum request inline since the user may cancel a dialog
2467 * if one is presented. Also, may also have a connecting return code.
2469 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2470 dwFlags, &This->dp2->spData );
2472 if( SUCCEEDED(hr) )
2474 EnumSessionAsyncCallbackData* lpData
2475 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpData ) );
2476 /* FIXME: need to kill the thread on object deletion */
2477 lpData->lpSpData = &This->dp2->spData;
2479 lpData->requestGuid = lpsd->guidApplication;
2480 lpData->dwEnumSessionFlags = dwFlags;
2481 lpData->dwTimeout = dwTimeout;
2483 This->dp2->hKillEnumSessionThreadEvent =
2484 CreateEventW( NULL, TRUE, FALSE, NULL );
2486 if( !DuplicateHandle( GetCurrentProcess(),
2487 This->dp2->hKillEnumSessionThreadEvent,
2488 GetCurrentProcess(),
2489 &lpData->hSuicideRequest,
2490 0, FALSE, DUPLICATE_SAME_ACCESS )
2493 ERR( "Can't duplicate thread killing handle\n" );
2496 TRACE( ": creating EnumSessionsRequest thread\n" );
2498 This->dp2->hEnumSessionThread = CreateThread( NULL,
2500 DP_EnumSessionsSendAsyncRequestThread,
2501 lpData,
2503 &dwThreadId );
2505 This->dp2->dwEnumSessionLock--;
2508 else
2510 /* Invalidate the session cache for the interface */
2511 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2513 /* Send the broadcast for session enumeration */
2514 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2515 dwFlags,
2516 &This->dp2->spData );
2519 SleepEx( dwTimeout, FALSE );
2521 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2522 This->dp2->lpNameServerData, dwTimeout,
2523 lpContext );
2526 return hr;
2529 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2530 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2531 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2532 LPVOID lpContext, DWORD dwFlags )
2534 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2535 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2536 lpContext, dwFlags, TRUE );
2539 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2540 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2541 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2542 LPVOID lpContext, DWORD dwFlags )
2544 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2545 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2546 lpContext, dwFlags, FALSE );
2549 static HRESULT DP_IF_GetPlayerCaps
2550 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
2551 DWORD dwFlags )
2553 DPSP_GETCAPSDATA data;
2555 TRACE("(%p)->(0x%08x,%p,0x%08x)\n", This, idPlayer, lpDPCaps, dwFlags);
2557 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2559 return DPERR_UNINITIALIZED;
2562 if ( lpDPCaps->dwSize != sizeof(DPCAPS) )
2564 return DPERR_INVALIDPARAMS;
2567 /* Query the service provider */
2568 data.idPlayer = idPlayer;
2569 data.dwFlags = dwFlags;
2570 data.lpCaps = lpDPCaps;
2571 data.lpISP = This->dp2->spData.lpISP;
2573 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2576 static HRESULT DP_IF_GetCaps
2577 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags )
2579 return DP_IF_GetPlayerCaps( This, DPID_ALLPLAYERS, lpDPCaps, dwFlags );
2582 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2583 ( LPDIRECTPLAY2A iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2585 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2586 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2589 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2590 ( LPDIRECTPLAY2 iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2592 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2593 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2596 static HRESULT DP_IF_GetGroupData
2597 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2598 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2600 lpGroupData lpGData;
2601 DWORD dwRequiredBufferSize;
2602 LPVOID lpCopyDataFrom;
2604 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2605 This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi );
2607 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2609 return DPERR_INVALIDGROUP;
2612 /* How much buffer is required? */
2613 if( dwFlags & DPSET_LOCAL )
2615 dwRequiredBufferSize = lpGData->dwLocalDataSize;
2616 lpCopyDataFrom = lpGData->lpLocalData;
2618 else
2620 dwRequiredBufferSize = lpGData->dwRemoteDataSize;
2621 lpCopyDataFrom = lpGData->lpRemoteData;
2624 /* Is the user requesting to know how big a buffer is required? */
2625 if( ( lpData == NULL ) ||
2626 ( *lpdwDataSize < dwRequiredBufferSize )
2629 *lpdwDataSize = dwRequiredBufferSize;
2630 return DPERR_BUFFERTOOSMALL;
2633 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2635 return DP_OK;
2638 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2639 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2640 LPDWORD lpdwDataSize, DWORD dwFlags )
2642 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2643 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2644 dwFlags, TRUE );
2647 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2648 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2649 LPDWORD lpdwDataSize, DWORD dwFlags )
2651 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2652 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2653 dwFlags, FALSE );
2656 static HRESULT DP_IF_GetGroupName
2657 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2658 LPDWORD lpdwDataSize, BOOL bAnsi )
2660 lpGroupData lpGData;
2661 LPDPNAME lpName = lpData;
2662 DWORD dwRequiredDataSize;
2664 FIXME("(%p)->(0x%08x,%p,%p,%u) ANSI ignored\n",
2665 This, idGroup, lpData, lpdwDataSize, bAnsi );
2667 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2669 return DPERR_INVALIDGROUP;
2672 dwRequiredDataSize = lpGData->name.dwSize;
2674 if( lpGData->name.u1.lpszShortNameA )
2676 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
2679 if( lpGData->name.u2.lpszLongNameA )
2681 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
2684 if( ( lpData == NULL ) ||
2685 ( *lpdwDataSize < dwRequiredDataSize )
2688 *lpdwDataSize = dwRequiredDataSize;
2689 return DPERR_BUFFERTOOSMALL;
2692 /* Copy the structure */
2693 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2695 if( lpGData->name.u1.lpszShortNameA )
2697 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2698 lpGData->name.u1.lpszShortNameA );
2700 else
2702 lpName->u1.lpszShortNameA = NULL;
2705 if( lpGData->name.u1.lpszShortNameA )
2707 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2708 lpGData->name.u2.lpszLongNameA );
2710 else
2712 lpName->u2.lpszLongNameA = NULL;
2715 return DP_OK;
2718 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2719 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2720 LPDWORD lpdwDataSize )
2722 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2723 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2726 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2727 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2728 LPDWORD lpdwDataSize )
2730 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2731 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2734 static HRESULT DP_IF_GetMessageCount
2735 ( IDirectPlay2Impl* This, DPID idPlayer,
2736 LPDWORD lpdwCount, BOOL bAnsi )
2738 FIXME("(%p)->(0x%08x,%p,%u): stub\n", This, idPlayer, lpdwCount, bAnsi );
2739 return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer,
2740 DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL,
2741 bAnsi );
2744 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2745 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDWORD lpdwCount )
2747 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2748 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, TRUE );
2751 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2752 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDWORD lpdwCount )
2754 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2755 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, FALSE );
2758 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2759 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2761 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2762 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2763 return DP_OK;
2766 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2767 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2769 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2770 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2771 return DP_OK;
2774 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2775 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2776 DWORD dwFlags )
2778 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2779 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2782 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2783 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2784 DWORD dwFlags )
2786 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2787 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2790 static HRESULT DP_IF_GetPlayerData
2791 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2792 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2794 lpPlayerList lpPList;
2795 DWORD dwRequiredBufferSize;
2796 LPVOID lpCopyDataFrom;
2798 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2799 This, idPlayer, lpData, lpdwDataSize, dwFlags, bAnsi );
2801 if( This->dp2->connectionInitialized == NO_PROVIDER )
2803 return DPERR_UNINITIALIZED;
2806 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2808 return DPERR_INVALIDPLAYER;
2811 if( lpdwDataSize == NULL )
2813 return DPERR_INVALIDPARAMS;
2816 /* How much buffer is required? */
2817 if( dwFlags & DPSET_LOCAL )
2819 dwRequiredBufferSize = lpPList->lpPData->dwLocalDataSize;
2820 lpCopyDataFrom = lpPList->lpPData->lpLocalData;
2822 else
2824 dwRequiredBufferSize = lpPList->lpPData->dwRemoteDataSize;
2825 lpCopyDataFrom = lpPList->lpPData->lpRemoteData;
2828 /* Is the user requesting to know how big a buffer is required? */
2829 if( ( lpData == NULL ) ||
2830 ( *lpdwDataSize < dwRequiredBufferSize )
2833 *lpdwDataSize = dwRequiredBufferSize;
2834 return DPERR_BUFFERTOOSMALL;
2837 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2839 return DP_OK;
2842 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2843 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2844 LPDWORD lpdwDataSize, DWORD dwFlags )
2846 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2847 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2848 dwFlags, TRUE );
2851 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2852 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2853 LPDWORD lpdwDataSize, DWORD dwFlags )
2855 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2856 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2857 dwFlags, FALSE );
2860 static HRESULT DP_IF_GetPlayerName
2861 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2862 LPDWORD lpdwDataSize, BOOL bAnsi )
2864 lpPlayerList lpPList;
2865 LPDPNAME lpName = lpData;
2866 DWORD dwRequiredDataSize;
2868 FIXME( "(%p)->(0x%08x,%p,%p,%u): ANSI\n",
2869 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2871 if( This->dp2->connectionInitialized == NO_PROVIDER )
2873 return DPERR_UNINITIALIZED;
2876 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2878 return DPERR_INVALIDPLAYER;
2881 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
2883 if( lpPList->lpPData->name.u1.lpszShortNameA )
2885 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
2888 if( lpPList->lpPData->name.u2.lpszLongNameA )
2890 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
2893 if( ( lpData == NULL ) ||
2894 ( *lpdwDataSize < dwRequiredDataSize )
2897 *lpdwDataSize = dwRequiredDataSize;
2898 return DPERR_BUFFERTOOSMALL;
2901 /* Copy the structure */
2902 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
2904 if( lpPList->lpPData->name.u1.lpszShortNameA )
2906 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2907 lpPList->lpPData->name.u1.lpszShortNameA );
2909 else
2911 lpName->u1.lpszShortNameA = NULL;
2914 if( lpPList->lpPData->name.u2.lpszLongNameA )
2916 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2917 lpPList->lpPData->name.u2.lpszLongNameA );
2919 else
2921 lpName->u2.lpszLongNameA = NULL;
2924 return DP_OK;
2927 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2928 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2929 LPDWORD lpdwDataSize )
2931 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2932 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
2935 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2936 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2937 LPDWORD lpdwDataSize )
2939 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2940 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
2943 static HRESULT DP_GetSessionDesc
2944 ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize,
2945 BOOL bAnsi )
2947 DWORD dwRequiredSize;
2949 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
2951 if( This->dp2->connectionInitialized == NO_PROVIDER )
2953 return DPERR_UNINITIALIZED;
2956 if( !This->dp2->bConnectionOpen )
2958 return DPERR_NOSESSIONS;
2961 if( ( lpdwDataSize == NULL ) || ( *lpdwDataSize >= MAXDWORD ) )
2963 return DPERR_INVALIDPARAMS;
2966 /* FIXME: Get from This->dp2->lpSessionDesc */
2967 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
2969 if ( ( lpData == NULL ) ||
2970 ( *lpdwDataSize < dwRequiredSize )
2973 *lpdwDataSize = dwRequiredSize;
2974 return DPERR_BUFFERTOOSMALL;
2977 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
2979 return DP_OK;
2982 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
2983 ( LPDIRECTPLAY2A iface, LPVOID lpData, LPDWORD lpdwDataSize )
2985 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2986 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2989 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
2990 ( LPDIRECTPLAY2 iface, LPVOID lpData, LPDWORD lpdwDataSize )
2992 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2993 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2996 /* Intended only for COM compatibility. Always returns an error. */
2997 static HRESULT WINAPI DirectPlay2AImpl_Initialize
2998 ( LPDIRECTPLAY2A iface, LPGUID lpGUID )
3000 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3001 TRACE("(%p)->(%p): stub\n", This, lpGUID );
3002 return DPERR_ALREADYINITIALIZED;
3005 /* Intended only for COM compatibility. Always returns an error. */
3006 static HRESULT WINAPI DirectPlay2WImpl_Initialize
3007 ( LPDIRECTPLAY2 iface, LPGUID lpGUID )
3009 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3010 TRACE("(%p)->(%p): stub\n", This, lpGUID );
3011 return DPERR_ALREADYINITIALIZED;
3015 static HRESULT DP_SecureOpen
3016 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
3017 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
3018 BOOL bAnsi )
3020 HRESULT hr = DP_OK;
3022 FIXME( "(%p)->(%p,0x%08x,%p,%p): partial stub\n",
3023 This, lpsd, dwFlags, lpSecurity, lpCredentials );
3025 if( ( lpsd == NULL ) ||
3026 ( lpsd->dwSize != sizeof(DPSESSIONDESC2) ) )
3028 return DPERR_INVALIDPARAMS;
3031 if( This->dp2->bConnectionOpen )
3033 TRACE( ": rejecting already open connection.\n" );
3034 return DPERR_ALREADYINITIALIZED;
3037 /* If we're enumerating, kill the thread */
3038 DP_KillEnumSessionThread( This );
3040 if( dwFlags & DPOPEN_JOIN )
3042 LPDPSESSIONDESC2 current = NULL;
3043 NS_ResetSessionEnumeration( This->dp2->lpNameServerData );
3044 while( ( current = NS_WalkSessions( This->dp2->lpNameServerData ) ) )
3046 if ( IsEqualGUID( &lpsd->guidInstance, &current->guidInstance ) )
3047 break;
3049 if ( current == NULL )
3050 return DPERR_NOSESSIONS;
3052 else if( dwFlags & DPOPEN_CREATE )
3054 /* Rightoo - this computer is the host and the local computer needs to be
3055 the name server so that others can join this session */
3056 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
3058 This->dp2->bHostInterface = TRUE;
3060 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
3061 if( FAILED( hr ) )
3063 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
3064 return hr;
3068 /* Invoke the conditional callback for the service provider */
3069 if( This->dp2->spData.lpCB->Open )
3071 DPSP_OPENDATA data;
3073 FIXME( "Not all data fields are correct. Need new parameter\n" );
3075 data.bCreate = (dwFlags & DPOPEN_CREATE ) ? TRUE : FALSE;
3076 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
3077 : NS_GetNSAddr( This->dp2->lpNameServerData );
3078 data.lpISP = This->dp2->spData.lpISP;
3079 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) ? TRUE : FALSE;
3080 data.dwOpenFlags = dwFlags;
3081 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
3083 hr = (*This->dp2->spData.lpCB->Open)(&data);
3084 if( FAILED( hr ) )
3086 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
3087 return hr;
3092 /* Create the system group of which everything is a part of */
3093 DPID systemGroup = DPID_SYSTEM_GROUP;
3095 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
3096 NULL, 0, 0, TRUE );
3100 if( dwFlags & DPOPEN_JOIN )
3102 DPID dpidServerId = DPID_UNKNOWN;
3104 /* Create the server player for this interface. This way we can receive
3105 * messages for this session.
3107 /* FIXME: I suppose that we should be setting an event for a receive
3108 * type of thing. That way the messaging thread could know to wake
3109 * up. DPlay would then trigger the hEvent for the player the
3110 * message is directed to.
3112 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
3114 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
3117 else if( dwFlags & DPOPEN_CREATE )
3119 DPID dpidNameServerId = DPID_NAME_SERVER;
3121 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
3122 0, DPPLAYER_SERVERPLAYER, bAnsi );
3125 if( FAILED(hr) )
3127 ERR( "Couldn't create name server/system player: %s\n",
3128 DPLAYX_HresultToString(hr) );
3130 else
3132 This->dp2->bConnectionOpen = TRUE;
3135 return hr;
3138 static HRESULT WINAPI DirectPlay2AImpl_Open
3139 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
3141 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3142 TRACE("(%p)->(%p,0x%08x)\n", This, lpsd, dwFlags );
3143 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, TRUE );
3146 static HRESULT WINAPI DirectPlay2WImpl_Open
3147 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
3149 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3150 TRACE("(%p)->(%p,0x%08x)\n", This, lpsd, dwFlags );
3151 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, FALSE );
3154 static HRESULT DP_IF_Receive
3155 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
3156 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi )
3158 LPDPMSG lpMsg = NULL;
3160 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p,%u): stub\n",
3161 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
3163 if( This->dp2->connectionInitialized == NO_PROVIDER )
3165 return DPERR_UNINITIALIZED;
3168 if ( ( lpdwDataSize == NULL ) ||
3169 ( ( dwFlags & DPRECEIVE_FROMPLAYER ) && ( lpidFrom == NULL ) ) ||
3170 ( ( dwFlags & DPRECEIVE_TOPLAYER ) && ( lpidTo == NULL ) ) )
3172 return DPERR_INVALIDPARAMS;
3175 if( dwFlags == 0 )
3177 dwFlags = DPRECEIVE_ALL;
3180 if( dwFlags & DPRECEIVE_ALL )
3182 lpMsg = DPQ_FIRST( This->dp2->receiveMsgs );
3184 else
3186 if ( (lpMsg = DPQ_FIRST( This->dp2->receiveMsgs )) )
3190 if ( ( ( dwFlags & DPRECEIVE_FROMPLAYER ) &&
3191 ( dwFlags & DPRECEIVE_TOPLAYER ) &&
3192 ( lpMsg->idFrom == *lpidFrom ) &&
3193 ( lpMsg->idTo == *lpidTo ) ) || /* From & To */
3194 ( ( dwFlags & DPRECEIVE_FROMPLAYER ) &&
3195 ( lpMsg->idFrom == *lpidFrom ) ) || /* From */
3196 ( ( dwFlags & DPRECEIVE_TOPLAYER ) &&
3197 ( lpMsg->idTo == *lpidTo ) ) ) /* To */
3199 break;
3202 while( (lpMsg = DPQ_NEXT( lpMsg->msgs )) );
3206 if( lpMsg == NULL )
3208 return DPERR_NOMESSAGES;
3211 /* Buffer size check */
3212 if ( ( lpData == NULL ) ||
3213 ( *lpdwDataSize < lpMsg->dwMsgSize ) )
3215 *lpdwDataSize = lpMsg->dwMsgSize;
3216 return DPERR_BUFFERTOOSMALL;
3219 /* Copy into the provided buffer */
3220 if (lpData) CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
3222 /* Set players */
3223 if ( lpidFrom )
3225 *lpidFrom = lpMsg->idFrom;
3227 if ( lpidTo )
3229 *lpidTo = lpMsg->idTo;
3232 /* Remove message from queue */
3233 if( !( dwFlags & DPRECEIVE_PEEK ) )
3235 HeapFree( GetProcessHeap(), 0, lpMsg->msg );
3236 DPQ_REMOVE( This->dp2->receiveMsgs, lpMsg, msgs );
3237 HeapFree( GetProcessHeap(), 0, lpMsg );
3240 return DP_OK;
3243 static HRESULT WINAPI DirectPlay2AImpl_Receive
3244 ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo,
3245 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
3247 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3248 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
3249 lpData, lpdwDataSize, TRUE );
3252 static HRESULT WINAPI DirectPlay2WImpl_Receive
3253 ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo,
3254 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
3256 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3257 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
3258 lpData, lpdwDataSize, FALSE );
3261 static HRESULT WINAPI DirectPlay2AImpl_Send
3262 ( LPDIRECTPLAY2A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3264 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3265 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3266 0, 0, NULL, NULL, TRUE );
3269 static HRESULT WINAPI DirectPlay2WImpl_Send
3270 ( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3272 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3273 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3274 0, 0, NULL, NULL, FALSE );
3277 static HRESULT DP_IF_SetGroupData
3278 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
3279 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3281 lpGroupData lpGData;
3283 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3284 This, idGroup, lpData, dwDataSize, dwFlags, bAnsi );
3286 /* Parameter check */
3287 if( ( lpData == NULL ) &&
3288 ( dwDataSize != 0 )
3291 return DPERR_INVALIDPARAMS;
3294 /* Find the pointer to the data for this player */
3295 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3297 return DPERR_INVALIDOBJECT;
3300 if( !(dwFlags & DPSET_LOCAL) )
3302 FIXME( "Was this group created by this interface?\n" );
3303 /* FIXME: If this is a remote update need to allow it but not
3304 * send a message.
3308 DP_SetGroupData( lpGData, dwFlags, lpData, dwDataSize );
3310 /* FIXME: Only send a message if this group is local to the session otherwise
3311 * it will have been rejected above
3313 if( !(dwFlags & DPSET_LOCAL) )
3315 FIXME( "Send msg?\n" );
3318 return DP_OK;
3321 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
3322 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
3323 DWORD dwDataSize, DWORD dwFlags )
3325 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3326 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, TRUE );
3329 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
3330 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
3331 DWORD dwDataSize, DWORD dwFlags )
3333 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3334 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, FALSE );
3337 static HRESULT DP_IF_SetGroupName
3338 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
3339 DWORD dwFlags, BOOL bAnsi )
3341 lpGroupData lpGData;
3343 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n", This, idGroup,
3344 lpGroupName, dwFlags, bAnsi );
3346 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3348 return DPERR_INVALIDGROUP;
3351 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
3353 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3354 FIXME( "Message not sent and dwFlags ignored\n" );
3356 return DP_OK;
3359 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
3360 ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName,
3361 DWORD dwFlags )
3363 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3364 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
3367 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
3368 ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName,
3369 DWORD dwFlags )
3371 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3372 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
3375 static HRESULT DP_IF_SetPlayerData
3376 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
3377 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3379 lpPlayerList lpPList;
3381 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3382 This, idPlayer, lpData, dwDataSize, dwFlags, bAnsi );
3384 if( This->dp2->connectionInitialized == NO_PROVIDER )
3386 return DPERR_UNINITIALIZED;
3389 /* Parameter check */
3390 if( ( ( lpData == NULL ) && ( dwDataSize != 0 ) ) ||
3391 ( dwDataSize >= MAXDWORD ) )
3393 return DPERR_INVALIDPARAMS;
3396 /* Find the pointer to the data for this player */
3397 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3399 return DPERR_INVALIDPLAYER;
3402 if( !(dwFlags & DPSET_LOCAL) )
3404 FIXME( "Was this group created by this interface?\n" );
3405 /* FIXME: If this is a remote update need to allow it but not
3406 * send a message.
3410 DP_SetPlayerData( lpPList->lpPData, dwFlags, lpData, dwDataSize );
3412 if( !(dwFlags & DPSET_LOCAL) )
3414 FIXME( "Send msg?\n" );
3417 return DP_OK;
3420 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3421 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
3422 DWORD dwDataSize, DWORD dwFlags )
3424 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3425 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3426 dwFlags, TRUE );
3429 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3430 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
3431 DWORD dwDataSize, DWORD dwFlags )
3433 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3434 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3435 dwFlags, FALSE );
3438 static HRESULT DP_IF_SetPlayerName
3439 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
3440 DWORD dwFlags, BOOL bAnsi )
3442 lpPlayerList lpPList;
3444 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n",
3445 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3447 if( This->dp2->connectionInitialized == NO_PROVIDER )
3449 return DPERR_UNINITIALIZED;
3452 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3454 return DPERR_INVALIDGROUP;
3457 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3459 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3460 FIXME( "Message not sent and dwFlags ignored\n" );
3462 return DP_OK;
3465 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3466 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName,
3467 DWORD dwFlags )
3469 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3470 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3473 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3474 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName,
3475 DWORD dwFlags )
3477 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3478 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3481 HRESULT DP_SetSessionDesc
3482 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
3483 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3485 DWORD dwRequiredSize;
3486 LPDPSESSIONDESC2 lpTempSessDesc;
3488 TRACE( "(%p)->(%p,0x%08x,%u,%u)\n",
3489 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3491 /* FIXME: Copy into This->dp2->lpSessionDesc */
3492 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3493 lpTempSessDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize );
3495 if( lpTempSessDesc == NULL )
3497 return DPERR_OUTOFMEMORY;
3500 /* Free the old */
3501 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3503 This->dp2->lpSessionDesc = lpTempSessDesc;
3504 /* Set the new */
3505 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3506 if( bInitial )
3508 /*Initializing session GUID*/
3509 CoCreateGuid( &(This->dp2->lpSessionDesc->guidInstance) );
3511 /* If this is an external invocation of the interface, we should be
3512 * letting everyone know that things have changed. Otherwise this is
3513 * just an initialization and it doesn't need to be propagated.
3515 if( !bInitial )
3517 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3520 return DP_OK;
3523 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3524 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3526 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3528 if( This->dp2->connectionInitialized == NO_PROVIDER )
3530 return DPERR_UNINITIALIZED;
3533 if( !This->dp2->bConnectionOpen )
3535 return DPERR_NOSESSIONS;
3538 if( dwFlags || (lpSessDesc == NULL) )
3540 return DPERR_INVALIDPARAMS;
3543 /* Illegal combinations of flags */
3544 if ( ( lpSessDesc->dwFlags & DPSESSION_MIGRATEHOST ) &&
3545 ( lpSessDesc->dwFlags & ( DPSESSION_CLIENTSERVER |
3546 DPSESSION_MULTICASTSERVER |
3547 DPSESSION_SECURESERVER ) ) )
3549 return DPERR_INVALIDFLAGS;
3552 /* Only the host is allowed to update the session desc */
3553 if( !This->dp2->bHostInterface )
3555 return DPERR_ACCESSDENIED;
3558 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3561 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3562 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3564 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3566 if( This->dp2->connectionInitialized == NO_PROVIDER )
3568 return DPERR_UNINITIALIZED;
3571 if( !This->dp2->bConnectionOpen )
3573 return DPERR_NOSESSIONS;
3576 if( dwFlags || (lpSessDesc == NULL) )
3578 return DPERR_INVALIDPARAMS;
3581 /* Illegal combinations of flags */
3582 if ( ( lpSessDesc->dwFlags & DPSESSION_MIGRATEHOST ) &&
3583 ( lpSessDesc->dwFlags & ( DPSESSION_CLIENTSERVER |
3584 DPSESSION_MULTICASTSERVER |
3585 DPSESSION_SECURESERVER ) ) )
3587 return DPERR_INVALIDFLAGS;
3590 /* Only the host is allowed to update the session desc */
3591 if( !This->dp2->bHostInterface )
3593 return DPERR_ACCESSDENIED;
3596 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3599 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3600 static DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3602 DWORD dwSize = 0;
3604 if( lpSessDesc == NULL )
3606 /* Hmmm..don't need any size? */
3607 ERR( "NULL lpSessDesc\n" );
3608 return dwSize;
3611 dwSize += sizeof( *lpSessDesc );
3613 if( bAnsi )
3615 if( lpSessDesc->u1.lpszSessionNameA )
3617 dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1;
3620 if( lpSessDesc->u2.lpszPasswordA )
3622 dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1;
3625 else /* UNICODE */
3627 if( lpSessDesc->u1.lpszSessionName )
3629 dwSize += sizeof( WCHAR ) *
3630 ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 );
3633 if( lpSessDesc->u2.lpszPassword )
3635 dwSize += sizeof( WCHAR ) *
3636 ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 );
3640 return dwSize;
3643 /* Assumes that contiguous buffers are already allocated. */
3644 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3645 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3647 BYTE* lpStartOfFreeSpace;
3649 if( lpSessionDest == NULL )
3651 ERR( "NULL lpSessionDest\n" );
3652 return;
3655 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3657 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3659 if( bAnsi )
3661 if( lpSessionSrc->u1.lpszSessionNameA )
3663 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3664 lpSessionDest->u1.lpszSessionNameA );
3665 lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3666 lpStartOfFreeSpace +=
3667 lstrlenA( lpSessionDest->u1.lpszSessionNameA ) + 1;
3670 if( lpSessionSrc->u2.lpszPasswordA )
3672 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3673 lpSessionDest->u2.lpszPasswordA );
3674 lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3675 lpStartOfFreeSpace +=
3676 lstrlenA( lpSessionDest->u2.lpszPasswordA ) + 1;
3679 else /* UNICODE */
3681 if( lpSessionSrc->u1.lpszSessionName )
3683 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3684 lpSessionDest->u1.lpszSessionName );
3685 lpSessionDest->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3686 lpStartOfFreeSpace += sizeof(WCHAR) *
3687 ( lstrlenW( lpSessionDest->u1.lpszSessionName ) + 1 );
3690 if( lpSessionSrc->u2.lpszPassword )
3692 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3693 lpSessionDest->u2.lpszPassword );
3694 lpSessionDest->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3695 lpStartOfFreeSpace += sizeof(WCHAR) *
3696 ( lstrlenW( lpSessionDest->u2.lpszPassword ) + 1 );
3702 static HRESULT DP_IF_AddGroupToGroup
3703 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3705 lpGroupData lpGData;
3706 lpGroupList lpNewGList;
3708 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, idParentGroup, idGroup );
3710 if( This->dp2->connectionInitialized == NO_PROVIDER )
3712 return DPERR_UNINITIALIZED;
3715 if( DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) == NULL )
3717 return DPERR_INVALIDGROUP;
3720 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3722 return DPERR_INVALIDGROUP;
3725 /* Create a player list (ie "shortcut" ) */
3726 lpNewGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewGList ) );
3727 if( lpNewGList == NULL )
3729 return DPERR_CANTADDPLAYER;
3732 /* Add the shortcut */
3733 lpGData->uRef++;
3734 lpNewGList->lpGData = lpGData;
3736 /* Add the player to the list of players for this group */
3737 DPQ_INSERT( lpGData->groups, lpNewGList, groups );
3739 /* Send a ADDGROUPTOGROUP message */
3740 FIXME( "Not sending message\n" );
3742 return DP_OK;
3745 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3746 ( LPDIRECTPLAY3A iface, DPID idParentGroup, DPID idGroup )
3748 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3749 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3752 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3753 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3755 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3756 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3759 static HRESULT DP_IF_CreateGroupInGroup
3760 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
3761 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
3762 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3764 lpGroupData lpGParentData;
3765 lpGroupList lpGList;
3766 lpGroupData lpGData;
3768 TRACE( "(%p)->(0x%08x,%p,%p,%p,0x%08x,0x%08x,%u)\n",
3769 This, idParentGroup, lpidGroup, lpGroupName, lpData,
3770 dwDataSize, dwFlags, bAnsi );
3772 /* Verify that the specified parent is valid */
3773 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This,
3774 idParentGroup ) ) == NULL
3777 return DPERR_INVALIDGROUP;
3780 lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName,
3781 dwFlags, idParentGroup, bAnsi );
3783 if( lpGData == NULL )
3785 return DPERR_CANTADDPLAYER; /* yes player not group */
3788 /* Something else is referencing this data */
3789 lpGData->uRef++;
3791 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
3793 /* The list has now been inserted into the interface group list. We now
3794 need to put a "shortcut" to this group in the parent group */
3795 lpGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGList ) );
3796 if( lpGList == NULL )
3798 FIXME( "Memory leak\n" );
3799 return DPERR_CANTADDPLAYER; /* yes player not group */
3802 lpGList->lpGData = lpGData;
3804 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
3806 /* Let the SP know that we've created this group */
3807 if( This->dp2->spData.lpCB->CreateGroup )
3809 DPSP_CREATEGROUPDATA data;
3811 TRACE( "Calling SP CreateGroup\n" );
3813 data.idGroup = *lpidGroup;
3814 data.dwFlags = dwFlags;
3815 data.lpSPMessageHeader = lpMsgHdr;
3816 data.lpISP = This->dp2->spData.lpISP;
3818 (*This->dp2->spData.lpCB->CreateGroup)( &data );
3821 /* Inform all other peers of the creation of a new group. If there are
3822 * no peers keep this quiet.
3824 if( This->dp2->lpSessionDesc &&
3825 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
3827 DPMSG_CREATEPLAYERORGROUP msg;
3829 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
3830 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
3831 msg.dpId = *lpidGroup;
3832 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
3833 msg.lpData = lpData;
3834 msg.dwDataSize = dwDataSize;
3835 msg.dpnName = *lpGroupName;
3837 /* FIXME: Correct to just use send effectively? */
3838 /* FIXME: Should size include data w/ message or just message "header" */
3839 /* FIXME: Check return code */
3840 DP_SendEx( (IDirectPlay2Impl*)This,
3841 DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
3842 0, 0, NULL, NULL, bAnsi );
3845 return DP_OK;
3848 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3849 ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup,
3850 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3851 DWORD dwFlags )
3853 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3855 if( This->dp2->connectionInitialized == NO_PROVIDER )
3857 return DPERR_UNINITIALIZED;
3860 if( lpidGroup == NULL ||
3861 !This->dp2->bConnectionOpen ||
3862 dwDataSize >= MAXDWORD ||
3863 ( lpData == NULL && dwDataSize != 0 ) )
3865 return DPERR_INVALIDPARAMS;
3868 *lpidGroup = DPID_UNKNOWN;
3870 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3871 lpGroupName, lpData, dwDataSize, dwFlags,
3872 TRUE );
3875 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3876 ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup,
3877 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3878 DWORD dwFlags )
3880 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3882 if( This->dp2->connectionInitialized == NO_PROVIDER )
3884 return DPERR_UNINITIALIZED;
3887 if( lpidGroup == NULL ||
3888 !This->dp2->bConnectionOpen ||
3889 dwDataSize >= MAXDWORD ||
3890 ( lpData == NULL && dwDataSize != 0 ) )
3892 return DPERR_INVALIDPARAMS;
3895 *lpidGroup = DPID_UNKNOWN;
3897 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3898 lpGroupName, lpData, dwDataSize,
3899 dwFlags, FALSE );
3902 static HRESULT DP_IF_DeleteGroupFromGroup
3903 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3905 lpGroupList lpGList;
3906 lpGroupData lpGParentData;
3908 TRACE("(%p)->(0x%08x,0x%08x)\n", This, idParentGroup, idGroup );
3910 /* Is the parent group valid? */
3911 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3913 return DPERR_INVALIDGROUP;
3916 /* Remove the group from the parent group queue */
3917 DPQ_REMOVE_ENTRY( lpGParentData->groups, groups, lpGData->dpid, ==, idGroup, lpGList );
3919 if( lpGList == NULL )
3921 return DPERR_INVALIDGROUP;
3924 /* Decrement the ref count */
3925 lpGList->lpGData->uRef--;
3927 /* Free up the list item */
3928 HeapFree( GetProcessHeap(), 0, lpGList );
3930 /* Should send a DELETEGROUPFROMGROUP message */
3931 FIXME( "message not sent\n" );
3933 return DP_OK;
3936 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3937 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3939 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3940 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3943 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3944 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3946 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3947 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3949 static BOOL DP_BuildCompoundAddr( GUID guidDataType,
3950 LPGUID lpcSpGuid,
3951 LPVOID* lplpAddrBuf,
3952 LPDWORD lpdwBufSize )
3954 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3955 HRESULT hr;
3957 dpCompoundAddress.dwDataSize = sizeof( GUID );
3958 dpCompoundAddress.guidDataType = guidDataType;
3959 dpCompoundAddress.lpData = lpcSpGuid;
3961 *lplpAddrBuf = NULL;
3962 *lpdwBufSize = 0;
3964 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3965 lpdwBufSize, TRUE );
3967 if( hr != DPERR_BUFFERTOOSMALL )
3969 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3970 return FALSE;
3973 /* Now allocate the buffer */
3974 *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3975 *lpdwBufSize );
3977 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3978 lpdwBufSize, TRUE );
3979 if( FAILED(hr) )
3981 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3982 return FALSE;
3985 return TRUE;
3988 static HRESULT WINAPI DP_IF_EnumConnections
3989 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication,
3990 LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext,
3991 DWORD dwFlags, BOOL bAnsi )
3993 HKEY hkResult;
3994 WCHAR searchSubKeySP[] = {
3995 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
3996 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
3997 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
3998 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
3999 WCHAR searchSubKeyLP[] = {
4000 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
4001 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
4002 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
4003 'L', 'o', 'b', 'b', 'y', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
4004 WCHAR guidDataSubKey[] = { 'G', 'u', 'i', 'd', 0 };
4005 WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */
4006 DWORD dwIndex, sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR);
4007 FILETIME filetime;
4009 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
4010 if( dwFlags == 0 )
4012 dwFlags = DPCONNECTION_DIRECTPLAY;
4015 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
4016 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) ) )
4018 return DPERR_INVALIDFLAGS;
4021 if( !lpEnumCallback )
4023 return DPERR_INVALIDPARAMS;
4027 /* Need to loop over the service providers in the registry */
4028 if( RegOpenKeyExW( HKEY_LOCAL_MACHINE,
4029 ( dwFlags & DPCONNECTION_DIRECTPLAY ) ? searchSubKeySP
4030 : searchSubKeyLP,
4031 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4033 /* Hmmm. Does this mean that there are no service providers? */
4034 ERR(": no service providers?\n");
4035 return DP_OK;
4039 /* Traverse all the service providers we have available */
4040 for( dwIndex=0;
4041 RegEnumKeyExW( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4042 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4043 ++dwIndex, sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR) )
4045 HKEY hkServiceProvider;
4046 GUID serviceProviderGUID;
4047 WCHAR guidKeyContent[39];
4048 DWORD sizeOfReturnBuffer = sizeof(guidKeyContent);
4049 DPNAME dpName;
4050 BOOL continueEnumeration = TRUE;
4052 LPVOID lpAddressBuffer = NULL;
4053 DWORD dwAddressBufferSize = 0;
4056 TRACE(" this time through: %s\n", debugstr_w(subKeyName) );
4058 /* Get a handle for this particular service provider */
4059 if( RegOpenKeyExW( hkResult, subKeyName, 0, KEY_READ,
4060 &hkServiceProvider ) != ERROR_SUCCESS )
4062 ERR(": what the heck is going on?\n" );
4063 continue;
4066 if( RegQueryValueExW( hkServiceProvider, guidDataSubKey,
4067 NULL, NULL, (LPBYTE)guidKeyContent,
4068 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4070 ERR(": missing GUID registry data members\n" );
4071 RegCloseKey(hkServiceProvider);
4072 continue;
4074 RegCloseKey(hkServiceProvider);
4076 CLSIDFromString( guidKeyContent, &serviceProviderGUID );
4078 /* Fill in the DPNAME struct for the service provider */
4079 dpName.dwSize = sizeof( dpName );
4080 dpName.dwFlags = 0;
4081 if ( bAnsi )
4083 dpName.u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4084 sizeOfSubKeyName+1 );
4085 WideCharToMultiByte( CP_ACP, 0, subKeyName,
4086 -1, dpName.u1.lpszShortNameA, -1, 0, 0);
4087 dpName.u2.lpszLongNameA = NULL;
4089 else
4091 dpName.u1.lpszShortName = subKeyName;
4092 dpName.u2.lpszLongName = NULL;
4095 /* Create the compound address for the service provider.
4096 * NOTE: This is a gruesome architectural scar right now. DP
4097 * uses DPL and DPL uses DP. Nasty stuff. This may be why the
4098 * native dll just gets around this little bit by allocating an
4099 * 80 byte buffer which isn't even filled with a valid compound
4100 * address. Oh well. Creating a proper compound address is the
4101 * way to go anyways despite this method taking slightly more
4102 * heap space and realtime :) */
4104 if ( DP_BuildCompoundAddr( ( ( dwFlags & DPCONNECTION_DIRECTPLAY )
4105 ? DPAID_ServiceProvider
4106 : DPAID_LobbyProvider ),
4107 &serviceProviderGUID,
4108 &lpAddressBuffer,
4109 &dwAddressBufferSize ) )
4111 /* The enumeration will return FALSE if we are not to continue */
4112 continueEnumeration = lpEnumCallback( &serviceProviderGUID, lpAddressBuffer,
4113 dwAddressBufferSize, &dpName,
4114 dwFlags, lpContext );
4116 else
4118 ERR( "Couldn't build compound address\n" );
4121 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
4122 if ( bAnsi )
4123 HeapFree( GetProcessHeap(), 0, dpName.u1.lpszShortNameA );
4125 if (!continueEnumeration)
4126 return DP_OK;
4129 return DP_OK;
4132 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
4133 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
4135 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4136 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
4137 return DP_IF_EnumConnections( iface, lpguidApplication, lpEnumCallback, lpContext, dwFlags, TRUE );
4140 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
4141 ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
4143 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4144 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
4145 return DP_IF_EnumConnections( iface, lpguidApplication, lpEnumCallback, lpContext, dwFlags, FALSE );
4148 static HRESULT DP_IF_EnumGroupsInGroup
4149 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
4150 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
4151 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
4153 lpGroupList lpGList;
4154 lpGroupData lpGData;
4156 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
4157 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
4158 lpContext, dwFlags, bAnsi );
4160 if( This->dp2->connectionInitialized == NO_PROVIDER )
4162 return DPERR_UNINITIALIZED;
4165 if( !This->dp2->bConnectionOpen )
4167 return DPERR_NOSESSIONS;
4170 if( ( lpEnumPlayersCallback2 == NULL ) ||
4171 ( ( dwFlags & DPENUMGROUPS_SESSION ) && ( lpguidInstance == NULL ) ) )
4173 return DPERR_INVALIDPARAMS;
4176 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4178 return DPERR_INVALIDGROUP;
4181 if( DPQ_IS_EMPTY( lpGData->groups ) )
4183 return DP_OK;
4186 lpGList = DPQ_FIRST( lpGData->groups );
4188 for( ;; )
4190 /* FIXME: Should check dwFlags for match here */
4192 if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP,
4193 &lpGList->lpGData->name, dwFlags,
4194 lpContext ) )
4196 return DP_OK; /* User requested break */
4199 if( DPQ_IS_ENDOFLIST( lpGList->groups ) )
4201 break;
4204 lpGList = DPQ_NEXT( lpGList->groups );
4208 return DP_OK;
4211 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
4212 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
4213 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
4214 DWORD dwFlags )
4216 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4217 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
4218 lpEnumPlayersCallback2, lpContext, dwFlags,
4219 TRUE );
4222 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
4223 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
4224 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
4225 DWORD dwFlags )
4227 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4228 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
4229 lpEnumPlayersCallback2, lpContext, dwFlags,
4230 FALSE );
4233 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
4234 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
4236 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4237 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
4238 return DP_OK;
4241 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
4242 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
4244 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4245 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
4246 return DP_OK;
4249 static BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
4250 REFGUID guidDataType,
4251 DWORD dwDataSize,
4252 LPCVOID lpData,
4253 LPVOID lpContext )
4255 /* Looking for the GUID of the provider to load */
4256 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
4257 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
4260 TRACE( "Found SP/LP (%s) %s (data size = 0x%08x)\n",
4261 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
4263 if( dwDataSize != sizeof( GUID ) )
4265 ERR( "Invalid sp/lp guid size 0x%08x\n", dwDataSize );
4268 memcpy( lpContext, lpData, dwDataSize );
4270 /* There shouldn't be more than 1 GUID/compound address */
4271 return FALSE;
4274 /* Still waiting for what we want */
4275 return TRUE;
4279 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
4280 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
4282 UINT i;
4283 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4284 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
4285 LPCSTR guidDataSubKey = "Guid";
4286 LPCSTR majVerDataSubKey = "dwReserved1";
4287 LPCSTR minVerDataSubKey = "dwReserved2";
4288 LPCSTR pathSubKey = "Path";
4290 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
4292 /* FIXME: Cloned code with a quick hack. */
4293 for( i=0; i<2; i++ )
4295 HKEY hkResult;
4296 LPCSTR searchSubKey;
4297 char subKeyName[51];
4298 DWORD dwIndex, sizeOfSubKeyName=50;
4299 FILETIME filetime;
4301 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
4302 *lpbIsDpSp = (i == 0) ? TRUE : FALSE;
4305 /* Need to loop over the service providers in the registry */
4306 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4307 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4309 /* Hmmm. Does this mean that there are no service providers? */
4310 ERR(": no service providers?\n");
4311 return 0;
4314 /* Traverse all the service providers we have available */
4315 for( dwIndex=0;
4316 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4317 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4318 ++dwIndex, sizeOfSubKeyName=51 )
4321 HKEY hkServiceProvider;
4322 GUID serviceProviderGUID;
4323 DWORD returnType, sizeOfReturnBuffer = 255;
4324 char returnBuffer[256];
4325 WCHAR buff[51];
4326 DWORD dwTemp, len;
4328 TRACE(" this time through: %s\n", subKeyName );
4330 /* Get a handle for this particular service provider */
4331 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4332 &hkServiceProvider ) != ERROR_SUCCESS )
4334 ERR(": what the heck is going on?\n" );
4335 continue;
4338 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4339 NULL, &returnType, (LPBYTE)returnBuffer,
4340 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4342 ERR(": missing GUID registry data members\n" );
4343 continue;
4346 /* FIXME: Check return types to ensure we're interpreting data right */
4347 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4348 CLSIDFromString( buff, &serviceProviderGUID );
4349 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4351 /* Determine if this is the Service Provider that the user asked for */
4352 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
4354 continue;
4357 if( i == 0 ) /* DP SP */
4359 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
4360 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
4361 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
4364 sizeOfReturnBuffer = 255;
4366 /* Get dwReserved1 */
4367 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
4368 NULL, &returnType, (LPBYTE)returnBuffer,
4369 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4371 ERR(": missing dwReserved1 registry data members\n") ;
4372 continue;
4375 if( i == 0 )
4376 memcpy( &lpSpData->dwReserved1, returnBuffer, sizeof(lpSpData->dwReserved1) );
4378 sizeOfReturnBuffer = 255;
4380 /* Get dwReserved2 */
4381 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4382 NULL, &returnType, (LPBYTE)returnBuffer,
4383 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4385 ERR(": missing dwReserved1 registry data members\n") ;
4386 continue;
4389 if( i == 0 )
4390 memcpy( &lpSpData->dwReserved2, returnBuffer, sizeof(lpSpData->dwReserved2) );
4392 sizeOfReturnBuffer = 255;
4394 /* Get the path for this service provider */
4395 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
4396 NULL, NULL, (LPBYTE)returnBuffer,
4397 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
4399 ERR(": missing PATH registry data members: 0x%08x\n", dwTemp );
4400 continue;
4403 TRACE( "Loading %s\n", returnBuffer );
4404 return LoadLibraryA( returnBuffer );
4408 return 0;
4411 static
4412 HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider )
4414 HRESULT hr;
4415 LPDPSP_SPINIT SPInit;
4417 /* Initialize the service provider by calling SPInit */
4418 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4420 if( SPInit == NULL )
4422 ERR( "Service provider doesn't provide SPInit interface?\n" );
4423 FreeLibrary( hServiceProvider );
4424 return DPERR_UNAVAILABLE;
4427 TRACE( "Calling SPInit (DP SP entry point)\n" );
4429 hr = (*SPInit)( &This->dp2->spData );
4431 if( FAILED(hr) )
4433 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4434 FreeLibrary( hServiceProvider );
4435 return hr;
4438 /* FIXME: Need to verify the sanity of the returned callback table
4439 * using IsBadCodePtr */
4440 This->dp2->bSPInitialized = TRUE;
4442 /* This interface is now initialized as a DP object */
4443 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
4445 /* Store the handle of the module so that we can unload it later */
4446 This->dp2->hServiceProvider = hServiceProvider;
4448 return hr;
4451 static
4452 HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hLobbyProvider )
4454 HRESULT hr;
4455 LPSP_INIT DPLSPInit;
4457 /* Initialize the service provider by calling SPInit */
4458 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
4460 if( DPLSPInit == NULL )
4462 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4463 FreeLibrary( hLobbyProvider );
4464 return DPERR_UNAVAILABLE;
4467 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4469 hr = (*DPLSPInit)( &This->dp2->dplspData );
4471 if( FAILED(hr) )
4473 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4474 FreeLibrary( hLobbyProvider );
4475 return hr;
4478 /* FIXME: Need to verify the sanity of the returned callback table
4479 * using IsBadCodePtr */
4481 This->dp2->bDPLSPInitialized = TRUE;
4483 /* This interface is now initialized as a lobby object */
4484 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
4486 /* Store the handle of the module so that we can unload it later */
4487 This->dp2->hDPLobbyProvider = hLobbyProvider;
4489 return hr;
4492 static HRESULT DP_IF_InitializeConnection
4493 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi )
4495 HMODULE hServiceProvider;
4496 HRESULT hr;
4497 GUID guidSP;
4498 const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
4499 BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4501 TRACE("(%p)->(%p,0x%08x,%u)\n", This, lpConnection, dwFlags, bAnsi );
4503 if ( lpConnection == NULL )
4505 return DPERR_INVALIDPARAMS;
4508 if( dwFlags != 0 )
4510 return DPERR_INVALIDFLAGS;
4513 if( This->dp2->connectionInitialized != NO_PROVIDER )
4515 return DPERR_ALREADYINITIALIZED;
4518 /* Find out what the requested SP is and how large this buffer is */
4519 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
4520 dwAddrSize, &guidSP );
4522 if( FAILED(hr) )
4524 ERR( "Invalid compound address?\n" );
4525 return DPERR_UNAVAILABLE;
4528 /* Load the service provider */
4529 hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp );
4531 if( hServiceProvider == 0 )
4533 ERR( "Unable to load service provider %s\n", debugstr_guid(&guidSP) );
4534 return DPERR_UNAVAILABLE;
4537 if( bIsDpSp )
4539 /* Fill in what we can of the Service Provider required information.
4540 * The rest was be done in DP_LoadSP
4542 This->dp2->spData.lpAddress = lpConnection;
4543 This->dp2->spData.dwAddressSize = dwAddrSize;
4544 This->dp2->spData.lpGuid = &guidSP;
4546 hr = DP_InitializeDPSP( This, hServiceProvider );
4548 else
4550 This->dp2->dplspData.lpAddress = lpConnection;
4552 hr = DP_InitializeDPLSP( This, hServiceProvider );
4555 if( FAILED(hr) )
4557 return hr;
4560 return DP_OK;
4563 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4564 ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
4566 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4567 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE );
4570 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4571 ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
4573 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4574 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE );
4577 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4578 ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4579 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4581 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4582 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4585 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4586 ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4587 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4589 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4590 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4593 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4594 ( LPDIRECTPLAY3A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4596 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4597 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4598 return DP_OK;
4601 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4602 ( LPDIRECTPLAY3 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4604 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4605 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4606 return DP_OK;
4609 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4610 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4612 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4613 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4614 return DP_OK;
4617 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4618 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4620 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4621 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4622 return DP_OK;
4625 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4626 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup )
4628 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4629 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, dwFlags, idGroup );
4630 return DP_OK;
4633 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4634 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup )
4636 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4637 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, dwFlags, idGroup );
4638 return DP_OK;
4641 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4642 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDWORD lpdwFlags )
4644 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4645 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpdwFlags );
4646 return DP_OK;
4649 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4650 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDWORD lpdwFlags )
4652 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4653 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpdwFlags );
4654 return DP_OK;
4657 static HRESULT DP_IF_GetGroupParent
4658 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
4659 BOOL bAnsi )
4661 lpGroupData lpGData;
4663 TRACE("(%p)->(0x%08x,%p,%u)\n", This, idGroup, lpidGroup, bAnsi );
4665 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4667 return DPERR_INVALIDGROUP;
4670 *lpidGroup = lpGData->dpid;
4672 return DP_OK;
4675 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4676 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
4678 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4679 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE );
4681 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4682 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
4684 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4685 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE );
4688 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4689 ( LPDIRECTPLAY3A iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4691 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4692 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4693 return DP_OK;
4696 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4697 ( LPDIRECTPLAY3 iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4699 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4700 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4701 return DP_OK;
4704 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4705 ( LPDIRECTPLAY3A iface, DPID idPlayer, LPDWORD lpdwFlags )
4707 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4708 FIXME("(%p)->(0x%08x,%p): stub\n", This, idPlayer, lpdwFlags );
4709 return DP_OK;
4712 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4713 ( LPDIRECTPLAY3 iface, DPID idPlayer, LPDWORD lpdwFlags )
4715 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4716 FIXME("(%p)->(0x%08x,%p): stub\n", This, idPlayer, lpdwFlags );
4717 return DP_OK;
4720 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4721 ( LPDIRECTPLAY4A iface, DPID idGroup, LPDPID lpidGroupOwner )
4723 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4724 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpidGroupOwner );
4725 return DP_OK;
4728 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4729 ( LPDIRECTPLAY4 iface, DPID idGroup, LPDPID lpidGroupOwner )
4731 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4732 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpidGroupOwner );
4733 return DP_OK;
4736 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4737 ( LPDIRECTPLAY4A iface, DPID idGroup , DPID idGroupOwner )
4739 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4740 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, idGroup, idGroupOwner );
4741 return DP_OK;
4744 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4745 ( LPDIRECTPLAY4 iface, DPID idGroup , DPID idGroupOwner )
4747 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4748 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, idGroup, idGroupOwner );
4749 return DP_OK;
4752 static HRESULT DP_SendEx
4753 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4754 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4755 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi )
4757 BOOL bValidDestination = FALSE;
4759 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,0x%08x,0x%08x,0x%08x,%p,%p,%u)"
4760 ": stub\n",
4761 This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority,
4762 dwTimeout, lpContext, lpdwMsgID, bAnsi );
4764 if( This->dp2->connectionInitialized == NO_PROVIDER )
4766 return DPERR_UNINITIALIZED;
4769 /* FIXME: Add parameter checking */
4770 /* FIXME: First call to this needs to acquire a message id which will be
4771 * used for multiple sends
4774 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4776 /* Verify that the message is being sent from a valid local player. The
4777 * from player may be anonymous DPID_UNKNOWN
4779 if( idFrom != DPID_UNKNOWN )
4781 if( DP_FindPlayer( This, idFrom ) == NULL )
4783 WARN( "INFO: Invalid from player 0x%08x\n", idFrom );
4784 return DPERR_INVALIDPLAYER;
4788 /* Verify that the message is being sent to a valid player, group or to
4789 * everyone. If it's valid, send it to those players.
4791 if( idTo == DPID_ALLPLAYERS )
4793 bValidDestination = TRUE;
4795 /* See if SP has the ability to multicast. If so, use it */
4796 if( This->dp2->spData.lpCB->SendToGroupEx )
4798 FIXME( "Use group sendex to group 0\n" );
4800 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4802 FIXME( "Use obsolete group send to group 0\n" );
4804 else /* No multicast, multiplicate */
4806 /* Send to all players we know about */
4807 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4811 if( ( !bValidDestination ) &&
4812 ( DP_FindPlayer( This, idTo ) != NULL )
4815 bValidDestination = TRUE;
4817 /* Have the service provider send this message */
4818 /* FIXME: Could optimize for local interface sends */
4819 return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority,
4820 dwTimeout, lpContext, lpdwMsgID );
4823 if( ( !bValidDestination ) &&
4824 ( DP_FindAnyGroup( This, idTo ) != NULL )
4827 bValidDestination = TRUE;
4829 /* See if SP has the ability to multicast. If so, use it */
4830 if( This->dp2->spData.lpCB->SendToGroupEx )
4832 FIXME( "Use group sendex\n" );
4834 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4836 FIXME( "Use obsolete group send to group\n" );
4838 else /* No multicast, multiplicate */
4840 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4843 #if 0
4844 if( bExpectReply )
4846 DWORD dwWaitReturn;
4848 This->dp2->hReplyEvent = CreateEventW( NULL, FALSE, FALSE, NULL );
4850 dwWaitReturn = WaitForSingleObject( hReplyEvent, dwTimeout );
4851 if( dwWaitReturn != WAIT_OBJECT_0 )
4853 ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
4856 #endif
4859 if( !bValidDestination )
4861 return DPERR_INVALIDPLAYER;
4863 else
4865 /* FIXME: Should return what the send returned */
4866 return DP_OK;
4871 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4872 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4873 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4874 LPVOID lpContext, LPDWORD lpdwMsgID )
4876 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4877 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4878 dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE );
4881 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4882 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4883 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4884 LPVOID lpContext, LPDWORD lpdwMsgID )
4886 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4887 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4888 dwPriority, dwTimeout, lpContext, lpdwMsgID, FALSE );
4891 static HRESULT DP_SP_SendEx
4892 ( IDirectPlay2Impl* This, DWORD dwFlags,
4893 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4894 LPVOID lpContext, LPDWORD lpdwMsgID )
4896 LPDPMSG lpMElem;
4898 FIXME( ": stub\n" );
4900 /* FIXME: This queuing should only be for async messages */
4902 lpMElem = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpMElem ) );
4903 lpMElem->msg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
4905 CopyMemory( lpMElem->msg, lpData, dwDataSize );
4907 /* FIXME: Need to queue based on priority */
4908 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
4910 return DP_OK;
4913 static HRESULT DP_IF_GetMessageQueue
4914 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4915 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi )
4917 HRESULT hr = DP_OK;
4919 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%p,%u): semi stub\n",
4920 This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi );
4922 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4923 /* FIXME: What about sends which are not immediate? */
4925 if( This->dp2->spData.lpCB->GetMessageQueue )
4927 DPSP_GETMESSAGEQUEUEDATA data;
4929 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4931 /* FIXME: None of this is documented :( */
4933 data.lpISP = This->dp2->spData.lpISP;
4934 data.dwFlags = dwFlags;
4935 data.idFrom = idFrom;
4936 data.idTo = idTo;
4937 data.lpdwNumMsgs = lpdwNumMsgs;
4938 data.lpdwNumBytes = lpdwNumBytes;
4940 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
4942 else
4944 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4947 return hr;
4950 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4951 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4952 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4954 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4955 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4956 lpdwNumBytes, TRUE );
4959 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4960 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4961 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4963 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4964 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4965 lpdwNumBytes, FALSE );
4968 static HRESULT DP_IF_CancelMessage
4969 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
4970 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi )
4972 HRESULT hr = DP_OK;
4974 FIXME( "(%p)->(0x%08x,0x%08x,%u): semi stub\n",
4975 This, dwMsgID, dwFlags, bAnsi );
4977 if( This->dp2->spData.lpCB->Cancel )
4979 DPSP_CANCELDATA data;
4981 TRACE( "Calling SP Cancel\n" );
4983 /* FIXME: Undocumented callback */
4985 data.lpISP = This->dp2->spData.lpISP;
4986 data.dwFlags = dwFlags;
4987 data.lprglpvSPMsgID = NULL;
4988 data.cSPMsgID = dwMsgID;
4989 data.dwMinPriority = dwMinPriority;
4990 data.dwMaxPriority = dwMaxPriority;
4992 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
4994 else
4996 FIXME( "SP doesn't implement Cancel\n" );
4999 return hr;
5002 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
5003 ( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags )
5005 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
5007 if( dwFlags != 0 )
5009 return DPERR_INVALIDFLAGS;
5012 if( dwMsgID == 0 )
5014 dwFlags |= DPCANCELSEND_ALL;
5017 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE );
5020 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
5021 ( LPDIRECTPLAY4 iface, DWORD dwMsgID, DWORD dwFlags )
5023 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
5025 if( dwFlags != 0 )
5027 return DPERR_INVALIDFLAGS;
5030 if( dwMsgID == 0 )
5032 dwFlags |= DPCANCELSEND_ALL;
5035 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, FALSE );
5038 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
5039 ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority,
5040 DWORD dwFlags )
5042 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
5044 if( dwFlags != 0 )
5046 return DPERR_INVALIDFLAGS;
5049 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
5050 dwMaxPriority, TRUE );
5053 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
5054 ( LPDIRECTPLAY4 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, FALSE );
5068 /* Note: Hack so we can reuse the old functions without compiler warnings */
5069 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5070 # define XCAST(fun) (typeof(directPlay2WVT.fun))
5071 #else
5072 # define XCAST(fun) (void*)
5073 #endif
5075 static const IDirectPlay2Vtbl directPlay2WVT =
5077 XCAST(QueryInterface)DP_QueryInterface,
5078 XCAST(AddRef)DP_AddRef,
5079 XCAST(Release)DP_Release,
5081 DirectPlay2WImpl_AddPlayerToGroup,
5082 DirectPlay2WImpl_Close,
5083 DirectPlay2WImpl_CreateGroup,
5084 DirectPlay2WImpl_CreatePlayer,
5085 DirectPlay2WImpl_DeletePlayerFromGroup,
5086 DirectPlay2WImpl_DestroyGroup,
5087 DirectPlay2WImpl_DestroyPlayer,
5088 DirectPlay2WImpl_EnumGroupPlayers,
5089 DirectPlay2WImpl_EnumGroups,
5090 DirectPlay2WImpl_EnumPlayers,
5091 DirectPlay2WImpl_EnumSessions,
5092 DirectPlay2WImpl_GetCaps,
5093 DirectPlay2WImpl_GetGroupData,
5094 DirectPlay2WImpl_GetGroupName,
5095 DirectPlay2WImpl_GetMessageCount,
5096 DirectPlay2WImpl_GetPlayerAddress,
5097 DirectPlay2WImpl_GetPlayerCaps,
5098 DirectPlay2WImpl_GetPlayerData,
5099 DirectPlay2WImpl_GetPlayerName,
5100 DirectPlay2WImpl_GetSessionDesc,
5101 DirectPlay2WImpl_Initialize,
5102 DirectPlay2WImpl_Open,
5103 DirectPlay2WImpl_Receive,
5104 DirectPlay2WImpl_Send,
5105 DirectPlay2WImpl_SetGroupData,
5106 DirectPlay2WImpl_SetGroupName,
5107 DirectPlay2WImpl_SetPlayerData,
5108 DirectPlay2WImpl_SetPlayerName,
5109 DirectPlay2WImpl_SetSessionDesc
5111 #undef XCAST
5113 /* Note: Hack so we can reuse the old functions without compiler warnings */
5114 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5115 # define XCAST(fun) (typeof(directPlay2AVT.fun))
5116 #else
5117 # define XCAST(fun) (void*)
5118 #endif
5120 static const IDirectPlay2Vtbl directPlay2AVT =
5122 XCAST(QueryInterface)DP_QueryInterface,
5123 XCAST(AddRef)DP_AddRef,
5124 XCAST(Release)DP_Release,
5126 DirectPlay2AImpl_AddPlayerToGroup,
5127 DirectPlay2AImpl_Close,
5128 DirectPlay2AImpl_CreateGroup,
5129 DirectPlay2AImpl_CreatePlayer,
5130 DirectPlay2AImpl_DeletePlayerFromGroup,
5131 DirectPlay2AImpl_DestroyGroup,
5132 DirectPlay2AImpl_DestroyPlayer,
5133 DirectPlay2AImpl_EnumGroupPlayers,
5134 DirectPlay2AImpl_EnumGroups,
5135 DirectPlay2AImpl_EnumPlayers,
5136 DirectPlay2AImpl_EnumSessions,
5137 DirectPlay2AImpl_GetCaps,
5138 DirectPlay2AImpl_GetGroupData,
5139 DirectPlay2AImpl_GetGroupName,
5140 DirectPlay2AImpl_GetMessageCount,
5141 DirectPlay2AImpl_GetPlayerAddress,
5142 DirectPlay2AImpl_GetPlayerCaps,
5143 DirectPlay2AImpl_GetPlayerData,
5144 DirectPlay2AImpl_GetPlayerName,
5145 DirectPlay2AImpl_GetSessionDesc,
5146 DirectPlay2AImpl_Initialize,
5147 DirectPlay2AImpl_Open,
5148 DirectPlay2AImpl_Receive,
5149 DirectPlay2AImpl_Send,
5150 DirectPlay2AImpl_SetGroupData,
5151 DirectPlay2AImpl_SetGroupName,
5152 DirectPlay2AImpl_SetPlayerData,
5153 DirectPlay2AImpl_SetPlayerName,
5154 DirectPlay2AImpl_SetSessionDesc
5156 #undef XCAST
5159 /* Note: Hack so we can reuse the old functions without compiler warnings */
5160 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5161 # define XCAST(fun) (typeof(directPlay3AVT.fun))
5162 #else
5163 # define XCAST(fun) (void*)
5164 #endif
5166 static const IDirectPlay3Vtbl directPlay3AVT =
5168 XCAST(QueryInterface)DP_QueryInterface,
5169 XCAST(AddRef)DP_AddRef,
5170 XCAST(Release)DP_Release,
5172 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
5173 XCAST(Close)DirectPlay2AImpl_Close,
5174 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
5175 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
5176 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
5177 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
5178 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
5179 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
5180 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
5181 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
5182 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
5183 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
5184 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
5185 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
5186 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5187 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5188 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5189 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5190 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5191 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5192 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5193 XCAST(Open)DirectPlay2AImpl_Open,
5194 XCAST(Receive)DirectPlay2AImpl_Receive,
5195 XCAST(Send)DirectPlay2AImpl_Send,
5196 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5197 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5198 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5199 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5200 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5202 DirectPlay3AImpl_AddGroupToGroup,
5203 DirectPlay3AImpl_CreateGroupInGroup,
5204 DirectPlay3AImpl_DeleteGroupFromGroup,
5205 DirectPlay3AImpl_EnumConnections,
5206 DirectPlay3AImpl_EnumGroupsInGroup,
5207 DirectPlay3AImpl_GetGroupConnectionSettings,
5208 DirectPlay3AImpl_InitializeConnection,
5209 DirectPlay3AImpl_SecureOpen,
5210 DirectPlay3AImpl_SendChatMessage,
5211 DirectPlay3AImpl_SetGroupConnectionSettings,
5212 DirectPlay3AImpl_StartSession,
5213 DirectPlay3AImpl_GetGroupFlags,
5214 DirectPlay3AImpl_GetGroupParent,
5215 DirectPlay3AImpl_GetPlayerAccount,
5216 DirectPlay3AImpl_GetPlayerFlags
5218 #undef XCAST
5220 /* Note: Hack so we can reuse the old functions without compiler warnings */
5221 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5222 # define XCAST(fun) (typeof(directPlay3WVT.fun))
5223 #else
5224 # define XCAST(fun) (void*)
5225 #endif
5226 static const IDirectPlay3Vtbl directPlay3WVT =
5228 XCAST(QueryInterface)DP_QueryInterface,
5229 XCAST(AddRef)DP_AddRef,
5230 XCAST(Release)DP_Release,
5232 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
5233 XCAST(Close)DirectPlay2WImpl_Close,
5234 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
5235 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
5236 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
5237 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
5238 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5239 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5240 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5241 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5242 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5243 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5244 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5245 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5246 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5247 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5248 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5249 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5250 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5251 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5252 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5253 XCAST(Open)DirectPlay2WImpl_Open,
5254 XCAST(Receive)DirectPlay2WImpl_Receive,
5255 XCAST(Send)DirectPlay2WImpl_Send,
5256 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5257 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5258 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5259 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5260 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5262 DirectPlay3WImpl_AddGroupToGroup,
5263 DirectPlay3WImpl_CreateGroupInGroup,
5264 DirectPlay3WImpl_DeleteGroupFromGroup,
5265 DirectPlay3WImpl_EnumConnections,
5266 DirectPlay3WImpl_EnumGroupsInGroup,
5267 DirectPlay3WImpl_GetGroupConnectionSettings,
5268 DirectPlay3WImpl_InitializeConnection,
5269 DirectPlay3WImpl_SecureOpen,
5270 DirectPlay3WImpl_SendChatMessage,
5271 DirectPlay3WImpl_SetGroupConnectionSettings,
5272 DirectPlay3WImpl_StartSession,
5273 DirectPlay3WImpl_GetGroupFlags,
5274 DirectPlay3WImpl_GetGroupParent,
5275 DirectPlay3WImpl_GetPlayerAccount,
5276 DirectPlay3WImpl_GetPlayerFlags
5278 #undef XCAST
5280 /* Note: Hack so we can reuse the old functions without compiler warnings */
5281 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5282 # define XCAST(fun) (typeof(directPlay4WVT.fun))
5283 #else
5284 # define XCAST(fun) (void*)
5285 #endif
5286 static const IDirectPlay4Vtbl directPlay4WVT =
5288 XCAST(QueryInterface)DP_QueryInterface,
5289 XCAST(AddRef)DP_AddRef,
5290 XCAST(Release)DP_Release,
5292 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
5293 XCAST(Close)DirectPlay2WImpl_Close,
5294 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
5295 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
5296 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
5297 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
5298 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5299 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5300 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5301 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5302 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5303 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5304 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5305 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5306 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5307 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5308 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5309 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5310 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5311 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5312 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5313 XCAST(Open)DirectPlay2WImpl_Open,
5314 XCAST(Receive)DirectPlay2WImpl_Receive,
5315 XCAST(Send)DirectPlay2WImpl_Send,
5316 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5317 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5318 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5319 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5320 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5322 XCAST(AddGroupToGroup)DirectPlay3WImpl_AddGroupToGroup,
5323 XCAST(CreateGroupInGroup)DirectPlay3WImpl_CreateGroupInGroup,
5324 XCAST(DeleteGroupFromGroup)DirectPlay3WImpl_DeleteGroupFromGroup,
5325 XCAST(EnumConnections)DirectPlay3WImpl_EnumConnections,
5326 XCAST(EnumGroupsInGroup)DirectPlay3WImpl_EnumGroupsInGroup,
5327 XCAST(GetGroupConnectionSettings)DirectPlay3WImpl_GetGroupConnectionSettings,
5328 XCAST(InitializeConnection)DirectPlay3WImpl_InitializeConnection,
5329 XCAST(SecureOpen)DirectPlay3WImpl_SecureOpen,
5330 XCAST(SendChatMessage)DirectPlay3WImpl_SendChatMessage,
5331 XCAST(SetGroupConnectionSettings)DirectPlay3WImpl_SetGroupConnectionSettings,
5332 XCAST(StartSession)DirectPlay3WImpl_StartSession,
5333 XCAST(GetGroupFlags)DirectPlay3WImpl_GetGroupFlags,
5334 XCAST(GetGroupParent)DirectPlay3WImpl_GetGroupParent,
5335 XCAST(GetPlayerAccount)DirectPlay3WImpl_GetPlayerAccount,
5336 XCAST(GetPlayerFlags)DirectPlay3WImpl_GetPlayerFlags,
5338 DirectPlay4WImpl_GetGroupOwner,
5339 DirectPlay4WImpl_SetGroupOwner,
5340 DirectPlay4WImpl_SendEx,
5341 DirectPlay4WImpl_GetMessageQueue,
5342 DirectPlay4WImpl_CancelMessage,
5343 DirectPlay4WImpl_CancelPriority
5345 #undef XCAST
5348 /* Note: Hack so we can reuse the old functions without compiler warnings */
5349 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5350 # define XCAST(fun) (typeof(directPlay4AVT.fun))
5351 #else
5352 # define XCAST(fun) (void*)
5353 #endif
5354 static const IDirectPlay4Vtbl directPlay4AVT =
5356 XCAST(QueryInterface)DP_QueryInterface,
5357 XCAST(AddRef)DP_AddRef,
5358 XCAST(Release)DP_Release,
5360 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
5361 XCAST(Close)DirectPlay2AImpl_Close,
5362 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
5363 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
5364 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
5365 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
5366 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
5367 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
5368 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
5369 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
5370 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
5371 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
5372 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
5373 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
5374 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5375 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5376 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5377 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5378 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5379 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5380 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5381 XCAST(Open)DirectPlay2AImpl_Open,
5382 XCAST(Receive)DirectPlay2AImpl_Receive,
5383 XCAST(Send)DirectPlay2AImpl_Send,
5384 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5385 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5386 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5387 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5388 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5390 XCAST(AddGroupToGroup)DirectPlay3AImpl_AddGroupToGroup,
5391 XCAST(CreateGroupInGroup)DirectPlay3AImpl_CreateGroupInGroup,
5392 XCAST(DeleteGroupFromGroup)DirectPlay3AImpl_DeleteGroupFromGroup,
5393 XCAST(EnumConnections)DirectPlay3AImpl_EnumConnections,
5394 XCAST(EnumGroupsInGroup)DirectPlay3AImpl_EnumGroupsInGroup,
5395 XCAST(GetGroupConnectionSettings)DirectPlay3AImpl_GetGroupConnectionSettings,
5396 XCAST(InitializeConnection)DirectPlay3AImpl_InitializeConnection,
5397 XCAST(SecureOpen)DirectPlay3AImpl_SecureOpen,
5398 XCAST(SendChatMessage)DirectPlay3AImpl_SendChatMessage,
5399 XCAST(SetGroupConnectionSettings)DirectPlay3AImpl_SetGroupConnectionSettings,
5400 XCAST(StartSession)DirectPlay3AImpl_StartSession,
5401 XCAST(GetGroupFlags)DirectPlay3AImpl_GetGroupFlags,
5402 XCAST(GetGroupParent)DirectPlay3AImpl_GetGroupParent,
5403 XCAST(GetPlayerAccount)DirectPlay3AImpl_GetPlayerAccount,
5404 XCAST(GetPlayerFlags)DirectPlay3AImpl_GetPlayerFlags,
5406 DirectPlay4AImpl_GetGroupOwner,
5407 DirectPlay4AImpl_SetGroupOwner,
5408 DirectPlay4AImpl_SendEx,
5409 DirectPlay4AImpl_GetMessageQueue,
5410 DirectPlay4AImpl_CancelMessage,
5411 DirectPlay4AImpl_CancelPriority
5413 #undef XCAST
5415 HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP,
5416 DPID idPlayer,
5417 LPVOID* lplpData )
5419 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5421 if( lpPlayer == NULL )
5423 return DPERR_INVALIDPLAYER;
5426 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
5428 return DP_OK;
5431 HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP,
5432 DPID idPlayer,
5433 LPVOID lpData )
5435 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5437 if( lpPlayer == NULL )
5439 return DPERR_INVALIDPLAYER;
5442 lpPlayer->lpPData->lpSPPlayerData = lpData;
5444 return DP_OK;
5447 /***************************************************************************
5448 * DirectPlayEnumerateAW
5450 * The pointer to the structure lpContext will be filled with the
5451 * appropriate data for each service offered by the OS. These services are
5452 * not necessarily available on this particular machine but are defined
5453 * as simple service providers under the "Service Providers" registry key.
5454 * This structure is then passed to lpEnumCallback for each of the different
5455 * services.
5457 * This API is useful only for applications written using DirectX3 or
5458 * worse. It is superseded by IDirectPlay3::EnumConnections which also
5459 * gives information on the actual connections.
5461 * defn of a service provider:
5462 * A dynamic-link library used by DirectPlay to communicate over a network.
5463 * The service provider contains all the network-specific code required
5464 * to send and receive messages. Online services and network operators can
5465 * supply service providers to use specialized hardware, protocols, communications
5466 * media, and network resources.
5469 static HRESULT DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA,
5470 LPDPENUMDPCALLBACKW lpEnumCallbackW,
5471 LPVOID lpContext)
5473 HKEY hkResult;
5474 static const WCHAR searchSubKey[] = {
5475 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
5476 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
5477 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
5478 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
5479 static const WCHAR guidKey[] = { 'G', 'u', 'i', 'd', 0 };
5480 static const WCHAR descW[] = { 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', 'W', 0 };
5482 DWORD dwIndex;
5483 FILETIME filetime;
5485 char *descriptionA = NULL;
5486 DWORD max_sizeOfDescriptionA = 0;
5487 WCHAR *descriptionW = NULL;
5488 DWORD max_sizeOfDescriptionW = 0;
5490 if (!lpEnumCallbackA && !lpEnumCallbackW)
5492 return DPERR_INVALIDPARAMS;
5495 /* Need to loop over the service providers in the registry */
5496 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, searchSubKey,
5497 0, KEY_READ, &hkResult) != ERROR_SUCCESS)
5499 /* Hmmm. Does this mean that there are no service providers? */
5500 ERR(": no service provider key in the registry - check your Wine installation !!!\n");
5501 return DPERR_GENERIC;
5504 /* Traverse all the service providers we have available */
5505 dwIndex = 0;
5506 while (1)
5508 WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */
5509 DWORD sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR);
5510 HKEY hkServiceProvider;
5511 GUID serviceProviderGUID;
5512 WCHAR guidKeyContent[(2 * 16) + 1 + 6 /* This corresponds to '{....-..-..-..-......}' */ ];
5513 DWORD sizeOfGuidKeyContent = sizeof(guidKeyContent);
5514 LONG ret_value;
5516 ret_value = RegEnumKeyExW(hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
5517 NULL, NULL, NULL, &filetime);
5518 if (ret_value == ERROR_NO_MORE_ITEMS)
5519 break;
5520 else if (ret_value != ERROR_SUCCESS)
5522 ERR(": could not enumerate on service provider key.\n");
5523 return DPERR_EXCEPTION;
5525 TRACE(" this time through sub-key %s.\n", debugstr_w(subKeyName));
5527 /* Open the key for this service provider */
5528 if (RegOpenKeyExW(hkResult, subKeyName, 0, KEY_READ, &hkServiceProvider) != ERROR_SUCCESS)
5530 ERR(": could not open registry key for service provider %s.\n", debugstr_w(subKeyName));
5531 continue;
5534 /* Get the GUID from the registry */
5535 if (RegQueryValueExW(hkServiceProvider, guidKey,
5536 NULL, NULL, (LPBYTE) guidKeyContent, &sizeOfGuidKeyContent) != ERROR_SUCCESS)
5538 ERR(": missing GUID registry data member for service provider %s.\n", debugstr_w(subKeyName));
5539 continue;
5541 if (sizeOfGuidKeyContent != sizeof(guidKeyContent))
5543 ERR(": invalid format for the GUID registry data member for service provider %s (%s).\n", debugstr_w(subKeyName), debugstr_w(guidKeyContent));
5544 continue;
5546 CLSIDFromString(guidKeyContent, &serviceProviderGUID );
5548 /* The enumeration will return FALSE if we are not to continue.
5550 * Note: on my windows box, major / minor version is 6 / 0 for all service providers
5551 * and have no relation to any of the two dwReserved1 and dwReserved2 keys.
5552 * I think that it simply means that they are in-line with DirectX 6.0
5554 if (lpEnumCallbackA)
5556 DWORD sizeOfDescription = 0;
5558 /* Note that this is the A case of this function, so use the A variant to get the description string */
5559 if (RegQueryValueExA(hkServiceProvider, "DescriptionA",
5560 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5562 ERR(": missing 'DescriptionA' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5563 continue;
5565 if (sizeOfDescription > max_sizeOfDescriptionA)
5567 HeapFree(GetProcessHeap(), 0, descriptionA);
5568 max_sizeOfDescriptionA = sizeOfDescription;
5570 descriptionA = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5571 RegQueryValueExA(hkServiceProvider, "DescriptionA",
5572 NULL, NULL, (LPBYTE) descriptionA, &sizeOfDescription);
5574 if (!lpEnumCallbackA(&serviceProviderGUID, descriptionA, 6, 0, lpContext))
5575 goto end;
5577 else
5579 DWORD sizeOfDescription = 0;
5581 if (RegQueryValueExW(hkServiceProvider, descW,
5582 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5584 ERR(": missing 'DescriptionW' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5585 continue;
5587 if (sizeOfDescription > max_sizeOfDescriptionW)
5589 HeapFree(GetProcessHeap(), 0, descriptionW);
5590 max_sizeOfDescriptionW = sizeOfDescription;
5592 descriptionW = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5593 RegQueryValueExW(hkServiceProvider, descW,
5594 NULL, NULL, (LPBYTE) descriptionW, &sizeOfDescription);
5596 if (!lpEnumCallbackW(&serviceProviderGUID, descriptionW, 6, 0, lpContext))
5597 goto end;
5600 dwIndex++;
5603 end:
5604 HeapFree(GetProcessHeap(), 0, descriptionA);
5605 HeapFree(GetProcessHeap(), 0, descriptionW);
5607 return DP_OK;
5610 /***************************************************************************
5611 * DirectPlayEnumerate [DPLAYX.9]
5612 * DirectPlayEnumerateA [DPLAYX.2]
5614 HRESULT WINAPI DirectPlayEnumerateA(LPDPENUMDPCALLBACKA lpEnumCallback, LPVOID lpContext )
5616 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5618 return DirectPlayEnumerateAW(lpEnumCallback, NULL, lpContext);
5621 /***************************************************************************
5622 * DirectPlayEnumerateW [DPLAYX.3]
5624 HRESULT WINAPI DirectPlayEnumerateW(LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5626 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5628 return DirectPlayEnumerateAW(NULL, lpEnumCallback, lpContext);
5631 typedef struct tagCreateEnum
5633 LPVOID lpConn;
5634 LPCGUID lpGuid;
5635 } CreateEnumData, *lpCreateEnumData;
5637 /* Find and copy the matching connection for the SP guid */
5638 static BOOL CALLBACK cbDPCreateEnumConnections(
5639 LPCGUID lpguidSP,
5640 LPVOID lpConnection,
5641 DWORD dwConnectionSize,
5642 LPCDPNAME lpName,
5643 DWORD dwFlags,
5644 LPVOID lpContext)
5646 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5648 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5650 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5652 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5653 dwConnectionSize );
5654 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5656 /* Found the record that we were looking for */
5657 return FALSE;
5660 /* Haven't found what were looking for yet */
5661 return TRUE;
5665 /***************************************************************************
5666 * DirectPlayCreate [DPLAYX.1]
5669 HRESULT WINAPI DirectPlayCreate
5670 ( LPGUID lpGUID, LPDIRECTPLAY *lplpDP, IUnknown *pUnk )
5672 HRESULT hr;
5673 LPDIRECTPLAY3A lpDP3A;
5674 CreateEnumData cbData;
5676 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5678 if( pUnk != NULL )
5680 return CLASS_E_NOAGGREGATION;
5683 if( (lplpDP == NULL) || (lpGUID == NULL) )
5685 return DPERR_INVALIDPARAMS;
5689 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5690 give them an IDirectPlay2A object and hope that doesn't cause problems */
5691 if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
5693 return DPERR_UNAVAILABLE;
5696 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
5698 /* The GUID_NULL means don't bind a service provider. Just return the
5699 interface as is */
5700 return DP_OK;
5703 /* Bind the desired service provider since lpGUID is non NULL */
5704 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
5706 /* We're going to use a DP3 interface */
5707 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
5708 (LPVOID*)&lpDP3A );
5709 if( FAILED(hr) )
5711 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
5712 return hr;
5715 cbData.lpConn = NULL;
5716 cbData.lpGuid = lpGUID;
5718 /* We were given a service provider, find info about it... */
5719 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
5720 &cbData, DPCONNECTION_DIRECTPLAY );
5721 if( ( FAILED(hr) ) ||
5722 ( cbData.lpConn == NULL )
5725 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
5726 IDirectPlayX_Release( lpDP3A );
5727 return DPERR_UNAVAILABLE;
5730 /* Initialize the service provider */
5731 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
5732 if( FAILED(hr) )
5734 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
5735 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5736 IDirectPlayX_Release( lpDP3A );
5737 return hr;
5740 /* Release our version of the interface now that we're done with it */
5741 IDirectPlayX_Release( lpDP3A );
5742 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5744 return DP_OK;