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
21 #include "wine/port.h"
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
34 #include "wine/unicode.h"
35 #include "wine/debug.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 lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid );
54 static lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* iface, LPDPID lpid,
55 LPDPNAME lpName, DWORD dwFlags,
56 HANDLE hEvent, BOOL bAnsi );
57 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, const DPNAME *lpSrc, BOOL bAnsi );
58 static void DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
59 LPVOID lpData, DWORD dwDataSize );
61 static lpGroupData DP_CreateGroup( IDirectPlay2AImpl* iface, const DPID *lpid,
62 const DPNAME *lpName, DWORD dwFlags,
63 DPID idParent, BOOL bAnsi );
64 static void DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
65 LPVOID lpData, DWORD dwDataSize );
66 static void DP_DeleteDPNameStruct( LPDPNAME lpDPName );
67 static void DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid );
68 static BOOL CALLBACK cbDeletePlayerFromAllGroups( DPID dpId,
73 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid );
74 static BOOL CALLBACK cbRemoveGroupOrPlayer( DPID dpId, DWORD dwPlayerType,
75 LPCDPNAME lpName, DWORD dwFlags,
77 static void DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid );
79 /* Forward declarations of virtual tables */
80 static const IDirectPlay2Vtbl directPlay2AVT;
81 static const IDirectPlay3Vtbl directPlay3AVT;
82 static const IDirectPlay4Vtbl directPlay4AVT;
84 static const IDirectPlay2Vtbl directPlay2WVT;
85 static const IDirectPlay3Vtbl directPlay3WVT;
86 static const IDirectPlay4Vtbl directPlay4WVT;
88 /* Helper methods for player/group interfaces */
89 static HRESULT DP_IF_DeletePlayerFromGroup
90 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
91 DPID idPlayer, BOOL bAnsi );
92 static HRESULT DP_IF_CreatePlayer
93 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, LPDPID lpidPlayer,
94 LPDPNAME lpPlayerName, HANDLE hEvent, LPVOID lpData,
95 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
96 static HRESULT DP_IF_DestroyGroup
97 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi );
98 static HRESULT DP_IF_DestroyPlayer
99 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi );
100 static HRESULT DP_IF_EnumGroupPlayers
101 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
102 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
103 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
104 static HRESULT DP_IF_EnumGroups
105 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
106 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
107 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
108 static HRESULT DP_IF_EnumPlayers
109 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
110 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
111 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
112 static HRESULT DP_IF_GetGroupData
113 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
114 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
115 static HRESULT DP_IF_GetGroupName
116 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
117 LPDWORD lpdwDataSize, BOOL bAnsi );
118 static HRESULT DP_IF_GetPlayerData
119 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
120 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
121 static HRESULT DP_IF_GetPlayerName
122 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
123 LPDWORD lpdwDataSize, BOOL bAnsi );
124 static HRESULT DP_IF_SetGroupName
125 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
126 DWORD dwFlags, BOOL bAnsi );
127 static HRESULT DP_IF_SetPlayerData
128 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
129 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
130 static HRESULT DP_IF_SetPlayerName
131 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
132 DWORD dwFlags, BOOL bAnsi );
133 static HRESULT DP_IF_AddGroupToGroup
134 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
135 static HRESULT DP_IF_CreateGroup
136 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
137 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
138 DWORD dwFlags, BOOL bAnsi );
139 static HRESULT DP_IF_CreateGroupInGroup
140 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
141 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
142 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
143 static HRESULT DP_IF_AddPlayerToGroup
144 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
145 DPID idPlayer, BOOL bAnsi );
146 static HRESULT DP_IF_DeleteGroupFromGroup
147 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
148 static HRESULT DP_SetSessionDesc
149 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
150 DWORD dwFlags, BOOL bInitial, BOOL bAnsi );
151 static HRESULT DP_SecureOpen
152 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
153 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
155 static HRESULT DP_SendEx
156 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
157 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
158 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi );
159 static HRESULT DP_IF_Receive
160 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
161 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi );
162 static HRESULT DP_IF_GetMessageQueue
163 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
164 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi );
165 static HRESULT DP_SP_SendEx
166 ( IDirectPlay2Impl* This, DWORD dwFlags,
167 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
168 LPVOID lpContext, LPDWORD lpdwMsgID );
169 static HRESULT DP_IF_SetGroupData
170 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
171 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
172 static HRESULT DP_IF_GetPlayerCaps
173 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
175 static HRESULT DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi );
176 static HRESULT DP_IF_CancelMessage
177 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
178 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi );
179 static HRESULT DP_IF_EnumGroupsInGroup
180 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
181 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
182 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
183 static HRESULT DP_IF_GetGroupParent
184 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
186 static HRESULT DP_IF_GetCaps
187 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags );
188 static HRESULT DP_IF_EnumSessions
189 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
190 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
191 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
192 static HRESULT DP_IF_InitializeConnection
193 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi );
194 static BOOL CALLBACK cbDPCreateEnumConnections( LPCGUID lpguidSP,
195 LPVOID lpConnection, DWORD dwConnectionSize, LPCDPNAME lpName,
196 DWORD dwFlags, LPVOID lpContext );
197 static BOOL DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
198 LPDWORD lpdwBufSize );
202 static inline DPID DP_NextObjectId(void);
203 static DPID DP_GetRemoteNextObjectId(void);
205 static DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi );
206 static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc,
207 LPCDPSESSIONDESC2 srcSessDesc, BOOL bAnsi );
210 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp );
211 static HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider );
212 static HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hServiceProvider );
219 #define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */
220 #define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported
221 we don't have to change much */
222 #define DPID_NAME_SERVER 0x19a9d65b /* Don't ask me why */
224 /* Strip out dwFlag values which cannot be sent in the CREATEGROUP msg */
225 #define DPMSG_CREATEGROUP_DWFLAGS(x) ( (x) & DPGROUP_HIDDEN )
227 /* Strip out all dwFlags values for CREATEPLAYER msg */
228 #define DPMSG_CREATEPLAYER_DWFLAGS(x) 0
230 static LONG kludgePlayerGroupId = 1000;
232 /* ------------------------------------------------------------------ */
235 static BOOL DP_CreateIUnknown( LPVOID lpDP )
237 IDirectPlay2AImpl *This = lpDP;
239 This->unk = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->unk) ) );
240 if ( This->unk == NULL )
245 InitializeCriticalSection( &This->unk->DP_lock );
246 This->unk->DP_lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectPlay2AImpl*->DirectPlayIUnknownData*->DP_lock");
251 static BOOL DP_DestroyIUnknown( LPVOID lpDP )
253 IDirectPlay2AImpl *This = lpDP;
255 This->unk->DP_lock.DebugInfo->Spare[0] = 0;
256 DeleteCriticalSection( &This->unk->DP_lock );
257 HeapFree( GetProcessHeap(), 0, This->unk );
262 static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
264 IDirectPlay2AImpl *This = lpDP;
266 This->dp2 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp2) ) );
267 if ( This->dp2 == NULL )
272 This->dp2->bConnectionOpen = FALSE;
274 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
275 This->dp2->dwEnumSessionLock = 0;
277 This->dp2->bHostInterface = FALSE;
279 DPQ_INIT(This->dp2->receiveMsgs);
280 DPQ_INIT(This->dp2->sendMsgs);
281 DPQ_INIT(This->dp2->replysExpected);
283 if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
285 /* FIXME: Memory leak */
289 /* Provide an initial session desc with nothing in it */
290 This->dp2->lpSessionDesc = HeapAlloc( GetProcessHeap(),
292 sizeof( *This->dp2->lpSessionDesc ) );
293 if( This->dp2->lpSessionDesc == NULL )
295 /* FIXME: Memory leak */
298 This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc );
300 /* We are emulating a dp 6 implementation */
301 This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION;
303 This->dp2->spData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
304 sizeof( *This->dp2->spData.lpCB ) );
305 This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB );
306 This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION;
308 /* This is the pointer to the service provider */
309 if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP,
310 (LPVOID*)&This->dp2->spData.lpISP, This ) )
313 /* FIXME: Memory leak */
317 /* Setup lobby provider information */
318 This->dp2->dplspData.dwSPVersion = DPSP_MAJORVERSION;
319 This->dp2->dplspData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
320 sizeof( *This->dp2->dplspData.lpCB ) );
321 This->dp2->dplspData.lpCB->dwSize = sizeof( *This->dp2->dplspData.lpCB );
323 if( FAILED( DPLSP_CreateInterface( &IID_IDPLobbySP,
324 (LPVOID*)&This->dp2->dplspData.lpISP, This ) )
327 /* FIXME: Memory leak */
334 /* Definition of the global function in dplayx_queue.h. #
335 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
336 DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
338 HeapFree( GetProcessHeap(), 0, elem );
341 /* Function to delete the list of groups with this interface. Needs to
342 * delete the group and player lists associated with this group as well
343 * as the group data associated with this group. It should not delete
344 * player data as that is shared with the top player list and will be
347 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList );
348 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList )
350 DPQ_DELETEQ( elem->lpGData->groups, groups,
351 lpGroupList, cbDeleteElemFromHeap );
352 DPQ_DELETEQ( elem->lpGData->players, players,
353 lpPlayerList, cbDeleteElemFromHeap );
354 HeapFree( GetProcessHeap(), 0, elem->lpGData );
355 HeapFree( GetProcessHeap(), 0, elem );
358 /* Function to delete the list of players with this interface. Needs to
359 * delete the player data for all players as well.
361 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList );
362 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList )
364 HeapFree( GetProcessHeap(), 0, elem->lpPData );
365 HeapFree( GetProcessHeap(), 0, elem );
368 static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
370 IDirectPlay2AImpl *This = lpDP;
372 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
374 TerminateThread( This->dp2->hEnumSessionThread, 0 );
375 CloseHandle( This->dp2->hEnumSessionThread );
378 /* Finish with the SP - have it shutdown */
379 if( This->dp2->spData.lpCB->ShutdownEx )
381 DPSP_SHUTDOWNDATA data;
383 TRACE( "Calling SP ShutdownEx\n" );
385 data.lpISP = This->dp2->spData.lpISP;
387 (*This->dp2->spData.lpCB->ShutdownEx)( &data );
389 else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
391 TRACE( "Calling obsolete SP Shutdown\n" );
392 (*This->dp2->spData.lpCB->Shutdown)();
395 /* Unload the SP (if it exists) */
396 if( This->dp2->hServiceProvider != 0 )
398 FreeLibrary( This->dp2->hServiceProvider );
401 /* Unload the Lobby Provider (if it exists) */
402 if( This->dp2->hDPLobbyProvider != 0 )
404 FreeLibrary( This->dp2->hDPLobbyProvider );
408 DPQ_DELETEQ( This->dp2->players, players, lpPlayerList, cbDeletePlayerElem );
409 DPQ_DELETEQ( This->dp2->groups, groups, lpGroupList, cbDeleteGroupsElem );
412 /* FIXME: Need to delete receive and send msgs queue contents */
414 NS_DeleteSessionCache( This->dp2->lpNameServerData );
416 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
418 IDirectPlaySP_Release( This->dp2->spData.lpISP );
420 /* Delete the contents */
421 HeapFree( GetProcessHeap(), 0, This->dp2 );
426 static BOOL DP_CreateDirectPlay3( LPVOID lpDP )
428 IDirectPlay3AImpl *This = lpDP;
430 This->dp3 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp3) ) );
431 if ( This->dp3 == NULL )
439 static BOOL DP_DestroyDirectPlay3( LPVOID lpDP )
441 IDirectPlay3AImpl *This = lpDP;
443 /* Delete the contents */
444 HeapFree( GetProcessHeap(), 0, This->dp3 );
449 static BOOL DP_CreateDirectPlay4( LPVOID lpDP )
451 IDirectPlay4AImpl *This = lpDP;
453 This->dp4 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp4) ) );
454 if ( This->dp4 == NULL )
462 static BOOL DP_DestroyDirectPlay4( LPVOID lpDP )
464 IDirectPlay3AImpl *This = lpDP;
466 /* Delete the contents */
467 HeapFree( GetProcessHeap(), 0, This->dp4 );
473 /* Create a new interface */
474 HRESULT DP_CreateInterface
475 ( REFIID riid, LPVOID* ppvObj )
477 TRACE( " for %s\n", debugstr_guid( riid ) );
479 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
480 sizeof( IDirectPlay2Impl ) );
482 if( *ppvObj == NULL )
484 return DPERR_OUTOFMEMORY;
487 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
489 IDirectPlay2Impl *This = *ppvObj;
490 This->lpVtbl = &directPlay2WVT;
492 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
494 IDirectPlay2AImpl *This = *ppvObj;
495 This->lpVtbl = &directPlay2AVT;
497 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
499 IDirectPlay3Impl *This = *ppvObj;
500 This->lpVtbl = &directPlay3WVT;
502 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
504 IDirectPlay3AImpl *This = *ppvObj;
505 This->lpVtbl = &directPlay3AVT;
507 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
509 IDirectPlay4Impl *This = *ppvObj;
510 This->lpVtbl = &directPlay4WVT;
512 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
514 IDirectPlay4AImpl *This = *ppvObj;
515 This->lpVtbl = &directPlay4AVT;
519 /* Unsupported interface */
520 HeapFree( GetProcessHeap(), 0, *ppvObj );
523 return E_NOINTERFACE;
527 if ( DP_CreateIUnknown( *ppvObj ) &&
528 DP_CreateDirectPlay2( *ppvObj ) &&
529 DP_CreateDirectPlay3( *ppvObj ) &&
530 DP_CreateDirectPlay4( *ppvObj )
533 IDirectPlayX_AddRef( (LPDIRECTPLAY2A)*ppvObj );
538 /* Initialize failed, destroy it */
539 DP_DestroyDirectPlay4( *ppvObj );
540 DP_DestroyDirectPlay3( *ppvObj );
541 DP_DestroyDirectPlay2( *ppvObj );
542 DP_DestroyIUnknown( *ppvObj );
544 HeapFree( GetProcessHeap(), 0, *ppvObj );
547 return DPERR_NOMEMORY;
551 /* Direct Play methods */
553 /* Shared between all dplay types */
554 static HRESULT WINAPI DP_QueryInterface
555 ( LPDIRECTPLAY2 iface, REFIID riid, LPVOID* ppvObj )
557 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
558 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
560 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
563 if( *ppvObj == NULL )
565 return DPERR_OUTOFMEMORY;
568 CopyMemory( *ppvObj, This, sizeof( *This ) );
569 (*(IDirectPlay2Impl**)ppvObj)->ulInterfaceRef = 0;
571 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
573 IDirectPlay2Impl *This = *ppvObj;
574 This->lpVtbl = &directPlay2WVT;
576 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
578 IDirectPlay2AImpl *This = *ppvObj;
579 This->lpVtbl = &directPlay2AVT;
581 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
583 IDirectPlay3Impl *This = *ppvObj;
584 This->lpVtbl = &directPlay3WVT;
586 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
588 IDirectPlay3AImpl *This = *ppvObj;
589 This->lpVtbl = &directPlay3AVT;
591 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
593 IDirectPlay4Impl *This = *ppvObj;
594 This->lpVtbl = &directPlay4WVT;
596 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
598 IDirectPlay4AImpl *This = *ppvObj;
599 This->lpVtbl = &directPlay4AVT;
603 /* Unsupported interface */
604 HeapFree( GetProcessHeap(), 0, *ppvObj );
607 return E_NOINTERFACE;
610 IDirectPlayX_AddRef( (LPDIRECTPLAY2)*ppvObj );
615 /* Shared between all dplay types */
616 static ULONG WINAPI DP_AddRef
617 ( LPDIRECTPLAY3 iface )
619 ULONG ulInterfaceRefCount, ulObjRefCount;
620 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
622 ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
623 ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
625 TRACE( "ref count incremented to %u:%u for %p\n",
626 ulInterfaceRefCount, ulObjRefCount, This );
628 return ulObjRefCount;
631 static ULONG WINAPI DP_Release
632 ( LPDIRECTPLAY3 iface )
634 ULONG ulInterfaceRefCount, ulObjRefCount;
636 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
638 ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
639 ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
641 TRACE( "ref count decremented to %u:%u for %p\n",
642 ulInterfaceRefCount, ulObjRefCount, This );
644 /* Deallocate if this is the last reference to the object */
645 if( ulObjRefCount == 0 )
647 /* If we're destroying the object, this must be the last ref
648 of the last interface */
649 DP_DestroyDirectPlay4( This );
650 DP_DestroyDirectPlay3( This );
651 DP_DestroyDirectPlay2( This );
652 DP_DestroyIUnknown( This );
655 /* Deallocate the interface */
656 if( ulInterfaceRefCount == 0 )
658 HeapFree( GetProcessHeap(), 0, This );
661 return ulObjRefCount;
664 static inline DPID DP_NextObjectId(void)
666 return (DPID)InterlockedIncrement( &kludgePlayerGroupId );
669 /* *lplpReply will be non NULL iff there is something to reply */
670 HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpcMessageBody,
671 DWORD dwMessageBodySize, LPCVOID lpcMessageHeader,
672 WORD wCommandId, WORD wVersion,
673 LPVOID* lplpReply, LPDWORD lpdwMsgSize )
675 TRACE( "(%p)->(%p,0x%08x,%p,%u,%u)\n",
676 This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId,
681 /* Name server needs to handle this request */
682 case DPMSGCMD_ENUMSESSIONSREQUEST:
685 NS_ReplyToEnumSessionsRequest( lpcMessageBody, lplpReply, lpdwMsgSize, This );
690 /* Name server needs to handle this request */
691 case DPMSGCMD_ENUMSESSIONSREPLY:
693 /* No reply expected */
694 NS_AddRemoteComputerAsNameServer( lpcMessageHeader,
695 This->dp2->spData.dwSPHeaderSize,
697 This->dp2->lpNameServerData );
701 case DPMSGCMD_REQUESTNEWPLAYERID:
703 LPCDPMSG_REQUESTNEWPLAYERID lpcMsg = lpcMessageBody;
705 LPDPMSG_NEWPLAYERIDREPLY lpReply;
707 *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
709 *lplpReply = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, *lpdwMsgSize );
711 FIXME( "Ignoring dwFlags 0x%08x in request msg\n",
714 /* Setup the reply */
715 lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) +
716 This->dp2->spData.dwSPHeaderSize );
718 lpReply->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
719 lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY;
720 lpReply->envelope.wVersion = DPMSGVER_DP6;
722 lpReply->dpidNewPlayerId = DP_NextObjectId();
724 TRACE( "Allocating new playerid 0x%08x from remote request\n",
725 lpReply->dpidNewPlayerId );
730 case DPMSGCMD_GETNAMETABLEREPLY:
731 case DPMSGCMD_NEWPLAYERIDREPLY:
735 if( wCommandId == DPMSGCMD_NEWPLAYERIDREPLY )
738 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
744 case DPMSGCMD_JUSTENVELOPE:
746 TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08x\n", lpcMessageHeader, ((const DWORD *)lpcMessageHeader)[1] );
747 NS_SetLocalAddr( This->dp2->lpNameServerData, lpcMessageHeader, 20 );
748 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
752 case DPMSGCMD_FORWARDADDPLAYER:
758 TRACE( "Sending message to self to get my addr\n" );
759 DP_MSG_ToSelf( This, 1 ); /* This is a hack right now */
764 case DPMSGCMD_FORWARDADDPLAYERNACK:
766 DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
772 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
778 /* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */
784 static HRESULT DP_IF_AddPlayerToGroup
785 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
786 DPID idPlayer, BOOL bAnsi )
789 lpPlayerList lpPList;
790 lpPlayerList lpNewPList;
792 TRACE( "(%p)->(%p,0x%08x,0x%08x,%u)\n",
793 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
795 if( This->dp2->connectionInitialized == NO_PROVIDER )
797 return DPERR_UNINITIALIZED;
801 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
803 return DPERR_INVALIDGROUP;
806 /* Find the player */
807 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
809 return DPERR_INVALIDPLAYER;
812 /* Create a player list (ie "shortcut" ) */
813 lpNewPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewPList ) );
814 if( lpNewPList == NULL )
816 return DPERR_CANTADDPLAYER;
819 /* Add the shortcut */
820 lpPList->lpPData->uRef++;
821 lpNewPList->lpPData = lpPList->lpPData;
823 /* Add the player to the list of players for this group */
824 DPQ_INSERT(lpGData->players,lpNewPList,players);
826 /* Let the SP know that we've added a player to the group */
827 if( This->dp2->spData.lpCB->AddPlayerToGroup )
829 DPSP_ADDPLAYERTOGROUPDATA data;
831 TRACE( "Calling SP AddPlayerToGroup\n" );
833 data.idPlayer = idPlayer;
834 data.idGroup = idGroup;
835 data.lpISP = This->dp2->spData.lpISP;
837 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
840 /* Inform all other peers of the addition of player to the group. If there are
841 * no peers keep this event quiet.
842 * Also, if this event was the result of another machine sending it to us,
843 * don't bother rebroadcasting it.
845 if( ( lpMsgHdr == NULL ) &&
846 This->dp2->lpSessionDesc &&
847 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
849 DPMSG_ADDPLAYERTOGROUP msg;
850 msg.dwType = DPSYS_ADDPLAYERTOGROUP;
852 msg.dpIdGroup = idGroup;
853 msg.dpIdPlayer = idPlayer;
855 /* FIXME: Correct to just use send effectively? */
856 /* FIXME: Should size include data w/ message or just message "header" */
857 /* FIXME: Check return code */
858 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
864 static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
865 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
867 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
868 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, TRUE );
871 static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
872 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
874 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
875 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, FALSE );
878 static HRESULT DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi )
882 TRACE("(%p)->(%u)\n", This, bAnsi );
884 /* FIXME: Need to find a new host I assume (how?) */
885 /* FIXME: Need to destroy all local groups */
886 /* FIXME: Need to migrate all remotely visible players to the new host */
888 /* Invoke the SP callback to inform of session close */
889 if( This->dp2->spData.lpCB->CloseEx )
893 TRACE( "Calling SP CloseEx\n" );
895 data.lpISP = This->dp2->spData.lpISP;
897 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
900 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
902 TRACE( "Calling SP Close (obsolete interface)\n" );
904 hr = (*This->dp2->spData.lpCB->Close)();
910 static HRESULT WINAPI DirectPlay2AImpl_Close
911 ( LPDIRECTPLAY2A iface )
913 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
914 return DP_IF_Close( This, TRUE );
917 static HRESULT WINAPI DirectPlay2WImpl_Close
918 ( LPDIRECTPLAY2 iface )
920 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
921 return DP_IF_Close( This, FALSE );
925 lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, const DPID *lpid,
926 const DPNAME *lpName, DWORD dwFlags,
927 DPID idParent, BOOL bAnsi )
931 /* Allocate the new space and add to end of high level group list */
932 lpGData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGData ) );
934 if( lpGData == NULL )
939 DPQ_INIT(lpGData->groups);
940 DPQ_INIT(lpGData->players);
942 /* Set the desired player ID - no sanity checking to see if it exists */
943 lpGData->dpid = *lpid;
945 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
947 /* FIXME: Should we check that the parent exists? */
948 lpGData->parent = idParent;
950 /* FIXME: Should we validate the dwFlags? */
951 lpGData->dwFlags = dwFlags;
953 TRACE( "Created group id 0x%08x\n", *lpid );
958 /* This method assumes that all links to it are already deleted */
960 DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid )
964 TRACE( "(%p)->(0x%08x)\n", This, dpid );
966 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
968 if( lpGList == NULL )
970 ERR( "DPID 0x%08x not found\n", dpid );
974 if( --(lpGList->lpGData->uRef) )
976 FIXME( "Why is this not the last reference to group?\n" );
981 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
982 HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
984 /* Remove and Delete Player List object */
985 HeapFree( GetProcessHeap(), 0, lpGList );
989 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid )
991 lpGroupList lpGroups;
993 TRACE( "(%p)->(0x%08x)\n", This, dpid );
995 if( dpid == DPID_SYSTEM_GROUP )
997 return This->dp2->lpSysGroup;
1001 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
1004 if( lpGroups == NULL )
1009 return lpGroups->lpGData;
1012 static HRESULT DP_IF_CreateGroup
1013 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
1014 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
1015 DWORD dwFlags, BOOL bAnsi )
1017 lpGroupData lpGData;
1019 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1020 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
1023 if( This->dp2->connectionInitialized == NO_PROVIDER )
1025 return DPERR_UNINITIALIZED;
1028 /* If the name is not specified, we must provide one */
1029 if( DPID_UNKNOWN == *lpidGroup )
1031 /* If we are the name server, we decide on the group ids. If not, we
1032 * must ask for one before attempting a creation.
1034 if( This->dp2->bHostInterface )
1036 *lpidGroup = DP_NextObjectId();
1040 *lpidGroup = DP_GetRemoteNextObjectId();
1044 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
1045 DPID_NOPARENT_GROUP, bAnsi );
1047 if( lpGData == NULL )
1049 return DPERR_CANTADDPLAYER; /* yes player not group */
1052 if( DPID_SYSTEM_GROUP == *lpidGroup )
1054 This->dp2->lpSysGroup = lpGData;
1055 TRACE( "Inserting system group\n" );
1059 /* Insert into the system group */
1060 lpGroupList lpGroup = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGroup ) );
1061 lpGroup->lpGData = lpGData;
1063 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
1066 /* Something is now referencing this data */
1069 /* Set all the important stuff for the group */
1070 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
1072 /* FIXME: We should only create the system group if GetCaps returns
1073 * DPCAPS_GROUPOPTIMIZED.
1076 /* Let the SP know that we've created this group */
1077 if( This->dp2->spData.lpCB->CreateGroup )
1079 DPSP_CREATEGROUPDATA data;
1080 DWORD dwCreateFlags = 0;
1082 TRACE( "Calling SP CreateGroup\n" );
1084 if( *lpidGroup == DPID_NOPARENT_GROUP )
1085 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
1087 if( lpMsgHdr == NULL )
1088 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1090 if( dwFlags & DPGROUP_HIDDEN )
1091 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
1093 data.idGroup = *lpidGroup;
1094 data.dwFlags = dwCreateFlags;
1095 data.lpSPMessageHeader = lpMsgHdr;
1096 data.lpISP = This->dp2->spData.lpISP;
1098 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1101 /* Inform all other peers of the creation of a new group. If there are
1102 * no peers keep this event quiet.
1103 * Also if this message was sent to us, don't rebroadcast.
1105 if( ( lpMsgHdr == NULL ) &&
1106 This->dp2->lpSessionDesc &&
1107 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1109 DPMSG_CREATEPLAYERORGROUP msg;
1110 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1112 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1113 msg.dpId = *lpidGroup;
1114 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1115 msg.lpData = lpData;
1116 msg.dwDataSize = dwDataSize;
1117 msg.dpnName = *lpGroupName;
1118 msg.dpIdParent = DPID_NOPARENT_GROUP;
1119 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
1121 /* FIXME: Correct to just use send effectively? */
1122 /* FIXME: Should size include data w/ message or just message "header" */
1123 /* FIXME: Check return code */
1124 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
1125 0, 0, NULL, NULL, bAnsi );
1131 static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
1132 ( LPDIRECTPLAY2A iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1133 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1135 *lpidGroup = DPID_UNKNOWN;
1137 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1138 lpGroupName, lpData, dwDataSize, dwFlags, TRUE );
1141 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
1142 ( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1143 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1145 *lpidGroup = DPID_UNKNOWN;
1147 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1148 lpGroupName, lpData, dwDataSize, dwFlags, FALSE );
1153 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
1154 LPVOID lpData, DWORD dwDataSize )
1156 /* Clear out the data with this player */
1157 if( dwFlags & DPSET_LOCAL )
1159 if ( lpGData->dwLocalDataSize != 0 )
1161 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
1162 lpGData->lpLocalData = NULL;
1163 lpGData->dwLocalDataSize = 0;
1168 if( lpGData->dwRemoteDataSize != 0 )
1170 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
1171 lpGData->lpRemoteData = NULL;
1172 lpGData->dwRemoteDataSize = 0;
1176 /* Reallocate for new data */
1177 if( lpData != NULL )
1179 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1180 sizeof( dwDataSize ) );
1181 CopyMemory( lpNewData, lpData, dwDataSize );
1183 if( dwFlags & DPSET_LOCAL )
1185 lpGData->lpLocalData = lpData;
1186 lpGData->dwLocalDataSize = dwDataSize;
1190 lpGData->lpRemoteData = lpNewData;
1191 lpGData->dwRemoteDataSize = dwDataSize;
1197 /* This function will just create the storage for the new player. */
1199 lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid,
1200 LPDPNAME lpName, DWORD dwFlags,
1201 HANDLE hEvent, BOOL bAnsi )
1203 lpPlayerData lpPData;
1205 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
1207 /* Allocate the storage for the player and associate it with list element */
1208 lpPData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPData ) );
1209 if( lpPData == NULL )
1214 /* Set the desired player ID */
1215 lpPData->dpid = *lpid;
1217 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
1219 lpPData->dwFlags = dwFlags;
1221 /* If we were given an event handle, duplicate it */
1224 if( !DuplicateHandle( GetCurrentProcess(), hEvent,
1225 GetCurrentProcess(), &lpPData->hEvent,
1226 0, FALSE, DUPLICATE_SAME_ACCESS )
1229 /* FIXME: Memory leak */
1230 ERR( "Can't duplicate player msg handle %p\n", hEvent );
1234 /* Initialize the SP data section */
1235 lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData();
1237 TRACE( "Created player id 0x%08x\n", *lpid );
1239 if( ~dwFlags & DPLAYI_PLAYER_SYSPLAYER )
1240 This->dp2->lpSessionDesc->dwCurrentPlayers++;
1245 /* Delete the contents of the DPNAME struct */
1247 DP_DeleteDPNameStruct( LPDPNAME lpDPName )
1249 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u1.lpszShortNameA );
1250 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u2.lpszLongNameA );
1253 /* This method assumes that all links to it are already deleted */
1255 DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid )
1257 lpPlayerList lpPList;
1259 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1261 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1263 if( lpPList == NULL )
1265 ERR( "DPID 0x%08x not found\n", dpid );
1269 /* Verify that this is the last reference to the data */
1270 if( --(lpPList->lpPData->uRef) )
1272 FIXME( "Why is this not the last reference to player?\n" );
1277 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1279 CloseHandle( lpPList->lpPData->hEvent );
1280 HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
1282 /* Delete Player List object */
1283 HeapFree( GetProcessHeap(), 0, lpPList );
1286 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid )
1288 lpPlayerList lpPlayers;
1290 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1292 if(This->dp2->lpSysGroup == NULL)
1295 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1300 /* Basic area for Dst must already be allocated */
1301 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, const DPNAME *lpSrc, BOOL bAnsi )
1305 ZeroMemory( lpDst, sizeof( *lpDst ) );
1306 lpDst->dwSize = sizeof( *lpDst );
1310 if( lpSrc->dwSize != sizeof( *lpSrc) )
1315 /* Delete any existing pointers */
1316 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1317 HeapFree( GetProcessHeap(), 0, lpDst->u2.lpszLongNameA );
1319 /* Copy as required */
1320 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1324 if( lpSrc->u1.lpszShortNameA )
1326 lpDst->u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), 0,
1327 strlen(lpSrc->u1.lpszShortNameA)+1 );
1328 strcpy( lpDst->u1.lpszShortNameA, lpSrc->u1.lpszShortNameA );
1330 if( lpSrc->u2.lpszLongNameA )
1332 lpDst->u2.lpszLongNameA = HeapAlloc( GetProcessHeap(), 0,
1333 strlen(lpSrc->u2.lpszLongNameA)+1 );
1334 strcpy( lpDst->u2.lpszLongNameA, lpSrc->u2.lpszLongNameA );
1339 if( lpSrc->u1.lpszShortNameA )
1341 lpDst->u1.lpszShortName = HeapAlloc( GetProcessHeap(), 0,
1342 (strlenW(lpSrc->u1.lpszShortName)+1)*sizeof(WCHAR) );
1343 strcpyW( lpDst->u1.lpszShortName, lpSrc->u1.lpszShortName );
1345 if( lpSrc->u2.lpszLongNameA )
1347 lpDst->u2.lpszLongName = HeapAlloc( GetProcessHeap(), 0,
1348 (strlenW(lpSrc->u2.lpszLongName)+1)*sizeof(WCHAR) );
1349 strcpyW( lpDst->u2.lpszLongName, lpSrc->u2.lpszLongName );
1357 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
1358 LPVOID lpData, DWORD dwDataSize )
1360 /* Clear out the data with this player */
1361 if( dwFlags & DPSET_LOCAL )
1363 if ( lpPData->dwLocalDataSize != 0 )
1365 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
1366 lpPData->lpLocalData = NULL;
1367 lpPData->dwLocalDataSize = 0;
1372 if( lpPData->dwRemoteDataSize != 0 )
1374 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
1375 lpPData->lpRemoteData = NULL;
1376 lpPData->dwRemoteDataSize = 0;
1380 /* Reallocate for new data */
1381 if( lpData != NULL )
1383 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1384 sizeof( dwDataSize ) );
1385 CopyMemory( lpNewData, lpData, dwDataSize );
1387 if( dwFlags & DPSET_LOCAL )
1389 lpPData->lpLocalData = lpData;
1390 lpPData->dwLocalDataSize = dwDataSize;
1394 lpPData->lpRemoteData = lpNewData;
1395 lpPData->dwRemoteDataSize = dwDataSize;
1401 static HRESULT DP_IF_CreatePlayer
1402 ( IDirectPlay2Impl* This,
1403 LPVOID lpMsgHdr, /* NULL for local creation, non NULL for remote creation */
1405 LPDPNAME lpPlayerName,
1413 lpPlayerData lpPData;
1414 lpPlayerList lpPList;
1415 DWORD dwCreateFlags = 0;
1417 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1418 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1419 dwDataSize, dwFlags, bAnsi );
1420 if( This->dp2->connectionInitialized == NO_PROVIDER )
1422 return DPERR_UNINITIALIZED;
1427 dwFlags = DPPLAYER_SPECTATOR;
1430 if( lpidPlayer == NULL )
1432 return DPERR_INVALIDPARAMS;
1436 /* Determine the creation flags for the player. These will be passed
1437 * to the name server if requesting a player id and to the SP when
1438 * informing it of the player creation
1441 if( dwFlags & DPPLAYER_SERVERPLAYER )
1443 if( *lpidPlayer == DPID_SERVERPLAYER )
1445 /* Server player for the host interface */
1446 dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
1448 else if( *lpidPlayer == DPID_NAME_SERVER )
1450 /* Name server - master of everything */
1451 dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
1455 /* Server player for a non host interface */
1456 dwCreateFlags |= DPLAYI_PLAYER_SYSPLAYER;
1460 if( lpMsgHdr == NULL )
1461 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1464 /* Verify we know how to handle all the flags */
1465 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1466 ( dwFlags & DPPLAYER_SPECTATOR )
1470 /* Assume non fatal failure */
1471 ERR( "unknown dwFlags = 0x%08x\n", dwFlags );
1474 /* If the name is not specified, we must provide one */
1475 if( *lpidPlayer == DPID_UNKNOWN )
1477 /* If we are the session master, we dish out the group/player ids */
1478 if( This->dp2->bHostInterface )
1480 *lpidPlayer = DP_NextObjectId();
1484 hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer );
1488 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1495 /* FIXME: Would be nice to perhaps verify that we don't already have
1500 /* We pass creation flags, so we can distinguish sysplayers and not count them in the current
1502 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwCreateFlags,
1505 if( lpPData == NULL )
1507 return DPERR_CANTADDPLAYER;
1510 /* Create the list object and link it in */
1511 lpPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPList ) );
1512 if( lpPList == NULL )
1514 FIXME( "Memory leak\n" );
1515 return DPERR_CANTADDPLAYER;
1519 lpPList->lpPData = lpPData;
1521 /* Add the player to the system group */
1522 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1524 /* Update the information and send it to all players in the session */
1525 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
1527 /* Let the SP know that we've created this player */
1528 if( This->dp2->spData.lpCB->CreatePlayer )
1530 DPSP_CREATEPLAYERDATA data;
1532 data.idPlayer = *lpidPlayer;
1533 data.dwFlags = dwCreateFlags;
1534 data.lpSPMessageHeader = lpMsgHdr;
1535 data.lpISP = This->dp2->spData.lpISP;
1537 TRACE( "Calling SP CreatePlayer 0x%08x: dwFlags: 0x%08x lpMsgHdr: %p\n",
1538 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
1540 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1545 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1549 /* Now let the SP know that this player is a member of the system group */
1550 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1552 DPSP_ADDPLAYERTOGROUPDATA data;
1554 data.idPlayer = *lpidPlayer;
1555 data.idGroup = DPID_SYSTEM_GROUP;
1556 data.lpISP = This->dp2->spData.lpISP;
1558 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1560 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1565 ERR( "Failed to add player to sys group with sp: %s\n",
1566 DPLAYX_HresultToString(hr) );
1571 if( This->dp2->bHostInterface == FALSE )
1573 /* Let the name server know about the creation of this player */
1574 /* FIXME: Is this only to be done for the creation of a server player or
1575 * is this used for regular players? If only for server players, move
1576 * this call to DP_SecureOpen(...);
1579 TRACE( "Sending message to self to get my addr\n" );
1580 DP_MSG_ToSelf( This, *lpidPlayer ); /* This is a hack right now */
1583 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
1586 /* Inform all other peers of the creation of a new player. If there are
1587 * no peers keep this quiet.
1588 * Also, if this was a remote event, no need to rebroadcast it.
1590 if( ( lpMsgHdr == NULL ) &&
1591 This->dp2->lpSessionDesc &&
1592 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1594 DPMSG_CREATEPLAYERORGROUP msg;
1595 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1597 msg.dwPlayerType = DPPLAYERTYPE_PLAYER;
1598 msg.dpId = *lpidPlayer;
1599 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */
1600 msg.lpData = lpData;
1601 msg.dwDataSize = dwDataSize;
1602 msg.dpnName = *lpPlayerName;
1603 msg.dpIdParent = DPID_NOPARENT_GROUP;
1604 msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
1606 /* FIXME: Correct to just use send effectively? */
1607 /* FIXME: Should size include data w/ message or just message "header" */
1608 /* FIXME: Check return code */
1609 hr = DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
1610 sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
1617 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
1618 ( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1619 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1621 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1623 if( lpidPlayer == NULL )
1625 return DPERR_INVALIDPARAMS;
1628 if( dwFlags & DPPLAYER_SERVERPLAYER )
1630 *lpidPlayer = DPID_SERVERPLAYER;
1634 *lpidPlayer = DPID_UNKNOWN;
1637 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1638 lpData, dwDataSize, dwFlags, TRUE );
1641 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
1642 ( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1643 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1645 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1647 if( lpidPlayer == NULL )
1649 return DPERR_INVALIDPARAMS;
1652 if( dwFlags & DPPLAYER_SERVERPLAYER )
1654 *lpidPlayer = DPID_SERVERPLAYER;
1658 *lpidPlayer = DPID_UNKNOWN;
1661 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1662 lpData, dwDataSize, dwFlags, FALSE );
1665 static DPID DP_GetRemoteNextObjectId(void)
1670 return DP_NextObjectId();
1673 static HRESULT DP_IF_DeletePlayerFromGroup
1674 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
1675 DPID idPlayer, BOOL bAnsi )
1679 lpGroupData lpGData;
1680 lpPlayerList lpPList;
1682 TRACE( "(%p)->(%p,0x%08x,0x%08x,%u)\n",
1683 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
1685 /* Find the group */
1686 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1688 return DPERR_INVALIDGROUP;
1691 /* Find the player */
1692 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
1694 return DPERR_INVALIDPLAYER;
1697 /* Remove the player shortcut from the group */
1698 DPQ_REMOVE_ENTRY( lpGData->players, players, lpPData->dpid, ==, idPlayer, lpPList );
1700 if( lpPList == NULL )
1702 return DPERR_INVALIDPLAYER;
1705 /* One less reference */
1706 lpPList->lpPData->uRef--;
1708 /* Delete the Player List element */
1709 HeapFree( GetProcessHeap(), 0, lpPList );
1711 /* Inform the SP if they care */
1712 if( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1714 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1716 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1718 data.idPlayer = idPlayer;
1719 data.idGroup = idGroup;
1720 data.lpISP = This->dp2->spData.lpISP;
1722 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1725 /* Need to send a DELETEPLAYERFROMGROUP message */
1726 FIXME( "Need to send a message\n" );
1731 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
1732 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
1734 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1735 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, TRUE );
1738 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
1739 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
1741 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1742 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, FALSE );
1745 typedef struct _DPRGOPContext
1747 IDirectPlay3Impl* This;
1750 } DPRGOPContext, *lpDPRGOPContext;
1752 static BOOL CALLBACK
1753 cbRemoveGroupOrPlayer(
1760 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1762 TRACE( "Removing element:0x%08x (type:0x%08x) from element:0x%08x\n",
1763 dpId, dwPlayerType, lpCtxt->idGroup );
1765 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1767 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt->This, lpCtxt->idGroup,
1772 ERR( "Unable to delete group 0x%08x from group 0x%08x\n",
1773 dpId, lpCtxt->idGroup );
1778 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl*)lpCtxt->This,
1779 NULL, lpCtxt->idGroup,
1780 dpId, lpCtxt->bAnsi )
1784 ERR( "Unable to delete player 0x%08x from grp 0x%08x\n",
1785 dpId, lpCtxt->idGroup );
1789 return TRUE; /* Continue enumeration */
1792 static HRESULT DP_IF_DestroyGroup
1793 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi )
1795 lpGroupData lpGData;
1796 DPRGOPContext context;
1798 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1799 This, lpMsgHdr, idGroup, bAnsi );
1801 /* Find the group */
1802 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1804 return DPERR_INVALIDPLAYER; /* yes player */
1807 context.This = (IDirectPlay3Impl*)This;
1808 context.bAnsi = bAnsi;
1809 context.idGroup = idGroup;
1811 /* Remove all players that this group has */
1812 DP_IF_EnumGroupPlayers( This, idGroup, NULL,
1813 cbRemoveGroupOrPlayer, &context, 0, bAnsi );
1815 /* Remove all links to groups that this group has since this is dp3 */
1816 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This, idGroup, NULL,
1817 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1819 /* Remove this group from the parent group - if it has one */
1820 if( ( idGroup != DPID_SYSTEM_GROUP ) &&
1821 ( lpGData->parent != DPID_SYSTEM_GROUP )
1824 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl*)This, lpGData->parent,
1828 /* Now delete this group data and list from the system group */
1829 DP_DeleteGroup( This, idGroup );
1831 /* Let the SP know that we've destroyed this group */
1832 if( This->dp2->spData.lpCB->DeleteGroup )
1834 DPSP_DELETEGROUPDATA data;
1836 FIXME( "data.dwFlags is incorrect\n" );
1838 data.idGroup = idGroup;
1840 data.lpISP = This->dp2->spData.lpISP;
1842 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1845 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1850 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
1851 ( LPDIRECTPLAY2A iface, DPID idGroup )
1853 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1854 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
1857 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
1858 ( LPDIRECTPLAY2 iface, DPID idGroup )
1860 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1861 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
1864 typedef struct _DPFAGContext
1866 IDirectPlay2Impl* This;
1869 } DPFAGContext, *lpDPFAGContext;
1871 static HRESULT DP_IF_DestroyPlayer
1872 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi )
1874 DPFAGContext cbContext;
1876 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1877 This, lpMsgHdr, idPlayer, bAnsi );
1879 if( This->dp2->connectionInitialized == NO_PROVIDER )
1881 return DPERR_UNINITIALIZED;
1884 if( DP_FindPlayer( This, idPlayer ) == NULL )
1886 return DPERR_INVALIDPLAYER;
1889 /* FIXME: If the player is remote, we must be the host to delete this */
1891 cbContext.This = This;
1892 cbContext.idPlayer = idPlayer;
1893 cbContext.bAnsi = bAnsi;
1895 /* Find each group and call DeletePlayerFromGroup if the player is a
1896 member of the group */
1897 DP_IF_EnumGroups( This, NULL, cbDeletePlayerFromAllGroups,
1898 &cbContext, DPENUMGROUPS_ALL, bAnsi );
1900 /* Now delete player and player list from the sys group */
1901 DP_DeletePlayer( This, idPlayer );
1903 /* Let the SP know that we've destroyed this group */
1904 if( This->dp2->spData.lpCB->DeletePlayer )
1906 DPSP_DELETEPLAYERDATA data;
1908 FIXME( "data.dwFlags is incorrect\n" );
1910 data.idPlayer = idPlayer;
1912 data.lpISP = This->dp2->spData.lpISP;
1914 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
1917 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
1922 static BOOL CALLBACK
1923 cbDeletePlayerFromAllGroups(
1930 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
1932 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1934 DP_IF_DeletePlayerFromGroup( lpCtxt->This, NULL, dpId, lpCtxt->idPlayer,
1937 /* Enumerate all groups in this group since this will normally only
1938 * be called for top level groups
1940 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)lpCtxt->This,
1942 cbDeletePlayerFromAllGroups,
1943 lpContext, DPENUMGROUPS_ALL,
1949 ERR( "Group callback has dwPlayerType = 0x%08x\n", dwPlayerType );
1955 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
1956 ( LPDIRECTPLAY2A iface, DPID idPlayer )
1958 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1959 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
1962 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
1963 ( LPDIRECTPLAY2 iface, DPID idPlayer )
1965 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1966 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
1969 static HRESULT DP_IF_EnumGroupPlayers
1970 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
1971 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1972 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1974 lpGroupData lpGData;
1975 lpPlayerList lpPList;
1977 FIXME("(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
1978 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
1979 lpContext, dwFlags, bAnsi );
1981 if( This->dp2->connectionInitialized == NO_PROVIDER )
1983 return DPERR_UNINITIALIZED;
1986 /* Find the group */
1987 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1989 return DPERR_INVALIDGROUP;
1992 if( DPQ_IS_EMPTY( lpGData->players ) )
1997 lpPList = DPQ_FIRST( lpGData->players );
1999 /* Walk the players in this group */
2002 /* We do not enum the name server or app server as they are of no
2003 * consequence to the end user.
2005 if( ( lpPList->lpPData->dpid != DPID_NAME_SERVER ) &&
2006 ( lpPList->lpPData->dpid != DPID_SERVERPLAYER )
2010 /* FIXME: Need to add stuff for dwFlags checking */
2012 if( !lpEnumPlayersCallback2( lpPList->lpPData->dpid, DPPLAYERTYPE_PLAYER,
2013 &lpPList->lpPData->name,
2014 lpPList->lpPData->dwFlags,
2018 /* User requested break */
2023 if( DPQ_IS_ENDOFLIST( lpPList->players ) )
2028 lpPList = DPQ_NEXT( lpPList->players );
2034 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
2035 ( LPDIRECTPLAY2A iface, DPID idGroup, LPGUID lpguidInstance,
2036 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2037 LPVOID lpContext, DWORD dwFlags )
2039 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2040 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2041 lpEnumPlayersCallback2, lpContext,
2045 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
2046 ( LPDIRECTPLAY2 iface, DPID idGroup, LPGUID lpguidInstance,
2047 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2048 LPVOID lpContext, DWORD dwFlags )
2050 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2051 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2052 lpEnumPlayersCallback2, lpContext,
2056 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2057 static HRESULT DP_IF_EnumGroups
2058 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2059 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2060 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2062 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This,
2063 DPID_SYSTEM_GROUP, lpguidInstance,
2064 lpEnumPlayersCallback2, lpContext,
2068 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
2069 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2070 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2071 LPVOID lpContext, DWORD dwFlags )
2073 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2074 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2075 lpContext, dwFlags, TRUE );
2078 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
2079 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2080 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2081 LPVOID lpContext, DWORD dwFlags )
2083 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2084 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2085 lpContext, dwFlags, FALSE );
2088 static HRESULT DP_IF_EnumPlayers
2089 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2090 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2091 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2093 return DP_IF_EnumGroupPlayers( This, DPID_SYSTEM_GROUP, lpguidInstance,
2094 lpEnumPlayersCallback2, lpContext,
2098 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
2099 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2100 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2101 LPVOID lpContext, DWORD dwFlags )
2103 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2104 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2105 lpContext, dwFlags, TRUE );
2108 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
2109 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2110 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2111 LPVOID lpContext, DWORD dwFlags )
2113 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2114 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2115 lpContext, dwFlags, FALSE );
2118 /* This function should call the registered callback function that the user
2119 passed into EnumSessions for each entry available.
2121 static void DP_InvokeEnumSessionCallbacks
2122 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2127 LPDPSESSIONDESC2 lpSessionDesc;
2129 FIXME( ": not checking for conditions\n" );
2131 /* Not sure if this should be pruning but it's convenient */
2132 NS_PruneSessionCache( lpNSInfo );
2134 NS_ResetSessionEnumeration( lpNSInfo );
2136 /* Enumerate all sessions */
2137 /* FIXME: Need to indicate ANSI */
2138 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2140 TRACE( "EnumSessionsCallback2 invoked\n" );
2141 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2147 /* Invoke one last time to indicate that there is no more to come */
2148 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2151 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2153 EnumSessionAsyncCallbackData* data = lpContext;
2154 HANDLE hSuicideRequest = data->hSuicideRequest;
2155 DWORD dwTimeout = data->dwTimeout;
2157 TRACE( "Thread started with timeout = 0x%08x\n", dwTimeout );
2163 /* Sleep up to dwTimeout waiting for request to terminate thread */
2164 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2166 TRACE( "Thread terminating on terminate request\n" );
2170 /* Now resend the enum request */
2171 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2172 data->dwEnumSessionFlags,
2177 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2178 /* FIXME: Should we kill this thread? How to inform the main thread? */
2183 TRACE( "Thread terminating\n" );
2185 /* Clean up the thread data */
2186 CloseHandle( hSuicideRequest );
2187 HeapFree( GetProcessHeap(), 0, lpContext );
2189 /* FIXME: Need to have some notification to main app thread that this is
2190 * dead. It would serve two purposes. 1) allow sync on termination
2191 * so that we don't actually send something to ourselves when we
2192 * become name server (race condition) and 2) so that if we die
2193 * abnormally something else will be able to tell.
2199 static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
2201 /* Does a thread exist? If so we were doing an async enum session */
2202 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2204 TRACE( "Killing EnumSession thread %p\n",
2205 This->dp2->hEnumSessionThread );
2207 /* Request that the thread kill itself nicely */
2208 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2209 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2211 /* We no longer need to know about the thread */
2212 CloseHandle( This->dp2->hEnumSessionThread );
2214 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2218 static HRESULT DP_IF_EnumSessions
2219 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2220 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2221 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2225 TRACE( "(%p)->(%p,0x%08x,%p,%p,0x%08x,%u)\n",
2226 This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags,
2228 if( This->dp2->connectionInitialized == NO_PROVIDER )
2230 return DPERR_UNINITIALIZED;
2233 /* Can't enumerate if the interface is already open */
2234 if( This->dp2->bConnectionOpen )
2236 return DPERR_GENERIC;
2240 /* The loading of a lobby provider _seems_ to require a backdoor loading
2241 * of the service provider to also associate with this DP object. This is
2242 * because the app doesn't seem to have to call EnumConnections and
2243 * InitializeConnection for the SP before calling this method. As such
2244 * we'll do their dirty work for them with a quick hack so as to always
2245 * load the TCP/IP service provider.
2247 * The correct solution would seem to involve creating a dialog box which
2248 * contains the possible SPs. These dialog boxes most likely follow SDK
2251 if( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
2253 LPVOID lpConnection;
2256 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2258 if( !DP_BuildSPCompoundAddr( (LPGUID)&DPSPGUID_TCPIP, &lpConnection, &dwSize ) )
2260 ERR( "Can't build compound addr\n" );
2261 return DPERR_GENERIC;
2264 hr = DP_IF_InitializeConnection( (IDirectPlay3Impl*)This, lpConnection,
2271 /* Free up the address buffer */
2272 HeapFree( GetProcessHeap(), 0, lpConnection );
2274 /* The SP is now initialized */
2275 This->dp2->bSPInitialized = TRUE;
2280 /* Use the service provider default? */
2281 if( dwTimeout == 0 )
2284 spCaps.dwSize = sizeof( spCaps );
2286 DP_IF_GetCaps( This, &spCaps, 0 );
2287 dwTimeout = spCaps.dwTimeout;
2289 /* The service provider doesn't provide one either! */
2290 if( dwTimeout == 0 )
2292 /* Provide the TCP/IP default */
2293 dwTimeout = DPMSG_WAIT_5_SECS;
2297 if( dwFlags & DPENUMSESSIONS_STOPASYNC )
2299 DP_KillEnumSessionThread( This );
2303 if( ( dwFlags & DPENUMSESSIONS_ASYNC ) )
2305 /* Enumerate everything presently in the local session cache */
2306 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2307 This->dp2->lpNameServerData, dwTimeout,
2310 if( This->dp2->dwEnumSessionLock != 0 )
2311 return DPERR_CONNECTING;
2313 /* See if we've already created a thread to service this interface */
2314 if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2317 This->dp2->dwEnumSessionLock++;
2319 /* Send the first enum request inline since the user may cancel a dialog
2320 * if one is presented. Also, may also have a connecting return code.
2322 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2323 dwFlags, &This->dp2->spData );
2327 EnumSessionAsyncCallbackData* lpData
2328 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpData ) );
2329 /* FIXME: need to kill the thread on object deletion */
2330 lpData->lpSpData = &This->dp2->spData;
2332 lpData->requestGuid = lpsd->guidApplication;
2333 lpData->dwEnumSessionFlags = dwFlags;
2334 lpData->dwTimeout = dwTimeout;
2336 This->dp2->hKillEnumSessionThreadEvent =
2337 CreateEventW( NULL, TRUE, FALSE, NULL );
2339 if( !DuplicateHandle( GetCurrentProcess(),
2340 This->dp2->hKillEnumSessionThreadEvent,
2341 GetCurrentProcess(),
2342 &lpData->hSuicideRequest,
2343 0, FALSE, DUPLICATE_SAME_ACCESS )
2346 ERR( "Can't duplicate thread killing handle\n" );
2349 TRACE( ": creating EnumSessionsRequest thread\n" );
2351 This->dp2->hEnumSessionThread = CreateThread( NULL,
2353 DP_EnumSessionsSendAsyncRequestThread,
2358 This->dp2->dwEnumSessionLock--;
2363 /* Invalidate the session cache for the interface */
2364 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2366 /* Send the broadcast for session enumeration */
2367 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2369 &This->dp2->spData );
2372 SleepEx( dwTimeout, FALSE );
2374 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2375 This->dp2->lpNameServerData, dwTimeout,
2382 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2383 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2384 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2385 LPVOID lpContext, DWORD dwFlags )
2387 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2388 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2389 lpContext, dwFlags, TRUE );
2392 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2393 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2394 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2395 LPVOID lpContext, DWORD dwFlags )
2397 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2398 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2399 lpContext, dwFlags, FALSE );
2402 static HRESULT DP_IF_GetPlayerCaps
2403 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
2406 DPSP_GETCAPSDATA data;
2408 TRACE("(%p)->(0x%08x,%p,0x%08x)\n", This, idPlayer, lpDPCaps, dwFlags);
2410 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2412 return DPERR_UNINITIALIZED;
2415 /* Query the service provider */
2416 data.idPlayer = idPlayer;
2417 data.dwFlags = dwFlags;
2418 data.lpCaps = lpDPCaps;
2419 data.lpISP = This->dp2->spData.lpISP;
2421 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2424 static HRESULT DP_IF_GetCaps
2425 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags )
2427 return DP_IF_GetPlayerCaps( This, DPID_ALLPLAYERS, lpDPCaps, dwFlags );
2430 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2431 ( LPDIRECTPLAY2A iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2433 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2434 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2437 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2438 ( LPDIRECTPLAY2 iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2440 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2441 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2444 static HRESULT DP_IF_GetGroupData
2445 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2446 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2448 lpGroupData lpGData;
2449 DWORD dwRequiredBufferSize;
2450 LPVOID lpCopyDataFrom;
2452 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2453 This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi );
2455 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2457 return DPERR_INVALIDGROUP;
2460 /* How much buffer is required? */
2461 if( dwFlags & DPSET_LOCAL )
2463 dwRequiredBufferSize = lpGData->dwLocalDataSize;
2464 lpCopyDataFrom = lpGData->lpLocalData;
2468 dwRequiredBufferSize = lpGData->dwRemoteDataSize;
2469 lpCopyDataFrom = lpGData->lpRemoteData;
2472 /* Is the user requesting to know how big a buffer is required? */
2473 if( ( lpData == NULL ) ||
2474 ( *lpdwDataSize < dwRequiredBufferSize )
2477 *lpdwDataSize = dwRequiredBufferSize;
2478 return DPERR_BUFFERTOOSMALL;
2481 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2486 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2487 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2488 LPDWORD lpdwDataSize, DWORD dwFlags )
2490 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2491 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2495 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2496 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2497 LPDWORD lpdwDataSize, DWORD dwFlags )
2499 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2500 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2504 static HRESULT DP_IF_GetGroupName
2505 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2506 LPDWORD lpdwDataSize, BOOL bAnsi )
2508 lpGroupData lpGData;
2509 LPDPNAME lpName = lpData;
2510 DWORD dwRequiredDataSize;
2512 FIXME("(%p)->(0x%08x,%p,%p,%u) ANSI ignored\n",
2513 This, idGroup, lpData, lpdwDataSize, bAnsi );
2515 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2517 return DPERR_INVALIDGROUP;
2520 dwRequiredDataSize = lpGData->name.dwSize;
2522 if( lpGData->name.u1.lpszShortNameA )
2524 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
2527 if( lpGData->name.u2.lpszLongNameA )
2529 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
2532 if( ( lpData == NULL ) ||
2533 ( *lpdwDataSize < dwRequiredDataSize )
2536 *lpdwDataSize = dwRequiredDataSize;
2537 return DPERR_BUFFERTOOSMALL;
2540 /* Copy the structure */
2541 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2543 if( lpGData->name.u1.lpszShortNameA )
2545 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2546 lpGData->name.u1.lpszShortNameA );
2550 lpName->u1.lpszShortNameA = NULL;
2553 if( lpGData->name.u1.lpszShortNameA )
2555 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2556 lpGData->name.u2.lpszLongNameA );
2560 lpName->u2.lpszLongNameA = NULL;
2566 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2567 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2568 LPDWORD lpdwDataSize )
2570 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2571 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2574 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2575 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2576 LPDWORD lpdwDataSize )
2578 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2579 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2582 static HRESULT DP_IF_GetMessageCount
2583 ( IDirectPlay2Impl* This, DPID idPlayer,
2584 LPDWORD lpdwCount, BOOL bAnsi )
2586 FIXME("(%p)->(0x%08x,%p,%u): stub\n", This, idPlayer, lpdwCount, bAnsi );
2587 return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer,
2588 DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL,
2592 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2593 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDWORD lpdwCount )
2595 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2596 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, TRUE );
2599 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2600 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDWORD lpdwCount )
2602 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2603 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, FALSE );
2606 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2607 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2609 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2610 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2614 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2615 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2617 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2618 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2622 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2623 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2626 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2627 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2630 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2631 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2634 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2635 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2638 static HRESULT DP_IF_GetPlayerData
2639 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2640 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2642 lpPlayerList lpPList;
2643 DWORD dwRequiredBufferSize;
2644 LPVOID lpCopyDataFrom;
2646 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2647 This, idPlayer, lpData, lpdwDataSize, dwFlags, bAnsi );
2649 if( This->dp2->connectionInitialized == NO_PROVIDER )
2651 return DPERR_UNINITIALIZED;
2654 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2656 return DPERR_INVALIDPLAYER;
2659 /* How much buffer is required? */
2660 if( dwFlags & DPSET_LOCAL )
2662 dwRequiredBufferSize = lpPList->lpPData->dwLocalDataSize;
2663 lpCopyDataFrom = lpPList->lpPData->lpLocalData;
2667 dwRequiredBufferSize = lpPList->lpPData->dwRemoteDataSize;
2668 lpCopyDataFrom = lpPList->lpPData->lpRemoteData;
2671 /* Is the user requesting to know how big a buffer is required? */
2672 if( ( lpData == NULL ) ||
2673 ( *lpdwDataSize < dwRequiredBufferSize )
2676 *lpdwDataSize = dwRequiredBufferSize;
2677 return DPERR_BUFFERTOOSMALL;
2680 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2685 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2686 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2687 LPDWORD lpdwDataSize, DWORD dwFlags )
2689 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2690 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2694 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2695 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2696 LPDWORD lpdwDataSize, DWORD dwFlags )
2698 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2699 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2703 static HRESULT DP_IF_GetPlayerName
2704 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2705 LPDWORD lpdwDataSize, BOOL bAnsi )
2707 lpPlayerList lpPList;
2708 LPDPNAME lpName = lpData;
2709 DWORD dwRequiredDataSize;
2711 FIXME( "(%p)->(0x%08x,%p,%p,%u): ANSI\n",
2712 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2714 if( This->dp2->connectionInitialized == NO_PROVIDER )
2716 return DPERR_UNINITIALIZED;
2719 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2721 return DPERR_INVALIDPLAYER;
2724 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
2726 if( lpPList->lpPData->name.u1.lpszShortNameA )
2728 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
2731 if( lpPList->lpPData->name.u2.lpszLongNameA )
2733 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
2736 if( ( lpData == NULL ) ||
2737 ( *lpdwDataSize < dwRequiredDataSize )
2740 *lpdwDataSize = dwRequiredDataSize;
2741 return DPERR_BUFFERTOOSMALL;
2744 /* Copy the structure */
2745 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
2747 if( lpPList->lpPData->name.u1.lpszShortNameA )
2749 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2750 lpPList->lpPData->name.u1.lpszShortNameA );
2754 lpName->u1.lpszShortNameA = NULL;
2757 if( lpPList->lpPData->name.u1.lpszShortNameA )
2759 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2760 lpPList->lpPData->name.u2.lpszLongNameA );
2764 lpName->u2.lpszLongNameA = NULL;
2770 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2771 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2772 LPDWORD lpdwDataSize )
2774 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2775 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
2778 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2779 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2780 LPDWORD lpdwDataSize )
2782 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2783 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
2786 static HRESULT DP_GetSessionDesc
2787 ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize,
2790 DWORD dwRequiredSize;
2792 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
2794 if( This->dp2->connectionInitialized == NO_PROVIDER )
2796 return DPERR_UNINITIALIZED;
2799 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
2801 return DPERR_INVALIDPARAMS;
2804 /* FIXME: Get from This->dp2->lpSessionDesc */
2805 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
2807 if ( ( lpData == NULL ) ||
2808 ( *lpdwDataSize < dwRequiredSize )
2811 *lpdwDataSize = dwRequiredSize;
2812 return DPERR_BUFFERTOOSMALL;
2815 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
2820 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
2821 ( LPDIRECTPLAY2A iface, LPVOID lpData, LPDWORD lpdwDataSize )
2823 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2824 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2827 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
2828 ( LPDIRECTPLAY2 iface, LPVOID lpData, LPDWORD lpdwDataSize )
2830 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2831 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2834 /* Intended only for COM compatibility. Always returns an error. */
2835 static HRESULT WINAPI DirectPlay2AImpl_Initialize
2836 ( LPDIRECTPLAY2A iface, LPGUID lpGUID )
2838 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2839 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2840 return DPERR_ALREADYINITIALIZED;
2843 /* Intended only for COM compatibility. Always returns an error. */
2844 static HRESULT WINAPI DirectPlay2WImpl_Initialize
2845 ( LPDIRECTPLAY2 iface, LPGUID lpGUID )
2847 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2848 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2849 return DPERR_ALREADYINITIALIZED;
2853 static HRESULT DP_SecureOpen
2854 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
2855 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
2860 FIXME( "(%p)->(%p,0x%08x,%p,%p): partial stub\n",
2861 This, lpsd, dwFlags, lpSecurity, lpCredentials );
2863 if( This->dp2->connectionInitialized == NO_PROVIDER )
2865 return DPERR_UNINITIALIZED;
2868 if( lpsd->dwSize != sizeof(DPSESSIONDESC2) )
2870 TRACE( ": rejecting invalid dpsd size (%d).\n", lpsd->dwSize );
2871 return DPERR_INVALIDPARAMS;
2874 if( This->dp2->bConnectionOpen )
2876 TRACE( ": rejecting already open connection.\n" );
2877 return DPERR_ALREADYINITIALIZED;
2880 /* If we're enumerating, kill the thread */
2881 DP_KillEnumSessionThread( This );
2883 if( dwFlags & DPOPEN_CREATE )
2885 /* Rightoo - this computer is the host and the local computer needs to be
2886 the name server so that others can join this session */
2887 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
2889 This->dp2->bHostInterface = TRUE;
2891 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
2894 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
2899 /* Invoke the conditional callback for the service provider */
2900 if( This->dp2->spData.lpCB->Open )
2904 FIXME( "Not all data fields are correct. Need new parameter\n" );
2906 data.bCreate = (dwFlags & DPOPEN_CREATE ) ? TRUE : FALSE;
2907 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
2908 : NS_GetNSAddr( This->dp2->lpNameServerData );
2909 data.lpISP = This->dp2->spData.lpISP;
2910 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) ? TRUE : FALSE;
2911 data.dwOpenFlags = dwFlags;
2912 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
2914 hr = (*This->dp2->spData.lpCB->Open)(&data);
2917 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
2923 /* Create the system group of which everything is a part of */
2924 DPID systemGroup = DPID_SYSTEM_GROUP;
2926 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
2931 if( dwFlags & DPOPEN_JOIN )
2933 DPID dpidServerId = DPID_UNKNOWN;
2935 /* Create the server player for this interface. This way we can receive
2936 * messages for this session.
2938 /* FIXME: I suppose that we should be setting an event for a receive
2939 * type of thing. That way the messaging thread could know to wake
2940 * up. DPlay would then trigger the hEvent for the player the
2941 * message is directed to.
2943 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
2945 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
2948 else if( dwFlags & DPOPEN_CREATE )
2950 DPID dpidNameServerId = DPID_NAME_SERVER;
2952 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
2953 0, DPPLAYER_SERVERPLAYER, bAnsi );
2958 ERR( "Couldn't create name server/system player: %s\n",
2959 DPLAYX_HresultToString(hr) );
2965 static HRESULT WINAPI DirectPlay2AImpl_Open
2966 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2968 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2969 TRACE("(%p)->(%p,0x%08x)\n", This, lpsd, dwFlags );
2970 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, TRUE );
2973 static HRESULT WINAPI DirectPlay2WImpl_Open
2974 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2976 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2977 TRACE("(%p)->(%p,0x%08x)\n", This, lpsd, dwFlags );
2978 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, FALSE );
2981 static HRESULT DP_IF_Receive
2982 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
2983 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi )
2985 LPDPMSG lpMsg = NULL;
2987 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p,%u): stub\n",
2988 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
2990 if( This->dp2->connectionInitialized == NO_PROVIDER )
2992 return DPERR_UNINITIALIZED;
2997 dwFlags = DPRECEIVE_ALL;
3000 /* If the lpData is NULL, we must be peeking the message */
3001 if( ( lpData == NULL ) &&
3002 !( dwFlags & DPRECEIVE_PEEK )
3005 return DPERR_INVALIDPARAMS;
3008 if( dwFlags & DPRECEIVE_ALL )
3010 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
3012 if( !( dwFlags & DPRECEIVE_PEEK ) )
3014 FIXME( "Remove from queue\n" );
3017 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
3018 ( dwFlags & DPRECEIVE_FROMPLAYER )
3021 FIXME( "Find matching message 0x%08x\n", dwFlags );
3025 ERR( "Hmmm..dwFlags 0x%08x\n", dwFlags );
3030 return DPERR_NOMESSAGES;
3033 /* Copy into the provided buffer */
3034 if (lpData) CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
3039 static HRESULT WINAPI DirectPlay2AImpl_Receive
3040 ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo,
3041 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
3043 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3044 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
3045 lpData, lpdwDataSize, TRUE );
3048 static HRESULT WINAPI DirectPlay2WImpl_Receive
3049 ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo,
3050 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
3052 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3053 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
3054 lpData, lpdwDataSize, FALSE );
3057 static HRESULT WINAPI DirectPlay2AImpl_Send
3058 ( LPDIRECTPLAY2A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3060 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3061 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3062 0, 0, NULL, NULL, TRUE );
3065 static HRESULT WINAPI DirectPlay2WImpl_Send
3066 ( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3068 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3069 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3070 0, 0, NULL, NULL, FALSE );
3073 static HRESULT DP_IF_SetGroupData
3074 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
3075 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3077 lpGroupData lpGData;
3079 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3080 This, idGroup, lpData, dwDataSize, dwFlags, bAnsi );
3082 /* Parameter check */
3083 if( ( lpData == NULL ) &&
3087 return DPERR_INVALIDPARAMS;
3090 /* Find the pointer to the data for this player */
3091 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3093 return DPERR_INVALIDOBJECT;
3096 if( !(dwFlags & DPSET_LOCAL) )
3098 FIXME( "Was this group created by this interface?\n" );
3099 /* FIXME: If this is a remote update need to allow it but not
3104 DP_SetGroupData( lpGData, dwFlags, lpData, dwDataSize );
3106 /* FIXME: Only send a message if this group is local to the session otherwise
3107 * it will have been rejected above
3109 if( !(dwFlags & DPSET_LOCAL) )
3111 FIXME( "Send msg?\n" );
3117 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
3118 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
3119 DWORD dwDataSize, DWORD dwFlags )
3121 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3122 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, TRUE );
3125 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
3126 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
3127 DWORD dwDataSize, DWORD dwFlags )
3129 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3130 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, FALSE );
3133 static HRESULT DP_IF_SetGroupName
3134 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
3135 DWORD dwFlags, BOOL bAnsi )
3137 lpGroupData lpGData;
3139 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n", This, idGroup,
3140 lpGroupName, dwFlags, bAnsi );
3142 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3144 return DPERR_INVALIDGROUP;
3147 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
3149 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3150 FIXME( "Message not sent and dwFlags ignored\n" );
3155 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
3156 ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName,
3159 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3160 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
3163 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
3164 ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName,
3167 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3168 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
3171 static HRESULT DP_IF_SetPlayerData
3172 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
3173 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3175 lpPlayerList lpPList;
3177 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3178 This, idPlayer, lpData, dwDataSize, dwFlags, bAnsi );
3180 if( This->dp2->connectionInitialized == NO_PROVIDER )
3182 return DPERR_UNINITIALIZED;
3185 /* Parameter check */
3186 if( ( lpData == NULL ) &&
3190 return DPERR_INVALIDPARAMS;
3193 /* Find the pointer to the data for this player */
3194 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3196 return DPERR_INVALIDPLAYER;
3199 if( !(dwFlags & DPSET_LOCAL) )
3201 FIXME( "Was this group created by this interface?\n" );
3202 /* FIXME: If this is a remote update need to allow it but not
3207 DP_SetPlayerData( lpPList->lpPData, dwFlags, lpData, dwDataSize );
3209 if( !(dwFlags & DPSET_LOCAL) )
3211 FIXME( "Send msg?\n" );
3217 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3218 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
3219 DWORD dwDataSize, DWORD dwFlags )
3221 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3222 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3226 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3227 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
3228 DWORD dwDataSize, DWORD dwFlags )
3230 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3231 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3235 static HRESULT DP_IF_SetPlayerName
3236 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
3237 DWORD dwFlags, BOOL bAnsi )
3239 lpPlayerList lpPList;
3241 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n",
3242 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3244 if( This->dp2->connectionInitialized == NO_PROVIDER )
3246 return DPERR_UNINITIALIZED;
3249 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3251 return DPERR_INVALIDGROUP;
3254 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3256 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3257 FIXME( "Message not sent and dwFlags ignored\n" );
3262 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3263 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName,
3266 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3267 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3270 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3271 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName,
3274 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3275 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3278 static HRESULT DP_SetSessionDesc
3279 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
3280 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3282 DWORD dwRequiredSize;
3283 LPDPSESSIONDESC2 lpTempSessDesc;
3285 TRACE( "(%p)->(%p,0x%08x,%u,%u)\n",
3286 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3288 if( This->dp2->connectionInitialized == NO_PROVIDER )
3290 return DPERR_UNINITIALIZED;
3295 return DPERR_INVALIDPARAMS;
3298 /* Only the host is allowed to update the session desc */
3299 if( !This->dp2->bHostInterface )
3301 return DPERR_ACCESSDENIED;
3304 /* FIXME: Copy into This->dp2->lpSessionDesc */
3305 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3306 lpTempSessDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize );
3308 if( lpTempSessDesc == NULL )
3310 return DPERR_OUTOFMEMORY;
3314 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3316 This->dp2->lpSessionDesc = lpTempSessDesc;
3318 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3321 /*Initializing session GUID*/
3322 CoCreateGuid( &(This->dp2->lpSessionDesc->guidInstance) );
3324 /* If this is an external invocation of the interface, we should be
3325 * letting everyone know that things have changed. Otherwise this is
3326 * just an initialization and it doesn't need to be propagated.
3330 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3336 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3337 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3339 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3340 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3343 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3344 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3346 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3347 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3350 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3351 static DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3355 if( lpSessDesc == NULL )
3357 /* Hmmm..don't need any size? */
3358 ERR( "NULL lpSessDesc\n" );
3362 dwSize += sizeof( *lpSessDesc );
3366 if( lpSessDesc->u1.lpszSessionNameA )
3368 dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1;
3371 if( lpSessDesc->u2.lpszPasswordA )
3373 dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1;
3378 if( lpSessDesc->u1.lpszSessionName )
3380 dwSize += sizeof( WCHAR ) *
3381 ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 );
3384 if( lpSessDesc->u2.lpszPassword )
3386 dwSize += sizeof( WCHAR ) *
3387 ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 );
3394 /* Assumes that contiguous buffers are already allocated. */
3395 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3396 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3398 BYTE* lpStartOfFreeSpace;
3400 if( lpSessionDest == NULL )
3402 ERR( "NULL lpSessionDest\n" );
3406 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3408 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3412 if( lpSessionSrc->u1.lpszSessionNameA )
3414 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3415 lpSessionDest->u1.lpszSessionNameA );
3416 lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3417 lpStartOfFreeSpace +=
3418 lstrlenA( lpSessionDest->u1.lpszSessionNameA ) + 1;
3421 if( lpSessionSrc->u2.lpszPasswordA )
3423 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3424 lpSessionDest->u2.lpszPasswordA );
3425 lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3426 lpStartOfFreeSpace +=
3427 lstrlenA( lpSessionDest->u2.lpszPasswordA ) + 1;
3432 if( lpSessionSrc->u1.lpszSessionName )
3434 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3435 lpSessionDest->u1.lpszSessionName );
3436 lpSessionDest->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3437 lpStartOfFreeSpace += sizeof(WCHAR) *
3438 ( lstrlenW( lpSessionDest->u1.lpszSessionName ) + 1 );
3441 if( lpSessionSrc->u2.lpszPassword )
3443 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3444 lpSessionDest->u2.lpszPassword );
3445 lpSessionDest->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3446 lpStartOfFreeSpace += sizeof(WCHAR) *
3447 ( lstrlenW( lpSessionDest->u2.lpszPassword ) + 1 );
3453 static HRESULT DP_IF_AddGroupToGroup
3454 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3456 lpGroupData lpGData;
3457 lpGroupList lpNewGList;
3459 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, idParentGroup, idGroup );
3461 if( This->dp2->connectionInitialized == NO_PROVIDER )
3463 return DPERR_UNINITIALIZED;
3466 if( DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) == NULL )
3468 return DPERR_INVALIDGROUP;
3471 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3473 return DPERR_INVALIDGROUP;
3476 /* Create a player list (ie "shortcut" ) */
3477 lpNewGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewGList ) );
3478 if( lpNewGList == NULL )
3480 return DPERR_CANTADDPLAYER;
3483 /* Add the shortcut */
3485 lpNewGList->lpGData = lpGData;
3487 /* Add the player to the list of players for this group */
3488 DPQ_INSERT( lpGData->groups, lpNewGList, groups );
3490 /* Send a ADDGROUPTOGROUP message */
3491 FIXME( "Not sending message\n" );
3496 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3497 ( LPDIRECTPLAY3A iface, DPID idParentGroup, DPID idGroup )
3499 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3500 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3503 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3504 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3506 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3507 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3510 static HRESULT DP_IF_CreateGroupInGroup
3511 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
3512 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
3513 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3515 lpGroupData lpGParentData;
3516 lpGroupList lpGList;
3517 lpGroupData lpGData;
3519 TRACE( "(%p)->(0x%08x,%p,%p,%p,0x%08x,0x%08x,%u)\n",
3520 This, idParentGroup, lpidGroup, lpGroupName, lpData,
3521 dwDataSize, dwFlags, bAnsi );
3523 if( This->dp2->connectionInitialized == NO_PROVIDER )
3525 return DPERR_UNINITIALIZED;
3528 /* Verify that the specified parent is valid */
3529 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This,
3530 idParentGroup ) ) == NULL
3533 return DPERR_INVALIDGROUP;
3536 lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName,
3537 dwFlags, idParentGroup, bAnsi );
3539 if( lpGData == NULL )
3541 return DPERR_CANTADDPLAYER; /* yes player not group */
3544 /* Something else is referencing this data */
3547 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
3549 /* The list has now been inserted into the interface group list. We now
3550 need to put a "shortcut" to this group in the parent group */
3551 lpGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGList ) );
3552 if( lpGList == NULL )
3554 FIXME( "Memory leak\n" );
3555 return DPERR_CANTADDPLAYER; /* yes player not group */
3558 lpGList->lpGData = lpGData;
3560 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
3562 /* Let the SP know that we've created this group */
3563 if( This->dp2->spData.lpCB->CreateGroup )
3565 DPSP_CREATEGROUPDATA data;
3567 TRACE( "Calling SP CreateGroup\n" );
3569 data.idGroup = *lpidGroup;
3570 data.dwFlags = dwFlags;
3571 data.lpSPMessageHeader = lpMsgHdr;
3572 data.lpISP = This->dp2->spData.lpISP;
3574 (*This->dp2->spData.lpCB->CreateGroup)( &data );
3577 /* Inform all other peers of the creation of a new group. If there are
3578 * no peers keep this quiet.
3580 if( This->dp2->lpSessionDesc &&
3581 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
3583 DPMSG_CREATEPLAYERORGROUP msg;
3585 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
3586 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
3587 msg.dpId = *lpidGroup;
3588 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
3589 msg.lpData = lpData;
3590 msg.dwDataSize = dwDataSize;
3591 msg.dpnName = *lpGroupName;
3593 /* FIXME: Correct to just use send effectively? */
3594 /* FIXME: Should size include data w/ message or just message "header" */
3595 /* FIXME: Check return code */
3596 DP_SendEx( (IDirectPlay2Impl*)This,
3597 DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
3598 0, 0, NULL, NULL, bAnsi );
3604 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3605 ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup,
3606 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3609 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3611 *lpidGroup = DPID_UNKNOWN;
3613 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3614 lpGroupName, lpData, dwDataSize, dwFlags,
3618 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3619 ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup,
3620 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3623 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3625 *lpidGroup = DPID_UNKNOWN;
3627 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3628 lpGroupName, lpData, dwDataSize,
3632 static HRESULT DP_IF_DeleteGroupFromGroup
3633 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3635 lpGroupList lpGList;
3636 lpGroupData lpGParentData;
3638 TRACE("(%p)->(0x%08x,0x%08x)\n", This, idParentGroup, idGroup );
3640 /* Is the parent group valid? */
3641 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3643 return DPERR_INVALIDGROUP;
3646 /* Remove the group from the parent group queue */
3647 DPQ_REMOVE_ENTRY( lpGParentData->groups, groups, lpGData->dpid, ==, idGroup, lpGList );
3649 if( lpGList == NULL )
3651 return DPERR_INVALIDGROUP;
3654 /* Decrement the ref count */
3655 lpGList->lpGData->uRef--;
3657 /* Free up the list item */
3658 HeapFree( GetProcessHeap(), 0, lpGList );
3660 /* Should send a DELETEGROUPFROMGROUP message */
3661 FIXME( "message not sent\n" );
3666 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3667 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3669 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3670 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3673 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3674 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3676 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3677 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3680 static BOOL DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
3681 LPDWORD lpdwBufSize )
3683 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3686 dpCompoundAddress.dwDataSize = sizeof( GUID );
3687 dpCompoundAddress.guidDataType = DPAID_ServiceProvider;
3688 dpCompoundAddress.lpData = lpcSpGuid;
3690 *lplpAddrBuf = NULL;
3693 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3694 lpdwBufSize, TRUE );
3696 if( hr != DPERR_BUFFERTOOSMALL )
3698 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3702 /* Now allocate the buffer */
3703 *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3706 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3707 lpdwBufSize, TRUE );
3710 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3717 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
3718 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3720 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3721 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3723 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
3726 dwFlags = DPCONNECTION_DIRECTPLAY;
3729 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
3730 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) )
3733 return DPERR_INVALIDFLAGS;
3736 if( !lpEnumCallback )
3738 return DPERR_INVALIDPARAMS;
3741 /* Enumerate DirectPlay service providers */
3742 if( dwFlags & DPCONNECTION_DIRECTPLAY )
3745 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3746 LPCSTR guidDataSubKey = "Guid";
3747 char subKeyName[51];
3748 DWORD dwIndex, sizeOfSubKeyName=50;
3751 /* Need to loop over the service providers in the registry */
3752 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3753 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3755 /* Hmmm. Does this mean that there are no service providers? */
3756 ERR(": no service providers?\n");
3761 /* Traverse all the service providers we have available */
3763 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3764 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3765 ++dwIndex, sizeOfSubKeyName=51 )
3768 HKEY hkServiceProvider;
3769 GUID serviceProviderGUID;
3770 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3771 char returnBuffer[51];
3776 LPVOID lpAddressBuffer = NULL;
3777 DWORD dwAddressBufferSize = 0;
3779 TRACE(" this time through: %s\n", subKeyName );
3781 /* Get a handle for this particular service provider */
3782 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3783 &hkServiceProvider ) != ERROR_SUCCESS )
3785 ERR(": what the heck is going on?\n" );
3789 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3790 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
3791 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3793 ERR(": missing GUID registry data members\n" );
3794 RegCloseKey(hkServiceProvider);
3797 RegCloseKey(hkServiceProvider);
3799 /* FIXME: Check return types to ensure we're interpreting data right */
3800 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3801 CLSIDFromString( buff, &serviceProviderGUID );
3802 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3804 /* Fill in the DPNAME struct for the service provider */
3805 dpName.dwSize = sizeof( dpName );
3807 dpName.u1.lpszShortNameA = subKeyName;
3808 dpName.u2.lpszLongNameA = NULL;
3810 /* Create the compound address for the service provider.
3811 * NOTE: This is a gruesome architectural scar right now. DP
3812 * uses DPL and DPL uses DP. Nasty stuff. This may be why the
3813 * native dll just gets around this little bit by allocating an
3814 * 80 byte buffer which isn't even filled with a valid compound
3815 * address. Oh well. Creating a proper compound address is the
3816 * way to go anyways despite this method taking slightly more
3817 * heap space and realtime :) */
3819 bBuildPass = DP_BuildSPCompoundAddr( &serviceProviderGUID,
3821 &dwAddressBufferSize );
3824 ERR( "Can't build compound addr\n" );
3825 return DPERR_GENERIC;
3828 /* The enumeration will return FALSE if we are not to continue */
3829 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3830 &dpName, dwFlags, lpContext ) )
3837 /* Enumerate DirectPlayLobby service providers */
3838 if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY )
3841 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3842 LPCSTR guidDataSubKey = "Guid";
3843 char subKeyName[51];
3844 DWORD dwIndex, sizeOfSubKeyName=50;
3847 /* Need to loop over the service providers in the registry */
3848 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3849 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3851 /* Hmmm. Does this mean that there are no service providers? */
3852 ERR(": no service providers?\n");
3857 /* Traverse all the lobby providers we have available */
3859 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3860 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3861 ++dwIndex, sizeOfSubKeyName=51 )
3864 HKEY hkServiceProvider;
3865 GUID serviceProviderGUID;
3866 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3867 char returnBuffer[51];
3872 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3873 LPVOID lpAddressBuffer = NULL;
3874 DWORD dwAddressBufferSize = 0;
3876 TRACE(" this time through: %s\n", subKeyName );
3878 /* Get a handle for this particular service provider */
3879 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3880 &hkServiceProvider ) != ERROR_SUCCESS )
3882 ERR(": what the heck is going on?\n" );
3886 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3887 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
3888 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3890 ERR(": missing GUID registry data members\n" );
3891 RegCloseKey(hkServiceProvider);
3894 RegCloseKey(hkServiceProvider);
3896 /* FIXME: Check return types to ensure we're interpreting data right */
3897 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3898 CLSIDFromString( buff, &serviceProviderGUID );
3899 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3901 /* Fill in the DPNAME struct for the service provider */
3902 dpName.dwSize = sizeof( dpName );
3904 dpName.u1.lpszShortNameA = subKeyName;
3905 dpName.u2.lpszLongNameA = NULL;
3907 /* Create the compound address for the service provider.
3908 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
3909 nast stuff. This may be why the native dll just gets around this little bit by
3910 allocating an 80 byte buffer which isn't even a filled with a valid compound
3911 address. Oh well. Creating a proper compound address is the way to go anyways
3912 despite this method taking slightly more heap space and realtime :) */
3914 dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
3915 dpCompoundAddress.dwDataSize = sizeof( GUID );
3916 dpCompoundAddress.lpData = &serviceProviderGUID;
3918 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3919 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
3921 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3925 /* Now allocate the buffer */
3926 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
3928 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3929 &dwAddressBufferSize, TRUE ) ) != DP_OK )
3931 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3932 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
3936 /* The enumeration will return FALSE if we are not to continue */
3937 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3938 &dpName, dwFlags, lpContext ) )
3940 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
3943 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
3950 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
3951 ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3953 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3954 FIXME("(%p)->(%p,%p,%p,0x%08x): stub\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3958 static HRESULT DP_IF_EnumGroupsInGroup
3959 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
3960 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
3961 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
3963 lpGroupList lpGList;
3964 lpGroupData lpGData;
3966 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
3967 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
3968 lpContext, dwFlags, bAnsi );
3970 if( This->dp2->connectionInitialized == NO_PROVIDER )
3972 return DPERR_UNINITIALIZED;
3975 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3977 return DPERR_INVALIDGROUP;
3980 if( DPQ_IS_EMPTY( lpGData->groups ) )
3985 lpGList = DPQ_FIRST( lpGData->groups );
3989 /* FIXME: Should check dwFlags for match here */
3991 if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP,
3992 &lpGList->lpGData->name, dwFlags,
3995 return DP_OK; /* User requested break */
3998 if( DPQ_IS_ENDOFLIST( lpGList->groups ) )
4003 lpGList = DPQ_NEXT( lpGList->groups );
4010 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
4011 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
4012 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
4015 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4016 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
4017 lpEnumPlayersCallback2, lpContext, dwFlags,
4021 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
4022 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
4023 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
4026 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4027 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
4028 lpEnumPlayersCallback2, lpContext, dwFlags,
4032 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
4033 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
4035 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4036 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
4040 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
4041 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
4043 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4044 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
4048 static BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
4049 REFGUID guidDataType,
4054 /* Looking for the GUID of the provider to load */
4055 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
4056 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
4059 TRACE( "Found SP/LP (%s) %s (data size = 0x%08x)\n",
4060 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
4062 if( dwDataSize != sizeof( GUID ) )
4064 ERR( "Invalid sp/lp guid size 0x%08x\n", dwDataSize );
4067 memcpy( lpContext, lpData, dwDataSize );
4069 /* There shouldn't be more than 1 GUID/compound address */
4073 /* Still waiting for what we want */
4078 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
4079 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
4082 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4083 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
4084 LPCSTR guidDataSubKey = "Guid";
4085 LPCSTR majVerDataSubKey = "dwReserved1";
4086 LPCSTR minVerDataSubKey = "dwReserved2";
4087 LPCSTR pathSubKey = "Path";
4089 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
4091 /* FIXME: Cloned code with a quick hack. */
4092 for( i=0; i<2; i++ )
4095 LPCSTR searchSubKey;
4096 char subKeyName[51];
4097 DWORD dwIndex, sizeOfSubKeyName=50;
4100 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
4101 *lpbIsDpSp = (i == 0) ? TRUE : FALSE;
4104 /* Need to loop over the service providers in the registry */
4105 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4106 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4108 /* Hmmm. Does this mean that there are no service providers? */
4109 ERR(": no service providers?\n");
4113 /* Traverse all the service providers we have available */
4115 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4116 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4117 ++dwIndex, sizeOfSubKeyName=51 )
4120 HKEY hkServiceProvider;
4121 GUID serviceProviderGUID;
4122 DWORD returnType, sizeOfReturnBuffer = 255;
4123 char returnBuffer[256];
4127 TRACE(" this time through: %s\n", subKeyName );
4129 /* Get a handle for this particular service provider */
4130 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4131 &hkServiceProvider ) != ERROR_SUCCESS )
4133 ERR(": what the heck is going on?\n" );
4137 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4138 NULL, &returnType, (LPBYTE)returnBuffer,
4139 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4141 ERR(": missing GUID registry data members\n" );
4145 /* FIXME: Check return types to ensure we're interpreting data right */
4146 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4147 CLSIDFromString( buff, &serviceProviderGUID );
4148 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4150 /* Determine if this is the Service Provider that the user asked for */
4151 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
4156 if( i == 0 ) /* DP SP */
4158 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
4159 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
4160 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
4163 sizeOfReturnBuffer = 255;
4165 /* Get dwReserved1 */
4166 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
4167 NULL, &returnType, (LPBYTE)returnBuffer,
4168 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4170 ERR(": missing dwReserved1 registry data members\n") ;
4175 memcpy( &lpSpData->dwReserved1, returnBuffer, sizeof(lpSpData->dwReserved1) );
4177 sizeOfReturnBuffer = 255;
4179 /* Get dwReserved2 */
4180 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4181 NULL, &returnType, (LPBYTE)returnBuffer,
4182 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4184 ERR(": missing dwReserved1 registry data members\n") ;
4189 memcpy( &lpSpData->dwReserved2, returnBuffer, sizeof(lpSpData->dwReserved2) );
4191 sizeOfReturnBuffer = 255;
4193 /* Get the path for this service provider */
4194 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
4195 NULL, NULL, (LPBYTE)returnBuffer,
4196 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
4198 ERR(": missing PATH registry data members: 0x%08x\n", dwTemp );
4202 TRACE( "Loading %s\n", returnBuffer );
4203 return LoadLibraryA( returnBuffer );
4211 HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider )
4214 LPDPSP_SPINIT SPInit;
4216 /* Initialize the service provider by calling SPInit */
4217 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4219 if( SPInit == NULL )
4221 ERR( "Service provider doesn't provide SPInit interface?\n" );
4222 FreeLibrary( hServiceProvider );
4223 return DPERR_UNAVAILABLE;
4226 TRACE( "Calling SPInit (DP SP entry point)\n" );
4228 hr = (*SPInit)( &This->dp2->spData );
4232 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4233 FreeLibrary( hServiceProvider );
4237 /* FIXME: Need to verify the sanity of the returned callback table
4238 * using IsBadCodePtr */
4239 This->dp2->bSPInitialized = TRUE;
4241 /* This interface is now initialized as a DP object */
4242 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
4244 /* Store the handle of the module so that we can unload it later */
4245 This->dp2->hServiceProvider = hServiceProvider;
4251 HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hLobbyProvider )
4254 LPSP_INIT DPLSPInit;
4256 /* Initialize the service provider by calling SPInit */
4257 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
4259 if( DPLSPInit == NULL )
4261 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4262 FreeLibrary( hLobbyProvider );
4263 return DPERR_UNAVAILABLE;
4266 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4268 hr = (*DPLSPInit)( &This->dp2->dplspData );
4272 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4273 FreeLibrary( hLobbyProvider );
4277 /* FIXME: Need to verify the sanity of the returned callback table
4278 * using IsBadCodePtr */
4280 This->dp2->bDPLSPInitialized = TRUE;
4282 /* This interface is now initialized as a lobby object */
4283 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
4285 /* Store the handle of the module so that we can unload it later */
4286 This->dp2->hDPLobbyProvider = hLobbyProvider;
4291 static HRESULT DP_IF_InitializeConnection
4292 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi )
4294 HMODULE hServiceProvider;
4297 const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
4298 BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4300 TRACE("(%p)->(%p,0x%08x,%u)\n", This, lpConnection, dwFlags, bAnsi );
4302 if ( lpConnection == NULL )
4304 return DPERR_INVALIDPARAMS;
4309 return DPERR_INVALIDFLAGS;
4312 if( This->dp2->connectionInitialized != NO_PROVIDER )
4314 return DPERR_ALREADYINITIALIZED;
4317 /* Find out what the requested SP is and how large this buffer is */
4318 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
4319 dwAddrSize, &guidSP );
4323 ERR( "Invalid compound address?\n" );
4324 return DPERR_UNAVAILABLE;
4327 /* Load the service provider */
4328 hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp );
4330 if( hServiceProvider == 0 )
4332 ERR( "Unable to load service provider %s\n", debugstr_guid(&guidSP) );
4333 return DPERR_UNAVAILABLE;
4338 /* Fill in what we can of the Service Provider required information.
4339 * The rest was be done in DP_LoadSP
4341 This->dp2->spData.lpAddress = lpConnection;
4342 This->dp2->spData.dwAddressSize = dwAddrSize;
4343 This->dp2->spData.lpGuid = &guidSP;
4345 hr = DP_InitializeDPSP( This, hServiceProvider );
4349 This->dp2->dplspData.lpAddress = lpConnection;
4351 hr = DP_InitializeDPLSP( This, hServiceProvider );
4362 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4363 ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
4365 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4367 /* This may not be externally invoked once either an SP or LP is initialized */
4368 if( This->dp2->connectionInitialized != NO_PROVIDER )
4370 return DPERR_ALREADYINITIALIZED;
4373 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE );
4376 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4377 ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
4379 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4381 /* This may not be externally invoked once either an SP or LP is initialized */
4382 if( This->dp2->connectionInitialized != NO_PROVIDER )
4384 return DPERR_ALREADYINITIALIZED;
4387 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE );
4390 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4391 ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4392 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4394 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4395 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4398 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4399 ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4400 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4402 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4403 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4406 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4407 ( LPDIRECTPLAY3A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4409 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4410 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4414 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4415 ( LPDIRECTPLAY3 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4417 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4418 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4422 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4423 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4425 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4426 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4430 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4431 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4433 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4434 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4438 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4439 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup )
4441 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4442 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, dwFlags, idGroup );
4446 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4447 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup )
4449 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4450 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, dwFlags, idGroup );
4454 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4455 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDWORD lpdwFlags )
4457 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4458 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpdwFlags );
4462 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4463 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDWORD lpdwFlags )
4465 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4466 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpdwFlags );
4470 static HRESULT DP_IF_GetGroupParent
4471 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
4474 lpGroupData lpGData;
4476 TRACE("(%p)->(0x%08x,%p,%u)\n", This, idGroup, lpidGroup, bAnsi );
4478 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4480 return DPERR_INVALIDGROUP;
4483 *lpidGroup = lpGData->dpid;
4488 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4489 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
4491 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4492 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE );
4494 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4495 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
4497 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4498 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE );
4501 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4502 ( LPDIRECTPLAY3A iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4504 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4505 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4509 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4510 ( LPDIRECTPLAY3 iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4512 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4513 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4517 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4518 ( LPDIRECTPLAY3A iface, DPID idPlayer, LPDWORD lpdwFlags )
4520 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4521 FIXME("(%p)->(0x%08x,%p): stub\n", This, idPlayer, lpdwFlags );
4525 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4526 ( LPDIRECTPLAY3 iface, DPID idPlayer, LPDWORD lpdwFlags )
4528 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4529 FIXME("(%p)->(0x%08x,%p): stub\n", This, idPlayer, lpdwFlags );
4533 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4534 ( LPDIRECTPLAY4A iface, DPID idGroup, LPDPID lpidGroupOwner )
4536 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4537 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpidGroupOwner );
4541 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4542 ( LPDIRECTPLAY4 iface, DPID idGroup, LPDPID lpidGroupOwner )
4544 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4545 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpidGroupOwner );
4549 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4550 ( LPDIRECTPLAY4A iface, DPID idGroup , DPID idGroupOwner )
4552 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4553 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, idGroup, idGroupOwner );
4557 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4558 ( LPDIRECTPLAY4 iface, DPID idGroup , DPID idGroupOwner )
4560 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4561 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, idGroup, idGroupOwner );
4565 static HRESULT DP_SendEx
4566 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4567 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4568 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi )
4570 BOOL bValidDestination = FALSE;
4572 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,0x%08x,0x%08x,0x%08x,%p,%p,%u)"
4574 This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority,
4575 dwTimeout, lpContext, lpdwMsgID, bAnsi );
4577 if( This->dp2->connectionInitialized == NO_PROVIDER )
4579 return DPERR_UNINITIALIZED;
4582 /* FIXME: Add parameter checking */
4583 /* FIXME: First call to this needs to acquire a message id which will be
4584 * used for multiple sends
4587 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4589 /* Verify that the message is being sent from a valid local player. The
4590 * from player may be anonymous DPID_UNKNOWN
4592 if( idFrom != DPID_UNKNOWN )
4594 if( DP_FindPlayer( This, idFrom ) == NULL )
4596 WARN( "INFO: Invalid from player 0x%08x\n", idFrom );
4597 return DPERR_INVALIDPLAYER;
4601 /* Verify that the message is being sent to a valid player, group or to
4602 * everyone. If it's valid, send it to those players.
4604 if( idTo == DPID_ALLPLAYERS )
4606 bValidDestination = TRUE;
4608 /* See if SP has the ability to multicast. If so, use it */
4609 if( This->dp2->spData.lpCB->SendToGroupEx )
4611 FIXME( "Use group sendex to group 0\n" );
4613 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4615 FIXME( "Use obsolete group send to group 0\n" );
4617 else /* No multicast, multiplicate */
4619 /* Send to all players we know about */
4620 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4624 if( ( !bValidDestination ) &&
4625 ( DP_FindPlayer( This, idTo ) != NULL )
4628 bValidDestination = TRUE;
4630 /* Have the service provider send this message */
4631 /* FIXME: Could optimize for local interface sends */
4632 return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority,
4633 dwTimeout, lpContext, lpdwMsgID );
4636 if( ( !bValidDestination ) &&
4637 ( DP_FindAnyGroup( This, idTo ) != NULL )
4640 bValidDestination = TRUE;
4642 /* See if SP has the ability to multicast. If so, use it */
4643 if( This->dp2->spData.lpCB->SendToGroupEx )
4645 FIXME( "Use group sendex\n" );
4647 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4649 FIXME( "Use obsolete group send to group\n" );
4651 else /* No multicast, multiplicate */
4653 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4661 This->dp2->hReplyEvent = CreateEventW( NULL, FALSE, FALSE, NULL );
4663 dwWaitReturn = WaitForSingleObject( hReplyEvent, dwTimeout );
4664 if( dwWaitReturn != WAIT_OBJECT_0 )
4666 ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
4672 if( !bValidDestination )
4674 return DPERR_INVALIDPLAYER;
4678 /* FIXME: Should return what the send returned */
4684 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4685 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4686 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4687 LPVOID lpContext, LPDWORD lpdwMsgID )
4689 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4690 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4691 dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE );
4694 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4695 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4696 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4697 LPVOID lpContext, LPDWORD lpdwMsgID )
4699 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4700 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4701 dwPriority, dwTimeout, lpContext, lpdwMsgID, FALSE );
4704 static HRESULT DP_SP_SendEx
4705 ( IDirectPlay2Impl* This, DWORD dwFlags,
4706 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4707 LPVOID lpContext, LPDWORD lpdwMsgID )
4711 FIXME( ": stub\n" );
4713 /* FIXME: This queuing should only be for async messages */
4715 lpMElem = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpMElem ) );
4716 lpMElem->msg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
4718 CopyMemory( lpMElem->msg, lpData, dwDataSize );
4720 /* FIXME: Need to queue based on priority */
4721 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
4726 static HRESULT DP_IF_GetMessageQueue
4727 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4728 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi )
4732 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%p,%u): semi stub\n",
4733 This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi );
4735 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4736 /* FIXME: What about sends which are not immediate? */
4738 if( This->dp2->spData.lpCB->GetMessageQueue )
4740 DPSP_GETMESSAGEQUEUEDATA data;
4742 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4744 /* FIXME: None of this is documented :( */
4746 data.lpISP = This->dp2->spData.lpISP;
4747 data.dwFlags = dwFlags;
4748 data.idFrom = idFrom;
4750 data.lpdwNumMsgs = lpdwNumMsgs;
4751 data.lpdwNumBytes = lpdwNumBytes;
4753 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
4757 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4763 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4764 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4765 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4767 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4768 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4769 lpdwNumBytes, TRUE );
4772 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4773 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4774 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4776 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4777 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4778 lpdwNumBytes, FALSE );
4781 static HRESULT DP_IF_CancelMessage
4782 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
4783 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi )
4787 FIXME( "(%p)->(0x%08x,0x%08x,%u): semi stub\n",
4788 This, dwMsgID, dwFlags, bAnsi );
4790 if( This->dp2->spData.lpCB->Cancel )
4792 DPSP_CANCELDATA data;
4794 TRACE( "Calling SP Cancel\n" );
4796 /* FIXME: Undocumented callback */
4798 data.lpISP = This->dp2->spData.lpISP;
4799 data.dwFlags = dwFlags;
4800 data.lprglpvSPMsgID = NULL;
4801 data.cSPMsgID = dwMsgID;
4802 data.dwMinPriority = dwMinPriority;
4803 data.dwMaxPriority = dwMaxPriority;
4805 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
4809 FIXME( "SP doesn't implement Cancel\n" );
4815 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
4816 ( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags )
4818 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4822 return DPERR_INVALIDFLAGS;
4827 dwFlags |= DPCANCELSEND_ALL;
4830 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE );
4833 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
4834 ( LPDIRECTPLAY4 iface, DWORD dwMsgID, DWORD dwFlags )
4836 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4840 return DPERR_INVALIDFLAGS;
4845 dwFlags |= DPCANCELSEND_ALL;
4848 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, FALSE );
4851 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
4852 ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4855 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4859 return DPERR_INVALIDFLAGS;
4862 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4863 dwMaxPriority, TRUE );
4866 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
4867 ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4870 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4874 return DPERR_INVALIDFLAGS;
4877 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4878 dwMaxPriority, FALSE );
4881 /* Note: Hack so we can reuse the old functions without compiler warnings */
4882 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4883 # define XCAST(fun) (typeof(directPlay2WVT.fun))
4885 # define XCAST(fun) (void*)
4888 static const IDirectPlay2Vtbl directPlay2WVT =
4890 XCAST(QueryInterface)DP_QueryInterface,
4891 XCAST(AddRef)DP_AddRef,
4892 XCAST(Release)DP_Release,
4894 DirectPlay2WImpl_AddPlayerToGroup,
4895 DirectPlay2WImpl_Close,
4896 DirectPlay2WImpl_CreateGroup,
4897 DirectPlay2WImpl_CreatePlayer,
4898 DirectPlay2WImpl_DeletePlayerFromGroup,
4899 DirectPlay2WImpl_DestroyGroup,
4900 DirectPlay2WImpl_DestroyPlayer,
4901 DirectPlay2WImpl_EnumGroupPlayers,
4902 DirectPlay2WImpl_EnumGroups,
4903 DirectPlay2WImpl_EnumPlayers,
4904 DirectPlay2WImpl_EnumSessions,
4905 DirectPlay2WImpl_GetCaps,
4906 DirectPlay2WImpl_GetGroupData,
4907 DirectPlay2WImpl_GetGroupName,
4908 DirectPlay2WImpl_GetMessageCount,
4909 DirectPlay2WImpl_GetPlayerAddress,
4910 DirectPlay2WImpl_GetPlayerCaps,
4911 DirectPlay2WImpl_GetPlayerData,
4912 DirectPlay2WImpl_GetPlayerName,
4913 DirectPlay2WImpl_GetSessionDesc,
4914 DirectPlay2WImpl_Initialize,
4915 DirectPlay2WImpl_Open,
4916 DirectPlay2WImpl_Receive,
4917 DirectPlay2WImpl_Send,
4918 DirectPlay2WImpl_SetGroupData,
4919 DirectPlay2WImpl_SetGroupName,
4920 DirectPlay2WImpl_SetPlayerData,
4921 DirectPlay2WImpl_SetPlayerName,
4922 DirectPlay2WImpl_SetSessionDesc
4926 /* Note: Hack so we can reuse the old functions without compiler warnings */
4927 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4928 # define XCAST(fun) (typeof(directPlay2AVT.fun))
4930 # define XCAST(fun) (void*)
4933 static const IDirectPlay2Vtbl directPlay2AVT =
4935 XCAST(QueryInterface)DP_QueryInterface,
4936 XCAST(AddRef)DP_AddRef,
4937 XCAST(Release)DP_Release,
4939 DirectPlay2AImpl_AddPlayerToGroup,
4940 DirectPlay2AImpl_Close,
4941 DirectPlay2AImpl_CreateGroup,
4942 DirectPlay2AImpl_CreatePlayer,
4943 DirectPlay2AImpl_DeletePlayerFromGroup,
4944 DirectPlay2AImpl_DestroyGroup,
4945 DirectPlay2AImpl_DestroyPlayer,
4946 DirectPlay2AImpl_EnumGroupPlayers,
4947 DirectPlay2AImpl_EnumGroups,
4948 DirectPlay2AImpl_EnumPlayers,
4949 DirectPlay2AImpl_EnumSessions,
4950 DirectPlay2AImpl_GetCaps,
4951 DirectPlay2AImpl_GetGroupData,
4952 DirectPlay2AImpl_GetGroupName,
4953 DirectPlay2AImpl_GetMessageCount,
4954 DirectPlay2AImpl_GetPlayerAddress,
4955 DirectPlay2AImpl_GetPlayerCaps,
4956 DirectPlay2AImpl_GetPlayerData,
4957 DirectPlay2AImpl_GetPlayerName,
4958 DirectPlay2AImpl_GetSessionDesc,
4959 DirectPlay2AImpl_Initialize,
4960 DirectPlay2AImpl_Open,
4961 DirectPlay2AImpl_Receive,
4962 DirectPlay2AImpl_Send,
4963 DirectPlay2AImpl_SetGroupData,
4964 DirectPlay2AImpl_SetGroupName,
4965 DirectPlay2AImpl_SetPlayerData,
4966 DirectPlay2AImpl_SetPlayerName,
4967 DirectPlay2AImpl_SetSessionDesc
4972 /* Note: Hack so we can reuse the old functions without compiler warnings */
4973 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4974 # define XCAST(fun) (typeof(directPlay3AVT.fun))
4976 # define XCAST(fun) (void*)
4979 static const IDirectPlay3Vtbl directPlay3AVT =
4981 XCAST(QueryInterface)DP_QueryInterface,
4982 XCAST(AddRef)DP_AddRef,
4983 XCAST(Release)DP_Release,
4985 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
4986 XCAST(Close)DirectPlay2AImpl_Close,
4987 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
4988 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
4989 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
4990 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
4991 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
4992 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
4993 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
4994 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
4995 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
4996 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
4997 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
4998 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
4999 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5000 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5001 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5002 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5003 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5004 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5005 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5006 XCAST(Open)DirectPlay2AImpl_Open,
5007 XCAST(Receive)DirectPlay2AImpl_Receive,
5008 XCAST(Send)DirectPlay2AImpl_Send,
5009 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5010 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5011 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5012 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5013 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5015 DirectPlay3AImpl_AddGroupToGroup,
5016 DirectPlay3AImpl_CreateGroupInGroup,
5017 DirectPlay3AImpl_DeleteGroupFromGroup,
5018 DirectPlay3AImpl_EnumConnections,
5019 DirectPlay3AImpl_EnumGroupsInGroup,
5020 DirectPlay3AImpl_GetGroupConnectionSettings,
5021 DirectPlay3AImpl_InitializeConnection,
5022 DirectPlay3AImpl_SecureOpen,
5023 DirectPlay3AImpl_SendChatMessage,
5024 DirectPlay3AImpl_SetGroupConnectionSettings,
5025 DirectPlay3AImpl_StartSession,
5026 DirectPlay3AImpl_GetGroupFlags,
5027 DirectPlay3AImpl_GetGroupParent,
5028 DirectPlay3AImpl_GetPlayerAccount,
5029 DirectPlay3AImpl_GetPlayerFlags
5033 /* Note: Hack so we can reuse the old functions without compiler warnings */
5034 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5035 # define XCAST(fun) (typeof(directPlay3WVT.fun))
5037 # define XCAST(fun) (void*)
5039 static const IDirectPlay3Vtbl directPlay3WVT =
5041 XCAST(QueryInterface)DP_QueryInterface,
5042 XCAST(AddRef)DP_AddRef,
5043 XCAST(Release)DP_Release,
5045 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
5046 XCAST(Close)DirectPlay2WImpl_Close,
5047 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
5048 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
5049 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
5050 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
5051 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5052 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5053 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5054 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5055 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5056 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5057 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5058 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5059 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5060 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5061 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5062 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5063 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5064 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5065 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5066 XCAST(Open)DirectPlay2WImpl_Open,
5067 XCAST(Receive)DirectPlay2WImpl_Receive,
5068 XCAST(Send)DirectPlay2WImpl_Send,
5069 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5070 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5071 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5072 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5073 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5075 DirectPlay3WImpl_AddGroupToGroup,
5076 DirectPlay3WImpl_CreateGroupInGroup,
5077 DirectPlay3WImpl_DeleteGroupFromGroup,
5078 DirectPlay3WImpl_EnumConnections,
5079 DirectPlay3WImpl_EnumGroupsInGroup,
5080 DirectPlay3WImpl_GetGroupConnectionSettings,
5081 DirectPlay3WImpl_InitializeConnection,
5082 DirectPlay3WImpl_SecureOpen,
5083 DirectPlay3WImpl_SendChatMessage,
5084 DirectPlay3WImpl_SetGroupConnectionSettings,
5085 DirectPlay3WImpl_StartSession,
5086 DirectPlay3WImpl_GetGroupFlags,
5087 DirectPlay3WImpl_GetGroupParent,
5088 DirectPlay3WImpl_GetPlayerAccount,
5089 DirectPlay3WImpl_GetPlayerFlags
5093 /* Note: Hack so we can reuse the old functions without compiler warnings */
5094 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5095 # define XCAST(fun) (typeof(directPlay4WVT.fun))
5097 # define XCAST(fun) (void*)
5099 static const IDirectPlay4Vtbl directPlay4WVT =
5101 XCAST(QueryInterface)DP_QueryInterface,
5102 XCAST(AddRef)DP_AddRef,
5103 XCAST(Release)DP_Release,
5105 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
5106 XCAST(Close)DirectPlay2WImpl_Close,
5107 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
5108 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
5109 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
5110 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
5111 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5112 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5113 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5114 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5115 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5116 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5117 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5118 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5119 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5120 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5121 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5122 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5123 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5124 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5125 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5126 XCAST(Open)DirectPlay2WImpl_Open,
5127 XCAST(Receive)DirectPlay2WImpl_Receive,
5128 XCAST(Send)DirectPlay2WImpl_Send,
5129 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5130 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5131 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5132 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5133 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5135 XCAST(AddGroupToGroup)DirectPlay3WImpl_AddGroupToGroup,
5136 XCAST(CreateGroupInGroup)DirectPlay3WImpl_CreateGroupInGroup,
5137 XCAST(DeleteGroupFromGroup)DirectPlay3WImpl_DeleteGroupFromGroup,
5138 XCAST(EnumConnections)DirectPlay3WImpl_EnumConnections,
5139 XCAST(EnumGroupsInGroup)DirectPlay3WImpl_EnumGroupsInGroup,
5140 XCAST(GetGroupConnectionSettings)DirectPlay3WImpl_GetGroupConnectionSettings,
5141 XCAST(InitializeConnection)DirectPlay3WImpl_InitializeConnection,
5142 XCAST(SecureOpen)DirectPlay3WImpl_SecureOpen,
5143 XCAST(SendChatMessage)DirectPlay3WImpl_SendChatMessage,
5144 XCAST(SetGroupConnectionSettings)DirectPlay3WImpl_SetGroupConnectionSettings,
5145 XCAST(StartSession)DirectPlay3WImpl_StartSession,
5146 XCAST(GetGroupFlags)DirectPlay3WImpl_GetGroupFlags,
5147 XCAST(GetGroupParent)DirectPlay3WImpl_GetGroupParent,
5148 XCAST(GetPlayerAccount)DirectPlay3WImpl_GetPlayerAccount,
5149 XCAST(GetPlayerFlags)DirectPlay3WImpl_GetPlayerFlags,
5151 DirectPlay4WImpl_GetGroupOwner,
5152 DirectPlay4WImpl_SetGroupOwner,
5153 DirectPlay4WImpl_SendEx,
5154 DirectPlay4WImpl_GetMessageQueue,
5155 DirectPlay4WImpl_CancelMessage,
5156 DirectPlay4WImpl_CancelPriority
5161 /* Note: Hack so we can reuse the old functions without compiler warnings */
5162 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5163 # define XCAST(fun) (typeof(directPlay4AVT.fun))
5165 # define XCAST(fun) (void*)
5167 static const IDirectPlay4Vtbl directPlay4AVT =
5169 XCAST(QueryInterface)DP_QueryInterface,
5170 XCAST(AddRef)DP_AddRef,
5171 XCAST(Release)DP_Release,
5173 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
5174 XCAST(Close)DirectPlay2AImpl_Close,
5175 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
5176 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
5177 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
5178 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
5179 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
5180 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
5181 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
5182 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
5183 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
5184 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
5185 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
5186 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
5187 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5188 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5189 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5190 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5191 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5192 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5193 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5194 XCAST(Open)DirectPlay2AImpl_Open,
5195 XCAST(Receive)DirectPlay2AImpl_Receive,
5196 XCAST(Send)DirectPlay2AImpl_Send,
5197 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5198 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5199 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5200 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5201 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5203 XCAST(AddGroupToGroup)DirectPlay3AImpl_AddGroupToGroup,
5204 XCAST(CreateGroupInGroup)DirectPlay3AImpl_CreateGroupInGroup,
5205 XCAST(DeleteGroupFromGroup)DirectPlay3AImpl_DeleteGroupFromGroup,
5206 XCAST(EnumConnections)DirectPlay3AImpl_EnumConnections,
5207 XCAST(EnumGroupsInGroup)DirectPlay3AImpl_EnumGroupsInGroup,
5208 XCAST(GetGroupConnectionSettings)DirectPlay3AImpl_GetGroupConnectionSettings,
5209 XCAST(InitializeConnection)DirectPlay3AImpl_InitializeConnection,
5210 XCAST(SecureOpen)DirectPlay3AImpl_SecureOpen,
5211 XCAST(SendChatMessage)DirectPlay3AImpl_SendChatMessage,
5212 XCAST(SetGroupConnectionSettings)DirectPlay3AImpl_SetGroupConnectionSettings,
5213 XCAST(StartSession)DirectPlay3AImpl_StartSession,
5214 XCAST(GetGroupFlags)DirectPlay3AImpl_GetGroupFlags,
5215 XCAST(GetGroupParent)DirectPlay3AImpl_GetGroupParent,
5216 XCAST(GetPlayerAccount)DirectPlay3AImpl_GetPlayerAccount,
5217 XCAST(GetPlayerFlags)DirectPlay3AImpl_GetPlayerFlags,
5219 DirectPlay4AImpl_GetGroupOwner,
5220 DirectPlay4AImpl_SetGroupOwner,
5221 DirectPlay4AImpl_SendEx,
5222 DirectPlay4AImpl_GetMessageQueue,
5223 DirectPlay4AImpl_CancelMessage,
5224 DirectPlay4AImpl_CancelPriority
5228 HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP,
5232 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5234 if( lpPlayer == NULL )
5236 return DPERR_INVALIDPLAYER;
5239 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
5244 HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP,
5248 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5250 if( lpPlayer == NULL )
5252 return DPERR_INVALIDPLAYER;
5255 lpPlayer->lpPData->lpSPPlayerData = lpData;
5260 /***************************************************************************
5261 * DirectPlayEnumerateAW
5263 * The pointer to the structure lpContext will be filled with the
5264 * appropriate data for each service offered by the OS. These services are
5265 * not necessarily available on this particular machine but are defined
5266 * as simple service providers under the "Service Providers" registry key.
5267 * This structure is then passed to lpEnumCallback for each of the different
5270 * This API is useful only for applications written using DirectX3 or
5271 * worse. It is superseded by IDirectPlay3::EnumConnections which also
5272 * gives information on the actual connections.
5274 * defn of a service provider:
5275 * A dynamic-link library used by DirectPlay to communicate over a network.
5276 * The service provider contains all the network-specific code required
5277 * to send and receive messages. Online services and network operators can
5278 * supply service providers to use specialized hardware, protocols, communications
5279 * media, and network resources.
5282 static HRESULT DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA,
5283 LPDPENUMDPCALLBACKW lpEnumCallbackW,
5287 static const WCHAR searchSubKey[] = {
5288 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
5289 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
5290 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
5291 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
5292 static const WCHAR guidKey[] = { 'G', 'u', 'i', 'd', 0 };
5293 static const WCHAR descW[] = { 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', 'W', 0 };
5298 char *descriptionA = NULL;
5299 DWORD max_sizeOfDescriptionA = 0;
5300 WCHAR *descriptionW = NULL;
5301 DWORD max_sizeOfDescriptionW = 0;
5303 if (!lpEnumCallbackA && !lpEnumCallbackW)
5305 return DPERR_INVALIDPARAMS;
5308 /* Need to loop over the service providers in the registry */
5309 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, searchSubKey,
5310 0, KEY_READ, &hkResult) != ERROR_SUCCESS)
5312 /* Hmmm. Does this mean that there are no service providers? */
5313 ERR(": no service provider key in the registry - check your Wine installation !!!\n");
5314 return DPERR_GENERIC;
5317 /* Traverse all the service providers we have available */
5321 WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */
5322 DWORD sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR);
5323 HKEY hkServiceProvider;
5324 GUID serviceProviderGUID;
5325 WCHAR guidKeyContent[(2 * 16) + 1 + 6 /* This corresponds to '{....-..-..-..-......}' */ ];
5326 DWORD sizeOfGuidKeyContent = sizeof(guidKeyContent);
5329 ret_value = RegEnumKeyExW(hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
5330 NULL, NULL, NULL, &filetime);
5331 if (ret_value == ERROR_NO_MORE_ITEMS)
5333 else if (ret_value != ERROR_SUCCESS)
5335 ERR(": could not enumerate on service provider key.\n");
5336 return DPERR_EXCEPTION;
5338 TRACE(" this time through sub-key %s.\n", debugstr_w(subKeyName));
5340 /* Open the key for this service provider */
5341 if (RegOpenKeyExW(hkResult, subKeyName, 0, KEY_READ, &hkServiceProvider) != ERROR_SUCCESS)
5343 ERR(": could not open registry key for service provider %s.\n", debugstr_w(subKeyName));
5347 /* Get the GUID from the registry */
5348 if (RegQueryValueExW(hkServiceProvider, guidKey,
5349 NULL, NULL, (LPBYTE) guidKeyContent, &sizeOfGuidKeyContent) != ERROR_SUCCESS)
5351 ERR(": missing GUID registry data member for service provider %s.\n", debugstr_w(subKeyName));
5354 if (sizeOfGuidKeyContent != sizeof(guidKeyContent))
5356 ERR(": invalid format for the GUID registry data member for service provider %s (%s).\n", debugstr_w(subKeyName), debugstr_w(guidKeyContent));
5359 CLSIDFromString(guidKeyContent, &serviceProviderGUID );
5361 /* The enumeration will return FALSE if we are not to continue.
5363 * Note: on my windows box, major / minor version is 6 / 0 for all service providers
5364 * and have no relation to any of the two dwReserved1 and dwReserved2 keys.
5365 * I think that it simply means that they are in-line with DirectX 6.0
5367 if (lpEnumCallbackA)
5369 DWORD sizeOfDescription = 0;
5371 /* Note that this is the A case of this function, so use the A variant to get the description string */
5372 if (RegQueryValueExA(hkServiceProvider, "DescriptionA",
5373 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5375 ERR(": missing 'DescriptionA' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5378 if (sizeOfDescription > max_sizeOfDescriptionA)
5380 HeapFree(GetProcessHeap(), 0, descriptionA);
5381 max_sizeOfDescriptionA = sizeOfDescription;
5383 descriptionA = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5384 RegQueryValueExA(hkServiceProvider, "DescriptionA",
5385 NULL, NULL, (LPBYTE) descriptionA, &sizeOfDescription);
5387 if (!lpEnumCallbackA(&serviceProviderGUID, descriptionA, 6, 0, lpContext))
5392 DWORD sizeOfDescription = 0;
5394 if (RegQueryValueExW(hkServiceProvider, descW,
5395 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5397 ERR(": missing 'DescriptionW' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5400 if (sizeOfDescription > max_sizeOfDescriptionW)
5402 HeapFree(GetProcessHeap(), 0, descriptionW);
5403 max_sizeOfDescriptionW = sizeOfDescription;
5405 descriptionW = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5406 RegQueryValueExW(hkServiceProvider, descW,
5407 NULL, NULL, (LPBYTE) descriptionW, &sizeOfDescription);
5409 if (!lpEnumCallbackW(&serviceProviderGUID, descriptionW, 6, 0, lpContext))
5417 HeapFree(GetProcessHeap(), 0, descriptionA);
5418 HeapFree(GetProcessHeap(), 0, descriptionW);
5423 /***************************************************************************
5424 * DirectPlayEnumerate [DPLAYX.9]
5425 * DirectPlayEnumerateA [DPLAYX.2]
5427 HRESULT WINAPI DirectPlayEnumerateA(LPDPENUMDPCALLBACKA lpEnumCallback, LPVOID lpContext )
5429 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5431 return DirectPlayEnumerateAW(lpEnumCallback, NULL, lpContext);
5434 /***************************************************************************
5435 * DirectPlayEnumerateW [DPLAYX.3]
5437 HRESULT WINAPI DirectPlayEnumerateW(LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5439 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5441 return DirectPlayEnumerateAW(NULL, lpEnumCallback, lpContext);
5444 typedef struct tagCreateEnum
5448 } CreateEnumData, *lpCreateEnumData;
5450 /* Find and copy the matching connection for the SP guid */
5451 static BOOL CALLBACK cbDPCreateEnumConnections(
5453 LPVOID lpConnection,
5454 DWORD dwConnectionSize,
5459 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5461 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5463 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5465 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5467 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5469 /* Found the record that we were looking for */
5473 /* Haven't found what were looking for yet */
5478 /***************************************************************************
5479 * DirectPlayCreate [DPLAYX.1]
5482 HRESULT WINAPI DirectPlayCreate
5483 ( LPGUID lpGUID, LPDIRECTPLAY *lplpDP, IUnknown *pUnk )
5486 LPDIRECTPLAY3A lpDP3A;
5487 CreateEnumData cbData;
5489 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5493 return CLASS_E_NOAGGREGATION;
5496 if( (lplpDP == NULL) || (lpGUID == NULL) )
5498 return DPERR_INVALIDPARAMS;
5502 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5503 give them an IDirectPlay2A object and hope that doesn't cause problems */
5504 if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
5506 return DPERR_UNAVAILABLE;
5509 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
5511 /* The GUID_NULL means don't bind a service provider. Just return the
5516 /* Bind the desired service provider since lpGUID is non NULL */
5517 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
5519 /* We're going to use a DP3 interface */
5520 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
5524 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
5528 cbData.lpConn = NULL;
5529 cbData.lpGuid = lpGUID;
5531 /* We were given a service provider, find info about it... */
5532 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
5533 &cbData, DPCONNECTION_DIRECTPLAY );
5534 if( ( FAILED(hr) ) ||
5535 ( cbData.lpConn == NULL )
5538 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
5539 IDirectPlayX_Release( lpDP3A );
5540 return DPERR_UNAVAILABLE;
5543 /* Initialize the service provider */
5544 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
5547 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
5548 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5549 IDirectPlayX_Release( lpDP3A );
5553 /* Release our version of the interface now that we're done with it */
5554 IDirectPlayX_Release( lpDP3A );
5555 HeapFree( GetProcessHeap(), 0, cbData.lpConn );