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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 IDirectPlay2Vtbl directPlay2AVT;
81 static IDirectPlay3Vtbl directPlay3AVT;
82 static IDirectPlay4Vtbl directPlay4AVT;
84 static IDirectPlay2Vtbl directPlay2WVT;
85 static IDirectPlay3Vtbl directPlay3WVT;
86 static 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 DWORD 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 );
250 static BOOL DP_DestroyIUnknown( LPVOID lpDP )
252 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;
254 DeleteCriticalSection( &This->unk->DP_lock );
255 HeapFree( GetProcessHeap(), 0, This->unk );
260 static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
262 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;
264 This->dp2 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp2) ) );
265 if ( This->dp2 == NULL )
270 This->dp2->bConnectionOpen = FALSE;
272 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
274 This->dp2->bHostInterface = FALSE;
276 DPQ_INIT(This->dp2->receiveMsgs);
277 DPQ_INIT(This->dp2->sendMsgs);
278 DPQ_INIT(This->dp2->replysExpected);
280 if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
282 /* FIXME: Memory leak */
286 /* Provide an initial session desc with nothing in it */
287 This->dp2->lpSessionDesc = HeapAlloc( GetProcessHeap(),
289 sizeof( *This->dp2->lpSessionDesc ) );
290 if( This->dp2->lpSessionDesc == NULL )
292 /* FIXME: Memory leak */
295 This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc );
297 /* We are emulating a dp 6 implementation */
298 This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION;
300 This->dp2->spData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
301 sizeof( *This->dp2->spData.lpCB ) );
302 This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB );
303 This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION;
305 /* This is the pointer to the service provider */
306 if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP,
307 (LPVOID*)&This->dp2->spData.lpISP, This ) )
310 /* FIXME: Memory leak */
314 /* Setup lobby provider information */
315 This->dp2->dplspData.dwSPVersion = DPSP_MAJORVERSION;
316 This->dp2->dplspData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
317 sizeof( *This->dp2->dplspData.lpCB ) );
318 This->dp2->dplspData.lpCB->dwSize = sizeof( *This->dp2->dplspData.lpCB );
320 if( FAILED( DPLSP_CreateInterface( &IID_IDPLobbySP,
321 (LPVOID*)&This->dp2->dplspData.lpISP, This ) )
324 /* FIXME: Memory leak */
331 /* Definition of the global function in dplayx_queue.h. #
332 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
333 DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
335 HeapFree( GetProcessHeap(), 0, elem );
338 /* Function to delete the list of groups with this interface. Needs to
339 * delete the group and player lists associated with this group as well
340 * as the group data associated with this group. It should not delete
341 * player data as that is shared with the top player list and will be
344 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList );
345 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList )
347 DPQ_DELETEQ( elem->lpGData->groups, groups,
348 lpGroupList, cbDeleteElemFromHeap );
349 DPQ_DELETEQ( elem->lpGData->players, players,
350 lpPlayerList, cbDeleteElemFromHeap );
351 HeapFree( GetProcessHeap(), 0, elem->lpGData );
352 HeapFree( GetProcessHeap(), 0, elem );
355 /* Function to delete the list of players with this interface. Needs to
356 * delete the player data for all players as well.
358 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList );
359 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList )
361 HeapFree( GetProcessHeap(), 0, elem->lpPData );
362 HeapFree( GetProcessHeap(), 0, elem );
365 static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
367 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;
369 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
371 TerminateThread( This->dp2->hEnumSessionThread, 0 );
372 CloseHandle( This->dp2->hEnumSessionThread );
375 /* Finish with the SP - have it shutdown */
376 if( This->dp2->spData.lpCB->ShutdownEx )
378 DPSP_SHUTDOWNDATA data;
380 TRACE( "Calling SP ShutdownEx\n" );
382 data.lpISP = This->dp2->spData.lpISP;
384 (*This->dp2->spData.lpCB->ShutdownEx)( &data );
386 else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
388 TRACE( "Calling obsolete SP Shutdown\n" );
389 (*This->dp2->spData.lpCB->Shutdown)();
392 /* Unload the SP (if it exists) */
393 if( This->dp2->hServiceProvider != 0 )
395 FreeLibrary( This->dp2->hServiceProvider );
398 /* Unload the Lobby Provider (if it exists) */
399 if( This->dp2->hDPLobbyProvider != 0 )
401 FreeLibrary( This->dp2->hDPLobbyProvider );
405 DPQ_DELETEQ( This->dp2->players, players, lpPlayerList, cbDeletePlayerElem );
406 DPQ_DELETEQ( This->dp2->groups, groups, lpGroupList, cbDeleteGroupsElem );
409 /* FIXME: Need to delete receive and send msgs queue contents */
411 NS_DeleteSessionCache( This->dp2->lpNameServerData );
413 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
415 IDirectPlaySP_Release( This->dp2->spData.lpISP );
417 /* Delete the contents */
418 HeapFree( GetProcessHeap(), 0, This->dp2 );
423 static BOOL DP_CreateDirectPlay3( LPVOID lpDP )
425 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;
427 This->dp3 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp3) ) );
428 if ( This->dp3 == NULL )
436 static BOOL DP_DestroyDirectPlay3( LPVOID lpDP )
438 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;
440 /* Delete the contents */
441 HeapFree( GetProcessHeap(), 0, This->dp3 );
446 static BOOL DP_CreateDirectPlay4( LPVOID lpDP )
448 IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)lpDP;
450 This->dp4 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp4) ) );
451 if ( This->dp4 == NULL )
459 static BOOL DP_DestroyDirectPlay4( LPVOID lpDP )
461 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;
463 /* Delete the contents */
464 HeapFree( GetProcessHeap(), 0, This->dp4 );
470 /* Create a new interface */
472 HRESULT DP_CreateInterface
473 ( REFIID riid, LPVOID* ppvObj )
475 TRACE( " for %s\n", debugstr_guid( riid ) );
477 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
478 sizeof( IDirectPlay2Impl ) );
480 if( *ppvObj == NULL )
482 return DPERR_OUTOFMEMORY;
485 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
487 IDirectPlay2Impl *This = (IDirectPlay2Impl *)*ppvObj;
488 This->lpVtbl = &directPlay2WVT;
490 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
492 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)*ppvObj;
493 This->lpVtbl = &directPlay2AVT;
495 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
497 IDirectPlay3Impl *This = (IDirectPlay3Impl *)*ppvObj;
498 This->lpVtbl = &directPlay3WVT;
500 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
502 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)*ppvObj;
503 This->lpVtbl = &directPlay3AVT;
505 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
507 IDirectPlay4Impl *This = (IDirectPlay4Impl *)*ppvObj;
508 This->lpVtbl = &directPlay4WVT;
510 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
512 IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)*ppvObj;
513 This->lpVtbl = &directPlay4AVT;
517 /* Unsupported interface */
518 HeapFree( GetProcessHeap(), 0, *ppvObj );
521 return E_NOINTERFACE;
525 if ( DP_CreateIUnknown( *ppvObj ) &&
526 DP_CreateDirectPlay2( *ppvObj ) &&
527 DP_CreateDirectPlay3( *ppvObj ) &&
528 DP_CreateDirectPlay4( *ppvObj )
531 IDirectPlayX_AddRef( (LPDIRECTPLAY2A)*ppvObj );
536 /* Initialize failed, destroy it */
537 DP_DestroyDirectPlay4( *ppvObj );
538 DP_DestroyDirectPlay3( *ppvObj );
539 DP_DestroyDirectPlay2( *ppvObj );
540 DP_DestroyIUnknown( *ppvObj );
542 HeapFree( GetProcessHeap(), 0, *ppvObj );
545 return DPERR_NOMEMORY;
549 /* Direct Play methods */
551 /* Shared between all dplay types */
552 static HRESULT WINAPI DP_QueryInterface
553 ( LPDIRECTPLAY2 iface, REFIID riid, LPVOID* ppvObj )
555 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
556 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
558 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
561 if( *ppvObj == NULL )
563 return DPERR_OUTOFMEMORY;
566 CopyMemory( *ppvObj, This, sizeof( *This ) );
567 (*(IDirectPlay2Impl**)ppvObj)->ulInterfaceRef = 0;
569 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
571 IDirectPlay2Impl *This = (IDirectPlay2Impl *)*ppvObj;
572 This->lpVtbl = &directPlay2WVT;
574 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
576 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)*ppvObj;
577 This->lpVtbl = &directPlay2AVT;
579 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
581 IDirectPlay3Impl *This = (IDirectPlay3Impl *)*ppvObj;
582 This->lpVtbl = &directPlay3WVT;
584 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
586 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)*ppvObj;
587 This->lpVtbl = &directPlay3AVT;
589 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
591 IDirectPlay4Impl *This = (IDirectPlay4Impl *)*ppvObj;
592 This->lpVtbl = &directPlay4WVT;
594 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
596 IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)*ppvObj;
597 This->lpVtbl = &directPlay4AVT;
601 /* Unsupported interface */
602 HeapFree( GetProcessHeap(), 0, *ppvObj );
605 return E_NOINTERFACE;
608 IDirectPlayX_AddRef( (LPDIRECTPLAY2)*ppvObj );
613 /* Shared between all dplay types */
614 static ULONG WINAPI DP_AddRef
615 ( LPDIRECTPLAY3 iface )
617 ULONG ulInterfaceRefCount, ulObjRefCount;
618 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
620 ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
621 ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
623 TRACE( "ref count incremented to %lu:%lu for %p\n",
624 ulInterfaceRefCount, ulObjRefCount, This );
626 return ulObjRefCount;
629 static ULONG WINAPI DP_Release
630 ( LPDIRECTPLAY3 iface )
632 ULONG ulInterfaceRefCount, ulObjRefCount;
634 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
636 ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
637 ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
639 TRACE( "ref count decremented to %lu:%lu for %p\n",
640 ulInterfaceRefCount, ulObjRefCount, This );
642 /* Deallocate if this is the last reference to the object */
643 if( ulObjRefCount == 0 )
645 /* If we're destroying the object, this must be the last ref
646 of the last interface */
647 DP_DestroyDirectPlay4( This );
648 DP_DestroyDirectPlay3( This );
649 DP_DestroyDirectPlay2( This );
650 DP_DestroyIUnknown( This );
653 /* Deallocate the interface */
654 if( ulInterfaceRefCount == 0 )
656 HeapFree( GetProcessHeap(), 0, This );
659 return ulObjRefCount;
662 static inline DPID DP_NextObjectId(void)
664 return (DPID)InterlockedIncrement( &kludgePlayerGroupId );
667 /* *lplpReply will be non NULL iff there is something to reply */
668 HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpcMessageBody,
669 DWORD dwMessageBodySize, LPCVOID lpcMessageHeader,
670 WORD wCommandId, WORD wVersion,
671 LPVOID* lplpReply, LPDWORD lpdwMsgSize )
673 TRACE( "(%p)->(%p,0x%08lx,%p,%u,%u)\n",
674 This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId,
679 /* Name server needs to handle this request */
680 case DPMSGCMD_ENUMSESSIONSREQUEST:
683 NS_ReplyToEnumSessionsRequest( lpcMessageBody, lplpReply, lpdwMsgSize, This );
688 /* Name server needs to handle this request */
689 case DPMSGCMD_ENUMSESSIONSREPLY:
691 /* No reply expected */
692 NS_AddRemoteComputerAsNameServer( lpcMessageHeader,
693 This->dp2->spData.dwSPHeaderSize,
694 (LPDPMSG_ENUMSESSIONSREPLY)lpcMessageBody,
695 This->dp2->lpNameServerData );
699 case DPMSGCMD_REQUESTNEWPLAYERID:
701 LPCDPMSG_REQUESTNEWPLAYERID lpcMsg =
702 (LPCDPMSG_REQUESTNEWPLAYERID)lpcMessageBody;
704 LPDPMSG_NEWPLAYERIDREPLY lpReply;
706 *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
708 *lplpReply = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, *lpdwMsgSize );
710 FIXME( "Ignoring dwFlags 0x%08lx in request msg\n",
713 /* Setup the reply */
714 lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) +
715 This->dp2->spData.dwSPHeaderSize );
717 lpReply->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
718 lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY;
719 lpReply->envelope.wVersion = DPMSGVER_DP6;
721 lpReply->dpidNewPlayerId = DP_NextObjectId();
723 TRACE( "Allocating new playerid 0x%08lx from remote request\n",
724 lpReply->dpidNewPlayerId );
729 case DPMSGCMD_GETNAMETABLEREPLY:
730 case DPMSGCMD_NEWPLAYERIDREPLY:
734 if( wCommandId == DPMSGCMD_NEWPLAYERIDREPLY )
737 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
743 case DPMSGCMD_JUSTENVELOPE:
745 TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08lx\n", lpcMessageHeader, ((LPDWORD)lpcMessageHeader)[1] );
746 NS_SetLocalAddr( This->dp2->lpNameServerData, lpcMessageHeader, 20 );
747 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
751 case DPMSGCMD_FORWARDADDPLAYER:
757 TRACE( "Sending message to self to get my addr\n" );
758 DP_MSG_ToSelf( This, 1 ); /* This is a hack right now */
763 case DPMSGCMD_FORWARDADDPLAYERNACK:
765 DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
771 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
777 /* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */
783 static HRESULT WINAPI DP_IF_AddPlayerToGroup
784 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
785 DPID idPlayer, BOOL bAnsi )
788 lpPlayerList lpPList;
789 lpPlayerList lpNewPList;
791 TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
792 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
795 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
797 return DPERR_INVALIDGROUP;
800 /* Find the player */
801 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
803 return DPERR_INVALIDPLAYER;
806 /* Create a player list (ie "shortcut" ) */
807 lpNewPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewPList ) );
808 if( lpNewPList == NULL )
810 return DPERR_CANTADDPLAYER;
813 /* Add the shortcut */
814 lpPList->lpPData->uRef++;
815 lpNewPList->lpPData = lpPList->lpPData;
817 /* Add the player to the list of players for this group */
818 DPQ_INSERT(lpGData->players,lpNewPList,players);
820 /* Let the SP know that we've added a player to the group */
821 if( This->dp2->spData.lpCB->AddPlayerToGroup )
823 DPSP_ADDPLAYERTOGROUPDATA data;
825 TRACE( "Calling SP AddPlayerToGroup\n" );
827 data.idPlayer = idPlayer;
828 data.idGroup = idGroup;
829 data.lpISP = This->dp2->spData.lpISP;
831 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
834 /* Inform all other peers of the addition of player to the group. If there are
835 * no peers keep this event quiet.
836 * Also, if this event was the result of another machine sending it to us,
837 * don't bother rebroadcasting it.
839 if( ( lpMsgHdr == NULL ) &&
840 This->dp2->lpSessionDesc &&
841 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
843 DPMSG_ADDPLAYERTOGROUP msg;
844 msg.dwType = DPSYS_ADDPLAYERTOGROUP;
846 msg.dpIdGroup = idGroup;
847 msg.dpIdPlayer = idPlayer;
849 /* FIXME: Correct to just use send effectively? */
850 /* FIXME: Should size include data w/ message or just message "header" */
851 /* FIXME: Check return code */
852 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
858 static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
859 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
861 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
862 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, TRUE );
865 static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
866 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
868 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
869 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, FALSE );
872 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi )
876 TRACE("(%p)->(%u)\n", This, bAnsi );
878 /* FIXME: Need to find a new host I assume (how?) */
879 /* FIXME: Need to destroy all local groups */
880 /* FIXME: Need to migrate all remotely visible players to the new host */
882 /* Invoke the SP callback to inform of session close */
883 if( This->dp2->spData.lpCB->CloseEx )
887 TRACE( "Calling SP CloseEx\n" );
889 data.lpISP = This->dp2->spData.lpISP;
891 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
894 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
896 TRACE( "Calling SP Close (obsolete interface)\n" );
898 hr = (*This->dp2->spData.lpCB->Close)();
904 static HRESULT WINAPI DirectPlay2AImpl_Close
905 ( LPDIRECTPLAY2A iface )
907 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
908 return DP_IF_Close( This, TRUE );
911 static HRESULT WINAPI DirectPlay2WImpl_Close
912 ( LPDIRECTPLAY2 iface )
914 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
915 return DP_IF_Close( This, FALSE );
919 lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, LPDPID lpid,
920 LPDPNAME lpName, DWORD dwFlags,
921 DPID idParent, BOOL bAnsi )
925 /* Allocate the new space and add to end of high level group list */
926 lpGData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGData ) );
928 if( lpGData == NULL )
933 DPQ_INIT(lpGData->groups);
934 DPQ_INIT(lpGData->players);
936 /* Set the desired player ID - no sanity checking to see if it exists */
937 lpGData->dpid = *lpid;
939 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
941 /* FIXME: Should we check that the parent exists? */
942 lpGData->parent = idParent;
944 /* FIXME: Should we validate the dwFlags? */
945 lpGData->dwFlags = dwFlags;
947 TRACE( "Created group id 0x%08lx\n", *lpid );
952 /* This method assumes that all links to it are already deleted */
954 DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid )
958 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
960 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
962 if( lpGList == NULL )
964 ERR( "DPID 0x%08lx not found\n", dpid );
968 if( --(lpGList->lpGData->uRef) )
970 FIXME( "Why is this not the last reference to group?\n" );
975 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
976 HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
978 /* Remove and Delete Player List object */
979 HeapFree( GetProcessHeap(), 0, lpGList );
983 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid )
985 lpGroupList lpGroups;
987 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
989 if( dpid == DPID_SYSTEM_GROUP )
991 return This->dp2->lpSysGroup;
995 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
998 if( lpGroups == NULL )
1003 return lpGroups->lpGData;
1006 static HRESULT WINAPI DP_IF_CreateGroup
1007 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
1008 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
1009 DWORD dwFlags, BOOL bAnsi )
1011 lpGroupData lpGData;
1013 TRACE( "(%p)->(%p,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
1014 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
1017 /* If the name is not specified, we must provide one */
1018 if( DPID_UNKNOWN == *lpidGroup )
1020 /* If we are the name server, we decide on the group ids. If not, we
1021 * must ask for one before attempting a creation.
1023 if( This->dp2->bHostInterface )
1025 *lpidGroup = DP_NextObjectId();
1029 *lpidGroup = DP_GetRemoteNextObjectId();
1033 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
1034 DPID_NOPARENT_GROUP, bAnsi );
1036 if( lpGData == NULL )
1038 return DPERR_CANTADDPLAYER; /* yes player not group */
1041 if( DPID_SYSTEM_GROUP == *lpidGroup )
1043 This->dp2->lpSysGroup = lpGData;
1044 TRACE( "Inserting system group\n" );
1048 /* Insert into the system group */
1049 lpGroupList lpGroup = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGroup ) );
1050 lpGroup->lpGData = lpGData;
1052 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
1055 /* Something is now referencing this data */
1058 /* Set all the important stuff for the group */
1059 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
1061 /* FIXME: We should only create the system group if GetCaps returns
1062 * DPCAPS_GROUPOPTIMIZED.
1065 /* Let the SP know that we've created this group */
1066 if( This->dp2->spData.lpCB->CreateGroup )
1068 DPSP_CREATEGROUPDATA data;
1069 DWORD dwCreateFlags = 0;
1071 TRACE( "Calling SP CreateGroup\n" );
1073 if( *lpidGroup == DPID_NOPARENT_GROUP )
1074 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
1076 if( lpMsgHdr == NULL )
1077 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1079 if( dwFlags & DPGROUP_HIDDEN )
1080 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
1082 data.idGroup = *lpidGroup;
1083 data.dwFlags = dwCreateFlags;
1084 data.lpSPMessageHeader = lpMsgHdr;
1085 data.lpISP = This->dp2->spData.lpISP;
1087 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1090 /* Inform all other peers of the creation of a new group. If there are
1091 * no peers keep this event quiet.
1092 * Also if this message was sent to us, don't rebroadcast.
1094 if( ( lpMsgHdr == NULL ) &&
1095 This->dp2->lpSessionDesc &&
1096 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1098 DPMSG_CREATEPLAYERORGROUP msg;
1099 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1101 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1102 msg.dpId = *lpidGroup;
1103 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1104 msg.lpData = lpData;
1105 msg.dwDataSize = dwDataSize;
1106 msg.dpnName = *lpGroupName;
1107 msg.dpIdParent = DPID_NOPARENT_GROUP;
1108 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
1110 /* FIXME: Correct to just use send effectively? */
1111 /* FIXME: Should size include data w/ message or just message "header" */
1112 /* FIXME: Check return code */
1113 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
1114 0, 0, NULL, NULL, bAnsi );
1120 static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
1121 ( LPDIRECTPLAY2A iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1122 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1124 *lpidGroup = DPID_UNKNOWN;
1126 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1127 lpGroupName, lpData, dwDataSize, dwFlags, TRUE );
1130 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
1131 ( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1132 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1134 *lpidGroup = DPID_UNKNOWN;
1136 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1137 lpGroupName, lpData, dwDataSize, dwFlags, FALSE );
1142 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
1143 LPVOID lpData, DWORD dwDataSize )
1145 /* Clear out the data with this player */
1146 if( ( dwFlags & DPSET_LOCAL ) &&
1147 ( lpGData->dwLocalDataSize != 0 )
1150 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
1151 lpGData->lpLocalData = NULL;
1152 lpGData->dwLocalDataSize = 0;
1154 if( ( dwFlags & DPSET_REMOTE ) &&
1155 ( lpGData->dwRemoteDataSize != 0 )
1158 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
1159 lpGData->lpRemoteData = NULL;
1160 lpGData->dwRemoteDataSize = 0;
1163 /* Reallocate for new data */
1164 if( lpData != NULL )
1166 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1167 sizeof( dwDataSize ) );
1168 CopyMemory( lpNewData, lpData, dwDataSize );
1170 if( dwFlags & DPSET_REMOTE )
1172 lpGData->lpRemoteData = lpNewData;
1173 lpGData->dwRemoteDataSize = dwDataSize;
1176 if( dwFlags & DPSET_LOCAL )
1178 lpGData->lpLocalData = lpData;
1179 lpGData->dwLocalDataSize = dwDataSize;
1185 /* This function will just create the storage for the new player. */
1187 lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid,
1188 LPDPNAME lpName, DWORD dwFlags,
1189 HANDLE hEvent, BOOL bAnsi )
1191 lpPlayerData lpPData;
1193 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
1195 /* Allocate the storage for the player and associate it with list element */
1196 lpPData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPData ) );
1197 if( lpPData == NULL )
1202 /* Set the desired player ID */
1203 lpPData->dpid = *lpid;
1205 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
1207 lpPData->dwFlags = dwFlags;
1209 /* If we were given an event handle, duplicate it */
1212 if( !DuplicateHandle( GetCurrentProcess(), hEvent,
1213 GetCurrentProcess(), &lpPData->hEvent,
1214 0, FALSE, DUPLICATE_SAME_ACCESS )
1217 /* FIXME: Memory leak */
1218 ERR( "Can't duplicate player msg handle %p\n", hEvent );
1222 /* Initialize the SP data section */
1223 lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData();
1225 TRACE( "Created player id 0x%08lx\n", *lpid );
1230 /* Delete the contents of the DPNAME struct */
1232 DP_DeleteDPNameStruct( LPDPNAME lpDPName )
1234 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u1.lpszShortNameA );
1235 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u2.lpszLongNameA );
1238 /* This method assumes that all links to it are already deleted */
1240 DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid )
1242 lpPlayerList lpPList;
1244 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
1246 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1248 if( lpPList == NULL )
1250 ERR( "DPID 0x%08lx not found\n", dpid );
1254 /* Verify that this is the last reference to the data */
1255 if( --(lpPList->lpPData->uRef) )
1257 FIXME( "Why is this not the last reference to player?\n" );
1262 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1264 CloseHandle( lpPList->lpPData->hEvent );
1265 HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
1267 /* Delete Player List object */
1268 HeapFree( GetProcessHeap(), 0, lpPList );
1271 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid )
1273 lpPlayerList lpPlayers;
1275 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
1277 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1282 /* Basic area for Dst must already be allocated */
1283 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi )
1287 ZeroMemory( lpDst, sizeof( *lpDst ) );
1288 lpDst->dwSize = sizeof( *lpDst );
1292 if( lpSrc->dwSize != sizeof( *lpSrc) )
1297 /* Delete any existing pointers */
1298 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1299 HeapFree( GetProcessHeap(), 0, lpDst->u2.lpszLongNameA );
1301 /* Copy as required */
1302 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1306 if( lpSrc->u1.lpszShortNameA )
1308 lpDst->u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), 0,
1309 strlen(lpSrc->u1.lpszShortNameA)+1 );
1310 strcpy( lpDst->u1.lpszShortNameA, lpSrc->u1.lpszShortNameA );
1312 if( lpSrc->u2.lpszLongNameA )
1314 lpDst->u2.lpszLongNameA = HeapAlloc( GetProcessHeap(), 0,
1315 strlen(lpSrc->u2.lpszLongNameA)+1 );
1316 strcpy( lpDst->u2.lpszLongNameA, lpSrc->u2.lpszLongNameA );
1321 if( lpSrc->u1.lpszShortNameA )
1323 lpDst->u1.lpszShortName = HeapAlloc( GetProcessHeap(), 0,
1324 (strlenW(lpSrc->u1.lpszShortName)+1)*sizeof(WCHAR) );
1325 strcpyW( lpDst->u1.lpszShortName, lpSrc->u1.lpszShortName );
1327 if( lpSrc->u2.lpszLongNameA )
1329 lpDst->u2.lpszLongName = HeapAlloc( GetProcessHeap(), 0,
1330 (strlenW(lpSrc->u2.lpszLongName)+1)*sizeof(WCHAR) );
1331 strcpyW( lpDst->u2.lpszLongName, lpSrc->u2.lpszLongName );
1339 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
1340 LPVOID lpData, DWORD dwDataSize )
1342 /* Clear out the data with this player */
1343 if( ( dwFlags & DPSET_LOCAL ) &&
1344 ( lpPData->dwLocalDataSize != 0 )
1347 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
1348 lpPData->lpLocalData = NULL;
1349 lpPData->dwLocalDataSize = 0;
1351 if( ( dwFlags & DPSET_REMOTE ) &&
1352 ( lpPData->dwRemoteDataSize != 0 )
1355 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
1356 lpPData->lpRemoteData = NULL;
1357 lpPData->dwRemoteDataSize = 0;
1360 /* Reallocate for new data */
1361 if( lpData != NULL )
1363 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1364 sizeof( dwDataSize ) );
1365 CopyMemory( lpNewData, lpData, dwDataSize );
1367 if( dwFlags & DPSET_REMOTE )
1369 lpPData->lpRemoteData = lpNewData;
1370 lpPData->dwRemoteDataSize = dwDataSize;
1373 if( dwFlags & DPSET_LOCAL )
1375 lpPData->lpLocalData = lpData;
1376 lpPData->dwLocalDataSize = dwDataSize;
1382 static HRESULT WINAPI DP_IF_CreatePlayer
1383 ( IDirectPlay2Impl* This,
1384 LPVOID lpMsgHdr, /* NULL for local creation, non NULL for remote creation */
1386 LPDPNAME lpPlayerName,
1394 lpPlayerData lpPData;
1395 lpPlayerList lpPList;
1396 DWORD dwCreateFlags = 0;
1398 TRACE( "(%p)->(%p,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
1399 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1400 dwDataSize, dwFlags, bAnsi );
1404 dwFlags = DPPLAYER_SPECTATOR;
1407 if( lpidPlayer == NULL )
1409 return DPERR_INVALIDPARAMS;
1413 /* Determine the creation flags for the player. These will be passed
1414 * to the name server if requesting a player id and to the SP when
1415 * informing it of the player creation
1418 if( dwFlags & DPPLAYER_SERVERPLAYER )
1420 if( *lpidPlayer == DPID_SERVERPLAYER )
1422 /* Server player for the host interface */
1423 dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
1425 else if( *lpidPlayer == DPID_NAME_SERVER )
1427 /* Name server - master of everything */
1428 dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
1432 /* Server player for a non host interface */
1433 dwCreateFlags |= DPLAYI_PLAYER_SYSPLAYER;
1437 if( lpMsgHdr == NULL )
1438 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1441 /* Verify we know how to handle all the flags */
1442 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1443 ( dwFlags & DPPLAYER_SPECTATOR )
1447 /* Assume non fatal failure */
1448 ERR( "unknown dwFlags = 0x%08lx\n", dwFlags );
1451 /* If the name is not specified, we must provide one */
1452 if( *lpidPlayer == DPID_UNKNOWN )
1454 /* If we are the session master, we dish out the group/player ids */
1455 if( This->dp2->bHostInterface )
1457 *lpidPlayer = DP_NextObjectId();
1461 hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer );
1465 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1472 /* FIXME: Would be nice to perhaps verify that we don't already have
1477 /* FIXME: Should we be storing these dwFlags or the creation ones? */
1478 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwFlags,
1481 if( lpPData == NULL )
1483 return DPERR_CANTADDPLAYER;
1486 /* Create the list object and link it in */
1487 lpPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPList ) );
1488 if( lpPList == NULL )
1490 FIXME( "Memory leak\n" );
1491 return DPERR_CANTADDPLAYER;
1495 lpPList->lpPData = lpPData;
1497 /* Add the player to the system group */
1498 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1500 /* Update the information and send it to all players in the session */
1501 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
1503 /* Let the SP know that we've created this player */
1504 if( This->dp2->spData.lpCB->CreatePlayer )
1506 DPSP_CREATEPLAYERDATA data;
1508 data.idPlayer = *lpidPlayer;
1509 data.dwFlags = dwCreateFlags;
1510 data.lpSPMessageHeader = lpMsgHdr;
1511 data.lpISP = This->dp2->spData.lpISP;
1513 TRACE( "Calling SP CreatePlayer 0x%08lx: dwFlags: 0x%08lx lpMsgHdr: %p\n",
1514 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
1516 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1521 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1525 /* Now let the SP know that this player is a member of the system group */
1526 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1528 DPSP_ADDPLAYERTOGROUPDATA data;
1530 data.idPlayer = *lpidPlayer;
1531 data.idGroup = DPID_SYSTEM_GROUP;
1532 data.lpISP = This->dp2->spData.lpISP;
1534 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1536 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1541 ERR( "Failed to add player to sys group with sp: %s\n",
1542 DPLAYX_HresultToString(hr) );
1547 if( This->dp2->bHostInterface == FALSE )
1549 /* Let the name server know about the creation of this player */
1550 /* FIXME: Is this only to be done for the creation of a server player or
1551 * is this used for regular players? If only for server players, move
1552 * this call to DP_SecureOpen(...);
1555 TRACE( "Sending message to self to get my addr\n" );
1556 DP_MSG_ToSelf( This, *lpidPlayer ); /* This is a hack right now */
1559 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
1562 /* Inform all other peers of the creation of a new player. If there are
1563 * no peers keep this quiet.
1564 * Also, if this was a remote event, no need to rebroadcast it.
1566 if( ( lpMsgHdr == NULL ) &&
1567 This->dp2->lpSessionDesc &&
1568 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1570 DPMSG_CREATEPLAYERORGROUP msg;
1571 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1573 msg.dwPlayerType = DPPLAYERTYPE_PLAYER;
1574 msg.dpId = *lpidPlayer;
1575 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */
1576 msg.lpData = lpData;
1577 msg.dwDataSize = dwDataSize;
1578 msg.dpnName = *lpPlayerName;
1579 msg.dpIdParent = DPID_NOPARENT_GROUP;
1580 msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
1582 /* FIXME: Correct to just use send effectively? */
1583 /* FIXME: Should size include data w/ message or just message "header" */
1584 /* FIXME: Check return code */
1585 hr = DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
1586 sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
1593 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
1594 ( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1595 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1597 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1599 if( dwFlags & DPPLAYER_SERVERPLAYER )
1601 *lpidPlayer = DPID_SERVERPLAYER;
1605 *lpidPlayer = DPID_UNKNOWN;
1608 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1609 lpData, dwDataSize, dwFlags, TRUE );
1612 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
1613 ( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1614 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1616 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1618 if( dwFlags & DPPLAYER_SERVERPLAYER )
1620 *lpidPlayer = DPID_SERVERPLAYER;
1624 *lpidPlayer = DPID_UNKNOWN;
1627 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1628 lpData, dwDataSize, dwFlags, FALSE );
1631 static DPID DP_GetRemoteNextObjectId(void)
1636 return DP_NextObjectId();
1639 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
1640 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
1641 DPID idPlayer, BOOL bAnsi )
1645 lpGroupData lpGData;
1646 lpPlayerList lpPList;
1648 TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
1649 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
1651 /* Find the group */
1652 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1654 return DPERR_INVALIDGROUP;
1657 /* Find the player */
1658 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
1660 return DPERR_INVALIDPLAYER;
1663 /* Remove the player shortcut from the group */
1664 DPQ_REMOVE_ENTRY( lpGData->players, players, lpPData->dpid, ==, idPlayer, lpPList );
1666 if( lpPList == NULL )
1668 return DPERR_INVALIDPLAYER;
1671 /* One less reference */
1672 lpPList->lpPData->uRef--;
1674 /* Delete the Player List element */
1675 HeapFree( GetProcessHeap(), 0, lpPList );
1677 /* Inform the SP if they care */
1678 if( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1680 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1682 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1684 data.idPlayer = idPlayer;
1685 data.idGroup = idGroup;
1686 data.lpISP = This->dp2->spData.lpISP;
1688 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1691 /* Need to send a DELETEPLAYERFROMGROUP message */
1692 FIXME( "Need to send a message\n" );
1697 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
1698 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
1700 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1701 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, TRUE );
1704 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
1705 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
1707 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1708 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, FALSE );
1711 typedef struct _DPRGOPContext
1713 IDirectPlay3Impl* This;
1716 } DPRGOPContext, *lpDPRGOPContext;
1718 static BOOL CALLBACK
1719 cbRemoveGroupOrPlayer(
1726 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1728 TRACE( "Removing element:0x%08lx (type:0x%08lx) from element:0x%08lx\n",
1729 dpId, dwPlayerType, lpCtxt->idGroup );
1731 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1733 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt->This, lpCtxt->idGroup,
1738 ERR( "Unable to delete group 0x%08lx from group 0x%08lx\n",
1739 dpId, lpCtxt->idGroup );
1744 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl*)lpCtxt->This,
1745 NULL, lpCtxt->idGroup,
1746 dpId, lpCtxt->bAnsi )
1750 ERR( "Unable to delete player 0x%08lx from grp 0x%08lx\n",
1751 dpId, lpCtxt->idGroup );
1755 return TRUE; /* Continue enumeration */
1758 static HRESULT WINAPI DP_IF_DestroyGroup
1759 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi )
1761 lpGroupData lpGData;
1762 DPRGOPContext context;
1764 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
1765 This, lpMsgHdr, idGroup, bAnsi );
1767 /* Find the group */
1768 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1770 return DPERR_INVALIDPLAYER; /* yes player */
1773 context.This = (IDirectPlay3Impl*)This;
1774 context.bAnsi = bAnsi;
1775 context.idGroup = idGroup;
1777 /* Remove all players that this group has */
1778 DP_IF_EnumGroupPlayers( This, idGroup, NULL,
1779 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1781 /* Remove all links to groups that this group has since this is dp3 */
1782 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This, idGroup, NULL,
1783 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1785 /* Remove this group from the parent group - if it has one */
1786 if( ( idGroup != DPID_SYSTEM_GROUP ) &&
1787 ( lpGData->parent != DPID_SYSTEM_GROUP )
1790 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl*)This, lpGData->parent,
1794 /* Now delete this group data and list from the system group */
1795 DP_DeleteGroup( This, idGroup );
1797 /* Let the SP know that we've destroyed this group */
1798 if( This->dp2->spData.lpCB->DeleteGroup )
1800 DPSP_DELETEGROUPDATA data;
1802 FIXME( "data.dwFlags is incorrect\n" );
1804 data.idGroup = idGroup;
1806 data.lpISP = This->dp2->spData.lpISP;
1808 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1811 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1816 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
1817 ( LPDIRECTPLAY2A iface, DPID idGroup )
1819 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1820 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
1823 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
1824 ( LPDIRECTPLAY2 iface, DPID idGroup )
1826 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1827 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
1830 typedef struct _DPFAGContext
1832 IDirectPlay2Impl* This;
1835 } DPFAGContext, *lpDPFAGContext;
1837 static HRESULT WINAPI DP_IF_DestroyPlayer
1838 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi )
1840 DPFAGContext cbContext;
1842 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
1843 This, lpMsgHdr, idPlayer, bAnsi );
1845 if( This->dp2->connectionInitialized == NO_PROVIDER )
1847 return DPERR_UNINITIALIZED;
1850 if( DP_FindPlayer( This, idPlayer ) == NULL )
1852 return DPERR_INVALIDPLAYER;
1855 /* FIXME: If the player is remote, we must be the host to delete this */
1857 cbContext.This = This;
1858 cbContext.idPlayer = idPlayer;
1859 cbContext.bAnsi = bAnsi;
1861 /* Find each group and call DeletePlayerFromGroup if the player is a
1862 member of the group */
1863 DP_IF_EnumGroups( This, NULL, cbDeletePlayerFromAllGroups,
1864 (LPVOID)&cbContext, DPENUMGROUPS_ALL, bAnsi );
1866 /* Now delete player and player list from the sys group */
1867 DP_DeletePlayer( This, idPlayer );
1869 /* Let the SP know that we've destroyed this group */
1870 if( This->dp2->spData.lpCB->DeletePlayer )
1872 DPSP_DELETEPLAYERDATA data;
1874 FIXME( "data.dwFlags is incorrect\n" );
1876 data.idPlayer = idPlayer;
1878 data.lpISP = This->dp2->spData.lpISP;
1880 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
1883 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
1888 static BOOL CALLBACK
1889 cbDeletePlayerFromAllGroups(
1896 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
1898 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1900 DP_IF_DeletePlayerFromGroup( lpCtxt->This, NULL, dpId, lpCtxt->idPlayer,
1903 /* Enumerate all groups in this group since this will normally only
1904 * be called for top level groups
1906 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)lpCtxt->This,
1908 cbDeletePlayerFromAllGroups,
1909 (LPVOID)lpContext, DPENUMGROUPS_ALL,
1915 ERR( "Group callback has dwPlayerType = 0x%08lx\n", dwPlayerType );
1921 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
1922 ( LPDIRECTPLAY2A iface, DPID idPlayer )
1924 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1925 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
1928 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
1929 ( LPDIRECTPLAY2 iface, DPID idPlayer )
1931 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1932 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
1935 static HRESULT WINAPI DP_IF_EnumGroupPlayers
1936 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
1937 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1938 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1940 lpGroupData lpGData;
1941 lpPlayerList lpPList;
1943 FIXME("(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
1944 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
1945 lpContext, dwFlags, bAnsi );
1947 if( This->dp2->connectionInitialized == NO_PROVIDER )
1949 return DPERR_UNINITIALIZED;
1952 /* Find the group */
1953 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1955 return DPERR_INVALIDGROUP;
1958 if( DPQ_IS_EMPTY( lpGData->players ) )
1963 lpPList = DPQ_FIRST( lpGData->players );
1965 /* Walk the players in this group */
1968 /* We do not enum the name server or app server as they are of no
1969 * concequence to the end user.
1971 if( ( lpPList->lpPData->dpid != DPID_NAME_SERVER ) &&
1972 ( lpPList->lpPData->dpid != DPID_SERVERPLAYER )
1976 /* FIXME: Need to add stuff for dwFlags checking */
1978 if( !lpEnumPlayersCallback2( lpPList->lpPData->dpid, DPPLAYERTYPE_PLAYER,
1979 &lpPList->lpPData->name,
1980 lpPList->lpPData->dwFlags,
1984 /* User requested break */
1989 if( DPQ_IS_ENDOFLIST( lpPList->players ) )
1994 lpPList = DPQ_NEXT( lpPList->players );
2000 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
2001 ( LPDIRECTPLAY2A iface, DPID idGroup, LPGUID lpguidInstance,
2002 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2003 LPVOID lpContext, DWORD dwFlags )
2005 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2006 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2007 lpEnumPlayersCallback2, lpContext,
2011 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
2012 ( LPDIRECTPLAY2 iface, DPID idGroup, LPGUID lpguidInstance,
2013 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2014 LPVOID lpContext, DWORD dwFlags )
2016 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2017 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2018 lpEnumPlayersCallback2, lpContext,
2022 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2023 static HRESULT WINAPI DP_IF_EnumGroups
2024 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2025 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2026 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2028 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This,
2029 DPID_SYSTEM_GROUP, lpguidInstance,
2030 lpEnumPlayersCallback2, lpContext,
2034 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
2035 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2036 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2037 LPVOID lpContext, DWORD dwFlags )
2039 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2040 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2041 lpContext, dwFlags, TRUE );
2044 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
2045 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2046 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2047 LPVOID lpContext, DWORD dwFlags )
2049 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2050 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2051 lpContext, dwFlags, FALSE );
2054 static HRESULT WINAPI DP_IF_EnumPlayers
2055 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2056 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2057 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2059 return DP_IF_EnumGroupPlayers( This, DPID_SYSTEM_GROUP, lpguidInstance,
2060 lpEnumPlayersCallback2, lpContext,
2064 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
2065 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2066 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2067 LPVOID lpContext, DWORD dwFlags )
2069 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2070 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2071 lpContext, dwFlags, TRUE );
2074 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
2075 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2076 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2077 LPVOID lpContext, DWORD dwFlags )
2079 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2080 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2081 lpContext, dwFlags, FALSE );
2084 /* This function should call the registered callback function that the user
2085 passed into EnumSessions for each entry available.
2087 static void DP_InvokeEnumSessionCallbacks
2088 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2093 LPDPSESSIONDESC2 lpSessionDesc;
2095 FIXME( ": not checking for conditions\n" );
2097 /* Not sure if this should be pruning but it's convenient */
2098 NS_PruneSessionCache( lpNSInfo );
2100 NS_ResetSessionEnumeration( lpNSInfo );
2102 /* Enumerate all sessions */
2103 /* FIXME: Need to indicate ANSI */
2104 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2106 TRACE( "EnumSessionsCallback2 invoked\n" );
2107 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2113 /* Invoke one last time to indicate that there is no more to come */
2114 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2117 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2119 EnumSessionAsyncCallbackData* data = (EnumSessionAsyncCallbackData*)lpContext;
2120 HANDLE hSuicideRequest = data->hSuicideRequest;
2121 DWORD dwTimeout = data->dwTimeout;
2123 TRACE( "Thread started with timeout = 0x%08lx\n", dwTimeout );
2129 /* Sleep up to dwTimeout waiting for request to terminate thread */
2130 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2132 TRACE( "Thread terminating on terminate request\n" );
2136 /* Now resend the enum request */
2137 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2138 data->dwEnumSessionFlags,
2143 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2144 /* FIXME: Should we kill this thread? How to inform the main thread? */
2149 TRACE( "Thread terminating\n" );
2151 /* Clean up the thread data */
2152 CloseHandle( hSuicideRequest );
2153 HeapFree( GetProcessHeap(), 0, lpContext );
2155 /* FIXME: Need to have some notification to main app thread that this is
2156 * dead. It would serve two purposes. 1) allow sync on termination
2157 * so that we don't actually send something to ourselves when we
2158 * become name server (race condition) and 2) so that if we die
2159 * abnormally something else will be able to tell.
2165 static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
2167 /* Does a thread exist? If so we were doing an async enum session */
2168 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2170 TRACE( "Killing EnumSession thread %p\n",
2171 This->dp2->hEnumSessionThread );
2173 /* Request that the thread kill itself nicely */
2174 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2175 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2177 /* We no longer need to know about the thread */
2178 CloseHandle( This->dp2->hEnumSessionThread );
2180 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2184 static HRESULT WINAPI DP_IF_EnumSessions
2185 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2186 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2187 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2191 TRACE( "(%p)->(%p,0x%08lx,%p,%p,0x%08lx,%u)\n",
2192 This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags,
2195 /* Can't enumerate if the interface is already open */
2196 if( This->dp2->bConnectionOpen )
2198 return DPERR_GENERIC;
2202 /* The loading of a lobby provider _seems_ to require a backdoor loading
2203 * of the service provider to also associate with this DP object. This is
2204 * because the app doesn't seem to have to call EnumConnections and
2205 * InitializeConnection for the SP before calling this method. As such
2206 * we'll do their dirty work for them with a quick hack so as to always
2207 * load the TCP/IP service provider.
2209 * The correct solution would seem to involve creating a dialog box which
2210 * contains the possible SPs. These dialog boxes most likely follow SDK
2213 if( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
2215 LPVOID lpConnection;
2218 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2220 if( !DP_BuildSPCompoundAddr( (LPGUID)&DPSPGUID_TCPIP, &lpConnection, &dwSize ) )
2222 ERR( "Can't build compound addr\n" );
2223 return DPERR_GENERIC;
2226 hr = DP_IF_InitializeConnection( (IDirectPlay3Impl*)This, lpConnection,
2233 /* Free up the address buffer */
2234 HeapFree( GetProcessHeap(), 0, lpConnection );
2236 /* The SP is now initialized */
2237 This->dp2->bSPInitialized = TRUE;
2242 /* Use the service provider default? */
2243 if( dwTimeout == 0 )
2246 spCaps.dwSize = sizeof( spCaps );
2248 DP_IF_GetCaps( This, &spCaps, 0 );
2249 dwTimeout = spCaps.dwTimeout;
2251 /* The service provider doesn't provide one either! */
2252 if( dwTimeout == 0 )
2254 /* Provide the TCP/IP default */
2255 dwTimeout = DPMSG_WAIT_5_SECS;
2259 if( dwFlags & DPENUMSESSIONS_STOPASYNC )
2261 DP_KillEnumSessionThread( This );
2265 /* FIXME: Interface locking sucks in this method */
2266 if( ( dwFlags & DPENUMSESSIONS_ASYNC ) )
2268 /* Enumerate everything presently in the local session cache */
2269 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2270 This->dp2->lpNameServerData, dwTimeout,
2274 /* See if we've already created a thread to service this interface */
2275 if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2279 /* Send the first enum request inline since the user may cancel a dialog
2280 * if one is presented. Also, may also have a connecting return code.
2282 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2283 dwFlags, &This->dp2->spData );
2287 EnumSessionAsyncCallbackData* lpData
2288 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpData ) );
2289 /* FIXME: need to kill the thread on object deletion */
2290 lpData->lpSpData = &This->dp2->spData;
2292 CopyMemory( &lpData->requestGuid, &lpsd->guidApplication, sizeof(GUID) );
2293 lpData->dwEnumSessionFlags = dwFlags;
2294 lpData->dwTimeout = dwTimeout;
2296 This->dp2->hKillEnumSessionThreadEvent =
2297 CreateEventW( NULL, TRUE, FALSE, NULL );
2299 if( !DuplicateHandle( GetCurrentProcess(),
2300 This->dp2->hKillEnumSessionThreadEvent,
2301 GetCurrentProcess(),
2302 &lpData->hSuicideRequest,
2303 0, FALSE, DUPLICATE_SAME_ACCESS )
2306 ERR( "Can't duplicate thread killing handle\n" );
2309 TRACE( ": creating EnumSessionsRequest thread\n" );
2311 This->dp2->hEnumSessionThread = CreateThread( NULL,
2313 DP_EnumSessionsSendAsyncRequestThread,
2322 /* Invalidate the session cache for the interface */
2323 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2325 /* Send the broadcast for session enumeration */
2326 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2328 &This->dp2->spData );
2331 SleepEx( dwTimeout, FALSE );
2333 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2334 This->dp2->lpNameServerData, dwTimeout,
2341 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2342 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2343 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2344 LPVOID lpContext, DWORD dwFlags )
2346 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2347 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2348 lpContext, dwFlags, TRUE );
2351 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2352 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2353 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2354 LPVOID lpContext, DWORD dwFlags )
2356 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2357 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2358 lpContext, dwFlags, FALSE );
2361 static HRESULT WINAPI DP_IF_GetPlayerCaps
2362 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
2365 DPSP_GETCAPSDATA data;
2367 TRACE("(%p)->(0x%08lx,%p,0x%08lx)\n", This, idPlayer, lpDPCaps, dwFlags);
2369 /* Query the service provider */
2370 data.idPlayer = idPlayer;
2371 data.dwFlags = dwFlags;
2372 data.lpCaps = lpDPCaps;
2373 data.lpISP = This->dp2->spData.lpISP;
2375 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2378 static HRESULT WINAPI DP_IF_GetCaps
2379 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags )
2381 return DP_IF_GetPlayerCaps( This, DPID_ALLPLAYERS, lpDPCaps, dwFlags );
2384 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2385 ( LPDIRECTPLAY2A iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2387 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2388 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2391 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2392 ( LPDIRECTPLAY2 iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2394 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2395 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2398 static HRESULT WINAPI DP_IF_GetGroupData
2399 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2400 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2402 lpGroupData lpGData;
2403 DWORD dwRequiredBufferSize;
2404 LPVOID lpCopyDataFrom;
2406 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
2407 This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi );
2409 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2411 return DPERR_INVALIDGROUP;
2414 /* How much buffer is required? */
2415 if( dwFlags & DPSET_REMOTE )
2417 dwRequiredBufferSize = lpGData->dwRemoteDataSize;
2418 lpCopyDataFrom = lpGData->lpRemoteData;
2420 else if( dwFlags & DPSET_LOCAL )
2422 dwRequiredBufferSize = lpGData->dwLocalDataSize;
2423 lpCopyDataFrom = lpGData->lpLocalData;
2427 ERR( "Neither local or remote data requested!?!\n" );
2428 dwRequiredBufferSize = 0;
2429 lpCopyDataFrom = NULL;
2432 /* Is the user requesting to know how big a buffer is required? */
2433 if( ( lpData == NULL ) ||
2434 ( *lpdwDataSize < dwRequiredBufferSize )
2437 *lpdwDataSize = dwRequiredBufferSize;
2438 return DPERR_BUFFERTOOSMALL;
2441 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2446 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2447 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2448 LPDWORD lpdwDataSize, DWORD dwFlags )
2450 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2451 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2455 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2456 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2457 LPDWORD lpdwDataSize, DWORD dwFlags )
2459 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2460 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2464 static HRESULT WINAPI DP_IF_GetGroupName
2465 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2466 LPDWORD lpdwDataSize, BOOL bAnsi )
2468 lpGroupData lpGData;
2469 LPDPNAME lpName = (LPDPNAME)lpData;
2470 DWORD dwRequiredDataSize;
2472 FIXME("(%p)->(0x%08lx,%p,%p,%u) ANSI ignored\n",
2473 This, idGroup, lpData, lpdwDataSize, bAnsi );
2475 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2477 return DPERR_INVALIDGROUP;
2480 dwRequiredDataSize = lpGData->name.dwSize;
2482 if( lpGData->name.u1.lpszShortNameA )
2484 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
2487 if( lpGData->name.u2.lpszLongNameA )
2489 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
2492 if( ( lpData == NULL ) ||
2493 ( *lpdwDataSize < dwRequiredDataSize )
2496 *lpdwDataSize = dwRequiredDataSize;
2497 return DPERR_BUFFERTOOSMALL;
2500 /* Copy the structure */
2501 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2503 if( lpGData->name.u1.lpszShortNameA )
2505 strcpy( ((BYTE*)lpName)+lpGData->name.dwSize,
2506 lpGData->name.u1.lpszShortNameA );
2510 lpName->u1.lpszShortNameA = NULL;
2513 if( lpGData->name.u1.lpszShortNameA )
2515 strcpy( ((BYTE*)lpName)+lpGData->name.dwSize,
2516 lpGData->name.u2.lpszLongNameA );
2520 lpName->u2.lpszLongNameA = NULL;
2526 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2527 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2528 LPDWORD lpdwDataSize )
2530 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2531 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2534 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2535 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2536 LPDWORD lpdwDataSize )
2538 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2539 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2542 static HRESULT WINAPI DP_IF_GetMessageCount
2543 ( IDirectPlay2Impl* This, DPID idPlayer,
2544 LPDWORD lpdwCount, BOOL bAnsi )
2546 FIXME("(%p)->(0x%08lx,%p,%u): stub\n", This, idPlayer, lpdwCount, bAnsi );
2547 return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer,
2548 DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL,
2552 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2553 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDWORD lpdwCount )
2555 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2556 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, TRUE );
2559 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2560 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDWORD lpdwCount )
2562 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2563 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, FALSE );
2566 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2567 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2569 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2570 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2574 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2575 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2577 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2578 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2582 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2583 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2586 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2587 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2590 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2591 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2594 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2595 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2598 static HRESULT WINAPI DP_IF_GetPlayerData
2599 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2600 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2602 lpPlayerList lpPList;
2603 DWORD dwRequiredBufferSize;
2604 LPVOID lpCopyDataFrom;
2606 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
2607 This, idPlayer, lpData, lpdwDataSize, dwFlags, bAnsi );
2609 if( This->dp2->connectionInitialized == NO_PROVIDER )
2611 return DPERR_UNINITIALIZED;
2614 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2616 return DPERR_INVALIDPLAYER;
2619 /* How much buffer is required? */
2620 if( dwFlags & DPSET_REMOTE )
2622 dwRequiredBufferSize = lpPList->lpPData->dwRemoteDataSize;
2623 lpCopyDataFrom = lpPList->lpPData->lpRemoteData;
2625 else if( dwFlags & DPSET_LOCAL )
2627 dwRequiredBufferSize = lpPList->lpPData->dwLocalDataSize;
2628 lpCopyDataFrom = lpPList->lpPData->lpLocalData;
2632 ERR( "Neither local or remote data requested!?!\n" );
2633 dwRequiredBufferSize = 0;
2634 lpCopyDataFrom = NULL;
2637 /* Is the user requesting to know how big a buffer is required? */
2638 if( ( lpData == NULL ) ||
2639 ( *lpdwDataSize < dwRequiredBufferSize )
2642 *lpdwDataSize = dwRequiredBufferSize;
2643 return DPERR_BUFFERTOOSMALL;
2646 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2651 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2652 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2653 LPDWORD lpdwDataSize, DWORD dwFlags )
2655 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2656 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2660 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2661 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2662 LPDWORD lpdwDataSize, DWORD dwFlags )
2664 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2665 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2669 static HRESULT WINAPI DP_IF_GetPlayerName
2670 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2671 LPDWORD lpdwDataSize, BOOL bAnsi )
2673 lpPlayerList lpPList;
2674 LPDPNAME lpName = (LPDPNAME)lpData;
2675 DWORD dwRequiredDataSize;
2677 FIXME( "(%p)->(0x%08lx,%p,%p,%u): ANSI \n",
2678 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2680 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2682 return DPERR_INVALIDPLAYER;
2685 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
2687 if( lpPList->lpPData->name.u1.lpszShortNameA )
2689 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
2692 if( lpPList->lpPData->name.u2.lpszLongNameA )
2694 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
2697 if( ( lpData == NULL ) ||
2698 ( *lpdwDataSize < dwRequiredDataSize )
2701 *lpdwDataSize = dwRequiredDataSize;
2702 return DPERR_BUFFERTOOSMALL;
2705 /* Copy the structure */
2706 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
2708 if( lpPList->lpPData->name.u1.lpszShortNameA )
2710 strcpy( ((BYTE*)lpName)+lpPList->lpPData->name.dwSize,
2711 lpPList->lpPData->name.u1.lpszShortNameA );
2715 lpName->u1.lpszShortNameA = NULL;
2718 if( lpPList->lpPData->name.u1.lpszShortNameA )
2720 strcpy( ((BYTE*)lpName)+lpPList->lpPData->name.dwSize,
2721 lpPList->lpPData->name.u2.lpszLongNameA );
2725 lpName->u2.lpszLongNameA = NULL;
2731 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2732 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2733 LPDWORD lpdwDataSize )
2735 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2736 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
2739 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2740 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2741 LPDWORD lpdwDataSize )
2743 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2744 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
2747 static HRESULT WINAPI DP_GetSessionDesc
2748 ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize,
2751 DWORD dwRequiredSize;
2753 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
2755 if( This->dp2->connectionInitialized == NO_PROVIDER )
2757 return DPERR_UNINITIALIZED;
2760 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
2762 return DPERR_INVALIDPARAMS;
2765 /* FIXME: Get from This->dp2->lpSessionDesc */
2766 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
2768 if ( ( lpData == NULL ) ||
2769 ( *lpdwDataSize < dwRequiredSize )
2772 *lpdwDataSize = dwRequiredSize;
2773 return DPERR_BUFFERTOOSMALL;
2776 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
2781 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
2782 ( LPDIRECTPLAY2A iface, LPVOID lpData, LPDWORD lpdwDataSize )
2784 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2785 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2788 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
2789 ( LPDIRECTPLAY2 iface, LPVOID lpData, LPDWORD lpdwDataSize )
2791 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2792 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2795 /* Intended only for COM compatibility. Always returns an error. */
2796 static HRESULT WINAPI DirectPlay2AImpl_Initialize
2797 ( LPDIRECTPLAY2A iface, LPGUID lpGUID )
2799 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2800 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2801 return DPERR_ALREADYINITIALIZED;
2804 /* Intended only for COM compatibility. Always returns an error. */
2805 static HRESULT WINAPI DirectPlay2WImpl_Initialize
2806 ( LPDIRECTPLAY2 iface, LPGUID lpGUID )
2808 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2809 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2810 return DPERR_ALREADYINITIALIZED;
2814 static HRESULT WINAPI DP_SecureOpen
2815 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
2816 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
2821 FIXME( "(%p)->(%p,0x%08lx,%p,%p): partial stub\n",
2822 This, lpsd, dwFlags, lpSecurity, lpCredentials );
2824 if( This->dp2->bConnectionOpen )
2826 TRACE( ": rejecting already open connection.\n" );
2827 return DPERR_ALREADYINITIALIZED;
2830 /* If we're enumerating, kill the thread */
2831 DP_KillEnumSessionThread( This );
2833 if( dwFlags & DPOPEN_CREATE )
2835 /* Rightoo - this computer is the host and the local computer needs to be
2836 the name server so that others can join this session */
2837 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
2839 This->dp2->bHostInterface = TRUE;
2841 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
2844 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
2849 /* Invoke the conditional callback for the service provider */
2850 if( This->dp2->spData.lpCB->Open )
2854 FIXME( "Not all data fields are correct. Need new parameter\n" );
2856 data.bCreate = (dwFlags & DPOPEN_CREATE ) ? TRUE : FALSE;
2857 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
2858 : NS_GetNSAddr( This->dp2->lpNameServerData );
2859 data.lpISP = This->dp2->spData.lpISP;
2860 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) ? TRUE : FALSE;
2861 data.dwOpenFlags = dwFlags;
2862 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
2864 hr = (*This->dp2->spData.lpCB->Open)(&data);
2867 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
2873 /* Create the system group of which everything is a part of */
2874 DPID systemGroup = DPID_SYSTEM_GROUP;
2876 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
2881 if( dwFlags & DPOPEN_JOIN )
2883 DPID dpidServerId = DPID_UNKNOWN;
2885 /* Create the server player for this interface. This way we can receive
2886 * messages for this session.
2888 /* FIXME: I suppose that we should be setting an event for a receive
2889 * type of thing. That way the messaging thread could know to wake
2890 * up. DPlay would then trigger the hEvent for the player the
2891 * message is directed to.
2893 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
2895 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
2898 else if( dwFlags & DPOPEN_CREATE )
2900 DPID dpidNameServerId = DPID_NAME_SERVER;
2902 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
2903 0, DPPLAYER_SERVERPLAYER, bAnsi );
2908 ERR( "Couldn't create name server/system player: %s\n",
2909 DPLAYX_HresultToString(hr) );
2915 static HRESULT WINAPI DirectPlay2AImpl_Open
2916 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2918 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2919 TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags );
2920 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, TRUE );
2923 static HRESULT WINAPI DirectPlay2WImpl_Open
2924 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2926 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2927 TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags );
2928 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, FALSE );
2931 static HRESULT WINAPI DP_IF_Receive
2932 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
2933 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi )
2935 LPDPMSG lpMsg = NULL;
2937 FIXME( "(%p)->(%p,%p,0x%08lx,%p,%p,%u): stub\n",
2938 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
2940 if( This->dp2->connectionInitialized == NO_PROVIDER )
2942 return DPERR_UNINITIALIZED;
2947 dwFlags = DPRECEIVE_ALL;
2950 /* If the lpData is NULL, we must be peeking the message */
2951 if( ( lpData == NULL ) &&
2952 !( dwFlags & DPRECEIVE_PEEK )
2955 return DPERR_INVALIDPARAMS;
2958 if( dwFlags & DPRECEIVE_ALL )
2960 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
2962 if( !( dwFlags & DPRECEIVE_PEEK ) )
2964 FIXME( "Remove from queue\n" );
2967 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
2968 ( dwFlags & DPRECEIVE_FROMPLAYER )
2971 FIXME( "Find matching message 0x%08lx\n", dwFlags );
2975 ERR( "Hmmm..dwFlags 0x%08lx\n", dwFlags );
2980 return DPERR_NOMESSAGES;
2983 /* Copy into the provided buffer */
2984 CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
2989 static HRESULT WINAPI DirectPlay2AImpl_Receive
2990 ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo,
2991 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
2993 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2994 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
2995 lpData, lpdwDataSize, TRUE );
2998 static HRESULT WINAPI DirectPlay2WImpl_Receive
2999 ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo,
3000 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
3002 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3003 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
3004 lpData, lpdwDataSize, FALSE );
3007 static HRESULT WINAPI DirectPlay2AImpl_Send
3008 ( LPDIRECTPLAY2A 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, TRUE );
3015 static HRESULT WINAPI DirectPlay2WImpl_Send
3016 ( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3018 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3019 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3020 0, 0, NULL, NULL, FALSE );
3023 static HRESULT WINAPI DP_IF_SetGroupData
3024 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
3025 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3027 lpGroupData lpGData;
3029 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
3030 This, idGroup, lpData, dwDataSize, dwFlags, bAnsi );
3032 /* Parameter check */
3033 if( ( lpData == NULL ) &&
3037 return DPERR_INVALIDPARAMS;
3040 /* Find the pointer to the data for this player */
3041 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3043 return DPERR_INVALIDOBJECT;
3046 if( dwFlags & DPSET_REMOTE )
3048 FIXME( "Was this group created by this interface?\n" );
3049 /* FIXME: If this is a remote update need to allow it but not
3054 DP_SetGroupData( lpGData, dwFlags, lpData, dwDataSize );
3056 /* FIXME: Only send a message if this group is local to the session otherwise
3057 * it will have been rejected above
3059 if( dwFlags & DPSET_REMOTE )
3061 FIXME( "Send msg?\n" );
3067 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
3068 ( LPDIRECTPLAY2A 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, TRUE );
3075 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
3076 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
3077 DWORD dwDataSize, DWORD dwFlags )
3079 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3080 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, FALSE );
3083 static HRESULT WINAPI DP_IF_SetGroupName
3084 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
3085 DWORD dwFlags, BOOL bAnsi )
3087 lpGroupData lpGData;
3089 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n", This, idGroup,
3090 lpGroupName, dwFlags, bAnsi );
3092 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3094 return DPERR_INVALIDGROUP;
3097 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
3099 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3100 FIXME( "Message not sent and dwFlags ignored\n" );
3105 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
3106 ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName,
3109 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3110 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
3113 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
3114 ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName,
3117 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3118 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
3121 static HRESULT WINAPI DP_IF_SetPlayerData
3122 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
3123 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3125 lpPlayerList lpPList;
3127 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
3128 This, idPlayer, lpData, dwDataSize, dwFlags, bAnsi );
3130 /* Parameter check */
3131 if( ( lpData == NULL ) &&
3135 return DPERR_INVALIDPARAMS;
3138 /* Find the pointer to the data for this player */
3139 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3141 return DPERR_INVALIDPLAYER;
3144 if( dwFlags & DPSET_REMOTE )
3146 FIXME( "Was this group created by this interface?\n" );
3147 /* FIXME: If this is a remote update need to allow it but not
3152 DP_SetPlayerData( lpPList->lpPData, dwFlags, lpData, dwDataSize );
3154 if( dwFlags & DPSET_REMOTE )
3156 FIXME( "Send msg?\n" );
3162 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3163 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
3164 DWORD dwDataSize, DWORD dwFlags )
3166 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3167 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3171 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3172 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
3173 DWORD dwDataSize, DWORD dwFlags )
3175 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3176 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3180 static HRESULT WINAPI DP_IF_SetPlayerName
3181 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
3182 DWORD dwFlags, BOOL bAnsi )
3184 lpPlayerList lpPList;
3186 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n",
3187 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3189 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3191 return DPERR_INVALIDGROUP;
3194 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3196 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3197 FIXME( "Message not sent and dwFlags ignored\n" );
3202 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3203 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName,
3206 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3207 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3210 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3211 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName,
3214 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3215 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3218 static HRESULT WINAPI DP_SetSessionDesc
3219 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
3220 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3222 DWORD dwRequiredSize;
3223 LPDPSESSIONDESC2 lpTempSessDesc;
3225 TRACE( "(%p)->(%p,0x%08lx,%u,%u)\n",
3226 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3228 if( This->dp2->connectionInitialized == NO_PROVIDER )
3230 return DPERR_UNINITIALIZED;
3235 return DPERR_INVALIDPARAMS;
3238 /* Only the host is allowed to update the session desc */
3239 if( !This->dp2->bHostInterface )
3241 return DPERR_ACCESSDENIED;
3244 /* FIXME: Copy into This->dp2->lpSessionDesc */
3245 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3246 lpTempSessDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize );
3248 if( lpTempSessDesc == NULL )
3250 return DPERR_OUTOFMEMORY;
3254 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3256 This->dp2->lpSessionDesc = lpTempSessDesc;
3259 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3261 /* If this is an external invocation of the interface, we should be
3262 * letting everyone know that things have changed. Otherwise this is
3263 * just an initialization and it doesn't need to be propagated.
3267 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3273 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3274 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3276 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3277 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3280 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3281 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3283 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3284 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3287 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3288 DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3292 if( lpSessDesc == NULL )
3294 /* Hmmm..don't need any size? */
3295 ERR( "NULL lpSessDesc\n" );
3299 dwSize += sizeof( *lpSessDesc );
3303 if( lpSessDesc->u1.lpszSessionNameA )
3305 dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1;
3308 if( lpSessDesc->u2.lpszPasswordA )
3310 dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1;
3315 if( lpSessDesc->u1.lpszSessionName )
3317 dwSize += sizeof( WCHAR ) *
3318 ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 );
3321 if( lpSessDesc->u2.lpszPassword )
3323 dwSize += sizeof( WCHAR ) *
3324 ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 );
3331 /* Assumes that contugous buffers are already allocated. */
3332 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3333 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3335 BYTE* lpStartOfFreeSpace;
3337 if( lpSessionDest == NULL )
3339 ERR( "NULL lpSessionDest\n" );
3343 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3345 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3349 if( lpSessionSrc->u1.lpszSessionNameA )
3351 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3352 lpSessionDest->u1.lpszSessionNameA );
3353 lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3354 lpStartOfFreeSpace +=
3355 lstrlenA( (LPSTR)lpSessionDest->u1.lpszSessionNameA ) + 1;
3358 if( lpSessionSrc->u2.lpszPasswordA )
3360 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3361 lpSessionDest->u2.lpszPasswordA );
3362 lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3363 lpStartOfFreeSpace +=
3364 lstrlenA( (LPSTR)lpSessionDest->u2.lpszPasswordA ) + 1;
3369 if( lpSessionSrc->u1.lpszSessionName )
3371 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3372 lpSessionDest->u1.lpszSessionName );
3373 lpSessionDest->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3374 lpStartOfFreeSpace += sizeof(WCHAR) *
3375 ( lstrlenW( (LPWSTR)lpSessionDest->u1.lpszSessionName ) + 1 );
3378 if( lpSessionSrc->u2.lpszPassword )
3380 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3381 lpSessionDest->u2.lpszPassword );
3382 lpSessionDest->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3383 lpStartOfFreeSpace += sizeof(WCHAR) *
3384 ( lstrlenW( (LPWSTR)lpSessionDest->u2.lpszPassword ) + 1 );
3390 static HRESULT WINAPI DP_IF_AddGroupToGroup
3391 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3393 lpGroupData lpGParentData;
3394 lpGroupData lpGData;
3395 lpGroupList lpNewGList;
3397 TRACE( "(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup );
3399 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3401 return DPERR_INVALIDGROUP;
3404 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3406 return DPERR_INVALIDGROUP;
3409 /* Create a player list (ie "shortcut" ) */
3410 lpNewGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewGList ) );
3411 if( lpNewGList == NULL )
3413 return DPERR_CANTADDPLAYER;
3416 /* Add the shortcut */
3418 lpNewGList->lpGData = lpGData;
3420 /* Add the player to the list of players for this group */
3421 DPQ_INSERT( lpGData->groups, lpNewGList, groups );
3423 /* Send a ADDGROUPTOGROUP message */
3424 FIXME( "Not sending message\n" );
3429 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3430 ( LPDIRECTPLAY3A iface, DPID idParentGroup, DPID idGroup )
3432 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3433 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3436 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3437 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3439 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3440 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3443 static HRESULT WINAPI DP_IF_CreateGroupInGroup
3444 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
3445 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
3446 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3448 lpGroupData lpGParentData;
3449 lpGroupList lpGList;
3450 lpGroupData lpGData;
3452 TRACE( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
3453 This, idParentGroup, lpidGroup, lpGroupName, lpData,
3454 dwDataSize, dwFlags, bAnsi );
3456 /* Verify that the specified parent is valid */
3457 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This,
3458 idParentGroup ) ) == NULL
3461 return DPERR_INVALIDGROUP;
3464 lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName,
3465 dwFlags, idParentGroup, bAnsi );
3467 if( lpGData == NULL )
3469 return DPERR_CANTADDPLAYER; /* yes player not group */
3472 /* Something else is referencing this data */
3475 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
3477 /* The list has now been inserted into the interface group list. We now
3478 need to put a "shortcut" to this group in the parent group */
3479 lpGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGList ) );
3480 if( lpGList == NULL )
3482 FIXME( "Memory leak\n" );
3483 return DPERR_CANTADDPLAYER; /* yes player not group */
3486 lpGList->lpGData = lpGData;
3488 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
3490 /* Let the SP know that we've created this group */
3491 if( This->dp2->spData.lpCB->CreateGroup )
3493 DPSP_CREATEGROUPDATA data;
3495 TRACE( "Calling SP CreateGroup\n" );
3497 data.idGroup = *lpidGroup;
3498 data.dwFlags = dwFlags;
3499 data.lpSPMessageHeader = lpMsgHdr;
3500 data.lpISP = This->dp2->spData.lpISP;
3502 (*This->dp2->spData.lpCB->CreateGroup)( &data );
3505 /* Inform all other peers of the creation of a new group. If there are
3506 * no peers keep this quiet.
3508 if( This->dp2->lpSessionDesc &&
3509 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
3511 DPMSG_CREATEPLAYERORGROUP msg;
3513 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
3514 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
3515 msg.dpId = *lpidGroup;
3516 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
3517 msg.lpData = lpData;
3518 msg.dwDataSize = dwDataSize;
3519 msg.dpnName = *lpGroupName;
3521 /* FIXME: Correct to just use send effectively? */
3522 /* FIXME: Should size include data w/ message or just message "header" */
3523 /* FIXME: Check return code */
3524 DP_SendEx( (IDirectPlay2Impl*)This,
3525 DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
3526 0, 0, NULL, NULL, bAnsi );
3532 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3533 ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup,
3534 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3537 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3539 *lpidGroup = DPID_UNKNOWN;
3541 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3542 lpGroupName, lpData, dwDataSize, dwFlags,
3546 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3547 ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup,
3548 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3551 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3553 *lpidGroup = DPID_UNKNOWN;
3555 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3556 lpGroupName, lpData, dwDataSize,
3560 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
3561 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3563 lpGroupList lpGList;
3564 lpGroupData lpGParentData;
3566 TRACE("(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup );
3568 /* Is the parent group valid? */
3569 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3571 return DPERR_INVALIDGROUP;
3574 /* Remove the group from the parent group queue */
3575 DPQ_REMOVE_ENTRY( lpGParentData->groups, groups, lpGData->dpid, ==, idGroup, lpGList );
3577 if( lpGList == NULL )
3579 return DPERR_INVALIDGROUP;
3582 /* Decrement the ref count */
3583 lpGList->lpGData->uRef--;
3585 /* Free up the list item */
3586 HeapFree( GetProcessHeap(), 0, lpGList );
3588 /* Should send a DELETEGROUPFROMGROUP message */
3589 FIXME( "message not sent\n" );
3594 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3595 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3597 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3598 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3601 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3602 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3604 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3605 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3609 BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
3610 LPDWORD lpdwBufSize )
3612 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3615 dpCompoundAddress.dwDataSize = sizeof( GUID );
3616 memcpy( &dpCompoundAddress.guidDataType, &DPAID_ServiceProvider,
3618 dpCompoundAddress.lpData = lpcSpGuid;
3620 *lplpAddrBuf = NULL;
3623 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3624 lpdwBufSize, TRUE );
3626 if( hr != DPERR_BUFFERTOOSMALL )
3628 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3632 /* Now allocate the buffer */
3633 *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3636 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3637 lpdwBufSize, TRUE );
3640 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3647 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
3648 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3650 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3651 TRACE("(%p)->(%p,%p,%p,0x%08lx)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3653 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
3656 dwFlags = DPCONNECTION_DIRECTPLAY;
3659 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
3660 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) )
3663 return DPERR_INVALIDFLAGS;
3666 if( !lpEnumCallback || !*lpEnumCallback )
3668 return DPERR_INVALIDPARAMS;
3671 /* Enumerate DirectPlay service providers */
3672 if( dwFlags & DPCONNECTION_DIRECTPLAY )
3675 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3676 LPCSTR guidDataSubKey = "Guid";
3677 char subKeyName[51];
3678 DWORD dwIndex, sizeOfSubKeyName=50;
3681 /* Need to loop over the service providers in the registry */
3682 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3683 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3685 /* Hmmm. Does this mean that there are no service providers? */
3686 ERR(": no service providers?\n");
3691 /* Traverse all the service providers we have available */
3693 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3694 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3695 ++dwIndex, sizeOfSubKeyName=51 )
3698 HKEY hkServiceProvider;
3699 GUID serviceProviderGUID;
3700 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3701 char returnBuffer[51];
3706 LPVOID lpAddressBuffer = NULL;
3707 DWORD dwAddressBufferSize = 0;
3709 TRACE(" this time through: %s\n", subKeyName );
3711 /* Get a handle for this particular service provider */
3712 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3713 &hkServiceProvider ) != ERROR_SUCCESS )
3715 ERR(": what the heck is going on?\n" );
3719 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3720 NULL, &returnTypeGUID, returnBuffer,
3721 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3723 ERR(": missing GUID registry data members\n" );
3727 /* FIXME: Check return types to ensure we're interpreting data right */
3728 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3729 CLSIDFromString( buff, &serviceProviderGUID );
3730 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3732 /* Fill in the DPNAME struct for the service provider */
3733 dpName.dwSize = sizeof( dpName );
3735 dpName.u1.lpszShortNameA = subKeyName;
3736 dpName.u2.lpszLongNameA = NULL;
3738 /* Create the compound address for the service provider.
3739 * NOTE: This is a gruesome architectural scar right now. DP
3740 * uses DPL and DPL uses DP. Nasty stuff. This may be why the
3741 * native dll just gets around this little bit by allocating an
3742 * 80 byte buffer which isn't even filled with a valid compound
3743 * address. Oh well. Creating a proper compound address is the
3744 * way to go anyways despite this method taking slightly more
3745 * heap space and realtime :) */
3747 bBuildPass = DP_BuildSPCompoundAddr( &serviceProviderGUID,
3749 &dwAddressBufferSize );
3752 ERR( "Can't build compound addr\n" );
3753 return DPERR_GENERIC;
3756 /* The enumeration will return FALSE if we are not to continue */
3757 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3758 &dpName, DPCONNECTION_DIRECTPLAY, lpContext ) )
3765 /* Enumerate DirectPlayLobby service providers */
3766 if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY )
3769 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3770 LPCSTR guidDataSubKey = "Guid";
3771 char subKeyName[51];
3772 DWORD dwIndex, sizeOfSubKeyName=50;
3775 /* Need to loop over the service providers in the registry */
3776 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3777 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3779 /* Hmmm. Does this mean that there are no service providers? */
3780 ERR(": no service providers?\n");
3785 /* Traverse all the lobby providers we have available */
3787 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3788 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3789 ++dwIndex, sizeOfSubKeyName=51 )
3792 HKEY hkServiceProvider;
3793 GUID serviceProviderGUID;
3794 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3795 char returnBuffer[51];
3800 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3801 LPVOID lpAddressBuffer = NULL;
3802 DWORD dwAddressBufferSize = 0;
3804 TRACE(" this time through: %s\n", subKeyName );
3806 /* Get a handle for this particular service provider */
3807 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3808 &hkServiceProvider ) != ERROR_SUCCESS )
3810 ERR(": what the heck is going on?\n" );
3814 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3815 NULL, &returnTypeGUID, returnBuffer,
3816 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3818 ERR(": missing GUID registry data members\n" );
3822 /* FIXME: Check return types to ensure we're interpreting data right */
3823 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3824 CLSIDFromString( buff, &serviceProviderGUID );
3825 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3827 /* Fill in the DPNAME struct for the service provider */
3828 dpName.dwSize = sizeof( dpName );
3830 dpName.u1.lpszShortNameA = subKeyName;
3831 dpName.u2.lpszLongNameA = NULL;
3833 /* Create the compound address for the service provider.
3834 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
3835 nast stuff. This may be why the native dll just gets around this little bit by
3836 allocating an 80 byte buffer which isn't even a filled with a valid compound
3837 address. Oh well. Creating a proper compound address is the way to go anyways
3838 despite this method taking slightly more heap space and realtime :) */
3840 dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
3841 dpCompoundAddress.dwDataSize = sizeof( GUID );
3842 dpCompoundAddress.lpData = &serviceProviderGUID;
3844 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3845 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
3847 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3851 /* Now allocate the buffer */
3852 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
3854 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3855 &dwAddressBufferSize, TRUE ) ) != DP_OK )
3857 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3861 /* The enumeration will return FALSE if we are not to continue */
3862 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3863 &dpName, DPCONNECTION_DIRECTPLAYLOBBY, lpContext ) )
3873 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
3874 ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3876 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3877 FIXME("(%p)->(%p,%p,%p,0x%08lx): stub\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3881 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
3882 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
3883 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
3884 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
3886 lpGroupList lpGList;
3887 lpGroupData lpGData;
3889 FIXME( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
3890 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
3891 lpContext, dwFlags, bAnsi );
3893 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3895 return DPERR_INVALIDGROUP;
3898 if( DPQ_IS_EMPTY( lpGData->groups ) )
3903 lpGList = DPQ_FIRST( lpGData->groups );
3907 /* FIXME: Should check dwFlags for match here */
3909 if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP,
3910 &lpGList->lpGData->name, dwFlags,
3913 return DP_OK; /* User requested break */
3916 if( DPQ_IS_ENDOFLIST( lpGList->groups ) )
3921 lpGList = DPQ_NEXT( lpGList->groups );
3928 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
3929 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3930 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3933 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3934 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3935 lpEnumPlayersCallback2, lpContext, dwFlags,
3939 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
3940 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3941 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3944 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3945 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3946 lpEnumPlayersCallback2, lpContext, dwFlags,
3950 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
3951 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3953 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3954 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3958 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
3959 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3961 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3962 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3966 BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
3967 REFGUID guidDataType,
3972 /* Looking for the GUID of the provider to load */
3973 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
3974 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
3977 TRACE( "Found SP/LP (%s) %s (data size = 0x%08lx)\n",
3978 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
3980 if( dwDataSize != sizeof( GUID ) )
3982 ERR( "Invalid sp/lp guid size 0x%08lx\n", dwDataSize );
3985 memcpy( lpContext, lpData, dwDataSize );
3987 /* There shouldn't be more than 1 GUID/compound address */
3991 /* Still waiting for what we want */
3996 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
3997 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
4000 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4001 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
4002 LPCSTR guidDataSubKey = "Guid";
4003 LPCSTR majVerDataSubKey = "dwReserved1";
4004 LPCSTR minVerDataSubKey = "dwReserved2";
4005 LPCSTR pathSubKey = "Path";
4007 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
4009 /* FIXME: Cloned code with a quick hack. */
4010 for( i=0; i<2; i++ )
4013 LPCSTR searchSubKey;
4014 char subKeyName[51];
4015 DWORD dwIndex, sizeOfSubKeyName=50;
4018 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
4019 *lpbIsDpSp = (i == 0) ? TRUE : FALSE;
4022 /* Need to loop over the service providers in the registry */
4023 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4024 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4026 /* Hmmm. Does this mean that there are no service providers? */
4027 ERR(": no service providers?\n");
4031 /* Traverse all the service providers we have available */
4033 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4034 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4035 ++dwIndex, sizeOfSubKeyName=51 )
4038 HKEY hkServiceProvider;
4039 GUID serviceProviderGUID;
4040 DWORD returnType, sizeOfReturnBuffer = 255;
4041 char returnBuffer[256];
4045 TRACE(" this time through: %s\n", subKeyName );
4047 /* Get a handle for this particular service provider */
4048 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4049 &hkServiceProvider ) != ERROR_SUCCESS )
4051 ERR(": what the heck is going on?\n" );
4055 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4056 NULL, &returnType, returnBuffer,
4057 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4059 ERR(": missing GUID registry data members\n" );
4063 /* FIXME: Check return types to ensure we're interpreting data right */
4064 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4065 CLSIDFromString( buff, &serviceProviderGUID );
4066 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4068 /* Determine if this is the Service Provider that the user asked for */
4069 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
4074 if( i == 0 ) /* DP SP */
4076 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
4077 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
4078 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
4081 sizeOfReturnBuffer = 255;
4083 /* Get dwReserved1 */
4084 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
4085 NULL, &returnType, returnBuffer,
4086 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4088 ERR(": missing dwReserved1 registry data members\n") ;
4093 memcpy( &lpSpData->dwReserved1, returnBuffer, sizeof(lpSpData->dwReserved1) );
4095 sizeOfReturnBuffer = 255;
4097 /* Get dwReserved2 */
4098 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4099 NULL, &returnType, returnBuffer,
4100 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4102 ERR(": missing dwReserved1 registry data members\n") ;
4107 memcpy( &lpSpData->dwReserved2, returnBuffer, sizeof(lpSpData->dwReserved2) );
4109 sizeOfReturnBuffer = 255;
4111 /* Get the path for this service provider */
4112 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
4113 NULL, NULL, returnBuffer,
4114 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
4116 ERR(": missing PATH registry data members: 0x%08lx\n", dwTemp );
4120 TRACE( "Loading %s\n", returnBuffer );
4121 return LoadLibraryA( returnBuffer );
4129 HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider )
4132 LPDPSP_SPINIT SPInit;
4134 /* Initialize the service provider by calling SPInit */
4135 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4137 if( SPInit == NULL )
4139 ERR( "Service provider doesn't provide SPInit interface?\n" );
4140 FreeLibrary( hServiceProvider );
4141 return DPERR_UNAVAILABLE;
4144 TRACE( "Calling SPInit (DP SP entry point)\n" );
4146 hr = (*SPInit)( &This->dp2->spData );
4150 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4151 FreeLibrary( hServiceProvider );
4155 /* FIXME: Need to verify the sanity of the returned callback table
4156 * using IsBadCodePtr */
4157 This->dp2->bSPInitialized = TRUE;
4159 /* This interface is now initialized as a DP object */
4160 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
4162 /* Store the handle of the module so that we can unload it later */
4163 This->dp2->hServiceProvider = hServiceProvider;
4169 HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hLobbyProvider )
4172 LPSP_INIT DPLSPInit;
4174 /* Initialize the service provider by calling SPInit */
4175 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
4177 if( DPLSPInit == NULL )
4179 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4180 FreeLibrary( hLobbyProvider );
4181 return DPERR_UNAVAILABLE;
4184 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4186 hr = (*DPLSPInit)( &This->dp2->dplspData );
4190 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4191 FreeLibrary( hLobbyProvider );
4195 /* FIXME: Need to verify the sanity of the returned callback table
4196 * using IsBadCodePtr */
4198 This->dp2->bDPLSPInitialized = TRUE;
4200 /* This interface is now initialized as a lobby object */
4201 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
4203 /* Store the handle of the module so that we can unload it later */
4204 This->dp2->hDPLobbyProvider = hLobbyProvider;
4209 static HRESULT WINAPI DP_IF_InitializeConnection
4210 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi )
4212 HMODULE hServiceProvider;
4215 const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
4216 BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4218 TRACE("(%p)->(%p,0x%08lx,%u)\n", This, lpConnection, dwFlags, bAnsi );
4222 return DPERR_INVALIDFLAGS;
4225 /* Find out what the requested SP is and how large this buffer is */
4226 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
4227 dwAddrSize, &guidSP );
4231 ERR( "Invalid compound address?\n" );
4232 return DPERR_UNAVAILABLE;
4235 /* Load the service provider */
4236 hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp );
4238 if( hServiceProvider == 0 )
4240 ERR( "Unable to load service provider\n" );
4241 return DPERR_UNAVAILABLE;
4246 /* Fill in what we can of the Service Provider required information.
4247 * The rest was be done in DP_LoadSP
4249 This->dp2->spData.lpAddress = lpConnection;
4250 This->dp2->spData.dwAddressSize = dwAddrSize;
4251 This->dp2->spData.lpGuid = &guidSP;
4253 hr = DP_InitializeDPSP( This, hServiceProvider );
4257 This->dp2->dplspData.lpAddress = lpConnection;
4259 hr = DP_InitializeDPLSP( This, hServiceProvider );
4270 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4271 ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
4273 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4275 /* This may not be externally invoked once either an SP or LP is initialized */
4276 if( This->dp2->connectionInitialized != NO_PROVIDER )
4278 return DPERR_ALREADYINITIALIZED;
4281 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE );
4284 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4285 ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
4287 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4289 /* This may not be externally invoked once either an SP or LP is initialized */
4290 if( This->dp2->connectionInitialized != NO_PROVIDER )
4292 return DPERR_ALREADYINITIALIZED;
4295 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE );
4298 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4299 ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4300 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4302 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4303 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4306 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4307 ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4308 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4310 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4311 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4314 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4315 ( LPDIRECTPLAY3A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4317 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4318 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4322 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4323 ( LPDIRECTPLAY3 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4325 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4326 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4330 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4331 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4333 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4334 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4338 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4339 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4341 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4342 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4346 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4347 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup )
4349 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4350 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
4354 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4355 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup )
4357 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4358 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
4362 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4363 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDWORD lpdwFlags )
4365 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4366 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
4370 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4371 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDWORD lpdwFlags )
4373 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4374 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
4378 static HRESULT WINAPI DP_IF_GetGroupParent
4379 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
4382 lpGroupData lpGData;
4384 TRACE("(%p)->(0x%08lx,%p,%u)\n", This, idGroup, lpidGroup, bAnsi );
4386 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4388 return DPERR_INVALIDGROUP;
4391 *lpidGroup = lpGData->dpid;
4396 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4397 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
4399 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4400 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE );
4402 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4403 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
4405 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4406 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE );
4409 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4410 ( LPDIRECTPLAY3A iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4412 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4413 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4417 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4418 ( LPDIRECTPLAY3 iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4420 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4421 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4425 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4426 ( LPDIRECTPLAY3A iface, DPID idPlayer, LPDWORD lpdwFlags )
4428 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4429 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
4433 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4434 ( LPDIRECTPLAY3 iface, DPID idPlayer, LPDWORD lpdwFlags )
4436 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4437 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
4441 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4442 ( LPDIRECTPLAY4A iface, DPID idGroup, LPDPID lpidGroupOwner )
4444 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4445 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
4449 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4450 ( LPDIRECTPLAY4 iface, DPID idGroup, LPDPID lpidGroupOwner )
4452 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4453 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
4457 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4458 ( LPDIRECTPLAY4A iface, DPID idGroup , DPID idGroupOwner )
4460 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4461 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
4465 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4466 ( LPDIRECTPLAY4 iface, DPID idGroup , DPID idGroupOwner )
4468 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4469 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
4473 static HRESULT WINAPI DP_SendEx
4474 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4475 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4476 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi )
4478 lpPlayerList lpPList;
4479 lpGroupData lpGData;
4480 BOOL bValidDestination = FALSE;
4482 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx,0x%08lx,0x%08lx,%p,%p,%u)"
4484 This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority,
4485 dwTimeout, lpContext, lpdwMsgID, bAnsi );
4487 /* FIXME: Add parameter checking */
4488 /* FIXME: First call to this needs to aquire a message id which will be
4489 * used for multiple sends
4492 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4494 /* Verify that the message is being sent from a valid local player. The
4495 * from player may be anonymous DPID_UNKNOWN
4497 if( idFrom != DPID_UNKNOWN )
4499 if( ( lpPList = DP_FindPlayer( This, idFrom ) ) == NULL )
4501 WARN( "INFO: Invalid from player 0x%08lx\n", idFrom );
4502 return DPERR_INVALIDPLAYER;
4506 /* Verify that the message is being sent to a valid player, group or to
4507 * everyone. If it's valid, send it to those players.
4509 if( idTo == DPID_ALLPLAYERS )
4511 bValidDestination = TRUE;
4513 /* See if SP has the ability to multicast. If so, use it */
4514 if( This->dp2->spData.lpCB->SendToGroupEx )
4516 FIXME( "Use group sendex to group 0\n" );
4518 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4520 FIXME( "Use obsolete group send to group 0\n" );
4522 else /* No multicast, multiplicate */
4524 /* Send to all players we know about */
4525 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4529 if( ( !bValidDestination ) &&
4530 ( DP_FindPlayer( This, idTo ) != NULL )
4533 bValidDestination = TRUE;
4535 /* Have the service provider send this message */
4536 /* FIXME: Could optimize for local interface sends */
4537 return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority,
4538 dwTimeout, lpContext, lpdwMsgID );
4541 if( ( !bValidDestination ) &&
4542 ( ( lpGData = DP_FindAnyGroup( This, idTo ) ) != NULL )
4545 bValidDestination = TRUE;
4547 /* See if SP has the ability to multicast. If so, use it */
4548 if( This->dp2->spData.lpCB->SendToGroupEx )
4550 FIXME( "Use group sendex\n" );
4552 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4554 FIXME( "Use obsolete group send to group\n" );
4556 else /* No multicast, multiplicate */
4558 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4566 This->dp2->hReplyEvent = CreateEventW( NULL, FALSE, FALSE, NULL );
4568 dwWaitReturn = WaitForSingleObject( hReplyEvent, dwTimeout );
4569 if( dwWaitReturn != WAIT_OBJECT_0 )
4571 ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
4577 if( !bValidDestination )
4579 return DPERR_INVALIDPLAYER;
4583 /* FIXME: Should return what the send returned */
4589 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4590 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4591 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4592 LPVOID lpContext, LPDWORD lpdwMsgID )
4594 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4595 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4596 dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE );
4599 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4600 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4601 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4602 LPVOID lpContext, LPDWORD lpdwMsgID )
4604 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4605 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4606 dwPriority, dwTimeout, lpContext, lpdwMsgID, FALSE );
4609 static HRESULT WINAPI DP_SP_SendEx
4610 ( IDirectPlay2Impl* This, DWORD dwFlags,
4611 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4612 LPVOID lpContext, LPDWORD lpdwMsgID )
4616 FIXME( ": stub\n" );
4618 /* FIXME: This queuing should only be for async messages */
4620 lpMElem = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpMElem ) );
4621 lpMElem->msg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
4623 CopyMemory( lpMElem->msg, lpData, dwDataSize );
4625 /* FIXME: Need to queue based on priority */
4626 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
4631 static HRESULT WINAPI DP_IF_GetMessageQueue
4632 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4633 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi )
4637 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,%p,%u): semi stub\n",
4638 This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi );
4640 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4641 /* FIXME: What about sends which are not immediate? */
4643 if( This->dp2->spData.lpCB->GetMessageQueue )
4645 DPSP_GETMESSAGEQUEUEDATA data;
4647 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4649 /* FIXME: None of this is documented :( */
4651 data.lpISP = This->dp2->spData.lpISP;
4652 data.dwFlags = dwFlags;
4653 data.idFrom = idFrom;
4655 data.lpdwNumMsgs = lpdwNumMsgs;
4656 data.lpdwNumBytes = lpdwNumBytes;
4658 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
4662 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4668 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4669 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4670 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4672 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4673 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4674 lpdwNumBytes, TRUE );
4677 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4678 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4679 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4681 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4682 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4683 lpdwNumBytes, FALSE );
4686 static HRESULT WINAPI DP_IF_CancelMessage
4687 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
4688 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi )
4692 FIXME( "(%p)->(0x%08lx,0x%08lx,%u): semi stub\n",
4693 This, dwMsgID, dwFlags, bAnsi );
4695 if( This->dp2->spData.lpCB->Cancel )
4697 DPSP_CANCELDATA data;
4699 TRACE( "Calling SP Cancel\n" );
4701 /* FIXME: Undocumented callback */
4703 data.lpISP = This->dp2->spData.lpISP;
4704 data.dwFlags = dwFlags;
4705 data.lprglpvSPMsgID = NULL;
4706 data.cSPMsgID = dwMsgID;
4707 data.dwMinPriority = dwMinPriority;
4708 data.dwMaxPriority = dwMaxPriority;
4710 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
4714 FIXME( "SP doesn't implement Cancel\n" );
4720 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
4721 ( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags )
4723 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4727 return DPERR_INVALIDFLAGS;
4732 dwFlags |= DPCANCELSEND_ALL;
4735 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE );
4738 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
4739 ( LPDIRECTPLAY4 iface, DWORD dwMsgID, DWORD dwFlags )
4741 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4745 return DPERR_INVALIDFLAGS;
4750 dwFlags |= DPCANCELSEND_ALL;
4753 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, FALSE );
4756 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
4757 ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4760 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4764 return DPERR_INVALIDFLAGS;
4767 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4768 dwMaxPriority, TRUE );
4771 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
4772 ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4775 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4779 return DPERR_INVALIDFLAGS;
4782 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4783 dwMaxPriority, FALSE );
4786 /* Note: Hack so we can reuse the old functions without compiler warnings */
4787 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4788 # define XCAST(fun) (typeof(directPlay2WVT.fun))
4790 # define XCAST(fun) (void*)
4793 static IDirectPlay2Vtbl directPlay2WVT =
4795 XCAST(QueryInterface)DP_QueryInterface,
4796 XCAST(AddRef)DP_AddRef,
4797 XCAST(Release)DP_Release,
4799 DirectPlay2WImpl_AddPlayerToGroup,
4800 DirectPlay2WImpl_Close,
4801 DirectPlay2WImpl_CreateGroup,
4802 DirectPlay2WImpl_CreatePlayer,
4803 DirectPlay2WImpl_DeletePlayerFromGroup,
4804 DirectPlay2WImpl_DestroyGroup,
4805 DirectPlay2WImpl_DestroyPlayer,
4806 DirectPlay2WImpl_EnumGroupPlayers,
4807 DirectPlay2WImpl_EnumGroups,
4808 DirectPlay2WImpl_EnumPlayers,
4809 DirectPlay2WImpl_EnumSessions,
4810 DirectPlay2WImpl_GetCaps,
4811 DirectPlay2WImpl_GetGroupData,
4812 DirectPlay2WImpl_GetGroupName,
4813 DirectPlay2WImpl_GetMessageCount,
4814 DirectPlay2WImpl_GetPlayerAddress,
4815 DirectPlay2WImpl_GetPlayerCaps,
4816 DirectPlay2WImpl_GetPlayerData,
4817 DirectPlay2WImpl_GetPlayerName,
4818 DirectPlay2WImpl_GetSessionDesc,
4819 DirectPlay2WImpl_Initialize,
4820 DirectPlay2WImpl_Open,
4821 DirectPlay2WImpl_Receive,
4822 DirectPlay2WImpl_Send,
4823 DirectPlay2WImpl_SetGroupData,
4824 DirectPlay2WImpl_SetGroupName,
4825 DirectPlay2WImpl_SetPlayerData,
4826 DirectPlay2WImpl_SetPlayerName,
4827 DirectPlay2WImpl_SetSessionDesc
4831 /* Note: Hack so we can reuse the old functions without compiler warnings */
4832 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4833 # define XCAST(fun) (typeof(directPlay2AVT.fun))
4835 # define XCAST(fun) (void*)
4838 static IDirectPlay2Vtbl directPlay2AVT =
4840 XCAST(QueryInterface)DP_QueryInterface,
4841 XCAST(AddRef)DP_AddRef,
4842 XCAST(Release)DP_Release,
4844 DirectPlay2AImpl_AddPlayerToGroup,
4845 DirectPlay2AImpl_Close,
4846 DirectPlay2AImpl_CreateGroup,
4847 DirectPlay2AImpl_CreatePlayer,
4848 DirectPlay2AImpl_DeletePlayerFromGroup,
4849 DirectPlay2AImpl_DestroyGroup,
4850 DirectPlay2AImpl_DestroyPlayer,
4851 DirectPlay2AImpl_EnumGroupPlayers,
4852 DirectPlay2AImpl_EnumGroups,
4853 DirectPlay2AImpl_EnumPlayers,
4854 DirectPlay2AImpl_EnumSessions,
4855 DirectPlay2AImpl_GetCaps,
4856 DirectPlay2AImpl_GetGroupData,
4857 DirectPlay2AImpl_GetGroupName,
4858 DirectPlay2AImpl_GetMessageCount,
4859 DirectPlay2AImpl_GetPlayerAddress,
4860 DirectPlay2AImpl_GetPlayerCaps,
4861 DirectPlay2AImpl_GetPlayerData,
4862 DirectPlay2AImpl_GetPlayerName,
4863 DirectPlay2AImpl_GetSessionDesc,
4864 DirectPlay2AImpl_Initialize,
4865 DirectPlay2AImpl_Open,
4866 DirectPlay2AImpl_Receive,
4867 DirectPlay2AImpl_Send,
4868 DirectPlay2AImpl_SetGroupData,
4869 DirectPlay2AImpl_SetGroupName,
4870 DirectPlay2AImpl_SetPlayerData,
4871 DirectPlay2AImpl_SetPlayerName,
4872 DirectPlay2AImpl_SetSessionDesc
4877 /* Note: Hack so we can reuse the old functions without compiler warnings */
4878 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4879 # define XCAST(fun) (typeof(directPlay3AVT.fun))
4881 # define XCAST(fun) (void*)
4884 static IDirectPlay3Vtbl directPlay3AVT =
4886 XCAST(QueryInterface)DP_QueryInterface,
4887 XCAST(AddRef)DP_AddRef,
4888 XCAST(Release)DP_Release,
4890 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
4891 XCAST(Close)DirectPlay2AImpl_Close,
4892 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
4893 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
4894 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
4895 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
4896 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
4897 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
4898 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
4899 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
4900 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
4901 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
4902 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
4903 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
4904 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
4905 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
4906 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
4907 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
4908 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
4909 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
4910 XCAST(Initialize)DirectPlay2AImpl_Initialize,
4911 XCAST(Open)DirectPlay2AImpl_Open,
4912 XCAST(Receive)DirectPlay2AImpl_Receive,
4913 XCAST(Send)DirectPlay2AImpl_Send,
4914 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
4915 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
4916 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
4917 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
4918 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
4920 DirectPlay3AImpl_AddGroupToGroup,
4921 DirectPlay3AImpl_CreateGroupInGroup,
4922 DirectPlay3AImpl_DeleteGroupFromGroup,
4923 DirectPlay3AImpl_EnumConnections,
4924 DirectPlay3AImpl_EnumGroupsInGroup,
4925 DirectPlay3AImpl_GetGroupConnectionSettings,
4926 DirectPlay3AImpl_InitializeConnection,
4927 DirectPlay3AImpl_SecureOpen,
4928 DirectPlay3AImpl_SendChatMessage,
4929 DirectPlay3AImpl_SetGroupConnectionSettings,
4930 DirectPlay3AImpl_StartSession,
4931 DirectPlay3AImpl_GetGroupFlags,
4932 DirectPlay3AImpl_GetGroupParent,
4933 DirectPlay3AImpl_GetPlayerAccount,
4934 DirectPlay3AImpl_GetPlayerFlags
4938 /* Note: Hack so we can reuse the old functions without compiler warnings */
4939 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4940 # define XCAST(fun) (typeof(directPlay3WVT.fun))
4942 # define XCAST(fun) (void*)
4944 static IDirectPlay3Vtbl directPlay3WVT =
4946 XCAST(QueryInterface)DP_QueryInterface,
4947 XCAST(AddRef)DP_AddRef,
4948 XCAST(Release)DP_Release,
4950 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
4951 XCAST(Close)DirectPlay2WImpl_Close,
4952 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
4953 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
4954 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
4955 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
4956 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
4957 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
4958 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
4959 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
4960 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
4961 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
4962 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
4963 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
4964 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
4965 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
4966 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
4967 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
4968 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
4969 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
4970 XCAST(Initialize)DirectPlay2WImpl_Initialize,
4971 XCAST(Open)DirectPlay2WImpl_Open,
4972 XCAST(Receive)DirectPlay2WImpl_Receive,
4973 XCAST(Send)DirectPlay2WImpl_Send,
4974 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
4975 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
4976 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
4977 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
4978 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
4980 DirectPlay3WImpl_AddGroupToGroup,
4981 DirectPlay3WImpl_CreateGroupInGroup,
4982 DirectPlay3WImpl_DeleteGroupFromGroup,
4983 DirectPlay3WImpl_EnumConnections,
4984 DirectPlay3WImpl_EnumGroupsInGroup,
4985 DirectPlay3WImpl_GetGroupConnectionSettings,
4986 DirectPlay3WImpl_InitializeConnection,
4987 DirectPlay3WImpl_SecureOpen,
4988 DirectPlay3WImpl_SendChatMessage,
4989 DirectPlay3WImpl_SetGroupConnectionSettings,
4990 DirectPlay3WImpl_StartSession,
4991 DirectPlay3WImpl_GetGroupFlags,
4992 DirectPlay3WImpl_GetGroupParent,
4993 DirectPlay3WImpl_GetPlayerAccount,
4994 DirectPlay3WImpl_GetPlayerFlags
4998 /* Note: Hack so we can reuse the old functions without compiler warnings */
4999 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5000 # define XCAST(fun) (typeof(directPlay4WVT.fun))
5002 # define XCAST(fun) (void*)
5004 static IDirectPlay4Vtbl directPlay4WVT =
5006 XCAST(QueryInterface)DP_QueryInterface,
5007 XCAST(AddRef)DP_AddRef,
5008 XCAST(Release)DP_Release,
5010 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
5011 XCAST(Close)DirectPlay2WImpl_Close,
5012 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
5013 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
5014 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
5015 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
5016 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5017 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5018 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5019 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5020 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5021 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5022 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5023 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5024 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5025 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5026 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5027 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5028 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5029 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5030 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5031 XCAST(Open)DirectPlay2WImpl_Open,
5032 XCAST(Receive)DirectPlay2WImpl_Receive,
5033 XCAST(Send)DirectPlay2WImpl_Send,
5034 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5035 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5036 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5037 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5038 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5040 XCAST(AddGroupToGroup)DirectPlay3WImpl_AddGroupToGroup,
5041 XCAST(CreateGroupInGroup)DirectPlay3WImpl_CreateGroupInGroup,
5042 XCAST(DeleteGroupFromGroup)DirectPlay3WImpl_DeleteGroupFromGroup,
5043 XCAST(EnumConnections)DirectPlay3WImpl_EnumConnections,
5044 XCAST(EnumGroupsInGroup)DirectPlay3WImpl_EnumGroupsInGroup,
5045 XCAST(GetGroupConnectionSettings)DirectPlay3WImpl_GetGroupConnectionSettings,
5046 XCAST(InitializeConnection)DirectPlay3WImpl_InitializeConnection,
5047 XCAST(SecureOpen)DirectPlay3WImpl_SecureOpen,
5048 XCAST(SendChatMessage)DirectPlay3WImpl_SendChatMessage,
5049 XCAST(SetGroupConnectionSettings)DirectPlay3WImpl_SetGroupConnectionSettings,
5050 XCAST(StartSession)DirectPlay3WImpl_StartSession,
5051 XCAST(GetGroupFlags)DirectPlay3WImpl_GetGroupFlags,
5052 XCAST(GetGroupParent)DirectPlay3WImpl_GetGroupParent,
5053 XCAST(GetPlayerAccount)DirectPlay3WImpl_GetPlayerAccount,
5054 XCAST(GetPlayerFlags)DirectPlay3WImpl_GetPlayerFlags,
5056 DirectPlay4WImpl_GetGroupOwner,
5057 DirectPlay4WImpl_SetGroupOwner,
5058 DirectPlay4WImpl_SendEx,
5059 DirectPlay4WImpl_GetMessageQueue,
5060 DirectPlay4WImpl_CancelMessage,
5061 DirectPlay4WImpl_CancelPriority
5066 /* Note: Hack so we can reuse the old functions without compiler warnings */
5067 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5068 # define XCAST(fun) (typeof(directPlay4AVT.fun))
5070 # define XCAST(fun) (void*)
5072 static IDirectPlay4Vtbl directPlay4AVT =
5074 XCAST(QueryInterface)DP_QueryInterface,
5075 XCAST(AddRef)DP_AddRef,
5076 XCAST(Release)DP_Release,
5078 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
5079 XCAST(Close)DirectPlay2AImpl_Close,
5080 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
5081 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
5082 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
5083 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
5084 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
5085 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
5086 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
5087 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
5088 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
5089 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
5090 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
5091 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
5092 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5093 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5094 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5095 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5096 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5097 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5098 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5099 XCAST(Open)DirectPlay2AImpl_Open,
5100 XCAST(Receive)DirectPlay2AImpl_Receive,
5101 XCAST(Send)DirectPlay2AImpl_Send,
5102 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5103 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5104 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5105 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5106 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5108 XCAST(AddGroupToGroup)DirectPlay3AImpl_AddGroupToGroup,
5109 XCAST(CreateGroupInGroup)DirectPlay3AImpl_CreateGroupInGroup,
5110 XCAST(DeleteGroupFromGroup)DirectPlay3AImpl_DeleteGroupFromGroup,
5111 XCAST(EnumConnections)DirectPlay3AImpl_EnumConnections,
5112 XCAST(EnumGroupsInGroup)DirectPlay3AImpl_EnumGroupsInGroup,
5113 XCAST(GetGroupConnectionSettings)DirectPlay3AImpl_GetGroupConnectionSettings,
5114 XCAST(InitializeConnection)DirectPlay3AImpl_InitializeConnection,
5115 XCAST(SecureOpen)DirectPlay3AImpl_SecureOpen,
5116 XCAST(SendChatMessage)DirectPlay3AImpl_SendChatMessage,
5117 XCAST(SetGroupConnectionSettings)DirectPlay3AImpl_SetGroupConnectionSettings,
5118 XCAST(StartSession)DirectPlay3AImpl_StartSession,
5119 XCAST(GetGroupFlags)DirectPlay3AImpl_GetGroupFlags,
5120 XCAST(GetGroupParent)DirectPlay3AImpl_GetGroupParent,
5121 XCAST(GetPlayerAccount)DirectPlay3AImpl_GetPlayerAccount,
5122 XCAST(GetPlayerFlags)DirectPlay3AImpl_GetPlayerFlags,
5124 DirectPlay4AImpl_GetGroupOwner,
5125 DirectPlay4AImpl_SetGroupOwner,
5126 DirectPlay4AImpl_SendEx,
5127 DirectPlay4AImpl_GetMessageQueue,
5128 DirectPlay4AImpl_CancelMessage,
5129 DirectPlay4AImpl_CancelPriority
5134 HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP,
5138 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5140 if( lpPlayer == NULL )
5142 return DPERR_INVALIDPLAYER;
5145 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
5151 HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP,
5155 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5157 if( lpPlayer == NULL )
5159 return DPERR_INVALIDPLAYER;
5162 lpPlayer->lpPData->lpSPPlayerData = lpData;
5167 /***************************************************************************
5168 * DirectPlayEnumerate [DPLAYX.9]
5169 * DirectPlayEnumerateA [DPLAYX.2]
5171 * The pointer to the structure lpContext will be filled with the
5172 * appropriate data for each service offered by the OS. These services are
5173 * not necessarily available on this particular machine but are defined
5174 * as simple service providers under the "Service Providers" registry key.
5175 * This structure is then passed to lpEnumCallback for each of the different
5178 * This API is useful only for applications written using DirectX3 or
5179 * worse. It is superseded by IDirectPlay3::EnumConnections which also
5180 * gives information on the actual connections.
5182 * defn of a service provider:
5183 * A dynamic-link library used by DirectPlay to communicate over a network.
5184 * The service provider contains all the network-specific code required
5185 * to send and receive messages. Online services and network operators can
5186 * supply service providers to use specialized hardware, protocols, communications
5187 * media, and network resources.
5189 * TODO: Allocate string buffer space from the heap (length from reg)
5190 * Pass real device driver numbers...
5191 * Get the GUID properly...
5193 HRESULT WINAPI DirectPlayEnumerateA( LPDPENUMDPCALLBACKA lpEnumCallback,
5198 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
5200 DWORD sizeOfSubKeyName=50;
5201 char subKeyName[51];
5204 TRACE(": lpEnumCallback=%p lpContext=%p\n", lpEnumCallback, lpContext );
5206 if( !lpEnumCallback || !*lpEnumCallback )
5208 return DPERR_INVALIDPARAMS;
5211 /* Need to loop over the service providers in the registry */
5212 if( RegOpenKeyExA( 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 providers?\n");
5217 return DPERR_NOSERVICEPROVIDER;
5220 /* Traverse all the service providers we have available */
5222 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
5223 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
5224 ++dwIndex, sizeOfSubKeyName=50 )
5226 LPCSTR majVerDataSubKey = "dwReserved1";
5227 LPCSTR minVerDataSubKey = "dwReserved2";
5228 LPCSTR guidDataSubKey = "Guid";
5229 HKEY hkServiceProvider;
5230 GUID serviceProviderGUID;
5231 DWORD returnTypeGUID, returnTypeReserved, sizeOfReturnBuffer = 50;
5232 char returnBuffer[51];
5234 DWORD majVersionNum , minVersionNum = 0;
5236 TRACE(" this time through: %s\n", subKeyName );
5238 /* Get a handle for this particular service provider */
5239 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
5240 &hkServiceProvider ) != ERROR_SUCCESS )
5242 ERR(": what the heck is going on?\n" );
5246 /* Get the GUID, Device major number and device minor number
5247 * from the registry.
5249 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
5250 NULL, &returnTypeGUID, returnBuffer,
5251 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5253 ERR(": missing GUID registry data members\n" );
5257 /* FIXME: Check return types to ensure we're interpreting data right */
5258 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
5259 CLSIDFromString( buff, &serviceProviderGUID );
5261 /* FIXME: Need to know which of dwReserved1 and dwReserved2 are maj and min */
5263 sizeOfReturnBuffer = 50;
5264 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
5265 NULL, &returnTypeReserved, returnBuffer,
5266 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5268 ERR(": missing dwReserved1 registry data members\n") ;
5271 memcpy( &majVersionNum, returnBuffer, sizeof(majVersionNum) );
5273 sizeOfReturnBuffer = 50;
5274 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
5275 NULL, &returnTypeReserved, returnBuffer,
5276 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5278 ERR(": missing dwReserved2 registry data members\n") ;
5281 memcpy( &minVersionNum, returnBuffer, sizeof(minVersionNum) );
5284 /* The enumeration will return FALSE if we are not to continue */
5285 if( !lpEnumCallback( &serviceProviderGUID , subKeyName,
5286 majVersionNum, minVersionNum, lpContext ) )
5288 WARN("lpEnumCallback returning FALSE\n" );
5297 /***************************************************************************
5298 * DirectPlayEnumerateW [DPLAYX.3]
5301 HRESULT WINAPI DirectPlayEnumerateW( LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5306 return DPERR_OUTOFMEMORY;
5310 typedef struct tagCreateEnum
5314 } CreateEnumData, *lpCreateEnumData;
5316 /* Find and copy the matching connection for the SP guid */
5317 static BOOL CALLBACK cbDPCreateEnumConnections(
5319 LPVOID lpConnection,
5320 DWORD dwConnectionSize,
5325 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5327 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5329 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5331 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5333 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5335 /* Found the record that we were looking for */
5339 /* Haven't found what were looking for yet */
5344 /***************************************************************************
5345 * DirectPlayCreate [DPLAYX.1]
5348 HRESULT WINAPI DirectPlayCreate
5349 ( LPGUID lpGUID, LPDIRECTPLAY2 *lplpDP, IUnknown *pUnk)
5352 LPDIRECTPLAY3A lpDP3A;
5353 CreateEnumData cbData;
5355 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5359 return CLASS_E_NOAGGREGATION;
5362 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5363 give them an IDirectPlay2A object and hope that doesn't cause problems */
5364 if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
5366 return DPERR_UNAVAILABLE;
5369 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
5371 /* The GUID_NULL means don't bind a service provider. Just return the
5376 /* Bind the desired service provider since lpGUID is non NULL */
5377 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
5379 /* We're going to use a DP3 interface */
5380 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
5384 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
5388 cbData.lpConn = NULL;
5389 cbData.lpGuid = lpGUID;
5391 /* We were given a service provider, find info about it... */
5392 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
5393 &cbData, DPCONNECTION_DIRECTPLAY );
5394 if( ( FAILED(hr) ) ||
5395 ( cbData.lpConn == NULL )
5398 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
5399 IDirectPlayX_Release( lpDP3A );
5400 return DPERR_UNAVAILABLE;
5403 /* Initialize the service provider */
5404 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
5407 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
5408 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5409 IDirectPlayX_Release( lpDP3A );
5413 /* Release our version of the interface now that we're done with it */
5414 IDirectPlayX_Release( lpDP3A );
5415 HeapFree( GetProcessHeap(), 0, cbData.lpConn );