Spelling stuff.
[wine/dcerpc.git] / dlls / dplayx / dplay.c
blob5410f520a5a9c81e1ff25e229ad852d73d6f13a0
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 )
4081 lpSpData->dwReserved1 = GET_DWORD( returnBuffer );
4084 sizeOfReturnBuffer = 255;
4086 /* Get dwReserved2 */
4087 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4088 NULL, &returnType, returnBuffer,
4089 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4091 ERR(": missing dwReserved1 registry data members\n") ;
4092 continue;
4095 if( i == 0 )
4097 lpSpData->dwReserved2 = GET_DWORD( returnBuffer );
4100 sizeOfReturnBuffer = 255;
4102 /* Get the path for this service provider */
4103 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
4104 NULL, NULL, returnBuffer,
4105 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
4107 ERR(": missing PATH registry data members: 0x%08lx\n", dwTemp );
4108 continue;
4111 TRACE( "Loading %s\n", returnBuffer );
4112 return LoadLibraryA( returnBuffer );
4116 return 0;
4119 static
4120 HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider )
4122 HRESULT hr;
4123 LPDPSP_SPINIT SPInit;
4125 /* Initialize the service provider by calling SPInit */
4126 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4128 if( SPInit == NULL )
4130 ERR( "Service provider doesn't provide SPInit interface?\n" );
4131 FreeLibrary( hServiceProvider );
4132 return DPERR_UNAVAILABLE;
4135 TRACE( "Calling SPInit (DP SP entry point)\n" );
4137 hr = (*SPInit)( &This->dp2->spData );
4139 if( FAILED(hr) )
4141 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4142 FreeLibrary( hServiceProvider );
4143 return hr;
4146 /* FIXME: Need to verify the sanity of the returned callback table
4147 * using IsBadCodePtr */
4148 This->dp2->bSPInitialized = TRUE;
4150 /* This interface is now initialized as a DP object */
4151 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
4153 /* Store the handle of the module so that we can unload it later */
4154 This->dp2->hServiceProvider = hServiceProvider;
4156 return hr;
4159 static
4160 HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hLobbyProvider )
4162 HRESULT hr;
4163 LPSP_INIT DPLSPInit;
4165 /* Initialize the service provider by calling SPInit */
4166 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
4168 if( DPLSPInit == NULL )
4170 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4171 FreeLibrary( hLobbyProvider );
4172 return DPERR_UNAVAILABLE;
4175 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4177 hr = (*DPLSPInit)( &This->dp2->dplspData );
4179 if( FAILED(hr) )
4181 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4182 FreeLibrary( hLobbyProvider );
4183 return hr;
4186 /* FIXME: Need to verify the sanity of the returned callback table
4187 * using IsBadCodePtr */
4189 This->dp2->bDPLSPInitialized = TRUE;
4191 /* This interface is now initialized as a lobby object */
4192 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
4194 /* Store the handle of the module so that we can unload it later */
4195 This->dp2->hDPLobbyProvider = hLobbyProvider;
4197 return hr;
4200 static HRESULT WINAPI DP_IF_InitializeConnection
4201 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi )
4203 HMODULE hServiceProvider;
4204 HRESULT hr;
4205 GUID guidSP;
4206 const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
4207 BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4209 TRACE("(%p)->(%p,0x%08lx,%u)\n", This, lpConnection, dwFlags, bAnsi );
4211 if( dwFlags != 0 )
4213 return DPERR_INVALIDFLAGS;
4216 /* Find out what the requested SP is and how large this buffer is */
4217 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
4218 dwAddrSize, &guidSP );
4220 if( FAILED(hr) )
4222 ERR( "Invalid compound address?\n" );
4223 return DPERR_UNAVAILABLE;
4226 /* Load the service provider */
4227 hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp );
4229 if( hServiceProvider == 0 )
4231 ERR( "Unable to load service provider\n" );
4232 return DPERR_UNAVAILABLE;
4235 if( bIsDpSp )
4237 /* Fill in what we can of the Service Provider required information.
4238 * The rest was be done in DP_LoadSP
4240 This->dp2->spData.lpAddress = lpConnection;
4241 This->dp2->spData.dwAddressSize = dwAddrSize;
4242 This->dp2->spData.lpGuid = &guidSP;
4244 hr = DP_InitializeDPSP( This, hServiceProvider );
4246 else
4248 This->dp2->dplspData.lpAddress = lpConnection;
4250 hr = DP_InitializeDPLSP( This, hServiceProvider );
4253 if( FAILED(hr) )
4255 return hr;
4258 return DP_OK;
4261 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4262 ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
4264 ICOM_THIS(IDirectPlay3Impl,iface);
4266 /* This may not be externally invoked once either an SP or LP is initialized */
4267 if( This->dp2->connectionInitialized != NO_PROVIDER )
4269 return DPERR_ALREADYINITIALIZED;
4272 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE );
4275 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4276 ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
4278 ICOM_THIS(IDirectPlay3Impl,iface);
4280 /* This may not be externally invoked once either an SP or LP is initialized */
4281 if( This->dp2->connectionInitialized != NO_PROVIDER )
4283 return DPERR_ALREADYINITIALIZED;
4286 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE );
4289 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4290 ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4291 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4293 ICOM_THIS(IDirectPlay2Impl,iface); /* Yes a dp 2 interface */
4294 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4297 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4298 ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4299 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4301 ICOM_THIS(IDirectPlay2Impl,iface); /* Yes a dp 2 interface */
4302 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4305 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4306 ( LPDIRECTPLAY3A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4308 ICOM_THIS(IDirectPlay3Impl,iface);
4309 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4310 return DP_OK;
4313 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4314 ( LPDIRECTPLAY3 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4316 ICOM_THIS(IDirectPlay3Impl,iface);
4317 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4318 return DP_OK;
4321 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4322 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4324 ICOM_THIS(IDirectPlay3Impl,iface);
4325 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4326 return DP_OK;
4329 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4330 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4332 ICOM_THIS(IDirectPlay3Impl,iface);
4333 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4334 return DP_OK;
4337 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4338 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup )
4340 ICOM_THIS(IDirectPlay3Impl,iface);
4341 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
4342 return DP_OK;
4345 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4346 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup )
4348 ICOM_THIS(IDirectPlay3Impl,iface);
4349 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
4350 return DP_OK;
4353 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4354 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDWORD lpdwFlags )
4356 ICOM_THIS(IDirectPlay3Impl,iface);
4357 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
4358 return DP_OK;
4361 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4362 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDWORD lpdwFlags )
4364 ICOM_THIS(IDirectPlay3Impl,iface);
4365 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
4366 return DP_OK;
4369 static HRESULT WINAPI DP_IF_GetGroupParent
4370 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
4371 BOOL bAnsi )
4373 lpGroupData lpGData;
4375 TRACE("(%p)->(0x%08lx,%p,%u)\n", This, idGroup, lpidGroup, bAnsi );
4377 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4379 return DPERR_INVALIDGROUP;
4382 *lpidGroup = lpGData->dpid;
4384 return DP_OK;
4387 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4388 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
4390 ICOM_THIS(IDirectPlay3Impl,iface);
4391 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE );
4393 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4394 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
4396 ICOM_THIS(IDirectPlay3Impl,iface);
4397 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE );
4400 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4401 ( LPDIRECTPLAY3A iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4403 ICOM_THIS(IDirectPlay3Impl,iface);
4404 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4405 return DP_OK;
4408 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4409 ( LPDIRECTPLAY3 iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4411 ICOM_THIS(IDirectPlay3Impl,iface);
4412 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4413 return DP_OK;
4416 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4417 ( LPDIRECTPLAY3A iface, DPID idPlayer, LPDWORD lpdwFlags )
4419 ICOM_THIS(IDirectPlay3Impl,iface);
4420 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
4421 return DP_OK;
4424 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4425 ( LPDIRECTPLAY3 iface, DPID idPlayer, LPDWORD lpdwFlags )
4427 ICOM_THIS(IDirectPlay3Impl,iface);
4428 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
4429 return DP_OK;
4432 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4433 ( LPDIRECTPLAY4A iface, DPID idGroup, LPDPID lpidGroupOwner )
4435 ICOM_THIS(IDirectPlay4Impl,iface);
4436 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
4437 return DP_OK;
4440 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4441 ( LPDIRECTPLAY4 iface, DPID idGroup, LPDPID lpidGroupOwner )
4443 ICOM_THIS(IDirectPlay4Impl,iface);
4444 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
4445 return DP_OK;
4448 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4449 ( LPDIRECTPLAY4A iface, DPID idGroup , DPID idGroupOwner )
4451 ICOM_THIS(IDirectPlay4Impl,iface);
4452 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
4453 return DP_OK;
4456 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4457 ( LPDIRECTPLAY4 iface, DPID idGroup , DPID idGroupOwner )
4459 ICOM_THIS(IDirectPlay4Impl,iface);
4460 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
4461 return DP_OK;
4464 static HRESULT WINAPI DP_SendEx
4465 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4466 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4467 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi )
4469 lpPlayerList lpPList;
4470 lpGroupData lpGData;
4471 BOOL bValidDestination = FALSE;
4473 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx,0x%08lx,0x%08lx,%p,%p,%u)"
4474 ": stub\n",
4475 This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority,
4476 dwTimeout, lpContext, lpdwMsgID, bAnsi );
4478 /* FIXME: Add parameter checking */
4479 /* FIXME: First call to this needs to aquire a message id which will be
4480 * used for multiple sends
4483 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4485 /* Verify that the message is being sent from a valid local player. The
4486 * from player may be anonymous DPID_UNKNOWN
4488 if( idFrom != DPID_UNKNOWN )
4490 if( ( lpPList = DP_FindPlayer( This, idFrom ) ) == NULL )
4492 WARN( "INFO: Invalid from player 0x%08lx\n", idFrom );
4493 return DPERR_INVALIDPLAYER;
4497 /* Verify that the message is being sent to a valid player, group or to
4498 * everyone. If it's valid, send it to those players.
4500 if( idTo == DPID_ALLPLAYERS )
4502 bValidDestination = TRUE;
4504 /* See if SP has the ability to multicast. If so, use it */
4505 if( This->dp2->spData.lpCB->SendToGroupEx )
4507 FIXME( "Use group sendex to group 0\n" );
4509 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4511 FIXME( "Use obsolete group send to group 0\n" );
4513 else /* No multicast, multiplicate */
4515 /* Send to all players we know about */
4516 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4520 if( ( !bValidDestination ) &&
4521 ( DP_FindPlayer( This, idTo ) != NULL )
4524 bValidDestination = TRUE;
4526 /* Have the service provider send this message */
4527 /* FIXME: Could optimize for local interface sends */
4528 return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority,
4529 dwTimeout, lpContext, lpdwMsgID );
4532 if( ( !bValidDestination ) &&
4533 ( ( lpGData = DP_FindAnyGroup( This, idTo ) ) != NULL )
4536 bValidDestination = TRUE;
4538 /* See if SP has the ability to multicast. If so, use it */
4539 if( This->dp2->spData.lpCB->SendToGroupEx )
4541 FIXME( "Use group sendex\n" );
4543 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4545 FIXME( "Use obsolete group send to group\n" );
4547 else /* No multicast, multiplicate */
4549 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4552 #if 0
4553 if( bExpectReply )
4555 DWORD dwWaitReturn;
4557 This->dp2->hReplyEvent = CreateEventA( NULL, FALSE, FALSE, NULL );
4559 dwWaitReturn = WaitForSingleObject( hReplyEvent, dwTimeout );
4560 if( dwWaitReturn != WAIT_OBJECT_0 )
4562 ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
4565 #endif
4568 if( !bValidDestination )
4570 return DPERR_INVALIDPLAYER;
4572 else
4574 /* FIXME: Should return what the send returned */
4575 return DP_OK;
4580 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4581 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4582 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4583 LPVOID lpContext, LPDWORD lpdwMsgID )
4585 ICOM_THIS(IDirectPlay2Impl,iface); /* yes downcast to 2 */
4586 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4587 dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE );
4590 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4591 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4592 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4593 LPVOID lpContext, LPDWORD lpdwMsgID )
4595 ICOM_THIS(IDirectPlay2Impl,iface); /* yes downcast to 2 */
4596 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4597 dwPriority, dwTimeout, lpContext, lpdwMsgID, FALSE );
4600 static HRESULT WINAPI DP_SP_SendEx
4601 ( IDirectPlay2Impl* This, DWORD dwFlags,
4602 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4603 LPVOID lpContext, LPDWORD lpdwMsgID )
4605 LPDPMSG lpMElem;
4607 FIXME( ": stub\n" );
4609 /* FIXME: This queuing should only be for async messages */
4611 lpMElem = (LPDPMSG)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4612 sizeof( *lpMElem ) );
4613 lpMElem->msg = (DPMSG_GENERIC*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4614 dwDataSize );
4616 CopyMemory( lpMElem->msg, lpData, dwDataSize );
4618 /* FIXME: Need to queue based on priority */
4619 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
4621 return DP_OK;
4624 static HRESULT WINAPI DP_IF_GetMessageQueue
4625 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4626 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi )
4628 HRESULT hr = DP_OK;
4630 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,%p,%u): semi stub\n",
4631 This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi );
4633 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4634 /* FIXME: What about sends which are not immediate? */
4636 if( This->dp2->spData.lpCB->GetMessageQueue )
4638 DPSP_GETMESSAGEQUEUEDATA data;
4640 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4642 /* FIXME: None of this is documented :( */
4644 data.lpISP = This->dp2->spData.lpISP;
4645 data.dwFlags = dwFlags;
4646 data.idFrom = idFrom;
4647 data.idTo = idTo;
4648 data.lpdwNumMsgs = lpdwNumMsgs;
4649 data.lpdwNumBytes = lpdwNumBytes;
4651 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
4653 else
4655 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4658 return hr;
4661 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4662 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4663 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4665 ICOM_THIS(IDirectPlay4Impl,iface);
4666 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4667 lpdwNumBytes, TRUE );
4670 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4671 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4672 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4674 ICOM_THIS(IDirectPlay4Impl,iface);
4675 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4676 lpdwNumBytes, FALSE );
4679 static HRESULT WINAPI DP_IF_CancelMessage
4680 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
4681 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi )
4683 HRESULT hr = DP_OK;
4685 FIXME( "(%p)->(0x%08lx,0x%08lx,%u): semi stub\n",
4686 This, dwMsgID, dwFlags, bAnsi );
4688 if( This->dp2->spData.lpCB->Cancel )
4690 DPSP_CANCELDATA data;
4692 TRACE( "Calling SP Cancel\n" );
4694 /* FIXME: Undocumented callback */
4696 data.lpISP = This->dp2->spData.lpISP;
4697 data.dwFlags = dwFlags;
4698 data.lprglpvSPMsgID = NULL;
4699 data.cSPMsgID = dwMsgID;
4700 data.dwMinPriority = dwMinPriority;
4701 data.dwMaxPriority = dwMaxPriority;
4703 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
4705 else
4707 FIXME( "SP doesn't implement Cancel\n" );
4710 return hr;
4713 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
4714 ( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags )
4716 ICOM_THIS(IDirectPlay4Impl,iface);
4718 if( dwFlags != 0 )
4720 return DPERR_INVALIDFLAGS;
4723 if( dwMsgID == 0 )
4725 dwFlags |= DPCANCELSEND_ALL;
4728 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE );
4731 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
4732 ( LPDIRECTPLAY4 iface, DWORD dwMsgID, DWORD dwFlags )
4734 ICOM_THIS(IDirectPlay4Impl,iface);
4736 if( dwFlags != 0 )
4738 return DPERR_INVALIDFLAGS;
4741 if( dwMsgID == 0 )
4743 dwFlags |= DPCANCELSEND_ALL;
4746 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, FALSE );
4749 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
4750 ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4751 DWORD dwFlags )
4753 ICOM_THIS(IDirectPlay4Impl,iface);
4755 if( dwFlags != 0 )
4757 return DPERR_INVALIDFLAGS;
4760 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4761 dwMaxPriority, TRUE );
4764 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
4765 ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4766 DWORD dwFlags )
4768 ICOM_THIS(IDirectPlay4Impl,iface);
4770 if( dwFlags != 0 )
4772 return DPERR_INVALIDFLAGS;
4775 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4776 dwMaxPriority, FALSE );
4779 /* Note: Hack so we can reuse the old functions without compiler warnings */
4780 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4781 # define XCAST(fun) (typeof(directPlay2WVT.fun))
4782 #else
4783 # define XCAST(fun) (void*)
4784 #endif
4786 static ICOM_VTABLE(IDirectPlay2) directPlay2WVT =
4788 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4789 XCAST(QueryInterface)DP_QueryInterface,
4790 XCAST(AddRef)DP_AddRef,
4791 XCAST(Release)DP_Release,
4793 DirectPlay2WImpl_AddPlayerToGroup,
4794 DirectPlay2WImpl_Close,
4795 DirectPlay2WImpl_CreateGroup,
4796 DirectPlay2WImpl_CreatePlayer,
4797 DirectPlay2WImpl_DeletePlayerFromGroup,
4798 DirectPlay2WImpl_DestroyGroup,
4799 DirectPlay2WImpl_DestroyPlayer,
4800 DirectPlay2WImpl_EnumGroupPlayers,
4801 DirectPlay2WImpl_EnumGroups,
4802 DirectPlay2WImpl_EnumPlayers,
4803 DirectPlay2WImpl_EnumSessions,
4804 DirectPlay2WImpl_GetCaps,
4805 DirectPlay2WImpl_GetGroupData,
4806 DirectPlay2WImpl_GetGroupName,
4807 DirectPlay2WImpl_GetMessageCount,
4808 DirectPlay2WImpl_GetPlayerAddress,
4809 DirectPlay2WImpl_GetPlayerCaps,
4810 DirectPlay2WImpl_GetPlayerData,
4811 DirectPlay2WImpl_GetPlayerName,
4812 DirectPlay2WImpl_GetSessionDesc,
4813 DirectPlay2WImpl_Initialize,
4814 DirectPlay2WImpl_Open,
4815 DirectPlay2WImpl_Receive,
4816 DirectPlay2WImpl_Send,
4817 DirectPlay2WImpl_SetGroupData,
4818 DirectPlay2WImpl_SetGroupName,
4819 DirectPlay2WImpl_SetPlayerData,
4820 DirectPlay2WImpl_SetPlayerName,
4821 DirectPlay2WImpl_SetSessionDesc
4823 #undef XCAST
4825 /* Note: Hack so we can reuse the old functions without compiler warnings */
4826 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4827 # define XCAST(fun) (typeof(directPlay2AVT.fun))
4828 #else
4829 # define XCAST(fun) (void*)
4830 #endif
4832 static ICOM_VTABLE(IDirectPlay2) directPlay2AVT =
4834 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4835 XCAST(QueryInterface)DP_QueryInterface,
4836 XCAST(AddRef)DP_AddRef,
4837 XCAST(Release)DP_Release,
4839 DirectPlay2AImpl_AddPlayerToGroup,
4840 DirectPlay2AImpl_Close,
4841 DirectPlay2AImpl_CreateGroup,
4842 DirectPlay2AImpl_CreatePlayer,
4843 DirectPlay2AImpl_DeletePlayerFromGroup,
4844 DirectPlay2AImpl_DestroyGroup,
4845 DirectPlay2AImpl_DestroyPlayer,
4846 DirectPlay2AImpl_EnumGroupPlayers,
4847 DirectPlay2AImpl_EnumGroups,
4848 DirectPlay2AImpl_EnumPlayers,
4849 DirectPlay2AImpl_EnumSessions,
4850 DirectPlay2AImpl_GetCaps,
4851 DirectPlay2AImpl_GetGroupData,
4852 DirectPlay2AImpl_GetGroupName,
4853 DirectPlay2AImpl_GetMessageCount,
4854 DirectPlay2AImpl_GetPlayerAddress,
4855 DirectPlay2AImpl_GetPlayerCaps,
4856 DirectPlay2AImpl_GetPlayerData,
4857 DirectPlay2AImpl_GetPlayerName,
4858 DirectPlay2AImpl_GetSessionDesc,
4859 DirectPlay2AImpl_Initialize,
4860 DirectPlay2AImpl_Open,
4861 DirectPlay2AImpl_Receive,
4862 DirectPlay2AImpl_Send,
4863 DirectPlay2AImpl_SetGroupData,
4864 DirectPlay2AImpl_SetGroupName,
4865 DirectPlay2AImpl_SetPlayerData,
4866 DirectPlay2AImpl_SetPlayerName,
4867 DirectPlay2AImpl_SetSessionDesc
4869 #undef XCAST
4872 /* Note: Hack so we can reuse the old functions without compiler warnings */
4873 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4874 # define XCAST(fun) (typeof(directPlay3AVT.fun))
4875 #else
4876 # define XCAST(fun) (void*)
4877 #endif
4879 static ICOM_VTABLE(IDirectPlay3) directPlay3AVT =
4881 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4882 XCAST(QueryInterface)DP_QueryInterface,
4883 XCAST(AddRef)DP_AddRef,
4884 XCAST(Release)DP_Release,
4886 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
4887 XCAST(Close)DirectPlay2AImpl_Close,
4888 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
4889 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
4890 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
4891 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
4892 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
4893 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
4894 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
4895 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
4896 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
4897 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
4898 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
4899 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
4900 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
4901 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
4902 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
4903 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
4904 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
4905 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
4906 XCAST(Initialize)DirectPlay2AImpl_Initialize,
4907 XCAST(Open)DirectPlay2AImpl_Open,
4908 XCAST(Receive)DirectPlay2AImpl_Receive,
4909 XCAST(Send)DirectPlay2AImpl_Send,
4910 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
4911 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
4912 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
4913 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
4914 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
4916 DirectPlay3AImpl_AddGroupToGroup,
4917 DirectPlay3AImpl_CreateGroupInGroup,
4918 DirectPlay3AImpl_DeleteGroupFromGroup,
4919 DirectPlay3AImpl_EnumConnections,
4920 DirectPlay3AImpl_EnumGroupsInGroup,
4921 DirectPlay3AImpl_GetGroupConnectionSettings,
4922 DirectPlay3AImpl_InitializeConnection,
4923 DirectPlay3AImpl_SecureOpen,
4924 DirectPlay3AImpl_SendChatMessage,
4925 DirectPlay3AImpl_SetGroupConnectionSettings,
4926 DirectPlay3AImpl_StartSession,
4927 DirectPlay3AImpl_GetGroupFlags,
4928 DirectPlay3AImpl_GetGroupParent,
4929 DirectPlay3AImpl_GetPlayerAccount,
4930 DirectPlay3AImpl_GetPlayerFlags
4932 #undef XCAST
4934 /* Note: Hack so we can reuse the old functions without compiler warnings */
4935 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4936 # define XCAST(fun) (typeof(directPlay3WVT.fun))
4937 #else
4938 # define XCAST(fun) (void*)
4939 #endif
4940 static ICOM_VTABLE(IDirectPlay3) directPlay3WVT =
4942 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4943 XCAST(QueryInterface)DP_QueryInterface,
4944 XCAST(AddRef)DP_AddRef,
4945 XCAST(Release)DP_Release,
4947 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
4948 XCAST(Close)DirectPlay2WImpl_Close,
4949 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
4950 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
4951 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
4952 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
4953 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
4954 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
4955 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
4956 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
4957 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
4958 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
4959 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
4960 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
4961 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
4962 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
4963 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
4964 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
4965 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
4966 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
4967 XCAST(Initialize)DirectPlay2WImpl_Initialize,
4968 XCAST(Open)DirectPlay2WImpl_Open,
4969 XCAST(Receive)DirectPlay2WImpl_Receive,
4970 XCAST(Send)DirectPlay2WImpl_Send,
4971 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
4972 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
4973 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
4974 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
4975 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
4977 DirectPlay3WImpl_AddGroupToGroup,
4978 DirectPlay3WImpl_CreateGroupInGroup,
4979 DirectPlay3WImpl_DeleteGroupFromGroup,
4980 DirectPlay3WImpl_EnumConnections,
4981 DirectPlay3WImpl_EnumGroupsInGroup,
4982 DirectPlay3WImpl_GetGroupConnectionSettings,
4983 DirectPlay3WImpl_InitializeConnection,
4984 DirectPlay3WImpl_SecureOpen,
4985 DirectPlay3WImpl_SendChatMessage,
4986 DirectPlay3WImpl_SetGroupConnectionSettings,
4987 DirectPlay3WImpl_StartSession,
4988 DirectPlay3WImpl_GetGroupFlags,
4989 DirectPlay3WImpl_GetGroupParent,
4990 DirectPlay3WImpl_GetPlayerAccount,
4991 DirectPlay3WImpl_GetPlayerFlags
4993 #undef XCAST
4995 /* Note: Hack so we can reuse the old functions without compiler warnings */
4996 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4997 # define XCAST(fun) (typeof(directPlay4WVT.fun))
4998 #else
4999 # define XCAST(fun) (void*)
5000 #endif
5001 static ICOM_VTABLE(IDirectPlay4) directPlay4WVT =
5003 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5004 XCAST(QueryInterface)DP_QueryInterface,
5005 XCAST(AddRef)DP_AddRef,
5006 XCAST(Release)DP_Release,
5008 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
5009 XCAST(Close)DirectPlay2WImpl_Close,
5010 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
5011 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
5012 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
5013 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
5014 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5015 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5016 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5017 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5018 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5019 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5020 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5021 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5022 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5023 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5024 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5025 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5026 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5027 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5028 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5029 XCAST(Open)DirectPlay2WImpl_Open,
5030 XCAST(Receive)DirectPlay2WImpl_Receive,
5031 XCAST(Send)DirectPlay2WImpl_Send,
5032 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5033 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5034 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5035 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5036 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5038 XCAST(AddGroupToGroup)DirectPlay3WImpl_AddGroupToGroup,
5039 XCAST(CreateGroupInGroup)DirectPlay3WImpl_CreateGroupInGroup,
5040 XCAST(DeleteGroupFromGroup)DirectPlay3WImpl_DeleteGroupFromGroup,
5041 XCAST(EnumConnections)DirectPlay3WImpl_EnumConnections,
5042 XCAST(EnumGroupsInGroup)DirectPlay3WImpl_EnumGroupsInGroup,
5043 XCAST(GetGroupConnectionSettings)DirectPlay3WImpl_GetGroupConnectionSettings,
5044 XCAST(InitializeConnection)DirectPlay3WImpl_InitializeConnection,
5045 XCAST(SecureOpen)DirectPlay3WImpl_SecureOpen,
5046 XCAST(SendChatMessage)DirectPlay3WImpl_SendChatMessage,
5047 XCAST(SetGroupConnectionSettings)DirectPlay3WImpl_SetGroupConnectionSettings,
5048 XCAST(StartSession)DirectPlay3WImpl_StartSession,
5049 XCAST(GetGroupFlags)DirectPlay3WImpl_GetGroupFlags,
5050 XCAST(GetGroupParent)DirectPlay3WImpl_GetGroupParent,
5051 XCAST(GetPlayerAccount)DirectPlay3WImpl_GetPlayerAccount,
5052 XCAST(GetPlayerFlags)DirectPlay3WImpl_GetPlayerFlags,
5054 DirectPlay4WImpl_GetGroupOwner,
5055 DirectPlay4WImpl_SetGroupOwner,
5056 DirectPlay4WImpl_SendEx,
5057 DirectPlay4WImpl_GetMessageQueue,
5058 DirectPlay4WImpl_CancelMessage,
5059 DirectPlay4WImpl_CancelPriority
5061 #undef XCAST
5064 /* Note: Hack so we can reuse the old functions without compiler warnings */
5065 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5066 # define XCAST(fun) (typeof(directPlay4AVT.fun))
5067 #else
5068 # define XCAST(fun) (void*)
5069 #endif
5070 static ICOM_VTABLE(IDirectPlay4) directPlay4AVT =
5072 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5073 XCAST(QueryInterface)DP_QueryInterface,
5074 XCAST(AddRef)DP_AddRef,
5075 XCAST(Release)DP_Release,
5077 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
5078 XCAST(Close)DirectPlay2AImpl_Close,
5079 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
5080 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
5081 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
5082 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
5083 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
5084 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
5085 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
5086 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
5087 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
5088 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
5089 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
5090 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
5091 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5092 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5093 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5094 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5095 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5096 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5097 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5098 XCAST(Open)DirectPlay2AImpl_Open,
5099 XCAST(Receive)DirectPlay2AImpl_Receive,
5100 XCAST(Send)DirectPlay2AImpl_Send,
5101 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5102 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5103 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5104 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5105 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5107 XCAST(AddGroupToGroup)DirectPlay3AImpl_AddGroupToGroup,
5108 XCAST(CreateGroupInGroup)DirectPlay3AImpl_CreateGroupInGroup,
5109 XCAST(DeleteGroupFromGroup)DirectPlay3AImpl_DeleteGroupFromGroup,
5110 XCAST(EnumConnections)DirectPlay3AImpl_EnumConnections,
5111 XCAST(EnumGroupsInGroup)DirectPlay3AImpl_EnumGroupsInGroup,
5112 XCAST(GetGroupConnectionSettings)DirectPlay3AImpl_GetGroupConnectionSettings,
5113 XCAST(InitializeConnection)DirectPlay3AImpl_InitializeConnection,
5114 XCAST(SecureOpen)DirectPlay3AImpl_SecureOpen,
5115 XCAST(SendChatMessage)DirectPlay3AImpl_SendChatMessage,
5116 XCAST(SetGroupConnectionSettings)DirectPlay3AImpl_SetGroupConnectionSettings,
5117 XCAST(StartSession)DirectPlay3AImpl_StartSession,
5118 XCAST(GetGroupFlags)DirectPlay3AImpl_GetGroupFlags,
5119 XCAST(GetGroupParent)DirectPlay3AImpl_GetGroupParent,
5120 XCAST(GetPlayerAccount)DirectPlay3AImpl_GetPlayerAccount,
5121 XCAST(GetPlayerFlags)DirectPlay3AImpl_GetPlayerFlags,
5123 DirectPlay4AImpl_GetGroupOwner,
5124 DirectPlay4AImpl_SetGroupOwner,
5125 DirectPlay4AImpl_SendEx,
5126 DirectPlay4AImpl_GetMessageQueue,
5127 DirectPlay4AImpl_CancelMessage,
5128 DirectPlay4AImpl_CancelPriority
5130 #undef XCAST
5132 extern
5133 HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP,
5134 DPID idPlayer,
5135 LPVOID* lplpData )
5137 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5139 if( lpPlayer == NULL )
5141 return DPERR_INVALIDPLAYER;
5144 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
5146 return DP_OK;
5149 extern
5150 HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP,
5151 DPID idPlayer,
5152 LPVOID lpData )
5154 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5156 if( lpPlayer == NULL )
5158 return DPERR_INVALIDPLAYER;
5161 lpPlayer->lpPData->lpSPPlayerData = lpData;
5163 return DP_OK;
5166 /***************************************************************************
5167 * DirectPlayEnumerate [DPLAYX.9]
5168 * DirectPlayEnumerateA [DPLAYX.2]
5170 * The pointer to the structure lpContext will be filled with the
5171 * appropriate data for each service offered by the OS. These services are
5172 * not necessarily available on this particular machine but are defined
5173 * as simple service providers under the "Service Providers" registry key.
5174 * This structure is then passed to lpEnumCallback for each of the different
5175 * services.
5177 * This API is useful only for applications written using DirectX3 or
5178 * worse. It is superceeded by IDirectPlay3::EnumConnections which also
5179 * gives information on the actual connections.
5181 * defn of a service provider:
5182 * A dynamic-link library used by DirectPlay to communicate over a network.
5183 * The service provider contains all the network-specific code required
5184 * to send and receive messages. Online services and network operators can
5185 * supply service providers to use specialized hardware, protocols, communications
5186 * media, and network resources.
5188 * TODO: Allocate string buffer space from the heap (length from reg)
5189 * Pass real device driver numbers...
5190 * Get the GUID properly...
5192 HRESULT WINAPI DirectPlayEnumerateA( LPDPENUMDPCALLBACKA lpEnumCallback,
5193 LPVOID lpContext )
5196 HKEY hkResult;
5197 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
5198 DWORD dwIndex;
5199 DWORD sizeOfSubKeyName=50;
5200 char subKeyName[51];
5201 FILETIME filetime;
5203 TRACE(": lpEnumCallback=%p lpContext=%p\n", lpEnumCallback, lpContext );
5205 if( !lpEnumCallback || !*lpEnumCallback )
5207 return DPERR_INVALIDPARAMS;
5210 /* Need to loop over the service providers in the registry */
5211 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
5212 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
5214 /* Hmmm. Does this mean that there are no service providers? */
5215 ERR(": no service providers?\n");
5216 return DP_OK;
5219 /* Traverse all the service providers we have available */
5220 for( dwIndex=0;
5221 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
5222 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
5223 ++dwIndex, sizeOfSubKeyName=50 )
5225 LPSTR majVerDataSubKey = "dwReserved1";
5226 LPSTR minVerDataSubKey = "dwReserved2";
5227 LPSTR guidDataSubKey = "Guid";
5228 HKEY hkServiceProvider;
5229 GUID serviceProviderGUID;
5230 DWORD returnTypeGUID, returnTypeReserved, sizeOfReturnBuffer = 50;
5231 char returnBuffer[51];
5232 WCHAR buff[51];
5233 DWORD majVersionNum , minVersionNum = 0;
5235 TRACE(" this time through: %s\n", subKeyName );
5237 /* Get a handle for this particular service provider */
5238 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
5239 &hkServiceProvider ) != ERROR_SUCCESS )
5241 ERR(": what the heck is going on?\n" );
5242 continue;
5245 /* Get the GUID, Device major number and device minor number
5246 * from the registry.
5248 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
5249 NULL, &returnTypeGUID, returnBuffer,
5250 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5252 ERR(": missing GUID registry data members\n" );
5253 continue;
5256 /* FIXME: Check return types to ensure we're interpreting data right */
5257 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
5258 CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
5260 /* FIXME: Need to know which of dwReserved1 and dwReserved2 are maj and min */
5262 sizeOfReturnBuffer = 50;
5263 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
5264 NULL, &returnTypeReserved, returnBuffer,
5265 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5267 ERR(": missing dwReserved1 registry data members\n") ;
5268 continue;
5271 majVersionNum = GET_DWORD( returnBuffer );
5273 sizeOfReturnBuffer = 50;
5274 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
5275 NULL, &returnTypeReserved, returnBuffer,
5276 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5278 ERR(": missing dwReserved2 registry data members\n") ;
5279 continue;
5282 minVersionNum = GET_DWORD( returnBuffer );
5285 /* The enumeration will return FALSE if we are not to continue */
5286 if( !lpEnumCallback( &serviceProviderGUID , subKeyName,
5287 majVersionNum, minVersionNum, lpContext ) )
5289 WARN("lpEnumCallback returning FALSE\n" );
5290 break;
5294 return DP_OK;
5298 /***************************************************************************
5299 * DirectPlayEnumerateW [DPLAYX.3]
5302 HRESULT WINAPI DirectPlayEnumerateW( LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5305 FIXME(":stub\n");
5307 return DPERR_OUTOFMEMORY;
5311 typedef struct tagCreateEnum
5313 LPVOID lpConn;
5314 LPCGUID lpGuid;
5315 } CreateEnumData, *lpCreateEnumData;
5317 /* Find and copy the matching connection for the SP guid */
5318 static BOOL CALLBACK cbDPCreateEnumConnections(
5319 LPCGUID lpguidSP,
5320 LPVOID lpConnection,
5321 DWORD dwConnectionSize,
5322 LPCDPNAME lpName,
5323 DWORD dwFlags,
5324 LPVOID lpContext)
5326 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5328 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5330 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5332 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5333 dwConnectionSize );
5334 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5336 /* Found the record that we were looking for */
5337 return FALSE;
5340 /* Haven't found what were looking for yet */
5341 return TRUE;
5345 /***************************************************************************
5346 * DirectPlayCreate [DPLAYX.1]
5349 HRESULT WINAPI DirectPlayCreate
5350 ( LPGUID lpGUID, LPDIRECTPLAY2 *lplpDP, IUnknown *pUnk)
5352 HRESULT hr;
5353 LPDIRECTPLAY3A lpDP3A;
5354 CreateEnumData cbData;
5356 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5358 if( pUnk != NULL )
5360 return CLASS_E_NOAGGREGATION;
5363 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5364 give them an IDirectPlay2A object and hope that doesn't cause problems */
5365 if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
5367 return DPERR_UNAVAILABLE;
5370 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
5372 /* The GUID_NULL means don't bind a service provider. Just return the
5373 interface as is */
5374 return DP_OK;
5377 /* Bind the desired service provider since lpGUID is non NULL */
5378 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
5380 /* We're going to use a DP3 interface */
5381 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
5382 (LPVOID*)&lpDP3A );
5383 if( FAILED(hr) )
5385 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
5386 return hr;
5389 cbData.lpConn = NULL;
5390 cbData.lpGuid = lpGUID;
5392 /* We were given a service provider, find info about it... */
5393 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
5394 &cbData, DPCONNECTION_DIRECTPLAY );
5395 if( ( FAILED(hr) ) ||
5396 ( cbData.lpConn == NULL )
5399 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
5400 IDirectPlayX_Release( lpDP3A );
5401 return DPERR_UNAVAILABLE;
5404 /* Initialize the service provider */
5405 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
5406 if( FAILED(hr) )
5408 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
5409 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5410 IDirectPlayX_Release( lpDP3A );
5411 return hr;
5414 /* Release our version of the interface now that we're done with it */
5415 IDirectPlayX_Release( lpDP3A );
5416 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5418 return DP_OK;