Removed trailing whitespace.
[wine/wine-gecko.git] / dlls / dplayx / dplay.c
blobedefc775792329731acf03d7471d6993e1f24fd0
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 #include "windef.h"
28 #include "winerror.h"
29 #include "winbase.h"
30 #include "winnt.h"
31 #include "winreg.h"
32 #include "winnls.h"
33 #include "wine/unicode.h"
34 #include "dplay.h"
35 #include "wine/debug.h"
37 #include "dpinit.h"
38 #include "dplayx_global.h"
39 #include "name_server.h"
40 #include "dplayx_queue.h"
41 #include "dplaysp.h"
42 #include "dplay_global.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(dplay);
46 /* FIXME: Should this be externed? */
47 extern HRESULT DPL_CreateCompoundAddress
48 ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
49 LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
52 /* Local function prototypes */
53 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid );
54 static lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* iface, LPDPID lpid,
55 LPDPNAME lpName, DWORD dwFlags,
56 HANDLE hEvent, BOOL bAnsi );
57 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi );
58 static void DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
59 LPVOID lpData, DWORD dwDataSize );
61 static lpGroupData DP_CreateGroup( IDirectPlay2AImpl* iface, LPDPID lpid,
62 LPDPNAME lpName, DWORD dwFlags,
63 DPID idParent, BOOL bAnsi );
64 static void DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
65 LPVOID lpData, DWORD dwDataSize );
66 static void DP_DeleteDPNameStruct( LPDPNAME lpDPName );
67 static void DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid );
68 static BOOL CALLBACK cbDeletePlayerFromAllGroups( DPID dpId,
69 DWORD dwPlayerType,
70 LPCDPNAME lpName,
71 DWORD dwFlags,
72 LPVOID lpContext );
73 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid );
74 static BOOL CALLBACK cbRemoveGroupOrPlayer( DPID dpId, DWORD dwPlayerType,
75 LPCDPNAME lpName, DWORD dwFlags,
76 LPVOID lpContext );
77 static void DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid );
79 /* Helper methods for player/group interfaces */
80 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
81 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
82 DPID idPlayer, BOOL bAnsi );
83 static HRESULT WINAPI DP_IF_CreatePlayer
84 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, LPDPID lpidPlayer,
85 LPDPNAME lpPlayerName, HANDLE hEvent, LPVOID lpData,
86 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
87 static HRESULT WINAPI DP_IF_DestroyGroup
88 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi );
89 static HRESULT WINAPI DP_IF_DestroyPlayer
90 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi );
91 static HRESULT WINAPI DP_IF_EnumGroupPlayers
92 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
93 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
94 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
95 static HRESULT WINAPI DP_IF_EnumGroups
96 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
97 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
98 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
99 static HRESULT WINAPI DP_IF_EnumPlayers
100 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
101 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
102 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
103 static HRESULT WINAPI DP_IF_GetGroupData
104 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
105 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
106 static HRESULT WINAPI DP_IF_GetGroupName
107 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
108 LPDWORD lpdwDataSize, BOOL bAnsi );
109 static HRESULT WINAPI DP_IF_GetPlayerData
110 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
111 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
112 static HRESULT WINAPI DP_IF_GetPlayerName
113 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
114 LPDWORD lpdwDataSize, BOOL bAnsi );
115 static HRESULT WINAPI DP_IF_SetGroupName
116 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
117 DWORD dwFlags, BOOL bAnsi );
118 static HRESULT WINAPI DP_IF_SetPlayerData
119 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
120 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
121 static HRESULT WINAPI DP_IF_SetPlayerName
122 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
123 DWORD dwFlags, BOOL bAnsi );
124 static HRESULT WINAPI DP_IF_AddGroupToGroup
125 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
126 static HRESULT WINAPI DP_IF_CreateGroup
127 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
128 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
129 DWORD dwFlags, BOOL bAnsi );
130 static HRESULT WINAPI DP_IF_CreateGroupInGroup
131 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
132 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
133 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
134 static HRESULT WINAPI DP_IF_AddPlayerToGroup
135 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
136 DPID idPlayer, BOOL bAnsi );
137 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
138 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
139 static HRESULT WINAPI DP_SetSessionDesc
140 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
141 DWORD dwFlags, BOOL bInitial, BOOL bAnsi );
142 static HRESULT WINAPI DP_SecureOpen
143 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
144 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
145 BOOL bAnsi );
146 static HRESULT WINAPI DP_SendEx
147 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
148 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
149 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi );
150 static HRESULT WINAPI DP_IF_Receive
151 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
152 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi );
153 static HRESULT WINAPI DP_IF_GetMessageQueue
154 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
155 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi );
156 static HRESULT WINAPI DP_SP_SendEx
157 ( IDirectPlay2Impl* This, DWORD dwFlags,
158 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
159 LPVOID lpContext, LPDWORD lpdwMsgID );
160 static HRESULT WINAPI DP_IF_SetGroupData
161 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
162 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
163 static HRESULT WINAPI DP_IF_GetPlayerCaps
164 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
165 DWORD dwFlags );
166 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi );
167 static HRESULT WINAPI DP_IF_CancelMessage
168 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
169 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi );
170 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
171 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
172 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
173 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
174 static HRESULT WINAPI DP_IF_GetGroupParent
175 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
176 BOOL bAnsi );
177 static HRESULT WINAPI DP_IF_GetCaps
178 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags );
179 static HRESULT WINAPI DP_IF_EnumSessions
180 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
181 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
182 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
183 static HRESULT WINAPI DP_IF_InitializeConnection
184 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi );
185 static BOOL CALLBACK cbDPCreateEnumConnections( LPCGUID lpguidSP,
186 LPVOID lpConnection, DWORD dwConnectionSize, LPCDPNAME lpName,
187 DWORD dwFlags, LPVOID lpContext );
188 static BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
189 LPDWORD lpdwBufSize );
193 static inline DPID DP_NextObjectId(void);
194 static DPID DP_GetRemoteNextObjectId(void);
197 static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc,
198 LPCDPSESSIONDESC2 srcSessDesc, BOOL bAnsi );
201 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp );
202 static HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider );
203 static HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hServiceProvider );
210 #define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */
211 #define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported
212 we don't have to change much */
213 #define DPID_NAME_SERVER 0x19a9d65b /* Don't ask me why */
215 /* Strip out dwFlag values which cannot be sent in the CREATEGROUP msg */
216 #define DPMSG_CREATEGROUP_DWFLAGS(x) ( (x) & DPGROUP_HIDDEN )
218 /* Strip out all dwFlags values for CREATEPLAYER msg */
219 #define DPMSG_CREATEPLAYER_DWFLAGS(x) 0
221 static DWORD kludgePlayerGroupId = 1000;
223 /* ------------------------------------------------------------------ */
226 static BOOL DP_CreateIUnknown( LPVOID lpDP )
228 ICOM_THIS(IDirectPlay2AImpl,lpDP);
230 This->unk = (DirectPlayIUnknownData*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
231 sizeof( *(This->unk) ) );
232 if ( This->unk == NULL )
234 return FALSE;
237 InitializeCriticalSection( &This->unk->DP_lock );
239 return TRUE;
242 static BOOL DP_DestroyIUnknown( LPVOID lpDP )
244 ICOM_THIS(IDirectPlay2AImpl,lpDP);
246 DeleteCriticalSection( &This->unk->DP_lock );
247 HeapFree( GetProcessHeap(), 0, This->unk );
249 return TRUE;
252 static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
254 ICOM_THIS(IDirectPlay2AImpl,lpDP);
256 This->dp2 = (DirectPlay2Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
257 sizeof( *(This->dp2) ) );
258 if ( This->dp2 == NULL )
260 return FALSE;
263 This->dp2->bConnectionOpen = FALSE;
265 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
267 This->dp2->bHostInterface = FALSE;
269 DPQ_INIT(This->dp2->receiveMsgs);
270 DPQ_INIT(This->dp2->sendMsgs);
271 DPQ_INIT(This->dp2->replysExpected);
273 if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
275 /* FIXME: Memory leak */
276 return FALSE;
279 /* Provide an initial session desc with nothing in it */
280 This->dp2->lpSessionDesc = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
281 HEAP_ZERO_MEMORY,
282 sizeof( *This->dp2->lpSessionDesc ) );
283 if( This->dp2->lpSessionDesc == NULL )
285 /* FIXME: Memory leak */
286 return FALSE;
288 This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc );
290 /* We are a emulating a dp 6 implementation */
291 This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION;
293 This->dp2->spData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
294 sizeof( *This->dp2->spData.lpCB ) );
295 This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB );
296 This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION;
298 /* This is the pointer to the service provider */
299 if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP,
300 (LPVOID*)&This->dp2->spData.lpISP, This ) )
303 /* FIXME: Memory leak */
304 return FALSE;
307 /* Setup lobby provider information */
308 This->dp2->dplspData.dwSPVersion = DPSP_MAJORVERSION;
309 This->dp2->dplspData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
310 sizeof( *This->dp2->dplspData.lpCB ) );
311 This->dp2->dplspData.lpCB->dwSize = sizeof( *This->dp2->dplspData.lpCB );
313 if( FAILED( DPLSP_CreateInterface( &IID_IDPLobbySP,
314 (LPVOID*)&This->dp2->dplspData.lpISP, This ) )
317 /* FIXME: Memory leak */
318 return FALSE;
321 return TRUE;
324 /* Definition of the global function in dplayx_queue.h. #
325 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
326 DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
328 HeapFree( GetProcessHeap(), 0, elem );
331 /* Function to delete the list of groups with this interface. Needs to
332 * delete the group and player lists associated with this group as well
333 * as the group data associated with this group. It should not delete
334 * player data as that is shared with the top player list and will be
335 * deleted with that.
337 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList );
338 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList )
340 DPQ_DELETEQ( elem->lpGData->groups, groups,
341 lpGroupList, cbDeleteElemFromHeap );
342 DPQ_DELETEQ( elem->lpGData->players, players,
343 lpPlayerList, cbDeleteElemFromHeap );
344 HeapFree( GetProcessHeap(), 0, elem->lpGData );
345 HeapFree( GetProcessHeap(), 0, elem );
348 /* Function to delete the list of players with this interface. Needs to
349 * delete the player data for all players as well.
351 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList );
352 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList )
354 HeapFree( GetProcessHeap(), 0, elem->lpPData );
355 HeapFree( GetProcessHeap(), 0, elem );
358 static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
360 ICOM_THIS(IDirectPlay2AImpl,lpDP);
362 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
364 TerminateThread( This->dp2->hEnumSessionThread, 0 );
365 CloseHandle( This->dp2->hEnumSessionThread );
368 /* Finish with the SP - have it shutdown */
369 if( This->dp2->spData.lpCB->ShutdownEx )
371 DPSP_SHUTDOWNDATA data;
373 TRACE( "Calling SP ShutdownEx\n" );
375 data.lpISP = This->dp2->spData.lpISP;
377 (*This->dp2->spData.lpCB->ShutdownEx)( &data );
379 else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
381 TRACE( "Calling obsolete SP Shutdown\n" );
382 (*This->dp2->spData.lpCB->Shutdown)();
385 /* Unload the SP (if it exists) */
386 if( This->dp2->hServiceProvider != 0 )
388 FreeLibrary( This->dp2->hServiceProvider );
391 /* Unload the Lobby Provider (if it exists) */
392 if( This->dp2->hDPLobbyProvider != 0 )
394 FreeLibrary( This->dp2->hDPLobbyProvider );
397 #if 0
398 DPQ_DELETEQ( This->dp2->players, players, lpPlayerList, cbDeletePlayerElem );
399 DPQ_DELETEQ( This->dp2->groups, groups, lpGroupList, cbDeleteGroupsElem );
400 #endif
402 /* FIXME: Need to delete receive and send msgs queue contents */
404 NS_DeleteSessionCache( This->dp2->lpNameServerData );
406 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
408 IDirectPlaySP_Release( This->dp2->spData.lpISP );
410 /* Delete the contents */
411 HeapFree( GetProcessHeap(), 0, This->dp2 );
413 return TRUE;
416 static BOOL DP_CreateDirectPlay3( LPVOID lpDP )
418 ICOM_THIS(IDirectPlay3AImpl,lpDP);
420 This->dp3 = (DirectPlay3Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
421 sizeof( *(This->dp3) ) );
422 if ( This->dp3 == NULL )
424 return FALSE;
427 return TRUE;
430 static BOOL DP_DestroyDirectPlay3( LPVOID lpDP )
432 ICOM_THIS(IDirectPlay3AImpl,lpDP);
434 /* Delete the contents */
435 HeapFree( GetProcessHeap(), 0, This->dp3 );
437 return TRUE;
440 static BOOL DP_CreateDirectPlay4( LPVOID lpDP )
442 ICOM_THIS(IDirectPlay4AImpl,lpDP);
444 This->dp4 = (DirectPlay4Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
445 sizeof( *(This->dp4) ) );
446 if ( This->dp4 == NULL )
448 return FALSE;
451 return TRUE;
454 static BOOL DP_DestroyDirectPlay4( LPVOID lpDP )
456 ICOM_THIS(IDirectPlay3AImpl,lpDP);
458 /* Delete the contents */
459 HeapFree( GetProcessHeap(), 0, This->dp4 );
461 return TRUE;
465 /* Create a new interface */
466 extern
467 HRESULT DP_CreateInterface
468 ( REFIID riid, LPVOID* ppvObj )
470 TRACE( " for %s\n", debugstr_guid( riid ) );
472 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
473 sizeof( IDirectPlay2Impl ) );
475 if( *ppvObj == NULL )
477 return DPERR_OUTOFMEMORY;
480 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
482 ICOM_THIS(IDirectPlay2Impl,*ppvObj);
483 ICOM_VTBL(This) = &directPlay2WVT;
485 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
487 ICOM_THIS(IDirectPlay2AImpl,*ppvObj);
488 ICOM_VTBL(This) = &directPlay2AVT;
490 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
492 ICOM_THIS(IDirectPlay3Impl,*ppvObj);
493 ICOM_VTBL(This) = &directPlay3WVT;
495 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
497 ICOM_THIS(IDirectPlay3AImpl,*ppvObj);
498 ICOM_VTBL(This) = &directPlay3AVT;
500 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
502 ICOM_THIS(IDirectPlay4Impl,*ppvObj);
503 ICOM_VTBL(This) = &directPlay4WVT;
505 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
507 ICOM_THIS(IDirectPlay4AImpl,*ppvObj);
508 ICOM_VTBL(This) = &directPlay4AVT;
510 else
512 /* Unsupported interface */
513 HeapFree( GetProcessHeap(), 0, *ppvObj );
514 *ppvObj = NULL;
516 return E_NOINTERFACE;
519 /* Initialize it */
520 if ( DP_CreateIUnknown( *ppvObj ) &&
521 DP_CreateDirectPlay2( *ppvObj ) &&
522 DP_CreateDirectPlay3( *ppvObj ) &&
523 DP_CreateDirectPlay4( *ppvObj )
526 IDirectPlayX_AddRef( (LPDIRECTPLAY2A)*ppvObj );
528 return S_OK;
531 /* Initialize failed, destroy it */
532 DP_DestroyDirectPlay4( *ppvObj );
533 DP_DestroyDirectPlay3( *ppvObj );
534 DP_DestroyDirectPlay2( *ppvObj );
535 DP_DestroyIUnknown( *ppvObj );
537 HeapFree( GetProcessHeap(), 0, *ppvObj );
539 *ppvObj = NULL;
540 return DPERR_NOMEMORY;
544 /* Direct Play methods */
546 /* Shared between all dplay types */
547 static HRESULT WINAPI DP_QueryInterface
548 ( LPDIRECTPLAY2 iface, REFIID riid, LPVOID* ppvObj )
550 ICOM_THIS(IDirectPlay2Impl,iface);
551 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
553 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
554 sizeof( *This ) );
556 if( *ppvObj == NULL )
558 return DPERR_OUTOFMEMORY;
561 CopyMemory( *ppvObj, This, sizeof( *This ) );
562 (*(IDirectPlay2Impl**)ppvObj)->ulInterfaceRef = 0;
564 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
566 ICOM_THIS(IDirectPlay2Impl,*ppvObj);
567 ICOM_VTBL(This) = &directPlay2WVT;
569 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
571 ICOM_THIS(IDirectPlay2AImpl,*ppvObj);
572 ICOM_VTBL(This) = &directPlay2AVT;
574 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
576 ICOM_THIS(IDirectPlay3Impl,*ppvObj);
577 ICOM_VTBL(This) = &directPlay3WVT;
579 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
581 ICOM_THIS(IDirectPlay3AImpl,*ppvObj);
582 ICOM_VTBL(This) = &directPlay3AVT;
584 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
586 ICOM_THIS(IDirectPlay4Impl,*ppvObj);
587 ICOM_VTBL(This) = &directPlay4WVT;
589 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
591 ICOM_THIS(IDirectPlay4AImpl,*ppvObj);
592 ICOM_VTBL(This) = &directPlay4AVT;
594 else
596 /* Unsupported interface */
597 HeapFree( GetProcessHeap(), 0, *ppvObj );
598 *ppvObj = NULL;
600 return E_NOINTERFACE;
603 IDirectPlayX_AddRef( (LPDIRECTPLAY2)*ppvObj );
605 return S_OK;
608 /* Shared between all dplay types */
609 static ULONG WINAPI DP_AddRef
610 ( LPDIRECTPLAY3 iface )
612 ULONG ulInterfaceRefCount, ulObjRefCount;
613 ICOM_THIS(IDirectPlay3Impl,iface);
615 ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
616 ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
618 TRACE( "ref count incremented to %lu:%lu for %p\n",
619 ulInterfaceRefCount, ulObjRefCount, This );
621 return ulObjRefCount;
624 static ULONG WINAPI DP_Release
625 ( LPDIRECTPLAY3 iface )
627 ULONG ulInterfaceRefCount, ulObjRefCount;
629 ICOM_THIS(IDirectPlay3Impl,iface);
631 ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
632 ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
634 TRACE( "ref count decremented to %lu:%lu for %p\n",
635 ulInterfaceRefCount, ulObjRefCount, This );
637 /* Deallocate if this is the last reference to the object */
638 if( ulObjRefCount == 0 )
640 /* If we're destroying the object, this must be the last ref
641 of the last interface */
642 DP_DestroyDirectPlay4( This );
643 DP_DestroyDirectPlay3( This );
644 DP_DestroyDirectPlay2( This );
645 DP_DestroyIUnknown( This );
648 /* Deallocate the interface */
649 if( ulInterfaceRefCount == 0 )
651 HeapFree( GetProcessHeap(), 0, This );
654 return ulObjRefCount;
657 static inline DPID DP_NextObjectId(void)
659 return (DPID)InterlockedIncrement( &kludgePlayerGroupId );
662 /* *lplpReply will be non NULL iff there is something to reply */
663 HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpcMessageBody,
664 DWORD dwMessageBodySize, LPCVOID lpcMessageHeader,
665 WORD wCommandId, WORD wVersion,
666 LPVOID* lplpReply, LPDWORD lpdwMsgSize )
668 TRACE( "(%p)->(%p,0x%08lx,%p,%u,%u)\n",
669 This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId,
670 wVersion );
672 switch( wCommandId )
674 /* Name server needs to handle this request */
675 case DPMSGCMD_ENUMSESSIONSREQUEST:
677 /* Reply expected */
678 NS_ReplyToEnumSessionsRequest( lpcMessageBody, lplpReply, lpdwMsgSize, This );
680 break;
683 /* Name server needs to handle this request */
684 case DPMSGCMD_ENUMSESSIONSREPLY:
686 /* No reply expected */
687 NS_AddRemoteComputerAsNameServer( lpcMessageHeader,
688 This->dp2->spData.dwSPHeaderSize,
689 (LPDPMSG_ENUMSESSIONSREPLY)lpcMessageBody,
690 This->dp2->lpNameServerData );
691 break;
694 case DPMSGCMD_REQUESTNEWPLAYERID:
696 LPCDPMSG_REQUESTNEWPLAYERID lpcMsg =
697 (LPCDPMSG_REQUESTNEWPLAYERID)lpcMessageBody;
699 LPDPMSG_NEWPLAYERIDREPLY lpReply;
701 *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
703 *lplpReply = (LPDPMSG_NEWPLAYERIDREPLY)HeapAlloc( GetProcessHeap(),
704 HEAP_ZERO_MEMORY,
705 *lpdwMsgSize );
707 FIXME( "Ignoring dwFlags 0x%08lx in request msg\n",
708 lpcMsg->dwFlags );
710 /* Setup the reply */
711 lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) +
712 This->dp2->spData.dwSPHeaderSize );
714 lpReply->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
715 lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY;
716 lpReply->envelope.wVersion = DPMSGVER_DP6;
718 lpReply->dpidNewPlayerId = DP_NextObjectId();
720 TRACE( "Allocating new playerid 0x%08lx from remote request\n",
721 lpReply->dpidNewPlayerId );
723 break;
726 case DPMSGCMD_GETNAMETABLEREPLY:
727 case DPMSGCMD_NEWPLAYERIDREPLY:
730 #if 0
731 if( wCommandId == DPMSGCMD_NEWPLAYERIDREPLY )
732 DebugBreak();
733 #endif
734 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
736 break;
739 #if 1
740 case DPMSGCMD_JUSTENVELOPE:
742 TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08lx\n", lpcMessageHeader, ((LPDWORD)lpcMessageHeader)[1] );
743 NS_SetLocalAddr( This->dp2->lpNameServerData, lpcMessageHeader, 20 );
744 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
746 #endif
748 case DPMSGCMD_FORWARDADDPLAYER:
750 #if 0
751 DebugBreak();
752 #endif
753 #if 1
754 TRACE( "Sending message to self to get my addr\n" );
755 DP_MSG_ToSelf( This, 1 ); /* This is a hack right now */
756 #endif
757 break;
760 case DPMSGCMD_FORWARDADDPLAYERNACK:
762 DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
763 break;
766 default:
768 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
769 DebugBreak();
770 break;
774 /* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */
776 return DP_OK;
780 static HRESULT WINAPI DP_IF_AddPlayerToGroup
781 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
782 DPID idPlayer, BOOL bAnsi )
784 lpGroupData lpGData;
785 lpPlayerList lpPList;
786 lpPlayerList lpNewPList;
788 TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
789 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
791 /* Find the group */
792 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
794 return DPERR_INVALIDGROUP;
797 /* Find the player */
798 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
800 return DPERR_INVALIDPLAYER;
803 /* Create a player list (ie "shortcut" ) */
804 lpNewPList = (lpPlayerList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
805 sizeof( *lpNewPList ) );
806 if( lpNewPList == NULL )
808 return DPERR_CANTADDPLAYER;
811 /* Add the shortcut */
812 lpPList->lpPData->uRef++;
813 lpNewPList->lpPData = lpPList->lpPData;
815 /* Add the player to the list of players for this group */
816 DPQ_INSERT(lpGData->players,lpNewPList,players);
818 /* Let the SP know that we've added a player to the group */
819 if( This->dp2->spData.lpCB->AddPlayerToGroup )
821 DPSP_ADDPLAYERTOGROUPDATA data;
823 TRACE( "Calling SP AddPlayerToGroup\n" );
825 data.idPlayer = idPlayer;
826 data.idGroup = idGroup;
827 data.lpISP = This->dp2->spData.lpISP;
829 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
832 /* Inform all other peers of the addition of player to the group. If there are
833 * no peers keep this event quiet.
834 * Also, if this event was the result of another machine sending it to us,
835 * don't bother rebroadcasting it.
837 if( ( lpMsgHdr == NULL ) &&
838 This->dp2->lpSessionDesc &&
839 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
841 DPMSG_ADDPLAYERTOGROUP msg;
842 msg.dwType = DPSYS_ADDPLAYERTOGROUP;
844 msg.dpIdGroup = idGroup;
845 msg.dpIdPlayer = idPlayer;
847 /* FIXME: Correct to just use send effectively? */
848 /* FIXME: Should size include data w/ message or just message "header" */
849 /* FIXME: Check return code */
850 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
853 return DP_OK;
856 static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
857 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
859 ICOM_THIS(IDirectPlay2Impl,iface);
860 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, TRUE );
863 static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
864 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
866 ICOM_THIS(IDirectPlay2Impl,iface);
867 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, FALSE );
870 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi )
872 HRESULT hr = DP_OK;
874 TRACE("(%p)->(%u)\n", This, bAnsi );
876 /* FIXME: Need to find a new host I assume (how?) */
877 /* FIXME: Need to destroy all local groups */
878 /* FIXME: Need to migrate all remotely visible players to the new host */
880 /* Invoke the SP callback to inform of session close */
881 if( This->dp2->spData.lpCB->CloseEx )
883 DPSP_CLOSEDATA data;
885 TRACE( "Calling SP CloseEx\n" );
887 data.lpISP = This->dp2->spData.lpISP;
889 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
892 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
894 TRACE( "Calling SP Close (obsolete interface)\n" );
896 hr = (*This->dp2->spData.lpCB->Close)();
899 return hr;
902 static HRESULT WINAPI DirectPlay2AImpl_Close
903 ( LPDIRECTPLAY2A iface )
905 ICOM_THIS(IDirectPlay2Impl,iface);
906 return DP_IF_Close( This, TRUE );
909 static HRESULT WINAPI DirectPlay2WImpl_Close
910 ( LPDIRECTPLAY2 iface )
912 ICOM_THIS(IDirectPlay2Impl,iface);
913 return DP_IF_Close( This, FALSE );
916 static
917 lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, LPDPID lpid,
918 LPDPNAME lpName, DWORD dwFlags,
919 DPID idParent, BOOL bAnsi )
921 lpGroupData lpGData;
923 /* Allocate the new space and add to end of high level group list */
924 lpGData = (lpGroupData) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
925 sizeof( *lpGData ) );
927 if( lpGData == NULL )
929 return NULL;
932 DPQ_INIT(lpGData->groups);
933 DPQ_INIT(lpGData->players);
935 /* Set the desired player ID - no sanity checking to see if it exists */
936 lpGData->dpid = *lpid;
938 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
940 /* FIXME: Should we check that the parent exists? */
941 lpGData->parent = idParent;
943 /* FIXME: Should we validate the dwFlags? */
944 lpGData->dwFlags = dwFlags;
946 TRACE( "Created group id 0x%08lx\n", *lpid );
948 return lpGData;
951 /* This method assumes that all links to it are already deleted */
952 static void
953 DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid )
955 lpGroupList lpGList;
957 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
959 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
961 if( lpGList == NULL )
963 ERR( "DPID 0x%08lx not found\n", dpid );
964 return;
967 if( --(lpGList->lpGData->uRef) )
969 FIXME( "Why is this not the last reference to group?\n" );
970 DebugBreak();
973 /* Delete player */
974 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
975 HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
977 /* Remove and Delete Player List object */
978 HeapFree( GetProcessHeap(), 0, lpGList );
982 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid )
984 lpGroupList lpGroups;
986 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
988 if( dpid == DPID_SYSTEM_GROUP )
990 return This->dp2->lpSysGroup;
992 else
994 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
997 if( lpGroups == NULL )
999 return NULL;
1002 return lpGroups->lpGData;
1005 static HRESULT WINAPI DP_IF_CreateGroup
1006 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
1007 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
1008 DWORD dwFlags, BOOL bAnsi )
1010 lpGroupData lpGData;
1012 TRACE( "(%p)->(%p,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
1013 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
1014 dwFlags, bAnsi );
1016 /* If the name is not specified, we must provide one */
1017 if( DPID_UNKNOWN == *lpidGroup )
1019 /* If we are the name server, we decide on the group ids. If not, we
1020 * must ask for one before attempting a creation.
1022 if( This->dp2->bHostInterface )
1024 *lpidGroup = DP_NextObjectId();
1026 else
1028 *lpidGroup = DP_GetRemoteNextObjectId();
1032 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
1033 DPID_NOPARENT_GROUP, bAnsi );
1035 if( lpGData == NULL )
1037 return DPERR_CANTADDPLAYER; /* yes player not group */
1040 if( DPID_SYSTEM_GROUP == *lpidGroup )
1042 This->dp2->lpSysGroup = lpGData;
1043 TRACE( "Inserting system group\n" );
1045 else
1047 /* Insert into the system group */
1048 lpGroupList lpGroup = (lpGroupList) HeapAlloc( GetProcessHeap(),
1049 HEAP_ZERO_MEMORY,
1050 sizeof( *lpGroup ) );
1051 lpGroup->lpGData = lpGData;
1053 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
1056 /* Something is now referencing this data */
1057 lpGData->uRef++;
1059 /* Set all the important stuff for the group */
1060 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
1062 /* FIXME: We should only create the system group if GetCaps returns
1063 * DPCAPS_GROUPOPTIMIZED.
1066 /* Let the SP know that we've created this group */
1067 if( This->dp2->spData.lpCB->CreateGroup )
1069 DPSP_CREATEGROUPDATA data;
1070 DWORD dwCreateFlags = 0;
1072 TRACE( "Calling SP CreateGroup\n" );
1074 if( *lpidGroup == DPID_NOPARENT_GROUP )
1075 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
1077 if( lpMsgHdr == NULL )
1078 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1080 if( dwFlags & DPGROUP_HIDDEN )
1081 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
1083 data.idGroup = *lpidGroup;
1084 data.dwFlags = dwCreateFlags;
1085 data.lpSPMessageHeader = lpMsgHdr;
1086 data.lpISP = This->dp2->spData.lpISP;
1088 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1091 /* Inform all other peers of the creation of a new group. If there are
1092 * no peers keep this event quiet.
1093 * Also if this message was sent to us, don't rebroadcast.
1095 if( ( lpMsgHdr == NULL ) &&
1096 This->dp2->lpSessionDesc &&
1097 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1099 DPMSG_CREATEPLAYERORGROUP msg;
1100 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1102 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1103 msg.dpId = *lpidGroup;
1104 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1105 msg.lpData = lpData;
1106 msg.dwDataSize = dwDataSize;
1107 msg.dpnName = *lpGroupName;
1108 msg.dpIdParent = DPID_NOPARENT_GROUP;
1109 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
1111 /* FIXME: Correct to just use send effectively? */
1112 /* FIXME: Should size include data w/ message or just message "header" */
1113 /* FIXME: Check return code */
1114 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
1115 0, 0, NULL, NULL, bAnsi );
1118 return DP_OK;
1121 static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
1122 ( LPDIRECTPLAY2A iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1123 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1125 *lpidGroup = DPID_UNKNOWN;
1127 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1128 lpGroupName, lpData, dwDataSize, dwFlags, TRUE );
1131 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
1132 ( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1133 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1135 *lpidGroup = DPID_UNKNOWN;
1137 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1138 lpGroupName, lpData, dwDataSize, dwFlags, FALSE );
1142 static void
1143 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
1144 LPVOID lpData, DWORD dwDataSize )
1146 /* Clear out the data with this player */
1147 if( ( dwFlags & DPSET_LOCAL ) &&
1148 ( lpGData->dwLocalDataSize != 0 )
1151 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
1152 lpGData->lpLocalData = NULL;
1153 lpGData->dwLocalDataSize = 0;
1155 if( ( dwFlags & DPSET_REMOTE ) &&
1156 ( lpGData->dwRemoteDataSize != 0 )
1159 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
1160 lpGData->lpRemoteData = NULL;
1161 lpGData->dwRemoteDataSize = 0;
1164 /* Reallocate for new data */
1165 if( lpData != NULL )
1167 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1168 sizeof( dwDataSize ) );
1169 CopyMemory( lpNewData, lpData, dwDataSize );
1171 if( dwFlags & DPSET_REMOTE )
1173 lpGData->lpRemoteData = lpNewData;
1174 lpGData->dwRemoteDataSize = dwDataSize;
1177 if( dwFlags & DPSET_LOCAL )
1179 lpGData->lpLocalData = lpData;
1180 lpGData->dwLocalDataSize = dwDataSize;
1186 /* This function will just create the storage for the new player. */
1187 static
1188 lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid,
1189 LPDPNAME lpName, DWORD dwFlags,
1190 HANDLE hEvent, BOOL bAnsi )
1192 lpPlayerData lpPData;
1194 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
1196 /* Allocate the storage for the player and associate it with list element */
1197 lpPData = (lpPlayerData) HeapAlloc( GetProcessHeap(),
1198 HEAP_ZERO_MEMORY,
1199 sizeof( *lpPData ) );
1200 if( lpPData == NULL )
1202 return NULL;
1205 /* Set the desired player ID */
1206 lpPData->dpid = *lpid;
1208 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
1210 lpPData->dwFlags = dwFlags;
1212 /* If we were given an event handle, duplicate it */
1213 if( hEvent != 0 )
1215 if( !DuplicateHandle( GetCurrentProcess(), hEvent,
1216 GetCurrentProcess(), &lpPData->hEvent,
1217 0, FALSE, DUPLICATE_SAME_ACCESS )
1220 /* FIXME: Memory leak */
1221 ERR( "Can't duplicate player msg handle %x\n", hEvent );
1225 /* Initialize the SP data section */
1226 lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData();
1228 TRACE( "Created player id 0x%08lx\n", *lpid );
1230 return lpPData;
1233 /* Delete the contents of the DPNAME struct */
1234 static void
1235 DP_DeleteDPNameStruct( LPDPNAME lpDPName )
1237 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u1.lpszShortNameA );
1238 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u2.lpszLongNameA );
1241 /* This method assumes that all links to it are already deleted */
1242 static void
1243 DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid )
1245 lpPlayerList lpPList;
1247 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
1249 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1251 if( lpPList == NULL )
1253 ERR( "DPID 0x%08lx not found\n", dpid );
1254 return;
1257 /* Verify that this is the last reference to the data */
1258 if( --(lpPList->lpPData->uRef) )
1260 FIXME( "Why is this not the last reference to player?\n" );
1261 DebugBreak();
1264 /* Delete player */
1265 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1267 CloseHandle( lpPList->lpPData->hEvent );
1268 HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
1270 /* Delete Player List object */
1271 HeapFree( GetProcessHeap(), 0, lpPList );
1274 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid )
1276 lpPlayerList lpPlayers;
1278 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
1280 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1282 return lpPlayers;
1285 /* Basic area for Dst must already be allocated */
1286 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi )
1288 if( lpSrc == NULL )
1290 ZeroMemory( lpDst, sizeof( *lpDst ) );
1291 lpDst->dwSize = sizeof( *lpDst );
1292 return TRUE;
1295 if( lpSrc->dwSize != sizeof( *lpSrc) )
1297 return FALSE;
1300 /* Delete any existing pointers */
1301 if( lpDst->u1.lpszShortNameA )
1303 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1306 if( lpDst->u2.lpszLongNameA )
1308 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1311 /* Copy as required */
1312 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1314 if( bAnsi )
1316 if( lpSrc->u1.lpszShortNameA )
1318 lpDst->u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), 0,
1319 strlen(lpSrc->u1.lpszShortNameA)+1 );
1320 strcpy( lpDst->u1.lpszShortNameA, lpSrc->u1.lpszShortNameA );
1322 if( lpSrc->u2.lpszLongNameA )
1324 lpDst->u2.lpszLongNameA = HeapAlloc( GetProcessHeap(), 0,
1325 strlen(lpSrc->u2.lpszLongNameA)+1 );
1326 strcpy( lpDst->u2.lpszLongNameA, lpSrc->u2.lpszLongNameA );
1329 else
1331 if( lpSrc->u1.lpszShortNameA )
1333 lpDst->u1.lpszShortName = HeapAlloc( GetProcessHeap(), 0,
1334 (strlenW(lpSrc->u1.lpszShortName)+1)*sizeof(WCHAR) );
1335 strcpyW( lpDst->u1.lpszShortName, lpSrc->u1.lpszShortName );
1337 if( lpSrc->u2.lpszLongNameA )
1339 lpDst->u2.lpszLongName = HeapAlloc( GetProcessHeap(), 0,
1340 (strlenW(lpSrc->u2.lpszLongName)+1)*sizeof(WCHAR) );
1341 strcpyW( lpDst->u2.lpszLongName, lpSrc->u2.lpszLongName );
1345 return TRUE;
1348 static void
1349 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
1350 LPVOID lpData, DWORD dwDataSize )
1352 /* Clear out the data with this player */
1353 if( ( dwFlags & DPSET_LOCAL ) &&
1354 ( lpPData->dwLocalDataSize != 0 )
1357 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
1358 lpPData->lpLocalData = NULL;
1359 lpPData->dwLocalDataSize = 0;
1361 if( ( dwFlags & DPSET_REMOTE ) &&
1362 ( lpPData->dwRemoteDataSize != 0 )
1365 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
1366 lpPData->lpRemoteData = NULL;
1367 lpPData->dwRemoteDataSize = 0;
1370 /* Reallocate for new data */
1371 if( lpData != NULL )
1373 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1374 sizeof( dwDataSize ) );
1375 CopyMemory( lpNewData, lpData, dwDataSize );
1377 if( dwFlags & DPSET_REMOTE )
1379 lpPData->lpRemoteData = lpNewData;
1380 lpPData->dwRemoteDataSize = dwDataSize;
1383 if( dwFlags & DPSET_LOCAL )
1385 lpPData->lpLocalData = lpData;
1386 lpPData->dwLocalDataSize = dwDataSize;
1392 static HRESULT WINAPI DP_IF_CreatePlayer
1393 ( IDirectPlay2Impl* This,
1394 LPVOID lpMsgHdr, /* NULL for local creation, non NULL for remote creation */
1395 LPDPID lpidPlayer,
1396 LPDPNAME lpPlayerName,
1397 HANDLE hEvent,
1398 LPVOID lpData,
1399 DWORD dwDataSize,
1400 DWORD dwFlags,
1401 BOOL bAnsi )
1403 HANDLE hr = DP_OK;
1404 lpPlayerData lpPData;
1405 lpPlayerList lpPList;
1406 DWORD dwCreateFlags = 0;
1408 TRACE( "(%p)->(%p,%p,%d,%p,0x%08lx,0x%08lx,%u)\n",
1409 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1410 dwDataSize, dwFlags, bAnsi );
1412 if( dwFlags == 0 )
1414 dwFlags = DPPLAYER_SPECTATOR;
1417 if( lpidPlayer == NULL )
1419 return DPERR_INVALIDPARAMS;
1423 /* Determine the creation flags for the player. These will be passed
1424 * to the name server if requesting a player id and to the SP when
1425 * informing it of the player creation
1428 if( dwFlags & DPPLAYER_SERVERPLAYER )
1430 if( *lpidPlayer == DPID_SERVERPLAYER )
1432 /* Server player for the host interface */
1433 dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
1435 else if( *lpidPlayer == DPID_NAME_SERVER )
1437 /* Name server - master of everything */
1438 dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
1440 else
1442 /* Server player for a non host interface */
1443 dwCreateFlags |= DPLAYI_PLAYER_SYSPLAYER;
1447 if( lpMsgHdr == NULL )
1448 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1451 /* Verify we know how to handle all the flags */
1452 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1453 ( dwFlags & DPPLAYER_SPECTATOR )
1457 /* Assume non fatal failure */
1458 ERR( "unknown dwFlags = 0x%08lx\n", dwFlags );
1461 /* If the name is not specified, we must provide one */
1462 if( *lpidPlayer == DPID_UNKNOWN )
1464 /* If we are the session master, we dish out the group/player ids */
1465 if( This->dp2->bHostInterface )
1467 *lpidPlayer = DP_NextObjectId();
1469 else
1471 hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer );
1473 if( FAILED(hr) )
1475 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1476 return hr;
1480 else
1482 /* FIXME: Would be nice to perhaps verify that we don't already have
1483 * this player.
1487 /* FIXME: Should we be storing these dwFlags or the creation ones? */
1488 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwFlags,
1489 hEvent, bAnsi );
1491 if( lpPData == NULL )
1493 return DPERR_CANTADDPLAYER;
1496 /* Create the list object and link it in */
1497 lpPList = (lpPlayerList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1498 sizeof( *lpPList ) );
1499 if( lpPList == NULL )
1501 FIXME( "Memory leak\n" );
1502 return DPERR_CANTADDPLAYER;
1505 lpPData->uRef = 1;
1506 lpPList->lpPData = lpPData;
1508 /* Add the player to the system group */
1509 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1511 /* Update the information and send it to all players in the session */
1512 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
1514 /* Let the SP know that we've created this player */
1515 if( This->dp2->spData.lpCB->CreatePlayer )
1517 DPSP_CREATEPLAYERDATA data;
1519 data.idPlayer = *lpidPlayer;
1520 data.dwFlags = dwCreateFlags;
1521 data.lpSPMessageHeader = lpMsgHdr;
1522 data.lpISP = This->dp2->spData.lpISP;
1524 TRACE( "Calling SP CreatePlayer 0x%08lx: dwFlags: 0x%08lx lpMsgHdr: %p\n",
1525 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
1527 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1530 if( FAILED(hr) )
1532 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1533 return hr;
1536 /* Now let the SP know that this player is a member of the system group */
1537 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1539 DPSP_ADDPLAYERTOGROUPDATA data;
1541 data.idPlayer = *lpidPlayer;
1542 data.idGroup = DPID_SYSTEM_GROUP;
1543 data.lpISP = This->dp2->spData.lpISP;
1545 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1547 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1550 if( FAILED(hr) )
1552 ERR( "Failed to add player to sys group with sp: %s\n",
1553 DPLAYX_HresultToString(hr) );
1554 return hr;
1557 #if 1
1558 if( This->dp2->bHostInterface == FALSE )
1560 /* Let the name server know about the creation of this player */
1561 /* FIXME: Is this only to be done for the creation of a server player or
1562 * is this used for regular players? If only for server players, move
1563 * this call to DP_SecureOpen(...);
1565 #if 0
1566 TRACE( "Sending message to self to get my addr\n" );
1567 DP_MSG_ToSelf( This, *lpidPlayer ); /* This is a hack right now */
1568 #endif
1570 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
1572 #else
1573 /* Inform all other peers of the creation of a new player. If there are
1574 * no peers keep this quiet.
1575 * Also, if this was a remote event, no need to rebroadcast it.
1577 if( ( lpMsgHdr == NULL ) &&
1578 This->dp2->lpSessionDesc &&
1579 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1581 DPMSG_CREATEPLAYERORGROUP msg;
1582 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1584 msg.dwPlayerType = DPPLAYERTYPE_PLAYER;
1585 msg.dpId = *lpidPlayer;
1586 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */
1587 msg.lpData = lpData;
1588 msg.dwDataSize = dwDataSize;
1589 msg.dpnName = *lpPlayerName;
1590 msg.dpIdParent = DPID_NOPARENT_GROUP;
1591 msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
1593 /* FIXME: Correct to just use send effectively? */
1594 /* FIXME: Should size include data w/ message or just message "header" */
1595 /* FIXME: Check return code */
1596 hr = DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
1597 sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
1599 #endif
1601 return hr;
1604 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
1605 ( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1606 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1608 ICOM_THIS(IDirectPlay2Impl,iface);
1610 if( dwFlags & DPPLAYER_SERVERPLAYER )
1612 *lpidPlayer = DPID_SERVERPLAYER;
1614 else
1616 *lpidPlayer = DPID_UNKNOWN;
1619 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1620 lpData, dwDataSize, dwFlags, TRUE );
1623 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
1624 ( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1625 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1627 ICOM_THIS(IDirectPlay2Impl,iface);
1629 if( dwFlags & DPPLAYER_SERVERPLAYER )
1631 *lpidPlayer = DPID_SERVERPLAYER;
1633 else
1635 *lpidPlayer = DPID_UNKNOWN;
1638 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1639 lpData, dwDataSize, dwFlags, FALSE );
1642 static DPID DP_GetRemoteNextObjectId(void)
1644 FIXME( ":stub\n" );
1646 /* Hack solution */
1647 return DP_NextObjectId();
1650 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
1651 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
1652 DPID idPlayer, BOOL bAnsi )
1654 HRESULT hr = DP_OK;
1656 lpGroupData lpGData;
1657 lpPlayerList lpPList;
1659 TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
1660 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
1662 /* Find the group */
1663 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1665 return DPERR_INVALIDGROUP;
1668 /* Find the player */
1669 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
1671 return DPERR_INVALIDPLAYER;
1674 /* Remove the player shortcut from the group */
1675 DPQ_REMOVE_ENTRY( lpGData->players, players, lpPData->dpid, ==, idPlayer, lpPList );
1677 if( lpPList == NULL )
1679 return DPERR_INVALIDPLAYER;
1682 /* One less reference */
1683 lpPList->lpPData->uRef--;
1685 /* Delete the Player List element */
1686 HeapFree( GetProcessHeap(), 0, lpPList );
1688 /* Inform the SP if they care */
1689 if( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1691 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1693 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1695 data.idPlayer = idPlayer;
1696 data.idGroup = idGroup;
1697 data.lpISP = This->dp2->spData.lpISP;
1699 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1702 /* Need to send a DELETEPLAYERFROMGROUP message */
1703 FIXME( "Need to send a message\n" );
1705 return hr;
1708 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
1709 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
1711 ICOM_THIS(IDirectPlay2Impl,iface);
1712 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, TRUE );
1715 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
1716 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
1718 ICOM_THIS(IDirectPlay2Impl,iface);
1719 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, FALSE );
1722 typedef struct _DPRGOPContext
1724 IDirectPlay3Impl* This;
1725 BOOL bAnsi;
1726 DPID idGroup;
1727 } DPRGOPContext, *lpDPRGOPContext;
1729 static BOOL CALLBACK
1730 cbRemoveGroupOrPlayer(
1731 DPID dpId,
1732 DWORD dwPlayerType,
1733 LPCDPNAME lpName,
1734 DWORD dwFlags,
1735 LPVOID lpContext )
1737 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1739 TRACE( "Removing element:0x%08lx (type:0x%08lx) from element:0x%08lx\n",
1740 dpId, dwPlayerType, lpCtxt->idGroup );
1742 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1744 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt->This, lpCtxt->idGroup,
1745 dpId )
1749 ERR( "Unable to delete group 0x%08lx from group 0x%08lx\n",
1750 dpId, lpCtxt->idGroup );
1753 else
1755 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl*)lpCtxt->This,
1756 NULL, lpCtxt->idGroup,
1757 dpId, lpCtxt->bAnsi )
1761 ERR( "Unable to delete player 0x%08lx from grp 0x%08lx\n",
1762 dpId, lpCtxt->idGroup );
1766 return TRUE; /* Continue enumeration */
1769 static HRESULT WINAPI DP_IF_DestroyGroup
1770 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi )
1772 lpGroupData lpGData;
1773 DPRGOPContext context;
1775 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
1776 This, lpMsgHdr, idGroup, bAnsi );
1778 /* Find the group */
1779 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1781 return DPERR_INVALIDPLAYER; /* yes player */
1784 context.This = (IDirectPlay3Impl*)This;
1785 context.bAnsi = bAnsi;
1786 context.idGroup = idGroup;
1788 /* Remove all players that this group has */
1789 DP_IF_EnumGroupPlayers( This, idGroup, NULL,
1790 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1792 /* Remove all links to groups that this group has since this is dp3 */
1793 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This, idGroup, NULL,
1794 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1796 /* Remove this group from the parent group - if it has one */
1797 if( ( idGroup != DPID_SYSTEM_GROUP ) &&
1798 ( lpGData->parent != DPID_SYSTEM_GROUP )
1801 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl*)This, lpGData->parent,
1802 idGroup );
1805 /* Now delete this group data and list from the system group */
1806 DP_DeleteGroup( This, idGroup );
1808 /* Let the SP know that we've destroyed this group */
1809 if( This->dp2->spData.lpCB->DeleteGroup )
1811 DPSP_DELETEGROUPDATA data;
1813 FIXME( "data.dwFlags is incorrect\n" );
1815 data.idGroup = idGroup;
1816 data.dwFlags = 0;
1817 data.lpISP = This->dp2->spData.lpISP;
1819 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1822 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1824 return DP_OK;
1827 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
1828 ( LPDIRECTPLAY2A iface, DPID idGroup )
1830 ICOM_THIS(IDirectPlay2Impl,iface);
1831 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
1834 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
1835 ( LPDIRECTPLAY2 iface, DPID idGroup )
1837 ICOM_THIS(IDirectPlay2Impl,iface);
1838 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
1841 typedef struct _DPFAGContext
1843 IDirectPlay2Impl* This;
1844 DPID idPlayer;
1845 BOOL bAnsi;
1846 } DPFAGContext, *lpDPFAGContext;
1848 static HRESULT WINAPI DP_IF_DestroyPlayer
1849 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi )
1851 DPFAGContext cbContext;
1853 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
1854 This, lpMsgHdr, idPlayer, bAnsi );
1856 if( DP_FindPlayer( This, idPlayer ) == NULL )
1858 return DPERR_INVALIDPLAYER;
1861 /* FIXME: If the player is remote, we must be the host to delete this */
1863 cbContext.This = This;
1864 cbContext.idPlayer = idPlayer;
1865 cbContext.bAnsi = bAnsi;
1867 /* Find each group and call DeletePlayerFromGroup if the player is a
1868 member of the group */
1869 DP_IF_EnumGroups( This, NULL, cbDeletePlayerFromAllGroups,
1870 (LPVOID)&cbContext, DPENUMGROUPS_ALL, bAnsi );
1872 /* Now delete player and player list from the sys group */
1873 DP_DeletePlayer( This, idPlayer );
1875 /* Let the SP know that we've destroyed this group */
1876 if( This->dp2->spData.lpCB->DeletePlayer )
1878 DPSP_DELETEPLAYERDATA data;
1880 FIXME( "data.dwFlags is incorrect\n" );
1882 data.idPlayer = idPlayer;
1883 data.dwFlags = 0;
1884 data.lpISP = This->dp2->spData.lpISP;
1886 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
1889 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
1891 return DP_OK;
1894 static BOOL CALLBACK
1895 cbDeletePlayerFromAllGroups(
1896 DPID dpId,
1897 DWORD dwPlayerType,
1898 LPCDPNAME lpName,
1899 DWORD dwFlags,
1900 LPVOID lpContext )
1902 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
1904 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1906 DP_IF_DeletePlayerFromGroup( lpCtxt->This, NULL, dpId, lpCtxt->idPlayer,
1907 lpCtxt->bAnsi );
1909 /* Enumerate all groups in this group since this will normally only
1910 * be called for top level groups
1912 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)lpCtxt->This,
1913 dpId, NULL,
1914 cbDeletePlayerFromAllGroups,
1915 (LPVOID)lpContext, DPENUMGROUPS_ALL,
1916 lpCtxt->bAnsi );
1919 else
1921 ERR( "Group callback has dwPlayerType = 0x%08lx\n", dwPlayerType );
1924 return TRUE;
1927 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
1928 ( LPDIRECTPLAY2A iface, DPID idPlayer )
1930 ICOM_THIS(IDirectPlay2Impl,iface);
1931 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
1934 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
1935 ( LPDIRECTPLAY2 iface, DPID idPlayer )
1937 ICOM_THIS(IDirectPlay2Impl,iface);
1938 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
1941 static HRESULT WINAPI DP_IF_EnumGroupPlayers
1942 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
1943 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1944 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1946 lpGroupData lpGData;
1947 lpPlayerList lpPList;
1949 FIXME("(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
1950 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
1951 lpContext, dwFlags, bAnsi );
1953 /* Find the group */
1954 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1956 return DPERR_INVALIDGROUP;
1959 if( DPQ_IS_EMPTY( lpGData->players ) )
1961 return DP_OK;
1964 lpPList = DPQ_FIRST( lpGData->players );
1966 /* Walk the players in this group */
1967 for( ;; )
1969 /* We do not enum the name server or app server as they are of no
1970 * concequence to the end user.
1972 if( ( lpPList->lpPData->dpid != DPID_NAME_SERVER ) &&
1973 ( lpPList->lpPData->dpid != DPID_SERVERPLAYER )
1977 /* FIXME: Need to add stuff for dwFlags checking */
1979 if( !lpEnumPlayersCallback2( lpPList->lpPData->dpid, DPPLAYERTYPE_PLAYER,
1980 &lpPList->lpPData->name,
1981 lpPList->lpPData->dwFlags,
1982 lpContext )
1985 /* User requested break */
1986 return DP_OK;
1990 if( DPQ_IS_ENDOFLIST( lpPList->players ) )
1992 break;
1995 lpPList = DPQ_NEXT( lpPList->players );
1998 return DP_OK;
2001 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
2002 ( LPDIRECTPLAY2A iface, DPID idGroup, LPGUID lpguidInstance,
2003 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2004 LPVOID lpContext, DWORD dwFlags )
2006 ICOM_THIS(IDirectPlay2Impl,iface);
2007 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2008 lpEnumPlayersCallback2, lpContext,
2009 dwFlags, TRUE );
2012 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
2013 ( LPDIRECTPLAY2 iface, DPID idGroup, LPGUID lpguidInstance,
2014 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2015 LPVOID lpContext, DWORD dwFlags )
2017 ICOM_THIS(IDirectPlay2Impl,iface);
2018 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2019 lpEnumPlayersCallback2, lpContext,
2020 dwFlags, FALSE );
2023 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2024 static HRESULT WINAPI DP_IF_EnumGroups
2025 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2026 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2027 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2029 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This,
2030 DPID_SYSTEM_GROUP, lpguidInstance,
2031 lpEnumPlayersCallback2, lpContext,
2032 dwFlags, bAnsi );
2035 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
2036 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2037 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2038 LPVOID lpContext, DWORD dwFlags )
2040 ICOM_THIS(IDirectPlay2Impl,iface);
2041 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2042 lpContext, dwFlags, TRUE );
2045 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
2046 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2047 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2048 LPVOID lpContext, DWORD dwFlags )
2050 ICOM_THIS(IDirectPlay2Impl,iface);
2051 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2052 lpContext, dwFlags, FALSE );
2055 static HRESULT WINAPI DP_IF_EnumPlayers
2056 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2057 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2058 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2060 return DP_IF_EnumGroupPlayers( This, DPID_SYSTEM_GROUP, lpguidInstance,
2061 lpEnumPlayersCallback2, lpContext,
2062 dwFlags, bAnsi );
2065 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
2066 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2067 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2068 LPVOID lpContext, DWORD dwFlags )
2070 ICOM_THIS(IDirectPlay2Impl,iface);
2071 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2072 lpContext, dwFlags, TRUE );
2075 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
2076 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2077 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2078 LPVOID lpContext, DWORD dwFlags )
2080 ICOM_THIS(IDirectPlay2Impl,iface);
2081 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2082 lpContext, dwFlags, FALSE );
2085 /* This function should call the registered callback function that the user
2086 passed into EnumSessions for each entry available.
2088 static void DP_InvokeEnumSessionCallbacks
2089 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2090 LPVOID lpNSInfo,
2091 DWORD dwTimeout,
2092 LPVOID lpContext )
2094 LPDPSESSIONDESC2 lpSessionDesc;
2096 FIXME( ": not checking for conditions\n" );
2098 /* Not sure if this should be pruning but it's convenient */
2099 NS_PruneSessionCache( lpNSInfo );
2101 NS_ResetSessionEnumeration( lpNSInfo );
2103 /* Enumerate all sessions */
2104 /* FIXME: Need to indicate ANSI */
2105 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2107 TRACE( "EnumSessionsCallback2 invoked\n" );
2108 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2110 return;
2114 /* Invoke one last time to indicate that there is no more to come */
2115 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2118 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2120 EnumSessionAsyncCallbackData* data = (EnumSessionAsyncCallbackData*)lpContext;
2121 HANDLE hSuicideRequest = data->hSuicideRequest;
2122 DWORD dwTimeout = data->dwTimeout;
2124 TRACE( "Thread started with timeout = 0x%08lx\n", dwTimeout );
2126 for( ;; )
2128 HRESULT hr;
2130 /* Sleep up to dwTimeout waiting for request to terminate thread */
2131 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2133 TRACE( "Thread terminating on terminate request\n" );
2134 break;
2137 /* Now resend the enum request */
2138 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2139 data->dwEnumSessionFlags,
2140 data->lpSpData );
2142 if( FAILED(hr) )
2144 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2145 /* FIXME: Should we kill this thread? How to inform the main thread? */
2150 TRACE( "Thread terminating\n" );
2152 /* Clean up the thread data */
2153 CloseHandle( hSuicideRequest );
2154 HeapFree( GetProcessHeap(), 0, lpContext );
2156 /* FIXME: Need to have some notification to main app thread that this is
2157 * dead. It would serve two purposes. 1) allow sync on termination
2158 * so that we don't actually send something to ourselves when we
2159 * become name server (race condition) and 2) so that if we die
2160 * abnormally something else will be able to tell.
2163 return 1;
2166 static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
2168 /* Does a thread exist? If so we were doing an async enum session */
2169 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2171 TRACE( "Killing EnumSession thread %u\n",
2172 This->dp2->hEnumSessionThread );
2174 /* Request that the thread kill itself nicely */
2175 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2176 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2178 /* We no longer need to know about the thread */
2179 CloseHandle( This->dp2->hEnumSessionThread );
2181 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2185 static HRESULT WINAPI DP_IF_EnumSessions
2186 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2187 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2188 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2190 HRESULT hr = DP_OK;
2192 TRACE( "(%p)->(%p,0x%08lx,%p,%p,0x%08lx,%u)\n",
2193 This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags,
2194 bAnsi );
2196 /* Can't enumerate if the interface is already open */
2197 if( This->dp2->bConnectionOpen )
2199 return DPERR_GENERIC;
2202 #if 1
2203 /* The loading of a lobby provider _seems_ to require a backdoor loading
2204 * of the service provider to also associate with this DP object. This is
2205 * because the app doesn't seem to have to call EnumConnections and
2206 * InitializeConnection for the SP before calling this method. As such
2207 * we'll do their dirty work for them with a quick hack so as to always
2208 * load the TCP/IP service provider.
2210 * The correct solution would seem to involve creating a dialog box which
2211 * contains the possible SPs. These dialog boxes most likely follow SDK
2212 * examples.
2214 if( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
2216 LPVOID lpConnection;
2217 DWORD dwSize;
2219 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2221 if( !DP_BuildSPCompoundAddr( (LPGUID)&DPSPGUID_TCPIP, &lpConnection, &dwSize ) )
2223 ERR( "Can't build compound addr\n" );
2224 return DPERR_GENERIC;
2227 hr = DP_IF_InitializeConnection( (IDirectPlay3Impl*)This, lpConnection,
2228 0, bAnsi );
2229 if( FAILED(hr) )
2231 return hr;
2234 /* Free up the address buffer */
2235 HeapFree( GetProcessHeap(), 0, lpConnection );
2237 /* The SP is now initialized */
2238 This->dp2->bSPInitialized = TRUE;
2240 #endif
2243 /* Use the service provider default? */
2244 if( dwTimeout == 0 )
2246 DPCAPS spCaps;
2247 spCaps.dwSize = sizeof( spCaps );
2249 DP_IF_GetCaps( This, &spCaps, 0 );
2250 dwTimeout = spCaps.dwTimeout;
2252 /* The service provider doesn't provide one either! */
2253 if( dwTimeout == 0 )
2255 /* Provide the TCP/IP default */
2256 dwTimeout = DPMSG_WAIT_5_SECS;
2260 if( dwFlags & DPENUMSESSIONS_STOPASYNC )
2262 DP_KillEnumSessionThread( This );
2263 return hr;
2266 /* FIXME: Interface locking sucks in this method */
2267 if( ( dwFlags & DPENUMSESSIONS_ASYNC ) )
2269 /* Enumerate everything presently in the local session cache */
2270 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2271 This->dp2->lpNameServerData, dwTimeout,
2272 lpContext );
2275 /* See if we've already created a thread to service this interface */
2276 if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2278 DWORD dwThreadId;
2280 /* Send the first enum request inline since the user may cancel a dialog
2281 * if one is presented. Also, may also have a connecting return code.
2283 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2284 dwFlags, &This->dp2->spData );
2286 if( !FAILED(hr) )
2288 EnumSessionAsyncCallbackData* lpData
2289 = (EnumSessionAsyncCallbackData*)HeapAlloc( GetProcessHeap(),
2290 HEAP_ZERO_MEMORY,
2291 sizeof( *lpData ) );
2292 /* FIXME: need to kill the thread on object deletion */
2293 lpData->lpSpData = &This->dp2->spData;
2295 CopyMemory( &lpData->requestGuid, &lpsd->guidApplication, sizeof(GUID) );
2296 lpData->dwEnumSessionFlags = dwFlags;
2297 lpData->dwTimeout = dwTimeout;
2299 This->dp2->hKillEnumSessionThreadEvent =
2300 CreateEventA( NULL, TRUE, FALSE, NULL );
2302 if( !DuplicateHandle( GetCurrentProcess(),
2303 This->dp2->hKillEnumSessionThreadEvent,
2304 GetCurrentProcess(),
2305 &lpData->hSuicideRequest,
2306 0, FALSE, DUPLICATE_SAME_ACCESS )
2309 ERR( "Can't duplicate thread killing handle\n" );
2312 TRACE( ": creating EnumSessionsRequest thread\n" );
2314 This->dp2->hEnumSessionThread = CreateThread( NULL,
2316 DP_EnumSessionsSendAsyncRequestThread,
2317 lpData,
2319 &dwThreadId );
2323 else
2325 /* Invalidate the session cache for the interface */
2326 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2328 /* Send the broadcast for session enumeration */
2329 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2330 dwFlags,
2331 &This->dp2->spData );
2334 SleepEx( dwTimeout, FALSE );
2336 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2337 This->dp2->lpNameServerData, dwTimeout,
2338 lpContext );
2341 return hr;
2344 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2345 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2346 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2347 LPVOID lpContext, DWORD dwFlags )
2349 ICOM_THIS(IDirectPlay2Impl,iface);
2350 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2351 lpContext, dwFlags, TRUE );
2354 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2355 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2356 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2357 LPVOID lpContext, DWORD dwFlags )
2359 ICOM_THIS(IDirectPlay2Impl,iface);
2360 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2361 lpContext, dwFlags, FALSE );
2364 static HRESULT WINAPI DP_IF_GetPlayerCaps
2365 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
2366 DWORD dwFlags )
2368 DPSP_GETCAPSDATA data;
2370 TRACE("(%p)->(0x%08lx,%p,0x%08lx)\n", This, idPlayer, lpDPCaps, dwFlags);
2372 /* Query the service provider */
2373 data.idPlayer = idPlayer;
2374 data.dwFlags = dwFlags;
2375 data.lpCaps = lpDPCaps;
2376 data.lpISP = This->dp2->spData.lpISP;
2378 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2381 static HRESULT WINAPI DP_IF_GetCaps
2382 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags )
2384 return DP_IF_GetPlayerCaps( This, DPID_ALLPLAYERS, lpDPCaps, dwFlags );
2387 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2388 ( LPDIRECTPLAY2A iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2390 ICOM_THIS(IDirectPlay2Impl,iface);
2391 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2394 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2395 ( LPDIRECTPLAY2 iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2397 ICOM_THIS(IDirectPlay2Impl,iface);
2398 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2401 static HRESULT WINAPI DP_IF_GetGroupData
2402 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2403 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2405 lpGroupData lpGData;
2406 DWORD dwRequiredBufferSize;
2407 LPVOID lpCopyDataFrom;
2409 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
2410 This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi );
2412 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2414 return DPERR_INVALIDGROUP;
2417 /* How much buffer is required? */
2418 if( dwFlags & DPSET_REMOTE )
2420 dwRequiredBufferSize = lpGData->dwRemoteDataSize;
2421 lpCopyDataFrom = lpGData->lpRemoteData;
2423 else if( dwFlags & DPSET_LOCAL )
2425 dwRequiredBufferSize = lpGData->dwLocalDataSize;
2426 lpCopyDataFrom = lpGData->lpLocalData;
2428 else
2430 ERR( "Neither local or remote data requested!?!\n" );
2431 dwRequiredBufferSize = 0;
2432 lpCopyDataFrom = NULL;
2435 /* Is the user requesting to know how big a buffer is required? */
2436 if( ( lpData == NULL ) ||
2437 ( *lpdwDataSize < dwRequiredBufferSize )
2440 *lpdwDataSize = dwRequiredBufferSize;
2441 return DPERR_BUFFERTOOSMALL;
2444 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2446 return DP_OK;
2449 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2450 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2451 LPDWORD lpdwDataSize, DWORD dwFlags )
2453 ICOM_THIS(IDirectPlay2Impl,iface);
2454 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2455 dwFlags, TRUE );
2458 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2459 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2460 LPDWORD lpdwDataSize, DWORD dwFlags )
2462 ICOM_THIS(IDirectPlay2Impl,iface);
2463 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2464 dwFlags, FALSE );
2467 static HRESULT WINAPI DP_IF_GetGroupName
2468 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2469 LPDWORD lpdwDataSize, BOOL bAnsi )
2471 lpGroupData lpGData;
2472 LPDPNAME lpName = (LPDPNAME)lpData;
2473 DWORD dwRequiredDataSize;
2475 FIXME("(%p)->(0x%08lx,%p,%p,%u) ANSI ignored\n",
2476 This, idGroup, lpData, lpdwDataSize, bAnsi );
2478 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2480 return DPERR_INVALIDGROUP;
2483 dwRequiredDataSize = lpGData->name.dwSize;
2485 if( lpGData->name.u1.lpszShortNameA )
2487 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
2490 if( lpGData->name.u2.lpszLongNameA )
2492 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
2495 if( ( lpData == NULL ) ||
2496 ( *lpdwDataSize < dwRequiredDataSize )
2499 *lpdwDataSize = dwRequiredDataSize;
2500 return DPERR_BUFFERTOOSMALL;
2503 /* Copy the structure */
2504 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2506 if( lpGData->name.u1.lpszShortNameA )
2508 strcpy( ((BYTE*)lpName)+lpGData->name.dwSize,
2509 lpGData->name.u1.lpszShortNameA );
2511 else
2513 lpName->u1.lpszShortNameA = NULL;
2516 if( lpGData->name.u1.lpszShortNameA )
2518 strcpy( ((BYTE*)lpName)+lpGData->name.dwSize,
2519 lpGData->name.u2.lpszLongNameA );
2521 else
2523 lpName->u2.lpszLongNameA = NULL;
2526 return DP_OK;
2529 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2530 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2531 LPDWORD lpdwDataSize )
2533 ICOM_THIS(IDirectPlay2Impl,iface);
2534 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2537 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2538 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2539 LPDWORD lpdwDataSize )
2541 ICOM_THIS(IDirectPlay2Impl,iface);
2542 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2545 static HRESULT WINAPI DP_IF_GetMessageCount
2546 ( IDirectPlay2Impl* This, DPID idPlayer,
2547 LPDWORD lpdwCount, BOOL bAnsi )
2549 FIXME("(%p)->(0x%08lx,%p,%u): stub\n", This, idPlayer, lpdwCount, bAnsi );
2550 return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer,
2551 DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL,
2552 bAnsi );
2555 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2556 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDWORD lpdwCount )
2558 ICOM_THIS(IDirectPlay2Impl,iface);
2559 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, TRUE );
2562 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2563 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDWORD lpdwCount )
2565 ICOM_THIS(IDirectPlay2Impl,iface);
2566 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, FALSE );
2569 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2570 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2572 ICOM_THIS(IDirectPlay2Impl,iface);
2573 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2574 return DP_OK;
2577 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2578 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2580 ICOM_THIS(IDirectPlay2Impl,iface);
2581 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2582 return DP_OK;
2585 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2586 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2587 DWORD dwFlags )
2589 ICOM_THIS(IDirectPlay2Impl,iface);
2590 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2593 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2594 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2595 DWORD dwFlags )
2597 ICOM_THIS(IDirectPlay2Impl,iface);
2598 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2601 static HRESULT WINAPI DP_IF_GetPlayerData
2602 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2603 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2605 lpPlayerList lpPList;
2606 DWORD dwRequiredBufferSize;
2607 LPVOID lpCopyDataFrom;
2609 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
2610 This, idPlayer, lpData, lpdwDataSize, dwFlags, bAnsi );
2612 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2614 return DPERR_INVALIDPLAYER;
2617 /* How much buffer is required? */
2618 if( dwFlags & DPSET_REMOTE )
2620 dwRequiredBufferSize = lpPList->lpPData->dwRemoteDataSize;
2621 lpCopyDataFrom = lpPList->lpPData->lpRemoteData;
2623 else if( dwFlags & DPSET_LOCAL )
2625 dwRequiredBufferSize = lpPList->lpPData->dwLocalDataSize;
2626 lpCopyDataFrom = lpPList->lpPData->lpLocalData;
2628 else
2630 ERR( "Neither local or remote data requested!?!\n" );
2631 dwRequiredBufferSize = 0;
2632 lpCopyDataFrom = NULL;
2635 /* Is the user requesting to know how big a buffer is required? */
2636 if( ( lpData == NULL ) ||
2637 ( *lpdwDataSize < dwRequiredBufferSize )
2640 *lpdwDataSize = dwRequiredBufferSize;
2641 return DPERR_BUFFERTOOSMALL;
2644 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2646 return DP_OK;
2649 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2650 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2651 LPDWORD lpdwDataSize, DWORD dwFlags )
2653 ICOM_THIS(IDirectPlay2Impl,iface);
2654 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2655 dwFlags, TRUE );
2658 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2659 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2660 LPDWORD lpdwDataSize, DWORD dwFlags )
2662 ICOM_THIS(IDirectPlay2Impl,iface);
2663 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2664 dwFlags, FALSE );
2667 static HRESULT WINAPI DP_IF_GetPlayerName
2668 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2669 LPDWORD lpdwDataSize, BOOL bAnsi )
2671 lpPlayerList lpPList;
2672 LPDPNAME lpName = (LPDPNAME)lpData;
2673 DWORD dwRequiredDataSize;
2675 FIXME( "(%p)->(0x%08lx,%p,%p,%u): ANSI \n",
2676 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2678 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2680 return DPERR_INVALIDPLAYER;
2683 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
2685 if( lpPList->lpPData->name.u1.lpszShortNameA )
2687 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
2690 if( lpPList->lpPData->name.u2.lpszLongNameA )
2692 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
2695 if( ( lpData == NULL ) ||
2696 ( *lpdwDataSize < dwRequiredDataSize )
2699 *lpdwDataSize = dwRequiredDataSize;
2700 return DPERR_BUFFERTOOSMALL;
2703 /* Copy the structure */
2704 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
2706 if( lpPList->lpPData->name.u1.lpszShortNameA )
2708 strcpy( ((BYTE*)lpName)+lpPList->lpPData->name.dwSize,
2709 lpPList->lpPData->name.u1.lpszShortNameA );
2711 else
2713 lpName->u1.lpszShortNameA = NULL;
2716 if( lpPList->lpPData->name.u1.lpszShortNameA )
2718 strcpy( ((BYTE*)lpName)+lpPList->lpPData->name.dwSize,
2719 lpPList->lpPData->name.u2.lpszLongNameA );
2721 else
2723 lpName->u2.lpszLongNameA = NULL;
2726 return DP_OK;
2729 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2730 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2731 LPDWORD lpdwDataSize )
2733 ICOM_THIS(IDirectPlay2Impl,iface);
2734 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
2737 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2738 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2739 LPDWORD lpdwDataSize )
2741 ICOM_THIS(IDirectPlay2Impl,iface);
2742 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
2745 static HRESULT WINAPI DP_GetSessionDesc
2746 ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize,
2747 BOOL bAnsi )
2749 DWORD dwRequiredSize;
2751 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
2753 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
2755 return DPERR_INVALIDPARAMS;
2758 /* FIXME: Get from This->dp2->lpSessionDesc */
2759 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
2761 if ( ( lpData == NULL ) ||
2762 ( *lpdwDataSize < dwRequiredSize )
2765 *lpdwDataSize = dwRequiredSize;
2766 return DPERR_BUFFERTOOSMALL;
2769 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
2771 return DP_OK;
2774 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
2775 ( LPDIRECTPLAY2A iface, LPVOID lpData, LPDWORD lpdwDataSize )
2777 ICOM_THIS(IDirectPlay2Impl,iface);
2778 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2781 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
2782 ( LPDIRECTPLAY2 iface, LPVOID lpData, LPDWORD lpdwDataSize )
2784 ICOM_THIS(IDirectPlay2Impl,iface);
2785 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2788 /* Intended only for COM compatibility. Always returns an error. */
2789 static HRESULT WINAPI DirectPlay2AImpl_Initialize
2790 ( LPDIRECTPLAY2A iface, LPGUID lpGUID )
2792 ICOM_THIS(IDirectPlay2Impl,iface);
2793 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2794 return DPERR_ALREADYINITIALIZED;
2797 /* Intended only for COM compatibility. Always returns an error. */
2798 static HRESULT WINAPI DirectPlay2WImpl_Initialize
2799 ( LPDIRECTPLAY2 iface, LPGUID lpGUID )
2801 ICOM_THIS(IDirectPlay2Impl,iface);
2802 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2803 return DPERR_ALREADYINITIALIZED;
2807 static HRESULT WINAPI DP_SecureOpen
2808 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
2809 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
2810 BOOL bAnsi )
2812 HRESULT hr = DP_OK;
2814 FIXME( "(%p)->(%p,0x%08lx,%p,%p): partial stub\n",
2815 This, lpsd, dwFlags, lpSecurity, lpCredentials );
2817 if( This->dp2->bConnectionOpen )
2819 TRACE( ": rejecting already open connection.\n" );
2820 return DPERR_ALREADYINITIALIZED;
2823 /* If we're enumerating, kill the thread */
2824 DP_KillEnumSessionThread( This );
2826 if( dwFlags & DPOPEN_CREATE )
2828 /* Rightoo - this computer is the host and the local computer needs to be
2829 the name server so that others can join this session */
2830 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
2832 This->dp2->bHostInterface = TRUE;
2834 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
2835 if( FAILED( hr ) )
2837 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
2838 return hr;
2842 /* Invoke the conditional callback for the service provider */
2843 if( This->dp2->spData.lpCB->Open )
2845 DPSP_OPENDATA data;
2847 FIXME( "Not all data fields are correct. Need new parameter\n" );
2849 data.bCreate = (dwFlags & DPOPEN_CREATE ) ? TRUE : FALSE;
2850 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
2851 : NS_GetNSAddr( This->dp2->lpNameServerData );
2852 data.lpISP = This->dp2->spData.lpISP;
2853 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) ? TRUE : FALSE;
2854 data.dwOpenFlags = dwFlags;
2855 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
2857 hr = (*This->dp2->spData.lpCB->Open)(&data);
2858 if( FAILED( hr ) )
2860 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
2861 return hr;
2866 /* Create the system group of which everything is a part of */
2867 DPID systemGroup = DPID_SYSTEM_GROUP;
2869 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
2870 NULL, 0, 0, TRUE );
2874 if( dwFlags & DPOPEN_JOIN )
2876 DPID dpidServerId = DPID_UNKNOWN;
2878 /* Create the server player for this interface. This way we can receive
2879 * messages for this session.
2881 /* FIXME: I suppose that we should be setting an event for a receive
2882 * type of thing. That way the messaging thread could know to wake
2883 * up. DPlay would then trigger the hEvent for the player the
2884 * message is directed to.
2886 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
2888 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
2891 else if( dwFlags & DPOPEN_CREATE )
2893 DPID dpidNameServerId = DPID_NAME_SERVER;
2895 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
2896 0, DPPLAYER_SERVERPLAYER, bAnsi );
2899 if( FAILED(hr) )
2901 ERR( "Couldn't create name server/system player: %s\n",
2902 DPLAYX_HresultToString(hr) );
2905 return hr;
2908 static HRESULT WINAPI DirectPlay2AImpl_Open
2909 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2911 ICOM_THIS(IDirectPlay2Impl,iface);
2912 TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags );
2913 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, TRUE );
2916 static HRESULT WINAPI DirectPlay2WImpl_Open
2917 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2919 ICOM_THIS(IDirectPlay2Impl,iface);
2920 TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags );
2921 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, FALSE );
2924 static HRESULT WINAPI DP_IF_Receive
2925 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
2926 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi )
2928 LPDPMSG lpMsg = NULL;
2930 FIXME( "(%p)->(%p,%p,0x%08lx,%p,%p,%u): stub\n",
2931 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
2933 if( dwFlags == 0 )
2935 dwFlags = DPRECEIVE_ALL;
2938 /* If the lpData is NULL, we must be peeking the message */
2939 if( ( lpData == NULL ) &&
2940 !( dwFlags & DPRECEIVE_PEEK )
2943 return DPERR_INVALIDPARAMS;
2946 if( dwFlags & DPRECEIVE_ALL )
2948 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
2950 if( !( dwFlags & DPRECEIVE_PEEK ) )
2952 FIXME( "Remove from queue\n" );
2955 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
2956 ( dwFlags & DPRECEIVE_FROMPLAYER )
2959 FIXME( "Find matching message 0x%08lx\n", dwFlags );
2961 else
2963 ERR( "Hmmm..dwFlags 0x%08lx\n", dwFlags );
2966 if( lpMsg == NULL )
2968 return DPERR_NOMESSAGES;
2971 /* Copy into the provided buffer */
2972 CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
2974 return DP_OK;
2977 static HRESULT WINAPI DirectPlay2AImpl_Receive
2978 ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo,
2979 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
2981 ICOM_THIS(IDirectPlay2Impl,iface);
2982 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
2983 lpData, lpdwDataSize, TRUE );
2986 static HRESULT WINAPI DirectPlay2WImpl_Receive
2987 ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo,
2988 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
2990 ICOM_THIS(IDirectPlay2Impl,iface);
2991 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
2992 lpData, lpdwDataSize, FALSE );
2995 static HRESULT WINAPI DirectPlay2AImpl_Send
2996 ( LPDIRECTPLAY2A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
2998 ICOM_THIS(IDirectPlay2Impl,iface);
2999 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3000 0, 0, NULL, NULL, TRUE );
3003 static HRESULT WINAPI DirectPlay2WImpl_Send
3004 ( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3006 ICOM_THIS(IDirectPlay2Impl,iface);
3007 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3008 0, 0, NULL, NULL, FALSE );
3011 static HRESULT WINAPI DP_IF_SetGroupData
3012 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
3013 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3015 lpGroupData lpGData;
3017 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
3018 This, idGroup, lpData, dwDataSize, dwFlags, bAnsi );
3020 /* Parameter check */
3021 if( ( lpData == NULL ) &&
3022 ( dwDataSize != 0 )
3025 return DPERR_INVALIDPARAMS;
3028 /* Find the pointer to the data for this player */
3029 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3031 return DPERR_INVALIDOBJECT;
3034 if( dwFlags & DPSET_REMOTE )
3036 FIXME( "Was this group created by this interface?\n" );
3037 /* FIXME: If this is a remote update need to allow it but not
3038 * send a message.
3042 DP_SetGroupData( lpGData, dwFlags, lpData, dwDataSize );
3044 /* FIXME: Only send a message if this group is local to the session otherwise
3045 * it will have been rejected above
3047 if( dwFlags & DPSET_REMOTE )
3049 FIXME( "Send msg?\n" );
3052 return DP_OK;
3055 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
3056 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
3057 DWORD dwDataSize, DWORD dwFlags )
3059 ICOM_THIS(IDirectPlay2Impl,iface);
3060 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, TRUE );
3063 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
3064 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
3065 DWORD dwDataSize, DWORD dwFlags )
3067 ICOM_THIS(IDirectPlay2Impl,iface);
3068 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, FALSE );
3071 static HRESULT WINAPI DP_IF_SetGroupName
3072 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
3073 DWORD dwFlags, BOOL bAnsi )
3075 lpGroupData lpGData;
3077 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n", This, idGroup,
3078 lpGroupName, dwFlags, bAnsi );
3080 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3082 return DPERR_INVALIDGROUP;
3085 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
3087 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3088 FIXME( "Message not sent and dwFlags ignored\n" );
3090 return DP_OK;
3093 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
3094 ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName,
3095 DWORD dwFlags )
3097 ICOM_THIS(IDirectPlay2Impl,iface);
3098 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
3101 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
3102 ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName,
3103 DWORD dwFlags )
3105 ICOM_THIS(IDirectPlay2Impl,iface);
3106 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
3109 static HRESULT WINAPI DP_IF_SetPlayerData
3110 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
3111 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3113 lpPlayerList lpPList;
3115 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
3116 This, idPlayer, lpData, dwDataSize, dwFlags, bAnsi );
3118 /* Parameter check */
3119 if( ( lpData == NULL ) &&
3120 ( dwDataSize != 0 )
3123 return DPERR_INVALIDPARAMS;
3126 /* Find the pointer to the data for this player */
3127 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3129 return DPERR_INVALIDPLAYER;
3132 if( dwFlags & DPSET_REMOTE )
3134 FIXME( "Was this group created by this interface?\n" );
3135 /* FIXME: If this is a remote update need to allow it but not
3136 * send a message.
3140 DP_SetPlayerData( lpPList->lpPData, dwFlags, lpData, dwDataSize );
3142 if( dwFlags & DPSET_REMOTE )
3144 FIXME( "Send msg?\n" );
3147 return DP_OK;
3150 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3151 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
3152 DWORD dwDataSize, DWORD dwFlags )
3154 ICOM_THIS(IDirectPlay2Impl,iface);
3155 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3156 dwFlags, TRUE );
3159 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3160 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
3161 DWORD dwDataSize, DWORD dwFlags )
3163 ICOM_THIS(IDirectPlay2Impl,iface);
3164 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3165 dwFlags, FALSE );
3168 static HRESULT WINAPI DP_IF_SetPlayerName
3169 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
3170 DWORD dwFlags, BOOL bAnsi )
3172 lpPlayerList lpPList;
3174 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n",
3175 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3177 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3179 return DPERR_INVALIDGROUP;
3182 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3184 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3185 FIXME( "Message not sent and dwFlags ignored\n" );
3187 return DP_OK;
3190 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3191 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName,
3192 DWORD dwFlags )
3194 ICOM_THIS(IDirectPlay2Impl,iface);
3195 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3198 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3199 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName,
3200 DWORD dwFlags )
3202 ICOM_THIS(IDirectPlay2Impl,iface);
3203 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3206 static HRESULT WINAPI DP_SetSessionDesc
3207 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
3208 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3210 DWORD dwRequiredSize;
3211 LPDPSESSIONDESC2 lpTempSessDesc;
3213 TRACE( "(%p)->(%p,0x%08lx,%u,%u)\n",
3214 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3216 if( dwFlags )
3218 return DPERR_INVALIDPARAMS;
3221 /* Only the host is allowed to update the session desc */
3222 if( !This->dp2->bHostInterface )
3224 return DPERR_ACCESSDENIED;
3227 /* FIXME: Copy into This->dp2->lpSessionDesc */
3228 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3229 lpTempSessDesc = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
3230 HEAP_ZERO_MEMORY,
3231 dwRequiredSize );
3233 if( lpTempSessDesc == NULL )
3235 return DPERR_OUTOFMEMORY;
3238 /* Free the old */
3239 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3241 This->dp2->lpSessionDesc = lpTempSessDesc;
3243 /* Set the new */
3244 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3246 /* If this is an external invocation of the interface, we should be
3247 * letting everyone know that things have changed. Otherwise this is
3248 * just an initialization and it doesn't need to be propagated.
3250 if( !bInitial )
3252 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3255 return DP_OK;
3258 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3259 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3261 ICOM_THIS(IDirectPlay2Impl,iface);
3262 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3265 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3266 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3268 ICOM_THIS(IDirectPlay2Impl,iface);
3269 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3272 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3273 DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3275 DWORD dwSize = 0;
3277 if( lpSessDesc == NULL )
3279 /* Hmmm..don't need any size? */
3280 ERR( "NULL lpSessDesc\n" );
3281 return dwSize;
3284 dwSize += sizeof( *lpSessDesc );
3286 if( bAnsi )
3288 if( lpSessDesc->u1.lpszSessionNameA )
3290 dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1;
3293 if( lpSessDesc->u2.lpszPasswordA )
3295 dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1;
3298 else /* UNICODE */
3300 if( lpSessDesc->u1.lpszSessionName )
3302 dwSize += sizeof( WCHAR ) *
3303 ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 );
3306 if( lpSessDesc->u2.lpszPassword )
3308 dwSize += sizeof( WCHAR ) *
3309 ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 );
3313 return dwSize;
3316 /* Assumes that contugous buffers are already allocated. */
3317 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3318 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3320 BYTE* lpStartOfFreeSpace;
3322 if( lpSessionDest == NULL )
3324 ERR( "NULL lpSessionDest\n" );
3325 return;
3328 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3330 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3332 if( bAnsi )
3334 if( lpSessionSrc->u1.lpszSessionNameA )
3336 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3337 lpSessionDest->u1.lpszSessionNameA );
3338 lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3339 lpStartOfFreeSpace +=
3340 lstrlenA( (LPSTR)lpSessionDest->u1.lpszSessionNameA ) + 1;
3343 if( lpSessionSrc->u2.lpszPasswordA )
3345 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3346 lpSessionDest->u2.lpszPasswordA );
3347 lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3348 lpStartOfFreeSpace +=
3349 lstrlenA( (LPSTR)lpSessionDest->u2.lpszPasswordA ) + 1;
3352 else /* UNICODE */
3354 if( lpSessionSrc->u1.lpszSessionName )
3356 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3357 lpSessionDest->u1.lpszSessionName );
3358 lpSessionDest->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3359 lpStartOfFreeSpace += sizeof(WCHAR) *
3360 ( lstrlenW( (LPWSTR)lpSessionDest->u1.lpszSessionName ) + 1 );
3363 if( lpSessionSrc->u2.lpszPassword )
3365 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3366 lpSessionDest->u2.lpszPassword );
3367 lpSessionDest->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3368 lpStartOfFreeSpace += sizeof(WCHAR) *
3369 ( lstrlenW( (LPWSTR)lpSessionDest->u2.lpszPassword ) + 1 );
3375 static HRESULT WINAPI DP_IF_AddGroupToGroup
3376 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3378 lpGroupData lpGParentData;
3379 lpGroupData lpGData;
3380 lpGroupList lpNewGList;
3382 TRACE( "(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup );
3384 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3386 return DPERR_INVALIDGROUP;
3389 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3391 return DPERR_INVALIDGROUP;
3394 /* Create a player list (ie "shortcut" ) */
3395 lpNewGList = (lpGroupList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3396 sizeof( *lpNewGList ) );
3397 if( lpNewGList == NULL )
3399 return DPERR_CANTADDPLAYER;
3402 /* Add the shortcut */
3403 lpGData->uRef++;
3404 lpNewGList->lpGData = lpGData;
3406 /* Add the player to the list of players for this group */
3407 DPQ_INSERT( lpGData->groups, lpNewGList, groups );
3409 /* Send a ADDGROUPTOGROUP message */
3410 FIXME( "Not sending message\n" );
3412 return DP_OK;
3415 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3416 ( LPDIRECTPLAY3A iface, DPID idParentGroup, DPID idGroup )
3418 ICOM_THIS(IDirectPlay3Impl,iface);
3419 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3422 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3423 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3425 ICOM_THIS(IDirectPlay3Impl,iface);
3426 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3429 static HRESULT WINAPI DP_IF_CreateGroupInGroup
3430 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
3431 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
3432 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3434 lpGroupData lpGParentData;
3435 lpGroupList lpGList;
3436 lpGroupData lpGData;
3438 TRACE( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
3439 This, idParentGroup, lpidGroup, lpGroupName, lpData,
3440 dwDataSize, dwFlags, bAnsi );
3442 /* Verify that the specified parent is valid */
3443 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This,
3444 idParentGroup ) ) == NULL
3447 return DPERR_INVALIDGROUP;
3450 lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName,
3451 dwFlags, idParentGroup, bAnsi );
3453 if( lpGData == NULL )
3455 return DPERR_CANTADDPLAYER; /* yes player not group */
3458 /* Something else is referencing this data */
3459 lpGData->uRef++;
3461 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
3463 /* The list has now been inserted into the interface group list. We now
3464 need to put a "shortcut" to this group in the parent group */
3465 lpGList = (lpGroupList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3466 sizeof( *lpGList ) );
3467 if( lpGList == NULL )
3469 FIXME( "Memory leak\n" );
3470 return DPERR_CANTADDPLAYER; /* yes player not group */
3473 lpGList->lpGData = lpGData;
3475 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
3477 /* Let the SP know that we've created this group */
3478 if( This->dp2->spData.lpCB->CreateGroup )
3480 DPSP_CREATEGROUPDATA data;
3482 TRACE( "Calling SP CreateGroup\n" );
3484 data.idGroup = *lpidGroup;
3485 data.dwFlags = dwFlags;
3486 data.lpSPMessageHeader = lpMsgHdr;
3487 data.lpISP = This->dp2->spData.lpISP;
3489 (*This->dp2->spData.lpCB->CreateGroup)( &data );
3492 /* Inform all other peers of the creation of a new group. If there are
3493 * no peers keep this quiet.
3495 if( This->dp2->lpSessionDesc &&
3496 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
3498 DPMSG_CREATEPLAYERORGROUP msg;
3500 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
3501 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
3502 msg.dpId = *lpidGroup;
3503 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
3504 msg.lpData = lpData;
3505 msg.dwDataSize = dwDataSize;
3506 msg.dpnName = *lpGroupName;
3508 /* FIXME: Correct to just use send effectively? */
3509 /* FIXME: Should size include data w/ message or just message "header" */
3510 /* FIXME: Check return code */
3511 DP_SendEx( (IDirectPlay2Impl*)This,
3512 DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
3513 0, 0, NULL, NULL, bAnsi );
3516 return DP_OK;
3519 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3520 ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup,
3521 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3522 DWORD dwFlags )
3524 ICOM_THIS(IDirectPlay3Impl,iface);
3526 *lpidGroup = DPID_UNKNOWN;
3528 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3529 lpGroupName, lpData, dwDataSize, dwFlags,
3530 TRUE );
3533 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3534 ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup,
3535 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3536 DWORD dwFlags )
3538 ICOM_THIS(IDirectPlay3Impl,iface);
3540 *lpidGroup = DPID_UNKNOWN;
3542 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3543 lpGroupName, lpData, dwDataSize,
3544 dwFlags, FALSE );
3547 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
3548 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3550 lpGroupList lpGList;
3551 lpGroupData lpGParentData;
3553 TRACE("(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup );
3555 /* Is the parent group valid? */
3556 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3558 return DPERR_INVALIDGROUP;
3561 /* Remove the group from the parent group queue */
3562 DPQ_REMOVE_ENTRY( lpGParentData->groups, groups, lpGData->dpid, ==, idGroup, lpGList );
3564 if( lpGList == NULL )
3566 return DPERR_INVALIDGROUP;
3569 /* Decrement the ref count */
3570 lpGList->lpGData->uRef--;
3572 /* Free up the list item */
3573 HeapFree( GetProcessHeap(), 0, lpGList );
3575 /* Should send a DELETEGROUPFROMGROUP message */
3576 FIXME( "message not sent\n" );
3578 return DP_OK;
3581 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3582 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3584 ICOM_THIS(IDirectPlay3Impl,iface);
3585 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3588 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3589 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3591 ICOM_THIS(IDirectPlay3Impl,iface);
3592 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3595 static
3596 BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
3597 LPDWORD lpdwBufSize )
3599 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3600 HRESULT hr;
3602 dpCompoundAddress.dwDataSize = sizeof( GUID );
3603 memcpy( &dpCompoundAddress.guidDataType, &DPAID_ServiceProvider,
3604 sizeof( GUID ) ) ;
3605 dpCompoundAddress.lpData = lpcSpGuid;
3607 *lplpAddrBuf = NULL;
3608 *lpdwBufSize = 0;
3610 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3611 lpdwBufSize, TRUE );
3613 if( hr != DPERR_BUFFERTOOSMALL )
3615 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3616 return FALSE;
3619 /* Now allocate the buffer */
3620 *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3621 *lpdwBufSize );
3623 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3624 lpdwBufSize, TRUE );
3625 if( FAILED(hr) )
3627 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3628 return FALSE;
3631 return TRUE;
3634 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
3635 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3637 ICOM_THIS(IDirectPlay3Impl,iface);
3638 TRACE("(%p)->(%p,%p,%p,0x%08lx)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3640 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
3641 if( dwFlags == 0 )
3643 dwFlags = DPCONNECTION_DIRECTPLAY;
3646 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
3647 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) )
3650 return DPERR_INVALIDFLAGS;
3653 if( !lpEnumCallback || !*lpEnumCallback )
3655 return DPERR_INVALIDPARAMS;
3658 /* Enumerate DirectPlay service providers */
3659 if( dwFlags & DPCONNECTION_DIRECTPLAY )
3661 HKEY hkResult;
3662 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3663 LPSTR guidDataSubKey = "Guid";
3664 char subKeyName[51];
3665 DWORD dwIndex, sizeOfSubKeyName=50;
3666 FILETIME filetime;
3668 /* Need to loop over the service providers in the registry */
3669 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3670 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3672 /* Hmmm. Does this mean that there are no service providers? */
3673 ERR(": no service providers?\n");
3674 return DP_OK;
3678 /* Traverse all the service providers we have available */
3679 for( dwIndex=0;
3680 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3681 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3682 ++dwIndex, sizeOfSubKeyName=51 )
3685 HKEY hkServiceProvider;
3686 GUID serviceProviderGUID;
3687 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3688 char returnBuffer[51];
3689 WCHAR buff[51];
3690 DPNAME dpName;
3691 BOOL bBuildPass;
3693 LPVOID lpAddressBuffer = NULL;
3694 DWORD dwAddressBufferSize = 0;
3696 TRACE(" this time through: %s\n", subKeyName );
3698 /* Get a handle for this particular service provider */
3699 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3700 &hkServiceProvider ) != ERROR_SUCCESS )
3702 ERR(": what the heck is going on?\n" );
3703 continue;
3706 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3707 NULL, &returnTypeGUID, returnBuffer,
3708 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3710 ERR(": missing GUID registry data members\n" );
3711 continue;
3714 /* FIXME: Check return types to ensure we're interpreting data right */
3715 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3716 CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
3717 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3719 /* Fill in the DPNAME struct for the service provider */
3720 dpName.dwSize = sizeof( dpName );
3721 dpName.dwFlags = 0;
3722 dpName.u1.lpszShortNameA = subKeyName;
3723 dpName.u2.lpszLongNameA = NULL;
3725 /* Create the compound address for the service provider.
3726 * NOTE: This is a gruesome architectural scar right now. DP
3727 * uses DPL and DPL uses DP. Nasty stuff. This may be why the
3728 * native dll just gets around this little bit by allocating an
3729 * 80 byte buffer which isn't even filled with a valid compound
3730 * address. Oh well. Creating a proper compound address is the
3731 * way to go anyways despite this method taking slightly more
3732 * heap space and realtime :) */
3734 bBuildPass = DP_BuildSPCompoundAddr( &serviceProviderGUID,
3735 &lpAddressBuffer,
3736 &dwAddressBufferSize );
3737 if( !bBuildPass )
3739 ERR( "Can't build compound addr\n" );
3740 return DPERR_GENERIC;
3743 /* The enumeration will return FALSE if we are not to continue */
3744 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3745 &dpName, DPCONNECTION_DIRECTPLAY, lpContext ) )
3747 return DP_OK;
3752 /* Enumerate DirectPlayLobby service providers */
3753 if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY )
3755 HKEY hkResult;
3756 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3757 LPSTR guidDataSubKey = "Guid";
3758 char subKeyName[51];
3759 DWORD dwIndex, sizeOfSubKeyName=50;
3760 FILETIME filetime;
3762 /* Need to loop over the service providers in the registry */
3763 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3764 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3766 /* Hmmm. Does this mean that there are no service providers? */
3767 ERR(": no service providers?\n");
3768 return DP_OK;
3772 /* Traverse all the lobby providers we have available */
3773 for( dwIndex=0;
3774 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3775 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3776 ++dwIndex, sizeOfSubKeyName=51 )
3779 HKEY hkServiceProvider;
3780 GUID serviceProviderGUID;
3781 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3782 char returnBuffer[51];
3783 WCHAR buff[51];
3784 DPNAME dpName;
3785 HRESULT hr;
3787 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3788 LPVOID lpAddressBuffer = NULL;
3789 DWORD dwAddressBufferSize = 0;
3791 TRACE(" this time through: %s\n", subKeyName );
3793 /* Get a handle for this particular service provider */
3794 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3795 &hkServiceProvider ) != ERROR_SUCCESS )
3797 ERR(": what the heck is going on?\n" );
3798 continue;
3801 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3802 NULL, &returnTypeGUID, returnBuffer,
3803 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3805 ERR(": missing GUID registry data members\n" );
3806 continue;
3809 /* FIXME: Check return types to ensure we're interpreting data right */
3810 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3811 CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
3812 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3814 /* Fill in the DPNAME struct for the service provider */
3815 dpName.dwSize = sizeof( dpName );
3816 dpName.dwFlags = 0;
3817 dpName.u1.lpszShortNameA = subKeyName;
3818 dpName.u2.lpszLongNameA = NULL;
3820 /* Create the compound address for the service provider.
3821 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
3822 nast stuff. This may be why the native dll just gets around this little bit by
3823 allocating an 80 byte buffer which isn't even a filled with a valid compound
3824 address. Oh well. Creating a proper compound address is the way to go anyways
3825 despite this method taking slightly more heap space and realtime :) */
3827 dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
3828 dpCompoundAddress.dwDataSize = sizeof( GUID );
3829 dpCompoundAddress.lpData = &serviceProviderGUID;
3831 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3832 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
3834 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3835 return hr;
3838 /* Now allocate the buffer */
3839 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
3841 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3842 &dwAddressBufferSize, TRUE ) ) != DP_OK )
3844 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3845 return hr;
3848 /* The enumeration will return FALSE if we are not to continue */
3849 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3850 &dpName, DPCONNECTION_DIRECTPLAYLOBBY, lpContext ) )
3852 return DP_OK;
3857 return DP_OK;
3860 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
3861 ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3863 ICOM_THIS(IDirectPlay3Impl,iface);
3864 FIXME("(%p)->(%p,%p,%p,0x%08lx): stub\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3865 return DP_OK;
3868 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
3869 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
3870 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
3871 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
3873 lpGroupList lpGList;
3874 lpGroupData lpGData;
3876 FIXME( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
3877 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
3878 lpContext, dwFlags, bAnsi );
3880 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3882 return DPERR_INVALIDGROUP;
3885 if( DPQ_IS_EMPTY( lpGData->groups ) )
3887 return DP_OK;
3890 lpGList = DPQ_FIRST( lpGData->groups );
3892 for( ;; )
3894 /* FIXME: Should check dwFlags for match here */
3896 if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP,
3897 &lpGList->lpGData->name, dwFlags,
3898 lpContext ) )
3900 return DP_OK; /* User requested break */
3903 if( DPQ_IS_ENDOFLIST( lpGList->groups ) )
3905 break;
3908 lpGList = DPQ_NEXT( lpGList->groups );
3912 return DP_OK;
3915 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
3916 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3917 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3918 DWORD dwFlags )
3920 ICOM_THIS(IDirectPlay3Impl,iface);
3921 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3922 lpEnumPlayersCallback2, lpContext, dwFlags,
3923 TRUE );
3926 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
3927 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3928 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3929 DWORD dwFlags )
3931 ICOM_THIS(IDirectPlay3Impl,iface);
3932 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3933 lpEnumPlayersCallback2, lpContext, dwFlags,
3934 FALSE );
3937 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
3938 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3940 ICOM_THIS(IDirectPlay3Impl,iface);
3941 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3942 return DP_OK;
3945 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
3946 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3948 ICOM_THIS(IDirectPlay3Impl,iface);
3949 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3950 return DP_OK;
3953 BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
3954 REFGUID guidDataType,
3955 DWORD dwDataSize,
3956 LPCVOID lpData,
3957 LPVOID lpContext )
3959 /* Looking for the GUID of the provider to load */
3960 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
3961 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
3964 TRACE( "Found SP/LP (%s) %s (data size = 0x%08lx)\n",
3965 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
3967 if( dwDataSize != sizeof( GUID ) )
3969 ERR( "Invalid sp/lp guid size 0x%08lx\n", dwDataSize );
3972 memcpy( lpContext, lpData, dwDataSize );
3974 /* There shouldn't be more than 1 GUID/compound address */
3975 return FALSE;
3978 /* Still waiting for what we want */
3979 return TRUE;
3983 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
3984 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
3986 UINT i;
3987 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3988 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3989 LPCSTR guidDataSubKey = "Guid";
3990 LPCSTR majVerDataSubKey = "dwReserved1";
3991 LPCSTR minVerDataSubKey = "dwReserved2";
3992 LPCSTR pathSubKey = "Path";
3994 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
3996 /* FIXME: Cloned code with a quick hack. */
3997 for( i=0; i<2; i++ )
3999 HKEY hkResult;
4000 LPCSTR searchSubKey;
4001 char subKeyName[51];
4002 DWORD dwIndex, sizeOfSubKeyName=50;
4003 FILETIME filetime;
4005 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
4006 *lpbIsDpSp = (i == 0) ? TRUE : FALSE;
4009 /* Need to loop over the service providers in the registry */
4010 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4011 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4013 /* Hmmm. Does this mean that there are no service providers? */
4014 ERR(": no service providers?\n");
4015 return 0;
4018 /* Traverse all the service providers we have available */
4019 for( dwIndex=0;
4020 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4021 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4022 ++dwIndex, sizeOfSubKeyName=51 )
4025 HKEY hkServiceProvider;
4026 GUID serviceProviderGUID;
4027 DWORD returnType, sizeOfReturnBuffer = 255;
4028 char returnBuffer[256];
4029 WCHAR buff[51];
4030 DWORD dwTemp, len;
4032 TRACE(" this time through: %s\n", subKeyName );
4034 /* Get a handle for this particular service provider */
4035 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4036 &hkServiceProvider ) != ERROR_SUCCESS )
4038 ERR(": what the heck is going on?\n" );
4039 continue;
4042 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4043 NULL, &returnType, returnBuffer,
4044 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4046 ERR(": missing GUID registry data members\n" );
4047 continue;
4050 /* FIXME: Check return types to ensure we're interpreting data right */
4051 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4052 CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
4053 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4055 /* Determine if this is the Service Provider that the user asked for */
4056 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
4058 continue;
4061 if( i == 0 ) /* DP SP */
4063 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
4064 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
4065 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
4068 sizeOfReturnBuffer = 255;
4070 /* Get dwReserved1 */
4071 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
4072 NULL, &returnType, returnBuffer,
4073 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4075 ERR(": missing dwReserved1 registry data members\n") ;
4076 continue;
4079 if( i == 0 )
4080 memcpy( &lpSpData->dwReserved1, returnBuffer, sizeof(lpSpData->dwReserved1) );
4082 sizeOfReturnBuffer = 255;
4084 /* Get dwReserved2 */
4085 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4086 NULL, &returnType, returnBuffer,
4087 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4089 ERR(": missing dwReserved1 registry data members\n") ;
4090 continue;
4093 if( i == 0 )
4094 memcpy( &lpSpData->dwReserved2, returnBuffer, sizeof(lpSpData->dwReserved2) );
4096 sizeOfReturnBuffer = 255;
4098 /* Get the path for this service provider */
4099 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
4100 NULL, NULL, returnBuffer,
4101 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
4103 ERR(": missing PATH registry data members: 0x%08lx\n", dwTemp );
4104 continue;
4107 TRACE( "Loading %s\n", returnBuffer );
4108 return LoadLibraryA( returnBuffer );
4112 return 0;
4115 static
4116 HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider )
4118 HRESULT hr;
4119 LPDPSP_SPINIT SPInit;
4121 /* Initialize the service provider by calling SPInit */
4122 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4124 if( SPInit == NULL )
4126 ERR( "Service provider doesn't provide SPInit interface?\n" );
4127 FreeLibrary( hServiceProvider );
4128 return DPERR_UNAVAILABLE;
4131 TRACE( "Calling SPInit (DP SP entry point)\n" );
4133 hr = (*SPInit)( &This->dp2->spData );
4135 if( FAILED(hr) )
4137 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4138 FreeLibrary( hServiceProvider );
4139 return hr;
4142 /* FIXME: Need to verify the sanity of the returned callback table
4143 * using IsBadCodePtr */
4144 This->dp2->bSPInitialized = TRUE;
4146 /* This interface is now initialized as a DP object */
4147 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
4149 /* Store the handle of the module so that we can unload it later */
4150 This->dp2->hServiceProvider = hServiceProvider;
4152 return hr;
4155 static
4156 HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hLobbyProvider )
4158 HRESULT hr;
4159 LPSP_INIT DPLSPInit;
4161 /* Initialize the service provider by calling SPInit */
4162 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
4164 if( DPLSPInit == NULL )
4166 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4167 FreeLibrary( hLobbyProvider );
4168 return DPERR_UNAVAILABLE;
4171 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4173 hr = (*DPLSPInit)( &This->dp2->dplspData );
4175 if( FAILED(hr) )
4177 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4178 FreeLibrary( hLobbyProvider );
4179 return hr;
4182 /* FIXME: Need to verify the sanity of the returned callback table
4183 * using IsBadCodePtr */
4185 This->dp2->bDPLSPInitialized = TRUE;
4187 /* This interface is now initialized as a lobby object */
4188 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
4190 /* Store the handle of the module so that we can unload it later */
4191 This->dp2->hDPLobbyProvider = hLobbyProvider;
4193 return hr;
4196 static HRESULT WINAPI DP_IF_InitializeConnection
4197 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi )
4199 HMODULE hServiceProvider;
4200 HRESULT hr;
4201 GUID guidSP;
4202 const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
4203 BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4205 TRACE("(%p)->(%p,0x%08lx,%u)\n", This, lpConnection, dwFlags, bAnsi );
4207 if( dwFlags != 0 )
4209 return DPERR_INVALIDFLAGS;
4212 /* Find out what the requested SP is and how large this buffer is */
4213 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
4214 dwAddrSize, &guidSP );
4216 if( FAILED(hr) )
4218 ERR( "Invalid compound address?\n" );
4219 return DPERR_UNAVAILABLE;
4222 /* Load the service provider */
4223 hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp );
4225 if( hServiceProvider == 0 )
4227 ERR( "Unable to load service provider\n" );
4228 return DPERR_UNAVAILABLE;
4231 if( bIsDpSp )
4233 /* Fill in what we can of the Service Provider required information.
4234 * The rest was be done in DP_LoadSP
4236 This->dp2->spData.lpAddress = lpConnection;
4237 This->dp2->spData.dwAddressSize = dwAddrSize;
4238 This->dp2->spData.lpGuid = &guidSP;
4240 hr = DP_InitializeDPSP( This, hServiceProvider );
4242 else
4244 This->dp2->dplspData.lpAddress = lpConnection;
4246 hr = DP_InitializeDPLSP( This, hServiceProvider );
4249 if( FAILED(hr) )
4251 return hr;
4254 return DP_OK;
4257 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4258 ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
4260 ICOM_THIS(IDirectPlay3Impl,iface);
4262 /* This may not be externally invoked once either an SP or LP is initialized */
4263 if( This->dp2->connectionInitialized != NO_PROVIDER )
4265 return DPERR_ALREADYINITIALIZED;
4268 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE );
4271 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4272 ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
4274 ICOM_THIS(IDirectPlay3Impl,iface);
4276 /* This may not be externally invoked once either an SP or LP is initialized */
4277 if( This->dp2->connectionInitialized != NO_PROVIDER )
4279 return DPERR_ALREADYINITIALIZED;
4282 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE );
4285 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4286 ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4287 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4289 ICOM_THIS(IDirectPlay2Impl,iface); /* Yes a dp 2 interface */
4290 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4293 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4294 ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4295 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4297 ICOM_THIS(IDirectPlay2Impl,iface); /* Yes a dp 2 interface */
4298 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4301 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4302 ( LPDIRECTPLAY3A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4304 ICOM_THIS(IDirectPlay3Impl,iface);
4305 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4306 return DP_OK;
4309 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4310 ( LPDIRECTPLAY3 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4312 ICOM_THIS(IDirectPlay3Impl,iface);
4313 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4314 return DP_OK;
4317 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4318 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4320 ICOM_THIS(IDirectPlay3Impl,iface);
4321 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4322 return DP_OK;
4325 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4326 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4328 ICOM_THIS(IDirectPlay3Impl,iface);
4329 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4330 return DP_OK;
4333 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4334 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup )
4336 ICOM_THIS(IDirectPlay3Impl,iface);
4337 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
4338 return DP_OK;
4341 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4342 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup )
4344 ICOM_THIS(IDirectPlay3Impl,iface);
4345 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
4346 return DP_OK;
4349 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4350 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDWORD lpdwFlags )
4352 ICOM_THIS(IDirectPlay3Impl,iface);
4353 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
4354 return DP_OK;
4357 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4358 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDWORD lpdwFlags )
4360 ICOM_THIS(IDirectPlay3Impl,iface);
4361 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
4362 return DP_OK;
4365 static HRESULT WINAPI DP_IF_GetGroupParent
4366 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
4367 BOOL bAnsi )
4369 lpGroupData lpGData;
4371 TRACE("(%p)->(0x%08lx,%p,%u)\n", This, idGroup, lpidGroup, bAnsi );
4373 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4375 return DPERR_INVALIDGROUP;
4378 *lpidGroup = lpGData->dpid;
4380 return DP_OK;
4383 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4384 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
4386 ICOM_THIS(IDirectPlay3Impl,iface);
4387 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE );
4389 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4390 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
4392 ICOM_THIS(IDirectPlay3Impl,iface);
4393 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE );
4396 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4397 ( LPDIRECTPLAY3A iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4399 ICOM_THIS(IDirectPlay3Impl,iface);
4400 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4401 return DP_OK;
4404 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4405 ( LPDIRECTPLAY3 iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4407 ICOM_THIS(IDirectPlay3Impl,iface);
4408 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4409 return DP_OK;
4412 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4413 ( LPDIRECTPLAY3A iface, DPID idPlayer, LPDWORD lpdwFlags )
4415 ICOM_THIS(IDirectPlay3Impl,iface);
4416 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
4417 return DP_OK;
4420 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4421 ( LPDIRECTPLAY3 iface, DPID idPlayer, LPDWORD lpdwFlags )
4423 ICOM_THIS(IDirectPlay3Impl,iface);
4424 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
4425 return DP_OK;
4428 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4429 ( LPDIRECTPLAY4A iface, DPID idGroup, LPDPID lpidGroupOwner )
4431 ICOM_THIS(IDirectPlay4Impl,iface);
4432 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
4433 return DP_OK;
4436 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4437 ( LPDIRECTPLAY4 iface, DPID idGroup, LPDPID lpidGroupOwner )
4439 ICOM_THIS(IDirectPlay4Impl,iface);
4440 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
4441 return DP_OK;
4444 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4445 ( LPDIRECTPLAY4A iface, DPID idGroup , DPID idGroupOwner )
4447 ICOM_THIS(IDirectPlay4Impl,iface);
4448 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
4449 return DP_OK;
4452 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4453 ( LPDIRECTPLAY4 iface, DPID idGroup , DPID idGroupOwner )
4455 ICOM_THIS(IDirectPlay4Impl,iface);
4456 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
4457 return DP_OK;
4460 static HRESULT WINAPI DP_SendEx
4461 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4462 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4463 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi )
4465 lpPlayerList lpPList;
4466 lpGroupData lpGData;
4467 BOOL bValidDestination = FALSE;
4469 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx,0x%08lx,0x%08lx,%p,%p,%u)"
4470 ": stub\n",
4471 This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority,
4472 dwTimeout, lpContext, lpdwMsgID, bAnsi );
4474 /* FIXME: Add parameter checking */
4475 /* FIXME: First call to this needs to aquire a message id which will be
4476 * used for multiple sends
4479 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4481 /* Verify that the message is being sent from a valid local player. The
4482 * from player may be anonymous DPID_UNKNOWN
4484 if( idFrom != DPID_UNKNOWN )
4486 if( ( lpPList = DP_FindPlayer( This, idFrom ) ) == NULL )
4488 WARN( "INFO: Invalid from player 0x%08lx\n", idFrom );
4489 return DPERR_INVALIDPLAYER;
4493 /* Verify that the message is being sent to a valid player, group or to
4494 * everyone. If it's valid, send it to those players.
4496 if( idTo == DPID_ALLPLAYERS )
4498 bValidDestination = TRUE;
4500 /* See if SP has the ability to multicast. If so, use it */
4501 if( This->dp2->spData.lpCB->SendToGroupEx )
4503 FIXME( "Use group sendex to group 0\n" );
4505 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4507 FIXME( "Use obsolete group send to group 0\n" );
4509 else /* No multicast, multiplicate */
4511 /* Send to all players we know about */
4512 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4516 if( ( !bValidDestination ) &&
4517 ( DP_FindPlayer( This, idTo ) != NULL )
4520 bValidDestination = TRUE;
4522 /* Have the service provider send this message */
4523 /* FIXME: Could optimize for local interface sends */
4524 return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority,
4525 dwTimeout, lpContext, lpdwMsgID );
4528 if( ( !bValidDestination ) &&
4529 ( ( lpGData = DP_FindAnyGroup( This, idTo ) ) != NULL )
4532 bValidDestination = TRUE;
4534 /* See if SP has the ability to multicast. If so, use it */
4535 if( This->dp2->spData.lpCB->SendToGroupEx )
4537 FIXME( "Use group sendex\n" );
4539 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4541 FIXME( "Use obsolete group send to group\n" );
4543 else /* No multicast, multiplicate */
4545 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4548 #if 0
4549 if( bExpectReply )
4551 DWORD dwWaitReturn;
4553 This->dp2->hReplyEvent = CreateEventA( NULL, FALSE, FALSE, NULL );
4555 dwWaitReturn = WaitForSingleObject( hReplyEvent, dwTimeout );
4556 if( dwWaitReturn != WAIT_OBJECT_0 )
4558 ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
4561 #endif
4564 if( !bValidDestination )
4566 return DPERR_INVALIDPLAYER;
4568 else
4570 /* FIXME: Should return what the send returned */
4571 return DP_OK;
4576 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4577 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4578 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4579 LPVOID lpContext, LPDWORD lpdwMsgID )
4581 ICOM_THIS(IDirectPlay2Impl,iface); /* yes downcast to 2 */
4582 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4583 dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE );
4586 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4587 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4588 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4589 LPVOID lpContext, LPDWORD lpdwMsgID )
4591 ICOM_THIS(IDirectPlay2Impl,iface); /* yes downcast to 2 */
4592 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4593 dwPriority, dwTimeout, lpContext, lpdwMsgID, FALSE );
4596 static HRESULT WINAPI DP_SP_SendEx
4597 ( IDirectPlay2Impl* This, DWORD dwFlags,
4598 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4599 LPVOID lpContext, LPDWORD lpdwMsgID )
4601 LPDPMSG lpMElem;
4603 FIXME( ": stub\n" );
4605 /* FIXME: This queuing should only be for async messages */
4607 lpMElem = (LPDPMSG)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4608 sizeof( *lpMElem ) );
4609 lpMElem->msg = (DPMSG_GENERIC*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4610 dwDataSize );
4612 CopyMemory( lpMElem->msg, lpData, dwDataSize );
4614 /* FIXME: Need to queue based on priority */
4615 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
4617 return DP_OK;
4620 static HRESULT WINAPI DP_IF_GetMessageQueue
4621 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4622 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi )
4624 HRESULT hr = DP_OK;
4626 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,%p,%u): semi stub\n",
4627 This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi );
4629 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4630 /* FIXME: What about sends which are not immediate? */
4632 if( This->dp2->spData.lpCB->GetMessageQueue )
4634 DPSP_GETMESSAGEQUEUEDATA data;
4636 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4638 /* FIXME: None of this is documented :( */
4640 data.lpISP = This->dp2->spData.lpISP;
4641 data.dwFlags = dwFlags;
4642 data.idFrom = idFrom;
4643 data.idTo = idTo;
4644 data.lpdwNumMsgs = lpdwNumMsgs;
4645 data.lpdwNumBytes = lpdwNumBytes;
4647 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
4649 else
4651 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4654 return hr;
4657 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4658 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4659 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4661 ICOM_THIS(IDirectPlay4Impl,iface);
4662 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4663 lpdwNumBytes, TRUE );
4666 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4667 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4668 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4670 ICOM_THIS(IDirectPlay4Impl,iface);
4671 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4672 lpdwNumBytes, FALSE );
4675 static HRESULT WINAPI DP_IF_CancelMessage
4676 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
4677 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi )
4679 HRESULT hr = DP_OK;
4681 FIXME( "(%p)->(0x%08lx,0x%08lx,%u): semi stub\n",
4682 This, dwMsgID, dwFlags, bAnsi );
4684 if( This->dp2->spData.lpCB->Cancel )
4686 DPSP_CANCELDATA data;
4688 TRACE( "Calling SP Cancel\n" );
4690 /* FIXME: Undocumented callback */
4692 data.lpISP = This->dp2->spData.lpISP;
4693 data.dwFlags = dwFlags;
4694 data.lprglpvSPMsgID = NULL;
4695 data.cSPMsgID = dwMsgID;
4696 data.dwMinPriority = dwMinPriority;
4697 data.dwMaxPriority = dwMaxPriority;
4699 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
4701 else
4703 FIXME( "SP doesn't implement Cancel\n" );
4706 return hr;
4709 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
4710 ( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags )
4712 ICOM_THIS(IDirectPlay4Impl,iface);
4714 if( dwFlags != 0 )
4716 return DPERR_INVALIDFLAGS;
4719 if( dwMsgID == 0 )
4721 dwFlags |= DPCANCELSEND_ALL;
4724 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE );
4727 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
4728 ( LPDIRECTPLAY4 iface, DWORD dwMsgID, DWORD dwFlags )
4730 ICOM_THIS(IDirectPlay4Impl,iface);
4732 if( dwFlags != 0 )
4734 return DPERR_INVALIDFLAGS;
4737 if( dwMsgID == 0 )
4739 dwFlags |= DPCANCELSEND_ALL;
4742 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, FALSE );
4745 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
4746 ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4747 DWORD dwFlags )
4749 ICOM_THIS(IDirectPlay4Impl,iface);
4751 if( dwFlags != 0 )
4753 return DPERR_INVALIDFLAGS;
4756 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4757 dwMaxPriority, TRUE );
4760 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
4761 ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4762 DWORD dwFlags )
4764 ICOM_THIS(IDirectPlay4Impl,iface);
4766 if( dwFlags != 0 )
4768 return DPERR_INVALIDFLAGS;
4771 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4772 dwMaxPriority, FALSE );
4775 /* Note: Hack so we can reuse the old functions without compiler warnings */
4776 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4777 # define XCAST(fun) (typeof(directPlay2WVT.fun))
4778 #else
4779 # define XCAST(fun) (void*)
4780 #endif
4782 static ICOM_VTABLE(IDirectPlay2) directPlay2WVT =
4784 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4785 XCAST(QueryInterface)DP_QueryInterface,
4786 XCAST(AddRef)DP_AddRef,
4787 XCAST(Release)DP_Release,
4789 DirectPlay2WImpl_AddPlayerToGroup,
4790 DirectPlay2WImpl_Close,
4791 DirectPlay2WImpl_CreateGroup,
4792 DirectPlay2WImpl_CreatePlayer,
4793 DirectPlay2WImpl_DeletePlayerFromGroup,
4794 DirectPlay2WImpl_DestroyGroup,
4795 DirectPlay2WImpl_DestroyPlayer,
4796 DirectPlay2WImpl_EnumGroupPlayers,
4797 DirectPlay2WImpl_EnumGroups,
4798 DirectPlay2WImpl_EnumPlayers,
4799 DirectPlay2WImpl_EnumSessions,
4800 DirectPlay2WImpl_GetCaps,
4801 DirectPlay2WImpl_GetGroupData,
4802 DirectPlay2WImpl_GetGroupName,
4803 DirectPlay2WImpl_GetMessageCount,
4804 DirectPlay2WImpl_GetPlayerAddress,
4805 DirectPlay2WImpl_GetPlayerCaps,
4806 DirectPlay2WImpl_GetPlayerData,
4807 DirectPlay2WImpl_GetPlayerName,
4808 DirectPlay2WImpl_GetSessionDesc,
4809 DirectPlay2WImpl_Initialize,
4810 DirectPlay2WImpl_Open,
4811 DirectPlay2WImpl_Receive,
4812 DirectPlay2WImpl_Send,
4813 DirectPlay2WImpl_SetGroupData,
4814 DirectPlay2WImpl_SetGroupName,
4815 DirectPlay2WImpl_SetPlayerData,
4816 DirectPlay2WImpl_SetPlayerName,
4817 DirectPlay2WImpl_SetSessionDesc
4819 #undef XCAST
4821 /* Note: Hack so we can reuse the old functions without compiler warnings */
4822 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4823 # define XCAST(fun) (typeof(directPlay2AVT.fun))
4824 #else
4825 # define XCAST(fun) (void*)
4826 #endif
4828 static ICOM_VTABLE(IDirectPlay2) directPlay2AVT =
4830 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4831 XCAST(QueryInterface)DP_QueryInterface,
4832 XCAST(AddRef)DP_AddRef,
4833 XCAST(Release)DP_Release,
4835 DirectPlay2AImpl_AddPlayerToGroup,
4836 DirectPlay2AImpl_Close,
4837 DirectPlay2AImpl_CreateGroup,
4838 DirectPlay2AImpl_CreatePlayer,
4839 DirectPlay2AImpl_DeletePlayerFromGroup,
4840 DirectPlay2AImpl_DestroyGroup,
4841 DirectPlay2AImpl_DestroyPlayer,
4842 DirectPlay2AImpl_EnumGroupPlayers,
4843 DirectPlay2AImpl_EnumGroups,
4844 DirectPlay2AImpl_EnumPlayers,
4845 DirectPlay2AImpl_EnumSessions,
4846 DirectPlay2AImpl_GetCaps,
4847 DirectPlay2AImpl_GetGroupData,
4848 DirectPlay2AImpl_GetGroupName,
4849 DirectPlay2AImpl_GetMessageCount,
4850 DirectPlay2AImpl_GetPlayerAddress,
4851 DirectPlay2AImpl_GetPlayerCaps,
4852 DirectPlay2AImpl_GetPlayerData,
4853 DirectPlay2AImpl_GetPlayerName,
4854 DirectPlay2AImpl_GetSessionDesc,
4855 DirectPlay2AImpl_Initialize,
4856 DirectPlay2AImpl_Open,
4857 DirectPlay2AImpl_Receive,
4858 DirectPlay2AImpl_Send,
4859 DirectPlay2AImpl_SetGroupData,
4860 DirectPlay2AImpl_SetGroupName,
4861 DirectPlay2AImpl_SetPlayerData,
4862 DirectPlay2AImpl_SetPlayerName,
4863 DirectPlay2AImpl_SetSessionDesc
4865 #undef XCAST
4868 /* Note: Hack so we can reuse the old functions without compiler warnings */
4869 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4870 # define XCAST(fun) (typeof(directPlay3AVT.fun))
4871 #else
4872 # define XCAST(fun) (void*)
4873 #endif
4875 static ICOM_VTABLE(IDirectPlay3) directPlay3AVT =
4877 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4878 XCAST(QueryInterface)DP_QueryInterface,
4879 XCAST(AddRef)DP_AddRef,
4880 XCAST(Release)DP_Release,
4882 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
4883 XCAST(Close)DirectPlay2AImpl_Close,
4884 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
4885 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
4886 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
4887 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
4888 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
4889 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
4890 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
4891 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
4892 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
4893 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
4894 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
4895 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
4896 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
4897 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
4898 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
4899 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
4900 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
4901 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
4902 XCAST(Initialize)DirectPlay2AImpl_Initialize,
4903 XCAST(Open)DirectPlay2AImpl_Open,
4904 XCAST(Receive)DirectPlay2AImpl_Receive,
4905 XCAST(Send)DirectPlay2AImpl_Send,
4906 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
4907 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
4908 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
4909 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
4910 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
4912 DirectPlay3AImpl_AddGroupToGroup,
4913 DirectPlay3AImpl_CreateGroupInGroup,
4914 DirectPlay3AImpl_DeleteGroupFromGroup,
4915 DirectPlay3AImpl_EnumConnections,
4916 DirectPlay3AImpl_EnumGroupsInGroup,
4917 DirectPlay3AImpl_GetGroupConnectionSettings,
4918 DirectPlay3AImpl_InitializeConnection,
4919 DirectPlay3AImpl_SecureOpen,
4920 DirectPlay3AImpl_SendChatMessage,
4921 DirectPlay3AImpl_SetGroupConnectionSettings,
4922 DirectPlay3AImpl_StartSession,
4923 DirectPlay3AImpl_GetGroupFlags,
4924 DirectPlay3AImpl_GetGroupParent,
4925 DirectPlay3AImpl_GetPlayerAccount,
4926 DirectPlay3AImpl_GetPlayerFlags
4928 #undef XCAST
4930 /* Note: Hack so we can reuse the old functions without compiler warnings */
4931 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4932 # define XCAST(fun) (typeof(directPlay3WVT.fun))
4933 #else
4934 # define XCAST(fun) (void*)
4935 #endif
4936 static ICOM_VTABLE(IDirectPlay3) directPlay3WVT =
4938 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4939 XCAST(QueryInterface)DP_QueryInterface,
4940 XCAST(AddRef)DP_AddRef,
4941 XCAST(Release)DP_Release,
4943 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
4944 XCAST(Close)DirectPlay2WImpl_Close,
4945 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
4946 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
4947 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
4948 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
4949 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
4950 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
4951 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
4952 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
4953 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
4954 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
4955 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
4956 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
4957 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
4958 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
4959 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
4960 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
4961 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
4962 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
4963 XCAST(Initialize)DirectPlay2WImpl_Initialize,
4964 XCAST(Open)DirectPlay2WImpl_Open,
4965 XCAST(Receive)DirectPlay2WImpl_Receive,
4966 XCAST(Send)DirectPlay2WImpl_Send,
4967 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
4968 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
4969 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
4970 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
4971 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
4973 DirectPlay3WImpl_AddGroupToGroup,
4974 DirectPlay3WImpl_CreateGroupInGroup,
4975 DirectPlay3WImpl_DeleteGroupFromGroup,
4976 DirectPlay3WImpl_EnumConnections,
4977 DirectPlay3WImpl_EnumGroupsInGroup,
4978 DirectPlay3WImpl_GetGroupConnectionSettings,
4979 DirectPlay3WImpl_InitializeConnection,
4980 DirectPlay3WImpl_SecureOpen,
4981 DirectPlay3WImpl_SendChatMessage,
4982 DirectPlay3WImpl_SetGroupConnectionSettings,
4983 DirectPlay3WImpl_StartSession,
4984 DirectPlay3WImpl_GetGroupFlags,
4985 DirectPlay3WImpl_GetGroupParent,
4986 DirectPlay3WImpl_GetPlayerAccount,
4987 DirectPlay3WImpl_GetPlayerFlags
4989 #undef XCAST
4991 /* Note: Hack so we can reuse the old functions without compiler warnings */
4992 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4993 # define XCAST(fun) (typeof(directPlay4WVT.fun))
4994 #else
4995 # define XCAST(fun) (void*)
4996 #endif
4997 static ICOM_VTABLE(IDirectPlay4) directPlay4WVT =
4999 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5000 XCAST(QueryInterface)DP_QueryInterface,
5001 XCAST(AddRef)DP_AddRef,
5002 XCAST(Release)DP_Release,
5004 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
5005 XCAST(Close)DirectPlay2WImpl_Close,
5006 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
5007 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
5008 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
5009 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
5010 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5011 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5012 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5013 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5014 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5015 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5016 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5017 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5018 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5019 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5020 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5021 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5022 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5023 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5024 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5025 XCAST(Open)DirectPlay2WImpl_Open,
5026 XCAST(Receive)DirectPlay2WImpl_Receive,
5027 XCAST(Send)DirectPlay2WImpl_Send,
5028 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5029 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5030 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5031 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5032 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5034 XCAST(AddGroupToGroup)DirectPlay3WImpl_AddGroupToGroup,
5035 XCAST(CreateGroupInGroup)DirectPlay3WImpl_CreateGroupInGroup,
5036 XCAST(DeleteGroupFromGroup)DirectPlay3WImpl_DeleteGroupFromGroup,
5037 XCAST(EnumConnections)DirectPlay3WImpl_EnumConnections,
5038 XCAST(EnumGroupsInGroup)DirectPlay3WImpl_EnumGroupsInGroup,
5039 XCAST(GetGroupConnectionSettings)DirectPlay3WImpl_GetGroupConnectionSettings,
5040 XCAST(InitializeConnection)DirectPlay3WImpl_InitializeConnection,
5041 XCAST(SecureOpen)DirectPlay3WImpl_SecureOpen,
5042 XCAST(SendChatMessage)DirectPlay3WImpl_SendChatMessage,
5043 XCAST(SetGroupConnectionSettings)DirectPlay3WImpl_SetGroupConnectionSettings,
5044 XCAST(StartSession)DirectPlay3WImpl_StartSession,
5045 XCAST(GetGroupFlags)DirectPlay3WImpl_GetGroupFlags,
5046 XCAST(GetGroupParent)DirectPlay3WImpl_GetGroupParent,
5047 XCAST(GetPlayerAccount)DirectPlay3WImpl_GetPlayerAccount,
5048 XCAST(GetPlayerFlags)DirectPlay3WImpl_GetPlayerFlags,
5050 DirectPlay4WImpl_GetGroupOwner,
5051 DirectPlay4WImpl_SetGroupOwner,
5052 DirectPlay4WImpl_SendEx,
5053 DirectPlay4WImpl_GetMessageQueue,
5054 DirectPlay4WImpl_CancelMessage,
5055 DirectPlay4WImpl_CancelPriority
5057 #undef XCAST
5060 /* Note: Hack so we can reuse the old functions without compiler warnings */
5061 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5062 # define XCAST(fun) (typeof(directPlay4AVT.fun))
5063 #else
5064 # define XCAST(fun) (void*)
5065 #endif
5066 static ICOM_VTABLE(IDirectPlay4) directPlay4AVT =
5068 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5069 XCAST(QueryInterface)DP_QueryInterface,
5070 XCAST(AddRef)DP_AddRef,
5071 XCAST(Release)DP_Release,
5073 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
5074 XCAST(Close)DirectPlay2AImpl_Close,
5075 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
5076 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
5077 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
5078 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
5079 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
5080 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
5081 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
5082 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
5083 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
5084 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
5085 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
5086 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
5087 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5088 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5089 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5090 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5091 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5092 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5093 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5094 XCAST(Open)DirectPlay2AImpl_Open,
5095 XCAST(Receive)DirectPlay2AImpl_Receive,
5096 XCAST(Send)DirectPlay2AImpl_Send,
5097 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5098 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5099 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5100 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5101 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5103 XCAST(AddGroupToGroup)DirectPlay3AImpl_AddGroupToGroup,
5104 XCAST(CreateGroupInGroup)DirectPlay3AImpl_CreateGroupInGroup,
5105 XCAST(DeleteGroupFromGroup)DirectPlay3AImpl_DeleteGroupFromGroup,
5106 XCAST(EnumConnections)DirectPlay3AImpl_EnumConnections,
5107 XCAST(EnumGroupsInGroup)DirectPlay3AImpl_EnumGroupsInGroup,
5108 XCAST(GetGroupConnectionSettings)DirectPlay3AImpl_GetGroupConnectionSettings,
5109 XCAST(InitializeConnection)DirectPlay3AImpl_InitializeConnection,
5110 XCAST(SecureOpen)DirectPlay3AImpl_SecureOpen,
5111 XCAST(SendChatMessage)DirectPlay3AImpl_SendChatMessage,
5112 XCAST(SetGroupConnectionSettings)DirectPlay3AImpl_SetGroupConnectionSettings,
5113 XCAST(StartSession)DirectPlay3AImpl_StartSession,
5114 XCAST(GetGroupFlags)DirectPlay3AImpl_GetGroupFlags,
5115 XCAST(GetGroupParent)DirectPlay3AImpl_GetGroupParent,
5116 XCAST(GetPlayerAccount)DirectPlay3AImpl_GetPlayerAccount,
5117 XCAST(GetPlayerFlags)DirectPlay3AImpl_GetPlayerFlags,
5119 DirectPlay4AImpl_GetGroupOwner,
5120 DirectPlay4AImpl_SetGroupOwner,
5121 DirectPlay4AImpl_SendEx,
5122 DirectPlay4AImpl_GetMessageQueue,
5123 DirectPlay4AImpl_CancelMessage,
5124 DirectPlay4AImpl_CancelPriority
5126 #undef XCAST
5128 extern
5129 HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP,
5130 DPID idPlayer,
5131 LPVOID* lplpData )
5133 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5135 if( lpPlayer == NULL )
5137 return DPERR_INVALIDPLAYER;
5140 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
5142 return DP_OK;
5145 extern
5146 HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP,
5147 DPID idPlayer,
5148 LPVOID lpData )
5150 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5152 if( lpPlayer == NULL )
5154 return DPERR_INVALIDPLAYER;
5157 lpPlayer->lpPData->lpSPPlayerData = lpData;
5159 return DP_OK;
5162 /***************************************************************************
5163 * DirectPlayEnumerate [DPLAYX.9]
5164 * DirectPlayEnumerateA [DPLAYX.2]
5166 * The pointer to the structure lpContext will be filled with the
5167 * appropriate data for each service offered by the OS. These services are
5168 * not necessarily available on this particular machine but are defined
5169 * as simple service providers under the "Service Providers" registry key.
5170 * This structure is then passed to lpEnumCallback for each of the different
5171 * services.
5173 * This API is useful only for applications written using DirectX3 or
5174 * worse. It is superceeded by IDirectPlay3::EnumConnections which also
5175 * gives information on the actual connections.
5177 * defn of a service provider:
5178 * A dynamic-link library used by DirectPlay to communicate over a network.
5179 * The service provider contains all the network-specific code required
5180 * to send and receive messages. Online services and network operators can
5181 * supply service providers to use specialized hardware, protocols, communications
5182 * media, and network resources.
5184 * TODO: Allocate string buffer space from the heap (length from reg)
5185 * Pass real device driver numbers...
5186 * Get the GUID properly...
5188 HRESULT WINAPI DirectPlayEnumerateA( LPDPENUMDPCALLBACKA lpEnumCallback,
5189 LPVOID lpContext )
5192 HKEY hkResult;
5193 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
5194 DWORD dwIndex;
5195 DWORD sizeOfSubKeyName=50;
5196 char subKeyName[51];
5197 FILETIME filetime;
5199 TRACE(": lpEnumCallback=%p lpContext=%p\n", lpEnumCallback, lpContext );
5201 if( !lpEnumCallback || !*lpEnumCallback )
5203 return DPERR_INVALIDPARAMS;
5206 /* Need to loop over the service providers in the registry */
5207 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
5208 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
5210 /* Hmmm. Does this mean that there are no service providers? */
5211 ERR(": no service providers?\n");
5212 return DP_OK;
5215 /* Traverse all the service providers we have available */
5216 for( dwIndex=0;
5217 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
5218 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
5219 ++dwIndex, sizeOfSubKeyName=50 )
5221 LPSTR majVerDataSubKey = "dwReserved1";
5222 LPSTR minVerDataSubKey = "dwReserved2";
5223 LPSTR guidDataSubKey = "Guid";
5224 HKEY hkServiceProvider;
5225 GUID serviceProviderGUID;
5226 DWORD returnTypeGUID, returnTypeReserved, sizeOfReturnBuffer = 50;
5227 char returnBuffer[51];
5228 WCHAR buff[51];
5229 DWORD majVersionNum , minVersionNum = 0;
5231 TRACE(" this time through: %s\n", subKeyName );
5233 /* Get a handle for this particular service provider */
5234 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
5235 &hkServiceProvider ) != ERROR_SUCCESS )
5237 ERR(": what the heck is going on?\n" );
5238 continue;
5241 /* Get the GUID, Device major number and device minor number
5242 * from the registry.
5244 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
5245 NULL, &returnTypeGUID, returnBuffer,
5246 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5248 ERR(": missing GUID registry data members\n" );
5249 continue;
5252 /* FIXME: Check return types to ensure we're interpreting data right */
5253 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
5254 CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
5256 /* FIXME: Need to know which of dwReserved1 and dwReserved2 are maj and min */
5258 sizeOfReturnBuffer = 50;
5259 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
5260 NULL, &returnTypeReserved, returnBuffer,
5261 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5263 ERR(": missing dwReserved1 registry data members\n") ;
5264 continue;
5266 memcpy( &majVersionNum, returnBuffer, sizeof(majVersionNum) );
5268 sizeOfReturnBuffer = 50;
5269 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
5270 NULL, &returnTypeReserved, returnBuffer,
5271 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5273 ERR(": missing dwReserved2 registry data members\n") ;
5274 continue;
5276 memcpy( &minVersionNum, returnBuffer, sizeof(minVersionNum) );
5279 /* The enumeration will return FALSE if we are not to continue */
5280 if( !lpEnumCallback( &serviceProviderGUID , subKeyName,
5281 majVersionNum, minVersionNum, lpContext ) )
5283 WARN("lpEnumCallback returning FALSE\n" );
5284 break;
5288 return DP_OK;
5292 /***************************************************************************
5293 * DirectPlayEnumerateW [DPLAYX.3]
5296 HRESULT WINAPI DirectPlayEnumerateW( LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5299 FIXME(":stub\n");
5301 return DPERR_OUTOFMEMORY;
5305 typedef struct tagCreateEnum
5307 LPVOID lpConn;
5308 LPCGUID lpGuid;
5309 } CreateEnumData, *lpCreateEnumData;
5311 /* Find and copy the matching connection for the SP guid */
5312 static BOOL CALLBACK cbDPCreateEnumConnections(
5313 LPCGUID lpguidSP,
5314 LPVOID lpConnection,
5315 DWORD dwConnectionSize,
5316 LPCDPNAME lpName,
5317 DWORD dwFlags,
5318 LPVOID lpContext)
5320 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5322 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5324 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5326 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5327 dwConnectionSize );
5328 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5330 /* Found the record that we were looking for */
5331 return FALSE;
5334 /* Haven't found what were looking for yet */
5335 return TRUE;
5339 /***************************************************************************
5340 * DirectPlayCreate [DPLAYX.1]
5343 HRESULT WINAPI DirectPlayCreate
5344 ( LPGUID lpGUID, LPDIRECTPLAY2 *lplpDP, IUnknown *pUnk)
5346 HRESULT hr;
5347 LPDIRECTPLAY3A lpDP3A;
5348 CreateEnumData cbData;
5350 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5352 if( pUnk != NULL )
5354 return CLASS_E_NOAGGREGATION;
5357 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5358 give them an IDirectPlay2A object and hope that doesn't cause problems */
5359 if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
5361 return DPERR_UNAVAILABLE;
5364 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
5366 /* The GUID_NULL means don't bind a service provider. Just return the
5367 interface as is */
5368 return DP_OK;
5371 /* Bind the desired service provider since lpGUID is non NULL */
5372 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
5374 /* We're going to use a DP3 interface */
5375 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
5376 (LPVOID*)&lpDP3A );
5377 if( FAILED(hr) )
5379 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
5380 return hr;
5383 cbData.lpConn = NULL;
5384 cbData.lpGuid = lpGUID;
5386 /* We were given a service provider, find info about it... */
5387 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
5388 &cbData, DPCONNECTION_DIRECTPLAY );
5389 if( ( FAILED(hr) ) ||
5390 ( cbData.lpConn == NULL )
5393 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
5394 IDirectPlayX_Release( lpDP3A );
5395 return DPERR_UNAVAILABLE;
5398 /* Initialize the service provider */
5399 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
5400 if( FAILED(hr) )
5402 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
5403 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5404 IDirectPlayX_Release( lpDP3A );
5405 return hr;
5408 /* Release our version of the interface now that we're done with it */
5409 IDirectPlayX_Release( lpDP3A );
5410 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5412 return DP_OK;