Add comment about CLIPBOARD_SetClipboardOwner.
[wine/multimedia.git] / dlls / dplayx / dplay.c
blobd532344cb7210a2620bdde06169e0521ad3323b5
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 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1311 HeapFree( GetProcessHeap(), 0, lpDst->u2.lpszLongNameA );
1313 /* Copy as required */
1314 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1316 if( bAnsi )
1318 if( lpSrc->u1.lpszShortNameA )
1320 lpDst->u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), 0,
1321 strlen(lpSrc->u1.lpszShortNameA)+1 );
1322 strcpy( lpDst->u1.lpszShortNameA, lpSrc->u1.lpszShortNameA );
1324 if( lpSrc->u2.lpszLongNameA )
1326 lpDst->u2.lpszLongNameA = HeapAlloc( GetProcessHeap(), 0,
1327 strlen(lpSrc->u2.lpszLongNameA)+1 );
1328 strcpy( lpDst->u2.lpszLongNameA, lpSrc->u2.lpszLongNameA );
1331 else
1333 if( lpSrc->u1.lpszShortNameA )
1335 lpDst->u1.lpszShortName = HeapAlloc( GetProcessHeap(), 0,
1336 (strlenW(lpSrc->u1.lpszShortName)+1)*sizeof(WCHAR) );
1337 strcpyW( lpDst->u1.lpszShortName, lpSrc->u1.lpszShortName );
1339 if( lpSrc->u2.lpszLongNameA )
1341 lpDst->u2.lpszLongName = HeapAlloc( GetProcessHeap(), 0,
1342 (strlenW(lpSrc->u2.lpszLongName)+1)*sizeof(WCHAR) );
1343 strcpyW( lpDst->u2.lpszLongName, lpSrc->u2.lpszLongName );
1347 return TRUE;
1350 static void
1351 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
1352 LPVOID lpData, DWORD dwDataSize )
1354 /* Clear out the data with this player */
1355 if( ( dwFlags & DPSET_LOCAL ) &&
1356 ( lpPData->dwLocalDataSize != 0 )
1359 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
1360 lpPData->lpLocalData = NULL;
1361 lpPData->dwLocalDataSize = 0;
1363 if( ( dwFlags & DPSET_REMOTE ) &&
1364 ( lpPData->dwRemoteDataSize != 0 )
1367 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
1368 lpPData->lpRemoteData = NULL;
1369 lpPData->dwRemoteDataSize = 0;
1372 /* Reallocate for new data */
1373 if( lpData != NULL )
1375 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1376 sizeof( dwDataSize ) );
1377 CopyMemory( lpNewData, lpData, dwDataSize );
1379 if( dwFlags & DPSET_REMOTE )
1381 lpPData->lpRemoteData = lpNewData;
1382 lpPData->dwRemoteDataSize = dwDataSize;
1385 if( dwFlags & DPSET_LOCAL )
1387 lpPData->lpLocalData = lpData;
1388 lpPData->dwLocalDataSize = dwDataSize;
1394 static HRESULT WINAPI DP_IF_CreatePlayer
1395 ( IDirectPlay2Impl* This,
1396 LPVOID lpMsgHdr, /* NULL for local creation, non NULL for remote creation */
1397 LPDPID lpidPlayer,
1398 LPDPNAME lpPlayerName,
1399 HANDLE hEvent,
1400 LPVOID lpData,
1401 DWORD dwDataSize,
1402 DWORD dwFlags,
1403 BOOL bAnsi )
1405 HRESULT hr = DP_OK;
1406 lpPlayerData lpPData;
1407 lpPlayerList lpPList;
1408 DWORD dwCreateFlags = 0;
1410 TRACE( "(%p)->(%p,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
1411 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1412 dwDataSize, dwFlags, bAnsi );
1414 if( dwFlags == 0 )
1416 dwFlags = DPPLAYER_SPECTATOR;
1419 if( lpidPlayer == NULL )
1421 return DPERR_INVALIDPARAMS;
1425 /* Determine the creation flags for the player. These will be passed
1426 * to the name server if requesting a player id and to the SP when
1427 * informing it of the player creation
1430 if( dwFlags & DPPLAYER_SERVERPLAYER )
1432 if( *lpidPlayer == DPID_SERVERPLAYER )
1434 /* Server player for the host interface */
1435 dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
1437 else if( *lpidPlayer == DPID_NAME_SERVER )
1439 /* Name server - master of everything */
1440 dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
1442 else
1444 /* Server player for a non host interface */
1445 dwCreateFlags |= DPLAYI_PLAYER_SYSPLAYER;
1449 if( lpMsgHdr == NULL )
1450 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1453 /* Verify we know how to handle all the flags */
1454 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1455 ( dwFlags & DPPLAYER_SPECTATOR )
1459 /* Assume non fatal failure */
1460 ERR( "unknown dwFlags = 0x%08lx\n", dwFlags );
1463 /* If the name is not specified, we must provide one */
1464 if( *lpidPlayer == DPID_UNKNOWN )
1466 /* If we are the session master, we dish out the group/player ids */
1467 if( This->dp2->bHostInterface )
1469 *lpidPlayer = DP_NextObjectId();
1471 else
1473 hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer );
1475 if( FAILED(hr) )
1477 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1478 return hr;
1482 else
1484 /* FIXME: Would be nice to perhaps verify that we don't already have
1485 * this player.
1489 /* FIXME: Should we be storing these dwFlags or the creation ones? */
1490 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwFlags,
1491 hEvent, bAnsi );
1493 if( lpPData == NULL )
1495 return DPERR_CANTADDPLAYER;
1498 /* Create the list object and link it in */
1499 lpPList = (lpPlayerList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1500 sizeof( *lpPList ) );
1501 if( lpPList == NULL )
1503 FIXME( "Memory leak\n" );
1504 return DPERR_CANTADDPLAYER;
1507 lpPData->uRef = 1;
1508 lpPList->lpPData = lpPData;
1510 /* Add the player to the system group */
1511 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1513 /* Update the information and send it to all players in the session */
1514 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
1516 /* Let the SP know that we've created this player */
1517 if( This->dp2->spData.lpCB->CreatePlayer )
1519 DPSP_CREATEPLAYERDATA data;
1521 data.idPlayer = *lpidPlayer;
1522 data.dwFlags = dwCreateFlags;
1523 data.lpSPMessageHeader = lpMsgHdr;
1524 data.lpISP = This->dp2->spData.lpISP;
1526 TRACE( "Calling SP CreatePlayer 0x%08lx: dwFlags: 0x%08lx lpMsgHdr: %p\n",
1527 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
1529 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1532 if( FAILED(hr) )
1534 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1535 return hr;
1538 /* Now let the SP know that this player is a member of the system group */
1539 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1541 DPSP_ADDPLAYERTOGROUPDATA data;
1543 data.idPlayer = *lpidPlayer;
1544 data.idGroup = DPID_SYSTEM_GROUP;
1545 data.lpISP = This->dp2->spData.lpISP;
1547 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1549 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1552 if( FAILED(hr) )
1554 ERR( "Failed to add player to sys group with sp: %s\n",
1555 DPLAYX_HresultToString(hr) );
1556 return hr;
1559 #if 1
1560 if( This->dp2->bHostInterface == FALSE )
1562 /* Let the name server know about the creation of this player */
1563 /* FIXME: Is this only to be done for the creation of a server player or
1564 * is this used for regular players? If only for server players, move
1565 * this call to DP_SecureOpen(...);
1567 #if 0
1568 TRACE( "Sending message to self to get my addr\n" );
1569 DP_MSG_ToSelf( This, *lpidPlayer ); /* This is a hack right now */
1570 #endif
1572 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
1574 #else
1575 /* Inform all other peers of the creation of a new player. If there are
1576 * no peers keep this quiet.
1577 * Also, if this was a remote event, no need to rebroadcast it.
1579 if( ( lpMsgHdr == NULL ) &&
1580 This->dp2->lpSessionDesc &&
1581 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1583 DPMSG_CREATEPLAYERORGROUP msg;
1584 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1586 msg.dwPlayerType = DPPLAYERTYPE_PLAYER;
1587 msg.dpId = *lpidPlayer;
1588 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */
1589 msg.lpData = lpData;
1590 msg.dwDataSize = dwDataSize;
1591 msg.dpnName = *lpPlayerName;
1592 msg.dpIdParent = DPID_NOPARENT_GROUP;
1593 msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
1595 /* FIXME: Correct to just use send effectively? */
1596 /* FIXME: Should size include data w/ message or just message "header" */
1597 /* FIXME: Check return code */
1598 hr = DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
1599 sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
1601 #endif
1603 return hr;
1606 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
1607 ( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1608 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1610 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1612 if( dwFlags & DPPLAYER_SERVERPLAYER )
1614 *lpidPlayer = DPID_SERVERPLAYER;
1616 else
1618 *lpidPlayer = DPID_UNKNOWN;
1621 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1622 lpData, dwDataSize, dwFlags, TRUE );
1625 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
1626 ( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1627 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1629 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1631 if( dwFlags & DPPLAYER_SERVERPLAYER )
1633 *lpidPlayer = DPID_SERVERPLAYER;
1635 else
1637 *lpidPlayer = DPID_UNKNOWN;
1640 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1641 lpData, dwDataSize, dwFlags, FALSE );
1644 static DPID DP_GetRemoteNextObjectId(void)
1646 FIXME( ":stub\n" );
1648 /* Hack solution */
1649 return DP_NextObjectId();
1652 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
1653 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
1654 DPID idPlayer, BOOL bAnsi )
1656 HRESULT hr = DP_OK;
1658 lpGroupData lpGData;
1659 lpPlayerList lpPList;
1661 TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
1662 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
1664 /* Find the group */
1665 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1667 return DPERR_INVALIDGROUP;
1670 /* Find the player */
1671 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
1673 return DPERR_INVALIDPLAYER;
1676 /* Remove the player shortcut from the group */
1677 DPQ_REMOVE_ENTRY( lpGData->players, players, lpPData->dpid, ==, idPlayer, lpPList );
1679 if( lpPList == NULL )
1681 return DPERR_INVALIDPLAYER;
1684 /* One less reference */
1685 lpPList->lpPData->uRef--;
1687 /* Delete the Player List element */
1688 HeapFree( GetProcessHeap(), 0, lpPList );
1690 /* Inform the SP if they care */
1691 if( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1693 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1695 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1697 data.idPlayer = idPlayer;
1698 data.idGroup = idGroup;
1699 data.lpISP = This->dp2->spData.lpISP;
1701 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1704 /* Need to send a DELETEPLAYERFROMGROUP message */
1705 FIXME( "Need to send a message\n" );
1707 return hr;
1710 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
1711 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
1713 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1714 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, TRUE );
1717 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
1718 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
1720 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1721 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, FALSE );
1724 typedef struct _DPRGOPContext
1726 IDirectPlay3Impl* This;
1727 BOOL bAnsi;
1728 DPID idGroup;
1729 } DPRGOPContext, *lpDPRGOPContext;
1731 static BOOL CALLBACK
1732 cbRemoveGroupOrPlayer(
1733 DPID dpId,
1734 DWORD dwPlayerType,
1735 LPCDPNAME lpName,
1736 DWORD dwFlags,
1737 LPVOID lpContext )
1739 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1741 TRACE( "Removing element:0x%08lx (type:0x%08lx) from element:0x%08lx\n",
1742 dpId, dwPlayerType, lpCtxt->idGroup );
1744 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1746 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt->This, lpCtxt->idGroup,
1747 dpId )
1751 ERR( "Unable to delete group 0x%08lx from group 0x%08lx\n",
1752 dpId, lpCtxt->idGroup );
1755 else
1757 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl*)lpCtxt->This,
1758 NULL, lpCtxt->idGroup,
1759 dpId, lpCtxt->bAnsi )
1763 ERR( "Unable to delete player 0x%08lx from grp 0x%08lx\n",
1764 dpId, lpCtxt->idGroup );
1768 return TRUE; /* Continue enumeration */
1771 static HRESULT WINAPI DP_IF_DestroyGroup
1772 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi )
1774 lpGroupData lpGData;
1775 DPRGOPContext context;
1777 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
1778 This, lpMsgHdr, idGroup, bAnsi );
1780 /* Find the group */
1781 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1783 return DPERR_INVALIDPLAYER; /* yes player */
1786 context.This = (IDirectPlay3Impl*)This;
1787 context.bAnsi = bAnsi;
1788 context.idGroup = idGroup;
1790 /* Remove all players that this group has */
1791 DP_IF_EnumGroupPlayers( This, idGroup, NULL,
1792 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1794 /* Remove all links to groups that this group has since this is dp3 */
1795 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This, idGroup, NULL,
1796 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1798 /* Remove this group from the parent group - if it has one */
1799 if( ( idGroup != DPID_SYSTEM_GROUP ) &&
1800 ( lpGData->parent != DPID_SYSTEM_GROUP )
1803 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl*)This, lpGData->parent,
1804 idGroup );
1807 /* Now delete this group data and list from the system group */
1808 DP_DeleteGroup( This, idGroup );
1810 /* Let the SP know that we've destroyed this group */
1811 if( This->dp2->spData.lpCB->DeleteGroup )
1813 DPSP_DELETEGROUPDATA data;
1815 FIXME( "data.dwFlags is incorrect\n" );
1817 data.idGroup = idGroup;
1818 data.dwFlags = 0;
1819 data.lpISP = This->dp2->spData.lpISP;
1821 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1824 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1826 return DP_OK;
1829 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
1830 ( LPDIRECTPLAY2A iface, DPID idGroup )
1832 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1833 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
1836 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
1837 ( LPDIRECTPLAY2 iface, DPID idGroup )
1839 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1840 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
1843 typedef struct _DPFAGContext
1845 IDirectPlay2Impl* This;
1846 DPID idPlayer;
1847 BOOL bAnsi;
1848 } DPFAGContext, *lpDPFAGContext;
1850 static HRESULT WINAPI DP_IF_DestroyPlayer
1851 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi )
1853 DPFAGContext cbContext;
1855 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
1856 This, lpMsgHdr, idPlayer, bAnsi );
1858 if( This->dp2->connectionInitialized == NO_PROVIDER )
1860 return DPERR_UNINITIALIZED;
1863 if( DP_FindPlayer( This, idPlayer ) == NULL )
1865 return DPERR_INVALIDPLAYER;
1868 /* FIXME: If the player is remote, we must be the host to delete this */
1870 cbContext.This = This;
1871 cbContext.idPlayer = idPlayer;
1872 cbContext.bAnsi = bAnsi;
1874 /* Find each group and call DeletePlayerFromGroup if the player is a
1875 member of the group */
1876 DP_IF_EnumGroups( This, NULL, cbDeletePlayerFromAllGroups,
1877 (LPVOID)&cbContext, DPENUMGROUPS_ALL, bAnsi );
1879 /* Now delete player and player list from the sys group */
1880 DP_DeletePlayer( This, idPlayer );
1882 /* Let the SP know that we've destroyed this group */
1883 if( This->dp2->spData.lpCB->DeletePlayer )
1885 DPSP_DELETEPLAYERDATA data;
1887 FIXME( "data.dwFlags is incorrect\n" );
1889 data.idPlayer = idPlayer;
1890 data.dwFlags = 0;
1891 data.lpISP = This->dp2->spData.lpISP;
1893 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
1896 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
1898 return DP_OK;
1901 static BOOL CALLBACK
1902 cbDeletePlayerFromAllGroups(
1903 DPID dpId,
1904 DWORD dwPlayerType,
1905 LPCDPNAME lpName,
1906 DWORD dwFlags,
1907 LPVOID lpContext )
1909 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
1911 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1913 DP_IF_DeletePlayerFromGroup( lpCtxt->This, NULL, dpId, lpCtxt->idPlayer,
1914 lpCtxt->bAnsi );
1916 /* Enumerate all groups in this group since this will normally only
1917 * be called for top level groups
1919 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)lpCtxt->This,
1920 dpId, NULL,
1921 cbDeletePlayerFromAllGroups,
1922 (LPVOID)lpContext, DPENUMGROUPS_ALL,
1923 lpCtxt->bAnsi );
1926 else
1928 ERR( "Group callback has dwPlayerType = 0x%08lx\n", dwPlayerType );
1931 return TRUE;
1934 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
1935 ( LPDIRECTPLAY2A iface, DPID idPlayer )
1937 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1938 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
1941 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
1942 ( LPDIRECTPLAY2 iface, DPID idPlayer )
1944 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
1945 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
1948 static HRESULT WINAPI DP_IF_EnumGroupPlayers
1949 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
1950 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1951 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1953 lpGroupData lpGData;
1954 lpPlayerList lpPList;
1956 FIXME("(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
1957 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
1958 lpContext, dwFlags, bAnsi );
1960 if( This->dp2->connectionInitialized == NO_PROVIDER )
1962 return DPERR_UNINITIALIZED;
1965 /* Find the group */
1966 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1968 return DPERR_INVALIDGROUP;
1971 if( DPQ_IS_EMPTY( lpGData->players ) )
1973 return DP_OK;
1976 lpPList = DPQ_FIRST( lpGData->players );
1978 /* Walk the players in this group */
1979 for( ;; )
1981 /* We do not enum the name server or app server as they are of no
1982 * concequence to the end user.
1984 if( ( lpPList->lpPData->dpid != DPID_NAME_SERVER ) &&
1985 ( lpPList->lpPData->dpid != DPID_SERVERPLAYER )
1989 /* FIXME: Need to add stuff for dwFlags checking */
1991 if( !lpEnumPlayersCallback2( lpPList->lpPData->dpid, DPPLAYERTYPE_PLAYER,
1992 &lpPList->lpPData->name,
1993 lpPList->lpPData->dwFlags,
1994 lpContext )
1997 /* User requested break */
1998 return DP_OK;
2002 if( DPQ_IS_ENDOFLIST( lpPList->players ) )
2004 break;
2007 lpPList = DPQ_NEXT( lpPList->players );
2010 return DP_OK;
2013 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
2014 ( LPDIRECTPLAY2A iface, DPID idGroup, LPGUID lpguidInstance,
2015 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2016 LPVOID lpContext, DWORD dwFlags )
2018 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2019 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2020 lpEnumPlayersCallback2, lpContext,
2021 dwFlags, TRUE );
2024 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
2025 ( LPDIRECTPLAY2 iface, DPID idGroup, LPGUID lpguidInstance,
2026 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2027 LPVOID lpContext, DWORD dwFlags )
2029 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2030 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2031 lpEnumPlayersCallback2, lpContext,
2032 dwFlags, FALSE );
2035 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2036 static HRESULT WINAPI DP_IF_EnumGroups
2037 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2038 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2039 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2041 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This,
2042 DPID_SYSTEM_GROUP, lpguidInstance,
2043 lpEnumPlayersCallback2, lpContext,
2044 dwFlags, bAnsi );
2047 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
2048 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2049 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2050 LPVOID lpContext, DWORD dwFlags )
2052 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2053 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2054 lpContext, dwFlags, TRUE );
2057 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
2058 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2059 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2060 LPVOID lpContext, DWORD dwFlags )
2062 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2063 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2064 lpContext, dwFlags, FALSE );
2067 static HRESULT WINAPI DP_IF_EnumPlayers
2068 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2069 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2070 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2072 return DP_IF_EnumGroupPlayers( This, DPID_SYSTEM_GROUP, lpguidInstance,
2073 lpEnumPlayersCallback2, lpContext,
2074 dwFlags, bAnsi );
2077 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
2078 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2079 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2080 LPVOID lpContext, DWORD dwFlags )
2082 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2083 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2084 lpContext, dwFlags, TRUE );
2087 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
2088 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2089 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2090 LPVOID lpContext, DWORD dwFlags )
2092 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2093 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2094 lpContext, dwFlags, FALSE );
2097 /* This function should call the registered callback function that the user
2098 passed into EnumSessions for each entry available.
2100 static void DP_InvokeEnumSessionCallbacks
2101 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2102 LPVOID lpNSInfo,
2103 DWORD dwTimeout,
2104 LPVOID lpContext )
2106 LPDPSESSIONDESC2 lpSessionDesc;
2108 FIXME( ": not checking for conditions\n" );
2110 /* Not sure if this should be pruning but it's convenient */
2111 NS_PruneSessionCache( lpNSInfo );
2113 NS_ResetSessionEnumeration( lpNSInfo );
2115 /* Enumerate all sessions */
2116 /* FIXME: Need to indicate ANSI */
2117 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2119 TRACE( "EnumSessionsCallback2 invoked\n" );
2120 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2122 return;
2126 /* Invoke one last time to indicate that there is no more to come */
2127 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2130 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2132 EnumSessionAsyncCallbackData* data = (EnumSessionAsyncCallbackData*)lpContext;
2133 HANDLE hSuicideRequest = data->hSuicideRequest;
2134 DWORD dwTimeout = data->dwTimeout;
2136 TRACE( "Thread started with timeout = 0x%08lx\n", dwTimeout );
2138 for( ;; )
2140 HRESULT hr;
2142 /* Sleep up to dwTimeout waiting for request to terminate thread */
2143 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2145 TRACE( "Thread terminating on terminate request\n" );
2146 break;
2149 /* Now resend the enum request */
2150 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2151 data->dwEnumSessionFlags,
2152 data->lpSpData );
2154 if( FAILED(hr) )
2156 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2157 /* FIXME: Should we kill this thread? How to inform the main thread? */
2162 TRACE( "Thread terminating\n" );
2164 /* Clean up the thread data */
2165 CloseHandle( hSuicideRequest );
2166 HeapFree( GetProcessHeap(), 0, lpContext );
2168 /* FIXME: Need to have some notification to main app thread that this is
2169 * dead. It would serve two purposes. 1) allow sync on termination
2170 * so that we don't actually send something to ourselves when we
2171 * become name server (race condition) and 2) so that if we die
2172 * abnormally something else will be able to tell.
2175 return 1;
2178 static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
2180 /* Does a thread exist? If so we were doing an async enum session */
2181 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2183 TRACE( "Killing EnumSession thread %p\n",
2184 This->dp2->hEnumSessionThread );
2186 /* Request that the thread kill itself nicely */
2187 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2188 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2190 /* We no longer need to know about the thread */
2191 CloseHandle( This->dp2->hEnumSessionThread );
2193 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2197 static HRESULT WINAPI DP_IF_EnumSessions
2198 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2199 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2200 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2202 HRESULT hr = DP_OK;
2204 TRACE( "(%p)->(%p,0x%08lx,%p,%p,0x%08lx,%u)\n",
2205 This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags,
2206 bAnsi );
2208 /* Can't enumerate if the interface is already open */
2209 if( This->dp2->bConnectionOpen )
2211 return DPERR_GENERIC;
2214 #if 1
2215 /* The loading of a lobby provider _seems_ to require a backdoor loading
2216 * of the service provider to also associate with this DP object. This is
2217 * because the app doesn't seem to have to call EnumConnections and
2218 * InitializeConnection for the SP before calling this method. As such
2219 * we'll do their dirty work for them with a quick hack so as to always
2220 * load the TCP/IP service provider.
2222 * The correct solution would seem to involve creating a dialog box which
2223 * contains the possible SPs. These dialog boxes most likely follow SDK
2224 * examples.
2226 if( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
2228 LPVOID lpConnection;
2229 DWORD dwSize;
2231 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2233 if( !DP_BuildSPCompoundAddr( (LPGUID)&DPSPGUID_TCPIP, &lpConnection, &dwSize ) )
2235 ERR( "Can't build compound addr\n" );
2236 return DPERR_GENERIC;
2239 hr = DP_IF_InitializeConnection( (IDirectPlay3Impl*)This, lpConnection,
2240 0, bAnsi );
2241 if( FAILED(hr) )
2243 return hr;
2246 /* Free up the address buffer */
2247 HeapFree( GetProcessHeap(), 0, lpConnection );
2249 /* The SP is now initialized */
2250 This->dp2->bSPInitialized = TRUE;
2252 #endif
2255 /* Use the service provider default? */
2256 if( dwTimeout == 0 )
2258 DPCAPS spCaps;
2259 spCaps.dwSize = sizeof( spCaps );
2261 DP_IF_GetCaps( This, &spCaps, 0 );
2262 dwTimeout = spCaps.dwTimeout;
2264 /* The service provider doesn't provide one either! */
2265 if( dwTimeout == 0 )
2267 /* Provide the TCP/IP default */
2268 dwTimeout = DPMSG_WAIT_5_SECS;
2272 if( dwFlags & DPENUMSESSIONS_STOPASYNC )
2274 DP_KillEnumSessionThread( This );
2275 return hr;
2278 /* FIXME: Interface locking sucks in this method */
2279 if( ( dwFlags & DPENUMSESSIONS_ASYNC ) )
2281 /* Enumerate everything presently in the local session cache */
2282 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2283 This->dp2->lpNameServerData, dwTimeout,
2284 lpContext );
2287 /* See if we've already created a thread to service this interface */
2288 if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2290 DWORD dwThreadId;
2292 /* Send the first enum request inline since the user may cancel a dialog
2293 * if one is presented. Also, may also have a connecting return code.
2295 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2296 dwFlags, &This->dp2->spData );
2298 if( !FAILED(hr) )
2300 EnumSessionAsyncCallbackData* lpData
2301 = (EnumSessionAsyncCallbackData*)HeapAlloc( GetProcessHeap(),
2302 HEAP_ZERO_MEMORY,
2303 sizeof( *lpData ) );
2304 /* FIXME: need to kill the thread on object deletion */
2305 lpData->lpSpData = &This->dp2->spData;
2307 CopyMemory( &lpData->requestGuid, &lpsd->guidApplication, sizeof(GUID) );
2308 lpData->dwEnumSessionFlags = dwFlags;
2309 lpData->dwTimeout = dwTimeout;
2311 This->dp2->hKillEnumSessionThreadEvent =
2312 CreateEventA( NULL, TRUE, FALSE, NULL );
2314 if( !DuplicateHandle( GetCurrentProcess(),
2315 This->dp2->hKillEnumSessionThreadEvent,
2316 GetCurrentProcess(),
2317 &lpData->hSuicideRequest,
2318 0, FALSE, DUPLICATE_SAME_ACCESS )
2321 ERR( "Can't duplicate thread killing handle\n" );
2324 TRACE( ": creating EnumSessionsRequest thread\n" );
2326 This->dp2->hEnumSessionThread = CreateThread( NULL,
2328 DP_EnumSessionsSendAsyncRequestThread,
2329 lpData,
2331 &dwThreadId );
2335 else
2337 /* Invalidate the session cache for the interface */
2338 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2340 /* Send the broadcast for session enumeration */
2341 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2342 dwFlags,
2343 &This->dp2->spData );
2346 SleepEx( dwTimeout, FALSE );
2348 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2349 This->dp2->lpNameServerData, dwTimeout,
2350 lpContext );
2353 return hr;
2356 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2357 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2358 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2359 LPVOID lpContext, DWORD dwFlags )
2361 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2362 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2363 lpContext, dwFlags, TRUE );
2366 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2367 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2368 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2369 LPVOID lpContext, DWORD dwFlags )
2371 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2372 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2373 lpContext, dwFlags, FALSE );
2376 static HRESULT WINAPI DP_IF_GetPlayerCaps
2377 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
2378 DWORD dwFlags )
2380 DPSP_GETCAPSDATA data;
2382 TRACE("(%p)->(0x%08lx,%p,0x%08lx)\n", This, idPlayer, lpDPCaps, dwFlags);
2384 /* Query the service provider */
2385 data.idPlayer = idPlayer;
2386 data.dwFlags = dwFlags;
2387 data.lpCaps = lpDPCaps;
2388 data.lpISP = This->dp2->spData.lpISP;
2390 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2393 static HRESULT WINAPI DP_IF_GetCaps
2394 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags )
2396 return DP_IF_GetPlayerCaps( This, DPID_ALLPLAYERS, lpDPCaps, dwFlags );
2399 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2400 ( LPDIRECTPLAY2A iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2402 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2403 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2406 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2407 ( LPDIRECTPLAY2 iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2409 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2410 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2413 static HRESULT WINAPI DP_IF_GetGroupData
2414 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2415 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2417 lpGroupData lpGData;
2418 DWORD dwRequiredBufferSize;
2419 LPVOID lpCopyDataFrom;
2421 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
2422 This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi );
2424 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2426 return DPERR_INVALIDGROUP;
2429 /* How much buffer is required? */
2430 if( dwFlags & DPSET_REMOTE )
2432 dwRequiredBufferSize = lpGData->dwRemoteDataSize;
2433 lpCopyDataFrom = lpGData->lpRemoteData;
2435 else if( dwFlags & DPSET_LOCAL )
2437 dwRequiredBufferSize = lpGData->dwLocalDataSize;
2438 lpCopyDataFrom = lpGData->lpLocalData;
2440 else
2442 ERR( "Neither local or remote data requested!?!\n" );
2443 dwRequiredBufferSize = 0;
2444 lpCopyDataFrom = NULL;
2447 /* Is the user requesting to know how big a buffer is required? */
2448 if( ( lpData == NULL ) ||
2449 ( *lpdwDataSize < dwRequiredBufferSize )
2452 *lpdwDataSize = dwRequiredBufferSize;
2453 return DPERR_BUFFERTOOSMALL;
2456 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2458 return DP_OK;
2461 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2462 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2463 LPDWORD lpdwDataSize, DWORD dwFlags )
2465 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2466 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2467 dwFlags, TRUE );
2470 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2471 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2472 LPDWORD lpdwDataSize, DWORD dwFlags )
2474 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2475 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2476 dwFlags, FALSE );
2479 static HRESULT WINAPI DP_IF_GetGroupName
2480 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2481 LPDWORD lpdwDataSize, BOOL bAnsi )
2483 lpGroupData lpGData;
2484 LPDPNAME lpName = (LPDPNAME)lpData;
2485 DWORD dwRequiredDataSize;
2487 FIXME("(%p)->(0x%08lx,%p,%p,%u) ANSI ignored\n",
2488 This, idGroup, lpData, lpdwDataSize, bAnsi );
2490 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2492 return DPERR_INVALIDGROUP;
2495 dwRequiredDataSize = lpGData->name.dwSize;
2497 if( lpGData->name.u1.lpszShortNameA )
2499 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
2502 if( lpGData->name.u2.lpszLongNameA )
2504 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
2507 if( ( lpData == NULL ) ||
2508 ( *lpdwDataSize < dwRequiredDataSize )
2511 *lpdwDataSize = dwRequiredDataSize;
2512 return DPERR_BUFFERTOOSMALL;
2515 /* Copy the structure */
2516 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2518 if( lpGData->name.u1.lpszShortNameA )
2520 strcpy( ((BYTE*)lpName)+lpGData->name.dwSize,
2521 lpGData->name.u1.lpszShortNameA );
2523 else
2525 lpName->u1.lpszShortNameA = NULL;
2528 if( lpGData->name.u1.lpszShortNameA )
2530 strcpy( ((BYTE*)lpName)+lpGData->name.dwSize,
2531 lpGData->name.u2.lpszLongNameA );
2533 else
2535 lpName->u2.lpszLongNameA = NULL;
2538 return DP_OK;
2541 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2542 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2543 LPDWORD lpdwDataSize )
2545 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2546 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2549 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2550 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2551 LPDWORD lpdwDataSize )
2553 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2554 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2557 static HRESULT WINAPI DP_IF_GetMessageCount
2558 ( IDirectPlay2Impl* This, DPID idPlayer,
2559 LPDWORD lpdwCount, BOOL bAnsi )
2561 FIXME("(%p)->(0x%08lx,%p,%u): stub\n", This, idPlayer, lpdwCount, bAnsi );
2562 return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer,
2563 DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL,
2564 bAnsi );
2567 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2568 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDWORD lpdwCount )
2570 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2571 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, TRUE );
2574 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2575 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDWORD lpdwCount )
2577 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2578 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, FALSE );
2581 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2582 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2584 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2585 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2586 return DP_OK;
2589 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2590 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2592 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2593 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2594 return DP_OK;
2597 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2598 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2599 DWORD dwFlags )
2601 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2602 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2605 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2606 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2607 DWORD dwFlags )
2609 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2610 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2613 static HRESULT WINAPI DP_IF_GetPlayerData
2614 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2615 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2617 lpPlayerList lpPList;
2618 DWORD dwRequiredBufferSize;
2619 LPVOID lpCopyDataFrom;
2621 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
2622 This, idPlayer, lpData, lpdwDataSize, dwFlags, bAnsi );
2624 if( This->dp2->connectionInitialized == NO_PROVIDER )
2626 return DPERR_UNINITIALIZED;
2629 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2631 return DPERR_INVALIDPLAYER;
2634 /* How much buffer is required? */
2635 if( dwFlags & DPSET_REMOTE )
2637 dwRequiredBufferSize = lpPList->lpPData->dwRemoteDataSize;
2638 lpCopyDataFrom = lpPList->lpPData->lpRemoteData;
2640 else if( dwFlags & DPSET_LOCAL )
2642 dwRequiredBufferSize = lpPList->lpPData->dwLocalDataSize;
2643 lpCopyDataFrom = lpPList->lpPData->lpLocalData;
2645 else
2647 ERR( "Neither local or remote data requested!?!\n" );
2648 dwRequiredBufferSize = 0;
2649 lpCopyDataFrom = NULL;
2652 /* Is the user requesting to know how big a buffer is required? */
2653 if( ( lpData == NULL ) ||
2654 ( *lpdwDataSize < dwRequiredBufferSize )
2657 *lpdwDataSize = dwRequiredBufferSize;
2658 return DPERR_BUFFERTOOSMALL;
2661 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2663 return DP_OK;
2666 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2667 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2668 LPDWORD lpdwDataSize, DWORD dwFlags )
2670 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2671 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2672 dwFlags, TRUE );
2675 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2676 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2677 LPDWORD lpdwDataSize, DWORD dwFlags )
2679 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2680 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2681 dwFlags, FALSE );
2684 static HRESULT WINAPI DP_IF_GetPlayerName
2685 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2686 LPDWORD lpdwDataSize, BOOL bAnsi )
2688 lpPlayerList lpPList;
2689 LPDPNAME lpName = (LPDPNAME)lpData;
2690 DWORD dwRequiredDataSize;
2692 FIXME( "(%p)->(0x%08lx,%p,%p,%u): ANSI \n",
2693 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2695 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2697 return DPERR_INVALIDPLAYER;
2700 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
2702 if( lpPList->lpPData->name.u1.lpszShortNameA )
2704 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
2707 if( lpPList->lpPData->name.u2.lpszLongNameA )
2709 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
2712 if( ( lpData == NULL ) ||
2713 ( *lpdwDataSize < dwRequiredDataSize )
2716 *lpdwDataSize = dwRequiredDataSize;
2717 return DPERR_BUFFERTOOSMALL;
2720 /* Copy the structure */
2721 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
2723 if( lpPList->lpPData->name.u1.lpszShortNameA )
2725 strcpy( ((BYTE*)lpName)+lpPList->lpPData->name.dwSize,
2726 lpPList->lpPData->name.u1.lpszShortNameA );
2728 else
2730 lpName->u1.lpszShortNameA = NULL;
2733 if( lpPList->lpPData->name.u1.lpszShortNameA )
2735 strcpy( ((BYTE*)lpName)+lpPList->lpPData->name.dwSize,
2736 lpPList->lpPData->name.u2.lpszLongNameA );
2738 else
2740 lpName->u2.lpszLongNameA = NULL;
2743 return DP_OK;
2746 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2747 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2748 LPDWORD lpdwDataSize )
2750 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2751 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
2754 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2755 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2756 LPDWORD lpdwDataSize )
2758 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2759 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
2762 static HRESULT WINAPI DP_GetSessionDesc
2763 ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize,
2764 BOOL bAnsi )
2766 DWORD dwRequiredSize;
2768 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
2770 if( This->dp2->connectionInitialized == NO_PROVIDER )
2772 return DPERR_UNINITIALIZED;
2775 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
2777 return DPERR_INVALIDPARAMS;
2780 /* FIXME: Get from This->dp2->lpSessionDesc */
2781 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
2783 if ( ( lpData == NULL ) ||
2784 ( *lpdwDataSize < dwRequiredSize )
2787 *lpdwDataSize = dwRequiredSize;
2788 return DPERR_BUFFERTOOSMALL;
2791 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
2793 return DP_OK;
2796 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
2797 ( LPDIRECTPLAY2A iface, LPVOID lpData, LPDWORD lpdwDataSize )
2799 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2800 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2803 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
2804 ( LPDIRECTPLAY2 iface, LPVOID lpData, LPDWORD lpdwDataSize )
2806 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2807 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2810 /* Intended only for COM compatibility. Always returns an error. */
2811 static HRESULT WINAPI DirectPlay2AImpl_Initialize
2812 ( LPDIRECTPLAY2A iface, LPGUID lpGUID )
2814 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2815 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2816 return DPERR_ALREADYINITIALIZED;
2819 /* Intended only for COM compatibility. Always returns an error. */
2820 static HRESULT WINAPI DirectPlay2WImpl_Initialize
2821 ( LPDIRECTPLAY2 iface, LPGUID lpGUID )
2823 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2824 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2825 return DPERR_ALREADYINITIALIZED;
2829 static HRESULT WINAPI DP_SecureOpen
2830 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
2831 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
2832 BOOL bAnsi )
2834 HRESULT hr = DP_OK;
2836 FIXME( "(%p)->(%p,0x%08lx,%p,%p): partial stub\n",
2837 This, lpsd, dwFlags, lpSecurity, lpCredentials );
2839 if( This->dp2->bConnectionOpen )
2841 TRACE( ": rejecting already open connection.\n" );
2842 return DPERR_ALREADYINITIALIZED;
2845 /* If we're enumerating, kill the thread */
2846 DP_KillEnumSessionThread( This );
2848 if( dwFlags & DPOPEN_CREATE )
2850 /* Rightoo - this computer is the host and the local computer needs to be
2851 the name server so that others can join this session */
2852 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
2854 This->dp2->bHostInterface = TRUE;
2856 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
2857 if( FAILED( hr ) )
2859 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
2860 return hr;
2864 /* Invoke the conditional callback for the service provider */
2865 if( This->dp2->spData.lpCB->Open )
2867 DPSP_OPENDATA data;
2869 FIXME( "Not all data fields are correct. Need new parameter\n" );
2871 data.bCreate = (dwFlags & DPOPEN_CREATE ) ? TRUE : FALSE;
2872 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
2873 : NS_GetNSAddr( This->dp2->lpNameServerData );
2874 data.lpISP = This->dp2->spData.lpISP;
2875 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) ? TRUE : FALSE;
2876 data.dwOpenFlags = dwFlags;
2877 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
2879 hr = (*This->dp2->spData.lpCB->Open)(&data);
2880 if( FAILED( hr ) )
2882 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
2883 return hr;
2888 /* Create the system group of which everything is a part of */
2889 DPID systemGroup = DPID_SYSTEM_GROUP;
2891 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
2892 NULL, 0, 0, TRUE );
2896 if( dwFlags & DPOPEN_JOIN )
2898 DPID dpidServerId = DPID_UNKNOWN;
2900 /* Create the server player for this interface. This way we can receive
2901 * messages for this session.
2903 /* FIXME: I suppose that we should be setting an event for a receive
2904 * type of thing. That way the messaging thread could know to wake
2905 * up. DPlay would then trigger the hEvent for the player the
2906 * message is directed to.
2908 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
2910 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
2913 else if( dwFlags & DPOPEN_CREATE )
2915 DPID dpidNameServerId = DPID_NAME_SERVER;
2917 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
2918 0, DPPLAYER_SERVERPLAYER, bAnsi );
2921 if( FAILED(hr) )
2923 ERR( "Couldn't create name server/system player: %s\n",
2924 DPLAYX_HresultToString(hr) );
2927 return hr;
2930 static HRESULT WINAPI DirectPlay2AImpl_Open
2931 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2933 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2934 TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags );
2935 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, TRUE );
2938 static HRESULT WINAPI DirectPlay2WImpl_Open
2939 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2941 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
2942 TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags );
2943 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, FALSE );
2946 static HRESULT WINAPI DP_IF_Receive
2947 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
2948 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi )
2950 LPDPMSG lpMsg = NULL;
2952 FIXME( "(%p)->(%p,%p,0x%08lx,%p,%p,%u): stub\n",
2953 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
2955 if( This->dp2->connectionInitialized == NO_PROVIDER )
2957 return DPERR_UNINITIALIZED;
2960 if( dwFlags == 0 )
2962 dwFlags = DPRECEIVE_ALL;
2965 /* If the lpData is NULL, we must be peeking the message */
2966 if( ( lpData == NULL ) &&
2967 !( dwFlags & DPRECEIVE_PEEK )
2970 return DPERR_INVALIDPARAMS;
2973 if( dwFlags & DPRECEIVE_ALL )
2975 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
2977 if( !( dwFlags & DPRECEIVE_PEEK ) )
2979 FIXME( "Remove from queue\n" );
2982 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
2983 ( dwFlags & DPRECEIVE_FROMPLAYER )
2986 FIXME( "Find matching message 0x%08lx\n", dwFlags );
2988 else
2990 ERR( "Hmmm..dwFlags 0x%08lx\n", dwFlags );
2993 if( lpMsg == NULL )
2995 return DPERR_NOMESSAGES;
2998 /* Copy into the provided buffer */
2999 CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
3001 return DP_OK;
3004 static HRESULT WINAPI DirectPlay2AImpl_Receive
3005 ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo,
3006 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
3008 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3009 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
3010 lpData, lpdwDataSize, TRUE );
3013 static HRESULT WINAPI DirectPlay2WImpl_Receive
3014 ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo,
3015 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
3017 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3018 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
3019 lpData, lpdwDataSize, FALSE );
3022 static HRESULT WINAPI DirectPlay2AImpl_Send
3023 ( LPDIRECTPLAY2A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3025 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3026 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3027 0, 0, NULL, NULL, TRUE );
3030 static HRESULT WINAPI DirectPlay2WImpl_Send
3031 ( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3033 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3034 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3035 0, 0, NULL, NULL, FALSE );
3038 static HRESULT WINAPI DP_IF_SetGroupData
3039 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
3040 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3042 lpGroupData lpGData;
3044 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
3045 This, idGroup, lpData, dwDataSize, dwFlags, bAnsi );
3047 /* Parameter check */
3048 if( ( lpData == NULL ) &&
3049 ( dwDataSize != 0 )
3052 return DPERR_INVALIDPARAMS;
3055 /* Find the pointer to the data for this player */
3056 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3058 return DPERR_INVALIDOBJECT;
3061 if( dwFlags & DPSET_REMOTE )
3063 FIXME( "Was this group created by this interface?\n" );
3064 /* FIXME: If this is a remote update need to allow it but not
3065 * send a message.
3069 DP_SetGroupData( lpGData, dwFlags, lpData, dwDataSize );
3071 /* FIXME: Only send a message if this group is local to the session otherwise
3072 * it will have been rejected above
3074 if( dwFlags & DPSET_REMOTE )
3076 FIXME( "Send msg?\n" );
3079 return DP_OK;
3082 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
3083 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
3084 DWORD dwDataSize, DWORD dwFlags )
3086 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3087 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, TRUE );
3090 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
3091 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
3092 DWORD dwDataSize, DWORD dwFlags )
3094 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3095 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, FALSE );
3098 static HRESULT WINAPI DP_IF_SetGroupName
3099 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
3100 DWORD dwFlags, BOOL bAnsi )
3102 lpGroupData lpGData;
3104 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n", This, idGroup,
3105 lpGroupName, dwFlags, bAnsi );
3107 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3109 return DPERR_INVALIDGROUP;
3112 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
3114 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3115 FIXME( "Message not sent and dwFlags ignored\n" );
3117 return DP_OK;
3120 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
3121 ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName,
3122 DWORD dwFlags )
3124 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3125 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
3128 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
3129 ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName,
3130 DWORD dwFlags )
3132 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3133 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
3136 static HRESULT WINAPI DP_IF_SetPlayerData
3137 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
3138 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3140 lpPlayerList lpPList;
3142 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
3143 This, idPlayer, lpData, dwDataSize, dwFlags, bAnsi );
3145 /* Parameter check */
3146 if( ( lpData == NULL ) &&
3147 ( dwDataSize != 0 )
3150 return DPERR_INVALIDPARAMS;
3153 /* Find the pointer to the data for this player */
3154 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3156 return DPERR_INVALIDPLAYER;
3159 if( dwFlags & DPSET_REMOTE )
3161 FIXME( "Was this group created by this interface?\n" );
3162 /* FIXME: If this is a remote update need to allow it but not
3163 * send a message.
3167 DP_SetPlayerData( lpPList->lpPData, dwFlags, lpData, dwDataSize );
3169 if( dwFlags & DPSET_REMOTE )
3171 FIXME( "Send msg?\n" );
3174 return DP_OK;
3177 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3178 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
3179 DWORD dwDataSize, DWORD dwFlags )
3181 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3182 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3183 dwFlags, TRUE );
3186 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3187 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
3188 DWORD dwDataSize, DWORD dwFlags )
3190 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3191 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3192 dwFlags, FALSE );
3195 static HRESULT WINAPI DP_IF_SetPlayerName
3196 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
3197 DWORD dwFlags, BOOL bAnsi )
3199 lpPlayerList lpPList;
3201 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n",
3202 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3204 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3206 return DPERR_INVALIDGROUP;
3209 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3211 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3212 FIXME( "Message not sent and dwFlags ignored\n" );
3214 return DP_OK;
3217 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3218 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName,
3219 DWORD dwFlags )
3221 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3222 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3225 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3226 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName,
3227 DWORD dwFlags )
3229 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3230 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3233 static HRESULT WINAPI DP_SetSessionDesc
3234 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
3235 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3237 DWORD dwRequiredSize;
3238 LPDPSESSIONDESC2 lpTempSessDesc;
3240 TRACE( "(%p)->(%p,0x%08lx,%u,%u)\n",
3241 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3243 if( This->dp2->connectionInitialized == NO_PROVIDER )
3245 return DPERR_UNINITIALIZED;
3248 if( dwFlags )
3250 return DPERR_INVALIDPARAMS;
3253 /* Only the host is allowed to update the session desc */
3254 if( !This->dp2->bHostInterface )
3256 return DPERR_ACCESSDENIED;
3259 /* FIXME: Copy into This->dp2->lpSessionDesc */
3260 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3261 lpTempSessDesc = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
3262 HEAP_ZERO_MEMORY,
3263 dwRequiredSize );
3265 if( lpTempSessDesc == NULL )
3267 return DPERR_OUTOFMEMORY;
3270 /* Free the old */
3271 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3273 This->dp2->lpSessionDesc = lpTempSessDesc;
3275 /* Set the new */
3276 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3278 /* If this is an external invocation of the interface, we should be
3279 * letting everyone know that things have changed. Otherwise this is
3280 * just an initialization and it doesn't need to be propagated.
3282 if( !bInitial )
3284 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3287 return DP_OK;
3290 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3291 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3293 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3294 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3297 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3298 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3300 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
3301 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3304 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3305 DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3307 DWORD dwSize = 0;
3309 if( lpSessDesc == NULL )
3311 /* Hmmm..don't need any size? */
3312 ERR( "NULL lpSessDesc\n" );
3313 return dwSize;
3316 dwSize += sizeof( *lpSessDesc );
3318 if( bAnsi )
3320 if( lpSessDesc->u1.lpszSessionNameA )
3322 dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1;
3325 if( lpSessDesc->u2.lpszPasswordA )
3327 dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1;
3330 else /* UNICODE */
3332 if( lpSessDesc->u1.lpszSessionName )
3334 dwSize += sizeof( WCHAR ) *
3335 ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 );
3338 if( lpSessDesc->u2.lpszPassword )
3340 dwSize += sizeof( WCHAR ) *
3341 ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 );
3345 return dwSize;
3348 /* Assumes that contugous buffers are already allocated. */
3349 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3350 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3352 BYTE* lpStartOfFreeSpace;
3354 if( lpSessionDest == NULL )
3356 ERR( "NULL lpSessionDest\n" );
3357 return;
3360 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3362 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3364 if( bAnsi )
3366 if( lpSessionSrc->u1.lpszSessionNameA )
3368 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3369 lpSessionDest->u1.lpszSessionNameA );
3370 lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3371 lpStartOfFreeSpace +=
3372 lstrlenA( (LPSTR)lpSessionDest->u1.lpszSessionNameA ) + 1;
3375 if( lpSessionSrc->u2.lpszPasswordA )
3377 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3378 lpSessionDest->u2.lpszPasswordA );
3379 lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3380 lpStartOfFreeSpace +=
3381 lstrlenA( (LPSTR)lpSessionDest->u2.lpszPasswordA ) + 1;
3384 else /* UNICODE */
3386 if( lpSessionSrc->u1.lpszSessionName )
3388 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3389 lpSessionDest->u1.lpszSessionName );
3390 lpSessionDest->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3391 lpStartOfFreeSpace += sizeof(WCHAR) *
3392 ( lstrlenW( (LPWSTR)lpSessionDest->u1.lpszSessionName ) + 1 );
3395 if( lpSessionSrc->u2.lpszPassword )
3397 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3398 lpSessionDest->u2.lpszPassword );
3399 lpSessionDest->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3400 lpStartOfFreeSpace += sizeof(WCHAR) *
3401 ( lstrlenW( (LPWSTR)lpSessionDest->u2.lpszPassword ) + 1 );
3407 static HRESULT WINAPI DP_IF_AddGroupToGroup
3408 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3410 lpGroupData lpGParentData;
3411 lpGroupData lpGData;
3412 lpGroupList lpNewGList;
3414 TRACE( "(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup );
3416 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3418 return DPERR_INVALIDGROUP;
3421 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3423 return DPERR_INVALIDGROUP;
3426 /* Create a player list (ie "shortcut" ) */
3427 lpNewGList = (lpGroupList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3428 sizeof( *lpNewGList ) );
3429 if( lpNewGList == NULL )
3431 return DPERR_CANTADDPLAYER;
3434 /* Add the shortcut */
3435 lpGData->uRef++;
3436 lpNewGList->lpGData = lpGData;
3438 /* Add the player to the list of players for this group */
3439 DPQ_INSERT( lpGData->groups, lpNewGList, groups );
3441 /* Send a ADDGROUPTOGROUP message */
3442 FIXME( "Not sending message\n" );
3444 return DP_OK;
3447 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3448 ( LPDIRECTPLAY3A iface, DPID idParentGroup, DPID idGroup )
3450 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3451 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3454 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3455 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3457 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3458 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3461 static HRESULT WINAPI DP_IF_CreateGroupInGroup
3462 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
3463 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
3464 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3466 lpGroupData lpGParentData;
3467 lpGroupList lpGList;
3468 lpGroupData lpGData;
3470 TRACE( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
3471 This, idParentGroup, lpidGroup, lpGroupName, lpData,
3472 dwDataSize, dwFlags, bAnsi );
3474 /* Verify that the specified parent is valid */
3475 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This,
3476 idParentGroup ) ) == NULL
3479 return DPERR_INVALIDGROUP;
3482 lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName,
3483 dwFlags, idParentGroup, bAnsi );
3485 if( lpGData == NULL )
3487 return DPERR_CANTADDPLAYER; /* yes player not group */
3490 /* Something else is referencing this data */
3491 lpGData->uRef++;
3493 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
3495 /* The list has now been inserted into the interface group list. We now
3496 need to put a "shortcut" to this group in the parent group */
3497 lpGList = (lpGroupList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3498 sizeof( *lpGList ) );
3499 if( lpGList == NULL )
3501 FIXME( "Memory leak\n" );
3502 return DPERR_CANTADDPLAYER; /* yes player not group */
3505 lpGList->lpGData = lpGData;
3507 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
3509 /* Let the SP know that we've created this group */
3510 if( This->dp2->spData.lpCB->CreateGroup )
3512 DPSP_CREATEGROUPDATA data;
3514 TRACE( "Calling SP CreateGroup\n" );
3516 data.idGroup = *lpidGroup;
3517 data.dwFlags = dwFlags;
3518 data.lpSPMessageHeader = lpMsgHdr;
3519 data.lpISP = This->dp2->spData.lpISP;
3521 (*This->dp2->spData.lpCB->CreateGroup)( &data );
3524 /* Inform all other peers of the creation of a new group. If there are
3525 * no peers keep this quiet.
3527 if( This->dp2->lpSessionDesc &&
3528 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
3530 DPMSG_CREATEPLAYERORGROUP msg;
3532 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
3533 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
3534 msg.dpId = *lpidGroup;
3535 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
3536 msg.lpData = lpData;
3537 msg.dwDataSize = dwDataSize;
3538 msg.dpnName = *lpGroupName;
3540 /* FIXME: Correct to just use send effectively? */
3541 /* FIXME: Should size include data w/ message or just message "header" */
3542 /* FIXME: Check return code */
3543 DP_SendEx( (IDirectPlay2Impl*)This,
3544 DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
3545 0, 0, NULL, NULL, bAnsi );
3548 return DP_OK;
3551 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3552 ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup,
3553 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3554 DWORD dwFlags )
3556 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3558 *lpidGroup = DPID_UNKNOWN;
3560 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3561 lpGroupName, lpData, dwDataSize, dwFlags,
3562 TRUE );
3565 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3566 ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup,
3567 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3568 DWORD dwFlags )
3570 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3572 *lpidGroup = DPID_UNKNOWN;
3574 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3575 lpGroupName, lpData, dwDataSize,
3576 dwFlags, FALSE );
3579 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
3580 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3582 lpGroupList lpGList;
3583 lpGroupData lpGParentData;
3585 TRACE("(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup );
3587 /* Is the parent group valid? */
3588 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3590 return DPERR_INVALIDGROUP;
3593 /* Remove the group from the parent group queue */
3594 DPQ_REMOVE_ENTRY( lpGParentData->groups, groups, lpGData->dpid, ==, idGroup, lpGList );
3596 if( lpGList == NULL )
3598 return DPERR_INVALIDGROUP;
3601 /* Decrement the ref count */
3602 lpGList->lpGData->uRef--;
3604 /* Free up the list item */
3605 HeapFree( GetProcessHeap(), 0, lpGList );
3607 /* Should send a DELETEGROUPFROMGROUP message */
3608 FIXME( "message not sent\n" );
3610 return DP_OK;
3613 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3614 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3616 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3617 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3620 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3621 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3623 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3624 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3627 static
3628 BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
3629 LPDWORD lpdwBufSize )
3631 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3632 HRESULT hr;
3634 dpCompoundAddress.dwDataSize = sizeof( GUID );
3635 memcpy( &dpCompoundAddress.guidDataType, &DPAID_ServiceProvider,
3636 sizeof( GUID ) ) ;
3637 dpCompoundAddress.lpData = lpcSpGuid;
3639 *lplpAddrBuf = NULL;
3640 *lpdwBufSize = 0;
3642 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3643 lpdwBufSize, TRUE );
3645 if( hr != DPERR_BUFFERTOOSMALL )
3647 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3648 return FALSE;
3651 /* Now allocate the buffer */
3652 *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3653 *lpdwBufSize );
3655 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3656 lpdwBufSize, TRUE );
3657 if( FAILED(hr) )
3659 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3660 return FALSE;
3663 return TRUE;
3666 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
3667 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3669 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3670 TRACE("(%p)->(%p,%p,%p,0x%08lx)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3672 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
3673 if( dwFlags == 0 )
3675 dwFlags = DPCONNECTION_DIRECTPLAY;
3678 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
3679 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) )
3682 return DPERR_INVALIDFLAGS;
3685 if( !lpEnumCallback || !*lpEnumCallback )
3687 return DPERR_INVALIDPARAMS;
3690 /* Enumerate DirectPlay service providers */
3691 if( dwFlags & DPCONNECTION_DIRECTPLAY )
3693 HKEY hkResult;
3694 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3695 LPCSTR guidDataSubKey = "Guid";
3696 char subKeyName[51];
3697 DWORD dwIndex, sizeOfSubKeyName=50;
3698 FILETIME filetime;
3700 /* Need to loop over the service providers in the registry */
3701 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3702 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3704 /* Hmmm. Does this mean that there are no service providers? */
3705 ERR(": no service providers?\n");
3706 return DP_OK;
3710 /* Traverse all the service providers we have available */
3711 for( dwIndex=0;
3712 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3713 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3714 ++dwIndex, sizeOfSubKeyName=51 )
3717 HKEY hkServiceProvider;
3718 GUID serviceProviderGUID;
3719 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3720 char returnBuffer[51];
3721 WCHAR buff[51];
3722 DPNAME dpName;
3723 BOOL bBuildPass;
3725 LPVOID lpAddressBuffer = NULL;
3726 DWORD dwAddressBufferSize = 0;
3728 TRACE(" this time through: %s\n", subKeyName );
3730 /* Get a handle for this particular service provider */
3731 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3732 &hkServiceProvider ) != ERROR_SUCCESS )
3734 ERR(": what the heck is going on?\n" );
3735 continue;
3738 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3739 NULL, &returnTypeGUID, returnBuffer,
3740 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3742 ERR(": missing GUID registry data members\n" );
3743 continue;
3746 /* FIXME: Check return types to ensure we're interpreting data right */
3747 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3748 CLSIDFromString( buff, &serviceProviderGUID );
3749 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3751 /* Fill in the DPNAME struct for the service provider */
3752 dpName.dwSize = sizeof( dpName );
3753 dpName.dwFlags = 0;
3754 dpName.u1.lpszShortNameA = subKeyName;
3755 dpName.u2.lpszLongNameA = NULL;
3757 /* Create the compound address for the service provider.
3758 * NOTE: This is a gruesome architectural scar right now. DP
3759 * uses DPL and DPL uses DP. Nasty stuff. This may be why the
3760 * native dll just gets around this little bit by allocating an
3761 * 80 byte buffer which isn't even filled with a valid compound
3762 * address. Oh well. Creating a proper compound address is the
3763 * way to go anyways despite this method taking slightly more
3764 * heap space and realtime :) */
3766 bBuildPass = DP_BuildSPCompoundAddr( &serviceProviderGUID,
3767 &lpAddressBuffer,
3768 &dwAddressBufferSize );
3769 if( !bBuildPass )
3771 ERR( "Can't build compound addr\n" );
3772 return DPERR_GENERIC;
3775 /* The enumeration will return FALSE if we are not to continue */
3776 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3777 &dpName, DPCONNECTION_DIRECTPLAY, lpContext ) )
3779 return DP_OK;
3784 /* Enumerate DirectPlayLobby service providers */
3785 if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY )
3787 HKEY hkResult;
3788 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3789 LPCSTR guidDataSubKey = "Guid";
3790 char subKeyName[51];
3791 DWORD dwIndex, sizeOfSubKeyName=50;
3792 FILETIME filetime;
3794 /* Need to loop over the service providers in the registry */
3795 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3796 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3798 /* Hmmm. Does this mean that there are no service providers? */
3799 ERR(": no service providers?\n");
3800 return DP_OK;
3804 /* Traverse all the lobby providers we have available */
3805 for( dwIndex=0;
3806 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3807 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3808 ++dwIndex, sizeOfSubKeyName=51 )
3811 HKEY hkServiceProvider;
3812 GUID serviceProviderGUID;
3813 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3814 char returnBuffer[51];
3815 WCHAR buff[51];
3816 DPNAME dpName;
3817 HRESULT hr;
3819 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3820 LPVOID lpAddressBuffer = NULL;
3821 DWORD dwAddressBufferSize = 0;
3823 TRACE(" this time through: %s\n", subKeyName );
3825 /* Get a handle for this particular service provider */
3826 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3827 &hkServiceProvider ) != ERROR_SUCCESS )
3829 ERR(": what the heck is going on?\n" );
3830 continue;
3833 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3834 NULL, &returnTypeGUID, returnBuffer,
3835 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3837 ERR(": missing GUID registry data members\n" );
3838 continue;
3841 /* FIXME: Check return types to ensure we're interpreting data right */
3842 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3843 CLSIDFromString( buff, &serviceProviderGUID );
3844 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3846 /* Fill in the DPNAME struct for the service provider */
3847 dpName.dwSize = sizeof( dpName );
3848 dpName.dwFlags = 0;
3849 dpName.u1.lpszShortNameA = subKeyName;
3850 dpName.u2.lpszLongNameA = NULL;
3852 /* Create the compound address for the service provider.
3853 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
3854 nast stuff. This may be why the native dll just gets around this little bit by
3855 allocating an 80 byte buffer which isn't even a filled with a valid compound
3856 address. Oh well. Creating a proper compound address is the way to go anyways
3857 despite this method taking slightly more heap space and realtime :) */
3859 dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
3860 dpCompoundAddress.dwDataSize = sizeof( GUID );
3861 dpCompoundAddress.lpData = &serviceProviderGUID;
3863 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3864 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
3866 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3867 return hr;
3870 /* Now allocate the buffer */
3871 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
3873 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3874 &dwAddressBufferSize, TRUE ) ) != DP_OK )
3876 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3877 return hr;
3880 /* The enumeration will return FALSE if we are not to continue */
3881 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3882 &dpName, DPCONNECTION_DIRECTPLAYLOBBY, lpContext ) )
3884 return DP_OK;
3889 return DP_OK;
3892 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
3893 ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3895 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3896 FIXME("(%p)->(%p,%p,%p,0x%08lx): stub\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3897 return DP_OK;
3900 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
3901 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
3902 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
3903 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
3905 lpGroupList lpGList;
3906 lpGroupData lpGData;
3908 FIXME( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
3909 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
3910 lpContext, dwFlags, bAnsi );
3912 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3914 return DPERR_INVALIDGROUP;
3917 if( DPQ_IS_EMPTY( lpGData->groups ) )
3919 return DP_OK;
3922 lpGList = DPQ_FIRST( lpGData->groups );
3924 for( ;; )
3926 /* FIXME: Should check dwFlags for match here */
3928 if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP,
3929 &lpGList->lpGData->name, dwFlags,
3930 lpContext ) )
3932 return DP_OK; /* User requested break */
3935 if( DPQ_IS_ENDOFLIST( lpGList->groups ) )
3937 break;
3940 lpGList = DPQ_NEXT( lpGList->groups );
3944 return DP_OK;
3947 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
3948 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3949 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3950 DWORD dwFlags )
3952 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3953 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3954 lpEnumPlayersCallback2, lpContext, dwFlags,
3955 TRUE );
3958 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
3959 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3960 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3961 DWORD dwFlags )
3963 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3964 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3965 lpEnumPlayersCallback2, lpContext, dwFlags,
3966 FALSE );
3969 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
3970 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3972 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3973 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3974 return DP_OK;
3977 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
3978 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3980 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
3981 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3982 return DP_OK;
3985 BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
3986 REFGUID guidDataType,
3987 DWORD dwDataSize,
3988 LPCVOID lpData,
3989 LPVOID lpContext )
3991 /* Looking for the GUID of the provider to load */
3992 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
3993 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
3996 TRACE( "Found SP/LP (%s) %s (data size = 0x%08lx)\n",
3997 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
3999 if( dwDataSize != sizeof( GUID ) )
4001 ERR( "Invalid sp/lp guid size 0x%08lx\n", dwDataSize );
4004 memcpy( lpContext, lpData, dwDataSize );
4006 /* There shouldn't be more than 1 GUID/compound address */
4007 return FALSE;
4010 /* Still waiting for what we want */
4011 return TRUE;
4015 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
4016 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
4018 UINT i;
4019 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4020 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
4021 LPCSTR guidDataSubKey = "Guid";
4022 LPCSTR majVerDataSubKey = "dwReserved1";
4023 LPCSTR minVerDataSubKey = "dwReserved2";
4024 LPCSTR pathSubKey = "Path";
4026 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
4028 /* FIXME: Cloned code with a quick hack. */
4029 for( i=0; i<2; i++ )
4031 HKEY hkResult;
4032 LPCSTR searchSubKey;
4033 char subKeyName[51];
4034 DWORD dwIndex, sizeOfSubKeyName=50;
4035 FILETIME filetime;
4037 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
4038 *lpbIsDpSp = (i == 0) ? TRUE : FALSE;
4041 /* Need to loop over the service providers in the registry */
4042 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4043 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4045 /* Hmmm. Does this mean that there are no service providers? */
4046 ERR(": no service providers?\n");
4047 return 0;
4050 /* Traverse all the service providers we have available */
4051 for( dwIndex=0;
4052 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4053 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4054 ++dwIndex, sizeOfSubKeyName=51 )
4057 HKEY hkServiceProvider;
4058 GUID serviceProviderGUID;
4059 DWORD returnType, sizeOfReturnBuffer = 255;
4060 char returnBuffer[256];
4061 WCHAR buff[51];
4062 DWORD dwTemp, len;
4064 TRACE(" this time through: %s\n", subKeyName );
4066 /* Get a handle for this particular service provider */
4067 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4068 &hkServiceProvider ) != ERROR_SUCCESS )
4070 ERR(": what the heck is going on?\n" );
4071 continue;
4074 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4075 NULL, &returnType, returnBuffer,
4076 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4078 ERR(": missing GUID registry data members\n" );
4079 continue;
4082 /* FIXME: Check return types to ensure we're interpreting data right */
4083 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4084 CLSIDFromString( buff, &serviceProviderGUID );
4085 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4087 /* Determine if this is the Service Provider that the user asked for */
4088 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
4090 continue;
4093 if( i == 0 ) /* DP SP */
4095 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
4096 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
4097 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
4100 sizeOfReturnBuffer = 255;
4102 /* Get dwReserved1 */
4103 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
4104 NULL, &returnType, returnBuffer,
4105 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4107 ERR(": missing dwReserved1 registry data members\n") ;
4108 continue;
4111 if( i == 0 )
4112 memcpy( &lpSpData->dwReserved1, returnBuffer, sizeof(lpSpData->dwReserved1) );
4114 sizeOfReturnBuffer = 255;
4116 /* Get dwReserved2 */
4117 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4118 NULL, &returnType, returnBuffer,
4119 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4121 ERR(": missing dwReserved1 registry data members\n") ;
4122 continue;
4125 if( i == 0 )
4126 memcpy( &lpSpData->dwReserved2, returnBuffer, sizeof(lpSpData->dwReserved2) );
4128 sizeOfReturnBuffer = 255;
4130 /* Get the path for this service provider */
4131 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
4132 NULL, NULL, returnBuffer,
4133 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
4135 ERR(": missing PATH registry data members: 0x%08lx\n", dwTemp );
4136 continue;
4139 TRACE( "Loading %s\n", returnBuffer );
4140 return LoadLibraryA( returnBuffer );
4144 return 0;
4147 static
4148 HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider )
4150 HRESULT hr;
4151 LPDPSP_SPINIT SPInit;
4153 /* Initialize the service provider by calling SPInit */
4154 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4156 if( SPInit == NULL )
4158 ERR( "Service provider doesn't provide SPInit interface?\n" );
4159 FreeLibrary( hServiceProvider );
4160 return DPERR_UNAVAILABLE;
4163 TRACE( "Calling SPInit (DP SP entry point)\n" );
4165 hr = (*SPInit)( &This->dp2->spData );
4167 if( FAILED(hr) )
4169 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4170 FreeLibrary( hServiceProvider );
4171 return hr;
4174 /* FIXME: Need to verify the sanity of the returned callback table
4175 * using IsBadCodePtr */
4176 This->dp2->bSPInitialized = TRUE;
4178 /* This interface is now initialized as a DP object */
4179 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
4181 /* Store the handle of the module so that we can unload it later */
4182 This->dp2->hServiceProvider = hServiceProvider;
4184 return hr;
4187 static
4188 HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hLobbyProvider )
4190 HRESULT hr;
4191 LPSP_INIT DPLSPInit;
4193 /* Initialize the service provider by calling SPInit */
4194 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
4196 if( DPLSPInit == NULL )
4198 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4199 FreeLibrary( hLobbyProvider );
4200 return DPERR_UNAVAILABLE;
4203 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4205 hr = (*DPLSPInit)( &This->dp2->dplspData );
4207 if( FAILED(hr) )
4209 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4210 FreeLibrary( hLobbyProvider );
4211 return hr;
4214 /* FIXME: Need to verify the sanity of the returned callback table
4215 * using IsBadCodePtr */
4217 This->dp2->bDPLSPInitialized = TRUE;
4219 /* This interface is now initialized as a lobby object */
4220 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
4222 /* Store the handle of the module so that we can unload it later */
4223 This->dp2->hDPLobbyProvider = hLobbyProvider;
4225 return hr;
4228 static HRESULT WINAPI DP_IF_InitializeConnection
4229 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi )
4231 HMODULE hServiceProvider;
4232 HRESULT hr;
4233 GUID guidSP;
4234 const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
4235 BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4237 TRACE("(%p)->(%p,0x%08lx,%u)\n", This, lpConnection, dwFlags, bAnsi );
4239 if( dwFlags != 0 )
4241 return DPERR_INVALIDFLAGS;
4244 /* Find out what the requested SP is and how large this buffer is */
4245 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
4246 dwAddrSize, &guidSP );
4248 if( FAILED(hr) )
4250 ERR( "Invalid compound address?\n" );
4251 return DPERR_UNAVAILABLE;
4254 /* Load the service provider */
4255 hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp );
4257 if( hServiceProvider == 0 )
4259 ERR( "Unable to load service provider\n" );
4260 return DPERR_UNAVAILABLE;
4263 if( bIsDpSp )
4265 /* Fill in what we can of the Service Provider required information.
4266 * The rest was be done in DP_LoadSP
4268 This->dp2->spData.lpAddress = lpConnection;
4269 This->dp2->spData.dwAddressSize = dwAddrSize;
4270 This->dp2->spData.lpGuid = &guidSP;
4272 hr = DP_InitializeDPSP( This, hServiceProvider );
4274 else
4276 This->dp2->dplspData.lpAddress = lpConnection;
4278 hr = DP_InitializeDPLSP( This, hServiceProvider );
4281 if( FAILED(hr) )
4283 return hr;
4286 return DP_OK;
4289 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4290 ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
4292 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4294 /* This may not be externally invoked once either an SP or LP is initialized */
4295 if( This->dp2->connectionInitialized != NO_PROVIDER )
4297 return DPERR_ALREADYINITIALIZED;
4300 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE );
4303 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4304 ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
4306 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4308 /* This may not be externally invoked once either an SP or LP is initialized */
4309 if( This->dp2->connectionInitialized != NO_PROVIDER )
4311 return DPERR_ALREADYINITIALIZED;
4314 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE );
4317 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4318 ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4319 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4321 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4322 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4325 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4326 ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4327 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4329 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */
4330 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4333 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4334 ( LPDIRECTPLAY3A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4336 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4337 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4338 return DP_OK;
4341 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4342 ( LPDIRECTPLAY3 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4344 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4345 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4346 return DP_OK;
4349 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4350 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4352 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4353 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4354 return DP_OK;
4357 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4358 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4360 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4361 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4362 return DP_OK;
4365 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4366 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup )
4368 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4369 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
4370 return DP_OK;
4373 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4374 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup )
4376 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4377 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
4378 return DP_OK;
4381 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4382 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDWORD lpdwFlags )
4384 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4385 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
4386 return DP_OK;
4389 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4390 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDWORD lpdwFlags )
4392 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4393 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
4394 return DP_OK;
4397 static HRESULT WINAPI DP_IF_GetGroupParent
4398 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
4399 BOOL bAnsi )
4401 lpGroupData lpGData;
4403 TRACE("(%p)->(0x%08lx,%p,%u)\n", This, idGroup, lpidGroup, bAnsi );
4405 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4407 return DPERR_INVALIDGROUP;
4410 *lpidGroup = lpGData->dpid;
4412 return DP_OK;
4415 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4416 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
4418 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4419 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE );
4421 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4422 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
4424 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4425 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE );
4428 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4429 ( LPDIRECTPLAY3A iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4431 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4432 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4433 return DP_OK;
4436 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4437 ( LPDIRECTPLAY3 iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4439 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4440 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4441 return DP_OK;
4444 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4445 ( LPDIRECTPLAY3A iface, DPID idPlayer, LPDWORD lpdwFlags )
4447 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4448 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
4449 return DP_OK;
4452 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4453 ( LPDIRECTPLAY3 iface, DPID idPlayer, LPDWORD lpdwFlags )
4455 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
4456 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
4457 return DP_OK;
4460 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4461 ( LPDIRECTPLAY4A iface, DPID idGroup, LPDPID lpidGroupOwner )
4463 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4464 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
4465 return DP_OK;
4468 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4469 ( LPDIRECTPLAY4 iface, DPID idGroup, LPDPID lpidGroupOwner )
4471 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4472 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
4473 return DP_OK;
4476 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4477 ( LPDIRECTPLAY4A iface, DPID idGroup , DPID idGroupOwner )
4479 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4480 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
4481 return DP_OK;
4484 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4485 ( LPDIRECTPLAY4 iface, DPID idGroup , DPID idGroupOwner )
4487 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4488 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
4489 return DP_OK;
4492 static HRESULT WINAPI DP_SendEx
4493 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4494 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4495 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi )
4497 lpPlayerList lpPList;
4498 lpGroupData lpGData;
4499 BOOL bValidDestination = FALSE;
4501 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx,0x%08lx,0x%08lx,%p,%p,%u)"
4502 ": stub\n",
4503 This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority,
4504 dwTimeout, lpContext, lpdwMsgID, bAnsi );
4506 /* FIXME: Add parameter checking */
4507 /* FIXME: First call to this needs to aquire a message id which will be
4508 * used for multiple sends
4511 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4513 /* Verify that the message is being sent from a valid local player. The
4514 * from player may be anonymous DPID_UNKNOWN
4516 if( idFrom != DPID_UNKNOWN )
4518 if( ( lpPList = DP_FindPlayer( This, idFrom ) ) == NULL )
4520 WARN( "INFO: Invalid from player 0x%08lx\n", idFrom );
4521 return DPERR_INVALIDPLAYER;
4525 /* Verify that the message is being sent to a valid player, group or to
4526 * everyone. If it's valid, send it to those players.
4528 if( idTo == DPID_ALLPLAYERS )
4530 bValidDestination = TRUE;
4532 /* See if SP has the ability to multicast. If so, use it */
4533 if( This->dp2->spData.lpCB->SendToGroupEx )
4535 FIXME( "Use group sendex to group 0\n" );
4537 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4539 FIXME( "Use obsolete group send to group 0\n" );
4541 else /* No multicast, multiplicate */
4543 /* Send to all players we know about */
4544 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4548 if( ( !bValidDestination ) &&
4549 ( DP_FindPlayer( This, idTo ) != NULL )
4552 bValidDestination = TRUE;
4554 /* Have the service provider send this message */
4555 /* FIXME: Could optimize for local interface sends */
4556 return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority,
4557 dwTimeout, lpContext, lpdwMsgID );
4560 if( ( !bValidDestination ) &&
4561 ( ( lpGData = DP_FindAnyGroup( This, idTo ) ) != NULL )
4564 bValidDestination = TRUE;
4566 /* See if SP has the ability to multicast. If so, use it */
4567 if( This->dp2->spData.lpCB->SendToGroupEx )
4569 FIXME( "Use group sendex\n" );
4571 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4573 FIXME( "Use obsolete group send to group\n" );
4575 else /* No multicast, multiplicate */
4577 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4580 #if 0
4581 if( bExpectReply )
4583 DWORD dwWaitReturn;
4585 This->dp2->hReplyEvent = CreateEventA( NULL, FALSE, FALSE, NULL );
4587 dwWaitReturn = WaitForSingleObject( hReplyEvent, dwTimeout );
4588 if( dwWaitReturn != WAIT_OBJECT_0 )
4590 ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
4593 #endif
4596 if( !bValidDestination )
4598 return DPERR_INVALIDPLAYER;
4600 else
4602 /* FIXME: Should return what the send returned */
4603 return DP_OK;
4608 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4609 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4610 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4611 LPVOID lpContext, LPDWORD lpdwMsgID )
4613 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4614 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4615 dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE );
4618 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4619 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4620 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4621 LPVOID lpContext, LPDWORD lpdwMsgID )
4623 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */
4624 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4625 dwPriority, dwTimeout, lpContext, lpdwMsgID, FALSE );
4628 static HRESULT WINAPI DP_SP_SendEx
4629 ( IDirectPlay2Impl* This, DWORD dwFlags,
4630 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4631 LPVOID lpContext, LPDWORD lpdwMsgID )
4633 LPDPMSG lpMElem;
4635 FIXME( ": stub\n" );
4637 /* FIXME: This queuing should only be for async messages */
4639 lpMElem = (LPDPMSG)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4640 sizeof( *lpMElem ) );
4641 lpMElem->msg = (DPMSG_GENERIC*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4642 dwDataSize );
4644 CopyMemory( lpMElem->msg, lpData, dwDataSize );
4646 /* FIXME: Need to queue based on priority */
4647 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
4649 return DP_OK;
4652 static HRESULT WINAPI DP_IF_GetMessageQueue
4653 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4654 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi )
4656 HRESULT hr = DP_OK;
4658 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,%p,%u): semi stub\n",
4659 This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi );
4661 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4662 /* FIXME: What about sends which are not immediate? */
4664 if( This->dp2->spData.lpCB->GetMessageQueue )
4666 DPSP_GETMESSAGEQUEUEDATA data;
4668 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4670 /* FIXME: None of this is documented :( */
4672 data.lpISP = This->dp2->spData.lpISP;
4673 data.dwFlags = dwFlags;
4674 data.idFrom = idFrom;
4675 data.idTo = idTo;
4676 data.lpdwNumMsgs = lpdwNumMsgs;
4677 data.lpdwNumBytes = lpdwNumBytes;
4679 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
4681 else
4683 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4686 return hr;
4689 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4690 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4691 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4693 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4694 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4695 lpdwNumBytes, TRUE );
4698 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4699 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4700 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4702 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4703 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4704 lpdwNumBytes, FALSE );
4707 static HRESULT WINAPI DP_IF_CancelMessage
4708 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
4709 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi )
4711 HRESULT hr = DP_OK;
4713 FIXME( "(%p)->(0x%08lx,0x%08lx,%u): semi stub\n",
4714 This, dwMsgID, dwFlags, bAnsi );
4716 if( This->dp2->spData.lpCB->Cancel )
4718 DPSP_CANCELDATA data;
4720 TRACE( "Calling SP Cancel\n" );
4722 /* FIXME: Undocumented callback */
4724 data.lpISP = This->dp2->spData.lpISP;
4725 data.dwFlags = dwFlags;
4726 data.lprglpvSPMsgID = NULL;
4727 data.cSPMsgID = dwMsgID;
4728 data.dwMinPriority = dwMinPriority;
4729 data.dwMaxPriority = dwMaxPriority;
4731 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
4733 else
4735 FIXME( "SP doesn't implement Cancel\n" );
4738 return hr;
4741 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
4742 ( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags )
4744 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4746 if( dwFlags != 0 )
4748 return DPERR_INVALIDFLAGS;
4751 if( dwMsgID == 0 )
4753 dwFlags |= DPCANCELSEND_ALL;
4756 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE );
4759 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
4760 ( LPDIRECTPLAY4 iface, DWORD dwMsgID, DWORD dwFlags )
4762 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4764 if( dwFlags != 0 )
4766 return DPERR_INVALIDFLAGS;
4769 if( dwMsgID == 0 )
4771 dwFlags |= DPCANCELSEND_ALL;
4774 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, FALSE );
4777 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
4778 ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4779 DWORD dwFlags )
4781 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4783 if( dwFlags != 0 )
4785 return DPERR_INVALIDFLAGS;
4788 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4789 dwMaxPriority, TRUE );
4792 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
4793 ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4794 DWORD dwFlags )
4796 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface;
4798 if( dwFlags != 0 )
4800 return DPERR_INVALIDFLAGS;
4803 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4804 dwMaxPriority, FALSE );
4807 /* Note: Hack so we can reuse the old functions without compiler warnings */
4808 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4809 # define XCAST(fun) (typeof(directPlay2WVT.fun))
4810 #else
4811 # define XCAST(fun) (void*)
4812 #endif
4814 static IDirectPlay2Vtbl directPlay2WVT =
4816 XCAST(QueryInterface)DP_QueryInterface,
4817 XCAST(AddRef)DP_AddRef,
4818 XCAST(Release)DP_Release,
4820 DirectPlay2WImpl_AddPlayerToGroup,
4821 DirectPlay2WImpl_Close,
4822 DirectPlay2WImpl_CreateGroup,
4823 DirectPlay2WImpl_CreatePlayer,
4824 DirectPlay2WImpl_DeletePlayerFromGroup,
4825 DirectPlay2WImpl_DestroyGroup,
4826 DirectPlay2WImpl_DestroyPlayer,
4827 DirectPlay2WImpl_EnumGroupPlayers,
4828 DirectPlay2WImpl_EnumGroups,
4829 DirectPlay2WImpl_EnumPlayers,
4830 DirectPlay2WImpl_EnumSessions,
4831 DirectPlay2WImpl_GetCaps,
4832 DirectPlay2WImpl_GetGroupData,
4833 DirectPlay2WImpl_GetGroupName,
4834 DirectPlay2WImpl_GetMessageCount,
4835 DirectPlay2WImpl_GetPlayerAddress,
4836 DirectPlay2WImpl_GetPlayerCaps,
4837 DirectPlay2WImpl_GetPlayerData,
4838 DirectPlay2WImpl_GetPlayerName,
4839 DirectPlay2WImpl_GetSessionDesc,
4840 DirectPlay2WImpl_Initialize,
4841 DirectPlay2WImpl_Open,
4842 DirectPlay2WImpl_Receive,
4843 DirectPlay2WImpl_Send,
4844 DirectPlay2WImpl_SetGroupData,
4845 DirectPlay2WImpl_SetGroupName,
4846 DirectPlay2WImpl_SetPlayerData,
4847 DirectPlay2WImpl_SetPlayerName,
4848 DirectPlay2WImpl_SetSessionDesc
4850 #undef XCAST
4852 /* Note: Hack so we can reuse the old functions without compiler warnings */
4853 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4854 # define XCAST(fun) (typeof(directPlay2AVT.fun))
4855 #else
4856 # define XCAST(fun) (void*)
4857 #endif
4859 static IDirectPlay2Vtbl directPlay2AVT =
4861 XCAST(QueryInterface)DP_QueryInterface,
4862 XCAST(AddRef)DP_AddRef,
4863 XCAST(Release)DP_Release,
4865 DirectPlay2AImpl_AddPlayerToGroup,
4866 DirectPlay2AImpl_Close,
4867 DirectPlay2AImpl_CreateGroup,
4868 DirectPlay2AImpl_CreatePlayer,
4869 DirectPlay2AImpl_DeletePlayerFromGroup,
4870 DirectPlay2AImpl_DestroyGroup,
4871 DirectPlay2AImpl_DestroyPlayer,
4872 DirectPlay2AImpl_EnumGroupPlayers,
4873 DirectPlay2AImpl_EnumGroups,
4874 DirectPlay2AImpl_EnumPlayers,
4875 DirectPlay2AImpl_EnumSessions,
4876 DirectPlay2AImpl_GetCaps,
4877 DirectPlay2AImpl_GetGroupData,
4878 DirectPlay2AImpl_GetGroupName,
4879 DirectPlay2AImpl_GetMessageCount,
4880 DirectPlay2AImpl_GetPlayerAddress,
4881 DirectPlay2AImpl_GetPlayerCaps,
4882 DirectPlay2AImpl_GetPlayerData,
4883 DirectPlay2AImpl_GetPlayerName,
4884 DirectPlay2AImpl_GetSessionDesc,
4885 DirectPlay2AImpl_Initialize,
4886 DirectPlay2AImpl_Open,
4887 DirectPlay2AImpl_Receive,
4888 DirectPlay2AImpl_Send,
4889 DirectPlay2AImpl_SetGroupData,
4890 DirectPlay2AImpl_SetGroupName,
4891 DirectPlay2AImpl_SetPlayerData,
4892 DirectPlay2AImpl_SetPlayerName,
4893 DirectPlay2AImpl_SetSessionDesc
4895 #undef XCAST
4898 /* Note: Hack so we can reuse the old functions without compiler warnings */
4899 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4900 # define XCAST(fun) (typeof(directPlay3AVT.fun))
4901 #else
4902 # define XCAST(fun) (void*)
4903 #endif
4905 static IDirectPlay3Vtbl directPlay3AVT =
4907 XCAST(QueryInterface)DP_QueryInterface,
4908 XCAST(AddRef)DP_AddRef,
4909 XCAST(Release)DP_Release,
4911 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
4912 XCAST(Close)DirectPlay2AImpl_Close,
4913 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
4914 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
4915 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
4916 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
4917 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
4918 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
4919 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
4920 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
4921 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
4922 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
4923 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
4924 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
4925 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
4926 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
4927 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
4928 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
4929 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
4930 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
4931 XCAST(Initialize)DirectPlay2AImpl_Initialize,
4932 XCAST(Open)DirectPlay2AImpl_Open,
4933 XCAST(Receive)DirectPlay2AImpl_Receive,
4934 XCAST(Send)DirectPlay2AImpl_Send,
4935 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
4936 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
4937 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
4938 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
4939 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
4941 DirectPlay3AImpl_AddGroupToGroup,
4942 DirectPlay3AImpl_CreateGroupInGroup,
4943 DirectPlay3AImpl_DeleteGroupFromGroup,
4944 DirectPlay3AImpl_EnumConnections,
4945 DirectPlay3AImpl_EnumGroupsInGroup,
4946 DirectPlay3AImpl_GetGroupConnectionSettings,
4947 DirectPlay3AImpl_InitializeConnection,
4948 DirectPlay3AImpl_SecureOpen,
4949 DirectPlay3AImpl_SendChatMessage,
4950 DirectPlay3AImpl_SetGroupConnectionSettings,
4951 DirectPlay3AImpl_StartSession,
4952 DirectPlay3AImpl_GetGroupFlags,
4953 DirectPlay3AImpl_GetGroupParent,
4954 DirectPlay3AImpl_GetPlayerAccount,
4955 DirectPlay3AImpl_GetPlayerFlags
4957 #undef XCAST
4959 /* Note: Hack so we can reuse the old functions without compiler warnings */
4960 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4961 # define XCAST(fun) (typeof(directPlay3WVT.fun))
4962 #else
4963 # define XCAST(fun) (void*)
4964 #endif
4965 static IDirectPlay3Vtbl directPlay3WVT =
4967 XCAST(QueryInterface)DP_QueryInterface,
4968 XCAST(AddRef)DP_AddRef,
4969 XCAST(Release)DP_Release,
4971 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
4972 XCAST(Close)DirectPlay2WImpl_Close,
4973 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
4974 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
4975 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
4976 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
4977 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
4978 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
4979 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
4980 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
4981 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
4982 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
4983 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
4984 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
4985 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
4986 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
4987 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
4988 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
4989 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
4990 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
4991 XCAST(Initialize)DirectPlay2WImpl_Initialize,
4992 XCAST(Open)DirectPlay2WImpl_Open,
4993 XCAST(Receive)DirectPlay2WImpl_Receive,
4994 XCAST(Send)DirectPlay2WImpl_Send,
4995 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
4996 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
4997 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
4998 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
4999 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5001 DirectPlay3WImpl_AddGroupToGroup,
5002 DirectPlay3WImpl_CreateGroupInGroup,
5003 DirectPlay3WImpl_DeleteGroupFromGroup,
5004 DirectPlay3WImpl_EnumConnections,
5005 DirectPlay3WImpl_EnumGroupsInGroup,
5006 DirectPlay3WImpl_GetGroupConnectionSettings,
5007 DirectPlay3WImpl_InitializeConnection,
5008 DirectPlay3WImpl_SecureOpen,
5009 DirectPlay3WImpl_SendChatMessage,
5010 DirectPlay3WImpl_SetGroupConnectionSettings,
5011 DirectPlay3WImpl_StartSession,
5012 DirectPlay3WImpl_GetGroupFlags,
5013 DirectPlay3WImpl_GetGroupParent,
5014 DirectPlay3WImpl_GetPlayerAccount,
5015 DirectPlay3WImpl_GetPlayerFlags
5017 #undef XCAST
5019 /* Note: Hack so we can reuse the old functions without compiler warnings */
5020 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5021 # define XCAST(fun) (typeof(directPlay4WVT.fun))
5022 #else
5023 # define XCAST(fun) (void*)
5024 #endif
5025 static IDirectPlay4Vtbl directPlay4WVT =
5027 XCAST(QueryInterface)DP_QueryInterface,
5028 XCAST(AddRef)DP_AddRef,
5029 XCAST(Release)DP_Release,
5031 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
5032 XCAST(Close)DirectPlay2WImpl_Close,
5033 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
5034 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
5035 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
5036 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
5037 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5038 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5039 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5040 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5041 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5042 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5043 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5044 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5045 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5046 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5047 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5048 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5049 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5050 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5051 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5052 XCAST(Open)DirectPlay2WImpl_Open,
5053 XCAST(Receive)DirectPlay2WImpl_Receive,
5054 XCAST(Send)DirectPlay2WImpl_Send,
5055 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5056 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5057 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5058 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5059 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5061 XCAST(AddGroupToGroup)DirectPlay3WImpl_AddGroupToGroup,
5062 XCAST(CreateGroupInGroup)DirectPlay3WImpl_CreateGroupInGroup,
5063 XCAST(DeleteGroupFromGroup)DirectPlay3WImpl_DeleteGroupFromGroup,
5064 XCAST(EnumConnections)DirectPlay3WImpl_EnumConnections,
5065 XCAST(EnumGroupsInGroup)DirectPlay3WImpl_EnumGroupsInGroup,
5066 XCAST(GetGroupConnectionSettings)DirectPlay3WImpl_GetGroupConnectionSettings,
5067 XCAST(InitializeConnection)DirectPlay3WImpl_InitializeConnection,
5068 XCAST(SecureOpen)DirectPlay3WImpl_SecureOpen,
5069 XCAST(SendChatMessage)DirectPlay3WImpl_SendChatMessage,
5070 XCAST(SetGroupConnectionSettings)DirectPlay3WImpl_SetGroupConnectionSettings,
5071 XCAST(StartSession)DirectPlay3WImpl_StartSession,
5072 XCAST(GetGroupFlags)DirectPlay3WImpl_GetGroupFlags,
5073 XCAST(GetGroupParent)DirectPlay3WImpl_GetGroupParent,
5074 XCAST(GetPlayerAccount)DirectPlay3WImpl_GetPlayerAccount,
5075 XCAST(GetPlayerFlags)DirectPlay3WImpl_GetPlayerFlags,
5077 DirectPlay4WImpl_GetGroupOwner,
5078 DirectPlay4WImpl_SetGroupOwner,
5079 DirectPlay4WImpl_SendEx,
5080 DirectPlay4WImpl_GetMessageQueue,
5081 DirectPlay4WImpl_CancelMessage,
5082 DirectPlay4WImpl_CancelPriority
5084 #undef XCAST
5087 /* Note: Hack so we can reuse the old functions without compiler warnings */
5088 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5089 # define XCAST(fun) (typeof(directPlay4AVT.fun))
5090 #else
5091 # define XCAST(fun) (void*)
5092 #endif
5093 static IDirectPlay4Vtbl directPlay4AVT =
5095 XCAST(QueryInterface)DP_QueryInterface,
5096 XCAST(AddRef)DP_AddRef,
5097 XCAST(Release)DP_Release,
5099 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
5100 XCAST(Close)DirectPlay2AImpl_Close,
5101 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
5102 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
5103 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
5104 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
5105 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
5106 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
5107 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
5108 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
5109 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
5110 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
5111 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
5112 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
5113 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5114 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5115 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5116 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5117 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5118 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5119 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5120 XCAST(Open)DirectPlay2AImpl_Open,
5121 XCAST(Receive)DirectPlay2AImpl_Receive,
5122 XCAST(Send)DirectPlay2AImpl_Send,
5123 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5124 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5125 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5126 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5127 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5129 XCAST(AddGroupToGroup)DirectPlay3AImpl_AddGroupToGroup,
5130 XCAST(CreateGroupInGroup)DirectPlay3AImpl_CreateGroupInGroup,
5131 XCAST(DeleteGroupFromGroup)DirectPlay3AImpl_DeleteGroupFromGroup,
5132 XCAST(EnumConnections)DirectPlay3AImpl_EnumConnections,
5133 XCAST(EnumGroupsInGroup)DirectPlay3AImpl_EnumGroupsInGroup,
5134 XCAST(GetGroupConnectionSettings)DirectPlay3AImpl_GetGroupConnectionSettings,
5135 XCAST(InitializeConnection)DirectPlay3AImpl_InitializeConnection,
5136 XCAST(SecureOpen)DirectPlay3AImpl_SecureOpen,
5137 XCAST(SendChatMessage)DirectPlay3AImpl_SendChatMessage,
5138 XCAST(SetGroupConnectionSettings)DirectPlay3AImpl_SetGroupConnectionSettings,
5139 XCAST(StartSession)DirectPlay3AImpl_StartSession,
5140 XCAST(GetGroupFlags)DirectPlay3AImpl_GetGroupFlags,
5141 XCAST(GetGroupParent)DirectPlay3AImpl_GetGroupParent,
5142 XCAST(GetPlayerAccount)DirectPlay3AImpl_GetPlayerAccount,
5143 XCAST(GetPlayerFlags)DirectPlay3AImpl_GetPlayerFlags,
5145 DirectPlay4AImpl_GetGroupOwner,
5146 DirectPlay4AImpl_SetGroupOwner,
5147 DirectPlay4AImpl_SendEx,
5148 DirectPlay4AImpl_GetMessageQueue,
5149 DirectPlay4AImpl_CancelMessage,
5150 DirectPlay4AImpl_CancelPriority
5152 #undef XCAST
5154 extern
5155 HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP,
5156 DPID idPlayer,
5157 LPVOID* lplpData )
5159 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5161 if( lpPlayer == NULL )
5163 return DPERR_INVALIDPLAYER;
5166 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
5168 return DP_OK;
5171 extern
5172 HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP,
5173 DPID idPlayer,
5174 LPVOID lpData )
5176 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5178 if( lpPlayer == NULL )
5180 return DPERR_INVALIDPLAYER;
5183 lpPlayer->lpPData->lpSPPlayerData = lpData;
5185 return DP_OK;
5188 /***************************************************************************
5189 * DirectPlayEnumerate [DPLAYX.9]
5190 * DirectPlayEnumerateA [DPLAYX.2]
5192 * The pointer to the structure lpContext will be filled with the
5193 * appropriate data for each service offered by the OS. These services are
5194 * not necessarily available on this particular machine but are defined
5195 * as simple service providers under the "Service Providers" registry key.
5196 * This structure is then passed to lpEnumCallback for each of the different
5197 * services.
5199 * This API is useful only for applications written using DirectX3 or
5200 * worse. It is superseded by IDirectPlay3::EnumConnections which also
5201 * gives information on the actual connections.
5203 * defn of a service provider:
5204 * A dynamic-link library used by DirectPlay to communicate over a network.
5205 * The service provider contains all the network-specific code required
5206 * to send and receive messages. Online services and network operators can
5207 * supply service providers to use specialized hardware, protocols, communications
5208 * media, and network resources.
5210 * TODO: Allocate string buffer space from the heap (length from reg)
5211 * Pass real device driver numbers...
5212 * Get the GUID properly...
5214 HRESULT WINAPI DirectPlayEnumerateA( LPDPENUMDPCALLBACKA lpEnumCallback,
5215 LPVOID lpContext )
5218 HKEY hkResult;
5219 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
5220 DWORD dwIndex;
5221 DWORD sizeOfSubKeyName=50;
5222 char subKeyName[51];
5223 FILETIME filetime;
5225 TRACE(": lpEnumCallback=%p lpContext=%p\n", lpEnumCallback, lpContext );
5227 if( !lpEnumCallback || !*lpEnumCallback )
5229 return DPERR_INVALIDPARAMS;
5232 /* Need to loop over the service providers in the registry */
5233 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
5234 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
5236 /* Hmmm. Does this mean that there are no service providers? */
5237 ERR(": no service providers?\n");
5238 return DPERR_NOSERVICEPROVIDER;
5241 /* Traverse all the service providers we have available */
5242 for( dwIndex=0;
5243 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
5244 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
5245 ++dwIndex, sizeOfSubKeyName=50 )
5247 LPCSTR majVerDataSubKey = "dwReserved1";
5248 LPCSTR minVerDataSubKey = "dwReserved2";
5249 LPCSTR guidDataSubKey = "Guid";
5250 HKEY hkServiceProvider;
5251 GUID serviceProviderGUID;
5252 DWORD returnTypeGUID, returnTypeReserved, sizeOfReturnBuffer = 50;
5253 char returnBuffer[51];
5254 WCHAR buff[51];
5255 DWORD majVersionNum , minVersionNum = 0;
5257 TRACE(" this time through: %s\n", subKeyName );
5259 /* Get a handle for this particular service provider */
5260 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
5261 &hkServiceProvider ) != ERROR_SUCCESS )
5263 ERR(": what the heck is going on?\n" );
5264 continue;
5267 /* Get the GUID, Device major number and device minor number
5268 * from the registry.
5270 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
5271 NULL, &returnTypeGUID, returnBuffer,
5272 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5274 ERR(": missing GUID registry data members\n" );
5275 continue;
5278 /* FIXME: Check return types to ensure we're interpreting data right */
5279 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
5280 CLSIDFromString( buff, &serviceProviderGUID );
5282 /* FIXME: Need to know which of dwReserved1 and dwReserved2 are maj and min */
5284 sizeOfReturnBuffer = 50;
5285 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
5286 NULL, &returnTypeReserved, returnBuffer,
5287 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5289 ERR(": missing dwReserved1 registry data members\n") ;
5290 continue;
5292 memcpy( &majVersionNum, returnBuffer, sizeof(majVersionNum) );
5294 sizeOfReturnBuffer = 50;
5295 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
5296 NULL, &returnTypeReserved, returnBuffer,
5297 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5299 ERR(": missing dwReserved2 registry data members\n") ;
5300 continue;
5302 memcpy( &minVersionNum, returnBuffer, sizeof(minVersionNum) );
5305 /* The enumeration will return FALSE if we are not to continue */
5306 if( !lpEnumCallback( &serviceProviderGUID , subKeyName,
5307 majVersionNum, minVersionNum, lpContext ) )
5309 WARN("lpEnumCallback returning FALSE\n" );
5310 break;
5314 return DP_OK;
5318 /***************************************************************************
5319 * DirectPlayEnumerateW [DPLAYX.3]
5322 HRESULT WINAPI DirectPlayEnumerateW( LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5325 FIXME(":stub\n");
5327 return DPERR_OUTOFMEMORY;
5331 typedef struct tagCreateEnum
5333 LPVOID lpConn;
5334 LPCGUID lpGuid;
5335 } CreateEnumData, *lpCreateEnumData;
5337 /* Find and copy the matching connection for the SP guid */
5338 static BOOL CALLBACK cbDPCreateEnumConnections(
5339 LPCGUID lpguidSP,
5340 LPVOID lpConnection,
5341 DWORD dwConnectionSize,
5342 LPCDPNAME lpName,
5343 DWORD dwFlags,
5344 LPVOID lpContext)
5346 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5348 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5350 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5352 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5353 dwConnectionSize );
5354 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5356 /* Found the record that we were looking for */
5357 return FALSE;
5360 /* Haven't found what were looking for yet */
5361 return TRUE;
5365 /***************************************************************************
5366 * DirectPlayCreate [DPLAYX.1]
5369 HRESULT WINAPI DirectPlayCreate
5370 ( LPGUID lpGUID, LPDIRECTPLAY2 *lplpDP, IUnknown *pUnk)
5372 HRESULT hr;
5373 LPDIRECTPLAY3A lpDP3A;
5374 CreateEnumData cbData;
5376 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5378 if( pUnk != NULL )
5380 return CLASS_E_NOAGGREGATION;
5383 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5384 give them an IDirectPlay2A object and hope that doesn't cause problems */
5385 if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
5387 return DPERR_UNAVAILABLE;
5390 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
5392 /* The GUID_NULL means don't bind a service provider. Just return the
5393 interface as is */
5394 return DP_OK;
5397 /* Bind the desired service provider since lpGUID is non NULL */
5398 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
5400 /* We're going to use a DP3 interface */
5401 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
5402 (LPVOID*)&lpDP3A );
5403 if( FAILED(hr) )
5405 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
5406 return hr;
5409 cbData.lpConn = NULL;
5410 cbData.lpGuid = lpGUID;
5412 /* We were given a service provider, find info about it... */
5413 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
5414 &cbData, DPCONNECTION_DIRECTPLAY );
5415 if( ( FAILED(hr) ) ||
5416 ( cbData.lpConn == NULL )
5419 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
5420 IDirectPlayX_Release( lpDP3A );
5421 return DPERR_UNAVAILABLE;
5424 /* Initialize the service provider */
5425 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
5426 if( FAILED(hr) )
5428 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
5429 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5430 IDirectPlayX_Release( lpDP3A );
5431 return hr;
5434 /* Release our version of the interface now that we're done with it */
5435 IDirectPlayX_Release( lpDP3A );
5436 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5438 return DP_OK;