Ensure MIPMAP levels is reset when rebinding an existing texture to a
[wine/dcerpc.git] / dlls / dplayx / dplay.c
blobe4ab5aeb977958d2002fa248c420480736b9627f
1 /* Direct Play 2,3,4 Implementation
3 * Copyright 1998,1999,2000,2001 - Peter Hunnisett
5 * <presently under construction - contact hunnise@nortelnetworks.com>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "config.h"
23 #include "wine/port.h"
25 #include <string.h>
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
29 #include "windef.h"
30 #include "winerror.h"
31 #include "winbase.h"
32 #include "winnt.h"
33 #include "winreg.h"
34 #include "winnls.h"
35 #include "wine/unicode.h"
36 #include "dplay.h"
37 #include "wine/debug.h"
39 #include "dpinit.h"
40 #include "dplayx_global.h"
41 #include "name_server.h"
42 #include "dplayx_queue.h"
43 #include "dplaysp.h"
44 #include "dplay_global.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(dplay);
48 /* FIXME: Should this be externed? */
49 extern HRESULT DPL_CreateCompoundAddress
50 ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
51 LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
54 /* Local function prototypes */
55 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid );
56 static lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* iface, LPDPID lpid,
57 LPDPNAME lpName, DWORD dwFlags,
58 HANDLE hEvent, BOOL bAnsi );
59 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi );
60 static void DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
61 LPVOID lpData, DWORD dwDataSize );
63 static lpGroupData DP_CreateGroup( IDirectPlay2AImpl* iface, LPDPID lpid,
64 LPDPNAME lpName, DWORD dwFlags,
65 DPID idParent, BOOL bAnsi );
66 static void DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
67 LPVOID lpData, DWORD dwDataSize );
68 static void DP_DeleteDPNameStruct( LPDPNAME lpDPName );
69 static void DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid );
70 static BOOL CALLBACK cbDeletePlayerFromAllGroups( DPID dpId,
71 DWORD dwPlayerType,
72 LPCDPNAME lpName,
73 DWORD dwFlags,
74 LPVOID lpContext );
75 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid );
76 static BOOL CALLBACK cbRemoveGroupOrPlayer( DPID dpId, DWORD dwPlayerType,
77 LPCDPNAME lpName, DWORD dwFlags,
78 LPVOID lpContext );
79 static void DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid );
81 /* Helper methods for player/group interfaces */
82 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
83 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
84 DPID idPlayer, BOOL bAnsi );
85 static HRESULT WINAPI DP_IF_CreatePlayer
86 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, LPDPID lpidPlayer,
87 LPDPNAME lpPlayerName, HANDLE hEvent, LPVOID lpData,
88 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
89 static HRESULT WINAPI DP_IF_DestroyGroup
90 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi );
91 static HRESULT WINAPI DP_IF_DestroyPlayer
92 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi );
93 static HRESULT WINAPI DP_IF_EnumGroupPlayers
94 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
95 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
96 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
97 static HRESULT WINAPI DP_IF_EnumGroups
98 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
99 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
100 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
101 static HRESULT WINAPI DP_IF_EnumPlayers
102 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
103 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
104 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
105 static HRESULT WINAPI DP_IF_GetGroupData
106 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
107 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
108 static HRESULT WINAPI DP_IF_GetGroupName
109 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
110 LPDWORD lpdwDataSize, BOOL bAnsi );
111 static HRESULT WINAPI DP_IF_GetPlayerData
112 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
113 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
114 static HRESULT WINAPI DP_IF_GetPlayerName
115 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
116 LPDWORD lpdwDataSize, BOOL bAnsi );
117 static HRESULT WINAPI DP_IF_SetGroupName
118 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
119 DWORD dwFlags, BOOL bAnsi );
120 static HRESULT WINAPI DP_IF_SetPlayerData
121 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
122 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
123 static HRESULT WINAPI DP_IF_SetPlayerName
124 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
125 DWORD dwFlags, BOOL bAnsi );
126 static HRESULT WINAPI DP_IF_AddGroupToGroup
127 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
128 static HRESULT WINAPI DP_IF_CreateGroup
129 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
130 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
131 DWORD dwFlags, BOOL bAnsi );
132 static HRESULT WINAPI DP_IF_CreateGroupInGroup
133 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
134 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
135 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
136 static HRESULT WINAPI DP_IF_AddPlayerToGroup
137 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
138 DPID idPlayer, BOOL bAnsi );
139 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
140 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
141 static HRESULT WINAPI DP_SetSessionDesc
142 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
143 DWORD dwFlags, BOOL bInitial, BOOL bAnsi );
144 static HRESULT WINAPI DP_SecureOpen
145 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
146 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
147 BOOL bAnsi );
148 static HRESULT WINAPI DP_SendEx
149 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
150 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
151 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi );
152 static HRESULT WINAPI DP_IF_Receive
153 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
154 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi );
155 static HRESULT WINAPI DP_IF_GetMessageQueue
156 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
157 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi );
158 static HRESULT WINAPI DP_SP_SendEx
159 ( IDirectPlay2Impl* This, DWORD dwFlags,
160 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
161 LPVOID lpContext, LPDWORD lpdwMsgID );
162 static HRESULT WINAPI DP_IF_SetGroupData
163 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
164 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
165 static HRESULT WINAPI DP_IF_GetPlayerCaps
166 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
167 DWORD dwFlags );
168 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi );
169 static HRESULT WINAPI DP_IF_CancelMessage
170 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
171 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi );
172 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
173 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
174 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
175 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
176 static HRESULT WINAPI DP_IF_GetGroupParent
177 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
178 BOOL bAnsi );
179 static HRESULT WINAPI DP_IF_GetCaps
180 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags );
181 static HRESULT WINAPI DP_IF_EnumSessions
182 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
183 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
184 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
185 static HRESULT WINAPI DP_IF_InitializeConnection
186 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi );
187 static BOOL CALLBACK cbDPCreateEnumConnections( LPCGUID lpguidSP,
188 LPVOID lpConnection, DWORD dwConnectionSize, LPCDPNAME lpName,
189 DWORD dwFlags, LPVOID lpContext );
190 static BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
191 LPDWORD lpdwBufSize );
195 static inline DPID DP_NextObjectId(void);
196 static DPID DP_GetRemoteNextObjectId(void);
199 static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc,
200 LPCDPSESSIONDESC2 srcSessDesc, BOOL bAnsi );
203 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp );
204 static HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider );
205 static HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hServiceProvider );
212 #define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */
213 #define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported
214 we don't have to change much */
215 #define DPID_NAME_SERVER 0x19a9d65b /* Don't ask me why */
217 /* Strip out dwFlag values which cannot be sent in the CREATEGROUP msg */
218 #define DPMSG_CREATEGROUP_DWFLAGS(x) ( (x) & DPGROUP_HIDDEN )
220 /* Strip out all dwFlags values for CREATEPLAYER msg */
221 #define DPMSG_CREATEPLAYER_DWFLAGS(x) 0
223 static DWORD kludgePlayerGroupId = 1000;
225 /* ------------------------------------------------------------------ */
228 static BOOL DP_CreateIUnknown( LPVOID lpDP )
230 ICOM_THIS(IDirectPlay2AImpl,lpDP);
232 This->unk = (DirectPlayIUnknownData*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
233 sizeof( *(This->unk) ) );
234 if ( This->unk == NULL )
236 return FALSE;
239 InitializeCriticalSection( &This->unk->DP_lock );
241 return TRUE;
244 static BOOL DP_DestroyIUnknown( LPVOID lpDP )
246 ICOM_THIS(IDirectPlay2AImpl,lpDP);
248 DeleteCriticalSection( &This->unk->DP_lock );
249 HeapFree( GetProcessHeap(), 0, This->unk );
251 return TRUE;
254 static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
256 ICOM_THIS(IDirectPlay2AImpl,lpDP);
258 This->dp2 = (DirectPlay2Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
259 sizeof( *(This->dp2) ) );
260 if ( This->dp2 == NULL )
262 return FALSE;
265 This->dp2->bConnectionOpen = FALSE;
267 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
269 This->dp2->bHostInterface = FALSE;
271 DPQ_INIT(This->dp2->receiveMsgs);
272 DPQ_INIT(This->dp2->sendMsgs);
273 DPQ_INIT(This->dp2->replysExpected);
275 if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
277 /* FIXME: Memory leak */
278 return FALSE;
281 /* Provide an initial session desc with nothing in it */
282 This->dp2->lpSessionDesc = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
283 HEAP_ZERO_MEMORY,
284 sizeof( *This->dp2->lpSessionDesc ) );
285 if( This->dp2->lpSessionDesc == NULL )
287 /* FIXME: Memory leak */
288 return FALSE;
290 This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc );
292 /* We are a emulating a dp 6 implementation */
293 This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION;
295 This->dp2->spData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
296 sizeof( *This->dp2->spData.lpCB ) );
297 This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB );
298 This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION;
300 /* This is the pointer to the service provider */
301 if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP,
302 (LPVOID*)&This->dp2->spData.lpISP, This ) )
305 /* FIXME: Memory leak */
306 return FALSE;
309 /* Setup lobby provider information */
310 This->dp2->dplspData.dwSPVersion = DPSP_MAJORVERSION;
311 This->dp2->dplspData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
312 sizeof( *This->dp2->dplspData.lpCB ) );
313 This->dp2->dplspData.lpCB->dwSize = sizeof( *This->dp2->dplspData.lpCB );
315 if( FAILED( DPLSP_CreateInterface( &IID_IDPLobbySP,
316 (LPVOID*)&This->dp2->dplspData.lpISP, This ) )
319 /* FIXME: Memory leak */
320 return FALSE;
323 return TRUE;
326 /* Definition of the global function in dplayx_queue.h. #
327 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
328 DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
330 HeapFree( GetProcessHeap(), 0, elem );
333 /* Function to delete the list of groups with this interface. Needs to
334 * delete the group and player lists associated with this group as well
335 * as the group data associated with this group. It should not delete
336 * player data as that is shared with the top player list and will be
337 * deleted with that.
339 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList );
340 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList )
342 DPQ_DELETEQ( elem->lpGData->groups, groups,
343 lpGroupList, cbDeleteElemFromHeap );
344 DPQ_DELETEQ( elem->lpGData->players, players,
345 lpPlayerList, cbDeleteElemFromHeap );
346 HeapFree( GetProcessHeap(), 0, elem->lpGData );
347 HeapFree( GetProcessHeap(), 0, elem );
350 /* Function to delete the list of players with this interface. Needs to
351 * delete the player data for all players as well.
353 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList );
354 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList )
356 HeapFree( GetProcessHeap(), 0, elem->lpPData );
357 HeapFree( GetProcessHeap(), 0, elem );
360 static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
362 ICOM_THIS(IDirectPlay2AImpl,lpDP);
364 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
366 TerminateThread( This->dp2->hEnumSessionThread, 0 );
367 CloseHandle( This->dp2->hEnumSessionThread );
370 /* Finish with the SP - have it shutdown */
371 if( This->dp2->spData.lpCB->ShutdownEx )
373 DPSP_SHUTDOWNDATA data;
375 TRACE( "Calling SP ShutdownEx\n" );
377 data.lpISP = This->dp2->spData.lpISP;
379 (*This->dp2->spData.lpCB->ShutdownEx)( &data );
381 else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
383 TRACE( "Calling obsolete SP Shutdown\n" );
384 (*This->dp2->spData.lpCB->Shutdown)();
387 /* Unload the SP (if it exists) */
388 if( This->dp2->hServiceProvider != 0 )
390 FreeLibrary( This->dp2->hServiceProvider );
393 /* Unload the Lobby Provider (if it exists) */
394 if( This->dp2->hDPLobbyProvider != 0 )
396 FreeLibrary( This->dp2->hDPLobbyProvider );
399 #if 0
400 DPQ_DELETEQ( This->dp2->players, players, lpPlayerList, cbDeletePlayerElem );
401 DPQ_DELETEQ( This->dp2->groups, groups, lpGroupList, cbDeleteGroupsElem );
402 #endif
404 /* FIXME: Need to delete receive and send msgs queue contents */
406 NS_DeleteSessionCache( This->dp2->lpNameServerData );
408 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
410 IDirectPlaySP_Release( This->dp2->spData.lpISP );
412 /* Delete the contents */
413 HeapFree( GetProcessHeap(), 0, This->dp2 );
415 return TRUE;
418 static BOOL DP_CreateDirectPlay3( LPVOID lpDP )
420 ICOM_THIS(IDirectPlay3AImpl,lpDP);
422 This->dp3 = (DirectPlay3Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
423 sizeof( *(This->dp3) ) );
424 if ( This->dp3 == NULL )
426 return FALSE;
429 return TRUE;
432 static BOOL DP_DestroyDirectPlay3( LPVOID lpDP )
434 ICOM_THIS(IDirectPlay3AImpl,lpDP);
436 /* Delete the contents */
437 HeapFree( GetProcessHeap(), 0, This->dp3 );
439 return TRUE;
442 static BOOL DP_CreateDirectPlay4( LPVOID lpDP )
444 ICOM_THIS(IDirectPlay4AImpl,lpDP);
446 This->dp4 = (DirectPlay4Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
447 sizeof( *(This->dp4) ) );
448 if ( This->dp4 == NULL )
450 return FALSE;
453 return TRUE;
456 static BOOL DP_DestroyDirectPlay4( LPVOID lpDP )
458 ICOM_THIS(IDirectPlay3AImpl,lpDP);
460 /* Delete the contents */
461 HeapFree( GetProcessHeap(), 0, This->dp4 );
463 return TRUE;
467 /* Create a new interface */
468 extern
469 HRESULT DP_CreateInterface
470 ( REFIID riid, LPVOID* ppvObj )
472 TRACE( " for %s\n", debugstr_guid( riid ) );
474 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
475 sizeof( IDirectPlay2Impl ) );
477 if( *ppvObj == NULL )
479 return DPERR_OUTOFMEMORY;
482 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
484 ICOM_THIS(IDirectPlay2Impl,*ppvObj);
485 This->lpVtbl = &directPlay2WVT;
487 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
489 ICOM_THIS(IDirectPlay2AImpl,*ppvObj);
490 This->lpVtbl = &directPlay2AVT;
492 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
494 ICOM_THIS(IDirectPlay3Impl,*ppvObj);
495 This->lpVtbl = &directPlay3WVT;
497 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
499 ICOM_THIS(IDirectPlay3AImpl,*ppvObj);
500 This->lpVtbl = &directPlay3AVT;
502 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
504 ICOM_THIS(IDirectPlay4Impl,*ppvObj);
505 This->lpVtbl = &directPlay4WVT;
507 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
509 ICOM_THIS(IDirectPlay4AImpl,*ppvObj);
510 This->lpVtbl = &directPlay4AVT;
512 else
514 /* Unsupported interface */
515 HeapFree( GetProcessHeap(), 0, *ppvObj );
516 *ppvObj = NULL;
518 return E_NOINTERFACE;
521 /* Initialize it */
522 if ( DP_CreateIUnknown( *ppvObj ) &&
523 DP_CreateDirectPlay2( *ppvObj ) &&
524 DP_CreateDirectPlay3( *ppvObj ) &&
525 DP_CreateDirectPlay4( *ppvObj )
528 IDirectPlayX_AddRef( (LPDIRECTPLAY2A)*ppvObj );
530 return S_OK;
533 /* Initialize failed, destroy it */
534 DP_DestroyDirectPlay4( *ppvObj );
535 DP_DestroyDirectPlay3( *ppvObj );
536 DP_DestroyDirectPlay2( *ppvObj );
537 DP_DestroyIUnknown( *ppvObj );
539 HeapFree( GetProcessHeap(), 0, *ppvObj );
541 *ppvObj = NULL;
542 return DPERR_NOMEMORY;
546 /* Direct Play methods */
548 /* Shared between all dplay types */
549 static HRESULT WINAPI DP_QueryInterface
550 ( LPDIRECTPLAY2 iface, REFIID riid, LPVOID* ppvObj )
552 ICOM_THIS(IDirectPlay2Impl,iface);
553 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
555 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
556 sizeof( *This ) );
558 if( *ppvObj == NULL )
560 return DPERR_OUTOFMEMORY;
563 CopyMemory( *ppvObj, This, sizeof( *This ) );
564 (*(IDirectPlay2Impl**)ppvObj)->ulInterfaceRef = 0;
566 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
568 ICOM_THIS(IDirectPlay2Impl,*ppvObj);
569 This->lpVtbl = &directPlay2WVT;
571 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
573 ICOM_THIS(IDirectPlay2AImpl,*ppvObj);
574 This->lpVtbl = &directPlay2AVT;
576 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
578 ICOM_THIS(IDirectPlay3Impl,*ppvObj);
579 This->lpVtbl = &directPlay3WVT;
581 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
583 ICOM_THIS(IDirectPlay3AImpl,*ppvObj);
584 This->lpVtbl = &directPlay3AVT;
586 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
588 ICOM_THIS(IDirectPlay4Impl,*ppvObj);
589 This->lpVtbl = &directPlay4WVT;
591 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
593 ICOM_THIS(IDirectPlay4AImpl,*ppvObj);
594 This->lpVtbl = &directPlay4AVT;
596 else
598 /* Unsupported interface */
599 HeapFree( GetProcessHeap(), 0, *ppvObj );
600 *ppvObj = NULL;
602 return E_NOINTERFACE;
605 IDirectPlayX_AddRef( (LPDIRECTPLAY2)*ppvObj );
607 return S_OK;
610 /* Shared between all dplay types */
611 static ULONG WINAPI DP_AddRef
612 ( LPDIRECTPLAY3 iface )
614 ULONG ulInterfaceRefCount, ulObjRefCount;
615 ICOM_THIS(IDirectPlay3Impl,iface);
617 ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
618 ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
620 TRACE( "ref count incremented to %lu:%lu for %p\n",
621 ulInterfaceRefCount, ulObjRefCount, This );
623 return ulObjRefCount;
626 static ULONG WINAPI DP_Release
627 ( LPDIRECTPLAY3 iface )
629 ULONG ulInterfaceRefCount, ulObjRefCount;
631 ICOM_THIS(IDirectPlay3Impl,iface);
633 ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
634 ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
636 TRACE( "ref count decremented to %lu:%lu for %p\n",
637 ulInterfaceRefCount, ulObjRefCount, This );
639 /* Deallocate if this is the last reference to the object */
640 if( ulObjRefCount == 0 )
642 /* If we're destroying the object, this must be the last ref
643 of the last interface */
644 DP_DestroyDirectPlay4( This );
645 DP_DestroyDirectPlay3( This );
646 DP_DestroyDirectPlay2( This );
647 DP_DestroyIUnknown( This );
650 /* Deallocate the interface */
651 if( ulInterfaceRefCount == 0 )
653 HeapFree( GetProcessHeap(), 0, This );
656 return ulObjRefCount;
659 static inline DPID DP_NextObjectId(void)
661 return (DPID)InterlockedIncrement( &kludgePlayerGroupId );
664 /* *lplpReply will be non NULL iff there is something to reply */
665 HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpcMessageBody,
666 DWORD dwMessageBodySize, LPCVOID lpcMessageHeader,
667 WORD wCommandId, WORD wVersion,
668 LPVOID* lplpReply, LPDWORD lpdwMsgSize )
670 TRACE( "(%p)->(%p,0x%08lx,%p,%u,%u)\n",
671 This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId,
672 wVersion );
674 switch( wCommandId )
676 /* Name server needs to handle this request */
677 case DPMSGCMD_ENUMSESSIONSREQUEST:
679 /* Reply expected */
680 NS_ReplyToEnumSessionsRequest( lpcMessageBody, lplpReply, lpdwMsgSize, This );
682 break;
685 /* Name server needs to handle this request */
686 case DPMSGCMD_ENUMSESSIONSREPLY:
688 /* No reply expected */
689 NS_AddRemoteComputerAsNameServer( lpcMessageHeader,
690 This->dp2->spData.dwSPHeaderSize,
691 (LPDPMSG_ENUMSESSIONSREPLY)lpcMessageBody,
692 This->dp2->lpNameServerData );
693 break;
696 case DPMSGCMD_REQUESTNEWPLAYERID:
698 LPCDPMSG_REQUESTNEWPLAYERID lpcMsg =
699 (LPCDPMSG_REQUESTNEWPLAYERID)lpcMessageBody;
701 LPDPMSG_NEWPLAYERIDREPLY lpReply;
703 *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
705 *lplpReply = (LPDPMSG_NEWPLAYERIDREPLY)HeapAlloc( GetProcessHeap(),
706 HEAP_ZERO_MEMORY,
707 *lpdwMsgSize );
709 FIXME( "Ignoring dwFlags 0x%08lx in request msg\n",
710 lpcMsg->dwFlags );
712 /* Setup the reply */
713 lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) +
714 This->dp2->spData.dwSPHeaderSize );
716 lpReply->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
717 lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY;
718 lpReply->envelope.wVersion = DPMSGVER_DP6;
720 lpReply->dpidNewPlayerId = DP_NextObjectId();
722 TRACE( "Allocating new playerid 0x%08lx from remote request\n",
723 lpReply->dpidNewPlayerId );
725 break;
728 case DPMSGCMD_GETNAMETABLEREPLY:
729 case DPMSGCMD_NEWPLAYERIDREPLY:
732 #if 0
733 if( wCommandId == DPMSGCMD_NEWPLAYERIDREPLY )
734 DebugBreak();
735 #endif
736 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
738 break;
741 #if 1
742 case DPMSGCMD_JUSTENVELOPE:
744 TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08lx\n", lpcMessageHeader, ((LPDWORD)lpcMessageHeader)[1] );
745 NS_SetLocalAddr( This->dp2->lpNameServerData, lpcMessageHeader, 20 );
746 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
748 #endif
750 case DPMSGCMD_FORWARDADDPLAYER:
752 #if 0
753 DebugBreak();
754 #endif
755 #if 1
756 TRACE( "Sending message to self to get my addr\n" );
757 DP_MSG_ToSelf( This, 1 ); /* This is a hack right now */
758 #endif
759 break;
762 case DPMSGCMD_FORWARDADDPLAYERNACK:
764 DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
765 break;
768 default:
770 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
771 DebugBreak();
772 break;
776 /* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */
778 return DP_OK;
782 static HRESULT WINAPI DP_IF_AddPlayerToGroup
783 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
784 DPID idPlayer, BOOL bAnsi )
786 lpGroupData lpGData;
787 lpPlayerList lpPList;
788 lpPlayerList lpNewPList;
790 TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
791 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
793 /* Find the group */
794 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
796 return DPERR_INVALIDGROUP;
799 /* Find the player */
800 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
802 return DPERR_INVALIDPLAYER;
805 /* Create a player list (ie "shortcut" ) */
806 lpNewPList = (lpPlayerList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
807 sizeof( *lpNewPList ) );
808 if( lpNewPList == NULL )
810 return DPERR_CANTADDPLAYER;
813 /* Add the shortcut */
814 lpPList->lpPData->uRef++;
815 lpNewPList->lpPData = lpPList->lpPData;
817 /* Add the player to the list of players for this group */
818 DPQ_INSERT(lpGData->players,lpNewPList,players);
820 /* Let the SP know that we've added a player to the group */
821 if( This->dp2->spData.lpCB->AddPlayerToGroup )
823 DPSP_ADDPLAYERTOGROUPDATA data;
825 TRACE( "Calling SP AddPlayerToGroup\n" );
827 data.idPlayer = idPlayer;
828 data.idGroup = idGroup;
829 data.lpISP = This->dp2->spData.lpISP;
831 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
834 /* Inform all other peers of the addition of player to the group. If there are
835 * no peers keep this event quiet.
836 * Also, if this event was the result of another machine sending it to us,
837 * don't bother rebroadcasting it.
839 if( ( lpMsgHdr == NULL ) &&
840 This->dp2->lpSessionDesc &&
841 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
843 DPMSG_ADDPLAYERTOGROUP msg;
844 msg.dwType = DPSYS_ADDPLAYERTOGROUP;
846 msg.dpIdGroup = idGroup;
847 msg.dpIdPlayer = idPlayer;
849 /* FIXME: Correct to just use send effectively? */
850 /* FIXME: Should size include data w/ message or just message "header" */
851 /* FIXME: Check return code */
852 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
855 return DP_OK;
858 static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
859 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
861 ICOM_THIS(IDirectPlay2Impl,iface);
862 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, TRUE );
865 static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
866 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
868 ICOM_THIS(IDirectPlay2Impl,iface);
869 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, FALSE );
872 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi )
874 HRESULT hr = DP_OK;
876 TRACE("(%p)->(%u)\n", This, bAnsi );
878 /* FIXME: Need to find a new host I assume (how?) */
879 /* FIXME: Need to destroy all local groups */
880 /* FIXME: Need to migrate all remotely visible players to the new host */
882 /* Invoke the SP callback to inform of session close */
883 if( This->dp2->spData.lpCB->CloseEx )
885 DPSP_CLOSEDATA data;
887 TRACE( "Calling SP CloseEx\n" );
889 data.lpISP = This->dp2->spData.lpISP;
891 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
894 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
896 TRACE( "Calling SP Close (obsolete interface)\n" );
898 hr = (*This->dp2->spData.lpCB->Close)();
901 return hr;
904 static HRESULT WINAPI DirectPlay2AImpl_Close
905 ( LPDIRECTPLAY2A iface )
907 ICOM_THIS(IDirectPlay2Impl,iface);
908 return DP_IF_Close( This, TRUE );
911 static HRESULT WINAPI DirectPlay2WImpl_Close
912 ( LPDIRECTPLAY2 iface )
914 ICOM_THIS(IDirectPlay2Impl,iface);
915 return DP_IF_Close( This, FALSE );
918 static
919 lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, LPDPID lpid,
920 LPDPNAME lpName, DWORD dwFlags,
921 DPID idParent, BOOL bAnsi )
923 lpGroupData lpGData;
925 /* Allocate the new space and add to end of high level group list */
926 lpGData = (lpGroupData) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
927 sizeof( *lpGData ) );
929 if( lpGData == NULL )
931 return NULL;
934 DPQ_INIT(lpGData->groups);
935 DPQ_INIT(lpGData->players);
937 /* Set the desired player ID - no sanity checking to see if it exists */
938 lpGData->dpid = *lpid;
940 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
942 /* FIXME: Should we check that the parent exists? */
943 lpGData->parent = idParent;
945 /* FIXME: Should we validate the dwFlags? */
946 lpGData->dwFlags = dwFlags;
948 TRACE( "Created group id 0x%08lx\n", *lpid );
950 return lpGData;
953 /* This method assumes that all links to it are already deleted */
954 static void
955 DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid )
957 lpGroupList lpGList;
959 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
961 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
963 if( lpGList == NULL )
965 ERR( "DPID 0x%08lx not found\n", dpid );
966 return;
969 if( --(lpGList->lpGData->uRef) )
971 FIXME( "Why is this not the last reference to group?\n" );
972 DebugBreak();
975 /* Delete player */
976 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
977 HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
979 /* Remove and Delete Player List object */
980 HeapFree( GetProcessHeap(), 0, lpGList );
984 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid )
986 lpGroupList lpGroups;
988 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
990 if( dpid == DPID_SYSTEM_GROUP )
992 return This->dp2->lpSysGroup;
994 else
996 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
999 if( lpGroups == NULL )
1001 return NULL;
1004 return lpGroups->lpGData;
1007 static HRESULT WINAPI DP_IF_CreateGroup
1008 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
1009 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
1010 DWORD dwFlags, BOOL bAnsi )
1012 lpGroupData lpGData;
1014 TRACE( "(%p)->(%p,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
1015 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
1016 dwFlags, bAnsi );
1018 /* If the name is not specified, we must provide one */
1019 if( DPID_UNKNOWN == *lpidGroup )
1021 /* If we are the name server, we decide on the group ids. If not, we
1022 * must ask for one before attempting a creation.
1024 if( This->dp2->bHostInterface )
1026 *lpidGroup = DP_NextObjectId();
1028 else
1030 *lpidGroup = DP_GetRemoteNextObjectId();
1034 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
1035 DPID_NOPARENT_GROUP, bAnsi );
1037 if( lpGData == NULL )
1039 return DPERR_CANTADDPLAYER; /* yes player not group */
1042 if( DPID_SYSTEM_GROUP == *lpidGroup )
1044 This->dp2->lpSysGroup = lpGData;
1045 TRACE( "Inserting system group\n" );
1047 else
1049 /* Insert into the system group */
1050 lpGroupList lpGroup = (lpGroupList) HeapAlloc( GetProcessHeap(),
1051 HEAP_ZERO_MEMORY,
1052 sizeof( *lpGroup ) );
1053 lpGroup->lpGData = lpGData;
1055 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
1058 /* Something is now referencing this data */
1059 lpGData->uRef++;
1061 /* Set all the important stuff for the group */
1062 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
1064 /* FIXME: We should only create the system group if GetCaps returns
1065 * DPCAPS_GROUPOPTIMIZED.
1068 /* Let the SP know that we've created this group */
1069 if( This->dp2->spData.lpCB->CreateGroup )
1071 DPSP_CREATEGROUPDATA data;
1072 DWORD dwCreateFlags = 0;
1074 TRACE( "Calling SP CreateGroup\n" );
1076 if( *lpidGroup == DPID_NOPARENT_GROUP )
1077 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
1079 if( lpMsgHdr == NULL )
1080 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1082 if( dwFlags & DPGROUP_HIDDEN )
1083 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
1085 data.idGroup = *lpidGroup;
1086 data.dwFlags = dwCreateFlags;
1087 data.lpSPMessageHeader = lpMsgHdr;
1088 data.lpISP = This->dp2->spData.lpISP;
1090 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1093 /* Inform all other peers of the creation of a new group. If there are
1094 * no peers keep this event quiet.
1095 * Also if this message was sent to us, don't rebroadcast.
1097 if( ( lpMsgHdr == NULL ) &&
1098 This->dp2->lpSessionDesc &&
1099 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1101 DPMSG_CREATEPLAYERORGROUP msg;
1102 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1104 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1105 msg.dpId = *lpidGroup;
1106 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1107 msg.lpData = lpData;
1108 msg.dwDataSize = dwDataSize;
1109 msg.dpnName = *lpGroupName;
1110 msg.dpIdParent = DPID_NOPARENT_GROUP;
1111 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
1113 /* FIXME: Correct to just use send effectively? */
1114 /* FIXME: Should size include data w/ message or just message "header" */
1115 /* FIXME: Check return code */
1116 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
1117 0, 0, NULL, NULL, bAnsi );
1120 return DP_OK;
1123 static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
1124 ( LPDIRECTPLAY2A iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1125 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1127 *lpidGroup = DPID_UNKNOWN;
1129 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1130 lpGroupName, lpData, dwDataSize, dwFlags, TRUE );
1133 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
1134 ( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1135 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1137 *lpidGroup = DPID_UNKNOWN;
1139 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1140 lpGroupName, lpData, dwDataSize, dwFlags, FALSE );
1144 static void
1145 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
1146 LPVOID lpData, DWORD dwDataSize )
1148 /* Clear out the data with this player */
1149 if( ( dwFlags & DPSET_LOCAL ) &&
1150 ( lpGData->dwLocalDataSize != 0 )
1153 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
1154 lpGData->lpLocalData = NULL;
1155 lpGData->dwLocalDataSize = 0;
1157 if( ( dwFlags & DPSET_REMOTE ) &&
1158 ( lpGData->dwRemoteDataSize != 0 )
1161 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
1162 lpGData->lpRemoteData = NULL;
1163 lpGData->dwRemoteDataSize = 0;
1166 /* Reallocate for new data */
1167 if( lpData != NULL )
1169 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1170 sizeof( dwDataSize ) );
1171 CopyMemory( lpNewData, lpData, dwDataSize );
1173 if( dwFlags & DPSET_REMOTE )
1175 lpGData->lpRemoteData = lpNewData;
1176 lpGData->dwRemoteDataSize = dwDataSize;
1179 if( dwFlags & DPSET_LOCAL )
1181 lpGData->lpLocalData = lpData;
1182 lpGData->dwLocalDataSize = dwDataSize;
1188 /* This function will just create the storage for the new player. */
1189 static
1190 lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid,
1191 LPDPNAME lpName, DWORD dwFlags,
1192 HANDLE hEvent, BOOL bAnsi )
1194 lpPlayerData lpPData;
1196 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
1198 /* Allocate the storage for the player and associate it with list element */
1199 lpPData = (lpPlayerData) HeapAlloc( GetProcessHeap(),
1200 HEAP_ZERO_MEMORY,
1201 sizeof( *lpPData ) );
1202 if( lpPData == NULL )
1204 return NULL;
1207 /* Set the desired player ID */
1208 lpPData->dpid = *lpid;
1210 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
1212 lpPData->dwFlags = dwFlags;
1214 /* If we were given an event handle, duplicate it */
1215 if( hEvent != 0 )
1217 if( !DuplicateHandle( GetCurrentProcess(), hEvent,
1218 GetCurrentProcess(), &lpPData->hEvent,
1219 0, FALSE, DUPLICATE_SAME_ACCESS )
1222 /* FIXME: Memory leak */
1223 ERR( "Can't duplicate player msg handle %p\n", hEvent );
1227 /* Initialize the SP data section */
1228 lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData();
1230 TRACE( "Created player id 0x%08lx\n", *lpid );
1232 return lpPData;
1235 /* Delete the contents of the DPNAME struct */
1236 static void
1237 DP_DeleteDPNameStruct( LPDPNAME lpDPName )
1239 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u1.lpszShortNameA );
1240 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u2.lpszLongNameA );
1243 /* This method assumes that all links to it are already deleted */
1244 static void
1245 DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid )
1247 lpPlayerList lpPList;
1249 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
1251 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1253 if( lpPList == NULL )
1255 ERR( "DPID 0x%08lx not found\n", dpid );
1256 return;
1259 /* Verify that this is the last reference to the data */
1260 if( --(lpPList->lpPData->uRef) )
1262 FIXME( "Why is this not the last reference to player?\n" );
1263 DebugBreak();
1266 /* Delete player */
1267 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1269 CloseHandle( lpPList->lpPData->hEvent );
1270 HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
1272 /* Delete Player List object */
1273 HeapFree( GetProcessHeap(), 0, lpPList );
1276 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid )
1278 lpPlayerList lpPlayers;
1280 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
1282 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1284 return lpPlayers;
1287 /* Basic area for Dst must already be allocated */
1288 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi )
1290 if( lpSrc == NULL )
1292 ZeroMemory( lpDst, sizeof( *lpDst ) );
1293 lpDst->dwSize = sizeof( *lpDst );
1294 return TRUE;
1297 if( lpSrc->dwSize != sizeof( *lpSrc) )
1299 return FALSE;
1302 /* Delete any existing pointers */
1303 if( lpDst->u1.lpszShortNameA )
1305 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1308 if( lpDst->u2.lpszLongNameA )
1310 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
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 ICOM_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 ICOM_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 ICOM_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 ICOM_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 ICOM_THIS(IDirectPlay2Impl,iface);
1833 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
1836 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
1837 ( LPDIRECTPLAY2 iface, DPID idGroup )
1839 ICOM_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( DP_FindPlayer( This, idPlayer ) == NULL )
1860 return DPERR_INVALIDPLAYER;
1863 /* FIXME: If the player is remote, we must be the host to delete this */
1865 cbContext.This = This;
1866 cbContext.idPlayer = idPlayer;
1867 cbContext.bAnsi = bAnsi;
1869 /* Find each group and call DeletePlayerFromGroup if the player is a
1870 member of the group */
1871 DP_IF_EnumGroups( This, NULL, cbDeletePlayerFromAllGroups,
1872 (LPVOID)&cbContext, DPENUMGROUPS_ALL, bAnsi );
1874 /* Now delete player and player list from the sys group */
1875 DP_DeletePlayer( This, idPlayer );
1877 /* Let the SP know that we've destroyed this group */
1878 if( This->dp2->spData.lpCB->DeletePlayer )
1880 DPSP_DELETEPLAYERDATA data;
1882 FIXME( "data.dwFlags is incorrect\n" );
1884 data.idPlayer = idPlayer;
1885 data.dwFlags = 0;
1886 data.lpISP = This->dp2->spData.lpISP;
1888 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
1891 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
1893 return DP_OK;
1896 static BOOL CALLBACK
1897 cbDeletePlayerFromAllGroups(
1898 DPID dpId,
1899 DWORD dwPlayerType,
1900 LPCDPNAME lpName,
1901 DWORD dwFlags,
1902 LPVOID lpContext )
1904 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
1906 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1908 DP_IF_DeletePlayerFromGroup( lpCtxt->This, NULL, dpId, lpCtxt->idPlayer,
1909 lpCtxt->bAnsi );
1911 /* Enumerate all groups in this group since this will normally only
1912 * be called for top level groups
1914 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)lpCtxt->This,
1915 dpId, NULL,
1916 cbDeletePlayerFromAllGroups,
1917 (LPVOID)lpContext, DPENUMGROUPS_ALL,
1918 lpCtxt->bAnsi );
1921 else
1923 ERR( "Group callback has dwPlayerType = 0x%08lx\n", dwPlayerType );
1926 return TRUE;
1929 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
1930 ( LPDIRECTPLAY2A iface, DPID idPlayer )
1932 ICOM_THIS(IDirectPlay2Impl,iface);
1933 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
1936 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
1937 ( LPDIRECTPLAY2 iface, DPID idPlayer )
1939 ICOM_THIS(IDirectPlay2Impl,iface);
1940 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
1943 static HRESULT WINAPI DP_IF_EnumGroupPlayers
1944 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
1945 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1946 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1948 lpGroupData lpGData;
1949 lpPlayerList lpPList;
1951 FIXME("(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
1952 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
1953 lpContext, dwFlags, bAnsi );
1955 /* Find the group */
1956 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1958 return DPERR_INVALIDGROUP;
1961 if( DPQ_IS_EMPTY( lpGData->players ) )
1963 return DP_OK;
1966 lpPList = DPQ_FIRST( lpGData->players );
1968 /* Walk the players in this group */
1969 for( ;; )
1971 /* We do not enum the name server or app server as they are of no
1972 * concequence to the end user.
1974 if( ( lpPList->lpPData->dpid != DPID_NAME_SERVER ) &&
1975 ( lpPList->lpPData->dpid != DPID_SERVERPLAYER )
1979 /* FIXME: Need to add stuff for dwFlags checking */
1981 if( !lpEnumPlayersCallback2( lpPList->lpPData->dpid, DPPLAYERTYPE_PLAYER,
1982 &lpPList->lpPData->name,
1983 lpPList->lpPData->dwFlags,
1984 lpContext )
1987 /* User requested break */
1988 return DP_OK;
1992 if( DPQ_IS_ENDOFLIST( lpPList->players ) )
1994 break;
1997 lpPList = DPQ_NEXT( lpPList->players );
2000 return DP_OK;
2003 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
2004 ( LPDIRECTPLAY2A iface, DPID idGroup, LPGUID lpguidInstance,
2005 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2006 LPVOID lpContext, DWORD dwFlags )
2008 ICOM_THIS(IDirectPlay2Impl,iface);
2009 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2010 lpEnumPlayersCallback2, lpContext,
2011 dwFlags, TRUE );
2014 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
2015 ( LPDIRECTPLAY2 iface, DPID idGroup, LPGUID lpguidInstance,
2016 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2017 LPVOID lpContext, DWORD dwFlags )
2019 ICOM_THIS(IDirectPlay2Impl,iface);
2020 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2021 lpEnumPlayersCallback2, lpContext,
2022 dwFlags, FALSE );
2025 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2026 static HRESULT WINAPI DP_IF_EnumGroups
2027 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2028 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2029 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2031 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This,
2032 DPID_SYSTEM_GROUP, lpguidInstance,
2033 lpEnumPlayersCallback2, lpContext,
2034 dwFlags, bAnsi );
2037 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
2038 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2039 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2040 LPVOID lpContext, DWORD dwFlags )
2042 ICOM_THIS(IDirectPlay2Impl,iface);
2043 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2044 lpContext, dwFlags, TRUE );
2047 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
2048 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2049 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2050 LPVOID lpContext, DWORD dwFlags )
2052 ICOM_THIS(IDirectPlay2Impl,iface);
2053 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2054 lpContext, dwFlags, FALSE );
2057 static HRESULT WINAPI DP_IF_EnumPlayers
2058 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2059 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2060 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2062 return DP_IF_EnumGroupPlayers( This, DPID_SYSTEM_GROUP, lpguidInstance,
2063 lpEnumPlayersCallback2, lpContext,
2064 dwFlags, bAnsi );
2067 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
2068 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2069 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2070 LPVOID lpContext, DWORD dwFlags )
2072 ICOM_THIS(IDirectPlay2Impl,iface);
2073 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2074 lpContext, dwFlags, TRUE );
2077 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
2078 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2079 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2080 LPVOID lpContext, DWORD dwFlags )
2082 ICOM_THIS(IDirectPlay2Impl,iface);
2083 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2084 lpContext, dwFlags, FALSE );
2087 /* This function should call the registered callback function that the user
2088 passed into EnumSessions for each entry available.
2090 static void DP_InvokeEnumSessionCallbacks
2091 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2092 LPVOID lpNSInfo,
2093 DWORD dwTimeout,
2094 LPVOID lpContext )
2096 LPDPSESSIONDESC2 lpSessionDesc;
2098 FIXME( ": not checking for conditions\n" );
2100 /* Not sure if this should be pruning but it's convenient */
2101 NS_PruneSessionCache( lpNSInfo );
2103 NS_ResetSessionEnumeration( lpNSInfo );
2105 /* Enumerate all sessions */
2106 /* FIXME: Need to indicate ANSI */
2107 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2109 TRACE( "EnumSessionsCallback2 invoked\n" );
2110 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2112 return;
2116 /* Invoke one last time to indicate that there is no more to come */
2117 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2120 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2122 EnumSessionAsyncCallbackData* data = (EnumSessionAsyncCallbackData*)lpContext;
2123 HANDLE hSuicideRequest = data->hSuicideRequest;
2124 DWORD dwTimeout = data->dwTimeout;
2126 TRACE( "Thread started with timeout = 0x%08lx\n", dwTimeout );
2128 for( ;; )
2130 HRESULT hr;
2132 /* Sleep up to dwTimeout waiting for request to terminate thread */
2133 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2135 TRACE( "Thread terminating on terminate request\n" );
2136 break;
2139 /* Now resend the enum request */
2140 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2141 data->dwEnumSessionFlags,
2142 data->lpSpData );
2144 if( FAILED(hr) )
2146 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2147 /* FIXME: Should we kill this thread? How to inform the main thread? */
2152 TRACE( "Thread terminating\n" );
2154 /* Clean up the thread data */
2155 CloseHandle( hSuicideRequest );
2156 HeapFree( GetProcessHeap(), 0, lpContext );
2158 /* FIXME: Need to have some notification to main app thread that this is
2159 * dead. It would serve two purposes. 1) allow sync on termination
2160 * so that we don't actually send something to ourselves when we
2161 * become name server (race condition) and 2) so that if we die
2162 * abnormally something else will be able to tell.
2165 return 1;
2168 static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
2170 /* Does a thread exist? If so we were doing an async enum session */
2171 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2173 TRACE( "Killing EnumSession thread %p\n",
2174 This->dp2->hEnumSessionThread );
2176 /* Request that the thread kill itself nicely */
2177 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2178 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2180 /* We no longer need to know about the thread */
2181 CloseHandle( This->dp2->hEnumSessionThread );
2183 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2187 static HRESULT WINAPI DP_IF_EnumSessions
2188 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2189 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2190 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2192 HRESULT hr = DP_OK;
2194 TRACE( "(%p)->(%p,0x%08lx,%p,%p,0x%08lx,%u)\n",
2195 This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags,
2196 bAnsi );
2198 /* Can't enumerate if the interface is already open */
2199 if( This->dp2->bConnectionOpen )
2201 return DPERR_GENERIC;
2204 #if 1
2205 /* The loading of a lobby provider _seems_ to require a backdoor loading
2206 * of the service provider to also associate with this DP object. This is
2207 * because the app doesn't seem to have to call EnumConnections and
2208 * InitializeConnection for the SP before calling this method. As such
2209 * we'll do their dirty work for them with a quick hack so as to always
2210 * load the TCP/IP service provider.
2212 * The correct solution would seem to involve creating a dialog box which
2213 * contains the possible SPs. These dialog boxes most likely follow SDK
2214 * examples.
2216 if( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
2218 LPVOID lpConnection;
2219 DWORD dwSize;
2221 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2223 if( !DP_BuildSPCompoundAddr( (LPGUID)&DPSPGUID_TCPIP, &lpConnection, &dwSize ) )
2225 ERR( "Can't build compound addr\n" );
2226 return DPERR_GENERIC;
2229 hr = DP_IF_InitializeConnection( (IDirectPlay3Impl*)This, lpConnection,
2230 0, bAnsi );
2231 if( FAILED(hr) )
2233 return hr;
2236 /* Free up the address buffer */
2237 HeapFree( GetProcessHeap(), 0, lpConnection );
2239 /* The SP is now initialized */
2240 This->dp2->bSPInitialized = TRUE;
2242 #endif
2245 /* Use the service provider default? */
2246 if( dwTimeout == 0 )
2248 DPCAPS spCaps;
2249 spCaps.dwSize = sizeof( spCaps );
2251 DP_IF_GetCaps( This, &spCaps, 0 );
2252 dwTimeout = spCaps.dwTimeout;
2254 /* The service provider doesn't provide one either! */
2255 if( dwTimeout == 0 )
2257 /* Provide the TCP/IP default */
2258 dwTimeout = DPMSG_WAIT_5_SECS;
2262 if( dwFlags & DPENUMSESSIONS_STOPASYNC )
2264 DP_KillEnumSessionThread( This );
2265 return hr;
2268 /* FIXME: Interface locking sucks in this method */
2269 if( ( dwFlags & DPENUMSESSIONS_ASYNC ) )
2271 /* Enumerate everything presently in the local session cache */
2272 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2273 This->dp2->lpNameServerData, dwTimeout,
2274 lpContext );
2277 /* See if we've already created a thread to service this interface */
2278 if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2280 DWORD dwThreadId;
2282 /* Send the first enum request inline since the user may cancel a dialog
2283 * if one is presented. Also, may also have a connecting return code.
2285 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2286 dwFlags, &This->dp2->spData );
2288 if( !FAILED(hr) )
2290 EnumSessionAsyncCallbackData* lpData
2291 = (EnumSessionAsyncCallbackData*)HeapAlloc( GetProcessHeap(),
2292 HEAP_ZERO_MEMORY,
2293 sizeof( *lpData ) );
2294 /* FIXME: need to kill the thread on object deletion */
2295 lpData->lpSpData = &This->dp2->spData;
2297 CopyMemory( &lpData->requestGuid, &lpsd->guidApplication, sizeof(GUID) );
2298 lpData->dwEnumSessionFlags = dwFlags;
2299 lpData->dwTimeout = dwTimeout;
2301 This->dp2->hKillEnumSessionThreadEvent =
2302 CreateEventA( NULL, TRUE, FALSE, NULL );
2304 if( !DuplicateHandle( GetCurrentProcess(),
2305 This->dp2->hKillEnumSessionThreadEvent,
2306 GetCurrentProcess(),
2307 &lpData->hSuicideRequest,
2308 0, FALSE, DUPLICATE_SAME_ACCESS )
2311 ERR( "Can't duplicate thread killing handle\n" );
2314 TRACE( ": creating EnumSessionsRequest thread\n" );
2316 This->dp2->hEnumSessionThread = CreateThread( NULL,
2318 DP_EnumSessionsSendAsyncRequestThread,
2319 lpData,
2321 &dwThreadId );
2325 else
2327 /* Invalidate the session cache for the interface */
2328 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2330 /* Send the broadcast for session enumeration */
2331 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2332 dwFlags,
2333 &This->dp2->spData );
2336 SleepEx( dwTimeout, FALSE );
2338 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2339 This->dp2->lpNameServerData, dwTimeout,
2340 lpContext );
2343 return hr;
2346 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2347 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2348 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2349 LPVOID lpContext, DWORD dwFlags )
2351 ICOM_THIS(IDirectPlay2Impl,iface);
2352 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2353 lpContext, dwFlags, TRUE );
2356 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2357 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2358 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2359 LPVOID lpContext, DWORD dwFlags )
2361 ICOM_THIS(IDirectPlay2Impl,iface);
2362 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2363 lpContext, dwFlags, FALSE );
2366 static HRESULT WINAPI DP_IF_GetPlayerCaps
2367 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
2368 DWORD dwFlags )
2370 DPSP_GETCAPSDATA data;
2372 TRACE("(%p)->(0x%08lx,%p,0x%08lx)\n", This, idPlayer, lpDPCaps, dwFlags);
2374 /* Query the service provider */
2375 data.idPlayer = idPlayer;
2376 data.dwFlags = dwFlags;
2377 data.lpCaps = lpDPCaps;
2378 data.lpISP = This->dp2->spData.lpISP;
2380 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2383 static HRESULT WINAPI DP_IF_GetCaps
2384 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags )
2386 return DP_IF_GetPlayerCaps( This, DPID_ALLPLAYERS, lpDPCaps, dwFlags );
2389 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2390 ( LPDIRECTPLAY2A iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2392 ICOM_THIS(IDirectPlay2Impl,iface);
2393 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2396 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2397 ( LPDIRECTPLAY2 iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2399 ICOM_THIS(IDirectPlay2Impl,iface);
2400 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2403 static HRESULT WINAPI DP_IF_GetGroupData
2404 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2405 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2407 lpGroupData lpGData;
2408 DWORD dwRequiredBufferSize;
2409 LPVOID lpCopyDataFrom;
2411 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
2412 This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi );
2414 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2416 return DPERR_INVALIDGROUP;
2419 /* How much buffer is required? */
2420 if( dwFlags & DPSET_REMOTE )
2422 dwRequiredBufferSize = lpGData->dwRemoteDataSize;
2423 lpCopyDataFrom = lpGData->lpRemoteData;
2425 else if( dwFlags & DPSET_LOCAL )
2427 dwRequiredBufferSize = lpGData->dwLocalDataSize;
2428 lpCopyDataFrom = lpGData->lpLocalData;
2430 else
2432 ERR( "Neither local or remote data requested!?!\n" );
2433 dwRequiredBufferSize = 0;
2434 lpCopyDataFrom = NULL;
2437 /* Is the user requesting to know how big a buffer is required? */
2438 if( ( lpData == NULL ) ||
2439 ( *lpdwDataSize < dwRequiredBufferSize )
2442 *lpdwDataSize = dwRequiredBufferSize;
2443 return DPERR_BUFFERTOOSMALL;
2446 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2448 return DP_OK;
2451 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2452 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2453 LPDWORD lpdwDataSize, DWORD dwFlags )
2455 ICOM_THIS(IDirectPlay2Impl,iface);
2456 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2457 dwFlags, TRUE );
2460 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2461 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2462 LPDWORD lpdwDataSize, DWORD dwFlags )
2464 ICOM_THIS(IDirectPlay2Impl,iface);
2465 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2466 dwFlags, FALSE );
2469 static HRESULT WINAPI DP_IF_GetGroupName
2470 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2471 LPDWORD lpdwDataSize, BOOL bAnsi )
2473 lpGroupData lpGData;
2474 LPDPNAME lpName = (LPDPNAME)lpData;
2475 DWORD dwRequiredDataSize;
2477 FIXME("(%p)->(0x%08lx,%p,%p,%u) ANSI ignored\n",
2478 This, idGroup, lpData, lpdwDataSize, bAnsi );
2480 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2482 return DPERR_INVALIDGROUP;
2485 dwRequiredDataSize = lpGData->name.dwSize;
2487 if( lpGData->name.u1.lpszShortNameA )
2489 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
2492 if( lpGData->name.u2.lpszLongNameA )
2494 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
2497 if( ( lpData == NULL ) ||
2498 ( *lpdwDataSize < dwRequiredDataSize )
2501 *lpdwDataSize = dwRequiredDataSize;
2502 return DPERR_BUFFERTOOSMALL;
2505 /* Copy the structure */
2506 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2508 if( lpGData->name.u1.lpszShortNameA )
2510 strcpy( ((BYTE*)lpName)+lpGData->name.dwSize,
2511 lpGData->name.u1.lpszShortNameA );
2513 else
2515 lpName->u1.lpszShortNameA = NULL;
2518 if( lpGData->name.u1.lpszShortNameA )
2520 strcpy( ((BYTE*)lpName)+lpGData->name.dwSize,
2521 lpGData->name.u2.lpszLongNameA );
2523 else
2525 lpName->u2.lpszLongNameA = NULL;
2528 return DP_OK;
2531 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2532 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2533 LPDWORD lpdwDataSize )
2535 ICOM_THIS(IDirectPlay2Impl,iface);
2536 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2539 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2540 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2541 LPDWORD lpdwDataSize )
2543 ICOM_THIS(IDirectPlay2Impl,iface);
2544 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2547 static HRESULT WINAPI DP_IF_GetMessageCount
2548 ( IDirectPlay2Impl* This, DPID idPlayer,
2549 LPDWORD lpdwCount, BOOL bAnsi )
2551 FIXME("(%p)->(0x%08lx,%p,%u): stub\n", This, idPlayer, lpdwCount, bAnsi );
2552 return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer,
2553 DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL,
2554 bAnsi );
2557 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2558 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDWORD lpdwCount )
2560 ICOM_THIS(IDirectPlay2Impl,iface);
2561 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, TRUE );
2564 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2565 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDWORD lpdwCount )
2567 ICOM_THIS(IDirectPlay2Impl,iface);
2568 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, FALSE );
2571 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2572 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2574 ICOM_THIS(IDirectPlay2Impl,iface);
2575 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2576 return DP_OK;
2579 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2580 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2582 ICOM_THIS(IDirectPlay2Impl,iface);
2583 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2584 return DP_OK;
2587 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2588 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2589 DWORD dwFlags )
2591 ICOM_THIS(IDirectPlay2Impl,iface);
2592 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2595 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2596 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2597 DWORD dwFlags )
2599 ICOM_THIS(IDirectPlay2Impl,iface);
2600 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2603 static HRESULT WINAPI DP_IF_GetPlayerData
2604 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2605 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2607 lpPlayerList lpPList;
2608 DWORD dwRequiredBufferSize;
2609 LPVOID lpCopyDataFrom;
2611 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
2612 This, idPlayer, lpData, lpdwDataSize, dwFlags, bAnsi );
2614 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2616 return DPERR_INVALIDPLAYER;
2619 /* How much buffer is required? */
2620 if( dwFlags & DPSET_REMOTE )
2622 dwRequiredBufferSize = lpPList->lpPData->dwRemoteDataSize;
2623 lpCopyDataFrom = lpPList->lpPData->lpRemoteData;
2625 else if( dwFlags & DPSET_LOCAL )
2627 dwRequiredBufferSize = lpPList->lpPData->dwLocalDataSize;
2628 lpCopyDataFrom = lpPList->lpPData->lpLocalData;
2630 else
2632 ERR( "Neither local or remote data requested!?!\n" );
2633 dwRequiredBufferSize = 0;
2634 lpCopyDataFrom = NULL;
2637 /* Is the user requesting to know how big a buffer is required? */
2638 if( ( lpData == NULL ) ||
2639 ( *lpdwDataSize < dwRequiredBufferSize )
2642 *lpdwDataSize = dwRequiredBufferSize;
2643 return DPERR_BUFFERTOOSMALL;
2646 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2648 return DP_OK;
2651 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2652 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2653 LPDWORD lpdwDataSize, DWORD dwFlags )
2655 ICOM_THIS(IDirectPlay2Impl,iface);
2656 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2657 dwFlags, TRUE );
2660 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2661 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2662 LPDWORD lpdwDataSize, DWORD dwFlags )
2664 ICOM_THIS(IDirectPlay2Impl,iface);
2665 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2666 dwFlags, FALSE );
2669 static HRESULT WINAPI DP_IF_GetPlayerName
2670 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2671 LPDWORD lpdwDataSize, BOOL bAnsi )
2673 lpPlayerList lpPList;
2674 LPDPNAME lpName = (LPDPNAME)lpData;
2675 DWORD dwRequiredDataSize;
2677 FIXME( "(%p)->(0x%08lx,%p,%p,%u): ANSI \n",
2678 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2680 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2682 return DPERR_INVALIDPLAYER;
2685 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
2687 if( lpPList->lpPData->name.u1.lpszShortNameA )
2689 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
2692 if( lpPList->lpPData->name.u2.lpszLongNameA )
2694 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
2697 if( ( lpData == NULL ) ||
2698 ( *lpdwDataSize < dwRequiredDataSize )
2701 *lpdwDataSize = dwRequiredDataSize;
2702 return DPERR_BUFFERTOOSMALL;
2705 /* Copy the structure */
2706 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
2708 if( lpPList->lpPData->name.u1.lpszShortNameA )
2710 strcpy( ((BYTE*)lpName)+lpPList->lpPData->name.dwSize,
2711 lpPList->lpPData->name.u1.lpszShortNameA );
2713 else
2715 lpName->u1.lpszShortNameA = NULL;
2718 if( lpPList->lpPData->name.u1.lpszShortNameA )
2720 strcpy( ((BYTE*)lpName)+lpPList->lpPData->name.dwSize,
2721 lpPList->lpPData->name.u2.lpszLongNameA );
2723 else
2725 lpName->u2.lpszLongNameA = NULL;
2728 return DP_OK;
2731 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2732 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2733 LPDWORD lpdwDataSize )
2735 ICOM_THIS(IDirectPlay2Impl,iface);
2736 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
2739 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2740 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2741 LPDWORD lpdwDataSize )
2743 ICOM_THIS(IDirectPlay2Impl,iface);
2744 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
2747 static HRESULT WINAPI DP_GetSessionDesc
2748 ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize,
2749 BOOL bAnsi )
2751 DWORD dwRequiredSize;
2753 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
2755 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
2757 return DPERR_INVALIDPARAMS;
2760 /* FIXME: Get from This->dp2->lpSessionDesc */
2761 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
2763 if ( ( lpData == NULL ) ||
2764 ( *lpdwDataSize < dwRequiredSize )
2767 *lpdwDataSize = dwRequiredSize;
2768 return DPERR_BUFFERTOOSMALL;
2771 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
2773 return DP_OK;
2776 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
2777 ( LPDIRECTPLAY2A iface, LPVOID lpData, LPDWORD lpdwDataSize )
2779 ICOM_THIS(IDirectPlay2Impl,iface);
2780 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2783 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
2784 ( LPDIRECTPLAY2 iface, LPVOID lpData, LPDWORD lpdwDataSize )
2786 ICOM_THIS(IDirectPlay2Impl,iface);
2787 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2790 /* Intended only for COM compatibility. Always returns an error. */
2791 static HRESULT WINAPI DirectPlay2AImpl_Initialize
2792 ( LPDIRECTPLAY2A iface, LPGUID lpGUID )
2794 ICOM_THIS(IDirectPlay2Impl,iface);
2795 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2796 return DPERR_ALREADYINITIALIZED;
2799 /* Intended only for COM compatibility. Always returns an error. */
2800 static HRESULT WINAPI DirectPlay2WImpl_Initialize
2801 ( LPDIRECTPLAY2 iface, LPGUID lpGUID )
2803 ICOM_THIS(IDirectPlay2Impl,iface);
2804 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2805 return DPERR_ALREADYINITIALIZED;
2809 static HRESULT WINAPI DP_SecureOpen
2810 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
2811 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
2812 BOOL bAnsi )
2814 HRESULT hr = DP_OK;
2816 FIXME( "(%p)->(%p,0x%08lx,%p,%p): partial stub\n",
2817 This, lpsd, dwFlags, lpSecurity, lpCredentials );
2819 if( This->dp2->bConnectionOpen )
2821 TRACE( ": rejecting already open connection.\n" );
2822 return DPERR_ALREADYINITIALIZED;
2825 /* If we're enumerating, kill the thread */
2826 DP_KillEnumSessionThread( This );
2828 if( dwFlags & DPOPEN_CREATE )
2830 /* Rightoo - this computer is the host and the local computer needs to be
2831 the name server so that others can join this session */
2832 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
2834 This->dp2->bHostInterface = TRUE;
2836 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
2837 if( FAILED( hr ) )
2839 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
2840 return hr;
2844 /* Invoke the conditional callback for the service provider */
2845 if( This->dp2->spData.lpCB->Open )
2847 DPSP_OPENDATA data;
2849 FIXME( "Not all data fields are correct. Need new parameter\n" );
2851 data.bCreate = (dwFlags & DPOPEN_CREATE ) ? TRUE : FALSE;
2852 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
2853 : NS_GetNSAddr( This->dp2->lpNameServerData );
2854 data.lpISP = This->dp2->spData.lpISP;
2855 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) ? TRUE : FALSE;
2856 data.dwOpenFlags = dwFlags;
2857 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
2859 hr = (*This->dp2->spData.lpCB->Open)(&data);
2860 if( FAILED( hr ) )
2862 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
2863 return hr;
2868 /* Create the system group of which everything is a part of */
2869 DPID systemGroup = DPID_SYSTEM_GROUP;
2871 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
2872 NULL, 0, 0, TRUE );
2876 if( dwFlags & DPOPEN_JOIN )
2878 DPID dpidServerId = DPID_UNKNOWN;
2880 /* Create the server player for this interface. This way we can receive
2881 * messages for this session.
2883 /* FIXME: I suppose that we should be setting an event for a receive
2884 * type of thing. That way the messaging thread could know to wake
2885 * up. DPlay would then trigger the hEvent for the player the
2886 * message is directed to.
2888 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
2890 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
2893 else if( dwFlags & DPOPEN_CREATE )
2895 DPID dpidNameServerId = DPID_NAME_SERVER;
2897 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
2898 0, DPPLAYER_SERVERPLAYER, bAnsi );
2901 if( FAILED(hr) )
2903 ERR( "Couldn't create name server/system player: %s\n",
2904 DPLAYX_HresultToString(hr) );
2907 return hr;
2910 static HRESULT WINAPI DirectPlay2AImpl_Open
2911 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2913 ICOM_THIS(IDirectPlay2Impl,iface);
2914 TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags );
2915 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, TRUE );
2918 static HRESULT WINAPI DirectPlay2WImpl_Open
2919 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2921 ICOM_THIS(IDirectPlay2Impl,iface);
2922 TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags );
2923 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, FALSE );
2926 static HRESULT WINAPI DP_IF_Receive
2927 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
2928 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi )
2930 LPDPMSG lpMsg = NULL;
2932 FIXME( "(%p)->(%p,%p,0x%08lx,%p,%p,%u): stub\n",
2933 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
2935 if( dwFlags == 0 )
2937 dwFlags = DPRECEIVE_ALL;
2940 /* If the lpData is NULL, we must be peeking the message */
2941 if( ( lpData == NULL ) &&
2942 !( dwFlags & DPRECEIVE_PEEK )
2945 return DPERR_INVALIDPARAMS;
2948 if( dwFlags & DPRECEIVE_ALL )
2950 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
2952 if( !( dwFlags & DPRECEIVE_PEEK ) )
2954 FIXME( "Remove from queue\n" );
2957 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
2958 ( dwFlags & DPRECEIVE_FROMPLAYER )
2961 FIXME( "Find matching message 0x%08lx\n", dwFlags );
2963 else
2965 ERR( "Hmmm..dwFlags 0x%08lx\n", dwFlags );
2968 if( lpMsg == NULL )
2970 return DPERR_NOMESSAGES;
2973 /* Copy into the provided buffer */
2974 CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
2976 return DP_OK;
2979 static HRESULT WINAPI DirectPlay2AImpl_Receive
2980 ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo,
2981 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
2983 ICOM_THIS(IDirectPlay2Impl,iface);
2984 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
2985 lpData, lpdwDataSize, TRUE );
2988 static HRESULT WINAPI DirectPlay2WImpl_Receive
2989 ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo,
2990 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
2992 ICOM_THIS(IDirectPlay2Impl,iface);
2993 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
2994 lpData, lpdwDataSize, FALSE );
2997 static HRESULT WINAPI DirectPlay2AImpl_Send
2998 ( LPDIRECTPLAY2A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3000 ICOM_THIS(IDirectPlay2Impl,iface);
3001 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3002 0, 0, NULL, NULL, TRUE );
3005 static HRESULT WINAPI DirectPlay2WImpl_Send
3006 ( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3008 ICOM_THIS(IDirectPlay2Impl,iface);
3009 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3010 0, 0, NULL, NULL, FALSE );
3013 static HRESULT WINAPI DP_IF_SetGroupData
3014 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
3015 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3017 lpGroupData lpGData;
3019 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
3020 This, idGroup, lpData, dwDataSize, dwFlags, bAnsi );
3022 /* Parameter check */
3023 if( ( lpData == NULL ) &&
3024 ( dwDataSize != 0 )
3027 return DPERR_INVALIDPARAMS;
3030 /* Find the pointer to the data for this player */
3031 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3033 return DPERR_INVALIDOBJECT;
3036 if( dwFlags & DPSET_REMOTE )
3038 FIXME( "Was this group created by this interface?\n" );
3039 /* FIXME: If this is a remote update need to allow it but not
3040 * send a message.
3044 DP_SetGroupData( lpGData, dwFlags, lpData, dwDataSize );
3046 /* FIXME: Only send a message if this group is local to the session otherwise
3047 * it will have been rejected above
3049 if( dwFlags & DPSET_REMOTE )
3051 FIXME( "Send msg?\n" );
3054 return DP_OK;
3057 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
3058 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
3059 DWORD dwDataSize, DWORD dwFlags )
3061 ICOM_THIS(IDirectPlay2Impl,iface);
3062 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, TRUE );
3065 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
3066 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
3067 DWORD dwDataSize, DWORD dwFlags )
3069 ICOM_THIS(IDirectPlay2Impl,iface);
3070 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, FALSE );
3073 static HRESULT WINAPI DP_IF_SetGroupName
3074 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
3075 DWORD dwFlags, BOOL bAnsi )
3077 lpGroupData lpGData;
3079 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n", This, idGroup,
3080 lpGroupName, dwFlags, bAnsi );
3082 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3084 return DPERR_INVALIDGROUP;
3087 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
3089 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3090 FIXME( "Message not sent and dwFlags ignored\n" );
3092 return DP_OK;
3095 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
3096 ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName,
3097 DWORD dwFlags )
3099 ICOM_THIS(IDirectPlay2Impl,iface);
3100 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
3103 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
3104 ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName,
3105 DWORD dwFlags )
3107 ICOM_THIS(IDirectPlay2Impl,iface);
3108 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
3111 static HRESULT WINAPI DP_IF_SetPlayerData
3112 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
3113 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3115 lpPlayerList lpPList;
3117 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
3118 This, idPlayer, lpData, dwDataSize, dwFlags, bAnsi );
3120 /* Parameter check */
3121 if( ( lpData == NULL ) &&
3122 ( dwDataSize != 0 )
3125 return DPERR_INVALIDPARAMS;
3128 /* Find the pointer to the data for this player */
3129 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3131 return DPERR_INVALIDPLAYER;
3134 if( dwFlags & DPSET_REMOTE )
3136 FIXME( "Was this group created by this interface?\n" );
3137 /* FIXME: If this is a remote update need to allow it but not
3138 * send a message.
3142 DP_SetPlayerData( lpPList->lpPData, dwFlags, lpData, dwDataSize );
3144 if( dwFlags & DPSET_REMOTE )
3146 FIXME( "Send msg?\n" );
3149 return DP_OK;
3152 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3153 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
3154 DWORD dwDataSize, DWORD dwFlags )
3156 ICOM_THIS(IDirectPlay2Impl,iface);
3157 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3158 dwFlags, TRUE );
3161 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3162 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
3163 DWORD dwDataSize, DWORD dwFlags )
3165 ICOM_THIS(IDirectPlay2Impl,iface);
3166 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3167 dwFlags, FALSE );
3170 static HRESULT WINAPI DP_IF_SetPlayerName
3171 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
3172 DWORD dwFlags, BOOL bAnsi )
3174 lpPlayerList lpPList;
3176 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n",
3177 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3179 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3181 return DPERR_INVALIDGROUP;
3184 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3186 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3187 FIXME( "Message not sent and dwFlags ignored\n" );
3189 return DP_OK;
3192 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3193 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName,
3194 DWORD dwFlags )
3196 ICOM_THIS(IDirectPlay2Impl,iface);
3197 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3200 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3201 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName,
3202 DWORD dwFlags )
3204 ICOM_THIS(IDirectPlay2Impl,iface);
3205 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3208 static HRESULT WINAPI DP_SetSessionDesc
3209 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
3210 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3212 DWORD dwRequiredSize;
3213 LPDPSESSIONDESC2 lpTempSessDesc;
3215 TRACE( "(%p)->(%p,0x%08lx,%u,%u)\n",
3216 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3218 if( dwFlags )
3220 return DPERR_INVALIDPARAMS;
3223 /* Only the host is allowed to update the session desc */
3224 if( !This->dp2->bHostInterface )
3226 return DPERR_ACCESSDENIED;
3229 /* FIXME: Copy into This->dp2->lpSessionDesc */
3230 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3231 lpTempSessDesc = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
3232 HEAP_ZERO_MEMORY,
3233 dwRequiredSize );
3235 if( lpTempSessDesc == NULL )
3237 return DPERR_OUTOFMEMORY;
3240 /* Free the old */
3241 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3243 This->dp2->lpSessionDesc = lpTempSessDesc;
3245 /* Set the new */
3246 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3248 /* If this is an external invocation of the interface, we should be
3249 * letting everyone know that things have changed. Otherwise this is
3250 * just an initialization and it doesn't need to be propagated.
3252 if( !bInitial )
3254 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3257 return DP_OK;
3260 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3261 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3263 ICOM_THIS(IDirectPlay2Impl,iface);
3264 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3267 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3268 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3270 ICOM_THIS(IDirectPlay2Impl,iface);
3271 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3274 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3275 DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3277 DWORD dwSize = 0;
3279 if( lpSessDesc == NULL )
3281 /* Hmmm..don't need any size? */
3282 ERR( "NULL lpSessDesc\n" );
3283 return dwSize;
3286 dwSize += sizeof( *lpSessDesc );
3288 if( bAnsi )
3290 if( lpSessDesc->u1.lpszSessionNameA )
3292 dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1;
3295 if( lpSessDesc->u2.lpszPasswordA )
3297 dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1;
3300 else /* UNICODE */
3302 if( lpSessDesc->u1.lpszSessionName )
3304 dwSize += sizeof( WCHAR ) *
3305 ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 );
3308 if( lpSessDesc->u2.lpszPassword )
3310 dwSize += sizeof( WCHAR ) *
3311 ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 );
3315 return dwSize;
3318 /* Assumes that contugous buffers are already allocated. */
3319 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3320 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3322 BYTE* lpStartOfFreeSpace;
3324 if( lpSessionDest == NULL )
3326 ERR( "NULL lpSessionDest\n" );
3327 return;
3330 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3332 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3334 if( bAnsi )
3336 if( lpSessionSrc->u1.lpszSessionNameA )
3338 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3339 lpSessionDest->u1.lpszSessionNameA );
3340 lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3341 lpStartOfFreeSpace +=
3342 lstrlenA( (LPSTR)lpSessionDest->u1.lpszSessionNameA ) + 1;
3345 if( lpSessionSrc->u2.lpszPasswordA )
3347 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3348 lpSessionDest->u2.lpszPasswordA );
3349 lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3350 lpStartOfFreeSpace +=
3351 lstrlenA( (LPSTR)lpSessionDest->u2.lpszPasswordA ) + 1;
3354 else /* UNICODE */
3356 if( lpSessionSrc->u1.lpszSessionName )
3358 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3359 lpSessionDest->u1.lpszSessionName );
3360 lpSessionDest->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3361 lpStartOfFreeSpace += sizeof(WCHAR) *
3362 ( lstrlenW( (LPWSTR)lpSessionDest->u1.lpszSessionName ) + 1 );
3365 if( lpSessionSrc->u2.lpszPassword )
3367 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3368 lpSessionDest->u2.lpszPassword );
3369 lpSessionDest->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3370 lpStartOfFreeSpace += sizeof(WCHAR) *
3371 ( lstrlenW( (LPWSTR)lpSessionDest->u2.lpszPassword ) + 1 );
3377 static HRESULT WINAPI DP_IF_AddGroupToGroup
3378 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3380 lpGroupData lpGParentData;
3381 lpGroupData lpGData;
3382 lpGroupList lpNewGList;
3384 TRACE( "(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup );
3386 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3388 return DPERR_INVALIDGROUP;
3391 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3393 return DPERR_INVALIDGROUP;
3396 /* Create a player list (ie "shortcut" ) */
3397 lpNewGList = (lpGroupList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3398 sizeof( *lpNewGList ) );
3399 if( lpNewGList == NULL )
3401 return DPERR_CANTADDPLAYER;
3404 /* Add the shortcut */
3405 lpGData->uRef++;
3406 lpNewGList->lpGData = lpGData;
3408 /* Add the player to the list of players for this group */
3409 DPQ_INSERT( lpGData->groups, lpNewGList, groups );
3411 /* Send a ADDGROUPTOGROUP message */
3412 FIXME( "Not sending message\n" );
3414 return DP_OK;
3417 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3418 ( LPDIRECTPLAY3A iface, DPID idParentGroup, DPID idGroup )
3420 ICOM_THIS(IDirectPlay3Impl,iface);
3421 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3424 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3425 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3427 ICOM_THIS(IDirectPlay3Impl,iface);
3428 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3431 static HRESULT WINAPI DP_IF_CreateGroupInGroup
3432 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
3433 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
3434 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3436 lpGroupData lpGParentData;
3437 lpGroupList lpGList;
3438 lpGroupData lpGData;
3440 TRACE( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
3441 This, idParentGroup, lpidGroup, lpGroupName, lpData,
3442 dwDataSize, dwFlags, bAnsi );
3444 /* Verify that the specified parent is valid */
3445 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This,
3446 idParentGroup ) ) == NULL
3449 return DPERR_INVALIDGROUP;
3452 lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName,
3453 dwFlags, idParentGroup, bAnsi );
3455 if( lpGData == NULL )
3457 return DPERR_CANTADDPLAYER; /* yes player not group */
3460 /* Something else is referencing this data */
3461 lpGData->uRef++;
3463 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
3465 /* The list has now been inserted into the interface group list. We now
3466 need to put a "shortcut" to this group in the parent group */
3467 lpGList = (lpGroupList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3468 sizeof( *lpGList ) );
3469 if( lpGList == NULL )
3471 FIXME( "Memory leak\n" );
3472 return DPERR_CANTADDPLAYER; /* yes player not group */
3475 lpGList->lpGData = lpGData;
3477 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
3479 /* Let the SP know that we've created this group */
3480 if( This->dp2->spData.lpCB->CreateGroup )
3482 DPSP_CREATEGROUPDATA data;
3484 TRACE( "Calling SP CreateGroup\n" );
3486 data.idGroup = *lpidGroup;
3487 data.dwFlags = dwFlags;
3488 data.lpSPMessageHeader = lpMsgHdr;
3489 data.lpISP = This->dp2->spData.lpISP;
3491 (*This->dp2->spData.lpCB->CreateGroup)( &data );
3494 /* Inform all other peers of the creation of a new group. If there are
3495 * no peers keep this quiet.
3497 if( This->dp2->lpSessionDesc &&
3498 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
3500 DPMSG_CREATEPLAYERORGROUP msg;
3502 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
3503 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
3504 msg.dpId = *lpidGroup;
3505 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
3506 msg.lpData = lpData;
3507 msg.dwDataSize = dwDataSize;
3508 msg.dpnName = *lpGroupName;
3510 /* FIXME: Correct to just use send effectively? */
3511 /* FIXME: Should size include data w/ message or just message "header" */
3512 /* FIXME: Check return code */
3513 DP_SendEx( (IDirectPlay2Impl*)This,
3514 DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
3515 0, 0, NULL, NULL, bAnsi );
3518 return DP_OK;
3521 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3522 ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup,
3523 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3524 DWORD dwFlags )
3526 ICOM_THIS(IDirectPlay3Impl,iface);
3528 *lpidGroup = DPID_UNKNOWN;
3530 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3531 lpGroupName, lpData, dwDataSize, dwFlags,
3532 TRUE );
3535 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3536 ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup,
3537 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3538 DWORD dwFlags )
3540 ICOM_THIS(IDirectPlay3Impl,iface);
3542 *lpidGroup = DPID_UNKNOWN;
3544 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3545 lpGroupName, lpData, dwDataSize,
3546 dwFlags, FALSE );
3549 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
3550 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3552 lpGroupList lpGList;
3553 lpGroupData lpGParentData;
3555 TRACE("(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup );
3557 /* Is the parent group valid? */
3558 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3560 return DPERR_INVALIDGROUP;
3563 /* Remove the group from the parent group queue */
3564 DPQ_REMOVE_ENTRY( lpGParentData->groups, groups, lpGData->dpid, ==, idGroup, lpGList );
3566 if( lpGList == NULL )
3568 return DPERR_INVALIDGROUP;
3571 /* Decrement the ref count */
3572 lpGList->lpGData->uRef--;
3574 /* Free up the list item */
3575 HeapFree( GetProcessHeap(), 0, lpGList );
3577 /* Should send a DELETEGROUPFROMGROUP message */
3578 FIXME( "message not sent\n" );
3580 return DP_OK;
3583 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3584 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3586 ICOM_THIS(IDirectPlay3Impl,iface);
3587 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3590 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3591 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3593 ICOM_THIS(IDirectPlay3Impl,iface);
3594 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3597 static
3598 BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
3599 LPDWORD lpdwBufSize )
3601 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3602 HRESULT hr;
3604 dpCompoundAddress.dwDataSize = sizeof( GUID );
3605 memcpy( &dpCompoundAddress.guidDataType, &DPAID_ServiceProvider,
3606 sizeof( GUID ) ) ;
3607 dpCompoundAddress.lpData = lpcSpGuid;
3609 *lplpAddrBuf = NULL;
3610 *lpdwBufSize = 0;
3612 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3613 lpdwBufSize, TRUE );
3615 if( hr != DPERR_BUFFERTOOSMALL )
3617 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3618 return FALSE;
3621 /* Now allocate the buffer */
3622 *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3623 *lpdwBufSize );
3625 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3626 lpdwBufSize, TRUE );
3627 if( FAILED(hr) )
3629 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3630 return FALSE;
3633 return TRUE;
3636 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
3637 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3639 ICOM_THIS(IDirectPlay3Impl,iface);
3640 TRACE("(%p)->(%p,%p,%p,0x%08lx)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3642 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
3643 if( dwFlags == 0 )
3645 dwFlags = DPCONNECTION_DIRECTPLAY;
3648 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
3649 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) )
3652 return DPERR_INVALIDFLAGS;
3655 if( !lpEnumCallback || !*lpEnumCallback )
3657 return DPERR_INVALIDPARAMS;
3660 /* Enumerate DirectPlay service providers */
3661 if( dwFlags & DPCONNECTION_DIRECTPLAY )
3663 HKEY hkResult;
3664 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3665 LPSTR guidDataSubKey = "Guid";
3666 char subKeyName[51];
3667 DWORD dwIndex, sizeOfSubKeyName=50;
3668 FILETIME filetime;
3670 /* Need to loop over the service providers in the registry */
3671 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3672 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3674 /* Hmmm. Does this mean that there are no service providers? */
3675 ERR(": no service providers?\n");
3676 return DP_OK;
3680 /* Traverse all the service providers we have available */
3681 for( dwIndex=0;
3682 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3683 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3684 ++dwIndex, sizeOfSubKeyName=51 )
3687 HKEY hkServiceProvider;
3688 GUID serviceProviderGUID;
3689 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3690 char returnBuffer[51];
3691 WCHAR buff[51];
3692 DPNAME dpName;
3693 BOOL bBuildPass;
3695 LPVOID lpAddressBuffer = NULL;
3696 DWORD dwAddressBufferSize = 0;
3698 TRACE(" this time through: %s\n", subKeyName );
3700 /* Get a handle for this particular service provider */
3701 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3702 &hkServiceProvider ) != ERROR_SUCCESS )
3704 ERR(": what the heck is going on?\n" );
3705 continue;
3708 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3709 NULL, &returnTypeGUID, returnBuffer,
3710 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3712 ERR(": missing GUID registry data members\n" );
3713 continue;
3716 /* FIXME: Check return types to ensure we're interpreting data right */
3717 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3718 CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
3719 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3721 /* Fill in the DPNAME struct for the service provider */
3722 dpName.dwSize = sizeof( dpName );
3723 dpName.dwFlags = 0;
3724 dpName.u1.lpszShortNameA = subKeyName;
3725 dpName.u2.lpszLongNameA = NULL;
3727 /* Create the compound address for the service provider.
3728 * NOTE: This is a gruesome architectural scar right now. DP
3729 * uses DPL and DPL uses DP. Nasty stuff. This may be why the
3730 * native dll just gets around this little bit by allocating an
3731 * 80 byte buffer which isn't even filled with a valid compound
3732 * address. Oh well. Creating a proper compound address is the
3733 * way to go anyways despite this method taking slightly more
3734 * heap space and realtime :) */
3736 bBuildPass = DP_BuildSPCompoundAddr( &serviceProviderGUID,
3737 &lpAddressBuffer,
3738 &dwAddressBufferSize );
3739 if( !bBuildPass )
3741 ERR( "Can't build compound addr\n" );
3742 return DPERR_GENERIC;
3745 /* The enumeration will return FALSE if we are not to continue */
3746 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3747 &dpName, DPCONNECTION_DIRECTPLAY, lpContext ) )
3749 return DP_OK;
3754 /* Enumerate DirectPlayLobby service providers */
3755 if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY )
3757 HKEY hkResult;
3758 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3759 LPSTR guidDataSubKey = "Guid";
3760 char subKeyName[51];
3761 DWORD dwIndex, sizeOfSubKeyName=50;
3762 FILETIME filetime;
3764 /* Need to loop over the service providers in the registry */
3765 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3766 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3768 /* Hmmm. Does this mean that there are no service providers? */
3769 ERR(": no service providers?\n");
3770 return DP_OK;
3774 /* Traverse all the lobby providers we have available */
3775 for( dwIndex=0;
3776 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3777 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3778 ++dwIndex, sizeOfSubKeyName=51 )
3781 HKEY hkServiceProvider;
3782 GUID serviceProviderGUID;
3783 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3784 char returnBuffer[51];
3785 WCHAR buff[51];
3786 DPNAME dpName;
3787 HRESULT hr;
3789 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3790 LPVOID lpAddressBuffer = NULL;
3791 DWORD dwAddressBufferSize = 0;
3793 TRACE(" this time through: %s\n", subKeyName );
3795 /* Get a handle for this particular service provider */
3796 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3797 &hkServiceProvider ) != ERROR_SUCCESS )
3799 ERR(": what the heck is going on?\n" );
3800 continue;
3803 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3804 NULL, &returnTypeGUID, returnBuffer,
3805 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3807 ERR(": missing GUID registry data members\n" );
3808 continue;
3811 /* FIXME: Check return types to ensure we're interpreting data right */
3812 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3813 CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
3814 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3816 /* Fill in the DPNAME struct for the service provider */
3817 dpName.dwSize = sizeof( dpName );
3818 dpName.dwFlags = 0;
3819 dpName.u1.lpszShortNameA = subKeyName;
3820 dpName.u2.lpszLongNameA = NULL;
3822 /* Create the compound address for the service provider.
3823 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
3824 nast stuff. This may be why the native dll just gets around this little bit by
3825 allocating an 80 byte buffer which isn't even a filled with a valid compound
3826 address. Oh well. Creating a proper compound address is the way to go anyways
3827 despite this method taking slightly more heap space and realtime :) */
3829 dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
3830 dpCompoundAddress.dwDataSize = sizeof( GUID );
3831 dpCompoundAddress.lpData = &serviceProviderGUID;
3833 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3834 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
3836 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3837 return hr;
3840 /* Now allocate the buffer */
3841 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
3843 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3844 &dwAddressBufferSize, TRUE ) ) != DP_OK )
3846 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3847 return hr;
3850 /* The enumeration will return FALSE if we are not to continue */
3851 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3852 &dpName, DPCONNECTION_DIRECTPLAYLOBBY, lpContext ) )
3854 return DP_OK;
3859 return DP_OK;
3862 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
3863 ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3865 ICOM_THIS(IDirectPlay3Impl,iface);
3866 FIXME("(%p)->(%p,%p,%p,0x%08lx): stub\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3867 return DP_OK;
3870 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
3871 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
3872 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
3873 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
3875 lpGroupList lpGList;
3876 lpGroupData lpGData;
3878 FIXME( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
3879 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
3880 lpContext, dwFlags, bAnsi );
3882 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3884 return DPERR_INVALIDGROUP;
3887 if( DPQ_IS_EMPTY( lpGData->groups ) )
3889 return DP_OK;
3892 lpGList = DPQ_FIRST( lpGData->groups );
3894 for( ;; )
3896 /* FIXME: Should check dwFlags for match here */
3898 if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP,
3899 &lpGList->lpGData->name, dwFlags,
3900 lpContext ) )
3902 return DP_OK; /* User requested break */
3905 if( DPQ_IS_ENDOFLIST( lpGList->groups ) )
3907 break;
3910 lpGList = DPQ_NEXT( lpGList->groups );
3914 return DP_OK;
3917 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
3918 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3919 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3920 DWORD dwFlags )
3922 ICOM_THIS(IDirectPlay3Impl,iface);
3923 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3924 lpEnumPlayersCallback2, lpContext, dwFlags,
3925 TRUE );
3928 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
3929 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3930 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3931 DWORD dwFlags )
3933 ICOM_THIS(IDirectPlay3Impl,iface);
3934 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3935 lpEnumPlayersCallback2, lpContext, dwFlags,
3936 FALSE );
3939 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
3940 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3942 ICOM_THIS(IDirectPlay3Impl,iface);
3943 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3944 return DP_OK;
3947 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
3948 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3950 ICOM_THIS(IDirectPlay3Impl,iface);
3951 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3952 return DP_OK;
3955 BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
3956 REFGUID guidDataType,
3957 DWORD dwDataSize,
3958 LPCVOID lpData,
3959 LPVOID lpContext )
3961 /* Looking for the GUID of the provider to load */
3962 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
3963 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
3966 TRACE( "Found SP/LP (%s) %s (data size = 0x%08lx)\n",
3967 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
3969 if( dwDataSize != sizeof( GUID ) )
3971 ERR( "Invalid sp/lp guid size 0x%08lx\n", dwDataSize );
3974 memcpy( lpContext, lpData, dwDataSize );
3976 /* There shouldn't be more than 1 GUID/compound address */
3977 return FALSE;
3980 /* Still waiting for what we want */
3981 return TRUE;
3985 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
3986 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
3988 UINT i;
3989 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3990 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3991 LPCSTR guidDataSubKey = "Guid";
3992 LPCSTR majVerDataSubKey = "dwReserved1";
3993 LPCSTR minVerDataSubKey = "dwReserved2";
3994 LPCSTR pathSubKey = "Path";
3996 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
3998 /* FIXME: Cloned code with a quick hack. */
3999 for( i=0; i<2; i++ )
4001 HKEY hkResult;
4002 LPCSTR searchSubKey;
4003 char subKeyName[51];
4004 DWORD dwIndex, sizeOfSubKeyName=50;
4005 FILETIME filetime;
4007 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
4008 *lpbIsDpSp = (i == 0) ? TRUE : FALSE;
4011 /* Need to loop over the service providers in the registry */
4012 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4013 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4015 /* Hmmm. Does this mean that there are no service providers? */
4016 ERR(": no service providers?\n");
4017 return 0;
4020 /* Traverse all the service providers we have available */
4021 for( dwIndex=0;
4022 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4023 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4024 ++dwIndex, sizeOfSubKeyName=51 )
4027 HKEY hkServiceProvider;
4028 GUID serviceProviderGUID;
4029 DWORD returnType, sizeOfReturnBuffer = 255;
4030 char returnBuffer[256];
4031 WCHAR buff[51];
4032 DWORD dwTemp, len;
4034 TRACE(" this time through: %s\n", subKeyName );
4036 /* Get a handle for this particular service provider */
4037 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4038 &hkServiceProvider ) != ERROR_SUCCESS )
4040 ERR(": what the heck is going on?\n" );
4041 continue;
4044 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4045 NULL, &returnType, returnBuffer,
4046 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4048 ERR(": missing GUID registry data members\n" );
4049 continue;
4052 /* FIXME: Check return types to ensure we're interpreting data right */
4053 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4054 CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
4055 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4057 /* Determine if this is the Service Provider that the user asked for */
4058 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
4060 continue;
4063 if( i == 0 ) /* DP SP */
4065 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
4066 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
4067 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
4070 sizeOfReturnBuffer = 255;
4072 /* Get dwReserved1 */
4073 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
4074 NULL, &returnType, returnBuffer,
4075 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4077 ERR(": missing dwReserved1 registry data members\n") ;
4078 continue;
4081 if( i == 0 )
4082 memcpy( &lpSpData->dwReserved1, returnBuffer, sizeof(lpSpData->dwReserved1) );
4084 sizeOfReturnBuffer = 255;
4086 /* Get dwReserved2 */
4087 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4088 NULL, &returnType, returnBuffer,
4089 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4091 ERR(": missing dwReserved1 registry data members\n") ;
4092 continue;
4095 if( i == 0 )
4096 memcpy( &lpSpData->dwReserved2, returnBuffer, sizeof(lpSpData->dwReserved2) );
4098 sizeOfReturnBuffer = 255;
4100 /* Get the path for this service provider */
4101 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
4102 NULL, NULL, returnBuffer,
4103 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
4105 ERR(": missing PATH registry data members: 0x%08lx\n", dwTemp );
4106 continue;
4109 TRACE( "Loading %s\n", returnBuffer );
4110 return LoadLibraryA( returnBuffer );
4114 return 0;
4117 static
4118 HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider )
4120 HRESULT hr;
4121 LPDPSP_SPINIT SPInit;
4123 /* Initialize the service provider by calling SPInit */
4124 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4126 if( SPInit == NULL )
4128 ERR( "Service provider doesn't provide SPInit interface?\n" );
4129 FreeLibrary( hServiceProvider );
4130 return DPERR_UNAVAILABLE;
4133 TRACE( "Calling SPInit (DP SP entry point)\n" );
4135 hr = (*SPInit)( &This->dp2->spData );
4137 if( FAILED(hr) )
4139 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4140 FreeLibrary( hServiceProvider );
4141 return hr;
4144 /* FIXME: Need to verify the sanity of the returned callback table
4145 * using IsBadCodePtr */
4146 This->dp2->bSPInitialized = TRUE;
4148 /* This interface is now initialized as a DP object */
4149 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
4151 /* Store the handle of the module so that we can unload it later */
4152 This->dp2->hServiceProvider = hServiceProvider;
4154 return hr;
4157 static
4158 HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hLobbyProvider )
4160 HRESULT hr;
4161 LPSP_INIT DPLSPInit;
4163 /* Initialize the service provider by calling SPInit */
4164 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
4166 if( DPLSPInit == NULL )
4168 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4169 FreeLibrary( hLobbyProvider );
4170 return DPERR_UNAVAILABLE;
4173 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4175 hr = (*DPLSPInit)( &This->dp2->dplspData );
4177 if( FAILED(hr) )
4179 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4180 FreeLibrary( hLobbyProvider );
4181 return hr;
4184 /* FIXME: Need to verify the sanity of the returned callback table
4185 * using IsBadCodePtr */
4187 This->dp2->bDPLSPInitialized = TRUE;
4189 /* This interface is now initialized as a lobby object */
4190 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
4192 /* Store the handle of the module so that we can unload it later */
4193 This->dp2->hDPLobbyProvider = hLobbyProvider;
4195 return hr;
4198 static HRESULT WINAPI DP_IF_InitializeConnection
4199 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi )
4201 HMODULE hServiceProvider;
4202 HRESULT hr;
4203 GUID guidSP;
4204 const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
4205 BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4207 TRACE("(%p)->(%p,0x%08lx,%u)\n", This, lpConnection, dwFlags, bAnsi );
4209 if( dwFlags != 0 )
4211 return DPERR_INVALIDFLAGS;
4214 /* Find out what the requested SP is and how large this buffer is */
4215 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
4216 dwAddrSize, &guidSP );
4218 if( FAILED(hr) )
4220 ERR( "Invalid compound address?\n" );
4221 return DPERR_UNAVAILABLE;
4224 /* Load the service provider */
4225 hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp );
4227 if( hServiceProvider == 0 )
4229 ERR( "Unable to load service provider\n" );
4230 return DPERR_UNAVAILABLE;
4233 if( bIsDpSp )
4235 /* Fill in what we can of the Service Provider required information.
4236 * The rest was be done in DP_LoadSP
4238 This->dp2->spData.lpAddress = lpConnection;
4239 This->dp2->spData.dwAddressSize = dwAddrSize;
4240 This->dp2->spData.lpGuid = &guidSP;
4242 hr = DP_InitializeDPSP( This, hServiceProvider );
4244 else
4246 This->dp2->dplspData.lpAddress = lpConnection;
4248 hr = DP_InitializeDPLSP( This, hServiceProvider );
4251 if( FAILED(hr) )
4253 return hr;
4256 return DP_OK;
4259 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4260 ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
4262 ICOM_THIS(IDirectPlay3Impl,iface);
4264 /* This may not be externally invoked once either an SP or LP is initialized */
4265 if( This->dp2->connectionInitialized != NO_PROVIDER )
4267 return DPERR_ALREADYINITIALIZED;
4270 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE );
4273 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4274 ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
4276 ICOM_THIS(IDirectPlay3Impl,iface);
4278 /* This may not be externally invoked once either an SP or LP is initialized */
4279 if( This->dp2->connectionInitialized != NO_PROVIDER )
4281 return DPERR_ALREADYINITIALIZED;
4284 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE );
4287 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4288 ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4289 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4291 ICOM_THIS(IDirectPlay2Impl,iface); /* Yes a dp 2 interface */
4292 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4295 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4296 ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4297 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4299 ICOM_THIS(IDirectPlay2Impl,iface); /* Yes a dp 2 interface */
4300 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4303 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4304 ( LPDIRECTPLAY3A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4306 ICOM_THIS(IDirectPlay3Impl,iface);
4307 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4308 return DP_OK;
4311 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4312 ( LPDIRECTPLAY3 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4314 ICOM_THIS(IDirectPlay3Impl,iface);
4315 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4316 return DP_OK;
4319 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4320 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4322 ICOM_THIS(IDirectPlay3Impl,iface);
4323 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4324 return DP_OK;
4327 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4328 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4330 ICOM_THIS(IDirectPlay3Impl,iface);
4331 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4332 return DP_OK;
4335 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4336 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup )
4338 ICOM_THIS(IDirectPlay3Impl,iface);
4339 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
4340 return DP_OK;
4343 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4344 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup )
4346 ICOM_THIS(IDirectPlay3Impl,iface);
4347 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
4348 return DP_OK;
4351 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4352 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDWORD lpdwFlags )
4354 ICOM_THIS(IDirectPlay3Impl,iface);
4355 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
4356 return DP_OK;
4359 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4360 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDWORD lpdwFlags )
4362 ICOM_THIS(IDirectPlay3Impl,iface);
4363 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
4364 return DP_OK;
4367 static HRESULT WINAPI DP_IF_GetGroupParent
4368 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
4369 BOOL bAnsi )
4371 lpGroupData lpGData;
4373 TRACE("(%p)->(0x%08lx,%p,%u)\n", This, idGroup, lpidGroup, bAnsi );
4375 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4377 return DPERR_INVALIDGROUP;
4380 *lpidGroup = lpGData->dpid;
4382 return DP_OK;
4385 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4386 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
4388 ICOM_THIS(IDirectPlay3Impl,iface);
4389 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE );
4391 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4392 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
4394 ICOM_THIS(IDirectPlay3Impl,iface);
4395 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE );
4398 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4399 ( LPDIRECTPLAY3A iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4401 ICOM_THIS(IDirectPlay3Impl,iface);
4402 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4403 return DP_OK;
4406 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4407 ( LPDIRECTPLAY3 iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4409 ICOM_THIS(IDirectPlay3Impl,iface);
4410 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4411 return DP_OK;
4414 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4415 ( LPDIRECTPLAY3A iface, DPID idPlayer, LPDWORD lpdwFlags )
4417 ICOM_THIS(IDirectPlay3Impl,iface);
4418 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
4419 return DP_OK;
4422 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4423 ( LPDIRECTPLAY3 iface, DPID idPlayer, LPDWORD lpdwFlags )
4425 ICOM_THIS(IDirectPlay3Impl,iface);
4426 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
4427 return DP_OK;
4430 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4431 ( LPDIRECTPLAY4A iface, DPID idGroup, LPDPID lpidGroupOwner )
4433 ICOM_THIS(IDirectPlay4Impl,iface);
4434 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
4435 return DP_OK;
4438 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4439 ( LPDIRECTPLAY4 iface, DPID idGroup, LPDPID lpidGroupOwner )
4441 ICOM_THIS(IDirectPlay4Impl,iface);
4442 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
4443 return DP_OK;
4446 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4447 ( LPDIRECTPLAY4A iface, DPID idGroup , DPID idGroupOwner )
4449 ICOM_THIS(IDirectPlay4Impl,iface);
4450 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
4451 return DP_OK;
4454 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4455 ( LPDIRECTPLAY4 iface, DPID idGroup , DPID idGroupOwner )
4457 ICOM_THIS(IDirectPlay4Impl,iface);
4458 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
4459 return DP_OK;
4462 static HRESULT WINAPI DP_SendEx
4463 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4464 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4465 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi )
4467 lpPlayerList lpPList;
4468 lpGroupData lpGData;
4469 BOOL bValidDestination = FALSE;
4471 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx,0x%08lx,0x%08lx,%p,%p,%u)"
4472 ": stub\n",
4473 This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority,
4474 dwTimeout, lpContext, lpdwMsgID, bAnsi );
4476 /* FIXME: Add parameter checking */
4477 /* FIXME: First call to this needs to aquire a message id which will be
4478 * used for multiple sends
4481 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4483 /* Verify that the message is being sent from a valid local player. The
4484 * from player may be anonymous DPID_UNKNOWN
4486 if( idFrom != DPID_UNKNOWN )
4488 if( ( lpPList = DP_FindPlayer( This, idFrom ) ) == NULL )
4490 WARN( "INFO: Invalid from player 0x%08lx\n", idFrom );
4491 return DPERR_INVALIDPLAYER;
4495 /* Verify that the message is being sent to a valid player, group or to
4496 * everyone. If it's valid, send it to those players.
4498 if( idTo == DPID_ALLPLAYERS )
4500 bValidDestination = TRUE;
4502 /* See if SP has the ability to multicast. If so, use it */
4503 if( This->dp2->spData.lpCB->SendToGroupEx )
4505 FIXME( "Use group sendex to group 0\n" );
4507 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4509 FIXME( "Use obsolete group send to group 0\n" );
4511 else /* No multicast, multiplicate */
4513 /* Send to all players we know about */
4514 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4518 if( ( !bValidDestination ) &&
4519 ( DP_FindPlayer( This, idTo ) != NULL )
4522 bValidDestination = TRUE;
4524 /* Have the service provider send this message */
4525 /* FIXME: Could optimize for local interface sends */
4526 return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority,
4527 dwTimeout, lpContext, lpdwMsgID );
4530 if( ( !bValidDestination ) &&
4531 ( ( lpGData = DP_FindAnyGroup( This, idTo ) ) != NULL )
4534 bValidDestination = TRUE;
4536 /* See if SP has the ability to multicast. If so, use it */
4537 if( This->dp2->spData.lpCB->SendToGroupEx )
4539 FIXME( "Use group sendex\n" );
4541 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4543 FIXME( "Use obsolete group send to group\n" );
4545 else /* No multicast, multiplicate */
4547 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4550 #if 0
4551 if( bExpectReply )
4553 DWORD dwWaitReturn;
4555 This->dp2->hReplyEvent = CreateEventA( NULL, FALSE, FALSE, NULL );
4557 dwWaitReturn = WaitForSingleObject( hReplyEvent, dwTimeout );
4558 if( dwWaitReturn != WAIT_OBJECT_0 )
4560 ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
4563 #endif
4566 if( !bValidDestination )
4568 return DPERR_INVALIDPLAYER;
4570 else
4572 /* FIXME: Should return what the send returned */
4573 return DP_OK;
4578 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4579 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4580 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4581 LPVOID lpContext, LPDWORD lpdwMsgID )
4583 ICOM_THIS(IDirectPlay2Impl,iface); /* yes downcast to 2 */
4584 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4585 dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE );
4588 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4589 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4590 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4591 LPVOID lpContext, LPDWORD lpdwMsgID )
4593 ICOM_THIS(IDirectPlay2Impl,iface); /* yes downcast to 2 */
4594 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4595 dwPriority, dwTimeout, lpContext, lpdwMsgID, FALSE );
4598 static HRESULT WINAPI DP_SP_SendEx
4599 ( IDirectPlay2Impl* This, DWORD dwFlags,
4600 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4601 LPVOID lpContext, LPDWORD lpdwMsgID )
4603 LPDPMSG lpMElem;
4605 FIXME( ": stub\n" );
4607 /* FIXME: This queuing should only be for async messages */
4609 lpMElem = (LPDPMSG)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4610 sizeof( *lpMElem ) );
4611 lpMElem->msg = (DPMSG_GENERIC*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4612 dwDataSize );
4614 CopyMemory( lpMElem->msg, lpData, dwDataSize );
4616 /* FIXME: Need to queue based on priority */
4617 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
4619 return DP_OK;
4622 static HRESULT WINAPI DP_IF_GetMessageQueue
4623 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4624 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi )
4626 HRESULT hr = DP_OK;
4628 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,%p,%u): semi stub\n",
4629 This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi );
4631 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4632 /* FIXME: What about sends which are not immediate? */
4634 if( This->dp2->spData.lpCB->GetMessageQueue )
4636 DPSP_GETMESSAGEQUEUEDATA data;
4638 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4640 /* FIXME: None of this is documented :( */
4642 data.lpISP = This->dp2->spData.lpISP;
4643 data.dwFlags = dwFlags;
4644 data.idFrom = idFrom;
4645 data.idTo = idTo;
4646 data.lpdwNumMsgs = lpdwNumMsgs;
4647 data.lpdwNumBytes = lpdwNumBytes;
4649 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
4651 else
4653 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4656 return hr;
4659 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4660 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4661 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4663 ICOM_THIS(IDirectPlay4Impl,iface);
4664 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4665 lpdwNumBytes, TRUE );
4668 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4669 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4670 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4672 ICOM_THIS(IDirectPlay4Impl,iface);
4673 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4674 lpdwNumBytes, FALSE );
4677 static HRESULT WINAPI DP_IF_CancelMessage
4678 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
4679 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi )
4681 HRESULT hr = DP_OK;
4683 FIXME( "(%p)->(0x%08lx,0x%08lx,%u): semi stub\n",
4684 This, dwMsgID, dwFlags, bAnsi );
4686 if( This->dp2->spData.lpCB->Cancel )
4688 DPSP_CANCELDATA data;
4690 TRACE( "Calling SP Cancel\n" );
4692 /* FIXME: Undocumented callback */
4694 data.lpISP = This->dp2->spData.lpISP;
4695 data.dwFlags = dwFlags;
4696 data.lprglpvSPMsgID = NULL;
4697 data.cSPMsgID = dwMsgID;
4698 data.dwMinPriority = dwMinPriority;
4699 data.dwMaxPriority = dwMaxPriority;
4701 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
4703 else
4705 FIXME( "SP doesn't implement Cancel\n" );
4708 return hr;
4711 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
4712 ( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags )
4714 ICOM_THIS(IDirectPlay4Impl,iface);
4716 if( dwFlags != 0 )
4718 return DPERR_INVALIDFLAGS;
4721 if( dwMsgID == 0 )
4723 dwFlags |= DPCANCELSEND_ALL;
4726 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE );
4729 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
4730 ( LPDIRECTPLAY4 iface, DWORD dwMsgID, DWORD dwFlags )
4732 ICOM_THIS(IDirectPlay4Impl,iface);
4734 if( dwFlags != 0 )
4736 return DPERR_INVALIDFLAGS;
4739 if( dwMsgID == 0 )
4741 dwFlags |= DPCANCELSEND_ALL;
4744 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, FALSE );
4747 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
4748 ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4749 DWORD dwFlags )
4751 ICOM_THIS(IDirectPlay4Impl,iface);
4753 if( dwFlags != 0 )
4755 return DPERR_INVALIDFLAGS;
4758 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4759 dwMaxPriority, TRUE );
4762 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
4763 ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4764 DWORD dwFlags )
4766 ICOM_THIS(IDirectPlay4Impl,iface);
4768 if( dwFlags != 0 )
4770 return DPERR_INVALIDFLAGS;
4773 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4774 dwMaxPriority, FALSE );
4777 /* Note: Hack so we can reuse the old functions without compiler warnings */
4778 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4779 # define XCAST(fun) (typeof(directPlay2WVT.fun))
4780 #else
4781 # define XCAST(fun) (void*)
4782 #endif
4784 static ICOM_VTABLE(IDirectPlay2) directPlay2WVT =
4786 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4787 XCAST(QueryInterface)DP_QueryInterface,
4788 XCAST(AddRef)DP_AddRef,
4789 XCAST(Release)DP_Release,
4791 DirectPlay2WImpl_AddPlayerToGroup,
4792 DirectPlay2WImpl_Close,
4793 DirectPlay2WImpl_CreateGroup,
4794 DirectPlay2WImpl_CreatePlayer,
4795 DirectPlay2WImpl_DeletePlayerFromGroup,
4796 DirectPlay2WImpl_DestroyGroup,
4797 DirectPlay2WImpl_DestroyPlayer,
4798 DirectPlay2WImpl_EnumGroupPlayers,
4799 DirectPlay2WImpl_EnumGroups,
4800 DirectPlay2WImpl_EnumPlayers,
4801 DirectPlay2WImpl_EnumSessions,
4802 DirectPlay2WImpl_GetCaps,
4803 DirectPlay2WImpl_GetGroupData,
4804 DirectPlay2WImpl_GetGroupName,
4805 DirectPlay2WImpl_GetMessageCount,
4806 DirectPlay2WImpl_GetPlayerAddress,
4807 DirectPlay2WImpl_GetPlayerCaps,
4808 DirectPlay2WImpl_GetPlayerData,
4809 DirectPlay2WImpl_GetPlayerName,
4810 DirectPlay2WImpl_GetSessionDesc,
4811 DirectPlay2WImpl_Initialize,
4812 DirectPlay2WImpl_Open,
4813 DirectPlay2WImpl_Receive,
4814 DirectPlay2WImpl_Send,
4815 DirectPlay2WImpl_SetGroupData,
4816 DirectPlay2WImpl_SetGroupName,
4817 DirectPlay2WImpl_SetPlayerData,
4818 DirectPlay2WImpl_SetPlayerName,
4819 DirectPlay2WImpl_SetSessionDesc
4821 #undef XCAST
4823 /* Note: Hack so we can reuse the old functions without compiler warnings */
4824 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4825 # define XCAST(fun) (typeof(directPlay2AVT.fun))
4826 #else
4827 # define XCAST(fun) (void*)
4828 #endif
4830 static ICOM_VTABLE(IDirectPlay2) directPlay2AVT =
4832 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4833 XCAST(QueryInterface)DP_QueryInterface,
4834 XCAST(AddRef)DP_AddRef,
4835 XCAST(Release)DP_Release,
4837 DirectPlay2AImpl_AddPlayerToGroup,
4838 DirectPlay2AImpl_Close,
4839 DirectPlay2AImpl_CreateGroup,
4840 DirectPlay2AImpl_CreatePlayer,
4841 DirectPlay2AImpl_DeletePlayerFromGroup,
4842 DirectPlay2AImpl_DestroyGroup,
4843 DirectPlay2AImpl_DestroyPlayer,
4844 DirectPlay2AImpl_EnumGroupPlayers,
4845 DirectPlay2AImpl_EnumGroups,
4846 DirectPlay2AImpl_EnumPlayers,
4847 DirectPlay2AImpl_EnumSessions,
4848 DirectPlay2AImpl_GetCaps,
4849 DirectPlay2AImpl_GetGroupData,
4850 DirectPlay2AImpl_GetGroupName,
4851 DirectPlay2AImpl_GetMessageCount,
4852 DirectPlay2AImpl_GetPlayerAddress,
4853 DirectPlay2AImpl_GetPlayerCaps,
4854 DirectPlay2AImpl_GetPlayerData,
4855 DirectPlay2AImpl_GetPlayerName,
4856 DirectPlay2AImpl_GetSessionDesc,
4857 DirectPlay2AImpl_Initialize,
4858 DirectPlay2AImpl_Open,
4859 DirectPlay2AImpl_Receive,
4860 DirectPlay2AImpl_Send,
4861 DirectPlay2AImpl_SetGroupData,
4862 DirectPlay2AImpl_SetGroupName,
4863 DirectPlay2AImpl_SetPlayerData,
4864 DirectPlay2AImpl_SetPlayerName,
4865 DirectPlay2AImpl_SetSessionDesc
4867 #undef XCAST
4870 /* Note: Hack so we can reuse the old functions without compiler warnings */
4871 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4872 # define XCAST(fun) (typeof(directPlay3AVT.fun))
4873 #else
4874 # define XCAST(fun) (void*)
4875 #endif
4877 static ICOM_VTABLE(IDirectPlay3) directPlay3AVT =
4879 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4880 XCAST(QueryInterface)DP_QueryInterface,
4881 XCAST(AddRef)DP_AddRef,
4882 XCAST(Release)DP_Release,
4884 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
4885 XCAST(Close)DirectPlay2AImpl_Close,
4886 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
4887 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
4888 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
4889 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
4890 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
4891 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
4892 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
4893 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
4894 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
4895 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
4896 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
4897 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
4898 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
4899 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
4900 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
4901 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
4902 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
4903 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
4904 XCAST(Initialize)DirectPlay2AImpl_Initialize,
4905 XCAST(Open)DirectPlay2AImpl_Open,
4906 XCAST(Receive)DirectPlay2AImpl_Receive,
4907 XCAST(Send)DirectPlay2AImpl_Send,
4908 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
4909 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
4910 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
4911 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
4912 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
4914 DirectPlay3AImpl_AddGroupToGroup,
4915 DirectPlay3AImpl_CreateGroupInGroup,
4916 DirectPlay3AImpl_DeleteGroupFromGroup,
4917 DirectPlay3AImpl_EnumConnections,
4918 DirectPlay3AImpl_EnumGroupsInGroup,
4919 DirectPlay3AImpl_GetGroupConnectionSettings,
4920 DirectPlay3AImpl_InitializeConnection,
4921 DirectPlay3AImpl_SecureOpen,
4922 DirectPlay3AImpl_SendChatMessage,
4923 DirectPlay3AImpl_SetGroupConnectionSettings,
4924 DirectPlay3AImpl_StartSession,
4925 DirectPlay3AImpl_GetGroupFlags,
4926 DirectPlay3AImpl_GetGroupParent,
4927 DirectPlay3AImpl_GetPlayerAccount,
4928 DirectPlay3AImpl_GetPlayerFlags
4930 #undef XCAST
4932 /* Note: Hack so we can reuse the old functions without compiler warnings */
4933 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4934 # define XCAST(fun) (typeof(directPlay3WVT.fun))
4935 #else
4936 # define XCAST(fun) (void*)
4937 #endif
4938 static ICOM_VTABLE(IDirectPlay3) directPlay3WVT =
4940 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4941 XCAST(QueryInterface)DP_QueryInterface,
4942 XCAST(AddRef)DP_AddRef,
4943 XCAST(Release)DP_Release,
4945 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
4946 XCAST(Close)DirectPlay2WImpl_Close,
4947 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
4948 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
4949 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
4950 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
4951 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
4952 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
4953 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
4954 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
4955 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
4956 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
4957 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
4958 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
4959 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
4960 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
4961 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
4962 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
4963 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
4964 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
4965 XCAST(Initialize)DirectPlay2WImpl_Initialize,
4966 XCAST(Open)DirectPlay2WImpl_Open,
4967 XCAST(Receive)DirectPlay2WImpl_Receive,
4968 XCAST(Send)DirectPlay2WImpl_Send,
4969 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
4970 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
4971 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
4972 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
4973 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
4975 DirectPlay3WImpl_AddGroupToGroup,
4976 DirectPlay3WImpl_CreateGroupInGroup,
4977 DirectPlay3WImpl_DeleteGroupFromGroup,
4978 DirectPlay3WImpl_EnumConnections,
4979 DirectPlay3WImpl_EnumGroupsInGroup,
4980 DirectPlay3WImpl_GetGroupConnectionSettings,
4981 DirectPlay3WImpl_InitializeConnection,
4982 DirectPlay3WImpl_SecureOpen,
4983 DirectPlay3WImpl_SendChatMessage,
4984 DirectPlay3WImpl_SetGroupConnectionSettings,
4985 DirectPlay3WImpl_StartSession,
4986 DirectPlay3WImpl_GetGroupFlags,
4987 DirectPlay3WImpl_GetGroupParent,
4988 DirectPlay3WImpl_GetPlayerAccount,
4989 DirectPlay3WImpl_GetPlayerFlags
4991 #undef XCAST
4993 /* Note: Hack so we can reuse the old functions without compiler warnings */
4994 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4995 # define XCAST(fun) (typeof(directPlay4WVT.fun))
4996 #else
4997 # define XCAST(fun) (void*)
4998 #endif
4999 static ICOM_VTABLE(IDirectPlay4) directPlay4WVT =
5001 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5002 XCAST(QueryInterface)DP_QueryInterface,
5003 XCAST(AddRef)DP_AddRef,
5004 XCAST(Release)DP_Release,
5006 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
5007 XCAST(Close)DirectPlay2WImpl_Close,
5008 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
5009 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
5010 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
5011 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
5012 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5013 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5014 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5015 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5016 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5017 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5018 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5019 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5020 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5021 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5022 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5023 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5024 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5025 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5026 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5027 XCAST(Open)DirectPlay2WImpl_Open,
5028 XCAST(Receive)DirectPlay2WImpl_Receive,
5029 XCAST(Send)DirectPlay2WImpl_Send,
5030 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5031 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5032 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5033 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5034 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5036 XCAST(AddGroupToGroup)DirectPlay3WImpl_AddGroupToGroup,
5037 XCAST(CreateGroupInGroup)DirectPlay3WImpl_CreateGroupInGroup,
5038 XCAST(DeleteGroupFromGroup)DirectPlay3WImpl_DeleteGroupFromGroup,
5039 XCAST(EnumConnections)DirectPlay3WImpl_EnumConnections,
5040 XCAST(EnumGroupsInGroup)DirectPlay3WImpl_EnumGroupsInGroup,
5041 XCAST(GetGroupConnectionSettings)DirectPlay3WImpl_GetGroupConnectionSettings,
5042 XCAST(InitializeConnection)DirectPlay3WImpl_InitializeConnection,
5043 XCAST(SecureOpen)DirectPlay3WImpl_SecureOpen,
5044 XCAST(SendChatMessage)DirectPlay3WImpl_SendChatMessage,
5045 XCAST(SetGroupConnectionSettings)DirectPlay3WImpl_SetGroupConnectionSettings,
5046 XCAST(StartSession)DirectPlay3WImpl_StartSession,
5047 XCAST(GetGroupFlags)DirectPlay3WImpl_GetGroupFlags,
5048 XCAST(GetGroupParent)DirectPlay3WImpl_GetGroupParent,
5049 XCAST(GetPlayerAccount)DirectPlay3WImpl_GetPlayerAccount,
5050 XCAST(GetPlayerFlags)DirectPlay3WImpl_GetPlayerFlags,
5052 DirectPlay4WImpl_GetGroupOwner,
5053 DirectPlay4WImpl_SetGroupOwner,
5054 DirectPlay4WImpl_SendEx,
5055 DirectPlay4WImpl_GetMessageQueue,
5056 DirectPlay4WImpl_CancelMessage,
5057 DirectPlay4WImpl_CancelPriority
5059 #undef XCAST
5062 /* Note: Hack so we can reuse the old functions without compiler warnings */
5063 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5064 # define XCAST(fun) (typeof(directPlay4AVT.fun))
5065 #else
5066 # define XCAST(fun) (void*)
5067 #endif
5068 static ICOM_VTABLE(IDirectPlay4) directPlay4AVT =
5070 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5071 XCAST(QueryInterface)DP_QueryInterface,
5072 XCAST(AddRef)DP_AddRef,
5073 XCAST(Release)DP_Release,
5075 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
5076 XCAST(Close)DirectPlay2AImpl_Close,
5077 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
5078 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
5079 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
5080 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
5081 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
5082 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
5083 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
5084 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
5085 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
5086 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
5087 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
5088 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
5089 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5090 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5091 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5092 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5093 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5094 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5095 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5096 XCAST(Open)DirectPlay2AImpl_Open,
5097 XCAST(Receive)DirectPlay2AImpl_Receive,
5098 XCAST(Send)DirectPlay2AImpl_Send,
5099 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5100 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5101 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5102 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5103 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5105 XCAST(AddGroupToGroup)DirectPlay3AImpl_AddGroupToGroup,
5106 XCAST(CreateGroupInGroup)DirectPlay3AImpl_CreateGroupInGroup,
5107 XCAST(DeleteGroupFromGroup)DirectPlay3AImpl_DeleteGroupFromGroup,
5108 XCAST(EnumConnections)DirectPlay3AImpl_EnumConnections,
5109 XCAST(EnumGroupsInGroup)DirectPlay3AImpl_EnumGroupsInGroup,
5110 XCAST(GetGroupConnectionSettings)DirectPlay3AImpl_GetGroupConnectionSettings,
5111 XCAST(InitializeConnection)DirectPlay3AImpl_InitializeConnection,
5112 XCAST(SecureOpen)DirectPlay3AImpl_SecureOpen,
5113 XCAST(SendChatMessage)DirectPlay3AImpl_SendChatMessage,
5114 XCAST(SetGroupConnectionSettings)DirectPlay3AImpl_SetGroupConnectionSettings,
5115 XCAST(StartSession)DirectPlay3AImpl_StartSession,
5116 XCAST(GetGroupFlags)DirectPlay3AImpl_GetGroupFlags,
5117 XCAST(GetGroupParent)DirectPlay3AImpl_GetGroupParent,
5118 XCAST(GetPlayerAccount)DirectPlay3AImpl_GetPlayerAccount,
5119 XCAST(GetPlayerFlags)DirectPlay3AImpl_GetPlayerFlags,
5121 DirectPlay4AImpl_GetGroupOwner,
5122 DirectPlay4AImpl_SetGroupOwner,
5123 DirectPlay4AImpl_SendEx,
5124 DirectPlay4AImpl_GetMessageQueue,
5125 DirectPlay4AImpl_CancelMessage,
5126 DirectPlay4AImpl_CancelPriority
5128 #undef XCAST
5130 extern
5131 HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP,
5132 DPID idPlayer,
5133 LPVOID* lplpData )
5135 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5137 if( lpPlayer == NULL )
5139 return DPERR_INVALIDPLAYER;
5142 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
5144 return DP_OK;
5147 extern
5148 HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP,
5149 DPID idPlayer,
5150 LPVOID lpData )
5152 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5154 if( lpPlayer == NULL )
5156 return DPERR_INVALIDPLAYER;
5159 lpPlayer->lpPData->lpSPPlayerData = lpData;
5161 return DP_OK;
5164 /***************************************************************************
5165 * DirectPlayEnumerate [DPLAYX.9]
5166 * DirectPlayEnumerateA [DPLAYX.2]
5168 * The pointer to the structure lpContext will be filled with the
5169 * appropriate data for each service offered by the OS. These services are
5170 * not necessarily available on this particular machine but are defined
5171 * as simple service providers under the "Service Providers" registry key.
5172 * This structure is then passed to lpEnumCallback for each of the different
5173 * services.
5175 * This API is useful only for applications written using DirectX3 or
5176 * worse. It is superceeded by IDirectPlay3::EnumConnections which also
5177 * gives information on the actual connections.
5179 * defn of a service provider:
5180 * A dynamic-link library used by DirectPlay to communicate over a network.
5181 * The service provider contains all the network-specific code required
5182 * to send and receive messages. Online services and network operators can
5183 * supply service providers to use specialized hardware, protocols, communications
5184 * media, and network resources.
5186 * TODO: Allocate string buffer space from the heap (length from reg)
5187 * Pass real device driver numbers...
5188 * Get the GUID properly...
5190 HRESULT WINAPI DirectPlayEnumerateA( LPDPENUMDPCALLBACKA lpEnumCallback,
5191 LPVOID lpContext )
5194 HKEY hkResult;
5195 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
5196 DWORD dwIndex;
5197 DWORD sizeOfSubKeyName=50;
5198 char subKeyName[51];
5199 FILETIME filetime;
5201 TRACE(": lpEnumCallback=%p lpContext=%p\n", lpEnumCallback, lpContext );
5203 if( !lpEnumCallback || !*lpEnumCallback )
5205 return DPERR_INVALIDPARAMS;
5208 /* Need to loop over the service providers in the registry */
5209 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
5210 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
5212 /* Hmmm. Does this mean that there are no service providers? */
5213 ERR(": no service providers?\n");
5214 return DPERR_NOSERVICEPROVIDER;
5217 /* Traverse all the service providers we have available */
5218 for( dwIndex=0;
5219 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
5220 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
5221 ++dwIndex, sizeOfSubKeyName=50 )
5223 LPSTR majVerDataSubKey = "dwReserved1";
5224 LPSTR minVerDataSubKey = "dwReserved2";
5225 LPSTR guidDataSubKey = "Guid";
5226 HKEY hkServiceProvider;
5227 GUID serviceProviderGUID;
5228 DWORD returnTypeGUID, returnTypeReserved, sizeOfReturnBuffer = 50;
5229 char returnBuffer[51];
5230 WCHAR buff[51];
5231 DWORD majVersionNum , minVersionNum = 0;
5233 TRACE(" this time through: %s\n", subKeyName );
5235 /* Get a handle for this particular service provider */
5236 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
5237 &hkServiceProvider ) != ERROR_SUCCESS )
5239 ERR(": what the heck is going on?\n" );
5240 continue;
5243 /* Get the GUID, Device major number and device minor number
5244 * from the registry.
5246 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
5247 NULL, &returnTypeGUID, returnBuffer,
5248 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5250 ERR(": missing GUID registry data members\n" );
5251 continue;
5254 /* FIXME: Check return types to ensure we're interpreting data right */
5255 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
5256 CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
5258 /* FIXME: Need to know which of dwReserved1 and dwReserved2 are maj and min */
5260 sizeOfReturnBuffer = 50;
5261 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
5262 NULL, &returnTypeReserved, returnBuffer,
5263 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5265 ERR(": missing dwReserved1 registry data members\n") ;
5266 continue;
5268 memcpy( &majVersionNum, returnBuffer, sizeof(majVersionNum) );
5270 sizeOfReturnBuffer = 50;
5271 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
5272 NULL, &returnTypeReserved, returnBuffer,
5273 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5275 ERR(": missing dwReserved2 registry data members\n") ;
5276 continue;
5278 memcpy( &minVersionNum, returnBuffer, sizeof(minVersionNum) );
5281 /* The enumeration will return FALSE if we are not to continue */
5282 if( !lpEnumCallback( &serviceProviderGUID , subKeyName,
5283 majVersionNum, minVersionNum, lpContext ) )
5285 WARN("lpEnumCallback returning FALSE\n" );
5286 break;
5290 return DP_OK;
5294 /***************************************************************************
5295 * DirectPlayEnumerateW [DPLAYX.3]
5298 HRESULT WINAPI DirectPlayEnumerateW( LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5301 FIXME(":stub\n");
5303 return DPERR_OUTOFMEMORY;
5307 typedef struct tagCreateEnum
5309 LPVOID lpConn;
5310 LPCGUID lpGuid;
5311 } CreateEnumData, *lpCreateEnumData;
5313 /* Find and copy the matching connection for the SP guid */
5314 static BOOL CALLBACK cbDPCreateEnumConnections(
5315 LPCGUID lpguidSP,
5316 LPVOID lpConnection,
5317 DWORD dwConnectionSize,
5318 LPCDPNAME lpName,
5319 DWORD dwFlags,
5320 LPVOID lpContext)
5322 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5324 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5326 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5328 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5329 dwConnectionSize );
5330 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5332 /* Found the record that we were looking for */
5333 return FALSE;
5336 /* Haven't found what were looking for yet */
5337 return TRUE;
5341 /***************************************************************************
5342 * DirectPlayCreate [DPLAYX.1]
5345 HRESULT WINAPI DirectPlayCreate
5346 ( LPGUID lpGUID, LPDIRECTPLAY2 *lplpDP, IUnknown *pUnk)
5348 HRESULT hr;
5349 LPDIRECTPLAY3A lpDP3A;
5350 CreateEnumData cbData;
5352 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5354 if( pUnk != NULL )
5356 return CLASS_E_NOAGGREGATION;
5359 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5360 give them an IDirectPlay2A object and hope that doesn't cause problems */
5361 if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
5363 return DPERR_UNAVAILABLE;
5366 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
5368 /* The GUID_NULL means don't bind a service provider. Just return the
5369 interface as is */
5370 return DP_OK;
5373 /* Bind the desired service provider since lpGUID is non NULL */
5374 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
5376 /* We're going to use a DP3 interface */
5377 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
5378 (LPVOID*)&lpDP3A );
5379 if( FAILED(hr) )
5381 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
5382 return hr;
5385 cbData.lpConn = NULL;
5386 cbData.lpGuid = lpGUID;
5388 /* We were given a service provider, find info about it... */
5389 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
5390 &cbData, DPCONNECTION_DIRECTPLAY );
5391 if( ( FAILED(hr) ) ||
5392 ( cbData.lpConn == NULL )
5395 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
5396 IDirectPlayX_Release( lpDP3A );
5397 return DPERR_UNAVAILABLE;
5400 /* Initialize the service provider */
5401 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
5402 if( FAILED(hr) )
5404 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
5405 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5406 IDirectPlayX_Release( lpDP3A );
5407 return hr;
5410 /* Release our version of the interface now that we're done with it */
5411 IDirectPlayX_Release( lpDP3A );
5412 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5414 return DP_OK;