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"
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, LPDPNAME lpSrc, BOOL bAnsi );
58 static void DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
59 LPVOID lpData, DWORD dwDataSize );
61 static lpGroupData DP_CreateGroup( IDirectPlay2AImpl* iface, LPDPID lpid,
62 LPDPNAME 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 WINAPI DP_IF_DeletePlayerFromGroup
90 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
91 DPID idPlayer, BOOL bAnsi );
92 static HRESULT WINAPI 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 WINAPI DP_IF_DestroyGroup
97 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi );
98 static HRESULT WINAPI DP_IF_DestroyPlayer
99 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi );
100 static HRESULT WINAPI DP_IF_EnumGroupPlayers
101 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
102 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
103 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
104 static HRESULT WINAPI DP_IF_EnumGroups
105 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
106 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
107 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
108 static HRESULT WINAPI DP_IF_EnumPlayers
109 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
110 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
111 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
112 static HRESULT WINAPI DP_IF_GetGroupData
113 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
114 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
115 static HRESULT WINAPI DP_IF_GetGroupName
116 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
117 LPDWORD lpdwDataSize, BOOL bAnsi );
118 static HRESULT WINAPI DP_IF_GetPlayerData
119 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
120 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
121 static HRESULT WINAPI DP_IF_GetPlayerName
122 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
123 LPDWORD lpdwDataSize, BOOL bAnsi );
124 static HRESULT WINAPI DP_IF_SetGroupName
125 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
126 DWORD dwFlags, BOOL bAnsi );
127 static HRESULT WINAPI DP_IF_SetPlayerData
128 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
129 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
130 static HRESULT WINAPI DP_IF_SetPlayerName
131 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
132 DWORD dwFlags, BOOL bAnsi );
133 static HRESULT WINAPI DP_IF_AddGroupToGroup
134 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
135 static HRESULT WINAPI 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 WINAPI 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 WINAPI DP_IF_AddPlayerToGroup
144 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
145 DPID idPlayer, BOOL bAnsi );
146 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
147 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
148 static HRESULT WINAPI DP_SetSessionDesc
149 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
150 DWORD dwFlags, BOOL bInitial, BOOL bAnsi );
151 static HRESULT WINAPI DP_SecureOpen
152 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
153 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
155 static HRESULT WINAPI 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 WINAPI DP_IF_Receive
160 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
161 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi );
162 static HRESULT WINAPI DP_IF_GetMessageQueue
163 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
164 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi );
165 static HRESULT WINAPI 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 WINAPI DP_IF_SetGroupData
170 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
171 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
172 static HRESULT WINAPI DP_IF_GetPlayerCaps
173 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
175 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi );
176 static HRESULT WINAPI DP_IF_CancelMessage
177 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
178 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi );
179 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
180 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
181 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
182 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
183 static HRESULT WINAPI DP_IF_GetGroupParent
184 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
186 static HRESULT WINAPI DP_IF_GetCaps
187 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags );
188 static HRESULT WINAPI DP_IF_EnumSessions
189 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
190 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
191 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
192 static HRESULT WINAPI 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 WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
198 LPDWORD lpdwBufSize );
202 static inline DPID DP_NextObjectId(void);
203 static DPID DP_GetRemoteNextObjectId(void);
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 = (IDirectPlay2AImpl *)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 = (IDirectPlay2AImpl *)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 = (IDirectPlay2AImpl *)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;
276 This->dp2->bHostInterface = FALSE;
278 DPQ_INIT(This->dp2->receiveMsgs);
279 DPQ_INIT(This->dp2->sendMsgs);
280 DPQ_INIT(This->dp2->replysExpected);
282 if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
284 /* FIXME: Memory leak */
288 /* Provide an initial session desc with nothing in it */
289 This->dp2->lpSessionDesc = HeapAlloc( GetProcessHeap(),
291 sizeof( *This->dp2->lpSessionDesc ) );
292 if( This->dp2->lpSessionDesc == NULL )
294 /* FIXME: Memory leak */
297 This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc );
299 /* We are emulating a dp 6 implementation */
300 This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION;
302 This->dp2->spData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
303 sizeof( *This->dp2->spData.lpCB ) );
304 This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB );
305 This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION;
307 /* This is the pointer to the service provider */
308 if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP,
309 (LPVOID*)&This->dp2->spData.lpISP, This ) )
312 /* FIXME: Memory leak */
316 /* Setup lobby provider information */
317 This->dp2->dplspData.dwSPVersion = DPSP_MAJORVERSION;
318 This->dp2->dplspData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
319 sizeof( *This->dp2->dplspData.lpCB ) );
320 This->dp2->dplspData.lpCB->dwSize = sizeof( *This->dp2->dplspData.lpCB );
322 if( FAILED( DPLSP_CreateInterface( &IID_IDPLobbySP,
323 (LPVOID*)&This->dp2->dplspData.lpISP, This ) )
326 /* FIXME: Memory leak */
333 /* Definition of the global function in dplayx_queue.h. #
334 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
335 DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
337 HeapFree( GetProcessHeap(), 0, elem );
340 /* Function to delete the list of groups with this interface. Needs to
341 * delete the group and player lists associated with this group as well
342 * as the group data associated with this group. It should not delete
343 * player data as that is shared with the top player list and will be
346 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList );
347 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList )
349 DPQ_DELETEQ( elem->lpGData->groups, groups,
350 lpGroupList, cbDeleteElemFromHeap );
351 DPQ_DELETEQ( elem->lpGData->players, players,
352 lpPlayerList, cbDeleteElemFromHeap );
353 HeapFree( GetProcessHeap(), 0, elem->lpGData );
354 HeapFree( GetProcessHeap(), 0, elem );
357 /* Function to delete the list of players with this interface. Needs to
358 * delete the player data for all players as well.
360 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList );
361 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList )
363 HeapFree( GetProcessHeap(), 0, elem->lpPData );
364 HeapFree( GetProcessHeap(), 0, elem );
367 static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
369 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;
371 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
373 TerminateThread( This->dp2->hEnumSessionThread, 0 );
374 CloseHandle( This->dp2->hEnumSessionThread );
377 /* Finish with the SP - have it shutdown */
378 if( This->dp2->spData.lpCB->ShutdownEx )
380 DPSP_SHUTDOWNDATA data;
382 TRACE( "Calling SP ShutdownEx\n" );
384 data.lpISP = This->dp2->spData.lpISP;
386 (*This->dp2->spData.lpCB->ShutdownEx)( &data );
388 else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
390 TRACE( "Calling obsolete SP Shutdown\n" );
391 (*This->dp2->spData.lpCB->Shutdown)();
394 /* Unload the SP (if it exists) */
395 if( This->dp2->hServiceProvider != 0 )
397 FreeLibrary( This->dp2->hServiceProvider );
400 /* Unload the Lobby Provider (if it exists) */
401 if( This->dp2->hDPLobbyProvider != 0 )
403 FreeLibrary( This->dp2->hDPLobbyProvider );
407 DPQ_DELETEQ( This->dp2->players, players, lpPlayerList, cbDeletePlayerElem );
408 DPQ_DELETEQ( This->dp2->groups, groups, lpGroupList, cbDeleteGroupsElem );
411 /* FIXME: Need to delete receive and send msgs queue contents */
413 NS_DeleteSessionCache( This->dp2->lpNameServerData );
415 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
417 IDirectPlaySP_Release( This->dp2->spData.lpISP );
419 /* Delete the contents */
420 HeapFree( GetProcessHeap(), 0, This->dp2 );
425 static BOOL DP_CreateDirectPlay3( LPVOID lpDP )
427 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;
429 This->dp3 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp3) ) );
430 if ( This->dp3 == NULL )
438 static BOOL DP_DestroyDirectPlay3( LPVOID lpDP )
440 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;
442 /* Delete the contents */
443 HeapFree( GetProcessHeap(), 0, This->dp3 );
448 static BOOL DP_CreateDirectPlay4( LPVOID lpDP )
450 IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)lpDP;
452 This->dp4 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp4) ) );
453 if ( This->dp4 == NULL )
461 static BOOL DP_DestroyDirectPlay4( LPVOID lpDP )
463 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;
465 /* Delete the contents */
466 HeapFree( GetProcessHeap(), 0, This->dp4 );
472 /* 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 = (IDirectPlay2Impl *)*ppvObj;
490 This->lpVtbl = &directPlay2WVT;
492 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
494 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)*ppvObj;
495 This->lpVtbl = &directPlay2AVT;
497 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
499 IDirectPlay3Impl *This = (IDirectPlay3Impl *)*ppvObj;
500 This->lpVtbl = &directPlay3WVT;
502 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
504 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)*ppvObj;
505 This->lpVtbl = &directPlay3AVT;
507 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
509 IDirectPlay4Impl *This = (IDirectPlay4Impl *)*ppvObj;
510 This->lpVtbl = &directPlay4WVT;
512 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
514 IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)*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 = (IDirectPlay2Impl *)*ppvObj;
574 This->lpVtbl = &directPlay2WVT;
576 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
578 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)*ppvObj;
579 This->lpVtbl = &directPlay2AVT;
581 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
583 IDirectPlay3Impl *This = (IDirectPlay3Impl *)*ppvObj;
584 This->lpVtbl = &directPlay3WVT;
586 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
588 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)*ppvObj;
589 This->lpVtbl = &directPlay3AVT;
591 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
593 IDirectPlay4Impl *This = (IDirectPlay4Impl *)*ppvObj;
594 This->lpVtbl = &directPlay4WVT;
596 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
598 IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)*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 =
704 (LPCDPMSG_REQUESTNEWPLAYERID)lpcMessageBody;
706 LPDPMSG_NEWPLAYERIDREPLY lpReply;
708 *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
710 *lplpReply = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, *lpdwMsgSize );
712 FIXME( "Ignoring dwFlags 0x%08x in request msg\n",
715 /* Setup the reply */
716 lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) +
717 This->dp2->spData.dwSPHeaderSize );
719 lpReply->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
720 lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY;
721 lpReply->envelope.wVersion = DPMSGVER_DP6;
723 lpReply->dpidNewPlayerId = DP_NextObjectId();
725 TRACE( "Allocating new playerid 0x%08x from remote request\n",
726 lpReply->dpidNewPlayerId );
731 case DPMSGCMD_GETNAMETABLEREPLY:
732 case DPMSGCMD_NEWPLAYERIDREPLY:
736 if( wCommandId == DPMSGCMD_NEWPLAYERIDREPLY )
739 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
745 case DPMSGCMD_JUSTENVELOPE:
747 TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08x\n", lpcMessageHeader, ((const DWORD *)lpcMessageHeader)[1] );
748 NS_SetLocalAddr( This->dp2->lpNameServerData, lpcMessageHeader, 20 );
749 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
753 case DPMSGCMD_FORWARDADDPLAYER:
759 TRACE( "Sending message to self to get my addr\n" );
760 DP_MSG_ToSelf( This, 1 ); /* This is a hack right now */
765 case DPMSGCMD_FORWARDADDPLAYERNACK:
767 DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
773 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
779 /* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */
785 static HRESULT WINAPI DP_IF_AddPlayerToGroup
786 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
787 DPID idPlayer, BOOL bAnsi )
790 lpPlayerList lpPList;
791 lpPlayerList lpNewPList;
793 TRACE( "(%p)->(%p,0x%08x,0x%08x,%u)\n",
794 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
797 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
799 return DPERR_INVALIDGROUP;
802 /* Find the player */
803 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
805 return DPERR_INVALIDPLAYER;
808 /* Create a player list (ie "shortcut" ) */
809 lpNewPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewPList ) );
810 if( lpNewPList == NULL )
812 return DPERR_CANTADDPLAYER;
815 /* Add the shortcut */
816 lpPList->lpPData->uRef++;
817 lpNewPList->lpPData = lpPList->lpPData;
819 /* Add the player to the list of players for this group */
820 DPQ_INSERT(lpGData->players,lpNewPList,players);
822 /* Let the SP know that we've added a player to the group */
823 if( This->dp2->spData.lpCB->AddPlayerToGroup )
825 DPSP_ADDPLAYERTOGROUPDATA data;
827 TRACE( "Calling SP AddPlayerToGroup\n" );
829 data.idPlayer = idPlayer;
830 data.idGroup = idGroup;
831 data.lpISP = This->dp2->spData.lpISP;
833 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
836 /* Inform all other peers of the addition of player to the group. If there are
837 * no peers keep this event quiet.
838 * Also, if this event was the result of another machine sending it to us,
839 * don't bother rebroadcasting it.
841 if( ( lpMsgHdr == NULL ) &&
842 This->dp2->lpSessionDesc &&
843 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
845 DPMSG_ADDPLAYERTOGROUP msg;
846 msg.dwType = DPSYS_ADDPLAYERTOGROUP;
848 msg.dpIdGroup = idGroup;
849 msg.dpIdPlayer = idPlayer;
851 /* FIXME: Correct to just use send effectively? */
852 /* FIXME: Should size include data w/ message or just message "header" */
853 /* FIXME: Check return code */
854 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
860 static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
861 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
863 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
864 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, TRUE );
867 static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
868 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
870 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
871 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, FALSE );
874 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi )
878 TRACE("(%p)->(%u)\n", This, bAnsi );
880 /* FIXME: Need to find a new host I assume (how?) */
881 /* FIXME: Need to destroy all local groups */
882 /* FIXME: Need to migrate all remotely visible players to the new host */
884 /* Invoke the SP callback to inform of session close */
885 if( This->dp2->spData.lpCB->CloseEx )
889 TRACE( "Calling SP CloseEx\n" );
891 data.lpISP = This->dp2->spData.lpISP;
893 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
896 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
898 TRACE( "Calling SP Close (obsolete interface)\n" );
900 hr = (*This->dp2->spData.lpCB->Close)();
906 static HRESULT WINAPI DirectPlay2AImpl_Close
907 ( LPDIRECTPLAY2A iface )
909 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
910 return DP_IF_Close( This, TRUE );
913 static HRESULT WINAPI DirectPlay2WImpl_Close
914 ( LPDIRECTPLAY2 iface )
916 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
917 return DP_IF_Close( This, FALSE );
921 lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, LPDPID lpid,
922 LPDPNAME lpName, DWORD dwFlags,
923 DPID idParent, BOOL bAnsi )
927 /* Allocate the new space and add to end of high level group list */
928 lpGData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGData ) );
930 if( lpGData == NULL )
935 DPQ_INIT(lpGData->groups);
936 DPQ_INIT(lpGData->players);
938 /* Set the desired player ID - no sanity checking to see if it exists */
939 lpGData->dpid = *lpid;
941 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
943 /* FIXME: Should we check that the parent exists? */
944 lpGData->parent = idParent;
946 /* FIXME: Should we validate the dwFlags? */
947 lpGData->dwFlags = dwFlags;
949 TRACE( "Created group id 0x%08x\n", *lpid );
954 /* This method assumes that all links to it are already deleted */
956 DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid )
960 TRACE( "(%p)->(0x%08x)\n", This, dpid );
962 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
964 if( lpGList == NULL )
966 ERR( "DPID 0x%08x not found\n", dpid );
970 if( --(lpGList->lpGData->uRef) )
972 FIXME( "Why is this not the last reference to group?\n" );
977 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
978 HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
980 /* Remove and Delete Player List object */
981 HeapFree( GetProcessHeap(), 0, lpGList );
985 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid )
987 lpGroupList lpGroups;
989 TRACE( "(%p)->(0x%08x)\n", This, dpid );
991 if( dpid == DPID_SYSTEM_GROUP )
993 return This->dp2->lpSysGroup;
997 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
1000 if( lpGroups == NULL )
1005 return lpGroups->lpGData;
1008 static HRESULT WINAPI DP_IF_CreateGroup
1009 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
1010 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
1011 DWORD dwFlags, BOOL bAnsi )
1013 lpGroupData lpGData;
1015 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1016 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
1019 /* If the name is not specified, we must provide one */
1020 if( DPID_UNKNOWN == *lpidGroup )
1022 /* If we are the name server, we decide on the group ids. If not, we
1023 * must ask for one before attempting a creation.
1025 if( This->dp2->bHostInterface )
1027 *lpidGroup = DP_NextObjectId();
1031 *lpidGroup = DP_GetRemoteNextObjectId();
1035 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
1036 DPID_NOPARENT_GROUP, bAnsi );
1038 if( lpGData == NULL )
1040 return DPERR_CANTADDPLAYER; /* yes player not group */
1043 if( DPID_SYSTEM_GROUP == *lpidGroup )
1045 This->dp2->lpSysGroup = lpGData;
1046 TRACE( "Inserting system group\n" );
1050 /* Insert into the system group */
1051 lpGroupList lpGroup = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGroup ) );
1052 lpGroup->lpGData = lpGData;
1054 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
1057 /* Something is now referencing this data */
1060 /* Set all the important stuff for the group */
1061 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
1063 /* FIXME: We should only create the system group if GetCaps returns
1064 * DPCAPS_GROUPOPTIMIZED.
1067 /* Let the SP know that we've created this group */
1068 if( This->dp2->spData.lpCB->CreateGroup )
1070 DPSP_CREATEGROUPDATA data;
1071 DWORD dwCreateFlags = 0;
1073 TRACE( "Calling SP CreateGroup\n" );
1075 if( *lpidGroup == DPID_NOPARENT_GROUP )
1076 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
1078 if( lpMsgHdr == NULL )
1079 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1081 if( dwFlags & DPGROUP_HIDDEN )
1082 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
1084 data.idGroup = *lpidGroup;
1085 data.dwFlags = dwCreateFlags;
1086 data.lpSPMessageHeader = lpMsgHdr;
1087 data.lpISP = This->dp2->spData.lpISP;
1089 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1092 /* Inform all other peers of the creation of a new group. If there are
1093 * no peers keep this event quiet.
1094 * Also if this message was sent to us, don't rebroadcast.
1096 if( ( lpMsgHdr == NULL ) &&
1097 This->dp2->lpSessionDesc &&
1098 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1100 DPMSG_CREATEPLAYERORGROUP msg;
1101 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1103 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1104 msg.dpId = *lpidGroup;
1105 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1106 msg.lpData = lpData;
1107 msg.dwDataSize = dwDataSize;
1108 msg.dpnName = *lpGroupName;
1109 msg.dpIdParent = DPID_NOPARENT_GROUP;
1110 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
1112 /* FIXME: Correct to just use send effectively? */
1113 /* FIXME: Should size include data w/ message or just message "header" */
1114 /* FIXME: Check return code */
1115 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
1116 0, 0, NULL, NULL, bAnsi );
1122 static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
1123 ( LPDIRECTPLAY2A iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1124 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1126 *lpidGroup = DPID_UNKNOWN;
1128 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1129 lpGroupName, lpData, dwDataSize, dwFlags, TRUE );
1132 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
1133 ( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1134 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1136 *lpidGroup = DPID_UNKNOWN;
1138 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1139 lpGroupName, lpData, dwDataSize, dwFlags, FALSE );
1144 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
1145 LPVOID lpData, DWORD dwDataSize )
1147 /* Clear out the data with this player */
1148 if( dwFlags & DPSET_LOCAL )
1150 if ( lpGData->dwLocalDataSize != 0 )
1152 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
1153 lpGData->lpLocalData = NULL;
1154 lpGData->dwLocalDataSize = 0;
1159 if( lpGData->dwRemoteDataSize != 0 )
1161 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
1162 lpGData->lpRemoteData = NULL;
1163 lpGData->dwRemoteDataSize = 0;
1167 /* Reallocate for new data */
1168 if( lpData != NULL )
1170 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1171 sizeof( dwDataSize ) );
1172 CopyMemory( lpNewData, lpData, dwDataSize );
1174 if( dwFlags & DPSET_LOCAL )
1176 lpGData->lpLocalData = lpData;
1177 lpGData->dwLocalDataSize = dwDataSize;
1181 lpGData->lpRemoteData = lpNewData;
1182 lpGData->dwRemoteDataSize = dwDataSize;
1188 /* This function will just create the storage for the new player. */
1190 lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid,
1191 LPDPNAME lpName, DWORD dwFlags,
1192 HANDLE hEvent, BOOL bAnsi )
1194 lpPlayerData lpPData;
1196 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
1198 /* Allocate the storage for the player and associate it with list element */
1199 lpPData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPData ) );
1200 if( lpPData == NULL )
1205 /* Set the desired player ID */
1206 lpPData->dpid = *lpid;
1208 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
1210 lpPData->dwFlags = dwFlags;
1212 /* If we were given an event handle, duplicate it */
1215 if( !DuplicateHandle( GetCurrentProcess(), hEvent,
1216 GetCurrentProcess(), &lpPData->hEvent,
1217 0, FALSE, DUPLICATE_SAME_ACCESS )
1220 /* FIXME: Memory leak */
1221 ERR( "Can't duplicate player msg handle %p\n", hEvent );
1225 /* Initialize the SP data section */
1226 lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData();
1228 TRACE( "Created player id 0x%08x\n", *lpid );
1233 /* Delete the contents of the DPNAME struct */
1235 DP_DeleteDPNameStruct( LPDPNAME lpDPName )
1237 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u1.lpszShortNameA );
1238 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u2.lpszLongNameA );
1241 /* This method assumes that all links to it are already deleted */
1243 DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid )
1245 lpPlayerList lpPList;
1247 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1249 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1251 if( lpPList == NULL )
1253 ERR( "DPID 0x%08x not found\n", dpid );
1257 /* Verify that this is the last reference to the data */
1258 if( --(lpPList->lpPData->uRef) )
1260 FIXME( "Why is this not the last reference to player?\n" );
1265 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1267 CloseHandle( lpPList->lpPData->hEvent );
1268 HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
1270 /* Delete Player List object */
1271 HeapFree( GetProcessHeap(), 0, lpPList );
1274 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid )
1276 lpPlayerList lpPlayers;
1278 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1280 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1285 /* Basic area for Dst must already be allocated */
1286 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi )
1290 ZeroMemory( lpDst, sizeof( *lpDst ) );
1291 lpDst->dwSize = sizeof( *lpDst );
1295 if( lpSrc->dwSize != sizeof( *lpSrc) )
1300 /* Delete any existing pointers */
1301 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1302 HeapFree( GetProcessHeap(), 0, lpDst->u2.lpszLongNameA );
1304 /* Copy as required */
1305 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1309 if( lpSrc->u1.lpszShortNameA )
1311 lpDst->u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), 0,
1312 strlen(lpSrc->u1.lpszShortNameA)+1 );
1313 strcpy( lpDst->u1.lpszShortNameA, lpSrc->u1.lpszShortNameA );
1315 if( lpSrc->u2.lpszLongNameA )
1317 lpDst->u2.lpszLongNameA = HeapAlloc( GetProcessHeap(), 0,
1318 strlen(lpSrc->u2.lpszLongNameA)+1 );
1319 strcpy( lpDst->u2.lpszLongNameA, lpSrc->u2.lpszLongNameA );
1324 if( lpSrc->u1.lpszShortNameA )
1326 lpDst->u1.lpszShortName = HeapAlloc( GetProcessHeap(), 0,
1327 (strlenW(lpSrc->u1.lpszShortName)+1)*sizeof(WCHAR) );
1328 strcpyW( lpDst->u1.lpszShortName, lpSrc->u1.lpszShortName );
1330 if( lpSrc->u2.lpszLongNameA )
1332 lpDst->u2.lpszLongName = HeapAlloc( GetProcessHeap(), 0,
1333 (strlenW(lpSrc->u2.lpszLongName)+1)*sizeof(WCHAR) );
1334 strcpyW( lpDst->u2.lpszLongName, lpSrc->u2.lpszLongName );
1342 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
1343 LPVOID lpData, DWORD dwDataSize )
1345 /* Clear out the data with this player */
1346 if( dwFlags & DPSET_LOCAL )
1348 if ( lpPData->dwLocalDataSize != 0 )
1350 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
1351 lpPData->lpLocalData = NULL;
1352 lpPData->dwLocalDataSize = 0;
1357 if( lpPData->dwRemoteDataSize != 0 )
1359 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
1360 lpPData->lpRemoteData = NULL;
1361 lpPData->dwRemoteDataSize = 0;
1365 /* Reallocate for new data */
1366 if( lpData != NULL )
1368 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1369 sizeof( dwDataSize ) );
1370 CopyMemory( lpNewData, lpData, dwDataSize );
1372 if( dwFlags & DPSET_LOCAL )
1374 lpPData->lpLocalData = lpData;
1375 lpPData->dwLocalDataSize = dwDataSize;
1379 lpPData->lpRemoteData = lpNewData;
1380 lpPData->dwRemoteDataSize = dwDataSize;
1386 static HRESULT WINAPI DP_IF_CreatePlayer
1387 ( IDirectPlay2Impl* This,
1388 LPVOID lpMsgHdr, /* NULL for local creation, non NULL for remote creation */
1390 LPDPNAME lpPlayerName,
1398 lpPlayerData lpPData;
1399 lpPlayerList lpPList;
1400 DWORD dwCreateFlags = 0;
1402 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1403 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1404 dwDataSize, dwFlags, bAnsi );
1408 dwFlags = DPPLAYER_SPECTATOR;
1411 if( lpidPlayer == NULL )
1413 return DPERR_INVALIDPARAMS;
1417 /* Determine the creation flags for the player. These will be passed
1418 * to the name server if requesting a player id and to the SP when
1419 * informing it of the player creation
1422 if( dwFlags & DPPLAYER_SERVERPLAYER )
1424 if( *lpidPlayer == DPID_SERVERPLAYER )
1426 /* Server player for the host interface */
1427 dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
1429 else if( *lpidPlayer == DPID_NAME_SERVER )
1431 /* Name server - master of everything */
1432 dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
1436 /* Server player for a non host interface */
1437 dwCreateFlags |= DPLAYI_PLAYER_SYSPLAYER;
1441 if( lpMsgHdr == NULL )
1442 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1445 /* Verify we know how to handle all the flags */
1446 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1447 ( dwFlags & DPPLAYER_SPECTATOR )
1451 /* Assume non fatal failure */
1452 ERR( "unknown dwFlags = 0x%08x\n", dwFlags );
1455 /* If the name is not specified, we must provide one */
1456 if( *lpidPlayer == DPID_UNKNOWN )
1458 /* If we are the session master, we dish out the group/player ids */
1459 if( This->dp2->bHostInterface )
1461 *lpidPlayer = DP_NextObjectId();
1465 hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer );
1469 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1476 /* FIXME: Would be nice to perhaps verify that we don't already have
1481 /* FIXME: Should we be storing these dwFlags or the creation ones? */
1482 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwFlags,
1485 if( lpPData == NULL )
1487 return DPERR_CANTADDPLAYER;
1490 /* Create the list object and link it in */
1491 lpPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPList ) );
1492 if( lpPList == NULL )
1494 FIXME( "Memory leak\n" );
1495 return DPERR_CANTADDPLAYER;
1499 lpPList->lpPData = lpPData;
1501 /* Add the player to the system group */
1502 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1504 /* Update the information and send it to all players in the session */
1505 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
1507 /* Let the SP know that we've created this player */
1508 if( This->dp2->spData.lpCB->CreatePlayer )
1510 DPSP_CREATEPLAYERDATA data;
1512 data.idPlayer = *lpidPlayer;
1513 data.dwFlags = dwCreateFlags;
1514 data.lpSPMessageHeader = lpMsgHdr;
1515 data.lpISP = This->dp2->spData.lpISP;
1517 TRACE( "Calling SP CreatePlayer 0x%08x: dwFlags: 0x%08x lpMsgHdr: %p\n",
1518 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
1520 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1525 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1529 /* Now let the SP know that this player is a member of the system group */
1530 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1532 DPSP_ADDPLAYERTOGROUPDATA data;
1534 data.idPlayer = *lpidPlayer;
1535 data.idGroup = DPID_SYSTEM_GROUP;
1536 data.lpISP = This->dp2->spData.lpISP;
1538 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1540 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1545 ERR( "Failed to add player to sys group with sp: %s\n",
1546 DPLAYX_HresultToString(hr) );
1551 if( This->dp2->bHostInterface == FALSE )
1553 /* Let the name server know about the creation of this player */
1554 /* FIXME: Is this only to be done for the creation of a server player or
1555 * is this used for regular players? If only for server players, move
1556 * this call to DP_SecureOpen(...);
1559 TRACE( "Sending message to self to get my addr\n" );
1560 DP_MSG_ToSelf( This, *lpidPlayer ); /* This is a hack right now */
1563 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
1566 /* Inform all other peers of the creation of a new player. If there are
1567 * no peers keep this quiet.
1568 * Also, if this was a remote event, no need to rebroadcast it.
1570 if( ( lpMsgHdr == NULL ) &&
1571 This->dp2->lpSessionDesc &&
1572 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1574 DPMSG_CREATEPLAYERORGROUP msg;
1575 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1577 msg.dwPlayerType = DPPLAYERTYPE_PLAYER;
1578 msg.dpId = *lpidPlayer;
1579 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */
1580 msg.lpData = lpData;
1581 msg.dwDataSize = dwDataSize;
1582 msg.dpnName = *lpPlayerName;
1583 msg.dpIdParent = DPID_NOPARENT_GROUP;
1584 msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
1586 /* FIXME: Correct to just use send effectively? */
1587 /* FIXME: Should size include data w/ message or just message "header" */
1588 /* FIXME: Check return code */
1589 hr = DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
1590 sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
1597 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
1598 ( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1599 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1601 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1603 if( dwFlags & DPPLAYER_SERVERPLAYER )
1605 *lpidPlayer = DPID_SERVERPLAYER;
1609 *lpidPlayer = DPID_UNKNOWN;
1612 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1613 lpData, dwDataSize, dwFlags, TRUE );
1616 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
1617 ( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1618 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1620 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1622 if( dwFlags & DPPLAYER_SERVERPLAYER )
1624 *lpidPlayer = DPID_SERVERPLAYER;
1628 *lpidPlayer = DPID_UNKNOWN;
1631 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1632 lpData, dwDataSize, dwFlags, FALSE );
1635 static DPID DP_GetRemoteNextObjectId(void)
1640 return DP_NextObjectId();
1643 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
1644 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
1645 DPID idPlayer, BOOL bAnsi )
1649 lpGroupData lpGData;
1650 lpPlayerList lpPList;
1652 TRACE( "(%p)->(%p,0x%08x,0x%08x,%u)\n",
1653 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
1655 /* Find the group */
1656 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1658 return DPERR_INVALIDGROUP;
1661 /* Find the player */
1662 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
1664 return DPERR_INVALIDPLAYER;
1667 /* Remove the player shortcut from the group */
1668 DPQ_REMOVE_ENTRY( lpGData->players, players, lpPData->dpid, ==, idPlayer, lpPList );
1670 if( lpPList == NULL )
1672 return DPERR_INVALIDPLAYER;
1675 /* One less reference */
1676 lpPList->lpPData->uRef--;
1678 /* Delete the Player List element */
1679 HeapFree( GetProcessHeap(), 0, lpPList );
1681 /* Inform the SP if they care */
1682 if( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1684 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1686 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1688 data.idPlayer = idPlayer;
1689 data.idGroup = idGroup;
1690 data.lpISP = This->dp2->spData.lpISP;
1692 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1695 /* Need to send a DELETEPLAYERFROMGROUP message */
1696 FIXME( "Need to send a message\n" );
1701 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
1702 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
1704 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1705 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, TRUE );
1708 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
1709 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
1711 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1712 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, FALSE );
1715 typedef struct _DPRGOPContext
1717 IDirectPlay3Impl* This;
1720 } DPRGOPContext, *lpDPRGOPContext;
1722 static BOOL CALLBACK
1723 cbRemoveGroupOrPlayer(
1730 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1732 TRACE( "Removing element:0x%08x (type:0x%08x) from element:0x%08x\n",
1733 dpId, dwPlayerType, lpCtxt->idGroup );
1735 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1737 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt->This, lpCtxt->idGroup,
1742 ERR( "Unable to delete group 0x%08x from group 0x%08x\n",
1743 dpId, lpCtxt->idGroup );
1748 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl*)lpCtxt->This,
1749 NULL, lpCtxt->idGroup,
1750 dpId, lpCtxt->bAnsi )
1754 ERR( "Unable to delete player 0x%08x from grp 0x%08x\n",
1755 dpId, lpCtxt->idGroup );
1759 return TRUE; /* Continue enumeration */
1762 static HRESULT WINAPI DP_IF_DestroyGroup
1763 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi )
1765 lpGroupData lpGData;
1766 DPRGOPContext context;
1768 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1769 This, lpMsgHdr, idGroup, bAnsi );
1771 /* Find the group */
1772 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1774 return DPERR_INVALIDPLAYER; /* yes player */
1777 context.This = (IDirectPlay3Impl*)This;
1778 context.bAnsi = bAnsi;
1779 context.idGroup = idGroup;
1781 /* Remove all players that this group has */
1782 DP_IF_EnumGroupPlayers( This, idGroup, NULL,
1783 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1785 /* Remove all links to groups that this group has since this is dp3 */
1786 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This, idGroup, NULL,
1787 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1789 /* Remove this group from the parent group - if it has one */
1790 if( ( idGroup != DPID_SYSTEM_GROUP ) &&
1791 ( lpGData->parent != DPID_SYSTEM_GROUP )
1794 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl*)This, lpGData->parent,
1798 /* Now delete this group data and list from the system group */
1799 DP_DeleteGroup( This, idGroup );
1801 /* Let the SP know that we've destroyed this group */
1802 if( This->dp2->spData.lpCB->DeleteGroup )
1804 DPSP_DELETEGROUPDATA data;
1806 FIXME( "data.dwFlags is incorrect\n" );
1808 data.idGroup = idGroup;
1810 data.lpISP = This->dp2->spData.lpISP;
1812 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1815 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1820 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
1821 ( LPDIRECTPLAY2A iface, DPID idGroup )
1823 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1824 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
1827 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
1828 ( LPDIRECTPLAY2 iface, DPID idGroup )
1830 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1831 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
1834 typedef struct _DPFAGContext
1836 IDirectPlay2Impl* This;
1839 } DPFAGContext, *lpDPFAGContext;
1841 static HRESULT WINAPI DP_IF_DestroyPlayer
1842 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi )
1844 DPFAGContext cbContext;
1846 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1847 This, lpMsgHdr, idPlayer, bAnsi );
1849 if( This->dp2->connectionInitialized == NO_PROVIDER )
1851 return DPERR_UNINITIALIZED;
1854 if( DP_FindPlayer( This, idPlayer ) == NULL )
1856 return DPERR_INVALIDPLAYER;
1859 /* FIXME: If the player is remote, we must be the host to delete this */
1861 cbContext.This = This;
1862 cbContext.idPlayer = idPlayer;
1863 cbContext.bAnsi = bAnsi;
1865 /* Find each group and call DeletePlayerFromGroup if the player is a
1866 member of the group */
1867 DP_IF_EnumGroups( This, NULL, cbDeletePlayerFromAllGroups,
1868 (LPVOID)&cbContext, DPENUMGROUPS_ALL, bAnsi );
1870 /* Now delete player and player list from the sys group */
1871 DP_DeletePlayer( This, idPlayer );
1873 /* Let the SP know that we've destroyed this group */
1874 if( This->dp2->spData.lpCB->DeletePlayer )
1876 DPSP_DELETEPLAYERDATA data;
1878 FIXME( "data.dwFlags is incorrect\n" );
1880 data.idPlayer = idPlayer;
1882 data.lpISP = This->dp2->spData.lpISP;
1884 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
1887 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
1892 static BOOL CALLBACK
1893 cbDeletePlayerFromAllGroups(
1900 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
1902 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1904 DP_IF_DeletePlayerFromGroup( lpCtxt->This, NULL, dpId, lpCtxt->idPlayer,
1907 /* Enumerate all groups in this group since this will normally only
1908 * be called for top level groups
1910 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)lpCtxt->This,
1912 cbDeletePlayerFromAllGroups,
1913 (LPVOID)lpContext, DPENUMGROUPS_ALL,
1919 ERR( "Group callback has dwPlayerType = 0x%08x\n", dwPlayerType );
1925 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
1926 ( LPDIRECTPLAY2A iface, DPID idPlayer )
1928 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1929 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
1932 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
1933 ( LPDIRECTPLAY2 iface, DPID idPlayer )
1935 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1936 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
1939 static HRESULT WINAPI DP_IF_EnumGroupPlayers
1940 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
1941 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1942 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1944 lpGroupData lpGData;
1945 lpPlayerList lpPList;
1947 FIXME("(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
1948 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
1949 lpContext, dwFlags, bAnsi );
1951 if( This->dp2->connectionInitialized == NO_PROVIDER )
1953 return DPERR_UNINITIALIZED;
1956 /* Find the group */
1957 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1959 return DPERR_INVALIDGROUP;
1962 if( DPQ_IS_EMPTY( lpGData->players ) )
1967 lpPList = DPQ_FIRST( lpGData->players );
1969 /* Walk the players in this group */
1972 /* We do not enum the name server or app server as they are of no
1973 * concequence to the end user.
1975 if( ( lpPList->lpPData->dpid != DPID_NAME_SERVER ) &&
1976 ( lpPList->lpPData->dpid != DPID_SERVERPLAYER )
1980 /* FIXME: Need to add stuff for dwFlags checking */
1982 if( !lpEnumPlayersCallback2( lpPList->lpPData->dpid, DPPLAYERTYPE_PLAYER,
1983 &lpPList->lpPData->name,
1984 lpPList->lpPData->dwFlags,
1988 /* User requested break */
1993 if( DPQ_IS_ENDOFLIST( lpPList->players ) )
1998 lpPList = DPQ_NEXT( lpPList->players );
2004 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
2005 ( LPDIRECTPLAY2A iface, DPID idGroup, LPGUID lpguidInstance,
2006 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2007 LPVOID lpContext, DWORD dwFlags )
2009 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2010 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2011 lpEnumPlayersCallback2, lpContext,
2015 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
2016 ( LPDIRECTPLAY2 iface, DPID idGroup, LPGUID lpguidInstance,
2017 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2018 LPVOID lpContext, DWORD dwFlags )
2020 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2021 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2022 lpEnumPlayersCallback2, lpContext,
2026 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2027 static HRESULT WINAPI DP_IF_EnumGroups
2028 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2029 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2030 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2032 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This,
2033 DPID_SYSTEM_GROUP, lpguidInstance,
2034 lpEnumPlayersCallback2, lpContext,
2038 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
2039 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2040 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2041 LPVOID lpContext, DWORD dwFlags )
2043 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2044 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2045 lpContext, dwFlags, TRUE );
2048 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
2049 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2050 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2051 LPVOID lpContext, DWORD dwFlags )
2053 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2054 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2055 lpContext, dwFlags, FALSE );
2058 static HRESULT WINAPI DP_IF_EnumPlayers
2059 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2060 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2061 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2063 return DP_IF_EnumGroupPlayers( This, DPID_SYSTEM_GROUP, lpguidInstance,
2064 lpEnumPlayersCallback2, lpContext,
2068 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
2069 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2070 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2071 LPVOID lpContext, DWORD dwFlags )
2073 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2074 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2075 lpContext, dwFlags, TRUE );
2078 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
2079 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2080 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2081 LPVOID lpContext, DWORD dwFlags )
2083 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2084 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2085 lpContext, dwFlags, FALSE );
2088 /* This function should call the registered callback function that the user
2089 passed into EnumSessions for each entry available.
2091 static void DP_InvokeEnumSessionCallbacks
2092 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2097 LPDPSESSIONDESC2 lpSessionDesc;
2099 FIXME( ": not checking for conditions\n" );
2101 /* Not sure if this should be pruning but it's convenient */
2102 NS_PruneSessionCache( lpNSInfo );
2104 NS_ResetSessionEnumeration( lpNSInfo );
2106 /* Enumerate all sessions */
2107 /* FIXME: Need to indicate ANSI */
2108 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2110 TRACE( "EnumSessionsCallback2 invoked\n" );
2111 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2117 /* Invoke one last time to indicate that there is no more to come */
2118 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2121 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2123 EnumSessionAsyncCallbackData* data = (EnumSessionAsyncCallbackData*)lpContext;
2124 HANDLE hSuicideRequest = data->hSuicideRequest;
2125 DWORD dwTimeout = data->dwTimeout;
2127 TRACE( "Thread started with timeout = 0x%08x\n", dwTimeout );
2133 /* Sleep up to dwTimeout waiting for request to terminate thread */
2134 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2136 TRACE( "Thread terminating on terminate request\n" );
2140 /* Now resend the enum request */
2141 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2142 data->dwEnumSessionFlags,
2147 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2148 /* FIXME: Should we kill this thread? How to inform the main thread? */
2153 TRACE( "Thread terminating\n" );
2155 /* Clean up the thread data */
2156 CloseHandle( hSuicideRequest );
2157 HeapFree( GetProcessHeap(), 0, lpContext );
2159 /* FIXME: Need to have some notification to main app thread that this is
2160 * dead. It would serve two purposes. 1) allow sync on termination
2161 * so that we don't actually send something to ourselves when we
2162 * become name server (race condition) and 2) so that if we die
2163 * abnormally something else will be able to tell.
2169 static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
2171 /* Does a thread exist? If so we were doing an async enum session */
2172 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2174 TRACE( "Killing EnumSession thread %p\n",
2175 This->dp2->hEnumSessionThread );
2177 /* Request that the thread kill itself nicely */
2178 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2179 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2181 /* We no longer need to know about the thread */
2182 CloseHandle( This->dp2->hEnumSessionThread );
2184 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2188 static HRESULT WINAPI DP_IF_EnumSessions
2189 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2190 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2191 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2195 TRACE( "(%p)->(%p,0x%08x,%p,%p,0x%08x,%u)\n",
2196 This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags,
2199 /* Can't enumerate if the interface is already open */
2200 if( This->dp2->bConnectionOpen )
2202 return DPERR_GENERIC;
2206 /* The loading of a lobby provider _seems_ to require a backdoor loading
2207 * of the service provider to also associate with this DP object. This is
2208 * because the app doesn't seem to have to call EnumConnections and
2209 * InitializeConnection for the SP before calling this method. As such
2210 * we'll do their dirty work for them with a quick hack so as to always
2211 * load the TCP/IP service provider.
2213 * The correct solution would seem to involve creating a dialog box which
2214 * contains the possible SPs. These dialog boxes most likely follow SDK
2217 if( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
2219 LPVOID lpConnection;
2222 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2224 if( !DP_BuildSPCompoundAddr( (LPGUID)&DPSPGUID_TCPIP, &lpConnection, &dwSize ) )
2226 ERR( "Can't build compound addr\n" );
2227 return DPERR_GENERIC;
2230 hr = DP_IF_InitializeConnection( (IDirectPlay3Impl*)This, lpConnection,
2237 /* Free up the address buffer */
2238 HeapFree( GetProcessHeap(), 0, lpConnection );
2240 /* The SP is now initialized */
2241 This->dp2->bSPInitialized = TRUE;
2246 /* Use the service provider default? */
2247 if( dwTimeout == 0 )
2250 spCaps.dwSize = sizeof( spCaps );
2252 DP_IF_GetCaps( This, &spCaps, 0 );
2253 dwTimeout = spCaps.dwTimeout;
2255 /* The service provider doesn't provide one either! */
2256 if( dwTimeout == 0 )
2258 /* Provide the TCP/IP default */
2259 dwTimeout = DPMSG_WAIT_5_SECS;
2263 if( dwFlags & DPENUMSESSIONS_STOPASYNC )
2265 DP_KillEnumSessionThread( This );
2269 /* FIXME: Interface locking sucks in this method */
2270 if( ( dwFlags & DPENUMSESSIONS_ASYNC ) )
2272 /* Enumerate everything presently in the local session cache */
2273 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2274 This->dp2->lpNameServerData, dwTimeout,
2278 /* See if we've already created a thread to service this interface */
2279 if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2283 /* Send the first enum request inline since the user may cancel a dialog
2284 * if one is presented. Also, may also have a connecting return code.
2286 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2287 dwFlags, &This->dp2->spData );
2291 EnumSessionAsyncCallbackData* lpData
2292 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpData ) );
2293 /* FIXME: need to kill the thread on object deletion */
2294 lpData->lpSpData = &This->dp2->spData;
2296 CopyMemory( &lpData->requestGuid, &lpsd->guidApplication, sizeof(GUID) );
2297 lpData->dwEnumSessionFlags = dwFlags;
2298 lpData->dwTimeout = dwTimeout;
2300 This->dp2->hKillEnumSessionThreadEvent =
2301 CreateEventW( NULL, TRUE, FALSE, NULL );
2303 if( !DuplicateHandle( GetCurrentProcess(),
2304 This->dp2->hKillEnumSessionThreadEvent,
2305 GetCurrentProcess(),
2306 &lpData->hSuicideRequest,
2307 0, FALSE, DUPLICATE_SAME_ACCESS )
2310 ERR( "Can't duplicate thread killing handle\n" );
2313 TRACE( ": creating EnumSessionsRequest thread\n" );
2315 This->dp2->hEnumSessionThread = CreateThread( NULL,
2317 DP_EnumSessionsSendAsyncRequestThread,
2326 /* Invalidate the session cache for the interface */
2327 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2329 /* Send the broadcast for session enumeration */
2330 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2332 &This->dp2->spData );
2335 SleepEx( dwTimeout, FALSE );
2337 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2338 This->dp2->lpNameServerData, dwTimeout,
2345 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2346 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2347 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2348 LPVOID lpContext, DWORD dwFlags )
2350 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2351 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2352 lpContext, dwFlags, TRUE );
2355 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2356 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2357 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2358 LPVOID lpContext, DWORD dwFlags )
2360 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2361 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2362 lpContext, dwFlags, FALSE );
2365 static HRESULT WINAPI DP_IF_GetPlayerCaps
2366 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
2369 DPSP_GETCAPSDATA data;
2371 TRACE("(%p)->(0x%08x,%p,0x%08x)\n", This, idPlayer, lpDPCaps, dwFlags);
2373 /* Query the service provider */
2374 data.idPlayer = idPlayer;
2375 data.dwFlags = dwFlags;
2376 data.lpCaps = lpDPCaps;
2377 data.lpISP = This->dp2->spData.lpISP;
2379 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2382 static HRESULT WINAPI DP_IF_GetCaps
2383 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags )
2385 return DP_IF_GetPlayerCaps( This, DPID_ALLPLAYERS, lpDPCaps, dwFlags );
2388 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2389 ( LPDIRECTPLAY2A iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2391 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2392 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2395 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2396 ( LPDIRECTPLAY2 iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2398 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2399 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2402 static HRESULT WINAPI DP_IF_GetGroupData
2403 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2404 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2406 lpGroupData lpGData;
2407 DWORD dwRequiredBufferSize;
2408 LPVOID lpCopyDataFrom;
2410 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2411 This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi );
2413 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2415 return DPERR_INVALIDGROUP;
2418 /* How much buffer is required? */
2419 if( dwFlags & DPSET_LOCAL )
2421 dwRequiredBufferSize = lpGData->dwLocalDataSize;
2422 lpCopyDataFrom = lpGData->lpLocalData;
2426 dwRequiredBufferSize = lpGData->dwRemoteDataSize;
2427 lpCopyDataFrom = lpGData->lpRemoteData;
2430 /* Is the user requesting to know how big a buffer is required? */
2431 if( ( lpData == NULL ) ||
2432 ( *lpdwDataSize < dwRequiredBufferSize )
2435 *lpdwDataSize = dwRequiredBufferSize;
2436 return DPERR_BUFFERTOOSMALL;
2439 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2444 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2445 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2446 LPDWORD lpdwDataSize, DWORD dwFlags )
2448 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2449 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2453 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2454 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2455 LPDWORD lpdwDataSize, DWORD dwFlags )
2457 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2458 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2462 static HRESULT WINAPI DP_IF_GetGroupName
2463 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2464 LPDWORD lpdwDataSize, BOOL bAnsi )
2466 lpGroupData lpGData;
2467 LPDPNAME lpName = (LPDPNAME)lpData;
2468 DWORD dwRequiredDataSize;
2470 FIXME("(%p)->(0x%08x,%p,%p,%u) ANSI ignored\n",
2471 This, idGroup, lpData, lpdwDataSize, bAnsi );
2473 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2475 return DPERR_INVALIDGROUP;
2478 dwRequiredDataSize = lpGData->name.dwSize;
2480 if( lpGData->name.u1.lpszShortNameA )
2482 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
2485 if( lpGData->name.u2.lpszLongNameA )
2487 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
2490 if( ( lpData == NULL ) ||
2491 ( *lpdwDataSize < dwRequiredDataSize )
2494 *lpdwDataSize = dwRequiredDataSize;
2495 return DPERR_BUFFERTOOSMALL;
2498 /* Copy the structure */
2499 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2501 if( lpGData->name.u1.lpszShortNameA )
2503 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2504 lpGData->name.u1.lpszShortNameA );
2508 lpName->u1.lpszShortNameA = NULL;
2511 if( lpGData->name.u1.lpszShortNameA )
2513 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2514 lpGData->name.u2.lpszLongNameA );
2518 lpName->u2.lpszLongNameA = NULL;
2524 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2525 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2526 LPDWORD lpdwDataSize )
2528 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2529 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2532 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2533 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2534 LPDWORD lpdwDataSize )
2536 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2537 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2540 static HRESULT WINAPI DP_IF_GetMessageCount
2541 ( IDirectPlay2Impl* This, DPID idPlayer,
2542 LPDWORD lpdwCount, BOOL bAnsi )
2544 FIXME("(%p)->(0x%08x,%p,%u): stub\n", This, idPlayer, lpdwCount, bAnsi );
2545 return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer,
2546 DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL,
2550 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2551 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDWORD lpdwCount )
2553 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2554 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, TRUE );
2557 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2558 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDWORD lpdwCount )
2560 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2561 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, FALSE );
2564 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2565 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2567 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2568 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2572 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2573 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2575 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2576 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2580 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2581 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2584 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2585 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2588 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2589 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2592 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2593 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2596 static HRESULT WINAPI DP_IF_GetPlayerData
2597 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2598 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2600 lpPlayerList lpPList;
2601 DWORD dwRequiredBufferSize;
2602 LPVOID lpCopyDataFrom;
2604 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2605 This, idPlayer, lpData, lpdwDataSize, dwFlags, bAnsi );
2607 if( This->dp2->connectionInitialized == NO_PROVIDER )
2609 return DPERR_UNINITIALIZED;
2612 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2614 return DPERR_INVALIDPLAYER;
2617 /* How much buffer is required? */
2618 if( dwFlags & DPSET_LOCAL )
2620 dwRequiredBufferSize = lpPList->lpPData->dwLocalDataSize;
2621 lpCopyDataFrom = lpPList->lpPData->lpLocalData;
2625 dwRequiredBufferSize = lpPList->lpPData->dwRemoteDataSize;
2626 lpCopyDataFrom = lpPList->lpPData->lpRemoteData;
2629 /* Is the user requesting to know how big a buffer is required? */
2630 if( ( lpData == NULL ) ||
2631 ( *lpdwDataSize < dwRequiredBufferSize )
2634 *lpdwDataSize = dwRequiredBufferSize;
2635 return DPERR_BUFFERTOOSMALL;
2638 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2643 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2644 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2645 LPDWORD lpdwDataSize, DWORD dwFlags )
2647 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2648 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2652 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2653 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2654 LPDWORD lpdwDataSize, DWORD dwFlags )
2656 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2657 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2661 static HRESULT WINAPI DP_IF_GetPlayerName
2662 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2663 LPDWORD lpdwDataSize, BOOL bAnsi )
2665 lpPlayerList lpPList;
2666 LPDPNAME lpName = (LPDPNAME)lpData;
2667 DWORD dwRequiredDataSize;
2669 FIXME( "(%p)->(0x%08x,%p,%p,%u): ANSI\n",
2670 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2672 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2674 return DPERR_INVALIDPLAYER;
2677 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
2679 if( lpPList->lpPData->name.u1.lpszShortNameA )
2681 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
2684 if( lpPList->lpPData->name.u2.lpszLongNameA )
2686 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
2689 if( ( lpData == NULL ) ||
2690 ( *lpdwDataSize < dwRequiredDataSize )
2693 *lpdwDataSize = dwRequiredDataSize;
2694 return DPERR_BUFFERTOOSMALL;
2697 /* Copy the structure */
2698 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
2700 if( lpPList->lpPData->name.u1.lpszShortNameA )
2702 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2703 lpPList->lpPData->name.u1.lpszShortNameA );
2707 lpName->u1.lpszShortNameA = NULL;
2710 if( lpPList->lpPData->name.u1.lpszShortNameA )
2712 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2713 lpPList->lpPData->name.u2.lpszLongNameA );
2717 lpName->u2.lpszLongNameA = NULL;
2723 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2724 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2725 LPDWORD lpdwDataSize )
2727 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2728 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
2731 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2732 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2733 LPDWORD lpdwDataSize )
2735 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2736 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
2739 static HRESULT WINAPI DP_GetSessionDesc
2740 ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize,
2743 DWORD dwRequiredSize;
2745 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
2747 if( This->dp2->connectionInitialized == NO_PROVIDER )
2749 return DPERR_UNINITIALIZED;
2752 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
2754 return DPERR_INVALIDPARAMS;
2757 /* FIXME: Get from This->dp2->lpSessionDesc */
2758 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
2760 if ( ( lpData == NULL ) ||
2761 ( *lpdwDataSize < dwRequiredSize )
2764 *lpdwDataSize = dwRequiredSize;
2765 return DPERR_BUFFERTOOSMALL;
2768 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
2773 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
2774 ( LPDIRECTPLAY2A iface, LPVOID lpData, LPDWORD lpdwDataSize )
2776 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2777 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2780 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
2781 ( LPDIRECTPLAY2 iface, LPVOID lpData, LPDWORD lpdwDataSize )
2783 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2784 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2787 /* Intended only for COM compatibility. Always returns an error. */
2788 static HRESULT WINAPI DirectPlay2AImpl_Initialize
2789 ( LPDIRECTPLAY2A iface, LPGUID lpGUID )
2791 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2792 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2793 return DPERR_ALREADYINITIALIZED;
2796 /* Intended only for COM compatibility. Always returns an error. */
2797 static HRESULT WINAPI DirectPlay2WImpl_Initialize
2798 ( LPDIRECTPLAY2 iface, LPGUID lpGUID )
2800 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2801 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2802 return DPERR_ALREADYINITIALIZED;
2806 static HRESULT WINAPI DP_SecureOpen
2807 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
2808 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
2813 FIXME( "(%p)->(%p,0x%08x,%p,%p): partial stub\n",
2814 This, lpsd, dwFlags, lpSecurity, lpCredentials );
2816 if( This->dp2->bConnectionOpen )
2818 TRACE( ": rejecting already open connection.\n" );
2819 return DPERR_ALREADYINITIALIZED;
2822 /* If we're enumerating, kill the thread */
2823 DP_KillEnumSessionThread( This );
2825 if( dwFlags & DPOPEN_CREATE )
2827 /* Rightoo - this computer is the host and the local computer needs to be
2828 the name server so that others can join this session */
2829 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
2831 This->dp2->bHostInterface = TRUE;
2833 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
2836 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
2841 /* Invoke the conditional callback for the service provider */
2842 if( This->dp2->spData.lpCB->Open )
2846 FIXME( "Not all data fields are correct. Need new parameter\n" );
2848 data.bCreate = (dwFlags & DPOPEN_CREATE ) ? TRUE : FALSE;
2849 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
2850 : NS_GetNSAddr( This->dp2->lpNameServerData );
2851 data.lpISP = This->dp2->spData.lpISP;
2852 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) ? TRUE : FALSE;
2853 data.dwOpenFlags = dwFlags;
2854 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
2856 hr = (*This->dp2->spData.lpCB->Open)(&data);
2859 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
2865 /* Create the system group of which everything is a part of */
2866 DPID systemGroup = DPID_SYSTEM_GROUP;
2868 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
2873 if( dwFlags & DPOPEN_JOIN )
2875 DPID dpidServerId = DPID_UNKNOWN;
2877 /* Create the server player for this interface. This way we can receive
2878 * messages for this session.
2880 /* FIXME: I suppose that we should be setting an event for a receive
2881 * type of thing. That way the messaging thread could know to wake
2882 * up. DPlay would then trigger the hEvent for the player the
2883 * message is directed to.
2885 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
2887 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
2890 else if( dwFlags & DPOPEN_CREATE )
2892 DPID dpidNameServerId = DPID_NAME_SERVER;
2894 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
2895 0, DPPLAYER_SERVERPLAYER, bAnsi );
2900 ERR( "Couldn't create name server/system player: %s\n",
2901 DPLAYX_HresultToString(hr) );
2907 static HRESULT WINAPI DirectPlay2AImpl_Open
2908 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2910 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2911 TRACE("(%p)->(%p,0x%08x)\n", This, lpsd, dwFlags );
2912 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, TRUE );
2915 static HRESULT WINAPI DirectPlay2WImpl_Open
2916 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2918 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2919 TRACE("(%p)->(%p,0x%08x)\n", This, lpsd, dwFlags );
2920 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, FALSE );
2923 static HRESULT WINAPI DP_IF_Receive
2924 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
2925 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi )
2927 LPDPMSG lpMsg = NULL;
2929 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p,%u): stub\n",
2930 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
2932 if( This->dp2->connectionInitialized == NO_PROVIDER )
2934 return DPERR_UNINITIALIZED;
2939 dwFlags = DPRECEIVE_ALL;
2942 /* If the lpData is NULL, we must be peeking the message */
2943 if( ( lpData == NULL ) &&
2944 !( dwFlags & DPRECEIVE_PEEK )
2947 return DPERR_INVALIDPARAMS;
2950 if( dwFlags & DPRECEIVE_ALL )
2952 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
2954 if( !( dwFlags & DPRECEIVE_PEEK ) )
2956 FIXME( "Remove from queue\n" );
2959 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
2960 ( dwFlags & DPRECEIVE_FROMPLAYER )
2963 FIXME( "Find matching message 0x%08x\n", dwFlags );
2967 ERR( "Hmmm..dwFlags 0x%08x\n", dwFlags );
2972 return DPERR_NOMESSAGES;
2975 /* Copy into the provided buffer */
2976 CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
2981 static HRESULT WINAPI DirectPlay2AImpl_Receive
2982 ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo,
2983 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
2985 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2986 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
2987 lpData, lpdwDataSize, TRUE );
2990 static HRESULT WINAPI DirectPlay2WImpl_Receive
2991 ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo,
2992 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
2994 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2995 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
2996 lpData, lpdwDataSize, FALSE );
2999 static HRESULT WINAPI DirectPlay2AImpl_Send
3000 ( LPDIRECTPLAY2A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3002 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3003 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3004 0, 0, NULL, NULL, TRUE );
3007 static HRESULT WINAPI DirectPlay2WImpl_Send
3008 ( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3010 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3011 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3012 0, 0, NULL, NULL, FALSE );
3015 static HRESULT WINAPI DP_IF_SetGroupData
3016 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
3017 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3019 lpGroupData lpGData;
3021 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3022 This, idGroup, lpData, dwDataSize, dwFlags, bAnsi );
3024 /* Parameter check */
3025 if( ( lpData == NULL ) &&
3029 return DPERR_INVALIDPARAMS;
3032 /* Find the pointer to the data for this player */
3033 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3035 return DPERR_INVALIDOBJECT;
3038 if( !(dwFlags & DPSET_LOCAL) )
3040 FIXME( "Was this group created by this interface?\n" );
3041 /* FIXME: If this is a remote update need to allow it but not
3046 DP_SetGroupData( lpGData, dwFlags, lpData, dwDataSize );
3048 /* FIXME: Only send a message if this group is local to the session otherwise
3049 * it will have been rejected above
3051 if( !(dwFlags & DPSET_LOCAL) )
3053 FIXME( "Send msg?\n" );
3059 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
3060 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
3061 DWORD dwDataSize, DWORD dwFlags )
3063 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3064 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, TRUE );
3067 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
3068 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
3069 DWORD dwDataSize, DWORD dwFlags )
3071 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3072 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, FALSE );
3075 static HRESULT WINAPI DP_IF_SetGroupName
3076 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
3077 DWORD dwFlags, BOOL bAnsi )
3079 lpGroupData lpGData;
3081 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n", This, idGroup,
3082 lpGroupName, dwFlags, bAnsi );
3084 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3086 return DPERR_INVALIDGROUP;
3089 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
3091 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3092 FIXME( "Message not sent and dwFlags ignored\n" );
3097 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
3098 ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName,
3101 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3102 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
3105 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
3106 ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName,
3109 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3110 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
3113 static HRESULT WINAPI DP_IF_SetPlayerData
3114 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
3115 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3117 lpPlayerList lpPList;
3119 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3120 This, idPlayer, lpData, dwDataSize, dwFlags, bAnsi );
3122 /* Parameter check */
3123 if( ( lpData == NULL ) &&
3127 return DPERR_INVALIDPARAMS;
3130 /* Find the pointer to the data for this player */
3131 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3133 return DPERR_INVALIDPLAYER;
3136 if( !(dwFlags & DPSET_LOCAL) )
3138 FIXME( "Was this group created by this interface?\n" );
3139 /* FIXME: If this is a remote update need to allow it but not
3144 DP_SetPlayerData( lpPList->lpPData, dwFlags, lpData, dwDataSize );
3146 if( !(dwFlags & DPSET_LOCAL) )
3148 FIXME( "Send msg?\n" );
3154 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3155 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
3156 DWORD dwDataSize, DWORD dwFlags )
3158 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3159 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3163 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3164 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
3165 DWORD dwDataSize, DWORD dwFlags )
3167 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3168 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3172 static HRESULT WINAPI DP_IF_SetPlayerName
3173 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
3174 DWORD dwFlags, BOOL bAnsi )
3176 lpPlayerList lpPList;
3178 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n",
3179 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3181 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3183 return DPERR_INVALIDGROUP;
3186 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3188 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3189 FIXME( "Message not sent and dwFlags ignored\n" );
3194 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3195 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName,
3198 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3199 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3202 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3203 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName,
3206 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3207 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3210 static HRESULT WINAPI DP_SetSessionDesc
3211 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
3212 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3214 DWORD dwRequiredSize;
3215 LPDPSESSIONDESC2 lpTempSessDesc;
3217 TRACE( "(%p)->(%p,0x%08x,%u,%u)\n",
3218 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3220 if( This->dp2->connectionInitialized == NO_PROVIDER )
3222 return DPERR_UNINITIALIZED;
3227 return DPERR_INVALIDPARAMS;
3230 /* Only the host is allowed to update the session desc */
3231 if( !This->dp2->bHostInterface )
3233 return DPERR_ACCESSDENIED;
3236 /* FIXME: Copy into This->dp2->lpSessionDesc */
3237 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3238 lpTempSessDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize );
3240 if( lpTempSessDesc == NULL )
3242 return DPERR_OUTOFMEMORY;
3246 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3248 This->dp2->lpSessionDesc = lpTempSessDesc;
3251 /*Initializing session GUID*/
3252 CoCreateGuid( &(This->dp2->lpSessionDesc->guidInstance) );
3255 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3257 /* If this is an external invocation of the interface, we should be
3258 * letting everyone know that things have changed. Otherwise this is
3259 * just an initialization and it doesn't need to be propagated.
3263 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3269 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3270 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3272 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3273 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3276 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3277 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3279 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3280 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3283 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3284 DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3288 if( lpSessDesc == NULL )
3290 /* Hmmm..don't need any size? */
3291 ERR( "NULL lpSessDesc\n" );
3295 dwSize += sizeof( *lpSessDesc );
3299 if( lpSessDesc->u1.lpszSessionNameA )
3301 dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1;
3304 if( lpSessDesc->u2.lpszPasswordA )
3306 dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1;
3311 if( lpSessDesc->u1.lpszSessionName )
3313 dwSize += sizeof( WCHAR ) *
3314 ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 );
3317 if( lpSessDesc->u2.lpszPassword )
3319 dwSize += sizeof( WCHAR ) *
3320 ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 );
3327 /* Assumes that contugous buffers are already allocated. */
3328 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3329 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3331 BYTE* lpStartOfFreeSpace;
3333 if( lpSessionDest == NULL )
3335 ERR( "NULL lpSessionDest\n" );
3339 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3341 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3345 if( lpSessionSrc->u1.lpszSessionNameA )
3347 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3348 lpSessionDest->u1.lpszSessionNameA );
3349 lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3350 lpStartOfFreeSpace +=
3351 lstrlenA( (LPSTR)lpSessionDest->u1.lpszSessionNameA ) + 1;
3354 if( lpSessionSrc->u2.lpszPasswordA )
3356 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3357 lpSessionDest->u2.lpszPasswordA );
3358 lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3359 lpStartOfFreeSpace +=
3360 lstrlenA( (LPSTR)lpSessionDest->u2.lpszPasswordA ) + 1;
3365 if( lpSessionSrc->u1.lpszSessionName )
3367 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3368 lpSessionDest->u1.lpszSessionName );
3369 lpSessionDest->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3370 lpStartOfFreeSpace += sizeof(WCHAR) *
3371 ( lstrlenW( (LPWSTR)lpSessionDest->u1.lpszSessionName ) + 1 );
3374 if( lpSessionSrc->u2.lpszPassword )
3376 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3377 lpSessionDest->u2.lpszPassword );
3378 lpSessionDest->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3379 lpStartOfFreeSpace += sizeof(WCHAR) *
3380 ( lstrlenW( (LPWSTR)lpSessionDest->u2.lpszPassword ) + 1 );
3386 static HRESULT WINAPI DP_IF_AddGroupToGroup
3387 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3389 lpGroupData lpGParentData;
3390 lpGroupData lpGData;
3391 lpGroupList lpNewGList;
3393 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, idParentGroup, idGroup );
3395 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3397 return DPERR_INVALIDGROUP;
3400 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3402 return DPERR_INVALIDGROUP;
3405 /* Create a player list (ie "shortcut" ) */
3406 lpNewGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewGList ) );
3407 if( lpNewGList == NULL )
3409 return DPERR_CANTADDPLAYER;
3412 /* Add the shortcut */
3414 lpNewGList->lpGData = lpGData;
3416 /* Add the player to the list of players for this group */
3417 DPQ_INSERT( lpGData->groups, lpNewGList, groups );
3419 /* Send a ADDGROUPTOGROUP message */
3420 FIXME( "Not sending message\n" );
3425 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3426 ( LPDIRECTPLAY3A iface, DPID idParentGroup, DPID idGroup )
3428 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3429 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3432 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3433 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3435 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3436 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3439 static HRESULT WINAPI DP_IF_CreateGroupInGroup
3440 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
3441 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
3442 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3444 lpGroupData lpGParentData;
3445 lpGroupList lpGList;
3446 lpGroupData lpGData;
3448 TRACE( "(%p)->(0x%08x,%p,%p,%p,0x%08x,0x%08x,%u)\n",
3449 This, idParentGroup, lpidGroup, lpGroupName, lpData,
3450 dwDataSize, dwFlags, bAnsi );
3452 /* Verify that the specified parent is valid */
3453 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This,
3454 idParentGroup ) ) == NULL
3457 return DPERR_INVALIDGROUP;
3460 lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName,
3461 dwFlags, idParentGroup, bAnsi );
3463 if( lpGData == NULL )
3465 return DPERR_CANTADDPLAYER; /* yes player not group */
3468 /* Something else is referencing this data */
3471 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
3473 /* The list has now been inserted into the interface group list. We now
3474 need to put a "shortcut" to this group in the parent group */
3475 lpGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGList ) );
3476 if( lpGList == NULL )
3478 FIXME( "Memory leak\n" );
3479 return DPERR_CANTADDPLAYER; /* yes player not group */
3482 lpGList->lpGData = lpGData;
3484 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
3486 /* Let the SP know that we've created this group */
3487 if( This->dp2->spData.lpCB->CreateGroup )
3489 DPSP_CREATEGROUPDATA data;
3491 TRACE( "Calling SP CreateGroup\n" );
3493 data.idGroup = *lpidGroup;
3494 data.dwFlags = dwFlags;
3495 data.lpSPMessageHeader = lpMsgHdr;
3496 data.lpISP = This->dp2->spData.lpISP;
3498 (*This->dp2->spData.lpCB->CreateGroup)( &data );
3501 /* Inform all other peers of the creation of a new group. If there are
3502 * no peers keep this quiet.
3504 if( This->dp2->lpSessionDesc &&
3505 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
3507 DPMSG_CREATEPLAYERORGROUP msg;
3509 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
3510 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
3511 msg.dpId = *lpidGroup;
3512 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
3513 msg.lpData = lpData;
3514 msg.dwDataSize = dwDataSize;
3515 msg.dpnName = *lpGroupName;
3517 /* FIXME: Correct to just use send effectively? */
3518 /* FIXME: Should size include data w/ message or just message "header" */
3519 /* FIXME: Check return code */
3520 DP_SendEx( (IDirectPlay2Impl*)This,
3521 DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
3522 0, 0, NULL, NULL, bAnsi );
3528 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3529 ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup,
3530 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3533 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3535 *lpidGroup = DPID_UNKNOWN;
3537 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3538 lpGroupName, lpData, dwDataSize, dwFlags,
3542 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3543 ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup,
3544 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3547 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3549 *lpidGroup = DPID_UNKNOWN;
3551 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3552 lpGroupName, lpData, dwDataSize,
3556 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
3557 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3559 lpGroupList lpGList;
3560 lpGroupData lpGParentData;
3562 TRACE("(%p)->(0x%08x,0x%08x)\n", This, idParentGroup, idGroup );
3564 /* Is the parent group valid? */
3565 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3567 return DPERR_INVALIDGROUP;
3570 /* Remove the group from the parent group queue */
3571 DPQ_REMOVE_ENTRY( lpGParentData->groups, groups, lpGData->dpid, ==, idGroup, lpGList );
3573 if( lpGList == NULL )
3575 return DPERR_INVALIDGROUP;
3578 /* Decrement the ref count */
3579 lpGList->lpGData->uRef--;
3581 /* Free up the list item */
3582 HeapFree( GetProcessHeap(), 0, lpGList );
3584 /* Should send a DELETEGROUPFROMGROUP message */
3585 FIXME( "message not sent\n" );
3590 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3591 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3593 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3594 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3597 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3598 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3600 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3601 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3605 BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
3606 LPDWORD lpdwBufSize )
3608 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3611 dpCompoundAddress.dwDataSize = sizeof( GUID );
3612 memcpy( &dpCompoundAddress.guidDataType, &DPAID_ServiceProvider,
3614 dpCompoundAddress.lpData = lpcSpGuid;
3616 *lplpAddrBuf = NULL;
3619 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3620 lpdwBufSize, TRUE );
3622 if( hr != DPERR_BUFFERTOOSMALL )
3624 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3628 /* Now allocate the buffer */
3629 *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3632 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3633 lpdwBufSize, TRUE );
3636 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3643 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
3644 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3646 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3647 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3649 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
3652 dwFlags = DPCONNECTION_DIRECTPLAY;
3655 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
3656 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) )
3659 return DPERR_INVALIDFLAGS;
3662 if( !lpEnumCallback || !*lpEnumCallback )
3664 return DPERR_INVALIDPARAMS;
3667 /* Enumerate DirectPlay service providers */
3668 if( dwFlags & DPCONNECTION_DIRECTPLAY )
3671 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3672 LPCSTR guidDataSubKey = "Guid";
3673 char subKeyName[51];
3674 DWORD dwIndex, sizeOfSubKeyName=50;
3677 /* Need to loop over the service providers in the registry */
3678 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3679 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3681 /* Hmmm. Does this mean that there are no service providers? */
3682 ERR(": no service providers?\n");
3687 /* Traverse all the service providers we have available */
3689 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3690 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3691 ++dwIndex, sizeOfSubKeyName=51 )
3694 HKEY hkServiceProvider;
3695 GUID serviceProviderGUID;
3696 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3697 char returnBuffer[51];
3702 LPVOID lpAddressBuffer = NULL;
3703 DWORD dwAddressBufferSize = 0;
3705 TRACE(" this time through: %s\n", subKeyName );
3707 /* Get a handle for this particular service provider */
3708 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3709 &hkServiceProvider ) != ERROR_SUCCESS )
3711 ERR(": what the heck is going on?\n" );
3715 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3716 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
3717 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3719 ERR(": missing GUID registry data members\n" );
3723 /* FIXME: Check return types to ensure we're interpreting data right */
3724 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3725 CLSIDFromString( buff, &serviceProviderGUID );
3726 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3728 /* Fill in the DPNAME struct for the service provider */
3729 dpName.dwSize = sizeof( dpName );
3731 dpName.u1.lpszShortNameA = subKeyName;
3732 dpName.u2.lpszLongNameA = NULL;
3734 /* Create the compound address for the service provider.
3735 * NOTE: This is a gruesome architectural scar right now. DP
3736 * uses DPL and DPL uses DP. Nasty stuff. This may be why the
3737 * native dll just gets around this little bit by allocating an
3738 * 80 byte buffer which isn't even filled with a valid compound
3739 * address. Oh well. Creating a proper compound address is the
3740 * way to go anyways despite this method taking slightly more
3741 * heap space and realtime :) */
3743 bBuildPass = DP_BuildSPCompoundAddr( &serviceProviderGUID,
3745 &dwAddressBufferSize );
3748 ERR( "Can't build compound addr\n" );
3749 return DPERR_GENERIC;
3752 /* The enumeration will return FALSE if we are not to continue */
3753 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3754 &dpName, DPCONNECTION_DIRECTPLAY, lpContext ) )
3761 /* Enumerate DirectPlayLobby service providers */
3762 if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY )
3765 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3766 LPCSTR guidDataSubKey = "Guid";
3767 char subKeyName[51];
3768 DWORD dwIndex, sizeOfSubKeyName=50;
3771 /* Need to loop over the service providers in the registry */
3772 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3773 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3775 /* Hmmm. Does this mean that there are no service providers? */
3776 ERR(": no service providers?\n");
3781 /* Traverse all the lobby providers we have available */
3783 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3784 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3785 ++dwIndex, sizeOfSubKeyName=51 )
3788 HKEY hkServiceProvider;
3789 GUID serviceProviderGUID;
3790 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3791 char returnBuffer[51];
3796 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3797 LPVOID lpAddressBuffer = NULL;
3798 DWORD dwAddressBufferSize = 0;
3800 TRACE(" this time through: %s\n", subKeyName );
3802 /* Get a handle for this particular service provider */
3803 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3804 &hkServiceProvider ) != ERROR_SUCCESS )
3806 ERR(": what the heck is going on?\n" );
3810 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3811 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
3812 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3814 ERR(": missing GUID registry data members\n" );
3818 /* FIXME: Check return types to ensure we're interpreting data right */
3819 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3820 CLSIDFromString( buff, &serviceProviderGUID );
3821 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3823 /* Fill in the DPNAME struct for the service provider */
3824 dpName.dwSize = sizeof( dpName );
3826 dpName.u1.lpszShortNameA = subKeyName;
3827 dpName.u2.lpszLongNameA = NULL;
3829 /* Create the compound address for the service provider.
3830 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
3831 nast stuff. This may be why the native dll just gets around this little bit by
3832 allocating an 80 byte buffer which isn't even a filled with a valid compound
3833 address. Oh well. Creating a proper compound address is the way to go anyways
3834 despite this method taking slightly more heap space and realtime :) */
3836 dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
3837 dpCompoundAddress.dwDataSize = sizeof( GUID );
3838 dpCompoundAddress.lpData = &serviceProviderGUID;
3840 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3841 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
3843 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3847 /* Now allocate the buffer */
3848 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
3850 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3851 &dwAddressBufferSize, TRUE ) ) != DP_OK )
3853 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3857 /* The enumeration will return FALSE if we are not to continue */
3858 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3859 &dpName, DPCONNECTION_DIRECTPLAYLOBBY, lpContext ) )
3869 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
3870 ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3872 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3873 FIXME("(%p)->(%p,%p,%p,0x%08x): stub\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3877 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
3878 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
3879 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
3880 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
3882 lpGroupList lpGList;
3883 lpGroupData lpGData;
3885 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
3886 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
3887 lpContext, dwFlags, bAnsi );
3889 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3891 return DPERR_INVALIDGROUP;
3894 if( DPQ_IS_EMPTY( lpGData->groups ) )
3899 lpGList = DPQ_FIRST( lpGData->groups );
3903 /* FIXME: Should check dwFlags for match here */
3905 if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP,
3906 &lpGList->lpGData->name, dwFlags,
3909 return DP_OK; /* User requested break */
3912 if( DPQ_IS_ENDOFLIST( lpGList->groups ) )
3917 lpGList = DPQ_NEXT( lpGList->groups );
3924 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
3925 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3926 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3929 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3930 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3931 lpEnumPlayersCallback2, lpContext, dwFlags,
3935 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
3936 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3937 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3940 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3941 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3942 lpEnumPlayersCallback2, lpContext, dwFlags,
3946 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
3947 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3949 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3950 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3954 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
3955 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3957 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3958 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3962 static BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
3963 REFGUID guidDataType,
3968 /* Looking for the GUID of the provider to load */
3969 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
3970 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
3973 TRACE( "Found SP/LP (%s) %s (data size = 0x%08x)\n",
3974 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
3976 if( dwDataSize != sizeof( GUID ) )
3978 ERR( "Invalid sp/lp guid size 0x%08x\n", dwDataSize );
3981 memcpy( lpContext, lpData, dwDataSize );
3983 /* There shouldn't be more than 1 GUID/compound address */
3987 /* Still waiting for what we want */
3992 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
3993 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
3996 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3997 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3998 LPCSTR guidDataSubKey = "Guid";
3999 LPCSTR majVerDataSubKey = "dwReserved1";
4000 LPCSTR minVerDataSubKey = "dwReserved2";
4001 LPCSTR pathSubKey = "Path";
4003 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
4005 /* FIXME: Cloned code with a quick hack. */
4006 for( i=0; i<2; i++ )
4009 LPCSTR searchSubKey;
4010 char subKeyName[51];
4011 DWORD dwIndex, sizeOfSubKeyName=50;
4014 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
4015 *lpbIsDpSp = (i == 0) ? TRUE : FALSE;
4018 /* Need to loop over the service providers in the registry */
4019 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4020 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4022 /* Hmmm. Does this mean that there are no service providers? */
4023 ERR(": no service providers?\n");
4027 /* Traverse all the service providers we have available */
4029 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4030 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4031 ++dwIndex, sizeOfSubKeyName=51 )
4034 HKEY hkServiceProvider;
4035 GUID serviceProviderGUID;
4036 DWORD returnType, sizeOfReturnBuffer = 255;
4037 char returnBuffer[256];
4041 TRACE(" this time through: %s\n", subKeyName );
4043 /* Get a handle for this particular service provider */
4044 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4045 &hkServiceProvider ) != ERROR_SUCCESS )
4047 ERR(": what the heck is going on?\n" );
4051 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4052 NULL, &returnType, (LPBYTE)returnBuffer,
4053 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4055 ERR(": missing GUID registry data members\n" );
4059 /* FIXME: Check return types to ensure we're interpreting data right */
4060 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4061 CLSIDFromString( buff, &serviceProviderGUID );
4062 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4064 /* Determine if this is the Service Provider that the user asked for */
4065 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
4070 if( i == 0 ) /* DP SP */
4072 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
4073 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
4074 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
4077 sizeOfReturnBuffer = 255;
4079 /* Get dwReserved1 */
4080 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
4081 NULL, &returnType, (LPBYTE)returnBuffer,
4082 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4084 ERR(": missing dwReserved1 registry data members\n") ;
4089 memcpy( &lpSpData->dwReserved1, returnBuffer, sizeof(lpSpData->dwReserved1) );
4091 sizeOfReturnBuffer = 255;
4093 /* Get dwReserved2 */
4094 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4095 NULL, &returnType, (LPBYTE)returnBuffer,
4096 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4098 ERR(": missing dwReserved1 registry data members\n") ;
4103 memcpy( &lpSpData->dwReserved2, returnBuffer, sizeof(lpSpData->dwReserved2) );
4105 sizeOfReturnBuffer = 255;
4107 /* Get the path for this service provider */
4108 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
4109 NULL, NULL, (LPBYTE)returnBuffer,
4110 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
4112 ERR(": missing PATH registry data members: 0x%08x\n", dwTemp );
4116 TRACE( "Loading %s\n", returnBuffer );
4117 return LoadLibraryA( returnBuffer );
4125 HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider )
4128 LPDPSP_SPINIT SPInit;
4130 /* Initialize the service provider by calling SPInit */
4131 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4133 if( SPInit == NULL )
4135 ERR( "Service provider doesn't provide SPInit interface?\n" );
4136 FreeLibrary( hServiceProvider );
4137 return DPERR_UNAVAILABLE;
4140 TRACE( "Calling SPInit (DP SP entry point)\n" );
4142 hr = (*SPInit)( &This->dp2->spData );
4146 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4147 FreeLibrary( hServiceProvider );
4151 /* FIXME: Need to verify the sanity of the returned callback table
4152 * using IsBadCodePtr */
4153 This->dp2->bSPInitialized = TRUE;
4155 /* This interface is now initialized as a DP object */
4156 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
4158 /* Store the handle of the module so that we can unload it later */
4159 This->dp2->hServiceProvider = hServiceProvider;
4165 HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hLobbyProvider )
4168 LPSP_INIT DPLSPInit;
4170 /* Initialize the service provider by calling SPInit */
4171 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
4173 if( DPLSPInit == NULL )
4175 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4176 FreeLibrary( hLobbyProvider );
4177 return DPERR_UNAVAILABLE;
4180 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4182 hr = (*DPLSPInit)( &This->dp2->dplspData );
4186 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4187 FreeLibrary( hLobbyProvider );
4191 /* FIXME: Need to verify the sanity of the returned callback table
4192 * using IsBadCodePtr */
4194 This->dp2->bDPLSPInitialized = TRUE;
4196 /* This interface is now initialized as a lobby object */
4197 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
4199 /* Store the handle of the module so that we can unload it later */
4200 This->dp2->hDPLobbyProvider = hLobbyProvider;
4205 static HRESULT WINAPI DP_IF_InitializeConnection
4206 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi )
4208 HMODULE hServiceProvider;
4211 const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
4212 BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4214 TRACE("(%p)->(%p,0x%08x,%u)\n", This, lpConnection, dwFlags, bAnsi );
4218 return DPERR_INVALIDFLAGS;
4221 /* Find out what the requested SP is and how large this buffer is */
4222 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
4223 dwAddrSize, &guidSP );
4227 ERR( "Invalid compound address?\n" );
4228 return DPERR_UNAVAILABLE;
4231 /* Load the service provider */
4232 hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp );
4234 if( hServiceProvider == 0 )
4236 ERR( "Unable to load service provider %s\n", debugstr_guid(&guidSP) );
4237 return DPERR_UNAVAILABLE;
4242 /* Fill in what we can of the Service Provider required information.
4243 * The rest was be done in DP_LoadSP
4245 This->dp2->spData.lpAddress = lpConnection;
4246 This->dp2->spData.dwAddressSize = dwAddrSize;
4247 This->dp2->spData.lpGuid = &guidSP;
4249 hr = DP_InitializeDPSP( This, hServiceProvider );
4253 This->dp2->dplspData.lpAddress = lpConnection;
4255 hr = DP_InitializeDPLSP( This, hServiceProvider );
4266 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4267 ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
4269 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4271 /* This may not be externally invoked once either an SP or LP is initialized */
4272 if( This->dp2->connectionInitialized != NO_PROVIDER )
4274 return DPERR_ALREADYINITIALIZED;
4277 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE );
4280 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4281 ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
4283 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4285 /* This may not be externally invoked once either an SP or LP is initialized */
4286 if( This->dp2->connectionInitialized != NO_PROVIDER )
4288 return DPERR_ALREADYINITIALIZED;
4291 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE );
4294 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4295 ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4296 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4298 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4299 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4302 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4303 ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4304 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4306 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4307 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4310 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4311 ( LPDIRECTPLAY3A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4313 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4314 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4318 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4319 ( LPDIRECTPLAY3 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4321 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4322 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4326 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4327 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4329 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4330 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4334 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4335 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4337 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4338 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4342 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4343 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup )
4345 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4346 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, dwFlags, idGroup );
4350 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4351 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup )
4353 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4354 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, dwFlags, idGroup );
4358 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4359 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDWORD lpdwFlags )
4361 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4362 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpdwFlags );
4366 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4367 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDWORD lpdwFlags )
4369 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4370 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpdwFlags );
4374 static HRESULT WINAPI DP_IF_GetGroupParent
4375 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
4378 lpGroupData lpGData;
4380 TRACE("(%p)->(0x%08x,%p,%u)\n", This, idGroup, lpidGroup, bAnsi );
4382 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4384 return DPERR_INVALIDGROUP;
4387 *lpidGroup = lpGData->dpid;
4392 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4393 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
4395 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4396 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE );
4398 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4399 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
4401 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4402 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE );
4405 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4406 ( LPDIRECTPLAY3A iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4408 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4409 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4413 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4414 ( LPDIRECTPLAY3 iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4416 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4417 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4421 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4422 ( LPDIRECTPLAY3A iface, DPID idPlayer, LPDWORD lpdwFlags )
4424 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4425 FIXME("(%p)->(0x%08x,%p): stub\n", This, idPlayer, lpdwFlags );
4429 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4430 ( LPDIRECTPLAY3 iface, DPID idPlayer, LPDWORD lpdwFlags )
4432 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4433 FIXME("(%p)->(0x%08x,%p): stub\n", This, idPlayer, lpdwFlags );
4437 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4438 ( LPDIRECTPLAY4A iface, DPID idGroup, LPDPID lpidGroupOwner )
4440 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4441 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpidGroupOwner );
4445 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4446 ( LPDIRECTPLAY4 iface, DPID idGroup, LPDPID lpidGroupOwner )
4448 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4449 FIXME("(%p)->(0x%08x,%p): stub\n", This, idGroup, lpidGroupOwner );
4453 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4454 ( LPDIRECTPLAY4A iface, DPID idGroup , DPID idGroupOwner )
4456 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4457 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, idGroup, idGroupOwner );
4461 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4462 ( LPDIRECTPLAY4 iface, DPID idGroup , DPID idGroupOwner )
4464 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4465 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This, idGroup, idGroupOwner );
4469 static HRESULT WINAPI DP_SendEx
4470 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4471 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4472 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi )
4474 lpPlayerList lpPList;
4475 lpGroupData lpGData;
4476 BOOL bValidDestination = FALSE;
4478 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,0x%08x,0x%08x,0x%08x,%p,%p,%u)"
4480 This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority,
4481 dwTimeout, lpContext, lpdwMsgID, bAnsi );
4483 /* FIXME: Add parameter checking */
4484 /* FIXME: First call to this needs to acquire a message id which will be
4485 * used for multiple sends
4488 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4490 /* Verify that the message is being sent from a valid local player. The
4491 * from player may be anonymous DPID_UNKNOWN
4493 if( idFrom != DPID_UNKNOWN )
4495 if( ( lpPList = DP_FindPlayer( This, idFrom ) ) == NULL )
4497 WARN( "INFO: Invalid from player 0x%08x\n", idFrom );
4498 return DPERR_INVALIDPLAYER;
4502 /* Verify that the message is being sent to a valid player, group or to
4503 * everyone. If it's valid, send it to those players.
4505 if( idTo == DPID_ALLPLAYERS )
4507 bValidDestination = TRUE;
4509 /* See if SP has the ability to multicast. If so, use it */
4510 if( This->dp2->spData.lpCB->SendToGroupEx )
4512 FIXME( "Use group sendex to group 0\n" );
4514 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4516 FIXME( "Use obsolete group send to group 0\n" );
4518 else /* No multicast, multiplicate */
4520 /* Send to all players we know about */
4521 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4525 if( ( !bValidDestination ) &&
4526 ( DP_FindPlayer( This, idTo ) != NULL )
4529 bValidDestination = TRUE;
4531 /* Have the service provider send this message */
4532 /* FIXME: Could optimize for local interface sends */
4533 return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority,
4534 dwTimeout, lpContext, lpdwMsgID );
4537 if( ( !bValidDestination ) &&
4538 ( ( lpGData = DP_FindAnyGroup( This, idTo ) ) != NULL )
4541 bValidDestination = TRUE;
4543 /* See if SP has the ability to multicast. If so, use it */
4544 if( This->dp2->spData.lpCB->SendToGroupEx )
4546 FIXME( "Use group sendex\n" );
4548 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4550 FIXME( "Use obsolete group send to group\n" );
4552 else /* No multicast, multiplicate */
4554 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4562 This->dp2->hReplyEvent = CreateEventW( NULL, FALSE, FALSE, NULL );
4564 dwWaitReturn = WaitForSingleObject( hReplyEvent, dwTimeout );
4565 if( dwWaitReturn != WAIT_OBJECT_0 )
4567 ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
4573 if( !bValidDestination )
4575 return DPERR_INVALIDPLAYER;
4579 /* FIXME: Should return what the send returned */
4585 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4586 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4587 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4588 LPVOID lpContext, LPDWORD lpdwMsgID )
4590 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4591 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4592 dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE );
4595 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4596 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4597 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4598 LPVOID lpContext, LPDWORD lpdwMsgID )
4600 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4601 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4602 dwPriority, dwTimeout, lpContext, lpdwMsgID, FALSE );
4605 static HRESULT WINAPI DP_SP_SendEx
4606 ( IDirectPlay2Impl* This, DWORD dwFlags,
4607 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4608 LPVOID lpContext, LPDWORD lpdwMsgID )
4612 FIXME( ": stub\n" );
4614 /* FIXME: This queuing should only be for async messages */
4616 lpMElem = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpMElem ) );
4617 lpMElem->msg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
4619 CopyMemory( lpMElem->msg, lpData, dwDataSize );
4621 /* FIXME: Need to queue based on priority */
4622 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
4627 static HRESULT WINAPI DP_IF_GetMessageQueue
4628 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4629 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi )
4633 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%p,%u): semi stub\n",
4634 This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi );
4636 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4637 /* FIXME: What about sends which are not immediate? */
4639 if( This->dp2->spData.lpCB->GetMessageQueue )
4641 DPSP_GETMESSAGEQUEUEDATA data;
4643 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4645 /* FIXME: None of this is documented :( */
4647 data.lpISP = This->dp2->spData.lpISP;
4648 data.dwFlags = dwFlags;
4649 data.idFrom = idFrom;
4651 data.lpdwNumMsgs = lpdwNumMsgs;
4652 data.lpdwNumBytes = lpdwNumBytes;
4654 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
4658 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4664 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4665 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4666 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4668 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4669 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4670 lpdwNumBytes, TRUE );
4673 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4674 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4675 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4677 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4678 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4679 lpdwNumBytes, FALSE );
4682 static HRESULT WINAPI DP_IF_CancelMessage
4683 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
4684 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi )
4688 FIXME( "(%p)->(0x%08x,0x%08x,%u): semi stub\n",
4689 This, dwMsgID, dwFlags, bAnsi );
4691 if( This->dp2->spData.lpCB->Cancel )
4693 DPSP_CANCELDATA data;
4695 TRACE( "Calling SP Cancel\n" );
4697 /* FIXME: Undocumented callback */
4699 data.lpISP = This->dp2->spData.lpISP;
4700 data.dwFlags = dwFlags;
4701 data.lprglpvSPMsgID = NULL;
4702 data.cSPMsgID = dwMsgID;
4703 data.dwMinPriority = dwMinPriority;
4704 data.dwMaxPriority = dwMaxPriority;
4706 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
4710 FIXME( "SP doesn't implement Cancel\n" );
4716 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
4717 ( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags )
4719 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4723 return DPERR_INVALIDFLAGS;
4728 dwFlags |= DPCANCELSEND_ALL;
4731 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE );
4734 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
4735 ( LPDIRECTPLAY4 iface, DWORD dwMsgID, DWORD dwFlags )
4737 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4741 return DPERR_INVALIDFLAGS;
4746 dwFlags |= DPCANCELSEND_ALL;
4749 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, FALSE );
4752 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
4753 ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4756 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4760 return DPERR_INVALIDFLAGS;
4763 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4764 dwMaxPriority, TRUE );
4767 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
4768 ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4771 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4775 return DPERR_INVALIDFLAGS;
4778 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4779 dwMaxPriority, FALSE );
4782 /* Note: Hack so we can reuse the old functions without compiler warnings */
4783 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4784 # define XCAST(fun) (typeof(directPlay2WVT.fun))
4786 # define XCAST(fun) (void*)
4789 static const IDirectPlay2Vtbl directPlay2WVT =
4791 XCAST(QueryInterface)DP_QueryInterface,
4792 XCAST(AddRef)DP_AddRef,
4793 XCAST(Release)DP_Release,
4795 DirectPlay2WImpl_AddPlayerToGroup,
4796 DirectPlay2WImpl_Close,
4797 DirectPlay2WImpl_CreateGroup,
4798 DirectPlay2WImpl_CreatePlayer,
4799 DirectPlay2WImpl_DeletePlayerFromGroup,
4800 DirectPlay2WImpl_DestroyGroup,
4801 DirectPlay2WImpl_DestroyPlayer,
4802 DirectPlay2WImpl_EnumGroupPlayers,
4803 DirectPlay2WImpl_EnumGroups,
4804 DirectPlay2WImpl_EnumPlayers,
4805 DirectPlay2WImpl_EnumSessions,
4806 DirectPlay2WImpl_GetCaps,
4807 DirectPlay2WImpl_GetGroupData,
4808 DirectPlay2WImpl_GetGroupName,
4809 DirectPlay2WImpl_GetMessageCount,
4810 DirectPlay2WImpl_GetPlayerAddress,
4811 DirectPlay2WImpl_GetPlayerCaps,
4812 DirectPlay2WImpl_GetPlayerData,
4813 DirectPlay2WImpl_GetPlayerName,
4814 DirectPlay2WImpl_GetSessionDesc,
4815 DirectPlay2WImpl_Initialize,
4816 DirectPlay2WImpl_Open,
4817 DirectPlay2WImpl_Receive,
4818 DirectPlay2WImpl_Send,
4819 DirectPlay2WImpl_SetGroupData,
4820 DirectPlay2WImpl_SetGroupName,
4821 DirectPlay2WImpl_SetPlayerData,
4822 DirectPlay2WImpl_SetPlayerName,
4823 DirectPlay2WImpl_SetSessionDesc
4827 /* Note: Hack so we can reuse the old functions without compiler warnings */
4828 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4829 # define XCAST(fun) (typeof(directPlay2AVT.fun))
4831 # define XCAST(fun) (void*)
4834 static const IDirectPlay2Vtbl directPlay2AVT =
4836 XCAST(QueryInterface)DP_QueryInterface,
4837 XCAST(AddRef)DP_AddRef,
4838 XCAST(Release)DP_Release,
4840 DirectPlay2AImpl_AddPlayerToGroup,
4841 DirectPlay2AImpl_Close,
4842 DirectPlay2AImpl_CreateGroup,
4843 DirectPlay2AImpl_CreatePlayer,
4844 DirectPlay2AImpl_DeletePlayerFromGroup,
4845 DirectPlay2AImpl_DestroyGroup,
4846 DirectPlay2AImpl_DestroyPlayer,
4847 DirectPlay2AImpl_EnumGroupPlayers,
4848 DirectPlay2AImpl_EnumGroups,
4849 DirectPlay2AImpl_EnumPlayers,
4850 DirectPlay2AImpl_EnumSessions,
4851 DirectPlay2AImpl_GetCaps,
4852 DirectPlay2AImpl_GetGroupData,
4853 DirectPlay2AImpl_GetGroupName,
4854 DirectPlay2AImpl_GetMessageCount,
4855 DirectPlay2AImpl_GetPlayerAddress,
4856 DirectPlay2AImpl_GetPlayerCaps,
4857 DirectPlay2AImpl_GetPlayerData,
4858 DirectPlay2AImpl_GetPlayerName,
4859 DirectPlay2AImpl_GetSessionDesc,
4860 DirectPlay2AImpl_Initialize,
4861 DirectPlay2AImpl_Open,
4862 DirectPlay2AImpl_Receive,
4863 DirectPlay2AImpl_Send,
4864 DirectPlay2AImpl_SetGroupData,
4865 DirectPlay2AImpl_SetGroupName,
4866 DirectPlay2AImpl_SetPlayerData,
4867 DirectPlay2AImpl_SetPlayerName,
4868 DirectPlay2AImpl_SetSessionDesc
4873 /* Note: Hack so we can reuse the old functions without compiler warnings */
4874 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4875 # define XCAST(fun) (typeof(directPlay3AVT.fun))
4877 # define XCAST(fun) (void*)
4880 static const IDirectPlay3Vtbl directPlay3AVT =
4882 XCAST(QueryInterface)DP_QueryInterface,
4883 XCAST(AddRef)DP_AddRef,
4884 XCAST(Release)DP_Release,
4886 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
4887 XCAST(Close)DirectPlay2AImpl_Close,
4888 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
4889 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
4890 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
4891 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
4892 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
4893 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
4894 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
4895 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
4896 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
4897 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
4898 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
4899 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
4900 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
4901 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
4902 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
4903 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
4904 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
4905 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
4906 XCAST(Initialize)DirectPlay2AImpl_Initialize,
4907 XCAST(Open)DirectPlay2AImpl_Open,
4908 XCAST(Receive)DirectPlay2AImpl_Receive,
4909 XCAST(Send)DirectPlay2AImpl_Send,
4910 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
4911 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
4912 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
4913 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
4914 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
4916 DirectPlay3AImpl_AddGroupToGroup,
4917 DirectPlay3AImpl_CreateGroupInGroup,
4918 DirectPlay3AImpl_DeleteGroupFromGroup,
4919 DirectPlay3AImpl_EnumConnections,
4920 DirectPlay3AImpl_EnumGroupsInGroup,
4921 DirectPlay3AImpl_GetGroupConnectionSettings,
4922 DirectPlay3AImpl_InitializeConnection,
4923 DirectPlay3AImpl_SecureOpen,
4924 DirectPlay3AImpl_SendChatMessage,
4925 DirectPlay3AImpl_SetGroupConnectionSettings,
4926 DirectPlay3AImpl_StartSession,
4927 DirectPlay3AImpl_GetGroupFlags,
4928 DirectPlay3AImpl_GetGroupParent,
4929 DirectPlay3AImpl_GetPlayerAccount,
4930 DirectPlay3AImpl_GetPlayerFlags
4934 /* Note: Hack so we can reuse the old functions without compiler warnings */
4935 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4936 # define XCAST(fun) (typeof(directPlay3WVT.fun))
4938 # define XCAST(fun) (void*)
4940 static const IDirectPlay3Vtbl directPlay3WVT =
4942 XCAST(QueryInterface)DP_QueryInterface,
4943 XCAST(AddRef)DP_AddRef,
4944 XCAST(Release)DP_Release,
4946 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
4947 XCAST(Close)DirectPlay2WImpl_Close,
4948 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
4949 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
4950 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
4951 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
4952 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
4953 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
4954 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
4955 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
4956 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
4957 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
4958 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
4959 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
4960 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
4961 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
4962 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
4963 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
4964 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
4965 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
4966 XCAST(Initialize)DirectPlay2WImpl_Initialize,
4967 XCAST(Open)DirectPlay2WImpl_Open,
4968 XCAST(Receive)DirectPlay2WImpl_Receive,
4969 XCAST(Send)DirectPlay2WImpl_Send,
4970 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
4971 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
4972 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
4973 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
4974 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
4976 DirectPlay3WImpl_AddGroupToGroup,
4977 DirectPlay3WImpl_CreateGroupInGroup,
4978 DirectPlay3WImpl_DeleteGroupFromGroup,
4979 DirectPlay3WImpl_EnumConnections,
4980 DirectPlay3WImpl_EnumGroupsInGroup,
4981 DirectPlay3WImpl_GetGroupConnectionSettings,
4982 DirectPlay3WImpl_InitializeConnection,
4983 DirectPlay3WImpl_SecureOpen,
4984 DirectPlay3WImpl_SendChatMessage,
4985 DirectPlay3WImpl_SetGroupConnectionSettings,
4986 DirectPlay3WImpl_StartSession,
4987 DirectPlay3WImpl_GetGroupFlags,
4988 DirectPlay3WImpl_GetGroupParent,
4989 DirectPlay3WImpl_GetPlayerAccount,
4990 DirectPlay3WImpl_GetPlayerFlags
4994 /* Note: Hack so we can reuse the old functions without compiler warnings */
4995 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4996 # define XCAST(fun) (typeof(directPlay4WVT.fun))
4998 # define XCAST(fun) (void*)
5000 static const IDirectPlay4Vtbl directPlay4WVT =
5002 XCAST(QueryInterface)DP_QueryInterface,
5003 XCAST(AddRef)DP_AddRef,
5004 XCAST(Release)DP_Release,
5006 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
5007 XCAST(Close)DirectPlay2WImpl_Close,
5008 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
5009 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
5010 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
5011 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
5012 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5013 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5014 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5015 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5016 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5017 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5018 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5019 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5020 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5021 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5022 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5023 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5024 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5025 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5026 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5027 XCAST(Open)DirectPlay2WImpl_Open,
5028 XCAST(Receive)DirectPlay2WImpl_Receive,
5029 XCAST(Send)DirectPlay2WImpl_Send,
5030 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5031 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5032 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5033 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5034 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5036 XCAST(AddGroupToGroup)DirectPlay3WImpl_AddGroupToGroup,
5037 XCAST(CreateGroupInGroup)DirectPlay3WImpl_CreateGroupInGroup,
5038 XCAST(DeleteGroupFromGroup)DirectPlay3WImpl_DeleteGroupFromGroup,
5039 XCAST(EnumConnections)DirectPlay3WImpl_EnumConnections,
5040 XCAST(EnumGroupsInGroup)DirectPlay3WImpl_EnumGroupsInGroup,
5041 XCAST(GetGroupConnectionSettings)DirectPlay3WImpl_GetGroupConnectionSettings,
5042 XCAST(InitializeConnection)DirectPlay3WImpl_InitializeConnection,
5043 XCAST(SecureOpen)DirectPlay3WImpl_SecureOpen,
5044 XCAST(SendChatMessage)DirectPlay3WImpl_SendChatMessage,
5045 XCAST(SetGroupConnectionSettings)DirectPlay3WImpl_SetGroupConnectionSettings,
5046 XCAST(StartSession)DirectPlay3WImpl_StartSession,
5047 XCAST(GetGroupFlags)DirectPlay3WImpl_GetGroupFlags,
5048 XCAST(GetGroupParent)DirectPlay3WImpl_GetGroupParent,
5049 XCAST(GetPlayerAccount)DirectPlay3WImpl_GetPlayerAccount,
5050 XCAST(GetPlayerFlags)DirectPlay3WImpl_GetPlayerFlags,
5052 DirectPlay4WImpl_GetGroupOwner,
5053 DirectPlay4WImpl_SetGroupOwner,
5054 DirectPlay4WImpl_SendEx,
5055 DirectPlay4WImpl_GetMessageQueue,
5056 DirectPlay4WImpl_CancelMessage,
5057 DirectPlay4WImpl_CancelPriority
5062 /* Note: Hack so we can reuse the old functions without compiler warnings */
5063 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5064 # define XCAST(fun) (typeof(directPlay4AVT.fun))
5066 # define XCAST(fun) (void*)
5068 static const IDirectPlay4Vtbl directPlay4AVT =
5070 XCAST(QueryInterface)DP_QueryInterface,
5071 XCAST(AddRef)DP_AddRef,
5072 XCAST(Release)DP_Release,
5074 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
5075 XCAST(Close)DirectPlay2AImpl_Close,
5076 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
5077 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
5078 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
5079 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
5080 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
5081 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
5082 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
5083 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
5084 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
5085 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
5086 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
5087 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
5088 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5089 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5090 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5091 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5092 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5093 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5094 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5095 XCAST(Open)DirectPlay2AImpl_Open,
5096 XCAST(Receive)DirectPlay2AImpl_Receive,
5097 XCAST(Send)DirectPlay2AImpl_Send,
5098 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5099 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5100 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5101 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5102 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5104 XCAST(AddGroupToGroup)DirectPlay3AImpl_AddGroupToGroup,
5105 XCAST(CreateGroupInGroup)DirectPlay3AImpl_CreateGroupInGroup,
5106 XCAST(DeleteGroupFromGroup)DirectPlay3AImpl_DeleteGroupFromGroup,
5107 XCAST(EnumConnections)DirectPlay3AImpl_EnumConnections,
5108 XCAST(EnumGroupsInGroup)DirectPlay3AImpl_EnumGroupsInGroup,
5109 XCAST(GetGroupConnectionSettings)DirectPlay3AImpl_GetGroupConnectionSettings,
5110 XCAST(InitializeConnection)DirectPlay3AImpl_InitializeConnection,
5111 XCAST(SecureOpen)DirectPlay3AImpl_SecureOpen,
5112 XCAST(SendChatMessage)DirectPlay3AImpl_SendChatMessage,
5113 XCAST(SetGroupConnectionSettings)DirectPlay3AImpl_SetGroupConnectionSettings,
5114 XCAST(StartSession)DirectPlay3AImpl_StartSession,
5115 XCAST(GetGroupFlags)DirectPlay3AImpl_GetGroupFlags,
5116 XCAST(GetGroupParent)DirectPlay3AImpl_GetGroupParent,
5117 XCAST(GetPlayerAccount)DirectPlay3AImpl_GetPlayerAccount,
5118 XCAST(GetPlayerFlags)DirectPlay3AImpl_GetPlayerFlags,
5120 DirectPlay4AImpl_GetGroupOwner,
5121 DirectPlay4AImpl_SetGroupOwner,
5122 DirectPlay4AImpl_SendEx,
5123 DirectPlay4AImpl_GetMessageQueue,
5124 DirectPlay4AImpl_CancelMessage,
5125 DirectPlay4AImpl_CancelPriority
5130 HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP,
5134 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5136 if( lpPlayer == NULL )
5138 return DPERR_INVALIDPLAYER;
5141 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
5147 HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP,
5151 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5153 if( lpPlayer == NULL )
5155 return DPERR_INVALIDPLAYER;
5158 lpPlayer->lpPData->lpSPPlayerData = lpData;
5163 /***************************************************************************
5164 * DirectPlayEnumerateAW
5166 * The pointer to the structure lpContext will be filled with the
5167 * appropriate data for each service offered by the OS. These services are
5168 * not necessarily available on this particular machine but are defined
5169 * as simple service providers under the "Service Providers" registry key.
5170 * This structure is then passed to lpEnumCallback for each of the different
5173 * This API is useful only for applications written using DirectX3 or
5174 * worse. It is superseded by IDirectPlay3::EnumConnections which also
5175 * gives information on the actual connections.
5177 * defn of a service provider:
5178 * A dynamic-link library used by DirectPlay to communicate over a network.
5179 * The service provider contains all the network-specific code required
5180 * to send and receive messages. Online services and network operators can
5181 * supply service providers to use specialized hardware, protocols, communications
5182 * media, and network resources.
5185 static HRESULT DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA,
5186 LPDPENUMDPCALLBACKW lpEnumCallbackW,
5190 static const WCHAR searchSubKey[] = {
5191 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
5192 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
5193 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
5194 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
5195 static const WCHAR guidKey[] = { 'G', 'u', 'i', 'd', 0 };
5196 static const WCHAR descW[] = { 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', 'W', 0 };
5201 char *descriptionA = NULL;
5202 DWORD max_sizeOfDescriptionA = 0;
5203 WCHAR *descriptionW = NULL;
5204 DWORD max_sizeOfDescriptionW = 0;
5206 if (!lpEnumCallbackA && !lpEnumCallbackW)
5208 return DPERR_INVALIDPARAMS;
5211 /* Need to loop over the service providers in the registry */
5212 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, searchSubKey,
5213 0, KEY_READ, &hkResult) != ERROR_SUCCESS)
5215 /* Hmmm. Does this mean that there are no service providers? */
5216 ERR(": no service provider key in the registry - check your Wine installation !!!\n");
5217 return DPERR_GENERIC;
5220 /* Traverse all the service providers we have available */
5224 WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */
5225 DWORD sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR);
5226 HKEY hkServiceProvider;
5227 GUID serviceProviderGUID;
5228 WCHAR guidKeyContent[(2 * 16) + 1 + 6 /* This corresponds to '{....-..-..-..-......}' */ ];
5229 DWORD sizeOfGuidKeyContent = sizeof(guidKeyContent);
5232 ret_value = RegEnumKeyExW(hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
5233 NULL, NULL, NULL, &filetime);
5234 if (ret_value == ERROR_NO_MORE_ITEMS)
5236 else if (ret_value != ERROR_SUCCESS)
5238 ERR(": could not enumerate on service provider key.\n");
5239 return DPERR_EXCEPTION;
5241 TRACE(" this time through sub-key %s.\n", debugstr_w(subKeyName));
5243 /* Open the key for this service provider */
5244 if (RegOpenKeyExW(hkResult, subKeyName, 0, KEY_READ, &hkServiceProvider) != ERROR_SUCCESS)
5246 ERR(": could not open registry key for service provider %s.\n", debugstr_w(subKeyName));
5250 /* Get the GUID from the registry */
5251 if (RegQueryValueExW(hkServiceProvider, guidKey,
5252 NULL, NULL, (LPBYTE) guidKeyContent, &sizeOfGuidKeyContent) != ERROR_SUCCESS)
5254 ERR(": missing GUID registry data member for service provider %s.\n", debugstr_w(subKeyName));
5257 if (sizeOfGuidKeyContent != sizeof(guidKeyContent))
5259 ERR(": invalid format for the GUID registry data member for service provider %s (%s).\n", debugstr_w(subKeyName), debugstr_w(guidKeyContent));
5262 CLSIDFromString(guidKeyContent, &serviceProviderGUID );
5264 /* The enumeration will return FALSE if we are not to continue.
5266 * Note: on my windows box, major / minor version is 6 / 0 for all service providers
5267 * and have no relations to any of the two dwReserved1 and dwReserved2 keys.
5268 * I think that it simply means that they are in-line with DirectX 6.0
5270 if (lpEnumCallbackA)
5272 DWORD sizeOfDescription = 0;
5274 /* Note that this the the A case of this function, so use the A variant to get the description string */
5275 if (RegQueryValueExA(hkServiceProvider, "DescriptionA",
5276 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5278 ERR(": missing 'DescriptionA' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5281 if (sizeOfDescription > max_sizeOfDescriptionA)
5283 HeapFree(GetProcessHeap(), 0, descriptionA);
5284 max_sizeOfDescriptionA = sizeOfDescription;
5285 descriptionA = HeapAlloc(GetProcessHeap(), 0, max_sizeOfDescriptionA);
5287 descriptionA = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5288 RegQueryValueExA(hkServiceProvider, "DescriptionA",
5289 NULL, NULL, (LPBYTE) descriptionA, &sizeOfDescription);
5291 if (!lpEnumCallbackA(&serviceProviderGUID, descriptionA, 6, 0, lpContext))
5296 DWORD sizeOfDescription = 0;
5298 if (RegQueryValueExW(hkServiceProvider, descW,
5299 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5301 ERR(": missing 'DescriptionW' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5304 if (sizeOfDescription > max_sizeOfDescriptionW)
5306 HeapFree(GetProcessHeap(), 0, descriptionW);
5307 max_sizeOfDescriptionW = sizeOfDescription;
5308 descriptionW = HeapAlloc(GetProcessHeap(), 0, max_sizeOfDescriptionW);
5310 descriptionW = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5311 RegQueryValueExW(hkServiceProvider, descW,
5312 NULL, NULL, (LPBYTE) descriptionW, &sizeOfDescription);
5314 if (!lpEnumCallbackW(&serviceProviderGUID, descriptionW, 6, 0, lpContext))
5322 HeapFree(GetProcessHeap(), 0, descriptionA);
5323 HeapFree(GetProcessHeap(), 0, descriptionW);
5328 /***************************************************************************
5329 * DirectPlayEnumerate [DPLAYX.9]
5330 * DirectPlayEnumerateA [DPLAYX.2]
5332 HRESULT WINAPI DirectPlayEnumerateA(LPDPENUMDPCALLBACKA lpEnumCallback, LPVOID lpContext )
5334 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5336 return DirectPlayEnumerateAW(lpEnumCallback, NULL, lpContext);
5339 /***************************************************************************
5340 * DirectPlayEnumerateW [DPLAYX.3]
5342 HRESULT WINAPI DirectPlayEnumerateW(LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5344 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5346 return DirectPlayEnumerateAW(NULL, lpEnumCallback, lpContext);
5349 typedef struct tagCreateEnum
5353 } CreateEnumData, *lpCreateEnumData;
5355 /* Find and copy the matching connection for the SP guid */
5356 static BOOL CALLBACK cbDPCreateEnumConnections(
5358 LPVOID lpConnection,
5359 DWORD dwConnectionSize,
5364 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5366 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5368 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5370 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5372 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5374 /* Found the record that we were looking for */
5378 /* Haven't found what were looking for yet */
5383 /***************************************************************************
5384 * DirectPlayCreate [DPLAYX.1]
5387 HRESULT WINAPI DirectPlayCreate
5388 ( LPGUID lpGUID, LPDIRECTPLAY2 *lplpDP, IUnknown *pUnk)
5391 LPDIRECTPLAY3A lpDP3A;
5392 CreateEnumData cbData;
5394 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5398 return CLASS_E_NOAGGREGATION;
5401 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5402 give them an IDirectPlay2A object and hope that doesn't cause problems */
5403 if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
5405 return DPERR_UNAVAILABLE;
5408 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
5410 /* The GUID_NULL means don't bind a service provider. Just return the
5415 /* Bind the desired service provider since lpGUID is non NULL */
5416 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
5418 /* We're going to use a DP3 interface */
5419 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
5423 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
5427 cbData.lpConn = NULL;
5428 cbData.lpGuid = lpGUID;
5430 /* We were given a service provider, find info about it... */
5431 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
5432 &cbData, DPCONNECTION_DIRECTPLAY );
5433 if( ( FAILED(hr) ) ||
5434 ( cbData.lpConn == NULL )
5437 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
5438 IDirectPlayX_Release( lpDP3A );
5439 return DPERR_UNAVAILABLE;
5442 /* Initialize the service provider */
5443 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
5446 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
5447 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5448 IDirectPlayX_Release( lpDP3A );
5452 /* Release our version of the interface now that we're done with it */
5453 IDirectPlayX_Release( lpDP3A );
5454 HeapFree( GetProcessHeap(), 0, cbData.lpConn );