- Provide lobby provider COM object header file and stub implementation
[wine/wine-kai.git] / dlls / dplayx / dplay.c
blob7548c52ce6cdcf265dc097c93ba19cbe78e7e039
1 /* Direct Play 2,3,4 Implementation
3 * Copyright 1998,1999,2000,2001 - Peter Hunnisett
5 * <presently under construction - contact hunnise@nortelnetworks.com>
7 */
9 #include <string.h>
10 #include "wine/port.h"
11 #include "windef.h"
12 #include "winerror.h"
13 #include "winbase.h"
14 #include "winnt.h"
15 #include "winreg.h"
16 #include "winnls.h"
17 #include "wine/unicode.h"
18 #include "dplay.h"
19 #include "debugtools.h"
21 #include "dpinit.h"
22 #include "dplayx_global.h"
23 #include "name_server.h"
24 #include "dplayx_queue.h"
25 #include "dplaysp.h"
26 #include "dplay_global.h"
28 DEFAULT_DEBUG_CHANNEL(dplay);
30 /* FIXME: Should this be externed? */
31 extern HRESULT DPL_CreateCompoundAddress
32 ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
33 LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
36 /* Local function prototypes */
37 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid );
38 static lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* iface, LPDPID lpid,
39 LPDPNAME lpName, DWORD dwFlags,
40 HANDLE hEvent, BOOL bAnsi );
41 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi );
42 static void DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
43 LPVOID lpData, DWORD dwDataSize );
45 static lpGroupData DP_CreateGroup( IDirectPlay2AImpl* iface, LPDPID lpid,
46 LPDPNAME lpName, DWORD dwFlags,
47 DPID idParent, BOOL bAnsi );
48 static void DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
49 LPVOID lpData, DWORD dwDataSize );
50 static void DP_DeleteDPNameStruct( LPDPNAME lpDPName );
51 static void DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid );
52 static BOOL CALLBACK cbDeletePlayerFromAllGroups( DPID dpId,
53 DWORD dwPlayerType,
54 LPCDPNAME lpName,
55 DWORD dwFlags,
56 LPVOID lpContext );
57 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid );
58 static BOOL CALLBACK cbRemoveGroupOrPlayer( DPID dpId, DWORD dwPlayerType,
59 LPCDPNAME lpName, DWORD dwFlags,
60 LPVOID lpContext );
61 static void DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid );
63 /* Helper methods for player/group interfaces */
64 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
65 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
66 DPID idPlayer, BOOL bAnsi );
67 static HRESULT WINAPI DP_IF_CreatePlayer
68 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, LPDPID lpidPlayer,
69 LPDPNAME lpPlayerName, HANDLE hEvent, LPVOID lpData,
70 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
71 static HRESULT WINAPI DP_IF_DestroyGroup
72 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi );
73 static HRESULT WINAPI DP_IF_DestroyPlayer
74 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi );
75 static HRESULT WINAPI DP_IF_EnumGroupPlayers
76 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
77 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
78 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
79 static HRESULT WINAPI DP_IF_EnumGroups
80 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
81 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
82 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
83 static HRESULT WINAPI DP_IF_EnumPlayers
84 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
85 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
86 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
87 static HRESULT WINAPI DP_IF_GetGroupData
88 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
89 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
90 static HRESULT WINAPI DP_IF_GetGroupName
91 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
92 LPDWORD lpdwDataSize, BOOL bAnsi );
93 static HRESULT WINAPI DP_IF_GetPlayerData
94 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
95 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
96 static HRESULT WINAPI DP_IF_GetPlayerName
97 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
98 LPDWORD lpdwDataSize, BOOL bAnsi );
99 static HRESULT WINAPI DP_IF_SetGroupName
100 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
101 DWORD dwFlags, BOOL bAnsi );
102 static HRESULT WINAPI DP_IF_SetPlayerData
103 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
104 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
105 static HRESULT WINAPI DP_IF_SetPlayerName
106 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
107 DWORD dwFlags, BOOL bAnsi );
108 static HRESULT WINAPI DP_IF_AddGroupToGroup
109 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
110 static HRESULT WINAPI DP_IF_CreateGroup
111 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
112 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
113 DWORD dwFlags, BOOL bAnsi );
114 static HRESULT WINAPI DP_IF_CreateGroupInGroup
115 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
116 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
117 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
118 static HRESULT WINAPI DP_IF_AddPlayerToGroup
119 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
120 DPID idPlayer, BOOL bAnsi );
121 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
122 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
123 static HRESULT WINAPI DP_SetSessionDesc
124 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
125 DWORD dwFlags, BOOL bInitial, BOOL bAnsi );
126 static HRESULT WINAPI DP_SecureOpen
127 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
128 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
129 BOOL bAnsi );
130 static HRESULT WINAPI DP_SendEx
131 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
132 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
133 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi );
134 static HRESULT WINAPI DP_IF_Receive
135 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
136 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi );
137 static HRESULT WINAPI DP_IF_GetMessageQueue
138 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
139 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi );
140 static HRESULT WINAPI DP_SP_SendEx
141 ( IDirectPlay2Impl* This, DWORD dwFlags,
142 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
143 LPVOID lpContext, LPDWORD lpdwMsgID );
144 static HRESULT WINAPI DP_IF_SetGroupData
145 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
146 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
147 static HRESULT WINAPI DP_IF_GetPlayerCaps
148 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
149 DWORD dwFlags );
150 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi );
151 static HRESULT WINAPI DP_IF_CancelMessage
152 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
153 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi );
154 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
155 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
156 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
157 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
158 static HRESULT WINAPI DP_IF_GetGroupParent
159 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
160 BOOL bAnsi );
161 static HRESULT WINAPI DP_IF_GetCaps
162 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags );
163 static HRESULT WINAPI DP_IF_EnumSessions
164 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
165 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
166 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
167 static HRESULT WINAPI DP_IF_InitializeConnection
168 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi );
169 static BOOL CALLBACK cbDPCreateEnumConnections( LPCGUID lpguidSP,
170 LPVOID lpConnection, DWORD dwConnectionSize, LPCDPNAME lpName,
171 DWORD dwFlags, LPVOID lpContext );
172 static BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
173 LPDWORD lpdwBufSize );
177 static inline DPID DP_NextObjectId(void);
178 static DPID DP_GetRemoteNextObjectId(void);
181 static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc,
182 LPCDPSESSIONDESC2 srcSessDesc, BOOL bAnsi );
185 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp );
186 static HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider );
187 static HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hServiceProvider );
194 #define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */
195 #define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported
196 we don't have to change much */
197 #define DPID_NAME_SERVER 0x19a9d65b /* Don't ask me why */
199 /* Strip out dwFlag values which cannot be sent in the CREATEGROUP msg */
200 #define DPMSG_CREATEGROUP_DWFLAGS(x) ( (x) & DPGROUP_HIDDEN )
202 /* Strip out all dwFlags values for CREATEPLAYER msg */
203 #define DPMSG_CREATEPLAYER_DWFLAGS(x) 0
205 static DWORD kludgePlayerGroupId = 1000;
207 /* ------------------------------------------------------------------ */
210 static BOOL DP_CreateIUnknown( LPVOID lpDP )
212 ICOM_THIS(IDirectPlay2AImpl,lpDP);
214 This->unk = (DirectPlayIUnknownData*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
215 sizeof( *(This->unk) ) );
216 if ( This->unk == NULL )
218 return FALSE;
221 InitializeCriticalSection( &This->unk->DP_lock );
223 return TRUE;
226 static BOOL DP_DestroyIUnknown( LPVOID lpDP )
228 ICOM_THIS(IDirectPlay2AImpl,lpDP);
230 DeleteCriticalSection( &This->unk->DP_lock );
231 HeapFree( GetProcessHeap(), 0, This->unk );
233 return TRUE;
236 static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
238 ICOM_THIS(IDirectPlay2AImpl,lpDP);
240 This->dp2 = (DirectPlay2Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
241 sizeof( *(This->dp2) ) );
242 if ( This->dp2 == NULL )
244 return FALSE;
247 This->dp2->bConnectionOpen = FALSE;
249 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
251 This->dp2->bHostInterface = FALSE;
253 DPQ_INIT(This->dp2->receiveMsgs);
254 DPQ_INIT(This->dp2->sendMsgs);
255 DPQ_INIT(This->dp2->replysExpected);
257 if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
259 /* FIXME: Memory leak */
260 return FALSE;
263 /* Provide an initial session desc with nothing in it */
264 This->dp2->lpSessionDesc = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
265 HEAP_ZERO_MEMORY,
266 sizeof( *This->dp2->lpSessionDesc ) );
267 if( This->dp2->lpSessionDesc == NULL )
269 /* FIXME: Memory leak */
270 return FALSE;
272 This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc );
274 /* We are a emulating a dp 6 implementation */
275 This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION;
277 This->dp2->spData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
278 sizeof( *This->dp2->spData.lpCB ) );
279 This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB );
280 This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION;
282 /* This is the pointer to the service provider */
283 if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP,
284 (LPVOID*)&This->dp2->spData.lpISP, This ) )
287 /* FIXME: Memory leak */
288 return FALSE;
291 /* Setup lobby provider information */
292 This->dp2->dplspData.dwSPVersion = DPSP_MAJORVERSION;
293 This->dp2->dplspData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
294 sizeof( *This->dp2->dplspData.lpCB ) );
295 This->dp2->dplspData.lpCB->dwSize = sizeof( *This->dp2->dplspData.lpCB );
297 if( FAILED( DPLSP_CreateInterface( &IID_IDPLobbySP,
298 (LPVOID*)&This->dp2->dplspData.lpISP, This ) )
301 /* FIXME: Memory leak */
302 return FALSE;
305 return TRUE;
308 /* Definition of the global function in dplayx_queue.h. #
309 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
310 DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
312 HeapFree( GetProcessHeap(), 0, elem );
315 /* Function to delete the list of groups with this interface. Needs to
316 * delete the group and player lists associated with this group as well
317 * as the group data associated with this group. It should not delete
318 * player data as that is shared with the top player list and will be
319 * deleted with that.
321 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList );
322 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList )
324 DPQ_DELETEQ( elem->lpGData->groups, groups,
325 lpGroupList, cbDeleteElemFromHeap );
326 DPQ_DELETEQ( elem->lpGData->players, players,
327 lpPlayerList, cbDeleteElemFromHeap );
328 HeapFree( GetProcessHeap(), 0, elem->lpGData );
329 HeapFree( GetProcessHeap(), 0, elem );
332 /* Function to delete the list of players with this interface. Needs to
333 * delete the player data for all players as well.
335 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList );
336 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList )
338 HeapFree( GetProcessHeap(), 0, elem->lpPData );
339 HeapFree( GetProcessHeap(), 0, elem );
342 static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
344 ICOM_THIS(IDirectPlay2AImpl,lpDP);
346 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
348 TerminateThread( This->dp2->hEnumSessionThread, 0 );
349 CloseHandle( This->dp2->hEnumSessionThread );
352 /* Finish with the SP - have it shutdown */
353 if( This->dp2->spData.lpCB->ShutdownEx )
355 DPSP_SHUTDOWNDATA data;
357 TRACE( "Calling SP ShutdownEx\n" );
359 data.lpISP = This->dp2->spData.lpISP;
361 (*This->dp2->spData.lpCB->ShutdownEx)( &data );
363 else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
365 TRACE( "Calling obsolete SP Shutdown\n" );
366 (*This->dp2->spData.lpCB->Shutdown)();
369 /* Unload the SP (if it exists) */
370 if( This->dp2->hServiceProvider != 0 )
372 FreeLibrary( This->dp2->hServiceProvider );
375 /* Unload the Lobby Provider (if it exists) */
376 if( This->dp2->hDPLobbyProvider != 0 )
378 FreeLibrary( This->dp2->hDPLobbyProvider );
381 #if 0
382 DPQ_DELETEQ( This->dp2->players, players, lpPlayerList, cbDeletePlayerElem );
383 DPQ_DELETEQ( This->dp2->groups, groups, lpGroupList, cbDeleteGroupsElem );
384 #endif
386 /* FIXME: Need to delete receive and send msgs queue contents */
388 NS_DeleteSessionCache( This->dp2->lpNameServerData );
390 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
392 IDirectPlaySP_Release( This->dp2->spData.lpISP );
394 /* Delete the contents */
395 HeapFree( GetProcessHeap(), 0, This->dp2 );
397 return TRUE;
400 static BOOL DP_CreateDirectPlay3( LPVOID lpDP )
402 ICOM_THIS(IDirectPlay3AImpl,lpDP);
404 This->dp3 = (DirectPlay3Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
405 sizeof( *(This->dp3) ) );
406 if ( This->dp3 == NULL )
408 return FALSE;
411 return TRUE;
414 static BOOL DP_DestroyDirectPlay3( LPVOID lpDP )
416 ICOM_THIS(IDirectPlay3AImpl,lpDP);
418 /* Delete the contents */
419 HeapFree( GetProcessHeap(), 0, This->dp3 );
421 return TRUE;
424 static BOOL DP_CreateDirectPlay4( LPVOID lpDP )
426 ICOM_THIS(IDirectPlay4AImpl,lpDP);
428 This->dp4 = (DirectPlay4Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
429 sizeof( *(This->dp4) ) );
430 if ( This->dp4 == NULL )
432 return FALSE;
435 return TRUE;
438 static BOOL DP_DestroyDirectPlay4( LPVOID lpDP )
440 ICOM_THIS(IDirectPlay3AImpl,lpDP);
442 /* Delete the contents */
443 HeapFree( GetProcessHeap(), 0, This->dp4 );
445 return TRUE;
449 /* Create a new interface */
450 extern
451 HRESULT DP_CreateInterface
452 ( REFIID riid, LPVOID* ppvObj )
454 TRACE( " for %s\n", debugstr_guid( riid ) );
456 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
457 sizeof( IDirectPlay2Impl ) );
459 if( *ppvObj == NULL )
461 return DPERR_OUTOFMEMORY;
464 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
466 ICOM_THIS(IDirectPlay2Impl,*ppvObj);
467 ICOM_VTBL(This) = &directPlay2WVT;
469 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
471 ICOM_THIS(IDirectPlay2AImpl,*ppvObj);
472 ICOM_VTBL(This) = &directPlay2AVT;
474 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
476 ICOM_THIS(IDirectPlay3Impl,*ppvObj);
477 ICOM_VTBL(This) = &directPlay3WVT;
479 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
481 ICOM_THIS(IDirectPlay3AImpl,*ppvObj);
482 ICOM_VTBL(This) = &directPlay3AVT;
484 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
486 ICOM_THIS(IDirectPlay4Impl,*ppvObj);
487 ICOM_VTBL(This) = &directPlay4WVT;
489 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
491 ICOM_THIS(IDirectPlay4AImpl,*ppvObj);
492 ICOM_VTBL(This) = &directPlay4AVT;
494 else
496 /* Unsupported interface */
497 HeapFree( GetProcessHeap(), 0, *ppvObj );
498 *ppvObj = NULL;
500 return E_NOINTERFACE;
503 /* Initialize it */
504 if ( DP_CreateIUnknown( *ppvObj ) &&
505 DP_CreateDirectPlay2( *ppvObj ) &&
506 DP_CreateDirectPlay3( *ppvObj ) &&
507 DP_CreateDirectPlay4( *ppvObj )
510 IDirectPlayX_AddRef( (LPDIRECTPLAY2A)*ppvObj );
512 return S_OK;
515 /* Initialize failed, destroy it */
516 DP_DestroyDirectPlay4( *ppvObj );
517 DP_DestroyDirectPlay3( *ppvObj );
518 DP_DestroyDirectPlay2( *ppvObj );
519 DP_DestroyIUnknown( *ppvObj );
521 HeapFree( GetProcessHeap(), 0, *ppvObj );
523 *ppvObj = NULL;
524 return DPERR_NOMEMORY;
528 /* Direct Play methods */
530 /* Shared between all dplay types */
531 static HRESULT WINAPI DP_QueryInterface
532 ( LPDIRECTPLAY2 iface, REFIID riid, LPVOID* ppvObj )
534 ICOM_THIS(IDirectPlay2Impl,iface);
535 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
537 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
538 sizeof( *This ) );
540 if( *ppvObj == NULL )
542 return DPERR_OUTOFMEMORY;
545 CopyMemory( *ppvObj, This, sizeof( *This ) );
546 (*(IDirectPlay2Impl**)ppvObj)->ulInterfaceRef = 0;
548 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
550 ICOM_THIS(IDirectPlay2Impl,*ppvObj);
551 ICOM_VTBL(This) = &directPlay2WVT;
553 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
555 ICOM_THIS(IDirectPlay2AImpl,*ppvObj);
556 ICOM_VTBL(This) = &directPlay2AVT;
558 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
560 ICOM_THIS(IDirectPlay3Impl,*ppvObj);
561 ICOM_VTBL(This) = &directPlay3WVT;
563 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
565 ICOM_THIS(IDirectPlay3AImpl,*ppvObj);
566 ICOM_VTBL(This) = &directPlay3AVT;
568 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
570 ICOM_THIS(IDirectPlay4Impl,*ppvObj);
571 ICOM_VTBL(This) = &directPlay4WVT;
573 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
575 ICOM_THIS(IDirectPlay4AImpl,*ppvObj);
576 ICOM_VTBL(This) = &directPlay4AVT;
578 else
580 /* Unsupported interface */
581 HeapFree( GetProcessHeap(), 0, *ppvObj );
582 *ppvObj = NULL;
584 return E_NOINTERFACE;
587 IDirectPlayX_AddRef( (LPDIRECTPLAY2)*ppvObj );
589 return S_OK;
592 /* Shared between all dplay types */
593 static ULONG WINAPI DP_AddRef
594 ( LPDIRECTPLAY3 iface )
596 ULONG ulInterfaceRefCount, ulObjRefCount;
597 ICOM_THIS(IDirectPlay3Impl,iface);
599 ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
600 ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
602 TRACE( "ref count incremented to %lu:%lu for %p\n",
603 ulInterfaceRefCount, ulObjRefCount, This );
605 return ulObjRefCount;
608 static ULONG WINAPI DP_Release
609 ( LPDIRECTPLAY3 iface )
611 ULONG ulInterfaceRefCount, ulObjRefCount;
613 ICOM_THIS(IDirectPlay3Impl,iface);
615 ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
616 ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
618 TRACE( "ref count decremented to %lu:%lu for %p\n",
619 ulInterfaceRefCount, ulObjRefCount, This );
621 /* Deallocate if this is the last reference to the object */
622 if( ulObjRefCount == 0 )
624 /* If we're destroying the object, this must be the last ref
625 of the last interface */
626 DP_DestroyDirectPlay4( This );
627 DP_DestroyDirectPlay3( This );
628 DP_DestroyDirectPlay2( This );
629 DP_DestroyIUnknown( This );
632 /* Deallocate the interface */
633 if( ulInterfaceRefCount == 0 )
635 HeapFree( GetProcessHeap(), 0, This );
638 return ulObjRefCount;
641 static inline DPID DP_NextObjectId(void)
643 return (DPID)InterlockedIncrement( &kludgePlayerGroupId );
646 /* *lplpReply will be non NULL iff there is something to reply */
647 HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpcMessageBody,
648 DWORD dwMessageBodySize, LPCVOID lpcMessageHeader,
649 WORD wCommandId, WORD wVersion,
650 LPVOID* lplpReply, LPDWORD lpdwMsgSize )
652 TRACE( "(%p)->(%p,0x%08lx,%p,%u,%u)\n",
653 This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId,
654 wVersion );
656 switch( wCommandId )
658 /* Name server needs to handle this request */
659 case DPMSGCMD_ENUMSESSIONSREQUEST:
661 /* Reply expected */
662 NS_ReplyToEnumSessionsRequest( lpcMessageBody, lplpReply, lpdwMsgSize, This );
664 break;
667 /* Name server needs to handle this request */
668 case DPMSGCMD_ENUMSESSIONSREPLY:
670 /* No reply expected */
671 NS_AddRemoteComputerAsNameServer( lpcMessageHeader,
672 This->dp2->spData.dwSPHeaderSize,
673 (LPDPMSG_ENUMSESSIONSREPLY)lpcMessageBody,
674 This->dp2->lpNameServerData );
675 break;
678 case DPMSGCMD_REQUESTNEWPLAYERID:
680 LPCDPMSG_REQUESTNEWPLAYERID lpcMsg =
681 (LPCDPMSG_REQUESTNEWPLAYERID)lpcMessageBody;
683 LPDPMSG_NEWPLAYERIDREPLY lpReply;
685 *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
687 *lplpReply = (LPDPMSG_NEWPLAYERIDREPLY)HeapAlloc( GetProcessHeap(),
688 HEAP_ZERO_MEMORY,
689 *lpdwMsgSize );
691 FIXME( "Ignoring dwFlags 0x%08lx in request msg\n",
692 lpcMsg->dwFlags );
694 /* Setup the reply */
695 lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) +
696 This->dp2->spData.dwSPHeaderSize );
698 lpReply->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
699 lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY;
700 lpReply->envelope.wVersion = DPMSGVER_DP6;
702 lpReply->dpidNewPlayerId = DP_NextObjectId();
704 TRACE( "Allocating new playerid 0x%08lx from remote request\n",
705 lpReply->dpidNewPlayerId );
707 break;
710 case DPMSGCMD_GETNAMETABLEREPLY:
711 case DPMSGCMD_NEWPLAYERIDREPLY:
714 #if 0
715 if( wCommandId == DPMSGCMD_NEWPLAYERIDREPLY )
716 DebugBreak();
717 #endif
718 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
720 break;
723 #if 1
724 case DPMSGCMD_JUSTENVELOPE:
726 TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08lx\n", lpcMessageHeader, ((LPDWORD)lpcMessageHeader)[1] );
727 NS_SetLocalAddr( This->dp2->lpNameServerData, lpcMessageHeader, 20 );
728 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
730 #endif
732 case DPMSGCMD_FORWARDADDPLAYER:
734 #if 0
735 DebugBreak();
736 #endif
737 #if 1
738 TRACE( "Sending message to self to get my addr\n" );
739 DP_MSG_ToSelf( This, 1 ); /* This is a hack right now */
740 #endif
741 break;
744 case DPMSGCMD_FORWARDADDPLAYERNACK:
746 DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
747 break;
750 default:
752 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
753 DebugBreak();
754 break;
758 /* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */
760 return DP_OK;
764 static HRESULT WINAPI DP_IF_AddPlayerToGroup
765 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
766 DPID idPlayer, BOOL bAnsi )
768 lpGroupData lpGData;
769 lpPlayerList lpPList;
770 lpPlayerList lpNewPList;
772 TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
773 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
775 /* Find the group */
776 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
778 return DPERR_INVALIDGROUP;
781 /* Find the player */
782 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
784 return DPERR_INVALIDPLAYER;
787 /* Create a player list (ie "shortcut" ) */
788 lpNewPList = (lpPlayerList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
789 sizeof( *lpNewPList ) );
790 if( lpNewPList == NULL )
792 return DPERR_CANTADDPLAYER;
795 /* Add the shortcut */
796 lpPList->lpPData->uRef++;
797 lpNewPList->lpPData = lpPList->lpPData;
799 /* Add the player to the list of players for this group */
800 DPQ_INSERT(lpGData->players,lpNewPList,players);
802 /* Let the SP know that we've added a player to the group */
803 if( This->dp2->spData.lpCB->AddPlayerToGroup )
805 DPSP_ADDPLAYERTOGROUPDATA data;
807 TRACE( "Calling SP AddPlayerToGroup\n" );
809 data.idPlayer = idPlayer;
810 data.idGroup = idGroup;
811 data.lpISP = This->dp2->spData.lpISP;
813 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
816 /* Inform all other peers of the addition of player to the group. If there are
817 * no peers keep this event quiet.
818 * Also, if this event was the result of another machine sending it to us,
819 * don't bother rebroadcasting it.
821 if( ( lpMsgHdr == NULL ) &&
822 This->dp2->lpSessionDesc &&
823 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
825 DPMSG_ADDPLAYERTOGROUP msg;
826 msg.dwType = DPSYS_ADDPLAYERTOGROUP;
828 msg.dpIdGroup = idGroup;
829 msg.dpIdPlayer = idPlayer;
831 /* FIXME: Correct to just use send effectively? */
832 /* FIXME: Should size include data w/ message or just message "header" */
833 /* FIXME: Check return code */
834 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
837 return DP_OK;
840 static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
841 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
843 ICOM_THIS(IDirectPlay2Impl,iface);
844 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, TRUE );
847 static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
848 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
850 ICOM_THIS(IDirectPlay2Impl,iface);
851 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, FALSE );
854 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi )
856 HRESULT hr = DP_OK;
858 TRACE("(%p)->(%u)\n", This, bAnsi );
860 /* FIXME: Need to find a new host I assume (how?) */
861 /* FIXME: Need to destroy all local groups */
862 /* FIXME: Need to migrate all remotely visible players to the new host */
864 /* Invoke the SP callback to inform of session close */
865 if( This->dp2->spData.lpCB->CloseEx )
867 DPSP_CLOSEDATA data;
869 TRACE( "Calling SP CloseEx\n" );
871 data.lpISP = This->dp2->spData.lpISP;
873 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
876 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
878 TRACE( "Calling SP Close (obsolete interface)\n" );
880 hr = (*This->dp2->spData.lpCB->Close)();
883 return hr;
886 static HRESULT WINAPI DirectPlay2AImpl_Close
887 ( LPDIRECTPLAY2A iface )
889 ICOM_THIS(IDirectPlay2Impl,iface);
890 return DP_IF_Close( This, TRUE );
893 static HRESULT WINAPI DirectPlay2WImpl_Close
894 ( LPDIRECTPLAY2 iface )
896 ICOM_THIS(IDirectPlay2Impl,iface);
897 return DP_IF_Close( This, FALSE );
900 static
901 lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, LPDPID lpid,
902 LPDPNAME lpName, DWORD dwFlags,
903 DPID idParent, BOOL bAnsi )
905 lpGroupData lpGData;
907 /* Allocate the new space and add to end of high level group list */
908 lpGData = (lpGroupData) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
909 sizeof( *lpGData ) );
911 if( lpGData == NULL )
913 return NULL;
916 DPQ_INIT(lpGData->groups);
917 DPQ_INIT(lpGData->players);
919 /* Set the desired player ID - no sanity checking to see if it exists */
920 lpGData->dpid = *lpid;
922 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
924 /* FIXME: Should we check that the parent exists? */
925 lpGData->parent = idParent;
927 /* FIXME: Should we validate the dwFlags? */
928 lpGData->dwFlags = dwFlags;
930 TRACE( "Created group id 0x%08lx\n", *lpid );
932 return lpGData;
935 /* This method assumes that all links to it are already deleted */
936 static void
937 DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid )
939 lpGroupList lpGList;
941 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
943 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
945 if( lpGList == NULL )
947 ERR( "DPID 0x%08lx not found\n", dpid );
948 return;
951 if( --(lpGList->lpGData->uRef) )
953 FIXME( "Why is this not the last reference to group?\n" );
954 DebugBreak();
957 /* Delete player */
958 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
959 HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
961 /* Remove and Delete Player List object */
962 HeapFree( GetProcessHeap(), 0, lpGList );
966 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid )
968 lpGroupList lpGroups;
970 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
972 if( dpid == DPID_SYSTEM_GROUP )
974 return This->dp2->lpSysGroup;
976 else
978 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
981 if( lpGroups == NULL )
983 return NULL;
986 return lpGroups->lpGData;
989 static HRESULT WINAPI DP_IF_CreateGroup
990 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
991 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
992 DWORD dwFlags, BOOL bAnsi )
994 lpGroupData lpGData;
996 TRACE( "(%p)->(%p,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
997 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
998 dwFlags, bAnsi );
1000 /* If the name is not specified, we must provide one */
1001 if( DPID_UNKNOWN == *lpidGroup )
1003 /* If we are the name server, we decide on the group ids. If not, we
1004 * must ask for one before attempting a creation.
1006 if( This->dp2->bHostInterface )
1008 *lpidGroup = DP_NextObjectId();
1010 else
1012 *lpidGroup = DP_GetRemoteNextObjectId();
1016 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
1017 DPID_NOPARENT_GROUP, bAnsi );
1019 if( lpGData == NULL )
1021 return DPERR_CANTADDPLAYER; /* yes player not group */
1024 if( DPID_SYSTEM_GROUP == *lpidGroup )
1026 This->dp2->lpSysGroup = lpGData;
1027 TRACE( "Inserting system group\n" );
1029 else
1031 /* Insert into the system group */
1032 lpGroupList lpGroup = (lpGroupList) HeapAlloc( GetProcessHeap(),
1033 HEAP_ZERO_MEMORY,
1034 sizeof( *lpGroup ) );
1035 lpGroup->lpGData = lpGData;
1037 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
1040 /* Something is now referencing this data */
1041 lpGData->uRef++;
1043 /* Set all the important stuff for the group */
1044 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
1046 /* FIXME: We should only create the system group if GetCaps returns
1047 * DPCAPS_GROUPOPTIMIZED.
1050 /* Let the SP know that we've created this group */
1051 if( This->dp2->spData.lpCB->CreateGroup )
1053 DPSP_CREATEGROUPDATA data;
1054 DWORD dwCreateFlags = 0;
1056 TRACE( "Calling SP CreateGroup\n" );
1058 if( *lpidGroup == DPID_NOPARENT_GROUP )
1059 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
1061 if( lpMsgHdr == NULL )
1062 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1064 if( dwFlags & DPGROUP_HIDDEN )
1065 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
1067 data.idGroup = *lpidGroup;
1068 data.dwFlags = dwCreateFlags;
1069 data.lpSPMessageHeader = lpMsgHdr;
1070 data.lpISP = This->dp2->spData.lpISP;
1072 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1075 /* Inform all other peers of the creation of a new group. If there are
1076 * no peers keep this event quiet.
1077 * Also if this message was sent to us, don't rebroadcast.
1079 if( ( lpMsgHdr == NULL ) &&
1080 This->dp2->lpSessionDesc &&
1081 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1083 DPMSG_CREATEPLAYERORGROUP msg;
1084 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1086 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1087 msg.dpId = *lpidGroup;
1088 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1089 msg.lpData = lpData;
1090 msg.dwDataSize = dwDataSize;
1091 msg.dpnName = *lpGroupName;
1092 msg.dpIdParent = DPID_NOPARENT_GROUP;
1093 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
1095 /* FIXME: Correct to just use send effectively? */
1096 /* FIXME: Should size include data w/ message or just message "header" */
1097 /* FIXME: Check return code */
1098 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
1099 0, 0, NULL, NULL, bAnsi );
1102 return DP_OK;
1105 static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
1106 ( LPDIRECTPLAY2A iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1107 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1109 *lpidGroup = DPID_UNKNOWN;
1111 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1112 lpGroupName, lpData, dwDataSize, dwFlags, TRUE );
1115 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
1116 ( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1117 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1119 *lpidGroup = DPID_UNKNOWN;
1121 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1122 lpGroupName, lpData, dwDataSize, dwFlags, FALSE );
1126 static void
1127 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
1128 LPVOID lpData, DWORD dwDataSize )
1130 /* Clear out the data with this player */
1131 if( ( dwFlags & DPSET_LOCAL ) &&
1132 ( lpGData->dwLocalDataSize != 0 )
1135 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
1136 lpGData->lpLocalData = NULL;
1137 lpGData->dwLocalDataSize = 0;
1139 if( ( dwFlags & DPSET_REMOTE ) &&
1140 ( lpGData->dwRemoteDataSize != 0 )
1143 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
1144 lpGData->lpRemoteData = NULL;
1145 lpGData->dwRemoteDataSize = 0;
1148 /* Reallocate for new data */
1149 if( lpData != NULL )
1151 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1152 sizeof( dwDataSize ) );
1153 CopyMemory( lpNewData, lpData, dwDataSize );
1155 if( dwFlags & DPSET_REMOTE )
1157 lpGData->lpRemoteData = lpNewData;
1158 lpGData->dwRemoteDataSize = dwDataSize;
1161 if( dwFlags & DPSET_LOCAL )
1163 lpGData->lpLocalData = lpData;
1164 lpGData->dwLocalDataSize = dwDataSize;
1170 /* This function will just create the storage for the new player. */
1171 static
1172 lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid,
1173 LPDPNAME lpName, DWORD dwFlags,
1174 HANDLE hEvent, BOOL bAnsi )
1176 lpPlayerData lpPData;
1178 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
1180 /* Allocate the storage for the player and associate it with list element */
1181 lpPData = (lpPlayerData) HeapAlloc( GetProcessHeap(),
1182 HEAP_ZERO_MEMORY,
1183 sizeof( *lpPData ) );
1184 if( lpPData == NULL )
1186 return NULL;
1189 /* Set the desired player ID */
1190 lpPData->dpid = *lpid;
1192 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
1194 lpPData->dwFlags = dwFlags;
1196 /* If we were given an event handle, duplicate it */
1197 if( hEvent != 0 )
1199 if( !DuplicateHandle( GetCurrentProcess(), hEvent,
1200 GetCurrentProcess(), &lpPData->hEvent,
1201 0, FALSE, DUPLICATE_SAME_ACCESS )
1204 /* FIXME: Memory leak */
1205 ERR( "Can't duplicate player msg handle %x\n", hEvent );
1209 /* Initialize the SP data section */
1210 lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData();
1212 TRACE( "Created player id 0x%08lx\n", *lpid );
1214 return lpPData;
1217 /* Delete the contents of the DPNAME struct */
1218 static void
1219 DP_DeleteDPNameStruct( LPDPNAME lpDPName )
1221 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u1.lpszShortNameA );
1222 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u2.lpszLongNameA );
1225 /* This method assumes that all links to it are already deleted */
1226 static void
1227 DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid )
1229 lpPlayerList lpPList;
1231 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
1233 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1235 if( lpPList == NULL )
1237 ERR( "DPID 0x%08lx not found\n", dpid );
1238 return;
1241 /* Verify that this is the last reference to the data */
1242 if( --(lpPList->lpPData->uRef) )
1244 FIXME( "Why is this not the last reference to player?\n" );
1245 DebugBreak();
1248 /* Delete player */
1249 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1251 CloseHandle( lpPList->lpPData->hEvent );
1252 HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
1254 /* Delete Player List object */
1255 HeapFree( GetProcessHeap(), 0, lpPList );
1258 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid )
1260 lpPlayerList lpPlayers;
1262 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
1264 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1266 return lpPlayers;
1269 /* Basic area for Dst must already be allocated */
1270 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi )
1272 if( lpSrc == NULL )
1274 ZeroMemory( lpDst, sizeof( *lpDst ) );
1275 lpDst->dwSize = sizeof( *lpDst );
1276 return TRUE;
1279 if( lpSrc->dwSize != sizeof( *lpSrc) )
1281 return FALSE;
1284 /* Delete any existing pointers */
1285 if( lpDst->u1.lpszShortNameA )
1287 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1290 if( lpDst->u2.lpszLongNameA )
1292 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1295 /* Copy as required */
1296 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1298 if( bAnsi )
1300 if( lpSrc->u1.lpszShortNameA )
1302 lpDst->u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), 0,
1303 strlen(lpSrc->u1.lpszShortNameA)+1 );
1304 strcpy( lpDst->u1.lpszShortNameA, lpSrc->u1.lpszShortNameA );
1306 if( lpSrc->u2.lpszLongNameA )
1308 lpDst->u2.lpszLongNameA = HeapAlloc( GetProcessHeap(), 0,
1309 strlen(lpSrc->u2.lpszLongNameA)+1 );
1310 strcpy( lpDst->u2.lpszLongNameA, lpSrc->u2.lpszLongNameA );
1313 else
1315 if( lpSrc->u1.lpszShortNameA )
1317 lpDst->u1.lpszShortName = HeapAlloc( GetProcessHeap(), 0,
1318 (strlenW(lpSrc->u1.lpszShortName)+1)*sizeof(WCHAR) );
1319 strcpyW( lpDst->u1.lpszShortName, lpSrc->u1.lpszShortName );
1321 if( lpSrc->u2.lpszLongNameA )
1323 lpDst->u2.lpszLongName = HeapAlloc( GetProcessHeap(), 0,
1324 (strlenW(lpSrc->u2.lpszLongName)+1)*sizeof(WCHAR) );
1325 strcpyW( lpDst->u2.lpszLongName, lpSrc->u2.lpszLongName );
1329 return TRUE;
1332 static void
1333 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
1334 LPVOID lpData, DWORD dwDataSize )
1336 /* Clear out the data with this player */
1337 if( ( dwFlags & DPSET_LOCAL ) &&
1338 ( lpPData->dwLocalDataSize != 0 )
1341 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
1342 lpPData->lpLocalData = NULL;
1343 lpPData->dwLocalDataSize = 0;
1345 if( ( dwFlags & DPSET_REMOTE ) &&
1346 ( lpPData->dwRemoteDataSize != 0 )
1349 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
1350 lpPData->lpRemoteData = NULL;
1351 lpPData->dwRemoteDataSize = 0;
1354 /* Reallocate for new data */
1355 if( lpData != NULL )
1357 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1358 sizeof( dwDataSize ) );
1359 CopyMemory( lpNewData, lpData, dwDataSize );
1361 if( dwFlags & DPSET_REMOTE )
1363 lpPData->lpRemoteData = lpNewData;
1364 lpPData->dwRemoteDataSize = dwDataSize;
1367 if( dwFlags & DPSET_LOCAL )
1369 lpPData->lpLocalData = lpData;
1370 lpPData->dwLocalDataSize = dwDataSize;
1376 static HRESULT WINAPI DP_IF_CreatePlayer
1377 ( IDirectPlay2Impl* This,
1378 LPVOID lpMsgHdr, /* NULL for local creation, non NULL for remote creation */
1379 LPDPID lpidPlayer,
1380 LPDPNAME lpPlayerName,
1381 HANDLE hEvent,
1382 LPVOID lpData,
1383 DWORD dwDataSize,
1384 DWORD dwFlags,
1385 BOOL bAnsi )
1387 HANDLE hr = DP_OK;
1388 lpPlayerData lpPData;
1389 lpPlayerList lpPList;
1390 DWORD dwCreateFlags = 0;
1392 TRACE( "(%p)->(%p,%p,%d,%p,0x%08lx,0x%08lx,%u)\n",
1393 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1394 dwDataSize, dwFlags, bAnsi );
1396 if( dwFlags == 0 )
1398 dwFlags = DPPLAYER_SPECTATOR;
1401 if( lpidPlayer == NULL )
1403 return DPERR_INVALIDPARAMS;
1407 /* Determine the creation flags for the player. These will be passed
1408 * to the name server if requesting a player id and to the SP when
1409 * informing it of the player creation
1412 if( dwFlags & DPPLAYER_SERVERPLAYER )
1414 if( *lpidPlayer == DPID_SERVERPLAYER )
1416 /* Server player for the host interface */
1417 dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
1419 else if( *lpidPlayer == DPID_NAME_SERVER )
1421 /* Name server - master of everything */
1422 dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
1424 else
1426 /* Server player for a non host interface */
1427 dwCreateFlags |= DPLAYI_PLAYER_SYSPLAYER;
1431 if( lpMsgHdr == NULL )
1432 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1435 /* Verify we know how to handle all the flags */
1436 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1437 ( dwFlags & DPPLAYER_SPECTATOR )
1441 /* Assume non fatal failure */
1442 ERR( "unknown dwFlags = 0x%08lx\n", dwFlags );
1445 /* If the name is not specified, we must provide one */
1446 if( *lpidPlayer == DPID_UNKNOWN )
1448 /* If we are the session master, we dish out the group/player ids */
1449 if( This->dp2->bHostInterface )
1451 *lpidPlayer = DP_NextObjectId();
1453 else
1455 hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer );
1457 if( FAILED(hr) )
1459 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1460 return hr;
1464 else
1466 /* FIXME: Would be nice to perhaps verify that we don't already have
1467 * this player.
1471 /* FIXME: Should we be storing these dwFlags or the creation ones? */
1472 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwFlags,
1473 hEvent, bAnsi );
1475 if( lpPData == NULL )
1477 return DPERR_CANTADDPLAYER;
1480 /* Create the list object and link it in */
1481 lpPList = (lpPlayerList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1482 sizeof( *lpPList ) );
1483 if( lpPList == NULL )
1485 FIXME( "Memory leak\n" );
1486 return DPERR_CANTADDPLAYER;
1489 lpPData->uRef = 1;
1490 lpPList->lpPData = lpPData;
1492 /* Add the player to the system group */
1493 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1495 /* Update the information and send it to all players in the session */
1496 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
1498 /* Let the SP know that we've created this player */
1499 if( This->dp2->spData.lpCB->CreatePlayer )
1501 DPSP_CREATEPLAYERDATA data;
1503 data.idPlayer = *lpidPlayer;
1504 data.dwFlags = dwCreateFlags;
1505 data.lpSPMessageHeader = lpMsgHdr;
1506 data.lpISP = This->dp2->spData.lpISP;
1508 TRACE( "Calling SP CreatePlayer 0x%08lx: dwFlags: 0x%08lx lpMsgHdr: %p\n",
1509 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
1511 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1514 if( FAILED(hr) )
1516 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1517 return hr;
1520 /* Now let the SP know that this player is a member of the system group */
1521 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1523 DPSP_ADDPLAYERTOGROUPDATA data;
1525 data.idPlayer = *lpidPlayer;
1526 data.idGroup = DPID_SYSTEM_GROUP;
1527 data.lpISP = This->dp2->spData.lpISP;
1529 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1531 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1534 if( FAILED(hr) )
1536 ERR( "Failed to add player to sys group with sp: %s\n",
1537 DPLAYX_HresultToString(hr) );
1538 return hr;
1541 #if 1
1542 if( This->dp2->bHostInterface == FALSE )
1544 /* Let the name server know about the creation of this player */
1545 /* FIXME: Is this only to be done for the creation of a server player or
1546 * is this used for regular players? If only for server players, move
1547 * this call to DP_SecureOpen(...);
1549 #if 0
1550 TRACE( "Sending message to self to get my addr\n" );
1551 DP_MSG_ToSelf( This, *lpidPlayer ); /* This is a hack right now */
1552 #endif
1554 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
1556 #else
1557 /* Inform all other peers of the creation of a new player. If there are
1558 * no peers keep this quiet.
1559 * Also, if this was a remote event, no need to rebroadcast it.
1561 if( ( lpMsgHdr == NULL ) &&
1562 This->dp2->lpSessionDesc &&
1563 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1565 DPMSG_CREATEPLAYERORGROUP msg;
1566 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1568 msg.dwPlayerType = DPPLAYERTYPE_PLAYER;
1569 msg.dpId = *lpidPlayer;
1570 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */
1571 msg.lpData = lpData;
1572 msg.dwDataSize = dwDataSize;
1573 msg.dpnName = *lpPlayerName;
1574 msg.dpIdParent = DPID_NOPARENT_GROUP;
1575 msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
1577 /* FIXME: Correct to just use send effectively? */
1578 /* FIXME: Should size include data w/ message or just message "header" */
1579 /* FIXME: Check return code */
1580 hr = DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
1581 sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
1583 #endif
1585 return hr;
1588 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
1589 ( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1590 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1592 ICOM_THIS(IDirectPlay2Impl,iface);
1594 if( dwFlags & DPPLAYER_SERVERPLAYER )
1596 *lpidPlayer = DPID_SERVERPLAYER;
1598 else
1600 *lpidPlayer = DPID_UNKNOWN;
1603 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1604 lpData, dwDataSize, dwFlags, TRUE );
1607 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
1608 ( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1609 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1611 ICOM_THIS(IDirectPlay2Impl,iface);
1613 if( dwFlags & DPPLAYER_SERVERPLAYER )
1615 *lpidPlayer = DPID_SERVERPLAYER;
1617 else
1619 *lpidPlayer = DPID_UNKNOWN;
1622 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1623 lpData, dwDataSize, dwFlags, FALSE );
1626 static DPID DP_GetRemoteNextObjectId(void)
1628 FIXME( ":stub\n" );
1630 /* Hack solution */
1631 return DP_NextObjectId();
1634 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
1635 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
1636 DPID idPlayer, BOOL bAnsi )
1638 HRESULT hr = DP_OK;
1640 lpGroupData lpGData;
1641 lpPlayerList lpPList;
1643 TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
1644 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
1646 /* Find the group */
1647 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1649 return DPERR_INVALIDGROUP;
1652 /* Find the player */
1653 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
1655 return DPERR_INVALIDPLAYER;
1658 /* Remove the player shortcut from the group */
1659 DPQ_REMOVE_ENTRY( lpGData->players, players, lpPData->dpid, ==, idPlayer, lpPList );
1661 if( lpPList == NULL )
1663 return DPERR_INVALIDPLAYER;
1666 /* One less reference */
1667 lpPList->lpPData->uRef--;
1669 /* Delete the Player List element */
1670 HeapFree( GetProcessHeap(), 0, lpPList );
1672 /* Inform the SP if they care */
1673 if( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1675 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1677 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1679 data.idPlayer = idPlayer;
1680 data.idGroup = idGroup;
1681 data.lpISP = This->dp2->spData.lpISP;
1683 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1686 /* Need to send a DELETEPLAYERFROMGROUP message */
1687 FIXME( "Need to send a message\n" );
1689 return hr;
1692 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
1693 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
1695 ICOM_THIS(IDirectPlay2Impl,iface);
1696 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, TRUE );
1699 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
1700 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
1702 ICOM_THIS(IDirectPlay2Impl,iface);
1703 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, FALSE );
1706 typedef struct _DPRGOPContext
1708 IDirectPlay3Impl* This;
1709 BOOL bAnsi;
1710 DPID idGroup;
1711 } DPRGOPContext, *lpDPRGOPContext;
1713 static BOOL CALLBACK
1714 cbRemoveGroupOrPlayer(
1715 DPID dpId,
1716 DWORD dwPlayerType,
1717 LPCDPNAME lpName,
1718 DWORD dwFlags,
1719 LPVOID lpContext )
1721 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1723 TRACE( "Removing element:0x%08lx (type:0x%08lx) from element:0x%08lx\n",
1724 dpId, dwPlayerType, lpCtxt->idGroup );
1726 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1728 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt->This, lpCtxt->idGroup,
1729 dpId )
1733 ERR( "Unable to delete group 0x%08lx from group 0x%08lx\n",
1734 dpId, lpCtxt->idGroup );
1737 else
1739 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl*)lpCtxt->This,
1740 NULL, lpCtxt->idGroup,
1741 dpId, lpCtxt->bAnsi )
1745 ERR( "Unable to delete player 0x%08lx from grp 0x%08lx\n",
1746 dpId, lpCtxt->idGroup );
1750 return TRUE; /* Continue enumeration */
1753 static HRESULT WINAPI DP_IF_DestroyGroup
1754 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi )
1756 lpGroupData lpGData;
1757 DPRGOPContext context;
1759 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
1760 This, lpMsgHdr, idGroup, bAnsi );
1762 /* Find the group */
1763 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1765 return DPERR_INVALIDPLAYER; /* yes player */
1768 context.This = (IDirectPlay3Impl*)This;
1769 context.bAnsi = bAnsi;
1770 context.idGroup = idGroup;
1772 /* Remove all players that this group has */
1773 DP_IF_EnumGroupPlayers( This, idGroup, NULL,
1774 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1776 /* Remove all links to groups that this group has since this is dp3 */
1777 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This, idGroup, NULL,
1778 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1780 /* Remove this group from the parent group - if it has one */
1781 if( ( idGroup != DPID_SYSTEM_GROUP ) &&
1782 ( lpGData->parent != DPID_SYSTEM_GROUP )
1785 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl*)This, lpGData->parent,
1786 idGroup );
1789 /* Now delete this group data and list from the system group */
1790 DP_DeleteGroup( This, idGroup );
1792 /* Let the SP know that we've destroyed this group */
1793 if( This->dp2->spData.lpCB->DeleteGroup )
1795 DPSP_DELETEGROUPDATA data;
1797 FIXME( "data.dwFlags is incorrect\n" );
1799 data.idGroup = idGroup;
1800 data.dwFlags = 0;
1801 data.lpISP = This->dp2->spData.lpISP;
1803 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1806 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1808 return DP_OK;
1811 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
1812 ( LPDIRECTPLAY2A iface, DPID idGroup )
1814 ICOM_THIS(IDirectPlay2Impl,iface);
1815 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
1818 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
1819 ( LPDIRECTPLAY2 iface, DPID idGroup )
1821 ICOM_THIS(IDirectPlay2Impl,iface);
1822 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
1825 typedef struct _DPFAGContext
1827 IDirectPlay2Impl* This;
1828 DPID idPlayer;
1829 BOOL bAnsi;
1830 } DPFAGContext, *lpDPFAGContext;
1832 static HRESULT WINAPI DP_IF_DestroyPlayer
1833 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi )
1835 DPFAGContext cbContext;
1837 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
1838 This, lpMsgHdr, idPlayer, bAnsi );
1840 if( DP_FindPlayer( This, idPlayer ) == NULL )
1842 return DPERR_INVALIDPLAYER;
1845 /* FIXME: If the player is remote, we must be the host to delete this */
1847 cbContext.This = This;
1848 cbContext.idPlayer = idPlayer;
1849 cbContext.bAnsi = bAnsi;
1851 /* Find each group and call DeletePlayerFromGroup if the player is a
1852 member of the group */
1853 DP_IF_EnumGroups( This, NULL, cbDeletePlayerFromAllGroups,
1854 (LPVOID)&cbContext, DPENUMGROUPS_ALL, bAnsi );
1856 /* Now delete player and player list from the sys group */
1857 DP_DeletePlayer( This, idPlayer );
1859 /* Let the SP know that we've destroyed this group */
1860 if( This->dp2->spData.lpCB->DeletePlayer )
1862 DPSP_DELETEPLAYERDATA data;
1864 FIXME( "data.dwFlags is incorrect\n" );
1866 data.idPlayer = idPlayer;
1867 data.dwFlags = 0;
1868 data.lpISP = This->dp2->spData.lpISP;
1870 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
1873 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
1875 return DP_OK;
1878 static BOOL CALLBACK
1879 cbDeletePlayerFromAllGroups(
1880 DPID dpId,
1881 DWORD dwPlayerType,
1882 LPCDPNAME lpName,
1883 DWORD dwFlags,
1884 LPVOID lpContext )
1886 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
1888 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1890 DP_IF_DeletePlayerFromGroup( lpCtxt->This, NULL, dpId, lpCtxt->idPlayer,
1891 lpCtxt->bAnsi );
1893 /* Enumerate all groups in this group since this will normally only
1894 * be called for top level groups
1896 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)lpCtxt->This,
1897 dpId, NULL,
1898 cbDeletePlayerFromAllGroups,
1899 (LPVOID)lpContext, DPENUMGROUPS_ALL,
1900 lpCtxt->bAnsi );
1903 else
1905 ERR( "Group callback has dwPlayerType = 0x%08lx\n", dwPlayerType );
1908 return TRUE;
1911 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
1912 ( LPDIRECTPLAY2A iface, DPID idPlayer )
1914 ICOM_THIS(IDirectPlay2Impl,iface);
1915 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
1918 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
1919 ( LPDIRECTPLAY2 iface, DPID idPlayer )
1921 ICOM_THIS(IDirectPlay2Impl,iface);
1922 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
1925 static HRESULT WINAPI DP_IF_EnumGroupPlayers
1926 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
1927 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1928 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1930 lpGroupData lpGData;
1931 lpPlayerList lpPList;
1933 FIXME("(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
1934 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
1935 lpContext, dwFlags, bAnsi );
1937 /* Find the group */
1938 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1940 return DPERR_INVALIDGROUP;
1943 if( DPQ_IS_EMPTY( lpGData->players ) )
1945 return DP_OK;
1948 lpPList = DPQ_FIRST( lpGData->players );
1950 /* Walk the players in this group */
1951 for( ;; )
1953 /* We do not enum the name server or app server as they are of no
1954 * concequence to the end user.
1956 if( ( lpPList->lpPData->dpid != DPID_NAME_SERVER ) &&
1957 ( lpPList->lpPData->dpid != DPID_SERVERPLAYER )
1961 /* FIXME: Need to add stuff for dwFlags checking */
1963 if( !lpEnumPlayersCallback2( lpPList->lpPData->dpid, DPPLAYERTYPE_PLAYER,
1964 &lpPList->lpPData->name,
1965 lpPList->lpPData->dwFlags,
1966 lpContext )
1969 /* User requested break */
1970 return DP_OK;
1974 if( DPQ_IS_ENDOFLIST( lpPList->players ) )
1976 break;
1979 lpPList = DPQ_NEXT( lpPList->players );
1982 return DP_OK;
1985 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
1986 ( LPDIRECTPLAY2A iface, DPID idGroup, LPGUID lpguidInstance,
1987 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1988 LPVOID lpContext, DWORD dwFlags )
1990 ICOM_THIS(IDirectPlay2Impl,iface);
1991 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
1992 lpEnumPlayersCallback2, lpContext,
1993 dwFlags, TRUE );
1996 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
1997 ( LPDIRECTPLAY2 iface, DPID idGroup, LPGUID lpguidInstance,
1998 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1999 LPVOID lpContext, DWORD dwFlags )
2001 ICOM_THIS(IDirectPlay2Impl,iface);
2002 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2003 lpEnumPlayersCallback2, lpContext,
2004 dwFlags, FALSE );
2007 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2008 static HRESULT WINAPI DP_IF_EnumGroups
2009 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2010 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2011 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2013 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This,
2014 DPID_SYSTEM_GROUP, lpguidInstance,
2015 lpEnumPlayersCallback2, lpContext,
2016 dwFlags, bAnsi );
2019 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
2020 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2021 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2022 LPVOID lpContext, DWORD dwFlags )
2024 ICOM_THIS(IDirectPlay2Impl,iface);
2025 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2026 lpContext, dwFlags, TRUE );
2029 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
2030 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2031 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2032 LPVOID lpContext, DWORD dwFlags )
2034 ICOM_THIS(IDirectPlay2Impl,iface);
2035 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2036 lpContext, dwFlags, FALSE );
2039 static HRESULT WINAPI DP_IF_EnumPlayers
2040 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2041 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2042 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2044 return DP_IF_EnumGroupPlayers( This, DPID_SYSTEM_GROUP, lpguidInstance,
2045 lpEnumPlayersCallback2, lpContext,
2046 dwFlags, bAnsi );
2049 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
2050 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2051 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2052 LPVOID lpContext, DWORD dwFlags )
2054 ICOM_THIS(IDirectPlay2Impl,iface);
2055 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2056 lpContext, dwFlags, TRUE );
2059 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
2060 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2061 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2062 LPVOID lpContext, DWORD dwFlags )
2064 ICOM_THIS(IDirectPlay2Impl,iface);
2065 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2066 lpContext, dwFlags, FALSE );
2069 /* This function should call the registered callback function that the user
2070 passed into EnumSessions for each entry available.
2072 static void DP_InvokeEnumSessionCallbacks
2073 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2074 LPVOID lpNSInfo,
2075 DWORD dwTimeout,
2076 LPVOID lpContext )
2078 LPDPSESSIONDESC2 lpSessionDesc;
2080 FIXME( ": not checking for conditions\n" );
2082 /* Not sure if this should be pruning but it's convenient */
2083 NS_PruneSessionCache( lpNSInfo );
2085 NS_ResetSessionEnumeration( lpNSInfo );
2087 /* Enumerate all sessions */
2088 /* FIXME: Need to indicate ANSI */
2089 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2091 TRACE( "EnumSessionsCallback2 invoked\n" );
2092 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2094 return;
2098 /* Invoke one last time to indicate that there is no more to come */
2099 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2102 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2104 EnumSessionAsyncCallbackData* data = (EnumSessionAsyncCallbackData*)lpContext;
2105 HANDLE hSuicideRequest = data->hSuicideRequest;
2106 DWORD dwTimeout = data->dwTimeout;
2108 TRACE( "Thread started with timeout = 0x%08lx\n", dwTimeout );
2110 for( ;; )
2112 HRESULT hr;
2114 /* Sleep up to dwTimeout waiting for request to terminate thread */
2115 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2117 TRACE( "Thread terminating on terminate request\n" );
2118 break;
2121 /* Now resend the enum request */
2122 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2123 data->dwEnumSessionFlags,
2124 data->lpSpData );
2126 if( FAILED(hr) )
2128 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2129 /* FIXME: Should we kill this thread? How to inform the main thread? */
2134 TRACE( "Thread terminating\n" );
2136 /* Clean up the thread data */
2137 CloseHandle( hSuicideRequest );
2138 HeapFree( GetProcessHeap(), 0, lpContext );
2140 /* FIXME: Need to have some notification to main app thread that this is
2141 * dead. It would serve two purposes. 1) allow sync on termination
2142 * so that we don't actually send something to ourselves when we
2143 * become name server (race condition) and 2) so that if we die
2144 * abnormally something else will be able to tell.
2147 return 1;
2150 static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
2152 /* Does a thread exist? If so we were doing an async enum session */
2153 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2155 TRACE( "Killing EnumSession thread %u\n",
2156 This->dp2->hEnumSessionThread );
2158 /* Request that the thread kill itself nicely */
2159 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2160 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2162 /* We no longer need to know about the thread */
2163 CloseHandle( This->dp2->hEnumSessionThread );
2165 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2169 static HRESULT WINAPI DP_IF_EnumSessions
2170 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2171 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2172 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2174 HRESULT hr = DP_OK;
2176 TRACE( "(%p)->(%p,0x%08lx,%p,%p,0x%08lx,%u)\n",
2177 This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags,
2178 bAnsi );
2180 /* Can't enumerate if the interface is already open */
2181 if( This->dp2->bConnectionOpen )
2183 return DPERR_GENERIC;
2186 #if 1
2187 /* The loading of a lobby provider _seems_ to require a backdoor loading
2188 * of the service provider to also associate with this DP object. This is
2189 * because the app doesn't seem to have to call EnumConnections and
2190 * InitializeConnection for the SP before calling this method. As such
2191 * we'll do their dirty work for them with a quick hack so as to always
2192 * load the TCP/IP service provider.
2194 * The correct solution would seem to involve creating a dialog box which
2195 * contains the possible SPs. These dialog boxes most likely follow SDK
2196 * examples.
2198 if( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
2200 LPVOID lpConnection;
2201 DWORD dwSize;
2203 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2205 if( !DP_BuildSPCompoundAddr( (LPGUID)&DPSPGUID_TCPIP, &lpConnection, &dwSize ) )
2207 ERR( "Can't build compound addr\n" );
2208 return DPERR_GENERIC;
2211 hr = DP_IF_InitializeConnection( (IDirectPlay3Impl*)This, lpConnection,
2212 0, bAnsi );
2213 if( FAILED(hr) )
2215 return hr;
2218 /* Free up the address buffer */
2219 HeapFree( GetProcessHeap(), 0, lpConnection );
2221 /* The SP is now initialized */
2222 This->dp2->bSPInitialized = TRUE;
2224 #endif
2227 /* Use the service provider default? */
2228 if( dwTimeout == 0 )
2230 DPCAPS spCaps;
2231 spCaps.dwSize = sizeof( spCaps );
2233 DP_IF_GetCaps( This, &spCaps, 0 );
2234 dwTimeout = spCaps.dwTimeout;
2236 /* The service provider doesn't provide one either! */
2237 if( dwTimeout == 0 )
2239 /* Provide the TCP/IP default */
2240 dwTimeout = DPMSG_WAIT_5_SECS;
2244 if( dwFlags & DPENUMSESSIONS_STOPASYNC )
2246 DP_KillEnumSessionThread( This );
2247 return hr;
2250 /* FIXME: Interface locking sucks in this method */
2251 if( ( dwFlags & DPENUMSESSIONS_ASYNC ) )
2253 /* Enumerate everything presently in the local session cache */
2254 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2255 This->dp2->lpNameServerData, dwTimeout,
2256 lpContext );
2259 /* See if we've already created a thread to service this interface */
2260 if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2262 DWORD dwThreadId;
2264 /* Send the first enum request inline since the user may cancel a dialog
2265 * if one is presented. Also, may also have a connecting return code.
2267 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2268 dwFlags, &This->dp2->spData );
2270 if( !FAILED(hr) )
2272 EnumSessionAsyncCallbackData* lpData
2273 = (EnumSessionAsyncCallbackData*)HeapAlloc( GetProcessHeap(),
2274 HEAP_ZERO_MEMORY,
2275 sizeof( *lpData ) );
2276 /* FIXME: need to kill the thread on object deletion */
2277 lpData->lpSpData = &This->dp2->spData;
2279 CopyMemory( &lpData->requestGuid, &lpsd->guidApplication, sizeof(GUID) );
2280 lpData->dwEnumSessionFlags = dwFlags;
2281 lpData->dwTimeout = dwTimeout;
2283 This->dp2->hKillEnumSessionThreadEvent =
2284 CreateEventA( NULL, TRUE, FALSE, NULL );
2286 if( !DuplicateHandle( GetCurrentProcess(),
2287 This->dp2->hKillEnumSessionThreadEvent,
2288 GetCurrentProcess(),
2289 &lpData->hSuicideRequest,
2290 0, FALSE, DUPLICATE_SAME_ACCESS )
2293 ERR( "Can't duplicate thread killing handle\n" );
2296 TRACE( ": creating EnumSessionsRequest thread\n" );
2298 This->dp2->hEnumSessionThread = CreateThread( NULL,
2300 DP_EnumSessionsSendAsyncRequestThread,
2301 lpData,
2303 &dwThreadId );
2307 else
2309 /* Invalidate the session cache for the interface */
2310 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2312 /* Send the broadcast for session enumeration */
2313 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2314 dwFlags,
2315 &This->dp2->spData );
2318 SleepEx( dwTimeout, FALSE );
2320 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2321 This->dp2->lpNameServerData, dwTimeout,
2322 lpContext );
2325 return hr;
2328 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2329 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2330 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2331 LPVOID lpContext, DWORD dwFlags )
2333 ICOM_THIS(IDirectPlay2Impl,iface);
2334 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2335 lpContext, dwFlags, TRUE );
2338 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2339 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2340 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2341 LPVOID lpContext, DWORD dwFlags )
2343 ICOM_THIS(IDirectPlay2Impl,iface);
2344 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2345 lpContext, dwFlags, FALSE );
2348 static HRESULT WINAPI DP_IF_GetPlayerCaps
2349 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
2350 DWORD dwFlags )
2352 DPSP_GETCAPSDATA data;
2354 TRACE("(%p)->(0x%08lx,%p,0x%08lx)\n", This, idPlayer, lpDPCaps, dwFlags);
2356 /* Query the service provider */
2357 data.idPlayer = idPlayer;
2358 data.dwFlags = dwFlags;
2359 data.lpCaps = lpDPCaps;
2360 data.lpISP = This->dp2->spData.lpISP;
2362 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2365 static HRESULT WINAPI DP_IF_GetCaps
2366 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags )
2368 return DP_IF_GetPlayerCaps( This, DPID_ALLPLAYERS, lpDPCaps, dwFlags );
2371 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2372 ( LPDIRECTPLAY2A iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2374 ICOM_THIS(IDirectPlay2Impl,iface);
2375 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2378 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2379 ( LPDIRECTPLAY2 iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2381 ICOM_THIS(IDirectPlay2Impl,iface);
2382 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2385 static HRESULT WINAPI DP_IF_GetGroupData
2386 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2387 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2389 lpGroupData lpGData;
2390 DWORD dwRequiredBufferSize;
2391 LPVOID lpCopyDataFrom;
2393 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
2394 This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi );
2396 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2398 return DPERR_INVALIDGROUP;
2401 /* How much buffer is required? */
2402 if( dwFlags & DPSET_REMOTE )
2404 dwRequiredBufferSize = lpGData->dwRemoteDataSize;
2405 lpCopyDataFrom = lpGData->lpRemoteData;
2407 else if( dwFlags & DPSET_LOCAL )
2409 dwRequiredBufferSize = lpGData->dwLocalDataSize;
2410 lpCopyDataFrom = lpGData->lpLocalData;
2412 else
2414 ERR( "Neither local or remote data requested!?!\n" );
2415 dwRequiredBufferSize = 0;
2416 lpCopyDataFrom = NULL;
2419 /* Is the user requesting to know how big a buffer is required? */
2420 if( ( lpData == NULL ) ||
2421 ( *lpdwDataSize < dwRequiredBufferSize )
2424 *lpdwDataSize = dwRequiredBufferSize;
2425 return DPERR_BUFFERTOOSMALL;
2428 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2430 return DP_OK;
2433 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2434 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2435 LPDWORD lpdwDataSize, DWORD dwFlags )
2437 ICOM_THIS(IDirectPlay2Impl,iface);
2438 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2439 dwFlags, TRUE );
2442 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2443 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2444 LPDWORD lpdwDataSize, DWORD dwFlags )
2446 ICOM_THIS(IDirectPlay2Impl,iface);
2447 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2448 dwFlags, FALSE );
2451 static HRESULT WINAPI DP_IF_GetGroupName
2452 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2453 LPDWORD lpdwDataSize, BOOL bAnsi )
2455 lpGroupData lpGData;
2456 LPDPNAME lpName = (LPDPNAME)lpData;
2457 DWORD dwRequiredDataSize;
2459 FIXME("(%p)->(0x%08lx,%p,%p,%u) ANSI ignored\n",
2460 This, idGroup, lpData, lpdwDataSize, bAnsi );
2462 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2464 return DPERR_INVALIDGROUP;
2467 dwRequiredDataSize = lpGData->name.dwSize;
2469 if( lpGData->name.u1.lpszShortNameA )
2471 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
2474 if( lpGData->name.u2.lpszLongNameA )
2476 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
2479 if( ( lpData == NULL ) ||
2480 ( *lpdwDataSize < dwRequiredDataSize )
2483 *lpdwDataSize = dwRequiredDataSize;
2484 return DPERR_BUFFERTOOSMALL;
2487 /* Copy the structure */
2488 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2490 if( lpGData->name.u1.lpszShortNameA )
2492 strcpy( ((BYTE*)lpName)+lpGData->name.dwSize,
2493 lpGData->name.u1.lpszShortNameA );
2495 else
2497 lpName->u1.lpszShortNameA = NULL;
2500 if( lpGData->name.u1.lpszShortNameA )
2502 strcpy( ((BYTE*)lpName)+lpGData->name.dwSize,
2503 lpGData->name.u2.lpszLongNameA );
2505 else
2507 lpName->u2.lpszLongNameA = NULL;
2510 return DP_OK;
2513 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2514 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2515 LPDWORD lpdwDataSize )
2517 ICOM_THIS(IDirectPlay2Impl,iface);
2518 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2521 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2522 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2523 LPDWORD lpdwDataSize )
2525 ICOM_THIS(IDirectPlay2Impl,iface);
2526 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2529 static HRESULT WINAPI DP_IF_GetMessageCount
2530 ( IDirectPlay2Impl* This, DPID idPlayer,
2531 LPDWORD lpdwCount, BOOL bAnsi )
2533 FIXME("(%p)->(0x%08lx,%p,%u): stub\n", This, idPlayer, lpdwCount, bAnsi );
2534 return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer,
2535 DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL,
2536 bAnsi );
2539 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2540 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDWORD lpdwCount )
2542 ICOM_THIS(IDirectPlay2Impl,iface);
2543 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, TRUE );
2546 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2547 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDWORD lpdwCount )
2549 ICOM_THIS(IDirectPlay2Impl,iface);
2550 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, FALSE );
2553 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2554 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2556 ICOM_THIS(IDirectPlay2Impl,iface);
2557 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2558 return DP_OK;
2561 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2562 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2564 ICOM_THIS(IDirectPlay2Impl,iface);
2565 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2566 return DP_OK;
2569 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2570 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2571 DWORD dwFlags )
2573 ICOM_THIS(IDirectPlay2Impl,iface);
2574 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2577 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2578 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2579 DWORD dwFlags )
2581 ICOM_THIS(IDirectPlay2Impl,iface);
2582 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2585 static HRESULT WINAPI DP_IF_GetPlayerData
2586 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2587 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2589 lpPlayerList lpPList;
2590 DWORD dwRequiredBufferSize;
2591 LPVOID lpCopyDataFrom;
2593 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
2594 This, idPlayer, lpData, lpdwDataSize, dwFlags, bAnsi );
2596 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2598 return DPERR_INVALIDPLAYER;
2601 /* How much buffer is required? */
2602 if( dwFlags & DPSET_REMOTE )
2604 dwRequiredBufferSize = lpPList->lpPData->dwRemoteDataSize;
2605 lpCopyDataFrom = lpPList->lpPData->lpRemoteData;
2607 else if( dwFlags & DPSET_LOCAL )
2609 dwRequiredBufferSize = lpPList->lpPData->dwLocalDataSize;
2610 lpCopyDataFrom = lpPList->lpPData->lpLocalData;
2612 else
2614 ERR( "Neither local or remote data requested!?!\n" );
2615 dwRequiredBufferSize = 0;
2616 lpCopyDataFrom = NULL;
2619 /* Is the user requesting to know how big a buffer is required? */
2620 if( ( lpData == NULL ) ||
2621 ( *lpdwDataSize < dwRequiredBufferSize )
2624 *lpdwDataSize = dwRequiredBufferSize;
2625 return DPERR_BUFFERTOOSMALL;
2628 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2630 return DP_OK;
2633 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2634 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2635 LPDWORD lpdwDataSize, DWORD dwFlags )
2637 ICOM_THIS(IDirectPlay2Impl,iface);
2638 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2639 dwFlags, TRUE );
2642 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2643 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2644 LPDWORD lpdwDataSize, DWORD dwFlags )
2646 ICOM_THIS(IDirectPlay2Impl,iface);
2647 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2648 dwFlags, FALSE );
2651 static HRESULT WINAPI DP_IF_GetPlayerName
2652 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2653 LPDWORD lpdwDataSize, BOOL bAnsi )
2655 lpPlayerList lpPList;
2656 LPDPNAME lpName = (LPDPNAME)lpData;
2657 DWORD dwRequiredDataSize;
2659 FIXME( "(%p)->(0x%08lx,%p,%p,%u): ANSI \n",
2660 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2662 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2664 return DPERR_INVALIDPLAYER;
2667 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
2669 if( lpPList->lpPData->name.u1.lpszShortNameA )
2671 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
2674 if( lpPList->lpPData->name.u2.lpszLongNameA )
2676 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
2679 if( ( lpData == NULL ) ||
2680 ( *lpdwDataSize < dwRequiredDataSize )
2683 *lpdwDataSize = dwRequiredDataSize;
2684 return DPERR_BUFFERTOOSMALL;
2687 /* Copy the structure */
2688 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
2690 if( lpPList->lpPData->name.u1.lpszShortNameA )
2692 strcpy( ((BYTE*)lpName)+lpPList->lpPData->name.dwSize,
2693 lpPList->lpPData->name.u1.lpszShortNameA );
2695 else
2697 lpName->u1.lpszShortNameA = NULL;
2700 if( lpPList->lpPData->name.u1.lpszShortNameA )
2702 strcpy( ((BYTE*)lpName)+lpPList->lpPData->name.dwSize,
2703 lpPList->lpPData->name.u2.lpszLongNameA );
2705 else
2707 lpName->u2.lpszLongNameA = NULL;
2710 return DP_OK;
2713 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2714 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2715 LPDWORD lpdwDataSize )
2717 ICOM_THIS(IDirectPlay2Impl,iface);
2718 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
2721 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2722 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2723 LPDWORD lpdwDataSize )
2725 ICOM_THIS(IDirectPlay2Impl,iface);
2726 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
2729 static HRESULT WINAPI DP_GetSessionDesc
2730 ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize,
2731 BOOL bAnsi )
2733 DWORD dwRequiredSize;
2735 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
2737 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
2739 return DPERR_INVALIDPARAMS;
2742 /* FIXME: Get from This->dp2->lpSessionDesc */
2743 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
2745 if ( ( lpData == NULL ) ||
2746 ( *lpdwDataSize < dwRequiredSize )
2749 *lpdwDataSize = dwRequiredSize;
2750 return DPERR_BUFFERTOOSMALL;
2753 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
2755 return DP_OK;
2758 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
2759 ( LPDIRECTPLAY2A iface, LPVOID lpData, LPDWORD lpdwDataSize )
2761 ICOM_THIS(IDirectPlay2Impl,iface);
2762 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2765 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
2766 ( LPDIRECTPLAY2 iface, LPVOID lpData, LPDWORD lpdwDataSize )
2768 ICOM_THIS(IDirectPlay2Impl,iface);
2769 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2772 /* Intended only for COM compatibility. Always returns an error. */
2773 static HRESULT WINAPI DirectPlay2AImpl_Initialize
2774 ( LPDIRECTPLAY2A iface, LPGUID lpGUID )
2776 ICOM_THIS(IDirectPlay2Impl,iface);
2777 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2778 return DPERR_ALREADYINITIALIZED;
2781 /* Intended only for COM compatibility. Always returns an error. */
2782 static HRESULT WINAPI DirectPlay2WImpl_Initialize
2783 ( LPDIRECTPLAY2 iface, LPGUID lpGUID )
2785 ICOM_THIS(IDirectPlay2Impl,iface);
2786 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2787 return DPERR_ALREADYINITIALIZED;
2791 static HRESULT WINAPI DP_SecureOpen
2792 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
2793 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
2794 BOOL bAnsi )
2796 HRESULT hr = DP_OK;
2798 FIXME( "(%p)->(%p,0x%08lx,%p,%p): partial stub\n",
2799 This, lpsd, dwFlags, lpSecurity, lpCredentials );
2801 if( This->dp2->bConnectionOpen )
2803 TRACE( ": rejecting already open connection.\n" );
2804 return DPERR_ALREADYINITIALIZED;
2807 /* If we're enumerating, kill the thread */
2808 DP_KillEnumSessionThread( This );
2810 if( dwFlags & DPOPEN_CREATE )
2812 /* Rightoo - this computer is the host and the local computer needs to be
2813 the name server so that others can join this session */
2814 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
2816 This->dp2->bHostInterface = TRUE;
2818 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
2819 if( FAILED( hr ) )
2821 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
2822 return hr;
2826 /* Invoke the conditional callback for the service provider */
2827 if( This->dp2->spData.lpCB->Open )
2829 DPSP_OPENDATA data;
2831 FIXME( "Not all data fields are correct. Need new parameter\n" );
2833 data.bCreate = (dwFlags & DPOPEN_CREATE ) ? TRUE : FALSE;
2834 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
2835 : NS_GetNSAddr( This->dp2->lpNameServerData );
2836 data.lpISP = This->dp2->spData.lpISP;
2837 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) ? TRUE : FALSE;
2838 data.dwOpenFlags = dwFlags;
2839 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
2841 hr = (*This->dp2->spData.lpCB->Open)(&data);
2842 if( FAILED( hr ) )
2844 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
2845 return hr;
2850 /* Create the system group of which everything is a part of */
2851 DPID systemGroup = DPID_SYSTEM_GROUP;
2853 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
2854 NULL, 0, 0, TRUE );
2858 if( dwFlags & DPOPEN_JOIN )
2860 DPID dpidServerId = DPID_UNKNOWN;
2862 /* Create the server player for this interface. This way we can receive
2863 * messages for this session.
2865 /* FIXME: I suppose that we should be setting an event for a receive
2866 * type of thing. That way the messaging thread could know to wake
2867 * up. DPlay would then trigger the hEvent for the player the
2868 * message is directed to.
2870 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
2872 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
2875 else if( dwFlags & DPOPEN_CREATE )
2877 DPID dpidNameServerId = DPID_NAME_SERVER;
2879 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
2880 0, DPPLAYER_SERVERPLAYER, bAnsi );
2883 if( FAILED(hr) )
2885 ERR( "Couldn't create name server/system player: %s\n",
2886 DPLAYX_HresultToString(hr) );
2889 return hr;
2892 static HRESULT WINAPI DirectPlay2AImpl_Open
2893 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2895 ICOM_THIS(IDirectPlay2Impl,iface);
2896 TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags );
2897 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, TRUE );
2900 static HRESULT WINAPI DirectPlay2WImpl_Open
2901 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2903 ICOM_THIS(IDirectPlay2Impl,iface);
2904 TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags );
2905 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, FALSE );
2908 static HRESULT WINAPI DP_IF_Receive
2909 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
2910 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi )
2912 LPDPMSG lpMsg = NULL;
2914 FIXME( "(%p)->(%p,%p,0x%08lx,%p,%p,%u): stub\n",
2915 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
2917 if( dwFlags == 0 )
2919 dwFlags = DPRECEIVE_ALL;
2922 /* If the lpData is NULL, we must be peeking the message */
2923 if( ( lpData == NULL ) &&
2924 !( dwFlags & DPRECEIVE_PEEK )
2927 return DPERR_INVALIDPARAMS;
2930 if( dwFlags & DPRECEIVE_ALL )
2932 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
2934 if( !( dwFlags & DPRECEIVE_PEEK ) )
2936 FIXME( "Remove from queue\n" );
2939 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
2940 ( dwFlags & DPRECEIVE_FROMPLAYER )
2943 FIXME( "Find matching message 0x%08lx\n", dwFlags );
2945 else
2947 ERR( "Hmmm..dwFlags 0x%08lx\n", dwFlags );
2950 if( lpMsg == NULL )
2952 return DPERR_NOMESSAGES;
2955 /* Copy into the provided buffer */
2956 CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
2958 return DP_OK;
2961 static HRESULT WINAPI DirectPlay2AImpl_Receive
2962 ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo,
2963 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
2965 ICOM_THIS(IDirectPlay2Impl,iface);
2966 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
2967 lpData, lpdwDataSize, TRUE );
2970 static HRESULT WINAPI DirectPlay2WImpl_Receive
2971 ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo,
2972 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
2974 ICOM_THIS(IDirectPlay2Impl,iface);
2975 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
2976 lpData, lpdwDataSize, FALSE );
2979 static HRESULT WINAPI DirectPlay2AImpl_Send
2980 ( LPDIRECTPLAY2A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
2982 ICOM_THIS(IDirectPlay2Impl,iface);
2983 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
2984 0, 0, NULL, NULL, TRUE );
2987 static HRESULT WINAPI DirectPlay2WImpl_Send
2988 ( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
2990 ICOM_THIS(IDirectPlay2Impl,iface);
2991 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
2992 0, 0, NULL, NULL, FALSE );
2995 static HRESULT WINAPI DP_IF_SetGroupData
2996 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2997 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
2999 lpGroupData lpGData;
3001 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
3002 This, idGroup, lpData, dwDataSize, dwFlags, bAnsi );
3004 /* Parameter check */
3005 if( ( lpData == NULL ) &&
3006 ( dwDataSize != 0 )
3009 return DPERR_INVALIDPARAMS;
3012 /* Find the pointer to the data for this player */
3013 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3015 return DPERR_INVALIDOBJECT;
3018 if( dwFlags & DPSET_REMOTE )
3020 FIXME( "Was this group created by this interface?\n" );
3021 /* FIXME: If this is a remote update need to allow it but not
3022 * send a message.
3026 DP_SetGroupData( lpGData, dwFlags, lpData, dwDataSize );
3028 /* FIXME: Only send a message if this group is local to the session otherwise
3029 * it will have been rejected above
3031 if( dwFlags & DPSET_REMOTE )
3033 FIXME( "Send msg?\n" );
3036 return DP_OK;
3039 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
3040 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
3041 DWORD dwDataSize, DWORD dwFlags )
3043 ICOM_THIS(IDirectPlay2Impl,iface);
3044 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, TRUE );
3047 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
3048 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
3049 DWORD dwDataSize, DWORD dwFlags )
3051 ICOM_THIS(IDirectPlay2Impl,iface);
3052 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, FALSE );
3055 static HRESULT WINAPI DP_IF_SetGroupName
3056 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
3057 DWORD dwFlags, BOOL bAnsi )
3059 lpGroupData lpGData;
3061 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n", This, idGroup,
3062 lpGroupName, dwFlags, bAnsi );
3064 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3066 return DPERR_INVALIDGROUP;
3069 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
3071 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3072 FIXME( "Message not sent and dwFlags ignored\n" );
3074 return DP_OK;
3077 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
3078 ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName,
3079 DWORD dwFlags )
3081 ICOM_THIS(IDirectPlay2Impl,iface);
3082 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
3085 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
3086 ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName,
3087 DWORD dwFlags )
3089 ICOM_THIS(IDirectPlay2Impl,iface);
3090 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
3093 static HRESULT WINAPI DP_IF_SetPlayerData
3094 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
3095 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3097 lpPlayerList lpPList;
3099 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
3100 This, idPlayer, lpData, dwDataSize, dwFlags, bAnsi );
3102 /* Parameter check */
3103 if( ( lpData == NULL ) &&
3104 ( dwDataSize != 0 )
3107 return DPERR_INVALIDPARAMS;
3110 /* Find the pointer to the data for this player */
3111 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3113 return DPERR_INVALIDPLAYER;
3116 if( dwFlags & DPSET_REMOTE )
3118 FIXME( "Was this group created by this interface?\n" );
3119 /* FIXME: If this is a remote update need to allow it but not
3120 * send a message.
3124 DP_SetPlayerData( lpPList->lpPData, dwFlags, lpData, dwDataSize );
3126 if( dwFlags & DPSET_REMOTE )
3128 FIXME( "Send msg?\n" );
3131 return DP_OK;
3134 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3135 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
3136 DWORD dwDataSize, DWORD dwFlags )
3138 ICOM_THIS(IDirectPlay2Impl,iface);
3139 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3140 dwFlags, TRUE );
3143 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3144 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
3145 DWORD dwDataSize, DWORD dwFlags )
3147 ICOM_THIS(IDirectPlay2Impl,iface);
3148 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3149 dwFlags, FALSE );
3152 static HRESULT WINAPI DP_IF_SetPlayerName
3153 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
3154 DWORD dwFlags, BOOL bAnsi )
3156 lpPlayerList lpPList;
3158 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n",
3159 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3161 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3163 return DPERR_INVALIDGROUP;
3166 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3168 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3169 FIXME( "Message not sent and dwFlags ignored\n" );
3171 return DP_OK;
3174 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3175 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName,
3176 DWORD dwFlags )
3178 ICOM_THIS(IDirectPlay2Impl,iface);
3179 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3182 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3183 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName,
3184 DWORD dwFlags )
3186 ICOM_THIS(IDirectPlay2Impl,iface);
3187 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3190 static HRESULT WINAPI DP_SetSessionDesc
3191 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
3192 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3194 DWORD dwRequiredSize;
3195 LPDPSESSIONDESC2 lpTempSessDesc;
3197 TRACE( "(%p)->(%p,0x%08lx,%u,%u)\n",
3198 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3200 if( dwFlags )
3202 return DPERR_INVALIDPARAMS;
3205 /* Only the host is allowed to update the session desc */
3206 if( !This->dp2->bHostInterface )
3208 return DPERR_ACCESSDENIED;
3211 /* FIXME: Copy into This->dp2->lpSessionDesc */
3212 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3213 lpTempSessDesc = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
3214 HEAP_ZERO_MEMORY,
3215 dwRequiredSize );
3217 if( lpTempSessDesc == NULL )
3219 return DPERR_OUTOFMEMORY;
3222 /* Free the old */
3223 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3225 This->dp2->lpSessionDesc = lpTempSessDesc;
3227 /* Set the new */
3228 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3230 /* If this is an external invocation of the interface, we should be
3231 * letting everyone know that things have changed. Otherwise this is
3232 * just an initialization and it doesn't need to be propagated.
3234 if( !bInitial )
3236 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3239 return DP_OK;
3242 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3243 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3245 ICOM_THIS(IDirectPlay2Impl,iface);
3246 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3249 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3250 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3252 ICOM_THIS(IDirectPlay2Impl,iface);
3253 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3256 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3257 DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3259 DWORD dwSize = 0;
3261 if( lpSessDesc == NULL )
3263 /* Hmmm..don't need any size? */
3264 ERR( "NULL lpSessDesc\n" );
3265 return dwSize;
3268 dwSize += sizeof( *lpSessDesc );
3270 if( bAnsi )
3272 if( lpSessDesc->u1.lpszSessionNameA )
3274 dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1;
3277 if( lpSessDesc->u2.lpszPasswordA )
3279 dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1;
3282 else /* UNICODE */
3284 if( lpSessDesc->u1.lpszSessionName )
3286 dwSize += sizeof( WCHAR ) *
3287 ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 );
3290 if( lpSessDesc->u2.lpszPassword )
3292 dwSize += sizeof( WCHAR ) *
3293 ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 );
3297 return dwSize;
3300 /* Assumes that contugous buffers are already allocated. */
3301 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3302 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3304 BYTE* lpStartOfFreeSpace;
3306 if( lpSessionDest == NULL )
3308 ERR( "NULL lpSessionDest\n" );
3309 return;
3312 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3314 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3316 if( bAnsi )
3318 if( lpSessionSrc->u1.lpszSessionNameA )
3320 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3321 lpSessionDest->u1.lpszSessionNameA );
3322 lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3323 lpStartOfFreeSpace +=
3324 lstrlenA( (LPSTR)lpSessionDest->u1.lpszSessionNameA ) + 1;
3327 if( lpSessionSrc->u2.lpszPasswordA )
3329 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3330 lpSessionDest->u2.lpszPasswordA );
3331 lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3332 lpStartOfFreeSpace +=
3333 lstrlenA( (LPSTR)lpSessionDest->u2.lpszPasswordA ) + 1;
3336 else /* UNICODE */
3338 if( lpSessionSrc->u1.lpszSessionName )
3340 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3341 lpSessionDest->u1.lpszSessionName );
3342 lpSessionDest->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3343 lpStartOfFreeSpace += sizeof(WCHAR) *
3344 ( lstrlenW( (LPWSTR)lpSessionDest->u1.lpszSessionName ) + 1 );
3347 if( lpSessionSrc->u2.lpszPassword )
3349 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3350 lpSessionDest->u2.lpszPassword );
3351 lpSessionDest->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3352 lpStartOfFreeSpace += sizeof(WCHAR) *
3353 ( lstrlenW( (LPWSTR)lpSessionDest->u2.lpszPassword ) + 1 );
3359 static HRESULT WINAPI DP_IF_AddGroupToGroup
3360 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3362 lpGroupData lpGParentData;
3363 lpGroupData lpGData;
3364 lpGroupList lpNewGList;
3366 TRACE( "(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup );
3368 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3370 return DPERR_INVALIDGROUP;
3373 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3375 return DPERR_INVALIDGROUP;
3378 /* Create a player list (ie "shortcut" ) */
3379 lpNewGList = (lpGroupList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3380 sizeof( *lpNewGList ) );
3381 if( lpNewGList == NULL )
3383 return DPERR_CANTADDPLAYER;
3386 /* Add the shortcut */
3387 lpGData->uRef++;
3388 lpNewGList->lpGData = lpGData;
3390 /* Add the player to the list of players for this group */
3391 DPQ_INSERT( lpGData->groups, lpNewGList, groups );
3393 /* Send a ADDGROUPTOGROUP message */
3394 FIXME( "Not sending message\n" );
3396 return DP_OK;
3399 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3400 ( LPDIRECTPLAY3A iface, DPID idParentGroup, DPID idGroup )
3402 ICOM_THIS(IDirectPlay3Impl,iface);
3403 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3406 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3407 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3409 ICOM_THIS(IDirectPlay3Impl,iface);
3410 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3413 static HRESULT WINAPI DP_IF_CreateGroupInGroup
3414 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
3415 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
3416 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3418 lpGroupData lpGParentData;
3419 lpGroupList lpGList;
3420 lpGroupData lpGData;
3422 TRACE( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
3423 This, idParentGroup, lpidGroup, lpGroupName, lpData,
3424 dwDataSize, dwFlags, bAnsi );
3426 /* Verify that the specified parent is valid */
3427 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This,
3428 idParentGroup ) ) == NULL
3431 return DPERR_INVALIDGROUP;
3434 lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName,
3435 dwFlags, idParentGroup, bAnsi );
3437 if( lpGData == NULL )
3439 return DPERR_CANTADDPLAYER; /* yes player not group */
3442 /* Something else is referencing this data */
3443 lpGData->uRef++;
3445 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
3447 /* The list has now been inserted into the interface group list. We now
3448 need to put a "shortcut" to this group in the parent group */
3449 lpGList = (lpGroupList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3450 sizeof( *lpGList ) );
3451 if( lpGList == NULL )
3453 FIXME( "Memory leak\n" );
3454 return DPERR_CANTADDPLAYER; /* yes player not group */
3457 lpGList->lpGData = lpGData;
3459 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
3461 /* Let the SP know that we've created this group */
3462 if( This->dp2->spData.lpCB->CreateGroup )
3464 DPSP_CREATEGROUPDATA data;
3466 TRACE( "Calling SP CreateGroup\n" );
3468 data.idGroup = *lpidGroup;
3469 data.dwFlags = dwFlags;
3470 data.lpSPMessageHeader = lpMsgHdr;
3471 data.lpISP = This->dp2->spData.lpISP;
3473 (*This->dp2->spData.lpCB->CreateGroup)( &data );
3476 /* Inform all other peers of the creation of a new group. If there are
3477 * no peers keep this quiet.
3479 if( This->dp2->lpSessionDesc &&
3480 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
3482 DPMSG_CREATEPLAYERORGROUP msg;
3484 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
3485 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
3486 msg.dpId = *lpidGroup;
3487 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
3488 msg.lpData = lpData;
3489 msg.dwDataSize = dwDataSize;
3490 msg.dpnName = *lpGroupName;
3492 /* FIXME: Correct to just use send effectively? */
3493 /* FIXME: Should size include data w/ message or just message "header" */
3494 /* FIXME: Check return code */
3495 DP_SendEx( (IDirectPlay2Impl*)This,
3496 DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
3497 0, 0, NULL, NULL, bAnsi );
3500 return DP_OK;
3503 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3504 ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup,
3505 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3506 DWORD dwFlags )
3508 ICOM_THIS(IDirectPlay3Impl,iface);
3510 *lpidGroup = DPID_UNKNOWN;
3512 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3513 lpGroupName, lpData, dwDataSize, dwFlags,
3514 TRUE );
3517 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3518 ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup,
3519 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3520 DWORD dwFlags )
3522 ICOM_THIS(IDirectPlay3Impl,iface);
3524 *lpidGroup = DPID_UNKNOWN;
3526 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3527 lpGroupName, lpData, dwDataSize,
3528 dwFlags, FALSE );
3531 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
3532 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3534 lpGroupList lpGList;
3535 lpGroupData lpGParentData;
3537 TRACE("(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup );
3539 /* Is the parent group valid? */
3540 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3542 return DPERR_INVALIDGROUP;
3545 /* Remove the group from the parent group queue */
3546 DPQ_REMOVE_ENTRY( lpGParentData->groups, groups, lpGData->dpid, ==, idGroup, lpGList );
3548 if( lpGList == NULL )
3550 return DPERR_INVALIDGROUP;
3553 /* Decrement the ref count */
3554 lpGList->lpGData->uRef--;
3556 /* Free up the list item */
3557 HeapFree( GetProcessHeap(), 0, lpGList );
3559 /* Should send a DELETEGROUPFROMGROUP message */
3560 FIXME( "message not sent\n" );
3562 return DP_OK;
3565 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3566 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3568 ICOM_THIS(IDirectPlay3Impl,iface);
3569 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3572 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3573 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3575 ICOM_THIS(IDirectPlay3Impl,iface);
3576 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3579 static
3580 BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
3581 LPDWORD lpdwBufSize )
3583 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3584 HRESULT hr;
3586 dpCompoundAddress.dwDataSize = sizeof( GUID );
3587 memcpy( &dpCompoundAddress.guidDataType, &DPAID_ServiceProvider,
3588 sizeof( GUID ) ) ;
3589 dpCompoundAddress.lpData = lpcSpGuid;
3591 *lplpAddrBuf = NULL;
3592 *lpdwBufSize = 0;
3594 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3595 lpdwBufSize, TRUE );
3597 if( hr != DPERR_BUFFERTOOSMALL )
3599 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3600 return FALSE;
3603 /* Now allocate the buffer */
3604 *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3605 *lpdwBufSize );
3607 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3608 lpdwBufSize, TRUE );
3609 if( FAILED(hr) )
3611 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3612 return FALSE;
3615 return TRUE;
3618 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
3619 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3621 ICOM_THIS(IDirectPlay3Impl,iface);
3622 TRACE("(%p)->(%p,%p,%p,0x%08lx)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3624 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
3625 if( dwFlags == 0 )
3627 dwFlags = DPCONNECTION_DIRECTPLAY;
3630 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
3631 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) )
3634 return DPERR_INVALIDFLAGS;
3637 if( !lpEnumCallback || !*lpEnumCallback )
3639 return DPERR_INVALIDPARAMS;
3642 /* Enumerate DirectPlay service providers */
3643 if( dwFlags & DPCONNECTION_DIRECTPLAY )
3645 HKEY hkResult;
3646 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3647 LPSTR guidDataSubKey = "Guid";
3648 char subKeyName[51];
3649 DWORD dwIndex, sizeOfSubKeyName=50;
3650 FILETIME filetime;
3652 /* Need to loop over the service providers in the registry */
3653 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3654 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3656 /* Hmmm. Does this mean that there are no service providers? */
3657 ERR(": no service providers?\n");
3658 return DP_OK;
3662 /* Traverse all the service providers we have available */
3663 for( dwIndex=0;
3664 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3665 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3666 ++dwIndex, sizeOfSubKeyName=51 )
3669 HKEY hkServiceProvider;
3670 GUID serviceProviderGUID;
3671 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3672 char returnBuffer[51];
3673 WCHAR buff[51];
3674 DPNAME dpName;
3675 BOOL bBuildPass;
3677 LPVOID lpAddressBuffer = NULL;
3678 DWORD dwAddressBufferSize = 0;
3680 TRACE(" this time through: %s\n", subKeyName );
3682 /* Get a handle for this particular service provider */
3683 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3684 &hkServiceProvider ) != ERROR_SUCCESS )
3686 ERR(": what the heck is going on?\n" );
3687 continue;
3690 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3691 NULL, &returnTypeGUID, returnBuffer,
3692 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3694 ERR(": missing GUID registry data members\n" );
3695 continue;
3698 /* FIXME: Check return types to ensure we're interpreting data right */
3699 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3700 CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
3701 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3703 /* Fill in the DPNAME struct for the service provider */
3704 dpName.dwSize = sizeof( dpName );
3705 dpName.dwFlags = 0;
3706 dpName.u1.lpszShortNameA = subKeyName;
3707 dpName.u2.lpszLongNameA = NULL;
3709 /* Create the compound address for the service provider.
3710 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
3711 nast stuff. This may be why the native dll just gets around this little bit by
3712 allocating an 80 byte buffer which isn't even a filled with a valid compound
3713 address. Oh well. Creating a proper compound address is the way to go anyways
3714 despite this method taking slightly more heap space and realtime :) */
3716 bBuildPass = DP_BuildSPCompoundAddr( &serviceProviderGUID,
3717 &lpAddressBuffer,
3718 &dwAddressBufferSize );
3719 if( !bBuildPass )
3721 ERR( "Can't build compound addr\n" );
3722 return DPERR_GENERIC;
3725 /* The enumeration will return FALSE if we are not to continue */
3726 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3727 &dpName, DPCONNECTION_DIRECTPLAY, lpContext ) )
3729 return DP_OK;
3734 /* Enumerate DirectPlayLobby service providers */
3735 if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY )
3737 HKEY hkResult;
3738 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3739 LPSTR guidDataSubKey = "Guid";
3740 char subKeyName[51];
3741 DWORD dwIndex, sizeOfSubKeyName=50;
3742 FILETIME filetime;
3744 /* Need to loop over the service providers in the registry */
3745 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3746 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3748 /* Hmmm. Does this mean that there are no service providers? */
3749 ERR(": no service providers?\n");
3750 return DP_OK;
3754 /* Traverse all the lobby providers we have available */
3755 for( dwIndex=0;
3756 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3757 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3758 ++dwIndex, sizeOfSubKeyName=51 )
3761 HKEY hkServiceProvider;
3762 GUID serviceProviderGUID;
3763 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3764 char returnBuffer[51];
3765 WCHAR buff[51];
3766 DPNAME dpName;
3767 HRESULT hr;
3769 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3770 LPVOID lpAddressBuffer = NULL;
3771 DWORD dwAddressBufferSize = 0;
3773 TRACE(" this time through: %s\n", subKeyName );
3775 /* Get a handle for this particular service provider */
3776 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3777 &hkServiceProvider ) != ERROR_SUCCESS )
3779 ERR(": what the heck is going on?\n" );
3780 continue;
3783 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3784 NULL, &returnTypeGUID, returnBuffer,
3785 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3787 ERR(": missing GUID registry data members\n" );
3788 continue;
3791 /* FIXME: Check return types to ensure we're interpreting data right */
3792 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3793 CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
3794 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3796 /* Fill in the DPNAME struct for the service provider */
3797 dpName.dwSize = sizeof( dpName );
3798 dpName.dwFlags = 0;
3799 dpName.u1.lpszShortNameA = subKeyName;
3800 dpName.u2.lpszLongNameA = NULL;
3802 /* Create the compound address for the service provider.
3803 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
3804 nast stuff. This may be why the native dll just gets around this little bit by
3805 allocating an 80 byte buffer which isn't even a filled with a valid compound
3806 address. Oh well. Creating a proper compound address is the way to go anyways
3807 despite this method taking slightly more heap space and realtime :) */
3809 dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
3810 dpCompoundAddress.dwDataSize = sizeof( GUID );
3811 dpCompoundAddress.lpData = &serviceProviderGUID;
3813 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3814 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
3816 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3817 return hr;
3820 /* Now allocate the buffer */
3821 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
3823 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3824 &dwAddressBufferSize, TRUE ) ) != DP_OK )
3826 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3827 return hr;
3830 /* The enumeration will return FALSE if we are not to continue */
3831 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3832 &dpName, DPCONNECTION_DIRECTPLAYLOBBY, lpContext ) )
3834 return DP_OK;
3839 return DP_OK;
3842 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
3843 ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3845 ICOM_THIS(IDirectPlay3Impl,iface);
3846 FIXME("(%p)->(%p,%p,%p,0x%08lx): stub\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3847 return DP_OK;
3850 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
3851 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
3852 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
3853 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
3855 lpGroupList lpGList;
3856 lpGroupData lpGData;
3858 FIXME( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
3859 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
3860 lpContext, dwFlags, bAnsi );
3862 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3864 return DPERR_INVALIDGROUP;
3867 if( DPQ_IS_EMPTY( lpGData->groups ) )
3869 return DP_OK;
3872 lpGList = DPQ_FIRST( lpGData->groups );
3874 for( ;; )
3876 /* FIXME: Should check dwFlags for match here */
3878 if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP,
3879 &lpGList->lpGData->name, dwFlags,
3880 lpContext ) )
3882 return DP_OK; /* User requested break */
3885 if( DPQ_IS_ENDOFLIST( lpGList->groups ) )
3887 break;
3890 lpGList = DPQ_NEXT( lpGList->groups );
3894 return DP_OK;
3897 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
3898 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3899 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3900 DWORD dwFlags )
3902 ICOM_THIS(IDirectPlay3Impl,iface);
3903 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3904 lpEnumPlayersCallback2, lpContext, dwFlags,
3905 TRUE );
3908 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
3909 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3910 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3911 DWORD dwFlags )
3913 ICOM_THIS(IDirectPlay3Impl,iface);
3914 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3915 lpEnumPlayersCallback2, lpContext, dwFlags,
3916 FALSE );
3919 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
3920 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3922 ICOM_THIS(IDirectPlay3Impl,iface);
3923 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3924 return DP_OK;
3927 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
3928 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3930 ICOM_THIS(IDirectPlay3Impl,iface);
3931 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3932 return DP_OK;
3935 BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
3936 REFGUID guidDataType,
3937 DWORD dwDataSize,
3938 LPCVOID lpData,
3939 LPVOID lpContext )
3941 /* Looking for the GUID of the provider to load */
3942 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
3943 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
3946 TRACE( "Found SP/LP (%s) %s (data size = 0x%08lx)\n",
3947 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
3949 if( dwDataSize != sizeof( GUID ) )
3951 ERR( "Invalid sp/lp guid size 0x%08lx\n", dwDataSize );
3954 memcpy( lpContext, lpData, dwDataSize );
3956 /* There shouldn't be more than 1 GUID/compound address */
3957 return FALSE;
3960 /* Still waiting for what we want */
3961 return TRUE;
3965 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
3966 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
3968 UINT i;
3969 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3970 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3971 LPCSTR guidDataSubKey = "Guid";
3972 LPCSTR majVerDataSubKey = "dwReserved1";
3973 LPCSTR minVerDataSubKey = "dwReserved2";
3974 LPCSTR pathSubKey = "Path";
3976 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
3978 /* FIXME: Cloned code with a quick hack. */
3979 for( i=0; i<2; i++ )
3981 HKEY hkResult;
3982 LPCSTR searchSubKey;
3983 char subKeyName[51];
3984 DWORD dwIndex, sizeOfSubKeyName=50;
3985 FILETIME filetime;
3987 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
3988 *lpbIsDpSp = (i == 0) ? TRUE : FALSE;
3991 /* Need to loop over the service providers in the registry */
3992 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3993 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3995 /* Hmmm. Does this mean that there are no service providers? */
3996 ERR(": no service providers?\n");
3997 return 0;
4000 /* Traverse all the service providers we have available */
4001 for( dwIndex=0;
4002 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4003 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4004 ++dwIndex, sizeOfSubKeyName=51 )
4007 HKEY hkServiceProvider;
4008 GUID serviceProviderGUID;
4009 DWORD returnType, sizeOfReturnBuffer = 255;
4010 char returnBuffer[256];
4011 WCHAR buff[51];
4012 DWORD dwTemp, len;
4014 TRACE(" this time through: %s\n", subKeyName );
4016 /* Get a handle for this particular service provider */
4017 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4018 &hkServiceProvider ) != ERROR_SUCCESS )
4020 ERR(": what the heck is going on?\n" );
4021 continue;
4024 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4025 NULL, &returnType, returnBuffer,
4026 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4028 ERR(": missing GUID registry data members\n" );
4029 continue;
4032 /* FIXME: Check return types to ensure we're interpreting data right */
4033 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4034 CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
4035 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4037 /* Determine if this is the Service Provider that the user asked for */
4038 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
4040 continue;
4043 if( i == 0 ) /* DP SP */
4045 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
4046 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
4047 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
4050 sizeOfReturnBuffer = 255;
4052 /* Get dwReserved1 */
4053 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
4054 NULL, &returnType, returnBuffer,
4055 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4057 ERR(": missing dwReserved1 registry data members\n") ;
4058 continue;
4061 if( i == 0 )
4063 lpSpData->dwReserved1 = GET_DWORD( returnBuffer );
4066 sizeOfReturnBuffer = 255;
4068 /* Get dwReserved2 */
4069 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4070 NULL, &returnType, returnBuffer,
4071 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4073 ERR(": missing dwReserved1 registry data members\n") ;
4074 continue;
4077 if( i == 0 )
4079 lpSpData->dwReserved2 = GET_DWORD( returnBuffer );
4082 sizeOfReturnBuffer = 255;
4084 /* Get the path for this service provider */
4085 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
4086 NULL, NULL, returnBuffer,
4087 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
4089 ERR(": missing PATH registry data members: 0x%08lx\n", dwTemp );
4090 continue;
4093 TRACE( "Loading %s\n", returnBuffer );
4094 return LoadLibraryA( returnBuffer );
4098 return 0;
4101 static
4102 HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider )
4104 HRESULT hr;
4105 LPDPSP_SPINIT SPInit;
4107 /* Initialize the service provider by calling SPInit */
4108 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4110 if( SPInit == NULL )
4112 ERR( "Service provider doesn't provide SPInit interface?\n" );
4113 FreeLibrary( hServiceProvider );
4114 return DPERR_UNAVAILABLE;
4117 TRACE( "Calling SPInit (DP SP entry point)\n" );
4119 hr = (*SPInit)( &This->dp2->spData );
4121 if( FAILED(hr) )
4123 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4124 FreeLibrary( hServiceProvider );
4125 return hr;
4128 /* FIXME: Need to verify the sanity of the returned callback table
4129 * using IsBadCodePtr */
4130 This->dp2->bSPInitialized = TRUE;
4132 /* This interface is now initialized as a DP object */
4133 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
4135 /* Store the handle of the module so that we can unload it later */
4136 This->dp2->hServiceProvider = hServiceProvider;
4138 return hr;
4141 static
4142 HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hLobbyProvider )
4144 HRESULT hr;
4145 LPSP_INIT DPLSPInit;
4147 /* Initialize the service provider by calling SPInit */
4148 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
4150 if( DPLSPInit == NULL )
4152 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4153 FreeLibrary( hLobbyProvider );
4154 return DPERR_UNAVAILABLE;
4157 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4159 hr = (*DPLSPInit)( &This->dp2->dplspData );
4161 if( FAILED(hr) )
4163 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4164 FreeLibrary( hLobbyProvider );
4165 return hr;
4168 /* FIXME: Need to verify the sanity of the returned callback table
4169 * using IsBadCodePtr */
4171 This->dp2->bDPLSPInitialized = TRUE;
4173 /* This interface is now initialized as a lobby object */
4174 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
4176 /* Store the handle of the module so that we can unload it later */
4177 This->dp2->hDPLobbyProvider = hLobbyProvider;
4179 return hr;
4182 static HRESULT WINAPI DP_IF_InitializeConnection
4183 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi )
4185 HMODULE hServiceProvider;
4186 HRESULT hr;
4187 GUID guidSP;
4188 const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
4189 BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4191 TRACE("(%p)->(%p,0x%08lx,%u)\n", This, lpConnection, dwFlags, bAnsi );
4193 if( dwFlags != 0 )
4195 return DPERR_INVALIDFLAGS;
4198 /* Find out what the requested SP is and how large this buffer is */
4199 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
4200 dwAddrSize, &guidSP );
4202 if( FAILED(hr) )
4204 ERR( "Invalid compound address?\n" );
4205 return DPERR_UNAVAILABLE;
4208 /* Load the service provider */
4209 hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp );
4211 if( hServiceProvider == 0 )
4213 ERR( "Unable to load service provider\n" );
4214 return DPERR_UNAVAILABLE;
4217 if( bIsDpSp )
4219 /* Fill in what we can of the Service Provider required information.
4220 * The rest was be done in DP_LoadSP
4222 This->dp2->spData.lpAddress = lpConnection;
4223 This->dp2->spData.dwAddressSize = dwAddrSize;
4224 This->dp2->spData.lpGuid = &guidSP;
4226 hr = DP_InitializeDPSP( This, hServiceProvider );
4228 else
4230 This->dp2->dplspData.lpAddress = lpConnection;
4232 hr = DP_InitializeDPLSP( This, hServiceProvider );
4235 if( FAILED(hr) )
4237 return hr;
4240 return DP_OK;
4243 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4244 ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
4246 ICOM_THIS(IDirectPlay3Impl,iface);
4248 /* This may not be externally invoked once either an SP or LP is initialized */
4249 if( This->dp2->connectionInitialized != NO_PROVIDER )
4251 return DPERR_ALREADYINITIALIZED;
4254 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE );
4257 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4258 ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
4260 ICOM_THIS(IDirectPlay3Impl,iface);
4262 /* This may not be externally invoked once either an SP or LP is initialized */
4263 if( This->dp2->connectionInitialized != NO_PROVIDER )
4265 return DPERR_ALREADYINITIALIZED;
4268 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE );
4271 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4272 ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4273 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4275 ICOM_THIS(IDirectPlay2Impl,iface); /* Yes a dp 2 interface */
4276 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4279 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4280 ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4281 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4283 ICOM_THIS(IDirectPlay2Impl,iface); /* Yes a dp 2 interface */
4284 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4287 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4288 ( LPDIRECTPLAY3A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4290 ICOM_THIS(IDirectPlay3Impl,iface);
4291 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4292 return DP_OK;
4295 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4296 ( LPDIRECTPLAY3 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4298 ICOM_THIS(IDirectPlay3Impl,iface);
4299 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4300 return DP_OK;
4303 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4304 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4306 ICOM_THIS(IDirectPlay3Impl,iface);
4307 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4308 return DP_OK;
4311 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4312 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4314 ICOM_THIS(IDirectPlay3Impl,iface);
4315 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4316 return DP_OK;
4319 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4320 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup )
4322 ICOM_THIS(IDirectPlay3Impl,iface);
4323 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
4324 return DP_OK;
4327 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4328 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup )
4330 ICOM_THIS(IDirectPlay3Impl,iface);
4331 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
4332 return DP_OK;
4335 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4336 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDWORD lpdwFlags )
4338 ICOM_THIS(IDirectPlay3Impl,iface);
4339 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
4340 return DP_OK;
4343 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4344 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDWORD lpdwFlags )
4346 ICOM_THIS(IDirectPlay3Impl,iface);
4347 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
4348 return DP_OK;
4351 static HRESULT WINAPI DP_IF_GetGroupParent
4352 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
4353 BOOL bAnsi )
4355 lpGroupData lpGData;
4357 TRACE("(%p)->(0x%08lx,%p,%u)\n", This, idGroup, lpidGroup, bAnsi );
4359 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4361 return DPERR_INVALIDGROUP;
4364 *lpidGroup = lpGData->dpid;
4366 return DP_OK;
4369 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4370 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
4372 ICOM_THIS(IDirectPlay3Impl,iface);
4373 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE );
4375 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4376 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
4378 ICOM_THIS(IDirectPlay3Impl,iface);
4379 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE );
4382 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4383 ( LPDIRECTPLAY3A iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4385 ICOM_THIS(IDirectPlay3Impl,iface);
4386 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4387 return DP_OK;
4390 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4391 ( LPDIRECTPLAY3 iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4393 ICOM_THIS(IDirectPlay3Impl,iface);
4394 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4395 return DP_OK;
4398 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4399 ( LPDIRECTPLAY3A iface, DPID idPlayer, LPDWORD lpdwFlags )
4401 ICOM_THIS(IDirectPlay3Impl,iface);
4402 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
4403 return DP_OK;
4406 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4407 ( LPDIRECTPLAY3 iface, DPID idPlayer, LPDWORD lpdwFlags )
4409 ICOM_THIS(IDirectPlay3Impl,iface);
4410 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
4411 return DP_OK;
4414 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4415 ( LPDIRECTPLAY4A iface, DPID idGroup, LPDPID lpidGroupOwner )
4417 ICOM_THIS(IDirectPlay4Impl,iface);
4418 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
4419 return DP_OK;
4422 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4423 ( LPDIRECTPLAY4 iface, DPID idGroup, LPDPID lpidGroupOwner )
4425 ICOM_THIS(IDirectPlay4Impl,iface);
4426 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
4427 return DP_OK;
4430 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4431 ( LPDIRECTPLAY4A iface, DPID idGroup , DPID idGroupOwner )
4433 ICOM_THIS(IDirectPlay4Impl,iface);
4434 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
4435 return DP_OK;
4438 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4439 ( LPDIRECTPLAY4 iface, DPID idGroup , DPID idGroupOwner )
4441 ICOM_THIS(IDirectPlay4Impl,iface);
4442 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
4443 return DP_OK;
4446 static HRESULT WINAPI DP_SendEx
4447 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4448 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4449 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi )
4451 lpPlayerList lpPList;
4452 lpGroupData lpGData;
4453 BOOL bValidDestination = FALSE;
4455 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx,0x%08lx,0x%08lx,%p,%p,%u)"
4456 ": stub\n",
4457 This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority,
4458 dwTimeout, lpContext, lpdwMsgID, bAnsi );
4460 /* FIXME: Add parameter checking */
4461 /* FIXME: First call to this needs to aquire a message id which will be
4462 * used for multiple sends
4465 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4467 /* Verify that the message is being sent from a valid local player. The
4468 * from player may be anonymous DPID_UNKNOWN
4470 if( idFrom != DPID_UNKNOWN )
4472 if( ( lpPList = DP_FindPlayer( This, idFrom ) ) == NULL )
4474 WARN( "INFO: Invalid from player 0x%08lx\n", idFrom );
4475 return DPERR_INVALIDPLAYER;
4479 /* Verify that the message is being sent to a valid player, group or to
4480 * everyone. If it's valid, send it to those players.
4482 if( idTo == DPID_ALLPLAYERS )
4484 bValidDestination = TRUE;
4486 /* See if SP has the ability to multicast. If so, use it */
4487 if( This->dp2->spData.lpCB->SendToGroupEx )
4489 FIXME( "Use group sendex to group 0\n" );
4491 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4493 FIXME( "Use obsolete group send to group 0\n" );
4495 else /* No multicast, multiplicate */
4497 /* Send to all players we know about */
4498 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4502 if( ( !bValidDestination ) &&
4503 ( DP_FindPlayer( This, idTo ) != NULL )
4506 bValidDestination = TRUE;
4508 /* Have the service provider send this message */
4509 /* FIXME: Could optimize for local interface sends */
4510 return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority,
4511 dwTimeout, lpContext, lpdwMsgID );
4514 if( ( !bValidDestination ) &&
4515 ( ( lpGData = DP_FindAnyGroup( This, idTo ) ) != NULL )
4518 bValidDestination = TRUE;
4520 /* See if SP has the ability to multicast. If so, use it */
4521 if( This->dp2->spData.lpCB->SendToGroupEx )
4523 FIXME( "Use group sendex\n" );
4525 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4527 FIXME( "Use obsolete group send to group\n" );
4529 else /* No multicast, multiplicate */
4531 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4534 #if 0
4535 if( bExpectReply )
4537 DWORD dwWaitReturn;
4539 This->dp2->hReplyEvent = CreateEventA( NULL, FALSE, FALSE, NULL );
4541 dwWaitReturn = WaitForSingleObject( hReplyEvent, dwTimeout );
4542 if( dwWaitReturn != WAIT_OBJECT_0 )
4544 ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
4547 #endif
4550 if( !bValidDestination )
4552 return DPERR_INVALIDPLAYER;
4554 else
4556 /* FIXME: Should return what the send returned */
4557 return DP_OK;
4562 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4563 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4564 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4565 LPVOID lpContext, LPDWORD lpdwMsgID )
4567 ICOM_THIS(IDirectPlay2Impl,iface); /* yes downcast to 2 */
4568 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4569 dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE );
4572 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4573 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4574 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4575 LPVOID lpContext, LPDWORD lpdwMsgID )
4577 ICOM_THIS(IDirectPlay2Impl,iface); /* yes downcast to 2 */
4578 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4579 dwPriority, dwTimeout, lpContext, lpdwMsgID, FALSE );
4582 static HRESULT WINAPI DP_SP_SendEx
4583 ( IDirectPlay2Impl* This, DWORD dwFlags,
4584 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4585 LPVOID lpContext, LPDWORD lpdwMsgID )
4587 LPDPMSG lpMElem;
4589 FIXME( ": stub\n" );
4591 /* FIXME: This queuing should only be for async messages */
4593 lpMElem = (LPDPMSG)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4594 sizeof( *lpMElem ) );
4595 lpMElem->msg = (DPMSG_GENERIC*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4596 dwDataSize );
4598 CopyMemory( lpMElem->msg, lpData, dwDataSize );
4600 /* FIXME: Need to queue based on priority */
4601 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
4603 return DP_OK;
4606 static HRESULT WINAPI DP_IF_GetMessageQueue
4607 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4608 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi )
4610 HRESULT hr = DP_OK;
4612 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,%p,%u): semi stub\n",
4613 This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi );
4615 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4616 /* FIXME: What about sends which are not immediate? */
4618 if( This->dp2->spData.lpCB->GetMessageQueue )
4620 DPSP_GETMESSAGEQUEUEDATA data;
4622 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4624 /* FIXME: None of this is documented :( */
4626 data.lpISP = This->dp2->spData.lpISP;
4627 data.dwFlags = dwFlags;
4628 data.idFrom = idFrom;
4629 data.idTo = idTo;
4630 data.lpdwNumMsgs = lpdwNumMsgs;
4631 data.lpdwNumBytes = lpdwNumBytes;
4633 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
4635 else
4637 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4640 return hr;
4643 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4644 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4645 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4647 ICOM_THIS(IDirectPlay4Impl,iface);
4648 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4649 lpdwNumBytes, TRUE );
4652 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4653 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4654 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4656 ICOM_THIS(IDirectPlay4Impl,iface);
4657 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4658 lpdwNumBytes, FALSE );
4661 static HRESULT WINAPI DP_IF_CancelMessage
4662 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
4663 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi )
4665 HRESULT hr = DP_OK;
4667 FIXME( "(%p)->(0x%08lx,0x%08lx,%u): semi stub\n",
4668 This, dwMsgID, dwFlags, bAnsi );
4670 if( This->dp2->spData.lpCB->Cancel )
4672 DPSP_CANCELDATA data;
4674 TRACE( "Calling SP Cancel\n" );
4676 /* FIXME: Undocumented callback */
4678 data.lpISP = This->dp2->spData.lpISP;
4679 data.dwFlags = dwFlags;
4680 data.lprglpvSPMsgID = NULL;
4681 data.cSPMsgID = dwMsgID;
4682 data.dwMinPriority = dwMinPriority;
4683 data.dwMaxPriority = dwMaxPriority;
4685 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
4687 else
4689 FIXME( "SP doesn't implement Cancel\n" );
4692 return hr;
4695 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
4696 ( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags )
4698 ICOM_THIS(IDirectPlay4Impl,iface);
4700 if( dwFlags != 0 )
4702 return DPERR_INVALIDFLAGS;
4705 if( dwMsgID == 0 )
4707 dwFlags |= DPCANCELSEND_ALL;
4710 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE );
4713 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
4714 ( LPDIRECTPLAY4 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, FALSE );
4731 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
4732 ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4733 DWORD dwFlags )
4735 ICOM_THIS(IDirectPlay4Impl,iface);
4737 if( dwFlags != 0 )
4739 return DPERR_INVALIDFLAGS;
4742 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4743 dwMaxPriority, TRUE );
4746 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
4747 ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4748 DWORD dwFlags )
4750 ICOM_THIS(IDirectPlay4Impl,iface);
4752 if( dwFlags != 0 )
4754 return DPERR_INVALIDFLAGS;
4757 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4758 dwMaxPriority, FALSE );
4761 /* Note: Hack so we can reuse the old functions without compiler warnings */
4762 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4763 # define XCAST(fun) (typeof(directPlay2WVT.fun))
4764 #else
4765 # define XCAST(fun) (void*)
4766 #endif
4768 static ICOM_VTABLE(IDirectPlay2) directPlay2WVT =
4770 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4771 XCAST(QueryInterface)DP_QueryInterface,
4772 XCAST(AddRef)DP_AddRef,
4773 XCAST(Release)DP_Release,
4775 DirectPlay2WImpl_AddPlayerToGroup,
4776 DirectPlay2WImpl_Close,
4777 DirectPlay2WImpl_CreateGroup,
4778 DirectPlay2WImpl_CreatePlayer,
4779 DirectPlay2WImpl_DeletePlayerFromGroup,
4780 DirectPlay2WImpl_DestroyGroup,
4781 DirectPlay2WImpl_DestroyPlayer,
4782 DirectPlay2WImpl_EnumGroupPlayers,
4783 DirectPlay2WImpl_EnumGroups,
4784 DirectPlay2WImpl_EnumPlayers,
4785 DirectPlay2WImpl_EnumSessions,
4786 DirectPlay2WImpl_GetCaps,
4787 DirectPlay2WImpl_GetGroupData,
4788 DirectPlay2WImpl_GetGroupName,
4789 DirectPlay2WImpl_GetMessageCount,
4790 DirectPlay2WImpl_GetPlayerAddress,
4791 DirectPlay2WImpl_GetPlayerCaps,
4792 DirectPlay2WImpl_GetPlayerData,
4793 DirectPlay2WImpl_GetPlayerName,
4794 DirectPlay2WImpl_GetSessionDesc,
4795 DirectPlay2WImpl_Initialize,
4796 DirectPlay2WImpl_Open,
4797 DirectPlay2WImpl_Receive,
4798 DirectPlay2WImpl_Send,
4799 DirectPlay2WImpl_SetGroupData,
4800 DirectPlay2WImpl_SetGroupName,
4801 DirectPlay2WImpl_SetPlayerData,
4802 DirectPlay2WImpl_SetPlayerName,
4803 DirectPlay2WImpl_SetSessionDesc
4805 #undef XCAST
4807 /* Note: Hack so we can reuse the old functions without compiler warnings */
4808 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4809 # define XCAST(fun) (typeof(directPlay2AVT.fun))
4810 #else
4811 # define XCAST(fun) (void*)
4812 #endif
4814 static ICOM_VTABLE(IDirectPlay2) directPlay2AVT =
4816 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4817 XCAST(QueryInterface)DP_QueryInterface,
4818 XCAST(AddRef)DP_AddRef,
4819 XCAST(Release)DP_Release,
4821 DirectPlay2AImpl_AddPlayerToGroup,
4822 DirectPlay2AImpl_Close,
4823 DirectPlay2AImpl_CreateGroup,
4824 DirectPlay2AImpl_CreatePlayer,
4825 DirectPlay2AImpl_DeletePlayerFromGroup,
4826 DirectPlay2AImpl_DestroyGroup,
4827 DirectPlay2AImpl_DestroyPlayer,
4828 DirectPlay2AImpl_EnumGroupPlayers,
4829 DirectPlay2AImpl_EnumGroups,
4830 DirectPlay2AImpl_EnumPlayers,
4831 DirectPlay2AImpl_EnumSessions,
4832 DirectPlay2AImpl_GetCaps,
4833 DirectPlay2AImpl_GetGroupData,
4834 DirectPlay2AImpl_GetGroupName,
4835 DirectPlay2AImpl_GetMessageCount,
4836 DirectPlay2AImpl_GetPlayerAddress,
4837 DirectPlay2AImpl_GetPlayerCaps,
4838 DirectPlay2AImpl_GetPlayerData,
4839 DirectPlay2AImpl_GetPlayerName,
4840 DirectPlay2AImpl_GetSessionDesc,
4841 DirectPlay2AImpl_Initialize,
4842 DirectPlay2AImpl_Open,
4843 DirectPlay2AImpl_Receive,
4844 DirectPlay2AImpl_Send,
4845 DirectPlay2AImpl_SetGroupData,
4846 DirectPlay2AImpl_SetGroupName,
4847 DirectPlay2AImpl_SetPlayerData,
4848 DirectPlay2AImpl_SetPlayerName,
4849 DirectPlay2AImpl_SetSessionDesc
4851 #undef XCAST
4854 /* Note: Hack so we can reuse the old functions without compiler warnings */
4855 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4856 # define XCAST(fun) (typeof(directPlay3AVT.fun))
4857 #else
4858 # define XCAST(fun) (void*)
4859 #endif
4861 static ICOM_VTABLE(IDirectPlay3) directPlay3AVT =
4863 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4864 XCAST(QueryInterface)DP_QueryInterface,
4865 XCAST(AddRef)DP_AddRef,
4866 XCAST(Release)DP_Release,
4868 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
4869 XCAST(Close)DirectPlay2AImpl_Close,
4870 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
4871 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
4872 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
4873 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
4874 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
4875 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
4876 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
4877 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
4878 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
4879 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
4880 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
4881 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
4882 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
4883 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
4884 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
4885 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
4886 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
4887 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
4888 XCAST(Initialize)DirectPlay2AImpl_Initialize,
4889 XCAST(Open)DirectPlay2AImpl_Open,
4890 XCAST(Receive)DirectPlay2AImpl_Receive,
4891 XCAST(Send)DirectPlay2AImpl_Send,
4892 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
4893 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
4894 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
4895 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
4896 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
4898 DirectPlay3AImpl_AddGroupToGroup,
4899 DirectPlay3AImpl_CreateGroupInGroup,
4900 DirectPlay3AImpl_DeleteGroupFromGroup,
4901 DirectPlay3AImpl_EnumConnections,
4902 DirectPlay3AImpl_EnumGroupsInGroup,
4903 DirectPlay3AImpl_GetGroupConnectionSettings,
4904 DirectPlay3AImpl_InitializeConnection,
4905 DirectPlay3AImpl_SecureOpen,
4906 DirectPlay3AImpl_SendChatMessage,
4907 DirectPlay3AImpl_SetGroupConnectionSettings,
4908 DirectPlay3AImpl_StartSession,
4909 DirectPlay3AImpl_GetGroupFlags,
4910 DirectPlay3AImpl_GetGroupParent,
4911 DirectPlay3AImpl_GetPlayerAccount,
4912 DirectPlay3AImpl_GetPlayerFlags
4914 #undef XCAST
4916 /* Note: Hack so we can reuse the old functions without compiler warnings */
4917 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4918 # define XCAST(fun) (typeof(directPlay3WVT.fun))
4919 #else
4920 # define XCAST(fun) (void*)
4921 #endif
4922 static ICOM_VTABLE(IDirectPlay3) directPlay3WVT =
4924 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4925 XCAST(QueryInterface)DP_QueryInterface,
4926 XCAST(AddRef)DP_AddRef,
4927 XCAST(Release)DP_Release,
4929 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
4930 XCAST(Close)DirectPlay2WImpl_Close,
4931 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
4932 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
4933 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
4934 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
4935 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
4936 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
4937 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
4938 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
4939 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
4940 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
4941 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
4942 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
4943 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
4944 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
4945 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
4946 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
4947 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
4948 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
4949 XCAST(Initialize)DirectPlay2WImpl_Initialize,
4950 XCAST(Open)DirectPlay2WImpl_Open,
4951 XCAST(Receive)DirectPlay2WImpl_Receive,
4952 XCAST(Send)DirectPlay2WImpl_Send,
4953 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
4954 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
4955 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
4956 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
4957 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
4959 DirectPlay3WImpl_AddGroupToGroup,
4960 DirectPlay3WImpl_CreateGroupInGroup,
4961 DirectPlay3WImpl_DeleteGroupFromGroup,
4962 DirectPlay3WImpl_EnumConnections,
4963 DirectPlay3WImpl_EnumGroupsInGroup,
4964 DirectPlay3WImpl_GetGroupConnectionSettings,
4965 DirectPlay3WImpl_InitializeConnection,
4966 DirectPlay3WImpl_SecureOpen,
4967 DirectPlay3WImpl_SendChatMessage,
4968 DirectPlay3WImpl_SetGroupConnectionSettings,
4969 DirectPlay3WImpl_StartSession,
4970 DirectPlay3WImpl_GetGroupFlags,
4971 DirectPlay3WImpl_GetGroupParent,
4972 DirectPlay3WImpl_GetPlayerAccount,
4973 DirectPlay3WImpl_GetPlayerFlags
4975 #undef XCAST
4977 /* Note: Hack so we can reuse the old functions without compiler warnings */
4978 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4979 # define XCAST(fun) (typeof(directPlay4WVT.fun))
4980 #else
4981 # define XCAST(fun) (void*)
4982 #endif
4983 static ICOM_VTABLE(IDirectPlay4) directPlay4WVT =
4985 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4986 XCAST(QueryInterface)DP_QueryInterface,
4987 XCAST(AddRef)DP_AddRef,
4988 XCAST(Release)DP_Release,
4990 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
4991 XCAST(Close)DirectPlay2WImpl_Close,
4992 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
4993 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
4994 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
4995 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
4996 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
4997 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
4998 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
4999 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5000 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5001 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5002 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5003 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5004 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5005 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5006 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5007 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5008 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5009 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5010 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5011 XCAST(Open)DirectPlay2WImpl_Open,
5012 XCAST(Receive)DirectPlay2WImpl_Receive,
5013 XCAST(Send)DirectPlay2WImpl_Send,
5014 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5015 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5016 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5017 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5018 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5020 XCAST(AddGroupToGroup)DirectPlay3WImpl_AddGroupToGroup,
5021 XCAST(CreateGroupInGroup)DirectPlay3WImpl_CreateGroupInGroup,
5022 XCAST(DeleteGroupFromGroup)DirectPlay3WImpl_DeleteGroupFromGroup,
5023 XCAST(EnumConnections)DirectPlay3WImpl_EnumConnections,
5024 XCAST(EnumGroupsInGroup)DirectPlay3WImpl_EnumGroupsInGroup,
5025 XCAST(GetGroupConnectionSettings)DirectPlay3WImpl_GetGroupConnectionSettings,
5026 XCAST(InitializeConnection)DirectPlay3WImpl_InitializeConnection,
5027 XCAST(SecureOpen)DirectPlay3WImpl_SecureOpen,
5028 XCAST(SendChatMessage)DirectPlay3WImpl_SendChatMessage,
5029 XCAST(SetGroupConnectionSettings)DirectPlay3WImpl_SetGroupConnectionSettings,
5030 XCAST(StartSession)DirectPlay3WImpl_StartSession,
5031 XCAST(GetGroupFlags)DirectPlay3WImpl_GetGroupFlags,
5032 XCAST(GetGroupParent)DirectPlay3WImpl_GetGroupParent,
5033 XCAST(GetPlayerAccount)DirectPlay3WImpl_GetPlayerAccount,
5034 XCAST(GetPlayerFlags)DirectPlay3WImpl_GetPlayerFlags,
5036 DirectPlay4WImpl_GetGroupOwner,
5037 DirectPlay4WImpl_SetGroupOwner,
5038 DirectPlay4WImpl_SendEx,
5039 DirectPlay4WImpl_GetMessageQueue,
5040 DirectPlay4WImpl_CancelMessage,
5041 DirectPlay4WImpl_CancelPriority
5043 #undef XCAST
5046 /* Note: Hack so we can reuse the old functions without compiler warnings */
5047 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5048 # define XCAST(fun) (typeof(directPlay4AVT.fun))
5049 #else
5050 # define XCAST(fun) (void*)
5051 #endif
5052 static ICOM_VTABLE(IDirectPlay4) directPlay4AVT =
5054 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5055 XCAST(QueryInterface)DP_QueryInterface,
5056 XCAST(AddRef)DP_AddRef,
5057 XCAST(Release)DP_Release,
5059 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
5060 XCAST(Close)DirectPlay2AImpl_Close,
5061 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
5062 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
5063 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
5064 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
5065 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
5066 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
5067 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
5068 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
5069 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
5070 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
5071 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
5072 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
5073 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5074 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5075 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5076 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5077 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5078 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5079 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5080 XCAST(Open)DirectPlay2AImpl_Open,
5081 XCAST(Receive)DirectPlay2AImpl_Receive,
5082 XCAST(Send)DirectPlay2AImpl_Send,
5083 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5084 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5085 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5086 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5087 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5089 XCAST(AddGroupToGroup)DirectPlay3AImpl_AddGroupToGroup,
5090 XCAST(CreateGroupInGroup)DirectPlay3AImpl_CreateGroupInGroup,
5091 XCAST(DeleteGroupFromGroup)DirectPlay3AImpl_DeleteGroupFromGroup,
5092 XCAST(EnumConnections)DirectPlay3AImpl_EnumConnections,
5093 XCAST(EnumGroupsInGroup)DirectPlay3AImpl_EnumGroupsInGroup,
5094 XCAST(GetGroupConnectionSettings)DirectPlay3AImpl_GetGroupConnectionSettings,
5095 XCAST(InitializeConnection)DirectPlay3AImpl_InitializeConnection,
5096 XCAST(SecureOpen)DirectPlay3AImpl_SecureOpen,
5097 XCAST(SendChatMessage)DirectPlay3AImpl_SendChatMessage,
5098 XCAST(SetGroupConnectionSettings)DirectPlay3AImpl_SetGroupConnectionSettings,
5099 XCAST(StartSession)DirectPlay3AImpl_StartSession,
5100 XCAST(GetGroupFlags)DirectPlay3AImpl_GetGroupFlags,
5101 XCAST(GetGroupParent)DirectPlay3AImpl_GetGroupParent,
5102 XCAST(GetPlayerAccount)DirectPlay3AImpl_GetPlayerAccount,
5103 XCAST(GetPlayerFlags)DirectPlay3AImpl_GetPlayerFlags,
5105 DirectPlay4AImpl_GetGroupOwner,
5106 DirectPlay4AImpl_SetGroupOwner,
5107 DirectPlay4AImpl_SendEx,
5108 DirectPlay4AImpl_GetMessageQueue,
5109 DirectPlay4AImpl_CancelMessage,
5110 DirectPlay4AImpl_CancelPriority
5112 #undef XCAST
5114 extern
5115 HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP,
5116 DPID idPlayer,
5117 LPVOID* lplpData )
5119 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5121 if( lpPlayer == NULL )
5123 return DPERR_INVALIDPLAYER;
5126 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
5128 return DP_OK;
5131 extern
5132 HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP,
5133 DPID idPlayer,
5134 LPVOID lpData )
5136 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5138 if( lpPlayer == NULL )
5140 return DPERR_INVALIDPLAYER;
5143 lpPlayer->lpPData->lpSPPlayerData = lpData;
5145 return DP_OK;
5148 /***************************************************************************
5149 * DirectPlayEnumerateA [DPLAYX.2][DPLAYX.9][DPLAY.2]
5151 * The pointer to the structure lpContext will be filled with the
5152 * appropriate data for each service offered by the OS. These services are
5153 * not necessarily available on this particular machine but are defined
5154 * as simple service providers under the "Service Providers" registry key.
5155 * This structure is then passed to lpEnumCallback for each of the different
5156 * services.
5158 * This API is useful only for applications written using DirectX3 or
5159 * worse. It is superceeded by IDirectPlay3::EnumConnections which also
5160 * gives information on the actual connections.
5162 * defn of a service provider:
5163 * A dynamic-link library used by DirectPlay to communicate over a network.
5164 * The service provider contains all the network-specific code required
5165 * to send and receive messages. Online services and network operators can
5166 * supply service providers to use specialized hardware, protocols, communications
5167 * media, and network resources.
5169 * TODO: Allocate string buffer space from the heap (length from reg)
5170 * Pass real device driver numbers...
5171 * Get the GUID properly...
5173 HRESULT WINAPI DirectPlayEnumerateA( LPDPENUMDPCALLBACKA lpEnumCallback,
5174 LPVOID lpContext )
5177 HKEY hkResult;
5178 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
5179 DWORD dwIndex;
5180 DWORD sizeOfSubKeyName=50;
5181 char subKeyName[51];
5182 FILETIME filetime;
5184 TRACE(": lpEnumCallback=%p lpContext=%p\n", lpEnumCallback, lpContext );
5186 if( !lpEnumCallback || !*lpEnumCallback )
5188 return DPERR_INVALIDPARAMS;
5191 /* Need to loop over the service providers in the registry */
5192 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
5193 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
5195 /* Hmmm. Does this mean that there are no service providers? */
5196 ERR(": no service providers?\n");
5197 return DP_OK;
5200 /* Traverse all the service providers we have available */
5201 for( dwIndex=0;
5202 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
5203 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
5204 ++dwIndex, sizeOfSubKeyName=50 )
5206 LPSTR majVerDataSubKey = "dwReserved1";
5207 LPSTR minVerDataSubKey = "dwReserved2";
5208 LPSTR guidDataSubKey = "Guid";
5209 HKEY hkServiceProvider;
5210 GUID serviceProviderGUID;
5211 DWORD returnTypeGUID, returnTypeReserved, sizeOfReturnBuffer = 50;
5212 char returnBuffer[51];
5213 WCHAR buff[51];
5214 DWORD majVersionNum , minVersionNum = 0;
5216 TRACE(" this time through: %s\n", subKeyName );
5218 /* Get a handle for this particular service provider */
5219 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
5220 &hkServiceProvider ) != ERROR_SUCCESS )
5222 ERR(": what the heck is going on?\n" );
5223 continue;
5226 /* Get the GUID, Device major number and device minor number
5227 * from the registry.
5229 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
5230 NULL, &returnTypeGUID, returnBuffer,
5231 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5233 ERR(": missing GUID registry data members\n" );
5234 continue;
5237 /* FIXME: Check return types to ensure we're interpreting data right */
5238 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
5239 CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
5241 /* FIXME: Need to know which of dwReserved1 and dwReserved2 are maj and min */
5243 sizeOfReturnBuffer = 50;
5244 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
5245 NULL, &returnTypeReserved, returnBuffer,
5246 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5248 ERR(": missing dwReserved1 registry data members\n") ;
5249 continue;
5252 majVersionNum = GET_DWORD( returnBuffer );
5254 sizeOfReturnBuffer = 50;
5255 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
5256 NULL, &returnTypeReserved, returnBuffer,
5257 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5259 ERR(": missing dwReserved2 registry data members\n") ;
5260 continue;
5263 minVersionNum = GET_DWORD( returnBuffer );
5266 /* The enumeration will return FALSE if we are not to continue */
5267 if( !lpEnumCallback( &serviceProviderGUID , subKeyName,
5268 majVersionNum, minVersionNum, lpContext ) )
5270 WARN("lpEnumCallback returning FALSE\n" );
5271 break;
5275 return DP_OK;
5279 /***************************************************************************
5280 * DirectPlayEnumerateW [DPLAYX.3]
5283 HRESULT WINAPI DirectPlayEnumerateW( LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5286 FIXME(":stub\n");
5288 return DPERR_OUTOFMEMORY;
5292 typedef struct tagCreateEnum
5294 LPVOID lpConn;
5295 LPCGUID lpGuid;
5296 } CreateEnumData, *lpCreateEnumData;
5298 /* Find and copy the matching connection for the SP guid */
5299 static BOOL CALLBACK cbDPCreateEnumConnections(
5300 LPCGUID lpguidSP,
5301 LPVOID lpConnection,
5302 DWORD dwConnectionSize,
5303 LPCDPNAME lpName,
5304 DWORD dwFlags,
5305 LPVOID lpContext)
5307 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5309 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5311 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5313 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5314 dwConnectionSize );
5315 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5317 /* Found the record that we were looking for */
5318 return FALSE;
5321 /* Haven't found what were looking for yet */
5322 return TRUE;
5326 /***************************************************************************
5327 * DirectPlayCreate [DPLAYX.1][DPLAY.1]
5330 HRESULT WINAPI DirectPlayCreate
5331 ( LPGUID lpGUID, LPDIRECTPLAY2 *lplpDP, IUnknown *pUnk)
5333 HRESULT hr;
5334 LPDIRECTPLAY3A lpDP3A;
5335 CreateEnumData cbData;
5337 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5339 if( pUnk != NULL )
5341 return CLASS_E_NOAGGREGATION;
5344 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5345 give them an IDirectPlay2A object and hope that doesn't cause problems */
5346 if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
5348 return DPERR_UNAVAILABLE;
5351 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
5353 /* The GUID_NULL means don't bind a service provider. Just return the
5354 interface as is */
5355 return DP_OK;
5358 /* Bind the desired service provider since lpGUID is non NULL */
5359 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
5361 /* We're going to use a DP3 interface */
5362 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
5363 (LPVOID*)&lpDP3A );
5364 if( FAILED(hr) )
5366 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
5367 return hr;
5370 cbData.lpConn = NULL;
5371 cbData.lpGuid = lpGUID;
5373 /* We were given a service provider, find info about it... */
5374 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
5375 &cbData, DPCONNECTION_DIRECTPLAY );
5376 if( ( FAILED(hr) ) ||
5377 ( cbData.lpConn == NULL )
5380 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
5381 IDirectPlayX_Release( lpDP3A );
5382 return DPERR_UNAVAILABLE;
5385 /* Initialize the service provider */
5386 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
5387 if( FAILED(hr) )
5389 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
5390 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5391 IDirectPlayX_Release( lpDP3A );
5392 return hr;
5395 /* Release our version of the interface now that we're done with it */
5396 IDirectPlayX_Release( lpDP3A );
5397 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5399 return DP_OK;