1 /* Direct Play 2,3,4 Implementation
3 * Copyright 1998,1999,2000,2001 - Peter Hunnisett
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "wine/port.h"
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
34 #include "wine/unicode.h"
35 #include "wine/debug.h"
38 #include "dplayx_global.h"
39 #include "name_server.h"
40 #include "dplayx_queue.h"
42 #include "dplay_global.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(dplay
);
46 /* FIXME: Should this be externed? */
47 extern HRESULT DPL_CreateCompoundAddress
48 ( LPCDPCOMPOUNDADDRESSELEMENT lpElements
, DWORD dwElementCount
,
49 LPVOID lpAddress
, LPDWORD lpdwAddressSize
, BOOL bAnsiInterface
);
52 /* Local function prototypes */
53 static lpPlayerList
DP_FindPlayer( IDirectPlay2AImpl
* This
, DPID dpid
);
54 static lpPlayerData
DP_CreatePlayer( IDirectPlay2Impl
* iface
, LPDPID lpid
,
55 LPDPNAME lpName
, DWORD dwFlags
,
56 HANDLE hEvent
, BOOL bAnsi
);
57 static BOOL
DP_CopyDPNAMEStruct( LPDPNAME lpDst
, const DPNAME
*lpSrc
, BOOL bAnsi
);
58 static void DP_SetPlayerData( lpPlayerData lpPData
, DWORD dwFlags
,
59 LPVOID lpData
, DWORD dwDataSize
);
61 static lpGroupData
DP_CreateGroup( IDirectPlay2AImpl
* iface
, const DPID
*lpid
,
62 const DPNAME
*lpName
, DWORD dwFlags
,
63 DPID idParent
, BOOL bAnsi
);
64 static void DP_SetGroupData( lpGroupData lpGData
, DWORD dwFlags
,
65 LPVOID lpData
, DWORD dwDataSize
);
66 static void DP_DeleteDPNameStruct( LPDPNAME lpDPName
);
67 static void DP_DeletePlayer( IDirectPlay2Impl
* This
, DPID dpid
);
68 static BOOL CALLBACK
cbDeletePlayerFromAllGroups( DPID dpId
,
73 static lpGroupData
DP_FindAnyGroup( IDirectPlay2AImpl
* This
, DPID dpid
);
74 static BOOL CALLBACK
cbRemoveGroupOrPlayer( DPID dpId
, DWORD dwPlayerType
,
75 LPCDPNAME lpName
, DWORD dwFlags
,
77 static void DP_DeleteGroup( IDirectPlay2Impl
* This
, DPID dpid
);
79 /* Forward declarations of virtual tables */
80 static const IDirectPlay2Vtbl directPlay2AVT
;
81 static const IDirectPlay3Vtbl directPlay3AVT
;
82 static const IDirectPlay4Vtbl directPlay4AVT
;
84 static const IDirectPlay2Vtbl directPlay2WVT
;
85 static const IDirectPlay3Vtbl directPlay3WVT
;
86 static const IDirectPlay4Vtbl directPlay4WVT
;
88 /* Helper methods for player/group interfaces */
89 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
90 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idGroup
,
91 DPID idPlayer
, BOOL bAnsi
);
92 static HRESULT WINAPI DP_IF_CreatePlayer
93 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, LPDPID lpidPlayer
,
94 LPDPNAME lpPlayerName
, HANDLE hEvent
, LPVOID lpData
,
95 DWORD dwDataSize
, DWORD dwFlags
, BOOL bAnsi
);
96 static HRESULT WINAPI DP_IF_DestroyGroup
97 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idGroup
, BOOL bAnsi
);
98 static HRESULT WINAPI DP_IF_DestroyPlayer
99 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idPlayer
, BOOL bAnsi
);
100 static HRESULT WINAPI DP_IF_EnumGroupPlayers
101 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPGUID lpguidInstance
,
102 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
103 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
);
104 static HRESULT WINAPI DP_IF_EnumGroups
105 ( IDirectPlay2Impl
* This
, LPGUID lpguidInstance
,
106 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
107 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
);
108 static HRESULT WINAPI DP_IF_EnumPlayers
109 ( IDirectPlay2Impl
* This
, LPGUID lpguidInstance
,
110 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
111 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
);
112 static HRESULT WINAPI DP_IF_GetGroupData
113 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPVOID lpData
,
114 LPDWORD lpdwDataSize
, DWORD dwFlags
, BOOL bAnsi
);
115 static HRESULT WINAPI DP_IF_GetGroupName
116 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPVOID lpData
,
117 LPDWORD lpdwDataSize
, BOOL bAnsi
);
118 static HRESULT WINAPI DP_IF_GetPlayerData
119 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPVOID lpData
,
120 LPDWORD lpdwDataSize
, DWORD dwFlags
, BOOL bAnsi
);
121 static HRESULT WINAPI DP_IF_GetPlayerName
122 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPVOID lpData
,
123 LPDWORD lpdwDataSize
, BOOL bAnsi
);
124 static HRESULT WINAPI DP_IF_SetGroupName
125 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPDPNAME lpGroupName
,
126 DWORD dwFlags
, BOOL bAnsi
);
127 static HRESULT WINAPI DP_IF_SetPlayerData
128 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPVOID lpData
,
129 DWORD dwDataSize
, DWORD dwFlags
, BOOL bAnsi
);
130 static HRESULT WINAPI DP_IF_SetPlayerName
131 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPDPNAME lpPlayerName
,
132 DWORD dwFlags
, BOOL bAnsi
);
133 static HRESULT WINAPI DP_IF_AddGroupToGroup
134 ( IDirectPlay3Impl
* This
, DPID idParentGroup
, DPID idGroup
);
135 static HRESULT WINAPI DP_IF_CreateGroup
136 ( IDirectPlay2AImpl
* This
, LPVOID lpMsgHdr
, LPDPID lpidGroup
,
137 LPDPNAME lpGroupName
, LPVOID lpData
, DWORD dwDataSize
,
138 DWORD dwFlags
, BOOL bAnsi
);
139 static HRESULT WINAPI DP_IF_CreateGroupInGroup
140 ( IDirectPlay3Impl
* This
, LPVOID lpMsgHdr
, DPID idParentGroup
,
141 LPDPID lpidGroup
, LPDPNAME lpGroupName
, LPVOID lpData
,
142 DWORD dwDataSize
, DWORD dwFlags
, BOOL bAnsi
);
143 static HRESULT WINAPI DP_IF_AddPlayerToGroup
144 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idGroup
,
145 DPID idPlayer
, BOOL bAnsi
);
146 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
147 ( IDirectPlay3Impl
* This
, DPID idParentGroup
, DPID idGroup
);
148 static HRESULT WINAPI DP_SetSessionDesc
149 ( IDirectPlay2Impl
* This
, LPCDPSESSIONDESC2 lpSessDesc
,
150 DWORD dwFlags
, BOOL bInitial
, BOOL bAnsi
);
151 static HRESULT WINAPI DP_SecureOpen
152 ( IDirectPlay2Impl
* This
, LPCDPSESSIONDESC2 lpsd
, DWORD dwFlags
,
153 LPCDPSECURITYDESC lpSecurity
, LPCDPCREDENTIALS lpCredentials
,
155 static HRESULT WINAPI DP_SendEx
156 ( IDirectPlay2Impl
* This
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
157 LPVOID lpData
, DWORD dwDataSize
, DWORD dwPriority
, DWORD dwTimeout
,
158 LPVOID lpContext
, LPDWORD lpdwMsgID
, BOOL bAnsi
);
159 static HRESULT WINAPI DP_IF_Receive
160 ( IDirectPlay2Impl
* This
, LPDPID lpidFrom
, LPDPID lpidTo
,
161 DWORD dwFlags
, LPVOID lpData
, LPDWORD lpdwDataSize
, BOOL bAnsi
);
162 static HRESULT WINAPI DP_IF_GetMessageQueue
163 ( IDirectPlay4Impl
* This
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
164 LPDWORD lpdwNumMsgs
, LPDWORD lpdwNumBytes
, BOOL bAnsi
);
165 static HRESULT WINAPI DP_SP_SendEx
166 ( IDirectPlay2Impl
* This
, DWORD dwFlags
,
167 LPVOID lpData
, DWORD dwDataSize
, DWORD dwPriority
, DWORD dwTimeout
,
168 LPVOID lpContext
, LPDWORD lpdwMsgID
);
169 static HRESULT WINAPI DP_IF_SetGroupData
170 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPVOID lpData
,
171 DWORD dwDataSize
, DWORD dwFlags
, BOOL bAnsi
);
172 static HRESULT WINAPI DP_IF_GetPlayerCaps
173 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPDPCAPS lpDPCaps
,
175 static HRESULT WINAPI
DP_IF_Close( IDirectPlay2Impl
* This
, BOOL bAnsi
);
176 static HRESULT WINAPI DP_IF_CancelMessage
177 ( IDirectPlay4Impl
* This
, DWORD dwMsgID
, DWORD dwFlags
,
178 DWORD dwMinPriority
, DWORD dwMaxPriority
, BOOL bAnsi
);
179 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
180 ( IDirectPlay3AImpl
* This
, DPID idGroup
, LPGUID lpguidInstance
,
181 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
182 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
);
183 static HRESULT WINAPI DP_IF_GetGroupParent
184 ( IDirectPlay3AImpl
* This
, DPID idGroup
, LPDPID lpidGroup
,
186 static HRESULT WINAPI DP_IF_GetCaps
187 ( IDirectPlay2Impl
* This
, LPDPCAPS lpDPCaps
, DWORD dwFlags
);
188 static HRESULT WINAPI DP_IF_EnumSessions
189 ( IDirectPlay2Impl
* This
, LPDPSESSIONDESC2 lpsd
, DWORD dwTimeout
,
190 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2
,
191 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
);
192 static HRESULT WINAPI DP_IF_InitializeConnection
193 ( IDirectPlay3Impl
* This
, LPVOID lpConnection
, DWORD dwFlags
, BOOL bAnsi
);
194 static BOOL CALLBACK
cbDPCreateEnumConnections( LPCGUID lpguidSP
,
195 LPVOID lpConnection
, DWORD dwConnectionSize
, LPCDPNAME lpName
,
196 DWORD dwFlags
, LPVOID lpContext
);
197 static BOOL WINAPI
DP_BuildSPCompoundAddr( LPGUID lpcSpGuid
, LPVOID
* lplpAddrBuf
,
198 LPDWORD lpdwBufSize
);
202 static inline DPID
DP_NextObjectId(void);
203 static DPID
DP_GetRemoteNextObjectId(void);
206 static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc
,
207 LPCDPSESSIONDESC2 srcSessDesc
, BOOL bAnsi
);
210 static HMODULE
DP_LoadSP( LPCGUID lpcGuid
, LPSPINITDATA lpSpData
, LPBOOL lpbIsDpSp
);
211 static HRESULT
DP_InitializeDPSP( IDirectPlay3Impl
* This
, HMODULE hServiceProvider
);
212 static HRESULT
DP_InitializeDPLSP( IDirectPlay3Impl
* This
, HMODULE hServiceProvider
);
219 #define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */
220 #define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported
221 we don't have to change much */
222 #define DPID_NAME_SERVER 0x19a9d65b /* Don't ask me why */
224 /* Strip out dwFlag values which cannot be sent in the CREATEGROUP msg */
225 #define DPMSG_CREATEGROUP_DWFLAGS(x) ( (x) & DPGROUP_HIDDEN )
227 /* Strip out all dwFlags values for CREATEPLAYER msg */
228 #define DPMSG_CREATEPLAYER_DWFLAGS(x) 0
230 static LONG kludgePlayerGroupId
= 1000;
232 /* ------------------------------------------------------------------ */
235 static BOOL
DP_CreateIUnknown( LPVOID lpDP
)
237 IDirectPlay2AImpl
*This
= (IDirectPlay2AImpl
*)lpDP
;
239 This
->unk
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *(This
->unk
) ) );
240 if ( This
->unk
== NULL
)
245 InitializeCriticalSection( &This
->unk
->DP_lock
);
246 This
->unk
->DP_lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": IDirectPlay2AImpl*->DirectPlayIUnknownData*->DP_lock");
251 static BOOL
DP_DestroyIUnknown( LPVOID lpDP
)
253 IDirectPlay2AImpl
*This
= (IDirectPlay2AImpl
*)lpDP
;
255 This
->unk
->DP_lock
.DebugInfo
->Spare
[0] = 0;
256 DeleteCriticalSection( &This
->unk
->DP_lock
);
257 HeapFree( GetProcessHeap(), 0, This
->unk
);
262 static BOOL
DP_CreateDirectPlay2( LPVOID lpDP
)
264 IDirectPlay2AImpl
*This
= (IDirectPlay2AImpl
*)lpDP
;
266 This
->dp2
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *(This
->dp2
) ) );
267 if ( This
->dp2
== NULL
)
272 This
->dp2
->bConnectionOpen
= FALSE
;
274 This
->dp2
->hEnumSessionThread
= INVALID_HANDLE_VALUE
;
275 This
->dp2
->dwEnumSessionLock
= 0;
277 This
->dp2
->bHostInterface
= FALSE
;
279 DPQ_INIT(This
->dp2
->receiveMsgs
);
280 DPQ_INIT(This
->dp2
->sendMsgs
);
281 DPQ_INIT(This
->dp2
->replysExpected
);
283 if( !NS_InitializeSessionCache( &This
->dp2
->lpNameServerData
) )
285 /* FIXME: Memory leak */
289 /* Provide an initial session desc with nothing in it */
290 This
->dp2
->lpSessionDesc
= HeapAlloc( GetProcessHeap(),
292 sizeof( *This
->dp2
->lpSessionDesc
) );
293 if( This
->dp2
->lpSessionDesc
== NULL
)
295 /* FIXME: Memory leak */
298 This
->dp2
->lpSessionDesc
->dwSize
= sizeof( *This
->dp2
->lpSessionDesc
);
300 /* We are emulating a dp 6 implementation */
301 This
->dp2
->spData
.dwSPVersion
= DPSP_MAJORVERSION
;
303 This
->dp2
->spData
.lpCB
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
304 sizeof( *This
->dp2
->spData
.lpCB
) );
305 This
->dp2
->spData
.lpCB
->dwSize
= sizeof( *This
->dp2
->spData
.lpCB
);
306 This
->dp2
->spData
.lpCB
->dwVersion
= DPSP_MAJORVERSION
;
308 /* This is the pointer to the service provider */
309 if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP
,
310 (LPVOID
*)&This
->dp2
->spData
.lpISP
, This
) )
313 /* FIXME: Memory leak */
317 /* Setup lobby provider information */
318 This
->dp2
->dplspData
.dwSPVersion
= DPSP_MAJORVERSION
;
319 This
->dp2
->dplspData
.lpCB
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
320 sizeof( *This
->dp2
->dplspData
.lpCB
) );
321 This
->dp2
->dplspData
.lpCB
->dwSize
= sizeof( *This
->dp2
->dplspData
.lpCB
);
323 if( FAILED( DPLSP_CreateInterface( &IID_IDPLobbySP
,
324 (LPVOID
*)&This
->dp2
->dplspData
.lpISP
, This
) )
327 /* FIXME: Memory leak */
334 /* Definition of the global function in dplayx_queue.h. #
335 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
336 DPQ_DECL_DELETECB( cbDeleteElemFromHeap
, LPVOID
)
338 HeapFree( GetProcessHeap(), 0, elem
);
341 /* Function to delete the list of groups with this interface. Needs to
342 * delete the group and player lists associated with this group as well
343 * as the group data associated with this group. It should not delete
344 * player data as that is shared with the top player list and will be
347 DPQ_DECL_DELETECB( cbDeleteGroupsElem
, lpGroupList
);
348 DPQ_DECL_DELETECB( cbDeleteGroupsElem
, lpGroupList
)
350 DPQ_DELETEQ( elem
->lpGData
->groups
, groups
,
351 lpGroupList
, cbDeleteElemFromHeap
);
352 DPQ_DELETEQ( elem
->lpGData
->players
, players
,
353 lpPlayerList
, cbDeleteElemFromHeap
);
354 HeapFree( GetProcessHeap(), 0, elem
->lpGData
);
355 HeapFree( GetProcessHeap(), 0, elem
);
358 /* Function to delete the list of players with this interface. Needs to
359 * delete the player data for all players as well.
361 DPQ_DECL_DELETECB( cbDeletePlayerElem
, lpPlayerList
);
362 DPQ_DECL_DELETECB( cbDeletePlayerElem
, lpPlayerList
)
364 HeapFree( GetProcessHeap(), 0, elem
->lpPData
);
365 HeapFree( GetProcessHeap(), 0, elem
);
368 static BOOL
DP_DestroyDirectPlay2( LPVOID lpDP
)
370 IDirectPlay2AImpl
*This
= (IDirectPlay2AImpl
*)lpDP
;
372 if( This
->dp2
->hEnumSessionThread
!= INVALID_HANDLE_VALUE
)
374 TerminateThread( This
->dp2
->hEnumSessionThread
, 0 );
375 CloseHandle( This
->dp2
->hEnumSessionThread
);
378 /* Finish with the SP - have it shutdown */
379 if( This
->dp2
->spData
.lpCB
->ShutdownEx
)
381 DPSP_SHUTDOWNDATA data
;
383 TRACE( "Calling SP ShutdownEx\n" );
385 data
.lpISP
= This
->dp2
->spData
.lpISP
;
387 (*This
->dp2
->spData
.lpCB
->ShutdownEx
)( &data
);
389 else if (This
->dp2
->spData
.lpCB
->Shutdown
) /* obsolete interface */
391 TRACE( "Calling obsolete SP Shutdown\n" );
392 (*This
->dp2
->spData
.lpCB
->Shutdown
)();
395 /* Unload the SP (if it exists) */
396 if( This
->dp2
->hServiceProvider
!= 0 )
398 FreeLibrary( This
->dp2
->hServiceProvider
);
401 /* Unload the Lobby Provider (if it exists) */
402 if( This
->dp2
->hDPLobbyProvider
!= 0 )
404 FreeLibrary( This
->dp2
->hDPLobbyProvider
);
408 DPQ_DELETEQ( This
->dp2
->players
, players
, lpPlayerList
, cbDeletePlayerElem
);
409 DPQ_DELETEQ( This
->dp2
->groups
, groups
, lpGroupList
, cbDeleteGroupsElem
);
412 /* FIXME: Need to delete receive and send msgs queue contents */
414 NS_DeleteSessionCache( This
->dp2
->lpNameServerData
);
416 HeapFree( GetProcessHeap(), 0, This
->dp2
->lpSessionDesc
);
418 IDirectPlaySP_Release( This
->dp2
->spData
.lpISP
);
420 /* Delete the contents */
421 HeapFree( GetProcessHeap(), 0, This
->dp2
);
426 static BOOL
DP_CreateDirectPlay3( LPVOID lpDP
)
428 IDirectPlay3AImpl
*This
= (IDirectPlay3AImpl
*)lpDP
;
430 This
->dp3
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *(This
->dp3
) ) );
431 if ( This
->dp3
== NULL
)
439 static BOOL
DP_DestroyDirectPlay3( LPVOID lpDP
)
441 IDirectPlay3AImpl
*This
= (IDirectPlay3AImpl
*)lpDP
;
443 /* Delete the contents */
444 HeapFree( GetProcessHeap(), 0, This
->dp3
);
449 static BOOL
DP_CreateDirectPlay4( LPVOID lpDP
)
451 IDirectPlay4AImpl
*This
= (IDirectPlay4AImpl
*)lpDP
;
453 This
->dp4
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *(This
->dp4
) ) );
454 if ( This
->dp4
== NULL
)
462 static BOOL
DP_DestroyDirectPlay4( LPVOID lpDP
)
464 IDirectPlay3AImpl
*This
= (IDirectPlay3AImpl
*)lpDP
;
466 /* Delete the contents */
467 HeapFree( GetProcessHeap(), 0, This
->dp4
);
473 /* Create a new interface */
475 HRESULT DP_CreateInterface
476 ( REFIID riid
, LPVOID
* ppvObj
)
478 TRACE( " for %s\n", debugstr_guid( riid
) );
480 *ppvObj
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
481 sizeof( IDirectPlay2Impl
) );
483 if( *ppvObj
== NULL
)
485 return DPERR_OUTOFMEMORY
;
488 if( IsEqualGUID( &IID_IDirectPlay2
, riid
) )
490 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)*ppvObj
;
491 This
->lpVtbl
= &directPlay2WVT
;
493 else if( IsEqualGUID( &IID_IDirectPlay2A
, riid
) )
495 IDirectPlay2AImpl
*This
= (IDirectPlay2AImpl
*)*ppvObj
;
496 This
->lpVtbl
= &directPlay2AVT
;
498 else if( IsEqualGUID( &IID_IDirectPlay3
, riid
) )
500 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)*ppvObj
;
501 This
->lpVtbl
= &directPlay3WVT
;
503 else if( IsEqualGUID( &IID_IDirectPlay3A
, riid
) )
505 IDirectPlay3AImpl
*This
= (IDirectPlay3AImpl
*)*ppvObj
;
506 This
->lpVtbl
= &directPlay3AVT
;
508 else if( IsEqualGUID( &IID_IDirectPlay4
, riid
) )
510 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)*ppvObj
;
511 This
->lpVtbl
= &directPlay4WVT
;
513 else if( IsEqualGUID( &IID_IDirectPlay4A
, riid
) )
515 IDirectPlay4AImpl
*This
= (IDirectPlay4AImpl
*)*ppvObj
;
516 This
->lpVtbl
= &directPlay4AVT
;
520 /* Unsupported interface */
521 HeapFree( GetProcessHeap(), 0, *ppvObj
);
524 return E_NOINTERFACE
;
528 if ( DP_CreateIUnknown( *ppvObj
) &&
529 DP_CreateDirectPlay2( *ppvObj
) &&
530 DP_CreateDirectPlay3( *ppvObj
) &&
531 DP_CreateDirectPlay4( *ppvObj
)
534 IDirectPlayX_AddRef( (LPDIRECTPLAY2A
)*ppvObj
);
539 /* Initialize failed, destroy it */
540 DP_DestroyDirectPlay4( *ppvObj
);
541 DP_DestroyDirectPlay3( *ppvObj
);
542 DP_DestroyDirectPlay2( *ppvObj
);
543 DP_DestroyIUnknown( *ppvObj
);
545 HeapFree( GetProcessHeap(), 0, *ppvObj
);
548 return DPERR_NOMEMORY
;
552 /* Direct Play methods */
554 /* Shared between all dplay types */
555 static HRESULT WINAPI DP_QueryInterface
556 ( LPDIRECTPLAY2 iface
, REFIID riid
, LPVOID
* ppvObj
)
558 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
559 TRACE("(%p)->(%s,%p)\n", This
, debugstr_guid( riid
), ppvObj
);
561 *ppvObj
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
564 if( *ppvObj
== NULL
)
566 return DPERR_OUTOFMEMORY
;
569 CopyMemory( *ppvObj
, This
, sizeof( *This
) );
570 (*(IDirectPlay2Impl
**)ppvObj
)->ulInterfaceRef
= 0;
572 if( IsEqualGUID( &IID_IDirectPlay2
, riid
) )
574 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)*ppvObj
;
575 This
->lpVtbl
= &directPlay2WVT
;
577 else if( IsEqualGUID( &IID_IDirectPlay2A
, riid
) )
579 IDirectPlay2AImpl
*This
= (IDirectPlay2AImpl
*)*ppvObj
;
580 This
->lpVtbl
= &directPlay2AVT
;
582 else if( IsEqualGUID( &IID_IDirectPlay3
, riid
) )
584 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)*ppvObj
;
585 This
->lpVtbl
= &directPlay3WVT
;
587 else if( IsEqualGUID( &IID_IDirectPlay3A
, riid
) )
589 IDirectPlay3AImpl
*This
= (IDirectPlay3AImpl
*)*ppvObj
;
590 This
->lpVtbl
= &directPlay3AVT
;
592 else if( IsEqualGUID( &IID_IDirectPlay4
, riid
) )
594 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)*ppvObj
;
595 This
->lpVtbl
= &directPlay4WVT
;
597 else if( IsEqualGUID( &IID_IDirectPlay4A
, riid
) )
599 IDirectPlay4AImpl
*This
= (IDirectPlay4AImpl
*)*ppvObj
;
600 This
->lpVtbl
= &directPlay4AVT
;
604 /* Unsupported interface */
605 HeapFree( GetProcessHeap(), 0, *ppvObj
);
608 return E_NOINTERFACE
;
611 IDirectPlayX_AddRef( (LPDIRECTPLAY2
)*ppvObj
);
616 /* Shared between all dplay types */
617 static ULONG WINAPI DP_AddRef
618 ( LPDIRECTPLAY3 iface
)
620 ULONG ulInterfaceRefCount
, ulObjRefCount
;
621 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
623 ulObjRefCount
= InterlockedIncrement( &This
->unk
->ulObjRef
);
624 ulInterfaceRefCount
= InterlockedIncrement( &This
->ulInterfaceRef
);
626 TRACE( "ref count incremented to %u:%u for %p\n",
627 ulInterfaceRefCount
, ulObjRefCount
, This
);
629 return ulObjRefCount
;
632 static ULONG WINAPI DP_Release
633 ( LPDIRECTPLAY3 iface
)
635 ULONG ulInterfaceRefCount
, ulObjRefCount
;
637 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
639 ulObjRefCount
= InterlockedDecrement( &This
->unk
->ulObjRef
);
640 ulInterfaceRefCount
= InterlockedDecrement( &This
->ulInterfaceRef
);
642 TRACE( "ref count decremented to %u:%u for %p\n",
643 ulInterfaceRefCount
, ulObjRefCount
, This
);
645 /* Deallocate if this is the last reference to the object */
646 if( ulObjRefCount
== 0 )
648 /* If we're destroying the object, this must be the last ref
649 of the last interface */
650 DP_DestroyDirectPlay4( This
);
651 DP_DestroyDirectPlay3( This
);
652 DP_DestroyDirectPlay2( This
);
653 DP_DestroyIUnknown( This
);
656 /* Deallocate the interface */
657 if( ulInterfaceRefCount
== 0 )
659 HeapFree( GetProcessHeap(), 0, This
);
662 return ulObjRefCount
;
665 static inline DPID
DP_NextObjectId(void)
667 return (DPID
)InterlockedIncrement( &kludgePlayerGroupId
);
670 /* *lplpReply will be non NULL iff there is something to reply */
671 HRESULT
DP_HandleMessage( IDirectPlay2Impl
* This
, LPCVOID lpcMessageBody
,
672 DWORD dwMessageBodySize
, LPCVOID lpcMessageHeader
,
673 WORD wCommandId
, WORD wVersion
,
674 LPVOID
* lplpReply
, LPDWORD lpdwMsgSize
)
676 TRACE( "(%p)->(%p,0x%08x,%p,%u,%u)\n",
677 This
, lpcMessageBody
, dwMessageBodySize
, lpcMessageHeader
, wCommandId
,
682 /* Name server needs to handle this request */
683 case DPMSGCMD_ENUMSESSIONSREQUEST
:
686 NS_ReplyToEnumSessionsRequest( lpcMessageBody
, lplpReply
, lpdwMsgSize
, This
);
691 /* Name server needs to handle this request */
692 case DPMSGCMD_ENUMSESSIONSREPLY
:
694 /* No reply expected */
695 NS_AddRemoteComputerAsNameServer( lpcMessageHeader
,
696 This
->dp2
->spData
.dwSPHeaderSize
,
698 This
->dp2
->lpNameServerData
);
702 case DPMSGCMD_REQUESTNEWPLAYERID
:
704 LPCDPMSG_REQUESTNEWPLAYERID lpcMsg
=
705 (LPCDPMSG_REQUESTNEWPLAYERID
)lpcMessageBody
;
707 LPDPMSG_NEWPLAYERIDREPLY lpReply
;
709 *lpdwMsgSize
= This
->dp2
->spData
.dwSPHeaderSize
+ sizeof( *lpReply
);
711 *lplpReply
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, *lpdwMsgSize
);
713 FIXME( "Ignoring dwFlags 0x%08x in request msg\n",
716 /* Setup the reply */
717 lpReply
= (LPDPMSG_NEWPLAYERIDREPLY
)( (BYTE
*)(*lplpReply
) +
718 This
->dp2
->spData
.dwSPHeaderSize
);
720 lpReply
->envelope
.dwMagic
= DPMSGMAGIC_DPLAYMSG
;
721 lpReply
->envelope
.wCommandId
= DPMSGCMD_NEWPLAYERIDREPLY
;
722 lpReply
->envelope
.wVersion
= DPMSGVER_DP6
;
724 lpReply
->dpidNewPlayerId
= DP_NextObjectId();
726 TRACE( "Allocating new playerid 0x%08x from remote request\n",
727 lpReply
->dpidNewPlayerId
);
732 case DPMSGCMD_GETNAMETABLEREPLY
:
733 case DPMSGCMD_NEWPLAYERIDREPLY
:
737 if( wCommandId
== DPMSGCMD_NEWPLAYERIDREPLY
)
740 DP_MSG_ReplyReceived( This
, wCommandId
, lpcMessageBody
, dwMessageBodySize
);
746 case DPMSGCMD_JUSTENVELOPE
:
748 TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08x\n", lpcMessageHeader
, ((const DWORD
*)lpcMessageHeader
)[1] );
749 NS_SetLocalAddr( This
->dp2
->lpNameServerData
, lpcMessageHeader
, 20 );
750 DP_MSG_ReplyReceived( This
, wCommandId
, lpcMessageBody
, dwMessageBodySize
);
754 case DPMSGCMD_FORWARDADDPLAYER
:
760 TRACE( "Sending message to self to get my addr\n" );
761 DP_MSG_ToSelf( This
, 1 ); /* This is a hack right now */
766 case DPMSGCMD_FORWARDADDPLAYERNACK
:
768 DP_MSG_ErrorReceived( This
, wCommandId
, lpcMessageBody
, dwMessageBodySize
);
774 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId
);
780 /* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */
786 static HRESULT WINAPI DP_IF_AddPlayerToGroup
787 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idGroup
,
788 DPID idPlayer
, BOOL bAnsi
)
791 lpPlayerList lpPList
;
792 lpPlayerList lpNewPList
;
794 TRACE( "(%p)->(%p,0x%08x,0x%08x,%u)\n",
795 This
, lpMsgHdr
, idGroup
, idPlayer
, bAnsi
);
798 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
800 return DPERR_INVALIDGROUP
;
803 /* Find the player */
804 if( ( lpPList
= DP_FindPlayer( This
, idPlayer
) ) == NULL
)
806 return DPERR_INVALIDPLAYER
;
809 /* Create a player list (ie "shortcut" ) */
810 lpNewPList
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpNewPList
) );
811 if( lpNewPList
== NULL
)
813 return DPERR_CANTADDPLAYER
;
816 /* Add the shortcut */
817 lpPList
->lpPData
->uRef
++;
818 lpNewPList
->lpPData
= lpPList
->lpPData
;
820 /* Add the player to the list of players for this group */
821 DPQ_INSERT(lpGData
->players
,lpNewPList
,players
);
823 /* Let the SP know that we've added a player to the group */
824 if( This
->dp2
->spData
.lpCB
->AddPlayerToGroup
)
826 DPSP_ADDPLAYERTOGROUPDATA data
;
828 TRACE( "Calling SP AddPlayerToGroup\n" );
830 data
.idPlayer
= idPlayer
;
831 data
.idGroup
= idGroup
;
832 data
.lpISP
= This
->dp2
->spData
.lpISP
;
834 (*This
->dp2
->spData
.lpCB
->AddPlayerToGroup
)( &data
);
837 /* Inform all other peers of the addition of player to the group. If there are
838 * no peers keep this event quiet.
839 * Also, if this event was the result of another machine sending it to us,
840 * don't bother rebroadcasting it.
842 if( ( lpMsgHdr
== NULL
) &&
843 This
->dp2
->lpSessionDesc
&&
844 ( This
->dp2
->lpSessionDesc
->dwFlags
& DPSESSION_MULTICASTSERVER
) )
846 DPMSG_ADDPLAYERTOGROUP msg
;
847 msg
.dwType
= DPSYS_ADDPLAYERTOGROUP
;
849 msg
.dpIdGroup
= idGroup
;
850 msg
.dpIdPlayer
= idPlayer
;
852 /* FIXME: Correct to just use send effectively? */
853 /* FIXME: Should size include data w/ message or just message "header" */
854 /* FIXME: Check return code */
855 DP_SendEx( This
, DPID_SERVERPLAYER
, DPID_ALLPLAYERS
, 0, &msg
, sizeof( msg
), 0, 0, NULL
, NULL
, bAnsi
);
861 static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
862 ( LPDIRECTPLAY2A iface
, DPID idGroup
, DPID idPlayer
)
864 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
865 return DP_IF_AddPlayerToGroup( This
, NULL
, idGroup
, idPlayer
, TRUE
);
868 static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
869 ( LPDIRECTPLAY2 iface
, DPID idGroup
, DPID idPlayer
)
871 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
872 return DP_IF_AddPlayerToGroup( This
, NULL
, idGroup
, idPlayer
, FALSE
);
875 static HRESULT WINAPI
DP_IF_Close( IDirectPlay2Impl
* This
, BOOL bAnsi
)
879 TRACE("(%p)->(%u)\n", This
, bAnsi
);
881 /* FIXME: Need to find a new host I assume (how?) */
882 /* FIXME: Need to destroy all local groups */
883 /* FIXME: Need to migrate all remotely visible players to the new host */
885 /* Invoke the SP callback to inform of session close */
886 if( This
->dp2
->spData
.lpCB
->CloseEx
)
890 TRACE( "Calling SP CloseEx\n" );
892 data
.lpISP
= This
->dp2
->spData
.lpISP
;
894 hr
= (*This
->dp2
->spData
.lpCB
->CloseEx
)( &data
);
897 else if ( This
->dp2
->spData
.lpCB
->Close
) /* Try obsolete version */
899 TRACE( "Calling SP Close (obsolete interface)\n" );
901 hr
= (*This
->dp2
->spData
.lpCB
->Close
)();
907 static HRESULT WINAPI DirectPlay2AImpl_Close
908 ( LPDIRECTPLAY2A iface
)
910 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
911 return DP_IF_Close( This
, TRUE
);
914 static HRESULT WINAPI DirectPlay2WImpl_Close
915 ( LPDIRECTPLAY2 iface
)
917 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
918 return DP_IF_Close( This
, FALSE
);
922 lpGroupData
DP_CreateGroup( IDirectPlay2AImpl
* This
, const DPID
*lpid
,
923 const DPNAME
*lpName
, DWORD dwFlags
,
924 DPID idParent
, BOOL bAnsi
)
928 /* Allocate the new space and add to end of high level group list */
929 lpGData
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpGData
) );
931 if( lpGData
== NULL
)
936 DPQ_INIT(lpGData
->groups
);
937 DPQ_INIT(lpGData
->players
);
939 /* Set the desired player ID - no sanity checking to see if it exists */
940 lpGData
->dpid
= *lpid
;
942 DP_CopyDPNAMEStruct( &lpGData
->name
, lpName
, bAnsi
);
944 /* FIXME: Should we check that the parent exists? */
945 lpGData
->parent
= idParent
;
947 /* FIXME: Should we validate the dwFlags? */
948 lpGData
->dwFlags
= dwFlags
;
950 TRACE( "Created group id 0x%08x\n", *lpid
);
955 /* This method assumes that all links to it are already deleted */
957 DP_DeleteGroup( IDirectPlay2Impl
* This
, DPID dpid
)
961 TRACE( "(%p)->(0x%08x)\n", This
, dpid
);
963 DPQ_REMOVE_ENTRY( This
->dp2
->lpSysGroup
->groups
, groups
, lpGData
->dpid
, ==, dpid
, lpGList
);
965 if( lpGList
== NULL
)
967 ERR( "DPID 0x%08x not found\n", dpid
);
971 if( --(lpGList
->lpGData
->uRef
) )
973 FIXME( "Why is this not the last reference to group?\n" );
978 DP_DeleteDPNameStruct( &lpGList
->lpGData
->name
);
979 HeapFree( GetProcessHeap(), 0, lpGList
->lpGData
);
981 /* Remove and Delete Player List object */
982 HeapFree( GetProcessHeap(), 0, lpGList
);
986 static lpGroupData
DP_FindAnyGroup( IDirectPlay2AImpl
* This
, DPID dpid
)
988 lpGroupList lpGroups
;
990 TRACE( "(%p)->(0x%08x)\n", This
, dpid
);
992 if( dpid
== DPID_SYSTEM_GROUP
)
994 return This
->dp2
->lpSysGroup
;
998 DPQ_FIND_ENTRY( This
->dp2
->lpSysGroup
->groups
, groups
, lpGData
->dpid
, ==, dpid
, lpGroups
);
1001 if( lpGroups
== NULL
)
1006 return lpGroups
->lpGData
;
1009 static HRESULT WINAPI DP_IF_CreateGroup
1010 ( IDirectPlay2AImpl
* This
, LPVOID lpMsgHdr
, LPDPID lpidGroup
,
1011 LPDPNAME lpGroupName
, LPVOID lpData
, DWORD dwDataSize
,
1012 DWORD dwFlags
, BOOL bAnsi
)
1014 lpGroupData lpGData
;
1016 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1017 This
, lpMsgHdr
, lpidGroup
, lpGroupName
, lpData
, dwDataSize
,
1020 /* If the name is not specified, we must provide one */
1021 if( DPID_UNKNOWN
== *lpidGroup
)
1023 /* If we are the name server, we decide on the group ids. If not, we
1024 * must ask for one before attempting a creation.
1026 if( This
->dp2
->bHostInterface
)
1028 *lpidGroup
= DP_NextObjectId();
1032 *lpidGroup
= DP_GetRemoteNextObjectId();
1036 lpGData
= DP_CreateGroup( This
, lpidGroup
, lpGroupName
, dwFlags
,
1037 DPID_NOPARENT_GROUP
, bAnsi
);
1039 if( lpGData
== NULL
)
1041 return DPERR_CANTADDPLAYER
; /* yes player not group */
1044 if( DPID_SYSTEM_GROUP
== *lpidGroup
)
1046 This
->dp2
->lpSysGroup
= lpGData
;
1047 TRACE( "Inserting system group\n" );
1051 /* Insert into the system group */
1052 lpGroupList lpGroup
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpGroup
) );
1053 lpGroup
->lpGData
= lpGData
;
1055 DPQ_INSERT( This
->dp2
->lpSysGroup
->groups
, lpGroup
, groups
);
1058 /* Something is now referencing this data */
1061 /* Set all the important stuff for the group */
1062 DP_SetGroupData( lpGData
, DPSET_REMOTE
, lpData
, dwDataSize
);
1064 /* FIXME: We should only create the system group if GetCaps returns
1065 * DPCAPS_GROUPOPTIMIZED.
1068 /* Let the SP know that we've created this group */
1069 if( This
->dp2
->spData
.lpCB
->CreateGroup
)
1071 DPSP_CREATEGROUPDATA data
;
1072 DWORD dwCreateFlags
= 0;
1074 TRACE( "Calling SP CreateGroup\n" );
1076 if( *lpidGroup
== DPID_NOPARENT_GROUP
)
1077 dwCreateFlags
|= DPLAYI_GROUP_SYSGROUP
;
1079 if( lpMsgHdr
== NULL
)
1080 dwCreateFlags
|= DPLAYI_PLAYER_PLAYERLOCAL
;
1082 if( dwFlags
& DPGROUP_HIDDEN
)
1083 dwCreateFlags
|= DPLAYI_GROUP_HIDDEN
;
1085 data
.idGroup
= *lpidGroup
;
1086 data
.dwFlags
= dwCreateFlags
;
1087 data
.lpSPMessageHeader
= lpMsgHdr
;
1088 data
.lpISP
= This
->dp2
->spData
.lpISP
;
1090 (*This
->dp2
->spData
.lpCB
->CreateGroup
)( &data
);
1093 /* Inform all other peers of the creation of a new group. If there are
1094 * no peers keep this event quiet.
1095 * Also if this message was sent to us, don't rebroadcast.
1097 if( ( lpMsgHdr
== NULL
) &&
1098 This
->dp2
->lpSessionDesc
&&
1099 ( This
->dp2
->lpSessionDesc
->dwFlags
& DPSESSION_MULTICASTSERVER
) )
1101 DPMSG_CREATEPLAYERORGROUP msg
;
1102 msg
.dwType
= DPSYS_CREATEPLAYERORGROUP
;
1104 msg
.dwPlayerType
= DPPLAYERTYPE_GROUP
;
1105 msg
.dpId
= *lpidGroup
;
1106 msg
.dwCurrentPlayers
= 0; /* FIXME: Incorrect? */
1107 msg
.lpData
= lpData
;
1108 msg
.dwDataSize
= dwDataSize
;
1109 msg
.dpnName
= *lpGroupName
;
1110 msg
.dpIdParent
= DPID_NOPARENT_GROUP
;
1111 msg
.dwFlags
= DPMSG_CREATEGROUP_DWFLAGS( dwFlags
);
1113 /* FIXME: Correct to just use send effectively? */
1114 /* FIXME: Should size include data w/ message or just message "header" */
1115 /* FIXME: Check return code */
1116 DP_SendEx( This
, DPID_SERVERPLAYER
, DPID_ALLPLAYERS
, 0, &msg
, sizeof( msg
),
1117 0, 0, NULL
, NULL
, bAnsi
);
1123 static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
1124 ( LPDIRECTPLAY2A iface
, LPDPID lpidGroup
, LPDPNAME lpGroupName
,
1125 LPVOID lpData
, DWORD dwDataSize
, DWORD dwFlags
)
1127 *lpidGroup
= DPID_UNKNOWN
;
1129 return DP_IF_CreateGroup( (IDirectPlay2AImpl
*)iface
, NULL
, lpidGroup
,
1130 lpGroupName
, lpData
, dwDataSize
, dwFlags
, TRUE
);
1133 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
1134 ( LPDIRECTPLAY2 iface
, LPDPID lpidGroup
, LPDPNAME lpGroupName
,
1135 LPVOID lpData
, DWORD dwDataSize
, DWORD dwFlags
)
1137 *lpidGroup
= DPID_UNKNOWN
;
1139 return DP_IF_CreateGroup( (IDirectPlay2AImpl
*)iface
, NULL
, lpidGroup
,
1140 lpGroupName
, lpData
, dwDataSize
, dwFlags
, FALSE
);
1145 DP_SetGroupData( lpGroupData lpGData
, DWORD dwFlags
,
1146 LPVOID lpData
, DWORD dwDataSize
)
1148 /* Clear out the data with this player */
1149 if( dwFlags
& DPSET_LOCAL
)
1151 if ( lpGData
->dwLocalDataSize
!= 0 )
1153 HeapFree( GetProcessHeap(), 0, lpGData
->lpLocalData
);
1154 lpGData
->lpLocalData
= NULL
;
1155 lpGData
->dwLocalDataSize
= 0;
1160 if( lpGData
->dwRemoteDataSize
!= 0 )
1162 HeapFree( GetProcessHeap(), 0, lpGData
->lpRemoteData
);
1163 lpGData
->lpRemoteData
= NULL
;
1164 lpGData
->dwRemoteDataSize
= 0;
1168 /* Reallocate for new data */
1169 if( lpData
!= NULL
)
1171 LPVOID lpNewData
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
1172 sizeof( dwDataSize
) );
1173 CopyMemory( lpNewData
, lpData
, dwDataSize
);
1175 if( dwFlags
& DPSET_LOCAL
)
1177 lpGData
->lpLocalData
= lpData
;
1178 lpGData
->dwLocalDataSize
= dwDataSize
;
1182 lpGData
->lpRemoteData
= lpNewData
;
1183 lpGData
->dwRemoteDataSize
= dwDataSize
;
1189 /* This function will just create the storage for the new player. */
1191 lpPlayerData
DP_CreatePlayer( IDirectPlay2Impl
* This
, LPDPID lpid
,
1192 LPDPNAME lpName
, DWORD dwFlags
,
1193 HANDLE hEvent
, BOOL bAnsi
)
1195 lpPlayerData lpPData
;
1197 TRACE( "(%p)->(%p,%p,%u)\n", This
, lpid
, lpName
, bAnsi
);
1199 /* Allocate the storage for the player and associate it with list element */
1200 lpPData
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpPData
) );
1201 if( lpPData
== NULL
)
1206 /* Set the desired player ID */
1207 lpPData
->dpid
= *lpid
;
1209 DP_CopyDPNAMEStruct( &lpPData
->name
, lpName
, bAnsi
);
1211 lpPData
->dwFlags
= dwFlags
;
1213 /* If we were given an event handle, duplicate it */
1216 if( !DuplicateHandle( GetCurrentProcess(), hEvent
,
1217 GetCurrentProcess(), &lpPData
->hEvent
,
1218 0, FALSE
, DUPLICATE_SAME_ACCESS
)
1221 /* FIXME: Memory leak */
1222 ERR( "Can't duplicate player msg handle %p\n", hEvent
);
1226 /* Initialize the SP data section */
1227 lpPData
->lpSPPlayerData
= DPSP_CreateSPPlayerData();
1229 TRACE( "Created player id 0x%08x\n", *lpid
);
1231 if( ~dwFlags
& DPLAYI_PLAYER_SYSPLAYER
)
1232 This
->dp2
->lpSessionDesc
->dwCurrentPlayers
++;
1237 /* Delete the contents of the DPNAME struct */
1239 DP_DeleteDPNameStruct( LPDPNAME lpDPName
)
1241 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY
, lpDPName
->u1
.lpszShortNameA
);
1242 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY
, lpDPName
->u2
.lpszLongNameA
);
1245 /* This method assumes that all links to it are already deleted */
1247 DP_DeletePlayer( IDirectPlay2Impl
* This
, DPID dpid
)
1249 lpPlayerList lpPList
;
1251 TRACE( "(%p)->(0x%08x)\n", This
, dpid
);
1253 DPQ_REMOVE_ENTRY( This
->dp2
->lpSysGroup
->players
, players
, lpPData
->dpid
, ==, dpid
, lpPList
);
1255 if( lpPList
== NULL
)
1257 ERR( "DPID 0x%08x not found\n", dpid
);
1261 /* Verify that this is the last reference to the data */
1262 if( --(lpPList
->lpPData
->uRef
) )
1264 FIXME( "Why is this not the last reference to player?\n" );
1269 DP_DeleteDPNameStruct( &lpPList
->lpPData
->name
);
1271 CloseHandle( lpPList
->lpPData
->hEvent
);
1272 HeapFree( GetProcessHeap(), 0, lpPList
->lpPData
);
1274 /* Delete Player List object */
1275 HeapFree( GetProcessHeap(), 0, lpPList
);
1278 static lpPlayerList
DP_FindPlayer( IDirectPlay2AImpl
* This
, DPID dpid
)
1280 lpPlayerList lpPlayers
;
1282 TRACE( "(%p)->(0x%08x)\n", This
, dpid
);
1284 if(This
->dp2
->lpSysGroup
== NULL
)
1287 DPQ_FIND_ENTRY( This
->dp2
->lpSysGroup
->players
, players
, lpPData
->dpid
, ==, dpid
, lpPlayers
);
1292 /* Basic area for Dst must already be allocated */
1293 static BOOL
DP_CopyDPNAMEStruct( LPDPNAME lpDst
, const DPNAME
*lpSrc
, BOOL bAnsi
)
1297 ZeroMemory( lpDst
, sizeof( *lpDst
) );
1298 lpDst
->dwSize
= sizeof( *lpDst
);
1302 if( lpSrc
->dwSize
!= sizeof( *lpSrc
) )
1307 /* Delete any existing pointers */
1308 HeapFree( GetProcessHeap(), 0, lpDst
->u1
.lpszShortNameA
);
1309 HeapFree( GetProcessHeap(), 0, lpDst
->u2
.lpszLongNameA
);
1311 /* Copy as required */
1312 CopyMemory( lpDst
, lpSrc
, lpSrc
->dwSize
);
1316 if( lpSrc
->u1
.lpszShortNameA
)
1318 lpDst
->u1
.lpszShortNameA
= HeapAlloc( GetProcessHeap(), 0,
1319 strlen(lpSrc
->u1
.lpszShortNameA
)+1 );
1320 strcpy( lpDst
->u1
.lpszShortNameA
, lpSrc
->u1
.lpszShortNameA
);
1322 if( lpSrc
->u2
.lpszLongNameA
)
1324 lpDst
->u2
.lpszLongNameA
= HeapAlloc( GetProcessHeap(), 0,
1325 strlen(lpSrc
->u2
.lpszLongNameA
)+1 );
1326 strcpy( lpDst
->u2
.lpszLongNameA
, lpSrc
->u2
.lpszLongNameA
);
1331 if( lpSrc
->u1
.lpszShortNameA
)
1333 lpDst
->u1
.lpszShortName
= HeapAlloc( GetProcessHeap(), 0,
1334 (strlenW(lpSrc
->u1
.lpszShortName
)+1)*sizeof(WCHAR
) );
1335 strcpyW( lpDst
->u1
.lpszShortName
, lpSrc
->u1
.lpszShortName
);
1337 if( lpSrc
->u2
.lpszLongNameA
)
1339 lpDst
->u2
.lpszLongName
= HeapAlloc( GetProcessHeap(), 0,
1340 (strlenW(lpSrc
->u2
.lpszLongName
)+1)*sizeof(WCHAR
) );
1341 strcpyW( lpDst
->u2
.lpszLongName
, lpSrc
->u2
.lpszLongName
);
1349 DP_SetPlayerData( lpPlayerData lpPData
, DWORD dwFlags
,
1350 LPVOID lpData
, DWORD dwDataSize
)
1352 /* Clear out the data with this player */
1353 if( dwFlags
& DPSET_LOCAL
)
1355 if ( lpPData
->dwLocalDataSize
!= 0 )
1357 HeapFree( GetProcessHeap(), 0, lpPData
->lpLocalData
);
1358 lpPData
->lpLocalData
= NULL
;
1359 lpPData
->dwLocalDataSize
= 0;
1364 if( lpPData
->dwRemoteDataSize
!= 0 )
1366 HeapFree( GetProcessHeap(), 0, lpPData
->lpRemoteData
);
1367 lpPData
->lpRemoteData
= NULL
;
1368 lpPData
->dwRemoteDataSize
= 0;
1372 /* Reallocate for new data */
1373 if( lpData
!= NULL
)
1375 LPVOID lpNewData
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
1376 sizeof( dwDataSize
) );
1377 CopyMemory( lpNewData
, lpData
, dwDataSize
);
1379 if( dwFlags
& DPSET_LOCAL
)
1381 lpPData
->lpLocalData
= lpData
;
1382 lpPData
->dwLocalDataSize
= dwDataSize
;
1386 lpPData
->lpRemoteData
= lpNewData
;
1387 lpPData
->dwRemoteDataSize
= dwDataSize
;
1393 static HRESULT WINAPI DP_IF_CreatePlayer
1394 ( IDirectPlay2Impl
* This
,
1395 LPVOID lpMsgHdr
, /* NULL for local creation, non NULL for remote creation */
1397 LPDPNAME lpPlayerName
,
1405 lpPlayerData lpPData
;
1406 lpPlayerList lpPList
;
1407 DWORD dwCreateFlags
= 0;
1409 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1410 This
, lpidPlayer
, lpPlayerName
, hEvent
, lpData
,
1411 dwDataSize
, dwFlags
, bAnsi
);
1415 dwFlags
= DPPLAYER_SPECTATOR
;
1418 if( lpidPlayer
== NULL
)
1420 return DPERR_INVALIDPARAMS
;
1424 /* Determine the creation flags for the player. These will be passed
1425 * to the name server if requesting a player id and to the SP when
1426 * informing it of the player creation
1429 if( dwFlags
& DPPLAYER_SERVERPLAYER
)
1431 if( *lpidPlayer
== DPID_SERVERPLAYER
)
1433 /* Server player for the host interface */
1434 dwCreateFlags
|= DPLAYI_PLAYER_APPSERVER
;
1436 else if( *lpidPlayer
== DPID_NAME_SERVER
)
1438 /* Name server - master of everything */
1439 dwCreateFlags
|= (DPLAYI_PLAYER_NAMESRVR
|DPLAYI_PLAYER_SYSPLAYER
);
1443 /* Server player for a non host interface */
1444 dwCreateFlags
|= DPLAYI_PLAYER_SYSPLAYER
;
1448 if( lpMsgHdr
== NULL
)
1449 dwCreateFlags
|= DPLAYI_PLAYER_PLAYERLOCAL
;
1452 /* Verify we know how to handle all the flags */
1453 if( !( ( dwFlags
& DPPLAYER_SERVERPLAYER
) ||
1454 ( dwFlags
& DPPLAYER_SPECTATOR
)
1458 /* Assume non fatal failure */
1459 ERR( "unknown dwFlags = 0x%08x\n", dwFlags
);
1462 /* If the name is not specified, we must provide one */
1463 if( *lpidPlayer
== DPID_UNKNOWN
)
1465 /* If we are the session master, we dish out the group/player ids */
1466 if( This
->dp2
->bHostInterface
)
1468 *lpidPlayer
= DP_NextObjectId();
1472 hr
= DP_MSG_SendRequestPlayerId( This
, dwCreateFlags
, lpidPlayer
);
1476 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr
) );
1483 /* FIXME: Would be nice to perhaps verify that we don't already have
1488 /* We pass creation flags, so we can distinguish sysplayers and not count them in the current
1490 lpPData
= DP_CreatePlayer( This
, lpidPlayer
, lpPlayerName
, dwCreateFlags
,
1493 if( lpPData
== NULL
)
1495 return DPERR_CANTADDPLAYER
;
1498 /* Create the list object and link it in */
1499 lpPList
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpPList
) );
1500 if( lpPList
== NULL
)
1502 FIXME( "Memory leak\n" );
1503 return DPERR_CANTADDPLAYER
;
1507 lpPList
->lpPData
= lpPData
;
1509 /* Add the player to the system group */
1510 DPQ_INSERT( This
->dp2
->lpSysGroup
->players
, lpPList
, players
);
1512 /* Update the information and send it to all players in the session */
1513 DP_SetPlayerData( lpPData
, DPSET_REMOTE
, lpData
, dwDataSize
);
1515 /* Let the SP know that we've created this player */
1516 if( This
->dp2
->spData
.lpCB
->CreatePlayer
)
1518 DPSP_CREATEPLAYERDATA data
;
1520 data
.idPlayer
= *lpidPlayer
;
1521 data
.dwFlags
= dwCreateFlags
;
1522 data
.lpSPMessageHeader
= lpMsgHdr
;
1523 data
.lpISP
= This
->dp2
->spData
.lpISP
;
1525 TRACE( "Calling SP CreatePlayer 0x%08x: dwFlags: 0x%08x lpMsgHdr: %p\n",
1526 *lpidPlayer
, data
.dwFlags
, data
.lpSPMessageHeader
);
1528 hr
= (*This
->dp2
->spData
.lpCB
->CreatePlayer
)( &data
);
1533 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr
) );
1537 /* Now let the SP know that this player is a member of the system group */
1538 if( This
->dp2
->spData
.lpCB
->AddPlayerToGroup
)
1540 DPSP_ADDPLAYERTOGROUPDATA data
;
1542 data
.idPlayer
= *lpidPlayer
;
1543 data
.idGroup
= DPID_SYSTEM_GROUP
;
1544 data
.lpISP
= This
->dp2
->spData
.lpISP
;
1546 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1548 hr
= (*This
->dp2
->spData
.lpCB
->AddPlayerToGroup
)( &data
);
1553 ERR( "Failed to add player to sys group with sp: %s\n",
1554 DPLAYX_HresultToString(hr
) );
1559 if( This
->dp2
->bHostInterface
== FALSE
)
1561 /* Let the name server know about the creation of this player */
1562 /* FIXME: Is this only to be done for the creation of a server player or
1563 * is this used for regular players? If only for server players, move
1564 * this call to DP_SecureOpen(...);
1567 TRACE( "Sending message to self to get my addr\n" );
1568 DP_MSG_ToSelf( This
, *lpidPlayer
); /* This is a hack right now */
1571 hr
= DP_MSG_ForwardPlayerCreation( This
, *lpidPlayer
);
1574 /* Inform all other peers of the creation of a new player. If there are
1575 * no peers keep this quiet.
1576 * Also, if this was a remote event, no need to rebroadcast it.
1578 if( ( lpMsgHdr
== NULL
) &&
1579 This
->dp2
->lpSessionDesc
&&
1580 ( This
->dp2
->lpSessionDesc
->dwFlags
& DPSESSION_MULTICASTSERVER
) )
1582 DPMSG_CREATEPLAYERORGROUP msg
;
1583 msg
.dwType
= DPSYS_CREATEPLAYERORGROUP
;
1585 msg
.dwPlayerType
= DPPLAYERTYPE_PLAYER
;
1586 msg
.dpId
= *lpidPlayer
;
1587 msg
.dwCurrentPlayers
= 0; /* FIXME: Incorrect */
1588 msg
.lpData
= lpData
;
1589 msg
.dwDataSize
= dwDataSize
;
1590 msg
.dpnName
= *lpPlayerName
;
1591 msg
.dpIdParent
= DPID_NOPARENT_GROUP
;
1592 msg
.dwFlags
= DPMSG_CREATEPLAYER_DWFLAGS( dwFlags
);
1594 /* FIXME: Correct to just use send effectively? */
1595 /* FIXME: Should size include data w/ message or just message "header" */
1596 /* FIXME: Check return code */
1597 hr
= DP_SendEx( This
, DPID_SERVERPLAYER
, DPID_ALLPLAYERS
, 0, &msg
,
1598 sizeof( msg
), 0, 0, NULL
, NULL
, bAnsi
);
1605 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
1606 ( LPDIRECTPLAY2A iface
, LPDPID lpidPlayer
, LPDPNAME lpPlayerName
,
1607 HANDLE hEvent
, LPVOID lpData
, DWORD dwDataSize
, DWORD dwFlags
)
1609 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
1611 if( dwFlags
& DPPLAYER_SERVERPLAYER
)
1613 *lpidPlayer
= DPID_SERVERPLAYER
;
1617 *lpidPlayer
= DPID_UNKNOWN
;
1620 return DP_IF_CreatePlayer( This
, NULL
, lpidPlayer
, lpPlayerName
, hEvent
,
1621 lpData
, dwDataSize
, dwFlags
, TRUE
);
1624 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
1625 ( LPDIRECTPLAY2 iface
, LPDPID lpidPlayer
, LPDPNAME lpPlayerName
,
1626 HANDLE hEvent
, LPVOID lpData
, DWORD dwDataSize
, DWORD dwFlags
)
1628 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
1630 if( dwFlags
& DPPLAYER_SERVERPLAYER
)
1632 *lpidPlayer
= DPID_SERVERPLAYER
;
1636 *lpidPlayer
= DPID_UNKNOWN
;
1639 return DP_IF_CreatePlayer( This
, NULL
, lpidPlayer
, lpPlayerName
, hEvent
,
1640 lpData
, dwDataSize
, dwFlags
, FALSE
);
1643 static DPID
DP_GetRemoteNextObjectId(void)
1648 return DP_NextObjectId();
1651 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
1652 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idGroup
,
1653 DPID idPlayer
, BOOL bAnsi
)
1657 lpGroupData lpGData
;
1658 lpPlayerList lpPList
;
1660 TRACE( "(%p)->(%p,0x%08x,0x%08x,%u)\n",
1661 This
, lpMsgHdr
, idGroup
, idPlayer
, bAnsi
);
1663 /* Find the group */
1664 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
1666 return DPERR_INVALIDGROUP
;
1669 /* Find the player */
1670 if( ( lpPList
= DP_FindPlayer( This
, idPlayer
) ) == NULL
)
1672 return DPERR_INVALIDPLAYER
;
1675 /* Remove the player shortcut from the group */
1676 DPQ_REMOVE_ENTRY( lpGData
->players
, players
, lpPData
->dpid
, ==, idPlayer
, lpPList
);
1678 if( lpPList
== NULL
)
1680 return DPERR_INVALIDPLAYER
;
1683 /* One less reference */
1684 lpPList
->lpPData
->uRef
--;
1686 /* Delete the Player List element */
1687 HeapFree( GetProcessHeap(), 0, lpPList
);
1689 /* Inform the SP if they care */
1690 if( This
->dp2
->spData
.lpCB
->RemovePlayerFromGroup
)
1692 DPSP_REMOVEPLAYERFROMGROUPDATA data
;
1694 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1696 data
.idPlayer
= idPlayer
;
1697 data
.idGroup
= idGroup
;
1698 data
.lpISP
= This
->dp2
->spData
.lpISP
;
1700 hr
= (*This
->dp2
->spData
.lpCB
->RemovePlayerFromGroup
)( &data
);
1703 /* Need to send a DELETEPLAYERFROMGROUP message */
1704 FIXME( "Need to send a message\n" );
1709 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
1710 ( LPDIRECTPLAY2A iface
, DPID idGroup
, DPID idPlayer
)
1712 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
1713 return DP_IF_DeletePlayerFromGroup( This
, NULL
, idGroup
, idPlayer
, TRUE
);
1716 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
1717 ( LPDIRECTPLAY2 iface
, DPID idGroup
, DPID idPlayer
)
1719 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
1720 return DP_IF_DeletePlayerFromGroup( This
, NULL
, idGroup
, idPlayer
, FALSE
);
1723 typedef struct _DPRGOPContext
1725 IDirectPlay3Impl
* This
;
1728 } DPRGOPContext
, *lpDPRGOPContext
;
1730 static BOOL CALLBACK
1731 cbRemoveGroupOrPlayer(
1738 lpDPRGOPContext lpCtxt
= (lpDPRGOPContext
)lpContext
;
1740 TRACE( "Removing element:0x%08x (type:0x%08x) from element:0x%08x\n",
1741 dpId
, dwPlayerType
, lpCtxt
->idGroup
);
1743 if( dwPlayerType
== DPPLAYERTYPE_GROUP
)
1745 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt
->This
, lpCtxt
->idGroup
,
1750 ERR( "Unable to delete group 0x%08x from group 0x%08x\n",
1751 dpId
, lpCtxt
->idGroup
);
1756 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl
*)lpCtxt
->This
,
1757 NULL
, lpCtxt
->idGroup
,
1758 dpId
, lpCtxt
->bAnsi
)
1762 ERR( "Unable to delete player 0x%08x from grp 0x%08x\n",
1763 dpId
, lpCtxt
->idGroup
);
1767 return TRUE
; /* Continue enumeration */
1770 static HRESULT WINAPI DP_IF_DestroyGroup
1771 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idGroup
, BOOL bAnsi
)
1773 lpGroupData lpGData
;
1774 DPRGOPContext context
;
1776 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1777 This
, lpMsgHdr
, idGroup
, bAnsi
);
1779 /* Find the group */
1780 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
1782 return DPERR_INVALIDPLAYER
; /* yes player */
1785 context
.This
= (IDirectPlay3Impl
*)This
;
1786 context
.bAnsi
= bAnsi
;
1787 context
.idGroup
= idGroup
;
1789 /* Remove all players that this group has */
1790 DP_IF_EnumGroupPlayers( This
, idGroup
, NULL
,
1791 cbRemoveGroupOrPlayer
, (LPVOID
)&context
, 0, bAnsi
);
1793 /* Remove all links to groups that this group has since this is dp3 */
1794 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl
*)This
, idGroup
, NULL
,
1795 cbRemoveGroupOrPlayer
, (LPVOID
)&context
, 0, bAnsi
);
1797 /* Remove this group from the parent group - if it has one */
1798 if( ( idGroup
!= DPID_SYSTEM_GROUP
) &&
1799 ( lpGData
->parent
!= DPID_SYSTEM_GROUP
)
1802 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl
*)This
, lpGData
->parent
,
1806 /* Now delete this group data and list from the system group */
1807 DP_DeleteGroup( This
, idGroup
);
1809 /* Let the SP know that we've destroyed this group */
1810 if( This
->dp2
->spData
.lpCB
->DeleteGroup
)
1812 DPSP_DELETEGROUPDATA data
;
1814 FIXME( "data.dwFlags is incorrect\n" );
1816 data
.idGroup
= idGroup
;
1818 data
.lpISP
= This
->dp2
->spData
.lpISP
;
1820 (*This
->dp2
->spData
.lpCB
->DeleteGroup
)( &data
);
1823 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1828 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
1829 ( LPDIRECTPLAY2A iface
, DPID idGroup
)
1831 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
1832 return DP_IF_DestroyGroup( This
, NULL
, idGroup
, TRUE
);
1835 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
1836 ( LPDIRECTPLAY2 iface
, DPID idGroup
)
1838 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
1839 return DP_IF_DestroyGroup( This
, NULL
, idGroup
, FALSE
);
1842 typedef struct _DPFAGContext
1844 IDirectPlay2Impl
* This
;
1847 } DPFAGContext
, *lpDPFAGContext
;
1849 static HRESULT WINAPI DP_IF_DestroyPlayer
1850 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idPlayer
, BOOL bAnsi
)
1852 DPFAGContext cbContext
;
1854 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1855 This
, lpMsgHdr
, idPlayer
, bAnsi
);
1857 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
1859 return DPERR_UNINITIALIZED
;
1862 if( DP_FindPlayer( This
, idPlayer
) == NULL
)
1864 return DPERR_INVALIDPLAYER
;
1867 /* FIXME: If the player is remote, we must be the host to delete this */
1869 cbContext
.This
= This
;
1870 cbContext
.idPlayer
= idPlayer
;
1871 cbContext
.bAnsi
= bAnsi
;
1873 /* Find each group and call DeletePlayerFromGroup if the player is a
1874 member of the group */
1875 DP_IF_EnumGroups( This
, NULL
, cbDeletePlayerFromAllGroups
,
1876 (LPVOID
)&cbContext
, DPENUMGROUPS_ALL
, bAnsi
);
1878 /* Now delete player and player list from the sys group */
1879 DP_DeletePlayer( This
, idPlayer
);
1881 /* Let the SP know that we've destroyed this group */
1882 if( This
->dp2
->spData
.lpCB
->DeletePlayer
)
1884 DPSP_DELETEPLAYERDATA data
;
1886 FIXME( "data.dwFlags is incorrect\n" );
1888 data
.idPlayer
= idPlayer
;
1890 data
.lpISP
= This
->dp2
->spData
.lpISP
;
1892 (*This
->dp2
->spData
.lpCB
->DeletePlayer
)( &data
);
1895 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
1900 static BOOL CALLBACK
1901 cbDeletePlayerFromAllGroups(
1908 lpDPFAGContext lpCtxt
= (lpDPFAGContext
)lpContext
;
1910 if( dwPlayerType
== DPPLAYERTYPE_GROUP
)
1912 DP_IF_DeletePlayerFromGroup( lpCtxt
->This
, NULL
, dpId
, lpCtxt
->idPlayer
,
1915 /* Enumerate all groups in this group since this will normally only
1916 * be called for top level groups
1918 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl
*)lpCtxt
->This
,
1920 cbDeletePlayerFromAllGroups
,
1921 lpContext
, DPENUMGROUPS_ALL
,
1927 ERR( "Group callback has dwPlayerType = 0x%08x\n", dwPlayerType
);
1933 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
1934 ( LPDIRECTPLAY2A iface
, DPID idPlayer
)
1936 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
1937 return DP_IF_DestroyPlayer( This
, NULL
, idPlayer
, TRUE
);
1940 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
1941 ( LPDIRECTPLAY2 iface
, DPID idPlayer
)
1943 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
1944 return DP_IF_DestroyPlayer( This
, NULL
, idPlayer
, FALSE
);
1947 static HRESULT WINAPI DP_IF_EnumGroupPlayers
1948 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPGUID lpguidInstance
,
1949 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
1950 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
)
1952 lpGroupData lpGData
;
1953 lpPlayerList lpPList
;
1955 FIXME("(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
1956 This
, idGroup
, lpguidInstance
, lpEnumPlayersCallback2
,
1957 lpContext
, dwFlags
, bAnsi
);
1959 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
1961 return DPERR_UNINITIALIZED
;
1964 /* Find the group */
1965 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
1967 return DPERR_INVALIDGROUP
;
1970 if( DPQ_IS_EMPTY( lpGData
->players
) )
1975 lpPList
= DPQ_FIRST( lpGData
->players
);
1977 /* Walk the players in this group */
1980 /* We do not enum the name server or app server as they are of no
1981 * consequence to the end user.
1983 if( ( lpPList
->lpPData
->dpid
!= DPID_NAME_SERVER
) &&
1984 ( lpPList
->lpPData
->dpid
!= DPID_SERVERPLAYER
)
1988 /* FIXME: Need to add stuff for dwFlags checking */
1990 if( !lpEnumPlayersCallback2( lpPList
->lpPData
->dpid
, DPPLAYERTYPE_PLAYER
,
1991 &lpPList
->lpPData
->name
,
1992 lpPList
->lpPData
->dwFlags
,
1996 /* User requested break */
2001 if( DPQ_IS_ENDOFLIST( lpPList
->players
) )
2006 lpPList
= DPQ_NEXT( lpPList
->players
);
2012 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
2013 ( LPDIRECTPLAY2A iface
, DPID idGroup
, LPGUID lpguidInstance
,
2014 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2015 LPVOID lpContext
, DWORD dwFlags
)
2017 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2018 return DP_IF_EnumGroupPlayers( This
, idGroup
, lpguidInstance
,
2019 lpEnumPlayersCallback2
, lpContext
,
2023 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
2024 ( LPDIRECTPLAY2 iface
, DPID idGroup
, LPGUID lpguidInstance
,
2025 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2026 LPVOID lpContext
, DWORD dwFlags
)
2028 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2029 return DP_IF_EnumGroupPlayers( This
, idGroup
, lpguidInstance
,
2030 lpEnumPlayersCallback2
, lpContext
,
2034 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2035 static HRESULT WINAPI DP_IF_EnumGroups
2036 ( IDirectPlay2Impl
* This
, LPGUID lpguidInstance
,
2037 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2038 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
)
2040 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl
*)This
,
2041 DPID_SYSTEM_GROUP
, lpguidInstance
,
2042 lpEnumPlayersCallback2
, lpContext
,
2046 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
2047 ( LPDIRECTPLAY2A iface
, LPGUID lpguidInstance
,
2048 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2049 LPVOID lpContext
, DWORD dwFlags
)
2051 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2052 return DP_IF_EnumGroups( This
, lpguidInstance
, lpEnumPlayersCallback2
,
2053 lpContext
, dwFlags
, TRUE
);
2056 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
2057 ( LPDIRECTPLAY2 iface
, LPGUID lpguidInstance
,
2058 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2059 LPVOID lpContext
, DWORD dwFlags
)
2061 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2062 return DP_IF_EnumGroups( This
, lpguidInstance
, lpEnumPlayersCallback2
,
2063 lpContext
, dwFlags
, FALSE
);
2066 static HRESULT WINAPI DP_IF_EnumPlayers
2067 ( IDirectPlay2Impl
* This
, LPGUID lpguidInstance
,
2068 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2069 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
)
2071 return DP_IF_EnumGroupPlayers( This
, DPID_SYSTEM_GROUP
, lpguidInstance
,
2072 lpEnumPlayersCallback2
, lpContext
,
2076 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
2077 ( LPDIRECTPLAY2A iface
, LPGUID lpguidInstance
,
2078 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2079 LPVOID lpContext
, DWORD dwFlags
)
2081 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2082 return DP_IF_EnumPlayers( This
, lpguidInstance
, lpEnumPlayersCallback2
,
2083 lpContext
, dwFlags
, TRUE
);
2086 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
2087 ( LPDIRECTPLAY2 iface
, LPGUID lpguidInstance
,
2088 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2089 LPVOID lpContext
, DWORD dwFlags
)
2091 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2092 return DP_IF_EnumPlayers( This
, lpguidInstance
, lpEnumPlayersCallback2
,
2093 lpContext
, dwFlags
, FALSE
);
2096 /* This function should call the registered callback function that the user
2097 passed into EnumSessions for each entry available.
2099 static void DP_InvokeEnumSessionCallbacks
2100 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2
,
2105 LPDPSESSIONDESC2 lpSessionDesc
;
2107 FIXME( ": not checking for conditions\n" );
2109 /* Not sure if this should be pruning but it's convenient */
2110 NS_PruneSessionCache( lpNSInfo
);
2112 NS_ResetSessionEnumeration( lpNSInfo
);
2114 /* Enumerate all sessions */
2115 /* FIXME: Need to indicate ANSI */
2116 while( (lpSessionDesc
= NS_WalkSessions( lpNSInfo
) ) != NULL
)
2118 TRACE( "EnumSessionsCallback2 invoked\n" );
2119 if( !lpEnumSessionsCallback2( lpSessionDesc
, &dwTimeout
, 0, lpContext
) )
2125 /* Invoke one last time to indicate that there is no more to come */
2126 lpEnumSessionsCallback2( NULL
, &dwTimeout
, DPESC_TIMEDOUT
, lpContext
);
2129 static DWORD CALLBACK
DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext
)
2131 EnumSessionAsyncCallbackData
* data
= (EnumSessionAsyncCallbackData
*)lpContext
;
2132 HANDLE hSuicideRequest
= data
->hSuicideRequest
;
2133 DWORD dwTimeout
= data
->dwTimeout
;
2135 TRACE( "Thread started with timeout = 0x%08x\n", dwTimeout
);
2141 /* Sleep up to dwTimeout waiting for request to terminate thread */
2142 if( WaitForSingleObject( hSuicideRequest
, dwTimeout
) == WAIT_OBJECT_0
)
2144 TRACE( "Thread terminating on terminate request\n" );
2148 /* Now resend the enum request */
2149 hr
= NS_SendSessionRequestBroadcast( &data
->requestGuid
,
2150 data
->dwEnumSessionFlags
,
2155 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr
) );
2156 /* FIXME: Should we kill this thread? How to inform the main thread? */
2161 TRACE( "Thread terminating\n" );
2163 /* Clean up the thread data */
2164 CloseHandle( hSuicideRequest
);
2165 HeapFree( GetProcessHeap(), 0, lpContext
);
2167 /* FIXME: Need to have some notification to main app thread that this is
2168 * dead. It would serve two purposes. 1) allow sync on termination
2169 * so that we don't actually send something to ourselves when we
2170 * become name server (race condition) and 2) so that if we die
2171 * abnormally something else will be able to tell.
2177 static void DP_KillEnumSessionThread( IDirectPlay2Impl
* This
)
2179 /* Does a thread exist? If so we were doing an async enum session */
2180 if( This
->dp2
->hEnumSessionThread
!= INVALID_HANDLE_VALUE
)
2182 TRACE( "Killing EnumSession thread %p\n",
2183 This
->dp2
->hEnumSessionThread
);
2185 /* Request that the thread kill itself nicely */
2186 SetEvent( This
->dp2
->hKillEnumSessionThreadEvent
);
2187 CloseHandle( This
->dp2
->hKillEnumSessionThreadEvent
);
2189 /* We no longer need to know about the thread */
2190 CloseHandle( This
->dp2
->hEnumSessionThread
);
2192 This
->dp2
->hEnumSessionThread
= INVALID_HANDLE_VALUE
;
2196 static HRESULT WINAPI DP_IF_EnumSessions
2197 ( IDirectPlay2Impl
* This
, LPDPSESSIONDESC2 lpsd
, DWORD dwTimeout
,
2198 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2
,
2199 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
)
2203 TRACE( "(%p)->(%p,0x%08x,%p,%p,0x%08x,%u)\n",
2204 This
, lpsd
, dwTimeout
, lpEnumSessionsCallback2
, lpContext
, dwFlags
,
2207 /* Can't enumerate if the interface is already open */
2208 if( This
->dp2
->bConnectionOpen
)
2210 return DPERR_GENERIC
;
2214 /* The loading of a lobby provider _seems_ to require a backdoor loading
2215 * of the service provider to also associate with this DP object. This is
2216 * because the app doesn't seem to have to call EnumConnections and
2217 * InitializeConnection for the SP before calling this method. As such
2218 * we'll do their dirty work for them with a quick hack so as to always
2219 * load the TCP/IP service provider.
2221 * The correct solution would seem to involve creating a dialog box which
2222 * contains the possible SPs. These dialog boxes most likely follow SDK
2225 if( This
->dp2
->bDPLSPInitialized
&& !This
->dp2
->bSPInitialized
)
2227 LPVOID lpConnection
;
2230 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2232 if( !DP_BuildSPCompoundAddr( (LPGUID
)&DPSPGUID_TCPIP
, &lpConnection
, &dwSize
) )
2234 ERR( "Can't build compound addr\n" );
2235 return DPERR_GENERIC
;
2238 hr
= DP_IF_InitializeConnection( (IDirectPlay3Impl
*)This
, lpConnection
,
2245 /* Free up the address buffer */
2246 HeapFree( GetProcessHeap(), 0, lpConnection
);
2248 /* The SP is now initialized */
2249 This
->dp2
->bSPInitialized
= TRUE
;
2254 /* Use the service provider default? */
2255 if( dwTimeout
== 0 )
2258 spCaps
.dwSize
= sizeof( spCaps
);
2260 DP_IF_GetCaps( This
, &spCaps
, 0 );
2261 dwTimeout
= spCaps
.dwTimeout
;
2263 /* The service provider doesn't provide one either! */
2264 if( dwTimeout
== 0 )
2266 /* Provide the TCP/IP default */
2267 dwTimeout
= DPMSG_WAIT_5_SECS
;
2271 if( dwFlags
& DPENUMSESSIONS_STOPASYNC
)
2273 DP_KillEnumSessionThread( This
);
2277 if( ( dwFlags
& DPENUMSESSIONS_ASYNC
) )
2279 /* Enumerate everything presently in the local session cache */
2280 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2
,
2281 This
->dp2
->lpNameServerData
, dwTimeout
,
2284 if( This
->dp2
->dwEnumSessionLock
!= 0 )
2285 return DPERR_CONNECTING
;
2287 /* See if we've already created a thread to service this interface */
2288 if( This
->dp2
->hEnumSessionThread
== INVALID_HANDLE_VALUE
)
2291 This
->dp2
->dwEnumSessionLock
++;
2293 /* Send the first enum request inline since the user may cancel a dialog
2294 * if one is presented. Also, may also have a connecting return code.
2296 hr
= NS_SendSessionRequestBroadcast( &lpsd
->guidApplication
,
2297 dwFlags
, &This
->dp2
->spData
);
2301 EnumSessionAsyncCallbackData
* lpData
2302 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpData
) );
2303 /* FIXME: need to kill the thread on object deletion */
2304 lpData
->lpSpData
= &This
->dp2
->spData
;
2306 lpData
->requestGuid
= lpsd
->guidApplication
;
2307 lpData
->dwEnumSessionFlags
= dwFlags
;
2308 lpData
->dwTimeout
= dwTimeout
;
2310 This
->dp2
->hKillEnumSessionThreadEvent
=
2311 CreateEventW( NULL
, TRUE
, FALSE
, NULL
);
2313 if( !DuplicateHandle( GetCurrentProcess(),
2314 This
->dp2
->hKillEnumSessionThreadEvent
,
2315 GetCurrentProcess(),
2316 &lpData
->hSuicideRequest
,
2317 0, FALSE
, DUPLICATE_SAME_ACCESS
)
2320 ERR( "Can't duplicate thread killing handle\n" );
2323 TRACE( ": creating EnumSessionsRequest thread\n" );
2325 This
->dp2
->hEnumSessionThread
= CreateThread( NULL
,
2327 DP_EnumSessionsSendAsyncRequestThread
,
2332 This
->dp2
->dwEnumSessionLock
--;
2337 /* Invalidate the session cache for the interface */
2338 NS_InvalidateSessionCache( This
->dp2
->lpNameServerData
);
2340 /* Send the broadcast for session enumeration */
2341 hr
= NS_SendSessionRequestBroadcast( &lpsd
->guidApplication
,
2343 &This
->dp2
->spData
);
2346 SleepEx( dwTimeout
, FALSE
);
2348 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2
,
2349 This
->dp2
->lpNameServerData
, dwTimeout
,
2356 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2357 ( LPDIRECTPLAY2A iface
, LPDPSESSIONDESC2 lpsd
, DWORD dwTimeout
,
2358 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2
,
2359 LPVOID lpContext
, DWORD dwFlags
)
2361 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2362 return DP_IF_EnumSessions( This
, lpsd
, dwTimeout
, lpEnumSessionsCallback2
,
2363 lpContext
, dwFlags
, TRUE
);
2366 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2367 ( LPDIRECTPLAY2 iface
, LPDPSESSIONDESC2 lpsd
, DWORD dwTimeout
,
2368 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2
,
2369 LPVOID lpContext
, DWORD dwFlags
)
2371 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2372 return DP_IF_EnumSessions( This
, lpsd
, dwTimeout
, lpEnumSessionsCallback2
,
2373 lpContext
, dwFlags
, FALSE
);
2376 static HRESULT WINAPI DP_IF_GetPlayerCaps
2377 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPDPCAPS lpDPCaps
,
2380 DPSP_GETCAPSDATA data
;
2382 TRACE("(%p)->(0x%08x,%p,0x%08x)\n", This
, idPlayer
, lpDPCaps
, dwFlags
);
2384 /* Query the service provider */
2385 data
.idPlayer
= idPlayer
;
2386 data
.dwFlags
= dwFlags
;
2387 data
.lpCaps
= lpDPCaps
;
2388 data
.lpISP
= This
->dp2
->spData
.lpISP
;
2390 return (*This
->dp2
->spData
.lpCB
->GetCaps
)( &data
);
2393 static HRESULT WINAPI DP_IF_GetCaps
2394 ( IDirectPlay2Impl
* This
, LPDPCAPS lpDPCaps
, DWORD dwFlags
)
2396 return DP_IF_GetPlayerCaps( This
, DPID_ALLPLAYERS
, lpDPCaps
, dwFlags
);
2399 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2400 ( LPDIRECTPLAY2A iface
, LPDPCAPS lpDPCaps
, DWORD dwFlags
)
2402 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2403 return DP_IF_GetCaps( This
, lpDPCaps
, dwFlags
);
2406 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2407 ( LPDIRECTPLAY2 iface
, LPDPCAPS lpDPCaps
, DWORD dwFlags
)
2409 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2410 return DP_IF_GetCaps( This
, lpDPCaps
, dwFlags
);
2413 static HRESULT WINAPI DP_IF_GetGroupData
2414 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPVOID lpData
,
2415 LPDWORD lpdwDataSize
, DWORD dwFlags
, BOOL bAnsi
)
2417 lpGroupData lpGData
;
2418 DWORD dwRequiredBufferSize
;
2419 LPVOID lpCopyDataFrom
;
2421 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2422 This
, idGroup
, lpData
, lpdwDataSize
, dwFlags
, bAnsi
);
2424 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
2426 return DPERR_INVALIDGROUP
;
2429 /* How much buffer is required? */
2430 if( dwFlags
& DPSET_LOCAL
)
2432 dwRequiredBufferSize
= lpGData
->dwLocalDataSize
;
2433 lpCopyDataFrom
= lpGData
->lpLocalData
;
2437 dwRequiredBufferSize
= lpGData
->dwRemoteDataSize
;
2438 lpCopyDataFrom
= lpGData
->lpRemoteData
;
2441 /* Is the user requesting to know how big a buffer is required? */
2442 if( ( lpData
== NULL
) ||
2443 ( *lpdwDataSize
< dwRequiredBufferSize
)
2446 *lpdwDataSize
= dwRequiredBufferSize
;
2447 return DPERR_BUFFERTOOSMALL
;
2450 CopyMemory( lpData
, lpCopyDataFrom
, dwRequiredBufferSize
);
2455 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2456 ( LPDIRECTPLAY2A iface
, DPID idGroup
, LPVOID lpData
,
2457 LPDWORD lpdwDataSize
, DWORD dwFlags
)
2459 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2460 return DP_IF_GetGroupData( This
, idGroup
, lpData
, lpdwDataSize
,
2464 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2465 ( LPDIRECTPLAY2 iface
, DPID idGroup
, LPVOID lpData
,
2466 LPDWORD lpdwDataSize
, DWORD dwFlags
)
2468 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2469 return DP_IF_GetGroupData( This
, idGroup
, lpData
, lpdwDataSize
,
2473 static HRESULT WINAPI DP_IF_GetGroupName
2474 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPVOID lpData
,
2475 LPDWORD lpdwDataSize
, BOOL bAnsi
)
2477 lpGroupData lpGData
;
2478 LPDPNAME lpName
= (LPDPNAME
)lpData
;
2479 DWORD dwRequiredDataSize
;
2481 FIXME("(%p)->(0x%08x,%p,%p,%u) ANSI ignored\n",
2482 This
, idGroup
, lpData
, lpdwDataSize
, bAnsi
);
2484 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
2486 return DPERR_INVALIDGROUP
;
2489 dwRequiredDataSize
= lpGData
->name
.dwSize
;
2491 if( lpGData
->name
.u1
.lpszShortNameA
)
2493 dwRequiredDataSize
+= strlen( lpGData
->name
.u1
.lpszShortNameA
) + 1;
2496 if( lpGData
->name
.u2
.lpszLongNameA
)
2498 dwRequiredDataSize
+= strlen( lpGData
->name
.u2
.lpszLongNameA
) + 1;
2501 if( ( lpData
== NULL
) ||
2502 ( *lpdwDataSize
< dwRequiredDataSize
)
2505 *lpdwDataSize
= dwRequiredDataSize
;
2506 return DPERR_BUFFERTOOSMALL
;
2509 /* Copy the structure */
2510 CopyMemory( lpName
, &lpGData
->name
, lpGData
->name
.dwSize
);
2512 if( lpGData
->name
.u1
.lpszShortNameA
)
2514 strcpy( ((char*)lpName
)+lpGData
->name
.dwSize
,
2515 lpGData
->name
.u1
.lpszShortNameA
);
2519 lpName
->u1
.lpszShortNameA
= NULL
;
2522 if( lpGData
->name
.u1
.lpszShortNameA
)
2524 strcpy( ((char*)lpName
)+lpGData
->name
.dwSize
,
2525 lpGData
->name
.u2
.lpszLongNameA
);
2529 lpName
->u2
.lpszLongNameA
= NULL
;
2535 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2536 ( LPDIRECTPLAY2A iface
, DPID idGroup
, LPVOID lpData
,
2537 LPDWORD lpdwDataSize
)
2539 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2540 return DP_IF_GetGroupName( This
, idGroup
, lpData
, lpdwDataSize
, TRUE
);
2543 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2544 ( LPDIRECTPLAY2 iface
, DPID idGroup
, LPVOID lpData
,
2545 LPDWORD lpdwDataSize
)
2547 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2548 return DP_IF_GetGroupName( This
, idGroup
, lpData
, lpdwDataSize
, FALSE
);
2551 static HRESULT WINAPI DP_IF_GetMessageCount
2552 ( IDirectPlay2Impl
* This
, DPID idPlayer
,
2553 LPDWORD lpdwCount
, BOOL bAnsi
)
2555 FIXME("(%p)->(0x%08x,%p,%u): stub\n", This
, idPlayer
, lpdwCount
, bAnsi
);
2556 return DP_IF_GetMessageQueue( (IDirectPlay4Impl
*)This
, 0, idPlayer
,
2557 DPMESSAGEQUEUE_RECEIVE
, lpdwCount
, NULL
,
2561 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2562 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPDWORD lpdwCount
)
2564 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2565 return DP_IF_GetMessageCount( This
, idPlayer
, lpdwCount
, TRUE
);
2568 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2569 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPDWORD lpdwCount
)
2571 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2572 return DP_IF_GetMessageCount( This
, idPlayer
, lpdwCount
, FALSE
);
2575 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2576 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPVOID lpData
, LPDWORD lpdwDataSize
)
2578 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2579 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This
, idPlayer
, lpData
, lpdwDataSize
);
2583 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2584 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPVOID lpData
, LPDWORD lpdwDataSize
)
2586 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2587 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This
, idPlayer
, lpData
, lpdwDataSize
);
2591 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2592 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPDPCAPS lpPlayerCaps
,
2595 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2596 return DP_IF_GetPlayerCaps( This
, idPlayer
, lpPlayerCaps
, dwFlags
);
2599 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2600 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPDPCAPS lpPlayerCaps
,
2603 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2604 return DP_IF_GetPlayerCaps( This
, idPlayer
, lpPlayerCaps
, dwFlags
);
2607 static HRESULT WINAPI DP_IF_GetPlayerData
2608 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPVOID lpData
,
2609 LPDWORD lpdwDataSize
, DWORD dwFlags
, BOOL bAnsi
)
2611 lpPlayerList lpPList
;
2612 DWORD dwRequiredBufferSize
;
2613 LPVOID lpCopyDataFrom
;
2615 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2616 This
, idPlayer
, lpData
, lpdwDataSize
, dwFlags
, bAnsi
);
2618 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
2620 return DPERR_UNINITIALIZED
;
2623 if( ( lpPList
= DP_FindPlayer( This
, idPlayer
) ) == NULL
)
2625 return DPERR_INVALIDPLAYER
;
2628 /* How much buffer is required? */
2629 if( dwFlags
& DPSET_LOCAL
)
2631 dwRequiredBufferSize
= lpPList
->lpPData
->dwLocalDataSize
;
2632 lpCopyDataFrom
= lpPList
->lpPData
->lpLocalData
;
2636 dwRequiredBufferSize
= lpPList
->lpPData
->dwRemoteDataSize
;
2637 lpCopyDataFrom
= lpPList
->lpPData
->lpRemoteData
;
2640 /* Is the user requesting to know how big a buffer is required? */
2641 if( ( lpData
== NULL
) ||
2642 ( *lpdwDataSize
< dwRequiredBufferSize
)
2645 *lpdwDataSize
= dwRequiredBufferSize
;
2646 return DPERR_BUFFERTOOSMALL
;
2649 CopyMemory( lpData
, lpCopyDataFrom
, dwRequiredBufferSize
);
2654 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2655 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPVOID lpData
,
2656 LPDWORD lpdwDataSize
, DWORD dwFlags
)
2658 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2659 return DP_IF_GetPlayerData( This
, idPlayer
, lpData
, lpdwDataSize
,
2663 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2664 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPVOID lpData
,
2665 LPDWORD lpdwDataSize
, DWORD dwFlags
)
2667 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2668 return DP_IF_GetPlayerData( This
, idPlayer
, lpData
, lpdwDataSize
,
2672 static HRESULT WINAPI DP_IF_GetPlayerName
2673 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPVOID lpData
,
2674 LPDWORD lpdwDataSize
, BOOL bAnsi
)
2676 lpPlayerList lpPList
;
2677 LPDPNAME lpName
= (LPDPNAME
)lpData
;
2678 DWORD dwRequiredDataSize
;
2680 FIXME( "(%p)->(0x%08x,%p,%p,%u): ANSI\n",
2681 This
, idPlayer
, lpData
, lpdwDataSize
, bAnsi
);
2683 if( ( lpPList
= DP_FindPlayer( This
, idPlayer
) ) == NULL
)
2685 return DPERR_INVALIDPLAYER
;
2688 dwRequiredDataSize
= lpPList
->lpPData
->name
.dwSize
;
2690 if( lpPList
->lpPData
->name
.u1
.lpszShortNameA
)
2692 dwRequiredDataSize
+= strlen( lpPList
->lpPData
->name
.u1
.lpszShortNameA
) + 1;
2695 if( lpPList
->lpPData
->name
.u2
.lpszLongNameA
)
2697 dwRequiredDataSize
+= strlen( lpPList
->lpPData
->name
.u2
.lpszLongNameA
) + 1;
2700 if( ( lpData
== NULL
) ||
2701 ( *lpdwDataSize
< dwRequiredDataSize
)
2704 *lpdwDataSize
= dwRequiredDataSize
;
2705 return DPERR_BUFFERTOOSMALL
;
2708 /* Copy the structure */
2709 CopyMemory( lpName
, &lpPList
->lpPData
->name
, lpPList
->lpPData
->name
.dwSize
);
2711 if( lpPList
->lpPData
->name
.u1
.lpszShortNameA
)
2713 strcpy( ((char*)lpName
)+lpPList
->lpPData
->name
.dwSize
,
2714 lpPList
->lpPData
->name
.u1
.lpszShortNameA
);
2718 lpName
->u1
.lpszShortNameA
= NULL
;
2721 if( lpPList
->lpPData
->name
.u1
.lpszShortNameA
)
2723 strcpy( ((char*)lpName
)+lpPList
->lpPData
->name
.dwSize
,
2724 lpPList
->lpPData
->name
.u2
.lpszLongNameA
);
2728 lpName
->u2
.lpszLongNameA
= NULL
;
2734 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2735 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPVOID lpData
,
2736 LPDWORD lpdwDataSize
)
2738 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2739 return DP_IF_GetPlayerName( This
, idPlayer
, lpData
, lpdwDataSize
, TRUE
);
2742 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2743 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPVOID lpData
,
2744 LPDWORD lpdwDataSize
)
2746 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2747 return DP_IF_GetPlayerName( This
, idPlayer
, lpData
, lpdwDataSize
, FALSE
);
2750 static HRESULT WINAPI DP_GetSessionDesc
2751 ( IDirectPlay2Impl
* This
, LPVOID lpData
, LPDWORD lpdwDataSize
,
2754 DWORD dwRequiredSize
;
2756 TRACE( "(%p)->(%p,%p,%u)\n", This
, lpData
, lpdwDataSize
, bAnsi
);
2758 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
2760 return DPERR_UNINITIALIZED
;
2763 if( ( lpData
== NULL
) && ( lpdwDataSize
== NULL
) )
2765 return DPERR_INVALIDPARAMS
;
2768 /* FIXME: Get from This->dp2->lpSessionDesc */
2769 dwRequiredSize
= DP_CalcSessionDescSize( This
->dp2
->lpSessionDesc
, bAnsi
);
2771 if ( ( lpData
== NULL
) ||
2772 ( *lpdwDataSize
< dwRequiredSize
)
2775 *lpdwDataSize
= dwRequiredSize
;
2776 return DPERR_BUFFERTOOSMALL
;
2779 DP_CopySessionDesc( lpData
, This
->dp2
->lpSessionDesc
, bAnsi
);
2784 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
2785 ( LPDIRECTPLAY2A iface
, LPVOID lpData
, LPDWORD lpdwDataSize
)
2787 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2788 return DP_GetSessionDesc( This
, lpData
, lpdwDataSize
, TRUE
);
2791 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
2792 ( LPDIRECTPLAY2 iface
, LPVOID lpData
, LPDWORD lpdwDataSize
)
2794 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2795 return DP_GetSessionDesc( This
, lpData
, lpdwDataSize
, TRUE
);
2798 /* Intended only for COM compatibility. Always returns an error. */
2799 static HRESULT WINAPI DirectPlay2AImpl_Initialize
2800 ( LPDIRECTPLAY2A iface
, LPGUID lpGUID
)
2802 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2803 TRACE("(%p)->(%p): stub\n", This
, lpGUID
);
2804 return DPERR_ALREADYINITIALIZED
;
2807 /* Intended only for COM compatibility. Always returns an error. */
2808 static HRESULT WINAPI DirectPlay2WImpl_Initialize
2809 ( LPDIRECTPLAY2 iface
, LPGUID lpGUID
)
2811 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2812 TRACE("(%p)->(%p): stub\n", This
, lpGUID
);
2813 return DPERR_ALREADYINITIALIZED
;
2817 static HRESULT WINAPI DP_SecureOpen
2818 ( IDirectPlay2Impl
* This
, LPCDPSESSIONDESC2 lpsd
, DWORD dwFlags
,
2819 LPCDPSECURITYDESC lpSecurity
, LPCDPCREDENTIALS lpCredentials
,
2824 FIXME( "(%p)->(%p,0x%08x,%p,%p): partial stub\n",
2825 This
, lpsd
, dwFlags
, lpSecurity
, lpCredentials
);
2827 if( This
->dp2
->bConnectionOpen
)
2829 TRACE( ": rejecting already open connection.\n" );
2830 return DPERR_ALREADYINITIALIZED
;
2833 /* If we're enumerating, kill the thread */
2834 DP_KillEnumSessionThread( This
);
2836 if( dwFlags
& DPOPEN_CREATE
)
2838 /* Rightoo - this computer is the host and the local computer needs to be
2839 the name server so that others can join this session */
2840 NS_SetLocalComputerAsNameServer( lpsd
, This
->dp2
->lpNameServerData
);
2842 This
->dp2
->bHostInterface
= TRUE
;
2844 hr
= DP_SetSessionDesc( This
, lpsd
, 0, TRUE
, bAnsi
);
2847 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr
) );
2852 /* Invoke the conditional callback for the service provider */
2853 if( This
->dp2
->spData
.lpCB
->Open
)
2857 FIXME( "Not all data fields are correct. Need new parameter\n" );
2859 data
.bCreate
= (dwFlags
& DPOPEN_CREATE
) ? TRUE
: FALSE
;
2860 data
.lpSPMessageHeader
= (dwFlags
& DPOPEN_CREATE
) ? NULL
2861 : NS_GetNSAddr( This
->dp2
->lpNameServerData
);
2862 data
.lpISP
= This
->dp2
->spData
.lpISP
;
2863 data
.bReturnStatus
= (dwFlags
& DPOPEN_RETURNSTATUS
) ? TRUE
: FALSE
;
2864 data
.dwOpenFlags
= dwFlags
;
2865 data
.dwSessionFlags
= This
->dp2
->lpSessionDesc
->dwFlags
;
2867 hr
= (*This
->dp2
->spData
.lpCB
->Open
)(&data
);
2870 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr
) );
2876 /* Create the system group of which everything is a part of */
2877 DPID systemGroup
= DPID_SYSTEM_GROUP
;
2879 hr
= DP_IF_CreateGroup( This
, NULL
, &systemGroup
, NULL
,
2884 if( dwFlags
& DPOPEN_JOIN
)
2886 DPID dpidServerId
= DPID_UNKNOWN
;
2888 /* Create the server player for this interface. This way we can receive
2889 * messages for this session.
2891 /* FIXME: I suppose that we should be setting an event for a receive
2892 * type of thing. That way the messaging thread could know to wake
2893 * up. DPlay would then trigger the hEvent for the player the
2894 * message is directed to.
2896 hr
= DP_IF_CreatePlayer( This
, NULL
, &dpidServerId
, NULL
, 0, NULL
,
2898 DPPLAYER_SERVERPLAYER
| DPPLAYER_LOCAL
, bAnsi
);
2901 else if( dwFlags
& DPOPEN_CREATE
)
2903 DPID dpidNameServerId
= DPID_NAME_SERVER
;
2905 hr
= DP_IF_CreatePlayer( This
, NULL
, &dpidNameServerId
, NULL
, 0, NULL
,
2906 0, DPPLAYER_SERVERPLAYER
, bAnsi
);
2911 ERR( "Couldn't create name server/system player: %s\n",
2912 DPLAYX_HresultToString(hr
) );
2918 static HRESULT WINAPI DirectPlay2AImpl_Open
2919 ( LPDIRECTPLAY2A iface
, LPDPSESSIONDESC2 lpsd
, DWORD dwFlags
)
2921 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2922 TRACE("(%p)->(%p,0x%08x)\n", This
, lpsd
, dwFlags
);
2923 return DP_SecureOpen( This
, lpsd
, dwFlags
, NULL
, NULL
, TRUE
);
2926 static HRESULT WINAPI DirectPlay2WImpl_Open
2927 ( LPDIRECTPLAY2 iface
, LPDPSESSIONDESC2 lpsd
, DWORD dwFlags
)
2929 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2930 TRACE("(%p)->(%p,0x%08x)\n", This
, lpsd
, dwFlags
);
2931 return DP_SecureOpen( This
, lpsd
, dwFlags
, NULL
, NULL
, FALSE
);
2934 static HRESULT WINAPI DP_IF_Receive
2935 ( IDirectPlay2Impl
* This
, LPDPID lpidFrom
, LPDPID lpidTo
,
2936 DWORD dwFlags
, LPVOID lpData
, LPDWORD lpdwDataSize
, BOOL bAnsi
)
2938 LPDPMSG lpMsg
= NULL
;
2940 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p,%u): stub\n",
2941 This
, lpidFrom
, lpidTo
, dwFlags
, lpData
, lpdwDataSize
, bAnsi
);
2943 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
2945 return DPERR_UNINITIALIZED
;
2950 dwFlags
= DPRECEIVE_ALL
;
2953 /* If the lpData is NULL, we must be peeking the message */
2954 if( ( lpData
== NULL
) &&
2955 !( dwFlags
& DPRECEIVE_PEEK
)
2958 return DPERR_INVALIDPARAMS
;
2961 if( dwFlags
& DPRECEIVE_ALL
)
2963 lpMsg
= This
->dp2
->receiveMsgs
.lpQHFirst
;
2965 if( !( dwFlags
& DPRECEIVE_PEEK
) )
2967 FIXME( "Remove from queue\n" );
2970 else if( ( dwFlags
& DPRECEIVE_TOPLAYER
) ||
2971 ( dwFlags
& DPRECEIVE_FROMPLAYER
)
2974 FIXME( "Find matching message 0x%08x\n", dwFlags
);
2978 ERR( "Hmmm..dwFlags 0x%08x\n", dwFlags
);
2983 return DPERR_NOMESSAGES
;
2986 /* Copy into the provided buffer */
2987 CopyMemory( lpData
, lpMsg
->msg
, *lpdwDataSize
);
2992 static HRESULT WINAPI DirectPlay2AImpl_Receive
2993 ( LPDIRECTPLAY2A iface
, LPDPID lpidFrom
, LPDPID lpidTo
,
2994 DWORD dwFlags
, LPVOID lpData
, LPDWORD lpdwDataSize
)
2996 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2997 return DP_IF_Receive( This
, lpidFrom
, lpidTo
, dwFlags
,
2998 lpData
, lpdwDataSize
, TRUE
);
3001 static HRESULT WINAPI DirectPlay2WImpl_Receive
3002 ( LPDIRECTPLAY2 iface
, LPDPID lpidFrom
, LPDPID lpidTo
,
3003 DWORD dwFlags
, LPVOID lpData
, LPDWORD lpdwDataSize
)
3005 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3006 return DP_IF_Receive( This
, lpidFrom
, lpidTo
, dwFlags
,
3007 lpData
, lpdwDataSize
, FALSE
);
3010 static HRESULT WINAPI DirectPlay2AImpl_Send
3011 ( LPDIRECTPLAY2A iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
, LPVOID lpData
, DWORD dwDataSize
)
3013 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3014 return DP_SendEx( This
, idFrom
, idTo
, dwFlags
, lpData
, dwDataSize
,
3015 0, 0, NULL
, NULL
, TRUE
);
3018 static HRESULT WINAPI DirectPlay2WImpl_Send
3019 ( LPDIRECTPLAY2 iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
, LPVOID lpData
, DWORD dwDataSize
)
3021 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3022 return DP_SendEx( This
, idFrom
, idTo
, dwFlags
, lpData
, dwDataSize
,
3023 0, 0, NULL
, NULL
, FALSE
);
3026 static HRESULT WINAPI DP_IF_SetGroupData
3027 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPVOID lpData
,
3028 DWORD dwDataSize
, DWORD dwFlags
, BOOL bAnsi
)
3030 lpGroupData lpGData
;
3032 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3033 This
, idGroup
, lpData
, dwDataSize
, dwFlags
, bAnsi
);
3035 /* Parameter check */
3036 if( ( lpData
== NULL
) &&
3040 return DPERR_INVALIDPARAMS
;
3043 /* Find the pointer to the data for this player */
3044 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
3046 return DPERR_INVALIDOBJECT
;
3049 if( !(dwFlags
& DPSET_LOCAL
) )
3051 FIXME( "Was this group created by this interface?\n" );
3052 /* FIXME: If this is a remote update need to allow it but not
3057 DP_SetGroupData( lpGData
, dwFlags
, lpData
, dwDataSize
);
3059 /* FIXME: Only send a message if this group is local to the session otherwise
3060 * it will have been rejected above
3062 if( !(dwFlags
& DPSET_LOCAL
) )
3064 FIXME( "Send msg?\n" );
3070 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
3071 ( LPDIRECTPLAY2A iface
, DPID idGroup
, LPVOID lpData
,
3072 DWORD dwDataSize
, DWORD dwFlags
)
3074 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3075 return DP_IF_SetGroupData( This
, idGroup
, lpData
, dwDataSize
, dwFlags
, TRUE
);
3078 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
3079 ( LPDIRECTPLAY2 iface
, DPID idGroup
, LPVOID lpData
,
3080 DWORD dwDataSize
, DWORD dwFlags
)
3082 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3083 return DP_IF_SetGroupData( This
, idGroup
, lpData
, dwDataSize
, dwFlags
, FALSE
);
3086 static HRESULT WINAPI DP_IF_SetGroupName
3087 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPDPNAME lpGroupName
,
3088 DWORD dwFlags
, BOOL bAnsi
)
3090 lpGroupData lpGData
;
3092 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n", This
, idGroup
,
3093 lpGroupName
, dwFlags
, bAnsi
);
3095 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
3097 return DPERR_INVALIDGROUP
;
3100 DP_CopyDPNAMEStruct( &lpGData
->name
, lpGroupName
, bAnsi
);
3102 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3103 FIXME( "Message not sent and dwFlags ignored\n" );
3108 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
3109 ( LPDIRECTPLAY2A iface
, DPID idGroup
, LPDPNAME lpGroupName
,
3112 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3113 return DP_IF_SetGroupName( This
, idGroup
, lpGroupName
, dwFlags
, TRUE
);
3116 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
3117 ( LPDIRECTPLAY2 iface
, DPID idGroup
, LPDPNAME lpGroupName
,
3120 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3121 return DP_IF_SetGroupName( This
, idGroup
, lpGroupName
, dwFlags
, FALSE
);
3124 static HRESULT WINAPI DP_IF_SetPlayerData
3125 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPVOID lpData
,
3126 DWORD dwDataSize
, DWORD dwFlags
, BOOL bAnsi
)
3128 lpPlayerList lpPList
;
3130 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3131 This
, idPlayer
, lpData
, dwDataSize
, dwFlags
, bAnsi
);
3133 /* Parameter check */
3134 if( ( lpData
== NULL
) &&
3138 return DPERR_INVALIDPARAMS
;
3141 /* Find the pointer to the data for this player */
3142 if( ( lpPList
= DP_FindPlayer( This
, idPlayer
) ) == NULL
)
3144 return DPERR_INVALIDPLAYER
;
3147 if( !(dwFlags
& DPSET_LOCAL
) )
3149 FIXME( "Was this group created by this interface?\n" );
3150 /* FIXME: If this is a remote update need to allow it but not
3155 DP_SetPlayerData( lpPList
->lpPData
, dwFlags
, lpData
, dwDataSize
);
3157 if( !(dwFlags
& DPSET_LOCAL
) )
3159 FIXME( "Send msg?\n" );
3165 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3166 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPVOID lpData
,
3167 DWORD dwDataSize
, DWORD dwFlags
)
3169 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3170 return DP_IF_SetPlayerData( This
, idPlayer
, lpData
, dwDataSize
,
3174 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3175 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPVOID lpData
,
3176 DWORD dwDataSize
, DWORD dwFlags
)
3178 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3179 return DP_IF_SetPlayerData( This
, idPlayer
, lpData
, dwDataSize
,
3183 static HRESULT WINAPI DP_IF_SetPlayerName
3184 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPDPNAME lpPlayerName
,
3185 DWORD dwFlags
, BOOL bAnsi
)
3187 lpPlayerList lpPList
;
3189 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n",
3190 This
, idPlayer
, lpPlayerName
, dwFlags
, bAnsi
);
3192 if( ( lpPList
= DP_FindPlayer( This
, idPlayer
) ) == NULL
)
3194 return DPERR_INVALIDGROUP
;
3197 DP_CopyDPNAMEStruct( &lpPList
->lpPData
->name
, lpPlayerName
, bAnsi
);
3199 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3200 FIXME( "Message not sent and dwFlags ignored\n" );
3205 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3206 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPDPNAME lpPlayerName
,
3209 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3210 return DP_IF_SetPlayerName( This
, idPlayer
, lpPlayerName
, dwFlags
, TRUE
);
3213 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3214 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPDPNAME lpPlayerName
,
3217 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3218 return DP_IF_SetPlayerName( This
, idPlayer
, lpPlayerName
, dwFlags
, FALSE
);
3221 static HRESULT WINAPI DP_SetSessionDesc
3222 ( IDirectPlay2Impl
* This
, LPCDPSESSIONDESC2 lpSessDesc
,
3223 DWORD dwFlags
, BOOL bInitial
, BOOL bAnsi
)
3225 DWORD dwRequiredSize
;
3226 LPDPSESSIONDESC2 lpTempSessDesc
;
3228 TRACE( "(%p)->(%p,0x%08x,%u,%u)\n",
3229 This
, lpSessDesc
, dwFlags
, bInitial
, bAnsi
);
3231 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
3233 return DPERR_UNINITIALIZED
;
3238 return DPERR_INVALIDPARAMS
;
3241 /* Only the host is allowed to update the session desc */
3242 if( !This
->dp2
->bHostInterface
)
3244 return DPERR_ACCESSDENIED
;
3247 /* FIXME: Copy into This->dp2->lpSessionDesc */
3248 dwRequiredSize
= DP_CalcSessionDescSize( lpSessDesc
, bAnsi
);
3249 lpTempSessDesc
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, dwRequiredSize
);
3251 if( lpTempSessDesc
== NULL
)
3253 return DPERR_OUTOFMEMORY
;
3257 HeapFree( GetProcessHeap(), 0, This
->dp2
->lpSessionDesc
);
3259 This
->dp2
->lpSessionDesc
= lpTempSessDesc
;
3261 DP_CopySessionDesc( This
->dp2
->lpSessionDesc
, lpSessDesc
, bAnsi
);
3264 /*Initializing session GUID*/
3265 CoCreateGuid( &(This
->dp2
->lpSessionDesc
->guidInstance
) );
3267 /* If this is an external invocation of the interface, we should be
3268 * letting everyone know that things have changed. Otherwise this is
3269 * just an initialization and it doesn't need to be propagated.
3273 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3279 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3280 ( LPDIRECTPLAY2A iface
, LPDPSESSIONDESC2 lpSessDesc
, DWORD dwFlags
)
3282 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3283 return DP_SetSessionDesc( This
, lpSessDesc
, dwFlags
, FALSE
, TRUE
);
3286 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3287 ( LPDIRECTPLAY2 iface
, LPDPSESSIONDESC2 lpSessDesc
, DWORD dwFlags
)
3289 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3290 return DP_SetSessionDesc( This
, lpSessDesc
, dwFlags
, FALSE
, TRUE
);
3293 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3294 DWORD
DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc
, BOOL bAnsi
)
3298 if( lpSessDesc
== NULL
)
3300 /* Hmmm..don't need any size? */
3301 ERR( "NULL lpSessDesc\n" );
3305 dwSize
+= sizeof( *lpSessDesc
);
3309 if( lpSessDesc
->u1
.lpszSessionNameA
)
3311 dwSize
+= lstrlenA( lpSessDesc
->u1
.lpszSessionNameA
) + 1;
3314 if( lpSessDesc
->u2
.lpszPasswordA
)
3316 dwSize
+= lstrlenA( lpSessDesc
->u2
.lpszPasswordA
) + 1;
3321 if( lpSessDesc
->u1
.lpszSessionName
)
3323 dwSize
+= sizeof( WCHAR
) *
3324 ( lstrlenW( lpSessDesc
->u1
.lpszSessionName
) + 1 );
3327 if( lpSessDesc
->u2
.lpszPassword
)
3329 dwSize
+= sizeof( WCHAR
) *
3330 ( lstrlenW( lpSessDesc
->u2
.lpszPassword
) + 1 );
3337 /* Assumes that contiguous buffers are already allocated. */
3338 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest
,
3339 LPCDPSESSIONDESC2 lpSessionSrc
, BOOL bAnsi
)
3341 BYTE
* lpStartOfFreeSpace
;
3343 if( lpSessionDest
== NULL
)
3345 ERR( "NULL lpSessionDest\n" );
3349 CopyMemory( lpSessionDest
, lpSessionSrc
, sizeof( *lpSessionSrc
) );
3351 lpStartOfFreeSpace
= ((BYTE
*)lpSessionDest
) + sizeof( *lpSessionSrc
);
3355 if( lpSessionSrc
->u1
.lpszSessionNameA
)
3357 lstrcpyA( (LPSTR
)lpStartOfFreeSpace
,
3358 lpSessionDest
->u1
.lpszSessionNameA
);
3359 lpSessionDest
->u1
.lpszSessionNameA
= (LPSTR
)lpStartOfFreeSpace
;
3360 lpStartOfFreeSpace
+=
3361 lstrlenA( lpSessionDest
->u1
.lpszSessionNameA
) + 1;
3364 if( lpSessionSrc
->u2
.lpszPasswordA
)
3366 lstrcpyA( (LPSTR
)lpStartOfFreeSpace
,
3367 lpSessionDest
->u2
.lpszPasswordA
);
3368 lpSessionDest
->u2
.lpszPasswordA
= (LPSTR
)lpStartOfFreeSpace
;
3369 lpStartOfFreeSpace
+=
3370 lstrlenA( lpSessionDest
->u2
.lpszPasswordA
) + 1;
3375 if( lpSessionSrc
->u1
.lpszSessionName
)
3377 lstrcpyW( (LPWSTR
)lpStartOfFreeSpace
,
3378 lpSessionDest
->u1
.lpszSessionName
);
3379 lpSessionDest
->u1
.lpszSessionName
= (LPWSTR
)lpStartOfFreeSpace
;
3380 lpStartOfFreeSpace
+= sizeof(WCHAR
) *
3381 ( lstrlenW( lpSessionDest
->u1
.lpszSessionName
) + 1 );
3384 if( lpSessionSrc
->u2
.lpszPassword
)
3386 lstrcpyW( (LPWSTR
)lpStartOfFreeSpace
,
3387 lpSessionDest
->u2
.lpszPassword
);
3388 lpSessionDest
->u2
.lpszPassword
= (LPWSTR
)lpStartOfFreeSpace
;
3389 lpStartOfFreeSpace
+= sizeof(WCHAR
) *
3390 ( lstrlenW( lpSessionDest
->u2
.lpszPassword
) + 1 );
3396 static HRESULT WINAPI DP_IF_AddGroupToGroup
3397 ( IDirectPlay3Impl
* This
, DPID idParentGroup
, DPID idGroup
)
3399 lpGroupData lpGData
;
3400 lpGroupList lpNewGList
;
3402 TRACE( "(%p)->(0x%08x,0x%08x)\n", This
, idParentGroup
, idGroup
);
3404 if( DP_FindAnyGroup( (IDirectPlay2AImpl
*)This
, idParentGroup
) == NULL
)
3406 return DPERR_INVALIDGROUP
;
3409 if( ( lpGData
= DP_FindAnyGroup( (IDirectPlay2AImpl
*)This
, idGroup
) ) == NULL
)
3411 return DPERR_INVALIDGROUP
;
3414 /* Create a player list (ie "shortcut" ) */
3415 lpNewGList
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpNewGList
) );
3416 if( lpNewGList
== NULL
)
3418 return DPERR_CANTADDPLAYER
;
3421 /* Add the shortcut */
3423 lpNewGList
->lpGData
= lpGData
;
3425 /* Add the player to the list of players for this group */
3426 DPQ_INSERT( lpGData
->groups
, lpNewGList
, groups
);
3428 /* Send a ADDGROUPTOGROUP message */
3429 FIXME( "Not sending message\n" );
3434 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3435 ( LPDIRECTPLAY3A iface
, DPID idParentGroup
, DPID idGroup
)
3437 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3438 return DP_IF_AddGroupToGroup( This
, idParentGroup
, idGroup
);
3441 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3442 ( LPDIRECTPLAY3 iface
, DPID idParentGroup
, DPID idGroup
)
3444 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3445 return DP_IF_AddGroupToGroup( This
, idParentGroup
, idGroup
);
3448 static HRESULT WINAPI DP_IF_CreateGroupInGroup
3449 ( IDirectPlay3Impl
* This
, LPVOID lpMsgHdr
, DPID idParentGroup
,
3450 LPDPID lpidGroup
, LPDPNAME lpGroupName
, LPVOID lpData
,
3451 DWORD dwDataSize
, DWORD dwFlags
, BOOL bAnsi
)
3453 lpGroupData lpGParentData
;
3454 lpGroupList lpGList
;
3455 lpGroupData lpGData
;
3457 TRACE( "(%p)->(0x%08x,%p,%p,%p,0x%08x,0x%08x,%u)\n",
3458 This
, idParentGroup
, lpidGroup
, lpGroupName
, lpData
,
3459 dwDataSize
, dwFlags
, bAnsi
);
3461 /* Verify that the specified parent is valid */
3462 if( ( lpGParentData
= DP_FindAnyGroup( (IDirectPlay2AImpl
*)This
,
3463 idParentGroup
) ) == NULL
3466 return DPERR_INVALIDGROUP
;
3469 lpGData
= DP_CreateGroup( (IDirectPlay2AImpl
*)This
, lpidGroup
, lpGroupName
,
3470 dwFlags
, idParentGroup
, bAnsi
);
3472 if( lpGData
== NULL
)
3474 return DPERR_CANTADDPLAYER
; /* yes player not group */
3477 /* Something else is referencing this data */
3480 DP_SetGroupData( lpGData
, DPSET_REMOTE
, lpData
, dwDataSize
);
3482 /* The list has now been inserted into the interface group list. We now
3483 need to put a "shortcut" to this group in the parent group */
3484 lpGList
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpGList
) );
3485 if( lpGList
== NULL
)
3487 FIXME( "Memory leak\n" );
3488 return DPERR_CANTADDPLAYER
; /* yes player not group */
3491 lpGList
->lpGData
= lpGData
;
3493 DPQ_INSERT( lpGParentData
->groups
, lpGList
, groups
);
3495 /* Let the SP know that we've created this group */
3496 if( This
->dp2
->spData
.lpCB
->CreateGroup
)
3498 DPSP_CREATEGROUPDATA data
;
3500 TRACE( "Calling SP CreateGroup\n" );
3502 data
.idGroup
= *lpidGroup
;
3503 data
.dwFlags
= dwFlags
;
3504 data
.lpSPMessageHeader
= lpMsgHdr
;
3505 data
.lpISP
= This
->dp2
->spData
.lpISP
;
3507 (*This
->dp2
->spData
.lpCB
->CreateGroup
)( &data
);
3510 /* Inform all other peers of the creation of a new group. If there are
3511 * no peers keep this quiet.
3513 if( This
->dp2
->lpSessionDesc
&&
3514 ( This
->dp2
->lpSessionDesc
->dwFlags
& DPSESSION_MULTICASTSERVER
) )
3516 DPMSG_CREATEPLAYERORGROUP msg
;
3518 msg
.dwType
= DPSYS_CREATEPLAYERORGROUP
;
3519 msg
.dwPlayerType
= DPPLAYERTYPE_GROUP
;
3520 msg
.dpId
= *lpidGroup
;
3521 msg
.dwCurrentPlayers
= idParentGroup
; /* FIXME: Incorrect? */
3522 msg
.lpData
= lpData
;
3523 msg
.dwDataSize
= dwDataSize
;
3524 msg
.dpnName
= *lpGroupName
;
3526 /* FIXME: Correct to just use send effectively? */
3527 /* FIXME: Should size include data w/ message or just message "header" */
3528 /* FIXME: Check return code */
3529 DP_SendEx( (IDirectPlay2Impl
*)This
,
3530 DPID_SERVERPLAYER
, DPID_ALLPLAYERS
, 0, &msg
, sizeof( msg
),
3531 0, 0, NULL
, NULL
, bAnsi
);
3537 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3538 ( LPDIRECTPLAY3A iface
, DPID idParentGroup
, LPDPID lpidGroup
,
3539 LPDPNAME lpGroupName
, LPVOID lpData
, DWORD dwDataSize
,
3542 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3544 *lpidGroup
= DPID_UNKNOWN
;
3546 return DP_IF_CreateGroupInGroup( This
, NULL
, idParentGroup
, lpidGroup
,
3547 lpGroupName
, lpData
, dwDataSize
, dwFlags
,
3551 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3552 ( LPDIRECTPLAY3 iface
, DPID idParentGroup
, LPDPID lpidGroup
,
3553 LPDPNAME lpGroupName
, LPVOID lpData
, DWORD dwDataSize
,
3556 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3558 *lpidGroup
= DPID_UNKNOWN
;
3560 return DP_IF_CreateGroupInGroup( This
, NULL
, idParentGroup
, lpidGroup
,
3561 lpGroupName
, lpData
, dwDataSize
,
3565 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
3566 ( IDirectPlay3Impl
* This
, DPID idParentGroup
, DPID idGroup
)
3568 lpGroupList lpGList
;
3569 lpGroupData lpGParentData
;
3571 TRACE("(%p)->(0x%08x,0x%08x)\n", This
, idParentGroup
, idGroup
);
3573 /* Is the parent group valid? */
3574 if( ( lpGParentData
= DP_FindAnyGroup( (IDirectPlay2AImpl
*)This
, idParentGroup
) ) == NULL
)
3576 return DPERR_INVALIDGROUP
;
3579 /* Remove the group from the parent group queue */
3580 DPQ_REMOVE_ENTRY( lpGParentData
->groups
, groups
, lpGData
->dpid
, ==, idGroup
, lpGList
);
3582 if( lpGList
== NULL
)
3584 return DPERR_INVALIDGROUP
;
3587 /* Decrement the ref count */
3588 lpGList
->lpGData
->uRef
--;
3590 /* Free up the list item */
3591 HeapFree( GetProcessHeap(), 0, lpGList
);
3593 /* Should send a DELETEGROUPFROMGROUP message */
3594 FIXME( "message not sent\n" );
3599 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3600 ( LPDIRECTPLAY3 iface
, DPID idParentGroup
, DPID idGroup
)
3602 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3603 return DP_IF_DeleteGroupFromGroup( This
, idParentGroup
, idGroup
);
3606 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3607 ( LPDIRECTPLAY3 iface
, DPID idParentGroup
, DPID idGroup
)
3609 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3610 return DP_IF_DeleteGroupFromGroup( This
, idParentGroup
, idGroup
);
3614 BOOL WINAPI
DP_BuildSPCompoundAddr( LPGUID lpcSpGuid
, LPVOID
* lplpAddrBuf
,
3615 LPDWORD lpdwBufSize
)
3617 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress
;
3620 dpCompoundAddress
.dwDataSize
= sizeof( GUID
);
3621 dpCompoundAddress
.guidDataType
= DPAID_ServiceProvider
;
3622 dpCompoundAddress
.lpData
= lpcSpGuid
;
3624 *lplpAddrBuf
= NULL
;
3627 hr
= DPL_CreateCompoundAddress( &dpCompoundAddress
, 1, *lplpAddrBuf
,
3628 lpdwBufSize
, TRUE
);
3630 if( hr
!= DPERR_BUFFERTOOSMALL
)
3632 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr
) );
3636 /* Now allocate the buffer */
3637 *lplpAddrBuf
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
3640 hr
= DPL_CreateCompoundAddress( &dpCompoundAddress
, 1, *lplpAddrBuf
,
3641 lpdwBufSize
, TRUE
);
3644 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr
) );
3651 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
3652 ( LPDIRECTPLAY3A iface
, LPCGUID lpguidApplication
, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback
, LPVOID lpContext
, DWORD dwFlags
)
3654 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3655 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This
, lpguidApplication
, lpEnumCallback
, lpContext
, dwFlags
);
3657 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
3660 dwFlags
= DPCONNECTION_DIRECTPLAY
;
3663 if( ! ( ( dwFlags
& DPCONNECTION_DIRECTPLAY
) ||
3664 ( dwFlags
& DPCONNECTION_DIRECTPLAYLOBBY
) )
3667 return DPERR_INVALIDFLAGS
;
3670 if( !lpEnumCallback
)
3672 return DPERR_INVALIDPARAMS
;
3675 /* Enumerate DirectPlay service providers */
3676 if( dwFlags
& DPCONNECTION_DIRECTPLAY
)
3679 LPCSTR searchSubKey
= "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3680 LPCSTR guidDataSubKey
= "Guid";
3681 char subKeyName
[51];
3682 DWORD dwIndex
, sizeOfSubKeyName
=50;
3685 /* Need to loop over the service providers in the registry */
3686 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE
, searchSubKey
,
3687 0, KEY_READ
, &hkResult
) != ERROR_SUCCESS
)
3689 /* Hmmm. Does this mean that there are no service providers? */
3690 ERR(": no service providers?\n");
3695 /* Traverse all the service providers we have available */
3697 RegEnumKeyExA( hkResult
, dwIndex
, subKeyName
, &sizeOfSubKeyName
,
3698 NULL
, NULL
, NULL
, &filetime
) != ERROR_NO_MORE_ITEMS
;
3699 ++dwIndex
, sizeOfSubKeyName
=51 )
3702 HKEY hkServiceProvider
;
3703 GUID serviceProviderGUID
;
3704 DWORD returnTypeGUID
, sizeOfReturnBuffer
= 50;
3705 char returnBuffer
[51];
3710 LPVOID lpAddressBuffer
= NULL
;
3711 DWORD dwAddressBufferSize
= 0;
3713 TRACE(" this time through: %s\n", subKeyName
);
3715 /* Get a handle for this particular service provider */
3716 if( RegOpenKeyExA( hkResult
, subKeyName
, 0, KEY_READ
,
3717 &hkServiceProvider
) != ERROR_SUCCESS
)
3719 ERR(": what the heck is going on?\n" );
3723 if( RegQueryValueExA( hkServiceProvider
, guidDataSubKey
,
3724 NULL
, &returnTypeGUID
, (LPBYTE
)returnBuffer
,
3725 &sizeOfReturnBuffer
) != ERROR_SUCCESS
)
3727 ERR(": missing GUID registry data members\n" );
3728 RegCloseKey(hkServiceProvider
);
3731 RegCloseKey(hkServiceProvider
);
3733 /* FIXME: Check return types to ensure we're interpreting data right */
3734 MultiByteToWideChar( CP_ACP
, 0, returnBuffer
, -1, buff
, sizeof(buff
)/sizeof(WCHAR
) );
3735 CLSIDFromString( buff
, &serviceProviderGUID
);
3736 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3738 /* Fill in the DPNAME struct for the service provider */
3739 dpName
.dwSize
= sizeof( dpName
);
3741 dpName
.u1
.lpszShortNameA
= subKeyName
;
3742 dpName
.u2
.lpszLongNameA
= NULL
;
3744 /* Create the compound address for the service provider.
3745 * NOTE: This is a gruesome architectural scar right now. DP
3746 * uses DPL and DPL uses DP. Nasty stuff. This may be why the
3747 * native dll just gets around this little bit by allocating an
3748 * 80 byte buffer which isn't even filled with a valid compound
3749 * address. Oh well. Creating a proper compound address is the
3750 * way to go anyways despite this method taking slightly more
3751 * heap space and realtime :) */
3753 bBuildPass
= DP_BuildSPCompoundAddr( &serviceProviderGUID
,
3755 &dwAddressBufferSize
);
3758 ERR( "Can't build compound addr\n" );
3759 return DPERR_GENERIC
;
3762 /* The enumeration will return FALSE if we are not to continue */
3763 if( !lpEnumCallback( &serviceProviderGUID
, lpAddressBuffer
, dwAddressBufferSize
,
3764 &dpName
, DPCONNECTION_DIRECTPLAY
, lpContext
) )
3771 /* Enumerate DirectPlayLobby service providers */
3772 if( dwFlags
& DPCONNECTION_DIRECTPLAYLOBBY
)
3775 LPCSTR searchSubKey
= "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3776 LPCSTR guidDataSubKey
= "Guid";
3777 char subKeyName
[51];
3778 DWORD dwIndex
, sizeOfSubKeyName
=50;
3781 /* Need to loop over the service providers in the registry */
3782 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE
, searchSubKey
,
3783 0, KEY_READ
, &hkResult
) != ERROR_SUCCESS
)
3785 /* Hmmm. Does this mean that there are no service providers? */
3786 ERR(": no service providers?\n");
3791 /* Traverse all the lobby providers we have available */
3793 RegEnumKeyExA( hkResult
, dwIndex
, subKeyName
, &sizeOfSubKeyName
,
3794 NULL
, NULL
, NULL
, &filetime
) != ERROR_NO_MORE_ITEMS
;
3795 ++dwIndex
, sizeOfSubKeyName
=51 )
3798 HKEY hkServiceProvider
;
3799 GUID serviceProviderGUID
;
3800 DWORD returnTypeGUID
, sizeOfReturnBuffer
= 50;
3801 char returnBuffer
[51];
3806 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress
;
3807 LPVOID lpAddressBuffer
= NULL
;
3808 DWORD dwAddressBufferSize
= 0;
3810 TRACE(" this time through: %s\n", subKeyName
);
3812 /* Get a handle for this particular service provider */
3813 if( RegOpenKeyExA( hkResult
, subKeyName
, 0, KEY_READ
,
3814 &hkServiceProvider
) != ERROR_SUCCESS
)
3816 ERR(": what the heck is going on?\n" );
3820 if( RegQueryValueExA( hkServiceProvider
, guidDataSubKey
,
3821 NULL
, &returnTypeGUID
, (LPBYTE
)returnBuffer
,
3822 &sizeOfReturnBuffer
) != ERROR_SUCCESS
)
3824 ERR(": missing GUID registry data members\n" );
3825 RegCloseKey(hkServiceProvider
);
3828 RegCloseKey(hkServiceProvider
);
3830 /* FIXME: Check return types to ensure we're interpreting data right */
3831 MultiByteToWideChar( CP_ACP
, 0, returnBuffer
, -1, buff
, sizeof(buff
)/sizeof(WCHAR
) );
3832 CLSIDFromString( buff
, &serviceProviderGUID
);
3833 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3835 /* Fill in the DPNAME struct for the service provider */
3836 dpName
.dwSize
= sizeof( dpName
);
3838 dpName
.u1
.lpszShortNameA
= subKeyName
;
3839 dpName
.u2
.lpszLongNameA
= NULL
;
3841 /* Create the compound address for the service provider.
3842 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
3843 nast stuff. This may be why the native dll just gets around this little bit by
3844 allocating an 80 byte buffer which isn't even a filled with a valid compound
3845 address. Oh well. Creating a proper compound address is the way to go anyways
3846 despite this method taking slightly more heap space and realtime :) */
3848 dpCompoundAddress
.guidDataType
= DPAID_LobbyProvider
;
3849 dpCompoundAddress
.dwDataSize
= sizeof( GUID
);
3850 dpCompoundAddress
.lpData
= &serviceProviderGUID
;
3852 if( ( hr
= DPL_CreateCompoundAddress( &dpCompoundAddress
, 1, lpAddressBuffer
,
3853 &dwAddressBufferSize
, TRUE
) ) != DPERR_BUFFERTOOSMALL
)
3855 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr
) );
3859 /* Now allocate the buffer */
3860 lpAddressBuffer
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, dwAddressBufferSize
);
3862 if( ( hr
= DPL_CreateCompoundAddress( &dpCompoundAddress
, 1, lpAddressBuffer
,
3863 &dwAddressBufferSize
, TRUE
) ) != DP_OK
)
3865 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr
) );
3866 HeapFree( GetProcessHeap(), 0, lpAddressBuffer
);
3870 /* The enumeration will return FALSE if we are not to continue */
3871 if( !lpEnumCallback( &serviceProviderGUID
, lpAddressBuffer
, dwAddressBufferSize
,
3872 &dpName
, DPCONNECTION_DIRECTPLAYLOBBY
, lpContext
) )
3874 HeapFree( GetProcessHeap(), 0, lpAddressBuffer
);
3877 HeapFree( GetProcessHeap(), 0, lpAddressBuffer
);
3884 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
3885 ( LPDIRECTPLAY3 iface
, LPCGUID lpguidApplication
, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback
, LPVOID lpContext
, DWORD dwFlags
)
3887 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3888 FIXME("(%p)->(%p,%p,%p,0x%08x): stub\n", This
, lpguidApplication
, lpEnumCallback
, lpContext
, dwFlags
);
3892 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
3893 ( IDirectPlay3AImpl
* This
, DPID idGroup
, LPGUID lpguidInstance
,
3894 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
3895 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
)
3897 lpGroupList lpGList
;
3898 lpGroupData lpGData
;
3900 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
3901 This
, idGroup
, lpguidInstance
, lpEnumPlayersCallback2
,
3902 lpContext
, dwFlags
, bAnsi
);
3904 if( ( lpGData
= DP_FindAnyGroup( (IDirectPlay2AImpl
*)This
, idGroup
) ) == NULL
)
3906 return DPERR_INVALIDGROUP
;
3909 if( DPQ_IS_EMPTY( lpGData
->groups
) )
3914 lpGList
= DPQ_FIRST( lpGData
->groups
);
3918 /* FIXME: Should check dwFlags for match here */
3920 if( !(*lpEnumPlayersCallback2
)( lpGList
->lpGData
->dpid
, DPPLAYERTYPE_GROUP
,
3921 &lpGList
->lpGData
->name
, dwFlags
,
3924 return DP_OK
; /* User requested break */
3927 if( DPQ_IS_ENDOFLIST( lpGList
->groups
) )
3932 lpGList
= DPQ_NEXT( lpGList
->groups
);
3939 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
3940 ( LPDIRECTPLAY3A iface
, DPID idGroup
, LPGUID lpguidInstance
,
3941 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
, LPVOID lpContext
,
3944 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3945 return DP_IF_EnumGroupsInGroup( This
, idGroup
, lpguidInstance
,
3946 lpEnumPlayersCallback2
, lpContext
, dwFlags
,
3950 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
3951 ( LPDIRECTPLAY3A iface
, DPID idGroup
, LPGUID lpguidInstance
,
3952 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
, LPVOID lpContext
,
3955 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3956 return DP_IF_EnumGroupsInGroup( This
, idGroup
, lpguidInstance
,
3957 lpEnumPlayersCallback2
, lpContext
, dwFlags
,
3961 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
3962 ( LPDIRECTPLAY3A iface
, DWORD dwFlags
, DPID idGroup
, LPVOID lpData
, LPDWORD lpdwDataSize
)
3964 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3965 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This
, dwFlags
, idGroup
, lpData
, lpdwDataSize
);
3969 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
3970 ( LPDIRECTPLAY3 iface
, DWORD dwFlags
, DPID idGroup
, LPVOID lpData
, LPDWORD lpdwDataSize
)
3972 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3973 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This
, dwFlags
, idGroup
, lpData
, lpdwDataSize
);
3977 static BOOL CALLBACK
DP_GetSpLpGuidFromCompoundAddress(
3978 REFGUID guidDataType
,
3983 /* Looking for the GUID of the provider to load */
3984 if( ( IsEqualGUID( guidDataType
, &DPAID_ServiceProvider
) ) ||
3985 ( IsEqualGUID( guidDataType
, &DPAID_LobbyProvider
) )
3988 TRACE( "Found SP/LP (%s) %s (data size = 0x%08x)\n",
3989 debugstr_guid( guidDataType
), debugstr_guid( lpData
), dwDataSize
);
3991 if( dwDataSize
!= sizeof( GUID
) )
3993 ERR( "Invalid sp/lp guid size 0x%08x\n", dwDataSize
);
3996 memcpy( lpContext
, lpData
, dwDataSize
);
3998 /* There shouldn't be more than 1 GUID/compound address */
4002 /* Still waiting for what we want */
4007 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
4008 static HMODULE
DP_LoadSP( LPCGUID lpcGuid
, LPSPINITDATA lpSpData
, LPBOOL lpbIsDpSp
)
4011 LPCSTR spSubKey
= "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4012 LPCSTR lpSubKey
= "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
4013 LPCSTR guidDataSubKey
= "Guid";
4014 LPCSTR majVerDataSubKey
= "dwReserved1";
4015 LPCSTR minVerDataSubKey
= "dwReserved2";
4016 LPCSTR pathSubKey
= "Path";
4018 TRACE( " request to load %s\n", debugstr_guid( lpcGuid
) );
4020 /* FIXME: Cloned code with a quick hack. */
4021 for( i
=0; i
<2; i
++ )
4024 LPCSTR searchSubKey
;
4025 char subKeyName
[51];
4026 DWORD dwIndex
, sizeOfSubKeyName
=50;
4029 (i
== 0) ? (searchSubKey
= spSubKey
) : (searchSubKey
= lpSubKey
);
4030 *lpbIsDpSp
= (i
== 0) ? TRUE
: FALSE
;
4033 /* Need to loop over the service providers in the registry */
4034 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE
, searchSubKey
,
4035 0, KEY_READ
, &hkResult
) != ERROR_SUCCESS
)
4037 /* Hmmm. Does this mean that there are no service providers? */
4038 ERR(": no service providers?\n");
4042 /* Traverse all the service providers we have available */
4044 RegEnumKeyExA( hkResult
, dwIndex
, subKeyName
, &sizeOfSubKeyName
,
4045 NULL
, NULL
, NULL
, &filetime
) != ERROR_NO_MORE_ITEMS
;
4046 ++dwIndex
, sizeOfSubKeyName
=51 )
4049 HKEY hkServiceProvider
;
4050 GUID serviceProviderGUID
;
4051 DWORD returnType
, sizeOfReturnBuffer
= 255;
4052 char returnBuffer
[256];
4056 TRACE(" this time through: %s\n", subKeyName
);
4058 /* Get a handle for this particular service provider */
4059 if( RegOpenKeyExA( hkResult
, subKeyName
, 0, KEY_READ
,
4060 &hkServiceProvider
) != ERROR_SUCCESS
)
4062 ERR(": what the heck is going on?\n" );
4066 if( RegQueryValueExA( hkServiceProvider
, guidDataSubKey
,
4067 NULL
, &returnType
, (LPBYTE
)returnBuffer
,
4068 &sizeOfReturnBuffer
) != ERROR_SUCCESS
)
4070 ERR(": missing GUID registry data members\n" );
4074 /* FIXME: Check return types to ensure we're interpreting data right */
4075 MultiByteToWideChar( CP_ACP
, 0, returnBuffer
, -1, buff
, sizeof(buff
)/sizeof(WCHAR
) );
4076 CLSIDFromString( buff
, &serviceProviderGUID
);
4077 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4079 /* Determine if this is the Service Provider that the user asked for */
4080 if( !IsEqualGUID( &serviceProviderGUID
, lpcGuid
) )
4085 if( i
== 0 ) /* DP SP */
4087 len
= MultiByteToWideChar( CP_ACP
, 0, subKeyName
, -1, NULL
, 0 );
4088 lpSpData
->lpszName
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof(WCHAR
) );
4089 MultiByteToWideChar( CP_ACP
, 0, subKeyName
, -1, lpSpData
->lpszName
, len
);
4092 sizeOfReturnBuffer
= 255;
4094 /* Get dwReserved1 */
4095 if( RegQueryValueExA( hkServiceProvider
, majVerDataSubKey
,
4096 NULL
, &returnType
, (LPBYTE
)returnBuffer
,
4097 &sizeOfReturnBuffer
) != ERROR_SUCCESS
)
4099 ERR(": missing dwReserved1 registry data members\n") ;
4104 memcpy( &lpSpData
->dwReserved1
, returnBuffer
, sizeof(lpSpData
->dwReserved1
) );
4106 sizeOfReturnBuffer
= 255;
4108 /* Get dwReserved2 */
4109 if( RegQueryValueExA( hkServiceProvider
, minVerDataSubKey
,
4110 NULL
, &returnType
, (LPBYTE
)returnBuffer
,
4111 &sizeOfReturnBuffer
) != ERROR_SUCCESS
)
4113 ERR(": missing dwReserved1 registry data members\n") ;
4118 memcpy( &lpSpData
->dwReserved2
, returnBuffer
, sizeof(lpSpData
->dwReserved2
) );
4120 sizeOfReturnBuffer
= 255;
4122 /* Get the path for this service provider */
4123 if( ( dwTemp
= RegQueryValueExA( hkServiceProvider
, pathSubKey
,
4124 NULL
, NULL
, (LPBYTE
)returnBuffer
,
4125 &sizeOfReturnBuffer
) ) != ERROR_SUCCESS
)
4127 ERR(": missing PATH registry data members: 0x%08x\n", dwTemp
);
4131 TRACE( "Loading %s\n", returnBuffer
);
4132 return LoadLibraryA( returnBuffer
);
4140 HRESULT
DP_InitializeDPSP( IDirectPlay3Impl
* This
, HMODULE hServiceProvider
)
4143 LPDPSP_SPINIT SPInit
;
4145 /* Initialize the service provider by calling SPInit */
4146 SPInit
= (LPDPSP_SPINIT
)GetProcAddress( hServiceProvider
, "SPInit" );
4148 if( SPInit
== NULL
)
4150 ERR( "Service provider doesn't provide SPInit interface?\n" );
4151 FreeLibrary( hServiceProvider
);
4152 return DPERR_UNAVAILABLE
;
4155 TRACE( "Calling SPInit (DP SP entry point)\n" );
4157 hr
= (*SPInit
)( &This
->dp2
->spData
);
4161 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr
) );
4162 FreeLibrary( hServiceProvider
);
4166 /* FIXME: Need to verify the sanity of the returned callback table
4167 * using IsBadCodePtr */
4168 This
->dp2
->bSPInitialized
= TRUE
;
4170 /* This interface is now initialized as a DP object */
4171 This
->dp2
->connectionInitialized
= DP_SERVICE_PROVIDER
;
4173 /* Store the handle of the module so that we can unload it later */
4174 This
->dp2
->hServiceProvider
= hServiceProvider
;
4180 HRESULT
DP_InitializeDPLSP( IDirectPlay3Impl
* This
, HMODULE hLobbyProvider
)
4183 LPSP_INIT DPLSPInit
;
4185 /* Initialize the service provider by calling SPInit */
4186 DPLSPInit
= (LPSP_INIT
)GetProcAddress( hLobbyProvider
, "DPLSPInit" );
4188 if( DPLSPInit
== NULL
)
4190 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4191 FreeLibrary( hLobbyProvider
);
4192 return DPERR_UNAVAILABLE
;
4195 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4197 hr
= (*DPLSPInit
)( &This
->dp2
->dplspData
);
4201 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr
) );
4202 FreeLibrary( hLobbyProvider
);
4206 /* FIXME: Need to verify the sanity of the returned callback table
4207 * using IsBadCodePtr */
4209 This
->dp2
->bDPLSPInitialized
= TRUE
;
4211 /* This interface is now initialized as a lobby object */
4212 This
->dp2
->connectionInitialized
= DP_LOBBY_PROVIDER
;
4214 /* Store the handle of the module so that we can unload it later */
4215 This
->dp2
->hDPLobbyProvider
= hLobbyProvider
;
4220 static HRESULT WINAPI DP_IF_InitializeConnection
4221 ( IDirectPlay3Impl
* This
, LPVOID lpConnection
, DWORD dwFlags
, BOOL bAnsi
)
4223 HMODULE hServiceProvider
;
4226 const DWORD dwAddrSize
= 80; /* FIXME: Need to calculate it correctly */
4227 BOOL bIsDpSp
; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4229 TRACE("(%p)->(%p,0x%08x,%u)\n", This
, lpConnection
, dwFlags
, bAnsi
);
4233 return DPERR_INVALIDFLAGS
;
4236 /* Find out what the requested SP is and how large this buffer is */
4237 hr
= DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress
, lpConnection
,
4238 dwAddrSize
, &guidSP
);
4242 ERR( "Invalid compound address?\n" );
4243 return DPERR_UNAVAILABLE
;
4246 /* Load the service provider */
4247 hServiceProvider
= DP_LoadSP( &guidSP
, &This
->dp2
->spData
, &bIsDpSp
);
4249 if( hServiceProvider
== 0 )
4251 ERR( "Unable to load service provider %s\n", debugstr_guid(&guidSP
) );
4252 return DPERR_UNAVAILABLE
;
4257 /* Fill in what we can of the Service Provider required information.
4258 * The rest was be done in DP_LoadSP
4260 This
->dp2
->spData
.lpAddress
= lpConnection
;
4261 This
->dp2
->spData
.dwAddressSize
= dwAddrSize
;
4262 This
->dp2
->spData
.lpGuid
= &guidSP
;
4264 hr
= DP_InitializeDPSP( This
, hServiceProvider
);
4268 This
->dp2
->dplspData
.lpAddress
= lpConnection
;
4270 hr
= DP_InitializeDPLSP( This
, hServiceProvider
);
4281 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4282 ( LPDIRECTPLAY3A iface
, LPVOID lpConnection
, DWORD dwFlags
)
4284 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4286 /* This may not be externally invoked once either an SP or LP is initialized */
4287 if( This
->dp2
->connectionInitialized
!= NO_PROVIDER
)
4289 return DPERR_ALREADYINITIALIZED
;
4292 return DP_IF_InitializeConnection( This
, lpConnection
, dwFlags
, TRUE
);
4295 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4296 ( LPDIRECTPLAY3 iface
, LPVOID lpConnection
, DWORD dwFlags
)
4298 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4300 /* This may not be externally invoked once either an SP or LP is initialized */
4301 if( This
->dp2
->connectionInitialized
!= NO_PROVIDER
)
4303 return DPERR_ALREADYINITIALIZED
;
4306 return DP_IF_InitializeConnection( This
, lpConnection
, dwFlags
, FALSE
);
4309 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4310 ( LPDIRECTPLAY3A iface
, LPCDPSESSIONDESC2 lpsd
, DWORD dwFlags
,
4311 LPCDPSECURITYDESC lpSecurity
, LPCDPCREDENTIALS lpCredentials
)
4313 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
; /* Yes a dp 2 interface */
4314 return DP_SecureOpen( This
, lpsd
, dwFlags
, lpSecurity
, lpCredentials
, TRUE
);
4317 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4318 ( LPDIRECTPLAY3 iface
, LPCDPSESSIONDESC2 lpsd
, DWORD dwFlags
,
4319 LPCDPSECURITYDESC lpSecurity
, LPCDPCREDENTIALS lpCredentials
)
4321 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
; /* Yes a dp 2 interface */
4322 return DP_SecureOpen( This
, lpsd
, dwFlags
, lpSecurity
, lpCredentials
, FALSE
);
4325 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4326 ( LPDIRECTPLAY3A iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
, LPDPCHAT lpChatMessage
)
4328 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4329 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This
, idFrom
, idTo
, dwFlags
, lpChatMessage
);
4333 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4334 ( LPDIRECTPLAY3 iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
, LPDPCHAT lpChatMessage
)
4336 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4337 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This
, idFrom
, idTo
, dwFlags
, lpChatMessage
);
4341 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4342 ( LPDIRECTPLAY3A iface
, DWORD dwFlags
, DPID idGroup
, LPDPLCONNECTION lpConnection
)
4344 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4345 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This
, dwFlags
, idGroup
, lpConnection
);
4349 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4350 ( LPDIRECTPLAY3 iface
, DWORD dwFlags
, DPID idGroup
, LPDPLCONNECTION lpConnection
)
4352 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4353 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This
, dwFlags
, idGroup
, lpConnection
);
4357 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4358 ( LPDIRECTPLAY3A iface
, DWORD dwFlags
, DPID idGroup
)
4360 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4361 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This
, dwFlags
, idGroup
);
4365 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4366 ( LPDIRECTPLAY3 iface
, DWORD dwFlags
, DPID idGroup
)
4368 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4369 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This
, dwFlags
, idGroup
);
4373 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4374 ( LPDIRECTPLAY3A iface
, DPID idGroup
, LPDWORD lpdwFlags
)
4376 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4377 FIXME("(%p)->(0x%08x,%p): stub\n", This
, idGroup
, lpdwFlags
);
4381 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4382 ( LPDIRECTPLAY3 iface
, DPID idGroup
, LPDWORD lpdwFlags
)
4384 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4385 FIXME("(%p)->(0x%08x,%p): stub\n", This
, idGroup
, lpdwFlags
);
4389 static HRESULT WINAPI DP_IF_GetGroupParent
4390 ( IDirectPlay3AImpl
* This
, DPID idGroup
, LPDPID lpidGroup
,
4393 lpGroupData lpGData
;
4395 TRACE("(%p)->(0x%08x,%p,%u)\n", This
, idGroup
, lpidGroup
, bAnsi
);
4397 if( ( lpGData
= DP_FindAnyGroup( (IDirectPlay2AImpl
*)This
, idGroup
) ) == NULL
)
4399 return DPERR_INVALIDGROUP
;
4402 *lpidGroup
= lpGData
->dpid
;
4407 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4408 ( LPDIRECTPLAY3A iface
, DPID idGroup
, LPDPID lpidGroup
)
4410 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4411 return DP_IF_GetGroupParent( This
, idGroup
, lpidGroup
, TRUE
);
4413 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4414 ( LPDIRECTPLAY3 iface
, DPID idGroup
, LPDPID lpidGroup
)
4416 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4417 return DP_IF_GetGroupParent( This
, idGroup
, lpidGroup
, FALSE
);
4420 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4421 ( LPDIRECTPLAY3A iface
, DPID idPlayer
, DWORD dwFlags
, LPVOID lpData
, LPDWORD lpdwDataSize
)
4423 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4424 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This
, idPlayer
, dwFlags
, lpData
, lpdwDataSize
);
4428 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4429 ( LPDIRECTPLAY3 iface
, DPID idPlayer
, DWORD dwFlags
, LPVOID lpData
, LPDWORD lpdwDataSize
)
4431 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4432 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This
, idPlayer
, dwFlags
, lpData
, lpdwDataSize
);
4436 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4437 ( LPDIRECTPLAY3A iface
, DPID idPlayer
, LPDWORD lpdwFlags
)
4439 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4440 FIXME("(%p)->(0x%08x,%p): stub\n", This
, idPlayer
, lpdwFlags
);
4444 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4445 ( LPDIRECTPLAY3 iface
, DPID idPlayer
, LPDWORD lpdwFlags
)
4447 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4448 FIXME("(%p)->(0x%08x,%p): stub\n", This
, idPlayer
, lpdwFlags
);
4452 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4453 ( LPDIRECTPLAY4A iface
, DPID idGroup
, LPDPID lpidGroupOwner
)
4455 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4456 FIXME("(%p)->(0x%08x,%p): stub\n", This
, idGroup
, lpidGroupOwner
);
4460 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4461 ( LPDIRECTPLAY4 iface
, DPID idGroup
, LPDPID lpidGroupOwner
)
4463 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4464 FIXME("(%p)->(0x%08x,%p): stub\n", This
, idGroup
, lpidGroupOwner
);
4468 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4469 ( LPDIRECTPLAY4A iface
, DPID idGroup
, DPID idGroupOwner
)
4471 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4472 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This
, idGroup
, idGroupOwner
);
4476 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4477 ( LPDIRECTPLAY4 iface
, DPID idGroup
, DPID idGroupOwner
)
4479 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4480 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This
, idGroup
, idGroupOwner
);
4484 static HRESULT WINAPI DP_SendEx
4485 ( IDirectPlay2Impl
* This
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
4486 LPVOID lpData
, DWORD dwDataSize
, DWORD dwPriority
, DWORD dwTimeout
,
4487 LPVOID lpContext
, LPDWORD lpdwMsgID
, BOOL bAnsi
)
4489 BOOL bValidDestination
= FALSE
;
4491 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,0x%08x,0x%08x,0x%08x,%p,%p,%u)"
4493 This
, idFrom
, idTo
, dwFlags
, lpData
, dwDataSize
, dwPriority
,
4494 dwTimeout
, lpContext
, lpdwMsgID
, bAnsi
);
4496 /* FIXME: Add parameter checking */
4497 /* FIXME: First call to this needs to acquire a message id which will be
4498 * used for multiple sends
4501 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4503 /* Verify that the message is being sent from a valid local player. The
4504 * from player may be anonymous DPID_UNKNOWN
4506 if( idFrom
!= DPID_UNKNOWN
)
4508 if( DP_FindPlayer( This
, idFrom
) == NULL
)
4510 WARN( "INFO: Invalid from player 0x%08x\n", idFrom
);
4511 return DPERR_INVALIDPLAYER
;
4515 /* Verify that the message is being sent to a valid player, group or to
4516 * everyone. If it's valid, send it to those players.
4518 if( idTo
== DPID_ALLPLAYERS
)
4520 bValidDestination
= TRUE
;
4522 /* See if SP has the ability to multicast. If so, use it */
4523 if( This
->dp2
->spData
.lpCB
->SendToGroupEx
)
4525 FIXME( "Use group sendex to group 0\n" );
4527 else if( This
->dp2
->spData
.lpCB
->SendToGroup
) /* obsolete interface */
4529 FIXME( "Use obsolete group send to group 0\n" );
4531 else /* No multicast, multiplicate */
4533 /* Send to all players we know about */
4534 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4538 if( ( !bValidDestination
) &&
4539 ( DP_FindPlayer( This
, idTo
) != NULL
)
4542 bValidDestination
= TRUE
;
4544 /* Have the service provider send this message */
4545 /* FIXME: Could optimize for local interface sends */
4546 return DP_SP_SendEx( This
, dwFlags
, lpData
, dwDataSize
, dwPriority
,
4547 dwTimeout
, lpContext
, lpdwMsgID
);
4550 if( ( !bValidDestination
) &&
4551 ( DP_FindAnyGroup( This
, idTo
) != NULL
)
4554 bValidDestination
= TRUE
;
4556 /* See if SP has the ability to multicast. If so, use it */
4557 if( This
->dp2
->spData
.lpCB
->SendToGroupEx
)
4559 FIXME( "Use group sendex\n" );
4561 else if( This
->dp2
->spData
.lpCB
->SendToGroup
) /* obsolete interface */
4563 FIXME( "Use obsolete group send to group\n" );
4565 else /* No multicast, multiplicate */
4567 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4575 This
->dp2
->hReplyEvent
= CreateEventW( NULL
, FALSE
, FALSE
, NULL
);
4577 dwWaitReturn
= WaitForSingleObject( hReplyEvent
, dwTimeout
);
4578 if( dwWaitReturn
!= WAIT_OBJECT_0
)
4580 ERR( "Wait failed 0x%08lx\n", dwWaitReturn
);
4586 if( !bValidDestination
)
4588 return DPERR_INVALIDPLAYER
;
4592 /* FIXME: Should return what the send returned */
4598 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4599 ( LPDIRECTPLAY4A iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
4600 LPVOID lpData
, DWORD dwDataSize
, DWORD dwPriority
, DWORD dwTimeout
,
4601 LPVOID lpContext
, LPDWORD lpdwMsgID
)
4603 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
; /* yes downcast to 2 */
4604 return DP_SendEx( This
, idFrom
, idTo
, dwFlags
, lpData
, dwDataSize
,
4605 dwPriority
, dwTimeout
, lpContext
, lpdwMsgID
, TRUE
);
4608 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4609 ( LPDIRECTPLAY4 iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
4610 LPVOID lpData
, DWORD dwDataSize
, DWORD dwPriority
, DWORD dwTimeout
,
4611 LPVOID lpContext
, LPDWORD lpdwMsgID
)
4613 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
; /* yes downcast to 2 */
4614 return DP_SendEx( This
, idFrom
, idTo
, dwFlags
, lpData
, dwDataSize
,
4615 dwPriority
, dwTimeout
, lpContext
, lpdwMsgID
, FALSE
);
4618 static HRESULT WINAPI DP_SP_SendEx
4619 ( IDirectPlay2Impl
* This
, DWORD dwFlags
,
4620 LPVOID lpData
, DWORD dwDataSize
, DWORD dwPriority
, DWORD dwTimeout
,
4621 LPVOID lpContext
, LPDWORD lpdwMsgID
)
4625 FIXME( ": stub\n" );
4627 /* FIXME: This queuing should only be for async messages */
4629 lpMElem
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpMElem
) );
4630 lpMElem
->msg
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, dwDataSize
);
4632 CopyMemory( lpMElem
->msg
, lpData
, dwDataSize
);
4634 /* FIXME: Need to queue based on priority */
4635 DPQ_INSERT( This
->dp2
->sendMsgs
, lpMElem
, msgs
);
4640 static HRESULT WINAPI DP_IF_GetMessageQueue
4641 ( IDirectPlay4Impl
* This
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
4642 LPDWORD lpdwNumMsgs
, LPDWORD lpdwNumBytes
, BOOL bAnsi
)
4646 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%p,%u): semi stub\n",
4647 This
, idFrom
, idTo
, dwFlags
, lpdwNumMsgs
, lpdwNumBytes
, bAnsi
);
4649 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4650 /* FIXME: What about sends which are not immediate? */
4652 if( This
->dp2
->spData
.lpCB
->GetMessageQueue
)
4654 DPSP_GETMESSAGEQUEUEDATA data
;
4656 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4658 /* FIXME: None of this is documented :( */
4660 data
.lpISP
= This
->dp2
->spData
.lpISP
;
4661 data
.dwFlags
= dwFlags
;
4662 data
.idFrom
= idFrom
;
4664 data
.lpdwNumMsgs
= lpdwNumMsgs
;
4665 data
.lpdwNumBytes
= lpdwNumBytes
;
4667 hr
= (*This
->dp2
->spData
.lpCB
->GetMessageQueue
)( &data
);
4671 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4677 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4678 ( LPDIRECTPLAY4A iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
4679 LPDWORD lpdwNumMsgs
, LPDWORD lpdwNumBytes
)
4681 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4682 return DP_IF_GetMessageQueue( This
, idFrom
, idTo
, dwFlags
, lpdwNumMsgs
,
4683 lpdwNumBytes
, TRUE
);
4686 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4687 ( LPDIRECTPLAY4 iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
4688 LPDWORD lpdwNumMsgs
, LPDWORD lpdwNumBytes
)
4690 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4691 return DP_IF_GetMessageQueue( This
, idFrom
, idTo
, dwFlags
, lpdwNumMsgs
,
4692 lpdwNumBytes
, FALSE
);
4695 static HRESULT WINAPI DP_IF_CancelMessage
4696 ( IDirectPlay4Impl
* This
, DWORD dwMsgID
, DWORD dwFlags
,
4697 DWORD dwMinPriority
, DWORD dwMaxPriority
, BOOL bAnsi
)
4701 FIXME( "(%p)->(0x%08x,0x%08x,%u): semi stub\n",
4702 This
, dwMsgID
, dwFlags
, bAnsi
);
4704 if( This
->dp2
->spData
.lpCB
->Cancel
)
4706 DPSP_CANCELDATA data
;
4708 TRACE( "Calling SP Cancel\n" );
4710 /* FIXME: Undocumented callback */
4712 data
.lpISP
= This
->dp2
->spData
.lpISP
;
4713 data
.dwFlags
= dwFlags
;
4714 data
.lprglpvSPMsgID
= NULL
;
4715 data
.cSPMsgID
= dwMsgID
;
4716 data
.dwMinPriority
= dwMinPriority
;
4717 data
.dwMaxPriority
= dwMaxPriority
;
4719 hr
= (*This
->dp2
->spData
.lpCB
->Cancel
)( &data
);
4723 FIXME( "SP doesn't implement Cancel\n" );
4729 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
4730 ( LPDIRECTPLAY4A iface
, DWORD dwMsgID
, DWORD dwFlags
)
4732 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4736 return DPERR_INVALIDFLAGS
;
4741 dwFlags
|= DPCANCELSEND_ALL
;
4744 return DP_IF_CancelMessage( This
, dwMsgID
, dwFlags
, 0, 0, TRUE
);
4747 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
4748 ( LPDIRECTPLAY4 iface
, DWORD dwMsgID
, DWORD dwFlags
)
4750 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4754 return DPERR_INVALIDFLAGS
;
4759 dwFlags
|= DPCANCELSEND_ALL
;
4762 return DP_IF_CancelMessage( This
, dwMsgID
, dwFlags
, 0, 0, FALSE
);
4765 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
4766 ( LPDIRECTPLAY4A iface
, DWORD dwMinPriority
, DWORD dwMaxPriority
,
4769 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4773 return DPERR_INVALIDFLAGS
;
4776 return DP_IF_CancelMessage( This
, 0, DPCANCELSEND_PRIORITY
, dwMinPriority
,
4777 dwMaxPriority
, TRUE
);
4780 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
4781 ( LPDIRECTPLAY4 iface
, DWORD dwMinPriority
, DWORD dwMaxPriority
,
4784 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4788 return DPERR_INVALIDFLAGS
;
4791 return DP_IF_CancelMessage( This
, 0, DPCANCELSEND_PRIORITY
, dwMinPriority
,
4792 dwMaxPriority
, FALSE
);
4795 /* Note: Hack so we can reuse the old functions without compiler warnings */
4796 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4797 # define XCAST(fun) (typeof(directPlay2WVT.fun))
4799 # define XCAST(fun) (void*)
4802 static const IDirectPlay2Vtbl directPlay2WVT
=
4804 XCAST(QueryInterface
)DP_QueryInterface
,
4805 XCAST(AddRef
)DP_AddRef
,
4806 XCAST(Release
)DP_Release
,
4808 DirectPlay2WImpl_AddPlayerToGroup
,
4809 DirectPlay2WImpl_Close
,
4810 DirectPlay2WImpl_CreateGroup
,
4811 DirectPlay2WImpl_CreatePlayer
,
4812 DirectPlay2WImpl_DeletePlayerFromGroup
,
4813 DirectPlay2WImpl_DestroyGroup
,
4814 DirectPlay2WImpl_DestroyPlayer
,
4815 DirectPlay2WImpl_EnumGroupPlayers
,
4816 DirectPlay2WImpl_EnumGroups
,
4817 DirectPlay2WImpl_EnumPlayers
,
4818 DirectPlay2WImpl_EnumSessions
,
4819 DirectPlay2WImpl_GetCaps
,
4820 DirectPlay2WImpl_GetGroupData
,
4821 DirectPlay2WImpl_GetGroupName
,
4822 DirectPlay2WImpl_GetMessageCount
,
4823 DirectPlay2WImpl_GetPlayerAddress
,
4824 DirectPlay2WImpl_GetPlayerCaps
,
4825 DirectPlay2WImpl_GetPlayerData
,
4826 DirectPlay2WImpl_GetPlayerName
,
4827 DirectPlay2WImpl_GetSessionDesc
,
4828 DirectPlay2WImpl_Initialize
,
4829 DirectPlay2WImpl_Open
,
4830 DirectPlay2WImpl_Receive
,
4831 DirectPlay2WImpl_Send
,
4832 DirectPlay2WImpl_SetGroupData
,
4833 DirectPlay2WImpl_SetGroupName
,
4834 DirectPlay2WImpl_SetPlayerData
,
4835 DirectPlay2WImpl_SetPlayerName
,
4836 DirectPlay2WImpl_SetSessionDesc
4840 /* Note: Hack so we can reuse the old functions without compiler warnings */
4841 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4842 # define XCAST(fun) (typeof(directPlay2AVT.fun))
4844 # define XCAST(fun) (void*)
4847 static const IDirectPlay2Vtbl directPlay2AVT
=
4849 XCAST(QueryInterface
)DP_QueryInterface
,
4850 XCAST(AddRef
)DP_AddRef
,
4851 XCAST(Release
)DP_Release
,
4853 DirectPlay2AImpl_AddPlayerToGroup
,
4854 DirectPlay2AImpl_Close
,
4855 DirectPlay2AImpl_CreateGroup
,
4856 DirectPlay2AImpl_CreatePlayer
,
4857 DirectPlay2AImpl_DeletePlayerFromGroup
,
4858 DirectPlay2AImpl_DestroyGroup
,
4859 DirectPlay2AImpl_DestroyPlayer
,
4860 DirectPlay2AImpl_EnumGroupPlayers
,
4861 DirectPlay2AImpl_EnumGroups
,
4862 DirectPlay2AImpl_EnumPlayers
,
4863 DirectPlay2AImpl_EnumSessions
,
4864 DirectPlay2AImpl_GetCaps
,
4865 DirectPlay2AImpl_GetGroupData
,
4866 DirectPlay2AImpl_GetGroupName
,
4867 DirectPlay2AImpl_GetMessageCount
,
4868 DirectPlay2AImpl_GetPlayerAddress
,
4869 DirectPlay2AImpl_GetPlayerCaps
,
4870 DirectPlay2AImpl_GetPlayerData
,
4871 DirectPlay2AImpl_GetPlayerName
,
4872 DirectPlay2AImpl_GetSessionDesc
,
4873 DirectPlay2AImpl_Initialize
,
4874 DirectPlay2AImpl_Open
,
4875 DirectPlay2AImpl_Receive
,
4876 DirectPlay2AImpl_Send
,
4877 DirectPlay2AImpl_SetGroupData
,
4878 DirectPlay2AImpl_SetGroupName
,
4879 DirectPlay2AImpl_SetPlayerData
,
4880 DirectPlay2AImpl_SetPlayerName
,
4881 DirectPlay2AImpl_SetSessionDesc
4886 /* Note: Hack so we can reuse the old functions without compiler warnings */
4887 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4888 # define XCAST(fun) (typeof(directPlay3AVT.fun))
4890 # define XCAST(fun) (void*)
4893 static const IDirectPlay3Vtbl directPlay3AVT
=
4895 XCAST(QueryInterface
)DP_QueryInterface
,
4896 XCAST(AddRef
)DP_AddRef
,
4897 XCAST(Release
)DP_Release
,
4899 XCAST(AddPlayerToGroup
)DirectPlay2AImpl_AddPlayerToGroup
,
4900 XCAST(Close
)DirectPlay2AImpl_Close
,
4901 XCAST(CreateGroup
)DirectPlay2AImpl_CreateGroup
,
4902 XCAST(CreatePlayer
)DirectPlay2AImpl_CreatePlayer
,
4903 XCAST(DeletePlayerFromGroup
)DirectPlay2AImpl_DeletePlayerFromGroup
,
4904 XCAST(DestroyGroup
)DirectPlay2AImpl_DestroyGroup
,
4905 XCAST(DestroyPlayer
)DirectPlay2AImpl_DestroyPlayer
,
4906 XCAST(EnumGroupPlayers
)DirectPlay2AImpl_EnumGroupPlayers
,
4907 XCAST(EnumGroups
)DirectPlay2AImpl_EnumGroups
,
4908 XCAST(EnumPlayers
)DirectPlay2AImpl_EnumPlayers
,
4909 XCAST(EnumSessions
)DirectPlay2AImpl_EnumSessions
,
4910 XCAST(GetCaps
)DirectPlay2AImpl_GetCaps
,
4911 XCAST(GetGroupData
)DirectPlay2AImpl_GetGroupData
,
4912 XCAST(GetGroupName
)DirectPlay2AImpl_GetGroupName
,
4913 XCAST(GetMessageCount
)DirectPlay2AImpl_GetMessageCount
,
4914 XCAST(GetPlayerAddress
)DirectPlay2AImpl_GetPlayerAddress
,
4915 XCAST(GetPlayerCaps
)DirectPlay2AImpl_GetPlayerCaps
,
4916 XCAST(GetPlayerData
)DirectPlay2AImpl_GetPlayerData
,
4917 XCAST(GetPlayerName
)DirectPlay2AImpl_GetPlayerName
,
4918 XCAST(GetSessionDesc
)DirectPlay2AImpl_GetSessionDesc
,
4919 XCAST(Initialize
)DirectPlay2AImpl_Initialize
,
4920 XCAST(Open
)DirectPlay2AImpl_Open
,
4921 XCAST(Receive
)DirectPlay2AImpl_Receive
,
4922 XCAST(Send
)DirectPlay2AImpl_Send
,
4923 XCAST(SetGroupData
)DirectPlay2AImpl_SetGroupData
,
4924 XCAST(SetGroupName
)DirectPlay2AImpl_SetGroupName
,
4925 XCAST(SetPlayerData
)DirectPlay2AImpl_SetPlayerData
,
4926 XCAST(SetPlayerName
)DirectPlay2AImpl_SetPlayerName
,
4927 XCAST(SetSessionDesc
)DirectPlay2AImpl_SetSessionDesc
,
4929 DirectPlay3AImpl_AddGroupToGroup
,
4930 DirectPlay3AImpl_CreateGroupInGroup
,
4931 DirectPlay3AImpl_DeleteGroupFromGroup
,
4932 DirectPlay3AImpl_EnumConnections
,
4933 DirectPlay3AImpl_EnumGroupsInGroup
,
4934 DirectPlay3AImpl_GetGroupConnectionSettings
,
4935 DirectPlay3AImpl_InitializeConnection
,
4936 DirectPlay3AImpl_SecureOpen
,
4937 DirectPlay3AImpl_SendChatMessage
,
4938 DirectPlay3AImpl_SetGroupConnectionSettings
,
4939 DirectPlay3AImpl_StartSession
,
4940 DirectPlay3AImpl_GetGroupFlags
,
4941 DirectPlay3AImpl_GetGroupParent
,
4942 DirectPlay3AImpl_GetPlayerAccount
,
4943 DirectPlay3AImpl_GetPlayerFlags
4947 /* Note: Hack so we can reuse the old functions without compiler warnings */
4948 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4949 # define XCAST(fun) (typeof(directPlay3WVT.fun))
4951 # define XCAST(fun) (void*)
4953 static const IDirectPlay3Vtbl directPlay3WVT
=
4955 XCAST(QueryInterface
)DP_QueryInterface
,
4956 XCAST(AddRef
)DP_AddRef
,
4957 XCAST(Release
)DP_Release
,
4959 XCAST(AddPlayerToGroup
)DirectPlay2WImpl_AddPlayerToGroup
,
4960 XCAST(Close
)DirectPlay2WImpl_Close
,
4961 XCAST(CreateGroup
)DirectPlay2WImpl_CreateGroup
,
4962 XCAST(CreatePlayer
)DirectPlay2WImpl_CreatePlayer
,
4963 XCAST(DeletePlayerFromGroup
)DirectPlay2WImpl_DeletePlayerFromGroup
,
4964 XCAST(DestroyGroup
)DirectPlay2WImpl_DestroyGroup
,
4965 XCAST(DestroyPlayer
)DirectPlay2WImpl_DestroyPlayer
,
4966 XCAST(EnumGroupPlayers
)DirectPlay2WImpl_EnumGroupPlayers
,
4967 XCAST(EnumGroups
)DirectPlay2WImpl_EnumGroups
,
4968 XCAST(EnumPlayers
)DirectPlay2WImpl_EnumPlayers
,
4969 XCAST(EnumSessions
)DirectPlay2WImpl_EnumSessions
,
4970 XCAST(GetCaps
)DirectPlay2WImpl_GetCaps
,
4971 XCAST(GetGroupData
)DirectPlay2WImpl_GetGroupData
,
4972 XCAST(GetGroupName
)DirectPlay2WImpl_GetGroupName
,
4973 XCAST(GetMessageCount
)DirectPlay2WImpl_GetMessageCount
,
4974 XCAST(GetPlayerAddress
)DirectPlay2WImpl_GetPlayerAddress
,
4975 XCAST(GetPlayerCaps
)DirectPlay2WImpl_GetPlayerCaps
,
4976 XCAST(GetPlayerData
)DirectPlay2WImpl_GetPlayerData
,
4977 XCAST(GetPlayerName
)DirectPlay2WImpl_GetPlayerName
,
4978 XCAST(GetSessionDesc
)DirectPlay2WImpl_GetSessionDesc
,
4979 XCAST(Initialize
)DirectPlay2WImpl_Initialize
,
4980 XCAST(Open
)DirectPlay2WImpl_Open
,
4981 XCAST(Receive
)DirectPlay2WImpl_Receive
,
4982 XCAST(Send
)DirectPlay2WImpl_Send
,
4983 XCAST(SetGroupData
)DirectPlay2WImpl_SetGroupData
,
4984 XCAST(SetGroupName
)DirectPlay2WImpl_SetGroupName
,
4985 XCAST(SetPlayerData
)DirectPlay2WImpl_SetPlayerData
,
4986 XCAST(SetPlayerName
)DirectPlay2WImpl_SetPlayerName
,
4987 XCAST(SetSessionDesc
)DirectPlay2WImpl_SetSessionDesc
,
4989 DirectPlay3WImpl_AddGroupToGroup
,
4990 DirectPlay3WImpl_CreateGroupInGroup
,
4991 DirectPlay3WImpl_DeleteGroupFromGroup
,
4992 DirectPlay3WImpl_EnumConnections
,
4993 DirectPlay3WImpl_EnumGroupsInGroup
,
4994 DirectPlay3WImpl_GetGroupConnectionSettings
,
4995 DirectPlay3WImpl_InitializeConnection
,
4996 DirectPlay3WImpl_SecureOpen
,
4997 DirectPlay3WImpl_SendChatMessage
,
4998 DirectPlay3WImpl_SetGroupConnectionSettings
,
4999 DirectPlay3WImpl_StartSession
,
5000 DirectPlay3WImpl_GetGroupFlags
,
5001 DirectPlay3WImpl_GetGroupParent
,
5002 DirectPlay3WImpl_GetPlayerAccount
,
5003 DirectPlay3WImpl_GetPlayerFlags
5007 /* Note: Hack so we can reuse the old functions without compiler warnings */
5008 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5009 # define XCAST(fun) (typeof(directPlay4WVT.fun))
5011 # define XCAST(fun) (void*)
5013 static const IDirectPlay4Vtbl directPlay4WVT
=
5015 XCAST(QueryInterface
)DP_QueryInterface
,
5016 XCAST(AddRef
)DP_AddRef
,
5017 XCAST(Release
)DP_Release
,
5019 XCAST(AddPlayerToGroup
)DirectPlay2WImpl_AddPlayerToGroup
,
5020 XCAST(Close
)DirectPlay2WImpl_Close
,
5021 XCAST(CreateGroup
)DirectPlay2WImpl_CreateGroup
,
5022 XCAST(CreatePlayer
)DirectPlay2WImpl_CreatePlayer
,
5023 XCAST(DeletePlayerFromGroup
)DirectPlay2WImpl_DeletePlayerFromGroup
,
5024 XCAST(DestroyGroup
)DirectPlay2WImpl_DestroyGroup
,
5025 XCAST(DestroyPlayer
)DirectPlay2WImpl_DestroyPlayer
,
5026 XCAST(EnumGroupPlayers
)DirectPlay2WImpl_EnumGroupPlayers
,
5027 XCAST(EnumGroups
)DirectPlay2WImpl_EnumGroups
,
5028 XCAST(EnumPlayers
)DirectPlay2WImpl_EnumPlayers
,
5029 XCAST(EnumSessions
)DirectPlay2WImpl_EnumSessions
,
5030 XCAST(GetCaps
)DirectPlay2WImpl_GetCaps
,
5031 XCAST(GetGroupData
)DirectPlay2WImpl_GetGroupData
,
5032 XCAST(GetGroupName
)DirectPlay2WImpl_GetGroupName
,
5033 XCAST(GetMessageCount
)DirectPlay2WImpl_GetMessageCount
,
5034 XCAST(GetPlayerAddress
)DirectPlay2WImpl_GetPlayerAddress
,
5035 XCAST(GetPlayerCaps
)DirectPlay2WImpl_GetPlayerCaps
,
5036 XCAST(GetPlayerData
)DirectPlay2WImpl_GetPlayerData
,
5037 XCAST(GetPlayerName
)DirectPlay2WImpl_GetPlayerName
,
5038 XCAST(GetSessionDesc
)DirectPlay2WImpl_GetSessionDesc
,
5039 XCAST(Initialize
)DirectPlay2WImpl_Initialize
,
5040 XCAST(Open
)DirectPlay2WImpl_Open
,
5041 XCAST(Receive
)DirectPlay2WImpl_Receive
,
5042 XCAST(Send
)DirectPlay2WImpl_Send
,
5043 XCAST(SetGroupData
)DirectPlay2WImpl_SetGroupData
,
5044 XCAST(SetGroupName
)DirectPlay2WImpl_SetGroupName
,
5045 XCAST(SetPlayerData
)DirectPlay2WImpl_SetPlayerData
,
5046 XCAST(SetPlayerName
)DirectPlay2WImpl_SetPlayerName
,
5047 XCAST(SetSessionDesc
)DirectPlay2WImpl_SetSessionDesc
,
5049 XCAST(AddGroupToGroup
)DirectPlay3WImpl_AddGroupToGroup
,
5050 XCAST(CreateGroupInGroup
)DirectPlay3WImpl_CreateGroupInGroup
,
5051 XCAST(DeleteGroupFromGroup
)DirectPlay3WImpl_DeleteGroupFromGroup
,
5052 XCAST(EnumConnections
)DirectPlay3WImpl_EnumConnections
,
5053 XCAST(EnumGroupsInGroup
)DirectPlay3WImpl_EnumGroupsInGroup
,
5054 XCAST(GetGroupConnectionSettings
)DirectPlay3WImpl_GetGroupConnectionSettings
,
5055 XCAST(InitializeConnection
)DirectPlay3WImpl_InitializeConnection
,
5056 XCAST(SecureOpen
)DirectPlay3WImpl_SecureOpen
,
5057 XCAST(SendChatMessage
)DirectPlay3WImpl_SendChatMessage
,
5058 XCAST(SetGroupConnectionSettings
)DirectPlay3WImpl_SetGroupConnectionSettings
,
5059 XCAST(StartSession
)DirectPlay3WImpl_StartSession
,
5060 XCAST(GetGroupFlags
)DirectPlay3WImpl_GetGroupFlags
,
5061 XCAST(GetGroupParent
)DirectPlay3WImpl_GetGroupParent
,
5062 XCAST(GetPlayerAccount
)DirectPlay3WImpl_GetPlayerAccount
,
5063 XCAST(GetPlayerFlags
)DirectPlay3WImpl_GetPlayerFlags
,
5065 DirectPlay4WImpl_GetGroupOwner
,
5066 DirectPlay4WImpl_SetGroupOwner
,
5067 DirectPlay4WImpl_SendEx
,
5068 DirectPlay4WImpl_GetMessageQueue
,
5069 DirectPlay4WImpl_CancelMessage
,
5070 DirectPlay4WImpl_CancelPriority
5075 /* Note: Hack so we can reuse the old functions without compiler warnings */
5076 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5077 # define XCAST(fun) (typeof(directPlay4AVT.fun))
5079 # define XCAST(fun) (void*)
5081 static const IDirectPlay4Vtbl directPlay4AVT
=
5083 XCAST(QueryInterface
)DP_QueryInterface
,
5084 XCAST(AddRef
)DP_AddRef
,
5085 XCAST(Release
)DP_Release
,
5087 XCAST(AddPlayerToGroup
)DirectPlay2AImpl_AddPlayerToGroup
,
5088 XCAST(Close
)DirectPlay2AImpl_Close
,
5089 XCAST(CreateGroup
)DirectPlay2AImpl_CreateGroup
,
5090 XCAST(CreatePlayer
)DirectPlay2AImpl_CreatePlayer
,
5091 XCAST(DeletePlayerFromGroup
)DirectPlay2AImpl_DeletePlayerFromGroup
,
5092 XCAST(DestroyGroup
)DirectPlay2AImpl_DestroyGroup
,
5093 XCAST(DestroyPlayer
)DirectPlay2AImpl_DestroyPlayer
,
5094 XCAST(EnumGroupPlayers
)DirectPlay2AImpl_EnumGroupPlayers
,
5095 XCAST(EnumGroups
)DirectPlay2AImpl_EnumGroups
,
5096 XCAST(EnumPlayers
)DirectPlay2AImpl_EnumPlayers
,
5097 XCAST(EnumSessions
)DirectPlay2AImpl_EnumSessions
,
5098 XCAST(GetCaps
)DirectPlay2AImpl_GetCaps
,
5099 XCAST(GetGroupData
)DirectPlay2AImpl_GetGroupData
,
5100 XCAST(GetGroupName
)DirectPlay2AImpl_GetGroupName
,
5101 XCAST(GetMessageCount
)DirectPlay2AImpl_GetMessageCount
,
5102 XCAST(GetPlayerAddress
)DirectPlay2AImpl_GetPlayerAddress
,
5103 XCAST(GetPlayerCaps
)DirectPlay2AImpl_GetPlayerCaps
,
5104 XCAST(GetPlayerData
)DirectPlay2AImpl_GetPlayerData
,
5105 XCAST(GetPlayerName
)DirectPlay2AImpl_GetPlayerName
,
5106 XCAST(GetSessionDesc
)DirectPlay2AImpl_GetSessionDesc
,
5107 XCAST(Initialize
)DirectPlay2AImpl_Initialize
,
5108 XCAST(Open
)DirectPlay2AImpl_Open
,
5109 XCAST(Receive
)DirectPlay2AImpl_Receive
,
5110 XCAST(Send
)DirectPlay2AImpl_Send
,
5111 XCAST(SetGroupData
)DirectPlay2AImpl_SetGroupData
,
5112 XCAST(SetGroupName
)DirectPlay2AImpl_SetGroupName
,
5113 XCAST(SetPlayerData
)DirectPlay2AImpl_SetPlayerData
,
5114 XCAST(SetPlayerName
)DirectPlay2AImpl_SetPlayerName
,
5115 XCAST(SetSessionDesc
)DirectPlay2AImpl_SetSessionDesc
,
5117 XCAST(AddGroupToGroup
)DirectPlay3AImpl_AddGroupToGroup
,
5118 XCAST(CreateGroupInGroup
)DirectPlay3AImpl_CreateGroupInGroup
,
5119 XCAST(DeleteGroupFromGroup
)DirectPlay3AImpl_DeleteGroupFromGroup
,
5120 XCAST(EnumConnections
)DirectPlay3AImpl_EnumConnections
,
5121 XCAST(EnumGroupsInGroup
)DirectPlay3AImpl_EnumGroupsInGroup
,
5122 XCAST(GetGroupConnectionSettings
)DirectPlay3AImpl_GetGroupConnectionSettings
,
5123 XCAST(InitializeConnection
)DirectPlay3AImpl_InitializeConnection
,
5124 XCAST(SecureOpen
)DirectPlay3AImpl_SecureOpen
,
5125 XCAST(SendChatMessage
)DirectPlay3AImpl_SendChatMessage
,
5126 XCAST(SetGroupConnectionSettings
)DirectPlay3AImpl_SetGroupConnectionSettings
,
5127 XCAST(StartSession
)DirectPlay3AImpl_StartSession
,
5128 XCAST(GetGroupFlags
)DirectPlay3AImpl_GetGroupFlags
,
5129 XCAST(GetGroupParent
)DirectPlay3AImpl_GetGroupParent
,
5130 XCAST(GetPlayerAccount
)DirectPlay3AImpl_GetPlayerAccount
,
5131 XCAST(GetPlayerFlags
)DirectPlay3AImpl_GetPlayerFlags
,
5133 DirectPlay4AImpl_GetGroupOwner
,
5134 DirectPlay4AImpl_SetGroupOwner
,
5135 DirectPlay4AImpl_SendEx
,
5136 DirectPlay4AImpl_GetMessageQueue
,
5137 DirectPlay4AImpl_CancelMessage
,
5138 DirectPlay4AImpl_CancelPriority
5143 HRESULT
DP_GetSPPlayerData( IDirectPlay2Impl
* lpDP
,
5147 lpPlayerList lpPlayer
= DP_FindPlayer( lpDP
, idPlayer
);
5149 if( lpPlayer
== NULL
)
5151 return DPERR_INVALIDPLAYER
;
5154 *lplpData
= lpPlayer
->lpPData
->lpSPPlayerData
;
5160 HRESULT
DP_SetSPPlayerData( IDirectPlay2Impl
* lpDP
,
5164 lpPlayerList lpPlayer
= DP_FindPlayer( lpDP
, idPlayer
);
5166 if( lpPlayer
== NULL
)
5168 return DPERR_INVALIDPLAYER
;
5171 lpPlayer
->lpPData
->lpSPPlayerData
= lpData
;
5176 /***************************************************************************
5177 * DirectPlayEnumerateAW
5179 * The pointer to the structure lpContext will be filled with the
5180 * appropriate data for each service offered by the OS. These services are
5181 * not necessarily available on this particular machine but are defined
5182 * as simple service providers under the "Service Providers" registry key.
5183 * This structure is then passed to lpEnumCallback for each of the different
5186 * This API is useful only for applications written using DirectX3 or
5187 * worse. It is superseded by IDirectPlay3::EnumConnections which also
5188 * gives information on the actual connections.
5190 * defn of a service provider:
5191 * A dynamic-link library used by DirectPlay to communicate over a network.
5192 * The service provider contains all the network-specific code required
5193 * to send and receive messages. Online services and network operators can
5194 * supply service providers to use specialized hardware, protocols, communications
5195 * media, and network resources.
5198 static HRESULT
DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA
,
5199 LPDPENUMDPCALLBACKW lpEnumCallbackW
,
5203 static const WCHAR searchSubKey
[] = {
5204 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
5205 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
5206 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
5207 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
5208 static const WCHAR guidKey
[] = { 'G', 'u', 'i', 'd', 0 };
5209 static const WCHAR descW
[] = { 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', 'W', 0 };
5214 char *descriptionA
= NULL
;
5215 DWORD max_sizeOfDescriptionA
= 0;
5216 WCHAR
*descriptionW
= NULL
;
5217 DWORD max_sizeOfDescriptionW
= 0;
5219 if (!lpEnumCallbackA
&& !lpEnumCallbackW
)
5221 return DPERR_INVALIDPARAMS
;
5224 /* Need to loop over the service providers in the registry */
5225 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, searchSubKey
,
5226 0, KEY_READ
, &hkResult
) != ERROR_SUCCESS
)
5228 /* Hmmm. Does this mean that there are no service providers? */
5229 ERR(": no service provider key in the registry - check your Wine installation !!!\n");
5230 return DPERR_GENERIC
;
5233 /* Traverse all the service providers we have available */
5237 WCHAR subKeyName
[255]; /* 255 is the maximum key size according to MSDN */
5238 DWORD sizeOfSubKeyName
= sizeof(subKeyName
) / sizeof(WCHAR
);
5239 HKEY hkServiceProvider
;
5240 GUID serviceProviderGUID
;
5241 WCHAR guidKeyContent
[(2 * 16) + 1 + 6 /* This corresponds to '{....-..-..-..-......}' */ ];
5242 DWORD sizeOfGuidKeyContent
= sizeof(guidKeyContent
);
5245 ret_value
= RegEnumKeyExW(hkResult
, dwIndex
, subKeyName
, &sizeOfSubKeyName
,
5246 NULL
, NULL
, NULL
, &filetime
);
5247 if (ret_value
== ERROR_NO_MORE_ITEMS
)
5249 else if (ret_value
!= ERROR_SUCCESS
)
5251 ERR(": could not enumerate on service provider key.\n");
5252 return DPERR_EXCEPTION
;
5254 TRACE(" this time through sub-key %s.\n", debugstr_w(subKeyName
));
5256 /* Open the key for this service provider */
5257 if (RegOpenKeyExW(hkResult
, subKeyName
, 0, KEY_READ
, &hkServiceProvider
) != ERROR_SUCCESS
)
5259 ERR(": could not open registry key for service provider %s.\n", debugstr_w(subKeyName
));
5263 /* Get the GUID from the registry */
5264 if (RegQueryValueExW(hkServiceProvider
, guidKey
,
5265 NULL
, NULL
, (LPBYTE
) guidKeyContent
, &sizeOfGuidKeyContent
) != ERROR_SUCCESS
)
5267 ERR(": missing GUID registry data member for service provider %s.\n", debugstr_w(subKeyName
));
5270 if (sizeOfGuidKeyContent
!= sizeof(guidKeyContent
))
5272 ERR(": invalid format for the GUID registry data member for service provider %s (%s).\n", debugstr_w(subKeyName
), debugstr_w(guidKeyContent
));
5275 CLSIDFromString(guidKeyContent
, &serviceProviderGUID
);
5277 /* The enumeration will return FALSE if we are not to continue.
5279 * Note: on my windows box, major / minor version is 6 / 0 for all service providers
5280 * and have no relation to any of the two dwReserved1 and dwReserved2 keys.
5281 * I think that it simply means that they are in-line with DirectX 6.0
5283 if (lpEnumCallbackA
)
5285 DWORD sizeOfDescription
= 0;
5287 /* Note that this is the A case of this function, so use the A variant to get the description string */
5288 if (RegQueryValueExA(hkServiceProvider
, "DescriptionA",
5289 NULL
, NULL
, NULL
, &sizeOfDescription
) != ERROR_SUCCESS
)
5291 ERR(": missing 'DescriptionA' registry data member for service provider %s.\n", debugstr_w(subKeyName
));
5294 if (sizeOfDescription
> max_sizeOfDescriptionA
)
5296 HeapFree(GetProcessHeap(), 0, descriptionA
);
5297 max_sizeOfDescriptionA
= sizeOfDescription
;
5299 descriptionA
= HeapAlloc(GetProcessHeap(), 0, sizeOfDescription
);
5300 RegQueryValueExA(hkServiceProvider
, "DescriptionA",
5301 NULL
, NULL
, (LPBYTE
) descriptionA
, &sizeOfDescription
);
5303 if (!lpEnumCallbackA(&serviceProviderGUID
, descriptionA
, 6, 0, lpContext
))
5308 DWORD sizeOfDescription
= 0;
5310 if (RegQueryValueExW(hkServiceProvider
, descW
,
5311 NULL
, NULL
, NULL
, &sizeOfDescription
) != ERROR_SUCCESS
)
5313 ERR(": missing 'DescriptionW' registry data member for service provider %s.\n", debugstr_w(subKeyName
));
5316 if (sizeOfDescription
> max_sizeOfDescriptionW
)
5318 HeapFree(GetProcessHeap(), 0, descriptionW
);
5319 max_sizeOfDescriptionW
= sizeOfDescription
;
5321 descriptionW
= HeapAlloc(GetProcessHeap(), 0, sizeOfDescription
);
5322 RegQueryValueExW(hkServiceProvider
, descW
,
5323 NULL
, NULL
, (LPBYTE
) descriptionW
, &sizeOfDescription
);
5325 if (!lpEnumCallbackW(&serviceProviderGUID
, descriptionW
, 6, 0, lpContext
))
5333 HeapFree(GetProcessHeap(), 0, descriptionA
);
5334 HeapFree(GetProcessHeap(), 0, descriptionW
);
5339 /***************************************************************************
5340 * DirectPlayEnumerate [DPLAYX.9]
5341 * DirectPlayEnumerateA [DPLAYX.2]
5343 HRESULT WINAPI
DirectPlayEnumerateA(LPDPENUMDPCALLBACKA lpEnumCallback
, LPVOID lpContext
)
5345 TRACE("(%p,%p)\n", lpEnumCallback
, lpContext
);
5347 return DirectPlayEnumerateAW(lpEnumCallback
, NULL
, lpContext
);
5350 /***************************************************************************
5351 * DirectPlayEnumerateW [DPLAYX.3]
5353 HRESULT WINAPI
DirectPlayEnumerateW(LPDPENUMDPCALLBACKW lpEnumCallback
, LPVOID lpContext
)
5355 TRACE("(%p,%p)\n", lpEnumCallback
, lpContext
);
5357 return DirectPlayEnumerateAW(NULL
, lpEnumCallback
, lpContext
);
5360 typedef struct tagCreateEnum
5364 } CreateEnumData
, *lpCreateEnumData
;
5366 /* Find and copy the matching connection for the SP guid */
5367 static BOOL CALLBACK
cbDPCreateEnumConnections(
5369 LPVOID lpConnection
,
5370 DWORD dwConnectionSize
,
5375 lpCreateEnumData lpData
= (lpCreateEnumData
)lpContext
;
5377 if( IsEqualGUID( lpguidSP
, lpData
->lpGuid
) )
5379 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData
->lpGuid
) );
5381 lpData
->lpConn
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
5383 CopyMemory( lpData
->lpConn
, lpConnection
, dwConnectionSize
);
5385 /* Found the record that we were looking for */
5389 /* Haven't found what were looking for yet */
5394 /***************************************************************************
5395 * DirectPlayCreate [DPLAYX.1]
5398 HRESULT WINAPI DirectPlayCreate
5399 ( LPGUID lpGUID
, LPDIRECTPLAY2
*lplpDP
, IUnknown
*pUnk
)
5402 LPDIRECTPLAY3A lpDP3A
;
5403 CreateEnumData cbData
;
5405 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID
), lplpDP
, pUnk
);
5409 return CLASS_E_NOAGGREGATION
;
5412 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5413 give them an IDirectPlay2A object and hope that doesn't cause problems */
5414 if( DP_CreateInterface( &IID_IDirectPlay2A
, (LPVOID
*)lplpDP
) != DP_OK
)
5416 return DPERR_UNAVAILABLE
;
5419 if( IsEqualGUID( &GUID_NULL
, lpGUID
) )
5421 /* The GUID_NULL means don't bind a service provider. Just return the
5426 /* Bind the desired service provider since lpGUID is non NULL */
5427 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID
) );
5429 /* We're going to use a DP3 interface */
5430 hr
= IDirectPlayX_QueryInterface( *lplpDP
, &IID_IDirectPlay3A
,
5434 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr
) );
5438 cbData
.lpConn
= NULL
;
5439 cbData
.lpGuid
= lpGUID
;
5441 /* We were given a service provider, find info about it... */
5442 hr
= IDirectPlayX_EnumConnections( lpDP3A
, NULL
, cbDPCreateEnumConnections
,
5443 &cbData
, DPCONNECTION_DIRECTPLAY
);
5444 if( ( FAILED(hr
) ) ||
5445 ( cbData
.lpConn
== NULL
)
5448 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr
) );
5449 IDirectPlayX_Release( lpDP3A
);
5450 return DPERR_UNAVAILABLE
;
5453 /* Initialize the service provider */
5454 hr
= IDirectPlayX_InitializeConnection( lpDP3A
, cbData
.lpConn
, 0 );
5457 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr
) );
5458 HeapFree( GetProcessHeap(), 0, cbData
.lpConn
);
5459 IDirectPlayX_Release( lpDP3A
);
5463 /* Release our version of the interface now that we're done with it */
5464 IDirectPlayX_Release( lpDP3A
);
5465 HeapFree( GetProcessHeap(), 0, cbData
.lpConn
);