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"
41 #include "wine/dplaysp.h"
42 #include "dplay_global.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(dplay
);
46 /* FIXME: Should this be externed? */
47 extern HRESULT DPL_CreateCompoundAddress
48 ( LPCDPCOMPOUNDADDRESSELEMENT lpElements
, DWORD dwElementCount
,
49 LPVOID lpAddress
, LPDWORD lpdwAddressSize
, BOOL bAnsiInterface
);
52 /* Local function prototypes */
53 static lpPlayerList
DP_FindPlayer( IDirectPlay2AImpl
* This
, DPID dpid
);
54 static lpPlayerData
DP_CreatePlayer( IDirectPlay2Impl
* iface
, LPDPID lpid
,
55 LPDPNAME lpName
, DWORD dwFlags
,
56 HANDLE hEvent
, BOOL bAnsi
);
57 static BOOL
DP_CopyDPNAMEStruct( LPDPNAME lpDst
, 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 */
474 HRESULT DP_CreateInterface
475 ( REFIID riid
, LPVOID
* ppvObj
)
477 TRACE( " for %s\n", debugstr_guid( riid
) );
479 *ppvObj
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
480 sizeof( IDirectPlay2Impl
) );
482 if( *ppvObj
== NULL
)
484 return DPERR_OUTOFMEMORY
;
487 if( IsEqualGUID( &IID_IDirectPlay2
, riid
) )
489 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)*ppvObj
;
490 This
->lpVtbl
= &directPlay2WVT
;
492 else if( IsEqualGUID( &IID_IDirectPlay2A
, riid
) )
494 IDirectPlay2AImpl
*This
= (IDirectPlay2AImpl
*)*ppvObj
;
495 This
->lpVtbl
= &directPlay2AVT
;
497 else if( IsEqualGUID( &IID_IDirectPlay3
, riid
) )
499 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)*ppvObj
;
500 This
->lpVtbl
= &directPlay3WVT
;
502 else if( IsEqualGUID( &IID_IDirectPlay3A
, riid
) )
504 IDirectPlay3AImpl
*This
= (IDirectPlay3AImpl
*)*ppvObj
;
505 This
->lpVtbl
= &directPlay3AVT
;
507 else if( IsEqualGUID( &IID_IDirectPlay4
, riid
) )
509 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)*ppvObj
;
510 This
->lpVtbl
= &directPlay4WVT
;
512 else if( IsEqualGUID( &IID_IDirectPlay4A
, riid
) )
514 IDirectPlay4AImpl
*This
= (IDirectPlay4AImpl
*)*ppvObj
;
515 This
->lpVtbl
= &directPlay4AVT
;
519 /* Unsupported interface */
520 HeapFree( GetProcessHeap(), 0, *ppvObj
);
523 return E_NOINTERFACE
;
527 if ( DP_CreateIUnknown( *ppvObj
) &&
528 DP_CreateDirectPlay2( *ppvObj
) &&
529 DP_CreateDirectPlay3( *ppvObj
) &&
530 DP_CreateDirectPlay4( *ppvObj
)
533 IDirectPlayX_AddRef( (LPDIRECTPLAY2A
)*ppvObj
);
538 /* Initialize failed, destroy it */
539 DP_DestroyDirectPlay4( *ppvObj
);
540 DP_DestroyDirectPlay3( *ppvObj
);
541 DP_DestroyDirectPlay2( *ppvObj
);
542 DP_DestroyIUnknown( *ppvObj
);
544 HeapFree( GetProcessHeap(), 0, *ppvObj
);
547 return DPERR_NOMEMORY
;
551 /* Direct Play methods */
553 /* Shared between all dplay types */
554 static HRESULT WINAPI DP_QueryInterface
555 ( LPDIRECTPLAY2 iface
, REFIID riid
, LPVOID
* ppvObj
)
557 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
558 TRACE("(%p)->(%s,%p)\n", This
, debugstr_guid( riid
), ppvObj
);
560 *ppvObj
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
563 if( *ppvObj
== NULL
)
565 return DPERR_OUTOFMEMORY
;
568 CopyMemory( *ppvObj
, This
, sizeof( *This
) );
569 (*(IDirectPlay2Impl
**)ppvObj
)->ulInterfaceRef
= 0;
571 if( IsEqualGUID( &IID_IDirectPlay2
, riid
) )
573 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)*ppvObj
;
574 This
->lpVtbl
= &directPlay2WVT
;
576 else if( IsEqualGUID( &IID_IDirectPlay2A
, riid
) )
578 IDirectPlay2AImpl
*This
= (IDirectPlay2AImpl
*)*ppvObj
;
579 This
->lpVtbl
= &directPlay2AVT
;
581 else if( IsEqualGUID( &IID_IDirectPlay3
, riid
) )
583 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)*ppvObj
;
584 This
->lpVtbl
= &directPlay3WVT
;
586 else if( IsEqualGUID( &IID_IDirectPlay3A
, riid
) )
588 IDirectPlay3AImpl
*This
= (IDirectPlay3AImpl
*)*ppvObj
;
589 This
->lpVtbl
= &directPlay3AVT
;
591 else if( IsEqualGUID( &IID_IDirectPlay4
, riid
) )
593 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)*ppvObj
;
594 This
->lpVtbl
= &directPlay4WVT
;
596 else if( IsEqualGUID( &IID_IDirectPlay4A
, riid
) )
598 IDirectPlay4AImpl
*This
= (IDirectPlay4AImpl
*)*ppvObj
;
599 This
->lpVtbl
= &directPlay4AVT
;
603 /* Unsupported interface */
604 HeapFree( GetProcessHeap(), 0, *ppvObj
);
607 return E_NOINTERFACE
;
610 IDirectPlayX_AddRef( (LPDIRECTPLAY2
)*ppvObj
);
615 /* Shared between all dplay types */
616 static ULONG WINAPI DP_AddRef
617 ( LPDIRECTPLAY3 iface
)
619 ULONG ulInterfaceRefCount
, ulObjRefCount
;
620 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
622 ulObjRefCount
= InterlockedIncrement( &This
->unk
->ulObjRef
);
623 ulInterfaceRefCount
= InterlockedIncrement( &This
->ulInterfaceRef
);
625 TRACE( "ref count incremented to %u:%u for %p\n",
626 ulInterfaceRefCount
, ulObjRefCount
, This
);
628 return ulObjRefCount
;
631 static ULONG WINAPI DP_Release
632 ( LPDIRECTPLAY3 iface
)
634 ULONG ulInterfaceRefCount
, ulObjRefCount
;
636 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
638 ulObjRefCount
= InterlockedDecrement( &This
->unk
->ulObjRef
);
639 ulInterfaceRefCount
= InterlockedDecrement( &This
->ulInterfaceRef
);
641 TRACE( "ref count decremented to %u:%u for %p\n",
642 ulInterfaceRefCount
, ulObjRefCount
, This
);
644 /* Deallocate if this is the last reference to the object */
645 if( ulObjRefCount
== 0 )
647 /* If we're destroying the object, this must be the last ref
648 of the last interface */
649 DP_DestroyDirectPlay4( This
);
650 DP_DestroyDirectPlay3( This
);
651 DP_DestroyDirectPlay2( This
);
652 DP_DestroyIUnknown( This
);
655 /* Deallocate the interface */
656 if( ulInterfaceRefCount
== 0 )
658 HeapFree( GetProcessHeap(), 0, This
);
661 return ulObjRefCount
;
664 static inline DPID
DP_NextObjectId(void)
666 return (DPID
)InterlockedIncrement( &kludgePlayerGroupId
);
669 /* *lplpReply will be non NULL iff there is something to reply */
670 HRESULT
DP_HandleMessage( IDirectPlay2Impl
* This
, LPCVOID lpcMessageBody
,
671 DWORD dwMessageBodySize
, LPCVOID lpcMessageHeader
,
672 WORD wCommandId
, WORD wVersion
,
673 LPVOID
* lplpReply
, LPDWORD lpdwMsgSize
)
675 TRACE( "(%p)->(%p,0x%08x,%p,%u,%u)\n",
676 This
, lpcMessageBody
, dwMessageBodySize
, lpcMessageHeader
, wCommandId
,
681 /* Name server needs to handle this request */
682 case DPMSGCMD_ENUMSESSIONSREQUEST
:
685 NS_ReplyToEnumSessionsRequest( lpcMessageBody
, lplpReply
, lpdwMsgSize
, This
);
690 /* Name server needs to handle this request */
691 case DPMSGCMD_ENUMSESSIONSREPLY
:
693 /* No reply expected */
694 NS_AddRemoteComputerAsNameServer( lpcMessageHeader
,
695 This
->dp2
->spData
.dwSPHeaderSize
,
697 This
->dp2
->lpNameServerData
);
701 case DPMSGCMD_REQUESTNEWPLAYERID
:
703 LPCDPMSG_REQUESTNEWPLAYERID lpcMsg
=
704 (LPCDPMSG_REQUESTNEWPLAYERID
)lpcMessageBody
;
706 LPDPMSG_NEWPLAYERIDREPLY lpReply
;
708 *lpdwMsgSize
= This
->dp2
->spData
.dwSPHeaderSize
+ sizeof( *lpReply
);
710 *lplpReply
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, *lpdwMsgSize
);
712 FIXME( "Ignoring dwFlags 0x%08x in request msg\n",
715 /* Setup the reply */
716 lpReply
= (LPDPMSG_NEWPLAYERIDREPLY
)( (BYTE
*)(*lplpReply
) +
717 This
->dp2
->spData
.dwSPHeaderSize
);
719 lpReply
->envelope
.dwMagic
= DPMSGMAGIC_DPLAYMSG
;
720 lpReply
->envelope
.wCommandId
= DPMSGCMD_NEWPLAYERIDREPLY
;
721 lpReply
->envelope
.wVersion
= DPMSGVER_DP6
;
723 lpReply
->dpidNewPlayerId
= DP_NextObjectId();
725 TRACE( "Allocating new playerid 0x%08x from remote request\n",
726 lpReply
->dpidNewPlayerId
);
731 case DPMSGCMD_GETNAMETABLEREPLY
:
732 case DPMSGCMD_NEWPLAYERIDREPLY
:
736 if( wCommandId
== DPMSGCMD_NEWPLAYERIDREPLY
)
739 DP_MSG_ReplyReceived( This
, wCommandId
, lpcMessageBody
, dwMessageBodySize
);
745 case DPMSGCMD_JUSTENVELOPE
:
747 TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08x\n", lpcMessageHeader
, ((const DWORD
*)lpcMessageHeader
)[1] );
748 NS_SetLocalAddr( This
->dp2
->lpNameServerData
, lpcMessageHeader
, 20 );
749 DP_MSG_ReplyReceived( This
, wCommandId
, lpcMessageBody
, dwMessageBodySize
);
753 case DPMSGCMD_FORWARDADDPLAYER
:
759 TRACE( "Sending message to self to get my addr\n" );
760 DP_MSG_ToSelf( This
, 1 ); /* This is a hack right now */
765 case DPMSGCMD_FORWARDADDPLAYERNACK
:
767 DP_MSG_ErrorReceived( This
, wCommandId
, lpcMessageBody
, dwMessageBodySize
);
773 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId
);
779 /* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */
785 static HRESULT WINAPI DP_IF_AddPlayerToGroup
786 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idGroup
,
787 DPID idPlayer
, BOOL bAnsi
)
790 lpPlayerList lpPList
;
791 lpPlayerList lpNewPList
;
793 TRACE( "(%p)->(%p,0x%08x,0x%08x,%u)\n",
794 This
, lpMsgHdr
, idGroup
, idPlayer
, bAnsi
);
797 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
799 return DPERR_INVALIDGROUP
;
802 /* Find the player */
803 if( ( lpPList
= DP_FindPlayer( This
, idPlayer
) ) == NULL
)
805 return DPERR_INVALIDPLAYER
;
808 /* Create a player list (ie "shortcut" ) */
809 lpNewPList
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpNewPList
) );
810 if( lpNewPList
== NULL
)
812 return DPERR_CANTADDPLAYER
;
815 /* Add the shortcut */
816 lpPList
->lpPData
->uRef
++;
817 lpNewPList
->lpPData
= lpPList
->lpPData
;
819 /* Add the player to the list of players for this group */
820 DPQ_INSERT(lpGData
->players
,lpNewPList
,players
);
822 /* Let the SP know that we've added a player to the group */
823 if( This
->dp2
->spData
.lpCB
->AddPlayerToGroup
)
825 DPSP_ADDPLAYERTOGROUPDATA data
;
827 TRACE( "Calling SP AddPlayerToGroup\n" );
829 data
.idPlayer
= idPlayer
;
830 data
.idGroup
= idGroup
;
831 data
.lpISP
= This
->dp2
->spData
.lpISP
;
833 (*This
->dp2
->spData
.lpCB
->AddPlayerToGroup
)( &data
);
836 /* Inform all other peers of the addition of player to the group. If there are
837 * no peers keep this event quiet.
838 * Also, if this event was the result of another machine sending it to us,
839 * don't bother rebroadcasting it.
841 if( ( lpMsgHdr
== NULL
) &&
842 This
->dp2
->lpSessionDesc
&&
843 ( This
->dp2
->lpSessionDesc
->dwFlags
& DPSESSION_MULTICASTSERVER
) )
845 DPMSG_ADDPLAYERTOGROUP msg
;
846 msg
.dwType
= DPSYS_ADDPLAYERTOGROUP
;
848 msg
.dpIdGroup
= idGroup
;
849 msg
.dpIdPlayer
= idPlayer
;
851 /* FIXME: Correct to just use send effectively? */
852 /* FIXME: Should size include data w/ message or just message "header" */
853 /* FIXME: Check return code */
854 DP_SendEx( This
, DPID_SERVERPLAYER
, DPID_ALLPLAYERS
, 0, &msg
, sizeof( msg
), 0, 0, NULL
, NULL
, bAnsi
);
860 static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
861 ( LPDIRECTPLAY2A iface
, DPID idGroup
, DPID idPlayer
)
863 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
864 return DP_IF_AddPlayerToGroup( This
, NULL
, idGroup
, idPlayer
, TRUE
);
867 static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
868 ( LPDIRECTPLAY2 iface
, DPID idGroup
, DPID idPlayer
)
870 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
871 return DP_IF_AddPlayerToGroup( This
, NULL
, idGroup
, idPlayer
, FALSE
);
874 static HRESULT WINAPI
DP_IF_Close( IDirectPlay2Impl
* This
, BOOL bAnsi
)
878 TRACE("(%p)->(%u)\n", This
, bAnsi
);
880 /* FIXME: Need to find a new host I assume (how?) */
881 /* FIXME: Need to destroy all local groups */
882 /* FIXME: Need to migrate all remotely visible players to the new host */
884 /* Invoke the SP callback to inform of session close */
885 if( This
->dp2
->spData
.lpCB
->CloseEx
)
889 TRACE( "Calling SP CloseEx\n" );
891 data
.lpISP
= This
->dp2
->spData
.lpISP
;
893 hr
= (*This
->dp2
->spData
.lpCB
->CloseEx
)( &data
);
896 else if ( This
->dp2
->spData
.lpCB
->Close
) /* Try obsolete version */
898 TRACE( "Calling SP Close (obsolete interface)\n" );
900 hr
= (*This
->dp2
->spData
.lpCB
->Close
)();
906 static HRESULT WINAPI DirectPlay2AImpl_Close
907 ( LPDIRECTPLAY2A iface
)
909 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
910 return DP_IF_Close( This
, TRUE
);
913 static HRESULT WINAPI DirectPlay2WImpl_Close
914 ( LPDIRECTPLAY2 iface
)
916 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
917 return DP_IF_Close( This
, FALSE
);
921 lpGroupData
DP_CreateGroup( IDirectPlay2AImpl
* This
, const DPID
*lpid
,
922 const DPNAME
*lpName
, DWORD dwFlags
,
923 DPID idParent
, BOOL bAnsi
)
927 /* Allocate the new space and add to end of high level group list */
928 lpGData
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpGData
) );
930 if( lpGData
== NULL
)
935 DPQ_INIT(lpGData
->groups
);
936 DPQ_INIT(lpGData
->players
);
938 /* Set the desired player ID - no sanity checking to see if it exists */
939 lpGData
->dpid
= *lpid
;
941 DP_CopyDPNAMEStruct( &lpGData
->name
, lpName
, bAnsi
);
943 /* FIXME: Should we check that the parent exists? */
944 lpGData
->parent
= idParent
;
946 /* FIXME: Should we validate the dwFlags? */
947 lpGData
->dwFlags
= dwFlags
;
949 TRACE( "Created group id 0x%08x\n", *lpid
);
954 /* This method assumes that all links to it are already deleted */
956 DP_DeleteGroup( IDirectPlay2Impl
* This
, DPID dpid
)
960 TRACE( "(%p)->(0x%08x)\n", This
, dpid
);
962 DPQ_REMOVE_ENTRY( This
->dp2
->lpSysGroup
->groups
, groups
, lpGData
->dpid
, ==, dpid
, lpGList
);
964 if( lpGList
== NULL
)
966 ERR( "DPID 0x%08x not found\n", dpid
);
970 if( --(lpGList
->lpGData
->uRef
) )
972 FIXME( "Why is this not the last reference to group?\n" );
977 DP_DeleteDPNameStruct( &lpGList
->lpGData
->name
);
978 HeapFree( GetProcessHeap(), 0, lpGList
->lpGData
);
980 /* Remove and Delete Player List object */
981 HeapFree( GetProcessHeap(), 0, lpGList
);
985 static lpGroupData
DP_FindAnyGroup( IDirectPlay2AImpl
* This
, DPID dpid
)
987 lpGroupList lpGroups
;
989 TRACE( "(%p)->(0x%08x)\n", This
, dpid
);
991 if( dpid
== DPID_SYSTEM_GROUP
)
993 return This
->dp2
->lpSysGroup
;
997 DPQ_FIND_ENTRY( This
->dp2
->lpSysGroup
->groups
, groups
, lpGData
->dpid
, ==, dpid
, lpGroups
);
1000 if( lpGroups
== NULL
)
1005 return lpGroups
->lpGData
;
1008 static HRESULT WINAPI DP_IF_CreateGroup
1009 ( IDirectPlay2AImpl
* This
, LPVOID lpMsgHdr
, LPDPID lpidGroup
,
1010 LPDPNAME lpGroupName
, LPVOID lpData
, DWORD dwDataSize
,
1011 DWORD dwFlags
, BOOL bAnsi
)
1013 lpGroupData lpGData
;
1015 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1016 This
, lpMsgHdr
, lpidGroup
, lpGroupName
, lpData
, dwDataSize
,
1019 /* If the name is not specified, we must provide one */
1020 if( DPID_UNKNOWN
== *lpidGroup
)
1022 /* If we are the name server, we decide on the group ids. If not, we
1023 * must ask for one before attempting a creation.
1025 if( This
->dp2
->bHostInterface
)
1027 *lpidGroup
= DP_NextObjectId();
1031 *lpidGroup
= DP_GetRemoteNextObjectId();
1035 lpGData
= DP_CreateGroup( This
, lpidGroup
, lpGroupName
, dwFlags
,
1036 DPID_NOPARENT_GROUP
, bAnsi
);
1038 if( lpGData
== NULL
)
1040 return DPERR_CANTADDPLAYER
; /* yes player not group */
1043 if( DPID_SYSTEM_GROUP
== *lpidGroup
)
1045 This
->dp2
->lpSysGroup
= lpGData
;
1046 TRACE( "Inserting system group\n" );
1050 /* Insert into the system group */
1051 lpGroupList lpGroup
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpGroup
) );
1052 lpGroup
->lpGData
= lpGData
;
1054 DPQ_INSERT( This
->dp2
->lpSysGroup
->groups
, lpGroup
, groups
);
1057 /* Something is now referencing this data */
1060 /* Set all the important stuff for the group */
1061 DP_SetGroupData( lpGData
, DPSET_REMOTE
, lpData
, dwDataSize
);
1063 /* FIXME: We should only create the system group if GetCaps returns
1064 * DPCAPS_GROUPOPTIMIZED.
1067 /* Let the SP know that we've created this group */
1068 if( This
->dp2
->spData
.lpCB
->CreateGroup
)
1070 DPSP_CREATEGROUPDATA data
;
1071 DWORD dwCreateFlags
= 0;
1073 TRACE( "Calling SP CreateGroup\n" );
1075 if( *lpidGroup
== DPID_NOPARENT_GROUP
)
1076 dwCreateFlags
|= DPLAYI_GROUP_SYSGROUP
;
1078 if( lpMsgHdr
== NULL
)
1079 dwCreateFlags
|= DPLAYI_PLAYER_PLAYERLOCAL
;
1081 if( dwFlags
& DPGROUP_HIDDEN
)
1082 dwCreateFlags
|= DPLAYI_GROUP_HIDDEN
;
1084 data
.idGroup
= *lpidGroup
;
1085 data
.dwFlags
= dwCreateFlags
;
1086 data
.lpSPMessageHeader
= lpMsgHdr
;
1087 data
.lpISP
= This
->dp2
->spData
.lpISP
;
1089 (*This
->dp2
->spData
.lpCB
->CreateGroup
)( &data
);
1092 /* Inform all other peers of the creation of a new group. If there are
1093 * no peers keep this event quiet.
1094 * Also if this message was sent to us, don't rebroadcast.
1096 if( ( lpMsgHdr
== NULL
) &&
1097 This
->dp2
->lpSessionDesc
&&
1098 ( This
->dp2
->lpSessionDesc
->dwFlags
& DPSESSION_MULTICASTSERVER
) )
1100 DPMSG_CREATEPLAYERORGROUP msg
;
1101 msg
.dwType
= DPSYS_CREATEPLAYERORGROUP
;
1103 msg
.dwPlayerType
= DPPLAYERTYPE_GROUP
;
1104 msg
.dpId
= *lpidGroup
;
1105 msg
.dwCurrentPlayers
= 0; /* FIXME: Incorrect? */
1106 msg
.lpData
= lpData
;
1107 msg
.dwDataSize
= dwDataSize
;
1108 msg
.dpnName
= *lpGroupName
;
1109 msg
.dpIdParent
= DPID_NOPARENT_GROUP
;
1110 msg
.dwFlags
= DPMSG_CREATEGROUP_DWFLAGS( dwFlags
);
1112 /* FIXME: Correct to just use send effectively? */
1113 /* FIXME: Should size include data w/ message or just message "header" */
1114 /* FIXME: Check return code */
1115 DP_SendEx( This
, DPID_SERVERPLAYER
, DPID_ALLPLAYERS
, 0, &msg
, sizeof( msg
),
1116 0, 0, NULL
, NULL
, bAnsi
);
1122 static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
1123 ( LPDIRECTPLAY2A iface
, LPDPID lpidGroup
, LPDPNAME lpGroupName
,
1124 LPVOID lpData
, DWORD dwDataSize
, DWORD dwFlags
)
1126 *lpidGroup
= DPID_UNKNOWN
;
1128 return DP_IF_CreateGroup( (IDirectPlay2AImpl
*)iface
, NULL
, lpidGroup
,
1129 lpGroupName
, lpData
, dwDataSize
, dwFlags
, TRUE
);
1132 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
1133 ( LPDIRECTPLAY2 iface
, LPDPID lpidGroup
, LPDPNAME lpGroupName
,
1134 LPVOID lpData
, DWORD dwDataSize
, DWORD dwFlags
)
1136 *lpidGroup
= DPID_UNKNOWN
;
1138 return DP_IF_CreateGroup( (IDirectPlay2AImpl
*)iface
, NULL
, lpidGroup
,
1139 lpGroupName
, lpData
, dwDataSize
, dwFlags
, FALSE
);
1144 DP_SetGroupData( lpGroupData lpGData
, DWORD dwFlags
,
1145 LPVOID lpData
, DWORD dwDataSize
)
1147 /* Clear out the data with this player */
1148 if( dwFlags
& DPSET_LOCAL
)
1150 if ( lpGData
->dwLocalDataSize
!= 0 )
1152 HeapFree( GetProcessHeap(), 0, lpGData
->lpLocalData
);
1153 lpGData
->lpLocalData
= NULL
;
1154 lpGData
->dwLocalDataSize
= 0;
1159 if( lpGData
->dwRemoteDataSize
!= 0 )
1161 HeapFree( GetProcessHeap(), 0, lpGData
->lpRemoteData
);
1162 lpGData
->lpRemoteData
= NULL
;
1163 lpGData
->dwRemoteDataSize
= 0;
1167 /* Reallocate for new data */
1168 if( lpData
!= NULL
)
1170 LPVOID lpNewData
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
1171 sizeof( dwDataSize
) );
1172 CopyMemory( lpNewData
, lpData
, dwDataSize
);
1174 if( dwFlags
& DPSET_LOCAL
)
1176 lpGData
->lpLocalData
= lpData
;
1177 lpGData
->dwLocalDataSize
= dwDataSize
;
1181 lpGData
->lpRemoteData
= lpNewData
;
1182 lpGData
->dwRemoteDataSize
= dwDataSize
;
1188 /* This function will just create the storage for the new player. */
1190 lpPlayerData
DP_CreatePlayer( IDirectPlay2Impl
* This
, LPDPID lpid
,
1191 LPDPNAME lpName
, DWORD dwFlags
,
1192 HANDLE hEvent
, BOOL bAnsi
)
1194 lpPlayerData lpPData
;
1196 TRACE( "(%p)->(%p,%p,%u)\n", This
, lpid
, lpName
, bAnsi
);
1198 /* Allocate the storage for the player and associate it with list element */
1199 lpPData
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpPData
) );
1200 if( lpPData
== NULL
)
1205 /* Set the desired player ID */
1206 lpPData
->dpid
= *lpid
;
1208 DP_CopyDPNAMEStruct( &lpPData
->name
, lpName
, bAnsi
);
1210 lpPData
->dwFlags
= dwFlags
;
1212 /* If we were given an event handle, duplicate it */
1215 if( !DuplicateHandle( GetCurrentProcess(), hEvent
,
1216 GetCurrentProcess(), &lpPData
->hEvent
,
1217 0, FALSE
, DUPLICATE_SAME_ACCESS
)
1220 /* FIXME: Memory leak */
1221 ERR( "Can't duplicate player msg handle %p\n", hEvent
);
1225 /* Initialize the SP data section */
1226 lpPData
->lpSPPlayerData
= DPSP_CreateSPPlayerData();
1228 TRACE( "Created player id 0x%08x\n", *lpid
);
1230 if( ~dwFlags
& DPLAYI_PLAYER_SYSPLAYER
)
1231 This
->dp2
->lpSessionDesc
->dwCurrentPlayers
++;
1236 /* Delete the contents of the DPNAME struct */
1238 DP_DeleteDPNameStruct( LPDPNAME lpDPName
)
1240 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY
, lpDPName
->u1
.lpszShortNameA
);
1241 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY
, lpDPName
->u2
.lpszLongNameA
);
1244 /* This method assumes that all links to it are already deleted */
1246 DP_DeletePlayer( IDirectPlay2Impl
* This
, DPID dpid
)
1248 lpPlayerList lpPList
;
1250 TRACE( "(%p)->(0x%08x)\n", This
, dpid
);
1252 DPQ_REMOVE_ENTRY( This
->dp2
->lpSysGroup
->players
, players
, lpPData
->dpid
, ==, dpid
, lpPList
);
1254 if( lpPList
== NULL
)
1256 ERR( "DPID 0x%08x not found\n", dpid
);
1260 /* Verify that this is the last reference to the data */
1261 if( --(lpPList
->lpPData
->uRef
) )
1263 FIXME( "Why is this not the last reference to player?\n" );
1268 DP_DeleteDPNameStruct( &lpPList
->lpPData
->name
);
1270 CloseHandle( lpPList
->lpPData
->hEvent
);
1271 HeapFree( GetProcessHeap(), 0, lpPList
->lpPData
);
1273 /* Delete Player List object */
1274 HeapFree( GetProcessHeap(), 0, lpPList
);
1277 static lpPlayerList
DP_FindPlayer( IDirectPlay2AImpl
* This
, DPID dpid
)
1279 lpPlayerList lpPlayers
;
1281 TRACE( "(%p)->(0x%08x)\n", This
, dpid
);
1283 if(This
->dp2
->lpSysGroup
== NULL
)
1286 DPQ_FIND_ENTRY( This
->dp2
->lpSysGroup
->players
, players
, lpPData
->dpid
, ==, dpid
, lpPlayers
);
1291 /* Basic area for Dst must already be allocated */
1292 static BOOL
DP_CopyDPNAMEStruct( LPDPNAME lpDst
, const DPNAME
*lpSrc
, BOOL bAnsi
)
1296 ZeroMemory( lpDst
, sizeof( *lpDst
) );
1297 lpDst
->dwSize
= sizeof( *lpDst
);
1301 if( lpSrc
->dwSize
!= sizeof( *lpSrc
) )
1306 /* Delete any existing pointers */
1307 HeapFree( GetProcessHeap(), 0, lpDst
->u1
.lpszShortNameA
);
1308 HeapFree( GetProcessHeap(), 0, lpDst
->u2
.lpszLongNameA
);
1310 /* Copy as required */
1311 CopyMemory( lpDst
, lpSrc
, lpSrc
->dwSize
);
1315 if( lpSrc
->u1
.lpszShortNameA
)
1317 lpDst
->u1
.lpszShortNameA
= HeapAlloc( GetProcessHeap(), 0,
1318 strlen(lpSrc
->u1
.lpszShortNameA
)+1 );
1319 strcpy( lpDst
->u1
.lpszShortNameA
, lpSrc
->u1
.lpszShortNameA
);
1321 if( lpSrc
->u2
.lpszLongNameA
)
1323 lpDst
->u2
.lpszLongNameA
= HeapAlloc( GetProcessHeap(), 0,
1324 strlen(lpSrc
->u2
.lpszLongNameA
)+1 );
1325 strcpy( lpDst
->u2
.lpszLongNameA
, lpSrc
->u2
.lpszLongNameA
);
1330 if( lpSrc
->u1
.lpszShortNameA
)
1332 lpDst
->u1
.lpszShortName
= HeapAlloc( GetProcessHeap(), 0,
1333 (strlenW(lpSrc
->u1
.lpszShortName
)+1)*sizeof(WCHAR
) );
1334 strcpyW( lpDst
->u1
.lpszShortName
, lpSrc
->u1
.lpszShortName
);
1336 if( lpSrc
->u2
.lpszLongNameA
)
1338 lpDst
->u2
.lpszLongName
= HeapAlloc( GetProcessHeap(), 0,
1339 (strlenW(lpSrc
->u2
.lpszLongName
)+1)*sizeof(WCHAR
) );
1340 strcpyW( lpDst
->u2
.lpszLongName
, lpSrc
->u2
.lpszLongName
);
1348 DP_SetPlayerData( lpPlayerData lpPData
, DWORD dwFlags
,
1349 LPVOID lpData
, DWORD dwDataSize
)
1351 /* Clear out the data with this player */
1352 if( dwFlags
& DPSET_LOCAL
)
1354 if ( lpPData
->dwLocalDataSize
!= 0 )
1356 HeapFree( GetProcessHeap(), 0, lpPData
->lpLocalData
);
1357 lpPData
->lpLocalData
= NULL
;
1358 lpPData
->dwLocalDataSize
= 0;
1363 if( lpPData
->dwRemoteDataSize
!= 0 )
1365 HeapFree( GetProcessHeap(), 0, lpPData
->lpRemoteData
);
1366 lpPData
->lpRemoteData
= NULL
;
1367 lpPData
->dwRemoteDataSize
= 0;
1371 /* Reallocate for new data */
1372 if( lpData
!= NULL
)
1374 LPVOID lpNewData
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
1375 sizeof( dwDataSize
) );
1376 CopyMemory( lpNewData
, lpData
, dwDataSize
);
1378 if( dwFlags
& DPSET_LOCAL
)
1380 lpPData
->lpLocalData
= lpData
;
1381 lpPData
->dwLocalDataSize
= dwDataSize
;
1385 lpPData
->lpRemoteData
= lpNewData
;
1386 lpPData
->dwRemoteDataSize
= dwDataSize
;
1392 static HRESULT WINAPI DP_IF_CreatePlayer
1393 ( IDirectPlay2Impl
* This
,
1394 LPVOID lpMsgHdr
, /* NULL for local creation, non NULL for remote creation */
1396 LPDPNAME lpPlayerName
,
1404 lpPlayerData lpPData
;
1405 lpPlayerList lpPList
;
1406 DWORD dwCreateFlags
= 0;
1408 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1409 This
, lpidPlayer
, lpPlayerName
, hEvent
, lpData
,
1410 dwDataSize
, dwFlags
, bAnsi
);
1414 dwFlags
= DPPLAYER_SPECTATOR
;
1417 if( lpidPlayer
== NULL
)
1419 return DPERR_INVALIDPARAMS
;
1423 /* Determine the creation flags for the player. These will be passed
1424 * to the name server if requesting a player id and to the SP when
1425 * informing it of the player creation
1428 if( dwFlags
& DPPLAYER_SERVERPLAYER
)
1430 if( *lpidPlayer
== DPID_SERVERPLAYER
)
1432 /* Server player for the host interface */
1433 dwCreateFlags
|= DPLAYI_PLAYER_APPSERVER
;
1435 else if( *lpidPlayer
== DPID_NAME_SERVER
)
1437 /* Name server - master of everything */
1438 dwCreateFlags
|= (DPLAYI_PLAYER_NAMESRVR
|DPLAYI_PLAYER_SYSPLAYER
);
1442 /* Server player for a non host interface */
1443 dwCreateFlags
|= DPLAYI_PLAYER_SYSPLAYER
;
1447 if( lpMsgHdr
== NULL
)
1448 dwCreateFlags
|= DPLAYI_PLAYER_PLAYERLOCAL
;
1451 /* Verify we know how to handle all the flags */
1452 if( !( ( dwFlags
& DPPLAYER_SERVERPLAYER
) ||
1453 ( dwFlags
& DPPLAYER_SPECTATOR
)
1457 /* Assume non fatal failure */
1458 ERR( "unknown dwFlags = 0x%08x\n", dwFlags
);
1461 /* If the name is not specified, we must provide one */
1462 if( *lpidPlayer
== DPID_UNKNOWN
)
1464 /* If we are the session master, we dish out the group/player ids */
1465 if( This
->dp2
->bHostInterface
)
1467 *lpidPlayer
= DP_NextObjectId();
1471 hr
= DP_MSG_SendRequestPlayerId( This
, dwCreateFlags
, lpidPlayer
);
1475 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr
) );
1482 /* FIXME: Would be nice to perhaps verify that we don't already have
1487 /* We pass creation flags, so we can distinguish sysplayers and not count them in the current
1489 lpPData
= DP_CreatePlayer( This
, lpidPlayer
, lpPlayerName
, dwCreateFlags
,
1492 if( lpPData
== NULL
)
1494 return DPERR_CANTADDPLAYER
;
1497 /* Create the list object and link it in */
1498 lpPList
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpPList
) );
1499 if( lpPList
== NULL
)
1501 FIXME( "Memory leak\n" );
1502 return DPERR_CANTADDPLAYER
;
1506 lpPList
->lpPData
= lpPData
;
1508 /* Add the player to the system group */
1509 DPQ_INSERT( This
->dp2
->lpSysGroup
->players
, lpPList
, players
);
1511 /* Update the information and send it to all players in the session */
1512 DP_SetPlayerData( lpPData
, DPSET_REMOTE
, lpData
, dwDataSize
);
1514 /* Let the SP know that we've created this player */
1515 if( This
->dp2
->spData
.lpCB
->CreatePlayer
)
1517 DPSP_CREATEPLAYERDATA data
;
1519 data
.idPlayer
= *lpidPlayer
;
1520 data
.dwFlags
= dwCreateFlags
;
1521 data
.lpSPMessageHeader
= lpMsgHdr
;
1522 data
.lpISP
= This
->dp2
->spData
.lpISP
;
1524 TRACE( "Calling SP CreatePlayer 0x%08x: dwFlags: 0x%08x lpMsgHdr: %p\n",
1525 *lpidPlayer
, data
.dwFlags
, data
.lpSPMessageHeader
);
1527 hr
= (*This
->dp2
->spData
.lpCB
->CreatePlayer
)( &data
);
1532 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr
) );
1536 /* Now let the SP know that this player is a member of the system group */
1537 if( This
->dp2
->spData
.lpCB
->AddPlayerToGroup
)
1539 DPSP_ADDPLAYERTOGROUPDATA data
;
1541 data
.idPlayer
= *lpidPlayer
;
1542 data
.idGroup
= DPID_SYSTEM_GROUP
;
1543 data
.lpISP
= This
->dp2
->spData
.lpISP
;
1545 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1547 hr
= (*This
->dp2
->spData
.lpCB
->AddPlayerToGroup
)( &data
);
1552 ERR( "Failed to add player to sys group with sp: %s\n",
1553 DPLAYX_HresultToString(hr
) );
1558 if( This
->dp2
->bHostInterface
== FALSE
)
1560 /* Let the name server know about the creation of this player */
1561 /* FIXME: Is this only to be done for the creation of a server player or
1562 * is this used for regular players? If only for server players, move
1563 * this call to DP_SecureOpen(...);
1566 TRACE( "Sending message to self to get my addr\n" );
1567 DP_MSG_ToSelf( This
, *lpidPlayer
); /* This is a hack right now */
1570 hr
= DP_MSG_ForwardPlayerCreation( This
, *lpidPlayer
);
1573 /* Inform all other peers of the creation of a new player. If there are
1574 * no peers keep this quiet.
1575 * Also, if this was a remote event, no need to rebroadcast it.
1577 if( ( lpMsgHdr
== NULL
) &&
1578 This
->dp2
->lpSessionDesc
&&
1579 ( This
->dp2
->lpSessionDesc
->dwFlags
& DPSESSION_MULTICASTSERVER
) )
1581 DPMSG_CREATEPLAYERORGROUP msg
;
1582 msg
.dwType
= DPSYS_CREATEPLAYERORGROUP
;
1584 msg
.dwPlayerType
= DPPLAYERTYPE_PLAYER
;
1585 msg
.dpId
= *lpidPlayer
;
1586 msg
.dwCurrentPlayers
= 0; /* FIXME: Incorrect */
1587 msg
.lpData
= lpData
;
1588 msg
.dwDataSize
= dwDataSize
;
1589 msg
.dpnName
= *lpPlayerName
;
1590 msg
.dpIdParent
= DPID_NOPARENT_GROUP
;
1591 msg
.dwFlags
= DPMSG_CREATEPLAYER_DWFLAGS( dwFlags
);
1593 /* FIXME: Correct to just use send effectively? */
1594 /* FIXME: Should size include data w/ message or just message "header" */
1595 /* FIXME: Check return code */
1596 hr
= DP_SendEx( This
, DPID_SERVERPLAYER
, DPID_ALLPLAYERS
, 0, &msg
,
1597 sizeof( msg
), 0, 0, NULL
, NULL
, bAnsi
);
1604 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
1605 ( LPDIRECTPLAY2A iface
, LPDPID lpidPlayer
, LPDPNAME lpPlayerName
,
1606 HANDLE hEvent
, LPVOID lpData
, DWORD dwDataSize
, DWORD dwFlags
)
1608 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
1610 if( dwFlags
& DPPLAYER_SERVERPLAYER
)
1612 *lpidPlayer
= DPID_SERVERPLAYER
;
1616 *lpidPlayer
= DPID_UNKNOWN
;
1619 return DP_IF_CreatePlayer( This
, NULL
, lpidPlayer
, lpPlayerName
, hEvent
,
1620 lpData
, dwDataSize
, dwFlags
, TRUE
);
1623 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
1624 ( LPDIRECTPLAY2 iface
, LPDPID lpidPlayer
, LPDPNAME lpPlayerName
,
1625 HANDLE hEvent
, LPVOID lpData
, DWORD dwDataSize
, DWORD dwFlags
)
1627 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
1629 if( dwFlags
& DPPLAYER_SERVERPLAYER
)
1631 *lpidPlayer
= DPID_SERVERPLAYER
;
1635 *lpidPlayer
= DPID_UNKNOWN
;
1638 return DP_IF_CreatePlayer( This
, NULL
, lpidPlayer
, lpPlayerName
, hEvent
,
1639 lpData
, dwDataSize
, dwFlags
, FALSE
);
1642 static DPID
DP_GetRemoteNextObjectId(void)
1647 return DP_NextObjectId();
1650 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
1651 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idGroup
,
1652 DPID idPlayer
, BOOL bAnsi
)
1656 lpGroupData lpGData
;
1657 lpPlayerList lpPList
;
1659 TRACE( "(%p)->(%p,0x%08x,0x%08x,%u)\n",
1660 This
, lpMsgHdr
, idGroup
, idPlayer
, bAnsi
);
1662 /* Find the group */
1663 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
1665 return DPERR_INVALIDGROUP
;
1668 /* Find the player */
1669 if( ( lpPList
= DP_FindPlayer( This
, idPlayer
) ) == NULL
)
1671 return DPERR_INVALIDPLAYER
;
1674 /* Remove the player shortcut from the group */
1675 DPQ_REMOVE_ENTRY( lpGData
->players
, players
, lpPData
->dpid
, ==, idPlayer
, lpPList
);
1677 if( lpPList
== NULL
)
1679 return DPERR_INVALIDPLAYER
;
1682 /* One less reference */
1683 lpPList
->lpPData
->uRef
--;
1685 /* Delete the Player List element */
1686 HeapFree( GetProcessHeap(), 0, lpPList
);
1688 /* Inform the SP if they care */
1689 if( This
->dp2
->spData
.lpCB
->RemovePlayerFromGroup
)
1691 DPSP_REMOVEPLAYERFROMGROUPDATA data
;
1693 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1695 data
.idPlayer
= idPlayer
;
1696 data
.idGroup
= idGroup
;
1697 data
.lpISP
= This
->dp2
->spData
.lpISP
;
1699 hr
= (*This
->dp2
->spData
.lpCB
->RemovePlayerFromGroup
)( &data
);
1702 /* Need to send a DELETEPLAYERFROMGROUP message */
1703 FIXME( "Need to send a message\n" );
1708 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
1709 ( LPDIRECTPLAY2A iface
, DPID idGroup
, DPID idPlayer
)
1711 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
1712 return DP_IF_DeletePlayerFromGroup( This
, NULL
, idGroup
, idPlayer
, TRUE
);
1715 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
1716 ( LPDIRECTPLAY2 iface
, DPID idGroup
, DPID idPlayer
)
1718 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
1719 return DP_IF_DeletePlayerFromGroup( This
, NULL
, idGroup
, idPlayer
, FALSE
);
1722 typedef struct _DPRGOPContext
1724 IDirectPlay3Impl
* This
;
1727 } DPRGOPContext
, *lpDPRGOPContext
;
1729 static BOOL CALLBACK
1730 cbRemoveGroupOrPlayer(
1737 lpDPRGOPContext lpCtxt
= (lpDPRGOPContext
)lpContext
;
1739 TRACE( "Removing element:0x%08x (type:0x%08x) from element:0x%08x\n",
1740 dpId
, dwPlayerType
, lpCtxt
->idGroup
);
1742 if( dwPlayerType
== DPPLAYERTYPE_GROUP
)
1744 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt
->This
, lpCtxt
->idGroup
,
1749 ERR( "Unable to delete group 0x%08x from group 0x%08x\n",
1750 dpId
, lpCtxt
->idGroup
);
1755 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl
*)lpCtxt
->This
,
1756 NULL
, lpCtxt
->idGroup
,
1757 dpId
, lpCtxt
->bAnsi
)
1761 ERR( "Unable to delete player 0x%08x from grp 0x%08x\n",
1762 dpId
, lpCtxt
->idGroup
);
1766 return TRUE
; /* Continue enumeration */
1769 static HRESULT WINAPI DP_IF_DestroyGroup
1770 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idGroup
, BOOL bAnsi
)
1772 lpGroupData lpGData
;
1773 DPRGOPContext context
;
1775 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1776 This
, lpMsgHdr
, idGroup
, bAnsi
);
1778 /* Find the group */
1779 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
1781 return DPERR_INVALIDPLAYER
; /* yes player */
1784 context
.This
= (IDirectPlay3Impl
*)This
;
1785 context
.bAnsi
= bAnsi
;
1786 context
.idGroup
= idGroup
;
1788 /* Remove all players that this group has */
1789 DP_IF_EnumGroupPlayers( This
, idGroup
, NULL
,
1790 cbRemoveGroupOrPlayer
, (LPVOID
)&context
, 0, bAnsi
);
1792 /* Remove all links to groups that this group has since this is dp3 */
1793 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl
*)This
, idGroup
, NULL
,
1794 cbRemoveGroupOrPlayer
, (LPVOID
)&context
, 0, bAnsi
);
1796 /* Remove this group from the parent group - if it has one */
1797 if( ( idGroup
!= DPID_SYSTEM_GROUP
) &&
1798 ( lpGData
->parent
!= DPID_SYSTEM_GROUP
)
1801 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl
*)This
, lpGData
->parent
,
1805 /* Now delete this group data and list from the system group */
1806 DP_DeleteGroup( This
, idGroup
);
1808 /* Let the SP know that we've destroyed this group */
1809 if( This
->dp2
->spData
.lpCB
->DeleteGroup
)
1811 DPSP_DELETEGROUPDATA data
;
1813 FIXME( "data.dwFlags is incorrect\n" );
1815 data
.idGroup
= idGroup
;
1817 data
.lpISP
= This
->dp2
->spData
.lpISP
;
1819 (*This
->dp2
->spData
.lpCB
->DeleteGroup
)( &data
);
1822 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1827 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
1828 ( LPDIRECTPLAY2A iface
, DPID idGroup
)
1830 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
1831 return DP_IF_DestroyGroup( This
, NULL
, idGroup
, TRUE
);
1834 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
1835 ( LPDIRECTPLAY2 iface
, DPID idGroup
)
1837 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
1838 return DP_IF_DestroyGroup( This
, NULL
, idGroup
, FALSE
);
1841 typedef struct _DPFAGContext
1843 IDirectPlay2Impl
* This
;
1846 } DPFAGContext
, *lpDPFAGContext
;
1848 static HRESULT WINAPI DP_IF_DestroyPlayer
1849 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idPlayer
, BOOL bAnsi
)
1851 DPFAGContext cbContext
;
1853 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1854 This
, lpMsgHdr
, idPlayer
, bAnsi
);
1856 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
1858 return DPERR_UNINITIALIZED
;
1861 if( DP_FindPlayer( This
, idPlayer
) == NULL
)
1863 return DPERR_INVALIDPLAYER
;
1866 /* FIXME: If the player is remote, we must be the host to delete this */
1868 cbContext
.This
= This
;
1869 cbContext
.idPlayer
= idPlayer
;
1870 cbContext
.bAnsi
= bAnsi
;
1872 /* Find each group and call DeletePlayerFromGroup if the player is a
1873 member of the group */
1874 DP_IF_EnumGroups( This
, NULL
, cbDeletePlayerFromAllGroups
,
1875 (LPVOID
)&cbContext
, DPENUMGROUPS_ALL
, bAnsi
);
1877 /* Now delete player and player list from the sys group */
1878 DP_DeletePlayer( This
, idPlayer
);
1880 /* Let the SP know that we've destroyed this group */
1881 if( This
->dp2
->spData
.lpCB
->DeletePlayer
)
1883 DPSP_DELETEPLAYERDATA data
;
1885 FIXME( "data.dwFlags is incorrect\n" );
1887 data
.idPlayer
= idPlayer
;
1889 data
.lpISP
= This
->dp2
->spData
.lpISP
;
1891 (*This
->dp2
->spData
.lpCB
->DeletePlayer
)( &data
);
1894 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
1899 static BOOL CALLBACK
1900 cbDeletePlayerFromAllGroups(
1907 lpDPFAGContext lpCtxt
= (lpDPFAGContext
)lpContext
;
1909 if( dwPlayerType
== DPPLAYERTYPE_GROUP
)
1911 DP_IF_DeletePlayerFromGroup( lpCtxt
->This
, NULL
, dpId
, lpCtxt
->idPlayer
,
1914 /* Enumerate all groups in this group since this will normally only
1915 * be called for top level groups
1917 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl
*)lpCtxt
->This
,
1919 cbDeletePlayerFromAllGroups
,
1920 lpContext
, DPENUMGROUPS_ALL
,
1926 ERR( "Group callback has dwPlayerType = 0x%08x\n", dwPlayerType
);
1932 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
1933 ( LPDIRECTPLAY2A iface
, DPID idPlayer
)
1935 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
1936 return DP_IF_DestroyPlayer( This
, NULL
, idPlayer
, TRUE
);
1939 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
1940 ( LPDIRECTPLAY2 iface
, DPID idPlayer
)
1942 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
1943 return DP_IF_DestroyPlayer( This
, NULL
, idPlayer
, FALSE
);
1946 static HRESULT WINAPI DP_IF_EnumGroupPlayers
1947 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPGUID lpguidInstance
,
1948 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
1949 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
)
1951 lpGroupData lpGData
;
1952 lpPlayerList lpPList
;
1954 FIXME("(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
1955 This
, idGroup
, lpguidInstance
, lpEnumPlayersCallback2
,
1956 lpContext
, dwFlags
, bAnsi
);
1958 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
1960 return DPERR_UNINITIALIZED
;
1963 /* Find the group */
1964 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
1966 return DPERR_INVALIDGROUP
;
1969 if( DPQ_IS_EMPTY( lpGData
->players
) )
1974 lpPList
= DPQ_FIRST( lpGData
->players
);
1976 /* Walk the players in this group */
1979 /* We do not enum the name server or app server as they are of no
1980 * consequence to the end user.
1982 if( ( lpPList
->lpPData
->dpid
!= DPID_NAME_SERVER
) &&
1983 ( lpPList
->lpPData
->dpid
!= DPID_SERVERPLAYER
)
1987 /* FIXME: Need to add stuff for dwFlags checking */
1989 if( !lpEnumPlayersCallback2( lpPList
->lpPData
->dpid
, DPPLAYERTYPE_PLAYER
,
1990 &lpPList
->lpPData
->name
,
1991 lpPList
->lpPData
->dwFlags
,
1995 /* User requested break */
2000 if( DPQ_IS_ENDOFLIST( lpPList
->players
) )
2005 lpPList
= DPQ_NEXT( lpPList
->players
);
2011 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
2012 ( LPDIRECTPLAY2A iface
, DPID idGroup
, LPGUID lpguidInstance
,
2013 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2014 LPVOID lpContext
, DWORD dwFlags
)
2016 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2017 return DP_IF_EnumGroupPlayers( This
, idGroup
, lpguidInstance
,
2018 lpEnumPlayersCallback2
, lpContext
,
2022 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
2023 ( LPDIRECTPLAY2 iface
, DPID idGroup
, LPGUID lpguidInstance
,
2024 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2025 LPVOID lpContext
, DWORD dwFlags
)
2027 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2028 return DP_IF_EnumGroupPlayers( This
, idGroup
, lpguidInstance
,
2029 lpEnumPlayersCallback2
, lpContext
,
2033 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2034 static HRESULT WINAPI DP_IF_EnumGroups
2035 ( IDirectPlay2Impl
* This
, LPGUID lpguidInstance
,
2036 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2037 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
)
2039 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl
*)This
,
2040 DPID_SYSTEM_GROUP
, lpguidInstance
,
2041 lpEnumPlayersCallback2
, lpContext
,
2045 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
2046 ( LPDIRECTPLAY2A iface
, LPGUID lpguidInstance
,
2047 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2048 LPVOID lpContext
, DWORD dwFlags
)
2050 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2051 return DP_IF_EnumGroups( This
, lpguidInstance
, lpEnumPlayersCallback2
,
2052 lpContext
, dwFlags
, TRUE
);
2055 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
2056 ( LPDIRECTPLAY2 iface
, LPGUID lpguidInstance
,
2057 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2058 LPVOID lpContext
, DWORD dwFlags
)
2060 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2061 return DP_IF_EnumGroups( This
, lpguidInstance
, lpEnumPlayersCallback2
,
2062 lpContext
, dwFlags
, FALSE
);
2065 static HRESULT WINAPI DP_IF_EnumPlayers
2066 ( IDirectPlay2Impl
* This
, LPGUID lpguidInstance
,
2067 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2068 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
)
2070 return DP_IF_EnumGroupPlayers( This
, DPID_SYSTEM_GROUP
, lpguidInstance
,
2071 lpEnumPlayersCallback2
, lpContext
,
2075 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
2076 ( LPDIRECTPLAY2A iface
, LPGUID lpguidInstance
,
2077 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2078 LPVOID lpContext
, DWORD dwFlags
)
2080 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2081 return DP_IF_EnumPlayers( This
, lpguidInstance
, lpEnumPlayersCallback2
,
2082 lpContext
, dwFlags
, TRUE
);
2085 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
2086 ( LPDIRECTPLAY2 iface
, LPGUID lpguidInstance
,
2087 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2088 LPVOID lpContext
, DWORD dwFlags
)
2090 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2091 return DP_IF_EnumPlayers( This
, lpguidInstance
, lpEnumPlayersCallback2
,
2092 lpContext
, dwFlags
, FALSE
);
2095 /* This function should call the registered callback function that the user
2096 passed into EnumSessions for each entry available.
2098 static void DP_InvokeEnumSessionCallbacks
2099 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2
,
2104 LPDPSESSIONDESC2 lpSessionDesc
;
2106 FIXME( ": not checking for conditions\n" );
2108 /* Not sure if this should be pruning but it's convenient */
2109 NS_PruneSessionCache( lpNSInfo
);
2111 NS_ResetSessionEnumeration( lpNSInfo
);
2113 /* Enumerate all sessions */
2114 /* FIXME: Need to indicate ANSI */
2115 while( (lpSessionDesc
= NS_WalkSessions( lpNSInfo
) ) != NULL
)
2117 TRACE( "EnumSessionsCallback2 invoked\n" );
2118 if( !lpEnumSessionsCallback2( lpSessionDesc
, &dwTimeout
, 0, lpContext
) )
2124 /* Invoke one last time to indicate that there is no more to come */
2125 lpEnumSessionsCallback2( NULL
, &dwTimeout
, DPESC_TIMEDOUT
, lpContext
);
2128 static DWORD CALLBACK
DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext
)
2130 EnumSessionAsyncCallbackData
* data
= (EnumSessionAsyncCallbackData
*)lpContext
;
2131 HANDLE hSuicideRequest
= data
->hSuicideRequest
;
2132 DWORD dwTimeout
= data
->dwTimeout
;
2134 TRACE( "Thread started with timeout = 0x%08x\n", dwTimeout
);
2140 /* Sleep up to dwTimeout waiting for request to terminate thread */
2141 if( WaitForSingleObject( hSuicideRequest
, dwTimeout
) == WAIT_OBJECT_0
)
2143 TRACE( "Thread terminating on terminate request\n" );
2147 /* Now resend the enum request */
2148 hr
= NS_SendSessionRequestBroadcast( &data
->requestGuid
,
2149 data
->dwEnumSessionFlags
,
2154 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr
) );
2155 /* FIXME: Should we kill this thread? How to inform the main thread? */
2160 TRACE( "Thread terminating\n" );
2162 /* Clean up the thread data */
2163 CloseHandle( hSuicideRequest
);
2164 HeapFree( GetProcessHeap(), 0, lpContext
);
2166 /* FIXME: Need to have some notification to main app thread that this is
2167 * dead. It would serve two purposes. 1) allow sync on termination
2168 * so that we don't actually send something to ourselves when we
2169 * become name server (race condition) and 2) so that if we die
2170 * abnormally something else will be able to tell.
2176 static void DP_KillEnumSessionThread( IDirectPlay2Impl
* This
)
2178 /* Does a thread exist? If so we were doing an async enum session */
2179 if( This
->dp2
->hEnumSessionThread
!= INVALID_HANDLE_VALUE
)
2181 TRACE( "Killing EnumSession thread %p\n",
2182 This
->dp2
->hEnumSessionThread
);
2184 /* Request that the thread kill itself nicely */
2185 SetEvent( This
->dp2
->hKillEnumSessionThreadEvent
);
2186 CloseHandle( This
->dp2
->hKillEnumSessionThreadEvent
);
2188 /* We no longer need to know about the thread */
2189 CloseHandle( This
->dp2
->hEnumSessionThread
);
2191 This
->dp2
->hEnumSessionThread
= INVALID_HANDLE_VALUE
;
2195 static HRESULT WINAPI DP_IF_EnumSessions
2196 ( IDirectPlay2Impl
* This
, LPDPSESSIONDESC2 lpsd
, DWORD dwTimeout
,
2197 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2
,
2198 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
)
2202 TRACE( "(%p)->(%p,0x%08x,%p,%p,0x%08x,%u)\n",
2203 This
, lpsd
, dwTimeout
, lpEnumSessionsCallback2
, lpContext
, dwFlags
,
2206 /* Can't enumerate if the interface is already open */
2207 if( This
->dp2
->bConnectionOpen
)
2209 return DPERR_GENERIC
;
2213 /* The loading of a lobby provider _seems_ to require a backdoor loading
2214 * of the service provider to also associate with this DP object. This is
2215 * because the app doesn't seem to have to call EnumConnections and
2216 * InitializeConnection for the SP before calling this method. As such
2217 * we'll do their dirty work for them with a quick hack so as to always
2218 * load the TCP/IP service provider.
2220 * The correct solution would seem to involve creating a dialog box which
2221 * contains the possible SPs. These dialog boxes most likely follow SDK
2224 if( This
->dp2
->bDPLSPInitialized
&& !This
->dp2
->bSPInitialized
)
2226 LPVOID lpConnection
;
2229 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2231 if( !DP_BuildSPCompoundAddr( (LPGUID
)&DPSPGUID_TCPIP
, &lpConnection
, &dwSize
) )
2233 ERR( "Can't build compound addr\n" );
2234 return DPERR_GENERIC
;
2237 hr
= DP_IF_InitializeConnection( (IDirectPlay3Impl
*)This
, lpConnection
,
2244 /* Free up the address buffer */
2245 HeapFree( GetProcessHeap(), 0, lpConnection
);
2247 /* The SP is now initialized */
2248 This
->dp2
->bSPInitialized
= TRUE
;
2253 /* Use the service provider default? */
2254 if( dwTimeout
== 0 )
2257 spCaps
.dwSize
= sizeof( spCaps
);
2259 DP_IF_GetCaps( This
, &spCaps
, 0 );
2260 dwTimeout
= spCaps
.dwTimeout
;
2262 /* The service provider doesn't provide one either! */
2263 if( dwTimeout
== 0 )
2265 /* Provide the TCP/IP default */
2266 dwTimeout
= DPMSG_WAIT_5_SECS
;
2270 if( dwFlags
& DPENUMSESSIONS_STOPASYNC
)
2272 DP_KillEnumSessionThread( This
);
2276 if( ( dwFlags
& DPENUMSESSIONS_ASYNC
) )
2278 /* Enumerate everything presently in the local session cache */
2279 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2
,
2280 This
->dp2
->lpNameServerData
, dwTimeout
,
2283 if( This
->dp2
->dwEnumSessionLock
!= 0 )
2284 return DPERR_CONNECTING
;
2286 /* See if we've already created a thread to service this interface */
2287 if( This
->dp2
->hEnumSessionThread
== INVALID_HANDLE_VALUE
)
2290 This
->dp2
->dwEnumSessionLock
++;
2292 /* Send the first enum request inline since the user may cancel a dialog
2293 * if one is presented. Also, may also have a connecting return code.
2295 hr
= NS_SendSessionRequestBroadcast( &lpsd
->guidApplication
,
2296 dwFlags
, &This
->dp2
->spData
);
2300 EnumSessionAsyncCallbackData
* lpData
2301 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpData
) );
2302 /* FIXME: need to kill the thread on object deletion */
2303 lpData
->lpSpData
= &This
->dp2
->spData
;
2305 lpData
->requestGuid
= lpsd
->guidApplication
;
2306 lpData
->dwEnumSessionFlags
= dwFlags
;
2307 lpData
->dwTimeout
= dwTimeout
;
2309 This
->dp2
->hKillEnumSessionThreadEvent
=
2310 CreateEventW( NULL
, TRUE
, FALSE
, NULL
);
2312 if( !DuplicateHandle( GetCurrentProcess(),
2313 This
->dp2
->hKillEnumSessionThreadEvent
,
2314 GetCurrentProcess(),
2315 &lpData
->hSuicideRequest
,
2316 0, FALSE
, DUPLICATE_SAME_ACCESS
)
2319 ERR( "Can't duplicate thread killing handle\n" );
2322 TRACE( ": creating EnumSessionsRequest thread\n" );
2324 This
->dp2
->hEnumSessionThread
= CreateThread( NULL
,
2326 DP_EnumSessionsSendAsyncRequestThread
,
2331 This
->dp2
->dwEnumSessionLock
--;
2336 /* Invalidate the session cache for the interface */
2337 NS_InvalidateSessionCache( This
->dp2
->lpNameServerData
);
2339 /* Send the broadcast for session enumeration */
2340 hr
= NS_SendSessionRequestBroadcast( &lpsd
->guidApplication
,
2342 &This
->dp2
->spData
);
2345 SleepEx( dwTimeout
, FALSE
);
2347 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2
,
2348 This
->dp2
->lpNameServerData
, dwTimeout
,
2355 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2356 ( LPDIRECTPLAY2A iface
, LPDPSESSIONDESC2 lpsd
, DWORD dwTimeout
,
2357 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2
,
2358 LPVOID lpContext
, DWORD dwFlags
)
2360 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2361 return DP_IF_EnumSessions( This
, lpsd
, dwTimeout
, lpEnumSessionsCallback2
,
2362 lpContext
, dwFlags
, TRUE
);
2365 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2366 ( LPDIRECTPLAY2 iface
, LPDPSESSIONDESC2 lpsd
, DWORD dwTimeout
,
2367 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2
,
2368 LPVOID lpContext
, DWORD dwFlags
)
2370 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2371 return DP_IF_EnumSessions( This
, lpsd
, dwTimeout
, lpEnumSessionsCallback2
,
2372 lpContext
, dwFlags
, FALSE
);
2375 static HRESULT WINAPI DP_IF_GetPlayerCaps
2376 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPDPCAPS lpDPCaps
,
2379 DPSP_GETCAPSDATA data
;
2381 TRACE("(%p)->(0x%08x,%p,0x%08x)\n", This
, idPlayer
, lpDPCaps
, dwFlags
);
2383 /* Query the service provider */
2384 data
.idPlayer
= idPlayer
;
2385 data
.dwFlags
= dwFlags
;
2386 data
.lpCaps
= lpDPCaps
;
2387 data
.lpISP
= This
->dp2
->spData
.lpISP
;
2389 return (*This
->dp2
->spData
.lpCB
->GetCaps
)( &data
);
2392 static HRESULT WINAPI DP_IF_GetCaps
2393 ( IDirectPlay2Impl
* This
, LPDPCAPS lpDPCaps
, DWORD dwFlags
)
2395 return DP_IF_GetPlayerCaps( This
, DPID_ALLPLAYERS
, lpDPCaps
, dwFlags
);
2398 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2399 ( LPDIRECTPLAY2A iface
, LPDPCAPS lpDPCaps
, DWORD dwFlags
)
2401 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2402 return DP_IF_GetCaps( This
, lpDPCaps
, dwFlags
);
2405 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2406 ( LPDIRECTPLAY2 iface
, LPDPCAPS lpDPCaps
, DWORD dwFlags
)
2408 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2409 return DP_IF_GetCaps( This
, lpDPCaps
, dwFlags
);
2412 static HRESULT WINAPI DP_IF_GetGroupData
2413 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPVOID lpData
,
2414 LPDWORD lpdwDataSize
, DWORD dwFlags
, BOOL bAnsi
)
2416 lpGroupData lpGData
;
2417 DWORD dwRequiredBufferSize
;
2418 LPVOID lpCopyDataFrom
;
2420 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2421 This
, idGroup
, lpData
, lpdwDataSize
, dwFlags
, bAnsi
);
2423 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
2425 return DPERR_INVALIDGROUP
;
2428 /* How much buffer is required? */
2429 if( dwFlags
& DPSET_LOCAL
)
2431 dwRequiredBufferSize
= lpGData
->dwLocalDataSize
;
2432 lpCopyDataFrom
= lpGData
->lpLocalData
;
2436 dwRequiredBufferSize
= lpGData
->dwRemoteDataSize
;
2437 lpCopyDataFrom
= lpGData
->lpRemoteData
;
2440 /* Is the user requesting to know how big a buffer is required? */
2441 if( ( lpData
== NULL
) ||
2442 ( *lpdwDataSize
< dwRequiredBufferSize
)
2445 *lpdwDataSize
= dwRequiredBufferSize
;
2446 return DPERR_BUFFERTOOSMALL
;
2449 CopyMemory( lpData
, lpCopyDataFrom
, dwRequiredBufferSize
);
2454 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2455 ( LPDIRECTPLAY2A iface
, DPID idGroup
, LPVOID lpData
,
2456 LPDWORD lpdwDataSize
, DWORD dwFlags
)
2458 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2459 return DP_IF_GetGroupData( This
, idGroup
, lpData
, lpdwDataSize
,
2463 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2464 ( LPDIRECTPLAY2 iface
, DPID idGroup
, LPVOID lpData
,
2465 LPDWORD lpdwDataSize
, DWORD dwFlags
)
2467 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2468 return DP_IF_GetGroupData( This
, idGroup
, lpData
, lpdwDataSize
,
2472 static HRESULT WINAPI DP_IF_GetGroupName
2473 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPVOID lpData
,
2474 LPDWORD lpdwDataSize
, BOOL bAnsi
)
2476 lpGroupData lpGData
;
2477 LPDPNAME lpName
= (LPDPNAME
)lpData
;
2478 DWORD dwRequiredDataSize
;
2480 FIXME("(%p)->(0x%08x,%p,%p,%u) ANSI ignored\n",
2481 This
, idGroup
, lpData
, lpdwDataSize
, bAnsi
);
2483 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
2485 return DPERR_INVALIDGROUP
;
2488 dwRequiredDataSize
= lpGData
->name
.dwSize
;
2490 if( lpGData
->name
.u1
.lpszShortNameA
)
2492 dwRequiredDataSize
+= strlen( lpGData
->name
.u1
.lpszShortNameA
) + 1;
2495 if( lpGData
->name
.u2
.lpszLongNameA
)
2497 dwRequiredDataSize
+= strlen( lpGData
->name
.u2
.lpszLongNameA
) + 1;
2500 if( ( lpData
== NULL
) ||
2501 ( *lpdwDataSize
< dwRequiredDataSize
)
2504 *lpdwDataSize
= dwRequiredDataSize
;
2505 return DPERR_BUFFERTOOSMALL
;
2508 /* Copy the structure */
2509 CopyMemory( lpName
, &lpGData
->name
, lpGData
->name
.dwSize
);
2511 if( lpGData
->name
.u1
.lpszShortNameA
)
2513 strcpy( ((char*)lpName
)+lpGData
->name
.dwSize
,
2514 lpGData
->name
.u1
.lpszShortNameA
);
2518 lpName
->u1
.lpszShortNameA
= NULL
;
2521 if( lpGData
->name
.u1
.lpszShortNameA
)
2523 strcpy( ((char*)lpName
)+lpGData
->name
.dwSize
,
2524 lpGData
->name
.u2
.lpszLongNameA
);
2528 lpName
->u2
.lpszLongNameA
= NULL
;
2534 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2535 ( LPDIRECTPLAY2A iface
, DPID idGroup
, LPVOID lpData
,
2536 LPDWORD lpdwDataSize
)
2538 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2539 return DP_IF_GetGroupName( This
, idGroup
, lpData
, lpdwDataSize
, TRUE
);
2542 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2543 ( LPDIRECTPLAY2 iface
, DPID idGroup
, LPVOID lpData
,
2544 LPDWORD lpdwDataSize
)
2546 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2547 return DP_IF_GetGroupName( This
, idGroup
, lpData
, lpdwDataSize
, FALSE
);
2550 static HRESULT WINAPI DP_IF_GetMessageCount
2551 ( IDirectPlay2Impl
* This
, DPID idPlayer
,
2552 LPDWORD lpdwCount
, BOOL bAnsi
)
2554 FIXME("(%p)->(0x%08x,%p,%u): stub\n", This
, idPlayer
, lpdwCount
, bAnsi
);
2555 return DP_IF_GetMessageQueue( (IDirectPlay4Impl
*)This
, 0, idPlayer
,
2556 DPMESSAGEQUEUE_RECEIVE
, lpdwCount
, NULL
,
2560 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2561 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPDWORD lpdwCount
)
2563 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2564 return DP_IF_GetMessageCount( This
, idPlayer
, lpdwCount
, TRUE
);
2567 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2568 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPDWORD lpdwCount
)
2570 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2571 return DP_IF_GetMessageCount( This
, idPlayer
, lpdwCount
, FALSE
);
2574 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2575 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPVOID lpData
, LPDWORD lpdwDataSize
)
2577 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2578 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This
, idPlayer
, lpData
, lpdwDataSize
);
2582 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2583 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPVOID lpData
, LPDWORD lpdwDataSize
)
2585 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2586 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This
, idPlayer
, lpData
, lpdwDataSize
);
2590 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2591 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPDPCAPS lpPlayerCaps
,
2594 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2595 return DP_IF_GetPlayerCaps( This
, idPlayer
, lpPlayerCaps
, dwFlags
);
2598 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2599 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPDPCAPS lpPlayerCaps
,
2602 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2603 return DP_IF_GetPlayerCaps( This
, idPlayer
, lpPlayerCaps
, dwFlags
);
2606 static HRESULT WINAPI DP_IF_GetPlayerData
2607 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPVOID lpData
,
2608 LPDWORD lpdwDataSize
, DWORD dwFlags
, BOOL bAnsi
)
2610 lpPlayerList lpPList
;
2611 DWORD dwRequiredBufferSize
;
2612 LPVOID lpCopyDataFrom
;
2614 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2615 This
, idPlayer
, lpData
, lpdwDataSize
, dwFlags
, bAnsi
);
2617 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
2619 return DPERR_UNINITIALIZED
;
2622 if( ( lpPList
= DP_FindPlayer( This
, idPlayer
) ) == NULL
)
2624 return DPERR_INVALIDPLAYER
;
2627 /* How much buffer is required? */
2628 if( dwFlags
& DPSET_LOCAL
)
2630 dwRequiredBufferSize
= lpPList
->lpPData
->dwLocalDataSize
;
2631 lpCopyDataFrom
= lpPList
->lpPData
->lpLocalData
;
2635 dwRequiredBufferSize
= lpPList
->lpPData
->dwRemoteDataSize
;
2636 lpCopyDataFrom
= lpPList
->lpPData
->lpRemoteData
;
2639 /* Is the user requesting to know how big a buffer is required? */
2640 if( ( lpData
== NULL
) ||
2641 ( *lpdwDataSize
< dwRequiredBufferSize
)
2644 *lpdwDataSize
= dwRequiredBufferSize
;
2645 return DPERR_BUFFERTOOSMALL
;
2648 CopyMemory( lpData
, lpCopyDataFrom
, dwRequiredBufferSize
);
2653 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2654 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPVOID lpData
,
2655 LPDWORD lpdwDataSize
, DWORD dwFlags
)
2657 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2658 return DP_IF_GetPlayerData( This
, idPlayer
, lpData
, lpdwDataSize
,
2662 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2663 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPVOID lpData
,
2664 LPDWORD lpdwDataSize
, DWORD dwFlags
)
2666 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2667 return DP_IF_GetPlayerData( This
, idPlayer
, lpData
, lpdwDataSize
,
2671 static HRESULT WINAPI DP_IF_GetPlayerName
2672 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPVOID lpData
,
2673 LPDWORD lpdwDataSize
, BOOL bAnsi
)
2675 lpPlayerList lpPList
;
2676 LPDPNAME lpName
= (LPDPNAME
)lpData
;
2677 DWORD dwRequiredDataSize
;
2679 FIXME( "(%p)->(0x%08x,%p,%p,%u): ANSI\n",
2680 This
, idPlayer
, lpData
, lpdwDataSize
, bAnsi
);
2682 if( ( lpPList
= DP_FindPlayer( This
, idPlayer
) ) == NULL
)
2684 return DPERR_INVALIDPLAYER
;
2687 dwRequiredDataSize
= lpPList
->lpPData
->name
.dwSize
;
2689 if( lpPList
->lpPData
->name
.u1
.lpszShortNameA
)
2691 dwRequiredDataSize
+= strlen( lpPList
->lpPData
->name
.u1
.lpszShortNameA
) + 1;
2694 if( lpPList
->lpPData
->name
.u2
.lpszLongNameA
)
2696 dwRequiredDataSize
+= strlen( lpPList
->lpPData
->name
.u2
.lpszLongNameA
) + 1;
2699 if( ( lpData
== NULL
) ||
2700 ( *lpdwDataSize
< dwRequiredDataSize
)
2703 *lpdwDataSize
= dwRequiredDataSize
;
2704 return DPERR_BUFFERTOOSMALL
;
2707 /* Copy the structure */
2708 CopyMemory( lpName
, &lpPList
->lpPData
->name
, lpPList
->lpPData
->name
.dwSize
);
2710 if( lpPList
->lpPData
->name
.u1
.lpszShortNameA
)
2712 strcpy( ((char*)lpName
)+lpPList
->lpPData
->name
.dwSize
,
2713 lpPList
->lpPData
->name
.u1
.lpszShortNameA
);
2717 lpName
->u1
.lpszShortNameA
= NULL
;
2720 if( lpPList
->lpPData
->name
.u1
.lpszShortNameA
)
2722 strcpy( ((char*)lpName
)+lpPList
->lpPData
->name
.dwSize
,
2723 lpPList
->lpPData
->name
.u2
.lpszLongNameA
);
2727 lpName
->u2
.lpszLongNameA
= NULL
;
2733 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2734 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPVOID lpData
,
2735 LPDWORD lpdwDataSize
)
2737 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2738 return DP_IF_GetPlayerName( This
, idPlayer
, lpData
, lpdwDataSize
, TRUE
);
2741 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2742 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPVOID lpData
,
2743 LPDWORD lpdwDataSize
)
2745 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2746 return DP_IF_GetPlayerName( This
, idPlayer
, lpData
, lpdwDataSize
, FALSE
);
2749 static HRESULT WINAPI DP_GetSessionDesc
2750 ( IDirectPlay2Impl
* This
, LPVOID lpData
, LPDWORD lpdwDataSize
,
2753 DWORD dwRequiredSize
;
2755 TRACE( "(%p)->(%p,%p,%u)\n", This
, lpData
, lpdwDataSize
, bAnsi
);
2757 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
2759 return DPERR_UNINITIALIZED
;
2762 if( ( lpData
== NULL
) && ( lpdwDataSize
== NULL
) )
2764 return DPERR_INVALIDPARAMS
;
2767 /* FIXME: Get from This->dp2->lpSessionDesc */
2768 dwRequiredSize
= DP_CalcSessionDescSize( This
->dp2
->lpSessionDesc
, bAnsi
);
2770 if ( ( lpData
== NULL
) ||
2771 ( *lpdwDataSize
< dwRequiredSize
)
2774 *lpdwDataSize
= dwRequiredSize
;
2775 return DPERR_BUFFERTOOSMALL
;
2778 DP_CopySessionDesc( lpData
, This
->dp2
->lpSessionDesc
, bAnsi
);
2783 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
2784 ( LPDIRECTPLAY2A iface
, LPVOID lpData
, LPDWORD lpdwDataSize
)
2786 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2787 return DP_GetSessionDesc( This
, lpData
, lpdwDataSize
, TRUE
);
2790 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
2791 ( LPDIRECTPLAY2 iface
, LPVOID lpData
, LPDWORD lpdwDataSize
)
2793 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2794 return DP_GetSessionDesc( This
, lpData
, lpdwDataSize
, TRUE
);
2797 /* Intended only for COM compatibility. Always returns an error. */
2798 static HRESULT WINAPI DirectPlay2AImpl_Initialize
2799 ( LPDIRECTPLAY2A iface
, LPGUID lpGUID
)
2801 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2802 TRACE("(%p)->(%p): stub\n", This
, lpGUID
);
2803 return DPERR_ALREADYINITIALIZED
;
2806 /* Intended only for COM compatibility. Always returns an error. */
2807 static HRESULT WINAPI DirectPlay2WImpl_Initialize
2808 ( LPDIRECTPLAY2 iface
, LPGUID lpGUID
)
2810 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2811 TRACE("(%p)->(%p): stub\n", This
, lpGUID
);
2812 return DPERR_ALREADYINITIALIZED
;
2816 static HRESULT WINAPI DP_SecureOpen
2817 ( IDirectPlay2Impl
* This
, LPCDPSESSIONDESC2 lpsd
, DWORD dwFlags
,
2818 LPCDPSECURITYDESC lpSecurity
, LPCDPCREDENTIALS lpCredentials
,
2823 FIXME( "(%p)->(%p,0x%08x,%p,%p): partial stub\n",
2824 This
, lpsd
, dwFlags
, lpSecurity
, lpCredentials
);
2826 if( This
->dp2
->bConnectionOpen
)
2828 TRACE( ": rejecting already open connection.\n" );
2829 return DPERR_ALREADYINITIALIZED
;
2832 /* If we're enumerating, kill the thread */
2833 DP_KillEnumSessionThread( This
);
2835 if( dwFlags
& DPOPEN_CREATE
)
2837 /* Rightoo - this computer is the host and the local computer needs to be
2838 the name server so that others can join this session */
2839 NS_SetLocalComputerAsNameServer( lpsd
, This
->dp2
->lpNameServerData
);
2841 This
->dp2
->bHostInterface
= TRUE
;
2843 hr
= DP_SetSessionDesc( This
, lpsd
, 0, TRUE
, bAnsi
);
2846 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr
) );
2851 /* Invoke the conditional callback for the service provider */
2852 if( This
->dp2
->spData
.lpCB
->Open
)
2856 FIXME( "Not all data fields are correct. Need new parameter\n" );
2858 data
.bCreate
= (dwFlags
& DPOPEN_CREATE
) ? TRUE
: FALSE
;
2859 data
.lpSPMessageHeader
= (dwFlags
& DPOPEN_CREATE
) ? NULL
2860 : NS_GetNSAddr( This
->dp2
->lpNameServerData
);
2861 data
.lpISP
= This
->dp2
->spData
.lpISP
;
2862 data
.bReturnStatus
= (dwFlags
& DPOPEN_RETURNSTATUS
) ? TRUE
: FALSE
;
2863 data
.dwOpenFlags
= dwFlags
;
2864 data
.dwSessionFlags
= This
->dp2
->lpSessionDesc
->dwFlags
;
2866 hr
= (*This
->dp2
->spData
.lpCB
->Open
)(&data
);
2869 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr
) );
2875 /* Create the system group of which everything is a part of */
2876 DPID systemGroup
= DPID_SYSTEM_GROUP
;
2878 hr
= DP_IF_CreateGroup( This
, NULL
, &systemGroup
, NULL
,
2883 if( dwFlags
& DPOPEN_JOIN
)
2885 DPID dpidServerId
= DPID_UNKNOWN
;
2887 /* Create the server player for this interface. This way we can receive
2888 * messages for this session.
2890 /* FIXME: I suppose that we should be setting an event for a receive
2891 * type of thing. That way the messaging thread could know to wake
2892 * up. DPlay would then trigger the hEvent for the player the
2893 * message is directed to.
2895 hr
= DP_IF_CreatePlayer( This
, NULL
, &dpidServerId
, NULL
, 0, NULL
,
2897 DPPLAYER_SERVERPLAYER
| DPPLAYER_LOCAL
, bAnsi
);
2900 else if( dwFlags
& DPOPEN_CREATE
)
2902 DPID dpidNameServerId
= DPID_NAME_SERVER
;
2904 hr
= DP_IF_CreatePlayer( This
, NULL
, &dpidNameServerId
, NULL
, 0, NULL
,
2905 0, DPPLAYER_SERVERPLAYER
, bAnsi
);
2910 ERR( "Couldn't create name server/system player: %s\n",
2911 DPLAYX_HresultToString(hr
) );
2917 static HRESULT WINAPI DirectPlay2AImpl_Open
2918 ( LPDIRECTPLAY2A iface
, LPDPSESSIONDESC2 lpsd
, DWORD dwFlags
)
2920 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2921 TRACE("(%p)->(%p,0x%08x)\n", This
, lpsd
, dwFlags
);
2922 return DP_SecureOpen( This
, lpsd
, dwFlags
, NULL
, NULL
, TRUE
);
2925 static HRESULT WINAPI DirectPlay2WImpl_Open
2926 ( LPDIRECTPLAY2 iface
, LPDPSESSIONDESC2 lpsd
, DWORD dwFlags
)
2928 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2929 TRACE("(%p)->(%p,0x%08x)\n", This
, lpsd
, dwFlags
);
2930 return DP_SecureOpen( This
, lpsd
, dwFlags
, NULL
, NULL
, FALSE
);
2933 static HRESULT WINAPI DP_IF_Receive
2934 ( IDirectPlay2Impl
* This
, LPDPID lpidFrom
, LPDPID lpidTo
,
2935 DWORD dwFlags
, LPVOID lpData
, LPDWORD lpdwDataSize
, BOOL bAnsi
)
2937 LPDPMSG lpMsg
= NULL
;
2939 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p,%u): stub\n",
2940 This
, lpidFrom
, lpidTo
, dwFlags
, lpData
, lpdwDataSize
, bAnsi
);
2942 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
2944 return DPERR_UNINITIALIZED
;
2949 dwFlags
= DPRECEIVE_ALL
;
2952 /* If the lpData is NULL, we must be peeking the message */
2953 if( ( lpData
== NULL
) &&
2954 !( dwFlags
& DPRECEIVE_PEEK
)
2957 return DPERR_INVALIDPARAMS
;
2960 if( dwFlags
& DPRECEIVE_ALL
)
2962 lpMsg
= This
->dp2
->receiveMsgs
.lpQHFirst
;
2964 if( !( dwFlags
& DPRECEIVE_PEEK
) )
2966 FIXME( "Remove from queue\n" );
2969 else if( ( dwFlags
& DPRECEIVE_TOPLAYER
) ||
2970 ( dwFlags
& DPRECEIVE_FROMPLAYER
)
2973 FIXME( "Find matching message 0x%08x\n", dwFlags
);
2977 ERR( "Hmmm..dwFlags 0x%08x\n", dwFlags
);
2982 return DPERR_NOMESSAGES
;
2985 /* Copy into the provided buffer */
2986 CopyMemory( lpData
, lpMsg
->msg
, *lpdwDataSize
);
2991 static HRESULT WINAPI DirectPlay2AImpl_Receive
2992 ( LPDIRECTPLAY2A iface
, LPDPID lpidFrom
, LPDPID lpidTo
,
2993 DWORD dwFlags
, LPVOID lpData
, LPDWORD lpdwDataSize
)
2995 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2996 return DP_IF_Receive( This
, lpidFrom
, lpidTo
, dwFlags
,
2997 lpData
, lpdwDataSize
, TRUE
);
3000 static HRESULT WINAPI DirectPlay2WImpl_Receive
3001 ( LPDIRECTPLAY2 iface
, LPDPID lpidFrom
, LPDPID lpidTo
,
3002 DWORD dwFlags
, LPVOID lpData
, LPDWORD lpdwDataSize
)
3004 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3005 return DP_IF_Receive( This
, lpidFrom
, lpidTo
, dwFlags
,
3006 lpData
, lpdwDataSize
, FALSE
);
3009 static HRESULT WINAPI DirectPlay2AImpl_Send
3010 ( LPDIRECTPLAY2A iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
, LPVOID lpData
, DWORD dwDataSize
)
3012 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3013 return DP_SendEx( This
, idFrom
, idTo
, dwFlags
, lpData
, dwDataSize
,
3014 0, 0, NULL
, NULL
, TRUE
);
3017 static HRESULT WINAPI DirectPlay2WImpl_Send
3018 ( LPDIRECTPLAY2 iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
, LPVOID lpData
, DWORD dwDataSize
)
3020 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3021 return DP_SendEx( This
, idFrom
, idTo
, dwFlags
, lpData
, dwDataSize
,
3022 0, 0, NULL
, NULL
, FALSE
);
3025 static HRESULT WINAPI DP_IF_SetGroupData
3026 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPVOID lpData
,
3027 DWORD dwDataSize
, DWORD dwFlags
, BOOL bAnsi
)
3029 lpGroupData lpGData
;
3031 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3032 This
, idGroup
, lpData
, dwDataSize
, dwFlags
, bAnsi
);
3034 /* Parameter check */
3035 if( ( lpData
== NULL
) &&
3039 return DPERR_INVALIDPARAMS
;
3042 /* Find the pointer to the data for this player */
3043 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
3045 return DPERR_INVALIDOBJECT
;
3048 if( !(dwFlags
& DPSET_LOCAL
) )
3050 FIXME( "Was this group created by this interface?\n" );
3051 /* FIXME: If this is a remote update need to allow it but not
3056 DP_SetGroupData( lpGData
, dwFlags
, lpData
, dwDataSize
);
3058 /* FIXME: Only send a message if this group is local to the session otherwise
3059 * it will have been rejected above
3061 if( !(dwFlags
& DPSET_LOCAL
) )
3063 FIXME( "Send msg?\n" );
3069 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
3070 ( LPDIRECTPLAY2A iface
, DPID idGroup
, LPVOID lpData
,
3071 DWORD dwDataSize
, DWORD dwFlags
)
3073 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3074 return DP_IF_SetGroupData( This
, idGroup
, lpData
, dwDataSize
, dwFlags
, TRUE
);
3077 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
3078 ( LPDIRECTPLAY2 iface
, DPID idGroup
, LPVOID lpData
,
3079 DWORD dwDataSize
, DWORD dwFlags
)
3081 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3082 return DP_IF_SetGroupData( This
, idGroup
, lpData
, dwDataSize
, dwFlags
, FALSE
);
3085 static HRESULT WINAPI DP_IF_SetGroupName
3086 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPDPNAME lpGroupName
,
3087 DWORD dwFlags
, BOOL bAnsi
)
3089 lpGroupData lpGData
;
3091 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n", This
, idGroup
,
3092 lpGroupName
, dwFlags
, bAnsi
);
3094 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
3096 return DPERR_INVALIDGROUP
;
3099 DP_CopyDPNAMEStruct( &lpGData
->name
, lpGroupName
, bAnsi
);
3101 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3102 FIXME( "Message not sent and dwFlags ignored\n" );
3107 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
3108 ( LPDIRECTPLAY2A iface
, DPID idGroup
, LPDPNAME lpGroupName
,
3111 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3112 return DP_IF_SetGroupName( This
, idGroup
, lpGroupName
, dwFlags
, TRUE
);
3115 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
3116 ( LPDIRECTPLAY2 iface
, DPID idGroup
, LPDPNAME lpGroupName
,
3119 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3120 return DP_IF_SetGroupName( This
, idGroup
, lpGroupName
, dwFlags
, FALSE
);
3123 static HRESULT WINAPI DP_IF_SetPlayerData
3124 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPVOID lpData
,
3125 DWORD dwDataSize
, DWORD dwFlags
, BOOL bAnsi
)
3127 lpPlayerList lpPList
;
3129 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3130 This
, idPlayer
, lpData
, dwDataSize
, dwFlags
, bAnsi
);
3132 /* Parameter check */
3133 if( ( lpData
== NULL
) &&
3137 return DPERR_INVALIDPARAMS
;
3140 /* Find the pointer to the data for this player */
3141 if( ( lpPList
= DP_FindPlayer( This
, idPlayer
) ) == NULL
)
3143 return DPERR_INVALIDPLAYER
;
3146 if( !(dwFlags
& DPSET_LOCAL
) )
3148 FIXME( "Was this group created by this interface?\n" );
3149 /* FIXME: If this is a remote update need to allow it but not
3154 DP_SetPlayerData( lpPList
->lpPData
, dwFlags
, lpData
, dwDataSize
);
3156 if( !(dwFlags
& DPSET_LOCAL
) )
3158 FIXME( "Send msg?\n" );
3164 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3165 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPVOID lpData
,
3166 DWORD dwDataSize
, DWORD dwFlags
)
3168 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3169 return DP_IF_SetPlayerData( This
, idPlayer
, lpData
, dwDataSize
,
3173 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3174 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPVOID lpData
,
3175 DWORD dwDataSize
, DWORD dwFlags
)
3177 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3178 return DP_IF_SetPlayerData( This
, idPlayer
, lpData
, dwDataSize
,
3182 static HRESULT WINAPI DP_IF_SetPlayerName
3183 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPDPNAME lpPlayerName
,
3184 DWORD dwFlags
, BOOL bAnsi
)
3186 lpPlayerList lpPList
;
3188 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n",
3189 This
, idPlayer
, lpPlayerName
, dwFlags
, bAnsi
);
3191 if( ( lpPList
= DP_FindPlayer( This
, idPlayer
) ) == NULL
)
3193 return DPERR_INVALIDGROUP
;
3196 DP_CopyDPNAMEStruct( &lpPList
->lpPData
->name
, lpPlayerName
, bAnsi
);
3198 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3199 FIXME( "Message not sent and dwFlags ignored\n" );
3204 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3205 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPDPNAME lpPlayerName
,
3208 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3209 return DP_IF_SetPlayerName( This
, idPlayer
, lpPlayerName
, dwFlags
, TRUE
);
3212 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3213 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPDPNAME lpPlayerName
,
3216 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3217 return DP_IF_SetPlayerName( This
, idPlayer
, lpPlayerName
, dwFlags
, FALSE
);
3220 static HRESULT WINAPI DP_SetSessionDesc
3221 ( IDirectPlay2Impl
* This
, LPCDPSESSIONDESC2 lpSessDesc
,
3222 DWORD dwFlags
, BOOL bInitial
, BOOL bAnsi
)
3224 DWORD dwRequiredSize
;
3225 LPDPSESSIONDESC2 lpTempSessDesc
;
3227 TRACE( "(%p)->(%p,0x%08x,%u,%u)\n",
3228 This
, lpSessDesc
, dwFlags
, bInitial
, bAnsi
);
3230 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
3232 return DPERR_UNINITIALIZED
;
3237 return DPERR_INVALIDPARAMS
;
3240 /* Only the host is allowed to update the session desc */
3241 if( !This
->dp2
->bHostInterface
)
3243 return DPERR_ACCESSDENIED
;
3246 /* FIXME: Copy into This->dp2->lpSessionDesc */
3247 dwRequiredSize
= DP_CalcSessionDescSize( lpSessDesc
, bAnsi
);
3248 lpTempSessDesc
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, dwRequiredSize
);
3250 if( lpTempSessDesc
== NULL
)
3252 return DPERR_OUTOFMEMORY
;
3256 HeapFree( GetProcessHeap(), 0, This
->dp2
->lpSessionDesc
);
3258 This
->dp2
->lpSessionDesc
= lpTempSessDesc
;
3260 DP_CopySessionDesc( This
->dp2
->lpSessionDesc
, lpSessDesc
, bAnsi
);
3263 /*Initializing session GUID*/
3264 CoCreateGuid( &(This
->dp2
->lpSessionDesc
->guidInstance
) );
3266 /* If this is an external invocation of the interface, we should be
3267 * letting everyone know that things have changed. Otherwise this is
3268 * just an initialization and it doesn't need to be propagated.
3272 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3278 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3279 ( LPDIRECTPLAY2A iface
, LPDPSESSIONDESC2 lpSessDesc
, DWORD dwFlags
)
3281 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3282 return DP_SetSessionDesc( This
, lpSessDesc
, dwFlags
, FALSE
, TRUE
);
3285 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3286 ( LPDIRECTPLAY2 iface
, LPDPSESSIONDESC2 lpSessDesc
, DWORD dwFlags
)
3288 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3289 return DP_SetSessionDesc( This
, lpSessDesc
, dwFlags
, FALSE
, TRUE
);
3292 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3293 DWORD
DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc
, BOOL bAnsi
)
3297 if( lpSessDesc
== NULL
)
3299 /* Hmmm..don't need any size? */
3300 ERR( "NULL lpSessDesc\n" );
3304 dwSize
+= sizeof( *lpSessDesc
);
3308 if( lpSessDesc
->u1
.lpszSessionNameA
)
3310 dwSize
+= lstrlenA( lpSessDesc
->u1
.lpszSessionNameA
) + 1;
3313 if( lpSessDesc
->u2
.lpszPasswordA
)
3315 dwSize
+= lstrlenA( lpSessDesc
->u2
.lpszPasswordA
) + 1;
3320 if( lpSessDesc
->u1
.lpszSessionName
)
3322 dwSize
+= sizeof( WCHAR
) *
3323 ( lstrlenW( lpSessDesc
->u1
.lpszSessionName
) + 1 );
3326 if( lpSessDesc
->u2
.lpszPassword
)
3328 dwSize
+= sizeof( WCHAR
) *
3329 ( lstrlenW( lpSessDesc
->u2
.lpszPassword
) + 1 );
3336 /* Assumes that contiguous buffers are already allocated. */
3337 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest
,
3338 LPCDPSESSIONDESC2 lpSessionSrc
, BOOL bAnsi
)
3340 BYTE
* lpStartOfFreeSpace
;
3342 if( lpSessionDest
== NULL
)
3344 ERR( "NULL lpSessionDest\n" );
3348 CopyMemory( lpSessionDest
, lpSessionSrc
, sizeof( *lpSessionSrc
) );
3350 lpStartOfFreeSpace
= ((BYTE
*)lpSessionDest
) + sizeof( *lpSessionSrc
);
3354 if( lpSessionSrc
->u1
.lpszSessionNameA
)
3356 lstrcpyA( (LPSTR
)lpStartOfFreeSpace
,
3357 lpSessionDest
->u1
.lpszSessionNameA
);
3358 lpSessionDest
->u1
.lpszSessionNameA
= (LPSTR
)lpStartOfFreeSpace
;
3359 lpStartOfFreeSpace
+=
3360 lstrlenA( lpSessionDest
->u1
.lpszSessionNameA
) + 1;
3363 if( lpSessionSrc
->u2
.lpszPasswordA
)
3365 lstrcpyA( (LPSTR
)lpStartOfFreeSpace
,
3366 lpSessionDest
->u2
.lpszPasswordA
);
3367 lpSessionDest
->u2
.lpszPasswordA
= (LPSTR
)lpStartOfFreeSpace
;
3368 lpStartOfFreeSpace
+=
3369 lstrlenA( lpSessionDest
->u2
.lpszPasswordA
) + 1;
3374 if( lpSessionSrc
->u1
.lpszSessionName
)
3376 lstrcpyW( (LPWSTR
)lpStartOfFreeSpace
,
3377 lpSessionDest
->u1
.lpszSessionName
);
3378 lpSessionDest
->u1
.lpszSessionName
= (LPWSTR
)lpStartOfFreeSpace
;
3379 lpStartOfFreeSpace
+= sizeof(WCHAR
) *
3380 ( lstrlenW( lpSessionDest
->u1
.lpszSessionName
) + 1 );
3383 if( lpSessionSrc
->u2
.lpszPassword
)
3385 lstrcpyW( (LPWSTR
)lpStartOfFreeSpace
,
3386 lpSessionDest
->u2
.lpszPassword
);
3387 lpSessionDest
->u2
.lpszPassword
= (LPWSTR
)lpStartOfFreeSpace
;
3388 lpStartOfFreeSpace
+= sizeof(WCHAR
) *
3389 ( lstrlenW( lpSessionDest
->u2
.lpszPassword
) + 1 );
3395 static HRESULT WINAPI DP_IF_AddGroupToGroup
3396 ( IDirectPlay3Impl
* This
, DPID idParentGroup
, DPID idGroup
)
3398 lpGroupData lpGData
;
3399 lpGroupList lpNewGList
;
3401 TRACE( "(%p)->(0x%08x,0x%08x)\n", This
, idParentGroup
, idGroup
);
3403 if( DP_FindAnyGroup( (IDirectPlay2AImpl
*)This
, idParentGroup
) == NULL
)
3405 return DPERR_INVALIDGROUP
;
3408 if( ( lpGData
= DP_FindAnyGroup( (IDirectPlay2AImpl
*)This
, idGroup
) ) == NULL
)
3410 return DPERR_INVALIDGROUP
;
3413 /* Create a player list (ie "shortcut" ) */
3414 lpNewGList
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpNewGList
) );
3415 if( lpNewGList
== NULL
)
3417 return DPERR_CANTADDPLAYER
;
3420 /* Add the shortcut */
3422 lpNewGList
->lpGData
= lpGData
;
3424 /* Add the player to the list of players for this group */
3425 DPQ_INSERT( lpGData
->groups
, lpNewGList
, groups
);
3427 /* Send a ADDGROUPTOGROUP message */
3428 FIXME( "Not sending message\n" );
3433 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3434 ( LPDIRECTPLAY3A iface
, DPID idParentGroup
, DPID idGroup
)
3436 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3437 return DP_IF_AddGroupToGroup( This
, idParentGroup
, idGroup
);
3440 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3441 ( LPDIRECTPLAY3 iface
, DPID idParentGroup
, DPID idGroup
)
3443 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3444 return DP_IF_AddGroupToGroup( This
, idParentGroup
, idGroup
);
3447 static HRESULT WINAPI DP_IF_CreateGroupInGroup
3448 ( IDirectPlay3Impl
* This
, LPVOID lpMsgHdr
, DPID idParentGroup
,
3449 LPDPID lpidGroup
, LPDPNAME lpGroupName
, LPVOID lpData
,
3450 DWORD dwDataSize
, DWORD dwFlags
, BOOL bAnsi
)
3452 lpGroupData lpGParentData
;
3453 lpGroupList lpGList
;
3454 lpGroupData lpGData
;
3456 TRACE( "(%p)->(0x%08x,%p,%p,%p,0x%08x,0x%08x,%u)\n",
3457 This
, idParentGroup
, lpidGroup
, lpGroupName
, lpData
,
3458 dwDataSize
, dwFlags
, bAnsi
);
3460 /* Verify that the specified parent is valid */
3461 if( ( lpGParentData
= DP_FindAnyGroup( (IDirectPlay2AImpl
*)This
,
3462 idParentGroup
) ) == NULL
3465 return DPERR_INVALIDGROUP
;
3468 lpGData
= DP_CreateGroup( (IDirectPlay2AImpl
*)This
, lpidGroup
, lpGroupName
,
3469 dwFlags
, idParentGroup
, bAnsi
);
3471 if( lpGData
== NULL
)
3473 return DPERR_CANTADDPLAYER
; /* yes player not group */
3476 /* Something else is referencing this data */
3479 DP_SetGroupData( lpGData
, DPSET_REMOTE
, lpData
, dwDataSize
);
3481 /* The list has now been inserted into the interface group list. We now
3482 need to put a "shortcut" to this group in the parent group */
3483 lpGList
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpGList
) );
3484 if( lpGList
== NULL
)
3486 FIXME( "Memory leak\n" );
3487 return DPERR_CANTADDPLAYER
; /* yes player not group */
3490 lpGList
->lpGData
= lpGData
;
3492 DPQ_INSERT( lpGParentData
->groups
, lpGList
, groups
);
3494 /* Let the SP know that we've created this group */
3495 if( This
->dp2
->spData
.lpCB
->CreateGroup
)
3497 DPSP_CREATEGROUPDATA data
;
3499 TRACE( "Calling SP CreateGroup\n" );
3501 data
.idGroup
= *lpidGroup
;
3502 data
.dwFlags
= dwFlags
;
3503 data
.lpSPMessageHeader
= lpMsgHdr
;
3504 data
.lpISP
= This
->dp2
->spData
.lpISP
;
3506 (*This
->dp2
->spData
.lpCB
->CreateGroup
)( &data
);
3509 /* Inform all other peers of the creation of a new group. If there are
3510 * no peers keep this quiet.
3512 if( This
->dp2
->lpSessionDesc
&&
3513 ( This
->dp2
->lpSessionDesc
->dwFlags
& DPSESSION_MULTICASTSERVER
) )
3515 DPMSG_CREATEPLAYERORGROUP msg
;
3517 msg
.dwType
= DPSYS_CREATEPLAYERORGROUP
;
3518 msg
.dwPlayerType
= DPPLAYERTYPE_GROUP
;
3519 msg
.dpId
= *lpidGroup
;
3520 msg
.dwCurrentPlayers
= idParentGroup
; /* FIXME: Incorrect? */
3521 msg
.lpData
= lpData
;
3522 msg
.dwDataSize
= dwDataSize
;
3523 msg
.dpnName
= *lpGroupName
;
3525 /* FIXME: Correct to just use send effectively? */
3526 /* FIXME: Should size include data w/ message or just message "header" */
3527 /* FIXME: Check return code */
3528 DP_SendEx( (IDirectPlay2Impl
*)This
,
3529 DPID_SERVERPLAYER
, DPID_ALLPLAYERS
, 0, &msg
, sizeof( msg
),
3530 0, 0, NULL
, NULL
, bAnsi
);
3536 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3537 ( LPDIRECTPLAY3A iface
, DPID idParentGroup
, LPDPID lpidGroup
,
3538 LPDPNAME lpGroupName
, LPVOID lpData
, DWORD dwDataSize
,
3541 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3543 *lpidGroup
= DPID_UNKNOWN
;
3545 return DP_IF_CreateGroupInGroup( This
, NULL
, idParentGroup
, lpidGroup
,
3546 lpGroupName
, lpData
, dwDataSize
, dwFlags
,
3550 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3551 ( LPDIRECTPLAY3 iface
, DPID idParentGroup
, LPDPID lpidGroup
,
3552 LPDPNAME lpGroupName
, LPVOID lpData
, DWORD dwDataSize
,
3555 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3557 *lpidGroup
= DPID_UNKNOWN
;
3559 return DP_IF_CreateGroupInGroup( This
, NULL
, idParentGroup
, lpidGroup
,
3560 lpGroupName
, lpData
, dwDataSize
,
3564 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
3565 ( IDirectPlay3Impl
* This
, DPID idParentGroup
, DPID idGroup
)
3567 lpGroupList lpGList
;
3568 lpGroupData lpGParentData
;
3570 TRACE("(%p)->(0x%08x,0x%08x)\n", This
, idParentGroup
, idGroup
);
3572 /* Is the parent group valid? */
3573 if( ( lpGParentData
= DP_FindAnyGroup( (IDirectPlay2AImpl
*)This
, idParentGroup
) ) == NULL
)
3575 return DPERR_INVALIDGROUP
;
3578 /* Remove the group from the parent group queue */
3579 DPQ_REMOVE_ENTRY( lpGParentData
->groups
, groups
, lpGData
->dpid
, ==, idGroup
, lpGList
);
3581 if( lpGList
== NULL
)
3583 return DPERR_INVALIDGROUP
;
3586 /* Decrement the ref count */
3587 lpGList
->lpGData
->uRef
--;
3589 /* Free up the list item */
3590 HeapFree( GetProcessHeap(), 0, lpGList
);
3592 /* Should send a DELETEGROUPFROMGROUP message */
3593 FIXME( "message not sent\n" );
3598 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3599 ( LPDIRECTPLAY3 iface
, DPID idParentGroup
, DPID idGroup
)
3601 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3602 return DP_IF_DeleteGroupFromGroup( This
, idParentGroup
, idGroup
);
3605 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3606 ( LPDIRECTPLAY3 iface
, DPID idParentGroup
, DPID idGroup
)
3608 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3609 return DP_IF_DeleteGroupFromGroup( This
, idParentGroup
, idGroup
);
3613 BOOL WINAPI
DP_BuildSPCompoundAddr( LPGUID lpcSpGuid
, LPVOID
* lplpAddrBuf
,
3614 LPDWORD lpdwBufSize
)
3616 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress
;
3619 dpCompoundAddress
.dwDataSize
= sizeof( GUID
);
3620 dpCompoundAddress
.guidDataType
= DPAID_ServiceProvider
;
3621 dpCompoundAddress
.lpData
= lpcSpGuid
;
3623 *lplpAddrBuf
= NULL
;
3626 hr
= DPL_CreateCompoundAddress( &dpCompoundAddress
, 1, *lplpAddrBuf
,
3627 lpdwBufSize
, TRUE
);
3629 if( hr
!= DPERR_BUFFERTOOSMALL
)
3631 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr
) );
3635 /* Now allocate the buffer */
3636 *lplpAddrBuf
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
3639 hr
= DPL_CreateCompoundAddress( &dpCompoundAddress
, 1, *lplpAddrBuf
,
3640 lpdwBufSize
, TRUE
);
3643 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr
) );
3650 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
3651 ( LPDIRECTPLAY3A iface
, LPCGUID lpguidApplication
, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback
, LPVOID lpContext
, DWORD dwFlags
)
3653 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3654 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This
, lpguidApplication
, lpEnumCallback
, lpContext
, dwFlags
);
3656 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
3659 dwFlags
= DPCONNECTION_DIRECTPLAY
;
3662 if( ! ( ( dwFlags
& DPCONNECTION_DIRECTPLAY
) ||
3663 ( dwFlags
& DPCONNECTION_DIRECTPLAYLOBBY
) )
3666 return DPERR_INVALIDFLAGS
;
3669 if( !lpEnumCallback
)
3671 return DPERR_INVALIDPARAMS
;
3674 /* Enumerate DirectPlay service providers */
3675 if( dwFlags
& DPCONNECTION_DIRECTPLAY
)
3678 LPCSTR searchSubKey
= "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3679 LPCSTR guidDataSubKey
= "Guid";
3680 char subKeyName
[51];
3681 DWORD dwIndex
, sizeOfSubKeyName
=50;
3684 /* Need to loop over the service providers in the registry */
3685 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE
, searchSubKey
,
3686 0, KEY_READ
, &hkResult
) != ERROR_SUCCESS
)
3688 /* Hmmm. Does this mean that there are no service providers? */
3689 ERR(": no service providers?\n");
3694 /* Traverse all the service providers we have available */
3696 RegEnumKeyExA( hkResult
, dwIndex
, subKeyName
, &sizeOfSubKeyName
,
3697 NULL
, NULL
, NULL
, &filetime
) != ERROR_NO_MORE_ITEMS
;
3698 ++dwIndex
, sizeOfSubKeyName
=51 )
3701 HKEY hkServiceProvider
;
3702 GUID serviceProviderGUID
;
3703 DWORD returnTypeGUID
, sizeOfReturnBuffer
= 50;
3704 char returnBuffer
[51];
3709 LPVOID lpAddressBuffer
= NULL
;
3710 DWORD dwAddressBufferSize
= 0;
3712 TRACE(" this time through: %s\n", subKeyName
);
3714 /* Get a handle for this particular service provider */
3715 if( RegOpenKeyExA( hkResult
, subKeyName
, 0, KEY_READ
,
3716 &hkServiceProvider
) != ERROR_SUCCESS
)
3718 ERR(": what the heck is going on?\n" );
3722 if( RegQueryValueExA( hkServiceProvider
, guidDataSubKey
,
3723 NULL
, &returnTypeGUID
, (LPBYTE
)returnBuffer
,
3724 &sizeOfReturnBuffer
) != ERROR_SUCCESS
)
3726 ERR(": missing GUID registry data members\n" );
3727 RegCloseKey(hkServiceProvider
);
3730 RegCloseKey(hkServiceProvider
);
3732 /* FIXME: Check return types to ensure we're interpreting data right */
3733 MultiByteToWideChar( CP_ACP
, 0, returnBuffer
, -1, buff
, sizeof(buff
)/sizeof(WCHAR
) );
3734 CLSIDFromString( buff
, &serviceProviderGUID
);
3735 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3737 /* Fill in the DPNAME struct for the service provider */
3738 dpName
.dwSize
= sizeof( dpName
);
3740 dpName
.u1
.lpszShortNameA
= subKeyName
;
3741 dpName
.u2
.lpszLongNameA
= NULL
;
3743 /* Create the compound address for the service provider.
3744 * NOTE: This is a gruesome architectural scar right now. DP
3745 * uses DPL and DPL uses DP. Nasty stuff. This may be why the
3746 * native dll just gets around this little bit by allocating an
3747 * 80 byte buffer which isn't even filled with a valid compound
3748 * address. Oh well. Creating a proper compound address is the
3749 * way to go anyways despite this method taking slightly more
3750 * heap space and realtime :) */
3752 bBuildPass
= DP_BuildSPCompoundAddr( &serviceProviderGUID
,
3754 &dwAddressBufferSize
);
3757 ERR( "Can't build compound addr\n" );
3758 return DPERR_GENERIC
;
3761 /* The enumeration will return FALSE if we are not to continue */
3762 if( !lpEnumCallback( &serviceProviderGUID
, lpAddressBuffer
, dwAddressBufferSize
,
3763 &dpName
, dwFlags
, lpContext
) )
3770 /* Enumerate DirectPlayLobby service providers */
3771 if( dwFlags
& DPCONNECTION_DIRECTPLAYLOBBY
)
3774 LPCSTR searchSubKey
= "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3775 LPCSTR guidDataSubKey
= "Guid";
3776 char subKeyName
[51];
3777 DWORD dwIndex
, sizeOfSubKeyName
=50;
3780 /* Need to loop over the service providers in the registry */
3781 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE
, searchSubKey
,
3782 0, KEY_READ
, &hkResult
) != ERROR_SUCCESS
)
3784 /* Hmmm. Does this mean that there are no service providers? */
3785 ERR(": no service providers?\n");
3790 /* Traverse all the lobby providers we have available */
3792 RegEnumKeyExA( hkResult
, dwIndex
, subKeyName
, &sizeOfSubKeyName
,
3793 NULL
, NULL
, NULL
, &filetime
) != ERROR_NO_MORE_ITEMS
;
3794 ++dwIndex
, sizeOfSubKeyName
=51 )
3797 HKEY hkServiceProvider
;
3798 GUID serviceProviderGUID
;
3799 DWORD returnTypeGUID
, sizeOfReturnBuffer
= 50;
3800 char returnBuffer
[51];
3805 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress
;
3806 LPVOID lpAddressBuffer
= NULL
;
3807 DWORD dwAddressBufferSize
= 0;
3809 TRACE(" this time through: %s\n", subKeyName
);
3811 /* Get a handle for this particular service provider */
3812 if( RegOpenKeyExA( hkResult
, subKeyName
, 0, KEY_READ
,
3813 &hkServiceProvider
) != ERROR_SUCCESS
)
3815 ERR(": what the heck is going on?\n" );
3819 if( RegQueryValueExA( hkServiceProvider
, guidDataSubKey
,
3820 NULL
, &returnTypeGUID
, (LPBYTE
)returnBuffer
,
3821 &sizeOfReturnBuffer
) != ERROR_SUCCESS
)
3823 ERR(": missing GUID registry data members\n" );
3824 RegCloseKey(hkServiceProvider
);
3827 RegCloseKey(hkServiceProvider
);
3829 /* FIXME: Check return types to ensure we're interpreting data right */
3830 MultiByteToWideChar( CP_ACP
, 0, returnBuffer
, -1, buff
, sizeof(buff
)/sizeof(WCHAR
) );
3831 CLSIDFromString( buff
, &serviceProviderGUID
);
3832 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3834 /* Fill in the DPNAME struct for the service provider */
3835 dpName
.dwSize
= sizeof( dpName
);
3837 dpName
.u1
.lpszShortNameA
= subKeyName
;
3838 dpName
.u2
.lpszLongNameA
= NULL
;
3840 /* Create the compound address for the service provider.
3841 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
3842 nast stuff. This may be why the native dll just gets around this little bit by
3843 allocating an 80 byte buffer which isn't even a filled with a valid compound
3844 address. Oh well. Creating a proper compound address is the way to go anyways
3845 despite this method taking slightly more heap space and realtime :) */
3847 dpCompoundAddress
.guidDataType
= DPAID_LobbyProvider
;
3848 dpCompoundAddress
.dwDataSize
= sizeof( GUID
);
3849 dpCompoundAddress
.lpData
= &serviceProviderGUID
;
3851 if( ( hr
= DPL_CreateCompoundAddress( &dpCompoundAddress
, 1, lpAddressBuffer
,
3852 &dwAddressBufferSize
, TRUE
) ) != DPERR_BUFFERTOOSMALL
)
3854 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr
) );
3858 /* Now allocate the buffer */
3859 lpAddressBuffer
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, dwAddressBufferSize
);
3861 if( ( hr
= DPL_CreateCompoundAddress( &dpCompoundAddress
, 1, lpAddressBuffer
,
3862 &dwAddressBufferSize
, TRUE
) ) != DP_OK
)
3864 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr
) );
3865 HeapFree( GetProcessHeap(), 0, lpAddressBuffer
);
3869 /* The enumeration will return FALSE if we are not to continue */
3870 if( !lpEnumCallback( &serviceProviderGUID
, lpAddressBuffer
, dwAddressBufferSize
,
3871 &dpName
, dwFlags
, lpContext
) )
3873 HeapFree( GetProcessHeap(), 0, lpAddressBuffer
);
3876 HeapFree( GetProcessHeap(), 0, lpAddressBuffer
);
3883 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
3884 ( LPDIRECTPLAY3 iface
, LPCGUID lpguidApplication
, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback
, LPVOID lpContext
, DWORD dwFlags
)
3886 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3887 FIXME("(%p)->(%p,%p,%p,0x%08x): stub\n", This
, lpguidApplication
, lpEnumCallback
, lpContext
, dwFlags
);
3891 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
3892 ( IDirectPlay3AImpl
* This
, DPID idGroup
, LPGUID lpguidInstance
,
3893 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
3894 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
)
3896 lpGroupList lpGList
;
3897 lpGroupData lpGData
;
3899 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
3900 This
, idGroup
, lpguidInstance
, lpEnumPlayersCallback2
,
3901 lpContext
, dwFlags
, bAnsi
);
3903 if( ( lpGData
= DP_FindAnyGroup( (IDirectPlay2AImpl
*)This
, idGroup
) ) == NULL
)
3905 return DPERR_INVALIDGROUP
;
3908 if( DPQ_IS_EMPTY( lpGData
->groups
) )
3913 lpGList
= DPQ_FIRST( lpGData
->groups
);
3917 /* FIXME: Should check dwFlags for match here */
3919 if( !(*lpEnumPlayersCallback2
)( lpGList
->lpGData
->dpid
, DPPLAYERTYPE_GROUP
,
3920 &lpGList
->lpGData
->name
, dwFlags
,
3923 return DP_OK
; /* User requested break */
3926 if( DPQ_IS_ENDOFLIST( lpGList
->groups
) )
3931 lpGList
= DPQ_NEXT( lpGList
->groups
);
3938 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
3939 ( LPDIRECTPLAY3A iface
, DPID idGroup
, LPGUID lpguidInstance
,
3940 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
, LPVOID lpContext
,
3943 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3944 return DP_IF_EnumGroupsInGroup( This
, idGroup
, lpguidInstance
,
3945 lpEnumPlayersCallback2
, lpContext
, dwFlags
,
3949 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
3950 ( LPDIRECTPLAY3A iface
, DPID idGroup
, LPGUID lpguidInstance
,
3951 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
, LPVOID lpContext
,
3954 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3955 return DP_IF_EnumGroupsInGroup( This
, idGroup
, lpguidInstance
,
3956 lpEnumPlayersCallback2
, lpContext
, dwFlags
,
3960 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
3961 ( LPDIRECTPLAY3A iface
, DWORD dwFlags
, DPID idGroup
, LPVOID lpData
, LPDWORD lpdwDataSize
)
3963 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3964 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This
, dwFlags
, idGroup
, lpData
, lpdwDataSize
);
3968 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
3969 ( LPDIRECTPLAY3 iface
, DWORD dwFlags
, DPID idGroup
, LPVOID lpData
, LPDWORD lpdwDataSize
)
3971 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3972 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This
, dwFlags
, idGroup
, lpData
, lpdwDataSize
);
3976 static BOOL CALLBACK
DP_GetSpLpGuidFromCompoundAddress(
3977 REFGUID guidDataType
,
3982 /* Looking for the GUID of the provider to load */
3983 if( ( IsEqualGUID( guidDataType
, &DPAID_ServiceProvider
) ) ||
3984 ( IsEqualGUID( guidDataType
, &DPAID_LobbyProvider
) )
3987 TRACE( "Found SP/LP (%s) %s (data size = 0x%08x)\n",
3988 debugstr_guid( guidDataType
), debugstr_guid( lpData
), dwDataSize
);
3990 if( dwDataSize
!= sizeof( GUID
) )
3992 ERR( "Invalid sp/lp guid size 0x%08x\n", dwDataSize
);
3995 memcpy( lpContext
, lpData
, dwDataSize
);
3997 /* There shouldn't be more than 1 GUID/compound address */
4001 /* Still waiting for what we want */
4006 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
4007 static HMODULE
DP_LoadSP( LPCGUID lpcGuid
, LPSPINITDATA lpSpData
, LPBOOL lpbIsDpSp
)
4010 LPCSTR spSubKey
= "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4011 LPCSTR lpSubKey
= "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
4012 LPCSTR guidDataSubKey
= "Guid";
4013 LPCSTR majVerDataSubKey
= "dwReserved1";
4014 LPCSTR minVerDataSubKey
= "dwReserved2";
4015 LPCSTR pathSubKey
= "Path";
4017 TRACE( " request to load %s\n", debugstr_guid( lpcGuid
) );
4019 /* FIXME: Cloned code with a quick hack. */
4020 for( i
=0; i
<2; i
++ )
4023 LPCSTR searchSubKey
;
4024 char subKeyName
[51];
4025 DWORD dwIndex
, sizeOfSubKeyName
=50;
4028 (i
== 0) ? (searchSubKey
= spSubKey
) : (searchSubKey
= lpSubKey
);
4029 *lpbIsDpSp
= (i
== 0) ? TRUE
: FALSE
;
4032 /* Need to loop over the service providers in the registry */
4033 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE
, searchSubKey
,
4034 0, KEY_READ
, &hkResult
) != ERROR_SUCCESS
)
4036 /* Hmmm. Does this mean that there are no service providers? */
4037 ERR(": no service providers?\n");
4041 /* Traverse all the service providers we have available */
4043 RegEnumKeyExA( hkResult
, dwIndex
, subKeyName
, &sizeOfSubKeyName
,
4044 NULL
, NULL
, NULL
, &filetime
) != ERROR_NO_MORE_ITEMS
;
4045 ++dwIndex
, sizeOfSubKeyName
=51 )
4048 HKEY hkServiceProvider
;
4049 GUID serviceProviderGUID
;
4050 DWORD returnType
, sizeOfReturnBuffer
= 255;
4051 char returnBuffer
[256];
4055 TRACE(" this time through: %s\n", subKeyName
);
4057 /* Get a handle for this particular service provider */
4058 if( RegOpenKeyExA( hkResult
, subKeyName
, 0, KEY_READ
,
4059 &hkServiceProvider
) != ERROR_SUCCESS
)
4061 ERR(": what the heck is going on?\n" );
4065 if( RegQueryValueExA( hkServiceProvider
, guidDataSubKey
,
4066 NULL
, &returnType
, (LPBYTE
)returnBuffer
,
4067 &sizeOfReturnBuffer
) != ERROR_SUCCESS
)
4069 ERR(": missing GUID registry data members\n" );
4073 /* FIXME: Check return types to ensure we're interpreting data right */
4074 MultiByteToWideChar( CP_ACP
, 0, returnBuffer
, -1, buff
, sizeof(buff
)/sizeof(WCHAR
) );
4075 CLSIDFromString( buff
, &serviceProviderGUID
);
4076 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4078 /* Determine if this is the Service Provider that the user asked for */
4079 if( !IsEqualGUID( &serviceProviderGUID
, lpcGuid
) )
4084 if( i
== 0 ) /* DP SP */
4086 len
= MultiByteToWideChar( CP_ACP
, 0, subKeyName
, -1, NULL
, 0 );
4087 lpSpData
->lpszName
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof(WCHAR
) );
4088 MultiByteToWideChar( CP_ACP
, 0, subKeyName
, -1, lpSpData
->lpszName
, len
);
4091 sizeOfReturnBuffer
= 255;
4093 /* Get dwReserved1 */
4094 if( RegQueryValueExA( hkServiceProvider
, majVerDataSubKey
,
4095 NULL
, &returnType
, (LPBYTE
)returnBuffer
,
4096 &sizeOfReturnBuffer
) != ERROR_SUCCESS
)
4098 ERR(": missing dwReserved1 registry data members\n") ;
4103 memcpy( &lpSpData
->dwReserved1
, returnBuffer
, sizeof(lpSpData
->dwReserved1
) );
4105 sizeOfReturnBuffer
= 255;
4107 /* Get dwReserved2 */
4108 if( RegQueryValueExA( hkServiceProvider
, minVerDataSubKey
,
4109 NULL
, &returnType
, (LPBYTE
)returnBuffer
,
4110 &sizeOfReturnBuffer
) != ERROR_SUCCESS
)
4112 ERR(": missing dwReserved1 registry data members\n") ;
4117 memcpy( &lpSpData
->dwReserved2
, returnBuffer
, sizeof(lpSpData
->dwReserved2
) );
4119 sizeOfReturnBuffer
= 255;
4121 /* Get the path for this service provider */
4122 if( ( dwTemp
= RegQueryValueExA( hkServiceProvider
, pathSubKey
,
4123 NULL
, NULL
, (LPBYTE
)returnBuffer
,
4124 &sizeOfReturnBuffer
) ) != ERROR_SUCCESS
)
4126 ERR(": missing PATH registry data members: 0x%08x\n", dwTemp
);
4130 TRACE( "Loading %s\n", returnBuffer
);
4131 return LoadLibraryA( returnBuffer
);
4139 HRESULT
DP_InitializeDPSP( IDirectPlay3Impl
* This
, HMODULE hServiceProvider
)
4142 LPDPSP_SPINIT SPInit
;
4144 /* Initialize the service provider by calling SPInit */
4145 SPInit
= (LPDPSP_SPINIT
)GetProcAddress( hServiceProvider
, "SPInit" );
4147 if( SPInit
== NULL
)
4149 ERR( "Service provider doesn't provide SPInit interface?\n" );
4150 FreeLibrary( hServiceProvider
);
4151 return DPERR_UNAVAILABLE
;
4154 TRACE( "Calling SPInit (DP SP entry point)\n" );
4156 hr
= (*SPInit
)( &This
->dp2
->spData
);
4160 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr
) );
4161 FreeLibrary( hServiceProvider
);
4165 /* FIXME: Need to verify the sanity of the returned callback table
4166 * using IsBadCodePtr */
4167 This
->dp2
->bSPInitialized
= TRUE
;
4169 /* This interface is now initialized as a DP object */
4170 This
->dp2
->connectionInitialized
= DP_SERVICE_PROVIDER
;
4172 /* Store the handle of the module so that we can unload it later */
4173 This
->dp2
->hServiceProvider
= hServiceProvider
;
4179 HRESULT
DP_InitializeDPLSP( IDirectPlay3Impl
* This
, HMODULE hLobbyProvider
)
4182 LPSP_INIT DPLSPInit
;
4184 /* Initialize the service provider by calling SPInit */
4185 DPLSPInit
= (LPSP_INIT
)GetProcAddress( hLobbyProvider
, "DPLSPInit" );
4187 if( DPLSPInit
== NULL
)
4189 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4190 FreeLibrary( hLobbyProvider
);
4191 return DPERR_UNAVAILABLE
;
4194 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4196 hr
= (*DPLSPInit
)( &This
->dp2
->dplspData
);
4200 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr
) );
4201 FreeLibrary( hLobbyProvider
);
4205 /* FIXME: Need to verify the sanity of the returned callback table
4206 * using IsBadCodePtr */
4208 This
->dp2
->bDPLSPInitialized
= TRUE
;
4210 /* This interface is now initialized as a lobby object */
4211 This
->dp2
->connectionInitialized
= DP_LOBBY_PROVIDER
;
4213 /* Store the handle of the module so that we can unload it later */
4214 This
->dp2
->hDPLobbyProvider
= hLobbyProvider
;
4219 static HRESULT WINAPI DP_IF_InitializeConnection
4220 ( IDirectPlay3Impl
* This
, LPVOID lpConnection
, DWORD dwFlags
, BOOL bAnsi
)
4222 HMODULE hServiceProvider
;
4225 const DWORD dwAddrSize
= 80; /* FIXME: Need to calculate it correctly */
4226 BOOL bIsDpSp
; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4228 TRACE("(%p)->(%p,0x%08x,%u)\n", This
, lpConnection
, dwFlags
, bAnsi
);
4230 if ( lpConnection
== NULL
)
4232 return DPERR_INVALIDPARAMS
;
4237 return DPERR_INVALIDFLAGS
;
4240 if( This
->dp2
->connectionInitialized
!= NO_PROVIDER
)
4242 return DPERR_ALREADYINITIALIZED
;
4245 /* Find out what the requested SP is and how large this buffer is */
4246 hr
= DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress
, lpConnection
,
4247 dwAddrSize
, &guidSP
);
4251 ERR( "Invalid compound address?\n" );
4252 return DPERR_UNAVAILABLE
;
4255 /* Load the service provider */
4256 hServiceProvider
= DP_LoadSP( &guidSP
, &This
->dp2
->spData
, &bIsDpSp
);
4258 if( hServiceProvider
== 0 )
4260 ERR( "Unable to load service provider %s\n", debugstr_guid(&guidSP
) );
4261 return DPERR_UNAVAILABLE
;
4266 /* Fill in what we can of the Service Provider required information.
4267 * The rest was be done in DP_LoadSP
4269 This
->dp2
->spData
.lpAddress
= lpConnection
;
4270 This
->dp2
->spData
.dwAddressSize
= dwAddrSize
;
4271 This
->dp2
->spData
.lpGuid
= &guidSP
;
4273 hr
= DP_InitializeDPSP( This
, hServiceProvider
);
4277 This
->dp2
->dplspData
.lpAddress
= lpConnection
;
4279 hr
= DP_InitializeDPLSP( This
, hServiceProvider
);
4290 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4291 ( LPDIRECTPLAY3A iface
, LPVOID lpConnection
, DWORD dwFlags
)
4293 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4295 /* This may not be externally invoked once either an SP or LP is initialized */
4296 if( This
->dp2
->connectionInitialized
!= NO_PROVIDER
)
4298 return DPERR_ALREADYINITIALIZED
;
4301 return DP_IF_InitializeConnection( This
, lpConnection
, dwFlags
, TRUE
);
4304 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4305 ( LPDIRECTPLAY3 iface
, LPVOID lpConnection
, DWORD dwFlags
)
4307 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4309 /* This may not be externally invoked once either an SP or LP is initialized */
4310 if( This
->dp2
->connectionInitialized
!= NO_PROVIDER
)
4312 return DPERR_ALREADYINITIALIZED
;
4315 return DP_IF_InitializeConnection( This
, lpConnection
, dwFlags
, FALSE
);
4318 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4319 ( LPDIRECTPLAY3A iface
, LPCDPSESSIONDESC2 lpsd
, DWORD dwFlags
,
4320 LPCDPSECURITYDESC lpSecurity
, LPCDPCREDENTIALS lpCredentials
)
4322 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
; /* Yes a dp 2 interface */
4323 return DP_SecureOpen( This
, lpsd
, dwFlags
, lpSecurity
, lpCredentials
, TRUE
);
4326 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4327 ( LPDIRECTPLAY3 iface
, LPCDPSESSIONDESC2 lpsd
, DWORD dwFlags
,
4328 LPCDPSECURITYDESC lpSecurity
, LPCDPCREDENTIALS lpCredentials
)
4330 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
; /* Yes a dp 2 interface */
4331 return DP_SecureOpen( This
, lpsd
, dwFlags
, lpSecurity
, lpCredentials
, FALSE
);
4334 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4335 ( LPDIRECTPLAY3A iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
, LPDPCHAT lpChatMessage
)
4337 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4338 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This
, idFrom
, idTo
, dwFlags
, lpChatMessage
);
4342 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4343 ( LPDIRECTPLAY3 iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
, LPDPCHAT lpChatMessage
)
4345 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4346 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This
, idFrom
, idTo
, dwFlags
, lpChatMessage
);
4350 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4351 ( LPDIRECTPLAY3A iface
, DWORD dwFlags
, DPID idGroup
, LPDPLCONNECTION lpConnection
)
4353 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4354 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This
, dwFlags
, idGroup
, lpConnection
);
4358 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4359 ( LPDIRECTPLAY3 iface
, DWORD dwFlags
, DPID idGroup
, LPDPLCONNECTION lpConnection
)
4361 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4362 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This
, dwFlags
, idGroup
, lpConnection
);
4366 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4367 ( LPDIRECTPLAY3A iface
, DWORD dwFlags
, DPID idGroup
)
4369 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4370 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This
, dwFlags
, idGroup
);
4374 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4375 ( LPDIRECTPLAY3 iface
, DWORD dwFlags
, DPID idGroup
)
4377 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4378 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This
, dwFlags
, idGroup
);
4382 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4383 ( LPDIRECTPLAY3A iface
, DPID idGroup
, LPDWORD lpdwFlags
)
4385 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4386 FIXME("(%p)->(0x%08x,%p): stub\n", This
, idGroup
, lpdwFlags
);
4390 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4391 ( LPDIRECTPLAY3 iface
, DPID idGroup
, LPDWORD lpdwFlags
)
4393 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4394 FIXME("(%p)->(0x%08x,%p): stub\n", This
, idGroup
, lpdwFlags
);
4398 static HRESULT WINAPI DP_IF_GetGroupParent
4399 ( IDirectPlay3AImpl
* This
, DPID idGroup
, LPDPID lpidGroup
,
4402 lpGroupData lpGData
;
4404 TRACE("(%p)->(0x%08x,%p,%u)\n", This
, idGroup
, lpidGroup
, bAnsi
);
4406 if( ( lpGData
= DP_FindAnyGroup( (IDirectPlay2AImpl
*)This
, idGroup
) ) == NULL
)
4408 return DPERR_INVALIDGROUP
;
4411 *lpidGroup
= lpGData
->dpid
;
4416 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4417 ( LPDIRECTPLAY3A iface
, DPID idGroup
, LPDPID lpidGroup
)
4419 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4420 return DP_IF_GetGroupParent( This
, idGroup
, lpidGroup
, TRUE
);
4422 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4423 ( LPDIRECTPLAY3 iface
, DPID idGroup
, LPDPID lpidGroup
)
4425 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4426 return DP_IF_GetGroupParent( This
, idGroup
, lpidGroup
, FALSE
);
4429 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4430 ( LPDIRECTPLAY3A iface
, DPID idPlayer
, DWORD dwFlags
, LPVOID lpData
, LPDWORD lpdwDataSize
)
4432 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4433 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This
, idPlayer
, dwFlags
, lpData
, lpdwDataSize
);
4437 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4438 ( LPDIRECTPLAY3 iface
, DPID idPlayer
, DWORD dwFlags
, LPVOID lpData
, LPDWORD lpdwDataSize
)
4440 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4441 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This
, idPlayer
, dwFlags
, lpData
, lpdwDataSize
);
4445 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4446 ( LPDIRECTPLAY3A iface
, DPID idPlayer
, LPDWORD lpdwFlags
)
4448 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4449 FIXME("(%p)->(0x%08x,%p): stub\n", This
, idPlayer
, lpdwFlags
);
4453 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4454 ( LPDIRECTPLAY3 iface
, DPID idPlayer
, LPDWORD lpdwFlags
)
4456 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4457 FIXME("(%p)->(0x%08x,%p): stub\n", This
, idPlayer
, lpdwFlags
);
4461 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4462 ( LPDIRECTPLAY4A iface
, DPID idGroup
, LPDPID lpidGroupOwner
)
4464 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4465 FIXME("(%p)->(0x%08x,%p): stub\n", This
, idGroup
, lpidGroupOwner
);
4469 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4470 ( LPDIRECTPLAY4 iface
, DPID idGroup
, LPDPID lpidGroupOwner
)
4472 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4473 FIXME("(%p)->(0x%08x,%p): stub\n", This
, idGroup
, lpidGroupOwner
);
4477 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4478 ( LPDIRECTPLAY4A iface
, DPID idGroup
, DPID idGroupOwner
)
4480 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4481 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This
, idGroup
, idGroupOwner
);
4485 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4486 ( LPDIRECTPLAY4 iface
, DPID idGroup
, DPID idGroupOwner
)
4488 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4489 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This
, idGroup
, idGroupOwner
);
4493 static HRESULT WINAPI DP_SendEx
4494 ( IDirectPlay2Impl
* This
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
4495 LPVOID lpData
, DWORD dwDataSize
, DWORD dwPriority
, DWORD dwTimeout
,
4496 LPVOID lpContext
, LPDWORD lpdwMsgID
, BOOL bAnsi
)
4498 BOOL bValidDestination
= FALSE
;
4500 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,0x%08x,0x%08x,0x%08x,%p,%p,%u)"
4502 This
, idFrom
, idTo
, dwFlags
, lpData
, dwDataSize
, dwPriority
,
4503 dwTimeout
, lpContext
, lpdwMsgID
, bAnsi
);
4505 /* FIXME: Add parameter checking */
4506 /* FIXME: First call to this needs to acquire a message id which will be
4507 * used for multiple sends
4510 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4512 /* Verify that the message is being sent from a valid local player. The
4513 * from player may be anonymous DPID_UNKNOWN
4515 if( idFrom
!= DPID_UNKNOWN
)
4517 if( DP_FindPlayer( This
, idFrom
) == NULL
)
4519 WARN( "INFO: Invalid from player 0x%08x\n", idFrom
);
4520 return DPERR_INVALIDPLAYER
;
4524 /* Verify that the message is being sent to a valid player, group or to
4525 * everyone. If it's valid, send it to those players.
4527 if( idTo
== DPID_ALLPLAYERS
)
4529 bValidDestination
= TRUE
;
4531 /* See if SP has the ability to multicast. If so, use it */
4532 if( This
->dp2
->spData
.lpCB
->SendToGroupEx
)
4534 FIXME( "Use group sendex to group 0\n" );
4536 else if( This
->dp2
->spData
.lpCB
->SendToGroup
) /* obsolete interface */
4538 FIXME( "Use obsolete group send to group 0\n" );
4540 else /* No multicast, multiplicate */
4542 /* Send to all players we know about */
4543 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4547 if( ( !bValidDestination
) &&
4548 ( DP_FindPlayer( This
, idTo
) != NULL
)
4551 bValidDestination
= TRUE
;
4553 /* Have the service provider send this message */
4554 /* FIXME: Could optimize for local interface sends */
4555 return DP_SP_SendEx( This
, dwFlags
, lpData
, dwDataSize
, dwPriority
,
4556 dwTimeout
, lpContext
, lpdwMsgID
);
4559 if( ( !bValidDestination
) &&
4560 ( DP_FindAnyGroup( This
, idTo
) != NULL
)
4563 bValidDestination
= TRUE
;
4565 /* See if SP has the ability to multicast. If so, use it */
4566 if( This
->dp2
->spData
.lpCB
->SendToGroupEx
)
4568 FIXME( "Use group sendex\n" );
4570 else if( This
->dp2
->spData
.lpCB
->SendToGroup
) /* obsolete interface */
4572 FIXME( "Use obsolete group send to group\n" );
4574 else /* No multicast, multiplicate */
4576 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4584 This
->dp2
->hReplyEvent
= CreateEventW( NULL
, FALSE
, FALSE
, NULL
);
4586 dwWaitReturn
= WaitForSingleObject( hReplyEvent
, dwTimeout
);
4587 if( dwWaitReturn
!= WAIT_OBJECT_0
)
4589 ERR( "Wait failed 0x%08lx\n", dwWaitReturn
);
4595 if( !bValidDestination
)
4597 return DPERR_INVALIDPLAYER
;
4601 /* FIXME: Should return what the send returned */
4607 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4608 ( LPDIRECTPLAY4A iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
4609 LPVOID lpData
, DWORD dwDataSize
, DWORD dwPriority
, DWORD dwTimeout
,
4610 LPVOID lpContext
, LPDWORD lpdwMsgID
)
4612 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
; /* yes downcast to 2 */
4613 return DP_SendEx( This
, idFrom
, idTo
, dwFlags
, lpData
, dwDataSize
,
4614 dwPriority
, dwTimeout
, lpContext
, lpdwMsgID
, TRUE
);
4617 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4618 ( LPDIRECTPLAY4 iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
4619 LPVOID lpData
, DWORD dwDataSize
, DWORD dwPriority
, DWORD dwTimeout
,
4620 LPVOID lpContext
, LPDWORD lpdwMsgID
)
4622 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
; /* yes downcast to 2 */
4623 return DP_SendEx( This
, idFrom
, idTo
, dwFlags
, lpData
, dwDataSize
,
4624 dwPriority
, dwTimeout
, lpContext
, lpdwMsgID
, FALSE
);
4627 static HRESULT WINAPI DP_SP_SendEx
4628 ( IDirectPlay2Impl
* This
, DWORD dwFlags
,
4629 LPVOID lpData
, DWORD dwDataSize
, DWORD dwPriority
, DWORD dwTimeout
,
4630 LPVOID lpContext
, LPDWORD lpdwMsgID
)
4634 FIXME( ": stub\n" );
4636 /* FIXME: This queuing should only be for async messages */
4638 lpMElem
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpMElem
) );
4639 lpMElem
->msg
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, dwDataSize
);
4641 CopyMemory( lpMElem
->msg
, lpData
, dwDataSize
);
4643 /* FIXME: Need to queue based on priority */
4644 DPQ_INSERT( This
->dp2
->sendMsgs
, lpMElem
, msgs
);
4649 static HRESULT WINAPI DP_IF_GetMessageQueue
4650 ( IDirectPlay4Impl
* This
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
4651 LPDWORD lpdwNumMsgs
, LPDWORD lpdwNumBytes
, BOOL bAnsi
)
4655 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%p,%u): semi stub\n",
4656 This
, idFrom
, idTo
, dwFlags
, lpdwNumMsgs
, lpdwNumBytes
, bAnsi
);
4658 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4659 /* FIXME: What about sends which are not immediate? */
4661 if( This
->dp2
->spData
.lpCB
->GetMessageQueue
)
4663 DPSP_GETMESSAGEQUEUEDATA data
;
4665 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4667 /* FIXME: None of this is documented :( */
4669 data
.lpISP
= This
->dp2
->spData
.lpISP
;
4670 data
.dwFlags
= dwFlags
;
4671 data
.idFrom
= idFrom
;
4673 data
.lpdwNumMsgs
= lpdwNumMsgs
;
4674 data
.lpdwNumBytes
= lpdwNumBytes
;
4676 hr
= (*This
->dp2
->spData
.lpCB
->GetMessageQueue
)( &data
);
4680 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4686 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4687 ( LPDIRECTPLAY4A 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
, TRUE
);
4695 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4696 ( LPDIRECTPLAY4 iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
4697 LPDWORD lpdwNumMsgs
, LPDWORD lpdwNumBytes
)
4699 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4700 return DP_IF_GetMessageQueue( This
, idFrom
, idTo
, dwFlags
, lpdwNumMsgs
,
4701 lpdwNumBytes
, FALSE
);
4704 static HRESULT WINAPI DP_IF_CancelMessage
4705 ( IDirectPlay4Impl
* This
, DWORD dwMsgID
, DWORD dwFlags
,
4706 DWORD dwMinPriority
, DWORD dwMaxPriority
, BOOL bAnsi
)
4710 FIXME( "(%p)->(0x%08x,0x%08x,%u): semi stub\n",
4711 This
, dwMsgID
, dwFlags
, bAnsi
);
4713 if( This
->dp2
->spData
.lpCB
->Cancel
)
4715 DPSP_CANCELDATA data
;
4717 TRACE( "Calling SP Cancel\n" );
4719 /* FIXME: Undocumented callback */
4721 data
.lpISP
= This
->dp2
->spData
.lpISP
;
4722 data
.dwFlags
= dwFlags
;
4723 data
.lprglpvSPMsgID
= NULL
;
4724 data
.cSPMsgID
= dwMsgID
;
4725 data
.dwMinPriority
= dwMinPriority
;
4726 data
.dwMaxPriority
= dwMaxPriority
;
4728 hr
= (*This
->dp2
->spData
.lpCB
->Cancel
)( &data
);
4732 FIXME( "SP doesn't implement Cancel\n" );
4738 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
4739 ( LPDIRECTPLAY4A iface
, DWORD dwMsgID
, DWORD dwFlags
)
4741 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4745 return DPERR_INVALIDFLAGS
;
4750 dwFlags
|= DPCANCELSEND_ALL
;
4753 return DP_IF_CancelMessage( This
, dwMsgID
, dwFlags
, 0, 0, TRUE
);
4756 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
4757 ( LPDIRECTPLAY4 iface
, DWORD dwMsgID
, DWORD dwFlags
)
4759 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4763 return DPERR_INVALIDFLAGS
;
4768 dwFlags
|= DPCANCELSEND_ALL
;
4771 return DP_IF_CancelMessage( This
, dwMsgID
, dwFlags
, 0, 0, FALSE
);
4774 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
4775 ( LPDIRECTPLAY4A iface
, DWORD dwMinPriority
, DWORD dwMaxPriority
,
4778 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4782 return DPERR_INVALIDFLAGS
;
4785 return DP_IF_CancelMessage( This
, 0, DPCANCELSEND_PRIORITY
, dwMinPriority
,
4786 dwMaxPriority
, TRUE
);
4789 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
4790 ( LPDIRECTPLAY4 iface
, DWORD dwMinPriority
, DWORD dwMaxPriority
,
4793 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4797 return DPERR_INVALIDFLAGS
;
4800 return DP_IF_CancelMessage( This
, 0, DPCANCELSEND_PRIORITY
, dwMinPriority
,
4801 dwMaxPriority
, FALSE
);
4804 /* Note: Hack so we can reuse the old functions without compiler warnings */
4805 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4806 # define XCAST(fun) (typeof(directPlay2WVT.fun))
4808 # define XCAST(fun) (void*)
4811 static const IDirectPlay2Vtbl directPlay2WVT
=
4813 XCAST(QueryInterface
)DP_QueryInterface
,
4814 XCAST(AddRef
)DP_AddRef
,
4815 XCAST(Release
)DP_Release
,
4817 DirectPlay2WImpl_AddPlayerToGroup
,
4818 DirectPlay2WImpl_Close
,
4819 DirectPlay2WImpl_CreateGroup
,
4820 DirectPlay2WImpl_CreatePlayer
,
4821 DirectPlay2WImpl_DeletePlayerFromGroup
,
4822 DirectPlay2WImpl_DestroyGroup
,
4823 DirectPlay2WImpl_DestroyPlayer
,
4824 DirectPlay2WImpl_EnumGroupPlayers
,
4825 DirectPlay2WImpl_EnumGroups
,
4826 DirectPlay2WImpl_EnumPlayers
,
4827 DirectPlay2WImpl_EnumSessions
,
4828 DirectPlay2WImpl_GetCaps
,
4829 DirectPlay2WImpl_GetGroupData
,
4830 DirectPlay2WImpl_GetGroupName
,
4831 DirectPlay2WImpl_GetMessageCount
,
4832 DirectPlay2WImpl_GetPlayerAddress
,
4833 DirectPlay2WImpl_GetPlayerCaps
,
4834 DirectPlay2WImpl_GetPlayerData
,
4835 DirectPlay2WImpl_GetPlayerName
,
4836 DirectPlay2WImpl_GetSessionDesc
,
4837 DirectPlay2WImpl_Initialize
,
4838 DirectPlay2WImpl_Open
,
4839 DirectPlay2WImpl_Receive
,
4840 DirectPlay2WImpl_Send
,
4841 DirectPlay2WImpl_SetGroupData
,
4842 DirectPlay2WImpl_SetGroupName
,
4843 DirectPlay2WImpl_SetPlayerData
,
4844 DirectPlay2WImpl_SetPlayerName
,
4845 DirectPlay2WImpl_SetSessionDesc
4849 /* Note: Hack so we can reuse the old functions without compiler warnings */
4850 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4851 # define XCAST(fun) (typeof(directPlay2AVT.fun))
4853 # define XCAST(fun) (void*)
4856 static const IDirectPlay2Vtbl directPlay2AVT
=
4858 XCAST(QueryInterface
)DP_QueryInterface
,
4859 XCAST(AddRef
)DP_AddRef
,
4860 XCAST(Release
)DP_Release
,
4862 DirectPlay2AImpl_AddPlayerToGroup
,
4863 DirectPlay2AImpl_Close
,
4864 DirectPlay2AImpl_CreateGroup
,
4865 DirectPlay2AImpl_CreatePlayer
,
4866 DirectPlay2AImpl_DeletePlayerFromGroup
,
4867 DirectPlay2AImpl_DestroyGroup
,
4868 DirectPlay2AImpl_DestroyPlayer
,
4869 DirectPlay2AImpl_EnumGroupPlayers
,
4870 DirectPlay2AImpl_EnumGroups
,
4871 DirectPlay2AImpl_EnumPlayers
,
4872 DirectPlay2AImpl_EnumSessions
,
4873 DirectPlay2AImpl_GetCaps
,
4874 DirectPlay2AImpl_GetGroupData
,
4875 DirectPlay2AImpl_GetGroupName
,
4876 DirectPlay2AImpl_GetMessageCount
,
4877 DirectPlay2AImpl_GetPlayerAddress
,
4878 DirectPlay2AImpl_GetPlayerCaps
,
4879 DirectPlay2AImpl_GetPlayerData
,
4880 DirectPlay2AImpl_GetPlayerName
,
4881 DirectPlay2AImpl_GetSessionDesc
,
4882 DirectPlay2AImpl_Initialize
,
4883 DirectPlay2AImpl_Open
,
4884 DirectPlay2AImpl_Receive
,
4885 DirectPlay2AImpl_Send
,
4886 DirectPlay2AImpl_SetGroupData
,
4887 DirectPlay2AImpl_SetGroupName
,
4888 DirectPlay2AImpl_SetPlayerData
,
4889 DirectPlay2AImpl_SetPlayerName
,
4890 DirectPlay2AImpl_SetSessionDesc
4895 /* Note: Hack so we can reuse the old functions without compiler warnings */
4896 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4897 # define XCAST(fun) (typeof(directPlay3AVT.fun))
4899 # define XCAST(fun) (void*)
4902 static const IDirectPlay3Vtbl directPlay3AVT
=
4904 XCAST(QueryInterface
)DP_QueryInterface
,
4905 XCAST(AddRef
)DP_AddRef
,
4906 XCAST(Release
)DP_Release
,
4908 XCAST(AddPlayerToGroup
)DirectPlay2AImpl_AddPlayerToGroup
,
4909 XCAST(Close
)DirectPlay2AImpl_Close
,
4910 XCAST(CreateGroup
)DirectPlay2AImpl_CreateGroup
,
4911 XCAST(CreatePlayer
)DirectPlay2AImpl_CreatePlayer
,
4912 XCAST(DeletePlayerFromGroup
)DirectPlay2AImpl_DeletePlayerFromGroup
,
4913 XCAST(DestroyGroup
)DirectPlay2AImpl_DestroyGroup
,
4914 XCAST(DestroyPlayer
)DirectPlay2AImpl_DestroyPlayer
,
4915 XCAST(EnumGroupPlayers
)DirectPlay2AImpl_EnumGroupPlayers
,
4916 XCAST(EnumGroups
)DirectPlay2AImpl_EnumGroups
,
4917 XCAST(EnumPlayers
)DirectPlay2AImpl_EnumPlayers
,
4918 XCAST(EnumSessions
)DirectPlay2AImpl_EnumSessions
,
4919 XCAST(GetCaps
)DirectPlay2AImpl_GetCaps
,
4920 XCAST(GetGroupData
)DirectPlay2AImpl_GetGroupData
,
4921 XCAST(GetGroupName
)DirectPlay2AImpl_GetGroupName
,
4922 XCAST(GetMessageCount
)DirectPlay2AImpl_GetMessageCount
,
4923 XCAST(GetPlayerAddress
)DirectPlay2AImpl_GetPlayerAddress
,
4924 XCAST(GetPlayerCaps
)DirectPlay2AImpl_GetPlayerCaps
,
4925 XCAST(GetPlayerData
)DirectPlay2AImpl_GetPlayerData
,
4926 XCAST(GetPlayerName
)DirectPlay2AImpl_GetPlayerName
,
4927 XCAST(GetSessionDesc
)DirectPlay2AImpl_GetSessionDesc
,
4928 XCAST(Initialize
)DirectPlay2AImpl_Initialize
,
4929 XCAST(Open
)DirectPlay2AImpl_Open
,
4930 XCAST(Receive
)DirectPlay2AImpl_Receive
,
4931 XCAST(Send
)DirectPlay2AImpl_Send
,
4932 XCAST(SetGroupData
)DirectPlay2AImpl_SetGroupData
,
4933 XCAST(SetGroupName
)DirectPlay2AImpl_SetGroupName
,
4934 XCAST(SetPlayerData
)DirectPlay2AImpl_SetPlayerData
,
4935 XCAST(SetPlayerName
)DirectPlay2AImpl_SetPlayerName
,
4936 XCAST(SetSessionDesc
)DirectPlay2AImpl_SetSessionDesc
,
4938 DirectPlay3AImpl_AddGroupToGroup
,
4939 DirectPlay3AImpl_CreateGroupInGroup
,
4940 DirectPlay3AImpl_DeleteGroupFromGroup
,
4941 DirectPlay3AImpl_EnumConnections
,
4942 DirectPlay3AImpl_EnumGroupsInGroup
,
4943 DirectPlay3AImpl_GetGroupConnectionSettings
,
4944 DirectPlay3AImpl_InitializeConnection
,
4945 DirectPlay3AImpl_SecureOpen
,
4946 DirectPlay3AImpl_SendChatMessage
,
4947 DirectPlay3AImpl_SetGroupConnectionSettings
,
4948 DirectPlay3AImpl_StartSession
,
4949 DirectPlay3AImpl_GetGroupFlags
,
4950 DirectPlay3AImpl_GetGroupParent
,
4951 DirectPlay3AImpl_GetPlayerAccount
,
4952 DirectPlay3AImpl_GetPlayerFlags
4956 /* Note: Hack so we can reuse the old functions without compiler warnings */
4957 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4958 # define XCAST(fun) (typeof(directPlay3WVT.fun))
4960 # define XCAST(fun) (void*)
4962 static const IDirectPlay3Vtbl directPlay3WVT
=
4964 XCAST(QueryInterface
)DP_QueryInterface
,
4965 XCAST(AddRef
)DP_AddRef
,
4966 XCAST(Release
)DP_Release
,
4968 XCAST(AddPlayerToGroup
)DirectPlay2WImpl_AddPlayerToGroup
,
4969 XCAST(Close
)DirectPlay2WImpl_Close
,
4970 XCAST(CreateGroup
)DirectPlay2WImpl_CreateGroup
,
4971 XCAST(CreatePlayer
)DirectPlay2WImpl_CreatePlayer
,
4972 XCAST(DeletePlayerFromGroup
)DirectPlay2WImpl_DeletePlayerFromGroup
,
4973 XCAST(DestroyGroup
)DirectPlay2WImpl_DestroyGroup
,
4974 XCAST(DestroyPlayer
)DirectPlay2WImpl_DestroyPlayer
,
4975 XCAST(EnumGroupPlayers
)DirectPlay2WImpl_EnumGroupPlayers
,
4976 XCAST(EnumGroups
)DirectPlay2WImpl_EnumGroups
,
4977 XCAST(EnumPlayers
)DirectPlay2WImpl_EnumPlayers
,
4978 XCAST(EnumSessions
)DirectPlay2WImpl_EnumSessions
,
4979 XCAST(GetCaps
)DirectPlay2WImpl_GetCaps
,
4980 XCAST(GetGroupData
)DirectPlay2WImpl_GetGroupData
,
4981 XCAST(GetGroupName
)DirectPlay2WImpl_GetGroupName
,
4982 XCAST(GetMessageCount
)DirectPlay2WImpl_GetMessageCount
,
4983 XCAST(GetPlayerAddress
)DirectPlay2WImpl_GetPlayerAddress
,
4984 XCAST(GetPlayerCaps
)DirectPlay2WImpl_GetPlayerCaps
,
4985 XCAST(GetPlayerData
)DirectPlay2WImpl_GetPlayerData
,
4986 XCAST(GetPlayerName
)DirectPlay2WImpl_GetPlayerName
,
4987 XCAST(GetSessionDesc
)DirectPlay2WImpl_GetSessionDesc
,
4988 XCAST(Initialize
)DirectPlay2WImpl_Initialize
,
4989 XCAST(Open
)DirectPlay2WImpl_Open
,
4990 XCAST(Receive
)DirectPlay2WImpl_Receive
,
4991 XCAST(Send
)DirectPlay2WImpl_Send
,
4992 XCAST(SetGroupData
)DirectPlay2WImpl_SetGroupData
,
4993 XCAST(SetGroupName
)DirectPlay2WImpl_SetGroupName
,
4994 XCAST(SetPlayerData
)DirectPlay2WImpl_SetPlayerData
,
4995 XCAST(SetPlayerName
)DirectPlay2WImpl_SetPlayerName
,
4996 XCAST(SetSessionDesc
)DirectPlay2WImpl_SetSessionDesc
,
4998 DirectPlay3WImpl_AddGroupToGroup
,
4999 DirectPlay3WImpl_CreateGroupInGroup
,
5000 DirectPlay3WImpl_DeleteGroupFromGroup
,
5001 DirectPlay3WImpl_EnumConnections
,
5002 DirectPlay3WImpl_EnumGroupsInGroup
,
5003 DirectPlay3WImpl_GetGroupConnectionSettings
,
5004 DirectPlay3WImpl_InitializeConnection
,
5005 DirectPlay3WImpl_SecureOpen
,
5006 DirectPlay3WImpl_SendChatMessage
,
5007 DirectPlay3WImpl_SetGroupConnectionSettings
,
5008 DirectPlay3WImpl_StartSession
,
5009 DirectPlay3WImpl_GetGroupFlags
,
5010 DirectPlay3WImpl_GetGroupParent
,
5011 DirectPlay3WImpl_GetPlayerAccount
,
5012 DirectPlay3WImpl_GetPlayerFlags
5016 /* Note: Hack so we can reuse the old functions without compiler warnings */
5017 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5018 # define XCAST(fun) (typeof(directPlay4WVT.fun))
5020 # define XCAST(fun) (void*)
5022 static const IDirectPlay4Vtbl directPlay4WVT
=
5024 XCAST(QueryInterface
)DP_QueryInterface
,
5025 XCAST(AddRef
)DP_AddRef
,
5026 XCAST(Release
)DP_Release
,
5028 XCAST(AddPlayerToGroup
)DirectPlay2WImpl_AddPlayerToGroup
,
5029 XCAST(Close
)DirectPlay2WImpl_Close
,
5030 XCAST(CreateGroup
)DirectPlay2WImpl_CreateGroup
,
5031 XCAST(CreatePlayer
)DirectPlay2WImpl_CreatePlayer
,
5032 XCAST(DeletePlayerFromGroup
)DirectPlay2WImpl_DeletePlayerFromGroup
,
5033 XCAST(DestroyGroup
)DirectPlay2WImpl_DestroyGroup
,
5034 XCAST(DestroyPlayer
)DirectPlay2WImpl_DestroyPlayer
,
5035 XCAST(EnumGroupPlayers
)DirectPlay2WImpl_EnumGroupPlayers
,
5036 XCAST(EnumGroups
)DirectPlay2WImpl_EnumGroups
,
5037 XCAST(EnumPlayers
)DirectPlay2WImpl_EnumPlayers
,
5038 XCAST(EnumSessions
)DirectPlay2WImpl_EnumSessions
,
5039 XCAST(GetCaps
)DirectPlay2WImpl_GetCaps
,
5040 XCAST(GetGroupData
)DirectPlay2WImpl_GetGroupData
,
5041 XCAST(GetGroupName
)DirectPlay2WImpl_GetGroupName
,
5042 XCAST(GetMessageCount
)DirectPlay2WImpl_GetMessageCount
,
5043 XCAST(GetPlayerAddress
)DirectPlay2WImpl_GetPlayerAddress
,
5044 XCAST(GetPlayerCaps
)DirectPlay2WImpl_GetPlayerCaps
,
5045 XCAST(GetPlayerData
)DirectPlay2WImpl_GetPlayerData
,
5046 XCAST(GetPlayerName
)DirectPlay2WImpl_GetPlayerName
,
5047 XCAST(GetSessionDesc
)DirectPlay2WImpl_GetSessionDesc
,
5048 XCAST(Initialize
)DirectPlay2WImpl_Initialize
,
5049 XCAST(Open
)DirectPlay2WImpl_Open
,
5050 XCAST(Receive
)DirectPlay2WImpl_Receive
,
5051 XCAST(Send
)DirectPlay2WImpl_Send
,
5052 XCAST(SetGroupData
)DirectPlay2WImpl_SetGroupData
,
5053 XCAST(SetGroupName
)DirectPlay2WImpl_SetGroupName
,
5054 XCAST(SetPlayerData
)DirectPlay2WImpl_SetPlayerData
,
5055 XCAST(SetPlayerName
)DirectPlay2WImpl_SetPlayerName
,
5056 XCAST(SetSessionDesc
)DirectPlay2WImpl_SetSessionDesc
,
5058 XCAST(AddGroupToGroup
)DirectPlay3WImpl_AddGroupToGroup
,
5059 XCAST(CreateGroupInGroup
)DirectPlay3WImpl_CreateGroupInGroup
,
5060 XCAST(DeleteGroupFromGroup
)DirectPlay3WImpl_DeleteGroupFromGroup
,
5061 XCAST(EnumConnections
)DirectPlay3WImpl_EnumConnections
,
5062 XCAST(EnumGroupsInGroup
)DirectPlay3WImpl_EnumGroupsInGroup
,
5063 XCAST(GetGroupConnectionSettings
)DirectPlay3WImpl_GetGroupConnectionSettings
,
5064 XCAST(InitializeConnection
)DirectPlay3WImpl_InitializeConnection
,
5065 XCAST(SecureOpen
)DirectPlay3WImpl_SecureOpen
,
5066 XCAST(SendChatMessage
)DirectPlay3WImpl_SendChatMessage
,
5067 XCAST(SetGroupConnectionSettings
)DirectPlay3WImpl_SetGroupConnectionSettings
,
5068 XCAST(StartSession
)DirectPlay3WImpl_StartSession
,
5069 XCAST(GetGroupFlags
)DirectPlay3WImpl_GetGroupFlags
,
5070 XCAST(GetGroupParent
)DirectPlay3WImpl_GetGroupParent
,
5071 XCAST(GetPlayerAccount
)DirectPlay3WImpl_GetPlayerAccount
,
5072 XCAST(GetPlayerFlags
)DirectPlay3WImpl_GetPlayerFlags
,
5074 DirectPlay4WImpl_GetGroupOwner
,
5075 DirectPlay4WImpl_SetGroupOwner
,
5076 DirectPlay4WImpl_SendEx
,
5077 DirectPlay4WImpl_GetMessageQueue
,
5078 DirectPlay4WImpl_CancelMessage
,
5079 DirectPlay4WImpl_CancelPriority
5084 /* Note: Hack so we can reuse the old functions without compiler warnings */
5085 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5086 # define XCAST(fun) (typeof(directPlay4AVT.fun))
5088 # define XCAST(fun) (void*)
5090 static const IDirectPlay4Vtbl directPlay4AVT
=
5092 XCAST(QueryInterface
)DP_QueryInterface
,
5093 XCAST(AddRef
)DP_AddRef
,
5094 XCAST(Release
)DP_Release
,
5096 XCAST(AddPlayerToGroup
)DirectPlay2AImpl_AddPlayerToGroup
,
5097 XCAST(Close
)DirectPlay2AImpl_Close
,
5098 XCAST(CreateGroup
)DirectPlay2AImpl_CreateGroup
,
5099 XCAST(CreatePlayer
)DirectPlay2AImpl_CreatePlayer
,
5100 XCAST(DeletePlayerFromGroup
)DirectPlay2AImpl_DeletePlayerFromGroup
,
5101 XCAST(DestroyGroup
)DirectPlay2AImpl_DestroyGroup
,
5102 XCAST(DestroyPlayer
)DirectPlay2AImpl_DestroyPlayer
,
5103 XCAST(EnumGroupPlayers
)DirectPlay2AImpl_EnumGroupPlayers
,
5104 XCAST(EnumGroups
)DirectPlay2AImpl_EnumGroups
,
5105 XCAST(EnumPlayers
)DirectPlay2AImpl_EnumPlayers
,
5106 XCAST(EnumSessions
)DirectPlay2AImpl_EnumSessions
,
5107 XCAST(GetCaps
)DirectPlay2AImpl_GetCaps
,
5108 XCAST(GetGroupData
)DirectPlay2AImpl_GetGroupData
,
5109 XCAST(GetGroupName
)DirectPlay2AImpl_GetGroupName
,
5110 XCAST(GetMessageCount
)DirectPlay2AImpl_GetMessageCount
,
5111 XCAST(GetPlayerAddress
)DirectPlay2AImpl_GetPlayerAddress
,
5112 XCAST(GetPlayerCaps
)DirectPlay2AImpl_GetPlayerCaps
,
5113 XCAST(GetPlayerData
)DirectPlay2AImpl_GetPlayerData
,
5114 XCAST(GetPlayerName
)DirectPlay2AImpl_GetPlayerName
,
5115 XCAST(GetSessionDesc
)DirectPlay2AImpl_GetSessionDesc
,
5116 XCAST(Initialize
)DirectPlay2AImpl_Initialize
,
5117 XCAST(Open
)DirectPlay2AImpl_Open
,
5118 XCAST(Receive
)DirectPlay2AImpl_Receive
,
5119 XCAST(Send
)DirectPlay2AImpl_Send
,
5120 XCAST(SetGroupData
)DirectPlay2AImpl_SetGroupData
,
5121 XCAST(SetGroupName
)DirectPlay2AImpl_SetGroupName
,
5122 XCAST(SetPlayerData
)DirectPlay2AImpl_SetPlayerData
,
5123 XCAST(SetPlayerName
)DirectPlay2AImpl_SetPlayerName
,
5124 XCAST(SetSessionDesc
)DirectPlay2AImpl_SetSessionDesc
,
5126 XCAST(AddGroupToGroup
)DirectPlay3AImpl_AddGroupToGroup
,
5127 XCAST(CreateGroupInGroup
)DirectPlay3AImpl_CreateGroupInGroup
,
5128 XCAST(DeleteGroupFromGroup
)DirectPlay3AImpl_DeleteGroupFromGroup
,
5129 XCAST(EnumConnections
)DirectPlay3AImpl_EnumConnections
,
5130 XCAST(EnumGroupsInGroup
)DirectPlay3AImpl_EnumGroupsInGroup
,
5131 XCAST(GetGroupConnectionSettings
)DirectPlay3AImpl_GetGroupConnectionSettings
,
5132 XCAST(InitializeConnection
)DirectPlay3AImpl_InitializeConnection
,
5133 XCAST(SecureOpen
)DirectPlay3AImpl_SecureOpen
,
5134 XCAST(SendChatMessage
)DirectPlay3AImpl_SendChatMessage
,
5135 XCAST(SetGroupConnectionSettings
)DirectPlay3AImpl_SetGroupConnectionSettings
,
5136 XCAST(StartSession
)DirectPlay3AImpl_StartSession
,
5137 XCAST(GetGroupFlags
)DirectPlay3AImpl_GetGroupFlags
,
5138 XCAST(GetGroupParent
)DirectPlay3AImpl_GetGroupParent
,
5139 XCAST(GetPlayerAccount
)DirectPlay3AImpl_GetPlayerAccount
,
5140 XCAST(GetPlayerFlags
)DirectPlay3AImpl_GetPlayerFlags
,
5142 DirectPlay4AImpl_GetGroupOwner
,
5143 DirectPlay4AImpl_SetGroupOwner
,
5144 DirectPlay4AImpl_SendEx
,
5145 DirectPlay4AImpl_GetMessageQueue
,
5146 DirectPlay4AImpl_CancelMessage
,
5147 DirectPlay4AImpl_CancelPriority
5151 HRESULT
DP_GetSPPlayerData( IDirectPlay2Impl
* lpDP
,
5155 lpPlayerList lpPlayer
= DP_FindPlayer( lpDP
, idPlayer
);
5157 if( lpPlayer
== NULL
)
5159 return DPERR_INVALIDPLAYER
;
5162 *lplpData
= lpPlayer
->lpPData
->lpSPPlayerData
;
5167 HRESULT
DP_SetSPPlayerData( IDirectPlay2Impl
* lpDP
,
5171 lpPlayerList lpPlayer
= DP_FindPlayer( lpDP
, idPlayer
);
5173 if( lpPlayer
== NULL
)
5175 return DPERR_INVALIDPLAYER
;
5178 lpPlayer
->lpPData
->lpSPPlayerData
= lpData
;
5183 /***************************************************************************
5184 * DirectPlayEnumerateAW
5186 * The pointer to the structure lpContext will be filled with the
5187 * appropriate data for each service offered by the OS. These services are
5188 * not necessarily available on this particular machine but are defined
5189 * as simple service providers under the "Service Providers" registry key.
5190 * This structure is then passed to lpEnumCallback for each of the different
5193 * This API is useful only for applications written using DirectX3 or
5194 * worse. It is superseded by IDirectPlay3::EnumConnections which also
5195 * gives information on the actual connections.
5197 * defn of a service provider:
5198 * A dynamic-link library used by DirectPlay to communicate over a network.
5199 * The service provider contains all the network-specific code required
5200 * to send and receive messages. Online services and network operators can
5201 * supply service providers to use specialized hardware, protocols, communications
5202 * media, and network resources.
5205 static HRESULT
DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA
,
5206 LPDPENUMDPCALLBACKW lpEnumCallbackW
,
5210 static const WCHAR searchSubKey
[] = {
5211 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
5212 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
5213 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
5214 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
5215 static const WCHAR guidKey
[] = { 'G', 'u', 'i', 'd', 0 };
5216 static const WCHAR descW
[] = { 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', 'W', 0 };
5221 char *descriptionA
= NULL
;
5222 DWORD max_sizeOfDescriptionA
= 0;
5223 WCHAR
*descriptionW
= NULL
;
5224 DWORD max_sizeOfDescriptionW
= 0;
5226 if (!lpEnumCallbackA
&& !lpEnumCallbackW
)
5228 return DPERR_INVALIDPARAMS
;
5231 /* Need to loop over the service providers in the registry */
5232 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, searchSubKey
,
5233 0, KEY_READ
, &hkResult
) != ERROR_SUCCESS
)
5235 /* Hmmm. Does this mean that there are no service providers? */
5236 ERR(": no service provider key in the registry - check your Wine installation !!!\n");
5237 return DPERR_GENERIC
;
5240 /* Traverse all the service providers we have available */
5244 WCHAR subKeyName
[255]; /* 255 is the maximum key size according to MSDN */
5245 DWORD sizeOfSubKeyName
= sizeof(subKeyName
) / sizeof(WCHAR
);
5246 HKEY hkServiceProvider
;
5247 GUID serviceProviderGUID
;
5248 WCHAR guidKeyContent
[(2 * 16) + 1 + 6 /* This corresponds to '{....-..-..-..-......}' */ ];
5249 DWORD sizeOfGuidKeyContent
= sizeof(guidKeyContent
);
5252 ret_value
= RegEnumKeyExW(hkResult
, dwIndex
, subKeyName
, &sizeOfSubKeyName
,
5253 NULL
, NULL
, NULL
, &filetime
);
5254 if (ret_value
== ERROR_NO_MORE_ITEMS
)
5256 else if (ret_value
!= ERROR_SUCCESS
)
5258 ERR(": could not enumerate on service provider key.\n");
5259 return DPERR_EXCEPTION
;
5261 TRACE(" this time through sub-key %s.\n", debugstr_w(subKeyName
));
5263 /* Open the key for this service provider */
5264 if (RegOpenKeyExW(hkResult
, subKeyName
, 0, KEY_READ
, &hkServiceProvider
) != ERROR_SUCCESS
)
5266 ERR(": could not open registry key for service provider %s.\n", debugstr_w(subKeyName
));
5270 /* Get the GUID from the registry */
5271 if (RegQueryValueExW(hkServiceProvider
, guidKey
,
5272 NULL
, NULL
, (LPBYTE
) guidKeyContent
, &sizeOfGuidKeyContent
) != ERROR_SUCCESS
)
5274 ERR(": missing GUID registry data member for service provider %s.\n", debugstr_w(subKeyName
));
5277 if (sizeOfGuidKeyContent
!= sizeof(guidKeyContent
))
5279 ERR(": invalid format for the GUID registry data member for service provider %s (%s).\n", debugstr_w(subKeyName
), debugstr_w(guidKeyContent
));
5282 CLSIDFromString(guidKeyContent
, &serviceProviderGUID
);
5284 /* The enumeration will return FALSE if we are not to continue.
5286 * Note: on my windows box, major / minor version is 6 / 0 for all service providers
5287 * and have no relation to any of the two dwReserved1 and dwReserved2 keys.
5288 * I think that it simply means that they are in-line with DirectX 6.0
5290 if (lpEnumCallbackA
)
5292 DWORD sizeOfDescription
= 0;
5294 /* Note that this is the A case of this function, so use the A variant to get the description string */
5295 if (RegQueryValueExA(hkServiceProvider
, "DescriptionA",
5296 NULL
, NULL
, NULL
, &sizeOfDescription
) != ERROR_SUCCESS
)
5298 ERR(": missing 'DescriptionA' registry data member for service provider %s.\n", debugstr_w(subKeyName
));
5301 if (sizeOfDescription
> max_sizeOfDescriptionA
)
5303 HeapFree(GetProcessHeap(), 0, descriptionA
);
5304 max_sizeOfDescriptionA
= sizeOfDescription
;
5306 descriptionA
= HeapAlloc(GetProcessHeap(), 0, sizeOfDescription
);
5307 RegQueryValueExA(hkServiceProvider
, "DescriptionA",
5308 NULL
, NULL
, (LPBYTE
) descriptionA
, &sizeOfDescription
);
5310 if (!lpEnumCallbackA(&serviceProviderGUID
, descriptionA
, 6, 0, lpContext
))
5315 DWORD sizeOfDescription
= 0;
5317 if (RegQueryValueExW(hkServiceProvider
, descW
,
5318 NULL
, NULL
, NULL
, &sizeOfDescription
) != ERROR_SUCCESS
)
5320 ERR(": missing 'DescriptionW' registry data member for service provider %s.\n", debugstr_w(subKeyName
));
5323 if (sizeOfDescription
> max_sizeOfDescriptionW
)
5325 HeapFree(GetProcessHeap(), 0, descriptionW
);
5326 max_sizeOfDescriptionW
= sizeOfDescription
;
5328 descriptionW
= HeapAlloc(GetProcessHeap(), 0, sizeOfDescription
);
5329 RegQueryValueExW(hkServiceProvider
, descW
,
5330 NULL
, NULL
, (LPBYTE
) descriptionW
, &sizeOfDescription
);
5332 if (!lpEnumCallbackW(&serviceProviderGUID
, descriptionW
, 6, 0, lpContext
))
5340 HeapFree(GetProcessHeap(), 0, descriptionA
);
5341 HeapFree(GetProcessHeap(), 0, descriptionW
);
5346 /***************************************************************************
5347 * DirectPlayEnumerate [DPLAYX.9]
5348 * DirectPlayEnumerateA [DPLAYX.2]
5350 HRESULT WINAPI
DirectPlayEnumerateA(LPDPENUMDPCALLBACKA lpEnumCallback
, LPVOID lpContext
)
5352 TRACE("(%p,%p)\n", lpEnumCallback
, lpContext
);
5354 return DirectPlayEnumerateAW(lpEnumCallback
, NULL
, lpContext
);
5357 /***************************************************************************
5358 * DirectPlayEnumerateW [DPLAYX.3]
5360 HRESULT WINAPI
DirectPlayEnumerateW(LPDPENUMDPCALLBACKW lpEnumCallback
, LPVOID lpContext
)
5362 TRACE("(%p,%p)\n", lpEnumCallback
, lpContext
);
5364 return DirectPlayEnumerateAW(NULL
, lpEnumCallback
, lpContext
);
5367 typedef struct tagCreateEnum
5371 } CreateEnumData
, *lpCreateEnumData
;
5373 /* Find and copy the matching connection for the SP guid */
5374 static BOOL CALLBACK
cbDPCreateEnumConnections(
5376 LPVOID lpConnection
,
5377 DWORD dwConnectionSize
,
5382 lpCreateEnumData lpData
= (lpCreateEnumData
)lpContext
;
5384 if( IsEqualGUID( lpguidSP
, lpData
->lpGuid
) )
5386 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData
->lpGuid
) );
5388 lpData
->lpConn
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
5390 CopyMemory( lpData
->lpConn
, lpConnection
, dwConnectionSize
);
5392 /* Found the record that we were looking for */
5396 /* Haven't found what were looking for yet */
5401 /***************************************************************************
5402 * DirectPlayCreate [DPLAYX.1]
5405 HRESULT WINAPI DirectPlayCreate
5406 ( LPGUID lpGUID
, LPDIRECTPLAY
*lplpDP
, IUnknown
*pUnk
)
5409 LPDIRECTPLAY3A lpDP3A
;
5410 CreateEnumData cbData
;
5412 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID
), lplpDP
, pUnk
);
5416 return CLASS_E_NOAGGREGATION
;
5419 if( (lplpDP
== NULL
) || (lpGUID
== NULL
) )
5421 return DPERR_INVALIDPARAMS
;
5425 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5426 give them an IDirectPlay2A object and hope that doesn't cause problems */
5427 if( DP_CreateInterface( &IID_IDirectPlay2A
, (LPVOID
*)lplpDP
) != DP_OK
)
5429 return DPERR_UNAVAILABLE
;
5432 if( IsEqualGUID( &GUID_NULL
, lpGUID
) )
5434 /* The GUID_NULL means don't bind a service provider. Just return the
5439 /* Bind the desired service provider since lpGUID is non NULL */
5440 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID
) );
5442 /* We're going to use a DP3 interface */
5443 hr
= IDirectPlayX_QueryInterface( *lplpDP
, &IID_IDirectPlay3A
,
5447 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr
) );
5451 cbData
.lpConn
= NULL
;
5452 cbData
.lpGuid
= lpGUID
;
5454 /* We were given a service provider, find info about it... */
5455 hr
= IDirectPlayX_EnumConnections( lpDP3A
, NULL
, cbDPCreateEnumConnections
,
5456 &cbData
, DPCONNECTION_DIRECTPLAY
);
5457 if( ( FAILED(hr
) ) ||
5458 ( cbData
.lpConn
== NULL
)
5461 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr
) );
5462 IDirectPlayX_Release( lpDP3A
);
5463 return DPERR_UNAVAILABLE
;
5466 /* Initialize the service provider */
5467 hr
= IDirectPlayX_InitializeConnection( lpDP3A
, cbData
.lpConn
, 0 );
5470 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr
) );
5471 HeapFree( GetProcessHeap(), 0, cbData
.lpConn
);
5472 IDirectPlayX_Release( lpDP3A
);
5476 /* Release our version of the interface now that we're done with it */
5477 IDirectPlayX_Release( lpDP3A
);
5478 HeapFree( GetProcessHeap(), 0, cbData
.lpConn
);