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 BOOL
DP_CopyDPNAMEStruct( LPDPNAME lpDst
, const DPNAME
*lpSrc
, BOOL bAnsi
);
54 static void DP_SetPlayerData( lpPlayerData lpPData
, DWORD dwFlags
,
55 LPVOID lpData
, DWORD dwDataSize
);
57 static lpGroupData
DP_CreateGroup( IDirectPlay2AImpl
* iface
, const DPID
*lpid
,
58 const DPNAME
*lpName
, DWORD dwFlags
,
59 DPID idParent
, BOOL bAnsi
);
60 static void DP_SetGroupData( lpGroupData lpGData
, DWORD dwFlags
,
61 LPVOID lpData
, DWORD dwDataSize
);
62 static void DP_DeleteDPNameStruct( LPDPNAME lpDPName
);
63 static void DP_DeletePlayer( IDirectPlay2Impl
* This
, DPID dpid
);
64 static BOOL CALLBACK
cbDeletePlayerFromAllGroups( DPID dpId
,
69 static lpGroupData
DP_FindAnyGroup( IDirectPlay2AImpl
* This
, DPID dpid
);
70 static BOOL CALLBACK
cbRemoveGroupOrPlayer( DPID dpId
, DWORD dwPlayerType
,
71 LPCDPNAME lpName
, DWORD dwFlags
,
73 static void DP_DeleteGroup( IDirectPlay2Impl
* This
, DPID dpid
);
75 /* Forward declarations of virtual tables */
76 static const IDirectPlay2Vtbl directPlay2AVT
;
77 static const IDirectPlay3Vtbl directPlay3AVT
;
78 static const IDirectPlay4Vtbl directPlay4AVT
;
80 static const IDirectPlay2Vtbl directPlay2WVT
;
81 static const IDirectPlay3Vtbl directPlay3WVT
;
82 static const IDirectPlay4Vtbl directPlay4WVT
;
84 /* Helper methods for player/group interfaces */
85 static HRESULT DP_IF_DeletePlayerFromGroup
86 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idGroup
,
87 DPID idPlayer
, BOOL bAnsi
);
88 static HRESULT DP_IF_CreatePlayer
89 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, LPDPID lpidPlayer
,
90 LPDPNAME lpPlayerName
, HANDLE hEvent
, LPVOID lpData
,
91 DWORD dwDataSize
, DWORD dwFlags
, BOOL bAnsi
);
92 static HRESULT DP_IF_DestroyGroup
93 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idGroup
, BOOL bAnsi
);
94 static HRESULT DP_IF_DestroyPlayer
95 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idPlayer
, BOOL bAnsi
);
96 static HRESULT DP_IF_EnumGroupPlayers
97 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPGUID lpguidInstance
,
98 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
99 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
);
100 static HRESULT DP_IF_EnumGroups
101 ( IDirectPlay2Impl
* This
, LPGUID lpguidInstance
,
102 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
103 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
);
104 static HRESULT DP_IF_EnumPlayers
105 ( IDirectPlay2Impl
* This
, LPGUID lpguidInstance
,
106 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
107 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
);
108 static HRESULT DP_IF_GetGroupData
109 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPVOID lpData
,
110 LPDWORD lpdwDataSize
, DWORD dwFlags
, BOOL bAnsi
);
111 static HRESULT DP_IF_GetGroupName
112 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPVOID lpData
,
113 LPDWORD lpdwDataSize
, BOOL bAnsi
);
114 static HRESULT DP_IF_GetPlayerData
115 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPVOID lpData
,
116 LPDWORD lpdwDataSize
, DWORD dwFlags
, BOOL bAnsi
);
117 static HRESULT DP_IF_GetPlayerName
118 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPVOID lpData
,
119 LPDWORD lpdwDataSize
, BOOL bAnsi
);
120 static HRESULT DP_IF_SetGroupName
121 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPDPNAME lpGroupName
,
122 DWORD dwFlags
, BOOL bAnsi
);
123 static HRESULT DP_IF_SetPlayerData
124 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPVOID lpData
,
125 DWORD dwDataSize
, DWORD dwFlags
, BOOL bAnsi
);
126 static HRESULT DP_IF_SetPlayerName
127 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPDPNAME lpPlayerName
,
128 DWORD dwFlags
, BOOL bAnsi
);
129 static HRESULT DP_IF_AddGroupToGroup
130 ( IDirectPlay3Impl
* This
, DPID idParentGroup
, DPID idGroup
);
131 static HRESULT DP_IF_CreateGroup
132 ( IDirectPlay2AImpl
* This
, LPVOID lpMsgHdr
, LPDPID lpidGroup
,
133 LPDPNAME lpGroupName
, LPVOID lpData
, DWORD dwDataSize
,
134 DWORD dwFlags
, BOOL bAnsi
);
135 static HRESULT DP_IF_CreateGroupInGroup
136 ( IDirectPlay3Impl
* This
, LPVOID lpMsgHdr
, DPID idParentGroup
,
137 LPDPID lpidGroup
, LPDPNAME lpGroupName
, LPVOID lpData
,
138 DWORD dwDataSize
, DWORD dwFlags
, BOOL bAnsi
);
139 static HRESULT DP_IF_AddPlayerToGroup
140 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idGroup
,
141 DPID idPlayer
, BOOL bAnsi
);
142 static HRESULT DP_IF_DeleteGroupFromGroup
143 ( IDirectPlay3Impl
* This
, DPID idParentGroup
, DPID idGroup
);
144 static HRESULT DP_SecureOpen
145 ( IDirectPlay2Impl
* This
, LPCDPSESSIONDESC2 lpsd
, DWORD dwFlags
,
146 LPCDPSECURITYDESC lpSecurity
, LPCDPCREDENTIALS lpCredentials
,
148 static HRESULT DP_SendEx
149 ( IDirectPlay2Impl
* This
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
150 LPVOID lpData
, DWORD dwDataSize
, DWORD dwPriority
, DWORD dwTimeout
,
151 LPVOID lpContext
, LPDWORD lpdwMsgID
, BOOL bAnsi
);
152 static HRESULT DP_IF_Receive
153 ( IDirectPlay2Impl
* This
, LPDPID lpidFrom
, LPDPID lpidTo
,
154 DWORD dwFlags
, LPVOID lpData
, LPDWORD lpdwDataSize
, BOOL bAnsi
);
155 static HRESULT DP_IF_GetMessageQueue
156 ( IDirectPlay4Impl
* This
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
157 LPDWORD lpdwNumMsgs
, LPDWORD lpdwNumBytes
, BOOL bAnsi
);
158 static HRESULT DP_SP_SendEx
159 ( IDirectPlay2Impl
* This
, DWORD dwFlags
,
160 LPVOID lpData
, DWORD dwDataSize
, DWORD dwPriority
, DWORD dwTimeout
,
161 LPVOID lpContext
, LPDWORD lpdwMsgID
);
162 static HRESULT DP_IF_SetGroupData
163 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPVOID lpData
,
164 DWORD dwDataSize
, DWORD dwFlags
, BOOL bAnsi
);
165 static HRESULT DP_IF_GetPlayerCaps
166 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPDPCAPS lpDPCaps
,
168 static HRESULT
DP_IF_Close( IDirectPlay2Impl
* This
, BOOL bAnsi
);
169 static HRESULT DP_IF_CancelMessage
170 ( IDirectPlay4Impl
* This
, DWORD dwMsgID
, DWORD dwFlags
,
171 DWORD dwMinPriority
, DWORD dwMaxPriority
, BOOL bAnsi
);
172 static HRESULT DP_IF_EnumGroupsInGroup
173 ( IDirectPlay3AImpl
* This
, DPID idGroup
, LPGUID lpguidInstance
,
174 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
175 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
);
176 static HRESULT DP_IF_GetGroupParent
177 ( IDirectPlay3AImpl
* This
, DPID idGroup
, LPDPID lpidGroup
,
179 static HRESULT DP_IF_GetCaps
180 ( IDirectPlay2Impl
* This
, LPDPCAPS lpDPCaps
, DWORD dwFlags
);
181 static HRESULT DP_IF_EnumSessions
182 ( IDirectPlay2Impl
* This
, LPDPSESSIONDESC2 lpsd
, DWORD dwTimeout
,
183 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2
,
184 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
);
185 static HRESULT DP_IF_InitializeConnection
186 ( IDirectPlay3Impl
* This
, LPVOID lpConnection
, DWORD dwFlags
, BOOL bAnsi
);
187 static BOOL CALLBACK
cbDPCreateEnumConnections( LPCGUID lpguidSP
,
188 LPVOID lpConnection
, DWORD dwConnectionSize
, LPCDPNAME lpName
,
189 DWORD dwFlags
, LPVOID lpContext
);
190 static BOOL
DP_BuildCompoundAddr( GUID guidDataType
, LPGUID lpcSpGuid
,
191 LPVOID
* lplpAddrBuf
, LPDWORD lpdwBufSize
);
195 static inline DPID
DP_NextObjectId(void);
196 static DPID
DP_GetRemoteNextObjectId(void);
198 static DWORD
DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc
, BOOL bAnsi
);
199 static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc
,
200 LPCDPSESSIONDESC2 srcSessDesc
, BOOL bAnsi
);
203 static HMODULE
DP_LoadSP( LPCGUID lpcGuid
, LPSPINITDATA lpSpData
, LPBOOL lpbIsDpSp
);
204 static HRESULT
DP_InitializeDPSP( IDirectPlay3Impl
* This
, HMODULE hServiceProvider
);
205 static HRESULT
DP_InitializeDPLSP( IDirectPlay3Impl
* This
, HMODULE hServiceProvider
);
212 #define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */
213 #define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported
214 we don't have to change much */
215 #define DPID_NAME_SERVER 0x19a9d65b /* Don't ask me why */
217 /* Strip out dwFlag values which cannot be sent in the CREATEGROUP msg */
218 #define DPMSG_CREATEGROUP_DWFLAGS(x) ( (x) & DPGROUP_HIDDEN )
220 /* Strip out all dwFlags values for CREATEPLAYER msg */
221 #define DPMSG_CREATEPLAYER_DWFLAGS(x) 0
223 static LONG kludgePlayerGroupId
= 1000;
225 /* ------------------------------------------------------------------ */
228 static BOOL
DP_CreateIUnknown( LPVOID lpDP
)
230 IDirectPlay2AImpl
*This
= lpDP
;
232 This
->unk
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *(This
->unk
) ) );
233 if ( This
->unk
== NULL
)
238 InitializeCriticalSection( &This
->unk
->DP_lock
);
239 This
->unk
->DP_lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": IDirectPlay2AImpl*->DirectPlayIUnknownData*->DP_lock");
244 static BOOL
DP_DestroyIUnknown( LPVOID lpDP
)
246 IDirectPlay2AImpl
*This
= lpDP
;
248 This
->unk
->DP_lock
.DebugInfo
->Spare
[0] = 0;
249 DeleteCriticalSection( &This
->unk
->DP_lock
);
250 HeapFree( GetProcessHeap(), 0, This
->unk
);
255 static BOOL
DP_CreateDirectPlay2( LPVOID lpDP
)
257 IDirectPlay2AImpl
*This
= lpDP
;
259 This
->dp2
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *(This
->dp2
) ) );
260 if ( This
->dp2
== NULL
)
265 This
->dp2
->bConnectionOpen
= FALSE
;
267 This
->dp2
->hEnumSessionThread
= INVALID_HANDLE_VALUE
;
268 This
->dp2
->dwEnumSessionLock
= 0;
270 This
->dp2
->bHostInterface
= FALSE
;
272 DPQ_INIT(This
->dp2
->receiveMsgs
);
273 DPQ_INIT(This
->dp2
->sendMsgs
);
274 DPQ_INIT(This
->dp2
->replysExpected
);
276 if( !NS_InitializeSessionCache( &This
->dp2
->lpNameServerData
) )
278 /* FIXME: Memory leak */
282 /* Provide an initial session desc with nothing in it */
283 This
->dp2
->lpSessionDesc
= HeapAlloc( GetProcessHeap(),
285 sizeof( *This
->dp2
->lpSessionDesc
) );
286 if( This
->dp2
->lpSessionDesc
== NULL
)
288 /* FIXME: Memory leak */
291 This
->dp2
->lpSessionDesc
->dwSize
= sizeof( *This
->dp2
->lpSessionDesc
);
293 /* We are emulating a dp 6 implementation */
294 This
->dp2
->spData
.dwSPVersion
= DPSP_MAJORVERSION
;
296 This
->dp2
->spData
.lpCB
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
297 sizeof( *This
->dp2
->spData
.lpCB
) );
298 This
->dp2
->spData
.lpCB
->dwSize
= sizeof( *This
->dp2
->spData
.lpCB
);
299 This
->dp2
->spData
.lpCB
->dwVersion
= DPSP_MAJORVERSION
;
301 /* This is the pointer to the service provider */
302 if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP
,
303 (LPVOID
*)&This
->dp2
->spData
.lpISP
, This
) )
306 /* FIXME: Memory leak */
310 /* Setup lobby provider information */
311 This
->dp2
->dplspData
.dwSPVersion
= DPSP_MAJORVERSION
;
312 This
->dp2
->dplspData
.lpCB
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
313 sizeof( *This
->dp2
->dplspData
.lpCB
) );
314 This
->dp2
->dplspData
.lpCB
->dwSize
= sizeof( *This
->dp2
->dplspData
.lpCB
);
316 if( FAILED( DPLSP_CreateInterface( &IID_IDPLobbySP
,
317 (LPVOID
*)&This
->dp2
->dplspData
.lpISP
, This
) )
320 /* FIXME: Memory leak */
327 /* Definition of the global function in dplayx_queue.h. #
328 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
329 DPQ_DECL_DELETECB( cbDeleteElemFromHeap
, LPVOID
)
331 HeapFree( GetProcessHeap(), 0, elem
);
334 static BOOL
DP_DestroyDirectPlay2( LPVOID lpDP
)
336 IDirectPlay2AImpl
*This
= lpDP
;
338 if( This
->dp2
->hEnumSessionThread
!= INVALID_HANDLE_VALUE
)
340 TerminateThread( This
->dp2
->hEnumSessionThread
, 0 );
341 CloseHandle( This
->dp2
->hEnumSessionThread
);
344 /* Finish with the SP - have it shutdown */
345 if( This
->dp2
->spData
.lpCB
->ShutdownEx
)
347 DPSP_SHUTDOWNDATA data
;
349 TRACE( "Calling SP ShutdownEx\n" );
351 data
.lpISP
= This
->dp2
->spData
.lpISP
;
353 (*This
->dp2
->spData
.lpCB
->ShutdownEx
)( &data
);
355 else if (This
->dp2
->spData
.lpCB
->Shutdown
) /* obsolete interface */
357 TRACE( "Calling obsolete SP Shutdown\n" );
358 (*This
->dp2
->spData
.lpCB
->Shutdown
)();
361 /* Unload the SP (if it exists) */
362 if( This
->dp2
->hServiceProvider
!= 0 )
364 FreeLibrary( This
->dp2
->hServiceProvider
);
367 /* Unload the Lobby Provider (if it exists) */
368 if( This
->dp2
->hDPLobbyProvider
!= 0 )
370 FreeLibrary( This
->dp2
->hDPLobbyProvider
);
373 /* FIXME: Need to delete receive and send msgs queue contents */
375 NS_DeleteSessionCache( This
->dp2
->lpNameServerData
);
377 HeapFree( GetProcessHeap(), 0, This
->dp2
->lpSessionDesc
);
379 IDirectPlaySP_Release( This
->dp2
->spData
.lpISP
);
381 /* Delete the contents */
382 HeapFree( GetProcessHeap(), 0, This
->dp2
);
387 static BOOL
DP_CreateDirectPlay3( LPVOID lpDP
)
389 IDirectPlay3AImpl
*This
= lpDP
;
391 This
->dp3
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *(This
->dp3
) ) );
392 if ( This
->dp3
== NULL
)
400 static BOOL
DP_DestroyDirectPlay3( LPVOID lpDP
)
402 IDirectPlay3AImpl
*This
= lpDP
;
404 /* Delete the contents */
405 HeapFree( GetProcessHeap(), 0, This
->dp3
);
410 static BOOL
DP_CreateDirectPlay4( LPVOID lpDP
)
412 IDirectPlay4AImpl
*This
= lpDP
;
414 This
->dp4
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *(This
->dp4
) ) );
415 if ( This
->dp4
== NULL
)
423 static BOOL
DP_DestroyDirectPlay4( LPVOID lpDP
)
425 IDirectPlay3AImpl
*This
= lpDP
;
427 /* Delete the contents */
428 HeapFree( GetProcessHeap(), 0, This
->dp4
);
434 /* Create a new interface */
435 HRESULT DP_CreateInterface
436 ( REFIID riid
, LPVOID
* ppvObj
)
438 TRACE( " for %s\n", debugstr_guid( riid
) );
440 *ppvObj
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
441 sizeof( IDirectPlay2Impl
) );
443 if( *ppvObj
== NULL
)
445 return DPERR_OUTOFMEMORY
;
448 if( IsEqualGUID( &IID_IDirectPlay2
, riid
) )
450 IDirectPlay2Impl
*This
= *ppvObj
;
451 This
->lpVtbl
= &directPlay2WVT
;
453 else if( IsEqualGUID( &IID_IDirectPlay2A
, riid
) )
455 IDirectPlay2AImpl
*This
= *ppvObj
;
456 This
->lpVtbl
= &directPlay2AVT
;
458 else if( IsEqualGUID( &IID_IDirectPlay3
, riid
) )
460 IDirectPlay3Impl
*This
= *ppvObj
;
461 This
->lpVtbl
= &directPlay3WVT
;
463 else if( IsEqualGUID( &IID_IDirectPlay3A
, riid
) )
465 IDirectPlay3AImpl
*This
= *ppvObj
;
466 This
->lpVtbl
= &directPlay3AVT
;
468 else if( IsEqualGUID( &IID_IDirectPlay4
, riid
) )
470 IDirectPlay4Impl
*This
= *ppvObj
;
471 This
->lpVtbl
= &directPlay4WVT
;
473 else if( IsEqualGUID( &IID_IDirectPlay4A
, riid
) )
475 IDirectPlay4AImpl
*This
= *ppvObj
;
476 This
->lpVtbl
= &directPlay4AVT
;
480 /* Unsupported interface */
481 HeapFree( GetProcessHeap(), 0, *ppvObj
);
484 return E_NOINTERFACE
;
488 if ( DP_CreateIUnknown( *ppvObj
) &&
489 DP_CreateDirectPlay2( *ppvObj
) &&
490 DP_CreateDirectPlay3( *ppvObj
) &&
491 DP_CreateDirectPlay4( *ppvObj
)
494 IDirectPlayX_AddRef( (LPDIRECTPLAY2A
)*ppvObj
);
499 /* Initialize failed, destroy it */
500 DP_DestroyDirectPlay4( *ppvObj
);
501 DP_DestroyDirectPlay3( *ppvObj
);
502 DP_DestroyDirectPlay2( *ppvObj
);
503 DP_DestroyIUnknown( *ppvObj
);
505 HeapFree( GetProcessHeap(), 0, *ppvObj
);
508 return DPERR_NOMEMORY
;
512 /* Direct Play methods */
514 /* Shared between all dplay types */
515 static HRESULT WINAPI DP_QueryInterface
516 ( LPDIRECTPLAY2 iface
, REFIID riid
, LPVOID
* ppvObj
)
518 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
519 TRACE("(%p)->(%s,%p)\n", This
, debugstr_guid( riid
), ppvObj
);
521 *ppvObj
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
524 if( *ppvObj
== NULL
)
526 return DPERR_OUTOFMEMORY
;
529 CopyMemory( *ppvObj
, This
, sizeof( *This
) );
530 (*(IDirectPlay2Impl
**)ppvObj
)->ulInterfaceRef
= 0;
532 if( IsEqualGUID( &IID_IDirectPlay2
, riid
) )
534 IDirectPlay2Impl
*This
= *ppvObj
;
535 This
->lpVtbl
= &directPlay2WVT
;
537 else if( IsEqualGUID( &IID_IDirectPlay2A
, riid
) )
539 IDirectPlay2AImpl
*This
= *ppvObj
;
540 This
->lpVtbl
= &directPlay2AVT
;
542 else if( IsEqualGUID( &IID_IDirectPlay3
, riid
) )
544 IDirectPlay3Impl
*This
= *ppvObj
;
545 This
->lpVtbl
= &directPlay3WVT
;
547 else if( IsEqualGUID( &IID_IDirectPlay3A
, riid
) )
549 IDirectPlay3AImpl
*This
= *ppvObj
;
550 This
->lpVtbl
= &directPlay3AVT
;
552 else if( IsEqualGUID( &IID_IDirectPlay4
, riid
) )
554 IDirectPlay4Impl
*This
= *ppvObj
;
555 This
->lpVtbl
= &directPlay4WVT
;
557 else if( IsEqualGUID( &IID_IDirectPlay4A
, riid
) )
559 IDirectPlay4AImpl
*This
= *ppvObj
;
560 This
->lpVtbl
= &directPlay4AVT
;
564 /* Unsupported interface */
565 HeapFree( GetProcessHeap(), 0, *ppvObj
);
568 return E_NOINTERFACE
;
571 IDirectPlayX_AddRef( (LPDIRECTPLAY2
)*ppvObj
);
576 /* Shared between all dplay types */
577 static ULONG WINAPI DP_AddRef
578 ( LPDIRECTPLAY3 iface
)
580 ULONG ulInterfaceRefCount
, ulObjRefCount
;
581 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
583 ulObjRefCount
= InterlockedIncrement( &This
->unk
->ulObjRef
);
584 ulInterfaceRefCount
= InterlockedIncrement( &This
->ulInterfaceRef
);
586 TRACE( "ref count incremented to %u:%u for %p\n",
587 ulInterfaceRefCount
, ulObjRefCount
, This
);
589 return ulObjRefCount
;
592 static ULONG WINAPI DP_Release
593 ( LPDIRECTPLAY3 iface
)
595 ULONG ulInterfaceRefCount
, ulObjRefCount
;
597 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
599 ulObjRefCount
= InterlockedDecrement( &This
->unk
->ulObjRef
);
600 ulInterfaceRefCount
= InterlockedDecrement( &This
->ulInterfaceRef
);
602 TRACE( "ref count decremented to %u:%u for %p\n",
603 ulInterfaceRefCount
, ulObjRefCount
, This
);
605 /* Deallocate if this is the last reference to the object */
606 if( ulObjRefCount
== 0 )
608 /* If we're destroying the object, this must be the last ref
609 of the last interface */
610 DP_DestroyDirectPlay4( This
);
611 DP_DestroyDirectPlay3( This
);
612 DP_DestroyDirectPlay2( This
);
613 DP_DestroyIUnknown( This
);
616 /* Deallocate the interface */
617 if( ulInterfaceRefCount
== 0 )
619 HeapFree( GetProcessHeap(), 0, This
);
622 return ulObjRefCount
;
625 static inline DPID
DP_NextObjectId(void)
627 return (DPID
)InterlockedIncrement( &kludgePlayerGroupId
);
630 /* *lplpReply will be non NULL iff there is something to reply */
631 HRESULT
DP_HandleMessage( IDirectPlay2Impl
* This
, LPCVOID lpcMessageBody
,
632 DWORD dwMessageBodySize
, LPCVOID lpcMessageHeader
,
633 WORD wCommandId
, WORD wVersion
,
634 LPVOID
* lplpReply
, LPDWORD lpdwMsgSize
)
636 TRACE( "(%p)->(%p,0x%08x,%p,0x%x,%u)\n",
637 This
, lpcMessageBody
, dwMessageBodySize
, lpcMessageHeader
, wCommandId
,
642 /* Name server needs to handle this request */
643 case DPMSGCMD_ENUMSESSIONS
:
646 NS_ReplyToEnumSessionsRequest( lpcMessageBody
, lplpReply
, lpdwMsgSize
, This
);
651 /* Name server needs to handle this request */
652 case DPMSGCMD_ENUMSESSIONSREPLY
:
654 /* No reply expected */
655 NS_AddRemoteComputerAsNameServer( lpcMessageHeader
,
656 This
->dp2
->spData
.dwSPHeaderSize
,
658 This
->dp2
->lpNameServerData
);
662 case DPMSGCMD_REQUESTPLAYERID
:
664 LPDPSP_MSG_REQUESTPLAYERID lpcMsg
= lpcMessageBody
;
665 LPDPSP_MSG_REQUESTPLAYERREPLY lpReply
;
667 *lpdwMsgSize
= This
->dp2
->spData
.dwSPHeaderSize
+ sizeof( *lpReply
);
669 *lplpReply
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, *lpdwMsgSize
);
671 lpReply
= (LPDPSP_MSG_REQUESTPLAYERREPLY
)( (LPBYTE
)(*lplpReply
) +
672 This
->dp2
->spData
.dwSPHeaderSize
);
674 lpReply
->envelope
.dwMagic
= DPMSG_SIGNATURE
;
675 lpReply
->envelope
.wCommandId
= DPMSGCMD_REQUESTPLAYERREPLY
;
676 lpReply
->envelope
.wVersion
= DX61AVERSION
;
678 if ( lpcMsg
->Flags
& DPLAYI_PLAYER_SYSPLAYER
)
680 /* Request to join the game */
682 if ( This
->dp2
->lpSessionDesc
->dwFlags
& DPSESSION_SECURESERVER
)
684 FIXME( "Fill lpReply->SecDesc with Game->SSPIProvider\n" );
686 FIXME( "Fill lpReply->CAPIProvider with Game->CAPIProvider\n" );
687 FIXME( "Fill lpReply->SecDesc->dwEncryptionAlgorithm with Game->EncryptionAlgorithm\n" );
689 /* Player is not local anymore */
690 lpcMsg
->Flags
^= DPLAYI_PLAYER_PLAYERLOCAL
;
692 lpReply
->ID
= DP_NextObjectId();
693 lpReply
->Result
= DP_IF_CreatePlayer( This
, lpcMessageHeader
,
694 &lpReply
->ID
, NULL
, 0, NULL
, 0,
695 lpcMsg
->Flags
, TRUE
/*TODO*/ );
696 lpReply
->Result
= S_OK
;
700 /* Request to to add a normal player from an
701 * existing member of the session */
703 if ( ( This
->dp2
->lpSessionDesc
->dwCurrentPlayers
704 == This
->dp2
->lpSessionDesc
->dwMaxPlayers
) ||
705 ( This
->dp2
->lpSessionDesc
->dwFlags
& DPSESSION_NEWPLAYERSDISABLED
) )
707 lpReply
->Result
= DPERR_NONEWPLAYERS
;
711 lpReply
->ID
= DP_NextObjectId();
712 lpReply
->Result
= S_OK
;
719 case DPMSGCMD_CREATEPLAYER
:
721 LPDPSP_MSG_CREATEPLAYER lpcMsg
= lpcMessageBody
;
722 LPDPLAYI_PACKEDPLAYER lpPackedPlayer
=
723 (LPDPLAYI_PACKEDPLAYER
)(((LPBYTE
) lpcMsg
) + lpcMsg
->CreateOffset
);
724 PACKEDPLAYERDATA packedPlayerData
;
726 DP_MSG_ParsePackedPlayer( This
,
727 (LPBYTE
) lpPackedPlayer
,
732 return DP_CreatePlayer( This
, lpPackedPlayer
->PlayerID
,
733 &packedPlayerData
.name
,
734 lpPackedPlayer
->Flags
,
735 packedPlayerData
.lpPlayerData
,
736 packedPlayerData
.dwPlayerDataSize
,
737 NULL
, TRUE
/*TODO*/, NULL
);
739 /* TODO send msg to upper layer */
743 case DPMSGCMD_PACKET
:
745 LPCDPSP_MSG_PACKET lpcMsg
= lpcMessageBody
;
746 LPDPSP_MSG_ENVELOPE packetData
;
748 /* TODO: We have to wait for all the messages in the sequence and
749 * assemble them in a bigger message. */
750 if ( lpcMsg
->TotalPackets
> 1 )
752 FIXME( "TODO: Message belongs to a sequence of %d, implement assembly\n",
753 lpcMsg
->TotalPackets
);
754 return DPERR_GENERIC
;
757 /* For now, for simplicity we'll just decapsulate the embedded
758 * message and work with it. */
759 packetData
= (LPVOID
)(lpcMsg
+ 1);
761 TRACE( "Processing embedded message with envelope (0x%08x, 0x%08x, %d)\n",
762 packetData
->dwMagic
, packetData
->wCommandId
, packetData
->wVersion
);
764 return DP_HandleMessage( This
,
768 packetData
->wCommandId
,
769 packetData
->wVersion
,
770 lplpReply
, lpdwMsgSize
);
774 case DPMSGCMD_REQUESTPLAYERREPLY
:
776 DP_MSG_ReplyReceived( This
, wCommandId
, lpcMessageHeader
,
777 lpcMessageBody
, dwMessageBodySize
);
781 case DPMSGCMD_ADDFORWARDREQUEST
:
783 /*LPCDPSP_MSG_ADDFORWARDREQUEST lpcMsg =
784 (LPCDPSP_MSG_ADDFORWARDREQUEST) lpcMessageBody;*/
786 /* TODO: Send ADDFORWARD messages to all the players to populate
788 * Start NametablePopulation timer and wait for ADDFORWARDACKs */
789 FIXME( "Spread name table population messages\n" );
791 /* TODO remember to set local addr somewhere */
792 /* call NS_SetLocalAddr with a SOCKADDR_IN */
794 FIXME( "This should happen after we received all the DPMSGCMD_ADDFORWARDACKs\n" );
795 DP_MSG_ReplyToEnumPlayersRequest( This
, lplpReply
, lpdwMsgSize
);
800 case DPMSGCMD_ADDFORWARDREPLY
:
802 DP_MSG_ReplyReceived( This
, wCommandId
, lpcMessageHeader
,
803 lpcMessageBody
, dwMessageBodySize
);
807 case DPMSGCMD_ENUMPLAYERSREPLY
:
808 case DPMSGCMD_SUPERENUMPLAYERSREPLY
:
810 /* If we're joining a session, when we receive this
811 * command we were waiting for a ADDFORWARDREPLY */
812 if ( !DP_MSG_ReplyReceived( This
, DPMSGCMD_ADDFORWARDREPLY
,
813 lpcMessageHeader
, lpcMessageBody
,
814 dwMessageBodySize
) )
816 /* If we were not joining a session, check if we are
817 * waiting for an enumeration of players or groups */
818 DP_MSG_ReplyReceived( This
, wCommandId
, lpcMessageHeader
,
819 lpcMessageBody
, dwMessageBodySize
);
824 case DPMSGCMD_ADDFORWARDACK
:
826 /* When we receive an ADDFORWARDACK for each of the ADDFORWARDs
827 * we've sent, send a SUPERENUMPLAYERSREPLY back to the peer
828 * that sent the ADDFORWARDREQUEST */
829 /* TODO: We'll skip this for now and just send the SUPERENUMPLAYERSREPLY
830 * right away when we get a ADDFORWARDREQUEST */
836 FIXME( "Unknown wCommandId 0x%08x. Ignoring message\n", wCommandId
);
837 return DPERR_GENERIC
;
845 static HRESULT DP_IF_AddPlayerToGroup
846 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idGroup
,
847 DPID idPlayer
, BOOL bAnsi
)
850 lpPlayerList lpPList
;
851 lpPlayerList lpNewPList
;
853 TRACE( "(%p)->(%p,0x%08x,0x%08x,%u)\n",
854 This
, lpMsgHdr
, idGroup
, idPlayer
, bAnsi
);
856 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
858 return DPERR_UNINITIALIZED
;
862 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
864 return DPERR_INVALIDGROUP
;
867 /* Find the player */
868 if( ( lpPList
= DP_FindPlayer( This
, idPlayer
) ) == NULL
)
870 return DPERR_INVALIDPLAYER
;
873 /* Create a player list (ie "shortcut" ) */
874 lpNewPList
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpNewPList
) );
875 if( lpNewPList
== NULL
)
877 return DPERR_CANTADDPLAYER
;
880 /* Add the shortcut */
881 lpPList
->lpPData
->uRef
++;
882 lpNewPList
->lpPData
= lpPList
->lpPData
;
884 /* Add the player to the list of players for this group */
885 DPQ_INSERT(lpGData
->players
,lpNewPList
,players
);
887 /* Let the SP know that we've added a player to the group */
888 if( This
->dp2
->spData
.lpCB
->AddPlayerToGroup
)
890 DPSP_ADDPLAYERTOGROUPDATA data
;
892 TRACE( "Calling SP AddPlayerToGroup\n" );
894 data
.idPlayer
= idPlayer
;
895 data
.idGroup
= idGroup
;
896 data
.lpISP
= This
->dp2
->spData
.lpISP
;
898 (*This
->dp2
->spData
.lpCB
->AddPlayerToGroup
)( &data
);
901 /* Inform all other peers of the addition of player to the group. If there are
902 * no peers keep this event quiet.
903 * Also, if this event was the result of another machine sending it to us,
904 * don't bother rebroadcasting it.
906 if( ( lpMsgHdr
== NULL
) &&
907 This
->dp2
->lpSessionDesc
&&
908 ( This
->dp2
->lpSessionDesc
->dwFlags
& DPSESSION_MULTICASTSERVER
) )
910 DPMSG_ADDPLAYERTOGROUP msg
;
911 msg
.dwType
= DPSYS_ADDPLAYERTOGROUP
;
913 msg
.dpIdGroup
= idGroup
;
914 msg
.dpIdPlayer
= idPlayer
;
916 /* FIXME: Correct to just use send effectively? */
917 /* FIXME: Should size include data w/ message or just message "header" */
918 /* FIXME: Check return code */
919 DP_SendEx( This
, DPID_SERVERPLAYER
, DPID_ALLPLAYERS
, 0, &msg
, sizeof( msg
), 0, 0, NULL
, NULL
, bAnsi
);
925 static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
926 ( LPDIRECTPLAY2A iface
, DPID idGroup
, DPID idPlayer
)
928 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
929 return DP_IF_AddPlayerToGroup( This
, NULL
, idGroup
, idPlayer
, TRUE
);
932 static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
933 ( LPDIRECTPLAY2 iface
, DPID idGroup
, DPID idPlayer
)
935 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
936 return DP_IF_AddPlayerToGroup( This
, NULL
, idGroup
, idPlayer
, FALSE
);
939 static HRESULT
DP_IF_Close( IDirectPlay2Impl
* This
, BOOL bAnsi
)
943 TRACE("(%p)->(%u)\n", This
, bAnsi
);
945 /* FIXME: Need to find a new host I assume (how?) */
946 /* FIXME: Need to destroy all local groups */
947 /* FIXME: Need to migrate all remotely visible players to the new host */
949 /* Invoke the SP callback to inform of session close */
950 if( This
->dp2
->spData
.lpCB
->CloseEx
)
954 TRACE( "Calling SP CloseEx\n" );
956 data
.lpISP
= This
->dp2
->spData
.lpISP
;
958 hr
= (*This
->dp2
->spData
.lpCB
->CloseEx
)( &data
);
961 else if ( This
->dp2
->spData
.lpCB
->Close
) /* Try obsolete version */
963 TRACE( "Calling SP Close (obsolete interface)\n" );
965 hr
= (*This
->dp2
->spData
.lpCB
->Close
)();
970 This
->dp2
->bConnectionOpen
= FALSE
;
976 static HRESULT WINAPI DirectPlay2AImpl_Close
977 ( LPDIRECTPLAY2A iface
)
979 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
980 return DP_IF_Close( This
, TRUE
);
983 static HRESULT WINAPI DirectPlay2WImpl_Close
984 ( LPDIRECTPLAY2 iface
)
986 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
987 return DP_IF_Close( This
, FALSE
);
991 lpGroupData
DP_CreateGroup( IDirectPlay2AImpl
* This
, const DPID
*lpid
,
992 const DPNAME
*lpName
, DWORD dwFlags
,
993 DPID idParent
, BOOL bAnsi
)
997 /* Allocate the new space and add to end of high level group list */
998 lpGData
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpGData
) );
1000 if( lpGData
== NULL
)
1005 DPQ_INIT(lpGData
->groups
);
1006 DPQ_INIT(lpGData
->players
);
1008 /* Set the desired player ID - no sanity checking to see if it exists */
1009 lpGData
->dpid
= *lpid
;
1011 DP_CopyDPNAMEStruct( &lpGData
->name
, lpName
, bAnsi
);
1013 /* FIXME: Should we check that the parent exists? */
1014 lpGData
->parent
= idParent
;
1016 /* FIXME: Should we validate the dwFlags? */
1017 lpGData
->dwFlags
= dwFlags
;
1019 TRACE( "Created group id 0x%08x\n", *lpid
);
1024 /* This method assumes that all links to it are already deleted */
1026 DP_DeleteGroup( IDirectPlay2Impl
* This
, DPID dpid
)
1028 lpGroupList lpGList
;
1030 TRACE( "(%p)->(0x%08x)\n", This
, dpid
);
1032 DPQ_REMOVE_ENTRY( This
->dp2
->lpSysGroup
->groups
, groups
, lpGData
->dpid
, ==, dpid
, lpGList
);
1034 if( lpGList
== NULL
)
1036 ERR( "DPID 0x%08x not found\n", dpid
);
1040 if( --(lpGList
->lpGData
->uRef
) )
1042 FIXME( "Why is this not the last reference to group?\n" );
1047 DP_DeleteDPNameStruct( &lpGList
->lpGData
->name
);
1048 HeapFree( GetProcessHeap(), 0, lpGList
->lpGData
);
1050 /* Remove and Delete Player List object */
1051 HeapFree( GetProcessHeap(), 0, lpGList
);
1055 static lpGroupData
DP_FindAnyGroup( IDirectPlay2AImpl
* This
, DPID dpid
)
1057 lpGroupList lpGroups
;
1059 TRACE( "(%p)->(0x%08x)\n", This
, dpid
);
1061 if( dpid
== DPID_SYSTEM_GROUP
)
1063 return This
->dp2
->lpSysGroup
;
1067 DPQ_FIND_ENTRY( This
->dp2
->lpSysGroup
->groups
, groups
, lpGData
->dpid
, ==, dpid
, lpGroups
);
1070 if( lpGroups
== NULL
)
1075 return lpGroups
->lpGData
;
1078 static HRESULT DP_IF_CreateGroup
1079 ( IDirectPlay2AImpl
* This
, LPVOID lpMsgHdr
, LPDPID lpidGroup
,
1080 LPDPNAME lpGroupName
, LPVOID lpData
, DWORD dwDataSize
,
1081 DWORD dwFlags
, BOOL bAnsi
)
1083 lpGroupData lpGData
;
1085 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1086 This
, lpMsgHdr
, lpidGroup
, lpGroupName
, lpData
, dwDataSize
,
1089 /* If the name is not specified, we must provide one */
1090 if( DPID_UNKNOWN
== *lpidGroup
)
1092 /* If we are the name server, we decide on the group ids. If not, we
1093 * must ask for one before attempting a creation.
1095 if( This
->dp2
->bHostInterface
)
1097 *lpidGroup
= DP_NextObjectId();
1101 *lpidGroup
= DP_GetRemoteNextObjectId();
1105 lpGData
= DP_CreateGroup( This
, lpidGroup
, lpGroupName
, dwFlags
,
1106 DPID_NOPARENT_GROUP
, bAnsi
);
1108 if( lpGData
== NULL
)
1110 return DPERR_CANTADDPLAYER
; /* yes player not group */
1113 if( DPID_SYSTEM_GROUP
== *lpidGroup
)
1115 This
->dp2
->lpSysGroup
= lpGData
;
1116 TRACE( "Inserting system group\n" );
1120 /* Insert into the system group */
1121 lpGroupList lpGroup
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpGroup
) );
1122 lpGroup
->lpGData
= lpGData
;
1124 DPQ_INSERT( This
->dp2
->lpSysGroup
->groups
, lpGroup
, groups
);
1127 /* Something is now referencing this data */
1130 /* Set all the important stuff for the group */
1131 DP_SetGroupData( lpGData
, DPSET_REMOTE
, lpData
, dwDataSize
);
1133 /* FIXME: We should only create the system group if GetCaps returns
1134 * DPCAPS_GROUPOPTIMIZED.
1137 /* Let the SP know that we've created this group */
1138 if( This
->dp2
->spData
.lpCB
->CreateGroup
)
1140 DPSP_CREATEGROUPDATA data
;
1141 DWORD dwCreateFlags
= 0;
1143 TRACE( "Calling SP CreateGroup\n" );
1145 if( *lpidGroup
== DPID_NOPARENT_GROUP
)
1146 dwCreateFlags
|= DPLAYI_GROUP_SYSGROUP
;
1148 if( lpMsgHdr
== NULL
)
1149 dwCreateFlags
|= DPLAYI_PLAYER_PLAYERLOCAL
;
1151 if( dwFlags
& DPGROUP_HIDDEN
)
1152 dwCreateFlags
|= DPLAYI_GROUP_HIDDEN
;
1154 data
.idGroup
= *lpidGroup
;
1155 data
.dwFlags
= dwCreateFlags
;
1156 data
.lpSPMessageHeader
= lpMsgHdr
;
1157 data
.lpISP
= This
->dp2
->spData
.lpISP
;
1159 (*This
->dp2
->spData
.lpCB
->CreateGroup
)( &data
);
1162 /* Inform all other peers of the creation of a new group. If there are
1163 * no peers keep this event quiet.
1164 * Also if this message was sent to us, don't rebroadcast.
1166 if( ( lpMsgHdr
== NULL
) &&
1167 This
->dp2
->lpSessionDesc
&&
1168 ( This
->dp2
->lpSessionDesc
->dwFlags
& DPSESSION_MULTICASTSERVER
) )
1170 DPMSG_CREATEPLAYERORGROUP msg
;
1171 msg
.dwType
= DPSYS_CREATEPLAYERORGROUP
;
1173 msg
.dwPlayerType
= DPPLAYERTYPE_GROUP
;
1174 msg
.dpId
= *lpidGroup
;
1175 msg
.dwCurrentPlayers
= 0; /* FIXME: Incorrect? */
1176 msg
.lpData
= lpData
;
1177 msg
.dwDataSize
= dwDataSize
;
1178 msg
.dpnName
= *lpGroupName
;
1179 msg
.dpIdParent
= DPID_NOPARENT_GROUP
;
1180 msg
.dwFlags
= DPMSG_CREATEGROUP_DWFLAGS( dwFlags
);
1182 /* FIXME: Correct to just use send effectively? */
1183 /* FIXME: Should size include data w/ message or just message "header" */
1184 /* FIXME: Check return code */
1185 DP_SendEx( This
, DPID_SERVERPLAYER
, DPID_ALLPLAYERS
, 0, &msg
, sizeof( msg
),
1186 0, 0, NULL
, NULL
, bAnsi
);
1192 static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
1193 ( LPDIRECTPLAY2A iface
, LPDPID lpidGroup
, LPDPNAME lpGroupName
,
1194 LPVOID lpData
, DWORD dwDataSize
, DWORD dwFlags
)
1196 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
1198 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
1200 return DPERR_UNINITIALIZED
;
1203 if( lpidGroup
== NULL
||
1204 !This
->dp2
->bConnectionOpen
||
1205 dwDataSize
>= MAXDWORD
||
1206 ( lpData
== NULL
&& dwDataSize
!= 0 ) )
1208 return DPERR_INVALIDPARAMS
;
1211 *lpidGroup
= DPID_UNKNOWN
;
1213 return DP_IF_CreateGroup( This
, NULL
, lpidGroup
,
1214 lpGroupName
, lpData
, dwDataSize
, dwFlags
, TRUE
);
1217 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
1218 ( LPDIRECTPLAY2 iface
, LPDPID lpidGroup
, LPDPNAME lpGroupName
,
1219 LPVOID lpData
, DWORD dwDataSize
, DWORD dwFlags
)
1221 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
1223 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
1225 return DPERR_UNINITIALIZED
;
1228 if( lpidGroup
== NULL
||
1229 !This
->dp2
->bConnectionOpen
||
1230 dwDataSize
>= MAXDWORD
||
1231 ( lpData
== NULL
&& dwDataSize
!= 0 ) )
1233 return DPERR_INVALIDPARAMS
;
1236 *lpidGroup
= DPID_UNKNOWN
;
1238 return DP_IF_CreateGroup( This
, NULL
, lpidGroup
,
1239 lpGroupName
, lpData
, dwDataSize
, dwFlags
, FALSE
);
1244 DP_SetGroupData( lpGroupData lpGData
, DWORD dwFlags
,
1245 LPVOID lpData
, DWORD dwDataSize
)
1247 /* Clear out the data with this player */
1248 if( dwFlags
& DPSET_LOCAL
)
1250 if ( lpGData
->dwLocalDataSize
!= 0 )
1252 HeapFree( GetProcessHeap(), 0, lpGData
->lpLocalData
);
1253 lpGData
->lpLocalData
= NULL
;
1254 lpGData
->dwLocalDataSize
= 0;
1259 if( lpGData
->dwRemoteDataSize
!= 0 )
1261 HeapFree( GetProcessHeap(), 0, lpGData
->lpRemoteData
);
1262 lpGData
->lpRemoteData
= NULL
;
1263 lpGData
->dwRemoteDataSize
= 0;
1267 /* Reallocate for new data */
1268 if( lpData
!= NULL
)
1270 LPVOID lpNewData
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
1271 sizeof( dwDataSize
) );
1272 CopyMemory( lpNewData
, lpData
, dwDataSize
);
1274 if( dwFlags
& DPSET_LOCAL
)
1276 lpGData
->lpLocalData
= lpData
;
1277 lpGData
->dwLocalDataSize
= dwDataSize
;
1281 lpGData
->lpRemoteData
= lpNewData
;
1282 lpGData
->dwRemoteDataSize
= dwDataSize
;
1289 HRESULT
DP_CreatePlayer( IDirectPlay2Impl
* This
, DPID idPlayer
,
1290 LPDPNAME lpName
, DWORD dwFlags
,
1291 LPVOID lpData
, DWORD dwDataSize
,
1292 HANDLE hEvent
, BOOL bAnsi
,
1293 lpPlayerData
* lplpPlayer
)
1295 /* Create the storage for a new player and insert
1296 * it in the list of players. */
1298 lpPlayerList lpPList
= NULL
;
1299 lpPlayerData lpPlayer
;
1302 TRACE( "(%p)->(0x%08x,%p,0x%08x,%p,%d,%p,%u,%p)\n",
1303 This
, idPlayer
, lpName
, dwFlags
, lpData
,
1304 dwDataSize
, hEvent
, bAnsi
, lplpPlayer
);
1306 /* Verify that we don't already have this player */
1307 DPQ_FIND_ENTRY( This
->dp2
->lpSysGroup
->players
, players
,
1308 lpPData
->dpid
, ==, idPlayer
, lpPList
);
1309 if ( lpPList
!= NULL
)
1311 hr
= DPERR_CANTCREATEPLAYER
;
1315 /* Allocate the storage for the player and associate it with list element */
1316 lpPlayer
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpPlayer
) );
1317 if( lpPlayer
== NULL
)
1319 hr
= DPERR_CANTCREATEPLAYER
;
1323 if ( lplpPlayer
!= NULL
)
1325 *lplpPlayer
= lpPlayer
;
1328 lpPlayer
->dpid
= idPlayer
;
1329 lpPlayer
->dwFlags
= dwFlags
;
1331 DP_CopyDPNAMEStruct( &lpPlayer
->name
, lpName
, bAnsi
);
1333 /* If we were given an event handle, duplicate it */
1336 if( !DuplicateHandle( GetCurrentProcess(), hEvent
,
1337 GetCurrentProcess(), &lpPlayer
->hEvent
,
1338 0, FALSE
, DUPLICATE_SAME_ACCESS
) )
1340 ERR( "Can't duplicate player msg handle %p\n", hEvent
);
1341 hr
= DPERR_CANTCREATEPLAYER
;
1346 /* Set player data */
1347 if ( lpData
!= NULL
)
1349 DP_SetPlayerData( lpPlayer
, DPSET_REMOTE
, lpData
, dwDataSize
);
1352 /* Initialize the SP data section */
1353 lpPlayer
->lpSPPlayerData
= DPSP_CreateSPPlayerData();
1355 if( ~dwFlags
& DPLAYI_PLAYER_SYSPLAYER
)
1357 This
->dp2
->lpSessionDesc
->dwCurrentPlayers
++;
1360 /* Create the list object and link it in */
1361 lpPList
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpPList
) );
1362 if( lpPList
== NULL
)
1364 hr
= DPERR_CANTADDPLAYER
;
1369 lpPList
->lpPData
= lpPlayer
;
1371 /* Add the player to the system group */
1372 DPQ_INSERT( This
->dp2
->lpSysGroup
->players
, lpPList
, players
);
1375 if ( ~dwFlags
& DPLAYI_PLAYER_PLAYERLOCAL
) {
1376 lpPlayerList lpPList
;
1378 HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct DPMSG
) );
1379 LPDPMSG_CREATEPLAYERORGROUP msg
=
1380 HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(DPMSG_CREATEPLAYERORGROUP
) );
1382 msg
->dwType
= DPSYS_CREATEPLAYERORGROUP
;
1383 msg
->dwPlayerType
= DPPLAYERTYPE_PLAYER
;
1384 msg
->dpId
= idPlayer
;
1385 msg
->dwCurrentPlayers
= This
->dp2
->lpSessionDesc
->dwCurrentPlayers
;
1386 msg
->lpData
= NULL
;/*TODO*/
1387 msg
->dwDataSize
= 0;/*TODO*/
1388 msg
->dpIdParent
= DPID_NOPARENT_GROUP
;
1389 msg
->dwFlags
= DPMSG_CREATEPLAYER_DWFLAGS( dwFlags
);
1392 msg
->dpnName
= *lpName
;
1395 lpMsg
->msg
= (LPDPMSG_GENERIC
) msg
;
1396 lpMsg
->dwMsgSize
= sizeof(LPDPMSG_CREATEPLAYERORGROUP
);
1397 DPQ_INSERT( This
->dp2
->receiveMsgs
, lpMsg
, msgs
);
1399 if ( (lpPList
= DPQ_FIRST( This
->dp2
->lpSysGroup
->players
)) )
1403 if ( ( lpPList
->lpPData
->dwFlags
& DPLAYI_PLAYER_PLAYERLOCAL
) &&
1404 lpPList
->lpPData
->hEvent
)
1406 SetEvent( lpPList
->lpPData
->hEvent
);
1409 while( (lpPList
= DPQ_NEXT( lpPList
->players
)) );
1416 DP_DeletePlayer( This
, idPlayer
);
1421 /* Delete the contents of the DPNAME struct */
1423 DP_DeleteDPNameStruct( LPDPNAME lpDPName
)
1425 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY
, lpDPName
->u1
.lpszShortNameA
);
1426 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY
, lpDPName
->u2
.lpszLongNameA
);
1429 /* This method assumes that all links to it are already deleted */
1431 DP_DeletePlayer( IDirectPlay2Impl
* This
, DPID dpid
)
1433 lpPlayerList lpPList
;
1435 TRACE( "(%p)->(0x%08x)\n", This
, dpid
);
1437 DPQ_REMOVE_ENTRY( This
->dp2
->lpSysGroup
->players
, players
, lpPData
->dpid
, ==, dpid
, lpPList
);
1439 if( lpPList
== NULL
)
1441 ERR( "DPID 0x%08x not found\n", dpid
);
1445 /* Verify that this is the last reference to the data */
1446 if( --(lpPList
->lpPData
->uRef
) )
1448 FIXME( "Why is this not the last reference to player?\n" );
1453 DP_DeleteDPNameStruct( &lpPList
->lpPData
->name
);
1455 CloseHandle( lpPList
->lpPData
->hEvent
);
1456 HeapFree( GetProcessHeap(), 0, lpPList
->lpPData
);
1458 /* Delete Player List object */
1459 HeapFree( GetProcessHeap(), 0, lpPList
);
1462 lpPlayerList
DP_FindPlayer( IDirectPlay2AImpl
* This
, DPID dpid
)
1464 lpPlayerList lpPlayers
;
1466 TRACE( "(%p)->(0x%08x)\n", This
, dpid
);
1468 if(This
->dp2
->lpSysGroup
== NULL
)
1471 DPQ_FIND_ENTRY( This
->dp2
->lpSysGroup
->players
, players
, lpPData
->dpid
, ==, dpid
, lpPlayers
);
1476 /* Basic area for Dst must already be allocated */
1477 static BOOL
DP_CopyDPNAMEStruct( LPDPNAME lpDst
, const DPNAME
*lpSrc
, BOOL bAnsi
)
1481 ZeroMemory( lpDst
, sizeof( *lpDst
) );
1482 lpDst
->dwSize
= sizeof( *lpDst
);
1486 if( lpSrc
->dwSize
!= sizeof( *lpSrc
) )
1491 /* Delete any existing pointers */
1492 HeapFree( GetProcessHeap(), 0, lpDst
->u1
.lpszShortNameA
);
1493 HeapFree( GetProcessHeap(), 0, lpDst
->u2
.lpszLongNameA
);
1495 /* Copy as required */
1496 CopyMemory( lpDst
, lpSrc
, lpSrc
->dwSize
);
1500 if( lpSrc
->u1
.lpszShortNameA
)
1502 lpDst
->u1
.lpszShortNameA
= HeapAlloc( GetProcessHeap(), 0,
1503 strlen(lpSrc
->u1
.lpszShortNameA
)+1 );
1504 strcpy( lpDst
->u1
.lpszShortNameA
, lpSrc
->u1
.lpszShortNameA
);
1508 lpDst
->u1
.lpszShortNameA
= NULL
;
1510 if( lpSrc
->u2
.lpszLongNameA
)
1512 lpDst
->u2
.lpszLongNameA
= HeapAlloc( GetProcessHeap(), 0,
1513 strlen(lpSrc
->u2
.lpszLongNameA
)+1 );
1514 strcpy( lpDst
->u2
.lpszLongNameA
, lpSrc
->u2
.lpszLongNameA
);
1518 lpDst
->u2
.lpszLongNameA
= NULL
;
1523 if( lpSrc
->u1
.lpszShortNameA
)
1525 lpDst
->u1
.lpszShortName
= HeapAlloc( GetProcessHeap(), 0,
1526 (strlenW(lpSrc
->u1
.lpszShortName
)+1)*sizeof(WCHAR
) );
1527 strcpyW( lpDst
->u1
.lpszShortName
, lpSrc
->u1
.lpszShortName
);
1531 lpDst
->u1
.lpszShortNameA
= NULL
;
1533 if( lpSrc
->u2
.lpszLongNameA
)
1535 lpDst
->u2
.lpszLongName
= HeapAlloc( GetProcessHeap(), 0,
1536 (strlenW(lpSrc
->u2
.lpszLongName
)+1)*sizeof(WCHAR
) );
1537 strcpyW( lpDst
->u2
.lpszLongName
, lpSrc
->u2
.lpszLongName
);
1541 lpDst
->u2
.lpszLongNameA
= NULL
;
1549 DP_SetPlayerData( lpPlayerData lpPData
, DWORD dwFlags
,
1550 LPVOID lpData
, DWORD dwDataSize
)
1552 /* Clear out the data with this player */
1553 if( dwFlags
& DPSET_LOCAL
)
1555 if ( lpPData
->dwLocalDataSize
!= 0 )
1557 HeapFree( GetProcessHeap(), 0, lpPData
->lpLocalData
);
1558 lpPData
->lpLocalData
= NULL
;
1559 lpPData
->dwLocalDataSize
= 0;
1564 if( lpPData
->dwRemoteDataSize
!= 0 )
1566 HeapFree( GetProcessHeap(), 0, lpPData
->lpRemoteData
);
1567 lpPData
->lpRemoteData
= NULL
;
1568 lpPData
->dwRemoteDataSize
= 0;
1572 /* Reallocate for new data */
1573 if( lpData
!= NULL
)
1575 LPVOID lpNewData
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
1576 sizeof( dwDataSize
) );
1577 CopyMemory( lpNewData
, lpData
, dwDataSize
);
1579 if( dwFlags
& DPSET_LOCAL
)
1581 lpPData
->lpLocalData
= lpData
;
1582 lpPData
->dwLocalDataSize
= dwDataSize
;
1586 lpPData
->lpRemoteData
= lpNewData
;
1587 lpPData
->dwRemoteDataSize
= dwDataSize
;
1593 static HRESULT DP_IF_CreatePlayer
1594 ( IDirectPlay2Impl
* This
,
1595 LPVOID lpMsgHdr
, /* NULL for local creation, non NULL for remote creation */
1597 LPDPNAME lpPlayerName
,
1605 lpPlayerData lpPData
;
1607 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1608 This
, lpidPlayer
, lpPlayerName
, hEvent
, lpData
,
1609 dwDataSize
, dwFlags
, bAnsi
);
1613 dwFlags
= DPPLAYER_SPECTATOR
;
1616 if( lpidPlayer
== NULL
)
1618 return DPERR_INVALIDPARAMS
;
1622 /* Determine the creation flags for the player. These will be passed
1623 * to the name server if requesting a player id and to the SP when
1624 * informing it of the player creation
1627 if( dwFlags
& DPPLAYER_SERVERPLAYER
)
1629 if( *lpidPlayer
== DPID_SERVERPLAYER
)
1631 /* Server player for the host interface */
1632 dwFlags
|= DPLAYI_PLAYER_APPSERVER
;
1634 else if( *lpidPlayer
== DPID_NAME_SERVER
)
1636 /* Name server - master of everything */
1637 dwFlags
|= (DPLAYI_PLAYER_NAMESRVR
|DPLAYI_PLAYER_SYSPLAYER
);
1641 /* Server player for a non host interface */
1642 dwFlags
|= DPLAYI_PLAYER_SYSPLAYER
;
1646 if( lpMsgHdr
== NULL
)
1647 dwFlags
|= DPLAYI_PLAYER_PLAYERLOCAL
;
1650 /* Verify we know how to handle all the flags */
1651 if( !( ( dwFlags
& DPPLAYER_SERVERPLAYER
) ||
1652 ( dwFlags
& DPPLAYER_SPECTATOR
)
1656 /* Assume non fatal failure */
1657 ERR( "unknown dwFlags = 0x%08x\n", dwFlags
);
1660 /* If the name is not specified, we must provide one */
1661 if( *lpidPlayer
== DPID_UNKNOWN
)
1663 /* If we are the session master, we dish out the group/player ids */
1664 if( This
->dp2
->bHostInterface
)
1666 *lpidPlayer
= DP_NextObjectId();
1670 hr
= DP_MSG_SendRequestPlayerId( This
, dwFlags
& 0x000000FF, lpidPlayer
);
1674 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr
) );
1680 hr
= DP_CreatePlayer( This
, *lpidPlayer
, lpPlayerName
, dwFlags
,
1681 lpData
, dwDataSize
, hEvent
, bAnsi
,
1688 /* Let the SP know that we've created this player */
1689 if( This
->dp2
->spData
.lpCB
->CreatePlayer
)
1691 DPSP_CREATEPLAYERDATA data
;
1693 data
.idPlayer
= *lpidPlayer
;
1694 data
.dwFlags
= dwFlags
;
1695 data
.lpSPMessageHeader
= lpMsgHdr
;
1696 data
.lpISP
= This
->dp2
->spData
.lpISP
;
1698 TRACE( "Calling SP CreatePlayer 0x%08x: dwFlags: 0x%08x lpMsgHdr: %p\n",
1699 *lpidPlayer
, data
.dwFlags
, data
.lpSPMessageHeader
);
1701 hr
= (*This
->dp2
->spData
.lpCB
->CreatePlayer
)( &data
);
1706 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr
) );
1710 /* Now let the SP know that this player is a member of the system group */
1711 if( This
->dp2
->spData
.lpCB
->AddPlayerToGroup
)
1713 DPSP_ADDPLAYERTOGROUPDATA data
;
1715 data
.idPlayer
= *lpidPlayer
;
1716 data
.idGroup
= DPID_SYSTEM_GROUP
;
1717 data
.lpISP
= This
->dp2
->spData
.lpISP
;
1719 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1721 hr
= (*This
->dp2
->spData
.lpCB
->AddPlayerToGroup
)( &data
);
1726 ERR( "Failed to add player to sys group with sp: %s\n",
1727 DPLAYX_HresultToString(hr
) );
1732 if ( ( ! This
->dp2
->bHostInterface
) && ( lpMsgHdr
== NULL
) )
1734 if ( dwFlags
& DPLAYI_PLAYER_SYSPLAYER
)
1736 /* Let the name server know about the creation of this player,
1737 * and reeceive the name table */
1738 hr
= DP_MSG_ForwardPlayerCreation( This
, *lpidPlayer
);
1742 /* Inform all other peers of the creation of a new player.
1743 * Also, if this was a remote event, no need to rebroadcast it. */
1744 hr
= DP_MSG_SendCreatePlayer( This
, lpPData
);
1751 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
1752 ( LPDIRECTPLAY2A iface
, LPDPID lpidPlayer
, LPDPNAME lpPlayerName
,
1753 HANDLE hEvent
, LPVOID lpData
, DWORD dwDataSize
, DWORD dwFlags
)
1755 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
1757 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
1759 return DPERR_UNINITIALIZED
;
1762 if( lpidPlayer
== NULL
|| !This
->dp2
->bConnectionOpen
)
1764 return DPERR_INVALIDPARAMS
;
1767 if ( This
->dp2
->lpSessionDesc
->dwFlags
& DPSESSION_NEWPLAYERSDISABLED
)
1769 return DPERR_CANTCREATEPLAYER
;
1772 if( dwFlags
& DPPLAYER_SERVERPLAYER
)
1774 *lpidPlayer
= DPID_SERVERPLAYER
;
1778 *lpidPlayer
= DPID_UNKNOWN
;
1781 return DP_IF_CreatePlayer( This
, NULL
, lpidPlayer
, lpPlayerName
, hEvent
,
1782 lpData
, dwDataSize
, dwFlags
, TRUE
);
1785 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
1786 ( LPDIRECTPLAY2 iface
, LPDPID lpidPlayer
, LPDPNAME lpPlayerName
,
1787 HANDLE hEvent
, LPVOID lpData
, DWORD dwDataSize
, DWORD dwFlags
)
1789 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
1791 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
1793 return DPERR_UNINITIALIZED
;
1796 if( lpidPlayer
== NULL
|| !This
->dp2
->bConnectionOpen
)
1798 return DPERR_INVALIDPARAMS
;
1801 if ( This
->dp2
->lpSessionDesc
->dwFlags
& DPSESSION_NEWPLAYERSDISABLED
)
1803 return DPERR_CANTCREATEPLAYER
;
1806 if( dwFlags
& DPPLAYER_SERVERPLAYER
)
1808 *lpidPlayer
= DPID_SERVERPLAYER
;
1812 *lpidPlayer
= DPID_UNKNOWN
;
1815 return DP_IF_CreatePlayer( This
, NULL
, lpidPlayer
, lpPlayerName
, hEvent
,
1816 lpData
, dwDataSize
, dwFlags
, FALSE
);
1819 static DPID
DP_GetRemoteNextObjectId(void)
1824 return DP_NextObjectId();
1827 static HRESULT DP_IF_DeletePlayerFromGroup
1828 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idGroup
,
1829 DPID idPlayer
, BOOL bAnsi
)
1833 lpGroupData lpGData
;
1834 lpPlayerList lpPList
;
1836 TRACE( "(%p)->(%p,0x%08x,0x%08x,%u)\n",
1837 This
, lpMsgHdr
, idGroup
, idPlayer
, bAnsi
);
1839 /* Find the group */
1840 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
1842 return DPERR_INVALIDGROUP
;
1845 /* Find the player */
1846 if( ( lpPList
= DP_FindPlayer( This
, idPlayer
) ) == NULL
)
1848 return DPERR_INVALIDPLAYER
;
1851 /* Remove the player shortcut from the group */
1852 DPQ_REMOVE_ENTRY( lpGData
->players
, players
, lpPData
->dpid
, ==, idPlayer
, lpPList
);
1854 if( lpPList
== NULL
)
1856 return DPERR_INVALIDPLAYER
;
1859 /* One less reference */
1860 lpPList
->lpPData
->uRef
--;
1862 /* Delete the Player List element */
1863 HeapFree( GetProcessHeap(), 0, lpPList
);
1865 /* Inform the SP if they care */
1866 if( This
->dp2
->spData
.lpCB
->RemovePlayerFromGroup
)
1868 DPSP_REMOVEPLAYERFROMGROUPDATA data
;
1870 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1872 data
.idPlayer
= idPlayer
;
1873 data
.idGroup
= idGroup
;
1874 data
.lpISP
= This
->dp2
->spData
.lpISP
;
1876 hr
= (*This
->dp2
->spData
.lpCB
->RemovePlayerFromGroup
)( &data
);
1879 /* Need to send a DELETEPLAYERFROMGROUP message */
1880 FIXME( "Need to send a message\n" );
1885 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
1886 ( LPDIRECTPLAY2A iface
, DPID idGroup
, DPID idPlayer
)
1888 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
1889 return DP_IF_DeletePlayerFromGroup( This
, NULL
, idGroup
, idPlayer
, TRUE
);
1892 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
1893 ( LPDIRECTPLAY2 iface
, DPID idGroup
, DPID idPlayer
)
1895 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
1896 return DP_IF_DeletePlayerFromGroup( This
, NULL
, idGroup
, idPlayer
, FALSE
);
1899 typedef struct _DPRGOPContext
1901 IDirectPlay3Impl
* This
;
1904 } DPRGOPContext
, *lpDPRGOPContext
;
1906 static BOOL CALLBACK
1907 cbRemoveGroupOrPlayer(
1914 lpDPRGOPContext lpCtxt
= (lpDPRGOPContext
)lpContext
;
1916 TRACE( "Removing element:0x%08x (type:0x%08x) from element:0x%08x\n",
1917 dpId
, dwPlayerType
, lpCtxt
->idGroup
);
1919 if( dwPlayerType
== DPPLAYERTYPE_GROUP
)
1921 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt
->This
, lpCtxt
->idGroup
,
1926 ERR( "Unable to delete group 0x%08x from group 0x%08x\n",
1927 dpId
, lpCtxt
->idGroup
);
1932 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl
*)lpCtxt
->This
,
1933 NULL
, lpCtxt
->idGroup
,
1934 dpId
, lpCtxt
->bAnsi
)
1938 ERR( "Unable to delete player 0x%08x from grp 0x%08x\n",
1939 dpId
, lpCtxt
->idGroup
);
1943 return TRUE
; /* Continue enumeration */
1946 static HRESULT DP_IF_DestroyGroup
1947 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idGroup
, BOOL bAnsi
)
1949 lpGroupData lpGData
;
1950 DPRGOPContext context
;
1952 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1953 This
, lpMsgHdr
, idGroup
, bAnsi
);
1955 /* Find the group */
1956 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
1958 return DPERR_INVALIDPLAYER
; /* yes player */
1961 context
.This
= (IDirectPlay3Impl
*)This
;
1962 context
.bAnsi
= bAnsi
;
1963 context
.idGroup
= idGroup
;
1965 /* Remove all players that this group has */
1966 DP_IF_EnumGroupPlayers( This
, idGroup
, NULL
,
1967 cbRemoveGroupOrPlayer
, &context
, 0, bAnsi
);
1969 /* Remove all links to groups that this group has since this is dp3 */
1970 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl
*)This
, idGroup
, NULL
,
1971 cbRemoveGroupOrPlayer
, (LPVOID
)&context
, 0, bAnsi
);
1973 /* Remove this group from the parent group - if it has one */
1974 if( ( idGroup
!= DPID_SYSTEM_GROUP
) &&
1975 ( lpGData
->parent
!= DPID_SYSTEM_GROUP
)
1978 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl
*)This
, lpGData
->parent
,
1982 /* Now delete this group data and list from the system group */
1983 DP_DeleteGroup( This
, idGroup
);
1985 /* Let the SP know that we've destroyed this group */
1986 if( This
->dp2
->spData
.lpCB
->DeleteGroup
)
1988 DPSP_DELETEGROUPDATA data
;
1990 FIXME( "data.dwFlags is incorrect\n" );
1992 data
.idGroup
= idGroup
;
1994 data
.lpISP
= This
->dp2
->spData
.lpISP
;
1996 (*This
->dp2
->spData
.lpCB
->DeleteGroup
)( &data
);
1999 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
2004 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
2005 ( LPDIRECTPLAY2A iface
, DPID idGroup
)
2007 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2008 return DP_IF_DestroyGroup( This
, NULL
, idGroup
, TRUE
);
2011 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
2012 ( LPDIRECTPLAY2 iface
, DPID idGroup
)
2014 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2015 return DP_IF_DestroyGroup( This
, NULL
, idGroup
, FALSE
);
2018 typedef struct _DPFAGContext
2020 IDirectPlay2Impl
* This
;
2023 } DPFAGContext
, *lpDPFAGContext
;
2025 static HRESULT DP_IF_DestroyPlayer
2026 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idPlayer
, BOOL bAnsi
)
2028 DPFAGContext cbContext
;
2030 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
2031 This
, lpMsgHdr
, idPlayer
, bAnsi
);
2033 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
2035 return DPERR_UNINITIALIZED
;
2038 if( DP_FindPlayer( This
, idPlayer
) == NULL
)
2040 return DPERR_INVALIDPLAYER
;
2043 /* FIXME: If the player is remote, we must be the host to delete this */
2045 cbContext
.This
= This
;
2046 cbContext
.idPlayer
= idPlayer
;
2047 cbContext
.bAnsi
= bAnsi
;
2049 /* Find each group and call DeletePlayerFromGroup if the player is a
2050 member of the group */
2051 DP_IF_EnumGroups( This
, NULL
, cbDeletePlayerFromAllGroups
,
2052 &cbContext
, DPENUMGROUPS_ALL
, bAnsi
);
2054 /* Now delete player and player list from the sys group */
2055 DP_DeletePlayer( This
, idPlayer
);
2057 /* Let the SP know that we've destroyed this group */
2058 if( This
->dp2
->spData
.lpCB
->DeletePlayer
)
2060 DPSP_DELETEPLAYERDATA data
;
2062 FIXME( "data.dwFlags is incorrect\n" );
2064 data
.idPlayer
= idPlayer
;
2066 data
.lpISP
= This
->dp2
->spData
.lpISP
;
2068 (*This
->dp2
->spData
.lpCB
->DeletePlayer
)( &data
);
2071 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
2076 static BOOL CALLBACK
2077 cbDeletePlayerFromAllGroups(
2084 lpDPFAGContext lpCtxt
= (lpDPFAGContext
)lpContext
;
2086 if( dwPlayerType
== DPPLAYERTYPE_GROUP
)
2088 DP_IF_DeletePlayerFromGroup( lpCtxt
->This
, NULL
, dpId
, lpCtxt
->idPlayer
,
2091 /* Enumerate all groups in this group since this will normally only
2092 * be called for top level groups
2094 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl
*)lpCtxt
->This
,
2096 cbDeletePlayerFromAllGroups
,
2097 lpContext
, DPENUMGROUPS_ALL
,
2103 ERR( "Group callback has dwPlayerType = 0x%08x\n", dwPlayerType
);
2109 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
2110 ( LPDIRECTPLAY2A iface
, DPID idPlayer
)
2112 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2113 return DP_IF_DestroyPlayer( This
, NULL
, idPlayer
, TRUE
);
2116 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
2117 ( LPDIRECTPLAY2 iface
, DPID idPlayer
)
2119 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2120 return DP_IF_DestroyPlayer( This
, NULL
, idPlayer
, FALSE
);
2123 static HRESULT DP_IF_EnumGroupPlayers
2124 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPGUID lpguidInstance
,
2125 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2126 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
)
2128 lpGroupData lpGData
;
2129 lpPlayerList lpPList
;
2131 FIXME("(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
2132 This
, idGroup
, lpguidInstance
, lpEnumPlayersCallback2
,
2133 lpContext
, dwFlags
, bAnsi
);
2135 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
2137 return DPERR_UNINITIALIZED
;
2140 if( !This
->dp2
->bConnectionOpen
)
2142 return DPERR_NOSESSIONS
;
2145 if( ( lpEnumPlayersCallback2
== NULL
) ||
2146 ( ( dwFlags
& DPENUMPLAYERS_SESSION
) && ( lpguidInstance
== NULL
) ) )
2148 return DPERR_INVALIDPARAMS
;
2151 /* Find the group */
2152 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
2154 return DPERR_INVALIDGROUP
;
2157 if( DPQ_IS_EMPTY( lpGData
->players
) )
2162 lpPList
= DPQ_FIRST( lpGData
->players
);
2164 /* Walk the players in this group */
2167 /* We do not enum the name server or app server as they are of no
2168 * consequence to the end user.
2170 if( ( lpPList
->lpPData
->dpid
!= DPID_NAME_SERVER
) &&
2171 ( lpPList
->lpPData
->dpid
!= DPID_SERVERPLAYER
)
2175 /* FIXME: Need to add stuff for dwFlags checking */
2177 if( !lpEnumPlayersCallback2( lpPList
->lpPData
->dpid
, DPPLAYERTYPE_PLAYER
,
2178 &lpPList
->lpPData
->name
,
2179 lpPList
->lpPData
->dwFlags
,
2183 /* User requested break */
2188 if( DPQ_IS_ENDOFLIST( lpPList
->players
) )
2193 lpPList
= DPQ_NEXT( lpPList
->players
);
2199 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
2200 ( LPDIRECTPLAY2A iface
, DPID idGroup
, LPGUID lpguidInstance
,
2201 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2202 LPVOID lpContext
, DWORD dwFlags
)
2204 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2205 return DP_IF_EnumGroupPlayers( This
, idGroup
, lpguidInstance
,
2206 lpEnumPlayersCallback2
, lpContext
,
2210 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
2211 ( LPDIRECTPLAY2 iface
, DPID idGroup
, LPGUID lpguidInstance
,
2212 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2213 LPVOID lpContext
, DWORD dwFlags
)
2215 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2216 return DP_IF_EnumGroupPlayers( This
, idGroup
, lpguidInstance
,
2217 lpEnumPlayersCallback2
, lpContext
,
2221 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2222 static HRESULT DP_IF_EnumGroups
2223 ( IDirectPlay2Impl
* This
, LPGUID lpguidInstance
,
2224 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2225 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
)
2227 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl
*)This
,
2228 DPID_SYSTEM_GROUP
, lpguidInstance
,
2229 lpEnumPlayersCallback2
, lpContext
,
2233 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
2234 ( LPDIRECTPLAY2A iface
, LPGUID lpguidInstance
,
2235 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2236 LPVOID lpContext
, DWORD dwFlags
)
2238 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2239 return DP_IF_EnumGroups( This
, lpguidInstance
, lpEnumPlayersCallback2
,
2240 lpContext
, dwFlags
, TRUE
);
2243 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
2244 ( LPDIRECTPLAY2 iface
, LPGUID lpguidInstance
,
2245 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2246 LPVOID lpContext
, DWORD dwFlags
)
2248 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2249 return DP_IF_EnumGroups( This
, lpguidInstance
, lpEnumPlayersCallback2
,
2250 lpContext
, dwFlags
, FALSE
);
2253 static HRESULT DP_IF_EnumPlayers
2254 ( IDirectPlay2Impl
* This
, LPGUID lpguidInstance
,
2255 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2256 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
)
2258 return DP_IF_EnumGroupPlayers( This
, DPID_SYSTEM_GROUP
, lpguidInstance
,
2259 lpEnumPlayersCallback2
, lpContext
,
2263 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
2264 ( LPDIRECTPLAY2A iface
, LPGUID lpguidInstance
,
2265 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2266 LPVOID lpContext
, DWORD dwFlags
)
2268 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2269 return DP_IF_EnumPlayers( This
, lpguidInstance
, lpEnumPlayersCallback2
,
2270 lpContext
, dwFlags
, TRUE
);
2273 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
2274 ( LPDIRECTPLAY2 iface
, LPGUID lpguidInstance
,
2275 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2276 LPVOID lpContext
, DWORD dwFlags
)
2278 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2279 return DP_IF_EnumPlayers( This
, lpguidInstance
, lpEnumPlayersCallback2
,
2280 lpContext
, dwFlags
, FALSE
);
2283 /* This function should call the registered callback function that the user
2284 passed into EnumSessions for each entry available.
2286 static void DP_InvokeEnumSessionCallbacks
2287 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2
,
2292 LPDPSESSIONDESC2 lpSessionDesc
;
2294 FIXME( ": not checking for conditions\n" );
2296 /* Not sure if this should be pruning but it's convenient */
2297 NS_PruneSessionCache( lpNSInfo
);
2299 NS_ResetSessionEnumeration( lpNSInfo
);
2301 /* Enumerate all sessions */
2302 /* FIXME: Need to indicate ANSI */
2303 while( (lpSessionDesc
= NS_WalkSessions( lpNSInfo
) ) != NULL
)
2305 TRACE( "EnumSessionsCallback2 invoked\n" );
2306 if( !lpEnumSessionsCallback2( lpSessionDesc
, &dwTimeout
, 0, lpContext
) )
2312 /* Invoke one last time to indicate that there is no more to come */
2313 lpEnumSessionsCallback2( NULL
, &dwTimeout
, DPESC_TIMEDOUT
, lpContext
);
2316 static DWORD CALLBACK
DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext
)
2318 EnumSessionAsyncCallbackData
* data
= lpContext
;
2319 HANDLE hSuicideRequest
= data
->hSuicideRequest
;
2320 DWORD dwTimeout
= data
->dwTimeout
;
2322 TRACE( "Thread started with timeout = 0x%08x\n", dwTimeout
);
2328 /* Sleep up to dwTimeout waiting for request to terminate thread */
2329 if( WaitForSingleObject( hSuicideRequest
, dwTimeout
) == WAIT_OBJECT_0
)
2331 TRACE( "Thread terminating on terminate request\n" );
2335 /* Now resend the enum request */
2336 hr
= NS_SendSessionRequestBroadcast( &data
->requestGuid
,
2337 data
->dwEnumSessionFlags
,
2342 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr
) );
2343 /* FIXME: Should we kill this thread? How to inform the main thread? */
2348 TRACE( "Thread terminating\n" );
2350 /* Clean up the thread data */
2351 CloseHandle( hSuicideRequest
);
2352 HeapFree( GetProcessHeap(), 0, lpContext
);
2354 /* FIXME: Need to have some notification to main app thread that this is
2355 * dead. It would serve two purposes. 1) allow sync on termination
2356 * so that we don't actually send something to ourselves when we
2357 * become name server (race condition) and 2) so that if we die
2358 * abnormally something else will be able to tell.
2364 static void DP_KillEnumSessionThread( IDirectPlay2Impl
* This
)
2366 /* Does a thread exist? If so we were doing an async enum session */
2367 if( This
->dp2
->hEnumSessionThread
!= INVALID_HANDLE_VALUE
)
2369 TRACE( "Killing EnumSession thread %p\n",
2370 This
->dp2
->hEnumSessionThread
);
2372 /* Request that the thread kill itself nicely */
2373 SetEvent( This
->dp2
->hKillEnumSessionThreadEvent
);
2374 CloseHandle( This
->dp2
->hKillEnumSessionThreadEvent
);
2376 /* We no longer need to know about the thread */
2377 CloseHandle( This
->dp2
->hEnumSessionThread
);
2379 This
->dp2
->hEnumSessionThread
= INVALID_HANDLE_VALUE
;
2383 static HRESULT DP_IF_EnumSessions
2384 ( IDirectPlay2Impl
* This
, LPDPSESSIONDESC2 lpsd
, DWORD dwTimeout
,
2385 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2
,
2386 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
)
2390 TRACE( "(%p)->(%p,0x%08x,%p,%p,0x%08x,%u)\n",
2391 This
, lpsd
, dwTimeout
, lpEnumSessionsCallback2
, lpContext
, dwFlags
,
2393 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
2395 return DPERR_UNINITIALIZED
;
2398 if( (lpsd
== NULL
) || (lpsd
->dwSize
!= sizeof(DPSESSIONDESC2
)) )
2400 return DPERR_INVALIDPARAMS
;
2403 /* Can't enumerate if the session is already open */
2404 if( This
->dp2
->bConnectionOpen
)
2406 return DPERR_GENERIC
;
2410 /* The loading of a lobby provider _seems_ to require a backdoor loading
2411 * of the service provider to also associate with this DP object. This is
2412 * because the app doesn't seem to have to call EnumConnections and
2413 * InitializeConnection for the SP before calling this method. As such
2414 * we'll do their dirty work for them with a quick hack so as to always
2415 * load the TCP/IP service provider.
2417 * The correct solution would seem to involve creating a dialog box which
2418 * contains the possible SPs. These dialog boxes most likely follow SDK
2421 if( This
->dp2
->bDPLSPInitialized
&& !This
->dp2
->bSPInitialized
)
2423 LPVOID lpConnection
;
2426 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2428 if( !DP_BuildCompoundAddr( DPAID_ServiceProvider
, (LPGUID
)&DPSPGUID_TCPIP
,
2429 &lpConnection
, &dwSize
) )
2431 ERR( "Can't build compound addr\n" );
2432 return DPERR_GENERIC
;
2435 hr
= DP_IF_InitializeConnection( (IDirectPlay3Impl
*)This
, lpConnection
,
2442 /* Free up the address buffer */
2443 HeapFree( GetProcessHeap(), 0, lpConnection
);
2445 /* The SP is now initialized */
2446 This
->dp2
->bSPInitialized
= TRUE
;
2451 /* Use the service provider default? */
2452 if( dwTimeout
== 0 )
2455 spCaps
.dwSize
= sizeof( spCaps
);
2457 DP_IF_GetCaps( This
, &spCaps
, 0 );
2458 dwTimeout
= spCaps
.dwTimeout
;
2460 /* The service provider doesn't provide one either! */
2461 if( dwTimeout
== 0 )
2463 /* Provide the TCP/IP default */
2464 dwTimeout
= DPMSG_WAIT_5_SECS
;
2468 if( dwFlags
& DPENUMSESSIONS_STOPASYNC
)
2470 DP_KillEnumSessionThread( This
);
2474 if( ( dwFlags
& DPENUMSESSIONS_ASYNC
) )
2476 /* Enumerate everything presently in the local session cache */
2477 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2
,
2478 This
->dp2
->lpNameServerData
, dwTimeout
,
2481 if( This
->dp2
->dwEnumSessionLock
!= 0 )
2482 return DPERR_CONNECTING
;
2484 /* See if we've already created a thread to service this interface */
2485 if( This
->dp2
->hEnumSessionThread
== INVALID_HANDLE_VALUE
)
2488 This
->dp2
->dwEnumSessionLock
++;
2490 /* Send the first enum request inline since the user may cancel a dialog
2491 * if one is presented. Also, may also have a connecting return code.
2493 hr
= NS_SendSessionRequestBroadcast( &lpsd
->guidApplication
,
2494 dwFlags
, &This
->dp2
->spData
);
2498 EnumSessionAsyncCallbackData
* lpData
2499 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpData
) );
2500 /* FIXME: need to kill the thread on object deletion */
2501 lpData
->lpSpData
= &This
->dp2
->spData
;
2503 lpData
->requestGuid
= lpsd
->guidApplication
;
2504 lpData
->dwEnumSessionFlags
= dwFlags
;
2505 lpData
->dwTimeout
= dwTimeout
;
2507 This
->dp2
->hKillEnumSessionThreadEvent
=
2508 CreateEventW( NULL
, TRUE
, FALSE
, NULL
);
2510 if( !DuplicateHandle( GetCurrentProcess(),
2511 This
->dp2
->hKillEnumSessionThreadEvent
,
2512 GetCurrentProcess(),
2513 &lpData
->hSuicideRequest
,
2514 0, FALSE
, DUPLICATE_SAME_ACCESS
)
2517 ERR( "Can't duplicate thread killing handle\n" );
2520 TRACE( ": creating EnumSessionsRequest thread\n" );
2522 This
->dp2
->hEnumSessionThread
= CreateThread( NULL
,
2524 DP_EnumSessionsSendAsyncRequestThread
,
2529 This
->dp2
->dwEnumSessionLock
--;
2534 /* Invalidate the session cache for the interface */
2535 NS_InvalidateSessionCache( This
->dp2
->lpNameServerData
);
2537 /* Send the broadcast for session enumeration */
2538 hr
= NS_SendSessionRequestBroadcast( &lpsd
->guidApplication
,
2540 &This
->dp2
->spData
);
2543 SleepEx( dwTimeout
, FALSE
);
2545 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2
,
2546 This
->dp2
->lpNameServerData
, dwTimeout
,
2553 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2554 ( LPDIRECTPLAY2A iface
, LPDPSESSIONDESC2 lpsd
, DWORD dwTimeout
,
2555 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2
,
2556 LPVOID lpContext
, DWORD dwFlags
)
2558 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2559 return DP_IF_EnumSessions( This
, lpsd
, dwTimeout
, lpEnumSessionsCallback2
,
2560 lpContext
, dwFlags
, TRUE
);
2563 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2564 ( LPDIRECTPLAY2 iface
, LPDPSESSIONDESC2 lpsd
, DWORD dwTimeout
,
2565 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2
,
2566 LPVOID lpContext
, DWORD dwFlags
)
2568 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2569 return DP_IF_EnumSessions( This
, lpsd
, dwTimeout
, lpEnumSessionsCallback2
,
2570 lpContext
, dwFlags
, FALSE
);
2573 static HRESULT DP_IF_GetPlayerCaps
2574 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPDPCAPS lpDPCaps
,
2577 DPSP_GETCAPSDATA data
;
2579 TRACE("(%p)->(0x%08x,%p,0x%08x)\n", This
, idPlayer
, lpDPCaps
, dwFlags
);
2581 if ( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
2583 return DPERR_UNINITIALIZED
;
2586 if ( lpDPCaps
->dwSize
!= sizeof(DPCAPS
) )
2588 return DPERR_INVALIDPARAMS
;
2591 /* Query the service provider */
2592 data
.idPlayer
= idPlayer
;
2593 data
.dwFlags
= dwFlags
;
2594 data
.lpCaps
= lpDPCaps
;
2595 data
.lpISP
= This
->dp2
->spData
.lpISP
;
2597 return (*This
->dp2
->spData
.lpCB
->GetCaps
)( &data
);
2600 static HRESULT DP_IF_GetCaps
2601 ( IDirectPlay2Impl
* This
, LPDPCAPS lpDPCaps
, DWORD dwFlags
)
2603 return DP_IF_GetPlayerCaps( This
, DPID_ALLPLAYERS
, lpDPCaps
, dwFlags
);
2606 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2607 ( LPDIRECTPLAY2A iface
, LPDPCAPS lpDPCaps
, DWORD dwFlags
)
2609 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2610 return DP_IF_GetCaps( This
, lpDPCaps
, dwFlags
);
2613 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2614 ( LPDIRECTPLAY2 iface
, LPDPCAPS lpDPCaps
, DWORD dwFlags
)
2616 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2617 return DP_IF_GetCaps( This
, lpDPCaps
, dwFlags
);
2620 static HRESULT DP_IF_GetGroupData
2621 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPVOID lpData
,
2622 LPDWORD lpdwDataSize
, DWORD dwFlags
, BOOL bAnsi
)
2624 lpGroupData lpGData
;
2625 DWORD dwRequiredBufferSize
;
2626 LPVOID lpCopyDataFrom
;
2628 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2629 This
, idGroup
, lpData
, lpdwDataSize
, dwFlags
, bAnsi
);
2631 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
2633 return DPERR_INVALIDGROUP
;
2636 /* How much buffer is required? */
2637 if( dwFlags
& DPSET_LOCAL
)
2639 dwRequiredBufferSize
= lpGData
->dwLocalDataSize
;
2640 lpCopyDataFrom
= lpGData
->lpLocalData
;
2644 dwRequiredBufferSize
= lpGData
->dwRemoteDataSize
;
2645 lpCopyDataFrom
= lpGData
->lpRemoteData
;
2648 /* Is the user requesting to know how big a buffer is required? */
2649 if( ( lpData
== NULL
) ||
2650 ( *lpdwDataSize
< dwRequiredBufferSize
)
2653 *lpdwDataSize
= dwRequiredBufferSize
;
2654 return DPERR_BUFFERTOOSMALL
;
2657 CopyMemory( lpData
, lpCopyDataFrom
, dwRequiredBufferSize
);
2662 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2663 ( LPDIRECTPLAY2A iface
, DPID idGroup
, LPVOID lpData
,
2664 LPDWORD lpdwDataSize
, DWORD dwFlags
)
2666 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2667 return DP_IF_GetGroupData( This
, idGroup
, lpData
, lpdwDataSize
,
2671 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2672 ( LPDIRECTPLAY2 iface
, DPID idGroup
, LPVOID lpData
,
2673 LPDWORD lpdwDataSize
, DWORD dwFlags
)
2675 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2676 return DP_IF_GetGroupData( This
, idGroup
, lpData
, lpdwDataSize
,
2680 static HRESULT DP_IF_GetGroupName
2681 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPVOID lpData
,
2682 LPDWORD lpdwDataSize
, BOOL bAnsi
)
2684 lpGroupData lpGData
;
2685 LPDPNAME lpName
= lpData
;
2686 DWORD dwRequiredDataSize
;
2688 FIXME("(%p)->(0x%08x,%p,%p,%u) ANSI ignored\n",
2689 This
, idGroup
, lpData
, lpdwDataSize
, bAnsi
);
2691 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
2693 return DPERR_INVALIDGROUP
;
2696 dwRequiredDataSize
= lpGData
->name
.dwSize
;
2698 if( lpGData
->name
.u1
.lpszShortNameA
)
2700 dwRequiredDataSize
+= strlen( lpGData
->name
.u1
.lpszShortNameA
) + 1;
2703 if( lpGData
->name
.u2
.lpszLongNameA
)
2705 dwRequiredDataSize
+= strlen( lpGData
->name
.u2
.lpszLongNameA
) + 1;
2708 if( ( lpData
== NULL
) ||
2709 ( *lpdwDataSize
< dwRequiredDataSize
)
2712 *lpdwDataSize
= dwRequiredDataSize
;
2713 return DPERR_BUFFERTOOSMALL
;
2716 /* Copy the structure */
2717 CopyMemory( lpName
, &lpGData
->name
, lpGData
->name
.dwSize
);
2719 if( lpGData
->name
.u1
.lpszShortNameA
)
2721 strcpy( ((char*)lpName
)+lpGData
->name
.dwSize
,
2722 lpGData
->name
.u1
.lpszShortNameA
);
2726 lpName
->u1
.lpszShortNameA
= NULL
;
2729 if( lpGData
->name
.u1
.lpszShortNameA
)
2731 strcpy( ((char*)lpName
)+lpGData
->name
.dwSize
,
2732 lpGData
->name
.u2
.lpszLongNameA
);
2736 lpName
->u2
.lpszLongNameA
= NULL
;
2742 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2743 ( LPDIRECTPLAY2A iface
, DPID idGroup
, LPVOID lpData
,
2744 LPDWORD lpdwDataSize
)
2746 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2747 return DP_IF_GetGroupName( This
, idGroup
, lpData
, lpdwDataSize
, TRUE
);
2750 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2751 ( LPDIRECTPLAY2 iface
, DPID idGroup
, LPVOID lpData
,
2752 LPDWORD lpdwDataSize
)
2754 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2755 return DP_IF_GetGroupName( This
, idGroup
, lpData
, lpdwDataSize
, FALSE
);
2758 static HRESULT DP_IF_GetMessageCount
2759 ( IDirectPlay2Impl
* This
, DPID idPlayer
,
2760 LPDWORD lpdwCount
, BOOL bAnsi
)
2762 FIXME("(%p)->(0x%08x,%p,%u): stub\n", This
, idPlayer
, lpdwCount
, bAnsi
);
2763 return DP_IF_GetMessageQueue( (IDirectPlay4Impl
*)This
, 0, idPlayer
,
2764 DPMESSAGEQUEUE_RECEIVE
, lpdwCount
, NULL
,
2768 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2769 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPDWORD lpdwCount
)
2771 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2772 return DP_IF_GetMessageCount( This
, idPlayer
, lpdwCount
, TRUE
);
2775 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2776 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPDWORD lpdwCount
)
2778 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2779 return DP_IF_GetMessageCount( This
, idPlayer
, lpdwCount
, FALSE
);
2782 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2783 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPVOID lpData
, LPDWORD lpdwDataSize
)
2785 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2786 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This
, idPlayer
, lpData
, lpdwDataSize
);
2790 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2791 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPVOID lpData
, LPDWORD lpdwDataSize
)
2793 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2794 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This
, idPlayer
, lpData
, lpdwDataSize
);
2798 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2799 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPDPCAPS lpPlayerCaps
,
2802 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2803 return DP_IF_GetPlayerCaps( This
, idPlayer
, lpPlayerCaps
, dwFlags
);
2806 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2807 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPDPCAPS lpPlayerCaps
,
2810 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2811 return DP_IF_GetPlayerCaps( This
, idPlayer
, lpPlayerCaps
, dwFlags
);
2814 static HRESULT DP_IF_GetPlayerData
2815 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPVOID lpData
,
2816 LPDWORD lpdwDataSize
, DWORD dwFlags
, BOOL bAnsi
)
2818 lpPlayerList lpPList
;
2819 DWORD dwRequiredBufferSize
;
2820 LPVOID lpCopyDataFrom
;
2822 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2823 This
, idPlayer
, lpData
, lpdwDataSize
, dwFlags
, bAnsi
);
2825 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
2827 return DPERR_UNINITIALIZED
;
2830 if( ( lpPList
= DP_FindPlayer( This
, idPlayer
) ) == NULL
)
2832 return DPERR_INVALIDPLAYER
;
2835 if( lpdwDataSize
== NULL
)
2837 return DPERR_INVALIDPARAMS
;
2840 /* How much buffer is required? */
2841 if( dwFlags
& DPSET_LOCAL
)
2843 dwRequiredBufferSize
= lpPList
->lpPData
->dwLocalDataSize
;
2844 lpCopyDataFrom
= lpPList
->lpPData
->lpLocalData
;
2848 dwRequiredBufferSize
= lpPList
->lpPData
->dwRemoteDataSize
;
2849 lpCopyDataFrom
= lpPList
->lpPData
->lpRemoteData
;
2852 /* Is the user requesting to know how big a buffer is required? */
2853 if( ( lpData
== NULL
) ||
2854 ( *lpdwDataSize
< dwRequiredBufferSize
)
2857 *lpdwDataSize
= dwRequiredBufferSize
;
2858 return DPERR_BUFFERTOOSMALL
;
2861 CopyMemory( lpData
, lpCopyDataFrom
, dwRequiredBufferSize
);
2866 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2867 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPVOID lpData
,
2868 LPDWORD lpdwDataSize
, DWORD dwFlags
)
2870 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2871 return DP_IF_GetPlayerData( This
, idPlayer
, lpData
, lpdwDataSize
,
2875 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2876 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPVOID lpData
,
2877 LPDWORD lpdwDataSize
, DWORD dwFlags
)
2879 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2880 return DP_IF_GetPlayerData( This
, idPlayer
, lpData
, lpdwDataSize
,
2884 static HRESULT DP_IF_GetPlayerName
2885 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPVOID lpData
,
2886 LPDWORD lpdwDataSize
, BOOL bAnsi
)
2888 lpPlayerList lpPList
;
2889 LPDPNAME lpName
= lpData
;
2890 DWORD dwRequiredDataSize
;
2892 FIXME( "(%p)->(0x%08x,%p,%p,%u): ANSI\n",
2893 This
, idPlayer
, lpData
, lpdwDataSize
, bAnsi
);
2895 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
2897 return DPERR_UNINITIALIZED
;
2900 if( ( lpPList
= DP_FindPlayer( This
, idPlayer
) ) == NULL
)
2902 return DPERR_INVALIDPLAYER
;
2905 dwRequiredDataSize
= lpPList
->lpPData
->name
.dwSize
;
2907 if( lpPList
->lpPData
->name
.u1
.lpszShortNameA
)
2909 dwRequiredDataSize
+= strlen( lpPList
->lpPData
->name
.u1
.lpszShortNameA
) + 1;
2912 if( lpPList
->lpPData
->name
.u2
.lpszLongNameA
)
2914 dwRequiredDataSize
+= strlen( lpPList
->lpPData
->name
.u2
.lpszLongNameA
) + 1;
2917 if( ( lpData
== NULL
) ||
2918 ( *lpdwDataSize
< dwRequiredDataSize
)
2921 *lpdwDataSize
= dwRequiredDataSize
;
2922 return DPERR_BUFFERTOOSMALL
;
2925 /* Copy the structure */
2926 CopyMemory( lpName
, &lpPList
->lpPData
->name
, lpPList
->lpPData
->name
.dwSize
);
2928 if( lpPList
->lpPData
->name
.u1
.lpszShortNameA
)
2930 strcpy( ((char*)lpName
)+lpPList
->lpPData
->name
.dwSize
,
2931 lpPList
->lpPData
->name
.u1
.lpszShortNameA
);
2935 lpName
->u1
.lpszShortNameA
= NULL
;
2938 if( lpPList
->lpPData
->name
.u2
.lpszLongNameA
)
2940 strcpy( ((char*)lpName
)+lpPList
->lpPData
->name
.dwSize
,
2941 lpPList
->lpPData
->name
.u2
.lpszLongNameA
);
2945 lpName
->u2
.lpszLongNameA
= NULL
;
2951 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2952 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPVOID lpData
,
2953 LPDWORD lpdwDataSize
)
2955 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2956 return DP_IF_GetPlayerName( This
, idPlayer
, lpData
, lpdwDataSize
, TRUE
);
2959 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2960 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPVOID lpData
,
2961 LPDWORD lpdwDataSize
)
2963 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2964 return DP_IF_GetPlayerName( This
, idPlayer
, lpData
, lpdwDataSize
, FALSE
);
2967 static HRESULT DP_GetSessionDesc
2968 ( IDirectPlay2Impl
* This
, LPVOID lpData
, LPDWORD lpdwDataSize
,
2971 DWORD dwRequiredSize
;
2973 TRACE( "(%p)->(%p,%p,%u)\n", This
, lpData
, lpdwDataSize
, bAnsi
);
2975 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
2977 return DPERR_UNINITIALIZED
;
2980 if( !This
->dp2
->bConnectionOpen
)
2982 return DPERR_NOSESSIONS
;
2985 if( ( lpdwDataSize
== NULL
) || ( *lpdwDataSize
>= MAXDWORD
) )
2987 return DPERR_INVALIDPARAMS
;
2990 /* FIXME: Get from This->dp2->lpSessionDesc */
2991 dwRequiredSize
= DP_CalcSessionDescSize( This
->dp2
->lpSessionDesc
, bAnsi
);
2993 if ( ( lpData
== NULL
) ||
2994 ( *lpdwDataSize
< dwRequiredSize
)
2997 *lpdwDataSize
= dwRequiredSize
;
2998 return DPERR_BUFFERTOOSMALL
;
3001 DP_CopySessionDesc( lpData
, This
->dp2
->lpSessionDesc
, bAnsi
);
3006 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
3007 ( LPDIRECTPLAY2A iface
, LPVOID lpData
, LPDWORD lpdwDataSize
)
3009 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3010 return DP_GetSessionDesc( This
, lpData
, lpdwDataSize
, TRUE
);
3013 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
3014 ( LPDIRECTPLAY2 iface
, LPVOID lpData
, LPDWORD lpdwDataSize
)
3016 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3017 return DP_GetSessionDesc( This
, lpData
, lpdwDataSize
, TRUE
);
3020 /* Intended only for COM compatibility. Always returns an error. */
3021 static HRESULT WINAPI DirectPlay2AImpl_Initialize
3022 ( LPDIRECTPLAY2A iface
, LPGUID lpGUID
)
3024 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3025 TRACE("(%p)->(%p): stub\n", This
, lpGUID
);
3026 return DPERR_ALREADYINITIALIZED
;
3029 /* Intended only for COM compatibility. Always returns an error. */
3030 static HRESULT WINAPI DirectPlay2WImpl_Initialize
3031 ( LPDIRECTPLAY2 iface
, LPGUID lpGUID
)
3033 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3034 TRACE("(%p)->(%p): stub\n", This
, lpGUID
);
3035 return DPERR_ALREADYINITIALIZED
;
3039 static HRESULT DP_SecureOpen
3040 ( IDirectPlay2Impl
* This
, LPCDPSESSIONDESC2 lpsd
, DWORD dwFlags
,
3041 LPCDPSECURITYDESC lpSecurity
, LPCDPCREDENTIALS lpCredentials
,
3046 FIXME( "(%p)->(%p,0x%08x,%p,%p): partial stub\n",
3047 This
, lpsd
, dwFlags
, lpSecurity
, lpCredentials
);
3049 if( ( lpsd
== NULL
) ||
3050 ( lpsd
->dwSize
!= sizeof(DPSESSIONDESC2
) ) )
3052 return DPERR_INVALIDPARAMS
;
3055 if( This
->dp2
->bConnectionOpen
)
3057 TRACE( ": rejecting already open connection.\n" );
3058 return DPERR_ALREADYINITIALIZED
;
3061 /* If we're enumerating, kill the thread */
3062 DP_KillEnumSessionThread( This
);
3064 if( dwFlags
& DPOPEN_JOIN
)
3066 LPDPSESSIONDESC2 current
= NULL
;
3067 NS_ResetSessionEnumeration( This
->dp2
->lpNameServerData
);
3068 while( ( current
= NS_WalkSessions( This
->dp2
->lpNameServerData
) ) )
3070 if ( IsEqualGUID( &lpsd
->guidInstance
, ¤t
->guidInstance
) )
3073 if ( current
== NULL
)
3074 return DPERR_NOSESSIONS
;
3076 else if( dwFlags
& DPOPEN_CREATE
)
3078 /* Rightoo - this computer is the host and the local computer needs to be
3079 the name server so that others can join this session */
3080 NS_SetLocalComputerAsNameServer( lpsd
, This
->dp2
->lpNameServerData
);
3082 This
->dp2
->bHostInterface
= TRUE
;
3084 hr
= DP_SetSessionDesc( This
, lpsd
, 0, TRUE
, bAnsi
);
3087 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr
) );
3092 /* Invoke the conditional callback for the service provider */
3093 if( This
->dp2
->spData
.lpCB
->Open
)
3097 FIXME( "Not all data fields are correct. Need new parameter\n" );
3099 data
.bCreate
= (dwFlags
& DPOPEN_CREATE
) ? TRUE
: FALSE
;
3100 data
.lpSPMessageHeader
= (dwFlags
& DPOPEN_CREATE
) ? NULL
3101 : NS_GetNSAddr( This
->dp2
->lpNameServerData
);
3102 data
.lpISP
= This
->dp2
->spData
.lpISP
;
3103 data
.bReturnStatus
= (dwFlags
& DPOPEN_RETURNSTATUS
) ? TRUE
: FALSE
;
3104 data
.dwOpenFlags
= dwFlags
;
3105 data
.dwSessionFlags
= This
->dp2
->lpSessionDesc
->dwFlags
;
3107 hr
= (*This
->dp2
->spData
.lpCB
->Open
)(&data
);
3110 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr
) );
3116 /* Create the system group of which everything is a part of */
3117 DPID systemGroup
= DPID_SYSTEM_GROUP
;
3119 hr
= DP_IF_CreateGroup( This
, NULL
, &systemGroup
, NULL
,
3124 if( dwFlags
& DPOPEN_JOIN
)
3126 DPID dpidServerId
= DPID_UNKNOWN
;
3128 /* Create the server player for this interface. This way we can receive
3129 * messages for this session.
3131 /* FIXME: I suppose that we should be setting an event for a receive
3132 * type of thing. That way the messaging thread could know to wake
3133 * up. DPlay would then trigger the hEvent for the player the
3134 * message is directed to.
3136 hr
= DP_IF_CreatePlayer( This
, NULL
, &dpidServerId
, NULL
, 0, NULL
,
3138 DPPLAYER_SERVERPLAYER
| DPPLAYER_LOCAL
, bAnsi
);
3141 else if( dwFlags
& DPOPEN_CREATE
)
3143 DPID dpidNameServerId
= DPID_NAME_SERVER
;
3145 hr
= DP_IF_CreatePlayer( This
, NULL
, &dpidNameServerId
, NULL
, 0, NULL
,
3146 0, DPPLAYER_SERVERPLAYER
, bAnsi
);
3151 ERR( "Couldn't create name server/system player: %s\n",
3152 DPLAYX_HresultToString(hr
) );
3156 This
->dp2
->bConnectionOpen
= TRUE
;
3162 static HRESULT WINAPI DirectPlay2AImpl_Open
3163 ( LPDIRECTPLAY2A iface
, LPDPSESSIONDESC2 lpsd
, DWORD dwFlags
)
3165 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3166 TRACE("(%p)->(%p,0x%08x)\n", This
, lpsd
, dwFlags
);
3167 return DP_SecureOpen( This
, lpsd
, dwFlags
, NULL
, NULL
, TRUE
);
3170 static HRESULT WINAPI DirectPlay2WImpl_Open
3171 ( LPDIRECTPLAY2 iface
, LPDPSESSIONDESC2 lpsd
, DWORD dwFlags
)
3173 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3174 TRACE("(%p)->(%p,0x%08x)\n", This
, lpsd
, dwFlags
);
3175 return DP_SecureOpen( This
, lpsd
, dwFlags
, NULL
, NULL
, FALSE
);
3178 static HRESULT DP_IF_Receive
3179 ( IDirectPlay2Impl
* This
, LPDPID lpidFrom
, LPDPID lpidTo
,
3180 DWORD dwFlags
, LPVOID lpData
, LPDWORD lpdwDataSize
, BOOL bAnsi
)
3182 LPDPMSG lpMsg
= NULL
;
3184 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p,%u): stub\n",
3185 This
, lpidFrom
, lpidTo
, dwFlags
, lpData
, lpdwDataSize
, bAnsi
);
3187 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
3189 return DPERR_UNINITIALIZED
;
3192 if ( ( lpdwDataSize
== NULL
) ||
3193 ( ( dwFlags
& DPRECEIVE_FROMPLAYER
) && ( lpidFrom
== NULL
) ) ||
3194 ( ( dwFlags
& DPRECEIVE_TOPLAYER
) && ( lpidTo
== NULL
) ) )
3196 return DPERR_INVALIDPARAMS
;
3201 dwFlags
= DPRECEIVE_ALL
;
3204 if( dwFlags
& DPRECEIVE_ALL
)
3206 lpMsg
= DPQ_FIRST( This
->dp2
->receiveMsgs
);
3210 if ( (lpMsg
= DPQ_FIRST( This
->dp2
->receiveMsgs
)) )
3214 if ( ( ( dwFlags
& DPRECEIVE_FROMPLAYER
) &&
3215 ( dwFlags
& DPRECEIVE_TOPLAYER
) &&
3216 ( lpMsg
->idFrom
== *lpidFrom
) &&
3217 ( lpMsg
->idTo
== *lpidTo
) ) || /* From & To */
3218 ( ( dwFlags
& DPRECEIVE_FROMPLAYER
) &&
3219 ( lpMsg
->idFrom
== *lpidFrom
) ) || /* From */
3220 ( ( dwFlags
& DPRECEIVE_TOPLAYER
) &&
3221 ( lpMsg
->idTo
== *lpidTo
) ) ) /* To */
3226 while( (lpMsg
= DPQ_NEXT( lpMsg
->msgs
)) );
3232 return DPERR_NOMESSAGES
;
3235 /* Buffer size check */
3236 if ( ( lpData
== NULL
) ||
3237 ( *lpdwDataSize
< lpMsg
->dwMsgSize
) )
3239 *lpdwDataSize
= lpMsg
->dwMsgSize
;
3240 return DPERR_BUFFERTOOSMALL
;
3243 /* Copy into the provided buffer */
3244 if (lpData
) CopyMemory( lpData
, lpMsg
->msg
, *lpdwDataSize
);
3249 *lpidFrom
= lpMsg
->idFrom
;
3253 *lpidTo
= lpMsg
->idTo
;
3256 /* Remove message from queue */
3257 if( !( dwFlags
& DPRECEIVE_PEEK
) )
3259 HeapFree( GetProcessHeap(), 0, lpMsg
->msg
);
3260 DPQ_REMOVE( This
->dp2
->receiveMsgs
, lpMsg
, msgs
);
3261 HeapFree( GetProcessHeap(), 0, lpMsg
);
3267 static HRESULT WINAPI DirectPlay2AImpl_Receive
3268 ( LPDIRECTPLAY2A iface
, LPDPID lpidFrom
, LPDPID lpidTo
,
3269 DWORD dwFlags
, LPVOID lpData
, LPDWORD lpdwDataSize
)
3271 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3272 return DP_IF_Receive( This
, lpidFrom
, lpidTo
, dwFlags
,
3273 lpData
, lpdwDataSize
, TRUE
);
3276 static HRESULT WINAPI DirectPlay2WImpl_Receive
3277 ( LPDIRECTPLAY2 iface
, LPDPID lpidFrom
, LPDPID lpidTo
,
3278 DWORD dwFlags
, LPVOID lpData
, LPDWORD lpdwDataSize
)
3280 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3281 return DP_IF_Receive( This
, lpidFrom
, lpidTo
, dwFlags
,
3282 lpData
, lpdwDataSize
, FALSE
);
3285 static HRESULT WINAPI DirectPlay2AImpl_Send
3286 ( LPDIRECTPLAY2A iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
, LPVOID lpData
, DWORD dwDataSize
)
3288 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3289 return DP_SendEx( This
, idFrom
, idTo
, dwFlags
, lpData
, dwDataSize
,
3290 0, 0, NULL
, NULL
, TRUE
);
3293 static HRESULT WINAPI DirectPlay2WImpl_Send
3294 ( LPDIRECTPLAY2 iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
, LPVOID lpData
, DWORD dwDataSize
)
3296 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3297 return DP_SendEx( This
, idFrom
, idTo
, dwFlags
, lpData
, dwDataSize
,
3298 0, 0, NULL
, NULL
, FALSE
);
3301 static HRESULT DP_IF_SetGroupData
3302 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPVOID lpData
,
3303 DWORD dwDataSize
, DWORD dwFlags
, BOOL bAnsi
)
3305 lpGroupData lpGData
;
3307 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3308 This
, idGroup
, lpData
, dwDataSize
, dwFlags
, bAnsi
);
3310 /* Parameter check */
3311 if( ( lpData
== NULL
) &&
3315 return DPERR_INVALIDPARAMS
;
3318 /* Find the pointer to the data for this player */
3319 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
3321 return DPERR_INVALIDOBJECT
;
3324 if( !(dwFlags
& DPSET_LOCAL
) )
3326 FIXME( "Was this group created by this interface?\n" );
3327 /* FIXME: If this is a remote update need to allow it but not
3332 DP_SetGroupData( lpGData
, dwFlags
, lpData
, dwDataSize
);
3334 /* FIXME: Only send a message if this group is local to the session otherwise
3335 * it will have been rejected above
3337 if( !(dwFlags
& DPSET_LOCAL
) )
3339 FIXME( "Send msg?\n" );
3345 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
3346 ( LPDIRECTPLAY2A iface
, DPID idGroup
, LPVOID lpData
,
3347 DWORD dwDataSize
, DWORD dwFlags
)
3349 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3350 return DP_IF_SetGroupData( This
, idGroup
, lpData
, dwDataSize
, dwFlags
, TRUE
);
3353 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
3354 ( LPDIRECTPLAY2 iface
, DPID idGroup
, LPVOID lpData
,
3355 DWORD dwDataSize
, DWORD dwFlags
)
3357 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3358 return DP_IF_SetGroupData( This
, idGroup
, lpData
, dwDataSize
, dwFlags
, FALSE
);
3361 static HRESULT DP_IF_SetGroupName
3362 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPDPNAME lpGroupName
,
3363 DWORD dwFlags
, BOOL bAnsi
)
3365 lpGroupData lpGData
;
3367 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n", This
, idGroup
,
3368 lpGroupName
, dwFlags
, bAnsi
);
3370 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
3372 return DPERR_INVALIDGROUP
;
3375 DP_CopyDPNAMEStruct( &lpGData
->name
, lpGroupName
, bAnsi
);
3377 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3378 FIXME( "Message not sent and dwFlags ignored\n" );
3383 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
3384 ( LPDIRECTPLAY2A iface
, DPID idGroup
, LPDPNAME lpGroupName
,
3387 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3388 return DP_IF_SetGroupName( This
, idGroup
, lpGroupName
, dwFlags
, TRUE
);
3391 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
3392 ( LPDIRECTPLAY2 iface
, DPID idGroup
, LPDPNAME lpGroupName
,
3395 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3396 return DP_IF_SetGroupName( This
, idGroup
, lpGroupName
, dwFlags
, FALSE
);
3399 static HRESULT DP_IF_SetPlayerData
3400 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPVOID lpData
,
3401 DWORD dwDataSize
, DWORD dwFlags
, BOOL bAnsi
)
3403 lpPlayerList lpPList
;
3405 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3406 This
, idPlayer
, lpData
, dwDataSize
, dwFlags
, bAnsi
);
3408 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
3410 return DPERR_UNINITIALIZED
;
3413 /* Parameter check */
3414 if( ( ( lpData
== NULL
) && ( dwDataSize
!= 0 ) ) ||
3415 ( dwDataSize
>= MAXDWORD
) )
3417 return DPERR_INVALIDPARAMS
;
3420 /* Find the pointer to the data for this player */
3421 if( ( lpPList
= DP_FindPlayer( This
, idPlayer
) ) == NULL
)
3423 return DPERR_INVALIDPLAYER
;
3426 if( !(dwFlags
& DPSET_LOCAL
) )
3428 FIXME( "Was this group created by this interface?\n" );
3429 /* FIXME: If this is a remote update need to allow it but not
3434 DP_SetPlayerData( lpPList
->lpPData
, dwFlags
, lpData
, dwDataSize
);
3436 if( !(dwFlags
& DPSET_LOCAL
) )
3438 FIXME( "Send msg?\n" );
3444 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3445 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPVOID lpData
,
3446 DWORD dwDataSize
, DWORD dwFlags
)
3448 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3449 return DP_IF_SetPlayerData( This
, idPlayer
, lpData
, dwDataSize
,
3453 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3454 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPVOID lpData
,
3455 DWORD dwDataSize
, DWORD dwFlags
)
3457 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3458 return DP_IF_SetPlayerData( This
, idPlayer
, lpData
, dwDataSize
,
3462 static HRESULT DP_IF_SetPlayerName
3463 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPDPNAME lpPlayerName
,
3464 DWORD dwFlags
, BOOL bAnsi
)
3466 lpPlayerList lpPList
;
3468 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n",
3469 This
, idPlayer
, lpPlayerName
, dwFlags
, bAnsi
);
3471 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
3473 return DPERR_UNINITIALIZED
;
3476 if( ( lpPList
= DP_FindPlayer( This
, idPlayer
) ) == NULL
)
3478 return DPERR_INVALIDGROUP
;
3481 DP_CopyDPNAMEStruct( &lpPList
->lpPData
->name
, lpPlayerName
, bAnsi
);
3483 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3484 FIXME( "Message not sent and dwFlags ignored\n" );
3489 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3490 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPDPNAME lpPlayerName
,
3493 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3494 return DP_IF_SetPlayerName( This
, idPlayer
, lpPlayerName
, dwFlags
, TRUE
);
3497 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3498 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPDPNAME lpPlayerName
,
3501 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3502 return DP_IF_SetPlayerName( This
, idPlayer
, lpPlayerName
, dwFlags
, FALSE
);
3505 HRESULT DP_SetSessionDesc
3506 ( IDirectPlay2Impl
* This
, LPCDPSESSIONDESC2 lpSessDesc
,
3507 DWORD dwFlags
, BOOL bInitial
, BOOL bAnsi
)
3509 DWORD dwRequiredSize
;
3510 LPDPSESSIONDESC2 lpTempSessDesc
;
3512 TRACE( "(%p)->(%p,0x%08x,%u,%u)\n",
3513 This
, lpSessDesc
, dwFlags
, bInitial
, bAnsi
);
3515 /* FIXME: Copy into This->dp2->lpSessionDesc */
3516 dwRequiredSize
= DP_CalcSessionDescSize( lpSessDesc
, bAnsi
);
3517 lpTempSessDesc
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, dwRequiredSize
);
3519 if( lpTempSessDesc
== NULL
)
3521 return DPERR_OUTOFMEMORY
;
3525 HeapFree( GetProcessHeap(), 0, This
->dp2
->lpSessionDesc
);
3527 This
->dp2
->lpSessionDesc
= lpTempSessDesc
;
3529 DP_CopySessionDesc( This
->dp2
->lpSessionDesc
, lpSessDesc
, bAnsi
);
3532 /*Initializing session GUID*/
3533 CoCreateGuid( &(This
->dp2
->lpSessionDesc
->guidInstance
) );
3535 /* If this is an external invocation of the interface, we should be
3536 * letting everyone know that things have changed. Otherwise this is
3537 * just an initialization and it doesn't need to be propagated.
3541 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3547 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3548 ( LPDIRECTPLAY2A iface
, LPDPSESSIONDESC2 lpSessDesc
, DWORD dwFlags
)
3550 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3552 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
3554 return DPERR_UNINITIALIZED
;
3557 if( !This
->dp2
->bConnectionOpen
)
3559 return DPERR_NOSESSIONS
;
3562 if( dwFlags
|| (lpSessDesc
== NULL
) )
3564 return DPERR_INVALIDPARAMS
;
3567 /* Illegal combinations of flags */
3568 if ( ( lpSessDesc
->dwFlags
& DPSESSION_MIGRATEHOST
) &&
3569 ( lpSessDesc
->dwFlags
& ( DPSESSION_CLIENTSERVER
|
3570 DPSESSION_MULTICASTSERVER
|
3571 DPSESSION_SECURESERVER
) ) )
3573 return DPERR_INVALIDFLAGS
;
3576 /* Only the host is allowed to update the session desc */
3577 if( !This
->dp2
->bHostInterface
)
3579 return DPERR_ACCESSDENIED
;
3582 return DP_SetSessionDesc( This
, lpSessDesc
, dwFlags
, FALSE
, TRUE
);
3585 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3586 ( LPDIRECTPLAY2 iface
, LPDPSESSIONDESC2 lpSessDesc
, DWORD dwFlags
)
3588 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3590 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
3592 return DPERR_UNINITIALIZED
;
3595 if( !This
->dp2
->bConnectionOpen
)
3597 return DPERR_NOSESSIONS
;
3600 if( dwFlags
|| (lpSessDesc
== NULL
) )
3602 return DPERR_INVALIDPARAMS
;
3605 /* Illegal combinations of flags */
3606 if ( ( lpSessDesc
->dwFlags
& DPSESSION_MIGRATEHOST
) &&
3607 ( lpSessDesc
->dwFlags
& ( DPSESSION_CLIENTSERVER
|
3608 DPSESSION_MULTICASTSERVER
|
3609 DPSESSION_SECURESERVER
) ) )
3611 return DPERR_INVALIDFLAGS
;
3614 /* Only the host is allowed to update the session desc */
3615 if( !This
->dp2
->bHostInterface
)
3617 return DPERR_ACCESSDENIED
;
3620 return DP_SetSessionDesc( This
, lpSessDesc
, dwFlags
, FALSE
, TRUE
);
3623 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3624 static DWORD
DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc
, BOOL bAnsi
)
3628 if( lpSessDesc
== NULL
)
3630 /* Hmmm..don't need any size? */
3631 ERR( "NULL lpSessDesc\n" );
3635 dwSize
+= sizeof( *lpSessDesc
);
3639 if( lpSessDesc
->u1
.lpszSessionNameA
)
3641 dwSize
+= lstrlenA( lpSessDesc
->u1
.lpszSessionNameA
) + 1;
3644 if( lpSessDesc
->u2
.lpszPasswordA
)
3646 dwSize
+= lstrlenA( lpSessDesc
->u2
.lpszPasswordA
) + 1;
3651 if( lpSessDesc
->u1
.lpszSessionName
)
3653 dwSize
+= sizeof( WCHAR
) *
3654 ( lstrlenW( lpSessDesc
->u1
.lpszSessionName
) + 1 );
3657 if( lpSessDesc
->u2
.lpszPassword
)
3659 dwSize
+= sizeof( WCHAR
) *
3660 ( lstrlenW( lpSessDesc
->u2
.lpszPassword
) + 1 );
3667 /* Assumes that contiguous buffers are already allocated. */
3668 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest
,
3669 LPCDPSESSIONDESC2 lpSessionSrc
, BOOL bAnsi
)
3671 BYTE
* lpStartOfFreeSpace
;
3673 if( lpSessionDest
== NULL
)
3675 ERR( "NULL lpSessionDest\n" );
3679 CopyMemory( lpSessionDest
, lpSessionSrc
, sizeof( *lpSessionSrc
) );
3681 lpStartOfFreeSpace
= ((BYTE
*)lpSessionDest
) + sizeof( *lpSessionSrc
);
3685 if( lpSessionSrc
->u1
.lpszSessionNameA
)
3687 lstrcpyA( (LPSTR
)lpStartOfFreeSpace
,
3688 lpSessionDest
->u1
.lpszSessionNameA
);
3689 lpSessionDest
->u1
.lpszSessionNameA
= (LPSTR
)lpStartOfFreeSpace
;
3690 lpStartOfFreeSpace
+=
3691 lstrlenA( lpSessionDest
->u1
.lpszSessionNameA
) + 1;
3694 if( lpSessionSrc
->u2
.lpszPasswordA
)
3696 lstrcpyA( (LPSTR
)lpStartOfFreeSpace
,
3697 lpSessionDest
->u2
.lpszPasswordA
);
3698 lpSessionDest
->u2
.lpszPasswordA
= (LPSTR
)lpStartOfFreeSpace
;
3699 lpStartOfFreeSpace
+=
3700 lstrlenA( lpSessionDest
->u2
.lpszPasswordA
) + 1;
3705 if( lpSessionSrc
->u1
.lpszSessionName
)
3707 lstrcpyW( (LPWSTR
)lpStartOfFreeSpace
,
3708 lpSessionDest
->u1
.lpszSessionName
);
3709 lpSessionDest
->u1
.lpszSessionName
= (LPWSTR
)lpStartOfFreeSpace
;
3710 lpStartOfFreeSpace
+= sizeof(WCHAR
) *
3711 ( lstrlenW( lpSessionDest
->u1
.lpszSessionName
) + 1 );
3714 if( lpSessionSrc
->u2
.lpszPassword
)
3716 lstrcpyW( (LPWSTR
)lpStartOfFreeSpace
,
3717 lpSessionDest
->u2
.lpszPassword
);
3718 lpSessionDest
->u2
.lpszPassword
= (LPWSTR
)lpStartOfFreeSpace
;
3719 lpStartOfFreeSpace
+= sizeof(WCHAR
) *
3720 ( lstrlenW( lpSessionDest
->u2
.lpszPassword
) + 1 );
3726 static HRESULT DP_IF_AddGroupToGroup
3727 ( IDirectPlay3Impl
* This
, DPID idParentGroup
, DPID idGroup
)
3729 lpGroupData lpGData
;
3730 lpGroupList lpNewGList
;
3732 TRACE( "(%p)->(0x%08x,0x%08x)\n", This
, idParentGroup
, idGroup
);
3734 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
3736 return DPERR_UNINITIALIZED
;
3739 if( DP_FindAnyGroup( (IDirectPlay2AImpl
*)This
, idParentGroup
) == NULL
)
3741 return DPERR_INVALIDGROUP
;
3744 if( ( lpGData
= DP_FindAnyGroup( (IDirectPlay2AImpl
*)This
, idGroup
) ) == NULL
)
3746 return DPERR_INVALIDGROUP
;
3749 /* Create a player list (ie "shortcut" ) */
3750 lpNewGList
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpNewGList
) );
3751 if( lpNewGList
== NULL
)
3753 return DPERR_CANTADDPLAYER
;
3756 /* Add the shortcut */
3758 lpNewGList
->lpGData
= lpGData
;
3760 /* Add the player to the list of players for this group */
3761 DPQ_INSERT( lpGData
->groups
, lpNewGList
, groups
);
3763 /* Send a ADDGROUPTOGROUP message */
3764 FIXME( "Not sending message\n" );
3769 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3770 ( LPDIRECTPLAY3A iface
, DPID idParentGroup
, DPID idGroup
)
3772 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3773 return DP_IF_AddGroupToGroup( This
, idParentGroup
, idGroup
);
3776 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3777 ( LPDIRECTPLAY3 iface
, DPID idParentGroup
, DPID idGroup
)
3779 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3780 return DP_IF_AddGroupToGroup( This
, idParentGroup
, idGroup
);
3783 static HRESULT DP_IF_CreateGroupInGroup
3784 ( IDirectPlay3Impl
* This
, LPVOID lpMsgHdr
, DPID idParentGroup
,
3785 LPDPID lpidGroup
, LPDPNAME lpGroupName
, LPVOID lpData
,
3786 DWORD dwDataSize
, DWORD dwFlags
, BOOL bAnsi
)
3788 lpGroupData lpGParentData
;
3789 lpGroupList lpGList
;
3790 lpGroupData lpGData
;
3792 TRACE( "(%p)->(0x%08x,%p,%p,%p,0x%08x,0x%08x,%u)\n",
3793 This
, idParentGroup
, lpidGroup
, lpGroupName
, lpData
,
3794 dwDataSize
, dwFlags
, bAnsi
);
3796 /* Verify that the specified parent is valid */
3797 if( ( lpGParentData
= DP_FindAnyGroup( (IDirectPlay2AImpl
*)This
,
3798 idParentGroup
) ) == NULL
3801 return DPERR_INVALIDGROUP
;
3804 lpGData
= DP_CreateGroup( (IDirectPlay2AImpl
*)This
, lpidGroup
, lpGroupName
,
3805 dwFlags
, idParentGroup
, bAnsi
);
3807 if( lpGData
== NULL
)
3809 return DPERR_CANTADDPLAYER
; /* yes player not group */
3812 /* Something else is referencing this data */
3815 DP_SetGroupData( lpGData
, DPSET_REMOTE
, lpData
, dwDataSize
);
3817 /* The list has now been inserted into the interface group list. We now
3818 need to put a "shortcut" to this group in the parent group */
3819 lpGList
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpGList
) );
3820 if( lpGList
== NULL
)
3822 FIXME( "Memory leak\n" );
3823 return DPERR_CANTADDPLAYER
; /* yes player not group */
3826 lpGList
->lpGData
= lpGData
;
3828 DPQ_INSERT( lpGParentData
->groups
, lpGList
, groups
);
3830 /* Let the SP know that we've created this group */
3831 if( This
->dp2
->spData
.lpCB
->CreateGroup
)
3833 DPSP_CREATEGROUPDATA data
;
3835 TRACE( "Calling SP CreateGroup\n" );
3837 data
.idGroup
= *lpidGroup
;
3838 data
.dwFlags
= dwFlags
;
3839 data
.lpSPMessageHeader
= lpMsgHdr
;
3840 data
.lpISP
= This
->dp2
->spData
.lpISP
;
3842 (*This
->dp2
->spData
.lpCB
->CreateGroup
)( &data
);
3845 /* Inform all other peers of the creation of a new group. If there are
3846 * no peers keep this quiet.
3848 if( This
->dp2
->lpSessionDesc
&&
3849 ( This
->dp2
->lpSessionDesc
->dwFlags
& DPSESSION_MULTICASTSERVER
) )
3851 DPMSG_CREATEPLAYERORGROUP msg
;
3853 msg
.dwType
= DPSYS_CREATEPLAYERORGROUP
;
3854 msg
.dwPlayerType
= DPPLAYERTYPE_GROUP
;
3855 msg
.dpId
= *lpidGroup
;
3856 msg
.dwCurrentPlayers
= idParentGroup
; /* FIXME: Incorrect? */
3857 msg
.lpData
= lpData
;
3858 msg
.dwDataSize
= dwDataSize
;
3859 msg
.dpnName
= *lpGroupName
;
3861 /* FIXME: Correct to just use send effectively? */
3862 /* FIXME: Should size include data w/ message or just message "header" */
3863 /* FIXME: Check return code */
3864 DP_SendEx( (IDirectPlay2Impl
*)This
,
3865 DPID_SERVERPLAYER
, DPID_ALLPLAYERS
, 0, &msg
, sizeof( msg
),
3866 0, 0, NULL
, NULL
, bAnsi
);
3872 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3873 ( LPDIRECTPLAY3A iface
, DPID idParentGroup
, LPDPID lpidGroup
,
3874 LPDPNAME lpGroupName
, LPVOID lpData
, DWORD dwDataSize
,
3877 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3879 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
3881 return DPERR_UNINITIALIZED
;
3884 if( lpidGroup
== NULL
||
3885 !This
->dp2
->bConnectionOpen
||
3886 dwDataSize
>= MAXDWORD
||
3887 ( lpData
== NULL
&& dwDataSize
!= 0 ) )
3889 return DPERR_INVALIDPARAMS
;
3892 *lpidGroup
= DPID_UNKNOWN
;
3894 return DP_IF_CreateGroupInGroup( This
, NULL
, idParentGroup
, lpidGroup
,
3895 lpGroupName
, lpData
, dwDataSize
, dwFlags
,
3899 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3900 ( LPDIRECTPLAY3 iface
, DPID idParentGroup
, LPDPID lpidGroup
,
3901 LPDPNAME lpGroupName
, LPVOID lpData
, DWORD dwDataSize
,
3904 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3906 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
3908 return DPERR_UNINITIALIZED
;
3911 if( lpidGroup
== NULL
||
3912 !This
->dp2
->bConnectionOpen
||
3913 dwDataSize
>= MAXDWORD
||
3914 ( lpData
== NULL
&& dwDataSize
!= 0 ) )
3916 return DPERR_INVALIDPARAMS
;
3919 *lpidGroup
= DPID_UNKNOWN
;
3921 return DP_IF_CreateGroupInGroup( This
, NULL
, idParentGroup
, lpidGroup
,
3922 lpGroupName
, lpData
, dwDataSize
,
3926 static HRESULT DP_IF_DeleteGroupFromGroup
3927 ( IDirectPlay3Impl
* This
, DPID idParentGroup
, DPID idGroup
)
3929 lpGroupList lpGList
;
3930 lpGroupData lpGParentData
;
3932 TRACE("(%p)->(0x%08x,0x%08x)\n", This
, idParentGroup
, idGroup
);
3934 /* Is the parent group valid? */
3935 if( ( lpGParentData
= DP_FindAnyGroup( (IDirectPlay2AImpl
*)This
, idParentGroup
) ) == NULL
)
3937 return DPERR_INVALIDGROUP
;
3940 /* Remove the group from the parent group queue */
3941 DPQ_REMOVE_ENTRY( lpGParentData
->groups
, groups
, lpGData
->dpid
, ==, idGroup
, lpGList
);
3943 if( lpGList
== NULL
)
3945 return DPERR_INVALIDGROUP
;
3948 /* Decrement the ref count */
3949 lpGList
->lpGData
->uRef
--;
3951 /* Free up the list item */
3952 HeapFree( GetProcessHeap(), 0, lpGList
);
3954 /* Should send a DELETEGROUPFROMGROUP message */
3955 FIXME( "message not sent\n" );
3960 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3961 ( LPDIRECTPLAY3 iface
, DPID idParentGroup
, DPID idGroup
)
3963 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3964 return DP_IF_DeleteGroupFromGroup( This
, idParentGroup
, idGroup
);
3967 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3968 ( LPDIRECTPLAY3 iface
, DPID idParentGroup
, DPID idGroup
)
3970 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3971 return DP_IF_DeleteGroupFromGroup( This
, idParentGroup
, idGroup
);
3973 static BOOL
DP_BuildCompoundAddr( GUID guidDataType
,
3975 LPVOID
* lplpAddrBuf
,
3976 LPDWORD lpdwBufSize
)
3978 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress
;
3981 dpCompoundAddress
.dwDataSize
= sizeof( GUID
);
3982 dpCompoundAddress
.guidDataType
= guidDataType
;
3983 dpCompoundAddress
.lpData
= lpcSpGuid
;
3985 *lplpAddrBuf
= NULL
;
3988 hr
= DPL_CreateCompoundAddress( &dpCompoundAddress
, 1, *lplpAddrBuf
,
3989 lpdwBufSize
, TRUE
);
3991 if( hr
!= DPERR_BUFFERTOOSMALL
)
3993 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr
) );
3997 /* Now allocate the buffer */
3998 *lplpAddrBuf
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
4001 hr
= DPL_CreateCompoundAddress( &dpCompoundAddress
, 1, *lplpAddrBuf
,
4002 lpdwBufSize
, TRUE
);
4005 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr
) );
4012 static HRESULT WINAPI DP_IF_EnumConnections
4013 ( LPDIRECTPLAY3A iface
, LPCGUID lpguidApplication
,
4014 LPDPENUMCONNECTIONSCALLBACK lpEnumCallback
, LPVOID lpContext
,
4015 DWORD dwFlags
, BOOL bAnsi
)
4018 WCHAR searchSubKeySP
[] = {
4019 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
4020 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
4021 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
4022 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
4023 WCHAR searchSubKeyLP
[] = {
4024 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
4025 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
4026 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
4027 'L', 'o', 'b', 'b', 'y', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
4028 WCHAR guidDataSubKey
[] = { 'G', 'u', 'i', 'd', 0 };
4029 WCHAR subKeyName
[255]; /* 255 is the maximum key size according to MSDN */
4030 DWORD dwIndex
, sizeOfSubKeyName
= sizeof(subKeyName
) / sizeof(WCHAR
);
4033 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
4036 dwFlags
= DPCONNECTION_DIRECTPLAY
;
4039 if( ! ( ( dwFlags
& DPCONNECTION_DIRECTPLAY
) ||
4040 ( dwFlags
& DPCONNECTION_DIRECTPLAYLOBBY
) ) )
4042 return DPERR_INVALIDFLAGS
;
4045 if( !lpEnumCallback
)
4047 return DPERR_INVALIDPARAMS
;
4051 /* Need to loop over the service providers in the registry */
4052 if( RegOpenKeyExW( HKEY_LOCAL_MACHINE
,
4053 ( dwFlags
& DPCONNECTION_DIRECTPLAY
) ? searchSubKeySP
4055 0, KEY_READ
, &hkResult
) != ERROR_SUCCESS
)
4057 /* Hmmm. Does this mean that there are no service providers? */
4058 ERR(": no service providers?\n");
4063 /* Traverse all the service providers we have available */
4065 RegEnumKeyExW( hkResult
, dwIndex
, subKeyName
, &sizeOfSubKeyName
,
4066 NULL
, NULL
, NULL
, &filetime
) != ERROR_NO_MORE_ITEMS
;
4067 ++dwIndex
, sizeOfSubKeyName
= sizeof(subKeyName
) / sizeof(WCHAR
) )
4069 HKEY hkServiceProvider
;
4070 GUID serviceProviderGUID
;
4071 WCHAR guidKeyContent
[39];
4072 DWORD sizeOfReturnBuffer
= sizeof(guidKeyContent
);
4074 BOOL continueEnumeration
= TRUE
;
4076 LPVOID lpAddressBuffer
= NULL
;
4077 DWORD dwAddressBufferSize
= 0;
4080 TRACE(" this time through: %s\n", debugstr_w(subKeyName
) );
4082 /* Get a handle for this particular service provider */
4083 if( RegOpenKeyExW( hkResult
, subKeyName
, 0, KEY_READ
,
4084 &hkServiceProvider
) != ERROR_SUCCESS
)
4086 ERR(": what the heck is going on?\n" );
4090 if( RegQueryValueExW( hkServiceProvider
, guidDataSubKey
,
4091 NULL
, NULL
, (LPBYTE
)guidKeyContent
,
4092 &sizeOfReturnBuffer
) != ERROR_SUCCESS
)
4094 ERR(": missing GUID registry data members\n" );
4095 RegCloseKey(hkServiceProvider
);
4098 RegCloseKey(hkServiceProvider
);
4100 CLSIDFromString( guidKeyContent
, &serviceProviderGUID
);
4102 /* Fill in the DPNAME struct for the service provider */
4103 dpName
.dwSize
= sizeof( dpName
);
4107 dpName
.u1
.lpszShortNameA
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
4108 sizeOfSubKeyName
+1 );
4109 WideCharToMultiByte( CP_ACP
, 0, subKeyName
,
4110 -1, dpName
.u1
.lpszShortNameA
, -1, 0, 0);
4111 dpName
.u2
.lpszLongNameA
= NULL
;
4115 dpName
.u1
.lpszShortName
= subKeyName
;
4116 dpName
.u2
.lpszLongName
= NULL
;
4119 /* Create the compound address for the service provider.
4120 * NOTE: This is a gruesome architectural scar right now. DP
4121 * uses DPL and DPL uses DP. Nasty stuff. This may be why the
4122 * native dll just gets around this little bit by allocating an
4123 * 80 byte buffer which isn't even filled with a valid compound
4124 * address. Oh well. Creating a proper compound address is the
4125 * way to go anyways despite this method taking slightly more
4126 * heap space and realtime :) */
4128 if ( DP_BuildCompoundAddr( ( ( dwFlags
& DPCONNECTION_DIRECTPLAY
)
4129 ? DPAID_ServiceProvider
4130 : DPAID_LobbyProvider
),
4131 &serviceProviderGUID
,
4133 &dwAddressBufferSize
) )
4135 /* The enumeration will return FALSE if we are not to continue */
4136 continueEnumeration
= lpEnumCallback( &serviceProviderGUID
, lpAddressBuffer
,
4137 dwAddressBufferSize
, &dpName
,
4138 dwFlags
, lpContext
);
4142 ERR( "Couldn't build compound address\n" );
4145 HeapFree( GetProcessHeap(), 0, lpAddressBuffer
);
4147 HeapFree( GetProcessHeap(), 0, dpName
.u1
.lpszShortNameA
);
4149 if (!continueEnumeration
)
4156 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
4157 ( LPDIRECTPLAY3A iface
, LPCGUID lpguidApplication
, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback
, LPVOID lpContext
, DWORD dwFlags
)
4159 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4160 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This
, lpguidApplication
, lpEnumCallback
, lpContext
, dwFlags
);
4161 return DP_IF_EnumConnections( iface
, lpguidApplication
, lpEnumCallback
, lpContext
, dwFlags
, TRUE
);
4164 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
4165 ( LPDIRECTPLAY3 iface
, LPCGUID lpguidApplication
, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback
, LPVOID lpContext
, DWORD dwFlags
)
4167 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4168 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This
, lpguidApplication
, lpEnumCallback
, lpContext
, dwFlags
);
4169 return DP_IF_EnumConnections( iface
, lpguidApplication
, lpEnumCallback
, lpContext
, dwFlags
, FALSE
);
4172 static HRESULT DP_IF_EnumGroupsInGroup
4173 ( IDirectPlay3AImpl
* This
, DPID idGroup
, LPGUID lpguidInstance
,
4174 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
4175 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
)
4177 lpGroupList lpGList
;
4178 lpGroupData lpGData
;
4180 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
4181 This
, idGroup
, lpguidInstance
, lpEnumPlayersCallback2
,
4182 lpContext
, dwFlags
, bAnsi
);
4184 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
4186 return DPERR_UNINITIALIZED
;
4189 if( !This
->dp2
->bConnectionOpen
)
4191 return DPERR_NOSESSIONS
;
4194 if( ( lpEnumPlayersCallback2
== NULL
) ||
4195 ( ( dwFlags
& DPENUMGROUPS_SESSION
) && ( lpguidInstance
== NULL
) ) )
4197 return DPERR_INVALIDPARAMS
;
4200 if( ( lpGData
= DP_FindAnyGroup( (IDirectPlay2AImpl
*)This
, idGroup
) ) == NULL
)
4202 return DPERR_INVALIDGROUP
;
4205 if( DPQ_IS_EMPTY( lpGData
->groups
) )
4210 lpGList
= DPQ_FIRST( lpGData
->groups
);
4214 /* FIXME: Should check dwFlags for match here */
4216 if( !(*lpEnumPlayersCallback2
)( lpGList
->lpGData
->dpid
, DPPLAYERTYPE_GROUP
,
4217 &lpGList
->lpGData
->name
, dwFlags
,
4220 return DP_OK
; /* User requested break */
4223 if( DPQ_IS_ENDOFLIST( lpGList
->groups
) )
4228 lpGList
= DPQ_NEXT( lpGList
->groups
);
4235 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
4236 ( LPDIRECTPLAY3A iface
, DPID idGroup
, LPGUID lpguidInstance
,
4237 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
, LPVOID lpContext
,
4240 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4241 return DP_IF_EnumGroupsInGroup( This
, idGroup
, lpguidInstance
,
4242 lpEnumPlayersCallback2
, lpContext
, dwFlags
,
4246 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
4247 ( LPDIRECTPLAY3A iface
, DPID idGroup
, LPGUID lpguidInstance
,
4248 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
, LPVOID lpContext
,
4251 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4252 return DP_IF_EnumGroupsInGroup( This
, idGroup
, lpguidInstance
,
4253 lpEnumPlayersCallback2
, lpContext
, dwFlags
,
4257 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
4258 ( LPDIRECTPLAY3A iface
, DWORD dwFlags
, DPID idGroup
, LPVOID lpData
, LPDWORD lpdwDataSize
)
4260 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4261 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This
, dwFlags
, idGroup
, lpData
, lpdwDataSize
);
4265 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
4266 ( LPDIRECTPLAY3 iface
, DWORD dwFlags
, DPID idGroup
, LPVOID lpData
, LPDWORD lpdwDataSize
)
4268 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4269 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This
, dwFlags
, idGroup
, lpData
, lpdwDataSize
);
4273 static BOOL CALLBACK
DP_GetSpLpGuidFromCompoundAddress(
4274 REFGUID guidDataType
,
4279 /* Looking for the GUID of the provider to load */
4280 if( ( IsEqualGUID( guidDataType
, &DPAID_ServiceProvider
) ) ||
4281 ( IsEqualGUID( guidDataType
, &DPAID_LobbyProvider
) )
4284 TRACE( "Found SP/LP (%s) %s (data size = 0x%08x)\n",
4285 debugstr_guid( guidDataType
), debugstr_guid( lpData
), dwDataSize
);
4287 if( dwDataSize
!= sizeof( GUID
) )
4289 ERR( "Invalid sp/lp guid size 0x%08x\n", dwDataSize
);
4292 memcpy( lpContext
, lpData
, dwDataSize
);
4294 /* There shouldn't be more than 1 GUID/compound address */
4298 /* Still waiting for what we want */
4303 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
4304 static HMODULE
DP_LoadSP( LPCGUID lpcGuid
, LPSPINITDATA lpSpData
, LPBOOL lpbIsDpSp
)
4307 LPCSTR spSubKey
= "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4308 LPCSTR lpSubKey
= "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
4309 LPCSTR guidDataSubKey
= "Guid";
4310 LPCSTR majVerDataSubKey
= "dwReserved1";
4311 LPCSTR minVerDataSubKey
= "dwReserved2";
4312 LPCSTR pathSubKey
= "Path";
4314 TRACE( " request to load %s\n", debugstr_guid( lpcGuid
) );
4316 /* FIXME: Cloned code with a quick hack. */
4317 for( i
=0; i
<2; i
++ )
4320 LPCSTR searchSubKey
;
4321 char subKeyName
[51];
4322 DWORD dwIndex
, sizeOfSubKeyName
=50;
4325 (i
== 0) ? (searchSubKey
= spSubKey
) : (searchSubKey
= lpSubKey
);
4326 *lpbIsDpSp
= (i
== 0) ? TRUE
: FALSE
;
4329 /* Need to loop over the service providers in the registry */
4330 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE
, searchSubKey
,
4331 0, KEY_READ
, &hkResult
) != ERROR_SUCCESS
)
4333 /* Hmmm. Does this mean that there are no service providers? */
4334 ERR(": no service providers?\n");
4338 /* Traverse all the service providers we have available */
4340 RegEnumKeyExA( hkResult
, dwIndex
, subKeyName
, &sizeOfSubKeyName
,
4341 NULL
, NULL
, NULL
, &filetime
) != ERROR_NO_MORE_ITEMS
;
4342 ++dwIndex
, sizeOfSubKeyName
=51 )
4345 HKEY hkServiceProvider
;
4346 GUID serviceProviderGUID
;
4347 DWORD returnType
, sizeOfReturnBuffer
= 255;
4348 char returnBuffer
[256];
4352 TRACE(" this time through: %s\n", subKeyName
);
4354 /* Get a handle for this particular service provider */
4355 if( RegOpenKeyExA( hkResult
, subKeyName
, 0, KEY_READ
,
4356 &hkServiceProvider
) != ERROR_SUCCESS
)
4358 ERR(": what the heck is going on?\n" );
4362 if( RegQueryValueExA( hkServiceProvider
, guidDataSubKey
,
4363 NULL
, &returnType
, (LPBYTE
)returnBuffer
,
4364 &sizeOfReturnBuffer
) != ERROR_SUCCESS
)
4366 ERR(": missing GUID registry data members\n" );
4370 /* FIXME: Check return types to ensure we're interpreting data right */
4371 MultiByteToWideChar( CP_ACP
, 0, returnBuffer
, -1, buff
, sizeof(buff
)/sizeof(WCHAR
) );
4372 CLSIDFromString( buff
, &serviceProviderGUID
);
4373 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4375 /* Determine if this is the Service Provider that the user asked for */
4376 if( !IsEqualGUID( &serviceProviderGUID
, lpcGuid
) )
4381 if( i
== 0 ) /* DP SP */
4383 len
= MultiByteToWideChar( CP_ACP
, 0, subKeyName
, -1, NULL
, 0 );
4384 lpSpData
->lpszName
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof(WCHAR
) );
4385 MultiByteToWideChar( CP_ACP
, 0, subKeyName
, -1, lpSpData
->lpszName
, len
);
4388 sizeOfReturnBuffer
= 255;
4390 /* Get dwReserved1 */
4391 if( RegQueryValueExA( hkServiceProvider
, majVerDataSubKey
,
4392 NULL
, &returnType
, (LPBYTE
)returnBuffer
,
4393 &sizeOfReturnBuffer
) != ERROR_SUCCESS
)
4395 ERR(": missing dwReserved1 registry data members\n") ;
4400 memcpy( &lpSpData
->dwReserved1
, returnBuffer
, sizeof(lpSpData
->dwReserved1
) );
4402 sizeOfReturnBuffer
= 255;
4404 /* Get dwReserved2 */
4405 if( RegQueryValueExA( hkServiceProvider
, minVerDataSubKey
,
4406 NULL
, &returnType
, (LPBYTE
)returnBuffer
,
4407 &sizeOfReturnBuffer
) != ERROR_SUCCESS
)
4409 ERR(": missing dwReserved1 registry data members\n") ;
4414 memcpy( &lpSpData
->dwReserved2
, returnBuffer
, sizeof(lpSpData
->dwReserved2
) );
4416 sizeOfReturnBuffer
= 255;
4418 /* Get the path for this service provider */
4419 if( ( dwTemp
= RegQueryValueExA( hkServiceProvider
, pathSubKey
,
4420 NULL
, NULL
, (LPBYTE
)returnBuffer
,
4421 &sizeOfReturnBuffer
) ) != ERROR_SUCCESS
)
4423 ERR(": missing PATH registry data members: 0x%08x\n", dwTemp
);
4427 TRACE( "Loading %s\n", returnBuffer
);
4428 return LoadLibraryA( returnBuffer
);
4436 HRESULT
DP_InitializeDPSP( IDirectPlay3Impl
* This
, HMODULE hServiceProvider
)
4439 LPDPSP_SPINIT SPInit
;
4441 /* Initialize the service provider by calling SPInit */
4442 SPInit
= (LPDPSP_SPINIT
)GetProcAddress( hServiceProvider
, "SPInit" );
4444 if( SPInit
== NULL
)
4446 ERR( "Service provider doesn't provide SPInit interface?\n" );
4447 FreeLibrary( hServiceProvider
);
4448 return DPERR_UNAVAILABLE
;
4451 TRACE( "Calling SPInit (DP SP entry point)\n" );
4453 hr
= (*SPInit
)( &This
->dp2
->spData
);
4457 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr
) );
4458 FreeLibrary( hServiceProvider
);
4462 /* FIXME: Need to verify the sanity of the returned callback table
4463 * using IsBadCodePtr */
4464 This
->dp2
->bSPInitialized
= TRUE
;
4466 /* This interface is now initialized as a DP object */
4467 This
->dp2
->connectionInitialized
= DP_SERVICE_PROVIDER
;
4469 /* Store the handle of the module so that we can unload it later */
4470 This
->dp2
->hServiceProvider
= hServiceProvider
;
4476 HRESULT
DP_InitializeDPLSP( IDirectPlay3Impl
* This
, HMODULE hLobbyProvider
)
4479 LPSP_INIT DPLSPInit
;
4481 /* Initialize the service provider by calling SPInit */
4482 DPLSPInit
= (LPSP_INIT
)GetProcAddress( hLobbyProvider
, "DPLSPInit" );
4484 if( DPLSPInit
== NULL
)
4486 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4487 FreeLibrary( hLobbyProvider
);
4488 return DPERR_UNAVAILABLE
;
4491 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4493 hr
= (*DPLSPInit
)( &This
->dp2
->dplspData
);
4497 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr
) );
4498 FreeLibrary( hLobbyProvider
);
4502 /* FIXME: Need to verify the sanity of the returned callback table
4503 * using IsBadCodePtr */
4505 This
->dp2
->bDPLSPInitialized
= TRUE
;
4507 /* This interface is now initialized as a lobby object */
4508 This
->dp2
->connectionInitialized
= DP_LOBBY_PROVIDER
;
4510 /* Store the handle of the module so that we can unload it later */
4511 This
->dp2
->hDPLobbyProvider
= hLobbyProvider
;
4516 static HRESULT DP_IF_InitializeConnection
4517 ( IDirectPlay3Impl
* This
, LPVOID lpConnection
, DWORD dwFlags
, BOOL bAnsi
)
4519 HMODULE hServiceProvider
;
4522 const DWORD dwAddrSize
= 80; /* FIXME: Need to calculate it correctly */
4523 BOOL bIsDpSp
; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4525 TRACE("(%p)->(%p,0x%08x,%u)\n", This
, lpConnection
, dwFlags
, bAnsi
);
4527 if ( lpConnection
== NULL
)
4529 return DPERR_INVALIDPARAMS
;
4534 return DPERR_INVALIDFLAGS
;
4537 if( This
->dp2
->connectionInitialized
!= NO_PROVIDER
)
4539 return DPERR_ALREADYINITIALIZED
;
4542 /* Find out what the requested SP is and how large this buffer is */
4543 hr
= DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress
, lpConnection
,
4544 dwAddrSize
, &guidSP
);
4548 ERR( "Invalid compound address?\n" );
4549 return DPERR_UNAVAILABLE
;
4552 /* Load the service provider */
4553 hServiceProvider
= DP_LoadSP( &guidSP
, &This
->dp2
->spData
, &bIsDpSp
);
4555 if( hServiceProvider
== 0 )
4557 ERR( "Unable to load service provider %s\n", debugstr_guid(&guidSP
) );
4558 return DPERR_UNAVAILABLE
;
4563 /* Fill in what we can of the Service Provider required information.
4564 * The rest was be done in DP_LoadSP
4566 This
->dp2
->spData
.lpAddress
= lpConnection
;
4567 This
->dp2
->spData
.dwAddressSize
= dwAddrSize
;
4568 This
->dp2
->spData
.lpGuid
= &guidSP
;
4570 hr
= DP_InitializeDPSP( This
, hServiceProvider
);
4574 This
->dp2
->dplspData
.lpAddress
= lpConnection
;
4576 hr
= DP_InitializeDPLSP( This
, hServiceProvider
);
4587 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4588 ( LPDIRECTPLAY3A iface
, LPVOID lpConnection
, DWORD dwFlags
)
4590 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4591 return DP_IF_InitializeConnection( This
, lpConnection
, dwFlags
, TRUE
);
4594 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4595 ( LPDIRECTPLAY3 iface
, LPVOID lpConnection
, DWORD dwFlags
)
4597 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4598 return DP_IF_InitializeConnection( This
, lpConnection
, dwFlags
, FALSE
);
4601 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4602 ( LPDIRECTPLAY3A iface
, LPCDPSESSIONDESC2 lpsd
, DWORD dwFlags
,
4603 LPCDPSECURITYDESC lpSecurity
, LPCDPCREDENTIALS lpCredentials
)
4605 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
; /* Yes a dp 2 interface */
4606 return DP_SecureOpen( This
, lpsd
, dwFlags
, lpSecurity
, lpCredentials
, TRUE
);
4609 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4610 ( LPDIRECTPLAY3 iface
, LPCDPSESSIONDESC2 lpsd
, DWORD dwFlags
,
4611 LPCDPSECURITYDESC lpSecurity
, LPCDPCREDENTIALS lpCredentials
)
4613 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
; /* Yes a dp 2 interface */
4614 return DP_SecureOpen( This
, lpsd
, dwFlags
, lpSecurity
, lpCredentials
, FALSE
);
4617 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4618 ( LPDIRECTPLAY3A iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
, LPDPCHAT lpChatMessage
)
4620 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4621 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This
, idFrom
, idTo
, dwFlags
, lpChatMessage
);
4625 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4626 ( LPDIRECTPLAY3 iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
, LPDPCHAT lpChatMessage
)
4628 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4629 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This
, idFrom
, idTo
, dwFlags
, lpChatMessage
);
4633 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4634 ( LPDIRECTPLAY3A iface
, DWORD dwFlags
, DPID idGroup
, LPDPLCONNECTION lpConnection
)
4636 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4637 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This
, dwFlags
, idGroup
, lpConnection
);
4641 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4642 ( LPDIRECTPLAY3 iface
, DWORD dwFlags
, DPID idGroup
, LPDPLCONNECTION lpConnection
)
4644 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4645 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This
, dwFlags
, idGroup
, lpConnection
);
4649 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4650 ( LPDIRECTPLAY3A iface
, DWORD dwFlags
, DPID idGroup
)
4652 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4653 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This
, dwFlags
, idGroup
);
4657 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4658 ( LPDIRECTPLAY3 iface
, DWORD dwFlags
, DPID idGroup
)
4660 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4661 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This
, dwFlags
, idGroup
);
4665 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4666 ( LPDIRECTPLAY3A iface
, DPID idGroup
, LPDWORD lpdwFlags
)
4668 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4669 FIXME("(%p)->(0x%08x,%p): stub\n", This
, idGroup
, lpdwFlags
);
4673 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4674 ( LPDIRECTPLAY3 iface
, DPID idGroup
, LPDWORD lpdwFlags
)
4676 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4677 FIXME("(%p)->(0x%08x,%p): stub\n", This
, idGroup
, lpdwFlags
);
4681 static HRESULT DP_IF_GetGroupParent
4682 ( IDirectPlay3AImpl
* This
, DPID idGroup
, LPDPID lpidGroup
,
4685 lpGroupData lpGData
;
4687 TRACE("(%p)->(0x%08x,%p,%u)\n", This
, idGroup
, lpidGroup
, bAnsi
);
4689 if( ( lpGData
= DP_FindAnyGroup( (IDirectPlay2AImpl
*)This
, idGroup
) ) == NULL
)
4691 return DPERR_INVALIDGROUP
;
4694 *lpidGroup
= lpGData
->dpid
;
4699 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4700 ( LPDIRECTPLAY3A iface
, DPID idGroup
, LPDPID lpidGroup
)
4702 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4703 return DP_IF_GetGroupParent( This
, idGroup
, lpidGroup
, TRUE
);
4705 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4706 ( LPDIRECTPLAY3 iface
, DPID idGroup
, LPDPID lpidGroup
)
4708 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4709 return DP_IF_GetGroupParent( This
, idGroup
, lpidGroup
, FALSE
);
4712 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4713 ( LPDIRECTPLAY3A iface
, DPID idPlayer
, DWORD dwFlags
, LPVOID lpData
, LPDWORD lpdwDataSize
)
4715 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4716 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This
, idPlayer
, dwFlags
, lpData
, lpdwDataSize
);
4720 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4721 ( LPDIRECTPLAY3 iface
, DPID idPlayer
, DWORD dwFlags
, LPVOID lpData
, LPDWORD lpdwDataSize
)
4723 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4724 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This
, idPlayer
, dwFlags
, lpData
, lpdwDataSize
);
4728 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4729 ( LPDIRECTPLAY3A iface
, DPID idPlayer
, LPDWORD lpdwFlags
)
4731 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4732 FIXME("(%p)->(0x%08x,%p): stub\n", This
, idPlayer
, lpdwFlags
);
4736 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4737 ( LPDIRECTPLAY3 iface
, DPID idPlayer
, LPDWORD lpdwFlags
)
4739 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4740 FIXME("(%p)->(0x%08x,%p): stub\n", This
, idPlayer
, lpdwFlags
);
4744 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4745 ( LPDIRECTPLAY4A iface
, DPID idGroup
, LPDPID lpidGroupOwner
)
4747 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4748 FIXME("(%p)->(0x%08x,%p): stub\n", This
, idGroup
, lpidGroupOwner
);
4752 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4753 ( LPDIRECTPLAY4 iface
, DPID idGroup
, LPDPID lpidGroupOwner
)
4755 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4756 FIXME("(%p)->(0x%08x,%p): stub\n", This
, idGroup
, lpidGroupOwner
);
4760 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4761 ( LPDIRECTPLAY4A iface
, DPID idGroup
, DPID idGroupOwner
)
4763 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4764 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This
, idGroup
, idGroupOwner
);
4768 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4769 ( LPDIRECTPLAY4 iface
, DPID idGroup
, DPID idGroupOwner
)
4771 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4772 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This
, idGroup
, idGroupOwner
);
4776 static HRESULT DP_SendEx
4777 ( IDirectPlay2Impl
* This
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
4778 LPVOID lpData
, DWORD dwDataSize
, DWORD dwPriority
, DWORD dwTimeout
,
4779 LPVOID lpContext
, LPDWORD lpdwMsgID
, BOOL bAnsi
)
4781 lpGroupData lpGData
;
4784 TRACE( "(%p)->(0x%08x,0x%08x,0x%08x,%p,0x%08x,0x%08x,0x%08x,%p,%p,%u)\n",
4785 This
, idFrom
, idTo
, dwFlags
, lpData
, dwDataSize
, dwPriority
,
4786 dwTimeout
, lpContext
, lpdwMsgID
, bAnsi
);
4788 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
4790 return DPERR_UNINITIALIZED
;
4793 /* FIXME: Add parameter checking */
4794 /* FIXME: First call to this needs to acquire a message id which will be
4795 * used for multiple sends
4798 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4800 /* Check idFrom points to a valid player */
4801 if ( DP_FindPlayer( This
, idFrom
) == NULL
)
4803 ERR( "Invalid from player 0x%08x\n", idFrom
);
4804 return DPERR_INVALIDPLAYER
;
4807 /* Check idTo: it can be a player or a group */
4808 if( idTo
== DPID_ALLPLAYERS
)
4810 bSendToGroup
= TRUE
;
4811 lpGData
= This
->dp2
->lpSysGroup
;
4813 else if ( DP_FindPlayer( This
, idTo
) )
4815 bSendToGroup
= FALSE
;
4817 else if ( ( lpGData
= DP_FindAnyGroup( This
, idTo
) ) )
4819 bSendToGroup
= TRUE
;
4823 return DPERR_INVALIDPLAYER
;
4829 DPSP_SENDTOGROUPEXDATA data
;
4831 data
.lpISP
= This
->dp2
->spData
.lpISP
;
4832 data
.dwFlags
= dwFlags
;
4833 data
.idGroupTo
= idTo
;
4834 data
.idPlayerFrom
= idFrom
;
4835 data
.lpSendBuffers
= lpData
;
4836 data
.cBuffers
= NULL
;
4837 data
.dwMessageSize
= dwDataSize
;
4838 data
.dwPriority
= dwPriority
;
4839 data
.dwTimeout
= dwTimeout
;
4840 data
.lpDPContext
= lpContext
;
4841 data
.lpdwSPMsgID
= lpdwMsgID
;
4843 return (*This
->dp2
->spData
.lpCB
->SendToGroupEx
)( &data
);
4846 lpPlayerList lpPList
;
4848 data
.dwFlags
= dwFlags
;
4849 data
.idPlayerFrom
= idFrom
;
4850 data
.lpMessage
= lpData
;
4851 data
.dwMessageSize
= dwDataSize
;
4852 data
.bSystemMessage
= FALSE
;
4853 data
.lpISP
= This
->dp2
->spData
.lpISP
;
4855 if ( (lpPList
= DPQ_FIRST( lpGData
->players
)) )
4859 if ( ~lpPList
->lpPData
->dwFlags
& DPLAYI_PLAYER_PLAYERLOCAL
)
4861 data
.idPlayerTo
= lpPList
->lpPData
->dpid
;
4862 (*This
->dp2
->spData
.lpCB
->Send
)( &data
);
4865 while( (lpPList
= DPQ_NEXT( lpPList
->players
)) );
4872 data
.dwFlags
= dwFlags
;
4873 data
.idPlayerFrom
= idFrom
;
4874 data
.idPlayerTo
= idTo
;
4875 data
.lpMessage
= lpData
;
4876 data
.dwMessageSize
= dwDataSize
;
4877 data
.bSystemMessage
= FALSE
;
4878 data
.lpISP
= This
->dp2
->spData
.lpISP
;
4880 return (*This
->dp2
->spData
.lpCB
->Send
)( &data
);
4883 /* Have the service provider send this message */
4885 return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority,
4886 dwTimeout, lpContext, lpdwMsgID );*/
4892 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4893 ( LPDIRECTPLAY4A iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
4894 LPVOID lpData
, DWORD dwDataSize
, DWORD dwPriority
, DWORD dwTimeout
,
4895 LPVOID lpContext
, LPDWORD lpdwMsgID
)
4897 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
; /* yes downcast to 2 */
4898 return DP_SendEx( This
, idFrom
, idTo
, dwFlags
, lpData
, dwDataSize
,
4899 dwPriority
, dwTimeout
, lpContext
, lpdwMsgID
, TRUE
);
4902 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4903 ( LPDIRECTPLAY4 iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
4904 LPVOID lpData
, DWORD dwDataSize
, DWORD dwPriority
, DWORD dwTimeout
,
4905 LPVOID lpContext
, LPDWORD lpdwMsgID
)
4907 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
; /* yes downcast to 2 */
4908 return DP_SendEx( This
, idFrom
, idTo
, dwFlags
, lpData
, dwDataSize
,
4909 dwPriority
, dwTimeout
, lpContext
, lpdwMsgID
, FALSE
);
4912 static HRESULT DP_SP_SendEx
4913 ( IDirectPlay2Impl
* This
, DWORD dwFlags
,
4914 LPVOID lpData
, DWORD dwDataSize
, DWORD dwPriority
, DWORD dwTimeout
,
4915 LPVOID lpContext
, LPDWORD lpdwMsgID
)
4919 FIXME( ": stub\n" );
4921 /* FIXME: This queuing should only be for async messages */
4923 lpMElem
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpMElem
) );
4924 lpMElem
->msg
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, dwDataSize
);
4926 CopyMemory( lpMElem
->msg
, lpData
, dwDataSize
);
4928 /* FIXME: Need to queue based on priority */
4929 DPQ_INSERT( This
->dp2
->sendMsgs
, lpMElem
, msgs
);
4934 static HRESULT DP_IF_GetMessageQueue
4935 ( IDirectPlay4Impl
* This
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
4936 LPDWORD lpdwNumMsgs
, LPDWORD lpdwNumBytes
, BOOL bAnsi
)
4940 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%p,%u): semi stub\n",
4941 This
, idFrom
, idTo
, dwFlags
, lpdwNumMsgs
, lpdwNumBytes
, bAnsi
);
4943 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4944 /* FIXME: What about sends which are not immediate? */
4946 if( This
->dp2
->spData
.lpCB
->GetMessageQueue
)
4948 DPSP_GETMESSAGEQUEUEDATA data
;
4950 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4952 /* FIXME: None of this is documented :( */
4954 data
.lpISP
= This
->dp2
->spData
.lpISP
;
4955 data
.dwFlags
= dwFlags
;
4956 data
.idFrom
= idFrom
;
4958 data
.lpdwNumMsgs
= lpdwNumMsgs
;
4959 data
.lpdwNumBytes
= lpdwNumBytes
;
4961 hr
= (*This
->dp2
->spData
.lpCB
->GetMessageQueue
)( &data
);
4965 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4971 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4972 ( LPDIRECTPLAY4A iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
4973 LPDWORD lpdwNumMsgs
, LPDWORD lpdwNumBytes
)
4975 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4976 return DP_IF_GetMessageQueue( This
, idFrom
, idTo
, dwFlags
, lpdwNumMsgs
,
4977 lpdwNumBytes
, TRUE
);
4980 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4981 ( LPDIRECTPLAY4 iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
4982 LPDWORD lpdwNumMsgs
, LPDWORD lpdwNumBytes
)
4984 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4985 return DP_IF_GetMessageQueue( This
, idFrom
, idTo
, dwFlags
, lpdwNumMsgs
,
4986 lpdwNumBytes
, FALSE
);
4989 static HRESULT DP_IF_CancelMessage
4990 ( IDirectPlay4Impl
* This
, DWORD dwMsgID
, DWORD dwFlags
,
4991 DWORD dwMinPriority
, DWORD dwMaxPriority
, BOOL bAnsi
)
4995 FIXME( "(%p)->(0x%08x,0x%08x,%u): semi stub\n",
4996 This
, dwMsgID
, dwFlags
, bAnsi
);
4998 if( This
->dp2
->spData
.lpCB
->Cancel
)
5000 DPSP_CANCELDATA data
;
5002 TRACE( "Calling SP Cancel\n" );
5004 /* FIXME: Undocumented callback */
5006 data
.lpISP
= This
->dp2
->spData
.lpISP
;
5007 data
.dwFlags
= dwFlags
;
5008 data
.lprglpvSPMsgID
= NULL
;
5009 data
.cSPMsgID
= dwMsgID
;
5010 data
.dwMinPriority
= dwMinPriority
;
5011 data
.dwMaxPriority
= dwMaxPriority
;
5013 hr
= (*This
->dp2
->spData
.lpCB
->Cancel
)( &data
);
5017 FIXME( "SP doesn't implement Cancel\n" );
5023 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
5024 ( LPDIRECTPLAY4A iface
, DWORD dwMsgID
, DWORD dwFlags
)
5026 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
5030 return DPERR_INVALIDFLAGS
;
5035 dwFlags
|= DPCANCELSEND_ALL
;
5038 return DP_IF_CancelMessage( This
, dwMsgID
, dwFlags
, 0, 0, TRUE
);
5041 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
5042 ( LPDIRECTPLAY4 iface
, DWORD dwMsgID
, DWORD dwFlags
)
5044 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
5048 return DPERR_INVALIDFLAGS
;
5053 dwFlags
|= DPCANCELSEND_ALL
;
5056 return DP_IF_CancelMessage( This
, dwMsgID
, dwFlags
, 0, 0, FALSE
);
5059 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
5060 ( LPDIRECTPLAY4A iface
, DWORD dwMinPriority
, DWORD dwMaxPriority
,
5063 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
5067 return DPERR_INVALIDFLAGS
;
5070 return DP_IF_CancelMessage( This
, 0, DPCANCELSEND_PRIORITY
, dwMinPriority
,
5071 dwMaxPriority
, TRUE
);
5074 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
5075 ( LPDIRECTPLAY4 iface
, DWORD dwMinPriority
, DWORD dwMaxPriority
,
5078 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
5082 return DPERR_INVALIDFLAGS
;
5085 return DP_IF_CancelMessage( This
, 0, DPCANCELSEND_PRIORITY
, dwMinPriority
,
5086 dwMaxPriority
, FALSE
);
5089 /* Note: Hack so we can reuse the old functions without compiler warnings */
5090 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5091 # define XCAST(fun) (typeof(directPlay2WVT.fun))
5093 # define XCAST(fun) (void*)
5096 static const IDirectPlay2Vtbl directPlay2WVT
=
5098 XCAST(QueryInterface
)DP_QueryInterface
,
5099 XCAST(AddRef
)DP_AddRef
,
5100 XCAST(Release
)DP_Release
,
5102 DirectPlay2WImpl_AddPlayerToGroup
,
5103 DirectPlay2WImpl_Close
,
5104 DirectPlay2WImpl_CreateGroup
,
5105 DirectPlay2WImpl_CreatePlayer
,
5106 DirectPlay2WImpl_DeletePlayerFromGroup
,
5107 DirectPlay2WImpl_DestroyGroup
,
5108 DirectPlay2WImpl_DestroyPlayer
,
5109 DirectPlay2WImpl_EnumGroupPlayers
,
5110 DirectPlay2WImpl_EnumGroups
,
5111 DirectPlay2WImpl_EnumPlayers
,
5112 DirectPlay2WImpl_EnumSessions
,
5113 DirectPlay2WImpl_GetCaps
,
5114 DirectPlay2WImpl_GetGroupData
,
5115 DirectPlay2WImpl_GetGroupName
,
5116 DirectPlay2WImpl_GetMessageCount
,
5117 DirectPlay2WImpl_GetPlayerAddress
,
5118 DirectPlay2WImpl_GetPlayerCaps
,
5119 DirectPlay2WImpl_GetPlayerData
,
5120 DirectPlay2WImpl_GetPlayerName
,
5121 DirectPlay2WImpl_GetSessionDesc
,
5122 DirectPlay2WImpl_Initialize
,
5123 DirectPlay2WImpl_Open
,
5124 DirectPlay2WImpl_Receive
,
5125 DirectPlay2WImpl_Send
,
5126 DirectPlay2WImpl_SetGroupData
,
5127 DirectPlay2WImpl_SetGroupName
,
5128 DirectPlay2WImpl_SetPlayerData
,
5129 DirectPlay2WImpl_SetPlayerName
,
5130 DirectPlay2WImpl_SetSessionDesc
5134 /* Note: Hack so we can reuse the old functions without compiler warnings */
5135 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5136 # define XCAST(fun) (typeof(directPlay2AVT.fun))
5138 # define XCAST(fun) (void*)
5141 static const IDirectPlay2Vtbl directPlay2AVT
=
5143 XCAST(QueryInterface
)DP_QueryInterface
,
5144 XCAST(AddRef
)DP_AddRef
,
5145 XCAST(Release
)DP_Release
,
5147 DirectPlay2AImpl_AddPlayerToGroup
,
5148 DirectPlay2AImpl_Close
,
5149 DirectPlay2AImpl_CreateGroup
,
5150 DirectPlay2AImpl_CreatePlayer
,
5151 DirectPlay2AImpl_DeletePlayerFromGroup
,
5152 DirectPlay2AImpl_DestroyGroup
,
5153 DirectPlay2AImpl_DestroyPlayer
,
5154 DirectPlay2AImpl_EnumGroupPlayers
,
5155 DirectPlay2AImpl_EnumGroups
,
5156 DirectPlay2AImpl_EnumPlayers
,
5157 DirectPlay2AImpl_EnumSessions
,
5158 DirectPlay2AImpl_GetCaps
,
5159 DirectPlay2AImpl_GetGroupData
,
5160 DirectPlay2AImpl_GetGroupName
,
5161 DirectPlay2AImpl_GetMessageCount
,
5162 DirectPlay2AImpl_GetPlayerAddress
,
5163 DirectPlay2AImpl_GetPlayerCaps
,
5164 DirectPlay2AImpl_GetPlayerData
,
5165 DirectPlay2AImpl_GetPlayerName
,
5166 DirectPlay2AImpl_GetSessionDesc
,
5167 DirectPlay2AImpl_Initialize
,
5168 DirectPlay2AImpl_Open
,
5169 DirectPlay2AImpl_Receive
,
5170 DirectPlay2AImpl_Send
,
5171 DirectPlay2AImpl_SetGroupData
,
5172 DirectPlay2AImpl_SetGroupName
,
5173 DirectPlay2AImpl_SetPlayerData
,
5174 DirectPlay2AImpl_SetPlayerName
,
5175 DirectPlay2AImpl_SetSessionDesc
5180 /* Note: Hack so we can reuse the old functions without compiler warnings */
5181 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5182 # define XCAST(fun) (typeof(directPlay3AVT.fun))
5184 # define XCAST(fun) (void*)
5187 static const IDirectPlay3Vtbl directPlay3AVT
=
5189 XCAST(QueryInterface
)DP_QueryInterface
,
5190 XCAST(AddRef
)DP_AddRef
,
5191 XCAST(Release
)DP_Release
,
5193 XCAST(AddPlayerToGroup
)DirectPlay2AImpl_AddPlayerToGroup
,
5194 XCAST(Close
)DirectPlay2AImpl_Close
,
5195 XCAST(CreateGroup
)DirectPlay2AImpl_CreateGroup
,
5196 XCAST(CreatePlayer
)DirectPlay2AImpl_CreatePlayer
,
5197 XCAST(DeletePlayerFromGroup
)DirectPlay2AImpl_DeletePlayerFromGroup
,
5198 XCAST(DestroyGroup
)DirectPlay2AImpl_DestroyGroup
,
5199 XCAST(DestroyPlayer
)DirectPlay2AImpl_DestroyPlayer
,
5200 XCAST(EnumGroupPlayers
)DirectPlay2AImpl_EnumGroupPlayers
,
5201 XCAST(EnumGroups
)DirectPlay2AImpl_EnumGroups
,
5202 XCAST(EnumPlayers
)DirectPlay2AImpl_EnumPlayers
,
5203 XCAST(EnumSessions
)DirectPlay2AImpl_EnumSessions
,
5204 XCAST(GetCaps
)DirectPlay2AImpl_GetCaps
,
5205 XCAST(GetGroupData
)DirectPlay2AImpl_GetGroupData
,
5206 XCAST(GetGroupName
)DirectPlay2AImpl_GetGroupName
,
5207 XCAST(GetMessageCount
)DirectPlay2AImpl_GetMessageCount
,
5208 XCAST(GetPlayerAddress
)DirectPlay2AImpl_GetPlayerAddress
,
5209 XCAST(GetPlayerCaps
)DirectPlay2AImpl_GetPlayerCaps
,
5210 XCAST(GetPlayerData
)DirectPlay2AImpl_GetPlayerData
,
5211 XCAST(GetPlayerName
)DirectPlay2AImpl_GetPlayerName
,
5212 XCAST(GetSessionDesc
)DirectPlay2AImpl_GetSessionDesc
,
5213 XCAST(Initialize
)DirectPlay2AImpl_Initialize
,
5214 XCAST(Open
)DirectPlay2AImpl_Open
,
5215 XCAST(Receive
)DirectPlay2AImpl_Receive
,
5216 XCAST(Send
)DirectPlay2AImpl_Send
,
5217 XCAST(SetGroupData
)DirectPlay2AImpl_SetGroupData
,
5218 XCAST(SetGroupName
)DirectPlay2AImpl_SetGroupName
,
5219 XCAST(SetPlayerData
)DirectPlay2AImpl_SetPlayerData
,
5220 XCAST(SetPlayerName
)DirectPlay2AImpl_SetPlayerName
,
5221 XCAST(SetSessionDesc
)DirectPlay2AImpl_SetSessionDesc
,
5223 DirectPlay3AImpl_AddGroupToGroup
,
5224 DirectPlay3AImpl_CreateGroupInGroup
,
5225 DirectPlay3AImpl_DeleteGroupFromGroup
,
5226 DirectPlay3AImpl_EnumConnections
,
5227 DirectPlay3AImpl_EnumGroupsInGroup
,
5228 DirectPlay3AImpl_GetGroupConnectionSettings
,
5229 DirectPlay3AImpl_InitializeConnection
,
5230 DirectPlay3AImpl_SecureOpen
,
5231 DirectPlay3AImpl_SendChatMessage
,
5232 DirectPlay3AImpl_SetGroupConnectionSettings
,
5233 DirectPlay3AImpl_StartSession
,
5234 DirectPlay3AImpl_GetGroupFlags
,
5235 DirectPlay3AImpl_GetGroupParent
,
5236 DirectPlay3AImpl_GetPlayerAccount
,
5237 DirectPlay3AImpl_GetPlayerFlags
5241 /* Note: Hack so we can reuse the old functions without compiler warnings */
5242 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5243 # define XCAST(fun) (typeof(directPlay3WVT.fun))
5245 # define XCAST(fun) (void*)
5247 static const IDirectPlay3Vtbl directPlay3WVT
=
5249 XCAST(QueryInterface
)DP_QueryInterface
,
5250 XCAST(AddRef
)DP_AddRef
,
5251 XCAST(Release
)DP_Release
,
5253 XCAST(AddPlayerToGroup
)DirectPlay2WImpl_AddPlayerToGroup
,
5254 XCAST(Close
)DirectPlay2WImpl_Close
,
5255 XCAST(CreateGroup
)DirectPlay2WImpl_CreateGroup
,
5256 XCAST(CreatePlayer
)DirectPlay2WImpl_CreatePlayer
,
5257 XCAST(DeletePlayerFromGroup
)DirectPlay2WImpl_DeletePlayerFromGroup
,
5258 XCAST(DestroyGroup
)DirectPlay2WImpl_DestroyGroup
,
5259 XCAST(DestroyPlayer
)DirectPlay2WImpl_DestroyPlayer
,
5260 XCAST(EnumGroupPlayers
)DirectPlay2WImpl_EnumGroupPlayers
,
5261 XCAST(EnumGroups
)DirectPlay2WImpl_EnumGroups
,
5262 XCAST(EnumPlayers
)DirectPlay2WImpl_EnumPlayers
,
5263 XCAST(EnumSessions
)DirectPlay2WImpl_EnumSessions
,
5264 XCAST(GetCaps
)DirectPlay2WImpl_GetCaps
,
5265 XCAST(GetGroupData
)DirectPlay2WImpl_GetGroupData
,
5266 XCAST(GetGroupName
)DirectPlay2WImpl_GetGroupName
,
5267 XCAST(GetMessageCount
)DirectPlay2WImpl_GetMessageCount
,
5268 XCAST(GetPlayerAddress
)DirectPlay2WImpl_GetPlayerAddress
,
5269 XCAST(GetPlayerCaps
)DirectPlay2WImpl_GetPlayerCaps
,
5270 XCAST(GetPlayerData
)DirectPlay2WImpl_GetPlayerData
,
5271 XCAST(GetPlayerName
)DirectPlay2WImpl_GetPlayerName
,
5272 XCAST(GetSessionDesc
)DirectPlay2WImpl_GetSessionDesc
,
5273 XCAST(Initialize
)DirectPlay2WImpl_Initialize
,
5274 XCAST(Open
)DirectPlay2WImpl_Open
,
5275 XCAST(Receive
)DirectPlay2WImpl_Receive
,
5276 XCAST(Send
)DirectPlay2WImpl_Send
,
5277 XCAST(SetGroupData
)DirectPlay2WImpl_SetGroupData
,
5278 XCAST(SetGroupName
)DirectPlay2WImpl_SetGroupName
,
5279 XCAST(SetPlayerData
)DirectPlay2WImpl_SetPlayerData
,
5280 XCAST(SetPlayerName
)DirectPlay2WImpl_SetPlayerName
,
5281 XCAST(SetSessionDesc
)DirectPlay2WImpl_SetSessionDesc
,
5283 DirectPlay3WImpl_AddGroupToGroup
,
5284 DirectPlay3WImpl_CreateGroupInGroup
,
5285 DirectPlay3WImpl_DeleteGroupFromGroup
,
5286 DirectPlay3WImpl_EnumConnections
,
5287 DirectPlay3WImpl_EnumGroupsInGroup
,
5288 DirectPlay3WImpl_GetGroupConnectionSettings
,
5289 DirectPlay3WImpl_InitializeConnection
,
5290 DirectPlay3WImpl_SecureOpen
,
5291 DirectPlay3WImpl_SendChatMessage
,
5292 DirectPlay3WImpl_SetGroupConnectionSettings
,
5293 DirectPlay3WImpl_StartSession
,
5294 DirectPlay3WImpl_GetGroupFlags
,
5295 DirectPlay3WImpl_GetGroupParent
,
5296 DirectPlay3WImpl_GetPlayerAccount
,
5297 DirectPlay3WImpl_GetPlayerFlags
5301 /* Note: Hack so we can reuse the old functions without compiler warnings */
5302 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5303 # define XCAST(fun) (typeof(directPlay4WVT.fun))
5305 # define XCAST(fun) (void*)
5307 static const IDirectPlay4Vtbl directPlay4WVT
=
5309 XCAST(QueryInterface
)DP_QueryInterface
,
5310 XCAST(AddRef
)DP_AddRef
,
5311 XCAST(Release
)DP_Release
,
5313 XCAST(AddPlayerToGroup
)DirectPlay2WImpl_AddPlayerToGroup
,
5314 XCAST(Close
)DirectPlay2WImpl_Close
,
5315 XCAST(CreateGroup
)DirectPlay2WImpl_CreateGroup
,
5316 XCAST(CreatePlayer
)DirectPlay2WImpl_CreatePlayer
,
5317 XCAST(DeletePlayerFromGroup
)DirectPlay2WImpl_DeletePlayerFromGroup
,
5318 XCAST(DestroyGroup
)DirectPlay2WImpl_DestroyGroup
,
5319 XCAST(DestroyPlayer
)DirectPlay2WImpl_DestroyPlayer
,
5320 XCAST(EnumGroupPlayers
)DirectPlay2WImpl_EnumGroupPlayers
,
5321 XCAST(EnumGroups
)DirectPlay2WImpl_EnumGroups
,
5322 XCAST(EnumPlayers
)DirectPlay2WImpl_EnumPlayers
,
5323 XCAST(EnumSessions
)DirectPlay2WImpl_EnumSessions
,
5324 XCAST(GetCaps
)DirectPlay2WImpl_GetCaps
,
5325 XCAST(GetGroupData
)DirectPlay2WImpl_GetGroupData
,
5326 XCAST(GetGroupName
)DirectPlay2WImpl_GetGroupName
,
5327 XCAST(GetMessageCount
)DirectPlay2WImpl_GetMessageCount
,
5328 XCAST(GetPlayerAddress
)DirectPlay2WImpl_GetPlayerAddress
,
5329 XCAST(GetPlayerCaps
)DirectPlay2WImpl_GetPlayerCaps
,
5330 XCAST(GetPlayerData
)DirectPlay2WImpl_GetPlayerData
,
5331 XCAST(GetPlayerName
)DirectPlay2WImpl_GetPlayerName
,
5332 XCAST(GetSessionDesc
)DirectPlay2WImpl_GetSessionDesc
,
5333 XCAST(Initialize
)DirectPlay2WImpl_Initialize
,
5334 XCAST(Open
)DirectPlay2WImpl_Open
,
5335 XCAST(Receive
)DirectPlay2WImpl_Receive
,
5336 XCAST(Send
)DirectPlay2WImpl_Send
,
5337 XCAST(SetGroupData
)DirectPlay2WImpl_SetGroupData
,
5338 XCAST(SetGroupName
)DirectPlay2WImpl_SetGroupName
,
5339 XCAST(SetPlayerData
)DirectPlay2WImpl_SetPlayerData
,
5340 XCAST(SetPlayerName
)DirectPlay2WImpl_SetPlayerName
,
5341 XCAST(SetSessionDesc
)DirectPlay2WImpl_SetSessionDesc
,
5343 XCAST(AddGroupToGroup
)DirectPlay3WImpl_AddGroupToGroup
,
5344 XCAST(CreateGroupInGroup
)DirectPlay3WImpl_CreateGroupInGroup
,
5345 XCAST(DeleteGroupFromGroup
)DirectPlay3WImpl_DeleteGroupFromGroup
,
5346 XCAST(EnumConnections
)DirectPlay3WImpl_EnumConnections
,
5347 XCAST(EnumGroupsInGroup
)DirectPlay3WImpl_EnumGroupsInGroup
,
5348 XCAST(GetGroupConnectionSettings
)DirectPlay3WImpl_GetGroupConnectionSettings
,
5349 XCAST(InitializeConnection
)DirectPlay3WImpl_InitializeConnection
,
5350 XCAST(SecureOpen
)DirectPlay3WImpl_SecureOpen
,
5351 XCAST(SendChatMessage
)DirectPlay3WImpl_SendChatMessage
,
5352 XCAST(SetGroupConnectionSettings
)DirectPlay3WImpl_SetGroupConnectionSettings
,
5353 XCAST(StartSession
)DirectPlay3WImpl_StartSession
,
5354 XCAST(GetGroupFlags
)DirectPlay3WImpl_GetGroupFlags
,
5355 XCAST(GetGroupParent
)DirectPlay3WImpl_GetGroupParent
,
5356 XCAST(GetPlayerAccount
)DirectPlay3WImpl_GetPlayerAccount
,
5357 XCAST(GetPlayerFlags
)DirectPlay3WImpl_GetPlayerFlags
,
5359 DirectPlay4WImpl_GetGroupOwner
,
5360 DirectPlay4WImpl_SetGroupOwner
,
5361 DirectPlay4WImpl_SendEx
,
5362 DirectPlay4WImpl_GetMessageQueue
,
5363 DirectPlay4WImpl_CancelMessage
,
5364 DirectPlay4WImpl_CancelPriority
5369 /* Note: Hack so we can reuse the old functions without compiler warnings */
5370 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5371 # define XCAST(fun) (typeof(directPlay4AVT.fun))
5373 # define XCAST(fun) (void*)
5375 static const IDirectPlay4Vtbl directPlay4AVT
=
5377 XCAST(QueryInterface
)DP_QueryInterface
,
5378 XCAST(AddRef
)DP_AddRef
,
5379 XCAST(Release
)DP_Release
,
5381 XCAST(AddPlayerToGroup
)DirectPlay2AImpl_AddPlayerToGroup
,
5382 XCAST(Close
)DirectPlay2AImpl_Close
,
5383 XCAST(CreateGroup
)DirectPlay2AImpl_CreateGroup
,
5384 XCAST(CreatePlayer
)DirectPlay2AImpl_CreatePlayer
,
5385 XCAST(DeletePlayerFromGroup
)DirectPlay2AImpl_DeletePlayerFromGroup
,
5386 XCAST(DestroyGroup
)DirectPlay2AImpl_DestroyGroup
,
5387 XCAST(DestroyPlayer
)DirectPlay2AImpl_DestroyPlayer
,
5388 XCAST(EnumGroupPlayers
)DirectPlay2AImpl_EnumGroupPlayers
,
5389 XCAST(EnumGroups
)DirectPlay2AImpl_EnumGroups
,
5390 XCAST(EnumPlayers
)DirectPlay2AImpl_EnumPlayers
,
5391 XCAST(EnumSessions
)DirectPlay2AImpl_EnumSessions
,
5392 XCAST(GetCaps
)DirectPlay2AImpl_GetCaps
,
5393 XCAST(GetGroupData
)DirectPlay2AImpl_GetGroupData
,
5394 XCAST(GetGroupName
)DirectPlay2AImpl_GetGroupName
,
5395 XCAST(GetMessageCount
)DirectPlay2AImpl_GetMessageCount
,
5396 XCAST(GetPlayerAddress
)DirectPlay2AImpl_GetPlayerAddress
,
5397 XCAST(GetPlayerCaps
)DirectPlay2AImpl_GetPlayerCaps
,
5398 XCAST(GetPlayerData
)DirectPlay2AImpl_GetPlayerData
,
5399 XCAST(GetPlayerName
)DirectPlay2AImpl_GetPlayerName
,
5400 XCAST(GetSessionDesc
)DirectPlay2AImpl_GetSessionDesc
,
5401 XCAST(Initialize
)DirectPlay2AImpl_Initialize
,
5402 XCAST(Open
)DirectPlay2AImpl_Open
,
5403 XCAST(Receive
)DirectPlay2AImpl_Receive
,
5404 XCAST(Send
)DirectPlay2AImpl_Send
,
5405 XCAST(SetGroupData
)DirectPlay2AImpl_SetGroupData
,
5406 XCAST(SetGroupName
)DirectPlay2AImpl_SetGroupName
,
5407 XCAST(SetPlayerData
)DirectPlay2AImpl_SetPlayerData
,
5408 XCAST(SetPlayerName
)DirectPlay2AImpl_SetPlayerName
,
5409 XCAST(SetSessionDesc
)DirectPlay2AImpl_SetSessionDesc
,
5411 XCAST(AddGroupToGroup
)DirectPlay3AImpl_AddGroupToGroup
,
5412 XCAST(CreateGroupInGroup
)DirectPlay3AImpl_CreateGroupInGroup
,
5413 XCAST(DeleteGroupFromGroup
)DirectPlay3AImpl_DeleteGroupFromGroup
,
5414 XCAST(EnumConnections
)DirectPlay3AImpl_EnumConnections
,
5415 XCAST(EnumGroupsInGroup
)DirectPlay3AImpl_EnumGroupsInGroup
,
5416 XCAST(GetGroupConnectionSettings
)DirectPlay3AImpl_GetGroupConnectionSettings
,
5417 XCAST(InitializeConnection
)DirectPlay3AImpl_InitializeConnection
,
5418 XCAST(SecureOpen
)DirectPlay3AImpl_SecureOpen
,
5419 XCAST(SendChatMessage
)DirectPlay3AImpl_SendChatMessage
,
5420 XCAST(SetGroupConnectionSettings
)DirectPlay3AImpl_SetGroupConnectionSettings
,
5421 XCAST(StartSession
)DirectPlay3AImpl_StartSession
,
5422 XCAST(GetGroupFlags
)DirectPlay3AImpl_GetGroupFlags
,
5423 XCAST(GetGroupParent
)DirectPlay3AImpl_GetGroupParent
,
5424 XCAST(GetPlayerAccount
)DirectPlay3AImpl_GetPlayerAccount
,
5425 XCAST(GetPlayerFlags
)DirectPlay3AImpl_GetPlayerFlags
,
5427 DirectPlay4AImpl_GetGroupOwner
,
5428 DirectPlay4AImpl_SetGroupOwner
,
5429 DirectPlay4AImpl_SendEx
,
5430 DirectPlay4AImpl_GetMessageQueue
,
5431 DirectPlay4AImpl_CancelMessage
,
5432 DirectPlay4AImpl_CancelPriority
5436 HRESULT
DP_GetSPPlayerData( IDirectPlay2Impl
* lpDP
,
5440 lpPlayerList lpPlayer
= DP_FindPlayer( lpDP
, idPlayer
);
5442 if( lpPlayer
== NULL
)
5444 return DPERR_INVALIDPLAYER
;
5447 *lplpData
= lpPlayer
->lpPData
->lpSPPlayerData
;
5452 HRESULT
DP_SetSPPlayerData( IDirectPlay2Impl
* lpDP
,
5456 lpPlayerList lpPlayer
= DP_FindPlayer( lpDP
, idPlayer
);
5458 if( lpPlayer
== NULL
)
5460 return DPERR_INVALIDPLAYER
;
5463 lpPlayer
->lpPData
->lpSPPlayerData
= lpData
;
5468 /***************************************************************************
5469 * DirectPlayEnumerateAW
5471 * The pointer to the structure lpContext will be filled with the
5472 * appropriate data for each service offered by the OS. These services are
5473 * not necessarily available on this particular machine but are defined
5474 * as simple service providers under the "Service Providers" registry key.
5475 * This structure is then passed to lpEnumCallback for each of the different
5478 * This API is useful only for applications written using DirectX3 or
5479 * worse. It is superseded by IDirectPlay3::EnumConnections which also
5480 * gives information on the actual connections.
5482 * defn of a service provider:
5483 * A dynamic-link library used by DirectPlay to communicate over a network.
5484 * The service provider contains all the network-specific code required
5485 * to send and receive messages. Online services and network operators can
5486 * supply service providers to use specialized hardware, protocols, communications
5487 * media, and network resources.
5490 static HRESULT
DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA
,
5491 LPDPENUMDPCALLBACKW lpEnumCallbackW
,
5495 static const WCHAR searchSubKey
[] = {
5496 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
5497 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
5498 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
5499 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
5500 static const WCHAR guidKey
[] = { 'G', 'u', 'i', 'd', 0 };
5501 static const WCHAR descW
[] = { 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', 'W', 0 };
5506 char *descriptionA
= NULL
;
5507 DWORD max_sizeOfDescriptionA
= 0;
5508 WCHAR
*descriptionW
= NULL
;
5509 DWORD max_sizeOfDescriptionW
= 0;
5511 if (!lpEnumCallbackA
&& !lpEnumCallbackW
)
5513 return DPERR_INVALIDPARAMS
;
5516 /* Need to loop over the service providers in the registry */
5517 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, searchSubKey
,
5518 0, KEY_READ
, &hkResult
) != ERROR_SUCCESS
)
5520 /* Hmmm. Does this mean that there are no service providers? */
5521 ERR(": no service provider key in the registry - check your Wine installation !!!\n");
5522 return DPERR_GENERIC
;
5525 /* Traverse all the service providers we have available */
5529 WCHAR subKeyName
[255]; /* 255 is the maximum key size according to MSDN */
5530 DWORD sizeOfSubKeyName
= sizeof(subKeyName
) / sizeof(WCHAR
);
5531 HKEY hkServiceProvider
;
5532 GUID serviceProviderGUID
;
5533 WCHAR guidKeyContent
[(2 * 16) + 1 + 6 /* This corresponds to '{....-..-..-..-......}' */ ];
5534 DWORD sizeOfGuidKeyContent
= sizeof(guidKeyContent
);
5537 ret_value
= RegEnumKeyExW(hkResult
, dwIndex
, subKeyName
, &sizeOfSubKeyName
,
5538 NULL
, NULL
, NULL
, &filetime
);
5539 if (ret_value
== ERROR_NO_MORE_ITEMS
)
5541 else if (ret_value
!= ERROR_SUCCESS
)
5543 ERR(": could not enumerate on service provider key.\n");
5544 return DPERR_EXCEPTION
;
5546 TRACE(" this time through sub-key %s.\n", debugstr_w(subKeyName
));
5548 /* Open the key for this service provider */
5549 if (RegOpenKeyExW(hkResult
, subKeyName
, 0, KEY_READ
, &hkServiceProvider
) != ERROR_SUCCESS
)
5551 ERR(": could not open registry key for service provider %s.\n", debugstr_w(subKeyName
));
5555 /* Get the GUID from the registry */
5556 if (RegQueryValueExW(hkServiceProvider
, guidKey
,
5557 NULL
, NULL
, (LPBYTE
) guidKeyContent
, &sizeOfGuidKeyContent
) != ERROR_SUCCESS
)
5559 ERR(": missing GUID registry data member for service provider %s.\n", debugstr_w(subKeyName
));
5562 if (sizeOfGuidKeyContent
!= sizeof(guidKeyContent
))
5564 ERR(": invalid format for the GUID registry data member for service provider %s (%s).\n", debugstr_w(subKeyName
), debugstr_w(guidKeyContent
));
5567 CLSIDFromString(guidKeyContent
, &serviceProviderGUID
);
5569 /* The enumeration will return FALSE if we are not to continue.
5571 * Note: on my windows box, major / minor version is 6 / 0 for all service providers
5572 * and have no relation to any of the two dwReserved1 and dwReserved2 keys.
5573 * I think that it simply means that they are in-line with DirectX 6.0
5575 if (lpEnumCallbackA
)
5577 DWORD sizeOfDescription
= 0;
5579 /* Note that this is the A case of this function, so use the A variant to get the description string */
5580 if (RegQueryValueExA(hkServiceProvider
, "DescriptionA",
5581 NULL
, NULL
, NULL
, &sizeOfDescription
) != ERROR_SUCCESS
)
5583 ERR(": missing 'DescriptionA' registry data member for service provider %s.\n", debugstr_w(subKeyName
));
5586 if (sizeOfDescription
> max_sizeOfDescriptionA
)
5588 HeapFree(GetProcessHeap(), 0, descriptionA
);
5589 max_sizeOfDescriptionA
= sizeOfDescription
;
5591 descriptionA
= HeapAlloc(GetProcessHeap(), 0, sizeOfDescription
);
5592 RegQueryValueExA(hkServiceProvider
, "DescriptionA",
5593 NULL
, NULL
, (LPBYTE
) descriptionA
, &sizeOfDescription
);
5595 if (!lpEnumCallbackA(&serviceProviderGUID
, descriptionA
, 6, 0, lpContext
))
5600 DWORD sizeOfDescription
= 0;
5602 if (RegQueryValueExW(hkServiceProvider
, descW
,
5603 NULL
, NULL
, NULL
, &sizeOfDescription
) != ERROR_SUCCESS
)
5605 ERR(": missing 'DescriptionW' registry data member for service provider %s.\n", debugstr_w(subKeyName
));
5608 if (sizeOfDescription
> max_sizeOfDescriptionW
)
5610 HeapFree(GetProcessHeap(), 0, descriptionW
);
5611 max_sizeOfDescriptionW
= sizeOfDescription
;
5613 descriptionW
= HeapAlloc(GetProcessHeap(), 0, sizeOfDescription
);
5614 RegQueryValueExW(hkServiceProvider
, descW
,
5615 NULL
, NULL
, (LPBYTE
) descriptionW
, &sizeOfDescription
);
5617 if (!lpEnumCallbackW(&serviceProviderGUID
, descriptionW
, 6, 0, lpContext
))
5625 HeapFree(GetProcessHeap(), 0, descriptionA
);
5626 HeapFree(GetProcessHeap(), 0, descriptionW
);
5631 /***************************************************************************
5632 * DirectPlayEnumerate [DPLAYX.9]
5633 * DirectPlayEnumerateA [DPLAYX.2]
5635 HRESULT WINAPI
DirectPlayEnumerateA(LPDPENUMDPCALLBACKA lpEnumCallback
, LPVOID lpContext
)
5637 TRACE("(%p,%p)\n", lpEnumCallback
, lpContext
);
5639 return DirectPlayEnumerateAW(lpEnumCallback
, NULL
, lpContext
);
5642 /***************************************************************************
5643 * DirectPlayEnumerateW [DPLAYX.3]
5645 HRESULT WINAPI
DirectPlayEnumerateW(LPDPENUMDPCALLBACKW lpEnumCallback
, LPVOID lpContext
)
5647 TRACE("(%p,%p)\n", lpEnumCallback
, lpContext
);
5649 return DirectPlayEnumerateAW(NULL
, lpEnumCallback
, lpContext
);
5652 typedef struct tagCreateEnum
5656 } CreateEnumData
, *lpCreateEnumData
;
5658 /* Find and copy the matching connection for the SP guid */
5659 static BOOL CALLBACK
cbDPCreateEnumConnections(
5661 LPVOID lpConnection
,
5662 DWORD dwConnectionSize
,
5667 lpCreateEnumData lpData
= (lpCreateEnumData
)lpContext
;
5669 if( IsEqualGUID( lpguidSP
, lpData
->lpGuid
) )
5671 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData
->lpGuid
) );
5673 lpData
->lpConn
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
5675 CopyMemory( lpData
->lpConn
, lpConnection
, dwConnectionSize
);
5677 /* Found the record that we were looking for */
5681 /* Haven't found what were looking for yet */
5686 /***************************************************************************
5687 * DirectPlayCreate [DPLAYX.1]
5690 HRESULT WINAPI DirectPlayCreate
5691 ( LPGUID lpGUID
, LPDIRECTPLAY
*lplpDP
, IUnknown
*pUnk
)
5694 LPDIRECTPLAY3A lpDP3A
;
5695 CreateEnumData cbData
;
5697 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID
), lplpDP
, pUnk
);
5701 return CLASS_E_NOAGGREGATION
;
5704 if( (lplpDP
== NULL
) || (lpGUID
== NULL
) )
5706 return DPERR_INVALIDPARAMS
;
5710 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5711 give them an IDirectPlay2A object and hope that doesn't cause problems */
5712 if( DP_CreateInterface( &IID_IDirectPlay2A
, (LPVOID
*)lplpDP
) != DP_OK
)
5714 return DPERR_UNAVAILABLE
;
5717 if( IsEqualGUID( &GUID_NULL
, lpGUID
) )
5719 /* The GUID_NULL means don't bind a service provider. Just return the
5724 /* Bind the desired service provider since lpGUID is non NULL */
5725 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID
) );
5727 /* We're going to use a DP3 interface */
5728 hr
= IDirectPlayX_QueryInterface( *lplpDP
, &IID_IDirectPlay3A
,
5732 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr
) );
5736 cbData
.lpConn
= NULL
;
5737 cbData
.lpGuid
= lpGUID
;
5739 /* We were given a service provider, find info about it... */
5740 hr
= IDirectPlayX_EnumConnections( lpDP3A
, NULL
, cbDPCreateEnumConnections
,
5741 &cbData
, DPCONNECTION_DIRECTPLAY
);
5742 if( ( FAILED(hr
) ) ||
5743 ( cbData
.lpConn
== NULL
)
5746 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr
) );
5747 IDirectPlayX_Release( lpDP3A
);
5748 return DPERR_UNAVAILABLE
;
5751 /* Initialize the service provider */
5752 hr
= IDirectPlayX_InitializeConnection( lpDP3A
, cbData
.lpConn
, 0 );
5755 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr
) );
5756 HeapFree( GetProcessHeap(), 0, cbData
.lpConn
);
5757 IDirectPlayX_Release( lpDP3A
);
5761 /* Release our version of the interface now that we're done with it */
5762 IDirectPlayX_Release( lpDP3A
);
5763 HeapFree( GetProcessHeap(), 0, cbData
.lpConn
);