Removed some uses of the non-standard ICOM_THIS macro.
[wine/multimedia.git] / dlls / dplayx / dplay.c
blob16e918d227d07eaebde70ec91db586c1eb747548
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
20 #include "config.h"
21 #include "wine/port.h"
23 #include <stdarg.h>
24 #include <string.h>
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
28 #include "windef.h"
29 #include "winerror.h"
30 #include "winbase.h"
31 #include "winnt.h"
32 #include "winreg.h"
33 #include "winnls.h"
34 #include "wine/unicode.h"
35 #include "wine/debug.h"
37 #include "dpinit.h"
38 #include "dplayx_global.h"
39 #include "name_server.h"
40 #include "dplayx_queue.h"
41 #include "dplaysp.h"
42 #include "dplay_global.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(dplay);
46 /* FIXME: Should this be externed? */
47 extern HRESULT DPL_CreateCompoundAddress
48 ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
49 LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
52 /* Local function prototypes */
53 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid );
54 static lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* iface, LPDPID lpid,
55 LPDPNAME lpName, DWORD dwFlags,
56 HANDLE hEvent, BOOL bAnsi );
57 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, 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,
69 DWORD dwPlayerType,
70 LPCDPNAME lpName,
71 DWORD dwFlags,
72 LPVOID lpContext );
73 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid );
74 static BOOL CALLBACK cbRemoveGroupOrPlayer( DPID dpId, DWORD dwPlayerType,
75 LPCDPNAME lpName, DWORD dwFlags,
76 LPVOID lpContext );
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,
154 BOOL bAnsi );
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,
174 DWORD dwFlags );
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,
185 BOOL bAnsi );
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 = (DirectPlayIUnknownData*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
240 sizeof( *(This->unk) ) );
241 if ( This->unk == NULL )
243 return FALSE;
246 InitializeCriticalSection( &This->unk->DP_lock );
248 return TRUE;
251 static BOOL DP_DestroyIUnknown( LPVOID lpDP )
253 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;
255 DeleteCriticalSection( &This->unk->DP_lock );
256 HeapFree( GetProcessHeap(), 0, This->unk );
258 return TRUE;
261 static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
263 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;
265 This->dp2 = (DirectPlay2Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
266 sizeof( *(This->dp2) ) );
267 if ( This->dp2 == NULL )
269 return FALSE;
272 This->dp2->bConnectionOpen = FALSE;
274 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
276 This->dp2->bHostInterface = FALSE;
278 DPQ_INIT(This->dp2->receiveMsgs);
279 DPQ_INIT(This->dp2->sendMsgs);
280 DPQ_INIT(This->dp2->replysExpected);
282 if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
284 /* FIXME: Memory leak */
285 return FALSE;
288 /* Provide an initial session desc with nothing in it */
289 This->dp2->lpSessionDesc = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
290 HEAP_ZERO_MEMORY,
291 sizeof( *This->dp2->lpSessionDesc ) );
292 if( This->dp2->lpSessionDesc == NULL )
294 /* FIXME: Memory leak */
295 return FALSE;
297 This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc );
299 /* We are a emulating a dp 6 implementation */
300 This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION;
302 This->dp2->spData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
303 sizeof( *This->dp2->spData.lpCB ) );
304 This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB );
305 This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION;
307 /* This is the pointer to the service provider */
308 if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP,
309 (LPVOID*)&This->dp2->spData.lpISP, This ) )
312 /* FIXME: Memory leak */
313 return FALSE;
316 /* Setup lobby provider information */
317 This->dp2->dplspData.dwSPVersion = DPSP_MAJORVERSION;
318 This->dp2->dplspData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
319 sizeof( *This->dp2->dplspData.lpCB ) );
320 This->dp2->dplspData.lpCB->dwSize = sizeof( *This->dp2->dplspData.lpCB );
322 if( FAILED( DPLSP_CreateInterface( &IID_IDPLobbySP,
323 (LPVOID*)&This->dp2->dplspData.lpISP, This ) )
326 /* FIXME: Memory leak */
327 return FALSE;
330 return TRUE;
333 /* Definition of the global function in dplayx_queue.h. #
334 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
335 DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
337 HeapFree( GetProcessHeap(), 0, elem );
340 /* Function to delete the list of groups with this interface. Needs to
341 * delete the group and player lists associated with this group as well
342 * as the group data associated with this group. It should not delete
343 * player data as that is shared with the top player list and will be
344 * deleted with that.
346 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList );
347 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList )
349 DPQ_DELETEQ( elem->lpGData->groups, groups,
350 lpGroupList, cbDeleteElemFromHeap );
351 DPQ_DELETEQ( elem->lpGData->players, players,
352 lpPlayerList, cbDeleteElemFromHeap );
353 HeapFree( GetProcessHeap(), 0, elem->lpGData );
354 HeapFree( GetProcessHeap(), 0, elem );
357 /* Function to delete the list of players with this interface. Needs to
358 * delete the player data for all players as well.
360 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList );
361 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList )
363 HeapFree( GetProcessHeap(), 0, elem->lpPData );
364 HeapFree( GetProcessHeap(), 0, elem );
367 static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
369 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;
371 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
373 TerminateThread( This->dp2->hEnumSessionThread, 0 );
374 CloseHandle( This->dp2->hEnumSessionThread );
377 /* Finish with the SP - have it shutdown */
378 if( This->dp2->spData.lpCB->ShutdownEx )
380 DPSP_SHUTDOWNDATA data;
382 TRACE( "Calling SP ShutdownEx\n" );
384 data.lpISP = This->dp2->spData.lpISP;
386 (*This->dp2->spData.lpCB->ShutdownEx)( &data );
388 else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
390 TRACE( "Calling obsolete SP Shutdown\n" );
391 (*This->dp2->spData.lpCB->Shutdown)();
394 /* Unload the SP (if it exists) */
395 if( This->dp2->hServiceProvider != 0 )
397 FreeLibrary( This->dp2->hServiceProvider );
400 /* Unload the Lobby Provider (if it exists) */
401 if( This->dp2->hDPLobbyProvider != 0 )
403 FreeLibrary( This->dp2->hDPLobbyProvider );
406 #if 0
407 DPQ_DELETEQ( This->dp2->players, players, lpPlayerList, cbDeletePlayerElem );
408 DPQ_DELETEQ( This->dp2->groups, groups, lpGroupList, cbDeleteGroupsElem );
409 #endif
411 /* FIXME: Need to delete receive and send msgs queue contents */
413 NS_DeleteSessionCache( This->dp2->lpNameServerData );
415 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
417 IDirectPlaySP_Release( This->dp2->spData.lpISP );
419 /* Delete the contents */
420 HeapFree( GetProcessHeap(), 0, This->dp2 );
422 return TRUE;
425 static BOOL DP_CreateDirectPlay3( LPVOID lpDP )
427 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;
429 This->dp3 = (DirectPlay3Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
430 sizeof( *(This->dp3) ) );
431 if ( This->dp3 == NULL )
433 return FALSE;
436 return TRUE;
439 static BOOL DP_DestroyDirectPlay3( LPVOID lpDP )
441 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;
443 /* Delete the contents */
444 HeapFree( GetProcessHeap(), 0, This->dp3 );
446 return TRUE;
449 static BOOL DP_CreateDirectPlay4( LPVOID lpDP )
451 IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)lpDP;
453 This->dp4 = (DirectPlay4Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
454 sizeof( *(This->dp4) ) );
455 if ( This->dp4 == NULL )
457 return FALSE;
460 return TRUE;
463 static BOOL DP_DestroyDirectPlay4( LPVOID lpDP )
465 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;
467 /* Delete the contents */
468 HeapFree( GetProcessHeap(), 0, This->dp4 );
470 return TRUE;
474 /* Create a new interface */
475 extern
476 HRESULT DP_CreateInterface
477 ( REFIID riid, LPVOID* ppvObj )
479 TRACE( " for %s\n", debugstr_guid( riid ) );
481 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
482 sizeof( IDirectPlay2Impl ) );
484 if( *ppvObj == NULL )
486 return DPERR_OUTOFMEMORY;
489 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
491 IDirectPlay2Impl *This = (IDirectPlay2Impl *)*ppvObj;
492 This->lpVtbl = &directPlay2WVT;
494 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
496 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)*ppvObj;
497 This->lpVtbl = &directPlay2AVT;
499 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
501 IDirectPlay3Impl *This = (IDirectPlay3Impl *)*ppvObj;
502 This->lpVtbl = &directPlay3WVT;
504 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
506 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)*ppvObj;
507 This->lpVtbl = &directPlay3AVT;
509 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
511 IDirectPlay4Impl *This = (IDirectPlay4Impl *)*ppvObj;
512 This->lpVtbl = &directPlay4WVT;
514 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
516 IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)*ppvObj;
517 This->lpVtbl = &directPlay4AVT;
519 else
521 /* Unsupported interface */
522 HeapFree( GetProcessHeap(), 0, *ppvObj );
523 *ppvObj = NULL;
525 return E_NOINTERFACE;
528 /* Initialize it */
529 if ( DP_CreateIUnknown( *ppvObj ) &&
530 DP_CreateDirectPlay2( *ppvObj ) &&
531 DP_CreateDirectPlay3( *ppvObj ) &&
532 DP_CreateDirectPlay4( *ppvObj )
535 IDirectPlayX_AddRef( (LPDIRECTPLAY2A)*ppvObj );
537 return S_OK;
540 /* Initialize failed, destroy it */
541 DP_DestroyDirectPlay4( *ppvObj );
542 DP_DestroyDirectPlay3( *ppvObj );
543 DP_DestroyDirectPlay2( *ppvObj );
544 DP_DestroyIUnknown( *ppvObj );
546 HeapFree( GetProcessHeap(), 0, *ppvObj );
548 *ppvObj = NULL;
549 return DPERR_NOMEMORY;
553 /* Direct Play methods */
555 /* Shared between all dplay types */
556 static HRESULT WINAPI DP_QueryInterface
557 ( LPDIRECTPLAY2 iface, REFIID riid, LPVOID* ppvObj )
559 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
560 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
562 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
563 sizeof( *This ) );
565 if( *ppvObj == NULL )
567 return DPERR_OUTOFMEMORY;
570 CopyMemory( *ppvObj, This, sizeof( *This ) );
571 (*(IDirectPlay2Impl**)ppvObj)->ulInterfaceRef = 0;
573 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
575 IDirectPlay2Impl *This = (IDirectPlay2Impl *)*ppvObj;
576 This->lpVtbl = &directPlay2WVT;
578 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
580 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)*ppvObj;
581 This->lpVtbl = &directPlay2AVT;
583 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
585 IDirectPlay3Impl *This = (IDirectPlay3Impl *)*ppvObj;
586 This->lpVtbl = &directPlay3WVT;
588 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
590 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)*ppvObj;
591 This->lpVtbl = &directPlay3AVT;
593 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
595 IDirectPlay4Impl *This = (IDirectPlay4Impl *)*ppvObj;
596 This->lpVtbl = &directPlay4WVT;
598 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
600 IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)*ppvObj;
601 This->lpVtbl = &directPlay4AVT;
603 else
605 /* Unsupported interface */
606 HeapFree( GetProcessHeap(), 0, *ppvObj );
607 *ppvObj = NULL;
609 return E_NOINTERFACE;
612 IDirectPlayX_AddRef( (LPDIRECTPLAY2)*ppvObj );
614 return S_OK;
617 /* Shared between all dplay types */
618 static ULONG WINAPI DP_AddRef
619 ( LPDIRECTPLAY3 iface )
621 ULONG ulInterfaceRefCount, ulObjRefCount;
622 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
624 ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
625 ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
627 TRACE( "ref count incremented to %lu:%lu for %p\n",
628 ulInterfaceRefCount, ulObjRefCount, This );
630 return ulObjRefCount;
633 static ULONG WINAPI DP_Release
634 ( LPDIRECTPLAY3 iface )
636 ULONG ulInterfaceRefCount, ulObjRefCount;
638 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
640 ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
641 ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
643 TRACE( "ref count decremented to %lu:%lu for %p\n",
644 ulInterfaceRefCount, ulObjRefCount, This );
646 /* Deallocate if this is the last reference to the object */
647 if( ulObjRefCount == 0 )
649 /* If we're destroying the object, this must be the last ref
650 of the last interface */
651 DP_DestroyDirectPlay4( This );
652 DP_DestroyDirectPlay3( This );
653 DP_DestroyDirectPlay2( This );
654 DP_DestroyIUnknown( This );
657 /* Deallocate the interface */
658 if( ulInterfaceRefCount == 0 )
660 HeapFree( GetProcessHeap(), 0, This );
663 return ulObjRefCount;
666 static inline DPID DP_NextObjectId(void)
668 return (DPID)InterlockedIncrement( &kludgePlayerGroupId );
671 /* *lplpReply will be non NULL iff there is something to reply */
672 HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpcMessageBody,
673 DWORD dwMessageBodySize, LPCVOID lpcMessageHeader,
674 WORD wCommandId, WORD wVersion,
675 LPVOID* lplpReply, LPDWORD lpdwMsgSize )
677 TRACE( "(%p)->(%p,0x%08lx,%p,%u,%u)\n",
678 This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId,
679 wVersion );
681 switch( wCommandId )
683 /* Name server needs to handle this request */
684 case DPMSGCMD_ENUMSESSIONSREQUEST:
686 /* Reply expected */
687 NS_ReplyToEnumSessionsRequest( lpcMessageBody, lplpReply, lpdwMsgSize, This );
689 break;
692 /* Name server needs to handle this request */
693 case DPMSGCMD_ENUMSESSIONSREPLY:
695 /* No reply expected */
696 NS_AddRemoteComputerAsNameServer( lpcMessageHeader,
697 This->dp2->spData.dwSPHeaderSize,
698 (LPDPMSG_ENUMSESSIONSREPLY)lpcMessageBody,
699 This->dp2->lpNameServerData );
700 break;
703 case DPMSGCMD_REQUESTNEWPLAYERID:
705 LPCDPMSG_REQUESTNEWPLAYERID lpcMsg =
706 (LPCDPMSG_REQUESTNEWPLAYERID)lpcMessageBody;
708 LPDPMSG_NEWPLAYERIDREPLY lpReply;
710 *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
712 *lplpReply = (LPDPMSG_NEWPLAYERIDREPLY)HeapAlloc( GetProcessHeap(),
713 HEAP_ZERO_MEMORY,
714 *lpdwMsgSize );
716 FIXME( "Ignoring dwFlags 0x%08lx in request msg\n",
717 lpcMsg->dwFlags );
719 /* Setup the reply */
720 lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) +
721 This->dp2->spData.dwSPHeaderSize );
723 lpReply->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
724 lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY;
725 lpReply->envelope.wVersion = DPMSGVER_DP6;
727 lpReply->dpidNewPlayerId = DP_NextObjectId();
729 TRACE( "Allocating new playerid 0x%08lx from remote request\n",
730 lpReply->dpidNewPlayerId );
732 break;
735 case DPMSGCMD_GETNAMETABLEREPLY:
736 case DPMSGCMD_NEWPLAYERIDREPLY:
739 #if 0
740 if( wCommandId == DPMSGCMD_NEWPLAYERIDREPLY )
741 DebugBreak();
742 #endif
743 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
745 break;
748 #if 1
749 case DPMSGCMD_JUSTENVELOPE:
751 TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08lx\n", lpcMessageHeader, ((LPDWORD)lpcMessageHeader)[1] );
752 NS_SetLocalAddr( This->dp2->lpNameServerData, lpcMessageHeader, 20 );
753 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
755 #endif
757 case DPMSGCMD_FORWARDADDPLAYER:
759 #if 0
760 DebugBreak();
761 #endif
762 #if 1
763 TRACE( "Sending message to self to get my addr\n" );
764 DP_MSG_ToSelf( This, 1 ); /* This is a hack right now */
765 #endif
766 break;
769 case DPMSGCMD_FORWARDADDPLAYERNACK:
771 DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
772 break;
775 default:
777 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
778 DebugBreak();
779 break;
783 /* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */
785 return DP_OK;
789 static HRESULT WINAPI DP_IF_AddPlayerToGroup
790 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
791 DPID idPlayer, BOOL bAnsi )
793 lpGroupData lpGData;
794 lpPlayerList lpPList;
795 lpPlayerList lpNewPList;
797 TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
798 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
800 /* Find the group */
801 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
803 return DPERR_INVALIDGROUP;
806 /* Find the player */
807 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
809 return DPERR_INVALIDPLAYER;
812 /* Create a player list (ie "shortcut" ) */
813 lpNewPList = (lpPlayerList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
814 sizeof( *lpNewPList ) );
815 if( lpNewPList == NULL )
817 return DPERR_CANTADDPLAYER;
820 /* Add the shortcut */
821 lpPList->lpPData->uRef++;
822 lpNewPList->lpPData = lpPList->lpPData;
824 /* Add the player to the list of players for this group */
825 DPQ_INSERT(lpGData->players,lpNewPList,players);
827 /* Let the SP know that we've added a player to the group */
828 if( This->dp2->spData.lpCB->AddPlayerToGroup )
830 DPSP_ADDPLAYERTOGROUPDATA data;
832 TRACE( "Calling SP AddPlayerToGroup\n" );
834 data.idPlayer = idPlayer;
835 data.idGroup = idGroup;
836 data.lpISP = This->dp2->spData.lpISP;
838 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
841 /* Inform all other peers of the addition of player to the group. If there are
842 * no peers keep this event quiet.
843 * Also, if this event was the result of another machine sending it to us,
844 * don't bother rebroadcasting it.
846 if( ( lpMsgHdr == NULL ) &&
847 This->dp2->lpSessionDesc &&
848 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
850 DPMSG_ADDPLAYERTOGROUP msg;
851 msg.dwType = DPSYS_ADDPLAYERTOGROUP;
853 msg.dpIdGroup = idGroup;
854 msg.dpIdPlayer = idPlayer;
856 /* FIXME: Correct to just use send effectively? */
857 /* FIXME: Should size include data w/ message or just message "header" */
858 /* FIXME: Check return code */
859 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
862 return DP_OK;
865 static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
866 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
868 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
869 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, TRUE );
872 static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
873 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
875 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
876 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, FALSE );
879 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi )
881 HRESULT hr = DP_OK;
883 TRACE("(%p)->(%u)\n", This, bAnsi );
885 /* FIXME: Need to find a new host I assume (how?) */
886 /* FIXME: Need to destroy all local groups */
887 /* FIXME: Need to migrate all remotely visible players to the new host */
889 /* Invoke the SP callback to inform of session close */
890 if( This->dp2->spData.lpCB->CloseEx )
892 DPSP_CLOSEDATA data;
894 TRACE( "Calling SP CloseEx\n" );
896 data.lpISP = This->dp2->spData.lpISP;
898 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
901 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
903 TRACE( "Calling SP Close (obsolete interface)\n" );
905 hr = (*This->dp2->spData.lpCB->Close)();
908 return hr;
911 static HRESULT WINAPI DirectPlay2AImpl_Close
912 ( LPDIRECTPLAY2A iface )
914 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
915 return DP_IF_Close( This, TRUE );
918 static HRESULT WINAPI DirectPlay2WImpl_Close
919 ( LPDIRECTPLAY2 iface )
921 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
922 return DP_IF_Close( This, FALSE );
925 static
926 lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, LPDPID lpid,
927 LPDPNAME lpName, DWORD dwFlags,
928 DPID idParent, BOOL bAnsi )
930 lpGroupData lpGData;
932 /* Allocate the new space and add to end of high level group list */
933 lpGData = (lpGroupData) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
934 sizeof( *lpGData ) );
936 if( lpGData == NULL )
938 return NULL;
941 DPQ_INIT(lpGData->groups);
942 DPQ_INIT(lpGData->players);
944 /* Set the desired player ID - no sanity checking to see if it exists */
945 lpGData->dpid = *lpid;
947 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
949 /* FIXME: Should we check that the parent exists? */
950 lpGData->parent = idParent;
952 /* FIXME: Should we validate the dwFlags? */
953 lpGData->dwFlags = dwFlags;
955 TRACE( "Created group id 0x%08lx\n", *lpid );
957 return lpGData;
960 /* This method assumes that all links to it are already deleted */
961 static void
962 DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid )
964 lpGroupList lpGList;
966 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
968 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
970 if( lpGList == NULL )
972 ERR( "DPID 0x%08lx not found\n", dpid );
973 return;
976 if( --(lpGList->lpGData->uRef) )
978 FIXME( "Why is this not the last reference to group?\n" );
979 DebugBreak();
982 /* Delete player */
983 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
984 HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
986 /* Remove and Delete Player List object */
987 HeapFree( GetProcessHeap(), 0, lpGList );
991 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid )
993 lpGroupList lpGroups;
995 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
997 if( dpid == DPID_SYSTEM_GROUP )
999 return This->dp2->lpSysGroup;
1001 else
1003 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
1006 if( lpGroups == NULL )
1008 return NULL;
1011 return lpGroups->lpGData;
1014 static HRESULT WINAPI DP_IF_CreateGroup
1015 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
1016 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
1017 DWORD dwFlags, BOOL bAnsi )
1019 lpGroupData lpGData;
1021 TRACE( "(%p)->(%p,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
1022 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
1023 dwFlags, bAnsi );
1025 /* If the name is not specified, we must provide one */
1026 if( DPID_UNKNOWN == *lpidGroup )
1028 /* If we are the name server, we decide on the group ids. If not, we
1029 * must ask for one before attempting a creation.
1031 if( This->dp2->bHostInterface )
1033 *lpidGroup = DP_NextObjectId();
1035 else
1037 *lpidGroup = DP_GetRemoteNextObjectId();
1041 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
1042 DPID_NOPARENT_GROUP, bAnsi );
1044 if( lpGData == NULL )
1046 return DPERR_CANTADDPLAYER; /* yes player not group */
1049 if( DPID_SYSTEM_GROUP == *lpidGroup )
1051 This->dp2->lpSysGroup = lpGData;
1052 TRACE( "Inserting system group\n" );
1054 else
1056 /* Insert into the system group */
1057 lpGroupList lpGroup = (lpGroupList) HeapAlloc( GetProcessHeap(),
1058 HEAP_ZERO_MEMORY,
1059 sizeof( *lpGroup ) );
1060 lpGroup->lpGData = lpGData;
1062 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
1065 /* Something is now referencing this data */
1066 lpGData->uRef++;
1068 /* Set all the important stuff for the group */
1069 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
1071 /* FIXME: We should only create the system group if GetCaps returns
1072 * DPCAPS_GROUPOPTIMIZED.
1075 /* Let the SP know that we've created this group */
1076 if( This->dp2->spData.lpCB->CreateGroup )
1078 DPSP_CREATEGROUPDATA data;
1079 DWORD dwCreateFlags = 0;
1081 TRACE( "Calling SP CreateGroup\n" );
1083 if( *lpidGroup == DPID_NOPARENT_GROUP )
1084 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
1086 if( lpMsgHdr == NULL )
1087 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1089 if( dwFlags & DPGROUP_HIDDEN )
1090 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
1092 data.idGroup = *lpidGroup;
1093 data.dwFlags = dwCreateFlags;
1094 data.lpSPMessageHeader = lpMsgHdr;
1095 data.lpISP = This->dp2->spData.lpISP;
1097 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1100 /* Inform all other peers of the creation of a new group. If there are
1101 * no peers keep this event quiet.
1102 * Also if this message was sent to us, don't rebroadcast.
1104 if( ( lpMsgHdr == NULL ) &&
1105 This->dp2->lpSessionDesc &&
1106 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1108 DPMSG_CREATEPLAYERORGROUP msg;
1109 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1111 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1112 msg.dpId = *lpidGroup;
1113 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1114 msg.lpData = lpData;
1115 msg.dwDataSize = dwDataSize;
1116 msg.dpnName = *lpGroupName;
1117 msg.dpIdParent = DPID_NOPARENT_GROUP;
1118 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
1120 /* FIXME: Correct to just use send effectively? */
1121 /* FIXME: Should size include data w/ message or just message "header" */
1122 /* FIXME: Check return code */
1123 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
1124 0, 0, NULL, NULL, bAnsi );
1127 return DP_OK;
1130 static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
1131 ( LPDIRECTPLAY2A 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, TRUE );
1140 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
1141 ( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1142 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1144 *lpidGroup = DPID_UNKNOWN;
1146 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1147 lpGroupName, lpData, dwDataSize, dwFlags, FALSE );
1151 static void
1152 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
1153 LPVOID lpData, DWORD dwDataSize )
1155 /* Clear out the data with this player */
1156 if( ( dwFlags & DPSET_LOCAL ) &&
1157 ( lpGData->dwLocalDataSize != 0 )
1160 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
1161 lpGData->lpLocalData = NULL;
1162 lpGData->dwLocalDataSize = 0;
1164 if( ( dwFlags & DPSET_REMOTE ) &&
1165 ( lpGData->dwRemoteDataSize != 0 )
1168 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
1169 lpGData->lpRemoteData = NULL;
1170 lpGData->dwRemoteDataSize = 0;
1173 /* Reallocate for new data */
1174 if( lpData != NULL )
1176 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1177 sizeof( dwDataSize ) );
1178 CopyMemory( lpNewData, lpData, dwDataSize );
1180 if( dwFlags & DPSET_REMOTE )
1182 lpGData->lpRemoteData = lpNewData;
1183 lpGData->dwRemoteDataSize = dwDataSize;
1186 if( dwFlags & DPSET_LOCAL )
1188 lpGData->lpLocalData = lpData;
1189 lpGData->dwLocalDataSize = dwDataSize;
1195 /* This function will just create the storage for the new player. */
1196 static
1197 lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid,
1198 LPDPNAME lpName, DWORD dwFlags,
1199 HANDLE hEvent, BOOL bAnsi )
1201 lpPlayerData lpPData;
1203 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
1205 /* Allocate the storage for the player and associate it with list element */
1206 lpPData = (lpPlayerData) HeapAlloc( GetProcessHeap(),
1207 HEAP_ZERO_MEMORY,
1208 sizeof( *lpPData ) );
1209 if( lpPData == NULL )
1211 return NULL;
1214 /* Set the desired player ID */
1215 lpPData->dpid = *lpid;
1217 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
1219 lpPData->dwFlags = dwFlags;
1221 /* If we were given an event handle, duplicate it */
1222 if( hEvent != 0 )
1224 if( !DuplicateHandle( GetCurrentProcess(), hEvent,
1225 GetCurrentProcess(), &lpPData->hEvent,
1226 0, FALSE, DUPLICATE_SAME_ACCESS )
1229 /* FIXME: Memory leak */
1230 ERR( "Can't duplicate player msg handle %p\n", hEvent );
1234 /* Initialize the SP data section */
1235 lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData();
1237 TRACE( "Created player id 0x%08lx\n", *lpid );
1239 return lpPData;
1242 /* Delete the contents of the DPNAME struct */
1243 static void
1244 DP_DeleteDPNameStruct( LPDPNAME lpDPName )
1246 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u1.lpszShortNameA );
1247 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u2.lpszLongNameA );
1250 /* This method assumes that all links to it are already deleted */
1251 static void
1252 DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid )
1254 lpPlayerList lpPList;
1256 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
1258 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1260 if( lpPList == NULL )
1262 ERR( "DPID 0x%08lx not found\n", dpid );
1263 return;
1266 /* Verify that this is the last reference to the data */
1267 if( --(lpPList->lpPData->uRef) )
1269 FIXME( "Why is this not the last reference to player?\n" );
1270 DebugBreak();
1273 /* Delete player */
1274 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1276 CloseHandle( lpPList->lpPData->hEvent );
1277 HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
1279 /* Delete Player List object */
1280 HeapFree( GetProcessHeap(), 0, lpPList );
1283 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid )
1285 lpPlayerList lpPlayers;
1287 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
1289 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1291 return lpPlayers;
1294 /* Basic area for Dst must already be allocated */
1295 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi )
1297 if( lpSrc == NULL )
1299 ZeroMemory( lpDst, sizeof( *lpDst ) );
1300 lpDst->dwSize = sizeof( *lpDst );
1301 return TRUE;
1304 if( lpSrc->dwSize != sizeof( *lpSrc) )
1306 return FALSE;
1309 /* Delete any existing pointers */
1310 if( lpDst->u1.lpszShortNameA )
1312 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1315 if( lpDst->u2.lpszLongNameA )
1317 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1320 /* Copy as required */
1321 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1323 if( bAnsi )
1325 if( lpSrc->u1.lpszShortNameA )
1327 lpDst->u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), 0,
1328 strlen(lpSrc->u1.lpszShortNameA)+1 );
1329 strcpy( lpDst->u1.lpszShortNameA, lpSrc->u1.lpszShortNameA );
1331 if( lpSrc->u2.lpszLongNameA )
1333 lpDst->u2.lpszLongNameA = HeapAlloc( GetProcessHeap(), 0,
1334 strlen(lpSrc->u2.lpszLongNameA)+1 );
1335 strcpy( lpDst->u2.lpszLongNameA, lpSrc->u2.lpszLongNameA );
1338 else
1340 if( lpSrc->u1.lpszShortNameA )
1342 lpDst->u1.lpszShortName = HeapAlloc( GetProcessHeap(), 0,
1343 (strlenW(lpSrc->u1.lpszShortName)+1)*sizeof(WCHAR) );
1344 strcpyW( lpDst->u1.lpszShortName, lpSrc->u1.lpszShortName );
1346 if( lpSrc->u2.lpszLongNameA )
1348 lpDst->u2.lpszLongName = HeapAlloc( GetProcessHeap(), 0,
1349 (strlenW(lpSrc->u2.lpszLongName)+1)*sizeof(WCHAR) );
1350 strcpyW( lpDst->u2.lpszLongName, lpSrc->u2.lpszLongName );
1354 return TRUE;
1357 static void
1358 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
1359 LPVOID lpData, DWORD dwDataSize )
1361 /* Clear out the data with this player */
1362 if( ( dwFlags & DPSET_LOCAL ) &&
1363 ( lpPData->dwLocalDataSize != 0 )
1366 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
1367 lpPData->lpLocalData = NULL;
1368 lpPData->dwLocalDataSize = 0;
1370 if( ( dwFlags & DPSET_REMOTE ) &&
1371 ( lpPData->dwRemoteDataSize != 0 )
1374 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
1375 lpPData->lpRemoteData = NULL;
1376 lpPData->dwRemoteDataSize = 0;
1379 /* Reallocate for new data */
1380 if( lpData != NULL )
1382 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1383 sizeof( dwDataSize ) );
1384 CopyMemory( lpNewData, lpData, dwDataSize );
1386 if( dwFlags & DPSET_REMOTE )
1388 lpPData->lpRemoteData = lpNewData;
1389 lpPData->dwRemoteDataSize = dwDataSize;
1392 if( dwFlags & DPSET_LOCAL )
1394 lpPData->lpLocalData = lpData;
1395 lpPData->dwLocalDataSize = dwDataSize;
1401 static HRESULT WINAPI DP_IF_CreatePlayer
1402 ( IDirectPlay2Impl* This,
1403 LPVOID lpMsgHdr, /* NULL for local creation, non NULL for remote creation */
1404 LPDPID lpidPlayer,
1405 LPDPNAME lpPlayerName,
1406 HANDLE hEvent,
1407 LPVOID lpData,
1408 DWORD dwDataSize,
1409 DWORD dwFlags,
1410 BOOL bAnsi )
1412 HRESULT hr = DP_OK;
1413 lpPlayerData lpPData;
1414 lpPlayerList lpPList;
1415 DWORD dwCreateFlags = 0;
1417 TRACE( "(%p)->(%p,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
1418 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1419 dwDataSize, dwFlags, bAnsi );
1421 if( dwFlags == 0 )
1423 dwFlags = DPPLAYER_SPECTATOR;
1426 if( lpidPlayer == NULL )
1428 return DPERR_INVALIDPARAMS;
1432 /* Determine the creation flags for the player. These will be passed
1433 * to the name server if requesting a player id and to the SP when
1434 * informing it of the player creation
1437 if( dwFlags & DPPLAYER_SERVERPLAYER )
1439 if( *lpidPlayer == DPID_SERVERPLAYER )
1441 /* Server player for the host interface */
1442 dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
1444 else if( *lpidPlayer == DPID_NAME_SERVER )
1446 /* Name server - master of everything */
1447 dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
1449 else
1451 /* Server player for a non host interface */
1452 dwCreateFlags |= DPLAYI_PLAYER_SYSPLAYER;
1456 if( lpMsgHdr == NULL )
1457 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1460 /* Verify we know how to handle all the flags */
1461 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1462 ( dwFlags & DPPLAYER_SPECTATOR )
1466 /* Assume non fatal failure */
1467 ERR( "unknown dwFlags = 0x%08lx\n", dwFlags );
1470 /* If the name is not specified, we must provide one */
1471 if( *lpidPlayer == DPID_UNKNOWN )
1473 /* If we are the session master, we dish out the group/player ids */
1474 if( This->dp2->bHostInterface )
1476 *lpidPlayer = DP_NextObjectId();
1478 else
1480 hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer );
1482 if( FAILED(hr) )
1484 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1485 return hr;
1489 else
1491 /* FIXME: Would be nice to perhaps verify that we don't already have
1492 * this player.
1496 /* FIXME: Should we be storing these dwFlags or the creation ones? */
1497 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwFlags,
1498 hEvent, bAnsi );
1500 if( lpPData == NULL )
1502 return DPERR_CANTADDPLAYER;
1505 /* Create the list object and link it in */
1506 lpPList = (lpPlayerList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1507 sizeof( *lpPList ) );
1508 if( lpPList == NULL )
1510 FIXME( "Memory leak\n" );
1511 return DPERR_CANTADDPLAYER;
1514 lpPData->uRef = 1;
1515 lpPList->lpPData = lpPData;
1517 /* Add the player to the system group */
1518 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1520 /* Update the information and send it to all players in the session */
1521 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
1523 /* Let the SP know that we've created this player */
1524 if( This->dp2->spData.lpCB->CreatePlayer )
1526 DPSP_CREATEPLAYERDATA data;
1528 data.idPlayer = *lpidPlayer;
1529 data.dwFlags = dwCreateFlags;
1530 data.lpSPMessageHeader = lpMsgHdr;
1531 data.lpISP = This->dp2->spData.lpISP;
1533 TRACE( "Calling SP CreatePlayer 0x%08lx: dwFlags: 0x%08lx lpMsgHdr: %p\n",
1534 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
1536 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1539 if( FAILED(hr) )
1541 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1542 return hr;
1545 /* Now let the SP know that this player is a member of the system group */
1546 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1548 DPSP_ADDPLAYERTOGROUPDATA data;
1550 data.idPlayer = *lpidPlayer;
1551 data.idGroup = DPID_SYSTEM_GROUP;
1552 data.lpISP = This->dp2->spData.lpISP;
1554 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1556 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1559 if( FAILED(hr) )
1561 ERR( "Failed to add player to sys group with sp: %s\n",
1562 DPLAYX_HresultToString(hr) );
1563 return hr;
1566 #if 1
1567 if( This->dp2->bHostInterface == FALSE )
1569 /* Let the name server know about the creation of this player */
1570 /* FIXME: Is this only to be done for the creation of a server player or
1571 * is this used for regular players? If only for server players, move
1572 * this call to DP_SecureOpen(...);
1574 #if 0
1575 TRACE( "Sending message to self to get my addr\n" );
1576 DP_MSG_ToSelf( This, *lpidPlayer ); /* This is a hack right now */
1577 #endif
1579 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
1581 #else
1582 /* Inform all other peers of the creation of a new player. If there are
1583 * no peers keep this quiet.
1584 * Also, if this was a remote event, no need to rebroadcast it.
1586 if( ( lpMsgHdr == NULL ) &&
1587 This->dp2->lpSessionDesc &&
1588 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1590 DPMSG_CREATEPLAYERORGROUP msg;
1591 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1593 msg.dwPlayerType = DPPLAYERTYPE_PLAYER;
1594 msg.dpId = *lpidPlayer;
1595 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */
1596 msg.lpData = lpData;
1597 msg.dwDataSize = dwDataSize;
1598 msg.dpnName = *lpPlayerName;
1599 msg.dpIdParent = DPID_NOPARENT_GROUP;
1600 msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
1602 /* FIXME: Correct to just use send effectively? */
1603 /* FIXME: Should size include data w/ message or just message "header" */
1604 /* FIXME: Check return code */
1605 hr = DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
1606 sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
1608 #endif
1610 return hr;
1613 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
1614 ( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1615 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1617 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1619 if( dwFlags & DPPLAYER_SERVERPLAYER )
1621 *lpidPlayer = DPID_SERVERPLAYER;
1623 else
1625 *lpidPlayer = DPID_UNKNOWN;
1628 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1629 lpData, dwDataSize, dwFlags, TRUE );
1632 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
1633 ( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1634 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1636 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1638 if( dwFlags & DPPLAYER_SERVERPLAYER )
1640 *lpidPlayer = DPID_SERVERPLAYER;
1642 else
1644 *lpidPlayer = DPID_UNKNOWN;
1647 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1648 lpData, dwDataSize, dwFlags, FALSE );
1651 static DPID DP_GetRemoteNextObjectId(void)
1653 FIXME( ":stub\n" );
1655 /* Hack solution */
1656 return DP_NextObjectId();
1659 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
1660 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
1661 DPID idPlayer, BOOL bAnsi )
1663 HRESULT hr = DP_OK;
1665 lpGroupData lpGData;
1666 lpPlayerList lpPList;
1668 TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
1669 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
1671 /* Find the group */
1672 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1674 return DPERR_INVALIDGROUP;
1677 /* Find the player */
1678 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
1680 return DPERR_INVALIDPLAYER;
1683 /* Remove the player shortcut from the group */
1684 DPQ_REMOVE_ENTRY( lpGData->players, players, lpPData->dpid, ==, idPlayer, lpPList );
1686 if( lpPList == NULL )
1688 return DPERR_INVALIDPLAYER;
1691 /* One less reference */
1692 lpPList->lpPData->uRef--;
1694 /* Delete the Player List element */
1695 HeapFree( GetProcessHeap(), 0, lpPList );
1697 /* Inform the SP if they care */
1698 if( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1700 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1702 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1704 data.idPlayer = idPlayer;
1705 data.idGroup = idGroup;
1706 data.lpISP = This->dp2->spData.lpISP;
1708 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1711 /* Need to send a DELETEPLAYERFROMGROUP message */
1712 FIXME( "Need to send a message\n" );
1714 return hr;
1717 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
1718 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
1720 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1721 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, TRUE );
1724 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
1725 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
1727 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1728 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, FALSE );
1731 typedef struct _DPRGOPContext
1733 IDirectPlay3Impl* This;
1734 BOOL bAnsi;
1735 DPID idGroup;
1736 } DPRGOPContext, *lpDPRGOPContext;
1738 static BOOL CALLBACK
1739 cbRemoveGroupOrPlayer(
1740 DPID dpId,
1741 DWORD dwPlayerType,
1742 LPCDPNAME lpName,
1743 DWORD dwFlags,
1744 LPVOID lpContext )
1746 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1748 TRACE( "Removing element:0x%08lx (type:0x%08lx) from element:0x%08lx\n",
1749 dpId, dwPlayerType, lpCtxt->idGroup );
1751 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1753 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt->This, lpCtxt->idGroup,
1754 dpId )
1758 ERR( "Unable to delete group 0x%08lx from group 0x%08lx\n",
1759 dpId, lpCtxt->idGroup );
1762 else
1764 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl*)lpCtxt->This,
1765 NULL, lpCtxt->idGroup,
1766 dpId, lpCtxt->bAnsi )
1770 ERR( "Unable to delete player 0x%08lx from grp 0x%08lx\n",
1771 dpId, lpCtxt->idGroup );
1775 return TRUE; /* Continue enumeration */
1778 static HRESULT WINAPI DP_IF_DestroyGroup
1779 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi )
1781 lpGroupData lpGData;
1782 DPRGOPContext context;
1784 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
1785 This, lpMsgHdr, idGroup, bAnsi );
1787 /* Find the group */
1788 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1790 return DPERR_INVALIDPLAYER; /* yes player */
1793 context.This = (IDirectPlay3Impl*)This;
1794 context.bAnsi = bAnsi;
1795 context.idGroup = idGroup;
1797 /* Remove all players that this group has */
1798 DP_IF_EnumGroupPlayers( This, idGroup, NULL,
1799 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1801 /* Remove all links to groups that this group has since this is dp3 */
1802 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This, idGroup, NULL,
1803 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1805 /* Remove this group from the parent group - if it has one */
1806 if( ( idGroup != DPID_SYSTEM_GROUP ) &&
1807 ( lpGData->parent != DPID_SYSTEM_GROUP )
1810 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl*)This, lpGData->parent,
1811 idGroup );
1814 /* Now delete this group data and list from the system group */
1815 DP_DeleteGroup( This, idGroup );
1817 /* Let the SP know that we've destroyed this group */
1818 if( This->dp2->spData.lpCB->DeleteGroup )
1820 DPSP_DELETEGROUPDATA data;
1822 FIXME( "data.dwFlags is incorrect\n" );
1824 data.idGroup = idGroup;
1825 data.dwFlags = 0;
1826 data.lpISP = This->dp2->spData.lpISP;
1828 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1831 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1833 return DP_OK;
1836 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
1837 ( LPDIRECTPLAY2A iface, DPID idGroup )
1839 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1840 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
1843 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
1844 ( LPDIRECTPLAY2 iface, DPID idGroup )
1846 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1847 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
1850 typedef struct _DPFAGContext
1852 IDirectPlay2Impl* This;
1853 DPID idPlayer;
1854 BOOL bAnsi;
1855 } DPFAGContext, *lpDPFAGContext;
1857 static HRESULT WINAPI DP_IF_DestroyPlayer
1858 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi )
1860 DPFAGContext cbContext;
1862 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
1863 This, lpMsgHdr, idPlayer, bAnsi );
1865 if( This->dp2->connectionInitialized == NO_PROVIDER )
1867 return DPERR_UNINITIALIZED;
1870 if( DP_FindPlayer( This, idPlayer ) == NULL )
1872 return DPERR_INVALIDPLAYER;
1875 /* FIXME: If the player is remote, we must be the host to delete this */
1877 cbContext.This = This;
1878 cbContext.idPlayer = idPlayer;
1879 cbContext.bAnsi = bAnsi;
1881 /* Find each group and call DeletePlayerFromGroup if the player is a
1882 member of the group */
1883 DP_IF_EnumGroups( This, NULL, cbDeletePlayerFromAllGroups,
1884 (LPVOID)&cbContext, DPENUMGROUPS_ALL, bAnsi );
1886 /* Now delete player and player list from the sys group */
1887 DP_DeletePlayer( This, idPlayer );
1889 /* Let the SP know that we've destroyed this group */
1890 if( This->dp2->spData.lpCB->DeletePlayer )
1892 DPSP_DELETEPLAYERDATA data;
1894 FIXME( "data.dwFlags is incorrect\n" );
1896 data.idPlayer = idPlayer;
1897 data.dwFlags = 0;
1898 data.lpISP = This->dp2->spData.lpISP;
1900 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
1903 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
1905 return DP_OK;
1908 static BOOL CALLBACK
1909 cbDeletePlayerFromAllGroups(
1910 DPID dpId,
1911 DWORD dwPlayerType,
1912 LPCDPNAME lpName,
1913 DWORD dwFlags,
1914 LPVOID lpContext )
1916 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
1918 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1920 DP_IF_DeletePlayerFromGroup( lpCtxt->This, NULL, dpId, lpCtxt->idPlayer,
1921 lpCtxt->bAnsi );
1923 /* Enumerate all groups in this group since this will normally only
1924 * be called for top level groups
1926 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)lpCtxt->This,
1927 dpId, NULL,
1928 cbDeletePlayerFromAllGroups,
1929 (LPVOID)lpContext, DPENUMGROUPS_ALL,
1930 lpCtxt->bAnsi );
1933 else
1935 ERR( "Group callback has dwPlayerType = 0x%08lx\n", dwPlayerType );
1938 return TRUE;
1941 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
1942 ( LPDIRECTPLAY2A iface, DPID idPlayer )
1944 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1945 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
1948 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
1949 ( LPDIRECTPLAY2 iface, DPID idPlayer )
1951 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1952 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
1955 static HRESULT WINAPI DP_IF_EnumGroupPlayers
1956 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
1957 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1958 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1960 lpGroupData lpGData;
1961 lpPlayerList lpPList;
1963 FIXME("(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
1964 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
1965 lpContext, dwFlags, bAnsi );
1967 if( This->dp2->connectionInitialized == NO_PROVIDER )
1969 return DPERR_UNINITIALIZED;
1972 /* Find the group */
1973 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1975 return DPERR_INVALIDGROUP;
1978 if( DPQ_IS_EMPTY( lpGData->players ) )
1980 return DP_OK;
1983 lpPList = DPQ_FIRST( lpGData->players );
1985 /* Walk the players in this group */
1986 for( ;; )
1988 /* We do not enum the name server or app server as they are of no
1989 * concequence to the end user.
1991 if( ( lpPList->lpPData->dpid != DPID_NAME_SERVER ) &&
1992 ( lpPList->lpPData->dpid != DPID_SERVERPLAYER )
1996 /* FIXME: Need to add stuff for dwFlags checking */
1998 if( !lpEnumPlayersCallback2( lpPList->lpPData->dpid, DPPLAYERTYPE_PLAYER,
1999 &lpPList->lpPData->name,
2000 lpPList->lpPData->dwFlags,
2001 lpContext )
2004 /* User requested break */
2005 return DP_OK;
2009 if( DPQ_IS_ENDOFLIST( lpPList->players ) )
2011 break;
2014 lpPList = DPQ_NEXT( lpPList->players );
2017 return DP_OK;
2020 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
2021 ( LPDIRECTPLAY2A iface, DPID idGroup, LPGUID lpguidInstance,
2022 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2023 LPVOID lpContext, DWORD dwFlags )
2025 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2026 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2027 lpEnumPlayersCallback2, lpContext,
2028 dwFlags, TRUE );
2031 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
2032 ( LPDIRECTPLAY2 iface, DPID idGroup, LPGUID lpguidInstance,
2033 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2034 LPVOID lpContext, DWORD dwFlags )
2036 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2037 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2038 lpEnumPlayersCallback2, lpContext,
2039 dwFlags, FALSE );
2042 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2043 static HRESULT WINAPI DP_IF_EnumGroups
2044 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2045 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2046 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2048 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This,
2049 DPID_SYSTEM_GROUP, lpguidInstance,
2050 lpEnumPlayersCallback2, lpContext,
2051 dwFlags, bAnsi );
2054 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
2055 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2056 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2057 LPVOID lpContext, DWORD dwFlags )
2059 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2060 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2061 lpContext, dwFlags, TRUE );
2064 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
2065 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2066 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2067 LPVOID lpContext, DWORD dwFlags )
2069 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2070 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2071 lpContext, dwFlags, FALSE );
2074 static HRESULT WINAPI DP_IF_EnumPlayers
2075 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2076 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2077 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2079 return DP_IF_EnumGroupPlayers( This, DPID_SYSTEM_GROUP, lpguidInstance,
2080 lpEnumPlayersCallback2, lpContext,
2081 dwFlags, bAnsi );
2084 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
2085 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2086 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2087 LPVOID lpContext, DWORD dwFlags )
2089 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2090 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2091 lpContext, dwFlags, TRUE );
2094 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
2095 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2096 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2097 LPVOID lpContext, DWORD dwFlags )
2099 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2100 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2101 lpContext, dwFlags, FALSE );
2104 /* This function should call the registered callback function that the user
2105 passed into EnumSessions for each entry available.
2107 static void DP_InvokeEnumSessionCallbacks
2108 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2109 LPVOID lpNSInfo,
2110 DWORD dwTimeout,
2111 LPVOID lpContext )
2113 LPDPSESSIONDESC2 lpSessionDesc;
2115 FIXME( ": not checking for conditions\n" );
2117 /* Not sure if this should be pruning but it's convenient */
2118 NS_PruneSessionCache( lpNSInfo );
2120 NS_ResetSessionEnumeration( lpNSInfo );
2122 /* Enumerate all sessions */
2123 /* FIXME: Need to indicate ANSI */
2124 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2126 TRACE( "EnumSessionsCallback2 invoked\n" );
2127 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2129 return;
2133 /* Invoke one last time to indicate that there is no more to come */
2134 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2137 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2139 EnumSessionAsyncCallbackData* data = (EnumSessionAsyncCallbackData*)lpContext;
2140 HANDLE hSuicideRequest = data->hSuicideRequest;
2141 DWORD dwTimeout = data->dwTimeout;
2143 TRACE( "Thread started with timeout = 0x%08lx\n", dwTimeout );
2145 for( ;; )
2147 HRESULT hr;
2149 /* Sleep up to dwTimeout waiting for request to terminate thread */
2150 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2152 TRACE( "Thread terminating on terminate request\n" );
2153 break;
2156 /* Now resend the enum request */
2157 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2158 data->dwEnumSessionFlags,
2159 data->lpSpData );
2161 if( FAILED(hr) )
2163 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2164 /* FIXME: Should we kill this thread? How to inform the main thread? */
2169 TRACE( "Thread terminating\n" );
2171 /* Clean up the thread data */
2172 CloseHandle( hSuicideRequest );
2173 HeapFree( GetProcessHeap(), 0, lpContext );
2175 /* FIXME: Need to have some notification to main app thread that this is
2176 * dead. It would serve two purposes. 1) allow sync on termination
2177 * so that we don't actually send something to ourselves when we
2178 * become name server (race condition) and 2) so that if we die
2179 * abnormally something else will be able to tell.
2182 return 1;
2185 static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
2187 /* Does a thread exist? If so we were doing an async enum session */
2188 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2190 TRACE( "Killing EnumSession thread %p\n",
2191 This->dp2->hEnumSessionThread );
2193 /* Request that the thread kill itself nicely */
2194 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2195 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2197 /* We no longer need to know about the thread */
2198 CloseHandle( This->dp2->hEnumSessionThread );
2200 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2204 static HRESULT WINAPI DP_IF_EnumSessions
2205 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2206 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2207 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2209 HRESULT hr = DP_OK;
2211 TRACE( "(%p)->(%p,0x%08lx,%p,%p,0x%08lx,%u)\n",
2212 This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags,
2213 bAnsi );
2215 /* Can't enumerate if the interface is already open */
2216 if( This->dp2->bConnectionOpen )
2218 return DPERR_GENERIC;
2221 #if 1
2222 /* The loading of a lobby provider _seems_ to require a backdoor loading
2223 * of the service provider to also associate with this DP object. This is
2224 * because the app doesn't seem to have to call EnumConnections and
2225 * InitializeConnection for the SP before calling this method. As such
2226 * we'll do their dirty work for them with a quick hack so as to always
2227 * load the TCP/IP service provider.
2229 * The correct solution would seem to involve creating a dialog box which
2230 * contains the possible SPs. These dialog boxes most likely follow SDK
2231 * examples.
2233 if( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
2235 LPVOID lpConnection;
2236 DWORD dwSize;
2238 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2240 if( !DP_BuildSPCompoundAddr( (LPGUID)&DPSPGUID_TCPIP, &lpConnection, &dwSize ) )
2242 ERR( "Can't build compound addr\n" );
2243 return DPERR_GENERIC;
2246 hr = DP_IF_InitializeConnection( (IDirectPlay3Impl*)This, lpConnection,
2247 0, bAnsi );
2248 if( FAILED(hr) )
2250 return hr;
2253 /* Free up the address buffer */
2254 HeapFree( GetProcessHeap(), 0, lpConnection );
2256 /* The SP is now initialized */
2257 This->dp2->bSPInitialized = TRUE;
2259 #endif
2262 /* Use the service provider default? */
2263 if( dwTimeout == 0 )
2265 DPCAPS spCaps;
2266 spCaps.dwSize = sizeof( spCaps );
2268 DP_IF_GetCaps( This, &spCaps, 0 );
2269 dwTimeout = spCaps.dwTimeout;
2271 /* The service provider doesn't provide one either! */
2272 if( dwTimeout == 0 )
2274 /* Provide the TCP/IP default */
2275 dwTimeout = DPMSG_WAIT_5_SECS;
2279 if( dwFlags & DPENUMSESSIONS_STOPASYNC )
2281 DP_KillEnumSessionThread( This );
2282 return hr;
2285 /* FIXME: Interface locking sucks in this method */
2286 if( ( dwFlags & DPENUMSESSIONS_ASYNC ) )
2288 /* Enumerate everything presently in the local session cache */
2289 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2290 This->dp2->lpNameServerData, dwTimeout,
2291 lpContext );
2294 /* See if we've already created a thread to service this interface */
2295 if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2297 DWORD dwThreadId;
2299 /* Send the first enum request inline since the user may cancel a dialog
2300 * if one is presented. Also, may also have a connecting return code.
2302 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2303 dwFlags, &This->dp2->spData );
2305 if( !FAILED(hr) )
2307 EnumSessionAsyncCallbackData* lpData
2308 = (EnumSessionAsyncCallbackData*)HeapAlloc( GetProcessHeap(),
2309 HEAP_ZERO_MEMORY,
2310 sizeof( *lpData ) );
2311 /* FIXME: need to kill the thread on object deletion */
2312 lpData->lpSpData = &This->dp2->spData;
2314 CopyMemory( &lpData->requestGuid, &lpsd->guidApplication, sizeof(GUID) );
2315 lpData->dwEnumSessionFlags = dwFlags;
2316 lpData->dwTimeout = dwTimeout;
2318 This->dp2->hKillEnumSessionThreadEvent =
2319 CreateEventA( NULL, TRUE, FALSE, NULL );
2321 if( !DuplicateHandle( GetCurrentProcess(),
2322 This->dp2->hKillEnumSessionThreadEvent,
2323 GetCurrentProcess(),
2324 &lpData->hSuicideRequest,
2325 0, FALSE, DUPLICATE_SAME_ACCESS )
2328 ERR( "Can't duplicate thread killing handle\n" );
2331 TRACE( ": creating EnumSessionsRequest thread\n" );
2333 This->dp2->hEnumSessionThread = CreateThread( NULL,
2335 DP_EnumSessionsSendAsyncRequestThread,
2336 lpData,
2338 &dwThreadId );
2342 else
2344 /* Invalidate the session cache for the interface */
2345 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2347 /* Send the broadcast for session enumeration */
2348 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2349 dwFlags,
2350 &This->dp2->spData );
2353 SleepEx( dwTimeout, FALSE );
2355 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2356 This->dp2->lpNameServerData, dwTimeout,
2357 lpContext );
2360 return hr;
2363 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2364 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2365 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2366 LPVOID lpContext, DWORD dwFlags )
2368 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2369 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2370 lpContext, dwFlags, TRUE );
2373 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2374 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2375 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2376 LPVOID lpContext, DWORD dwFlags )
2378 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2379 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2380 lpContext, dwFlags, FALSE );
2383 static HRESULT WINAPI DP_IF_GetPlayerCaps
2384 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
2385 DWORD dwFlags )
2387 DPSP_GETCAPSDATA data;
2389 TRACE("(%p)->(0x%08lx,%p,0x%08lx)\n", This, idPlayer, lpDPCaps, dwFlags);
2391 /* Query the service provider */
2392 data.idPlayer = idPlayer;
2393 data.dwFlags = dwFlags;
2394 data.lpCaps = lpDPCaps;
2395 data.lpISP = This->dp2->spData.lpISP;
2397 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2400 static HRESULT WINAPI DP_IF_GetCaps
2401 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags )
2403 return DP_IF_GetPlayerCaps( This, DPID_ALLPLAYERS, lpDPCaps, dwFlags );
2406 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2407 ( LPDIRECTPLAY2A iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2409 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2410 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2413 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2414 ( LPDIRECTPLAY2 iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2416 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2417 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2420 static HRESULT WINAPI DP_IF_GetGroupData
2421 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2422 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2424 lpGroupData lpGData;
2425 DWORD dwRequiredBufferSize;
2426 LPVOID lpCopyDataFrom;
2428 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
2429 This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi );
2431 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2433 return DPERR_INVALIDGROUP;
2436 /* How much buffer is required? */
2437 if( dwFlags & DPSET_REMOTE )
2439 dwRequiredBufferSize = lpGData->dwRemoteDataSize;
2440 lpCopyDataFrom = lpGData->lpRemoteData;
2442 else if( dwFlags & DPSET_LOCAL )
2444 dwRequiredBufferSize = lpGData->dwLocalDataSize;
2445 lpCopyDataFrom = lpGData->lpLocalData;
2447 else
2449 ERR( "Neither local or remote data requested!?!\n" );
2450 dwRequiredBufferSize = 0;
2451 lpCopyDataFrom = NULL;
2454 /* Is the user requesting to know how big a buffer is required? */
2455 if( ( lpData == NULL ) ||
2456 ( *lpdwDataSize < dwRequiredBufferSize )
2459 *lpdwDataSize = dwRequiredBufferSize;
2460 return DPERR_BUFFERTOOSMALL;
2463 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2465 return DP_OK;
2468 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2469 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2470 LPDWORD lpdwDataSize, DWORD dwFlags )
2472 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2473 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2474 dwFlags, TRUE );
2477 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2478 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2479 LPDWORD lpdwDataSize, DWORD dwFlags )
2481 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2482 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2483 dwFlags, FALSE );
2486 static HRESULT WINAPI DP_IF_GetGroupName
2487 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2488 LPDWORD lpdwDataSize, BOOL bAnsi )
2490 lpGroupData lpGData;
2491 LPDPNAME lpName = (LPDPNAME)lpData;
2492 DWORD dwRequiredDataSize;
2494 FIXME("(%p)->(0x%08lx,%p,%p,%u) ANSI ignored\n",
2495 This, idGroup, lpData, lpdwDataSize, bAnsi );
2497 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2499 return DPERR_INVALIDGROUP;
2502 dwRequiredDataSize = lpGData->name.dwSize;
2504 if( lpGData->name.u1.lpszShortNameA )
2506 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
2509 if( lpGData->name.u2.lpszLongNameA )
2511 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
2514 if( ( lpData == NULL ) ||
2515 ( *lpdwDataSize < dwRequiredDataSize )
2518 *lpdwDataSize = dwRequiredDataSize;
2519 return DPERR_BUFFERTOOSMALL;
2522 /* Copy the structure */
2523 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2525 if( lpGData->name.u1.lpszShortNameA )
2527 strcpy( ((BYTE*)lpName)+lpGData->name.dwSize,
2528 lpGData->name.u1.lpszShortNameA );
2530 else
2532 lpName->u1.lpszShortNameA = NULL;
2535 if( lpGData->name.u1.lpszShortNameA )
2537 strcpy( ((BYTE*)lpName)+lpGData->name.dwSize,
2538 lpGData->name.u2.lpszLongNameA );
2540 else
2542 lpName->u2.lpszLongNameA = NULL;
2545 return DP_OK;
2548 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2549 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2550 LPDWORD lpdwDataSize )
2552 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2553 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2556 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2557 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2558 LPDWORD lpdwDataSize )
2560 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2561 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2564 static HRESULT WINAPI DP_IF_GetMessageCount
2565 ( IDirectPlay2Impl* This, DPID idPlayer,
2566 LPDWORD lpdwCount, BOOL bAnsi )
2568 FIXME("(%p)->(0x%08lx,%p,%u): stub\n", This, idPlayer, lpdwCount, bAnsi );
2569 return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer,
2570 DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL,
2571 bAnsi );
2574 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2575 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDWORD lpdwCount )
2577 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2578 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, TRUE );
2581 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2582 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDWORD lpdwCount )
2584 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2585 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, FALSE );
2588 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2589 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2591 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2592 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2593 return DP_OK;
2596 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2597 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2599 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2600 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2601 return DP_OK;
2604 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2605 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2606 DWORD dwFlags )
2608 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2609 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2612 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2613 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2614 DWORD dwFlags )
2616 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2617 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2620 static HRESULT WINAPI DP_IF_GetPlayerData
2621 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2622 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2624 lpPlayerList lpPList;
2625 DWORD dwRequiredBufferSize;
2626 LPVOID lpCopyDataFrom;
2628 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
2629 This, idPlayer, lpData, lpdwDataSize, dwFlags, bAnsi );
2631 if( This->dp2->connectionInitialized == NO_PROVIDER )
2633 return DPERR_UNINITIALIZED;
2636 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2638 return DPERR_INVALIDPLAYER;
2641 /* How much buffer is required? */
2642 if( dwFlags & DPSET_REMOTE )
2644 dwRequiredBufferSize = lpPList->lpPData->dwRemoteDataSize;
2645 lpCopyDataFrom = lpPList->lpPData->lpRemoteData;
2647 else if( dwFlags & DPSET_LOCAL )
2649 dwRequiredBufferSize = lpPList->lpPData->dwLocalDataSize;
2650 lpCopyDataFrom = lpPList->lpPData->lpLocalData;
2652 else
2654 ERR( "Neither local or remote data requested!?!\n" );
2655 dwRequiredBufferSize = 0;
2656 lpCopyDataFrom = NULL;
2659 /* Is the user requesting to know how big a buffer is required? */
2660 if( ( lpData == NULL ) ||
2661 ( *lpdwDataSize < dwRequiredBufferSize )
2664 *lpdwDataSize = dwRequiredBufferSize;
2665 return DPERR_BUFFERTOOSMALL;
2668 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2670 return DP_OK;
2673 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2674 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2675 LPDWORD lpdwDataSize, DWORD dwFlags )
2677 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2678 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2679 dwFlags, TRUE );
2682 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2683 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2684 LPDWORD lpdwDataSize, DWORD dwFlags )
2686 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2687 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2688 dwFlags, FALSE );
2691 static HRESULT WINAPI DP_IF_GetPlayerName
2692 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2693 LPDWORD lpdwDataSize, BOOL bAnsi )
2695 lpPlayerList lpPList;
2696 LPDPNAME lpName = (LPDPNAME)lpData;
2697 DWORD dwRequiredDataSize;
2699 FIXME( "(%p)->(0x%08lx,%p,%p,%u): ANSI \n",
2700 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2702 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2704 return DPERR_INVALIDPLAYER;
2707 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
2709 if( lpPList->lpPData->name.u1.lpszShortNameA )
2711 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
2714 if( lpPList->lpPData->name.u2.lpszLongNameA )
2716 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
2719 if( ( lpData == NULL ) ||
2720 ( *lpdwDataSize < dwRequiredDataSize )
2723 *lpdwDataSize = dwRequiredDataSize;
2724 return DPERR_BUFFERTOOSMALL;
2727 /* Copy the structure */
2728 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
2730 if( lpPList->lpPData->name.u1.lpszShortNameA )
2732 strcpy( ((BYTE*)lpName)+lpPList->lpPData->name.dwSize,
2733 lpPList->lpPData->name.u1.lpszShortNameA );
2735 else
2737 lpName->u1.lpszShortNameA = NULL;
2740 if( lpPList->lpPData->name.u1.lpszShortNameA )
2742 strcpy( ((BYTE*)lpName)+lpPList->lpPData->name.dwSize,
2743 lpPList->lpPData->name.u2.lpszLongNameA );
2745 else
2747 lpName->u2.lpszLongNameA = NULL;
2750 return DP_OK;
2753 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2754 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2755 LPDWORD lpdwDataSize )
2757 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2758 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
2761 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2762 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2763 LPDWORD lpdwDataSize )
2765 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2766 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
2769 static HRESULT WINAPI DP_GetSessionDesc
2770 ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize,
2771 BOOL bAnsi )
2773 DWORD dwRequiredSize;
2775 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
2777 if( This->dp2->connectionInitialized == NO_PROVIDER )
2779 return DPERR_UNINITIALIZED;
2782 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
2784 return DPERR_INVALIDPARAMS;
2787 /* FIXME: Get from This->dp2->lpSessionDesc */
2788 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
2790 if ( ( lpData == NULL ) ||
2791 ( *lpdwDataSize < dwRequiredSize )
2794 *lpdwDataSize = dwRequiredSize;
2795 return DPERR_BUFFERTOOSMALL;
2798 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
2800 return DP_OK;
2803 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
2804 ( LPDIRECTPLAY2A iface, LPVOID lpData, LPDWORD lpdwDataSize )
2806 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2807 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2810 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
2811 ( LPDIRECTPLAY2 iface, LPVOID lpData, LPDWORD lpdwDataSize )
2813 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2814 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2817 /* Intended only for COM compatibility. Always returns an error. */
2818 static HRESULT WINAPI DirectPlay2AImpl_Initialize
2819 ( LPDIRECTPLAY2A iface, LPGUID lpGUID )
2821 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2822 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2823 return DPERR_ALREADYINITIALIZED;
2826 /* Intended only for COM compatibility. Always returns an error. */
2827 static HRESULT WINAPI DirectPlay2WImpl_Initialize
2828 ( LPDIRECTPLAY2 iface, LPGUID lpGUID )
2830 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2831 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2832 return DPERR_ALREADYINITIALIZED;
2836 static HRESULT WINAPI DP_SecureOpen
2837 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
2838 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
2839 BOOL bAnsi )
2841 HRESULT hr = DP_OK;
2843 FIXME( "(%p)->(%p,0x%08lx,%p,%p): partial stub\n",
2844 This, lpsd, dwFlags, lpSecurity, lpCredentials );
2846 if( This->dp2->bConnectionOpen )
2848 TRACE( ": rejecting already open connection.\n" );
2849 return DPERR_ALREADYINITIALIZED;
2852 /* If we're enumerating, kill the thread */
2853 DP_KillEnumSessionThread( This );
2855 if( dwFlags & DPOPEN_CREATE )
2857 /* Rightoo - this computer is the host and the local computer needs to be
2858 the name server so that others can join this session */
2859 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
2861 This->dp2->bHostInterface = TRUE;
2863 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
2864 if( FAILED( hr ) )
2866 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
2867 return hr;
2871 /* Invoke the conditional callback for the service provider */
2872 if( This->dp2->spData.lpCB->Open )
2874 DPSP_OPENDATA data;
2876 FIXME( "Not all data fields are correct. Need new parameter\n" );
2878 data.bCreate = (dwFlags & DPOPEN_CREATE ) ? TRUE : FALSE;
2879 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
2880 : NS_GetNSAddr( This->dp2->lpNameServerData );
2881 data.lpISP = This->dp2->spData.lpISP;
2882 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) ? TRUE : FALSE;
2883 data.dwOpenFlags = dwFlags;
2884 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
2886 hr = (*This->dp2->spData.lpCB->Open)(&data);
2887 if( FAILED( hr ) )
2889 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
2890 return hr;
2895 /* Create the system group of which everything is a part of */
2896 DPID systemGroup = DPID_SYSTEM_GROUP;
2898 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
2899 NULL, 0, 0, TRUE );
2903 if( dwFlags & DPOPEN_JOIN )
2905 DPID dpidServerId = DPID_UNKNOWN;
2907 /* Create the server player for this interface. This way we can receive
2908 * messages for this session.
2910 /* FIXME: I suppose that we should be setting an event for a receive
2911 * type of thing. That way the messaging thread could know to wake
2912 * up. DPlay would then trigger the hEvent for the player the
2913 * message is directed to.
2915 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
2917 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
2920 else if( dwFlags & DPOPEN_CREATE )
2922 DPID dpidNameServerId = DPID_NAME_SERVER;
2924 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
2925 0, DPPLAYER_SERVERPLAYER, bAnsi );
2928 if( FAILED(hr) )
2930 ERR( "Couldn't create name server/system player: %s\n",
2931 DPLAYX_HresultToString(hr) );
2934 return hr;
2937 static HRESULT WINAPI DirectPlay2AImpl_Open
2938 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2940 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2941 TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags );
2942 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, TRUE );
2945 static HRESULT WINAPI DirectPlay2WImpl_Open
2946 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2948 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2949 TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags );
2950 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, FALSE );
2953 static HRESULT WINAPI DP_IF_Receive
2954 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
2955 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi )
2957 LPDPMSG lpMsg = NULL;
2959 FIXME( "(%p)->(%p,%p,0x%08lx,%p,%p,%u): stub\n",
2960 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
2962 if( This->dp2->connectionInitialized == NO_PROVIDER )
2964 return DPERR_UNINITIALIZED;
2967 if( dwFlags == 0 )
2969 dwFlags = DPRECEIVE_ALL;
2972 /* If the lpData is NULL, we must be peeking the message */
2973 if( ( lpData == NULL ) &&
2974 !( dwFlags & DPRECEIVE_PEEK )
2977 return DPERR_INVALIDPARAMS;
2980 if( dwFlags & DPRECEIVE_ALL )
2982 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
2984 if( !( dwFlags & DPRECEIVE_PEEK ) )
2986 FIXME( "Remove from queue\n" );
2989 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
2990 ( dwFlags & DPRECEIVE_FROMPLAYER )
2993 FIXME( "Find matching message 0x%08lx\n", dwFlags );
2995 else
2997 ERR( "Hmmm..dwFlags 0x%08lx\n", dwFlags );
3000 if( lpMsg == NULL )
3002 return DPERR_NOMESSAGES;
3005 /* Copy into the provided buffer */
3006 CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
3008 return DP_OK;
3011 static HRESULT WINAPI DirectPlay2AImpl_Receive
3012 ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo,
3013 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
3015 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3016 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
3017 lpData, lpdwDataSize, TRUE );
3020 static HRESULT WINAPI DirectPlay2WImpl_Receive
3021 ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo,
3022 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
3024 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3025 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
3026 lpData, lpdwDataSize, FALSE );
3029 static HRESULT WINAPI DirectPlay2AImpl_Send
3030 ( LPDIRECTPLAY2A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3032 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3033 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3034 0, 0, NULL, NULL, TRUE );
3037 static HRESULT WINAPI DirectPlay2WImpl_Send
3038 ( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3040 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3041 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3042 0, 0, NULL, NULL, FALSE );
3045 static HRESULT WINAPI DP_IF_SetGroupData
3046 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
3047 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3049 lpGroupData lpGData;
3051 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
3052 This, idGroup, lpData, dwDataSize, dwFlags, bAnsi );
3054 /* Parameter check */
3055 if( ( lpData == NULL ) &&
3056 ( dwDataSize != 0 )
3059 return DPERR_INVALIDPARAMS;
3062 /* Find the pointer to the data for this player */
3063 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3065 return DPERR_INVALIDOBJECT;
3068 if( dwFlags & DPSET_REMOTE )
3070 FIXME( "Was this group created by this interface?\n" );
3071 /* FIXME: If this is a remote update need to allow it but not
3072 * send a message.
3076 DP_SetGroupData( lpGData, dwFlags, lpData, dwDataSize );
3078 /* FIXME: Only send a message if this group is local to the session otherwise
3079 * it will have been rejected above
3081 if( dwFlags & DPSET_REMOTE )
3083 FIXME( "Send msg?\n" );
3086 return DP_OK;
3089 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
3090 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
3091 DWORD dwDataSize, DWORD dwFlags )
3093 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3094 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, TRUE );
3097 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
3098 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
3099 DWORD dwDataSize, DWORD dwFlags )
3101 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3102 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, FALSE );
3105 static HRESULT WINAPI DP_IF_SetGroupName
3106 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
3107 DWORD dwFlags, BOOL bAnsi )
3109 lpGroupData lpGData;
3111 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n", This, idGroup,
3112 lpGroupName, dwFlags, bAnsi );
3114 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3116 return DPERR_INVALIDGROUP;
3119 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
3121 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3122 FIXME( "Message not sent and dwFlags ignored\n" );
3124 return DP_OK;
3127 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
3128 ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName,
3129 DWORD dwFlags )
3131 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3132 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
3135 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
3136 ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName,
3137 DWORD dwFlags )
3139 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3140 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
3143 static HRESULT WINAPI DP_IF_SetPlayerData
3144 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
3145 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3147 lpPlayerList lpPList;
3149 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
3150 This, idPlayer, lpData, dwDataSize, dwFlags, bAnsi );
3152 /* Parameter check */
3153 if( ( lpData == NULL ) &&
3154 ( dwDataSize != 0 )
3157 return DPERR_INVALIDPARAMS;
3160 /* Find the pointer to the data for this player */
3161 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3163 return DPERR_INVALIDPLAYER;
3166 if( dwFlags & DPSET_REMOTE )
3168 FIXME( "Was this group created by this interface?\n" );
3169 /* FIXME: If this is a remote update need to allow it but not
3170 * send a message.
3174 DP_SetPlayerData( lpPList->lpPData, dwFlags, lpData, dwDataSize );
3176 if( dwFlags & DPSET_REMOTE )
3178 FIXME( "Send msg?\n" );
3181 return DP_OK;
3184 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3185 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
3186 DWORD dwDataSize, DWORD dwFlags )
3188 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3189 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3190 dwFlags, TRUE );
3193 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3194 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
3195 DWORD dwDataSize, DWORD dwFlags )
3197 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3198 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3199 dwFlags, FALSE );
3202 static HRESULT WINAPI DP_IF_SetPlayerName
3203 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
3204 DWORD dwFlags, BOOL bAnsi )
3206 lpPlayerList lpPList;
3208 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n",
3209 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3211 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3213 return DPERR_INVALIDGROUP;
3216 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3218 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3219 FIXME( "Message not sent and dwFlags ignored\n" );
3221 return DP_OK;
3224 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3225 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName,
3226 DWORD dwFlags )
3228 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3229 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3232 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3233 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName,
3234 DWORD dwFlags )
3236 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3237 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3240 static HRESULT WINAPI DP_SetSessionDesc
3241 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
3242 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3244 DWORD dwRequiredSize;
3245 LPDPSESSIONDESC2 lpTempSessDesc;
3247 TRACE( "(%p)->(%p,0x%08lx,%u,%u)\n",
3248 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3250 if( This->dp2->connectionInitialized == NO_PROVIDER )
3252 return DPERR_UNINITIALIZED;
3255 if( dwFlags )
3257 return DPERR_INVALIDPARAMS;
3260 /* Only the host is allowed to update the session desc */
3261 if( !This->dp2->bHostInterface )
3263 return DPERR_ACCESSDENIED;
3266 /* FIXME: Copy into This->dp2->lpSessionDesc */
3267 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3268 lpTempSessDesc = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
3269 HEAP_ZERO_MEMORY,
3270 dwRequiredSize );
3272 if( lpTempSessDesc == NULL )
3274 return DPERR_OUTOFMEMORY;
3277 /* Free the old */
3278 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3280 This->dp2->lpSessionDesc = lpTempSessDesc;
3282 /* Set the new */
3283 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3285 /* If this is an external invocation of the interface, we should be
3286 * letting everyone know that things have changed. Otherwise this is
3287 * just an initialization and it doesn't need to be propagated.
3289 if( !bInitial )
3291 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3294 return DP_OK;
3297 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3298 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3300 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3301 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3304 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3305 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3307 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3308 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3311 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3312 DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3314 DWORD dwSize = 0;
3316 if( lpSessDesc == NULL )
3318 /* Hmmm..don't need any size? */
3319 ERR( "NULL lpSessDesc\n" );
3320 return dwSize;
3323 dwSize += sizeof( *lpSessDesc );
3325 if( bAnsi )
3327 if( lpSessDesc->u1.lpszSessionNameA )
3329 dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1;
3332 if( lpSessDesc->u2.lpszPasswordA )
3334 dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1;
3337 else /* UNICODE */
3339 if( lpSessDesc->u1.lpszSessionName )
3341 dwSize += sizeof( WCHAR ) *
3342 ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 );
3345 if( lpSessDesc->u2.lpszPassword )
3347 dwSize += sizeof( WCHAR ) *
3348 ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 );
3352 return dwSize;
3355 /* Assumes that contugous buffers are already allocated. */
3356 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3357 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3359 BYTE* lpStartOfFreeSpace;
3361 if( lpSessionDest == NULL )
3363 ERR( "NULL lpSessionDest\n" );
3364 return;
3367 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3369 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3371 if( bAnsi )
3373 if( lpSessionSrc->u1.lpszSessionNameA )
3375 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3376 lpSessionDest->u1.lpszSessionNameA );
3377 lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3378 lpStartOfFreeSpace +=
3379 lstrlenA( (LPSTR)lpSessionDest->u1.lpszSessionNameA ) + 1;
3382 if( lpSessionSrc->u2.lpszPasswordA )
3384 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3385 lpSessionDest->u2.lpszPasswordA );
3386 lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3387 lpStartOfFreeSpace +=
3388 lstrlenA( (LPSTR)lpSessionDest->u2.lpszPasswordA ) + 1;
3391 else /* UNICODE */
3393 if( lpSessionSrc->u1.lpszSessionName )
3395 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3396 lpSessionDest->u1.lpszSessionName );
3397 lpSessionDest->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3398 lpStartOfFreeSpace += sizeof(WCHAR) *
3399 ( lstrlenW( (LPWSTR)lpSessionDest->u1.lpszSessionName ) + 1 );
3402 if( lpSessionSrc->u2.lpszPassword )
3404 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3405 lpSessionDest->u2.lpszPassword );
3406 lpSessionDest->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3407 lpStartOfFreeSpace += sizeof(WCHAR) *
3408 ( lstrlenW( (LPWSTR)lpSessionDest->u2.lpszPassword ) + 1 );
3414 static HRESULT WINAPI DP_IF_AddGroupToGroup
3415 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3417 lpGroupData lpGParentData;
3418 lpGroupData lpGData;
3419 lpGroupList lpNewGList;
3421 TRACE( "(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup );
3423 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3425 return DPERR_INVALIDGROUP;
3428 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3430 return DPERR_INVALIDGROUP;
3433 /* Create a player list (ie "shortcut" ) */
3434 lpNewGList = (lpGroupList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3435 sizeof( *lpNewGList ) );
3436 if( lpNewGList == NULL )
3438 return DPERR_CANTADDPLAYER;
3441 /* Add the shortcut */
3442 lpGData->uRef++;
3443 lpNewGList->lpGData = lpGData;
3445 /* Add the player to the list of players for this group */
3446 DPQ_INSERT( lpGData->groups, lpNewGList, groups );
3448 /* Send a ADDGROUPTOGROUP message */
3449 FIXME( "Not sending message\n" );
3451 return DP_OK;
3454 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3455 ( LPDIRECTPLAY3A iface, DPID idParentGroup, DPID idGroup )
3457 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3458 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3461 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3462 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3464 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3465 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3468 static HRESULT WINAPI DP_IF_CreateGroupInGroup
3469 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
3470 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
3471 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3473 lpGroupData lpGParentData;
3474 lpGroupList lpGList;
3475 lpGroupData lpGData;
3477 TRACE( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
3478 This, idParentGroup, lpidGroup, lpGroupName, lpData,
3479 dwDataSize, dwFlags, bAnsi );
3481 /* Verify that the specified parent is valid */
3482 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This,
3483 idParentGroup ) ) == NULL
3486 return DPERR_INVALIDGROUP;
3489 lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName,
3490 dwFlags, idParentGroup, bAnsi );
3492 if( lpGData == NULL )
3494 return DPERR_CANTADDPLAYER; /* yes player not group */
3497 /* Something else is referencing this data */
3498 lpGData->uRef++;
3500 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
3502 /* The list has now been inserted into the interface group list. We now
3503 need to put a "shortcut" to this group in the parent group */
3504 lpGList = (lpGroupList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3505 sizeof( *lpGList ) );
3506 if( lpGList == NULL )
3508 FIXME( "Memory leak\n" );
3509 return DPERR_CANTADDPLAYER; /* yes player not group */
3512 lpGList->lpGData = lpGData;
3514 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
3516 /* Let the SP know that we've created this group */
3517 if( This->dp2->spData.lpCB->CreateGroup )
3519 DPSP_CREATEGROUPDATA data;
3521 TRACE( "Calling SP CreateGroup\n" );
3523 data.idGroup = *lpidGroup;
3524 data.dwFlags = dwFlags;
3525 data.lpSPMessageHeader = lpMsgHdr;
3526 data.lpISP = This->dp2->spData.lpISP;
3528 (*This->dp2->spData.lpCB->CreateGroup)( &data );
3531 /* Inform all other peers of the creation of a new group. If there are
3532 * no peers keep this quiet.
3534 if( This->dp2->lpSessionDesc &&
3535 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
3537 DPMSG_CREATEPLAYERORGROUP msg;
3539 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
3540 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
3541 msg.dpId = *lpidGroup;
3542 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
3543 msg.lpData = lpData;
3544 msg.dwDataSize = dwDataSize;
3545 msg.dpnName = *lpGroupName;
3547 /* FIXME: Correct to just use send effectively? */
3548 /* FIXME: Should size include data w/ message or just message "header" */
3549 /* FIXME: Check return code */
3550 DP_SendEx( (IDirectPlay2Impl*)This,
3551 DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
3552 0, 0, NULL, NULL, bAnsi );
3555 return DP_OK;
3558 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3559 ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup,
3560 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3561 DWORD dwFlags )
3563 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3565 *lpidGroup = DPID_UNKNOWN;
3567 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3568 lpGroupName, lpData, dwDataSize, dwFlags,
3569 TRUE );
3572 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3573 ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup,
3574 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3575 DWORD dwFlags )
3577 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3579 *lpidGroup = DPID_UNKNOWN;
3581 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3582 lpGroupName, lpData, dwDataSize,
3583 dwFlags, FALSE );
3586 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
3587 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3589 lpGroupList lpGList;
3590 lpGroupData lpGParentData;
3592 TRACE("(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup );
3594 /* Is the parent group valid? */
3595 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3597 return DPERR_INVALIDGROUP;
3600 /* Remove the group from the parent group queue */
3601 DPQ_REMOVE_ENTRY( lpGParentData->groups, groups, lpGData->dpid, ==, idGroup, lpGList );
3603 if( lpGList == NULL )
3605 return DPERR_INVALIDGROUP;
3608 /* Decrement the ref count */
3609 lpGList->lpGData->uRef--;
3611 /* Free up the list item */
3612 HeapFree( GetProcessHeap(), 0, lpGList );
3614 /* Should send a DELETEGROUPFROMGROUP message */
3615 FIXME( "message not sent\n" );
3617 return DP_OK;
3620 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3621 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3623 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3624 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3627 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3628 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3630 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3631 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3634 static
3635 BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
3636 LPDWORD lpdwBufSize )
3638 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3639 HRESULT hr;
3641 dpCompoundAddress.dwDataSize = sizeof( GUID );
3642 memcpy( &dpCompoundAddress.guidDataType, &DPAID_ServiceProvider,
3643 sizeof( GUID ) ) ;
3644 dpCompoundAddress.lpData = lpcSpGuid;
3646 *lplpAddrBuf = NULL;
3647 *lpdwBufSize = 0;
3649 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3650 lpdwBufSize, TRUE );
3652 if( hr != DPERR_BUFFERTOOSMALL )
3654 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3655 return FALSE;
3658 /* Now allocate the buffer */
3659 *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3660 *lpdwBufSize );
3662 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3663 lpdwBufSize, TRUE );
3664 if( FAILED(hr) )
3666 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3667 return FALSE;
3670 return TRUE;
3673 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
3674 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3676 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3677 TRACE("(%p)->(%p,%p,%p,0x%08lx)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3679 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
3680 if( dwFlags == 0 )
3682 dwFlags = DPCONNECTION_DIRECTPLAY;
3685 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
3686 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) )
3689 return DPERR_INVALIDFLAGS;
3692 if( !lpEnumCallback || !*lpEnumCallback )
3694 return DPERR_INVALIDPARAMS;
3697 /* Enumerate DirectPlay service providers */
3698 if( dwFlags & DPCONNECTION_DIRECTPLAY )
3700 HKEY hkResult;
3701 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3702 LPCSTR guidDataSubKey = "Guid";
3703 char subKeyName[51];
3704 DWORD dwIndex, sizeOfSubKeyName=50;
3705 FILETIME filetime;
3707 /* Need to loop over the service providers in the registry */
3708 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3709 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3711 /* Hmmm. Does this mean that there are no service providers? */
3712 ERR(": no service providers?\n");
3713 return DP_OK;
3717 /* Traverse all the service providers we have available */
3718 for( dwIndex=0;
3719 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3720 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3721 ++dwIndex, sizeOfSubKeyName=51 )
3724 HKEY hkServiceProvider;
3725 GUID serviceProviderGUID;
3726 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3727 char returnBuffer[51];
3728 WCHAR buff[51];
3729 DPNAME dpName;
3730 BOOL bBuildPass;
3732 LPVOID lpAddressBuffer = NULL;
3733 DWORD dwAddressBufferSize = 0;
3735 TRACE(" this time through: %s\n", subKeyName );
3737 /* Get a handle for this particular service provider */
3738 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3739 &hkServiceProvider ) != ERROR_SUCCESS )
3741 ERR(": what the heck is going on?\n" );
3742 continue;
3745 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3746 NULL, &returnTypeGUID, returnBuffer,
3747 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3749 ERR(": missing GUID registry data members\n" );
3750 continue;
3753 /* FIXME: Check return types to ensure we're interpreting data right */
3754 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3755 CLSIDFromString( buff, &serviceProviderGUID );
3756 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3758 /* Fill in the DPNAME struct for the service provider */
3759 dpName.dwSize = sizeof( dpName );
3760 dpName.dwFlags = 0;
3761 dpName.u1.lpszShortNameA = subKeyName;
3762 dpName.u2.lpszLongNameA = NULL;
3764 /* Create the compound address for the service provider.
3765 * NOTE: This is a gruesome architectural scar right now. DP
3766 * uses DPL and DPL uses DP. Nasty stuff. This may be why the
3767 * native dll just gets around this little bit by allocating an
3768 * 80 byte buffer which isn't even filled with a valid compound
3769 * address. Oh well. Creating a proper compound address is the
3770 * way to go anyways despite this method taking slightly more
3771 * heap space and realtime :) */
3773 bBuildPass = DP_BuildSPCompoundAddr( &serviceProviderGUID,
3774 &lpAddressBuffer,
3775 &dwAddressBufferSize );
3776 if( !bBuildPass )
3778 ERR( "Can't build compound addr\n" );
3779 return DPERR_GENERIC;
3782 /* The enumeration will return FALSE if we are not to continue */
3783 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3784 &dpName, DPCONNECTION_DIRECTPLAY, lpContext ) )
3786 return DP_OK;
3791 /* Enumerate DirectPlayLobby service providers */
3792 if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY )
3794 HKEY hkResult;
3795 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3796 LPCSTR guidDataSubKey = "Guid";
3797 char subKeyName[51];
3798 DWORD dwIndex, sizeOfSubKeyName=50;
3799 FILETIME filetime;
3801 /* Need to loop over the service providers in the registry */
3802 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3803 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3805 /* Hmmm. Does this mean that there are no service providers? */
3806 ERR(": no service providers?\n");
3807 return DP_OK;
3811 /* Traverse all the lobby providers we have available */
3812 for( dwIndex=0;
3813 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3814 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3815 ++dwIndex, sizeOfSubKeyName=51 )
3818 HKEY hkServiceProvider;
3819 GUID serviceProviderGUID;
3820 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3821 char returnBuffer[51];
3822 WCHAR buff[51];
3823 DPNAME dpName;
3824 HRESULT hr;
3826 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3827 LPVOID lpAddressBuffer = NULL;
3828 DWORD dwAddressBufferSize = 0;
3830 TRACE(" this time through: %s\n", subKeyName );
3832 /* Get a handle for this particular service provider */
3833 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3834 &hkServiceProvider ) != ERROR_SUCCESS )
3836 ERR(": what the heck is going on?\n" );
3837 continue;
3840 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3841 NULL, &returnTypeGUID, returnBuffer,
3842 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3844 ERR(": missing GUID registry data members\n" );
3845 continue;
3848 /* FIXME: Check return types to ensure we're interpreting data right */
3849 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3850 CLSIDFromString( buff, &serviceProviderGUID );
3851 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3853 /* Fill in the DPNAME struct for the service provider */
3854 dpName.dwSize = sizeof( dpName );
3855 dpName.dwFlags = 0;
3856 dpName.u1.lpszShortNameA = subKeyName;
3857 dpName.u2.lpszLongNameA = NULL;
3859 /* Create the compound address for the service provider.
3860 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
3861 nast stuff. This may be why the native dll just gets around this little bit by
3862 allocating an 80 byte buffer which isn't even a filled with a valid compound
3863 address. Oh well. Creating a proper compound address is the way to go anyways
3864 despite this method taking slightly more heap space and realtime :) */
3866 dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
3867 dpCompoundAddress.dwDataSize = sizeof( GUID );
3868 dpCompoundAddress.lpData = &serviceProviderGUID;
3870 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3871 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
3873 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3874 return hr;
3877 /* Now allocate the buffer */
3878 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
3880 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3881 &dwAddressBufferSize, TRUE ) ) != DP_OK )
3883 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3884 return hr;
3887 /* The enumeration will return FALSE if we are not to continue */
3888 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3889 &dpName, DPCONNECTION_DIRECTPLAYLOBBY, lpContext ) )
3891 return DP_OK;
3896 return DP_OK;
3899 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
3900 ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3902 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3903 FIXME("(%p)->(%p,%p,%p,0x%08lx): stub\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3904 return DP_OK;
3907 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
3908 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
3909 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
3910 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
3912 lpGroupList lpGList;
3913 lpGroupData lpGData;
3915 FIXME( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
3916 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
3917 lpContext, dwFlags, bAnsi );
3919 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3921 return DPERR_INVALIDGROUP;
3924 if( DPQ_IS_EMPTY( lpGData->groups ) )
3926 return DP_OK;
3929 lpGList = DPQ_FIRST( lpGData->groups );
3931 for( ;; )
3933 /* FIXME: Should check dwFlags for match here */
3935 if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP,
3936 &lpGList->lpGData->name, dwFlags,
3937 lpContext ) )
3939 return DP_OK; /* User requested break */
3942 if( DPQ_IS_ENDOFLIST( lpGList->groups ) )
3944 break;
3947 lpGList = DPQ_NEXT( lpGList->groups );
3951 return DP_OK;
3954 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
3955 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3956 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3957 DWORD dwFlags )
3959 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3960 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3961 lpEnumPlayersCallback2, lpContext, dwFlags,
3962 TRUE );
3965 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
3966 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3967 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3968 DWORD dwFlags )
3970 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3971 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3972 lpEnumPlayersCallback2, lpContext, dwFlags,
3973 FALSE );
3976 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
3977 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3979 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3980 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3981 return DP_OK;
3984 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
3985 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3987 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3988 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3989 return DP_OK;
3992 BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
3993 REFGUID guidDataType,
3994 DWORD dwDataSize,
3995 LPCVOID lpData,
3996 LPVOID lpContext )
3998 /* Looking for the GUID of the provider to load */
3999 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
4000 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
4003 TRACE( "Found SP/LP (%s) %s (data size = 0x%08lx)\n",
4004 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
4006 if( dwDataSize != sizeof( GUID ) )
4008 ERR( "Invalid sp/lp guid size 0x%08lx\n", dwDataSize );
4011 memcpy( lpContext, lpData, dwDataSize );
4013 /* There shouldn't be more than 1 GUID/compound address */
4014 return FALSE;
4017 /* Still waiting for what we want */
4018 return TRUE;
4022 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
4023 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
4025 UINT i;
4026 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4027 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
4028 LPCSTR guidDataSubKey = "Guid";
4029 LPCSTR majVerDataSubKey = "dwReserved1";
4030 LPCSTR minVerDataSubKey = "dwReserved2";
4031 LPCSTR pathSubKey = "Path";
4033 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
4035 /* FIXME: Cloned code with a quick hack. */
4036 for( i=0; i<2; i++ )
4038 HKEY hkResult;
4039 LPCSTR searchSubKey;
4040 char subKeyName[51];
4041 DWORD dwIndex, sizeOfSubKeyName=50;
4042 FILETIME filetime;
4044 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
4045 *lpbIsDpSp = (i == 0) ? TRUE : FALSE;
4048 /* Need to loop over the service providers in the registry */
4049 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4050 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4052 /* Hmmm. Does this mean that there are no service providers? */
4053 ERR(": no service providers?\n");
4054 return 0;
4057 /* Traverse all the service providers we have available */
4058 for( dwIndex=0;
4059 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4060 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4061 ++dwIndex, sizeOfSubKeyName=51 )
4064 HKEY hkServiceProvider;
4065 GUID serviceProviderGUID;
4066 DWORD returnType, sizeOfReturnBuffer = 255;
4067 char returnBuffer[256];
4068 WCHAR buff[51];
4069 DWORD dwTemp, len;
4071 TRACE(" this time through: %s\n", subKeyName );
4073 /* Get a handle for this particular service provider */
4074 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4075 &hkServiceProvider ) != ERROR_SUCCESS )
4077 ERR(": what the heck is going on?\n" );
4078 continue;
4081 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4082 NULL, &returnType, returnBuffer,
4083 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4085 ERR(": missing GUID registry data members\n" );
4086 continue;
4089 /* FIXME: Check return types to ensure we're interpreting data right */
4090 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4091 CLSIDFromString( buff, &serviceProviderGUID );
4092 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4094 /* Determine if this is the Service Provider that the user asked for */
4095 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
4097 continue;
4100 if( i == 0 ) /* DP SP */
4102 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
4103 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
4104 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
4107 sizeOfReturnBuffer = 255;
4109 /* Get dwReserved1 */
4110 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
4111 NULL, &returnType, returnBuffer,
4112 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4114 ERR(": missing dwReserved1 registry data members\n") ;
4115 continue;
4118 if( i == 0 )
4119 memcpy( &lpSpData->dwReserved1, returnBuffer, sizeof(lpSpData->dwReserved1) );
4121 sizeOfReturnBuffer = 255;
4123 /* Get dwReserved2 */
4124 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4125 NULL, &returnType, returnBuffer,
4126 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4128 ERR(": missing dwReserved1 registry data members\n") ;
4129 continue;
4132 if( i == 0 )
4133 memcpy( &lpSpData->dwReserved2, returnBuffer, sizeof(lpSpData->dwReserved2) );
4135 sizeOfReturnBuffer = 255;
4137 /* Get the path for this service provider */
4138 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
4139 NULL, NULL, returnBuffer,
4140 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
4142 ERR(": missing PATH registry data members: 0x%08lx\n", dwTemp );
4143 continue;
4146 TRACE( "Loading %s\n", returnBuffer );
4147 return LoadLibraryA( returnBuffer );
4151 return 0;
4154 static
4155 HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider )
4157 HRESULT hr;
4158 LPDPSP_SPINIT SPInit;
4160 /* Initialize the service provider by calling SPInit */
4161 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4163 if( SPInit == NULL )
4165 ERR( "Service provider doesn't provide SPInit interface?\n" );
4166 FreeLibrary( hServiceProvider );
4167 return DPERR_UNAVAILABLE;
4170 TRACE( "Calling SPInit (DP SP entry point)\n" );
4172 hr = (*SPInit)( &This->dp2->spData );
4174 if( FAILED(hr) )
4176 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4177 FreeLibrary( hServiceProvider );
4178 return hr;
4181 /* FIXME: Need to verify the sanity of the returned callback table
4182 * using IsBadCodePtr */
4183 This->dp2->bSPInitialized = TRUE;
4185 /* This interface is now initialized as a DP object */
4186 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
4188 /* Store the handle of the module so that we can unload it later */
4189 This->dp2->hServiceProvider = hServiceProvider;
4191 return hr;
4194 static
4195 HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hLobbyProvider )
4197 HRESULT hr;
4198 LPSP_INIT DPLSPInit;
4200 /* Initialize the service provider by calling SPInit */
4201 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
4203 if( DPLSPInit == NULL )
4205 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4206 FreeLibrary( hLobbyProvider );
4207 return DPERR_UNAVAILABLE;
4210 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4212 hr = (*DPLSPInit)( &This->dp2->dplspData );
4214 if( FAILED(hr) )
4216 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4217 FreeLibrary( hLobbyProvider );
4218 return hr;
4221 /* FIXME: Need to verify the sanity of the returned callback table
4222 * using IsBadCodePtr */
4224 This->dp2->bDPLSPInitialized = TRUE;
4226 /* This interface is now initialized as a lobby object */
4227 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
4229 /* Store the handle of the module so that we can unload it later */
4230 This->dp2->hDPLobbyProvider = hLobbyProvider;
4232 return hr;
4235 static HRESULT WINAPI DP_IF_InitializeConnection
4236 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi )
4238 HMODULE hServiceProvider;
4239 HRESULT hr;
4240 GUID guidSP;
4241 const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
4242 BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4244 TRACE("(%p)->(%p,0x%08lx,%u)\n", This, lpConnection, dwFlags, bAnsi );
4246 if( dwFlags != 0 )
4248 return DPERR_INVALIDFLAGS;
4251 /* Find out what the requested SP is and how large this buffer is */
4252 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
4253 dwAddrSize, &guidSP );
4255 if( FAILED(hr) )
4257 ERR( "Invalid compound address?\n" );
4258 return DPERR_UNAVAILABLE;
4261 /* Load the service provider */
4262 hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp );
4264 if( hServiceProvider == 0 )
4266 ERR( "Unable to load service provider\n" );
4267 return DPERR_UNAVAILABLE;
4270 if( bIsDpSp )
4272 /* Fill in what we can of the Service Provider required information.
4273 * The rest was be done in DP_LoadSP
4275 This->dp2->spData.lpAddress = lpConnection;
4276 This->dp2->spData.dwAddressSize = dwAddrSize;
4277 This->dp2->spData.lpGuid = &guidSP;
4279 hr = DP_InitializeDPSP( This, hServiceProvider );
4281 else
4283 This->dp2->dplspData.lpAddress = lpConnection;
4285 hr = DP_InitializeDPLSP( This, hServiceProvider );
4288 if( FAILED(hr) )
4290 return hr;
4293 return DP_OK;
4296 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4297 ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
4299 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4301 /* This may not be externally invoked once either an SP or LP is initialized */
4302 if( This->dp2->connectionInitialized != NO_PROVIDER )
4304 return DPERR_ALREADYINITIALIZED;
4307 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE );
4310 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4311 ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
4313 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4315 /* This may not be externally invoked once either an SP or LP is initialized */
4316 if( This->dp2->connectionInitialized != NO_PROVIDER )
4318 return DPERR_ALREADYINITIALIZED;
4321 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE );
4324 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4325 ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4326 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4328 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4329 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4332 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4333 ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4334 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4336 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4337 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4340 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4341 ( LPDIRECTPLAY3A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4343 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4344 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4345 return DP_OK;
4348 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4349 ( LPDIRECTPLAY3 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4351 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4352 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4353 return DP_OK;
4356 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4357 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4359 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4360 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4361 return DP_OK;
4364 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4365 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4367 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4368 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4369 return DP_OK;
4372 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4373 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup )
4375 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4376 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
4377 return DP_OK;
4380 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4381 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup )
4383 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4384 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
4385 return DP_OK;
4388 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4389 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDWORD lpdwFlags )
4391 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4392 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
4393 return DP_OK;
4396 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4397 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDWORD lpdwFlags )
4399 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4400 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
4401 return DP_OK;
4404 static HRESULT WINAPI DP_IF_GetGroupParent
4405 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
4406 BOOL bAnsi )
4408 lpGroupData lpGData;
4410 TRACE("(%p)->(0x%08lx,%p,%u)\n", This, idGroup, lpidGroup, bAnsi );
4412 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4414 return DPERR_INVALIDGROUP;
4417 *lpidGroup = lpGData->dpid;
4419 return DP_OK;
4422 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4423 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
4425 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4426 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE );
4428 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4429 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
4431 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4432 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE );
4435 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4436 ( LPDIRECTPLAY3A iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4438 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4439 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4440 return DP_OK;
4443 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4444 ( LPDIRECTPLAY3 iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4446 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4447 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4448 return DP_OK;
4451 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4452 ( LPDIRECTPLAY3A iface, DPID idPlayer, LPDWORD lpdwFlags )
4454 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4455 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
4456 return DP_OK;
4459 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4460 ( LPDIRECTPLAY3 iface, DPID idPlayer, LPDWORD lpdwFlags )
4462 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4463 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
4464 return DP_OK;
4467 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4468 ( LPDIRECTPLAY4A iface, DPID idGroup, LPDPID lpidGroupOwner )
4470 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4471 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
4472 return DP_OK;
4475 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4476 ( LPDIRECTPLAY4 iface, DPID idGroup, LPDPID lpidGroupOwner )
4478 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4479 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
4480 return DP_OK;
4483 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4484 ( LPDIRECTPLAY4A iface, DPID idGroup , DPID idGroupOwner )
4486 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4487 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
4488 return DP_OK;
4491 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4492 ( LPDIRECTPLAY4 iface, DPID idGroup , DPID idGroupOwner )
4494 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4495 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
4496 return DP_OK;
4499 static HRESULT WINAPI DP_SendEx
4500 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4501 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4502 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi )
4504 lpPlayerList lpPList;
4505 lpGroupData lpGData;
4506 BOOL bValidDestination = FALSE;
4508 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx,0x%08lx,0x%08lx,%p,%p,%u)"
4509 ": stub\n",
4510 This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority,
4511 dwTimeout, lpContext, lpdwMsgID, bAnsi );
4513 /* FIXME: Add parameter checking */
4514 /* FIXME: First call to this needs to aquire a message id which will be
4515 * used for multiple sends
4518 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4520 /* Verify that the message is being sent from a valid local player. The
4521 * from player may be anonymous DPID_UNKNOWN
4523 if( idFrom != DPID_UNKNOWN )
4525 if( ( lpPList = DP_FindPlayer( This, idFrom ) ) == NULL )
4527 WARN( "INFO: Invalid from player 0x%08lx\n", idFrom );
4528 return DPERR_INVALIDPLAYER;
4532 /* Verify that the message is being sent to a valid player, group or to
4533 * everyone. If it's valid, send it to those players.
4535 if( idTo == DPID_ALLPLAYERS )
4537 bValidDestination = TRUE;
4539 /* See if SP has the ability to multicast. If so, use it */
4540 if( This->dp2->spData.lpCB->SendToGroupEx )
4542 FIXME( "Use group sendex to group 0\n" );
4544 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4546 FIXME( "Use obsolete group send to group 0\n" );
4548 else /* No multicast, multiplicate */
4550 /* Send to all players we know about */
4551 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4555 if( ( !bValidDestination ) &&
4556 ( DP_FindPlayer( This, idTo ) != NULL )
4559 bValidDestination = TRUE;
4561 /* Have the service provider send this message */
4562 /* FIXME: Could optimize for local interface sends */
4563 return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority,
4564 dwTimeout, lpContext, lpdwMsgID );
4567 if( ( !bValidDestination ) &&
4568 ( ( lpGData = DP_FindAnyGroup( This, idTo ) ) != NULL )
4571 bValidDestination = TRUE;
4573 /* See if SP has the ability to multicast. If so, use it */
4574 if( This->dp2->spData.lpCB->SendToGroupEx )
4576 FIXME( "Use group sendex\n" );
4578 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4580 FIXME( "Use obsolete group send to group\n" );
4582 else /* No multicast, multiplicate */
4584 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4587 #if 0
4588 if( bExpectReply )
4590 DWORD dwWaitReturn;
4592 This->dp2->hReplyEvent = CreateEventA( NULL, FALSE, FALSE, NULL );
4594 dwWaitReturn = WaitForSingleObject( hReplyEvent, dwTimeout );
4595 if( dwWaitReturn != WAIT_OBJECT_0 )
4597 ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
4600 #endif
4603 if( !bValidDestination )
4605 return DPERR_INVALIDPLAYER;
4607 else
4609 /* FIXME: Should return what the send returned */
4610 return DP_OK;
4615 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4616 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4617 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4618 LPVOID lpContext, LPDWORD lpdwMsgID )
4620 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4621 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4622 dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE );
4625 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4626 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4627 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4628 LPVOID lpContext, LPDWORD lpdwMsgID )
4630 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4631 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4632 dwPriority, dwTimeout, lpContext, lpdwMsgID, FALSE );
4635 static HRESULT WINAPI DP_SP_SendEx
4636 ( IDirectPlay2Impl* This, DWORD dwFlags,
4637 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4638 LPVOID lpContext, LPDWORD lpdwMsgID )
4640 LPDPMSG lpMElem;
4642 FIXME( ": stub\n" );
4644 /* FIXME: This queuing should only be for async messages */
4646 lpMElem = (LPDPMSG)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4647 sizeof( *lpMElem ) );
4648 lpMElem->msg = (DPMSG_GENERIC*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4649 dwDataSize );
4651 CopyMemory( lpMElem->msg, lpData, dwDataSize );
4653 /* FIXME: Need to queue based on priority */
4654 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
4656 return DP_OK;
4659 static HRESULT WINAPI DP_IF_GetMessageQueue
4660 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4661 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi )
4663 HRESULT hr = DP_OK;
4665 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,%p,%u): semi stub\n",
4666 This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi );
4668 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4669 /* FIXME: What about sends which are not immediate? */
4671 if( This->dp2->spData.lpCB->GetMessageQueue )
4673 DPSP_GETMESSAGEQUEUEDATA data;
4675 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4677 /* FIXME: None of this is documented :( */
4679 data.lpISP = This->dp2->spData.lpISP;
4680 data.dwFlags = dwFlags;
4681 data.idFrom = idFrom;
4682 data.idTo = idTo;
4683 data.lpdwNumMsgs = lpdwNumMsgs;
4684 data.lpdwNumBytes = lpdwNumBytes;
4686 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
4688 else
4690 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4693 return hr;
4696 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4697 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4698 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4700 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4701 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4702 lpdwNumBytes, TRUE );
4705 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4706 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4707 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4709 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4710 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4711 lpdwNumBytes, FALSE );
4714 static HRESULT WINAPI DP_IF_CancelMessage
4715 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
4716 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi )
4718 HRESULT hr = DP_OK;
4720 FIXME( "(%p)->(0x%08lx,0x%08lx,%u): semi stub\n",
4721 This, dwMsgID, dwFlags, bAnsi );
4723 if( This->dp2->spData.lpCB->Cancel )
4725 DPSP_CANCELDATA data;
4727 TRACE( "Calling SP Cancel\n" );
4729 /* FIXME: Undocumented callback */
4731 data.lpISP = This->dp2->spData.lpISP;
4732 data.dwFlags = dwFlags;
4733 data.lprglpvSPMsgID = NULL;
4734 data.cSPMsgID = dwMsgID;
4735 data.dwMinPriority = dwMinPriority;
4736 data.dwMaxPriority = dwMaxPriority;
4738 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
4740 else
4742 FIXME( "SP doesn't implement Cancel\n" );
4745 return hr;
4748 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
4749 ( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags )
4751 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4753 if( dwFlags != 0 )
4755 return DPERR_INVALIDFLAGS;
4758 if( dwMsgID == 0 )
4760 dwFlags |= DPCANCELSEND_ALL;
4763 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE );
4766 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
4767 ( LPDIRECTPLAY4 iface, DWORD dwMsgID, DWORD dwFlags )
4769 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4771 if( dwFlags != 0 )
4773 return DPERR_INVALIDFLAGS;
4776 if( dwMsgID == 0 )
4778 dwFlags |= DPCANCELSEND_ALL;
4781 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, FALSE );
4784 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
4785 ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4786 DWORD dwFlags )
4788 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4790 if( dwFlags != 0 )
4792 return DPERR_INVALIDFLAGS;
4795 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4796 dwMaxPriority, TRUE );
4799 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
4800 ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4801 DWORD dwFlags )
4803 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4805 if( dwFlags != 0 )
4807 return DPERR_INVALIDFLAGS;
4810 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4811 dwMaxPriority, FALSE );
4814 /* Note: Hack so we can reuse the old functions without compiler warnings */
4815 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4816 # define XCAST(fun) (typeof(directPlay2WVT.fun))
4817 #else
4818 # define XCAST(fun) (void*)
4819 #endif
4821 static IDirectPlay2Vtbl directPlay2WVT =
4823 XCAST(QueryInterface)DP_QueryInterface,
4824 XCAST(AddRef)DP_AddRef,
4825 XCAST(Release)DP_Release,
4827 DirectPlay2WImpl_AddPlayerToGroup,
4828 DirectPlay2WImpl_Close,
4829 DirectPlay2WImpl_CreateGroup,
4830 DirectPlay2WImpl_CreatePlayer,
4831 DirectPlay2WImpl_DeletePlayerFromGroup,
4832 DirectPlay2WImpl_DestroyGroup,
4833 DirectPlay2WImpl_DestroyPlayer,
4834 DirectPlay2WImpl_EnumGroupPlayers,
4835 DirectPlay2WImpl_EnumGroups,
4836 DirectPlay2WImpl_EnumPlayers,
4837 DirectPlay2WImpl_EnumSessions,
4838 DirectPlay2WImpl_GetCaps,
4839 DirectPlay2WImpl_GetGroupData,
4840 DirectPlay2WImpl_GetGroupName,
4841 DirectPlay2WImpl_GetMessageCount,
4842 DirectPlay2WImpl_GetPlayerAddress,
4843 DirectPlay2WImpl_GetPlayerCaps,
4844 DirectPlay2WImpl_GetPlayerData,
4845 DirectPlay2WImpl_GetPlayerName,
4846 DirectPlay2WImpl_GetSessionDesc,
4847 DirectPlay2WImpl_Initialize,
4848 DirectPlay2WImpl_Open,
4849 DirectPlay2WImpl_Receive,
4850 DirectPlay2WImpl_Send,
4851 DirectPlay2WImpl_SetGroupData,
4852 DirectPlay2WImpl_SetGroupName,
4853 DirectPlay2WImpl_SetPlayerData,
4854 DirectPlay2WImpl_SetPlayerName,
4855 DirectPlay2WImpl_SetSessionDesc
4857 #undef XCAST
4859 /* Note: Hack so we can reuse the old functions without compiler warnings */
4860 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4861 # define XCAST(fun) (typeof(directPlay2AVT.fun))
4862 #else
4863 # define XCAST(fun) (void*)
4864 #endif
4866 static IDirectPlay2Vtbl directPlay2AVT =
4868 XCAST(QueryInterface)DP_QueryInterface,
4869 XCAST(AddRef)DP_AddRef,
4870 XCAST(Release)DP_Release,
4872 DirectPlay2AImpl_AddPlayerToGroup,
4873 DirectPlay2AImpl_Close,
4874 DirectPlay2AImpl_CreateGroup,
4875 DirectPlay2AImpl_CreatePlayer,
4876 DirectPlay2AImpl_DeletePlayerFromGroup,
4877 DirectPlay2AImpl_DestroyGroup,
4878 DirectPlay2AImpl_DestroyPlayer,
4879 DirectPlay2AImpl_EnumGroupPlayers,
4880 DirectPlay2AImpl_EnumGroups,
4881 DirectPlay2AImpl_EnumPlayers,
4882 DirectPlay2AImpl_EnumSessions,
4883 DirectPlay2AImpl_GetCaps,
4884 DirectPlay2AImpl_GetGroupData,
4885 DirectPlay2AImpl_GetGroupName,
4886 DirectPlay2AImpl_GetMessageCount,
4887 DirectPlay2AImpl_GetPlayerAddress,
4888 DirectPlay2AImpl_GetPlayerCaps,
4889 DirectPlay2AImpl_GetPlayerData,
4890 DirectPlay2AImpl_GetPlayerName,
4891 DirectPlay2AImpl_GetSessionDesc,
4892 DirectPlay2AImpl_Initialize,
4893 DirectPlay2AImpl_Open,
4894 DirectPlay2AImpl_Receive,
4895 DirectPlay2AImpl_Send,
4896 DirectPlay2AImpl_SetGroupData,
4897 DirectPlay2AImpl_SetGroupName,
4898 DirectPlay2AImpl_SetPlayerData,
4899 DirectPlay2AImpl_SetPlayerName,
4900 DirectPlay2AImpl_SetSessionDesc
4902 #undef XCAST
4905 /* Note: Hack so we can reuse the old functions without compiler warnings */
4906 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4907 # define XCAST(fun) (typeof(directPlay3AVT.fun))
4908 #else
4909 # define XCAST(fun) (void*)
4910 #endif
4912 static IDirectPlay3Vtbl directPlay3AVT =
4914 XCAST(QueryInterface)DP_QueryInterface,
4915 XCAST(AddRef)DP_AddRef,
4916 XCAST(Release)DP_Release,
4918 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
4919 XCAST(Close)DirectPlay2AImpl_Close,
4920 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
4921 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
4922 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
4923 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
4924 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
4925 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
4926 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
4927 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
4928 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
4929 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
4930 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
4931 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
4932 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
4933 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
4934 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
4935 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
4936 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
4937 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
4938 XCAST(Initialize)DirectPlay2AImpl_Initialize,
4939 XCAST(Open)DirectPlay2AImpl_Open,
4940 XCAST(Receive)DirectPlay2AImpl_Receive,
4941 XCAST(Send)DirectPlay2AImpl_Send,
4942 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
4943 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
4944 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
4945 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
4946 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
4948 DirectPlay3AImpl_AddGroupToGroup,
4949 DirectPlay3AImpl_CreateGroupInGroup,
4950 DirectPlay3AImpl_DeleteGroupFromGroup,
4951 DirectPlay3AImpl_EnumConnections,
4952 DirectPlay3AImpl_EnumGroupsInGroup,
4953 DirectPlay3AImpl_GetGroupConnectionSettings,
4954 DirectPlay3AImpl_InitializeConnection,
4955 DirectPlay3AImpl_SecureOpen,
4956 DirectPlay3AImpl_SendChatMessage,
4957 DirectPlay3AImpl_SetGroupConnectionSettings,
4958 DirectPlay3AImpl_StartSession,
4959 DirectPlay3AImpl_GetGroupFlags,
4960 DirectPlay3AImpl_GetGroupParent,
4961 DirectPlay3AImpl_GetPlayerAccount,
4962 DirectPlay3AImpl_GetPlayerFlags
4964 #undef XCAST
4966 /* Note: Hack so we can reuse the old functions without compiler warnings */
4967 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4968 # define XCAST(fun) (typeof(directPlay3WVT.fun))
4969 #else
4970 # define XCAST(fun) (void*)
4971 #endif
4972 static IDirectPlay3Vtbl directPlay3WVT =
4974 XCAST(QueryInterface)DP_QueryInterface,
4975 XCAST(AddRef)DP_AddRef,
4976 XCAST(Release)DP_Release,
4978 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
4979 XCAST(Close)DirectPlay2WImpl_Close,
4980 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
4981 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
4982 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
4983 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
4984 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
4985 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
4986 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
4987 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
4988 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
4989 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
4990 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
4991 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
4992 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
4993 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
4994 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
4995 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
4996 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
4997 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
4998 XCAST(Initialize)DirectPlay2WImpl_Initialize,
4999 XCAST(Open)DirectPlay2WImpl_Open,
5000 XCAST(Receive)DirectPlay2WImpl_Receive,
5001 XCAST(Send)DirectPlay2WImpl_Send,
5002 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5003 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5004 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5005 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5006 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5008 DirectPlay3WImpl_AddGroupToGroup,
5009 DirectPlay3WImpl_CreateGroupInGroup,
5010 DirectPlay3WImpl_DeleteGroupFromGroup,
5011 DirectPlay3WImpl_EnumConnections,
5012 DirectPlay3WImpl_EnumGroupsInGroup,
5013 DirectPlay3WImpl_GetGroupConnectionSettings,
5014 DirectPlay3WImpl_InitializeConnection,
5015 DirectPlay3WImpl_SecureOpen,
5016 DirectPlay3WImpl_SendChatMessage,
5017 DirectPlay3WImpl_SetGroupConnectionSettings,
5018 DirectPlay3WImpl_StartSession,
5019 DirectPlay3WImpl_GetGroupFlags,
5020 DirectPlay3WImpl_GetGroupParent,
5021 DirectPlay3WImpl_GetPlayerAccount,
5022 DirectPlay3WImpl_GetPlayerFlags
5024 #undef XCAST
5026 /* Note: Hack so we can reuse the old functions without compiler warnings */
5027 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5028 # define XCAST(fun) (typeof(directPlay4WVT.fun))
5029 #else
5030 # define XCAST(fun) (void*)
5031 #endif
5032 static IDirectPlay4Vtbl directPlay4WVT =
5034 XCAST(QueryInterface)DP_QueryInterface,
5035 XCAST(AddRef)DP_AddRef,
5036 XCAST(Release)DP_Release,
5038 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
5039 XCAST(Close)DirectPlay2WImpl_Close,
5040 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
5041 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
5042 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
5043 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
5044 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5045 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5046 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5047 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5048 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5049 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5050 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5051 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5052 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5053 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5054 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5055 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5056 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5057 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5058 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5059 XCAST(Open)DirectPlay2WImpl_Open,
5060 XCAST(Receive)DirectPlay2WImpl_Receive,
5061 XCAST(Send)DirectPlay2WImpl_Send,
5062 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5063 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5064 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5065 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5066 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5068 XCAST(AddGroupToGroup)DirectPlay3WImpl_AddGroupToGroup,
5069 XCAST(CreateGroupInGroup)DirectPlay3WImpl_CreateGroupInGroup,
5070 XCAST(DeleteGroupFromGroup)DirectPlay3WImpl_DeleteGroupFromGroup,
5071 XCAST(EnumConnections)DirectPlay3WImpl_EnumConnections,
5072 XCAST(EnumGroupsInGroup)DirectPlay3WImpl_EnumGroupsInGroup,
5073 XCAST(GetGroupConnectionSettings)DirectPlay3WImpl_GetGroupConnectionSettings,
5074 XCAST(InitializeConnection)DirectPlay3WImpl_InitializeConnection,
5075 XCAST(SecureOpen)DirectPlay3WImpl_SecureOpen,
5076 XCAST(SendChatMessage)DirectPlay3WImpl_SendChatMessage,
5077 XCAST(SetGroupConnectionSettings)DirectPlay3WImpl_SetGroupConnectionSettings,
5078 XCAST(StartSession)DirectPlay3WImpl_StartSession,
5079 XCAST(GetGroupFlags)DirectPlay3WImpl_GetGroupFlags,
5080 XCAST(GetGroupParent)DirectPlay3WImpl_GetGroupParent,
5081 XCAST(GetPlayerAccount)DirectPlay3WImpl_GetPlayerAccount,
5082 XCAST(GetPlayerFlags)DirectPlay3WImpl_GetPlayerFlags,
5084 DirectPlay4WImpl_GetGroupOwner,
5085 DirectPlay4WImpl_SetGroupOwner,
5086 DirectPlay4WImpl_SendEx,
5087 DirectPlay4WImpl_GetMessageQueue,
5088 DirectPlay4WImpl_CancelMessage,
5089 DirectPlay4WImpl_CancelPriority
5091 #undef XCAST
5094 /* Note: Hack so we can reuse the old functions without compiler warnings */
5095 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5096 # define XCAST(fun) (typeof(directPlay4AVT.fun))
5097 #else
5098 # define XCAST(fun) (void*)
5099 #endif
5100 static IDirectPlay4Vtbl directPlay4AVT =
5102 XCAST(QueryInterface)DP_QueryInterface,
5103 XCAST(AddRef)DP_AddRef,
5104 XCAST(Release)DP_Release,
5106 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
5107 XCAST(Close)DirectPlay2AImpl_Close,
5108 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
5109 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
5110 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
5111 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
5112 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
5113 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
5114 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
5115 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
5116 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
5117 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
5118 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
5119 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
5120 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5121 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5122 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5123 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5124 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5125 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5126 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5127 XCAST(Open)DirectPlay2AImpl_Open,
5128 XCAST(Receive)DirectPlay2AImpl_Receive,
5129 XCAST(Send)DirectPlay2AImpl_Send,
5130 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5131 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5132 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5133 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5134 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5136 XCAST(AddGroupToGroup)DirectPlay3AImpl_AddGroupToGroup,
5137 XCAST(CreateGroupInGroup)DirectPlay3AImpl_CreateGroupInGroup,
5138 XCAST(DeleteGroupFromGroup)DirectPlay3AImpl_DeleteGroupFromGroup,
5139 XCAST(EnumConnections)DirectPlay3AImpl_EnumConnections,
5140 XCAST(EnumGroupsInGroup)DirectPlay3AImpl_EnumGroupsInGroup,
5141 XCAST(GetGroupConnectionSettings)DirectPlay3AImpl_GetGroupConnectionSettings,
5142 XCAST(InitializeConnection)DirectPlay3AImpl_InitializeConnection,
5143 XCAST(SecureOpen)DirectPlay3AImpl_SecureOpen,
5144 XCAST(SendChatMessage)DirectPlay3AImpl_SendChatMessage,
5145 XCAST(SetGroupConnectionSettings)DirectPlay3AImpl_SetGroupConnectionSettings,
5146 XCAST(StartSession)DirectPlay3AImpl_StartSession,
5147 XCAST(GetGroupFlags)DirectPlay3AImpl_GetGroupFlags,
5148 XCAST(GetGroupParent)DirectPlay3AImpl_GetGroupParent,
5149 XCAST(GetPlayerAccount)DirectPlay3AImpl_GetPlayerAccount,
5150 XCAST(GetPlayerFlags)DirectPlay3AImpl_GetPlayerFlags,
5152 DirectPlay4AImpl_GetGroupOwner,
5153 DirectPlay4AImpl_SetGroupOwner,
5154 DirectPlay4AImpl_SendEx,
5155 DirectPlay4AImpl_GetMessageQueue,
5156 DirectPlay4AImpl_CancelMessage,
5157 DirectPlay4AImpl_CancelPriority
5159 #undef XCAST
5161 extern
5162 HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP,
5163 DPID idPlayer,
5164 LPVOID* lplpData )
5166 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5168 if( lpPlayer == NULL )
5170 return DPERR_INVALIDPLAYER;
5173 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
5175 return DP_OK;
5178 extern
5179 HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP,
5180 DPID idPlayer,
5181 LPVOID lpData )
5183 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5185 if( lpPlayer == NULL )
5187 return DPERR_INVALIDPLAYER;
5190 lpPlayer->lpPData->lpSPPlayerData = lpData;
5192 return DP_OK;
5195 /***************************************************************************
5196 * DirectPlayEnumerate [DPLAYX.9]
5197 * DirectPlayEnumerateA [DPLAYX.2]
5199 * The pointer to the structure lpContext will be filled with the
5200 * appropriate data for each service offered by the OS. These services are
5201 * not necessarily available on this particular machine but are defined
5202 * as simple service providers under the "Service Providers" registry key.
5203 * This structure is then passed to lpEnumCallback for each of the different
5204 * services.
5206 * This API is useful only for applications written using DirectX3 or
5207 * worse. It is superseded by IDirectPlay3::EnumConnections which also
5208 * gives information on the actual connections.
5210 * defn of a service provider:
5211 * A dynamic-link library used by DirectPlay to communicate over a network.
5212 * The service provider contains all the network-specific code required
5213 * to send and receive messages. Online services and network operators can
5214 * supply service providers to use specialized hardware, protocols, communications
5215 * media, and network resources.
5217 * TODO: Allocate string buffer space from the heap (length from reg)
5218 * Pass real device driver numbers...
5219 * Get the GUID properly...
5221 HRESULT WINAPI DirectPlayEnumerateA( LPDPENUMDPCALLBACKA lpEnumCallback,
5222 LPVOID lpContext )
5225 HKEY hkResult;
5226 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
5227 DWORD dwIndex;
5228 DWORD sizeOfSubKeyName=50;
5229 char subKeyName[51];
5230 FILETIME filetime;
5232 TRACE(": lpEnumCallback=%p lpContext=%p\n", lpEnumCallback, lpContext );
5234 if( !lpEnumCallback || !*lpEnumCallback )
5236 return DPERR_INVALIDPARAMS;
5239 /* Need to loop over the service providers in the registry */
5240 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
5241 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
5243 /* Hmmm. Does this mean that there are no service providers? */
5244 ERR(": no service providers?\n");
5245 return DPERR_NOSERVICEPROVIDER;
5248 /* Traverse all the service providers we have available */
5249 for( dwIndex=0;
5250 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
5251 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
5252 ++dwIndex, sizeOfSubKeyName=50 )
5254 LPCSTR majVerDataSubKey = "dwReserved1";
5255 LPCSTR minVerDataSubKey = "dwReserved2";
5256 LPCSTR guidDataSubKey = "Guid";
5257 HKEY hkServiceProvider;
5258 GUID serviceProviderGUID;
5259 DWORD returnTypeGUID, returnTypeReserved, sizeOfReturnBuffer = 50;
5260 char returnBuffer[51];
5261 WCHAR buff[51];
5262 DWORD majVersionNum , minVersionNum = 0;
5264 TRACE(" this time through: %s\n", subKeyName );
5266 /* Get a handle for this particular service provider */
5267 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
5268 &hkServiceProvider ) != ERROR_SUCCESS )
5270 ERR(": what the heck is going on?\n" );
5271 continue;
5274 /* Get the GUID, Device major number and device minor number
5275 * from the registry.
5277 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
5278 NULL, &returnTypeGUID, returnBuffer,
5279 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5281 ERR(": missing GUID registry data members\n" );
5282 continue;
5285 /* FIXME: Check return types to ensure we're interpreting data right */
5286 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
5287 CLSIDFromString( buff, &serviceProviderGUID );
5289 /* FIXME: Need to know which of dwReserved1 and dwReserved2 are maj and min */
5291 sizeOfReturnBuffer = 50;
5292 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
5293 NULL, &returnTypeReserved, returnBuffer,
5294 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5296 ERR(": missing dwReserved1 registry data members\n") ;
5297 continue;
5299 memcpy( &majVersionNum, returnBuffer, sizeof(majVersionNum) );
5301 sizeOfReturnBuffer = 50;
5302 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
5303 NULL, &returnTypeReserved, returnBuffer,
5304 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5306 ERR(": missing dwReserved2 registry data members\n") ;
5307 continue;
5309 memcpy( &minVersionNum, returnBuffer, sizeof(minVersionNum) );
5312 /* The enumeration will return FALSE if we are not to continue */
5313 if( !lpEnumCallback( &serviceProviderGUID , subKeyName,
5314 majVersionNum, minVersionNum, lpContext ) )
5316 WARN("lpEnumCallback returning FALSE\n" );
5317 break;
5321 return DP_OK;
5325 /***************************************************************************
5326 * DirectPlayEnumerateW [DPLAYX.3]
5329 HRESULT WINAPI DirectPlayEnumerateW( LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5332 FIXME(":stub\n");
5334 return DPERR_OUTOFMEMORY;
5338 typedef struct tagCreateEnum
5340 LPVOID lpConn;
5341 LPCGUID lpGuid;
5342 } CreateEnumData, *lpCreateEnumData;
5344 /* Find and copy the matching connection for the SP guid */
5345 static BOOL CALLBACK cbDPCreateEnumConnections(
5346 LPCGUID lpguidSP,
5347 LPVOID lpConnection,
5348 DWORD dwConnectionSize,
5349 LPCDPNAME lpName,
5350 DWORD dwFlags,
5351 LPVOID lpContext)
5353 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5355 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5357 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5359 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5360 dwConnectionSize );
5361 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5363 /* Found the record that we were looking for */
5364 return FALSE;
5367 /* Haven't found what were looking for yet */
5368 return TRUE;
5372 /***************************************************************************
5373 * DirectPlayCreate [DPLAYX.1]
5376 HRESULT WINAPI DirectPlayCreate
5377 ( LPGUID lpGUID, LPDIRECTPLAY2 *lplpDP, IUnknown *pUnk)
5379 HRESULT hr;
5380 LPDIRECTPLAY3A lpDP3A;
5381 CreateEnumData cbData;
5383 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5385 if( pUnk != NULL )
5387 return CLASS_E_NOAGGREGATION;
5390 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5391 give them an IDirectPlay2A object and hope that doesn't cause problems */
5392 if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
5394 return DPERR_UNAVAILABLE;
5397 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
5399 /* The GUID_NULL means don't bind a service provider. Just return the
5400 interface as is */
5401 return DP_OK;
5404 /* Bind the desired service provider since lpGUID is non NULL */
5405 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
5407 /* We're going to use a DP3 interface */
5408 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
5409 (LPVOID*)&lpDP3A );
5410 if( FAILED(hr) )
5412 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
5413 return hr;
5416 cbData.lpConn = NULL;
5417 cbData.lpGuid = lpGUID;
5419 /* We were given a service provider, find info about it... */
5420 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
5421 &cbData, DPCONNECTION_DIRECTPLAY );
5422 if( ( FAILED(hr) ) ||
5423 ( cbData.lpConn == NULL )
5426 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
5427 IDirectPlayX_Release( lpDP3A );
5428 return DPERR_UNAVAILABLE;
5431 /* Initialize the service provider */
5432 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
5433 if( FAILED(hr) )
5435 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
5436 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5437 IDirectPlayX_Release( lpDP3A );
5438 return hr;
5441 /* Release our version of the interface now that we're done with it */
5442 IDirectPlayX_Release( lpDP3A );
5443 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5445 return DP_OK;