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 lpPlayerData
DP_CreatePlayer( IDirectPlay2Impl
* iface
, LPDPID lpid
,
54 LPDPNAME lpName
, DWORD dwFlags
,
55 HANDLE hEvent
, BOOL bAnsi
);
56 static BOOL
DP_CopyDPNAMEStruct( LPDPNAME lpDst
, const DPNAME
*lpSrc
, BOOL bAnsi
);
57 static void DP_SetPlayerData( lpPlayerData lpPData
, DWORD dwFlags
,
58 LPVOID lpData
, DWORD dwDataSize
);
60 static lpGroupData
DP_CreateGroup( IDirectPlay2AImpl
* iface
, const DPID
*lpid
,
61 const DPNAME
*lpName
, DWORD dwFlags
,
62 DPID idParent
, BOOL bAnsi
);
63 static void DP_SetGroupData( lpGroupData lpGData
, DWORD dwFlags
,
64 LPVOID lpData
, DWORD dwDataSize
);
65 static void DP_DeleteDPNameStruct( LPDPNAME lpDPName
);
66 static void DP_DeletePlayer( IDirectPlay2Impl
* This
, DPID dpid
);
67 static BOOL CALLBACK
cbDeletePlayerFromAllGroups( DPID dpId
,
72 static lpGroupData
DP_FindAnyGroup( IDirectPlay2AImpl
* This
, DPID dpid
);
73 static BOOL CALLBACK
cbRemoveGroupOrPlayer( DPID dpId
, DWORD dwPlayerType
,
74 LPCDPNAME lpName
, DWORD dwFlags
,
76 static void DP_DeleteGroup( IDirectPlay2Impl
* This
, DPID dpid
);
78 /* Forward declarations of virtual tables */
79 static const IDirectPlay2Vtbl directPlay2AVT
;
80 static const IDirectPlay3Vtbl directPlay3AVT
;
81 static const IDirectPlay4Vtbl directPlay4AVT
;
83 static const IDirectPlay2Vtbl directPlay2WVT
;
84 static const IDirectPlay3Vtbl directPlay3WVT
;
85 static const IDirectPlay4Vtbl directPlay4WVT
;
87 /* Helper methods for player/group interfaces */
88 static HRESULT DP_IF_DeletePlayerFromGroup
89 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idGroup
,
90 DPID idPlayer
, BOOL bAnsi
);
91 static HRESULT DP_IF_CreatePlayer
92 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, LPDPID lpidPlayer
,
93 LPDPNAME lpPlayerName
, HANDLE hEvent
, LPVOID lpData
,
94 DWORD dwDataSize
, DWORD dwFlags
, BOOL bAnsi
);
95 static HRESULT DP_IF_DestroyGroup
96 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idGroup
, BOOL bAnsi
);
97 static HRESULT DP_IF_DestroyPlayer
98 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idPlayer
, BOOL bAnsi
);
99 static HRESULT DP_IF_EnumGroupPlayers
100 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPGUID lpguidInstance
,
101 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
102 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
);
103 static HRESULT DP_IF_EnumGroups
104 ( IDirectPlay2Impl
* This
, LPGUID lpguidInstance
,
105 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
106 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
);
107 static HRESULT DP_IF_EnumPlayers
108 ( IDirectPlay2Impl
* This
, LPGUID lpguidInstance
,
109 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
110 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
);
111 static HRESULT DP_IF_GetGroupData
112 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPVOID lpData
,
113 LPDWORD lpdwDataSize
, DWORD dwFlags
, BOOL bAnsi
);
114 static HRESULT DP_IF_GetGroupName
115 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPVOID lpData
,
116 LPDWORD lpdwDataSize
, BOOL bAnsi
);
117 static HRESULT DP_IF_GetPlayerData
118 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPVOID lpData
,
119 LPDWORD lpdwDataSize
, DWORD dwFlags
, BOOL bAnsi
);
120 static HRESULT DP_IF_GetPlayerName
121 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPVOID lpData
,
122 LPDWORD lpdwDataSize
, BOOL bAnsi
);
123 static HRESULT DP_IF_SetGroupName
124 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPDPNAME lpGroupName
,
125 DWORD dwFlags
, BOOL bAnsi
);
126 static HRESULT DP_IF_SetPlayerData
127 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPVOID lpData
,
128 DWORD dwDataSize
, DWORD dwFlags
, BOOL bAnsi
);
129 static HRESULT DP_IF_SetPlayerName
130 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPDPNAME lpPlayerName
,
131 DWORD dwFlags
, BOOL bAnsi
);
132 static HRESULT DP_IF_AddGroupToGroup
133 ( IDirectPlay3Impl
* This
, DPID idParentGroup
, DPID idGroup
);
134 static HRESULT DP_IF_CreateGroup
135 ( IDirectPlay2AImpl
* This
, LPVOID lpMsgHdr
, LPDPID lpidGroup
,
136 LPDPNAME lpGroupName
, LPVOID lpData
, DWORD dwDataSize
,
137 DWORD dwFlags
, BOOL bAnsi
);
138 static HRESULT DP_IF_CreateGroupInGroup
139 ( IDirectPlay3Impl
* This
, LPVOID lpMsgHdr
, DPID idParentGroup
,
140 LPDPID lpidGroup
, LPDPNAME lpGroupName
, LPVOID lpData
,
141 DWORD dwDataSize
, DWORD dwFlags
, BOOL bAnsi
);
142 static HRESULT DP_IF_AddPlayerToGroup
143 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idGroup
,
144 DPID idPlayer
, BOOL bAnsi
);
145 static HRESULT DP_IF_DeleteGroupFromGroup
146 ( IDirectPlay3Impl
* This
, DPID idParentGroup
, DPID idGroup
);
147 static HRESULT DP_SecureOpen
148 ( IDirectPlay2Impl
* This
, LPCDPSESSIONDESC2 lpsd
, DWORD dwFlags
,
149 LPCDPSECURITYDESC lpSecurity
, LPCDPCREDENTIALS lpCredentials
,
151 static HRESULT DP_SendEx
152 ( IDirectPlay2Impl
* This
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
153 LPVOID lpData
, DWORD dwDataSize
, DWORD dwPriority
, DWORD dwTimeout
,
154 LPVOID lpContext
, LPDWORD lpdwMsgID
, BOOL bAnsi
);
155 static HRESULT DP_IF_Receive
156 ( IDirectPlay2Impl
* This
, LPDPID lpidFrom
, LPDPID lpidTo
,
157 DWORD dwFlags
, LPVOID lpData
, LPDWORD lpdwDataSize
, BOOL bAnsi
);
158 static HRESULT DP_IF_GetMessageQueue
159 ( IDirectPlay4Impl
* This
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
160 LPDWORD lpdwNumMsgs
, LPDWORD lpdwNumBytes
, BOOL bAnsi
);
161 static HRESULT DP_SP_SendEx
162 ( IDirectPlay2Impl
* This
, DWORD dwFlags
,
163 LPVOID lpData
, DWORD dwDataSize
, DWORD dwPriority
, DWORD dwTimeout
,
164 LPVOID lpContext
, LPDWORD lpdwMsgID
);
165 static HRESULT DP_IF_SetGroupData
166 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPVOID lpData
,
167 DWORD dwDataSize
, DWORD dwFlags
, BOOL bAnsi
);
168 static HRESULT DP_IF_GetPlayerCaps
169 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPDPCAPS lpDPCaps
,
171 static HRESULT
DP_IF_Close( IDirectPlay2Impl
* This
, BOOL bAnsi
);
172 static HRESULT DP_IF_CancelMessage
173 ( IDirectPlay4Impl
* This
, DWORD dwMsgID
, DWORD dwFlags
,
174 DWORD dwMinPriority
, DWORD dwMaxPriority
, BOOL bAnsi
);
175 static HRESULT DP_IF_EnumGroupsInGroup
176 ( IDirectPlay3AImpl
* This
, DPID idGroup
, LPGUID lpguidInstance
,
177 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
178 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
);
179 static HRESULT DP_IF_GetGroupParent
180 ( IDirectPlay3AImpl
* This
, DPID idGroup
, LPDPID lpidGroup
,
182 static HRESULT DP_IF_GetCaps
183 ( IDirectPlay2Impl
* This
, LPDPCAPS lpDPCaps
, DWORD dwFlags
);
184 static HRESULT DP_IF_EnumSessions
185 ( IDirectPlay2Impl
* This
, LPDPSESSIONDESC2 lpsd
, DWORD dwTimeout
,
186 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2
,
187 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
);
188 static HRESULT DP_IF_InitializeConnection
189 ( IDirectPlay3Impl
* This
, LPVOID lpConnection
, DWORD dwFlags
, BOOL bAnsi
);
190 static BOOL CALLBACK
cbDPCreateEnumConnections( LPCGUID lpguidSP
,
191 LPVOID lpConnection
, DWORD dwConnectionSize
, LPCDPNAME lpName
,
192 DWORD dwFlags
, LPVOID lpContext
);
193 static BOOL
DP_BuildCompoundAddr( GUID guidDataType
, LPGUID lpcSpGuid
,
194 LPVOID
* lplpAddrBuf
, LPDWORD lpdwBufSize
);
198 static inline DPID
DP_NextObjectId(void);
199 static DPID
DP_GetRemoteNextObjectId(void);
201 static DWORD
DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc
, BOOL bAnsi
);
202 static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc
,
203 LPCDPSESSIONDESC2 srcSessDesc
, BOOL bAnsi
);
206 static HMODULE
DP_LoadSP( LPCGUID lpcGuid
, LPSPINITDATA lpSpData
, LPBOOL lpbIsDpSp
);
207 static HRESULT
DP_InitializeDPSP( IDirectPlay3Impl
* This
, HMODULE hServiceProvider
);
208 static HRESULT
DP_InitializeDPLSP( IDirectPlay3Impl
* This
, HMODULE hServiceProvider
);
215 #define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */
216 #define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported
217 we don't have to change much */
218 #define DPID_NAME_SERVER 0x19a9d65b /* Don't ask me why */
220 /* Strip out dwFlag values which cannot be sent in the CREATEGROUP msg */
221 #define DPMSG_CREATEGROUP_DWFLAGS(x) ( (x) & DPGROUP_HIDDEN )
223 /* Strip out all dwFlags values for CREATEPLAYER msg */
224 #define DPMSG_CREATEPLAYER_DWFLAGS(x) 0
226 static LONG kludgePlayerGroupId
= 1000;
228 /* ------------------------------------------------------------------ */
231 static BOOL
DP_CreateIUnknown( LPVOID lpDP
)
233 IDirectPlay2AImpl
*This
= lpDP
;
235 This
->unk
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *(This
->unk
) ) );
236 if ( This
->unk
== NULL
)
241 InitializeCriticalSection( &This
->unk
->DP_lock
);
242 This
->unk
->DP_lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": IDirectPlay2AImpl*->DirectPlayIUnknownData*->DP_lock");
247 static BOOL
DP_DestroyIUnknown( LPVOID lpDP
)
249 IDirectPlay2AImpl
*This
= lpDP
;
251 This
->unk
->DP_lock
.DebugInfo
->Spare
[0] = 0;
252 DeleteCriticalSection( &This
->unk
->DP_lock
);
253 HeapFree( GetProcessHeap(), 0, This
->unk
);
258 static BOOL
DP_CreateDirectPlay2( LPVOID lpDP
)
260 IDirectPlay2AImpl
*This
= lpDP
;
262 This
->dp2
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *(This
->dp2
) ) );
263 if ( This
->dp2
== NULL
)
268 This
->dp2
->bConnectionOpen
= FALSE
;
270 This
->dp2
->hEnumSessionThread
= INVALID_HANDLE_VALUE
;
271 This
->dp2
->dwEnumSessionLock
= 0;
273 This
->dp2
->bHostInterface
= FALSE
;
275 DPQ_INIT(This
->dp2
->receiveMsgs
);
276 DPQ_INIT(This
->dp2
->sendMsgs
);
277 DPQ_INIT(This
->dp2
->replysExpected
);
279 if( !NS_InitializeSessionCache( &This
->dp2
->lpNameServerData
) )
281 /* FIXME: Memory leak */
285 /* Provide an initial session desc with nothing in it */
286 This
->dp2
->lpSessionDesc
= HeapAlloc( GetProcessHeap(),
288 sizeof( *This
->dp2
->lpSessionDesc
) );
289 if( This
->dp2
->lpSessionDesc
== NULL
)
291 /* FIXME: Memory leak */
294 This
->dp2
->lpSessionDesc
->dwSize
= sizeof( *This
->dp2
->lpSessionDesc
);
296 /* We are emulating a dp 6 implementation */
297 This
->dp2
->spData
.dwSPVersion
= DPSP_MAJORVERSION
;
299 This
->dp2
->spData
.lpCB
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
300 sizeof( *This
->dp2
->spData
.lpCB
) );
301 This
->dp2
->spData
.lpCB
->dwSize
= sizeof( *This
->dp2
->spData
.lpCB
);
302 This
->dp2
->spData
.lpCB
->dwVersion
= DPSP_MAJORVERSION
;
304 /* This is the pointer to the service provider */
305 if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP
,
306 (LPVOID
*)&This
->dp2
->spData
.lpISP
, This
) )
309 /* FIXME: Memory leak */
313 /* Setup lobby provider information */
314 This
->dp2
->dplspData
.dwSPVersion
= DPSP_MAJORVERSION
;
315 This
->dp2
->dplspData
.lpCB
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
316 sizeof( *This
->dp2
->dplspData
.lpCB
) );
317 This
->dp2
->dplspData
.lpCB
->dwSize
= sizeof( *This
->dp2
->dplspData
.lpCB
);
319 if( FAILED( DPLSP_CreateInterface( &IID_IDPLobbySP
,
320 (LPVOID
*)&This
->dp2
->dplspData
.lpISP
, This
) )
323 /* FIXME: Memory leak */
330 /* Definition of the global function in dplayx_queue.h. #
331 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
332 DPQ_DECL_DELETECB( cbDeleteElemFromHeap
, LPVOID
)
334 HeapFree( GetProcessHeap(), 0, elem
);
337 static BOOL
DP_DestroyDirectPlay2( LPVOID lpDP
)
339 IDirectPlay2AImpl
*This
= lpDP
;
341 if( This
->dp2
->hEnumSessionThread
!= INVALID_HANDLE_VALUE
)
343 TerminateThread( This
->dp2
->hEnumSessionThread
, 0 );
344 CloseHandle( This
->dp2
->hEnumSessionThread
);
347 /* Finish with the SP - have it shutdown */
348 if( This
->dp2
->spData
.lpCB
->ShutdownEx
)
350 DPSP_SHUTDOWNDATA data
;
352 TRACE( "Calling SP ShutdownEx\n" );
354 data
.lpISP
= This
->dp2
->spData
.lpISP
;
356 (*This
->dp2
->spData
.lpCB
->ShutdownEx
)( &data
);
358 else if (This
->dp2
->spData
.lpCB
->Shutdown
) /* obsolete interface */
360 TRACE( "Calling obsolete SP Shutdown\n" );
361 (*This
->dp2
->spData
.lpCB
->Shutdown
)();
364 /* Unload the SP (if it exists) */
365 if( This
->dp2
->hServiceProvider
!= 0 )
367 FreeLibrary( This
->dp2
->hServiceProvider
);
370 /* Unload the Lobby Provider (if it exists) */
371 if( This
->dp2
->hDPLobbyProvider
!= 0 )
373 FreeLibrary( This
->dp2
->hDPLobbyProvider
);
376 /* FIXME: Need to delete receive and send msgs queue contents */
378 NS_DeleteSessionCache( This
->dp2
->lpNameServerData
);
380 HeapFree( GetProcessHeap(), 0, This
->dp2
->lpSessionDesc
);
382 IDirectPlaySP_Release( This
->dp2
->spData
.lpISP
);
384 /* Delete the contents */
385 HeapFree( GetProcessHeap(), 0, This
->dp2
);
390 static BOOL
DP_CreateDirectPlay3( LPVOID lpDP
)
392 IDirectPlay3AImpl
*This
= lpDP
;
394 This
->dp3
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *(This
->dp3
) ) );
395 if ( This
->dp3
== NULL
)
403 static BOOL
DP_DestroyDirectPlay3( LPVOID lpDP
)
405 IDirectPlay3AImpl
*This
= lpDP
;
407 /* Delete the contents */
408 HeapFree( GetProcessHeap(), 0, This
->dp3
);
413 static BOOL
DP_CreateDirectPlay4( LPVOID lpDP
)
415 IDirectPlay4AImpl
*This
= lpDP
;
417 This
->dp4
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *(This
->dp4
) ) );
418 if ( This
->dp4
== NULL
)
426 static BOOL
DP_DestroyDirectPlay4( LPVOID lpDP
)
428 IDirectPlay3AImpl
*This
= lpDP
;
430 /* Delete the contents */
431 HeapFree( GetProcessHeap(), 0, This
->dp4
);
437 /* Create a new interface */
438 HRESULT DP_CreateInterface
439 ( REFIID riid
, LPVOID
* ppvObj
)
441 TRACE( " for %s\n", debugstr_guid( riid
) );
443 *ppvObj
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
444 sizeof( IDirectPlay2Impl
) );
446 if( *ppvObj
== NULL
)
448 return DPERR_OUTOFMEMORY
;
451 if( IsEqualGUID( &IID_IDirectPlay2
, riid
) )
453 IDirectPlay2Impl
*This
= *ppvObj
;
454 This
->lpVtbl
= &directPlay2WVT
;
456 else if( IsEqualGUID( &IID_IDirectPlay2A
, riid
) )
458 IDirectPlay2AImpl
*This
= *ppvObj
;
459 This
->lpVtbl
= &directPlay2AVT
;
461 else if( IsEqualGUID( &IID_IDirectPlay3
, riid
) )
463 IDirectPlay3Impl
*This
= *ppvObj
;
464 This
->lpVtbl
= &directPlay3WVT
;
466 else if( IsEqualGUID( &IID_IDirectPlay3A
, riid
) )
468 IDirectPlay3AImpl
*This
= *ppvObj
;
469 This
->lpVtbl
= &directPlay3AVT
;
471 else if( IsEqualGUID( &IID_IDirectPlay4
, riid
) )
473 IDirectPlay4Impl
*This
= *ppvObj
;
474 This
->lpVtbl
= &directPlay4WVT
;
476 else if( IsEqualGUID( &IID_IDirectPlay4A
, riid
) )
478 IDirectPlay4AImpl
*This
= *ppvObj
;
479 This
->lpVtbl
= &directPlay4AVT
;
483 /* Unsupported interface */
484 HeapFree( GetProcessHeap(), 0, *ppvObj
);
487 return E_NOINTERFACE
;
491 if ( DP_CreateIUnknown( *ppvObj
) &&
492 DP_CreateDirectPlay2( *ppvObj
) &&
493 DP_CreateDirectPlay3( *ppvObj
) &&
494 DP_CreateDirectPlay4( *ppvObj
)
497 IDirectPlayX_AddRef( (LPDIRECTPLAY2A
)*ppvObj
);
502 /* Initialize failed, destroy it */
503 DP_DestroyDirectPlay4( *ppvObj
);
504 DP_DestroyDirectPlay3( *ppvObj
);
505 DP_DestroyDirectPlay2( *ppvObj
);
506 DP_DestroyIUnknown( *ppvObj
);
508 HeapFree( GetProcessHeap(), 0, *ppvObj
);
511 return DPERR_NOMEMORY
;
515 /* Direct Play methods */
517 /* Shared between all dplay types */
518 static HRESULT WINAPI DP_QueryInterface
519 ( LPDIRECTPLAY2 iface
, REFIID riid
, LPVOID
* ppvObj
)
521 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
522 TRACE("(%p)->(%s,%p)\n", This
, debugstr_guid( riid
), ppvObj
);
524 *ppvObj
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
527 if( *ppvObj
== NULL
)
529 return DPERR_OUTOFMEMORY
;
532 CopyMemory( *ppvObj
, This
, sizeof( *This
) );
533 (*(IDirectPlay2Impl
**)ppvObj
)->ulInterfaceRef
= 0;
535 if( IsEqualGUID( &IID_IDirectPlay2
, riid
) )
537 IDirectPlay2Impl
*This
= *ppvObj
;
538 This
->lpVtbl
= &directPlay2WVT
;
540 else if( IsEqualGUID( &IID_IDirectPlay2A
, riid
) )
542 IDirectPlay2AImpl
*This
= *ppvObj
;
543 This
->lpVtbl
= &directPlay2AVT
;
545 else if( IsEqualGUID( &IID_IDirectPlay3
, riid
) )
547 IDirectPlay3Impl
*This
= *ppvObj
;
548 This
->lpVtbl
= &directPlay3WVT
;
550 else if( IsEqualGUID( &IID_IDirectPlay3A
, riid
) )
552 IDirectPlay3AImpl
*This
= *ppvObj
;
553 This
->lpVtbl
= &directPlay3AVT
;
555 else if( IsEqualGUID( &IID_IDirectPlay4
, riid
) )
557 IDirectPlay4Impl
*This
= *ppvObj
;
558 This
->lpVtbl
= &directPlay4WVT
;
560 else if( IsEqualGUID( &IID_IDirectPlay4A
, riid
) )
562 IDirectPlay4AImpl
*This
= *ppvObj
;
563 This
->lpVtbl
= &directPlay4AVT
;
567 /* Unsupported interface */
568 HeapFree( GetProcessHeap(), 0, *ppvObj
);
571 return E_NOINTERFACE
;
574 IDirectPlayX_AddRef( (LPDIRECTPLAY2
)*ppvObj
);
579 /* Shared between all dplay types */
580 static ULONG WINAPI DP_AddRef
581 ( LPDIRECTPLAY3 iface
)
583 ULONG ulInterfaceRefCount
, ulObjRefCount
;
584 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
586 ulObjRefCount
= InterlockedIncrement( &This
->unk
->ulObjRef
);
587 ulInterfaceRefCount
= InterlockedIncrement( &This
->ulInterfaceRef
);
589 TRACE( "ref count incremented to %u:%u for %p\n",
590 ulInterfaceRefCount
, ulObjRefCount
, This
);
592 return ulObjRefCount
;
595 static ULONG WINAPI DP_Release
596 ( LPDIRECTPLAY3 iface
)
598 ULONG ulInterfaceRefCount
, ulObjRefCount
;
600 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
602 ulObjRefCount
= InterlockedDecrement( &This
->unk
->ulObjRef
);
603 ulInterfaceRefCount
= InterlockedDecrement( &This
->ulInterfaceRef
);
605 TRACE( "ref count decremented to %u:%u for %p\n",
606 ulInterfaceRefCount
, ulObjRefCount
, This
);
608 /* Deallocate if this is the last reference to the object */
609 if( ulObjRefCount
== 0 )
611 /* If we're destroying the object, this must be the last ref
612 of the last interface */
613 DP_DestroyDirectPlay4( This
);
614 DP_DestroyDirectPlay3( This
);
615 DP_DestroyDirectPlay2( This
);
616 DP_DestroyIUnknown( This
);
619 /* Deallocate the interface */
620 if( ulInterfaceRefCount
== 0 )
622 HeapFree( GetProcessHeap(), 0, This
);
625 return ulObjRefCount
;
628 static inline DPID
DP_NextObjectId(void)
630 return (DPID
)InterlockedIncrement( &kludgePlayerGroupId
);
633 /* *lplpReply will be non NULL iff there is something to reply */
634 HRESULT
DP_HandleMessage( IDirectPlay2Impl
* This
, LPCVOID lpcMessageBody
,
635 DWORD dwMessageBodySize
, LPCVOID lpcMessageHeader
,
636 WORD wCommandId
, WORD wVersion
,
637 LPVOID
* lplpReply
, LPDWORD lpdwMsgSize
)
639 TRACE( "(%p)->(%p,0x%08x,%p,0x%x,%u)\n",
640 This
, lpcMessageBody
, dwMessageBodySize
, lpcMessageHeader
, wCommandId
,
645 /* Name server needs to handle this request */
646 case DPMSGCMD_ENUMSESSIONS
:
649 NS_ReplyToEnumSessionsRequest( lpcMessageBody
, lplpReply
, lpdwMsgSize
, This
);
654 /* Name server needs to handle this request */
655 case DPMSGCMD_ENUMSESSIONSREPLY
:
657 /* No reply expected */
658 NS_AddRemoteComputerAsNameServer( lpcMessageHeader
,
659 This
->dp2
->spData
.dwSPHeaderSize
,
661 This
->dp2
->lpNameServerData
);
665 case DPMSGCMD_REQUESTPLAYERID
:
667 LPDPSP_MSG_REQUESTPLAYERID lpcMsg
= lpcMessageBody
;
668 LPDPSP_MSG_REQUESTPLAYERREPLY lpReply
;
670 *lpdwMsgSize
= This
->dp2
->spData
.dwSPHeaderSize
+ sizeof( *lpReply
);
672 *lplpReply
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, *lpdwMsgSize
);
674 lpReply
= (LPDPSP_MSG_REQUESTPLAYERREPLY
)( (LPBYTE
)(*lplpReply
) +
675 This
->dp2
->spData
.dwSPHeaderSize
);
677 lpReply
->envelope
.dwMagic
= DPMSG_SIGNATURE
;
678 lpReply
->envelope
.wCommandId
= DPMSGCMD_REQUESTPLAYERREPLY
;
679 lpReply
->envelope
.wVersion
= DX61AVERSION
;
681 if ( lpcMsg
->Flags
& DPLAYI_PLAYER_SYSPLAYER
)
683 /* Request to join the game */
685 if ( This
->dp2
->lpSessionDesc
->dwFlags
& DPSESSION_SECURESERVER
)
687 FIXME( "Fill lpReply->SecDesc with Game->SSPIProvider\n" );
689 FIXME( "Fill lpReply->CAPIProvider with Game->CAPIProvider\n" );
690 FIXME( "Fill lpReply->SecDesc->dwEncryptionAlgorithm with Game->EncryptionAlgorithm\n" );
692 /* Player is not local anymore */
693 lpcMsg
->Flags
^= DPLAYI_PLAYER_PLAYERLOCAL
;
695 lpReply
->ID
= DP_NextObjectId();
696 lpReply
->Result
= DP_IF_CreatePlayer( This
, lpcMessageHeader
,
697 &lpReply
->ID
, NULL
, 0, NULL
, 0,
698 lpcMsg
->Flags
, TRUE
/*TODO*/ );
699 lpReply
->Result
= S_OK
;
703 /* Request to to add a normal player from an
704 * existing member of the session */
706 if ( ( This
->dp2
->lpSessionDesc
->dwCurrentPlayers
707 == This
->dp2
->lpSessionDesc
->dwMaxPlayers
) ||
708 ( This
->dp2
->lpSessionDesc
->dwFlags
& DPSESSION_NEWPLAYERSDISABLED
) )
710 lpReply
->Result
= DPERR_NONEWPLAYERS
;
714 lpReply
->ID
= DP_NextObjectId();
715 lpReply
->Result
= S_OK
;
722 case DPMSGCMD_PACKET
:
724 LPCDPSP_MSG_PACKET lpcMsg
= lpcMessageBody
;
725 LPDPSP_MSG_ENVELOPE packetData
;
727 /* TODO: We have to wait for all the messages in the sequence and
728 * assemble them in a bigger message. */
729 if ( lpcMsg
->TotalPackets
> 1 )
731 FIXME( "TODO: Message belongs to a sequence of %d, implement assembly\n",
732 lpcMsg
->TotalPackets
);
733 return DPERR_GENERIC
;
736 /* For now, for simplicity we'll just decapsulate the embedded
737 * message and work with it. */
738 packetData
= (LPVOID
)(lpcMsg
+ 1);
740 TRACE( "Processing embedded message with envelope (0x%08x, 0x%08x, %d)\n",
741 packetData
->dwMagic
, packetData
->wCommandId
, packetData
->wVersion
);
743 return DP_HandleMessage( This
,
747 packetData
->wCommandId
,
748 packetData
->wVersion
,
749 lplpReply
, lpdwMsgSize
);
753 case DPMSGCMD_REQUESTPLAYERREPLY
:
755 DP_MSG_ReplyReceived( This
, wCommandId
, lpcMessageHeader
,
756 lpcMessageBody
, dwMessageBodySize
);
760 case DPMSGCMD_ADDFORWARDREQUEST
:
762 /*LPCDPSP_MSG_ADDFORWARDREQUEST lpcMsg =
763 (LPCDPSP_MSG_ADDFORWARDREQUEST) lpcMessageBody;*/
765 /* TODO: Send ADDFORWARD messages to all the players to populate
767 * Start NametablePopulation timer and wait for ADDFORWARDACKs */
768 FIXME( "Spread name table population messages\n" );
770 /* TODO remember to set local addr somewhere */
771 /* call NS_SetLocalAddr with a SOCKADDR_IN */
773 FIXME( "This should happen after we received all the DPMSGCMD_ADDFORWARDACKs\n" );
774 DP_MSG_ReplyToEnumPlayersRequest( This
, lplpReply
, lpdwMsgSize
);
779 case DPMSGCMD_ADDFORWARDREPLY
:
781 DP_MSG_ReplyReceived( This
, wCommandId
, lpcMessageHeader
,
782 lpcMessageBody
, dwMessageBodySize
);
786 case DPMSGCMD_ENUMPLAYERSREPLY
:
787 case DPMSGCMD_SUPERENUMPLAYERSREPLY
:
789 /* If we're joining a session, when we receive this
790 * command we were waiting for a ADDFORWARDREPLY */
791 if ( !DP_MSG_ReplyReceived( This
, DPMSGCMD_ADDFORWARDREPLY
,
792 lpcMessageHeader
, lpcMessageBody
,
793 dwMessageBodySize
) )
795 /* If we were not joining a session, check if we are
796 * waiting for an enumeration of players or groups */
797 DP_MSG_ReplyReceived( This
, wCommandId
, lpcMessageHeader
,
798 lpcMessageBody
, dwMessageBodySize
);
803 case DPMSGCMD_ADDFORWARDACK
:
805 /* When we receive an ADDFORWARDACK for each of the ADDFORWARDs
806 * we've sent, send a SUPERENUMPLAYERSREPLY back to the peer
807 * that sent the ADDFORWARDREQUEST */
808 /* TODO: We'll skip this for now and just send the SUPERENUMPLAYERSREPLY
809 * right away when we get a ADDFORWARDREQUEST */
815 FIXME( "Unknown wCommandId 0x%08x. Ignoring message\n", wCommandId
);
816 return DPERR_GENERIC
;
824 static HRESULT DP_IF_AddPlayerToGroup
825 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idGroup
,
826 DPID idPlayer
, BOOL bAnsi
)
829 lpPlayerList lpPList
;
830 lpPlayerList lpNewPList
;
832 TRACE( "(%p)->(%p,0x%08x,0x%08x,%u)\n",
833 This
, lpMsgHdr
, idGroup
, idPlayer
, bAnsi
);
835 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
837 return DPERR_UNINITIALIZED
;
841 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
843 return DPERR_INVALIDGROUP
;
846 /* Find the player */
847 if( ( lpPList
= DP_FindPlayer( This
, idPlayer
) ) == NULL
)
849 return DPERR_INVALIDPLAYER
;
852 /* Create a player list (ie "shortcut" ) */
853 lpNewPList
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpNewPList
) );
854 if( lpNewPList
== NULL
)
856 return DPERR_CANTADDPLAYER
;
859 /* Add the shortcut */
860 lpPList
->lpPData
->uRef
++;
861 lpNewPList
->lpPData
= lpPList
->lpPData
;
863 /* Add the player to the list of players for this group */
864 DPQ_INSERT(lpGData
->players
,lpNewPList
,players
);
866 /* Let the SP know that we've added a player to the group */
867 if( This
->dp2
->spData
.lpCB
->AddPlayerToGroup
)
869 DPSP_ADDPLAYERTOGROUPDATA data
;
871 TRACE( "Calling SP AddPlayerToGroup\n" );
873 data
.idPlayer
= idPlayer
;
874 data
.idGroup
= idGroup
;
875 data
.lpISP
= This
->dp2
->spData
.lpISP
;
877 (*This
->dp2
->spData
.lpCB
->AddPlayerToGroup
)( &data
);
880 /* Inform all other peers of the addition of player to the group. If there are
881 * no peers keep this event quiet.
882 * Also, if this event was the result of another machine sending it to us,
883 * don't bother rebroadcasting it.
885 if( ( lpMsgHdr
== NULL
) &&
886 This
->dp2
->lpSessionDesc
&&
887 ( This
->dp2
->lpSessionDesc
->dwFlags
& DPSESSION_MULTICASTSERVER
) )
889 DPMSG_ADDPLAYERTOGROUP msg
;
890 msg
.dwType
= DPSYS_ADDPLAYERTOGROUP
;
892 msg
.dpIdGroup
= idGroup
;
893 msg
.dpIdPlayer
= idPlayer
;
895 /* FIXME: Correct to just use send effectively? */
896 /* FIXME: Should size include data w/ message or just message "header" */
897 /* FIXME: Check return code */
898 DP_SendEx( This
, DPID_SERVERPLAYER
, DPID_ALLPLAYERS
, 0, &msg
, sizeof( msg
), 0, 0, NULL
, NULL
, bAnsi
);
904 static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
905 ( LPDIRECTPLAY2A iface
, DPID idGroup
, DPID idPlayer
)
907 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
908 return DP_IF_AddPlayerToGroup( This
, NULL
, idGroup
, idPlayer
, TRUE
);
911 static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
912 ( LPDIRECTPLAY2 iface
, DPID idGroup
, DPID idPlayer
)
914 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
915 return DP_IF_AddPlayerToGroup( This
, NULL
, idGroup
, idPlayer
, FALSE
);
918 static HRESULT
DP_IF_Close( IDirectPlay2Impl
* This
, BOOL bAnsi
)
922 TRACE("(%p)->(%u)\n", This
, bAnsi
);
924 /* FIXME: Need to find a new host I assume (how?) */
925 /* FIXME: Need to destroy all local groups */
926 /* FIXME: Need to migrate all remotely visible players to the new host */
928 /* Invoke the SP callback to inform of session close */
929 if( This
->dp2
->spData
.lpCB
->CloseEx
)
933 TRACE( "Calling SP CloseEx\n" );
935 data
.lpISP
= This
->dp2
->spData
.lpISP
;
937 hr
= (*This
->dp2
->spData
.lpCB
->CloseEx
)( &data
);
940 else if ( This
->dp2
->spData
.lpCB
->Close
) /* Try obsolete version */
942 TRACE( "Calling SP Close (obsolete interface)\n" );
944 hr
= (*This
->dp2
->spData
.lpCB
->Close
)();
949 This
->dp2
->bConnectionOpen
= FALSE
;
955 static HRESULT WINAPI DirectPlay2AImpl_Close
956 ( LPDIRECTPLAY2A iface
)
958 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
959 return DP_IF_Close( This
, TRUE
);
962 static HRESULT WINAPI DirectPlay2WImpl_Close
963 ( LPDIRECTPLAY2 iface
)
965 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
966 return DP_IF_Close( This
, FALSE
);
970 lpGroupData
DP_CreateGroup( IDirectPlay2AImpl
* This
, const DPID
*lpid
,
971 const DPNAME
*lpName
, DWORD dwFlags
,
972 DPID idParent
, BOOL bAnsi
)
976 /* Allocate the new space and add to end of high level group list */
977 lpGData
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpGData
) );
979 if( lpGData
== NULL
)
984 DPQ_INIT(lpGData
->groups
);
985 DPQ_INIT(lpGData
->players
);
987 /* Set the desired player ID - no sanity checking to see if it exists */
988 lpGData
->dpid
= *lpid
;
990 DP_CopyDPNAMEStruct( &lpGData
->name
, lpName
, bAnsi
);
992 /* FIXME: Should we check that the parent exists? */
993 lpGData
->parent
= idParent
;
995 /* FIXME: Should we validate the dwFlags? */
996 lpGData
->dwFlags
= dwFlags
;
998 TRACE( "Created group id 0x%08x\n", *lpid
);
1003 /* This method assumes that all links to it are already deleted */
1005 DP_DeleteGroup( IDirectPlay2Impl
* This
, DPID dpid
)
1007 lpGroupList lpGList
;
1009 TRACE( "(%p)->(0x%08x)\n", This
, dpid
);
1011 DPQ_REMOVE_ENTRY( This
->dp2
->lpSysGroup
->groups
, groups
, lpGData
->dpid
, ==, dpid
, lpGList
);
1013 if( lpGList
== NULL
)
1015 ERR( "DPID 0x%08x not found\n", dpid
);
1019 if( --(lpGList
->lpGData
->uRef
) )
1021 FIXME( "Why is this not the last reference to group?\n" );
1026 DP_DeleteDPNameStruct( &lpGList
->lpGData
->name
);
1027 HeapFree( GetProcessHeap(), 0, lpGList
->lpGData
);
1029 /* Remove and Delete Player List object */
1030 HeapFree( GetProcessHeap(), 0, lpGList
);
1034 static lpGroupData
DP_FindAnyGroup( IDirectPlay2AImpl
* This
, DPID dpid
)
1036 lpGroupList lpGroups
;
1038 TRACE( "(%p)->(0x%08x)\n", This
, dpid
);
1040 if( dpid
== DPID_SYSTEM_GROUP
)
1042 return This
->dp2
->lpSysGroup
;
1046 DPQ_FIND_ENTRY( This
->dp2
->lpSysGroup
->groups
, groups
, lpGData
->dpid
, ==, dpid
, lpGroups
);
1049 if( lpGroups
== NULL
)
1054 return lpGroups
->lpGData
;
1057 static HRESULT DP_IF_CreateGroup
1058 ( IDirectPlay2AImpl
* This
, LPVOID lpMsgHdr
, LPDPID lpidGroup
,
1059 LPDPNAME lpGroupName
, LPVOID lpData
, DWORD dwDataSize
,
1060 DWORD dwFlags
, BOOL bAnsi
)
1062 lpGroupData lpGData
;
1064 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1065 This
, lpMsgHdr
, lpidGroup
, lpGroupName
, lpData
, dwDataSize
,
1068 /* If the name is not specified, we must provide one */
1069 if( DPID_UNKNOWN
== *lpidGroup
)
1071 /* If we are the name server, we decide on the group ids. If not, we
1072 * must ask for one before attempting a creation.
1074 if( This
->dp2
->bHostInterface
)
1076 *lpidGroup
= DP_NextObjectId();
1080 *lpidGroup
= DP_GetRemoteNextObjectId();
1084 lpGData
= DP_CreateGroup( This
, lpidGroup
, lpGroupName
, dwFlags
,
1085 DPID_NOPARENT_GROUP
, bAnsi
);
1087 if( lpGData
== NULL
)
1089 return DPERR_CANTADDPLAYER
; /* yes player not group */
1092 if( DPID_SYSTEM_GROUP
== *lpidGroup
)
1094 This
->dp2
->lpSysGroup
= lpGData
;
1095 TRACE( "Inserting system group\n" );
1099 /* Insert into the system group */
1100 lpGroupList lpGroup
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpGroup
) );
1101 lpGroup
->lpGData
= lpGData
;
1103 DPQ_INSERT( This
->dp2
->lpSysGroup
->groups
, lpGroup
, groups
);
1106 /* Something is now referencing this data */
1109 /* Set all the important stuff for the group */
1110 DP_SetGroupData( lpGData
, DPSET_REMOTE
, lpData
, dwDataSize
);
1112 /* FIXME: We should only create the system group if GetCaps returns
1113 * DPCAPS_GROUPOPTIMIZED.
1116 /* Let the SP know that we've created this group */
1117 if( This
->dp2
->spData
.lpCB
->CreateGroup
)
1119 DPSP_CREATEGROUPDATA data
;
1120 DWORD dwCreateFlags
= 0;
1122 TRACE( "Calling SP CreateGroup\n" );
1124 if( *lpidGroup
== DPID_NOPARENT_GROUP
)
1125 dwCreateFlags
|= DPLAYI_GROUP_SYSGROUP
;
1127 if( lpMsgHdr
== NULL
)
1128 dwCreateFlags
|= DPLAYI_PLAYER_PLAYERLOCAL
;
1130 if( dwFlags
& DPGROUP_HIDDEN
)
1131 dwCreateFlags
|= DPLAYI_GROUP_HIDDEN
;
1133 data
.idGroup
= *lpidGroup
;
1134 data
.dwFlags
= dwCreateFlags
;
1135 data
.lpSPMessageHeader
= lpMsgHdr
;
1136 data
.lpISP
= This
->dp2
->spData
.lpISP
;
1138 (*This
->dp2
->spData
.lpCB
->CreateGroup
)( &data
);
1141 /* Inform all other peers of the creation of a new group. If there are
1142 * no peers keep this event quiet.
1143 * Also if this message was sent to us, don't rebroadcast.
1145 if( ( lpMsgHdr
== NULL
) &&
1146 This
->dp2
->lpSessionDesc
&&
1147 ( This
->dp2
->lpSessionDesc
->dwFlags
& DPSESSION_MULTICASTSERVER
) )
1149 DPMSG_CREATEPLAYERORGROUP msg
;
1150 msg
.dwType
= DPSYS_CREATEPLAYERORGROUP
;
1152 msg
.dwPlayerType
= DPPLAYERTYPE_GROUP
;
1153 msg
.dpId
= *lpidGroup
;
1154 msg
.dwCurrentPlayers
= 0; /* FIXME: Incorrect? */
1155 msg
.lpData
= lpData
;
1156 msg
.dwDataSize
= dwDataSize
;
1157 msg
.dpnName
= *lpGroupName
;
1158 msg
.dpIdParent
= DPID_NOPARENT_GROUP
;
1159 msg
.dwFlags
= DPMSG_CREATEGROUP_DWFLAGS( dwFlags
);
1161 /* FIXME: Correct to just use send effectively? */
1162 /* FIXME: Should size include data w/ message or just message "header" */
1163 /* FIXME: Check return code */
1164 DP_SendEx( This
, DPID_SERVERPLAYER
, DPID_ALLPLAYERS
, 0, &msg
, sizeof( msg
),
1165 0, 0, NULL
, NULL
, bAnsi
);
1171 static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
1172 ( LPDIRECTPLAY2A iface
, LPDPID lpidGroup
, LPDPNAME lpGroupName
,
1173 LPVOID lpData
, DWORD dwDataSize
, DWORD dwFlags
)
1175 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
1177 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
1179 return DPERR_UNINITIALIZED
;
1182 if( lpidGroup
== NULL
||
1183 !This
->dp2
->bConnectionOpen
||
1184 dwDataSize
>= MAXDWORD
||
1185 ( lpData
== NULL
&& dwDataSize
!= 0 ) )
1187 return DPERR_INVALIDPARAMS
;
1190 *lpidGroup
= DPID_UNKNOWN
;
1192 return DP_IF_CreateGroup( This
, NULL
, lpidGroup
,
1193 lpGroupName
, lpData
, dwDataSize
, dwFlags
, TRUE
);
1196 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
1197 ( LPDIRECTPLAY2 iface
, LPDPID lpidGroup
, LPDPNAME lpGroupName
,
1198 LPVOID lpData
, DWORD dwDataSize
, DWORD dwFlags
)
1200 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
1202 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
1204 return DPERR_UNINITIALIZED
;
1207 if( lpidGroup
== NULL
||
1208 !This
->dp2
->bConnectionOpen
||
1209 dwDataSize
>= MAXDWORD
||
1210 ( lpData
== NULL
&& dwDataSize
!= 0 ) )
1212 return DPERR_INVALIDPARAMS
;
1215 *lpidGroup
= DPID_UNKNOWN
;
1217 return DP_IF_CreateGroup( This
, NULL
, lpidGroup
,
1218 lpGroupName
, lpData
, dwDataSize
, dwFlags
, FALSE
);
1223 DP_SetGroupData( lpGroupData lpGData
, DWORD dwFlags
,
1224 LPVOID lpData
, DWORD dwDataSize
)
1226 /* Clear out the data with this player */
1227 if( dwFlags
& DPSET_LOCAL
)
1229 if ( lpGData
->dwLocalDataSize
!= 0 )
1231 HeapFree( GetProcessHeap(), 0, lpGData
->lpLocalData
);
1232 lpGData
->lpLocalData
= NULL
;
1233 lpGData
->dwLocalDataSize
= 0;
1238 if( lpGData
->dwRemoteDataSize
!= 0 )
1240 HeapFree( GetProcessHeap(), 0, lpGData
->lpRemoteData
);
1241 lpGData
->lpRemoteData
= NULL
;
1242 lpGData
->dwRemoteDataSize
= 0;
1246 /* Reallocate for new data */
1247 if( lpData
!= NULL
)
1249 LPVOID lpNewData
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
1250 sizeof( dwDataSize
) );
1251 CopyMemory( lpNewData
, lpData
, dwDataSize
);
1253 if( dwFlags
& DPSET_LOCAL
)
1255 lpGData
->lpLocalData
= lpData
;
1256 lpGData
->dwLocalDataSize
= dwDataSize
;
1260 lpGData
->lpRemoteData
= lpNewData
;
1261 lpGData
->dwRemoteDataSize
= dwDataSize
;
1267 /* This function will just create the storage for the new player. */
1269 lpPlayerData
DP_CreatePlayer( IDirectPlay2Impl
* This
, LPDPID lpid
,
1270 LPDPNAME lpName
, DWORD dwFlags
,
1271 HANDLE hEvent
, BOOL bAnsi
)
1273 lpPlayerData lpPData
;
1275 TRACE( "(%p)->(%p,%p,%u)\n", This
, lpid
, lpName
, bAnsi
);
1277 /* Allocate the storage for the player and associate it with list element */
1278 lpPData
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpPData
) );
1279 if( lpPData
== NULL
)
1284 /* Set the desired player ID */
1285 lpPData
->dpid
= *lpid
;
1287 DP_CopyDPNAMEStruct( &lpPData
->name
, lpName
, bAnsi
);
1289 lpPData
->dwFlags
= dwFlags
;
1291 /* If we were given an event handle, duplicate it */
1294 if( !DuplicateHandle( GetCurrentProcess(), hEvent
,
1295 GetCurrentProcess(), &lpPData
->hEvent
,
1296 0, FALSE
, DUPLICATE_SAME_ACCESS
)
1299 /* FIXME: Memory leak */
1300 ERR( "Can't duplicate player msg handle %p\n", hEvent
);
1304 /* Initialize the SP data section */
1305 lpPData
->lpSPPlayerData
= DPSP_CreateSPPlayerData();
1307 TRACE( "Created player id 0x%08x\n", *lpid
);
1309 if( ~dwFlags
& DPLAYI_PLAYER_SYSPLAYER
)
1310 This
->dp2
->lpSessionDesc
->dwCurrentPlayers
++;
1315 /* Delete the contents of the DPNAME struct */
1317 DP_DeleteDPNameStruct( LPDPNAME lpDPName
)
1319 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY
, lpDPName
->u1
.lpszShortNameA
);
1320 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY
, lpDPName
->u2
.lpszLongNameA
);
1323 /* This method assumes that all links to it are already deleted */
1325 DP_DeletePlayer( IDirectPlay2Impl
* This
, DPID dpid
)
1327 lpPlayerList lpPList
;
1329 TRACE( "(%p)->(0x%08x)\n", This
, dpid
);
1331 DPQ_REMOVE_ENTRY( This
->dp2
->lpSysGroup
->players
, players
, lpPData
->dpid
, ==, dpid
, lpPList
);
1333 if( lpPList
== NULL
)
1335 ERR( "DPID 0x%08x not found\n", dpid
);
1339 /* Verify that this is the last reference to the data */
1340 if( --(lpPList
->lpPData
->uRef
) )
1342 FIXME( "Why is this not the last reference to player?\n" );
1347 DP_DeleteDPNameStruct( &lpPList
->lpPData
->name
);
1349 CloseHandle( lpPList
->lpPData
->hEvent
);
1350 HeapFree( GetProcessHeap(), 0, lpPList
->lpPData
);
1352 /* Delete Player List object */
1353 HeapFree( GetProcessHeap(), 0, lpPList
);
1356 lpPlayerList
DP_FindPlayer( IDirectPlay2AImpl
* This
, DPID dpid
)
1358 lpPlayerList lpPlayers
;
1360 TRACE( "(%p)->(0x%08x)\n", This
, dpid
);
1362 if(This
->dp2
->lpSysGroup
== NULL
)
1365 DPQ_FIND_ENTRY( This
->dp2
->lpSysGroup
->players
, players
, lpPData
->dpid
, ==, dpid
, lpPlayers
);
1370 /* Basic area for Dst must already be allocated */
1371 static BOOL
DP_CopyDPNAMEStruct( LPDPNAME lpDst
, const DPNAME
*lpSrc
, BOOL bAnsi
)
1375 ZeroMemory( lpDst
, sizeof( *lpDst
) );
1376 lpDst
->dwSize
= sizeof( *lpDst
);
1380 if( lpSrc
->dwSize
!= sizeof( *lpSrc
) )
1385 /* Delete any existing pointers */
1386 HeapFree( GetProcessHeap(), 0, lpDst
->u1
.lpszShortNameA
);
1387 HeapFree( GetProcessHeap(), 0, lpDst
->u2
.lpszLongNameA
);
1389 /* Copy as required */
1390 CopyMemory( lpDst
, lpSrc
, lpSrc
->dwSize
);
1394 if( lpSrc
->u1
.lpszShortNameA
)
1396 lpDst
->u1
.lpszShortNameA
= HeapAlloc( GetProcessHeap(), 0,
1397 strlen(lpSrc
->u1
.lpszShortNameA
)+1 );
1398 strcpy( lpDst
->u1
.lpszShortNameA
, lpSrc
->u1
.lpszShortNameA
);
1402 lpDst
->u1
.lpszShortNameA
= NULL
;
1404 if( lpSrc
->u2
.lpszLongNameA
)
1406 lpDst
->u2
.lpszLongNameA
= HeapAlloc( GetProcessHeap(), 0,
1407 strlen(lpSrc
->u2
.lpszLongNameA
)+1 );
1408 strcpy( lpDst
->u2
.lpszLongNameA
, lpSrc
->u2
.lpszLongNameA
);
1412 lpDst
->u2
.lpszLongNameA
= NULL
;
1417 if( lpSrc
->u1
.lpszShortNameA
)
1419 lpDst
->u1
.lpszShortName
= HeapAlloc( GetProcessHeap(), 0,
1420 (strlenW(lpSrc
->u1
.lpszShortName
)+1)*sizeof(WCHAR
) );
1421 strcpyW( lpDst
->u1
.lpszShortName
, lpSrc
->u1
.lpszShortName
);
1425 lpDst
->u1
.lpszShortNameA
= NULL
;
1427 if( lpSrc
->u2
.lpszLongNameA
)
1429 lpDst
->u2
.lpszLongName
= HeapAlloc( GetProcessHeap(), 0,
1430 (strlenW(lpSrc
->u2
.lpszLongName
)+1)*sizeof(WCHAR
) );
1431 strcpyW( lpDst
->u2
.lpszLongName
, lpSrc
->u2
.lpszLongName
);
1435 lpDst
->u2
.lpszLongNameA
= NULL
;
1443 DP_SetPlayerData( lpPlayerData lpPData
, DWORD dwFlags
,
1444 LPVOID lpData
, DWORD dwDataSize
)
1446 /* Clear out the data with this player */
1447 if( dwFlags
& DPSET_LOCAL
)
1449 if ( lpPData
->dwLocalDataSize
!= 0 )
1451 HeapFree( GetProcessHeap(), 0, lpPData
->lpLocalData
);
1452 lpPData
->lpLocalData
= NULL
;
1453 lpPData
->dwLocalDataSize
= 0;
1458 if( lpPData
->dwRemoteDataSize
!= 0 )
1460 HeapFree( GetProcessHeap(), 0, lpPData
->lpRemoteData
);
1461 lpPData
->lpRemoteData
= NULL
;
1462 lpPData
->dwRemoteDataSize
= 0;
1466 /* Reallocate for new data */
1467 if( lpData
!= NULL
)
1469 LPVOID lpNewData
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
1470 sizeof( dwDataSize
) );
1471 CopyMemory( lpNewData
, lpData
, dwDataSize
);
1473 if( dwFlags
& DPSET_LOCAL
)
1475 lpPData
->lpLocalData
= lpData
;
1476 lpPData
->dwLocalDataSize
= dwDataSize
;
1480 lpPData
->lpRemoteData
= lpNewData
;
1481 lpPData
->dwRemoteDataSize
= dwDataSize
;
1487 static HRESULT DP_IF_CreatePlayer
1488 ( IDirectPlay2Impl
* This
,
1489 LPVOID lpMsgHdr
, /* NULL for local creation, non NULL for remote creation */
1491 LPDPNAME lpPlayerName
,
1499 lpPlayerData lpPData
;
1500 lpPlayerList lpPList
;
1502 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1503 This
, lpidPlayer
, lpPlayerName
, hEvent
, lpData
,
1504 dwDataSize
, dwFlags
, bAnsi
);
1508 dwFlags
= DPPLAYER_SPECTATOR
;
1511 if( lpidPlayer
== NULL
)
1513 return DPERR_INVALIDPARAMS
;
1517 /* Determine the creation flags for the player. These will be passed
1518 * to the name server if requesting a player id and to the SP when
1519 * informing it of the player creation
1522 if( dwFlags
& DPPLAYER_SERVERPLAYER
)
1524 if( *lpidPlayer
== DPID_SERVERPLAYER
)
1526 /* Server player for the host interface */
1527 dwFlags
|= DPLAYI_PLAYER_APPSERVER
;
1529 else if( *lpidPlayer
== DPID_NAME_SERVER
)
1531 /* Name server - master of everything */
1532 dwFlags
|= (DPLAYI_PLAYER_NAMESRVR
|DPLAYI_PLAYER_SYSPLAYER
);
1536 /* Server player for a non host interface */
1537 dwFlags
|= DPLAYI_PLAYER_SYSPLAYER
;
1541 if( lpMsgHdr
== NULL
)
1542 dwFlags
|= DPLAYI_PLAYER_PLAYERLOCAL
;
1545 /* Verify we know how to handle all the flags */
1546 if( !( ( dwFlags
& DPPLAYER_SERVERPLAYER
) ||
1547 ( dwFlags
& DPPLAYER_SPECTATOR
)
1551 /* Assume non fatal failure */
1552 ERR( "unknown dwFlags = 0x%08x\n", dwFlags
);
1555 /* If the name is not specified, we must provide one */
1556 if( *lpidPlayer
== DPID_UNKNOWN
)
1558 /* If we are the session master, we dish out the group/player ids */
1559 if( This
->dp2
->bHostInterface
)
1561 *lpidPlayer
= DP_NextObjectId();
1565 hr
= DP_MSG_SendRequestPlayerId( This
, dwFlags
& 0x000000FF, lpidPlayer
);
1569 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr
) );
1576 /* Verify that we don't already have this player */
1578 lpPlayerList lpPlayers
= NULL
;
1579 DPQ_FIND_ENTRY( This
->dp2
->lpSysGroup
->players
, players
,
1580 lpPData
->dpid
, ==, *lpidPlayer
, lpPlayers
);
1582 if (lpPlayers
!= NULL
)
1584 return DPERR_CANTCREATEPLAYER
;
1589 lpPData
= DP_CreatePlayer( This
, lpidPlayer
, lpPlayerName
, dwFlags
,
1592 if( lpPData
== NULL
)
1594 return DPERR_CANTADDPLAYER
;
1597 /* Create the list object and link it in */
1598 lpPList
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpPList
) );
1599 if( lpPList
== NULL
)
1601 FIXME( "Memory leak\n" );
1602 return DPERR_CANTADDPLAYER
;
1606 lpPList
->lpPData
= lpPData
;
1608 /* Add the player to the system group */
1609 DPQ_INSERT( This
->dp2
->lpSysGroup
->players
, lpPList
, players
);
1611 /* Update the information and send it to all players in the session */
1612 DP_SetPlayerData( lpPData
, DPSET_REMOTE
, lpData
, dwDataSize
);
1614 /* Let the SP know that we've created this player */
1615 if( This
->dp2
->spData
.lpCB
->CreatePlayer
)
1617 DPSP_CREATEPLAYERDATA data
;
1619 data
.idPlayer
= *lpidPlayer
;
1620 data
.dwFlags
= dwFlags
;
1621 data
.lpSPMessageHeader
= lpMsgHdr
;
1622 data
.lpISP
= This
->dp2
->spData
.lpISP
;
1624 TRACE( "Calling SP CreatePlayer 0x%08x: dwFlags: 0x%08x lpMsgHdr: %p\n",
1625 *lpidPlayer
, data
.dwFlags
, data
.lpSPMessageHeader
);
1627 hr
= (*This
->dp2
->spData
.lpCB
->CreatePlayer
)( &data
);
1632 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr
) );
1636 /* Now let the SP know that this player is a member of the system group */
1637 if( This
->dp2
->spData
.lpCB
->AddPlayerToGroup
)
1639 DPSP_ADDPLAYERTOGROUPDATA data
;
1641 data
.idPlayer
= *lpidPlayer
;
1642 data
.idGroup
= DPID_SYSTEM_GROUP
;
1643 data
.lpISP
= This
->dp2
->spData
.lpISP
;
1645 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1647 hr
= (*This
->dp2
->spData
.lpCB
->AddPlayerToGroup
)( &data
);
1652 ERR( "Failed to add player to sys group with sp: %s\n",
1653 DPLAYX_HresultToString(hr
) );
1658 if( This
->dp2
->bHostInterface
== FALSE
)
1660 /* Let the name server know about the creation of this player */
1661 /* FIXME: Is this only to be done for the creation of a server player or
1662 * is this used for regular players? If only for server players, move
1663 * this call to DP_SecureOpen(...);
1666 hr
= DP_MSG_ForwardPlayerCreation( This
, *lpidPlayer
);
1669 /* Inform all other peers of the creation of a new player. If there are
1670 * no peers keep this quiet.
1671 * Also, if this was a remote event, no need to rebroadcast it.
1673 if( ( lpMsgHdr
== NULL
) &&
1674 This
->dp2
->lpSessionDesc
&&
1675 ( This
->dp2
->lpSessionDesc
->dwFlags
& DPSESSION_MULTICASTSERVER
) )
1677 DPMSG_CREATEPLAYERORGROUP msg
;
1678 msg
.dwType
= DPSYS_CREATEPLAYERORGROUP
;
1680 msg
.dwPlayerType
= DPPLAYERTYPE_PLAYER
;
1681 msg
.dpId
= *lpidPlayer
;
1682 msg
.dwCurrentPlayers
= 0; /* FIXME: Incorrect */
1683 msg
.lpData
= lpData
;
1684 msg
.dwDataSize
= dwDataSize
;
1685 msg
.dpnName
= *lpPlayerName
;
1686 msg
.dpIdParent
= DPID_NOPARENT_GROUP
;
1687 msg
.dwFlags
= DPMSG_CREATEPLAYER_DWFLAGS( dwFlags
);
1689 /* FIXME: Correct to just use send effectively? */
1690 /* FIXME: Should size include data w/ message or just message "header" */
1691 /* FIXME: Check return code */
1692 hr
= DP_SendEx( This
, DPID_SERVERPLAYER
, DPID_ALLPLAYERS
, 0, &msg
,
1693 sizeof( msg
), 0, 0, NULL
, NULL
, bAnsi
);
1700 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
1701 ( LPDIRECTPLAY2A iface
, LPDPID lpidPlayer
, LPDPNAME lpPlayerName
,
1702 HANDLE hEvent
, LPVOID lpData
, DWORD dwDataSize
, DWORD dwFlags
)
1704 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
1706 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
1708 return DPERR_UNINITIALIZED
;
1711 if( lpidPlayer
== NULL
|| !This
->dp2
->bConnectionOpen
)
1713 return DPERR_INVALIDPARAMS
;
1716 if ( This
->dp2
->lpSessionDesc
->dwFlags
& DPSESSION_NEWPLAYERSDISABLED
)
1718 return DPERR_CANTCREATEPLAYER
;
1721 if( dwFlags
& DPPLAYER_SERVERPLAYER
)
1723 *lpidPlayer
= DPID_SERVERPLAYER
;
1727 *lpidPlayer
= DPID_UNKNOWN
;
1730 return DP_IF_CreatePlayer( This
, NULL
, lpidPlayer
, lpPlayerName
, hEvent
,
1731 lpData
, dwDataSize
, dwFlags
, TRUE
);
1734 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
1735 ( LPDIRECTPLAY2 iface
, LPDPID lpidPlayer
, LPDPNAME lpPlayerName
,
1736 HANDLE hEvent
, LPVOID lpData
, DWORD dwDataSize
, DWORD dwFlags
)
1738 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
1740 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
1742 return DPERR_UNINITIALIZED
;
1745 if( lpidPlayer
== NULL
|| !This
->dp2
->bConnectionOpen
)
1747 return DPERR_INVALIDPARAMS
;
1750 if ( This
->dp2
->lpSessionDesc
->dwFlags
& DPSESSION_NEWPLAYERSDISABLED
)
1752 return DPERR_CANTCREATEPLAYER
;
1755 if( dwFlags
& DPPLAYER_SERVERPLAYER
)
1757 *lpidPlayer
= DPID_SERVERPLAYER
;
1761 *lpidPlayer
= DPID_UNKNOWN
;
1764 return DP_IF_CreatePlayer( This
, NULL
, lpidPlayer
, lpPlayerName
, hEvent
,
1765 lpData
, dwDataSize
, dwFlags
, FALSE
);
1768 static DPID
DP_GetRemoteNextObjectId(void)
1773 return DP_NextObjectId();
1776 static HRESULT DP_IF_DeletePlayerFromGroup
1777 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idGroup
,
1778 DPID idPlayer
, BOOL bAnsi
)
1782 lpGroupData lpGData
;
1783 lpPlayerList lpPList
;
1785 TRACE( "(%p)->(%p,0x%08x,0x%08x,%u)\n",
1786 This
, lpMsgHdr
, idGroup
, idPlayer
, bAnsi
);
1788 /* Find the group */
1789 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
1791 return DPERR_INVALIDGROUP
;
1794 /* Find the player */
1795 if( ( lpPList
= DP_FindPlayer( This
, idPlayer
) ) == NULL
)
1797 return DPERR_INVALIDPLAYER
;
1800 /* Remove the player shortcut from the group */
1801 DPQ_REMOVE_ENTRY( lpGData
->players
, players
, lpPData
->dpid
, ==, idPlayer
, lpPList
);
1803 if( lpPList
== NULL
)
1805 return DPERR_INVALIDPLAYER
;
1808 /* One less reference */
1809 lpPList
->lpPData
->uRef
--;
1811 /* Delete the Player List element */
1812 HeapFree( GetProcessHeap(), 0, lpPList
);
1814 /* Inform the SP if they care */
1815 if( This
->dp2
->spData
.lpCB
->RemovePlayerFromGroup
)
1817 DPSP_REMOVEPLAYERFROMGROUPDATA data
;
1819 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1821 data
.idPlayer
= idPlayer
;
1822 data
.idGroup
= idGroup
;
1823 data
.lpISP
= This
->dp2
->spData
.lpISP
;
1825 hr
= (*This
->dp2
->spData
.lpCB
->RemovePlayerFromGroup
)( &data
);
1828 /* Need to send a DELETEPLAYERFROMGROUP message */
1829 FIXME( "Need to send a message\n" );
1834 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
1835 ( LPDIRECTPLAY2A iface
, DPID idGroup
, DPID idPlayer
)
1837 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
1838 return DP_IF_DeletePlayerFromGroup( This
, NULL
, idGroup
, idPlayer
, TRUE
);
1841 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
1842 ( LPDIRECTPLAY2 iface
, DPID idGroup
, DPID idPlayer
)
1844 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
1845 return DP_IF_DeletePlayerFromGroup( This
, NULL
, idGroup
, idPlayer
, FALSE
);
1848 typedef struct _DPRGOPContext
1850 IDirectPlay3Impl
* This
;
1853 } DPRGOPContext
, *lpDPRGOPContext
;
1855 static BOOL CALLBACK
1856 cbRemoveGroupOrPlayer(
1863 lpDPRGOPContext lpCtxt
= (lpDPRGOPContext
)lpContext
;
1865 TRACE( "Removing element:0x%08x (type:0x%08x) from element:0x%08x\n",
1866 dpId
, dwPlayerType
, lpCtxt
->idGroup
);
1868 if( dwPlayerType
== DPPLAYERTYPE_GROUP
)
1870 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt
->This
, lpCtxt
->idGroup
,
1875 ERR( "Unable to delete group 0x%08x from group 0x%08x\n",
1876 dpId
, lpCtxt
->idGroup
);
1881 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl
*)lpCtxt
->This
,
1882 NULL
, lpCtxt
->idGroup
,
1883 dpId
, lpCtxt
->bAnsi
)
1887 ERR( "Unable to delete player 0x%08x from grp 0x%08x\n",
1888 dpId
, lpCtxt
->idGroup
);
1892 return TRUE
; /* Continue enumeration */
1895 static HRESULT DP_IF_DestroyGroup
1896 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idGroup
, BOOL bAnsi
)
1898 lpGroupData lpGData
;
1899 DPRGOPContext context
;
1901 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1902 This
, lpMsgHdr
, idGroup
, bAnsi
);
1904 /* Find the group */
1905 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
1907 return DPERR_INVALIDPLAYER
; /* yes player */
1910 context
.This
= (IDirectPlay3Impl
*)This
;
1911 context
.bAnsi
= bAnsi
;
1912 context
.idGroup
= idGroup
;
1914 /* Remove all players that this group has */
1915 DP_IF_EnumGroupPlayers( This
, idGroup
, NULL
,
1916 cbRemoveGroupOrPlayer
, &context
, 0, bAnsi
);
1918 /* Remove all links to groups that this group has since this is dp3 */
1919 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl
*)This
, idGroup
, NULL
,
1920 cbRemoveGroupOrPlayer
, (LPVOID
)&context
, 0, bAnsi
);
1922 /* Remove this group from the parent group - if it has one */
1923 if( ( idGroup
!= DPID_SYSTEM_GROUP
) &&
1924 ( lpGData
->parent
!= DPID_SYSTEM_GROUP
)
1927 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl
*)This
, lpGData
->parent
,
1931 /* Now delete this group data and list from the system group */
1932 DP_DeleteGroup( This
, idGroup
);
1934 /* Let the SP know that we've destroyed this group */
1935 if( This
->dp2
->spData
.lpCB
->DeleteGroup
)
1937 DPSP_DELETEGROUPDATA data
;
1939 FIXME( "data.dwFlags is incorrect\n" );
1941 data
.idGroup
= idGroup
;
1943 data
.lpISP
= This
->dp2
->spData
.lpISP
;
1945 (*This
->dp2
->spData
.lpCB
->DeleteGroup
)( &data
);
1948 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1953 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
1954 ( LPDIRECTPLAY2A iface
, DPID idGroup
)
1956 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
1957 return DP_IF_DestroyGroup( This
, NULL
, idGroup
, TRUE
);
1960 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
1961 ( LPDIRECTPLAY2 iface
, DPID idGroup
)
1963 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
1964 return DP_IF_DestroyGroup( This
, NULL
, idGroup
, FALSE
);
1967 typedef struct _DPFAGContext
1969 IDirectPlay2Impl
* This
;
1972 } DPFAGContext
, *lpDPFAGContext
;
1974 static HRESULT DP_IF_DestroyPlayer
1975 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idPlayer
, BOOL bAnsi
)
1977 DPFAGContext cbContext
;
1979 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1980 This
, lpMsgHdr
, idPlayer
, bAnsi
);
1982 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
1984 return DPERR_UNINITIALIZED
;
1987 if( DP_FindPlayer( This
, idPlayer
) == NULL
)
1989 return DPERR_INVALIDPLAYER
;
1992 /* FIXME: If the player is remote, we must be the host to delete this */
1994 cbContext
.This
= This
;
1995 cbContext
.idPlayer
= idPlayer
;
1996 cbContext
.bAnsi
= bAnsi
;
1998 /* Find each group and call DeletePlayerFromGroup if the player is a
1999 member of the group */
2000 DP_IF_EnumGroups( This
, NULL
, cbDeletePlayerFromAllGroups
,
2001 &cbContext
, DPENUMGROUPS_ALL
, bAnsi
);
2003 /* Now delete player and player list from the sys group */
2004 DP_DeletePlayer( This
, idPlayer
);
2006 /* Let the SP know that we've destroyed this group */
2007 if( This
->dp2
->spData
.lpCB
->DeletePlayer
)
2009 DPSP_DELETEPLAYERDATA data
;
2011 FIXME( "data.dwFlags is incorrect\n" );
2013 data
.idPlayer
= idPlayer
;
2015 data
.lpISP
= This
->dp2
->spData
.lpISP
;
2017 (*This
->dp2
->spData
.lpCB
->DeletePlayer
)( &data
);
2020 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
2025 static BOOL CALLBACK
2026 cbDeletePlayerFromAllGroups(
2033 lpDPFAGContext lpCtxt
= (lpDPFAGContext
)lpContext
;
2035 if( dwPlayerType
== DPPLAYERTYPE_GROUP
)
2037 DP_IF_DeletePlayerFromGroup( lpCtxt
->This
, NULL
, dpId
, lpCtxt
->idPlayer
,
2040 /* Enumerate all groups in this group since this will normally only
2041 * be called for top level groups
2043 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl
*)lpCtxt
->This
,
2045 cbDeletePlayerFromAllGroups
,
2046 lpContext
, DPENUMGROUPS_ALL
,
2052 ERR( "Group callback has dwPlayerType = 0x%08x\n", dwPlayerType
);
2058 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
2059 ( LPDIRECTPLAY2A iface
, DPID idPlayer
)
2061 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2062 return DP_IF_DestroyPlayer( This
, NULL
, idPlayer
, TRUE
);
2065 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
2066 ( LPDIRECTPLAY2 iface
, DPID idPlayer
)
2068 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2069 return DP_IF_DestroyPlayer( This
, NULL
, idPlayer
, FALSE
);
2072 static HRESULT DP_IF_EnumGroupPlayers
2073 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPGUID lpguidInstance
,
2074 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2075 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
)
2077 lpGroupData lpGData
;
2078 lpPlayerList lpPList
;
2080 FIXME("(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
2081 This
, idGroup
, lpguidInstance
, lpEnumPlayersCallback2
,
2082 lpContext
, dwFlags
, bAnsi
);
2084 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
2086 return DPERR_UNINITIALIZED
;
2089 if( !This
->dp2
->bConnectionOpen
)
2091 return DPERR_NOSESSIONS
;
2094 if( ( lpEnumPlayersCallback2
== NULL
) ||
2095 ( ( dwFlags
& DPENUMPLAYERS_SESSION
) && ( lpguidInstance
== NULL
) ) )
2097 return DPERR_INVALIDPARAMS
;
2100 /* Find the group */
2101 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
2103 return DPERR_INVALIDGROUP
;
2106 if( DPQ_IS_EMPTY( lpGData
->players
) )
2111 lpPList
= DPQ_FIRST( lpGData
->players
);
2113 /* Walk the players in this group */
2116 /* We do not enum the name server or app server as they are of no
2117 * consequence to the end user.
2119 if( ( lpPList
->lpPData
->dpid
!= DPID_NAME_SERVER
) &&
2120 ( lpPList
->lpPData
->dpid
!= DPID_SERVERPLAYER
)
2124 /* FIXME: Need to add stuff for dwFlags checking */
2126 if( !lpEnumPlayersCallback2( lpPList
->lpPData
->dpid
, DPPLAYERTYPE_PLAYER
,
2127 &lpPList
->lpPData
->name
,
2128 lpPList
->lpPData
->dwFlags
,
2132 /* User requested break */
2137 if( DPQ_IS_ENDOFLIST( lpPList
->players
) )
2142 lpPList
= DPQ_NEXT( lpPList
->players
);
2148 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
2149 ( LPDIRECTPLAY2A iface
, DPID idGroup
, LPGUID lpguidInstance
,
2150 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2151 LPVOID lpContext
, DWORD dwFlags
)
2153 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2154 return DP_IF_EnumGroupPlayers( This
, idGroup
, lpguidInstance
,
2155 lpEnumPlayersCallback2
, lpContext
,
2159 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
2160 ( LPDIRECTPLAY2 iface
, DPID idGroup
, LPGUID lpguidInstance
,
2161 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2162 LPVOID lpContext
, DWORD dwFlags
)
2164 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2165 return DP_IF_EnumGroupPlayers( This
, idGroup
, lpguidInstance
,
2166 lpEnumPlayersCallback2
, lpContext
,
2170 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2171 static HRESULT DP_IF_EnumGroups
2172 ( IDirectPlay2Impl
* This
, LPGUID lpguidInstance
,
2173 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2174 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
)
2176 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl
*)This
,
2177 DPID_SYSTEM_GROUP
, lpguidInstance
,
2178 lpEnumPlayersCallback2
, lpContext
,
2182 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
2183 ( LPDIRECTPLAY2A iface
, LPGUID lpguidInstance
,
2184 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2185 LPVOID lpContext
, DWORD dwFlags
)
2187 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2188 return DP_IF_EnumGroups( This
, lpguidInstance
, lpEnumPlayersCallback2
,
2189 lpContext
, dwFlags
, TRUE
);
2192 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
2193 ( LPDIRECTPLAY2 iface
, LPGUID lpguidInstance
,
2194 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2195 LPVOID lpContext
, DWORD dwFlags
)
2197 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2198 return DP_IF_EnumGroups( This
, lpguidInstance
, lpEnumPlayersCallback2
,
2199 lpContext
, dwFlags
, FALSE
);
2202 static HRESULT DP_IF_EnumPlayers
2203 ( IDirectPlay2Impl
* This
, LPGUID lpguidInstance
,
2204 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2205 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
)
2207 return DP_IF_EnumGroupPlayers( This
, DPID_SYSTEM_GROUP
, lpguidInstance
,
2208 lpEnumPlayersCallback2
, lpContext
,
2212 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
2213 ( LPDIRECTPLAY2A iface
, LPGUID lpguidInstance
,
2214 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2215 LPVOID lpContext
, DWORD dwFlags
)
2217 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2218 return DP_IF_EnumPlayers( This
, lpguidInstance
, lpEnumPlayersCallback2
,
2219 lpContext
, dwFlags
, TRUE
);
2222 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
2223 ( LPDIRECTPLAY2 iface
, LPGUID lpguidInstance
,
2224 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2225 LPVOID lpContext
, DWORD dwFlags
)
2227 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2228 return DP_IF_EnumPlayers( This
, lpguidInstance
, lpEnumPlayersCallback2
,
2229 lpContext
, dwFlags
, FALSE
);
2232 /* This function should call the registered callback function that the user
2233 passed into EnumSessions for each entry available.
2235 static void DP_InvokeEnumSessionCallbacks
2236 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2
,
2241 LPDPSESSIONDESC2 lpSessionDesc
;
2243 FIXME( ": not checking for conditions\n" );
2245 /* Not sure if this should be pruning but it's convenient */
2246 NS_PruneSessionCache( lpNSInfo
);
2248 NS_ResetSessionEnumeration( lpNSInfo
);
2250 /* Enumerate all sessions */
2251 /* FIXME: Need to indicate ANSI */
2252 while( (lpSessionDesc
= NS_WalkSessions( lpNSInfo
) ) != NULL
)
2254 TRACE( "EnumSessionsCallback2 invoked\n" );
2255 if( !lpEnumSessionsCallback2( lpSessionDesc
, &dwTimeout
, 0, lpContext
) )
2261 /* Invoke one last time to indicate that there is no more to come */
2262 lpEnumSessionsCallback2( NULL
, &dwTimeout
, DPESC_TIMEDOUT
, lpContext
);
2265 static DWORD CALLBACK
DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext
)
2267 EnumSessionAsyncCallbackData
* data
= lpContext
;
2268 HANDLE hSuicideRequest
= data
->hSuicideRequest
;
2269 DWORD dwTimeout
= data
->dwTimeout
;
2271 TRACE( "Thread started with timeout = 0x%08x\n", dwTimeout
);
2277 /* Sleep up to dwTimeout waiting for request to terminate thread */
2278 if( WaitForSingleObject( hSuicideRequest
, dwTimeout
) == WAIT_OBJECT_0
)
2280 TRACE( "Thread terminating on terminate request\n" );
2284 /* Now resend the enum request */
2285 hr
= NS_SendSessionRequestBroadcast( &data
->requestGuid
,
2286 data
->dwEnumSessionFlags
,
2291 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr
) );
2292 /* FIXME: Should we kill this thread? How to inform the main thread? */
2297 TRACE( "Thread terminating\n" );
2299 /* Clean up the thread data */
2300 CloseHandle( hSuicideRequest
);
2301 HeapFree( GetProcessHeap(), 0, lpContext
);
2303 /* FIXME: Need to have some notification to main app thread that this is
2304 * dead. It would serve two purposes. 1) allow sync on termination
2305 * so that we don't actually send something to ourselves when we
2306 * become name server (race condition) and 2) so that if we die
2307 * abnormally something else will be able to tell.
2313 static void DP_KillEnumSessionThread( IDirectPlay2Impl
* This
)
2315 /* Does a thread exist? If so we were doing an async enum session */
2316 if( This
->dp2
->hEnumSessionThread
!= INVALID_HANDLE_VALUE
)
2318 TRACE( "Killing EnumSession thread %p\n",
2319 This
->dp2
->hEnumSessionThread
);
2321 /* Request that the thread kill itself nicely */
2322 SetEvent( This
->dp2
->hKillEnumSessionThreadEvent
);
2323 CloseHandle( This
->dp2
->hKillEnumSessionThreadEvent
);
2325 /* We no longer need to know about the thread */
2326 CloseHandle( This
->dp2
->hEnumSessionThread
);
2328 This
->dp2
->hEnumSessionThread
= INVALID_HANDLE_VALUE
;
2332 static HRESULT DP_IF_EnumSessions
2333 ( IDirectPlay2Impl
* This
, LPDPSESSIONDESC2 lpsd
, DWORD dwTimeout
,
2334 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2
,
2335 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
)
2339 TRACE( "(%p)->(%p,0x%08x,%p,%p,0x%08x,%u)\n",
2340 This
, lpsd
, dwTimeout
, lpEnumSessionsCallback2
, lpContext
, dwFlags
,
2342 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
2344 return DPERR_UNINITIALIZED
;
2347 if( (lpsd
== NULL
) || (lpsd
->dwSize
!= sizeof(DPSESSIONDESC2
)) )
2349 return DPERR_INVALIDPARAMS
;
2352 /* Can't enumerate if the session is already open */
2353 if( This
->dp2
->bConnectionOpen
)
2355 return DPERR_GENERIC
;
2359 /* The loading of a lobby provider _seems_ to require a backdoor loading
2360 * of the service provider to also associate with this DP object. This is
2361 * because the app doesn't seem to have to call EnumConnections and
2362 * InitializeConnection for the SP before calling this method. As such
2363 * we'll do their dirty work for them with a quick hack so as to always
2364 * load the TCP/IP service provider.
2366 * The correct solution would seem to involve creating a dialog box which
2367 * contains the possible SPs. These dialog boxes most likely follow SDK
2370 if( This
->dp2
->bDPLSPInitialized
&& !This
->dp2
->bSPInitialized
)
2372 LPVOID lpConnection
;
2375 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2377 if( !DP_BuildCompoundAddr( DPAID_ServiceProvider
, (LPGUID
)&DPSPGUID_TCPIP
,
2378 &lpConnection
, &dwSize
) )
2380 ERR( "Can't build compound addr\n" );
2381 return DPERR_GENERIC
;
2384 hr
= DP_IF_InitializeConnection( (IDirectPlay3Impl
*)This
, lpConnection
,
2391 /* Free up the address buffer */
2392 HeapFree( GetProcessHeap(), 0, lpConnection
);
2394 /* The SP is now initialized */
2395 This
->dp2
->bSPInitialized
= TRUE
;
2400 /* Use the service provider default? */
2401 if( dwTimeout
== 0 )
2404 spCaps
.dwSize
= sizeof( spCaps
);
2406 DP_IF_GetCaps( This
, &spCaps
, 0 );
2407 dwTimeout
= spCaps
.dwTimeout
;
2409 /* The service provider doesn't provide one either! */
2410 if( dwTimeout
== 0 )
2412 /* Provide the TCP/IP default */
2413 dwTimeout
= DPMSG_WAIT_5_SECS
;
2417 if( dwFlags
& DPENUMSESSIONS_STOPASYNC
)
2419 DP_KillEnumSessionThread( This
);
2423 if( ( dwFlags
& DPENUMSESSIONS_ASYNC
) )
2425 /* Enumerate everything presently in the local session cache */
2426 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2
,
2427 This
->dp2
->lpNameServerData
, dwTimeout
,
2430 if( This
->dp2
->dwEnumSessionLock
!= 0 )
2431 return DPERR_CONNECTING
;
2433 /* See if we've already created a thread to service this interface */
2434 if( This
->dp2
->hEnumSessionThread
== INVALID_HANDLE_VALUE
)
2437 This
->dp2
->dwEnumSessionLock
++;
2439 /* Send the first enum request inline since the user may cancel a dialog
2440 * if one is presented. Also, may also have a connecting return code.
2442 hr
= NS_SendSessionRequestBroadcast( &lpsd
->guidApplication
,
2443 dwFlags
, &This
->dp2
->spData
);
2447 EnumSessionAsyncCallbackData
* lpData
2448 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpData
) );
2449 /* FIXME: need to kill the thread on object deletion */
2450 lpData
->lpSpData
= &This
->dp2
->spData
;
2452 lpData
->requestGuid
= lpsd
->guidApplication
;
2453 lpData
->dwEnumSessionFlags
= dwFlags
;
2454 lpData
->dwTimeout
= dwTimeout
;
2456 This
->dp2
->hKillEnumSessionThreadEvent
=
2457 CreateEventW( NULL
, TRUE
, FALSE
, NULL
);
2459 if( !DuplicateHandle( GetCurrentProcess(),
2460 This
->dp2
->hKillEnumSessionThreadEvent
,
2461 GetCurrentProcess(),
2462 &lpData
->hSuicideRequest
,
2463 0, FALSE
, DUPLICATE_SAME_ACCESS
)
2466 ERR( "Can't duplicate thread killing handle\n" );
2469 TRACE( ": creating EnumSessionsRequest thread\n" );
2471 This
->dp2
->hEnumSessionThread
= CreateThread( NULL
,
2473 DP_EnumSessionsSendAsyncRequestThread
,
2478 This
->dp2
->dwEnumSessionLock
--;
2483 /* Invalidate the session cache for the interface */
2484 NS_InvalidateSessionCache( This
->dp2
->lpNameServerData
);
2486 /* Send the broadcast for session enumeration */
2487 hr
= NS_SendSessionRequestBroadcast( &lpsd
->guidApplication
,
2489 &This
->dp2
->spData
);
2492 SleepEx( dwTimeout
, FALSE
);
2494 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2
,
2495 This
->dp2
->lpNameServerData
, dwTimeout
,
2502 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2503 ( LPDIRECTPLAY2A iface
, LPDPSESSIONDESC2 lpsd
, DWORD dwTimeout
,
2504 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2
,
2505 LPVOID lpContext
, DWORD dwFlags
)
2507 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2508 return DP_IF_EnumSessions( This
, lpsd
, dwTimeout
, lpEnumSessionsCallback2
,
2509 lpContext
, dwFlags
, TRUE
);
2512 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2513 ( LPDIRECTPLAY2 iface
, LPDPSESSIONDESC2 lpsd
, DWORD dwTimeout
,
2514 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2
,
2515 LPVOID lpContext
, DWORD dwFlags
)
2517 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2518 return DP_IF_EnumSessions( This
, lpsd
, dwTimeout
, lpEnumSessionsCallback2
,
2519 lpContext
, dwFlags
, FALSE
);
2522 static HRESULT DP_IF_GetPlayerCaps
2523 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPDPCAPS lpDPCaps
,
2526 DPSP_GETCAPSDATA data
;
2528 TRACE("(%p)->(0x%08x,%p,0x%08x)\n", This
, idPlayer
, lpDPCaps
, dwFlags
);
2530 if ( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
2532 return DPERR_UNINITIALIZED
;
2535 if ( lpDPCaps
->dwSize
!= sizeof(DPCAPS
) )
2537 return DPERR_INVALIDPARAMS
;
2540 /* Query the service provider */
2541 data
.idPlayer
= idPlayer
;
2542 data
.dwFlags
= dwFlags
;
2543 data
.lpCaps
= lpDPCaps
;
2544 data
.lpISP
= This
->dp2
->spData
.lpISP
;
2546 return (*This
->dp2
->spData
.lpCB
->GetCaps
)( &data
);
2549 static HRESULT DP_IF_GetCaps
2550 ( IDirectPlay2Impl
* This
, LPDPCAPS lpDPCaps
, DWORD dwFlags
)
2552 return DP_IF_GetPlayerCaps( This
, DPID_ALLPLAYERS
, lpDPCaps
, dwFlags
);
2555 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2556 ( LPDIRECTPLAY2A iface
, LPDPCAPS lpDPCaps
, DWORD dwFlags
)
2558 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2559 return DP_IF_GetCaps( This
, lpDPCaps
, dwFlags
);
2562 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2563 ( LPDIRECTPLAY2 iface
, LPDPCAPS lpDPCaps
, DWORD dwFlags
)
2565 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2566 return DP_IF_GetCaps( This
, lpDPCaps
, dwFlags
);
2569 static HRESULT DP_IF_GetGroupData
2570 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPVOID lpData
,
2571 LPDWORD lpdwDataSize
, DWORD dwFlags
, BOOL bAnsi
)
2573 lpGroupData lpGData
;
2574 DWORD dwRequiredBufferSize
;
2575 LPVOID lpCopyDataFrom
;
2577 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2578 This
, idGroup
, lpData
, lpdwDataSize
, dwFlags
, bAnsi
);
2580 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
2582 return DPERR_INVALIDGROUP
;
2585 /* How much buffer is required? */
2586 if( dwFlags
& DPSET_LOCAL
)
2588 dwRequiredBufferSize
= lpGData
->dwLocalDataSize
;
2589 lpCopyDataFrom
= lpGData
->lpLocalData
;
2593 dwRequiredBufferSize
= lpGData
->dwRemoteDataSize
;
2594 lpCopyDataFrom
= lpGData
->lpRemoteData
;
2597 /* Is the user requesting to know how big a buffer is required? */
2598 if( ( lpData
== NULL
) ||
2599 ( *lpdwDataSize
< dwRequiredBufferSize
)
2602 *lpdwDataSize
= dwRequiredBufferSize
;
2603 return DPERR_BUFFERTOOSMALL
;
2606 CopyMemory( lpData
, lpCopyDataFrom
, dwRequiredBufferSize
);
2611 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2612 ( LPDIRECTPLAY2A iface
, DPID idGroup
, LPVOID lpData
,
2613 LPDWORD lpdwDataSize
, DWORD dwFlags
)
2615 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2616 return DP_IF_GetGroupData( This
, idGroup
, lpData
, lpdwDataSize
,
2620 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2621 ( LPDIRECTPLAY2 iface
, DPID idGroup
, LPVOID lpData
,
2622 LPDWORD lpdwDataSize
, DWORD dwFlags
)
2624 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2625 return DP_IF_GetGroupData( This
, idGroup
, lpData
, lpdwDataSize
,
2629 static HRESULT DP_IF_GetGroupName
2630 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPVOID lpData
,
2631 LPDWORD lpdwDataSize
, BOOL bAnsi
)
2633 lpGroupData lpGData
;
2634 LPDPNAME lpName
= lpData
;
2635 DWORD dwRequiredDataSize
;
2637 FIXME("(%p)->(0x%08x,%p,%p,%u) ANSI ignored\n",
2638 This
, idGroup
, lpData
, lpdwDataSize
, bAnsi
);
2640 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
2642 return DPERR_INVALIDGROUP
;
2645 dwRequiredDataSize
= lpGData
->name
.dwSize
;
2647 if( lpGData
->name
.u1
.lpszShortNameA
)
2649 dwRequiredDataSize
+= strlen( lpGData
->name
.u1
.lpszShortNameA
) + 1;
2652 if( lpGData
->name
.u2
.lpszLongNameA
)
2654 dwRequiredDataSize
+= strlen( lpGData
->name
.u2
.lpszLongNameA
) + 1;
2657 if( ( lpData
== NULL
) ||
2658 ( *lpdwDataSize
< dwRequiredDataSize
)
2661 *lpdwDataSize
= dwRequiredDataSize
;
2662 return DPERR_BUFFERTOOSMALL
;
2665 /* Copy the structure */
2666 CopyMemory( lpName
, &lpGData
->name
, lpGData
->name
.dwSize
);
2668 if( lpGData
->name
.u1
.lpszShortNameA
)
2670 strcpy( ((char*)lpName
)+lpGData
->name
.dwSize
,
2671 lpGData
->name
.u1
.lpszShortNameA
);
2675 lpName
->u1
.lpszShortNameA
= NULL
;
2678 if( lpGData
->name
.u1
.lpszShortNameA
)
2680 strcpy( ((char*)lpName
)+lpGData
->name
.dwSize
,
2681 lpGData
->name
.u2
.lpszLongNameA
);
2685 lpName
->u2
.lpszLongNameA
= NULL
;
2691 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2692 ( LPDIRECTPLAY2A iface
, DPID idGroup
, LPVOID lpData
,
2693 LPDWORD lpdwDataSize
)
2695 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2696 return DP_IF_GetGroupName( This
, idGroup
, lpData
, lpdwDataSize
, TRUE
);
2699 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2700 ( LPDIRECTPLAY2 iface
, DPID idGroup
, LPVOID lpData
,
2701 LPDWORD lpdwDataSize
)
2703 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2704 return DP_IF_GetGroupName( This
, idGroup
, lpData
, lpdwDataSize
, FALSE
);
2707 static HRESULT DP_IF_GetMessageCount
2708 ( IDirectPlay2Impl
* This
, DPID idPlayer
,
2709 LPDWORD lpdwCount
, BOOL bAnsi
)
2711 FIXME("(%p)->(0x%08x,%p,%u): stub\n", This
, idPlayer
, lpdwCount
, bAnsi
);
2712 return DP_IF_GetMessageQueue( (IDirectPlay4Impl
*)This
, 0, idPlayer
,
2713 DPMESSAGEQUEUE_RECEIVE
, lpdwCount
, NULL
,
2717 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2718 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPDWORD lpdwCount
)
2720 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2721 return DP_IF_GetMessageCount( This
, idPlayer
, lpdwCount
, TRUE
);
2724 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2725 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPDWORD lpdwCount
)
2727 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2728 return DP_IF_GetMessageCount( This
, idPlayer
, lpdwCount
, FALSE
);
2731 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2732 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPVOID lpData
, LPDWORD lpdwDataSize
)
2734 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2735 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This
, idPlayer
, lpData
, lpdwDataSize
);
2739 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2740 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPVOID lpData
, LPDWORD lpdwDataSize
)
2742 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2743 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This
, idPlayer
, lpData
, lpdwDataSize
);
2747 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2748 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPDPCAPS lpPlayerCaps
,
2751 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2752 return DP_IF_GetPlayerCaps( This
, idPlayer
, lpPlayerCaps
, dwFlags
);
2755 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2756 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPDPCAPS lpPlayerCaps
,
2759 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2760 return DP_IF_GetPlayerCaps( This
, idPlayer
, lpPlayerCaps
, dwFlags
);
2763 static HRESULT DP_IF_GetPlayerData
2764 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPVOID lpData
,
2765 LPDWORD lpdwDataSize
, DWORD dwFlags
, BOOL bAnsi
)
2767 lpPlayerList lpPList
;
2768 DWORD dwRequiredBufferSize
;
2769 LPVOID lpCopyDataFrom
;
2771 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x,%u)\n",
2772 This
, idPlayer
, lpData
, lpdwDataSize
, dwFlags
, bAnsi
);
2774 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
2776 return DPERR_UNINITIALIZED
;
2779 if( ( lpPList
= DP_FindPlayer( This
, idPlayer
) ) == NULL
)
2781 return DPERR_INVALIDPLAYER
;
2784 if( lpdwDataSize
== NULL
)
2786 return DPERR_INVALIDPARAMS
;
2789 /* How much buffer is required? */
2790 if( dwFlags
& DPSET_LOCAL
)
2792 dwRequiredBufferSize
= lpPList
->lpPData
->dwLocalDataSize
;
2793 lpCopyDataFrom
= lpPList
->lpPData
->lpLocalData
;
2797 dwRequiredBufferSize
= lpPList
->lpPData
->dwRemoteDataSize
;
2798 lpCopyDataFrom
= lpPList
->lpPData
->lpRemoteData
;
2801 /* Is the user requesting to know how big a buffer is required? */
2802 if( ( lpData
== NULL
) ||
2803 ( *lpdwDataSize
< dwRequiredBufferSize
)
2806 *lpdwDataSize
= dwRequiredBufferSize
;
2807 return DPERR_BUFFERTOOSMALL
;
2810 CopyMemory( lpData
, lpCopyDataFrom
, dwRequiredBufferSize
);
2815 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2816 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPVOID lpData
,
2817 LPDWORD lpdwDataSize
, DWORD dwFlags
)
2819 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2820 return DP_IF_GetPlayerData( This
, idPlayer
, lpData
, lpdwDataSize
,
2824 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2825 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPVOID lpData
,
2826 LPDWORD lpdwDataSize
, DWORD dwFlags
)
2828 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2829 return DP_IF_GetPlayerData( This
, idPlayer
, lpData
, lpdwDataSize
,
2833 static HRESULT DP_IF_GetPlayerName
2834 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPVOID lpData
,
2835 LPDWORD lpdwDataSize
, BOOL bAnsi
)
2837 lpPlayerList lpPList
;
2838 LPDPNAME lpName
= lpData
;
2839 DWORD dwRequiredDataSize
;
2841 FIXME( "(%p)->(0x%08x,%p,%p,%u): ANSI\n",
2842 This
, idPlayer
, lpData
, lpdwDataSize
, bAnsi
);
2844 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
2846 return DPERR_UNINITIALIZED
;
2849 if( ( lpPList
= DP_FindPlayer( This
, idPlayer
) ) == NULL
)
2851 return DPERR_INVALIDPLAYER
;
2854 dwRequiredDataSize
= lpPList
->lpPData
->name
.dwSize
;
2856 if( lpPList
->lpPData
->name
.u1
.lpszShortNameA
)
2858 dwRequiredDataSize
+= strlen( lpPList
->lpPData
->name
.u1
.lpszShortNameA
) + 1;
2861 if( lpPList
->lpPData
->name
.u2
.lpszLongNameA
)
2863 dwRequiredDataSize
+= strlen( lpPList
->lpPData
->name
.u2
.lpszLongNameA
) + 1;
2866 if( ( lpData
== NULL
) ||
2867 ( *lpdwDataSize
< dwRequiredDataSize
)
2870 *lpdwDataSize
= dwRequiredDataSize
;
2871 return DPERR_BUFFERTOOSMALL
;
2874 /* Copy the structure */
2875 CopyMemory( lpName
, &lpPList
->lpPData
->name
, lpPList
->lpPData
->name
.dwSize
);
2877 if( lpPList
->lpPData
->name
.u1
.lpszShortNameA
)
2879 strcpy( ((char*)lpName
)+lpPList
->lpPData
->name
.dwSize
,
2880 lpPList
->lpPData
->name
.u1
.lpszShortNameA
);
2884 lpName
->u1
.lpszShortNameA
= NULL
;
2887 if( lpPList
->lpPData
->name
.u2
.lpszLongNameA
)
2889 strcpy( ((char*)lpName
)+lpPList
->lpPData
->name
.dwSize
,
2890 lpPList
->lpPData
->name
.u2
.lpszLongNameA
);
2894 lpName
->u2
.lpszLongNameA
= NULL
;
2900 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2901 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPVOID lpData
,
2902 LPDWORD lpdwDataSize
)
2904 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2905 return DP_IF_GetPlayerName( This
, idPlayer
, lpData
, lpdwDataSize
, TRUE
);
2908 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2909 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPVOID lpData
,
2910 LPDWORD lpdwDataSize
)
2912 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2913 return DP_IF_GetPlayerName( This
, idPlayer
, lpData
, lpdwDataSize
, FALSE
);
2916 static HRESULT DP_GetSessionDesc
2917 ( IDirectPlay2Impl
* This
, LPVOID lpData
, LPDWORD lpdwDataSize
,
2920 DWORD dwRequiredSize
;
2922 TRACE( "(%p)->(%p,%p,%u)\n", This
, lpData
, lpdwDataSize
, bAnsi
);
2924 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
2926 return DPERR_UNINITIALIZED
;
2929 if( !This
->dp2
->bConnectionOpen
)
2931 return DPERR_NOSESSIONS
;
2934 if( ( lpdwDataSize
== NULL
) || ( *lpdwDataSize
>= MAXDWORD
) )
2936 return DPERR_INVALIDPARAMS
;
2939 /* FIXME: Get from This->dp2->lpSessionDesc */
2940 dwRequiredSize
= DP_CalcSessionDescSize( This
->dp2
->lpSessionDesc
, bAnsi
);
2942 if ( ( lpData
== NULL
) ||
2943 ( *lpdwDataSize
< dwRequiredSize
)
2946 *lpdwDataSize
= dwRequiredSize
;
2947 return DPERR_BUFFERTOOSMALL
;
2950 DP_CopySessionDesc( lpData
, This
->dp2
->lpSessionDesc
, bAnsi
);
2955 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
2956 ( LPDIRECTPLAY2A iface
, LPVOID lpData
, LPDWORD lpdwDataSize
)
2958 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2959 return DP_GetSessionDesc( This
, lpData
, lpdwDataSize
, TRUE
);
2962 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
2963 ( LPDIRECTPLAY2 iface
, LPVOID lpData
, LPDWORD lpdwDataSize
)
2965 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2966 return DP_GetSessionDesc( This
, lpData
, lpdwDataSize
, TRUE
);
2969 /* Intended only for COM compatibility. Always returns an error. */
2970 static HRESULT WINAPI DirectPlay2AImpl_Initialize
2971 ( LPDIRECTPLAY2A iface
, LPGUID lpGUID
)
2973 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2974 TRACE("(%p)->(%p): stub\n", This
, lpGUID
);
2975 return DPERR_ALREADYINITIALIZED
;
2978 /* Intended only for COM compatibility. Always returns an error. */
2979 static HRESULT WINAPI DirectPlay2WImpl_Initialize
2980 ( LPDIRECTPLAY2 iface
, LPGUID lpGUID
)
2982 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
2983 TRACE("(%p)->(%p): stub\n", This
, lpGUID
);
2984 return DPERR_ALREADYINITIALIZED
;
2988 static HRESULT DP_SecureOpen
2989 ( IDirectPlay2Impl
* This
, LPCDPSESSIONDESC2 lpsd
, DWORD dwFlags
,
2990 LPCDPSECURITYDESC lpSecurity
, LPCDPCREDENTIALS lpCredentials
,
2995 FIXME( "(%p)->(%p,0x%08x,%p,%p): partial stub\n",
2996 This
, lpsd
, dwFlags
, lpSecurity
, lpCredentials
);
2998 if( ( lpsd
== NULL
) ||
2999 ( lpsd
->dwSize
!= sizeof(DPSESSIONDESC2
) ) )
3001 return DPERR_INVALIDPARAMS
;
3004 if( This
->dp2
->bConnectionOpen
)
3006 TRACE( ": rejecting already open connection.\n" );
3007 return DPERR_ALREADYINITIALIZED
;
3010 /* If we're enumerating, kill the thread */
3011 DP_KillEnumSessionThread( This
);
3013 if( dwFlags
& DPOPEN_JOIN
)
3015 LPDPSESSIONDESC2 current
= NULL
;
3016 NS_ResetSessionEnumeration( This
->dp2
->lpNameServerData
);
3017 while( ( current
= NS_WalkSessions( This
->dp2
->lpNameServerData
) ) )
3019 if ( IsEqualGUID( &lpsd
->guidInstance
, ¤t
->guidInstance
) )
3022 if ( current
== NULL
)
3023 return DPERR_NOSESSIONS
;
3025 else if( dwFlags
& DPOPEN_CREATE
)
3027 /* Rightoo - this computer is the host and the local computer needs to be
3028 the name server so that others can join this session */
3029 NS_SetLocalComputerAsNameServer( lpsd
, This
->dp2
->lpNameServerData
);
3031 This
->dp2
->bHostInterface
= TRUE
;
3033 hr
= DP_SetSessionDesc( This
, lpsd
, 0, TRUE
, bAnsi
);
3036 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr
) );
3041 /* Invoke the conditional callback for the service provider */
3042 if( This
->dp2
->spData
.lpCB
->Open
)
3046 FIXME( "Not all data fields are correct. Need new parameter\n" );
3048 data
.bCreate
= (dwFlags
& DPOPEN_CREATE
) ? TRUE
: FALSE
;
3049 data
.lpSPMessageHeader
= (dwFlags
& DPOPEN_CREATE
) ? NULL
3050 : NS_GetNSAddr( This
->dp2
->lpNameServerData
);
3051 data
.lpISP
= This
->dp2
->spData
.lpISP
;
3052 data
.bReturnStatus
= (dwFlags
& DPOPEN_RETURNSTATUS
) ? TRUE
: FALSE
;
3053 data
.dwOpenFlags
= dwFlags
;
3054 data
.dwSessionFlags
= This
->dp2
->lpSessionDesc
->dwFlags
;
3056 hr
= (*This
->dp2
->spData
.lpCB
->Open
)(&data
);
3059 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr
) );
3065 /* Create the system group of which everything is a part of */
3066 DPID systemGroup
= DPID_SYSTEM_GROUP
;
3068 hr
= DP_IF_CreateGroup( This
, NULL
, &systemGroup
, NULL
,
3073 if( dwFlags
& DPOPEN_JOIN
)
3075 DPID dpidServerId
= DPID_UNKNOWN
;
3077 /* Create the server player for this interface. This way we can receive
3078 * messages for this session.
3080 /* FIXME: I suppose that we should be setting an event for a receive
3081 * type of thing. That way the messaging thread could know to wake
3082 * up. DPlay would then trigger the hEvent for the player the
3083 * message is directed to.
3085 hr
= DP_IF_CreatePlayer( This
, NULL
, &dpidServerId
, NULL
, 0, NULL
,
3087 DPPLAYER_SERVERPLAYER
| DPPLAYER_LOCAL
, bAnsi
);
3090 else if( dwFlags
& DPOPEN_CREATE
)
3092 DPID dpidNameServerId
= DPID_NAME_SERVER
;
3094 hr
= DP_IF_CreatePlayer( This
, NULL
, &dpidNameServerId
, NULL
, 0, NULL
,
3095 0, DPPLAYER_SERVERPLAYER
, bAnsi
);
3100 ERR( "Couldn't create name server/system player: %s\n",
3101 DPLAYX_HresultToString(hr
) );
3105 This
->dp2
->bConnectionOpen
= TRUE
;
3111 static HRESULT WINAPI DirectPlay2AImpl_Open
3112 ( LPDIRECTPLAY2A iface
, LPDPSESSIONDESC2 lpsd
, DWORD dwFlags
)
3114 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3115 TRACE("(%p)->(%p,0x%08x)\n", This
, lpsd
, dwFlags
);
3116 return DP_SecureOpen( This
, lpsd
, dwFlags
, NULL
, NULL
, TRUE
);
3119 static HRESULT WINAPI DirectPlay2WImpl_Open
3120 ( LPDIRECTPLAY2 iface
, LPDPSESSIONDESC2 lpsd
, DWORD dwFlags
)
3122 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3123 TRACE("(%p)->(%p,0x%08x)\n", This
, lpsd
, dwFlags
);
3124 return DP_SecureOpen( This
, lpsd
, dwFlags
, NULL
, NULL
, FALSE
);
3127 static HRESULT DP_IF_Receive
3128 ( IDirectPlay2Impl
* This
, LPDPID lpidFrom
, LPDPID lpidTo
,
3129 DWORD dwFlags
, LPVOID lpData
, LPDWORD lpdwDataSize
, BOOL bAnsi
)
3131 LPDPMSG lpMsg
= NULL
;
3133 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p,%u): stub\n",
3134 This
, lpidFrom
, lpidTo
, dwFlags
, lpData
, lpdwDataSize
, bAnsi
);
3136 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
3138 return DPERR_UNINITIALIZED
;
3143 dwFlags
= DPRECEIVE_ALL
;
3146 /* If the lpData is NULL, we must be peeking the message */
3147 if( ( lpData
== NULL
) &&
3148 !( dwFlags
& DPRECEIVE_PEEK
)
3151 return DPERR_INVALIDPARAMS
;
3154 if( dwFlags
& DPRECEIVE_ALL
)
3156 lpMsg
= This
->dp2
->receiveMsgs
.lpQHFirst
;
3158 if( !( dwFlags
& DPRECEIVE_PEEK
) )
3160 FIXME( "Remove from queue\n" );
3163 else if( ( dwFlags
& DPRECEIVE_TOPLAYER
) ||
3164 ( dwFlags
& DPRECEIVE_FROMPLAYER
)
3167 FIXME( "Find matching message 0x%08x\n", dwFlags
);
3171 ERR( "Hmmm..dwFlags 0x%08x\n", dwFlags
);
3176 return DPERR_NOMESSAGES
;
3179 /* Copy into the provided buffer */
3180 if (lpData
) CopyMemory( lpData
, lpMsg
->msg
, *lpdwDataSize
);
3185 static HRESULT WINAPI DirectPlay2AImpl_Receive
3186 ( LPDIRECTPLAY2A iface
, LPDPID lpidFrom
, LPDPID lpidTo
,
3187 DWORD dwFlags
, LPVOID lpData
, LPDWORD lpdwDataSize
)
3189 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3190 return DP_IF_Receive( This
, lpidFrom
, lpidTo
, dwFlags
,
3191 lpData
, lpdwDataSize
, TRUE
);
3194 static HRESULT WINAPI DirectPlay2WImpl_Receive
3195 ( LPDIRECTPLAY2 iface
, LPDPID lpidFrom
, LPDPID lpidTo
,
3196 DWORD dwFlags
, LPVOID lpData
, LPDWORD lpdwDataSize
)
3198 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3199 return DP_IF_Receive( This
, lpidFrom
, lpidTo
, dwFlags
,
3200 lpData
, lpdwDataSize
, FALSE
);
3203 static HRESULT WINAPI DirectPlay2AImpl_Send
3204 ( LPDIRECTPLAY2A iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
, LPVOID lpData
, DWORD dwDataSize
)
3206 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3207 return DP_SendEx( This
, idFrom
, idTo
, dwFlags
, lpData
, dwDataSize
,
3208 0, 0, NULL
, NULL
, TRUE
);
3211 static HRESULT WINAPI DirectPlay2WImpl_Send
3212 ( LPDIRECTPLAY2 iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
, LPVOID lpData
, DWORD dwDataSize
)
3214 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3215 return DP_SendEx( This
, idFrom
, idTo
, dwFlags
, lpData
, dwDataSize
,
3216 0, 0, NULL
, NULL
, FALSE
);
3219 static HRESULT DP_IF_SetGroupData
3220 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPVOID lpData
,
3221 DWORD dwDataSize
, DWORD dwFlags
, BOOL bAnsi
)
3223 lpGroupData lpGData
;
3225 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3226 This
, idGroup
, lpData
, dwDataSize
, dwFlags
, bAnsi
);
3228 /* Parameter check */
3229 if( ( lpData
== NULL
) &&
3233 return DPERR_INVALIDPARAMS
;
3236 /* Find the pointer to the data for this player */
3237 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
3239 return DPERR_INVALIDOBJECT
;
3242 if( !(dwFlags
& DPSET_LOCAL
) )
3244 FIXME( "Was this group created by this interface?\n" );
3245 /* FIXME: If this is a remote update need to allow it but not
3250 DP_SetGroupData( lpGData
, dwFlags
, lpData
, dwDataSize
);
3252 /* FIXME: Only send a message if this group is local to the session otherwise
3253 * it will have been rejected above
3255 if( !(dwFlags
& DPSET_LOCAL
) )
3257 FIXME( "Send msg?\n" );
3263 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
3264 ( LPDIRECTPLAY2A iface
, DPID idGroup
, LPVOID lpData
,
3265 DWORD dwDataSize
, DWORD dwFlags
)
3267 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3268 return DP_IF_SetGroupData( This
, idGroup
, lpData
, dwDataSize
, dwFlags
, TRUE
);
3271 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
3272 ( LPDIRECTPLAY2 iface
, DPID idGroup
, LPVOID lpData
,
3273 DWORD dwDataSize
, DWORD dwFlags
)
3275 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3276 return DP_IF_SetGroupData( This
, idGroup
, lpData
, dwDataSize
, dwFlags
, FALSE
);
3279 static HRESULT DP_IF_SetGroupName
3280 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPDPNAME lpGroupName
,
3281 DWORD dwFlags
, BOOL bAnsi
)
3283 lpGroupData lpGData
;
3285 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n", This
, idGroup
,
3286 lpGroupName
, dwFlags
, bAnsi
);
3288 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
3290 return DPERR_INVALIDGROUP
;
3293 DP_CopyDPNAMEStruct( &lpGData
->name
, lpGroupName
, bAnsi
);
3295 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3296 FIXME( "Message not sent and dwFlags ignored\n" );
3301 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
3302 ( LPDIRECTPLAY2A iface
, DPID idGroup
, LPDPNAME lpGroupName
,
3305 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3306 return DP_IF_SetGroupName( This
, idGroup
, lpGroupName
, dwFlags
, TRUE
);
3309 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
3310 ( LPDIRECTPLAY2 iface
, DPID idGroup
, LPDPNAME lpGroupName
,
3313 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3314 return DP_IF_SetGroupName( This
, idGroup
, lpGroupName
, dwFlags
, FALSE
);
3317 static HRESULT DP_IF_SetPlayerData
3318 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPVOID lpData
,
3319 DWORD dwDataSize
, DWORD dwFlags
, BOOL bAnsi
)
3321 lpPlayerList lpPList
;
3323 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x,%u)\n",
3324 This
, idPlayer
, lpData
, dwDataSize
, dwFlags
, bAnsi
);
3326 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
3328 return DPERR_UNINITIALIZED
;
3331 /* Parameter check */
3332 if( ( ( lpData
== NULL
) && ( dwDataSize
!= 0 ) ) ||
3333 ( dwDataSize
>= MAXDWORD
) )
3335 return DPERR_INVALIDPARAMS
;
3338 /* Find the pointer to the data for this player */
3339 if( ( lpPList
= DP_FindPlayer( This
, idPlayer
) ) == NULL
)
3341 return DPERR_INVALIDPLAYER
;
3344 if( !(dwFlags
& DPSET_LOCAL
) )
3346 FIXME( "Was this group created by this interface?\n" );
3347 /* FIXME: If this is a remote update need to allow it but not
3352 DP_SetPlayerData( lpPList
->lpPData
, dwFlags
, lpData
, dwDataSize
);
3354 if( !(dwFlags
& DPSET_LOCAL
) )
3356 FIXME( "Send msg?\n" );
3362 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3363 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPVOID lpData
,
3364 DWORD dwDataSize
, DWORD dwFlags
)
3366 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3367 return DP_IF_SetPlayerData( This
, idPlayer
, lpData
, dwDataSize
,
3371 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3372 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPVOID lpData
,
3373 DWORD dwDataSize
, DWORD dwFlags
)
3375 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3376 return DP_IF_SetPlayerData( This
, idPlayer
, lpData
, dwDataSize
,
3380 static HRESULT DP_IF_SetPlayerName
3381 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPDPNAME lpPlayerName
,
3382 DWORD dwFlags
, BOOL bAnsi
)
3384 lpPlayerList lpPList
;
3386 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n",
3387 This
, idPlayer
, lpPlayerName
, dwFlags
, bAnsi
);
3389 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
3391 return DPERR_UNINITIALIZED
;
3394 if( ( lpPList
= DP_FindPlayer( This
, idPlayer
) ) == NULL
)
3396 return DPERR_INVALIDGROUP
;
3399 DP_CopyDPNAMEStruct( &lpPList
->lpPData
->name
, lpPlayerName
, bAnsi
);
3401 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3402 FIXME( "Message not sent and dwFlags ignored\n" );
3407 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3408 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPDPNAME lpPlayerName
,
3411 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3412 return DP_IF_SetPlayerName( This
, idPlayer
, lpPlayerName
, dwFlags
, TRUE
);
3415 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3416 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPDPNAME lpPlayerName
,
3419 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3420 return DP_IF_SetPlayerName( This
, idPlayer
, lpPlayerName
, dwFlags
, FALSE
);
3423 HRESULT DP_SetSessionDesc
3424 ( IDirectPlay2Impl
* This
, LPCDPSESSIONDESC2 lpSessDesc
,
3425 DWORD dwFlags
, BOOL bInitial
, BOOL bAnsi
)
3427 DWORD dwRequiredSize
;
3428 LPDPSESSIONDESC2 lpTempSessDesc
;
3430 TRACE( "(%p)->(%p,0x%08x,%u,%u)\n",
3431 This
, lpSessDesc
, dwFlags
, bInitial
, bAnsi
);
3433 /* FIXME: Copy into This->dp2->lpSessionDesc */
3434 dwRequiredSize
= DP_CalcSessionDescSize( lpSessDesc
, bAnsi
);
3435 lpTempSessDesc
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, dwRequiredSize
);
3437 if( lpTempSessDesc
== NULL
)
3439 return DPERR_OUTOFMEMORY
;
3443 HeapFree( GetProcessHeap(), 0, This
->dp2
->lpSessionDesc
);
3445 This
->dp2
->lpSessionDesc
= lpTempSessDesc
;
3447 DP_CopySessionDesc( This
->dp2
->lpSessionDesc
, lpSessDesc
, bAnsi
);
3450 /*Initializing session GUID*/
3451 CoCreateGuid( &(This
->dp2
->lpSessionDesc
->guidInstance
) );
3453 /* If this is an external invocation of the interface, we should be
3454 * letting everyone know that things have changed. Otherwise this is
3455 * just an initialization and it doesn't need to be propagated.
3459 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3465 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3466 ( LPDIRECTPLAY2A iface
, LPDPSESSIONDESC2 lpSessDesc
, DWORD dwFlags
)
3468 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3470 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
3472 return DPERR_UNINITIALIZED
;
3475 if( !This
->dp2
->bConnectionOpen
)
3477 return DPERR_NOSESSIONS
;
3480 if( dwFlags
|| (lpSessDesc
== NULL
) )
3482 return DPERR_INVALIDPARAMS
;
3485 /* Illegal combinations of flags */
3486 if ( ( lpSessDesc
->dwFlags
& DPSESSION_MIGRATEHOST
) &&
3487 ( lpSessDesc
->dwFlags
& ( DPSESSION_CLIENTSERVER
|
3488 DPSESSION_MULTICASTSERVER
|
3489 DPSESSION_SECURESERVER
) ) )
3491 return DPERR_INVALIDFLAGS
;
3494 /* Only the host is allowed to update the session desc */
3495 if( !This
->dp2
->bHostInterface
)
3497 return DPERR_ACCESSDENIED
;
3500 return DP_SetSessionDesc( This
, lpSessDesc
, dwFlags
, FALSE
, TRUE
);
3503 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3504 ( LPDIRECTPLAY2 iface
, LPDPSESSIONDESC2 lpSessDesc
, DWORD dwFlags
)
3506 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
;
3508 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
3510 return DPERR_UNINITIALIZED
;
3513 if( !This
->dp2
->bConnectionOpen
)
3515 return DPERR_NOSESSIONS
;
3518 if( dwFlags
|| (lpSessDesc
== NULL
) )
3520 return DPERR_INVALIDPARAMS
;
3523 /* Illegal combinations of flags */
3524 if ( ( lpSessDesc
->dwFlags
& DPSESSION_MIGRATEHOST
) &&
3525 ( lpSessDesc
->dwFlags
& ( DPSESSION_CLIENTSERVER
|
3526 DPSESSION_MULTICASTSERVER
|
3527 DPSESSION_SECURESERVER
) ) )
3529 return DPERR_INVALIDFLAGS
;
3532 /* Only the host is allowed to update the session desc */
3533 if( !This
->dp2
->bHostInterface
)
3535 return DPERR_ACCESSDENIED
;
3538 return DP_SetSessionDesc( This
, lpSessDesc
, dwFlags
, FALSE
, TRUE
);
3541 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3542 static DWORD
DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc
, BOOL bAnsi
)
3546 if( lpSessDesc
== NULL
)
3548 /* Hmmm..don't need any size? */
3549 ERR( "NULL lpSessDesc\n" );
3553 dwSize
+= sizeof( *lpSessDesc
);
3557 if( lpSessDesc
->u1
.lpszSessionNameA
)
3559 dwSize
+= lstrlenA( lpSessDesc
->u1
.lpszSessionNameA
) + 1;
3562 if( lpSessDesc
->u2
.lpszPasswordA
)
3564 dwSize
+= lstrlenA( lpSessDesc
->u2
.lpszPasswordA
) + 1;
3569 if( lpSessDesc
->u1
.lpszSessionName
)
3571 dwSize
+= sizeof( WCHAR
) *
3572 ( lstrlenW( lpSessDesc
->u1
.lpszSessionName
) + 1 );
3575 if( lpSessDesc
->u2
.lpszPassword
)
3577 dwSize
+= sizeof( WCHAR
) *
3578 ( lstrlenW( lpSessDesc
->u2
.lpszPassword
) + 1 );
3585 /* Assumes that contiguous buffers are already allocated. */
3586 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest
,
3587 LPCDPSESSIONDESC2 lpSessionSrc
, BOOL bAnsi
)
3589 BYTE
* lpStartOfFreeSpace
;
3591 if( lpSessionDest
== NULL
)
3593 ERR( "NULL lpSessionDest\n" );
3597 CopyMemory( lpSessionDest
, lpSessionSrc
, sizeof( *lpSessionSrc
) );
3599 lpStartOfFreeSpace
= ((BYTE
*)lpSessionDest
) + sizeof( *lpSessionSrc
);
3603 if( lpSessionSrc
->u1
.lpszSessionNameA
)
3605 lstrcpyA( (LPSTR
)lpStartOfFreeSpace
,
3606 lpSessionDest
->u1
.lpszSessionNameA
);
3607 lpSessionDest
->u1
.lpszSessionNameA
= (LPSTR
)lpStartOfFreeSpace
;
3608 lpStartOfFreeSpace
+=
3609 lstrlenA( lpSessionDest
->u1
.lpszSessionNameA
) + 1;
3612 if( lpSessionSrc
->u2
.lpszPasswordA
)
3614 lstrcpyA( (LPSTR
)lpStartOfFreeSpace
,
3615 lpSessionDest
->u2
.lpszPasswordA
);
3616 lpSessionDest
->u2
.lpszPasswordA
= (LPSTR
)lpStartOfFreeSpace
;
3617 lpStartOfFreeSpace
+=
3618 lstrlenA( lpSessionDest
->u2
.lpszPasswordA
) + 1;
3623 if( lpSessionSrc
->u1
.lpszSessionName
)
3625 lstrcpyW( (LPWSTR
)lpStartOfFreeSpace
,
3626 lpSessionDest
->u1
.lpszSessionName
);
3627 lpSessionDest
->u1
.lpszSessionName
= (LPWSTR
)lpStartOfFreeSpace
;
3628 lpStartOfFreeSpace
+= sizeof(WCHAR
) *
3629 ( lstrlenW( lpSessionDest
->u1
.lpszSessionName
) + 1 );
3632 if( lpSessionSrc
->u2
.lpszPassword
)
3634 lstrcpyW( (LPWSTR
)lpStartOfFreeSpace
,
3635 lpSessionDest
->u2
.lpszPassword
);
3636 lpSessionDest
->u2
.lpszPassword
= (LPWSTR
)lpStartOfFreeSpace
;
3637 lpStartOfFreeSpace
+= sizeof(WCHAR
) *
3638 ( lstrlenW( lpSessionDest
->u2
.lpszPassword
) + 1 );
3644 static HRESULT DP_IF_AddGroupToGroup
3645 ( IDirectPlay3Impl
* This
, DPID idParentGroup
, DPID idGroup
)
3647 lpGroupData lpGData
;
3648 lpGroupList lpNewGList
;
3650 TRACE( "(%p)->(0x%08x,0x%08x)\n", This
, idParentGroup
, idGroup
);
3652 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
3654 return DPERR_UNINITIALIZED
;
3657 if( DP_FindAnyGroup( (IDirectPlay2AImpl
*)This
, idParentGroup
) == NULL
)
3659 return DPERR_INVALIDGROUP
;
3662 if( ( lpGData
= DP_FindAnyGroup( (IDirectPlay2AImpl
*)This
, idGroup
) ) == NULL
)
3664 return DPERR_INVALIDGROUP
;
3667 /* Create a player list (ie "shortcut" ) */
3668 lpNewGList
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpNewGList
) );
3669 if( lpNewGList
== NULL
)
3671 return DPERR_CANTADDPLAYER
;
3674 /* Add the shortcut */
3676 lpNewGList
->lpGData
= lpGData
;
3678 /* Add the player to the list of players for this group */
3679 DPQ_INSERT( lpGData
->groups
, lpNewGList
, groups
);
3681 /* Send a ADDGROUPTOGROUP message */
3682 FIXME( "Not sending message\n" );
3687 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3688 ( LPDIRECTPLAY3A iface
, DPID idParentGroup
, DPID idGroup
)
3690 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3691 return DP_IF_AddGroupToGroup( This
, idParentGroup
, idGroup
);
3694 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3695 ( LPDIRECTPLAY3 iface
, DPID idParentGroup
, DPID idGroup
)
3697 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3698 return DP_IF_AddGroupToGroup( This
, idParentGroup
, idGroup
);
3701 static HRESULT DP_IF_CreateGroupInGroup
3702 ( IDirectPlay3Impl
* This
, LPVOID lpMsgHdr
, DPID idParentGroup
,
3703 LPDPID lpidGroup
, LPDPNAME lpGroupName
, LPVOID lpData
,
3704 DWORD dwDataSize
, DWORD dwFlags
, BOOL bAnsi
)
3706 lpGroupData lpGParentData
;
3707 lpGroupList lpGList
;
3708 lpGroupData lpGData
;
3710 TRACE( "(%p)->(0x%08x,%p,%p,%p,0x%08x,0x%08x,%u)\n",
3711 This
, idParentGroup
, lpidGroup
, lpGroupName
, lpData
,
3712 dwDataSize
, dwFlags
, bAnsi
);
3714 /* Verify that the specified parent is valid */
3715 if( ( lpGParentData
= DP_FindAnyGroup( (IDirectPlay2AImpl
*)This
,
3716 idParentGroup
) ) == NULL
3719 return DPERR_INVALIDGROUP
;
3722 lpGData
= DP_CreateGroup( (IDirectPlay2AImpl
*)This
, lpidGroup
, lpGroupName
,
3723 dwFlags
, idParentGroup
, bAnsi
);
3725 if( lpGData
== NULL
)
3727 return DPERR_CANTADDPLAYER
; /* yes player not group */
3730 /* Something else is referencing this data */
3733 DP_SetGroupData( lpGData
, DPSET_REMOTE
, lpData
, dwDataSize
);
3735 /* The list has now been inserted into the interface group list. We now
3736 need to put a "shortcut" to this group in the parent group */
3737 lpGList
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpGList
) );
3738 if( lpGList
== NULL
)
3740 FIXME( "Memory leak\n" );
3741 return DPERR_CANTADDPLAYER
; /* yes player not group */
3744 lpGList
->lpGData
= lpGData
;
3746 DPQ_INSERT( lpGParentData
->groups
, lpGList
, groups
);
3748 /* Let the SP know that we've created this group */
3749 if( This
->dp2
->spData
.lpCB
->CreateGroup
)
3751 DPSP_CREATEGROUPDATA data
;
3753 TRACE( "Calling SP CreateGroup\n" );
3755 data
.idGroup
= *lpidGroup
;
3756 data
.dwFlags
= dwFlags
;
3757 data
.lpSPMessageHeader
= lpMsgHdr
;
3758 data
.lpISP
= This
->dp2
->spData
.lpISP
;
3760 (*This
->dp2
->spData
.lpCB
->CreateGroup
)( &data
);
3763 /* Inform all other peers of the creation of a new group. If there are
3764 * no peers keep this quiet.
3766 if( This
->dp2
->lpSessionDesc
&&
3767 ( This
->dp2
->lpSessionDesc
->dwFlags
& DPSESSION_MULTICASTSERVER
) )
3769 DPMSG_CREATEPLAYERORGROUP msg
;
3771 msg
.dwType
= DPSYS_CREATEPLAYERORGROUP
;
3772 msg
.dwPlayerType
= DPPLAYERTYPE_GROUP
;
3773 msg
.dpId
= *lpidGroup
;
3774 msg
.dwCurrentPlayers
= idParentGroup
; /* FIXME: Incorrect? */
3775 msg
.lpData
= lpData
;
3776 msg
.dwDataSize
= dwDataSize
;
3777 msg
.dpnName
= *lpGroupName
;
3779 /* FIXME: Correct to just use send effectively? */
3780 /* FIXME: Should size include data w/ message or just message "header" */
3781 /* FIXME: Check return code */
3782 DP_SendEx( (IDirectPlay2Impl
*)This
,
3783 DPID_SERVERPLAYER
, DPID_ALLPLAYERS
, 0, &msg
, sizeof( msg
),
3784 0, 0, NULL
, NULL
, bAnsi
);
3790 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3791 ( LPDIRECTPLAY3A iface
, DPID idParentGroup
, LPDPID lpidGroup
,
3792 LPDPNAME lpGroupName
, LPVOID lpData
, DWORD dwDataSize
,
3795 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3797 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
3799 return DPERR_UNINITIALIZED
;
3802 if( lpidGroup
== NULL
||
3803 !This
->dp2
->bConnectionOpen
||
3804 dwDataSize
>= MAXDWORD
||
3805 ( lpData
== NULL
&& dwDataSize
!= 0 ) )
3807 return DPERR_INVALIDPARAMS
;
3810 *lpidGroup
= DPID_UNKNOWN
;
3812 return DP_IF_CreateGroupInGroup( This
, NULL
, idParentGroup
, lpidGroup
,
3813 lpGroupName
, lpData
, dwDataSize
, dwFlags
,
3817 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3818 ( LPDIRECTPLAY3 iface
, DPID idParentGroup
, LPDPID lpidGroup
,
3819 LPDPNAME lpGroupName
, LPVOID lpData
, DWORD dwDataSize
,
3822 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3824 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
3826 return DPERR_UNINITIALIZED
;
3829 if( lpidGroup
== NULL
||
3830 !This
->dp2
->bConnectionOpen
||
3831 dwDataSize
>= MAXDWORD
||
3832 ( lpData
== NULL
&& dwDataSize
!= 0 ) )
3834 return DPERR_INVALIDPARAMS
;
3837 *lpidGroup
= DPID_UNKNOWN
;
3839 return DP_IF_CreateGroupInGroup( This
, NULL
, idParentGroup
, lpidGroup
,
3840 lpGroupName
, lpData
, dwDataSize
,
3844 static HRESULT DP_IF_DeleteGroupFromGroup
3845 ( IDirectPlay3Impl
* This
, DPID idParentGroup
, DPID idGroup
)
3847 lpGroupList lpGList
;
3848 lpGroupData lpGParentData
;
3850 TRACE("(%p)->(0x%08x,0x%08x)\n", This
, idParentGroup
, idGroup
);
3852 /* Is the parent group valid? */
3853 if( ( lpGParentData
= DP_FindAnyGroup( (IDirectPlay2AImpl
*)This
, idParentGroup
) ) == NULL
)
3855 return DPERR_INVALIDGROUP
;
3858 /* Remove the group from the parent group queue */
3859 DPQ_REMOVE_ENTRY( lpGParentData
->groups
, groups
, lpGData
->dpid
, ==, idGroup
, lpGList
);
3861 if( lpGList
== NULL
)
3863 return DPERR_INVALIDGROUP
;
3866 /* Decrement the ref count */
3867 lpGList
->lpGData
->uRef
--;
3869 /* Free up the list item */
3870 HeapFree( GetProcessHeap(), 0, lpGList
);
3872 /* Should send a DELETEGROUPFROMGROUP message */
3873 FIXME( "message not sent\n" );
3878 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3879 ( LPDIRECTPLAY3 iface
, DPID idParentGroup
, DPID idGroup
)
3881 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3882 return DP_IF_DeleteGroupFromGroup( This
, idParentGroup
, idGroup
);
3885 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3886 ( LPDIRECTPLAY3 iface
, DPID idParentGroup
, DPID idGroup
)
3888 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
3889 return DP_IF_DeleteGroupFromGroup( This
, idParentGroup
, idGroup
);
3891 static BOOL
DP_BuildCompoundAddr( GUID guidDataType
,
3893 LPVOID
* lplpAddrBuf
,
3894 LPDWORD lpdwBufSize
)
3896 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress
;
3899 dpCompoundAddress
.dwDataSize
= sizeof( GUID
);
3900 dpCompoundAddress
.guidDataType
= guidDataType
;
3901 dpCompoundAddress
.lpData
= lpcSpGuid
;
3903 *lplpAddrBuf
= NULL
;
3906 hr
= DPL_CreateCompoundAddress( &dpCompoundAddress
, 1, *lplpAddrBuf
,
3907 lpdwBufSize
, TRUE
);
3909 if( hr
!= DPERR_BUFFERTOOSMALL
)
3911 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr
) );
3915 /* Now allocate the buffer */
3916 *lplpAddrBuf
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
3919 hr
= DPL_CreateCompoundAddress( &dpCompoundAddress
, 1, *lplpAddrBuf
,
3920 lpdwBufSize
, TRUE
);
3923 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr
) );
3930 static HRESULT WINAPI DP_IF_EnumConnections
3931 ( LPDIRECTPLAY3A iface
, LPCGUID lpguidApplication
,
3932 LPDPENUMCONNECTIONSCALLBACK lpEnumCallback
, LPVOID lpContext
,
3933 DWORD dwFlags
, BOOL bAnsi
)
3936 WCHAR searchSubKeySP
[] = {
3937 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
3938 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
3939 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
3940 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
3941 WCHAR searchSubKeyLP
[] = {
3942 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
3943 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
3944 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
3945 'L', 'o', 'b', 'b', 'y', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
3946 WCHAR guidDataSubKey
[] = { 'G', 'u', 'i', 'd', 0 };
3947 WCHAR subKeyName
[255]; /* 255 is the maximum key size according to MSDN */
3948 DWORD dwIndex
, sizeOfSubKeyName
= sizeof(subKeyName
) / sizeof(WCHAR
);
3951 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
3954 dwFlags
= DPCONNECTION_DIRECTPLAY
;
3957 if( ! ( ( dwFlags
& DPCONNECTION_DIRECTPLAY
) ||
3958 ( dwFlags
& DPCONNECTION_DIRECTPLAYLOBBY
) ) )
3960 return DPERR_INVALIDFLAGS
;
3963 if( !lpEnumCallback
)
3965 return DPERR_INVALIDPARAMS
;
3969 /* Need to loop over the service providers in the registry */
3970 if( RegOpenKeyExW( HKEY_LOCAL_MACHINE
,
3971 ( dwFlags
& DPCONNECTION_DIRECTPLAY
) ? searchSubKeySP
3973 0, KEY_READ
, &hkResult
) != ERROR_SUCCESS
)
3975 /* Hmmm. Does this mean that there are no service providers? */
3976 ERR(": no service providers?\n");
3981 /* Traverse all the service providers we have available */
3983 RegEnumKeyExW( hkResult
, dwIndex
, subKeyName
, &sizeOfSubKeyName
,
3984 NULL
, NULL
, NULL
, &filetime
) != ERROR_NO_MORE_ITEMS
;
3985 ++dwIndex
, sizeOfSubKeyName
= sizeof(subKeyName
) / sizeof(WCHAR
) )
3987 HKEY hkServiceProvider
;
3988 GUID serviceProviderGUID
;
3989 WCHAR guidKeyContent
[39];
3990 DWORD sizeOfReturnBuffer
= sizeof(guidKeyContent
);
3992 BOOL continueEnumeration
= TRUE
;
3994 LPVOID lpAddressBuffer
= NULL
;
3995 DWORD dwAddressBufferSize
= 0;
3998 TRACE(" this time through: %s\n", debugstr_w(subKeyName
) );
4000 /* Get a handle for this particular service provider */
4001 if( RegOpenKeyExW( hkResult
, subKeyName
, 0, KEY_READ
,
4002 &hkServiceProvider
) != ERROR_SUCCESS
)
4004 ERR(": what the heck is going on?\n" );
4008 if( RegQueryValueExW( hkServiceProvider
, guidDataSubKey
,
4009 NULL
, NULL
, (LPBYTE
)guidKeyContent
,
4010 &sizeOfReturnBuffer
) != ERROR_SUCCESS
)
4012 ERR(": missing GUID registry data members\n" );
4013 RegCloseKey(hkServiceProvider
);
4016 RegCloseKey(hkServiceProvider
);
4018 CLSIDFromString( guidKeyContent
, &serviceProviderGUID
);
4020 /* Fill in the DPNAME struct for the service provider */
4021 dpName
.dwSize
= sizeof( dpName
);
4025 dpName
.u1
.lpszShortNameA
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
4026 sizeOfSubKeyName
+1 );
4027 WideCharToMultiByte( CP_ACP
, 0, subKeyName
,
4028 -1, dpName
.u1
.lpszShortNameA
, -1, 0, 0);
4029 dpName
.u2
.lpszLongNameA
= NULL
;
4033 dpName
.u1
.lpszShortName
= subKeyName
;
4034 dpName
.u2
.lpszLongName
= NULL
;
4037 /* Create the compound address for the service provider.
4038 * NOTE: This is a gruesome architectural scar right now. DP
4039 * uses DPL and DPL uses DP. Nasty stuff. This may be why the
4040 * native dll just gets around this little bit by allocating an
4041 * 80 byte buffer which isn't even filled with a valid compound
4042 * address. Oh well. Creating a proper compound address is the
4043 * way to go anyways despite this method taking slightly more
4044 * heap space and realtime :) */
4046 if ( DP_BuildCompoundAddr( ( ( dwFlags
& DPCONNECTION_DIRECTPLAY
)
4047 ? DPAID_ServiceProvider
4048 : DPAID_LobbyProvider
),
4049 &serviceProviderGUID
,
4051 &dwAddressBufferSize
) )
4053 /* The enumeration will return FALSE if we are not to continue */
4054 continueEnumeration
= lpEnumCallback( &serviceProviderGUID
, lpAddressBuffer
,
4055 dwAddressBufferSize
, &dpName
,
4056 dwFlags
, lpContext
);
4060 ERR( "Couldn't build compound address\n" );
4063 HeapFree( GetProcessHeap(), 0, lpAddressBuffer
);
4065 HeapFree( GetProcessHeap(), 0, dpName
.u1
.lpszShortNameA
);
4067 if (!continueEnumeration
)
4074 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
4075 ( LPDIRECTPLAY3A iface
, LPCGUID lpguidApplication
, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback
, LPVOID lpContext
, DWORD dwFlags
)
4077 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4078 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This
, lpguidApplication
, lpEnumCallback
, lpContext
, dwFlags
);
4079 return DP_IF_EnumConnections( iface
, lpguidApplication
, lpEnumCallback
, lpContext
, dwFlags
, TRUE
);
4082 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
4083 ( LPDIRECTPLAY3 iface
, LPCGUID lpguidApplication
, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback
, LPVOID lpContext
, DWORD dwFlags
)
4085 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4086 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This
, lpguidApplication
, lpEnumCallback
, lpContext
, dwFlags
);
4087 return DP_IF_EnumConnections( iface
, lpguidApplication
, lpEnumCallback
, lpContext
, dwFlags
, FALSE
);
4090 static HRESULT DP_IF_EnumGroupsInGroup
4091 ( IDirectPlay3AImpl
* This
, DPID idGroup
, LPGUID lpguidInstance
,
4092 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
4093 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
)
4095 lpGroupList lpGList
;
4096 lpGroupData lpGData
;
4098 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x,%u): semi stub\n",
4099 This
, idGroup
, lpguidInstance
, lpEnumPlayersCallback2
,
4100 lpContext
, dwFlags
, bAnsi
);
4102 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
4104 return DPERR_UNINITIALIZED
;
4107 if( !This
->dp2
->bConnectionOpen
)
4109 return DPERR_NOSESSIONS
;
4112 if( ( lpEnumPlayersCallback2
== NULL
) ||
4113 ( ( dwFlags
& DPENUMGROUPS_SESSION
) && ( lpguidInstance
== NULL
) ) )
4115 return DPERR_INVALIDPARAMS
;
4118 if( ( lpGData
= DP_FindAnyGroup( (IDirectPlay2AImpl
*)This
, idGroup
) ) == NULL
)
4120 return DPERR_INVALIDGROUP
;
4123 if( DPQ_IS_EMPTY( lpGData
->groups
) )
4128 lpGList
= DPQ_FIRST( lpGData
->groups
);
4132 /* FIXME: Should check dwFlags for match here */
4134 if( !(*lpEnumPlayersCallback2
)( lpGList
->lpGData
->dpid
, DPPLAYERTYPE_GROUP
,
4135 &lpGList
->lpGData
->name
, dwFlags
,
4138 return DP_OK
; /* User requested break */
4141 if( DPQ_IS_ENDOFLIST( lpGList
->groups
) )
4146 lpGList
= DPQ_NEXT( lpGList
->groups
);
4153 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
4154 ( LPDIRECTPLAY3A iface
, DPID idGroup
, LPGUID lpguidInstance
,
4155 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
, LPVOID lpContext
,
4158 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4159 return DP_IF_EnumGroupsInGroup( This
, idGroup
, lpguidInstance
,
4160 lpEnumPlayersCallback2
, lpContext
, dwFlags
,
4164 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
4165 ( LPDIRECTPLAY3A iface
, DPID idGroup
, LPGUID lpguidInstance
,
4166 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
, LPVOID lpContext
,
4169 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4170 return DP_IF_EnumGroupsInGroup( This
, idGroup
, lpguidInstance
,
4171 lpEnumPlayersCallback2
, lpContext
, dwFlags
,
4175 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
4176 ( LPDIRECTPLAY3A iface
, DWORD dwFlags
, DPID idGroup
, LPVOID lpData
, LPDWORD lpdwDataSize
)
4178 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4179 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This
, dwFlags
, idGroup
, lpData
, lpdwDataSize
);
4183 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
4184 ( LPDIRECTPLAY3 iface
, DWORD dwFlags
, DPID idGroup
, LPVOID lpData
, LPDWORD lpdwDataSize
)
4186 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4187 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This
, dwFlags
, idGroup
, lpData
, lpdwDataSize
);
4191 static BOOL CALLBACK
DP_GetSpLpGuidFromCompoundAddress(
4192 REFGUID guidDataType
,
4197 /* Looking for the GUID of the provider to load */
4198 if( ( IsEqualGUID( guidDataType
, &DPAID_ServiceProvider
) ) ||
4199 ( IsEqualGUID( guidDataType
, &DPAID_LobbyProvider
) )
4202 TRACE( "Found SP/LP (%s) %s (data size = 0x%08x)\n",
4203 debugstr_guid( guidDataType
), debugstr_guid( lpData
), dwDataSize
);
4205 if( dwDataSize
!= sizeof( GUID
) )
4207 ERR( "Invalid sp/lp guid size 0x%08x\n", dwDataSize
);
4210 memcpy( lpContext
, lpData
, dwDataSize
);
4212 /* There shouldn't be more than 1 GUID/compound address */
4216 /* Still waiting for what we want */
4221 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
4222 static HMODULE
DP_LoadSP( LPCGUID lpcGuid
, LPSPINITDATA lpSpData
, LPBOOL lpbIsDpSp
)
4225 LPCSTR spSubKey
= "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4226 LPCSTR lpSubKey
= "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
4227 LPCSTR guidDataSubKey
= "Guid";
4228 LPCSTR majVerDataSubKey
= "dwReserved1";
4229 LPCSTR minVerDataSubKey
= "dwReserved2";
4230 LPCSTR pathSubKey
= "Path";
4232 TRACE( " request to load %s\n", debugstr_guid( lpcGuid
) );
4234 /* FIXME: Cloned code with a quick hack. */
4235 for( i
=0; i
<2; i
++ )
4238 LPCSTR searchSubKey
;
4239 char subKeyName
[51];
4240 DWORD dwIndex
, sizeOfSubKeyName
=50;
4243 (i
== 0) ? (searchSubKey
= spSubKey
) : (searchSubKey
= lpSubKey
);
4244 *lpbIsDpSp
= (i
== 0) ? TRUE
: FALSE
;
4247 /* Need to loop over the service providers in the registry */
4248 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE
, searchSubKey
,
4249 0, KEY_READ
, &hkResult
) != ERROR_SUCCESS
)
4251 /* Hmmm. Does this mean that there are no service providers? */
4252 ERR(": no service providers?\n");
4256 /* Traverse all the service providers we have available */
4258 RegEnumKeyExA( hkResult
, dwIndex
, subKeyName
, &sizeOfSubKeyName
,
4259 NULL
, NULL
, NULL
, &filetime
) != ERROR_NO_MORE_ITEMS
;
4260 ++dwIndex
, sizeOfSubKeyName
=51 )
4263 HKEY hkServiceProvider
;
4264 GUID serviceProviderGUID
;
4265 DWORD returnType
, sizeOfReturnBuffer
= 255;
4266 char returnBuffer
[256];
4270 TRACE(" this time through: %s\n", subKeyName
);
4272 /* Get a handle for this particular service provider */
4273 if( RegOpenKeyExA( hkResult
, subKeyName
, 0, KEY_READ
,
4274 &hkServiceProvider
) != ERROR_SUCCESS
)
4276 ERR(": what the heck is going on?\n" );
4280 if( RegQueryValueExA( hkServiceProvider
, guidDataSubKey
,
4281 NULL
, &returnType
, (LPBYTE
)returnBuffer
,
4282 &sizeOfReturnBuffer
) != ERROR_SUCCESS
)
4284 ERR(": missing GUID registry data members\n" );
4288 /* FIXME: Check return types to ensure we're interpreting data right */
4289 MultiByteToWideChar( CP_ACP
, 0, returnBuffer
, -1, buff
, sizeof(buff
)/sizeof(WCHAR
) );
4290 CLSIDFromString( buff
, &serviceProviderGUID
);
4291 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4293 /* Determine if this is the Service Provider that the user asked for */
4294 if( !IsEqualGUID( &serviceProviderGUID
, lpcGuid
) )
4299 if( i
== 0 ) /* DP SP */
4301 len
= MultiByteToWideChar( CP_ACP
, 0, subKeyName
, -1, NULL
, 0 );
4302 lpSpData
->lpszName
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof(WCHAR
) );
4303 MultiByteToWideChar( CP_ACP
, 0, subKeyName
, -1, lpSpData
->lpszName
, len
);
4306 sizeOfReturnBuffer
= 255;
4308 /* Get dwReserved1 */
4309 if( RegQueryValueExA( hkServiceProvider
, majVerDataSubKey
,
4310 NULL
, &returnType
, (LPBYTE
)returnBuffer
,
4311 &sizeOfReturnBuffer
) != ERROR_SUCCESS
)
4313 ERR(": missing dwReserved1 registry data members\n") ;
4318 memcpy( &lpSpData
->dwReserved1
, returnBuffer
, sizeof(lpSpData
->dwReserved1
) );
4320 sizeOfReturnBuffer
= 255;
4322 /* Get dwReserved2 */
4323 if( RegQueryValueExA( hkServiceProvider
, minVerDataSubKey
,
4324 NULL
, &returnType
, (LPBYTE
)returnBuffer
,
4325 &sizeOfReturnBuffer
) != ERROR_SUCCESS
)
4327 ERR(": missing dwReserved1 registry data members\n") ;
4332 memcpy( &lpSpData
->dwReserved2
, returnBuffer
, sizeof(lpSpData
->dwReserved2
) );
4334 sizeOfReturnBuffer
= 255;
4336 /* Get the path for this service provider */
4337 if( ( dwTemp
= RegQueryValueExA( hkServiceProvider
, pathSubKey
,
4338 NULL
, NULL
, (LPBYTE
)returnBuffer
,
4339 &sizeOfReturnBuffer
) ) != ERROR_SUCCESS
)
4341 ERR(": missing PATH registry data members: 0x%08x\n", dwTemp
);
4345 TRACE( "Loading %s\n", returnBuffer
);
4346 return LoadLibraryA( returnBuffer
);
4354 HRESULT
DP_InitializeDPSP( IDirectPlay3Impl
* This
, HMODULE hServiceProvider
)
4357 LPDPSP_SPINIT SPInit
;
4359 /* Initialize the service provider by calling SPInit */
4360 SPInit
= (LPDPSP_SPINIT
)GetProcAddress( hServiceProvider
, "SPInit" );
4362 if( SPInit
== NULL
)
4364 ERR( "Service provider doesn't provide SPInit interface?\n" );
4365 FreeLibrary( hServiceProvider
);
4366 return DPERR_UNAVAILABLE
;
4369 TRACE( "Calling SPInit (DP SP entry point)\n" );
4371 hr
= (*SPInit
)( &This
->dp2
->spData
);
4375 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr
) );
4376 FreeLibrary( hServiceProvider
);
4380 /* FIXME: Need to verify the sanity of the returned callback table
4381 * using IsBadCodePtr */
4382 This
->dp2
->bSPInitialized
= TRUE
;
4384 /* This interface is now initialized as a DP object */
4385 This
->dp2
->connectionInitialized
= DP_SERVICE_PROVIDER
;
4387 /* Store the handle of the module so that we can unload it later */
4388 This
->dp2
->hServiceProvider
= hServiceProvider
;
4394 HRESULT
DP_InitializeDPLSP( IDirectPlay3Impl
* This
, HMODULE hLobbyProvider
)
4397 LPSP_INIT DPLSPInit
;
4399 /* Initialize the service provider by calling SPInit */
4400 DPLSPInit
= (LPSP_INIT
)GetProcAddress( hLobbyProvider
, "DPLSPInit" );
4402 if( DPLSPInit
== NULL
)
4404 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4405 FreeLibrary( hLobbyProvider
);
4406 return DPERR_UNAVAILABLE
;
4409 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4411 hr
= (*DPLSPInit
)( &This
->dp2
->dplspData
);
4415 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr
) );
4416 FreeLibrary( hLobbyProvider
);
4420 /* FIXME: Need to verify the sanity of the returned callback table
4421 * using IsBadCodePtr */
4423 This
->dp2
->bDPLSPInitialized
= TRUE
;
4425 /* This interface is now initialized as a lobby object */
4426 This
->dp2
->connectionInitialized
= DP_LOBBY_PROVIDER
;
4428 /* Store the handle of the module so that we can unload it later */
4429 This
->dp2
->hDPLobbyProvider
= hLobbyProvider
;
4434 static HRESULT DP_IF_InitializeConnection
4435 ( IDirectPlay3Impl
* This
, LPVOID lpConnection
, DWORD dwFlags
, BOOL bAnsi
)
4437 HMODULE hServiceProvider
;
4440 const DWORD dwAddrSize
= 80; /* FIXME: Need to calculate it correctly */
4441 BOOL bIsDpSp
; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4443 TRACE("(%p)->(%p,0x%08x,%u)\n", This
, lpConnection
, dwFlags
, bAnsi
);
4445 if ( lpConnection
== NULL
)
4447 return DPERR_INVALIDPARAMS
;
4452 return DPERR_INVALIDFLAGS
;
4455 if( This
->dp2
->connectionInitialized
!= NO_PROVIDER
)
4457 return DPERR_ALREADYINITIALIZED
;
4460 /* Find out what the requested SP is and how large this buffer is */
4461 hr
= DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress
, lpConnection
,
4462 dwAddrSize
, &guidSP
);
4466 ERR( "Invalid compound address?\n" );
4467 return DPERR_UNAVAILABLE
;
4470 /* Load the service provider */
4471 hServiceProvider
= DP_LoadSP( &guidSP
, &This
->dp2
->spData
, &bIsDpSp
);
4473 if( hServiceProvider
== 0 )
4475 ERR( "Unable to load service provider %s\n", debugstr_guid(&guidSP
) );
4476 return DPERR_UNAVAILABLE
;
4481 /* Fill in what we can of the Service Provider required information.
4482 * The rest was be done in DP_LoadSP
4484 This
->dp2
->spData
.lpAddress
= lpConnection
;
4485 This
->dp2
->spData
.dwAddressSize
= dwAddrSize
;
4486 This
->dp2
->spData
.lpGuid
= &guidSP
;
4488 hr
= DP_InitializeDPSP( This
, hServiceProvider
);
4492 This
->dp2
->dplspData
.lpAddress
= lpConnection
;
4494 hr
= DP_InitializeDPLSP( This
, hServiceProvider
);
4505 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4506 ( LPDIRECTPLAY3A iface
, LPVOID lpConnection
, DWORD dwFlags
)
4508 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4509 return DP_IF_InitializeConnection( This
, lpConnection
, dwFlags
, TRUE
);
4512 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4513 ( LPDIRECTPLAY3 iface
, LPVOID lpConnection
, DWORD dwFlags
)
4515 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4516 return DP_IF_InitializeConnection( This
, lpConnection
, dwFlags
, FALSE
);
4519 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4520 ( LPDIRECTPLAY3A iface
, LPCDPSESSIONDESC2 lpsd
, DWORD dwFlags
,
4521 LPCDPSECURITYDESC lpSecurity
, LPCDPCREDENTIALS lpCredentials
)
4523 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
; /* Yes a dp 2 interface */
4524 return DP_SecureOpen( This
, lpsd
, dwFlags
, lpSecurity
, lpCredentials
, TRUE
);
4527 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4528 ( LPDIRECTPLAY3 iface
, LPCDPSESSIONDESC2 lpsd
, DWORD dwFlags
,
4529 LPCDPSECURITYDESC lpSecurity
, LPCDPCREDENTIALS lpCredentials
)
4531 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
; /* Yes a dp 2 interface */
4532 return DP_SecureOpen( This
, lpsd
, dwFlags
, lpSecurity
, lpCredentials
, FALSE
);
4535 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4536 ( LPDIRECTPLAY3A iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
, LPDPCHAT lpChatMessage
)
4538 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4539 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This
, idFrom
, idTo
, dwFlags
, lpChatMessage
);
4543 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4544 ( LPDIRECTPLAY3 iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
, LPDPCHAT lpChatMessage
)
4546 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4547 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This
, idFrom
, idTo
, dwFlags
, lpChatMessage
);
4551 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4552 ( LPDIRECTPLAY3A iface
, DWORD dwFlags
, DPID idGroup
, LPDPLCONNECTION lpConnection
)
4554 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4555 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This
, dwFlags
, idGroup
, lpConnection
);
4559 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4560 ( LPDIRECTPLAY3 iface
, DWORD dwFlags
, DPID idGroup
, LPDPLCONNECTION lpConnection
)
4562 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4563 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This
, dwFlags
, idGroup
, lpConnection
);
4567 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4568 ( LPDIRECTPLAY3A iface
, DWORD dwFlags
, DPID idGroup
)
4570 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4571 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This
, dwFlags
, idGroup
);
4575 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4576 ( LPDIRECTPLAY3 iface
, DWORD dwFlags
, DPID idGroup
)
4578 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4579 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This
, dwFlags
, idGroup
);
4583 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4584 ( LPDIRECTPLAY3A iface
, DPID idGroup
, LPDWORD lpdwFlags
)
4586 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4587 FIXME("(%p)->(0x%08x,%p): stub\n", This
, idGroup
, lpdwFlags
);
4591 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4592 ( LPDIRECTPLAY3 iface
, DPID idGroup
, LPDWORD lpdwFlags
)
4594 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4595 FIXME("(%p)->(0x%08x,%p): stub\n", This
, idGroup
, lpdwFlags
);
4599 static HRESULT DP_IF_GetGroupParent
4600 ( IDirectPlay3AImpl
* This
, DPID idGroup
, LPDPID lpidGroup
,
4603 lpGroupData lpGData
;
4605 TRACE("(%p)->(0x%08x,%p,%u)\n", This
, idGroup
, lpidGroup
, bAnsi
);
4607 if( ( lpGData
= DP_FindAnyGroup( (IDirectPlay2AImpl
*)This
, idGroup
) ) == NULL
)
4609 return DPERR_INVALIDGROUP
;
4612 *lpidGroup
= lpGData
->dpid
;
4617 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4618 ( LPDIRECTPLAY3A iface
, DPID idGroup
, LPDPID lpidGroup
)
4620 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4621 return DP_IF_GetGroupParent( This
, idGroup
, lpidGroup
, TRUE
);
4623 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4624 ( LPDIRECTPLAY3 iface
, DPID idGroup
, LPDPID lpidGroup
)
4626 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4627 return DP_IF_GetGroupParent( This
, idGroup
, lpidGroup
, FALSE
);
4630 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4631 ( LPDIRECTPLAY3A iface
, DPID idPlayer
, DWORD dwFlags
, LPVOID lpData
, LPDWORD lpdwDataSize
)
4633 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4634 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This
, idPlayer
, dwFlags
, lpData
, lpdwDataSize
);
4638 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4639 ( LPDIRECTPLAY3 iface
, DPID idPlayer
, DWORD dwFlags
, LPVOID lpData
, LPDWORD lpdwDataSize
)
4641 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4642 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This
, idPlayer
, dwFlags
, lpData
, lpdwDataSize
);
4646 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4647 ( LPDIRECTPLAY3A iface
, DPID idPlayer
, LPDWORD lpdwFlags
)
4649 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4650 FIXME("(%p)->(0x%08x,%p): stub\n", This
, idPlayer
, lpdwFlags
);
4654 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4655 ( LPDIRECTPLAY3 iface
, DPID idPlayer
, LPDWORD lpdwFlags
)
4657 IDirectPlay3Impl
*This
= (IDirectPlay3Impl
*)iface
;
4658 FIXME("(%p)->(0x%08x,%p): stub\n", This
, idPlayer
, lpdwFlags
);
4662 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4663 ( LPDIRECTPLAY4A iface
, DPID idGroup
, LPDPID lpidGroupOwner
)
4665 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4666 FIXME("(%p)->(0x%08x,%p): stub\n", This
, idGroup
, lpidGroupOwner
);
4670 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4671 ( LPDIRECTPLAY4 iface
, DPID idGroup
, LPDPID lpidGroupOwner
)
4673 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4674 FIXME("(%p)->(0x%08x,%p): stub\n", This
, idGroup
, lpidGroupOwner
);
4678 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4679 ( LPDIRECTPLAY4A iface
, DPID idGroup
, DPID idGroupOwner
)
4681 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4682 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This
, idGroup
, idGroupOwner
);
4686 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4687 ( LPDIRECTPLAY4 iface
, DPID idGroup
, DPID idGroupOwner
)
4689 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4690 FIXME("(%p)->(0x%08x,0x%08x): stub\n", This
, idGroup
, idGroupOwner
);
4694 static HRESULT DP_SendEx
4695 ( IDirectPlay2Impl
* This
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
4696 LPVOID lpData
, DWORD dwDataSize
, DWORD dwPriority
, DWORD dwTimeout
,
4697 LPVOID lpContext
, LPDWORD lpdwMsgID
, BOOL bAnsi
)
4699 BOOL bValidDestination
= FALSE
;
4701 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,0x%08x,0x%08x,0x%08x,%p,%p,%u)"
4703 This
, idFrom
, idTo
, dwFlags
, lpData
, dwDataSize
, dwPriority
,
4704 dwTimeout
, lpContext
, lpdwMsgID
, bAnsi
);
4706 if( This
->dp2
->connectionInitialized
== NO_PROVIDER
)
4708 return DPERR_UNINITIALIZED
;
4711 /* FIXME: Add parameter checking */
4712 /* FIXME: First call to this needs to acquire a message id which will be
4713 * used for multiple sends
4716 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4718 /* Verify that the message is being sent from a valid local player. The
4719 * from player may be anonymous DPID_UNKNOWN
4721 if( idFrom
!= DPID_UNKNOWN
)
4723 if( DP_FindPlayer( This
, idFrom
) == NULL
)
4725 WARN( "INFO: Invalid from player 0x%08x\n", idFrom
);
4726 return DPERR_INVALIDPLAYER
;
4730 /* Verify that the message is being sent to a valid player, group or to
4731 * everyone. If it's valid, send it to those players.
4733 if( idTo
== DPID_ALLPLAYERS
)
4735 bValidDestination
= TRUE
;
4737 /* See if SP has the ability to multicast. If so, use it */
4738 if( This
->dp2
->spData
.lpCB
->SendToGroupEx
)
4740 FIXME( "Use group sendex to group 0\n" );
4742 else if( This
->dp2
->spData
.lpCB
->SendToGroup
) /* obsolete interface */
4744 FIXME( "Use obsolete group send to group 0\n" );
4746 else /* No multicast, multiplicate */
4748 /* Send to all players we know about */
4749 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4753 if( ( !bValidDestination
) &&
4754 ( DP_FindPlayer( This
, idTo
) != NULL
)
4757 bValidDestination
= TRUE
;
4759 /* Have the service provider send this message */
4760 /* FIXME: Could optimize for local interface sends */
4761 return DP_SP_SendEx( This
, dwFlags
, lpData
, dwDataSize
, dwPriority
,
4762 dwTimeout
, lpContext
, lpdwMsgID
);
4765 if( ( !bValidDestination
) &&
4766 ( DP_FindAnyGroup( This
, idTo
) != NULL
)
4769 bValidDestination
= TRUE
;
4771 /* See if SP has the ability to multicast. If so, use it */
4772 if( This
->dp2
->spData
.lpCB
->SendToGroupEx
)
4774 FIXME( "Use group sendex\n" );
4776 else if( This
->dp2
->spData
.lpCB
->SendToGroup
) /* obsolete interface */
4778 FIXME( "Use obsolete group send to group\n" );
4780 else /* No multicast, multiplicate */
4782 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4790 This
->dp2
->hReplyEvent
= CreateEventW( NULL
, FALSE
, FALSE
, NULL
);
4792 dwWaitReturn
= WaitForSingleObject( hReplyEvent
, dwTimeout
);
4793 if( dwWaitReturn
!= WAIT_OBJECT_0
)
4795 ERR( "Wait failed 0x%08lx\n", dwWaitReturn
);
4801 if( !bValidDestination
)
4803 return DPERR_INVALIDPLAYER
;
4807 /* FIXME: Should return what the send returned */
4813 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4814 ( LPDIRECTPLAY4A iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
4815 LPVOID lpData
, DWORD dwDataSize
, DWORD dwPriority
, DWORD dwTimeout
,
4816 LPVOID lpContext
, LPDWORD lpdwMsgID
)
4818 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
; /* yes downcast to 2 */
4819 return DP_SendEx( This
, idFrom
, idTo
, dwFlags
, lpData
, dwDataSize
,
4820 dwPriority
, dwTimeout
, lpContext
, lpdwMsgID
, TRUE
);
4823 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4824 ( LPDIRECTPLAY4 iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
4825 LPVOID lpData
, DWORD dwDataSize
, DWORD dwPriority
, DWORD dwTimeout
,
4826 LPVOID lpContext
, LPDWORD lpdwMsgID
)
4828 IDirectPlay2Impl
*This
= (IDirectPlay2Impl
*)iface
; /* yes downcast to 2 */
4829 return DP_SendEx( This
, idFrom
, idTo
, dwFlags
, lpData
, dwDataSize
,
4830 dwPriority
, dwTimeout
, lpContext
, lpdwMsgID
, FALSE
);
4833 static HRESULT DP_SP_SendEx
4834 ( IDirectPlay2Impl
* This
, DWORD dwFlags
,
4835 LPVOID lpData
, DWORD dwDataSize
, DWORD dwPriority
, DWORD dwTimeout
,
4836 LPVOID lpContext
, LPDWORD lpdwMsgID
)
4840 FIXME( ": stub\n" );
4842 /* FIXME: This queuing should only be for async messages */
4844 lpMElem
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpMElem
) );
4845 lpMElem
->msg
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, dwDataSize
);
4847 CopyMemory( lpMElem
->msg
, lpData
, dwDataSize
);
4849 /* FIXME: Need to queue based on priority */
4850 DPQ_INSERT( This
->dp2
->sendMsgs
, lpMElem
, msgs
);
4855 static HRESULT DP_IF_GetMessageQueue
4856 ( IDirectPlay4Impl
* This
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
4857 LPDWORD lpdwNumMsgs
, LPDWORD lpdwNumBytes
, BOOL bAnsi
)
4861 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%p,%u): semi stub\n",
4862 This
, idFrom
, idTo
, dwFlags
, lpdwNumMsgs
, lpdwNumBytes
, bAnsi
);
4864 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4865 /* FIXME: What about sends which are not immediate? */
4867 if( This
->dp2
->spData
.lpCB
->GetMessageQueue
)
4869 DPSP_GETMESSAGEQUEUEDATA data
;
4871 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4873 /* FIXME: None of this is documented :( */
4875 data
.lpISP
= This
->dp2
->spData
.lpISP
;
4876 data
.dwFlags
= dwFlags
;
4877 data
.idFrom
= idFrom
;
4879 data
.lpdwNumMsgs
= lpdwNumMsgs
;
4880 data
.lpdwNumBytes
= lpdwNumBytes
;
4882 hr
= (*This
->dp2
->spData
.lpCB
->GetMessageQueue
)( &data
);
4886 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4892 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4893 ( LPDIRECTPLAY4A iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
4894 LPDWORD lpdwNumMsgs
, LPDWORD lpdwNumBytes
)
4896 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4897 return DP_IF_GetMessageQueue( This
, idFrom
, idTo
, dwFlags
, lpdwNumMsgs
,
4898 lpdwNumBytes
, TRUE
);
4901 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4902 ( LPDIRECTPLAY4 iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
4903 LPDWORD lpdwNumMsgs
, LPDWORD lpdwNumBytes
)
4905 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4906 return DP_IF_GetMessageQueue( This
, idFrom
, idTo
, dwFlags
, lpdwNumMsgs
,
4907 lpdwNumBytes
, FALSE
);
4910 static HRESULT DP_IF_CancelMessage
4911 ( IDirectPlay4Impl
* This
, DWORD dwMsgID
, DWORD dwFlags
,
4912 DWORD dwMinPriority
, DWORD dwMaxPriority
, BOOL bAnsi
)
4916 FIXME( "(%p)->(0x%08x,0x%08x,%u): semi stub\n",
4917 This
, dwMsgID
, dwFlags
, bAnsi
);
4919 if( This
->dp2
->spData
.lpCB
->Cancel
)
4921 DPSP_CANCELDATA data
;
4923 TRACE( "Calling SP Cancel\n" );
4925 /* FIXME: Undocumented callback */
4927 data
.lpISP
= This
->dp2
->spData
.lpISP
;
4928 data
.dwFlags
= dwFlags
;
4929 data
.lprglpvSPMsgID
= NULL
;
4930 data
.cSPMsgID
= dwMsgID
;
4931 data
.dwMinPriority
= dwMinPriority
;
4932 data
.dwMaxPriority
= dwMaxPriority
;
4934 hr
= (*This
->dp2
->spData
.lpCB
->Cancel
)( &data
);
4938 FIXME( "SP doesn't implement Cancel\n" );
4944 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
4945 ( LPDIRECTPLAY4A iface
, DWORD dwMsgID
, DWORD dwFlags
)
4947 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4951 return DPERR_INVALIDFLAGS
;
4956 dwFlags
|= DPCANCELSEND_ALL
;
4959 return DP_IF_CancelMessage( This
, dwMsgID
, dwFlags
, 0, 0, TRUE
);
4962 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
4963 ( LPDIRECTPLAY4 iface
, DWORD dwMsgID
, DWORD dwFlags
)
4965 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4969 return DPERR_INVALIDFLAGS
;
4974 dwFlags
|= DPCANCELSEND_ALL
;
4977 return DP_IF_CancelMessage( This
, dwMsgID
, dwFlags
, 0, 0, FALSE
);
4980 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
4981 ( LPDIRECTPLAY4A iface
, DWORD dwMinPriority
, DWORD dwMaxPriority
,
4984 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
4988 return DPERR_INVALIDFLAGS
;
4991 return DP_IF_CancelMessage( This
, 0, DPCANCELSEND_PRIORITY
, dwMinPriority
,
4992 dwMaxPriority
, TRUE
);
4995 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
4996 ( LPDIRECTPLAY4 iface
, DWORD dwMinPriority
, DWORD dwMaxPriority
,
4999 IDirectPlay4Impl
*This
= (IDirectPlay4Impl
*)iface
;
5003 return DPERR_INVALIDFLAGS
;
5006 return DP_IF_CancelMessage( This
, 0, DPCANCELSEND_PRIORITY
, dwMinPriority
,
5007 dwMaxPriority
, FALSE
);
5010 /* Note: Hack so we can reuse the old functions without compiler warnings */
5011 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5012 # define XCAST(fun) (typeof(directPlay2WVT.fun))
5014 # define XCAST(fun) (void*)
5017 static const IDirectPlay2Vtbl directPlay2WVT
=
5019 XCAST(QueryInterface
)DP_QueryInterface
,
5020 XCAST(AddRef
)DP_AddRef
,
5021 XCAST(Release
)DP_Release
,
5023 DirectPlay2WImpl_AddPlayerToGroup
,
5024 DirectPlay2WImpl_Close
,
5025 DirectPlay2WImpl_CreateGroup
,
5026 DirectPlay2WImpl_CreatePlayer
,
5027 DirectPlay2WImpl_DeletePlayerFromGroup
,
5028 DirectPlay2WImpl_DestroyGroup
,
5029 DirectPlay2WImpl_DestroyPlayer
,
5030 DirectPlay2WImpl_EnumGroupPlayers
,
5031 DirectPlay2WImpl_EnumGroups
,
5032 DirectPlay2WImpl_EnumPlayers
,
5033 DirectPlay2WImpl_EnumSessions
,
5034 DirectPlay2WImpl_GetCaps
,
5035 DirectPlay2WImpl_GetGroupData
,
5036 DirectPlay2WImpl_GetGroupName
,
5037 DirectPlay2WImpl_GetMessageCount
,
5038 DirectPlay2WImpl_GetPlayerAddress
,
5039 DirectPlay2WImpl_GetPlayerCaps
,
5040 DirectPlay2WImpl_GetPlayerData
,
5041 DirectPlay2WImpl_GetPlayerName
,
5042 DirectPlay2WImpl_GetSessionDesc
,
5043 DirectPlay2WImpl_Initialize
,
5044 DirectPlay2WImpl_Open
,
5045 DirectPlay2WImpl_Receive
,
5046 DirectPlay2WImpl_Send
,
5047 DirectPlay2WImpl_SetGroupData
,
5048 DirectPlay2WImpl_SetGroupName
,
5049 DirectPlay2WImpl_SetPlayerData
,
5050 DirectPlay2WImpl_SetPlayerName
,
5051 DirectPlay2WImpl_SetSessionDesc
5055 /* Note: Hack so we can reuse the old functions without compiler warnings */
5056 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5057 # define XCAST(fun) (typeof(directPlay2AVT.fun))
5059 # define XCAST(fun) (void*)
5062 static const IDirectPlay2Vtbl directPlay2AVT
=
5064 XCAST(QueryInterface
)DP_QueryInterface
,
5065 XCAST(AddRef
)DP_AddRef
,
5066 XCAST(Release
)DP_Release
,
5068 DirectPlay2AImpl_AddPlayerToGroup
,
5069 DirectPlay2AImpl_Close
,
5070 DirectPlay2AImpl_CreateGroup
,
5071 DirectPlay2AImpl_CreatePlayer
,
5072 DirectPlay2AImpl_DeletePlayerFromGroup
,
5073 DirectPlay2AImpl_DestroyGroup
,
5074 DirectPlay2AImpl_DestroyPlayer
,
5075 DirectPlay2AImpl_EnumGroupPlayers
,
5076 DirectPlay2AImpl_EnumGroups
,
5077 DirectPlay2AImpl_EnumPlayers
,
5078 DirectPlay2AImpl_EnumSessions
,
5079 DirectPlay2AImpl_GetCaps
,
5080 DirectPlay2AImpl_GetGroupData
,
5081 DirectPlay2AImpl_GetGroupName
,
5082 DirectPlay2AImpl_GetMessageCount
,
5083 DirectPlay2AImpl_GetPlayerAddress
,
5084 DirectPlay2AImpl_GetPlayerCaps
,
5085 DirectPlay2AImpl_GetPlayerData
,
5086 DirectPlay2AImpl_GetPlayerName
,
5087 DirectPlay2AImpl_GetSessionDesc
,
5088 DirectPlay2AImpl_Initialize
,
5089 DirectPlay2AImpl_Open
,
5090 DirectPlay2AImpl_Receive
,
5091 DirectPlay2AImpl_Send
,
5092 DirectPlay2AImpl_SetGroupData
,
5093 DirectPlay2AImpl_SetGroupName
,
5094 DirectPlay2AImpl_SetPlayerData
,
5095 DirectPlay2AImpl_SetPlayerName
,
5096 DirectPlay2AImpl_SetSessionDesc
5101 /* Note: Hack so we can reuse the old functions without compiler warnings */
5102 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5103 # define XCAST(fun) (typeof(directPlay3AVT.fun))
5105 # define XCAST(fun) (void*)
5108 static const IDirectPlay3Vtbl directPlay3AVT
=
5110 XCAST(QueryInterface
)DP_QueryInterface
,
5111 XCAST(AddRef
)DP_AddRef
,
5112 XCAST(Release
)DP_Release
,
5114 XCAST(AddPlayerToGroup
)DirectPlay2AImpl_AddPlayerToGroup
,
5115 XCAST(Close
)DirectPlay2AImpl_Close
,
5116 XCAST(CreateGroup
)DirectPlay2AImpl_CreateGroup
,
5117 XCAST(CreatePlayer
)DirectPlay2AImpl_CreatePlayer
,
5118 XCAST(DeletePlayerFromGroup
)DirectPlay2AImpl_DeletePlayerFromGroup
,
5119 XCAST(DestroyGroup
)DirectPlay2AImpl_DestroyGroup
,
5120 XCAST(DestroyPlayer
)DirectPlay2AImpl_DestroyPlayer
,
5121 XCAST(EnumGroupPlayers
)DirectPlay2AImpl_EnumGroupPlayers
,
5122 XCAST(EnumGroups
)DirectPlay2AImpl_EnumGroups
,
5123 XCAST(EnumPlayers
)DirectPlay2AImpl_EnumPlayers
,
5124 XCAST(EnumSessions
)DirectPlay2AImpl_EnumSessions
,
5125 XCAST(GetCaps
)DirectPlay2AImpl_GetCaps
,
5126 XCAST(GetGroupData
)DirectPlay2AImpl_GetGroupData
,
5127 XCAST(GetGroupName
)DirectPlay2AImpl_GetGroupName
,
5128 XCAST(GetMessageCount
)DirectPlay2AImpl_GetMessageCount
,
5129 XCAST(GetPlayerAddress
)DirectPlay2AImpl_GetPlayerAddress
,
5130 XCAST(GetPlayerCaps
)DirectPlay2AImpl_GetPlayerCaps
,
5131 XCAST(GetPlayerData
)DirectPlay2AImpl_GetPlayerData
,
5132 XCAST(GetPlayerName
)DirectPlay2AImpl_GetPlayerName
,
5133 XCAST(GetSessionDesc
)DirectPlay2AImpl_GetSessionDesc
,
5134 XCAST(Initialize
)DirectPlay2AImpl_Initialize
,
5135 XCAST(Open
)DirectPlay2AImpl_Open
,
5136 XCAST(Receive
)DirectPlay2AImpl_Receive
,
5137 XCAST(Send
)DirectPlay2AImpl_Send
,
5138 XCAST(SetGroupData
)DirectPlay2AImpl_SetGroupData
,
5139 XCAST(SetGroupName
)DirectPlay2AImpl_SetGroupName
,
5140 XCAST(SetPlayerData
)DirectPlay2AImpl_SetPlayerData
,
5141 XCAST(SetPlayerName
)DirectPlay2AImpl_SetPlayerName
,
5142 XCAST(SetSessionDesc
)DirectPlay2AImpl_SetSessionDesc
,
5144 DirectPlay3AImpl_AddGroupToGroup
,
5145 DirectPlay3AImpl_CreateGroupInGroup
,
5146 DirectPlay3AImpl_DeleteGroupFromGroup
,
5147 DirectPlay3AImpl_EnumConnections
,
5148 DirectPlay3AImpl_EnumGroupsInGroup
,
5149 DirectPlay3AImpl_GetGroupConnectionSettings
,
5150 DirectPlay3AImpl_InitializeConnection
,
5151 DirectPlay3AImpl_SecureOpen
,
5152 DirectPlay3AImpl_SendChatMessage
,
5153 DirectPlay3AImpl_SetGroupConnectionSettings
,
5154 DirectPlay3AImpl_StartSession
,
5155 DirectPlay3AImpl_GetGroupFlags
,
5156 DirectPlay3AImpl_GetGroupParent
,
5157 DirectPlay3AImpl_GetPlayerAccount
,
5158 DirectPlay3AImpl_GetPlayerFlags
5162 /* Note: Hack so we can reuse the old functions without compiler warnings */
5163 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5164 # define XCAST(fun) (typeof(directPlay3WVT.fun))
5166 # define XCAST(fun) (void*)
5168 static const IDirectPlay3Vtbl directPlay3WVT
=
5170 XCAST(QueryInterface
)DP_QueryInterface
,
5171 XCAST(AddRef
)DP_AddRef
,
5172 XCAST(Release
)DP_Release
,
5174 XCAST(AddPlayerToGroup
)DirectPlay2WImpl_AddPlayerToGroup
,
5175 XCAST(Close
)DirectPlay2WImpl_Close
,
5176 XCAST(CreateGroup
)DirectPlay2WImpl_CreateGroup
,
5177 XCAST(CreatePlayer
)DirectPlay2WImpl_CreatePlayer
,
5178 XCAST(DeletePlayerFromGroup
)DirectPlay2WImpl_DeletePlayerFromGroup
,
5179 XCAST(DestroyGroup
)DirectPlay2WImpl_DestroyGroup
,
5180 XCAST(DestroyPlayer
)DirectPlay2WImpl_DestroyPlayer
,
5181 XCAST(EnumGroupPlayers
)DirectPlay2WImpl_EnumGroupPlayers
,
5182 XCAST(EnumGroups
)DirectPlay2WImpl_EnumGroups
,
5183 XCAST(EnumPlayers
)DirectPlay2WImpl_EnumPlayers
,
5184 XCAST(EnumSessions
)DirectPlay2WImpl_EnumSessions
,
5185 XCAST(GetCaps
)DirectPlay2WImpl_GetCaps
,
5186 XCAST(GetGroupData
)DirectPlay2WImpl_GetGroupData
,
5187 XCAST(GetGroupName
)DirectPlay2WImpl_GetGroupName
,
5188 XCAST(GetMessageCount
)DirectPlay2WImpl_GetMessageCount
,
5189 XCAST(GetPlayerAddress
)DirectPlay2WImpl_GetPlayerAddress
,
5190 XCAST(GetPlayerCaps
)DirectPlay2WImpl_GetPlayerCaps
,
5191 XCAST(GetPlayerData
)DirectPlay2WImpl_GetPlayerData
,
5192 XCAST(GetPlayerName
)DirectPlay2WImpl_GetPlayerName
,
5193 XCAST(GetSessionDesc
)DirectPlay2WImpl_GetSessionDesc
,
5194 XCAST(Initialize
)DirectPlay2WImpl_Initialize
,
5195 XCAST(Open
)DirectPlay2WImpl_Open
,
5196 XCAST(Receive
)DirectPlay2WImpl_Receive
,
5197 XCAST(Send
)DirectPlay2WImpl_Send
,
5198 XCAST(SetGroupData
)DirectPlay2WImpl_SetGroupData
,
5199 XCAST(SetGroupName
)DirectPlay2WImpl_SetGroupName
,
5200 XCAST(SetPlayerData
)DirectPlay2WImpl_SetPlayerData
,
5201 XCAST(SetPlayerName
)DirectPlay2WImpl_SetPlayerName
,
5202 XCAST(SetSessionDesc
)DirectPlay2WImpl_SetSessionDesc
,
5204 DirectPlay3WImpl_AddGroupToGroup
,
5205 DirectPlay3WImpl_CreateGroupInGroup
,
5206 DirectPlay3WImpl_DeleteGroupFromGroup
,
5207 DirectPlay3WImpl_EnumConnections
,
5208 DirectPlay3WImpl_EnumGroupsInGroup
,
5209 DirectPlay3WImpl_GetGroupConnectionSettings
,
5210 DirectPlay3WImpl_InitializeConnection
,
5211 DirectPlay3WImpl_SecureOpen
,
5212 DirectPlay3WImpl_SendChatMessage
,
5213 DirectPlay3WImpl_SetGroupConnectionSettings
,
5214 DirectPlay3WImpl_StartSession
,
5215 DirectPlay3WImpl_GetGroupFlags
,
5216 DirectPlay3WImpl_GetGroupParent
,
5217 DirectPlay3WImpl_GetPlayerAccount
,
5218 DirectPlay3WImpl_GetPlayerFlags
5222 /* Note: Hack so we can reuse the old functions without compiler warnings */
5223 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5224 # define XCAST(fun) (typeof(directPlay4WVT.fun))
5226 # define XCAST(fun) (void*)
5228 static const IDirectPlay4Vtbl directPlay4WVT
=
5230 XCAST(QueryInterface
)DP_QueryInterface
,
5231 XCAST(AddRef
)DP_AddRef
,
5232 XCAST(Release
)DP_Release
,
5234 XCAST(AddPlayerToGroup
)DirectPlay2WImpl_AddPlayerToGroup
,
5235 XCAST(Close
)DirectPlay2WImpl_Close
,
5236 XCAST(CreateGroup
)DirectPlay2WImpl_CreateGroup
,
5237 XCAST(CreatePlayer
)DirectPlay2WImpl_CreatePlayer
,
5238 XCAST(DeletePlayerFromGroup
)DirectPlay2WImpl_DeletePlayerFromGroup
,
5239 XCAST(DestroyGroup
)DirectPlay2WImpl_DestroyGroup
,
5240 XCAST(DestroyPlayer
)DirectPlay2WImpl_DestroyPlayer
,
5241 XCAST(EnumGroupPlayers
)DirectPlay2WImpl_EnumGroupPlayers
,
5242 XCAST(EnumGroups
)DirectPlay2WImpl_EnumGroups
,
5243 XCAST(EnumPlayers
)DirectPlay2WImpl_EnumPlayers
,
5244 XCAST(EnumSessions
)DirectPlay2WImpl_EnumSessions
,
5245 XCAST(GetCaps
)DirectPlay2WImpl_GetCaps
,
5246 XCAST(GetGroupData
)DirectPlay2WImpl_GetGroupData
,
5247 XCAST(GetGroupName
)DirectPlay2WImpl_GetGroupName
,
5248 XCAST(GetMessageCount
)DirectPlay2WImpl_GetMessageCount
,
5249 XCAST(GetPlayerAddress
)DirectPlay2WImpl_GetPlayerAddress
,
5250 XCAST(GetPlayerCaps
)DirectPlay2WImpl_GetPlayerCaps
,
5251 XCAST(GetPlayerData
)DirectPlay2WImpl_GetPlayerData
,
5252 XCAST(GetPlayerName
)DirectPlay2WImpl_GetPlayerName
,
5253 XCAST(GetSessionDesc
)DirectPlay2WImpl_GetSessionDesc
,
5254 XCAST(Initialize
)DirectPlay2WImpl_Initialize
,
5255 XCAST(Open
)DirectPlay2WImpl_Open
,
5256 XCAST(Receive
)DirectPlay2WImpl_Receive
,
5257 XCAST(Send
)DirectPlay2WImpl_Send
,
5258 XCAST(SetGroupData
)DirectPlay2WImpl_SetGroupData
,
5259 XCAST(SetGroupName
)DirectPlay2WImpl_SetGroupName
,
5260 XCAST(SetPlayerData
)DirectPlay2WImpl_SetPlayerData
,
5261 XCAST(SetPlayerName
)DirectPlay2WImpl_SetPlayerName
,
5262 XCAST(SetSessionDesc
)DirectPlay2WImpl_SetSessionDesc
,
5264 XCAST(AddGroupToGroup
)DirectPlay3WImpl_AddGroupToGroup
,
5265 XCAST(CreateGroupInGroup
)DirectPlay3WImpl_CreateGroupInGroup
,
5266 XCAST(DeleteGroupFromGroup
)DirectPlay3WImpl_DeleteGroupFromGroup
,
5267 XCAST(EnumConnections
)DirectPlay3WImpl_EnumConnections
,
5268 XCAST(EnumGroupsInGroup
)DirectPlay3WImpl_EnumGroupsInGroup
,
5269 XCAST(GetGroupConnectionSettings
)DirectPlay3WImpl_GetGroupConnectionSettings
,
5270 XCAST(InitializeConnection
)DirectPlay3WImpl_InitializeConnection
,
5271 XCAST(SecureOpen
)DirectPlay3WImpl_SecureOpen
,
5272 XCAST(SendChatMessage
)DirectPlay3WImpl_SendChatMessage
,
5273 XCAST(SetGroupConnectionSettings
)DirectPlay3WImpl_SetGroupConnectionSettings
,
5274 XCAST(StartSession
)DirectPlay3WImpl_StartSession
,
5275 XCAST(GetGroupFlags
)DirectPlay3WImpl_GetGroupFlags
,
5276 XCAST(GetGroupParent
)DirectPlay3WImpl_GetGroupParent
,
5277 XCAST(GetPlayerAccount
)DirectPlay3WImpl_GetPlayerAccount
,
5278 XCAST(GetPlayerFlags
)DirectPlay3WImpl_GetPlayerFlags
,
5280 DirectPlay4WImpl_GetGroupOwner
,
5281 DirectPlay4WImpl_SetGroupOwner
,
5282 DirectPlay4WImpl_SendEx
,
5283 DirectPlay4WImpl_GetMessageQueue
,
5284 DirectPlay4WImpl_CancelMessage
,
5285 DirectPlay4WImpl_CancelPriority
5290 /* Note: Hack so we can reuse the old functions without compiler warnings */
5291 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5292 # define XCAST(fun) (typeof(directPlay4AVT.fun))
5294 # define XCAST(fun) (void*)
5296 static const IDirectPlay4Vtbl directPlay4AVT
=
5298 XCAST(QueryInterface
)DP_QueryInterface
,
5299 XCAST(AddRef
)DP_AddRef
,
5300 XCAST(Release
)DP_Release
,
5302 XCAST(AddPlayerToGroup
)DirectPlay2AImpl_AddPlayerToGroup
,
5303 XCAST(Close
)DirectPlay2AImpl_Close
,
5304 XCAST(CreateGroup
)DirectPlay2AImpl_CreateGroup
,
5305 XCAST(CreatePlayer
)DirectPlay2AImpl_CreatePlayer
,
5306 XCAST(DeletePlayerFromGroup
)DirectPlay2AImpl_DeletePlayerFromGroup
,
5307 XCAST(DestroyGroup
)DirectPlay2AImpl_DestroyGroup
,
5308 XCAST(DestroyPlayer
)DirectPlay2AImpl_DestroyPlayer
,
5309 XCAST(EnumGroupPlayers
)DirectPlay2AImpl_EnumGroupPlayers
,
5310 XCAST(EnumGroups
)DirectPlay2AImpl_EnumGroups
,
5311 XCAST(EnumPlayers
)DirectPlay2AImpl_EnumPlayers
,
5312 XCAST(EnumSessions
)DirectPlay2AImpl_EnumSessions
,
5313 XCAST(GetCaps
)DirectPlay2AImpl_GetCaps
,
5314 XCAST(GetGroupData
)DirectPlay2AImpl_GetGroupData
,
5315 XCAST(GetGroupName
)DirectPlay2AImpl_GetGroupName
,
5316 XCAST(GetMessageCount
)DirectPlay2AImpl_GetMessageCount
,
5317 XCAST(GetPlayerAddress
)DirectPlay2AImpl_GetPlayerAddress
,
5318 XCAST(GetPlayerCaps
)DirectPlay2AImpl_GetPlayerCaps
,
5319 XCAST(GetPlayerData
)DirectPlay2AImpl_GetPlayerData
,
5320 XCAST(GetPlayerName
)DirectPlay2AImpl_GetPlayerName
,
5321 XCAST(GetSessionDesc
)DirectPlay2AImpl_GetSessionDesc
,
5322 XCAST(Initialize
)DirectPlay2AImpl_Initialize
,
5323 XCAST(Open
)DirectPlay2AImpl_Open
,
5324 XCAST(Receive
)DirectPlay2AImpl_Receive
,
5325 XCAST(Send
)DirectPlay2AImpl_Send
,
5326 XCAST(SetGroupData
)DirectPlay2AImpl_SetGroupData
,
5327 XCAST(SetGroupName
)DirectPlay2AImpl_SetGroupName
,
5328 XCAST(SetPlayerData
)DirectPlay2AImpl_SetPlayerData
,
5329 XCAST(SetPlayerName
)DirectPlay2AImpl_SetPlayerName
,
5330 XCAST(SetSessionDesc
)DirectPlay2AImpl_SetSessionDesc
,
5332 XCAST(AddGroupToGroup
)DirectPlay3AImpl_AddGroupToGroup
,
5333 XCAST(CreateGroupInGroup
)DirectPlay3AImpl_CreateGroupInGroup
,
5334 XCAST(DeleteGroupFromGroup
)DirectPlay3AImpl_DeleteGroupFromGroup
,
5335 XCAST(EnumConnections
)DirectPlay3AImpl_EnumConnections
,
5336 XCAST(EnumGroupsInGroup
)DirectPlay3AImpl_EnumGroupsInGroup
,
5337 XCAST(GetGroupConnectionSettings
)DirectPlay3AImpl_GetGroupConnectionSettings
,
5338 XCAST(InitializeConnection
)DirectPlay3AImpl_InitializeConnection
,
5339 XCAST(SecureOpen
)DirectPlay3AImpl_SecureOpen
,
5340 XCAST(SendChatMessage
)DirectPlay3AImpl_SendChatMessage
,
5341 XCAST(SetGroupConnectionSettings
)DirectPlay3AImpl_SetGroupConnectionSettings
,
5342 XCAST(StartSession
)DirectPlay3AImpl_StartSession
,
5343 XCAST(GetGroupFlags
)DirectPlay3AImpl_GetGroupFlags
,
5344 XCAST(GetGroupParent
)DirectPlay3AImpl_GetGroupParent
,
5345 XCAST(GetPlayerAccount
)DirectPlay3AImpl_GetPlayerAccount
,
5346 XCAST(GetPlayerFlags
)DirectPlay3AImpl_GetPlayerFlags
,
5348 DirectPlay4AImpl_GetGroupOwner
,
5349 DirectPlay4AImpl_SetGroupOwner
,
5350 DirectPlay4AImpl_SendEx
,
5351 DirectPlay4AImpl_GetMessageQueue
,
5352 DirectPlay4AImpl_CancelMessage
,
5353 DirectPlay4AImpl_CancelPriority
5357 HRESULT
DP_GetSPPlayerData( IDirectPlay2Impl
* lpDP
,
5361 lpPlayerList lpPlayer
= DP_FindPlayer( lpDP
, idPlayer
);
5363 if( lpPlayer
== NULL
)
5365 return DPERR_INVALIDPLAYER
;
5368 *lplpData
= lpPlayer
->lpPData
->lpSPPlayerData
;
5373 HRESULT
DP_SetSPPlayerData( IDirectPlay2Impl
* lpDP
,
5377 lpPlayerList lpPlayer
= DP_FindPlayer( lpDP
, idPlayer
);
5379 if( lpPlayer
== NULL
)
5381 return DPERR_INVALIDPLAYER
;
5384 lpPlayer
->lpPData
->lpSPPlayerData
= lpData
;
5389 /***************************************************************************
5390 * DirectPlayEnumerateAW
5392 * The pointer to the structure lpContext will be filled with the
5393 * appropriate data for each service offered by the OS. These services are
5394 * not necessarily available on this particular machine but are defined
5395 * as simple service providers under the "Service Providers" registry key.
5396 * This structure is then passed to lpEnumCallback for each of the different
5399 * This API is useful only for applications written using DirectX3 or
5400 * worse. It is superseded by IDirectPlay3::EnumConnections which also
5401 * gives information on the actual connections.
5403 * defn of a service provider:
5404 * A dynamic-link library used by DirectPlay to communicate over a network.
5405 * The service provider contains all the network-specific code required
5406 * to send and receive messages. Online services and network operators can
5407 * supply service providers to use specialized hardware, protocols, communications
5408 * media, and network resources.
5411 static HRESULT
DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA
,
5412 LPDPENUMDPCALLBACKW lpEnumCallbackW
,
5416 static const WCHAR searchSubKey
[] = {
5417 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
5418 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
5419 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
5420 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
5421 static const WCHAR guidKey
[] = { 'G', 'u', 'i', 'd', 0 };
5422 static const WCHAR descW
[] = { 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', 'W', 0 };
5427 char *descriptionA
= NULL
;
5428 DWORD max_sizeOfDescriptionA
= 0;
5429 WCHAR
*descriptionW
= NULL
;
5430 DWORD max_sizeOfDescriptionW
= 0;
5432 if (!lpEnumCallbackA
&& !lpEnumCallbackW
)
5434 return DPERR_INVALIDPARAMS
;
5437 /* Need to loop over the service providers in the registry */
5438 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, searchSubKey
,
5439 0, KEY_READ
, &hkResult
) != ERROR_SUCCESS
)
5441 /* Hmmm. Does this mean that there are no service providers? */
5442 ERR(": no service provider key in the registry - check your Wine installation !!!\n");
5443 return DPERR_GENERIC
;
5446 /* Traverse all the service providers we have available */
5450 WCHAR subKeyName
[255]; /* 255 is the maximum key size according to MSDN */
5451 DWORD sizeOfSubKeyName
= sizeof(subKeyName
) / sizeof(WCHAR
);
5452 HKEY hkServiceProvider
;
5453 GUID serviceProviderGUID
;
5454 WCHAR guidKeyContent
[(2 * 16) + 1 + 6 /* This corresponds to '{....-..-..-..-......}' */ ];
5455 DWORD sizeOfGuidKeyContent
= sizeof(guidKeyContent
);
5458 ret_value
= RegEnumKeyExW(hkResult
, dwIndex
, subKeyName
, &sizeOfSubKeyName
,
5459 NULL
, NULL
, NULL
, &filetime
);
5460 if (ret_value
== ERROR_NO_MORE_ITEMS
)
5462 else if (ret_value
!= ERROR_SUCCESS
)
5464 ERR(": could not enumerate on service provider key.\n");
5465 return DPERR_EXCEPTION
;
5467 TRACE(" this time through sub-key %s.\n", debugstr_w(subKeyName
));
5469 /* Open the key for this service provider */
5470 if (RegOpenKeyExW(hkResult
, subKeyName
, 0, KEY_READ
, &hkServiceProvider
) != ERROR_SUCCESS
)
5472 ERR(": could not open registry key for service provider %s.\n", debugstr_w(subKeyName
));
5476 /* Get the GUID from the registry */
5477 if (RegQueryValueExW(hkServiceProvider
, guidKey
,
5478 NULL
, NULL
, (LPBYTE
) guidKeyContent
, &sizeOfGuidKeyContent
) != ERROR_SUCCESS
)
5480 ERR(": missing GUID registry data member for service provider %s.\n", debugstr_w(subKeyName
));
5483 if (sizeOfGuidKeyContent
!= sizeof(guidKeyContent
))
5485 ERR(": invalid format for the GUID registry data member for service provider %s (%s).\n", debugstr_w(subKeyName
), debugstr_w(guidKeyContent
));
5488 CLSIDFromString(guidKeyContent
, &serviceProviderGUID
);
5490 /* The enumeration will return FALSE if we are not to continue.
5492 * Note: on my windows box, major / minor version is 6 / 0 for all service providers
5493 * and have no relation to any of the two dwReserved1 and dwReserved2 keys.
5494 * I think that it simply means that they are in-line with DirectX 6.0
5496 if (lpEnumCallbackA
)
5498 DWORD sizeOfDescription
= 0;
5500 /* Note that this is the A case of this function, so use the A variant to get the description string */
5501 if (RegQueryValueExA(hkServiceProvider
, "DescriptionA",
5502 NULL
, NULL
, NULL
, &sizeOfDescription
) != ERROR_SUCCESS
)
5504 ERR(": missing 'DescriptionA' registry data member for service provider %s.\n", debugstr_w(subKeyName
));
5507 if (sizeOfDescription
> max_sizeOfDescriptionA
)
5509 HeapFree(GetProcessHeap(), 0, descriptionA
);
5510 max_sizeOfDescriptionA
= sizeOfDescription
;
5512 descriptionA
= HeapAlloc(GetProcessHeap(), 0, sizeOfDescription
);
5513 RegQueryValueExA(hkServiceProvider
, "DescriptionA",
5514 NULL
, NULL
, (LPBYTE
) descriptionA
, &sizeOfDescription
);
5516 if (!lpEnumCallbackA(&serviceProviderGUID
, descriptionA
, 6, 0, lpContext
))
5521 DWORD sizeOfDescription
= 0;
5523 if (RegQueryValueExW(hkServiceProvider
, descW
,
5524 NULL
, NULL
, NULL
, &sizeOfDescription
) != ERROR_SUCCESS
)
5526 ERR(": missing 'DescriptionW' registry data member for service provider %s.\n", debugstr_w(subKeyName
));
5529 if (sizeOfDescription
> max_sizeOfDescriptionW
)
5531 HeapFree(GetProcessHeap(), 0, descriptionW
);
5532 max_sizeOfDescriptionW
= sizeOfDescription
;
5534 descriptionW
= HeapAlloc(GetProcessHeap(), 0, sizeOfDescription
);
5535 RegQueryValueExW(hkServiceProvider
, descW
,
5536 NULL
, NULL
, (LPBYTE
) descriptionW
, &sizeOfDescription
);
5538 if (!lpEnumCallbackW(&serviceProviderGUID
, descriptionW
, 6, 0, lpContext
))
5546 HeapFree(GetProcessHeap(), 0, descriptionA
);
5547 HeapFree(GetProcessHeap(), 0, descriptionW
);
5552 /***************************************************************************
5553 * DirectPlayEnumerate [DPLAYX.9]
5554 * DirectPlayEnumerateA [DPLAYX.2]
5556 HRESULT WINAPI
DirectPlayEnumerateA(LPDPENUMDPCALLBACKA lpEnumCallback
, LPVOID lpContext
)
5558 TRACE("(%p,%p)\n", lpEnumCallback
, lpContext
);
5560 return DirectPlayEnumerateAW(lpEnumCallback
, NULL
, lpContext
);
5563 /***************************************************************************
5564 * DirectPlayEnumerateW [DPLAYX.3]
5566 HRESULT WINAPI
DirectPlayEnumerateW(LPDPENUMDPCALLBACKW lpEnumCallback
, LPVOID lpContext
)
5568 TRACE("(%p,%p)\n", lpEnumCallback
, lpContext
);
5570 return DirectPlayEnumerateAW(NULL
, lpEnumCallback
, lpContext
);
5573 typedef struct tagCreateEnum
5577 } CreateEnumData
, *lpCreateEnumData
;
5579 /* Find and copy the matching connection for the SP guid */
5580 static BOOL CALLBACK
cbDPCreateEnumConnections(
5582 LPVOID lpConnection
,
5583 DWORD dwConnectionSize
,
5588 lpCreateEnumData lpData
= (lpCreateEnumData
)lpContext
;
5590 if( IsEqualGUID( lpguidSP
, lpData
->lpGuid
) )
5592 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData
->lpGuid
) );
5594 lpData
->lpConn
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
5596 CopyMemory( lpData
->lpConn
, lpConnection
, dwConnectionSize
);
5598 /* Found the record that we were looking for */
5602 /* Haven't found what were looking for yet */
5607 /***************************************************************************
5608 * DirectPlayCreate [DPLAYX.1]
5611 HRESULT WINAPI DirectPlayCreate
5612 ( LPGUID lpGUID
, LPDIRECTPLAY
*lplpDP
, IUnknown
*pUnk
)
5615 LPDIRECTPLAY3A lpDP3A
;
5616 CreateEnumData cbData
;
5618 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID
), lplpDP
, pUnk
);
5622 return CLASS_E_NOAGGREGATION
;
5625 if( (lplpDP
== NULL
) || (lpGUID
== NULL
) )
5627 return DPERR_INVALIDPARAMS
;
5631 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5632 give them an IDirectPlay2A object and hope that doesn't cause problems */
5633 if( DP_CreateInterface( &IID_IDirectPlay2A
, (LPVOID
*)lplpDP
) != DP_OK
)
5635 return DPERR_UNAVAILABLE
;
5638 if( IsEqualGUID( &GUID_NULL
, lpGUID
) )
5640 /* The GUID_NULL means don't bind a service provider. Just return the
5645 /* Bind the desired service provider since lpGUID is non NULL */
5646 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID
) );
5648 /* We're going to use a DP3 interface */
5649 hr
= IDirectPlayX_QueryInterface( *lplpDP
, &IID_IDirectPlay3A
,
5653 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr
) );
5657 cbData
.lpConn
= NULL
;
5658 cbData
.lpGuid
= lpGUID
;
5660 /* We were given a service provider, find info about it... */
5661 hr
= IDirectPlayX_EnumConnections( lpDP3A
, NULL
, cbDPCreateEnumConnections
,
5662 &cbData
, DPCONNECTION_DIRECTPLAY
);
5663 if( ( FAILED(hr
) ) ||
5664 ( cbData
.lpConn
== NULL
)
5667 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr
) );
5668 IDirectPlayX_Release( lpDP3A
);
5669 return DPERR_UNAVAILABLE
;
5672 /* Initialize the service provider */
5673 hr
= IDirectPlayX_InitializeConnection( lpDP3A
, cbData
.lpConn
, 0 );
5676 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr
) );
5677 HeapFree( GetProcessHeap(), 0, cbData
.lpConn
);
5678 IDirectPlayX_Release( lpDP3A
);
5682 /* Release our version of the interface now that we're done with it */
5683 IDirectPlayX_Release( lpDP3A
);
5684 HeapFree( GetProcessHeap(), 0, cbData
.lpConn
);