1 /* Direct Play 2,3,4 Implementation
3 * Copyright 1998,1999,2000,2001 - Peter Hunnisett
5 * <presently under construction - contact hunnise@nortelnetworks.com>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "wine/port.h"
33 #include "wine/unicode.h"
35 #include "wine/debug.h"
38 #include "dplayx_global.h"
39 #include "name_server.h"
40 #include "dplayx_queue.h"
42 #include "dplay_global.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(dplay
);
46 /* FIXME: Should this be externed? */
47 extern HRESULT DPL_CreateCompoundAddress
48 ( LPCDPCOMPOUNDADDRESSELEMENT lpElements
, DWORD dwElementCount
,
49 LPVOID lpAddress
, LPDWORD lpdwAddressSize
, BOOL bAnsiInterface
);
52 /* Local function prototypes */
53 static lpPlayerList
DP_FindPlayer( IDirectPlay2AImpl
* This
, DPID dpid
);
54 static lpPlayerData
DP_CreatePlayer( IDirectPlay2Impl
* iface
, LPDPID lpid
,
55 LPDPNAME lpName
, DWORD dwFlags
,
56 HANDLE hEvent
, BOOL bAnsi
);
57 static BOOL
DP_CopyDPNAMEStruct( LPDPNAME lpDst
, LPDPNAME lpSrc
, BOOL bAnsi
);
58 static void DP_SetPlayerData( lpPlayerData lpPData
, DWORD dwFlags
,
59 LPVOID lpData
, DWORD dwDataSize
);
61 static lpGroupData
DP_CreateGroup( IDirectPlay2AImpl
* iface
, LPDPID lpid
,
62 LPDPNAME lpName
, DWORD dwFlags
,
63 DPID idParent
, BOOL bAnsi
);
64 static void DP_SetGroupData( lpGroupData lpGData
, DWORD dwFlags
,
65 LPVOID lpData
, DWORD dwDataSize
);
66 static void DP_DeleteDPNameStruct( LPDPNAME lpDPName
);
67 static void DP_DeletePlayer( IDirectPlay2Impl
* This
, DPID dpid
);
68 static BOOL CALLBACK
cbDeletePlayerFromAllGroups( DPID dpId
,
73 static lpGroupData
DP_FindAnyGroup( IDirectPlay2AImpl
* This
, DPID dpid
);
74 static BOOL CALLBACK
cbRemoveGroupOrPlayer( DPID dpId
, DWORD dwPlayerType
,
75 LPCDPNAME lpName
, DWORD dwFlags
,
77 static void DP_DeleteGroup( IDirectPlay2Impl
* This
, DPID dpid
);
79 /* Helper methods for player/group interfaces */
80 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
81 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idGroup
,
82 DPID idPlayer
, BOOL bAnsi
);
83 static HRESULT WINAPI DP_IF_CreatePlayer
84 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, LPDPID lpidPlayer
,
85 LPDPNAME lpPlayerName
, HANDLE hEvent
, LPVOID lpData
,
86 DWORD dwDataSize
, DWORD dwFlags
, BOOL bAnsi
);
87 static HRESULT WINAPI DP_IF_DestroyGroup
88 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idGroup
, BOOL bAnsi
);
89 static HRESULT WINAPI DP_IF_DestroyPlayer
90 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idPlayer
, BOOL bAnsi
);
91 static HRESULT WINAPI DP_IF_EnumGroupPlayers
92 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPGUID lpguidInstance
,
93 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
94 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
);
95 static HRESULT WINAPI DP_IF_EnumGroups
96 ( IDirectPlay2Impl
* This
, LPGUID lpguidInstance
,
97 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
98 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
);
99 static HRESULT WINAPI DP_IF_EnumPlayers
100 ( IDirectPlay2Impl
* This
, LPGUID lpguidInstance
,
101 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
102 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
);
103 static HRESULT WINAPI DP_IF_GetGroupData
104 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPVOID lpData
,
105 LPDWORD lpdwDataSize
, DWORD dwFlags
, BOOL bAnsi
);
106 static HRESULT WINAPI DP_IF_GetGroupName
107 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPVOID lpData
,
108 LPDWORD lpdwDataSize
, BOOL bAnsi
);
109 static HRESULT WINAPI DP_IF_GetPlayerData
110 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPVOID lpData
,
111 LPDWORD lpdwDataSize
, DWORD dwFlags
, BOOL bAnsi
);
112 static HRESULT WINAPI DP_IF_GetPlayerName
113 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPVOID lpData
,
114 LPDWORD lpdwDataSize
, BOOL bAnsi
);
115 static HRESULT WINAPI DP_IF_SetGroupName
116 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPDPNAME lpGroupName
,
117 DWORD dwFlags
, BOOL bAnsi
);
118 static HRESULT WINAPI DP_IF_SetPlayerData
119 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPVOID lpData
,
120 DWORD dwDataSize
, DWORD dwFlags
, BOOL bAnsi
);
121 static HRESULT WINAPI DP_IF_SetPlayerName
122 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPDPNAME lpPlayerName
,
123 DWORD dwFlags
, BOOL bAnsi
);
124 static HRESULT WINAPI DP_IF_AddGroupToGroup
125 ( IDirectPlay3Impl
* This
, DPID idParentGroup
, DPID idGroup
);
126 static HRESULT WINAPI DP_IF_CreateGroup
127 ( IDirectPlay2AImpl
* This
, LPVOID lpMsgHdr
, LPDPID lpidGroup
,
128 LPDPNAME lpGroupName
, LPVOID lpData
, DWORD dwDataSize
,
129 DWORD dwFlags
, BOOL bAnsi
);
130 static HRESULT WINAPI DP_IF_CreateGroupInGroup
131 ( IDirectPlay3Impl
* This
, LPVOID lpMsgHdr
, DPID idParentGroup
,
132 LPDPID lpidGroup
, LPDPNAME lpGroupName
, LPVOID lpData
,
133 DWORD dwDataSize
, DWORD dwFlags
, BOOL bAnsi
);
134 static HRESULT WINAPI DP_IF_AddPlayerToGroup
135 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idGroup
,
136 DPID idPlayer
, BOOL bAnsi
);
137 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
138 ( IDirectPlay3Impl
* This
, DPID idParentGroup
, DPID idGroup
);
139 static HRESULT WINAPI DP_SetSessionDesc
140 ( IDirectPlay2Impl
* This
, LPCDPSESSIONDESC2 lpSessDesc
,
141 DWORD dwFlags
, BOOL bInitial
, BOOL bAnsi
);
142 static HRESULT WINAPI DP_SecureOpen
143 ( IDirectPlay2Impl
* This
, LPCDPSESSIONDESC2 lpsd
, DWORD dwFlags
,
144 LPCDPSECURITYDESC lpSecurity
, LPCDPCREDENTIALS lpCredentials
,
146 static HRESULT WINAPI DP_SendEx
147 ( IDirectPlay2Impl
* This
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
148 LPVOID lpData
, DWORD dwDataSize
, DWORD dwPriority
, DWORD dwTimeout
,
149 LPVOID lpContext
, LPDWORD lpdwMsgID
, BOOL bAnsi
);
150 static HRESULT WINAPI DP_IF_Receive
151 ( IDirectPlay2Impl
* This
, LPDPID lpidFrom
, LPDPID lpidTo
,
152 DWORD dwFlags
, LPVOID lpData
, LPDWORD lpdwDataSize
, BOOL bAnsi
);
153 static HRESULT WINAPI DP_IF_GetMessageQueue
154 ( IDirectPlay4Impl
* This
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
155 LPDWORD lpdwNumMsgs
, LPDWORD lpdwNumBytes
, BOOL bAnsi
);
156 static HRESULT WINAPI DP_SP_SendEx
157 ( IDirectPlay2Impl
* This
, DWORD dwFlags
,
158 LPVOID lpData
, DWORD dwDataSize
, DWORD dwPriority
, DWORD dwTimeout
,
159 LPVOID lpContext
, LPDWORD lpdwMsgID
);
160 static HRESULT WINAPI DP_IF_SetGroupData
161 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPVOID lpData
,
162 DWORD dwDataSize
, DWORD dwFlags
, BOOL bAnsi
);
163 static HRESULT WINAPI DP_IF_GetPlayerCaps
164 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPDPCAPS lpDPCaps
,
166 static HRESULT WINAPI
DP_IF_Close( IDirectPlay2Impl
* This
, BOOL bAnsi
);
167 static HRESULT WINAPI DP_IF_CancelMessage
168 ( IDirectPlay4Impl
* This
, DWORD dwMsgID
, DWORD dwFlags
,
169 DWORD dwMinPriority
, DWORD dwMaxPriority
, BOOL bAnsi
);
170 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
171 ( IDirectPlay3AImpl
* This
, DPID idGroup
, LPGUID lpguidInstance
,
172 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
173 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
);
174 static HRESULT WINAPI DP_IF_GetGroupParent
175 ( IDirectPlay3AImpl
* This
, DPID idGroup
, LPDPID lpidGroup
,
177 static HRESULT WINAPI DP_IF_GetCaps
178 ( IDirectPlay2Impl
* This
, LPDPCAPS lpDPCaps
, DWORD dwFlags
);
179 static HRESULT WINAPI DP_IF_EnumSessions
180 ( IDirectPlay2Impl
* This
, LPDPSESSIONDESC2 lpsd
, DWORD dwTimeout
,
181 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2
,
182 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
);
183 static HRESULT WINAPI DP_IF_InitializeConnection
184 ( IDirectPlay3Impl
* This
, LPVOID lpConnection
, DWORD dwFlags
, BOOL bAnsi
);
185 static BOOL CALLBACK
cbDPCreateEnumConnections( LPCGUID lpguidSP
,
186 LPVOID lpConnection
, DWORD dwConnectionSize
, LPCDPNAME lpName
,
187 DWORD dwFlags
, LPVOID lpContext
);
188 static BOOL WINAPI
DP_BuildSPCompoundAddr( LPGUID lpcSpGuid
, LPVOID
* lplpAddrBuf
,
189 LPDWORD lpdwBufSize
);
193 static inline DPID
DP_NextObjectId(void);
194 static DPID
DP_GetRemoteNextObjectId(void);
197 static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc
,
198 LPCDPSESSIONDESC2 srcSessDesc
, BOOL bAnsi
);
201 static HMODULE
DP_LoadSP( LPCGUID lpcGuid
, LPSPINITDATA lpSpData
, LPBOOL lpbIsDpSp
);
202 static HRESULT
DP_InitializeDPSP( IDirectPlay3Impl
* This
, HMODULE hServiceProvider
);
203 static HRESULT
DP_InitializeDPLSP( IDirectPlay3Impl
* This
, HMODULE hServiceProvider
);
210 #define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */
211 #define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported
212 we don't have to change much */
213 #define DPID_NAME_SERVER 0x19a9d65b /* Don't ask me why */
215 /* Strip out dwFlag values which cannot be sent in the CREATEGROUP msg */
216 #define DPMSG_CREATEGROUP_DWFLAGS(x) ( (x) & DPGROUP_HIDDEN )
218 /* Strip out all dwFlags values for CREATEPLAYER msg */
219 #define DPMSG_CREATEPLAYER_DWFLAGS(x) 0
221 static DWORD kludgePlayerGroupId
= 1000;
223 /* ------------------------------------------------------------------ */
226 static BOOL
DP_CreateIUnknown( LPVOID lpDP
)
228 ICOM_THIS(IDirectPlay2AImpl
,lpDP
);
230 This
->unk
= (DirectPlayIUnknownData
*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
231 sizeof( *(This
->unk
) ) );
232 if ( This
->unk
== NULL
)
237 InitializeCriticalSection( &This
->unk
->DP_lock
);
242 static BOOL
DP_DestroyIUnknown( LPVOID lpDP
)
244 ICOM_THIS(IDirectPlay2AImpl
,lpDP
);
246 DeleteCriticalSection( &This
->unk
->DP_lock
);
247 HeapFree( GetProcessHeap(), 0, This
->unk
);
252 static BOOL
DP_CreateDirectPlay2( LPVOID lpDP
)
254 ICOM_THIS(IDirectPlay2AImpl
,lpDP
);
256 This
->dp2
= (DirectPlay2Data
*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
257 sizeof( *(This
->dp2
) ) );
258 if ( This
->dp2
== NULL
)
263 This
->dp2
->bConnectionOpen
= FALSE
;
265 This
->dp2
->hEnumSessionThread
= INVALID_HANDLE_VALUE
;
267 This
->dp2
->bHostInterface
= FALSE
;
269 DPQ_INIT(This
->dp2
->receiveMsgs
);
270 DPQ_INIT(This
->dp2
->sendMsgs
);
271 DPQ_INIT(This
->dp2
->replysExpected
);
273 if( !NS_InitializeSessionCache( &This
->dp2
->lpNameServerData
) )
275 /* FIXME: Memory leak */
279 /* Provide an initial session desc with nothing in it */
280 This
->dp2
->lpSessionDesc
= (LPDPSESSIONDESC2
)HeapAlloc( GetProcessHeap(),
282 sizeof( *This
->dp2
->lpSessionDesc
) );
283 if( This
->dp2
->lpSessionDesc
== NULL
)
285 /* FIXME: Memory leak */
288 This
->dp2
->lpSessionDesc
->dwSize
= sizeof( *This
->dp2
->lpSessionDesc
);
290 /* We are a emulating a dp 6 implementation */
291 This
->dp2
->spData
.dwSPVersion
= DPSP_MAJORVERSION
;
293 This
->dp2
->spData
.lpCB
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
294 sizeof( *This
->dp2
->spData
.lpCB
) );
295 This
->dp2
->spData
.lpCB
->dwSize
= sizeof( *This
->dp2
->spData
.lpCB
);
296 This
->dp2
->spData
.lpCB
->dwVersion
= DPSP_MAJORVERSION
;
298 /* This is the pointer to the service provider */
299 if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP
,
300 (LPVOID
*)&This
->dp2
->spData
.lpISP
, This
) )
303 /* FIXME: Memory leak */
307 /* Setup lobby provider information */
308 This
->dp2
->dplspData
.dwSPVersion
= DPSP_MAJORVERSION
;
309 This
->dp2
->dplspData
.lpCB
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
310 sizeof( *This
->dp2
->dplspData
.lpCB
) );
311 This
->dp2
->dplspData
.lpCB
->dwSize
= sizeof( *This
->dp2
->dplspData
.lpCB
);
313 if( FAILED( DPLSP_CreateInterface( &IID_IDPLobbySP
,
314 (LPVOID
*)&This
->dp2
->dplspData
.lpISP
, This
) )
317 /* FIXME: Memory leak */
324 /* Definition of the global function in dplayx_queue.h. #
325 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
326 DPQ_DECL_DELETECB( cbDeleteElemFromHeap
, LPVOID
)
328 HeapFree( GetProcessHeap(), 0, elem
);
331 /* Function to delete the list of groups with this interface. Needs to
332 * delete the group and player lists associated with this group as well
333 * as the group data associated with this group. It should not delete
334 * player data as that is shared with the top player list and will be
337 DPQ_DECL_DELETECB( cbDeleteGroupsElem
, lpGroupList
);
338 DPQ_DECL_DELETECB( cbDeleteGroupsElem
, lpGroupList
)
340 DPQ_DELETEQ( elem
->lpGData
->groups
, groups
,
341 lpGroupList
, cbDeleteElemFromHeap
);
342 DPQ_DELETEQ( elem
->lpGData
->players
, players
,
343 lpPlayerList
, cbDeleteElemFromHeap
);
344 HeapFree( GetProcessHeap(), 0, elem
->lpGData
);
345 HeapFree( GetProcessHeap(), 0, elem
);
348 /* Function to delete the list of players with this interface. Needs to
349 * delete the player data for all players as well.
351 DPQ_DECL_DELETECB( cbDeletePlayerElem
, lpPlayerList
);
352 DPQ_DECL_DELETECB( cbDeletePlayerElem
, lpPlayerList
)
354 HeapFree( GetProcessHeap(), 0, elem
->lpPData
);
355 HeapFree( GetProcessHeap(), 0, elem
);
358 static BOOL
DP_DestroyDirectPlay2( LPVOID lpDP
)
360 ICOM_THIS(IDirectPlay2AImpl
,lpDP
);
362 if( This
->dp2
->hEnumSessionThread
!= INVALID_HANDLE_VALUE
)
364 TerminateThread( This
->dp2
->hEnumSessionThread
, 0 );
365 CloseHandle( This
->dp2
->hEnumSessionThread
);
368 /* Finish with the SP - have it shutdown */
369 if( This
->dp2
->spData
.lpCB
->ShutdownEx
)
371 DPSP_SHUTDOWNDATA data
;
373 TRACE( "Calling SP ShutdownEx\n" );
375 data
.lpISP
= This
->dp2
->spData
.lpISP
;
377 (*This
->dp2
->spData
.lpCB
->ShutdownEx
)( &data
);
379 else if (This
->dp2
->spData
.lpCB
->Shutdown
) /* obsolete interface */
381 TRACE( "Calling obsolete SP Shutdown\n" );
382 (*This
->dp2
->spData
.lpCB
->Shutdown
)();
385 /* Unload the SP (if it exists) */
386 if( This
->dp2
->hServiceProvider
!= 0 )
388 FreeLibrary( This
->dp2
->hServiceProvider
);
391 /* Unload the Lobby Provider (if it exists) */
392 if( This
->dp2
->hDPLobbyProvider
!= 0 )
394 FreeLibrary( This
->dp2
->hDPLobbyProvider
);
398 DPQ_DELETEQ( This
->dp2
->players
, players
, lpPlayerList
, cbDeletePlayerElem
);
399 DPQ_DELETEQ( This
->dp2
->groups
, groups
, lpGroupList
, cbDeleteGroupsElem
);
402 /* FIXME: Need to delete receive and send msgs queue contents */
404 NS_DeleteSessionCache( This
->dp2
->lpNameServerData
);
406 HeapFree( GetProcessHeap(), 0, This
->dp2
->lpSessionDesc
);
408 IDirectPlaySP_Release( This
->dp2
->spData
.lpISP
);
410 /* Delete the contents */
411 HeapFree( GetProcessHeap(), 0, This
->dp2
);
416 static BOOL
DP_CreateDirectPlay3( LPVOID lpDP
)
418 ICOM_THIS(IDirectPlay3AImpl
,lpDP
);
420 This
->dp3
= (DirectPlay3Data
*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
421 sizeof( *(This
->dp3
) ) );
422 if ( This
->dp3
== NULL
)
430 static BOOL
DP_DestroyDirectPlay3( LPVOID lpDP
)
432 ICOM_THIS(IDirectPlay3AImpl
,lpDP
);
434 /* Delete the contents */
435 HeapFree( GetProcessHeap(), 0, This
->dp3
);
440 static BOOL
DP_CreateDirectPlay4( LPVOID lpDP
)
442 ICOM_THIS(IDirectPlay4AImpl
,lpDP
);
444 This
->dp4
= (DirectPlay4Data
*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
445 sizeof( *(This
->dp4
) ) );
446 if ( This
->dp4
== NULL
)
454 static BOOL
DP_DestroyDirectPlay4( LPVOID lpDP
)
456 ICOM_THIS(IDirectPlay3AImpl
,lpDP
);
458 /* Delete the contents */
459 HeapFree( GetProcessHeap(), 0, This
->dp4
);
465 /* Create a new interface */
467 HRESULT DP_CreateInterface
468 ( REFIID riid
, LPVOID
* ppvObj
)
470 TRACE( " for %s\n", debugstr_guid( riid
) );
472 *ppvObj
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
473 sizeof( IDirectPlay2Impl
) );
475 if( *ppvObj
== NULL
)
477 return DPERR_OUTOFMEMORY
;
480 if( IsEqualGUID( &IID_IDirectPlay2
, riid
) )
482 ICOM_THIS(IDirectPlay2Impl
,*ppvObj
);
483 ICOM_VTBL(This
) = &directPlay2WVT
;
485 else if( IsEqualGUID( &IID_IDirectPlay2A
, riid
) )
487 ICOM_THIS(IDirectPlay2AImpl
,*ppvObj
);
488 ICOM_VTBL(This
) = &directPlay2AVT
;
490 else if( IsEqualGUID( &IID_IDirectPlay3
, riid
) )
492 ICOM_THIS(IDirectPlay3Impl
,*ppvObj
);
493 ICOM_VTBL(This
) = &directPlay3WVT
;
495 else if( IsEqualGUID( &IID_IDirectPlay3A
, riid
) )
497 ICOM_THIS(IDirectPlay3AImpl
,*ppvObj
);
498 ICOM_VTBL(This
) = &directPlay3AVT
;
500 else if( IsEqualGUID( &IID_IDirectPlay4
, riid
) )
502 ICOM_THIS(IDirectPlay4Impl
,*ppvObj
);
503 ICOM_VTBL(This
) = &directPlay4WVT
;
505 else if( IsEqualGUID( &IID_IDirectPlay4A
, riid
) )
507 ICOM_THIS(IDirectPlay4AImpl
,*ppvObj
);
508 ICOM_VTBL(This
) = &directPlay4AVT
;
512 /* Unsupported interface */
513 HeapFree( GetProcessHeap(), 0, *ppvObj
);
516 return E_NOINTERFACE
;
520 if ( DP_CreateIUnknown( *ppvObj
) &&
521 DP_CreateDirectPlay2( *ppvObj
) &&
522 DP_CreateDirectPlay3( *ppvObj
) &&
523 DP_CreateDirectPlay4( *ppvObj
)
526 IDirectPlayX_AddRef( (LPDIRECTPLAY2A
)*ppvObj
);
531 /* Initialize failed, destroy it */
532 DP_DestroyDirectPlay4( *ppvObj
);
533 DP_DestroyDirectPlay3( *ppvObj
);
534 DP_DestroyDirectPlay2( *ppvObj
);
535 DP_DestroyIUnknown( *ppvObj
);
537 HeapFree( GetProcessHeap(), 0, *ppvObj
);
540 return DPERR_NOMEMORY
;
544 /* Direct Play methods */
546 /* Shared between all dplay types */
547 static HRESULT WINAPI DP_QueryInterface
548 ( LPDIRECTPLAY2 iface
, REFIID riid
, LPVOID
* ppvObj
)
550 ICOM_THIS(IDirectPlay2Impl
,iface
);
551 TRACE("(%p)->(%s,%p)\n", This
, debugstr_guid( riid
), ppvObj
);
553 *ppvObj
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
556 if( *ppvObj
== NULL
)
558 return DPERR_OUTOFMEMORY
;
561 CopyMemory( *ppvObj
, This
, sizeof( *This
) );
562 (*(IDirectPlay2Impl
**)ppvObj
)->ulInterfaceRef
= 0;
564 if( IsEqualGUID( &IID_IDirectPlay2
, riid
) )
566 ICOM_THIS(IDirectPlay2Impl
,*ppvObj
);
567 ICOM_VTBL(This
) = &directPlay2WVT
;
569 else if( IsEqualGUID( &IID_IDirectPlay2A
, riid
) )
571 ICOM_THIS(IDirectPlay2AImpl
,*ppvObj
);
572 ICOM_VTBL(This
) = &directPlay2AVT
;
574 else if( IsEqualGUID( &IID_IDirectPlay3
, riid
) )
576 ICOM_THIS(IDirectPlay3Impl
,*ppvObj
);
577 ICOM_VTBL(This
) = &directPlay3WVT
;
579 else if( IsEqualGUID( &IID_IDirectPlay3A
, riid
) )
581 ICOM_THIS(IDirectPlay3AImpl
,*ppvObj
);
582 ICOM_VTBL(This
) = &directPlay3AVT
;
584 else if( IsEqualGUID( &IID_IDirectPlay4
, riid
) )
586 ICOM_THIS(IDirectPlay4Impl
,*ppvObj
);
587 ICOM_VTBL(This
) = &directPlay4WVT
;
589 else if( IsEqualGUID( &IID_IDirectPlay4A
, riid
) )
591 ICOM_THIS(IDirectPlay4AImpl
,*ppvObj
);
592 ICOM_VTBL(This
) = &directPlay4AVT
;
596 /* Unsupported interface */
597 HeapFree( GetProcessHeap(), 0, *ppvObj
);
600 return E_NOINTERFACE
;
603 IDirectPlayX_AddRef( (LPDIRECTPLAY2
)*ppvObj
);
608 /* Shared between all dplay types */
609 static ULONG WINAPI DP_AddRef
610 ( LPDIRECTPLAY3 iface
)
612 ULONG ulInterfaceRefCount
, ulObjRefCount
;
613 ICOM_THIS(IDirectPlay3Impl
,iface
);
615 ulObjRefCount
= InterlockedIncrement( &This
->unk
->ulObjRef
);
616 ulInterfaceRefCount
= InterlockedIncrement( &This
->ulInterfaceRef
);
618 TRACE( "ref count incremented to %lu:%lu for %p\n",
619 ulInterfaceRefCount
, ulObjRefCount
, This
);
621 return ulObjRefCount
;
624 static ULONG WINAPI DP_Release
625 ( LPDIRECTPLAY3 iface
)
627 ULONG ulInterfaceRefCount
, ulObjRefCount
;
629 ICOM_THIS(IDirectPlay3Impl
,iface
);
631 ulObjRefCount
= InterlockedDecrement( &This
->unk
->ulObjRef
);
632 ulInterfaceRefCount
= InterlockedDecrement( &This
->ulInterfaceRef
);
634 TRACE( "ref count decremented to %lu:%lu for %p\n",
635 ulInterfaceRefCount
, ulObjRefCount
, This
);
637 /* Deallocate if this is the last reference to the object */
638 if( ulObjRefCount
== 0 )
640 /* If we're destroying the object, this must be the last ref
641 of the last interface */
642 DP_DestroyDirectPlay4( This
);
643 DP_DestroyDirectPlay3( This
);
644 DP_DestroyDirectPlay2( This
);
645 DP_DestroyIUnknown( This
);
648 /* Deallocate the interface */
649 if( ulInterfaceRefCount
== 0 )
651 HeapFree( GetProcessHeap(), 0, This
);
654 return ulObjRefCount
;
657 static inline DPID
DP_NextObjectId(void)
659 return (DPID
)InterlockedIncrement( &kludgePlayerGroupId
);
662 /* *lplpReply will be non NULL iff there is something to reply */
663 HRESULT
DP_HandleMessage( IDirectPlay2Impl
* This
, LPCVOID lpcMessageBody
,
664 DWORD dwMessageBodySize
, LPCVOID lpcMessageHeader
,
665 WORD wCommandId
, WORD wVersion
,
666 LPVOID
* lplpReply
, LPDWORD lpdwMsgSize
)
668 TRACE( "(%p)->(%p,0x%08lx,%p,%u,%u)\n",
669 This
, lpcMessageBody
, dwMessageBodySize
, lpcMessageHeader
, wCommandId
,
674 /* Name server needs to handle this request */
675 case DPMSGCMD_ENUMSESSIONSREQUEST
:
678 NS_ReplyToEnumSessionsRequest( lpcMessageBody
, lplpReply
, lpdwMsgSize
, This
);
683 /* Name server needs to handle this request */
684 case DPMSGCMD_ENUMSESSIONSREPLY
:
686 /* No reply expected */
687 NS_AddRemoteComputerAsNameServer( lpcMessageHeader
,
688 This
->dp2
->spData
.dwSPHeaderSize
,
689 (LPDPMSG_ENUMSESSIONSREPLY
)lpcMessageBody
,
690 This
->dp2
->lpNameServerData
);
694 case DPMSGCMD_REQUESTNEWPLAYERID
:
696 LPCDPMSG_REQUESTNEWPLAYERID lpcMsg
=
697 (LPCDPMSG_REQUESTNEWPLAYERID
)lpcMessageBody
;
699 LPDPMSG_NEWPLAYERIDREPLY lpReply
;
701 *lpdwMsgSize
= This
->dp2
->spData
.dwSPHeaderSize
+ sizeof( *lpReply
);
703 *lplpReply
= (LPDPMSG_NEWPLAYERIDREPLY
)HeapAlloc( GetProcessHeap(),
707 FIXME( "Ignoring dwFlags 0x%08lx in request msg\n",
710 /* Setup the reply */
711 lpReply
= (LPDPMSG_NEWPLAYERIDREPLY
)( (BYTE
*)(*lplpReply
) +
712 This
->dp2
->spData
.dwSPHeaderSize
);
714 lpReply
->envelope
.dwMagic
= DPMSGMAGIC_DPLAYMSG
;
715 lpReply
->envelope
.wCommandId
= DPMSGCMD_NEWPLAYERIDREPLY
;
716 lpReply
->envelope
.wVersion
= DPMSGVER_DP6
;
718 lpReply
->dpidNewPlayerId
= DP_NextObjectId();
720 TRACE( "Allocating new playerid 0x%08lx from remote request\n",
721 lpReply
->dpidNewPlayerId
);
726 case DPMSGCMD_GETNAMETABLEREPLY
:
727 case DPMSGCMD_NEWPLAYERIDREPLY
:
731 if( wCommandId
== DPMSGCMD_NEWPLAYERIDREPLY
)
734 DP_MSG_ReplyReceived( This
, wCommandId
, lpcMessageBody
, dwMessageBodySize
);
740 case DPMSGCMD_JUSTENVELOPE
:
742 TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08lx\n", lpcMessageHeader
, ((LPDWORD
)lpcMessageHeader
)[1] );
743 NS_SetLocalAddr( This
->dp2
->lpNameServerData
, lpcMessageHeader
, 20 );
744 DP_MSG_ReplyReceived( This
, wCommandId
, lpcMessageBody
, dwMessageBodySize
);
748 case DPMSGCMD_FORWARDADDPLAYER
:
754 TRACE( "Sending message to self to get my addr\n" );
755 DP_MSG_ToSelf( This
, 1 ); /* This is a hack right now */
760 case DPMSGCMD_FORWARDADDPLAYERNACK
:
762 DP_MSG_ErrorReceived( This
, wCommandId
, lpcMessageBody
, dwMessageBodySize
);
768 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId
);
774 /* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */
780 static HRESULT WINAPI DP_IF_AddPlayerToGroup
781 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idGroup
,
782 DPID idPlayer
, BOOL bAnsi
)
785 lpPlayerList lpPList
;
786 lpPlayerList lpNewPList
;
788 TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
789 This
, lpMsgHdr
, idGroup
, idPlayer
, bAnsi
);
792 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
794 return DPERR_INVALIDGROUP
;
797 /* Find the player */
798 if( ( lpPList
= DP_FindPlayer( This
, idPlayer
) ) == NULL
)
800 return DPERR_INVALIDPLAYER
;
803 /* Create a player list (ie "shortcut" ) */
804 lpNewPList
= (lpPlayerList
)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
805 sizeof( *lpNewPList
) );
806 if( lpNewPList
== NULL
)
808 return DPERR_CANTADDPLAYER
;
811 /* Add the shortcut */
812 lpPList
->lpPData
->uRef
++;
813 lpNewPList
->lpPData
= lpPList
->lpPData
;
815 /* Add the player to the list of players for this group */
816 DPQ_INSERT(lpGData
->players
,lpNewPList
,players
);
818 /* Let the SP know that we've added a player to the group */
819 if( This
->dp2
->spData
.lpCB
->AddPlayerToGroup
)
821 DPSP_ADDPLAYERTOGROUPDATA data
;
823 TRACE( "Calling SP AddPlayerToGroup\n" );
825 data
.idPlayer
= idPlayer
;
826 data
.idGroup
= idGroup
;
827 data
.lpISP
= This
->dp2
->spData
.lpISP
;
829 (*This
->dp2
->spData
.lpCB
->AddPlayerToGroup
)( &data
);
832 /* Inform all other peers of the addition of player to the group. If there are
833 * no peers keep this event quiet.
834 * Also, if this event was the result of another machine sending it to us,
835 * don't bother rebroadcasting it.
837 if( ( lpMsgHdr
== NULL
) &&
838 This
->dp2
->lpSessionDesc
&&
839 ( This
->dp2
->lpSessionDesc
->dwFlags
& DPSESSION_MULTICASTSERVER
) )
841 DPMSG_ADDPLAYERTOGROUP msg
;
842 msg
.dwType
= DPSYS_ADDPLAYERTOGROUP
;
844 msg
.dpIdGroup
= idGroup
;
845 msg
.dpIdPlayer
= idPlayer
;
847 /* FIXME: Correct to just use send effectively? */
848 /* FIXME: Should size include data w/ message or just message "header" */
849 /* FIXME: Check return code */
850 DP_SendEx( This
, DPID_SERVERPLAYER
, DPID_ALLPLAYERS
, 0, &msg
, sizeof( msg
), 0, 0, NULL
, NULL
, bAnsi
);
856 static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
857 ( LPDIRECTPLAY2A iface
, DPID idGroup
, DPID idPlayer
)
859 ICOM_THIS(IDirectPlay2Impl
,iface
);
860 return DP_IF_AddPlayerToGroup( This
, NULL
, idGroup
, idPlayer
, TRUE
);
863 static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
864 ( LPDIRECTPLAY2 iface
, DPID idGroup
, DPID idPlayer
)
866 ICOM_THIS(IDirectPlay2Impl
,iface
);
867 return DP_IF_AddPlayerToGroup( This
, NULL
, idGroup
, idPlayer
, FALSE
);
870 static HRESULT WINAPI
DP_IF_Close( IDirectPlay2Impl
* This
, BOOL bAnsi
)
874 TRACE("(%p)->(%u)\n", This
, bAnsi
);
876 /* FIXME: Need to find a new host I assume (how?) */
877 /* FIXME: Need to destroy all local groups */
878 /* FIXME: Need to migrate all remotely visible players to the new host */
880 /* Invoke the SP callback to inform of session close */
881 if( This
->dp2
->spData
.lpCB
->CloseEx
)
885 TRACE( "Calling SP CloseEx\n" );
887 data
.lpISP
= This
->dp2
->spData
.lpISP
;
889 hr
= (*This
->dp2
->spData
.lpCB
->CloseEx
)( &data
);
892 else if ( This
->dp2
->spData
.lpCB
->Close
) /* Try obsolete version */
894 TRACE( "Calling SP Close (obsolete interface)\n" );
896 hr
= (*This
->dp2
->spData
.lpCB
->Close
)();
902 static HRESULT WINAPI DirectPlay2AImpl_Close
903 ( LPDIRECTPLAY2A iface
)
905 ICOM_THIS(IDirectPlay2Impl
,iface
);
906 return DP_IF_Close( This
, TRUE
);
909 static HRESULT WINAPI DirectPlay2WImpl_Close
910 ( LPDIRECTPLAY2 iface
)
912 ICOM_THIS(IDirectPlay2Impl
,iface
);
913 return DP_IF_Close( This
, FALSE
);
917 lpGroupData
DP_CreateGroup( IDirectPlay2AImpl
* This
, LPDPID lpid
,
918 LPDPNAME lpName
, DWORD dwFlags
,
919 DPID idParent
, BOOL bAnsi
)
923 /* Allocate the new space and add to end of high level group list */
924 lpGData
= (lpGroupData
) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
925 sizeof( *lpGData
) );
927 if( lpGData
== NULL
)
932 DPQ_INIT(lpGData
->groups
);
933 DPQ_INIT(lpGData
->players
);
935 /* Set the desired player ID - no sanity checking to see if it exists */
936 lpGData
->dpid
= *lpid
;
938 DP_CopyDPNAMEStruct( &lpGData
->name
, lpName
, bAnsi
);
940 /* FIXME: Should we check that the parent exists? */
941 lpGData
->parent
= idParent
;
943 /* FIXME: Should we validate the dwFlags? */
944 lpGData
->dwFlags
= dwFlags
;
946 TRACE( "Created group id 0x%08lx\n", *lpid
);
951 /* This method assumes that all links to it are already deleted */
953 DP_DeleteGroup( IDirectPlay2Impl
* This
, DPID dpid
)
957 TRACE( "(%p)->(0x%08lx)\n", This
, dpid
);
959 DPQ_REMOVE_ENTRY( This
->dp2
->lpSysGroup
->groups
, groups
, lpGData
->dpid
, ==, dpid
, lpGList
);
961 if( lpGList
== NULL
)
963 ERR( "DPID 0x%08lx not found\n", dpid
);
967 if( --(lpGList
->lpGData
->uRef
) )
969 FIXME( "Why is this not the last reference to group?\n" );
974 DP_DeleteDPNameStruct( &lpGList
->lpGData
->name
);
975 HeapFree( GetProcessHeap(), 0, lpGList
->lpGData
);
977 /* Remove and Delete Player List object */
978 HeapFree( GetProcessHeap(), 0, lpGList
);
982 static lpGroupData
DP_FindAnyGroup( IDirectPlay2AImpl
* This
, DPID dpid
)
984 lpGroupList lpGroups
;
986 TRACE( "(%p)->(0x%08lx)\n", This
, dpid
);
988 if( dpid
== DPID_SYSTEM_GROUP
)
990 return This
->dp2
->lpSysGroup
;
994 DPQ_FIND_ENTRY( This
->dp2
->lpSysGroup
->groups
, groups
, lpGData
->dpid
, ==, dpid
, lpGroups
);
997 if( lpGroups
== NULL
)
1002 return lpGroups
->lpGData
;
1005 static HRESULT WINAPI DP_IF_CreateGroup
1006 ( IDirectPlay2AImpl
* This
, LPVOID lpMsgHdr
, LPDPID lpidGroup
,
1007 LPDPNAME lpGroupName
, LPVOID lpData
, DWORD dwDataSize
,
1008 DWORD dwFlags
, BOOL bAnsi
)
1010 lpGroupData lpGData
;
1012 TRACE( "(%p)->(%p,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
1013 This
, lpMsgHdr
, lpidGroup
, lpGroupName
, lpData
, dwDataSize
,
1016 /* If the name is not specified, we must provide one */
1017 if( DPID_UNKNOWN
== *lpidGroup
)
1019 /* If we are the name server, we decide on the group ids. If not, we
1020 * must ask for one before attempting a creation.
1022 if( This
->dp2
->bHostInterface
)
1024 *lpidGroup
= DP_NextObjectId();
1028 *lpidGroup
= DP_GetRemoteNextObjectId();
1032 lpGData
= DP_CreateGroup( This
, lpidGroup
, lpGroupName
, dwFlags
,
1033 DPID_NOPARENT_GROUP
, bAnsi
);
1035 if( lpGData
== NULL
)
1037 return DPERR_CANTADDPLAYER
; /* yes player not group */
1040 if( DPID_SYSTEM_GROUP
== *lpidGroup
)
1042 This
->dp2
->lpSysGroup
= lpGData
;
1043 TRACE( "Inserting system group\n" );
1047 /* Insert into the system group */
1048 lpGroupList lpGroup
= (lpGroupList
) HeapAlloc( GetProcessHeap(),
1050 sizeof( *lpGroup
) );
1051 lpGroup
->lpGData
= lpGData
;
1053 DPQ_INSERT( This
->dp2
->lpSysGroup
->groups
, lpGroup
, groups
);
1056 /* Something is now referencing this data */
1059 /* Set all the important stuff for the group */
1060 DP_SetGroupData( lpGData
, DPSET_REMOTE
, lpData
, dwDataSize
);
1062 /* FIXME: We should only create the system group if GetCaps returns
1063 * DPCAPS_GROUPOPTIMIZED.
1066 /* Let the SP know that we've created this group */
1067 if( This
->dp2
->spData
.lpCB
->CreateGroup
)
1069 DPSP_CREATEGROUPDATA data
;
1070 DWORD dwCreateFlags
= 0;
1072 TRACE( "Calling SP CreateGroup\n" );
1074 if( *lpidGroup
== DPID_NOPARENT_GROUP
)
1075 dwCreateFlags
|= DPLAYI_GROUP_SYSGROUP
;
1077 if( lpMsgHdr
== NULL
)
1078 dwCreateFlags
|= DPLAYI_PLAYER_PLAYERLOCAL
;
1080 if( dwFlags
& DPGROUP_HIDDEN
)
1081 dwCreateFlags
|= DPLAYI_GROUP_HIDDEN
;
1083 data
.idGroup
= *lpidGroup
;
1084 data
.dwFlags
= dwCreateFlags
;
1085 data
.lpSPMessageHeader
= lpMsgHdr
;
1086 data
.lpISP
= This
->dp2
->spData
.lpISP
;
1088 (*This
->dp2
->spData
.lpCB
->CreateGroup
)( &data
);
1091 /* Inform all other peers of the creation of a new group. If there are
1092 * no peers keep this event quiet.
1093 * Also if this message was sent to us, don't rebroadcast.
1095 if( ( lpMsgHdr
== NULL
) &&
1096 This
->dp2
->lpSessionDesc
&&
1097 ( This
->dp2
->lpSessionDesc
->dwFlags
& DPSESSION_MULTICASTSERVER
) )
1099 DPMSG_CREATEPLAYERORGROUP msg
;
1100 msg
.dwType
= DPSYS_CREATEPLAYERORGROUP
;
1102 msg
.dwPlayerType
= DPPLAYERTYPE_GROUP
;
1103 msg
.dpId
= *lpidGroup
;
1104 msg
.dwCurrentPlayers
= 0; /* FIXME: Incorrect? */
1105 msg
.lpData
= lpData
;
1106 msg
.dwDataSize
= dwDataSize
;
1107 msg
.dpnName
= *lpGroupName
;
1108 msg
.dpIdParent
= DPID_NOPARENT_GROUP
;
1109 msg
.dwFlags
= DPMSG_CREATEGROUP_DWFLAGS( dwFlags
);
1111 /* FIXME: Correct to just use send effectively? */
1112 /* FIXME: Should size include data w/ message or just message "header" */
1113 /* FIXME: Check return code */
1114 DP_SendEx( This
, DPID_SERVERPLAYER
, DPID_ALLPLAYERS
, 0, &msg
, sizeof( msg
),
1115 0, 0, NULL
, NULL
, bAnsi
);
1121 static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
1122 ( LPDIRECTPLAY2A iface
, LPDPID lpidGroup
, LPDPNAME lpGroupName
,
1123 LPVOID lpData
, DWORD dwDataSize
, DWORD dwFlags
)
1125 *lpidGroup
= DPID_UNKNOWN
;
1127 return DP_IF_CreateGroup( (IDirectPlay2AImpl
*)iface
, NULL
, lpidGroup
,
1128 lpGroupName
, lpData
, dwDataSize
, dwFlags
, TRUE
);
1131 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
1132 ( LPDIRECTPLAY2 iface
, LPDPID lpidGroup
, LPDPNAME lpGroupName
,
1133 LPVOID lpData
, DWORD dwDataSize
, DWORD dwFlags
)
1135 *lpidGroup
= DPID_UNKNOWN
;
1137 return DP_IF_CreateGroup( (IDirectPlay2AImpl
*)iface
, NULL
, lpidGroup
,
1138 lpGroupName
, lpData
, dwDataSize
, dwFlags
, FALSE
);
1143 DP_SetGroupData( lpGroupData lpGData
, DWORD dwFlags
,
1144 LPVOID lpData
, DWORD dwDataSize
)
1146 /* Clear out the data with this player */
1147 if( ( dwFlags
& DPSET_LOCAL
) &&
1148 ( lpGData
->dwLocalDataSize
!= 0 )
1151 HeapFree( GetProcessHeap(), 0, lpGData
->lpLocalData
);
1152 lpGData
->lpLocalData
= NULL
;
1153 lpGData
->dwLocalDataSize
= 0;
1155 if( ( dwFlags
& DPSET_REMOTE
) &&
1156 ( lpGData
->dwRemoteDataSize
!= 0 )
1159 HeapFree( GetProcessHeap(), 0, lpGData
->lpRemoteData
);
1160 lpGData
->lpRemoteData
= NULL
;
1161 lpGData
->dwRemoteDataSize
= 0;
1164 /* Reallocate for new data */
1165 if( lpData
!= NULL
)
1167 LPVOID lpNewData
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
1168 sizeof( dwDataSize
) );
1169 CopyMemory( lpNewData
, lpData
, dwDataSize
);
1171 if( dwFlags
& DPSET_REMOTE
)
1173 lpGData
->lpRemoteData
= lpNewData
;
1174 lpGData
->dwRemoteDataSize
= dwDataSize
;
1177 if( dwFlags
& DPSET_LOCAL
)
1179 lpGData
->lpLocalData
= lpData
;
1180 lpGData
->dwLocalDataSize
= dwDataSize
;
1186 /* This function will just create the storage for the new player. */
1188 lpPlayerData
DP_CreatePlayer( IDirectPlay2Impl
* This
, LPDPID lpid
,
1189 LPDPNAME lpName
, DWORD dwFlags
,
1190 HANDLE hEvent
, BOOL bAnsi
)
1192 lpPlayerData lpPData
;
1194 TRACE( "(%p)->(%p,%p,%u)\n", This
, lpid
, lpName
, bAnsi
);
1196 /* Allocate the storage for the player and associate it with list element */
1197 lpPData
= (lpPlayerData
) HeapAlloc( GetProcessHeap(),
1199 sizeof( *lpPData
) );
1200 if( lpPData
== NULL
)
1205 /* Set the desired player ID */
1206 lpPData
->dpid
= *lpid
;
1208 DP_CopyDPNAMEStruct( &lpPData
->name
, lpName
, bAnsi
);
1210 lpPData
->dwFlags
= dwFlags
;
1212 /* If we were given an event handle, duplicate it */
1215 if( !DuplicateHandle( GetCurrentProcess(), hEvent
,
1216 GetCurrentProcess(), &lpPData
->hEvent
,
1217 0, FALSE
, DUPLICATE_SAME_ACCESS
)
1220 /* FIXME: Memory leak */
1221 ERR( "Can't duplicate player msg handle %x\n", hEvent
);
1225 /* Initialize the SP data section */
1226 lpPData
->lpSPPlayerData
= DPSP_CreateSPPlayerData();
1228 TRACE( "Created player id 0x%08lx\n", *lpid
);
1233 /* Delete the contents of the DPNAME struct */
1235 DP_DeleteDPNameStruct( LPDPNAME lpDPName
)
1237 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY
, lpDPName
->u1
.lpszShortNameA
);
1238 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY
, lpDPName
->u2
.lpszLongNameA
);
1241 /* This method assumes that all links to it are already deleted */
1243 DP_DeletePlayer( IDirectPlay2Impl
* This
, DPID dpid
)
1245 lpPlayerList lpPList
;
1247 TRACE( "(%p)->(0x%08lx)\n", This
, dpid
);
1249 DPQ_REMOVE_ENTRY( This
->dp2
->lpSysGroup
->players
, players
, lpPData
->dpid
, ==, dpid
, lpPList
);
1251 if( lpPList
== NULL
)
1253 ERR( "DPID 0x%08lx not found\n", dpid
);
1257 /* Verify that this is the last reference to the data */
1258 if( --(lpPList
->lpPData
->uRef
) )
1260 FIXME( "Why is this not the last reference to player?\n" );
1265 DP_DeleteDPNameStruct( &lpPList
->lpPData
->name
);
1267 CloseHandle( lpPList
->lpPData
->hEvent
);
1268 HeapFree( GetProcessHeap(), 0, lpPList
->lpPData
);
1270 /* Delete Player List object */
1271 HeapFree( GetProcessHeap(), 0, lpPList
);
1274 static lpPlayerList
DP_FindPlayer( IDirectPlay2AImpl
* This
, DPID dpid
)
1276 lpPlayerList lpPlayers
;
1278 TRACE( "(%p)->(0x%08lx)\n", This
, dpid
);
1280 DPQ_FIND_ENTRY( This
->dp2
->lpSysGroup
->players
, players
, lpPData
->dpid
, ==, dpid
, lpPlayers
);
1285 /* Basic area for Dst must already be allocated */
1286 static BOOL
DP_CopyDPNAMEStruct( LPDPNAME lpDst
, LPDPNAME lpSrc
, BOOL bAnsi
)
1290 ZeroMemory( lpDst
, sizeof( *lpDst
) );
1291 lpDst
->dwSize
= sizeof( *lpDst
);
1295 if( lpSrc
->dwSize
!= sizeof( *lpSrc
) )
1300 /* Delete any existing pointers */
1301 if( lpDst
->u1
.lpszShortNameA
)
1303 HeapFree( GetProcessHeap(), 0, lpDst
->u1
.lpszShortNameA
);
1306 if( lpDst
->u2
.lpszLongNameA
)
1308 HeapFree( GetProcessHeap(), 0, lpDst
->u1
.lpszShortNameA
);
1311 /* Copy as required */
1312 CopyMemory( lpDst
, lpSrc
, lpSrc
->dwSize
);
1316 if( lpSrc
->u1
.lpszShortNameA
)
1318 lpDst
->u1
.lpszShortNameA
= HeapAlloc( GetProcessHeap(), 0,
1319 strlen(lpSrc
->u1
.lpszShortNameA
)+1 );
1320 strcpy( lpDst
->u1
.lpszShortNameA
, lpSrc
->u1
.lpszShortNameA
);
1322 if( lpSrc
->u2
.lpszLongNameA
)
1324 lpDst
->u2
.lpszLongNameA
= HeapAlloc( GetProcessHeap(), 0,
1325 strlen(lpSrc
->u2
.lpszLongNameA
)+1 );
1326 strcpy( lpDst
->u2
.lpszLongNameA
, lpSrc
->u2
.lpszLongNameA
);
1331 if( lpSrc
->u1
.lpszShortNameA
)
1333 lpDst
->u1
.lpszShortName
= HeapAlloc( GetProcessHeap(), 0,
1334 (strlenW(lpSrc
->u1
.lpszShortName
)+1)*sizeof(WCHAR
) );
1335 strcpyW( lpDst
->u1
.lpszShortName
, lpSrc
->u1
.lpszShortName
);
1337 if( lpSrc
->u2
.lpszLongNameA
)
1339 lpDst
->u2
.lpszLongName
= HeapAlloc( GetProcessHeap(), 0,
1340 (strlenW(lpSrc
->u2
.lpszLongName
)+1)*sizeof(WCHAR
) );
1341 strcpyW( lpDst
->u2
.lpszLongName
, lpSrc
->u2
.lpszLongName
);
1349 DP_SetPlayerData( lpPlayerData lpPData
, DWORD dwFlags
,
1350 LPVOID lpData
, DWORD dwDataSize
)
1352 /* Clear out the data with this player */
1353 if( ( dwFlags
& DPSET_LOCAL
) &&
1354 ( lpPData
->dwLocalDataSize
!= 0 )
1357 HeapFree( GetProcessHeap(), 0, lpPData
->lpLocalData
);
1358 lpPData
->lpLocalData
= NULL
;
1359 lpPData
->dwLocalDataSize
= 0;
1361 if( ( dwFlags
& DPSET_REMOTE
) &&
1362 ( lpPData
->dwRemoteDataSize
!= 0 )
1365 HeapFree( GetProcessHeap(), 0, lpPData
->lpRemoteData
);
1366 lpPData
->lpRemoteData
= NULL
;
1367 lpPData
->dwRemoteDataSize
= 0;
1370 /* Reallocate for new data */
1371 if( lpData
!= NULL
)
1373 LPVOID lpNewData
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
1374 sizeof( dwDataSize
) );
1375 CopyMemory( lpNewData
, lpData
, dwDataSize
);
1377 if( dwFlags
& DPSET_REMOTE
)
1379 lpPData
->lpRemoteData
= lpNewData
;
1380 lpPData
->dwRemoteDataSize
= dwDataSize
;
1383 if( dwFlags
& DPSET_LOCAL
)
1385 lpPData
->lpLocalData
= lpData
;
1386 lpPData
->dwLocalDataSize
= dwDataSize
;
1392 static HRESULT WINAPI DP_IF_CreatePlayer
1393 ( IDirectPlay2Impl
* This
,
1394 LPVOID lpMsgHdr
, /* NULL for local creation, non NULL for remote creation */
1396 LPDPNAME lpPlayerName
,
1404 lpPlayerData lpPData
;
1405 lpPlayerList lpPList
;
1406 DWORD dwCreateFlags
= 0;
1408 TRACE( "(%p)->(%p,%p,%d,%p,0x%08lx,0x%08lx,%u)\n",
1409 This
, lpidPlayer
, lpPlayerName
, hEvent
, lpData
,
1410 dwDataSize
, dwFlags
, bAnsi
);
1414 dwFlags
= DPPLAYER_SPECTATOR
;
1417 if( lpidPlayer
== NULL
)
1419 return DPERR_INVALIDPARAMS
;
1423 /* Determine the creation flags for the player. These will be passed
1424 * to the name server if requesting a player id and to the SP when
1425 * informing it of the player creation
1428 if( dwFlags
& DPPLAYER_SERVERPLAYER
)
1430 if( *lpidPlayer
== DPID_SERVERPLAYER
)
1432 /* Server player for the host interface */
1433 dwCreateFlags
|= DPLAYI_PLAYER_APPSERVER
;
1435 else if( *lpidPlayer
== DPID_NAME_SERVER
)
1437 /* Name server - master of everything */
1438 dwCreateFlags
|= (DPLAYI_PLAYER_NAMESRVR
|DPLAYI_PLAYER_SYSPLAYER
);
1442 /* Server player for a non host interface */
1443 dwCreateFlags
|= DPLAYI_PLAYER_SYSPLAYER
;
1447 if( lpMsgHdr
== NULL
)
1448 dwCreateFlags
|= DPLAYI_PLAYER_PLAYERLOCAL
;
1451 /* Verify we know how to handle all the flags */
1452 if( !( ( dwFlags
& DPPLAYER_SERVERPLAYER
) ||
1453 ( dwFlags
& DPPLAYER_SPECTATOR
)
1457 /* Assume non fatal failure */
1458 ERR( "unknown dwFlags = 0x%08lx\n", dwFlags
);
1461 /* If the name is not specified, we must provide one */
1462 if( *lpidPlayer
== DPID_UNKNOWN
)
1464 /* If we are the session master, we dish out the group/player ids */
1465 if( This
->dp2
->bHostInterface
)
1467 *lpidPlayer
= DP_NextObjectId();
1471 hr
= DP_MSG_SendRequestPlayerId( This
, dwCreateFlags
, lpidPlayer
);
1475 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr
) );
1482 /* FIXME: Would be nice to perhaps verify that we don't already have
1487 /* FIXME: Should we be storing these dwFlags or the creation ones? */
1488 lpPData
= DP_CreatePlayer( This
, lpidPlayer
, lpPlayerName
, dwFlags
,
1491 if( lpPData
== NULL
)
1493 return DPERR_CANTADDPLAYER
;
1496 /* Create the list object and link it in */
1497 lpPList
= (lpPlayerList
)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
1498 sizeof( *lpPList
) );
1499 if( lpPList
== NULL
)
1501 FIXME( "Memory leak\n" );
1502 return DPERR_CANTADDPLAYER
;
1506 lpPList
->lpPData
= lpPData
;
1508 /* Add the player to the system group */
1509 DPQ_INSERT( This
->dp2
->lpSysGroup
->players
, lpPList
, players
);
1511 /* Update the information and send it to all players in the session */
1512 DP_SetPlayerData( lpPData
, DPSET_REMOTE
, lpData
, dwDataSize
);
1514 /* Let the SP know that we've created this player */
1515 if( This
->dp2
->spData
.lpCB
->CreatePlayer
)
1517 DPSP_CREATEPLAYERDATA data
;
1519 data
.idPlayer
= *lpidPlayer
;
1520 data
.dwFlags
= dwCreateFlags
;
1521 data
.lpSPMessageHeader
= lpMsgHdr
;
1522 data
.lpISP
= This
->dp2
->spData
.lpISP
;
1524 TRACE( "Calling SP CreatePlayer 0x%08lx: dwFlags: 0x%08lx lpMsgHdr: %p\n",
1525 *lpidPlayer
, data
.dwFlags
, data
.lpSPMessageHeader
);
1527 hr
= (*This
->dp2
->spData
.lpCB
->CreatePlayer
)( &data
);
1532 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr
) );
1536 /* Now let the SP know that this player is a member of the system group */
1537 if( This
->dp2
->spData
.lpCB
->AddPlayerToGroup
)
1539 DPSP_ADDPLAYERTOGROUPDATA data
;
1541 data
.idPlayer
= *lpidPlayer
;
1542 data
.idGroup
= DPID_SYSTEM_GROUP
;
1543 data
.lpISP
= This
->dp2
->spData
.lpISP
;
1545 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1547 hr
= (*This
->dp2
->spData
.lpCB
->AddPlayerToGroup
)( &data
);
1552 ERR( "Failed to add player to sys group with sp: %s\n",
1553 DPLAYX_HresultToString(hr
) );
1558 if( This
->dp2
->bHostInterface
== FALSE
)
1560 /* Let the name server know about the creation of this player */
1561 /* FIXME: Is this only to be done for the creation of a server player or
1562 * is this used for regular players? If only for server players, move
1563 * this call to DP_SecureOpen(...);
1566 TRACE( "Sending message to self to get my addr\n" );
1567 DP_MSG_ToSelf( This
, *lpidPlayer
); /* This is a hack right now */
1570 hr
= DP_MSG_ForwardPlayerCreation( This
, *lpidPlayer
);
1573 /* Inform all other peers of the creation of a new player. If there are
1574 * no peers keep this quiet.
1575 * Also, if this was a remote event, no need to rebroadcast it.
1577 if( ( lpMsgHdr
== NULL
) &&
1578 This
->dp2
->lpSessionDesc
&&
1579 ( This
->dp2
->lpSessionDesc
->dwFlags
& DPSESSION_MULTICASTSERVER
) )
1581 DPMSG_CREATEPLAYERORGROUP msg
;
1582 msg
.dwType
= DPSYS_CREATEPLAYERORGROUP
;
1584 msg
.dwPlayerType
= DPPLAYERTYPE_PLAYER
;
1585 msg
.dpId
= *lpidPlayer
;
1586 msg
.dwCurrentPlayers
= 0; /* FIXME: Incorrect */
1587 msg
.lpData
= lpData
;
1588 msg
.dwDataSize
= dwDataSize
;
1589 msg
.dpnName
= *lpPlayerName
;
1590 msg
.dpIdParent
= DPID_NOPARENT_GROUP
;
1591 msg
.dwFlags
= DPMSG_CREATEPLAYER_DWFLAGS( dwFlags
);
1593 /* FIXME: Correct to just use send effectively? */
1594 /* FIXME: Should size include data w/ message or just message "header" */
1595 /* FIXME: Check return code */
1596 hr
= DP_SendEx( This
, DPID_SERVERPLAYER
, DPID_ALLPLAYERS
, 0, &msg
,
1597 sizeof( msg
), 0, 0, NULL
, NULL
, bAnsi
);
1604 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
1605 ( LPDIRECTPLAY2A iface
, LPDPID lpidPlayer
, LPDPNAME lpPlayerName
,
1606 HANDLE hEvent
, LPVOID lpData
, DWORD dwDataSize
, DWORD dwFlags
)
1608 ICOM_THIS(IDirectPlay2Impl
,iface
);
1610 if( dwFlags
& DPPLAYER_SERVERPLAYER
)
1612 *lpidPlayer
= DPID_SERVERPLAYER
;
1616 *lpidPlayer
= DPID_UNKNOWN
;
1619 return DP_IF_CreatePlayer( This
, NULL
, lpidPlayer
, lpPlayerName
, hEvent
,
1620 lpData
, dwDataSize
, dwFlags
, TRUE
);
1623 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
1624 ( LPDIRECTPLAY2 iface
, LPDPID lpidPlayer
, LPDPNAME lpPlayerName
,
1625 HANDLE hEvent
, LPVOID lpData
, DWORD dwDataSize
, DWORD dwFlags
)
1627 ICOM_THIS(IDirectPlay2Impl
,iface
);
1629 if( dwFlags
& DPPLAYER_SERVERPLAYER
)
1631 *lpidPlayer
= DPID_SERVERPLAYER
;
1635 *lpidPlayer
= DPID_UNKNOWN
;
1638 return DP_IF_CreatePlayer( This
, NULL
, lpidPlayer
, lpPlayerName
, hEvent
,
1639 lpData
, dwDataSize
, dwFlags
, FALSE
);
1642 static DPID
DP_GetRemoteNextObjectId(void)
1647 return DP_NextObjectId();
1650 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
1651 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idGroup
,
1652 DPID idPlayer
, BOOL bAnsi
)
1656 lpGroupData lpGData
;
1657 lpPlayerList lpPList
;
1659 TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
1660 This
, lpMsgHdr
, idGroup
, idPlayer
, bAnsi
);
1662 /* Find the group */
1663 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
1665 return DPERR_INVALIDGROUP
;
1668 /* Find the player */
1669 if( ( lpPList
= DP_FindPlayer( This
, idPlayer
) ) == NULL
)
1671 return DPERR_INVALIDPLAYER
;
1674 /* Remove the player shortcut from the group */
1675 DPQ_REMOVE_ENTRY( lpGData
->players
, players
, lpPData
->dpid
, ==, idPlayer
, lpPList
);
1677 if( lpPList
== NULL
)
1679 return DPERR_INVALIDPLAYER
;
1682 /* One less reference */
1683 lpPList
->lpPData
->uRef
--;
1685 /* Delete the Player List element */
1686 HeapFree( GetProcessHeap(), 0, lpPList
);
1688 /* Inform the SP if they care */
1689 if( This
->dp2
->spData
.lpCB
->RemovePlayerFromGroup
)
1691 DPSP_REMOVEPLAYERFROMGROUPDATA data
;
1693 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1695 data
.idPlayer
= idPlayer
;
1696 data
.idGroup
= idGroup
;
1697 data
.lpISP
= This
->dp2
->spData
.lpISP
;
1699 hr
= (*This
->dp2
->spData
.lpCB
->RemovePlayerFromGroup
)( &data
);
1702 /* Need to send a DELETEPLAYERFROMGROUP message */
1703 FIXME( "Need to send a message\n" );
1708 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
1709 ( LPDIRECTPLAY2A iface
, DPID idGroup
, DPID idPlayer
)
1711 ICOM_THIS(IDirectPlay2Impl
,iface
);
1712 return DP_IF_DeletePlayerFromGroup( This
, NULL
, idGroup
, idPlayer
, TRUE
);
1715 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
1716 ( LPDIRECTPLAY2 iface
, DPID idGroup
, DPID idPlayer
)
1718 ICOM_THIS(IDirectPlay2Impl
,iface
);
1719 return DP_IF_DeletePlayerFromGroup( This
, NULL
, idGroup
, idPlayer
, FALSE
);
1722 typedef struct _DPRGOPContext
1724 IDirectPlay3Impl
* This
;
1727 } DPRGOPContext
, *lpDPRGOPContext
;
1729 static BOOL CALLBACK
1730 cbRemoveGroupOrPlayer(
1737 lpDPRGOPContext lpCtxt
= (lpDPRGOPContext
)lpContext
;
1739 TRACE( "Removing element:0x%08lx (type:0x%08lx) from element:0x%08lx\n",
1740 dpId
, dwPlayerType
, lpCtxt
->idGroup
);
1742 if( dwPlayerType
== DPPLAYERTYPE_GROUP
)
1744 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt
->This
, lpCtxt
->idGroup
,
1749 ERR( "Unable to delete group 0x%08lx from group 0x%08lx\n",
1750 dpId
, lpCtxt
->idGroup
);
1755 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl
*)lpCtxt
->This
,
1756 NULL
, lpCtxt
->idGroup
,
1757 dpId
, lpCtxt
->bAnsi
)
1761 ERR( "Unable to delete player 0x%08lx from grp 0x%08lx\n",
1762 dpId
, lpCtxt
->idGroup
);
1766 return TRUE
; /* Continue enumeration */
1769 static HRESULT WINAPI DP_IF_DestroyGroup
1770 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idGroup
, BOOL bAnsi
)
1772 lpGroupData lpGData
;
1773 DPRGOPContext context
;
1775 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
1776 This
, lpMsgHdr
, idGroup
, bAnsi
);
1778 /* Find the group */
1779 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
1781 return DPERR_INVALIDPLAYER
; /* yes player */
1784 context
.This
= (IDirectPlay3Impl
*)This
;
1785 context
.bAnsi
= bAnsi
;
1786 context
.idGroup
= idGroup
;
1788 /* Remove all players that this group has */
1789 DP_IF_EnumGroupPlayers( This
, idGroup
, NULL
,
1790 cbRemoveGroupOrPlayer
, (LPVOID
)&context
, 0, bAnsi
);
1792 /* Remove all links to groups that this group has since this is dp3 */
1793 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl
*)This
, idGroup
, NULL
,
1794 cbRemoveGroupOrPlayer
, (LPVOID
)&context
, 0, bAnsi
);
1796 /* Remove this group from the parent group - if it has one */
1797 if( ( idGroup
!= DPID_SYSTEM_GROUP
) &&
1798 ( lpGData
->parent
!= DPID_SYSTEM_GROUP
)
1801 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl
*)This
, lpGData
->parent
,
1805 /* Now delete this group data and list from the system group */
1806 DP_DeleteGroup( This
, idGroup
);
1808 /* Let the SP know that we've destroyed this group */
1809 if( This
->dp2
->spData
.lpCB
->DeleteGroup
)
1811 DPSP_DELETEGROUPDATA data
;
1813 FIXME( "data.dwFlags is incorrect\n" );
1815 data
.idGroup
= idGroup
;
1817 data
.lpISP
= This
->dp2
->spData
.lpISP
;
1819 (*This
->dp2
->spData
.lpCB
->DeleteGroup
)( &data
);
1822 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1827 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
1828 ( LPDIRECTPLAY2A iface
, DPID idGroup
)
1830 ICOM_THIS(IDirectPlay2Impl
,iface
);
1831 return DP_IF_DestroyGroup( This
, NULL
, idGroup
, TRUE
);
1834 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
1835 ( LPDIRECTPLAY2 iface
, DPID idGroup
)
1837 ICOM_THIS(IDirectPlay2Impl
,iface
);
1838 return DP_IF_DestroyGroup( This
, NULL
, idGroup
, FALSE
);
1841 typedef struct _DPFAGContext
1843 IDirectPlay2Impl
* This
;
1846 } DPFAGContext
, *lpDPFAGContext
;
1848 static HRESULT WINAPI DP_IF_DestroyPlayer
1849 ( IDirectPlay2Impl
* This
, LPVOID lpMsgHdr
, DPID idPlayer
, BOOL bAnsi
)
1851 DPFAGContext cbContext
;
1853 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
1854 This
, lpMsgHdr
, idPlayer
, bAnsi
);
1856 if( DP_FindPlayer( This
, idPlayer
) == NULL
)
1858 return DPERR_INVALIDPLAYER
;
1861 /* FIXME: If the player is remote, we must be the host to delete this */
1863 cbContext
.This
= This
;
1864 cbContext
.idPlayer
= idPlayer
;
1865 cbContext
.bAnsi
= bAnsi
;
1867 /* Find each group and call DeletePlayerFromGroup if the player is a
1868 member of the group */
1869 DP_IF_EnumGroups( This
, NULL
, cbDeletePlayerFromAllGroups
,
1870 (LPVOID
)&cbContext
, DPENUMGROUPS_ALL
, bAnsi
);
1872 /* Now delete player and player list from the sys group */
1873 DP_DeletePlayer( This
, idPlayer
);
1875 /* Let the SP know that we've destroyed this group */
1876 if( This
->dp2
->spData
.lpCB
->DeletePlayer
)
1878 DPSP_DELETEPLAYERDATA data
;
1880 FIXME( "data.dwFlags is incorrect\n" );
1882 data
.idPlayer
= idPlayer
;
1884 data
.lpISP
= This
->dp2
->spData
.lpISP
;
1886 (*This
->dp2
->spData
.lpCB
->DeletePlayer
)( &data
);
1889 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
1894 static BOOL CALLBACK
1895 cbDeletePlayerFromAllGroups(
1902 lpDPFAGContext lpCtxt
= (lpDPFAGContext
)lpContext
;
1904 if( dwPlayerType
== DPPLAYERTYPE_GROUP
)
1906 DP_IF_DeletePlayerFromGroup( lpCtxt
->This
, NULL
, dpId
, lpCtxt
->idPlayer
,
1909 /* Enumerate all groups in this group since this will normally only
1910 * be called for top level groups
1912 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl
*)lpCtxt
->This
,
1914 cbDeletePlayerFromAllGroups
,
1915 (LPVOID
)lpContext
, DPENUMGROUPS_ALL
,
1921 ERR( "Group callback has dwPlayerType = 0x%08lx\n", dwPlayerType
);
1927 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
1928 ( LPDIRECTPLAY2A iface
, DPID idPlayer
)
1930 ICOM_THIS(IDirectPlay2Impl
,iface
);
1931 return DP_IF_DestroyPlayer( This
, NULL
, idPlayer
, TRUE
);
1934 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
1935 ( LPDIRECTPLAY2 iface
, DPID idPlayer
)
1937 ICOM_THIS(IDirectPlay2Impl
,iface
);
1938 return DP_IF_DestroyPlayer( This
, NULL
, idPlayer
, FALSE
);
1941 static HRESULT WINAPI DP_IF_EnumGroupPlayers
1942 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPGUID lpguidInstance
,
1943 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
1944 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
)
1946 lpGroupData lpGData
;
1947 lpPlayerList lpPList
;
1949 FIXME("(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
1950 This
, idGroup
, lpguidInstance
, lpEnumPlayersCallback2
,
1951 lpContext
, dwFlags
, bAnsi
);
1953 /* Find the group */
1954 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
1956 return DPERR_INVALIDGROUP
;
1959 if( DPQ_IS_EMPTY( lpGData
->players
) )
1964 lpPList
= DPQ_FIRST( lpGData
->players
);
1966 /* Walk the players in this group */
1969 /* We do not enum the name server or app server as they are of no
1970 * concequence to the end user.
1972 if( ( lpPList
->lpPData
->dpid
!= DPID_NAME_SERVER
) &&
1973 ( lpPList
->lpPData
->dpid
!= DPID_SERVERPLAYER
)
1977 /* FIXME: Need to add stuff for dwFlags checking */
1979 if( !lpEnumPlayersCallback2( lpPList
->lpPData
->dpid
, DPPLAYERTYPE_PLAYER
,
1980 &lpPList
->lpPData
->name
,
1981 lpPList
->lpPData
->dwFlags
,
1985 /* User requested break */
1990 if( DPQ_IS_ENDOFLIST( lpPList
->players
) )
1995 lpPList
= DPQ_NEXT( lpPList
->players
);
2001 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
2002 ( LPDIRECTPLAY2A iface
, DPID idGroup
, LPGUID lpguidInstance
,
2003 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2004 LPVOID lpContext
, DWORD dwFlags
)
2006 ICOM_THIS(IDirectPlay2Impl
,iface
);
2007 return DP_IF_EnumGroupPlayers( This
, idGroup
, lpguidInstance
,
2008 lpEnumPlayersCallback2
, lpContext
,
2012 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
2013 ( LPDIRECTPLAY2 iface
, DPID idGroup
, LPGUID lpguidInstance
,
2014 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2015 LPVOID lpContext
, DWORD dwFlags
)
2017 ICOM_THIS(IDirectPlay2Impl
,iface
);
2018 return DP_IF_EnumGroupPlayers( This
, idGroup
, lpguidInstance
,
2019 lpEnumPlayersCallback2
, lpContext
,
2023 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2024 static HRESULT WINAPI DP_IF_EnumGroups
2025 ( IDirectPlay2Impl
* This
, LPGUID lpguidInstance
,
2026 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2027 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
)
2029 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl
*)This
,
2030 DPID_SYSTEM_GROUP
, lpguidInstance
,
2031 lpEnumPlayersCallback2
, lpContext
,
2035 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
2036 ( LPDIRECTPLAY2A iface
, LPGUID lpguidInstance
,
2037 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2038 LPVOID lpContext
, DWORD dwFlags
)
2040 ICOM_THIS(IDirectPlay2Impl
,iface
);
2041 return DP_IF_EnumGroups( This
, lpguidInstance
, lpEnumPlayersCallback2
,
2042 lpContext
, dwFlags
, TRUE
);
2045 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
2046 ( LPDIRECTPLAY2 iface
, LPGUID lpguidInstance
,
2047 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2048 LPVOID lpContext
, DWORD dwFlags
)
2050 ICOM_THIS(IDirectPlay2Impl
,iface
);
2051 return DP_IF_EnumGroups( This
, lpguidInstance
, lpEnumPlayersCallback2
,
2052 lpContext
, dwFlags
, FALSE
);
2055 static HRESULT WINAPI DP_IF_EnumPlayers
2056 ( IDirectPlay2Impl
* This
, LPGUID lpguidInstance
,
2057 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2058 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
)
2060 return DP_IF_EnumGroupPlayers( This
, DPID_SYSTEM_GROUP
, lpguidInstance
,
2061 lpEnumPlayersCallback2
, lpContext
,
2065 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
2066 ( LPDIRECTPLAY2A iface
, LPGUID lpguidInstance
,
2067 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2068 LPVOID lpContext
, DWORD dwFlags
)
2070 ICOM_THIS(IDirectPlay2Impl
,iface
);
2071 return DP_IF_EnumPlayers( This
, lpguidInstance
, lpEnumPlayersCallback2
,
2072 lpContext
, dwFlags
, TRUE
);
2075 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
2076 ( LPDIRECTPLAY2 iface
, LPGUID lpguidInstance
,
2077 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
2078 LPVOID lpContext
, DWORD dwFlags
)
2080 ICOM_THIS(IDirectPlay2Impl
,iface
);
2081 return DP_IF_EnumPlayers( This
, lpguidInstance
, lpEnumPlayersCallback2
,
2082 lpContext
, dwFlags
, FALSE
);
2085 /* This function should call the registered callback function that the user
2086 passed into EnumSessions for each entry available.
2088 static void DP_InvokeEnumSessionCallbacks
2089 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2
,
2094 LPDPSESSIONDESC2 lpSessionDesc
;
2096 FIXME( ": not checking for conditions\n" );
2098 /* Not sure if this should be pruning but it's convenient */
2099 NS_PruneSessionCache( lpNSInfo
);
2101 NS_ResetSessionEnumeration( lpNSInfo
);
2103 /* Enumerate all sessions */
2104 /* FIXME: Need to indicate ANSI */
2105 while( (lpSessionDesc
= NS_WalkSessions( lpNSInfo
) ) != NULL
)
2107 TRACE( "EnumSessionsCallback2 invoked\n" );
2108 if( !lpEnumSessionsCallback2( lpSessionDesc
, &dwTimeout
, 0, lpContext
) )
2114 /* Invoke one last time to indicate that there is no more to come */
2115 lpEnumSessionsCallback2( NULL
, &dwTimeout
, DPESC_TIMEDOUT
, lpContext
);
2118 static DWORD CALLBACK
DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext
)
2120 EnumSessionAsyncCallbackData
* data
= (EnumSessionAsyncCallbackData
*)lpContext
;
2121 HANDLE hSuicideRequest
= data
->hSuicideRequest
;
2122 DWORD dwTimeout
= data
->dwTimeout
;
2124 TRACE( "Thread started with timeout = 0x%08lx\n", dwTimeout
);
2130 /* Sleep up to dwTimeout waiting for request to terminate thread */
2131 if( WaitForSingleObject( hSuicideRequest
, dwTimeout
) == WAIT_OBJECT_0
)
2133 TRACE( "Thread terminating on terminate request\n" );
2137 /* Now resend the enum request */
2138 hr
= NS_SendSessionRequestBroadcast( &data
->requestGuid
,
2139 data
->dwEnumSessionFlags
,
2144 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr
) );
2145 /* FIXME: Should we kill this thread? How to inform the main thread? */
2150 TRACE( "Thread terminating\n" );
2152 /* Clean up the thread data */
2153 CloseHandle( hSuicideRequest
);
2154 HeapFree( GetProcessHeap(), 0, lpContext
);
2156 /* FIXME: Need to have some notification to main app thread that this is
2157 * dead. It would serve two purposes. 1) allow sync on termination
2158 * so that we don't actually send something to ourselves when we
2159 * become name server (race condition) and 2) so that if we die
2160 * abnormally something else will be able to tell.
2166 static void DP_KillEnumSessionThread( IDirectPlay2Impl
* This
)
2168 /* Does a thread exist? If so we were doing an async enum session */
2169 if( This
->dp2
->hEnumSessionThread
!= INVALID_HANDLE_VALUE
)
2171 TRACE( "Killing EnumSession thread %u\n",
2172 This
->dp2
->hEnumSessionThread
);
2174 /* Request that the thread kill itself nicely */
2175 SetEvent( This
->dp2
->hKillEnumSessionThreadEvent
);
2176 CloseHandle( This
->dp2
->hKillEnumSessionThreadEvent
);
2178 /* We no longer need to know about the thread */
2179 CloseHandle( This
->dp2
->hEnumSessionThread
);
2181 This
->dp2
->hEnumSessionThread
= INVALID_HANDLE_VALUE
;
2185 static HRESULT WINAPI DP_IF_EnumSessions
2186 ( IDirectPlay2Impl
* This
, LPDPSESSIONDESC2 lpsd
, DWORD dwTimeout
,
2187 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2
,
2188 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
)
2192 TRACE( "(%p)->(%p,0x%08lx,%p,%p,0x%08lx,%u)\n",
2193 This
, lpsd
, dwTimeout
, lpEnumSessionsCallback2
, lpContext
, dwFlags
,
2196 /* Can't enumerate if the interface is already open */
2197 if( This
->dp2
->bConnectionOpen
)
2199 return DPERR_GENERIC
;
2203 /* The loading of a lobby provider _seems_ to require a backdoor loading
2204 * of the service provider to also associate with this DP object. This is
2205 * because the app doesn't seem to have to call EnumConnections and
2206 * InitializeConnection for the SP before calling this method. As such
2207 * we'll do their dirty work for them with a quick hack so as to always
2208 * load the TCP/IP service provider.
2210 * The correct solution would seem to involve creating a dialog box which
2211 * contains the possible SPs. These dialog boxes most likely follow SDK
2214 if( This
->dp2
->bDPLSPInitialized
&& !This
->dp2
->bSPInitialized
)
2216 LPVOID lpConnection
;
2219 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2221 if( !DP_BuildSPCompoundAddr( (LPGUID
)&DPSPGUID_TCPIP
, &lpConnection
, &dwSize
) )
2223 ERR( "Can't build compound addr\n" );
2224 return DPERR_GENERIC
;
2227 hr
= DP_IF_InitializeConnection( (IDirectPlay3Impl
*)This
, lpConnection
,
2234 /* Free up the address buffer */
2235 HeapFree( GetProcessHeap(), 0, lpConnection
);
2237 /* The SP is now initialized */
2238 This
->dp2
->bSPInitialized
= TRUE
;
2243 /* Use the service provider default? */
2244 if( dwTimeout
== 0 )
2247 spCaps
.dwSize
= sizeof( spCaps
);
2249 DP_IF_GetCaps( This
, &spCaps
, 0 );
2250 dwTimeout
= spCaps
.dwTimeout
;
2252 /* The service provider doesn't provide one either! */
2253 if( dwTimeout
== 0 )
2255 /* Provide the TCP/IP default */
2256 dwTimeout
= DPMSG_WAIT_5_SECS
;
2260 if( dwFlags
& DPENUMSESSIONS_STOPASYNC
)
2262 DP_KillEnumSessionThread( This
);
2266 /* FIXME: Interface locking sucks in this method */
2267 if( ( dwFlags
& DPENUMSESSIONS_ASYNC
) )
2269 /* Enumerate everything presently in the local session cache */
2270 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2
,
2271 This
->dp2
->lpNameServerData
, dwTimeout
,
2275 /* See if we've already created a thread to service this interface */
2276 if( This
->dp2
->hEnumSessionThread
== INVALID_HANDLE_VALUE
)
2280 /* Send the first enum request inline since the user may cancel a dialog
2281 * if one is presented. Also, may also have a connecting return code.
2283 hr
= NS_SendSessionRequestBroadcast( &lpsd
->guidApplication
,
2284 dwFlags
, &This
->dp2
->spData
);
2288 EnumSessionAsyncCallbackData
* lpData
2289 = (EnumSessionAsyncCallbackData
*)HeapAlloc( GetProcessHeap(),
2291 sizeof( *lpData
) );
2292 /* FIXME: need to kill the thread on object deletion */
2293 lpData
->lpSpData
= &This
->dp2
->spData
;
2295 CopyMemory( &lpData
->requestGuid
, &lpsd
->guidApplication
, sizeof(GUID
) );
2296 lpData
->dwEnumSessionFlags
= dwFlags
;
2297 lpData
->dwTimeout
= dwTimeout
;
2299 This
->dp2
->hKillEnumSessionThreadEvent
=
2300 CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
2302 if( !DuplicateHandle( GetCurrentProcess(),
2303 This
->dp2
->hKillEnumSessionThreadEvent
,
2304 GetCurrentProcess(),
2305 &lpData
->hSuicideRequest
,
2306 0, FALSE
, DUPLICATE_SAME_ACCESS
)
2309 ERR( "Can't duplicate thread killing handle\n" );
2312 TRACE( ": creating EnumSessionsRequest thread\n" );
2314 This
->dp2
->hEnumSessionThread
= CreateThread( NULL
,
2316 DP_EnumSessionsSendAsyncRequestThread
,
2325 /* Invalidate the session cache for the interface */
2326 NS_InvalidateSessionCache( This
->dp2
->lpNameServerData
);
2328 /* Send the broadcast for session enumeration */
2329 hr
= NS_SendSessionRequestBroadcast( &lpsd
->guidApplication
,
2331 &This
->dp2
->spData
);
2334 SleepEx( dwTimeout
, FALSE
);
2336 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2
,
2337 This
->dp2
->lpNameServerData
, dwTimeout
,
2344 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2345 ( LPDIRECTPLAY2A iface
, LPDPSESSIONDESC2 lpsd
, DWORD dwTimeout
,
2346 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2
,
2347 LPVOID lpContext
, DWORD dwFlags
)
2349 ICOM_THIS(IDirectPlay2Impl
,iface
);
2350 return DP_IF_EnumSessions( This
, lpsd
, dwTimeout
, lpEnumSessionsCallback2
,
2351 lpContext
, dwFlags
, TRUE
);
2354 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2355 ( LPDIRECTPLAY2 iface
, LPDPSESSIONDESC2 lpsd
, DWORD dwTimeout
,
2356 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2
,
2357 LPVOID lpContext
, DWORD dwFlags
)
2359 ICOM_THIS(IDirectPlay2Impl
,iface
);
2360 return DP_IF_EnumSessions( This
, lpsd
, dwTimeout
, lpEnumSessionsCallback2
,
2361 lpContext
, dwFlags
, FALSE
);
2364 static HRESULT WINAPI DP_IF_GetPlayerCaps
2365 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPDPCAPS lpDPCaps
,
2368 DPSP_GETCAPSDATA data
;
2370 TRACE("(%p)->(0x%08lx,%p,0x%08lx)\n", This
, idPlayer
, lpDPCaps
, dwFlags
);
2372 /* Query the service provider */
2373 data
.idPlayer
= idPlayer
;
2374 data
.dwFlags
= dwFlags
;
2375 data
.lpCaps
= lpDPCaps
;
2376 data
.lpISP
= This
->dp2
->spData
.lpISP
;
2378 return (*This
->dp2
->spData
.lpCB
->GetCaps
)( &data
);
2381 static HRESULT WINAPI DP_IF_GetCaps
2382 ( IDirectPlay2Impl
* This
, LPDPCAPS lpDPCaps
, DWORD dwFlags
)
2384 return DP_IF_GetPlayerCaps( This
, DPID_ALLPLAYERS
, lpDPCaps
, dwFlags
);
2387 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2388 ( LPDIRECTPLAY2A iface
, LPDPCAPS lpDPCaps
, DWORD dwFlags
)
2390 ICOM_THIS(IDirectPlay2Impl
,iface
);
2391 return DP_IF_GetCaps( This
, lpDPCaps
, dwFlags
);
2394 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2395 ( LPDIRECTPLAY2 iface
, LPDPCAPS lpDPCaps
, DWORD dwFlags
)
2397 ICOM_THIS(IDirectPlay2Impl
,iface
);
2398 return DP_IF_GetCaps( This
, lpDPCaps
, dwFlags
);
2401 static HRESULT WINAPI DP_IF_GetGroupData
2402 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPVOID lpData
,
2403 LPDWORD lpdwDataSize
, DWORD dwFlags
, BOOL bAnsi
)
2405 lpGroupData lpGData
;
2406 DWORD dwRequiredBufferSize
;
2407 LPVOID lpCopyDataFrom
;
2409 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
2410 This
, idGroup
, lpData
, lpdwDataSize
, dwFlags
, bAnsi
);
2412 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
2414 return DPERR_INVALIDGROUP
;
2417 /* How much buffer is required? */
2418 if( dwFlags
& DPSET_REMOTE
)
2420 dwRequiredBufferSize
= lpGData
->dwRemoteDataSize
;
2421 lpCopyDataFrom
= lpGData
->lpRemoteData
;
2423 else if( dwFlags
& DPSET_LOCAL
)
2425 dwRequiredBufferSize
= lpGData
->dwLocalDataSize
;
2426 lpCopyDataFrom
= lpGData
->lpLocalData
;
2430 ERR( "Neither local or remote data requested!?!\n" );
2431 dwRequiredBufferSize
= 0;
2432 lpCopyDataFrom
= NULL
;
2435 /* Is the user requesting to know how big a buffer is required? */
2436 if( ( lpData
== NULL
) ||
2437 ( *lpdwDataSize
< dwRequiredBufferSize
)
2440 *lpdwDataSize
= dwRequiredBufferSize
;
2441 return DPERR_BUFFERTOOSMALL
;
2444 CopyMemory( lpData
, lpCopyDataFrom
, dwRequiredBufferSize
);
2449 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2450 ( LPDIRECTPLAY2A iface
, DPID idGroup
, LPVOID lpData
,
2451 LPDWORD lpdwDataSize
, DWORD dwFlags
)
2453 ICOM_THIS(IDirectPlay2Impl
,iface
);
2454 return DP_IF_GetGroupData( This
, idGroup
, lpData
, lpdwDataSize
,
2458 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2459 ( LPDIRECTPLAY2 iface
, DPID idGroup
, LPVOID lpData
,
2460 LPDWORD lpdwDataSize
, DWORD dwFlags
)
2462 ICOM_THIS(IDirectPlay2Impl
,iface
);
2463 return DP_IF_GetGroupData( This
, idGroup
, lpData
, lpdwDataSize
,
2467 static HRESULT WINAPI DP_IF_GetGroupName
2468 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPVOID lpData
,
2469 LPDWORD lpdwDataSize
, BOOL bAnsi
)
2471 lpGroupData lpGData
;
2472 LPDPNAME lpName
= (LPDPNAME
)lpData
;
2473 DWORD dwRequiredDataSize
;
2475 FIXME("(%p)->(0x%08lx,%p,%p,%u) ANSI ignored\n",
2476 This
, idGroup
, lpData
, lpdwDataSize
, bAnsi
);
2478 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
2480 return DPERR_INVALIDGROUP
;
2483 dwRequiredDataSize
= lpGData
->name
.dwSize
;
2485 if( lpGData
->name
.u1
.lpszShortNameA
)
2487 dwRequiredDataSize
+= strlen( lpGData
->name
.u1
.lpszShortNameA
) + 1;
2490 if( lpGData
->name
.u2
.lpszLongNameA
)
2492 dwRequiredDataSize
+= strlen( lpGData
->name
.u2
.lpszLongNameA
) + 1;
2495 if( ( lpData
== NULL
) ||
2496 ( *lpdwDataSize
< dwRequiredDataSize
)
2499 *lpdwDataSize
= dwRequiredDataSize
;
2500 return DPERR_BUFFERTOOSMALL
;
2503 /* Copy the structure */
2504 CopyMemory( lpName
, &lpGData
->name
, lpGData
->name
.dwSize
);
2506 if( lpGData
->name
.u1
.lpszShortNameA
)
2508 strcpy( ((BYTE
*)lpName
)+lpGData
->name
.dwSize
,
2509 lpGData
->name
.u1
.lpszShortNameA
);
2513 lpName
->u1
.lpszShortNameA
= NULL
;
2516 if( lpGData
->name
.u1
.lpszShortNameA
)
2518 strcpy( ((BYTE
*)lpName
)+lpGData
->name
.dwSize
,
2519 lpGData
->name
.u2
.lpszLongNameA
);
2523 lpName
->u2
.lpszLongNameA
= NULL
;
2529 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2530 ( LPDIRECTPLAY2A iface
, DPID idGroup
, LPVOID lpData
,
2531 LPDWORD lpdwDataSize
)
2533 ICOM_THIS(IDirectPlay2Impl
,iface
);
2534 return DP_IF_GetGroupName( This
, idGroup
, lpData
, lpdwDataSize
, TRUE
);
2537 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2538 ( LPDIRECTPLAY2 iface
, DPID idGroup
, LPVOID lpData
,
2539 LPDWORD lpdwDataSize
)
2541 ICOM_THIS(IDirectPlay2Impl
,iface
);
2542 return DP_IF_GetGroupName( This
, idGroup
, lpData
, lpdwDataSize
, FALSE
);
2545 static HRESULT WINAPI DP_IF_GetMessageCount
2546 ( IDirectPlay2Impl
* This
, DPID idPlayer
,
2547 LPDWORD lpdwCount
, BOOL bAnsi
)
2549 FIXME("(%p)->(0x%08lx,%p,%u): stub\n", This
, idPlayer
, lpdwCount
, bAnsi
);
2550 return DP_IF_GetMessageQueue( (IDirectPlay4Impl
*)This
, 0, idPlayer
,
2551 DPMESSAGEQUEUE_RECEIVE
, lpdwCount
, NULL
,
2555 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2556 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPDWORD lpdwCount
)
2558 ICOM_THIS(IDirectPlay2Impl
,iface
);
2559 return DP_IF_GetMessageCount( This
, idPlayer
, lpdwCount
, TRUE
);
2562 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2563 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPDWORD lpdwCount
)
2565 ICOM_THIS(IDirectPlay2Impl
,iface
);
2566 return DP_IF_GetMessageCount( This
, idPlayer
, lpdwCount
, FALSE
);
2569 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2570 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPVOID lpData
, LPDWORD lpdwDataSize
)
2572 ICOM_THIS(IDirectPlay2Impl
,iface
);
2573 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This
, idPlayer
, lpData
, lpdwDataSize
);
2577 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2578 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPVOID lpData
, LPDWORD lpdwDataSize
)
2580 ICOM_THIS(IDirectPlay2Impl
,iface
);
2581 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This
, idPlayer
, lpData
, lpdwDataSize
);
2585 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2586 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPDPCAPS lpPlayerCaps
,
2589 ICOM_THIS(IDirectPlay2Impl
,iface
);
2590 return DP_IF_GetPlayerCaps( This
, idPlayer
, lpPlayerCaps
, dwFlags
);
2593 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2594 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPDPCAPS lpPlayerCaps
,
2597 ICOM_THIS(IDirectPlay2Impl
,iface
);
2598 return DP_IF_GetPlayerCaps( This
, idPlayer
, lpPlayerCaps
, dwFlags
);
2601 static HRESULT WINAPI DP_IF_GetPlayerData
2602 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPVOID lpData
,
2603 LPDWORD lpdwDataSize
, DWORD dwFlags
, BOOL bAnsi
)
2605 lpPlayerList lpPList
;
2606 DWORD dwRequiredBufferSize
;
2607 LPVOID lpCopyDataFrom
;
2609 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
2610 This
, idPlayer
, lpData
, lpdwDataSize
, dwFlags
, bAnsi
);
2612 if( ( lpPList
= DP_FindPlayer( This
, idPlayer
) ) == NULL
)
2614 return DPERR_INVALIDPLAYER
;
2617 /* How much buffer is required? */
2618 if( dwFlags
& DPSET_REMOTE
)
2620 dwRequiredBufferSize
= lpPList
->lpPData
->dwRemoteDataSize
;
2621 lpCopyDataFrom
= lpPList
->lpPData
->lpRemoteData
;
2623 else if( dwFlags
& DPSET_LOCAL
)
2625 dwRequiredBufferSize
= lpPList
->lpPData
->dwLocalDataSize
;
2626 lpCopyDataFrom
= lpPList
->lpPData
->lpLocalData
;
2630 ERR( "Neither local or remote data requested!?!\n" );
2631 dwRequiredBufferSize
= 0;
2632 lpCopyDataFrom
= NULL
;
2635 /* Is the user requesting to know how big a buffer is required? */
2636 if( ( lpData
== NULL
) ||
2637 ( *lpdwDataSize
< dwRequiredBufferSize
)
2640 *lpdwDataSize
= dwRequiredBufferSize
;
2641 return DPERR_BUFFERTOOSMALL
;
2644 CopyMemory( lpData
, lpCopyDataFrom
, dwRequiredBufferSize
);
2649 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2650 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPVOID lpData
,
2651 LPDWORD lpdwDataSize
, DWORD dwFlags
)
2653 ICOM_THIS(IDirectPlay2Impl
,iface
);
2654 return DP_IF_GetPlayerData( This
, idPlayer
, lpData
, lpdwDataSize
,
2658 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2659 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPVOID lpData
,
2660 LPDWORD lpdwDataSize
, DWORD dwFlags
)
2662 ICOM_THIS(IDirectPlay2Impl
,iface
);
2663 return DP_IF_GetPlayerData( This
, idPlayer
, lpData
, lpdwDataSize
,
2667 static HRESULT WINAPI DP_IF_GetPlayerName
2668 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPVOID lpData
,
2669 LPDWORD lpdwDataSize
, BOOL bAnsi
)
2671 lpPlayerList lpPList
;
2672 LPDPNAME lpName
= (LPDPNAME
)lpData
;
2673 DWORD dwRequiredDataSize
;
2675 FIXME( "(%p)->(0x%08lx,%p,%p,%u): ANSI \n",
2676 This
, idPlayer
, lpData
, lpdwDataSize
, bAnsi
);
2678 if( ( lpPList
= DP_FindPlayer( This
, idPlayer
) ) == NULL
)
2680 return DPERR_INVALIDPLAYER
;
2683 dwRequiredDataSize
= lpPList
->lpPData
->name
.dwSize
;
2685 if( lpPList
->lpPData
->name
.u1
.lpszShortNameA
)
2687 dwRequiredDataSize
+= strlen( lpPList
->lpPData
->name
.u1
.lpszShortNameA
) + 1;
2690 if( lpPList
->lpPData
->name
.u2
.lpszLongNameA
)
2692 dwRequiredDataSize
+= strlen( lpPList
->lpPData
->name
.u2
.lpszLongNameA
) + 1;
2695 if( ( lpData
== NULL
) ||
2696 ( *lpdwDataSize
< dwRequiredDataSize
)
2699 *lpdwDataSize
= dwRequiredDataSize
;
2700 return DPERR_BUFFERTOOSMALL
;
2703 /* Copy the structure */
2704 CopyMemory( lpName
, &lpPList
->lpPData
->name
, lpPList
->lpPData
->name
.dwSize
);
2706 if( lpPList
->lpPData
->name
.u1
.lpszShortNameA
)
2708 strcpy( ((BYTE
*)lpName
)+lpPList
->lpPData
->name
.dwSize
,
2709 lpPList
->lpPData
->name
.u1
.lpszShortNameA
);
2713 lpName
->u1
.lpszShortNameA
= NULL
;
2716 if( lpPList
->lpPData
->name
.u1
.lpszShortNameA
)
2718 strcpy( ((BYTE
*)lpName
)+lpPList
->lpPData
->name
.dwSize
,
2719 lpPList
->lpPData
->name
.u2
.lpszLongNameA
);
2723 lpName
->u2
.lpszLongNameA
= NULL
;
2729 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2730 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPVOID lpData
,
2731 LPDWORD lpdwDataSize
)
2733 ICOM_THIS(IDirectPlay2Impl
,iface
);
2734 return DP_IF_GetPlayerName( This
, idPlayer
, lpData
, lpdwDataSize
, TRUE
);
2737 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2738 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPVOID lpData
,
2739 LPDWORD lpdwDataSize
)
2741 ICOM_THIS(IDirectPlay2Impl
,iface
);
2742 return DP_IF_GetPlayerName( This
, idPlayer
, lpData
, lpdwDataSize
, FALSE
);
2745 static HRESULT WINAPI DP_GetSessionDesc
2746 ( IDirectPlay2Impl
* This
, LPVOID lpData
, LPDWORD lpdwDataSize
,
2749 DWORD dwRequiredSize
;
2751 TRACE( "(%p)->(%p,%p,%u)\n", This
, lpData
, lpdwDataSize
, bAnsi
);
2753 if( ( lpData
== NULL
) && ( lpdwDataSize
== NULL
) )
2755 return DPERR_INVALIDPARAMS
;
2758 /* FIXME: Get from This->dp2->lpSessionDesc */
2759 dwRequiredSize
= DP_CalcSessionDescSize( This
->dp2
->lpSessionDesc
, bAnsi
);
2761 if ( ( lpData
== NULL
) ||
2762 ( *lpdwDataSize
< dwRequiredSize
)
2765 *lpdwDataSize
= dwRequiredSize
;
2766 return DPERR_BUFFERTOOSMALL
;
2769 DP_CopySessionDesc( lpData
, This
->dp2
->lpSessionDesc
, bAnsi
);
2774 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
2775 ( LPDIRECTPLAY2A iface
, LPVOID lpData
, LPDWORD lpdwDataSize
)
2777 ICOM_THIS(IDirectPlay2Impl
,iface
);
2778 return DP_GetSessionDesc( This
, lpData
, lpdwDataSize
, TRUE
);
2781 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
2782 ( LPDIRECTPLAY2 iface
, LPVOID lpData
, LPDWORD lpdwDataSize
)
2784 ICOM_THIS(IDirectPlay2Impl
,iface
);
2785 return DP_GetSessionDesc( This
, lpData
, lpdwDataSize
, TRUE
);
2788 /* Intended only for COM compatibility. Always returns an error. */
2789 static HRESULT WINAPI DirectPlay2AImpl_Initialize
2790 ( LPDIRECTPLAY2A iface
, LPGUID lpGUID
)
2792 ICOM_THIS(IDirectPlay2Impl
,iface
);
2793 TRACE("(%p)->(%p): stub\n", This
, lpGUID
);
2794 return DPERR_ALREADYINITIALIZED
;
2797 /* Intended only for COM compatibility. Always returns an error. */
2798 static HRESULT WINAPI DirectPlay2WImpl_Initialize
2799 ( LPDIRECTPLAY2 iface
, LPGUID lpGUID
)
2801 ICOM_THIS(IDirectPlay2Impl
,iface
);
2802 TRACE("(%p)->(%p): stub\n", This
, lpGUID
);
2803 return DPERR_ALREADYINITIALIZED
;
2807 static HRESULT WINAPI DP_SecureOpen
2808 ( IDirectPlay2Impl
* This
, LPCDPSESSIONDESC2 lpsd
, DWORD dwFlags
,
2809 LPCDPSECURITYDESC lpSecurity
, LPCDPCREDENTIALS lpCredentials
,
2814 FIXME( "(%p)->(%p,0x%08lx,%p,%p): partial stub\n",
2815 This
, lpsd
, dwFlags
, lpSecurity
, lpCredentials
);
2817 if( This
->dp2
->bConnectionOpen
)
2819 TRACE( ": rejecting already open connection.\n" );
2820 return DPERR_ALREADYINITIALIZED
;
2823 /* If we're enumerating, kill the thread */
2824 DP_KillEnumSessionThread( This
);
2826 if( dwFlags
& DPOPEN_CREATE
)
2828 /* Rightoo - this computer is the host and the local computer needs to be
2829 the name server so that others can join this session */
2830 NS_SetLocalComputerAsNameServer( lpsd
, This
->dp2
->lpNameServerData
);
2832 This
->dp2
->bHostInterface
= TRUE
;
2834 hr
= DP_SetSessionDesc( This
, lpsd
, 0, TRUE
, bAnsi
);
2837 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr
) );
2842 /* Invoke the conditional callback for the service provider */
2843 if( This
->dp2
->spData
.lpCB
->Open
)
2847 FIXME( "Not all data fields are correct. Need new parameter\n" );
2849 data
.bCreate
= (dwFlags
& DPOPEN_CREATE
) ? TRUE
: FALSE
;
2850 data
.lpSPMessageHeader
= (dwFlags
& DPOPEN_CREATE
) ? NULL
2851 : NS_GetNSAddr( This
->dp2
->lpNameServerData
);
2852 data
.lpISP
= This
->dp2
->spData
.lpISP
;
2853 data
.bReturnStatus
= (dwFlags
& DPOPEN_RETURNSTATUS
) ? TRUE
: FALSE
;
2854 data
.dwOpenFlags
= dwFlags
;
2855 data
.dwSessionFlags
= This
->dp2
->lpSessionDesc
->dwFlags
;
2857 hr
= (*This
->dp2
->spData
.lpCB
->Open
)(&data
);
2860 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr
) );
2866 /* Create the system group of which everything is a part of */
2867 DPID systemGroup
= DPID_SYSTEM_GROUP
;
2869 hr
= DP_IF_CreateGroup( This
, NULL
, &systemGroup
, NULL
,
2874 if( dwFlags
& DPOPEN_JOIN
)
2876 DPID dpidServerId
= DPID_UNKNOWN
;
2878 /* Create the server player for this interface. This way we can receive
2879 * messages for this session.
2881 /* FIXME: I suppose that we should be setting an event for a receive
2882 * type of thing. That way the messaging thread could know to wake
2883 * up. DPlay would then trigger the hEvent for the player the
2884 * message is directed to.
2886 hr
= DP_IF_CreatePlayer( This
, NULL
, &dpidServerId
, NULL
, 0, NULL
,
2888 DPPLAYER_SERVERPLAYER
| DPPLAYER_LOCAL
, bAnsi
);
2891 else if( dwFlags
& DPOPEN_CREATE
)
2893 DPID dpidNameServerId
= DPID_NAME_SERVER
;
2895 hr
= DP_IF_CreatePlayer( This
, NULL
, &dpidNameServerId
, NULL
, 0, NULL
,
2896 0, DPPLAYER_SERVERPLAYER
, bAnsi
);
2901 ERR( "Couldn't create name server/system player: %s\n",
2902 DPLAYX_HresultToString(hr
) );
2908 static HRESULT WINAPI DirectPlay2AImpl_Open
2909 ( LPDIRECTPLAY2A iface
, LPDPSESSIONDESC2 lpsd
, DWORD dwFlags
)
2911 ICOM_THIS(IDirectPlay2Impl
,iface
);
2912 TRACE("(%p)->(%p,0x%08lx)\n", This
, lpsd
, dwFlags
);
2913 return DP_SecureOpen( This
, lpsd
, dwFlags
, NULL
, NULL
, TRUE
);
2916 static HRESULT WINAPI DirectPlay2WImpl_Open
2917 ( LPDIRECTPLAY2 iface
, LPDPSESSIONDESC2 lpsd
, DWORD dwFlags
)
2919 ICOM_THIS(IDirectPlay2Impl
,iface
);
2920 TRACE("(%p)->(%p,0x%08lx)\n", This
, lpsd
, dwFlags
);
2921 return DP_SecureOpen( This
, lpsd
, dwFlags
, NULL
, NULL
, FALSE
);
2924 static HRESULT WINAPI DP_IF_Receive
2925 ( IDirectPlay2Impl
* This
, LPDPID lpidFrom
, LPDPID lpidTo
,
2926 DWORD dwFlags
, LPVOID lpData
, LPDWORD lpdwDataSize
, BOOL bAnsi
)
2928 LPDPMSG lpMsg
= NULL
;
2930 FIXME( "(%p)->(%p,%p,0x%08lx,%p,%p,%u): stub\n",
2931 This
, lpidFrom
, lpidTo
, dwFlags
, lpData
, lpdwDataSize
, bAnsi
);
2935 dwFlags
= DPRECEIVE_ALL
;
2938 /* If the lpData is NULL, we must be peeking the message */
2939 if( ( lpData
== NULL
) &&
2940 !( dwFlags
& DPRECEIVE_PEEK
)
2943 return DPERR_INVALIDPARAMS
;
2946 if( dwFlags
& DPRECEIVE_ALL
)
2948 lpMsg
= This
->dp2
->receiveMsgs
.lpQHFirst
;
2950 if( !( dwFlags
& DPRECEIVE_PEEK
) )
2952 FIXME( "Remove from queue\n" );
2955 else if( ( dwFlags
& DPRECEIVE_TOPLAYER
) ||
2956 ( dwFlags
& DPRECEIVE_FROMPLAYER
)
2959 FIXME( "Find matching message 0x%08lx\n", dwFlags
);
2963 ERR( "Hmmm..dwFlags 0x%08lx\n", dwFlags
);
2968 return DPERR_NOMESSAGES
;
2971 /* Copy into the provided buffer */
2972 CopyMemory( lpData
, lpMsg
->msg
, *lpdwDataSize
);
2977 static HRESULT WINAPI DirectPlay2AImpl_Receive
2978 ( LPDIRECTPLAY2A iface
, LPDPID lpidFrom
, LPDPID lpidTo
,
2979 DWORD dwFlags
, LPVOID lpData
, LPDWORD lpdwDataSize
)
2981 ICOM_THIS(IDirectPlay2Impl
,iface
);
2982 return DP_IF_Receive( This
, lpidFrom
, lpidTo
, dwFlags
,
2983 lpData
, lpdwDataSize
, TRUE
);
2986 static HRESULT WINAPI DirectPlay2WImpl_Receive
2987 ( LPDIRECTPLAY2 iface
, LPDPID lpidFrom
, LPDPID lpidTo
,
2988 DWORD dwFlags
, LPVOID lpData
, LPDWORD lpdwDataSize
)
2990 ICOM_THIS(IDirectPlay2Impl
,iface
);
2991 return DP_IF_Receive( This
, lpidFrom
, lpidTo
, dwFlags
,
2992 lpData
, lpdwDataSize
, FALSE
);
2995 static HRESULT WINAPI DirectPlay2AImpl_Send
2996 ( LPDIRECTPLAY2A iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
, LPVOID lpData
, DWORD dwDataSize
)
2998 ICOM_THIS(IDirectPlay2Impl
,iface
);
2999 return DP_SendEx( This
, idFrom
, idTo
, dwFlags
, lpData
, dwDataSize
,
3000 0, 0, NULL
, NULL
, TRUE
);
3003 static HRESULT WINAPI DirectPlay2WImpl_Send
3004 ( LPDIRECTPLAY2 iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
, LPVOID lpData
, DWORD dwDataSize
)
3006 ICOM_THIS(IDirectPlay2Impl
,iface
);
3007 return DP_SendEx( This
, idFrom
, idTo
, dwFlags
, lpData
, dwDataSize
,
3008 0, 0, NULL
, NULL
, FALSE
);
3011 static HRESULT WINAPI DP_IF_SetGroupData
3012 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPVOID lpData
,
3013 DWORD dwDataSize
, DWORD dwFlags
, BOOL bAnsi
)
3015 lpGroupData lpGData
;
3017 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
3018 This
, idGroup
, lpData
, dwDataSize
, dwFlags
, bAnsi
);
3020 /* Parameter check */
3021 if( ( lpData
== NULL
) &&
3025 return DPERR_INVALIDPARAMS
;
3028 /* Find the pointer to the data for this player */
3029 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
3031 return DPERR_INVALIDOBJECT
;
3034 if( dwFlags
& DPSET_REMOTE
)
3036 FIXME( "Was this group created by this interface?\n" );
3037 /* FIXME: If this is a remote update need to allow it but not
3042 DP_SetGroupData( lpGData
, dwFlags
, lpData
, dwDataSize
);
3044 /* FIXME: Only send a message if this group is local to the session otherwise
3045 * it will have been rejected above
3047 if( dwFlags
& DPSET_REMOTE
)
3049 FIXME( "Send msg?\n" );
3055 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
3056 ( LPDIRECTPLAY2A iface
, DPID idGroup
, LPVOID lpData
,
3057 DWORD dwDataSize
, DWORD dwFlags
)
3059 ICOM_THIS(IDirectPlay2Impl
,iface
);
3060 return DP_IF_SetGroupData( This
, idGroup
, lpData
, dwDataSize
, dwFlags
, TRUE
);
3063 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
3064 ( LPDIRECTPLAY2 iface
, DPID idGroup
, LPVOID lpData
,
3065 DWORD dwDataSize
, DWORD dwFlags
)
3067 ICOM_THIS(IDirectPlay2Impl
,iface
);
3068 return DP_IF_SetGroupData( This
, idGroup
, lpData
, dwDataSize
, dwFlags
, FALSE
);
3071 static HRESULT WINAPI DP_IF_SetGroupName
3072 ( IDirectPlay2Impl
* This
, DPID idGroup
, LPDPNAME lpGroupName
,
3073 DWORD dwFlags
, BOOL bAnsi
)
3075 lpGroupData lpGData
;
3077 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n", This
, idGroup
,
3078 lpGroupName
, dwFlags
, bAnsi
);
3080 if( ( lpGData
= DP_FindAnyGroup( This
, idGroup
) ) == NULL
)
3082 return DPERR_INVALIDGROUP
;
3085 DP_CopyDPNAMEStruct( &lpGData
->name
, lpGroupName
, bAnsi
);
3087 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3088 FIXME( "Message not sent and dwFlags ignored\n" );
3093 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
3094 ( LPDIRECTPLAY2A iface
, DPID idGroup
, LPDPNAME lpGroupName
,
3097 ICOM_THIS(IDirectPlay2Impl
,iface
);
3098 return DP_IF_SetGroupName( This
, idGroup
, lpGroupName
, dwFlags
, TRUE
);
3101 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
3102 ( LPDIRECTPLAY2 iface
, DPID idGroup
, LPDPNAME lpGroupName
,
3105 ICOM_THIS(IDirectPlay2Impl
,iface
);
3106 return DP_IF_SetGroupName( This
, idGroup
, lpGroupName
, dwFlags
, FALSE
);
3109 static HRESULT WINAPI DP_IF_SetPlayerData
3110 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPVOID lpData
,
3111 DWORD dwDataSize
, DWORD dwFlags
, BOOL bAnsi
)
3113 lpPlayerList lpPList
;
3115 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
3116 This
, idPlayer
, lpData
, dwDataSize
, dwFlags
, bAnsi
);
3118 /* Parameter check */
3119 if( ( lpData
== NULL
) &&
3123 return DPERR_INVALIDPARAMS
;
3126 /* Find the pointer to the data for this player */
3127 if( ( lpPList
= DP_FindPlayer( This
, idPlayer
) ) == NULL
)
3129 return DPERR_INVALIDPLAYER
;
3132 if( dwFlags
& DPSET_REMOTE
)
3134 FIXME( "Was this group created by this interface?\n" );
3135 /* FIXME: If this is a remote update need to allow it but not
3140 DP_SetPlayerData( lpPList
->lpPData
, dwFlags
, lpData
, dwDataSize
);
3142 if( dwFlags
& DPSET_REMOTE
)
3144 FIXME( "Send msg?\n" );
3150 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3151 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPVOID lpData
,
3152 DWORD dwDataSize
, DWORD dwFlags
)
3154 ICOM_THIS(IDirectPlay2Impl
,iface
);
3155 return DP_IF_SetPlayerData( This
, idPlayer
, lpData
, dwDataSize
,
3159 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3160 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPVOID lpData
,
3161 DWORD dwDataSize
, DWORD dwFlags
)
3163 ICOM_THIS(IDirectPlay2Impl
,iface
);
3164 return DP_IF_SetPlayerData( This
, idPlayer
, lpData
, dwDataSize
,
3168 static HRESULT WINAPI DP_IF_SetPlayerName
3169 ( IDirectPlay2Impl
* This
, DPID idPlayer
, LPDPNAME lpPlayerName
,
3170 DWORD dwFlags
, BOOL bAnsi
)
3172 lpPlayerList lpPList
;
3174 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n",
3175 This
, idPlayer
, lpPlayerName
, dwFlags
, bAnsi
);
3177 if( ( lpPList
= DP_FindPlayer( This
, idPlayer
) ) == NULL
)
3179 return DPERR_INVALIDGROUP
;
3182 DP_CopyDPNAMEStruct( &lpPList
->lpPData
->name
, lpPlayerName
, bAnsi
);
3184 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3185 FIXME( "Message not sent and dwFlags ignored\n" );
3190 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3191 ( LPDIRECTPLAY2A iface
, DPID idPlayer
, LPDPNAME lpPlayerName
,
3194 ICOM_THIS(IDirectPlay2Impl
,iface
);
3195 return DP_IF_SetPlayerName( This
, idPlayer
, lpPlayerName
, dwFlags
, TRUE
);
3198 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3199 ( LPDIRECTPLAY2 iface
, DPID idPlayer
, LPDPNAME lpPlayerName
,
3202 ICOM_THIS(IDirectPlay2Impl
,iface
);
3203 return DP_IF_SetPlayerName( This
, idPlayer
, lpPlayerName
, dwFlags
, FALSE
);
3206 static HRESULT WINAPI DP_SetSessionDesc
3207 ( IDirectPlay2Impl
* This
, LPCDPSESSIONDESC2 lpSessDesc
,
3208 DWORD dwFlags
, BOOL bInitial
, BOOL bAnsi
)
3210 DWORD dwRequiredSize
;
3211 LPDPSESSIONDESC2 lpTempSessDesc
;
3213 TRACE( "(%p)->(%p,0x%08lx,%u,%u)\n",
3214 This
, lpSessDesc
, dwFlags
, bInitial
, bAnsi
);
3218 return DPERR_INVALIDPARAMS
;
3221 /* Only the host is allowed to update the session desc */
3222 if( !This
->dp2
->bHostInterface
)
3224 return DPERR_ACCESSDENIED
;
3227 /* FIXME: Copy into This->dp2->lpSessionDesc */
3228 dwRequiredSize
= DP_CalcSessionDescSize( lpSessDesc
, bAnsi
);
3229 lpTempSessDesc
= (LPDPSESSIONDESC2
)HeapAlloc( GetProcessHeap(),
3233 if( lpTempSessDesc
== NULL
)
3235 return DPERR_OUTOFMEMORY
;
3239 HeapFree( GetProcessHeap(), 0, This
->dp2
->lpSessionDesc
);
3241 This
->dp2
->lpSessionDesc
= lpTempSessDesc
;
3244 DP_CopySessionDesc( This
->dp2
->lpSessionDesc
, lpSessDesc
, bAnsi
);
3246 /* If this is an external invocation of the interface, we should be
3247 * letting everyone know that things have changed. Otherwise this is
3248 * just an initialization and it doesn't need to be propagated.
3252 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3258 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3259 ( LPDIRECTPLAY2A iface
, LPDPSESSIONDESC2 lpSessDesc
, DWORD dwFlags
)
3261 ICOM_THIS(IDirectPlay2Impl
,iface
);
3262 return DP_SetSessionDesc( This
, lpSessDesc
, dwFlags
, FALSE
, TRUE
);
3265 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3266 ( LPDIRECTPLAY2 iface
, LPDPSESSIONDESC2 lpSessDesc
, DWORD dwFlags
)
3268 ICOM_THIS(IDirectPlay2Impl
,iface
);
3269 return DP_SetSessionDesc( This
, lpSessDesc
, dwFlags
, FALSE
, TRUE
);
3272 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3273 DWORD
DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc
, BOOL bAnsi
)
3277 if( lpSessDesc
== NULL
)
3279 /* Hmmm..don't need any size? */
3280 ERR( "NULL lpSessDesc\n" );
3284 dwSize
+= sizeof( *lpSessDesc
);
3288 if( lpSessDesc
->u1
.lpszSessionNameA
)
3290 dwSize
+= lstrlenA( lpSessDesc
->u1
.lpszSessionNameA
) + 1;
3293 if( lpSessDesc
->u2
.lpszPasswordA
)
3295 dwSize
+= lstrlenA( lpSessDesc
->u2
.lpszPasswordA
) + 1;
3300 if( lpSessDesc
->u1
.lpszSessionName
)
3302 dwSize
+= sizeof( WCHAR
) *
3303 ( lstrlenW( lpSessDesc
->u1
.lpszSessionName
) + 1 );
3306 if( lpSessDesc
->u2
.lpszPassword
)
3308 dwSize
+= sizeof( WCHAR
) *
3309 ( lstrlenW( lpSessDesc
->u2
.lpszPassword
) + 1 );
3316 /* Assumes that contugous buffers are already allocated. */
3317 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest
,
3318 LPCDPSESSIONDESC2 lpSessionSrc
, BOOL bAnsi
)
3320 BYTE
* lpStartOfFreeSpace
;
3322 if( lpSessionDest
== NULL
)
3324 ERR( "NULL lpSessionDest\n" );
3328 CopyMemory( lpSessionDest
, lpSessionSrc
, sizeof( *lpSessionSrc
) );
3330 lpStartOfFreeSpace
= ((BYTE
*)lpSessionDest
) + sizeof( *lpSessionSrc
);
3334 if( lpSessionSrc
->u1
.lpszSessionNameA
)
3336 lstrcpyA( (LPSTR
)lpStartOfFreeSpace
,
3337 lpSessionDest
->u1
.lpszSessionNameA
);
3338 lpSessionDest
->u1
.lpszSessionNameA
= (LPSTR
)lpStartOfFreeSpace
;
3339 lpStartOfFreeSpace
+=
3340 lstrlenA( (LPSTR
)lpSessionDest
->u1
.lpszSessionNameA
) + 1;
3343 if( lpSessionSrc
->u2
.lpszPasswordA
)
3345 lstrcpyA( (LPSTR
)lpStartOfFreeSpace
,
3346 lpSessionDest
->u2
.lpszPasswordA
);
3347 lpSessionDest
->u2
.lpszPasswordA
= (LPSTR
)lpStartOfFreeSpace
;
3348 lpStartOfFreeSpace
+=
3349 lstrlenA( (LPSTR
)lpSessionDest
->u2
.lpszPasswordA
) + 1;
3354 if( lpSessionSrc
->u1
.lpszSessionName
)
3356 lstrcpyW( (LPWSTR
)lpStartOfFreeSpace
,
3357 lpSessionDest
->u1
.lpszSessionName
);
3358 lpSessionDest
->u1
.lpszSessionName
= (LPWSTR
)lpStartOfFreeSpace
;
3359 lpStartOfFreeSpace
+= sizeof(WCHAR
) *
3360 ( lstrlenW( (LPWSTR
)lpSessionDest
->u1
.lpszSessionName
) + 1 );
3363 if( lpSessionSrc
->u2
.lpszPassword
)
3365 lstrcpyW( (LPWSTR
)lpStartOfFreeSpace
,
3366 lpSessionDest
->u2
.lpszPassword
);
3367 lpSessionDest
->u2
.lpszPassword
= (LPWSTR
)lpStartOfFreeSpace
;
3368 lpStartOfFreeSpace
+= sizeof(WCHAR
) *
3369 ( lstrlenW( (LPWSTR
)lpSessionDest
->u2
.lpszPassword
) + 1 );
3375 static HRESULT WINAPI DP_IF_AddGroupToGroup
3376 ( IDirectPlay3Impl
* This
, DPID idParentGroup
, DPID idGroup
)
3378 lpGroupData lpGParentData
;
3379 lpGroupData lpGData
;
3380 lpGroupList lpNewGList
;
3382 TRACE( "(%p)->(0x%08lx,0x%08lx)\n", This
, idParentGroup
, idGroup
);
3384 if( ( lpGParentData
= DP_FindAnyGroup( (IDirectPlay2AImpl
*)This
, idParentGroup
) ) == NULL
)
3386 return DPERR_INVALIDGROUP
;
3389 if( ( lpGData
= DP_FindAnyGroup( (IDirectPlay2AImpl
*)This
, idGroup
) ) == NULL
)
3391 return DPERR_INVALIDGROUP
;
3394 /* Create a player list (ie "shortcut" ) */
3395 lpNewGList
= (lpGroupList
)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
3396 sizeof( *lpNewGList
) );
3397 if( lpNewGList
== NULL
)
3399 return DPERR_CANTADDPLAYER
;
3402 /* Add the shortcut */
3404 lpNewGList
->lpGData
= lpGData
;
3406 /* Add the player to the list of players for this group */
3407 DPQ_INSERT( lpGData
->groups
, lpNewGList
, groups
);
3409 /* Send a ADDGROUPTOGROUP message */
3410 FIXME( "Not sending message\n" );
3415 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3416 ( LPDIRECTPLAY3A iface
, DPID idParentGroup
, DPID idGroup
)
3418 ICOM_THIS(IDirectPlay3Impl
,iface
);
3419 return DP_IF_AddGroupToGroup( This
, idParentGroup
, idGroup
);
3422 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3423 ( LPDIRECTPLAY3 iface
, DPID idParentGroup
, DPID idGroup
)
3425 ICOM_THIS(IDirectPlay3Impl
,iface
);
3426 return DP_IF_AddGroupToGroup( This
, idParentGroup
, idGroup
);
3429 static HRESULT WINAPI DP_IF_CreateGroupInGroup
3430 ( IDirectPlay3Impl
* This
, LPVOID lpMsgHdr
, DPID idParentGroup
,
3431 LPDPID lpidGroup
, LPDPNAME lpGroupName
, LPVOID lpData
,
3432 DWORD dwDataSize
, DWORD dwFlags
, BOOL bAnsi
)
3434 lpGroupData lpGParentData
;
3435 lpGroupList lpGList
;
3436 lpGroupData lpGData
;
3438 TRACE( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
3439 This
, idParentGroup
, lpidGroup
, lpGroupName
, lpData
,
3440 dwDataSize
, dwFlags
, bAnsi
);
3442 /* Verify that the specified parent is valid */
3443 if( ( lpGParentData
= DP_FindAnyGroup( (IDirectPlay2AImpl
*)This
,
3444 idParentGroup
) ) == NULL
3447 return DPERR_INVALIDGROUP
;
3450 lpGData
= DP_CreateGroup( (IDirectPlay2AImpl
*)This
, lpidGroup
, lpGroupName
,
3451 dwFlags
, idParentGroup
, bAnsi
);
3453 if( lpGData
== NULL
)
3455 return DPERR_CANTADDPLAYER
; /* yes player not group */
3458 /* Something else is referencing this data */
3461 DP_SetGroupData( lpGData
, DPSET_REMOTE
, lpData
, dwDataSize
);
3463 /* The list has now been inserted into the interface group list. We now
3464 need to put a "shortcut" to this group in the parent group */
3465 lpGList
= (lpGroupList
)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
3466 sizeof( *lpGList
) );
3467 if( lpGList
== NULL
)
3469 FIXME( "Memory leak\n" );
3470 return DPERR_CANTADDPLAYER
; /* yes player not group */
3473 lpGList
->lpGData
= lpGData
;
3475 DPQ_INSERT( lpGParentData
->groups
, lpGList
, groups
);
3477 /* Let the SP know that we've created this group */
3478 if( This
->dp2
->spData
.lpCB
->CreateGroup
)
3480 DPSP_CREATEGROUPDATA data
;
3482 TRACE( "Calling SP CreateGroup\n" );
3484 data
.idGroup
= *lpidGroup
;
3485 data
.dwFlags
= dwFlags
;
3486 data
.lpSPMessageHeader
= lpMsgHdr
;
3487 data
.lpISP
= This
->dp2
->spData
.lpISP
;
3489 (*This
->dp2
->spData
.lpCB
->CreateGroup
)( &data
);
3492 /* Inform all other peers of the creation of a new group. If there are
3493 * no peers keep this quiet.
3495 if( This
->dp2
->lpSessionDesc
&&
3496 ( This
->dp2
->lpSessionDesc
->dwFlags
& DPSESSION_MULTICASTSERVER
) )
3498 DPMSG_CREATEPLAYERORGROUP msg
;
3500 msg
.dwType
= DPSYS_CREATEPLAYERORGROUP
;
3501 msg
.dwPlayerType
= DPPLAYERTYPE_GROUP
;
3502 msg
.dpId
= *lpidGroup
;
3503 msg
.dwCurrentPlayers
= idParentGroup
; /* FIXME: Incorrect? */
3504 msg
.lpData
= lpData
;
3505 msg
.dwDataSize
= dwDataSize
;
3506 msg
.dpnName
= *lpGroupName
;
3508 /* FIXME: Correct to just use send effectively? */
3509 /* FIXME: Should size include data w/ message or just message "header" */
3510 /* FIXME: Check return code */
3511 DP_SendEx( (IDirectPlay2Impl
*)This
,
3512 DPID_SERVERPLAYER
, DPID_ALLPLAYERS
, 0, &msg
, sizeof( msg
),
3513 0, 0, NULL
, NULL
, bAnsi
);
3519 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3520 ( LPDIRECTPLAY3A iface
, DPID idParentGroup
, LPDPID lpidGroup
,
3521 LPDPNAME lpGroupName
, LPVOID lpData
, DWORD dwDataSize
,
3524 ICOM_THIS(IDirectPlay3Impl
,iface
);
3526 *lpidGroup
= DPID_UNKNOWN
;
3528 return DP_IF_CreateGroupInGroup( This
, NULL
, idParentGroup
, lpidGroup
,
3529 lpGroupName
, lpData
, dwDataSize
, dwFlags
,
3533 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3534 ( LPDIRECTPLAY3 iface
, DPID idParentGroup
, LPDPID lpidGroup
,
3535 LPDPNAME lpGroupName
, LPVOID lpData
, DWORD dwDataSize
,
3538 ICOM_THIS(IDirectPlay3Impl
,iface
);
3540 *lpidGroup
= DPID_UNKNOWN
;
3542 return DP_IF_CreateGroupInGroup( This
, NULL
, idParentGroup
, lpidGroup
,
3543 lpGroupName
, lpData
, dwDataSize
,
3547 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
3548 ( IDirectPlay3Impl
* This
, DPID idParentGroup
, DPID idGroup
)
3550 lpGroupList lpGList
;
3551 lpGroupData lpGParentData
;
3553 TRACE("(%p)->(0x%08lx,0x%08lx)\n", This
, idParentGroup
, idGroup
);
3555 /* Is the parent group valid? */
3556 if( ( lpGParentData
= DP_FindAnyGroup( (IDirectPlay2AImpl
*)This
, idParentGroup
) ) == NULL
)
3558 return DPERR_INVALIDGROUP
;
3561 /* Remove the group from the parent group queue */
3562 DPQ_REMOVE_ENTRY( lpGParentData
->groups
, groups
, lpGData
->dpid
, ==, idGroup
, lpGList
);
3564 if( lpGList
== NULL
)
3566 return DPERR_INVALIDGROUP
;
3569 /* Decrement the ref count */
3570 lpGList
->lpGData
->uRef
--;
3572 /* Free up the list item */
3573 HeapFree( GetProcessHeap(), 0, lpGList
);
3575 /* Should send a DELETEGROUPFROMGROUP message */
3576 FIXME( "message not sent\n" );
3581 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3582 ( LPDIRECTPLAY3 iface
, DPID idParentGroup
, DPID idGroup
)
3584 ICOM_THIS(IDirectPlay3Impl
,iface
);
3585 return DP_IF_DeleteGroupFromGroup( This
, idParentGroup
, idGroup
);
3588 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3589 ( LPDIRECTPLAY3 iface
, DPID idParentGroup
, DPID idGroup
)
3591 ICOM_THIS(IDirectPlay3Impl
,iface
);
3592 return DP_IF_DeleteGroupFromGroup( This
, idParentGroup
, idGroup
);
3596 BOOL WINAPI
DP_BuildSPCompoundAddr( LPGUID lpcSpGuid
, LPVOID
* lplpAddrBuf
,
3597 LPDWORD lpdwBufSize
)
3599 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress
;
3602 dpCompoundAddress
.dwDataSize
= sizeof( GUID
);
3603 memcpy( &dpCompoundAddress
.guidDataType
, &DPAID_ServiceProvider
,
3605 dpCompoundAddress
.lpData
= lpcSpGuid
;
3607 *lplpAddrBuf
= NULL
;
3610 hr
= DPL_CreateCompoundAddress( &dpCompoundAddress
, 1, *lplpAddrBuf
,
3611 lpdwBufSize
, TRUE
);
3613 if( hr
!= DPERR_BUFFERTOOSMALL
)
3615 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr
) );
3619 /* Now allocate the buffer */
3620 *lplpAddrBuf
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
3623 hr
= DPL_CreateCompoundAddress( &dpCompoundAddress
, 1, *lplpAddrBuf
,
3624 lpdwBufSize
, TRUE
);
3627 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr
) );
3634 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
3635 ( LPDIRECTPLAY3A iface
, LPCGUID lpguidApplication
, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback
, LPVOID lpContext
, DWORD dwFlags
)
3637 ICOM_THIS(IDirectPlay3Impl
,iface
);
3638 TRACE("(%p)->(%p,%p,%p,0x%08lx)\n", This
, lpguidApplication
, lpEnumCallback
, lpContext
, dwFlags
);
3640 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
3643 dwFlags
= DPCONNECTION_DIRECTPLAY
;
3646 if( ! ( ( dwFlags
& DPCONNECTION_DIRECTPLAY
) ||
3647 ( dwFlags
& DPCONNECTION_DIRECTPLAYLOBBY
) )
3650 return DPERR_INVALIDFLAGS
;
3653 if( !lpEnumCallback
|| !*lpEnumCallback
)
3655 return DPERR_INVALIDPARAMS
;
3658 /* Enumerate DirectPlay service providers */
3659 if( dwFlags
& DPCONNECTION_DIRECTPLAY
)
3662 LPCSTR searchSubKey
= "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3663 LPSTR guidDataSubKey
= "Guid";
3664 char subKeyName
[51];
3665 DWORD dwIndex
, sizeOfSubKeyName
=50;
3668 /* Need to loop over the service providers in the registry */
3669 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE
, searchSubKey
,
3670 0, KEY_READ
, &hkResult
) != ERROR_SUCCESS
)
3672 /* Hmmm. Does this mean that there are no service providers? */
3673 ERR(": no service providers?\n");
3678 /* Traverse all the service providers we have available */
3680 RegEnumKeyExA( hkResult
, dwIndex
, subKeyName
, &sizeOfSubKeyName
,
3681 NULL
, NULL
, NULL
, &filetime
) != ERROR_NO_MORE_ITEMS
;
3682 ++dwIndex
, sizeOfSubKeyName
=51 )
3685 HKEY hkServiceProvider
;
3686 GUID serviceProviderGUID
;
3687 DWORD returnTypeGUID
, sizeOfReturnBuffer
= 50;
3688 char returnBuffer
[51];
3693 LPVOID lpAddressBuffer
= NULL
;
3694 DWORD dwAddressBufferSize
= 0;
3696 TRACE(" this time through: %s\n", subKeyName
);
3698 /* Get a handle for this particular service provider */
3699 if( RegOpenKeyExA( hkResult
, subKeyName
, 0, KEY_READ
,
3700 &hkServiceProvider
) != ERROR_SUCCESS
)
3702 ERR(": what the heck is going on?\n" );
3706 if( RegQueryValueExA( hkServiceProvider
, guidDataSubKey
,
3707 NULL
, &returnTypeGUID
, returnBuffer
,
3708 &sizeOfReturnBuffer
) != ERROR_SUCCESS
)
3710 ERR(": missing GUID registry data members\n" );
3714 /* FIXME: Check return types to ensure we're interpreting data right */
3715 MultiByteToWideChar( CP_ACP
, 0, returnBuffer
, -1, buff
, sizeof(buff
)/sizeof(WCHAR
) );
3716 CLSIDFromString( (LPCOLESTR
)buff
, &serviceProviderGUID
);
3717 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3719 /* Fill in the DPNAME struct for the service provider */
3720 dpName
.dwSize
= sizeof( dpName
);
3722 dpName
.u1
.lpszShortNameA
= subKeyName
;
3723 dpName
.u2
.lpszLongNameA
= NULL
;
3725 /* Create the compound address for the service provider.
3726 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
3727 nast stuff. This may be why the native dll just gets around this little bit by
3728 allocating an 80 byte buffer which isn't even a filled with a valid compound
3729 address. Oh well. Creating a proper compound address is the way to go anyways
3730 despite this method taking slightly more heap space and realtime :) */
3732 bBuildPass
= DP_BuildSPCompoundAddr( &serviceProviderGUID
,
3734 &dwAddressBufferSize
);
3737 ERR( "Can't build compound addr\n" );
3738 return DPERR_GENERIC
;
3741 /* The enumeration will return FALSE if we are not to continue */
3742 if( !lpEnumCallback( &serviceProviderGUID
, lpAddressBuffer
, dwAddressBufferSize
,
3743 &dpName
, DPCONNECTION_DIRECTPLAY
, lpContext
) )
3750 /* Enumerate DirectPlayLobby service providers */
3751 if( dwFlags
& DPCONNECTION_DIRECTPLAYLOBBY
)
3754 LPCSTR searchSubKey
= "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3755 LPSTR guidDataSubKey
= "Guid";
3756 char subKeyName
[51];
3757 DWORD dwIndex
, sizeOfSubKeyName
=50;
3760 /* Need to loop over the service providers in the registry */
3761 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE
, searchSubKey
,
3762 0, KEY_READ
, &hkResult
) != ERROR_SUCCESS
)
3764 /* Hmmm. Does this mean that there are no service providers? */
3765 ERR(": no service providers?\n");
3770 /* Traverse all the lobby providers we have available */
3772 RegEnumKeyExA( hkResult
, dwIndex
, subKeyName
, &sizeOfSubKeyName
,
3773 NULL
, NULL
, NULL
, &filetime
) != ERROR_NO_MORE_ITEMS
;
3774 ++dwIndex
, sizeOfSubKeyName
=51 )
3777 HKEY hkServiceProvider
;
3778 GUID serviceProviderGUID
;
3779 DWORD returnTypeGUID
, sizeOfReturnBuffer
= 50;
3780 char returnBuffer
[51];
3785 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress
;
3786 LPVOID lpAddressBuffer
= NULL
;
3787 DWORD dwAddressBufferSize
= 0;
3789 TRACE(" this time through: %s\n", subKeyName
);
3791 /* Get a handle for this particular service provider */
3792 if( RegOpenKeyExA( hkResult
, subKeyName
, 0, KEY_READ
,
3793 &hkServiceProvider
) != ERROR_SUCCESS
)
3795 ERR(": what the heck is going on?\n" );
3799 if( RegQueryValueExA( hkServiceProvider
, guidDataSubKey
,
3800 NULL
, &returnTypeGUID
, returnBuffer
,
3801 &sizeOfReturnBuffer
) != ERROR_SUCCESS
)
3803 ERR(": missing GUID registry data members\n" );
3807 /* FIXME: Check return types to ensure we're interpreting data right */
3808 MultiByteToWideChar( CP_ACP
, 0, returnBuffer
, -1, buff
, sizeof(buff
)/sizeof(WCHAR
) );
3809 CLSIDFromString( (LPCOLESTR
)buff
, &serviceProviderGUID
);
3810 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3812 /* Fill in the DPNAME struct for the service provider */
3813 dpName
.dwSize
= sizeof( dpName
);
3815 dpName
.u1
.lpszShortNameA
= subKeyName
;
3816 dpName
.u2
.lpszLongNameA
= NULL
;
3818 /* Create the compound address for the service provider.
3819 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
3820 nast stuff. This may be why the native dll just gets around this little bit by
3821 allocating an 80 byte buffer which isn't even a filled with a valid compound
3822 address. Oh well. Creating a proper compound address is the way to go anyways
3823 despite this method taking slightly more heap space and realtime :) */
3825 dpCompoundAddress
.guidDataType
= DPAID_LobbyProvider
;
3826 dpCompoundAddress
.dwDataSize
= sizeof( GUID
);
3827 dpCompoundAddress
.lpData
= &serviceProviderGUID
;
3829 if( ( hr
= DPL_CreateCompoundAddress( &dpCompoundAddress
, 1, lpAddressBuffer
,
3830 &dwAddressBufferSize
, TRUE
) ) != DPERR_BUFFERTOOSMALL
)
3832 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr
) );
3836 /* Now allocate the buffer */
3837 lpAddressBuffer
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, dwAddressBufferSize
);
3839 if( ( hr
= DPL_CreateCompoundAddress( &dpCompoundAddress
, 1, lpAddressBuffer
,
3840 &dwAddressBufferSize
, TRUE
) ) != DP_OK
)
3842 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr
) );
3846 /* The enumeration will return FALSE if we are not to continue */
3847 if( !lpEnumCallback( &serviceProviderGUID
, lpAddressBuffer
, dwAddressBufferSize
,
3848 &dpName
, DPCONNECTION_DIRECTPLAYLOBBY
, lpContext
) )
3858 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
3859 ( LPDIRECTPLAY3 iface
, LPCGUID lpguidApplication
, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback
, LPVOID lpContext
, DWORD dwFlags
)
3861 ICOM_THIS(IDirectPlay3Impl
,iface
);
3862 FIXME("(%p)->(%p,%p,%p,0x%08lx): stub\n", This
, lpguidApplication
, lpEnumCallback
, lpContext
, dwFlags
);
3866 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
3867 ( IDirectPlay3AImpl
* This
, DPID idGroup
, LPGUID lpguidInstance
,
3868 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
,
3869 LPVOID lpContext
, DWORD dwFlags
, BOOL bAnsi
)
3871 lpGroupList lpGList
;
3872 lpGroupData lpGData
;
3874 FIXME( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
3875 This
, idGroup
, lpguidInstance
, lpEnumPlayersCallback2
,
3876 lpContext
, dwFlags
, bAnsi
);
3878 if( ( lpGData
= DP_FindAnyGroup( (IDirectPlay2AImpl
*)This
, idGroup
) ) == NULL
)
3880 return DPERR_INVALIDGROUP
;
3883 if( DPQ_IS_EMPTY( lpGData
->groups
) )
3888 lpGList
= DPQ_FIRST( lpGData
->groups
);
3892 /* FIXME: Should check dwFlags for match here */
3894 if( !(*lpEnumPlayersCallback2
)( lpGList
->lpGData
->dpid
, DPPLAYERTYPE_GROUP
,
3895 &lpGList
->lpGData
->name
, dwFlags
,
3898 return DP_OK
; /* User requested break */
3901 if( DPQ_IS_ENDOFLIST( lpGList
->groups
) )
3906 lpGList
= DPQ_NEXT( lpGList
->groups
);
3913 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
3914 ( LPDIRECTPLAY3A iface
, DPID idGroup
, LPGUID lpguidInstance
,
3915 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
, LPVOID lpContext
,
3918 ICOM_THIS(IDirectPlay3Impl
,iface
);
3919 return DP_IF_EnumGroupsInGroup( This
, idGroup
, lpguidInstance
,
3920 lpEnumPlayersCallback2
, lpContext
, dwFlags
,
3924 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
3925 ( LPDIRECTPLAY3A iface
, DPID idGroup
, LPGUID lpguidInstance
,
3926 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2
, LPVOID lpContext
,
3929 ICOM_THIS(IDirectPlay3Impl
,iface
);
3930 return DP_IF_EnumGroupsInGroup( This
, idGroup
, lpguidInstance
,
3931 lpEnumPlayersCallback2
, lpContext
, dwFlags
,
3935 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
3936 ( LPDIRECTPLAY3A iface
, DWORD dwFlags
, DPID idGroup
, LPVOID lpData
, LPDWORD lpdwDataSize
)
3938 ICOM_THIS(IDirectPlay3Impl
,iface
);
3939 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This
, dwFlags
, idGroup
, lpData
, lpdwDataSize
);
3943 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
3944 ( LPDIRECTPLAY3 iface
, DWORD dwFlags
, DPID idGroup
, LPVOID lpData
, LPDWORD lpdwDataSize
)
3946 ICOM_THIS(IDirectPlay3Impl
,iface
);
3947 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This
, dwFlags
, idGroup
, lpData
, lpdwDataSize
);
3951 BOOL CALLBACK
DP_GetSpLpGuidFromCompoundAddress(
3952 REFGUID guidDataType
,
3957 /* Looking for the GUID of the provider to load */
3958 if( ( IsEqualGUID( guidDataType
, &DPAID_ServiceProvider
) ) ||
3959 ( IsEqualGUID( guidDataType
, &DPAID_LobbyProvider
) )
3962 TRACE( "Found SP/LP (%s) %s (data size = 0x%08lx)\n",
3963 debugstr_guid( guidDataType
), debugstr_guid( lpData
), dwDataSize
);
3965 if( dwDataSize
!= sizeof( GUID
) )
3967 ERR( "Invalid sp/lp guid size 0x%08lx\n", dwDataSize
);
3970 memcpy( lpContext
, lpData
, dwDataSize
);
3972 /* There shouldn't be more than 1 GUID/compound address */
3976 /* Still waiting for what we want */
3981 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
3982 static HMODULE
DP_LoadSP( LPCGUID lpcGuid
, LPSPINITDATA lpSpData
, LPBOOL lpbIsDpSp
)
3985 LPCSTR spSubKey
= "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3986 LPCSTR lpSubKey
= "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3987 LPCSTR guidDataSubKey
= "Guid";
3988 LPCSTR majVerDataSubKey
= "dwReserved1";
3989 LPCSTR minVerDataSubKey
= "dwReserved2";
3990 LPCSTR pathSubKey
= "Path";
3992 TRACE( " request to load %s\n", debugstr_guid( lpcGuid
) );
3994 /* FIXME: Cloned code with a quick hack. */
3995 for( i
=0; i
<2; i
++ )
3998 LPCSTR searchSubKey
;
3999 char subKeyName
[51];
4000 DWORD dwIndex
, sizeOfSubKeyName
=50;
4003 (i
== 0) ? (searchSubKey
= spSubKey
) : (searchSubKey
= lpSubKey
);
4004 *lpbIsDpSp
= (i
== 0) ? TRUE
: FALSE
;
4007 /* Need to loop over the service providers in the registry */
4008 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE
, searchSubKey
,
4009 0, KEY_READ
, &hkResult
) != ERROR_SUCCESS
)
4011 /* Hmmm. Does this mean that there are no service providers? */
4012 ERR(": no service providers?\n");
4016 /* Traverse all the service providers we have available */
4018 RegEnumKeyExA( hkResult
, dwIndex
, subKeyName
, &sizeOfSubKeyName
,
4019 NULL
, NULL
, NULL
, &filetime
) != ERROR_NO_MORE_ITEMS
;
4020 ++dwIndex
, sizeOfSubKeyName
=51 )
4023 HKEY hkServiceProvider
;
4024 GUID serviceProviderGUID
;
4025 DWORD returnType
, sizeOfReturnBuffer
= 255;
4026 char returnBuffer
[256];
4030 TRACE(" this time through: %s\n", subKeyName
);
4032 /* Get a handle for this particular service provider */
4033 if( RegOpenKeyExA( hkResult
, subKeyName
, 0, KEY_READ
,
4034 &hkServiceProvider
) != ERROR_SUCCESS
)
4036 ERR(": what the heck is going on?\n" );
4040 if( RegQueryValueExA( hkServiceProvider
, guidDataSubKey
,
4041 NULL
, &returnType
, returnBuffer
,
4042 &sizeOfReturnBuffer
) != ERROR_SUCCESS
)
4044 ERR(": missing GUID registry data members\n" );
4048 /* FIXME: Check return types to ensure we're interpreting data right */
4049 MultiByteToWideChar( CP_ACP
, 0, returnBuffer
, -1, buff
, sizeof(buff
)/sizeof(WCHAR
) );
4050 CLSIDFromString( (LPCOLESTR
)buff
, &serviceProviderGUID
);
4051 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4053 /* Determine if this is the Service Provider that the user asked for */
4054 if( !IsEqualGUID( &serviceProviderGUID
, lpcGuid
) )
4059 if( i
== 0 ) /* DP SP */
4061 len
= MultiByteToWideChar( CP_ACP
, 0, subKeyName
, -1, NULL
, 0 );
4062 lpSpData
->lpszName
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof(WCHAR
) );
4063 MultiByteToWideChar( CP_ACP
, 0, subKeyName
, -1, lpSpData
->lpszName
, len
);
4066 sizeOfReturnBuffer
= 255;
4068 /* Get dwReserved1 */
4069 if( RegQueryValueExA( hkServiceProvider
, majVerDataSubKey
,
4070 NULL
, &returnType
, returnBuffer
,
4071 &sizeOfReturnBuffer
) != ERROR_SUCCESS
)
4073 ERR(": missing dwReserved1 registry data members\n") ;
4079 lpSpData
->dwReserved1
= GET_DWORD( returnBuffer
);
4082 sizeOfReturnBuffer
= 255;
4084 /* Get dwReserved2 */
4085 if( RegQueryValueExA( hkServiceProvider
, minVerDataSubKey
,
4086 NULL
, &returnType
, returnBuffer
,
4087 &sizeOfReturnBuffer
) != ERROR_SUCCESS
)
4089 ERR(": missing dwReserved1 registry data members\n") ;
4095 lpSpData
->dwReserved2
= GET_DWORD( returnBuffer
);
4098 sizeOfReturnBuffer
= 255;
4100 /* Get the path for this service provider */
4101 if( ( dwTemp
= RegQueryValueExA( hkServiceProvider
, pathSubKey
,
4102 NULL
, NULL
, returnBuffer
,
4103 &sizeOfReturnBuffer
) ) != ERROR_SUCCESS
)
4105 ERR(": missing PATH registry data members: 0x%08lx\n", dwTemp
);
4109 TRACE( "Loading %s\n", returnBuffer
);
4110 return LoadLibraryA( returnBuffer
);
4118 HRESULT
DP_InitializeDPSP( IDirectPlay3Impl
* This
, HMODULE hServiceProvider
)
4121 LPDPSP_SPINIT SPInit
;
4123 /* Initialize the service provider by calling SPInit */
4124 SPInit
= (LPDPSP_SPINIT
)GetProcAddress( hServiceProvider
, "SPInit" );
4126 if( SPInit
== NULL
)
4128 ERR( "Service provider doesn't provide SPInit interface?\n" );
4129 FreeLibrary( hServiceProvider
);
4130 return DPERR_UNAVAILABLE
;
4133 TRACE( "Calling SPInit (DP SP entry point)\n" );
4135 hr
= (*SPInit
)( &This
->dp2
->spData
);
4139 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr
) );
4140 FreeLibrary( hServiceProvider
);
4144 /* FIXME: Need to verify the sanity of the returned callback table
4145 * using IsBadCodePtr */
4146 This
->dp2
->bSPInitialized
= TRUE
;
4148 /* This interface is now initialized as a DP object */
4149 This
->dp2
->connectionInitialized
= DP_SERVICE_PROVIDER
;
4151 /* Store the handle of the module so that we can unload it later */
4152 This
->dp2
->hServiceProvider
= hServiceProvider
;
4158 HRESULT
DP_InitializeDPLSP( IDirectPlay3Impl
* This
, HMODULE hLobbyProvider
)
4161 LPSP_INIT DPLSPInit
;
4163 /* Initialize the service provider by calling SPInit */
4164 DPLSPInit
= (LPSP_INIT
)GetProcAddress( hLobbyProvider
, "DPLSPInit" );
4166 if( DPLSPInit
== NULL
)
4168 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4169 FreeLibrary( hLobbyProvider
);
4170 return DPERR_UNAVAILABLE
;
4173 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4175 hr
= (*DPLSPInit
)( &This
->dp2
->dplspData
);
4179 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr
) );
4180 FreeLibrary( hLobbyProvider
);
4184 /* FIXME: Need to verify the sanity of the returned callback table
4185 * using IsBadCodePtr */
4187 This
->dp2
->bDPLSPInitialized
= TRUE
;
4189 /* This interface is now initialized as a lobby object */
4190 This
->dp2
->connectionInitialized
= DP_LOBBY_PROVIDER
;
4192 /* Store the handle of the module so that we can unload it later */
4193 This
->dp2
->hDPLobbyProvider
= hLobbyProvider
;
4198 static HRESULT WINAPI DP_IF_InitializeConnection
4199 ( IDirectPlay3Impl
* This
, LPVOID lpConnection
, DWORD dwFlags
, BOOL bAnsi
)
4201 HMODULE hServiceProvider
;
4204 const DWORD dwAddrSize
= 80; /* FIXME: Need to calculate it correctly */
4205 BOOL bIsDpSp
; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4207 TRACE("(%p)->(%p,0x%08lx,%u)\n", This
, lpConnection
, dwFlags
, bAnsi
);
4211 return DPERR_INVALIDFLAGS
;
4214 /* Find out what the requested SP is and how large this buffer is */
4215 hr
= DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress
, lpConnection
,
4216 dwAddrSize
, &guidSP
);
4220 ERR( "Invalid compound address?\n" );
4221 return DPERR_UNAVAILABLE
;
4224 /* Load the service provider */
4225 hServiceProvider
= DP_LoadSP( &guidSP
, &This
->dp2
->spData
, &bIsDpSp
);
4227 if( hServiceProvider
== 0 )
4229 ERR( "Unable to load service provider\n" );
4230 return DPERR_UNAVAILABLE
;
4235 /* Fill in what we can of the Service Provider required information.
4236 * The rest was be done in DP_LoadSP
4238 This
->dp2
->spData
.lpAddress
= lpConnection
;
4239 This
->dp2
->spData
.dwAddressSize
= dwAddrSize
;
4240 This
->dp2
->spData
.lpGuid
= &guidSP
;
4242 hr
= DP_InitializeDPSP( This
, hServiceProvider
);
4246 This
->dp2
->dplspData
.lpAddress
= lpConnection
;
4248 hr
= DP_InitializeDPLSP( This
, hServiceProvider
);
4259 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4260 ( LPDIRECTPLAY3A iface
, LPVOID lpConnection
, DWORD dwFlags
)
4262 ICOM_THIS(IDirectPlay3Impl
,iface
);
4264 /* This may not be externally invoked once either an SP or LP is initialized */
4265 if( This
->dp2
->connectionInitialized
!= NO_PROVIDER
)
4267 return DPERR_ALREADYINITIALIZED
;
4270 return DP_IF_InitializeConnection( This
, lpConnection
, dwFlags
, TRUE
);
4273 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4274 ( LPDIRECTPLAY3 iface
, LPVOID lpConnection
, DWORD dwFlags
)
4276 ICOM_THIS(IDirectPlay3Impl
,iface
);
4278 /* This may not be externally invoked once either an SP or LP is initialized */
4279 if( This
->dp2
->connectionInitialized
!= NO_PROVIDER
)
4281 return DPERR_ALREADYINITIALIZED
;
4284 return DP_IF_InitializeConnection( This
, lpConnection
, dwFlags
, FALSE
);
4287 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4288 ( LPDIRECTPLAY3A iface
, LPCDPSESSIONDESC2 lpsd
, DWORD dwFlags
,
4289 LPCDPSECURITYDESC lpSecurity
, LPCDPCREDENTIALS lpCredentials
)
4291 ICOM_THIS(IDirectPlay2Impl
,iface
); /* Yes a dp 2 interface */
4292 return DP_SecureOpen( This
, lpsd
, dwFlags
, lpSecurity
, lpCredentials
, TRUE
);
4295 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4296 ( LPDIRECTPLAY3 iface
, LPCDPSESSIONDESC2 lpsd
, DWORD dwFlags
,
4297 LPCDPSECURITYDESC lpSecurity
, LPCDPCREDENTIALS lpCredentials
)
4299 ICOM_THIS(IDirectPlay2Impl
,iface
); /* Yes a dp 2 interface */
4300 return DP_SecureOpen( This
, lpsd
, dwFlags
, lpSecurity
, lpCredentials
, FALSE
);
4303 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4304 ( LPDIRECTPLAY3A iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
, LPDPCHAT lpChatMessage
)
4306 ICOM_THIS(IDirectPlay3Impl
,iface
);
4307 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This
, idFrom
, idTo
, dwFlags
, lpChatMessage
);
4311 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4312 ( LPDIRECTPLAY3 iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
, LPDPCHAT lpChatMessage
)
4314 ICOM_THIS(IDirectPlay3Impl
,iface
);
4315 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This
, idFrom
, idTo
, dwFlags
, lpChatMessage
);
4319 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4320 ( LPDIRECTPLAY3A iface
, DWORD dwFlags
, DPID idGroup
, LPDPLCONNECTION lpConnection
)
4322 ICOM_THIS(IDirectPlay3Impl
,iface
);
4323 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This
, dwFlags
, idGroup
, lpConnection
);
4327 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4328 ( LPDIRECTPLAY3 iface
, DWORD dwFlags
, DPID idGroup
, LPDPLCONNECTION lpConnection
)
4330 ICOM_THIS(IDirectPlay3Impl
,iface
);
4331 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This
, dwFlags
, idGroup
, lpConnection
);
4335 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4336 ( LPDIRECTPLAY3A iface
, DWORD dwFlags
, DPID idGroup
)
4338 ICOM_THIS(IDirectPlay3Impl
,iface
);
4339 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This
, dwFlags
, idGroup
);
4343 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4344 ( LPDIRECTPLAY3 iface
, DWORD dwFlags
, DPID idGroup
)
4346 ICOM_THIS(IDirectPlay3Impl
,iface
);
4347 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This
, dwFlags
, idGroup
);
4351 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4352 ( LPDIRECTPLAY3A iface
, DPID idGroup
, LPDWORD lpdwFlags
)
4354 ICOM_THIS(IDirectPlay3Impl
,iface
);
4355 FIXME("(%p)->(0x%08lx,%p): stub\n", This
, idGroup
, lpdwFlags
);
4359 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4360 ( LPDIRECTPLAY3 iface
, DPID idGroup
, LPDWORD lpdwFlags
)
4362 ICOM_THIS(IDirectPlay3Impl
,iface
);
4363 FIXME("(%p)->(0x%08lx,%p): stub\n", This
, idGroup
, lpdwFlags
);
4367 static HRESULT WINAPI DP_IF_GetGroupParent
4368 ( IDirectPlay3AImpl
* This
, DPID idGroup
, LPDPID lpidGroup
,
4371 lpGroupData lpGData
;
4373 TRACE("(%p)->(0x%08lx,%p,%u)\n", This
, idGroup
, lpidGroup
, bAnsi
);
4375 if( ( lpGData
= DP_FindAnyGroup( (IDirectPlay2AImpl
*)This
, idGroup
) ) == NULL
)
4377 return DPERR_INVALIDGROUP
;
4380 *lpidGroup
= lpGData
->dpid
;
4385 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4386 ( LPDIRECTPLAY3A iface
, DPID idGroup
, LPDPID lpidGroup
)
4388 ICOM_THIS(IDirectPlay3Impl
,iface
);
4389 return DP_IF_GetGroupParent( This
, idGroup
, lpidGroup
, TRUE
);
4391 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4392 ( LPDIRECTPLAY3 iface
, DPID idGroup
, LPDPID lpidGroup
)
4394 ICOM_THIS(IDirectPlay3Impl
,iface
);
4395 return DP_IF_GetGroupParent( This
, idGroup
, lpidGroup
, FALSE
);
4398 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4399 ( LPDIRECTPLAY3A iface
, DPID idPlayer
, DWORD dwFlags
, LPVOID lpData
, LPDWORD lpdwDataSize
)
4401 ICOM_THIS(IDirectPlay3Impl
,iface
);
4402 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This
, idPlayer
, dwFlags
, lpData
, lpdwDataSize
);
4406 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4407 ( LPDIRECTPLAY3 iface
, DPID idPlayer
, DWORD dwFlags
, LPVOID lpData
, LPDWORD lpdwDataSize
)
4409 ICOM_THIS(IDirectPlay3Impl
,iface
);
4410 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This
, idPlayer
, dwFlags
, lpData
, lpdwDataSize
);
4414 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4415 ( LPDIRECTPLAY3A iface
, DPID idPlayer
, LPDWORD lpdwFlags
)
4417 ICOM_THIS(IDirectPlay3Impl
,iface
);
4418 FIXME("(%p)->(0x%08lx,%p): stub\n", This
, idPlayer
, lpdwFlags
);
4422 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4423 ( LPDIRECTPLAY3 iface
, DPID idPlayer
, LPDWORD lpdwFlags
)
4425 ICOM_THIS(IDirectPlay3Impl
,iface
);
4426 FIXME("(%p)->(0x%08lx,%p): stub\n", This
, idPlayer
, lpdwFlags
);
4430 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4431 ( LPDIRECTPLAY4A iface
, DPID idGroup
, LPDPID lpidGroupOwner
)
4433 ICOM_THIS(IDirectPlay4Impl
,iface
);
4434 FIXME("(%p)->(0x%08lx,%p): stub\n", This
, idGroup
, lpidGroupOwner
);
4438 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4439 ( LPDIRECTPLAY4 iface
, DPID idGroup
, LPDPID lpidGroupOwner
)
4441 ICOM_THIS(IDirectPlay4Impl
,iface
);
4442 FIXME("(%p)->(0x%08lx,%p): stub\n", This
, idGroup
, lpidGroupOwner
);
4446 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4447 ( LPDIRECTPLAY4A iface
, DPID idGroup
, DPID idGroupOwner
)
4449 ICOM_THIS(IDirectPlay4Impl
,iface
);
4450 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This
, idGroup
, idGroupOwner
);
4454 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4455 ( LPDIRECTPLAY4 iface
, DPID idGroup
, DPID idGroupOwner
)
4457 ICOM_THIS(IDirectPlay4Impl
,iface
);
4458 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This
, idGroup
, idGroupOwner
);
4462 static HRESULT WINAPI DP_SendEx
4463 ( IDirectPlay2Impl
* This
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
4464 LPVOID lpData
, DWORD dwDataSize
, DWORD dwPriority
, DWORD dwTimeout
,
4465 LPVOID lpContext
, LPDWORD lpdwMsgID
, BOOL bAnsi
)
4467 lpPlayerList lpPList
;
4468 lpGroupData lpGData
;
4469 BOOL bValidDestination
= FALSE
;
4471 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx,0x%08lx,0x%08lx,%p,%p,%u)"
4473 This
, idFrom
, idTo
, dwFlags
, lpData
, dwDataSize
, dwPriority
,
4474 dwTimeout
, lpContext
, lpdwMsgID
, bAnsi
);
4476 /* FIXME: Add parameter checking */
4477 /* FIXME: First call to this needs to aquire a message id which will be
4478 * used for multiple sends
4481 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4483 /* Verify that the message is being sent from a valid local player. The
4484 * from player may be anonymous DPID_UNKNOWN
4486 if( idFrom
!= DPID_UNKNOWN
)
4488 if( ( lpPList
= DP_FindPlayer( This
, idFrom
) ) == NULL
)
4490 WARN( "INFO: Invalid from player 0x%08lx\n", idFrom
);
4491 return DPERR_INVALIDPLAYER
;
4495 /* Verify that the message is being sent to a valid player, group or to
4496 * everyone. If it's valid, send it to those players.
4498 if( idTo
== DPID_ALLPLAYERS
)
4500 bValidDestination
= TRUE
;
4502 /* See if SP has the ability to multicast. If so, use it */
4503 if( This
->dp2
->spData
.lpCB
->SendToGroupEx
)
4505 FIXME( "Use group sendex to group 0\n" );
4507 else if( This
->dp2
->spData
.lpCB
->SendToGroup
) /* obsolete interface */
4509 FIXME( "Use obsolete group send to group 0\n" );
4511 else /* No multicast, multiplicate */
4513 /* Send to all players we know about */
4514 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4518 if( ( !bValidDestination
) &&
4519 ( DP_FindPlayer( This
, idTo
) != NULL
)
4522 bValidDestination
= TRUE
;
4524 /* Have the service provider send this message */
4525 /* FIXME: Could optimize for local interface sends */
4526 return DP_SP_SendEx( This
, dwFlags
, lpData
, dwDataSize
, dwPriority
,
4527 dwTimeout
, lpContext
, lpdwMsgID
);
4530 if( ( !bValidDestination
) &&
4531 ( ( lpGData
= DP_FindAnyGroup( This
, idTo
) ) != NULL
)
4534 bValidDestination
= TRUE
;
4536 /* See if SP has the ability to multicast. If so, use it */
4537 if( This
->dp2
->spData
.lpCB
->SendToGroupEx
)
4539 FIXME( "Use group sendex\n" );
4541 else if( This
->dp2
->spData
.lpCB
->SendToGroup
) /* obsolete interface */
4543 FIXME( "Use obsolete group send to group\n" );
4545 else /* No multicast, multiplicate */
4547 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4555 This
->dp2
->hReplyEvent
= CreateEventA( NULL
, FALSE
, FALSE
, NULL
);
4557 dwWaitReturn
= WaitForSingleObject( hReplyEvent
, dwTimeout
);
4558 if( dwWaitReturn
!= WAIT_OBJECT_0
)
4560 ERR( "Wait failed 0x%08lx\n", dwWaitReturn
);
4566 if( !bValidDestination
)
4568 return DPERR_INVALIDPLAYER
;
4572 /* FIXME: Should return what the send returned */
4578 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4579 ( LPDIRECTPLAY4A iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
4580 LPVOID lpData
, DWORD dwDataSize
, DWORD dwPriority
, DWORD dwTimeout
,
4581 LPVOID lpContext
, LPDWORD lpdwMsgID
)
4583 ICOM_THIS(IDirectPlay2Impl
,iface
); /* yes downcast to 2 */
4584 return DP_SendEx( This
, idFrom
, idTo
, dwFlags
, lpData
, dwDataSize
,
4585 dwPriority
, dwTimeout
, lpContext
, lpdwMsgID
, TRUE
);
4588 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4589 ( LPDIRECTPLAY4 iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
4590 LPVOID lpData
, DWORD dwDataSize
, DWORD dwPriority
, DWORD dwTimeout
,
4591 LPVOID lpContext
, LPDWORD lpdwMsgID
)
4593 ICOM_THIS(IDirectPlay2Impl
,iface
); /* yes downcast to 2 */
4594 return DP_SendEx( This
, idFrom
, idTo
, dwFlags
, lpData
, dwDataSize
,
4595 dwPriority
, dwTimeout
, lpContext
, lpdwMsgID
, FALSE
);
4598 static HRESULT WINAPI DP_SP_SendEx
4599 ( IDirectPlay2Impl
* This
, DWORD dwFlags
,
4600 LPVOID lpData
, DWORD dwDataSize
, DWORD dwPriority
, DWORD dwTimeout
,
4601 LPVOID lpContext
, LPDWORD lpdwMsgID
)
4605 FIXME( ": stub\n" );
4607 /* FIXME: This queuing should only be for async messages */
4609 lpMElem
= (LPDPMSG
)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
4610 sizeof( *lpMElem
) );
4611 lpMElem
->msg
= (DPMSG_GENERIC
*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
4614 CopyMemory( lpMElem
->msg
, lpData
, dwDataSize
);
4616 /* FIXME: Need to queue based on priority */
4617 DPQ_INSERT( This
->dp2
->sendMsgs
, lpMElem
, msgs
);
4622 static HRESULT WINAPI DP_IF_GetMessageQueue
4623 ( IDirectPlay4Impl
* This
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
4624 LPDWORD lpdwNumMsgs
, LPDWORD lpdwNumBytes
, BOOL bAnsi
)
4628 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,%p,%u): semi stub\n",
4629 This
, idFrom
, idTo
, dwFlags
, lpdwNumMsgs
, lpdwNumBytes
, bAnsi
);
4631 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4632 /* FIXME: What about sends which are not immediate? */
4634 if( This
->dp2
->spData
.lpCB
->GetMessageQueue
)
4636 DPSP_GETMESSAGEQUEUEDATA data
;
4638 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4640 /* FIXME: None of this is documented :( */
4642 data
.lpISP
= This
->dp2
->spData
.lpISP
;
4643 data
.dwFlags
= dwFlags
;
4644 data
.idFrom
= idFrom
;
4646 data
.lpdwNumMsgs
= lpdwNumMsgs
;
4647 data
.lpdwNumBytes
= lpdwNumBytes
;
4649 hr
= (*This
->dp2
->spData
.lpCB
->GetMessageQueue
)( &data
);
4653 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4659 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4660 ( LPDIRECTPLAY4A iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
4661 LPDWORD lpdwNumMsgs
, LPDWORD lpdwNumBytes
)
4663 ICOM_THIS(IDirectPlay4Impl
,iface
);
4664 return DP_IF_GetMessageQueue( This
, idFrom
, idTo
, dwFlags
, lpdwNumMsgs
,
4665 lpdwNumBytes
, TRUE
);
4668 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4669 ( LPDIRECTPLAY4 iface
, DPID idFrom
, DPID idTo
, DWORD dwFlags
,
4670 LPDWORD lpdwNumMsgs
, LPDWORD lpdwNumBytes
)
4672 ICOM_THIS(IDirectPlay4Impl
,iface
);
4673 return DP_IF_GetMessageQueue( This
, idFrom
, idTo
, dwFlags
, lpdwNumMsgs
,
4674 lpdwNumBytes
, FALSE
);
4677 static HRESULT WINAPI DP_IF_CancelMessage
4678 ( IDirectPlay4Impl
* This
, DWORD dwMsgID
, DWORD dwFlags
,
4679 DWORD dwMinPriority
, DWORD dwMaxPriority
, BOOL bAnsi
)
4683 FIXME( "(%p)->(0x%08lx,0x%08lx,%u): semi stub\n",
4684 This
, dwMsgID
, dwFlags
, bAnsi
);
4686 if( This
->dp2
->spData
.lpCB
->Cancel
)
4688 DPSP_CANCELDATA data
;
4690 TRACE( "Calling SP Cancel\n" );
4692 /* FIXME: Undocumented callback */
4694 data
.lpISP
= This
->dp2
->spData
.lpISP
;
4695 data
.dwFlags
= dwFlags
;
4696 data
.lprglpvSPMsgID
= NULL
;
4697 data
.cSPMsgID
= dwMsgID
;
4698 data
.dwMinPriority
= dwMinPriority
;
4699 data
.dwMaxPriority
= dwMaxPriority
;
4701 hr
= (*This
->dp2
->spData
.lpCB
->Cancel
)( &data
);
4705 FIXME( "SP doesn't implement Cancel\n" );
4711 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
4712 ( LPDIRECTPLAY4A iface
, DWORD dwMsgID
, DWORD dwFlags
)
4714 ICOM_THIS(IDirectPlay4Impl
,iface
);
4718 return DPERR_INVALIDFLAGS
;
4723 dwFlags
|= DPCANCELSEND_ALL
;
4726 return DP_IF_CancelMessage( This
, dwMsgID
, dwFlags
, 0, 0, TRUE
);
4729 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
4730 ( LPDIRECTPLAY4 iface
, DWORD dwMsgID
, DWORD dwFlags
)
4732 ICOM_THIS(IDirectPlay4Impl
,iface
);
4736 return DPERR_INVALIDFLAGS
;
4741 dwFlags
|= DPCANCELSEND_ALL
;
4744 return DP_IF_CancelMessage( This
, dwMsgID
, dwFlags
, 0, 0, FALSE
);
4747 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
4748 ( LPDIRECTPLAY4A iface
, DWORD dwMinPriority
, DWORD dwMaxPriority
,
4751 ICOM_THIS(IDirectPlay4Impl
,iface
);
4755 return DPERR_INVALIDFLAGS
;
4758 return DP_IF_CancelMessage( This
, 0, DPCANCELSEND_PRIORITY
, dwMinPriority
,
4759 dwMaxPriority
, TRUE
);
4762 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
4763 ( LPDIRECTPLAY4 iface
, DWORD dwMinPriority
, DWORD dwMaxPriority
,
4766 ICOM_THIS(IDirectPlay4Impl
,iface
);
4770 return DPERR_INVALIDFLAGS
;
4773 return DP_IF_CancelMessage( This
, 0, DPCANCELSEND_PRIORITY
, dwMinPriority
,
4774 dwMaxPriority
, FALSE
);
4777 /* Note: Hack so we can reuse the old functions without compiler warnings */
4778 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4779 # define XCAST(fun) (typeof(directPlay2WVT.fun))
4781 # define XCAST(fun) (void*)
4784 static ICOM_VTABLE(IDirectPlay2
) directPlay2WVT
=
4786 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4787 XCAST(QueryInterface
)DP_QueryInterface
,
4788 XCAST(AddRef
)DP_AddRef
,
4789 XCAST(Release
)DP_Release
,
4791 DirectPlay2WImpl_AddPlayerToGroup
,
4792 DirectPlay2WImpl_Close
,
4793 DirectPlay2WImpl_CreateGroup
,
4794 DirectPlay2WImpl_CreatePlayer
,
4795 DirectPlay2WImpl_DeletePlayerFromGroup
,
4796 DirectPlay2WImpl_DestroyGroup
,
4797 DirectPlay2WImpl_DestroyPlayer
,
4798 DirectPlay2WImpl_EnumGroupPlayers
,
4799 DirectPlay2WImpl_EnumGroups
,
4800 DirectPlay2WImpl_EnumPlayers
,
4801 DirectPlay2WImpl_EnumSessions
,
4802 DirectPlay2WImpl_GetCaps
,
4803 DirectPlay2WImpl_GetGroupData
,
4804 DirectPlay2WImpl_GetGroupName
,
4805 DirectPlay2WImpl_GetMessageCount
,
4806 DirectPlay2WImpl_GetPlayerAddress
,
4807 DirectPlay2WImpl_GetPlayerCaps
,
4808 DirectPlay2WImpl_GetPlayerData
,
4809 DirectPlay2WImpl_GetPlayerName
,
4810 DirectPlay2WImpl_GetSessionDesc
,
4811 DirectPlay2WImpl_Initialize
,
4812 DirectPlay2WImpl_Open
,
4813 DirectPlay2WImpl_Receive
,
4814 DirectPlay2WImpl_Send
,
4815 DirectPlay2WImpl_SetGroupData
,
4816 DirectPlay2WImpl_SetGroupName
,
4817 DirectPlay2WImpl_SetPlayerData
,
4818 DirectPlay2WImpl_SetPlayerName
,
4819 DirectPlay2WImpl_SetSessionDesc
4823 /* Note: Hack so we can reuse the old functions without compiler warnings */
4824 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4825 # define XCAST(fun) (typeof(directPlay2AVT.fun))
4827 # define XCAST(fun) (void*)
4830 static ICOM_VTABLE(IDirectPlay2
) directPlay2AVT
=
4832 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4833 XCAST(QueryInterface
)DP_QueryInterface
,
4834 XCAST(AddRef
)DP_AddRef
,
4835 XCAST(Release
)DP_Release
,
4837 DirectPlay2AImpl_AddPlayerToGroup
,
4838 DirectPlay2AImpl_Close
,
4839 DirectPlay2AImpl_CreateGroup
,
4840 DirectPlay2AImpl_CreatePlayer
,
4841 DirectPlay2AImpl_DeletePlayerFromGroup
,
4842 DirectPlay2AImpl_DestroyGroup
,
4843 DirectPlay2AImpl_DestroyPlayer
,
4844 DirectPlay2AImpl_EnumGroupPlayers
,
4845 DirectPlay2AImpl_EnumGroups
,
4846 DirectPlay2AImpl_EnumPlayers
,
4847 DirectPlay2AImpl_EnumSessions
,
4848 DirectPlay2AImpl_GetCaps
,
4849 DirectPlay2AImpl_GetGroupData
,
4850 DirectPlay2AImpl_GetGroupName
,
4851 DirectPlay2AImpl_GetMessageCount
,
4852 DirectPlay2AImpl_GetPlayerAddress
,
4853 DirectPlay2AImpl_GetPlayerCaps
,
4854 DirectPlay2AImpl_GetPlayerData
,
4855 DirectPlay2AImpl_GetPlayerName
,
4856 DirectPlay2AImpl_GetSessionDesc
,
4857 DirectPlay2AImpl_Initialize
,
4858 DirectPlay2AImpl_Open
,
4859 DirectPlay2AImpl_Receive
,
4860 DirectPlay2AImpl_Send
,
4861 DirectPlay2AImpl_SetGroupData
,
4862 DirectPlay2AImpl_SetGroupName
,
4863 DirectPlay2AImpl_SetPlayerData
,
4864 DirectPlay2AImpl_SetPlayerName
,
4865 DirectPlay2AImpl_SetSessionDesc
4870 /* Note: Hack so we can reuse the old functions without compiler warnings */
4871 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4872 # define XCAST(fun) (typeof(directPlay3AVT.fun))
4874 # define XCAST(fun) (void*)
4877 static ICOM_VTABLE(IDirectPlay3
) directPlay3AVT
=
4879 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4880 XCAST(QueryInterface
)DP_QueryInterface
,
4881 XCAST(AddRef
)DP_AddRef
,
4882 XCAST(Release
)DP_Release
,
4884 XCAST(AddPlayerToGroup
)DirectPlay2AImpl_AddPlayerToGroup
,
4885 XCAST(Close
)DirectPlay2AImpl_Close
,
4886 XCAST(CreateGroup
)DirectPlay2AImpl_CreateGroup
,
4887 XCAST(CreatePlayer
)DirectPlay2AImpl_CreatePlayer
,
4888 XCAST(DeletePlayerFromGroup
)DirectPlay2AImpl_DeletePlayerFromGroup
,
4889 XCAST(DestroyGroup
)DirectPlay2AImpl_DestroyGroup
,
4890 XCAST(DestroyPlayer
)DirectPlay2AImpl_DestroyPlayer
,
4891 XCAST(EnumGroupPlayers
)DirectPlay2AImpl_EnumGroupPlayers
,
4892 XCAST(EnumGroups
)DirectPlay2AImpl_EnumGroups
,
4893 XCAST(EnumPlayers
)DirectPlay2AImpl_EnumPlayers
,
4894 XCAST(EnumSessions
)DirectPlay2AImpl_EnumSessions
,
4895 XCAST(GetCaps
)DirectPlay2AImpl_GetCaps
,
4896 XCAST(GetGroupData
)DirectPlay2AImpl_GetGroupData
,
4897 XCAST(GetGroupName
)DirectPlay2AImpl_GetGroupName
,
4898 XCAST(GetMessageCount
)DirectPlay2AImpl_GetMessageCount
,
4899 XCAST(GetPlayerAddress
)DirectPlay2AImpl_GetPlayerAddress
,
4900 XCAST(GetPlayerCaps
)DirectPlay2AImpl_GetPlayerCaps
,
4901 XCAST(GetPlayerData
)DirectPlay2AImpl_GetPlayerData
,
4902 XCAST(GetPlayerName
)DirectPlay2AImpl_GetPlayerName
,
4903 XCAST(GetSessionDesc
)DirectPlay2AImpl_GetSessionDesc
,
4904 XCAST(Initialize
)DirectPlay2AImpl_Initialize
,
4905 XCAST(Open
)DirectPlay2AImpl_Open
,
4906 XCAST(Receive
)DirectPlay2AImpl_Receive
,
4907 XCAST(Send
)DirectPlay2AImpl_Send
,
4908 XCAST(SetGroupData
)DirectPlay2AImpl_SetGroupData
,
4909 XCAST(SetGroupName
)DirectPlay2AImpl_SetGroupName
,
4910 XCAST(SetPlayerData
)DirectPlay2AImpl_SetPlayerData
,
4911 XCAST(SetPlayerName
)DirectPlay2AImpl_SetPlayerName
,
4912 XCAST(SetSessionDesc
)DirectPlay2AImpl_SetSessionDesc
,
4914 DirectPlay3AImpl_AddGroupToGroup
,
4915 DirectPlay3AImpl_CreateGroupInGroup
,
4916 DirectPlay3AImpl_DeleteGroupFromGroup
,
4917 DirectPlay3AImpl_EnumConnections
,
4918 DirectPlay3AImpl_EnumGroupsInGroup
,
4919 DirectPlay3AImpl_GetGroupConnectionSettings
,
4920 DirectPlay3AImpl_InitializeConnection
,
4921 DirectPlay3AImpl_SecureOpen
,
4922 DirectPlay3AImpl_SendChatMessage
,
4923 DirectPlay3AImpl_SetGroupConnectionSettings
,
4924 DirectPlay3AImpl_StartSession
,
4925 DirectPlay3AImpl_GetGroupFlags
,
4926 DirectPlay3AImpl_GetGroupParent
,
4927 DirectPlay3AImpl_GetPlayerAccount
,
4928 DirectPlay3AImpl_GetPlayerFlags
4932 /* Note: Hack so we can reuse the old functions without compiler warnings */
4933 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4934 # define XCAST(fun) (typeof(directPlay3WVT.fun))
4936 # define XCAST(fun) (void*)
4938 static ICOM_VTABLE(IDirectPlay3
) directPlay3WVT
=
4940 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4941 XCAST(QueryInterface
)DP_QueryInterface
,
4942 XCAST(AddRef
)DP_AddRef
,
4943 XCAST(Release
)DP_Release
,
4945 XCAST(AddPlayerToGroup
)DirectPlay2WImpl_AddPlayerToGroup
,
4946 XCAST(Close
)DirectPlay2WImpl_Close
,
4947 XCAST(CreateGroup
)DirectPlay2WImpl_CreateGroup
,
4948 XCAST(CreatePlayer
)DirectPlay2WImpl_CreatePlayer
,
4949 XCAST(DeletePlayerFromGroup
)DirectPlay2WImpl_DeletePlayerFromGroup
,
4950 XCAST(DestroyGroup
)DirectPlay2WImpl_DestroyGroup
,
4951 XCAST(DestroyPlayer
)DirectPlay2WImpl_DestroyPlayer
,
4952 XCAST(EnumGroupPlayers
)DirectPlay2WImpl_EnumGroupPlayers
,
4953 XCAST(EnumGroups
)DirectPlay2WImpl_EnumGroups
,
4954 XCAST(EnumPlayers
)DirectPlay2WImpl_EnumPlayers
,
4955 XCAST(EnumSessions
)DirectPlay2WImpl_EnumSessions
,
4956 XCAST(GetCaps
)DirectPlay2WImpl_GetCaps
,
4957 XCAST(GetGroupData
)DirectPlay2WImpl_GetGroupData
,
4958 XCAST(GetGroupName
)DirectPlay2WImpl_GetGroupName
,
4959 XCAST(GetMessageCount
)DirectPlay2WImpl_GetMessageCount
,
4960 XCAST(GetPlayerAddress
)DirectPlay2WImpl_GetPlayerAddress
,
4961 XCAST(GetPlayerCaps
)DirectPlay2WImpl_GetPlayerCaps
,
4962 XCAST(GetPlayerData
)DirectPlay2WImpl_GetPlayerData
,
4963 XCAST(GetPlayerName
)DirectPlay2WImpl_GetPlayerName
,
4964 XCAST(GetSessionDesc
)DirectPlay2WImpl_GetSessionDesc
,
4965 XCAST(Initialize
)DirectPlay2WImpl_Initialize
,
4966 XCAST(Open
)DirectPlay2WImpl_Open
,
4967 XCAST(Receive
)DirectPlay2WImpl_Receive
,
4968 XCAST(Send
)DirectPlay2WImpl_Send
,
4969 XCAST(SetGroupData
)DirectPlay2WImpl_SetGroupData
,
4970 XCAST(SetGroupName
)DirectPlay2WImpl_SetGroupName
,
4971 XCAST(SetPlayerData
)DirectPlay2WImpl_SetPlayerData
,
4972 XCAST(SetPlayerName
)DirectPlay2WImpl_SetPlayerName
,
4973 XCAST(SetSessionDesc
)DirectPlay2WImpl_SetSessionDesc
,
4975 DirectPlay3WImpl_AddGroupToGroup
,
4976 DirectPlay3WImpl_CreateGroupInGroup
,
4977 DirectPlay3WImpl_DeleteGroupFromGroup
,
4978 DirectPlay3WImpl_EnumConnections
,
4979 DirectPlay3WImpl_EnumGroupsInGroup
,
4980 DirectPlay3WImpl_GetGroupConnectionSettings
,
4981 DirectPlay3WImpl_InitializeConnection
,
4982 DirectPlay3WImpl_SecureOpen
,
4983 DirectPlay3WImpl_SendChatMessage
,
4984 DirectPlay3WImpl_SetGroupConnectionSettings
,
4985 DirectPlay3WImpl_StartSession
,
4986 DirectPlay3WImpl_GetGroupFlags
,
4987 DirectPlay3WImpl_GetGroupParent
,
4988 DirectPlay3WImpl_GetPlayerAccount
,
4989 DirectPlay3WImpl_GetPlayerFlags
4993 /* Note: Hack so we can reuse the old functions without compiler warnings */
4994 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4995 # define XCAST(fun) (typeof(directPlay4WVT.fun))
4997 # define XCAST(fun) (void*)
4999 static ICOM_VTABLE(IDirectPlay4
) directPlay4WVT
=
5001 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5002 XCAST(QueryInterface
)DP_QueryInterface
,
5003 XCAST(AddRef
)DP_AddRef
,
5004 XCAST(Release
)DP_Release
,
5006 XCAST(AddPlayerToGroup
)DirectPlay2WImpl_AddPlayerToGroup
,
5007 XCAST(Close
)DirectPlay2WImpl_Close
,
5008 XCAST(CreateGroup
)DirectPlay2WImpl_CreateGroup
,
5009 XCAST(CreatePlayer
)DirectPlay2WImpl_CreatePlayer
,
5010 XCAST(DeletePlayerFromGroup
)DirectPlay2WImpl_DeletePlayerFromGroup
,
5011 XCAST(DestroyGroup
)DirectPlay2WImpl_DestroyGroup
,
5012 XCAST(DestroyPlayer
)DirectPlay2WImpl_DestroyPlayer
,
5013 XCAST(EnumGroupPlayers
)DirectPlay2WImpl_EnumGroupPlayers
,
5014 XCAST(EnumGroups
)DirectPlay2WImpl_EnumGroups
,
5015 XCAST(EnumPlayers
)DirectPlay2WImpl_EnumPlayers
,
5016 XCAST(EnumSessions
)DirectPlay2WImpl_EnumSessions
,
5017 XCAST(GetCaps
)DirectPlay2WImpl_GetCaps
,
5018 XCAST(GetGroupData
)DirectPlay2WImpl_GetGroupData
,
5019 XCAST(GetGroupName
)DirectPlay2WImpl_GetGroupName
,
5020 XCAST(GetMessageCount
)DirectPlay2WImpl_GetMessageCount
,
5021 XCAST(GetPlayerAddress
)DirectPlay2WImpl_GetPlayerAddress
,
5022 XCAST(GetPlayerCaps
)DirectPlay2WImpl_GetPlayerCaps
,
5023 XCAST(GetPlayerData
)DirectPlay2WImpl_GetPlayerData
,
5024 XCAST(GetPlayerName
)DirectPlay2WImpl_GetPlayerName
,
5025 XCAST(GetSessionDesc
)DirectPlay2WImpl_GetSessionDesc
,
5026 XCAST(Initialize
)DirectPlay2WImpl_Initialize
,
5027 XCAST(Open
)DirectPlay2WImpl_Open
,
5028 XCAST(Receive
)DirectPlay2WImpl_Receive
,
5029 XCAST(Send
)DirectPlay2WImpl_Send
,
5030 XCAST(SetGroupData
)DirectPlay2WImpl_SetGroupData
,
5031 XCAST(SetGroupName
)DirectPlay2WImpl_SetGroupName
,
5032 XCAST(SetPlayerData
)DirectPlay2WImpl_SetPlayerData
,
5033 XCAST(SetPlayerName
)DirectPlay2WImpl_SetPlayerName
,
5034 XCAST(SetSessionDesc
)DirectPlay2WImpl_SetSessionDesc
,
5036 XCAST(AddGroupToGroup
)DirectPlay3WImpl_AddGroupToGroup
,
5037 XCAST(CreateGroupInGroup
)DirectPlay3WImpl_CreateGroupInGroup
,
5038 XCAST(DeleteGroupFromGroup
)DirectPlay3WImpl_DeleteGroupFromGroup
,
5039 XCAST(EnumConnections
)DirectPlay3WImpl_EnumConnections
,
5040 XCAST(EnumGroupsInGroup
)DirectPlay3WImpl_EnumGroupsInGroup
,
5041 XCAST(GetGroupConnectionSettings
)DirectPlay3WImpl_GetGroupConnectionSettings
,
5042 XCAST(InitializeConnection
)DirectPlay3WImpl_InitializeConnection
,
5043 XCAST(SecureOpen
)DirectPlay3WImpl_SecureOpen
,
5044 XCAST(SendChatMessage
)DirectPlay3WImpl_SendChatMessage
,
5045 XCAST(SetGroupConnectionSettings
)DirectPlay3WImpl_SetGroupConnectionSettings
,
5046 XCAST(StartSession
)DirectPlay3WImpl_StartSession
,
5047 XCAST(GetGroupFlags
)DirectPlay3WImpl_GetGroupFlags
,
5048 XCAST(GetGroupParent
)DirectPlay3WImpl_GetGroupParent
,
5049 XCAST(GetPlayerAccount
)DirectPlay3WImpl_GetPlayerAccount
,
5050 XCAST(GetPlayerFlags
)DirectPlay3WImpl_GetPlayerFlags
,
5052 DirectPlay4WImpl_GetGroupOwner
,
5053 DirectPlay4WImpl_SetGroupOwner
,
5054 DirectPlay4WImpl_SendEx
,
5055 DirectPlay4WImpl_GetMessageQueue
,
5056 DirectPlay4WImpl_CancelMessage
,
5057 DirectPlay4WImpl_CancelPriority
5062 /* Note: Hack so we can reuse the old functions without compiler warnings */
5063 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5064 # define XCAST(fun) (typeof(directPlay4AVT.fun))
5066 # define XCAST(fun) (void*)
5068 static ICOM_VTABLE(IDirectPlay4
) directPlay4AVT
=
5070 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5071 XCAST(QueryInterface
)DP_QueryInterface
,
5072 XCAST(AddRef
)DP_AddRef
,
5073 XCAST(Release
)DP_Release
,
5075 XCAST(AddPlayerToGroup
)DirectPlay2AImpl_AddPlayerToGroup
,
5076 XCAST(Close
)DirectPlay2AImpl_Close
,
5077 XCAST(CreateGroup
)DirectPlay2AImpl_CreateGroup
,
5078 XCAST(CreatePlayer
)DirectPlay2AImpl_CreatePlayer
,
5079 XCAST(DeletePlayerFromGroup
)DirectPlay2AImpl_DeletePlayerFromGroup
,
5080 XCAST(DestroyGroup
)DirectPlay2AImpl_DestroyGroup
,
5081 XCAST(DestroyPlayer
)DirectPlay2AImpl_DestroyPlayer
,
5082 XCAST(EnumGroupPlayers
)DirectPlay2AImpl_EnumGroupPlayers
,
5083 XCAST(EnumGroups
)DirectPlay2AImpl_EnumGroups
,
5084 XCAST(EnumPlayers
)DirectPlay2AImpl_EnumPlayers
,
5085 XCAST(EnumSessions
)DirectPlay2AImpl_EnumSessions
,
5086 XCAST(GetCaps
)DirectPlay2AImpl_GetCaps
,
5087 XCAST(GetGroupData
)DirectPlay2AImpl_GetGroupData
,
5088 XCAST(GetGroupName
)DirectPlay2AImpl_GetGroupName
,
5089 XCAST(GetMessageCount
)DirectPlay2AImpl_GetMessageCount
,
5090 XCAST(GetPlayerAddress
)DirectPlay2AImpl_GetPlayerAddress
,
5091 XCAST(GetPlayerCaps
)DirectPlay2AImpl_GetPlayerCaps
,
5092 XCAST(GetPlayerData
)DirectPlay2AImpl_GetPlayerData
,
5093 XCAST(GetPlayerName
)DirectPlay2AImpl_GetPlayerName
,
5094 XCAST(GetSessionDesc
)DirectPlay2AImpl_GetSessionDesc
,
5095 XCAST(Initialize
)DirectPlay2AImpl_Initialize
,
5096 XCAST(Open
)DirectPlay2AImpl_Open
,
5097 XCAST(Receive
)DirectPlay2AImpl_Receive
,
5098 XCAST(Send
)DirectPlay2AImpl_Send
,
5099 XCAST(SetGroupData
)DirectPlay2AImpl_SetGroupData
,
5100 XCAST(SetGroupName
)DirectPlay2AImpl_SetGroupName
,
5101 XCAST(SetPlayerData
)DirectPlay2AImpl_SetPlayerData
,
5102 XCAST(SetPlayerName
)DirectPlay2AImpl_SetPlayerName
,
5103 XCAST(SetSessionDesc
)DirectPlay2AImpl_SetSessionDesc
,
5105 XCAST(AddGroupToGroup
)DirectPlay3AImpl_AddGroupToGroup
,
5106 XCAST(CreateGroupInGroup
)DirectPlay3AImpl_CreateGroupInGroup
,
5107 XCAST(DeleteGroupFromGroup
)DirectPlay3AImpl_DeleteGroupFromGroup
,
5108 XCAST(EnumConnections
)DirectPlay3AImpl_EnumConnections
,
5109 XCAST(EnumGroupsInGroup
)DirectPlay3AImpl_EnumGroupsInGroup
,
5110 XCAST(GetGroupConnectionSettings
)DirectPlay3AImpl_GetGroupConnectionSettings
,
5111 XCAST(InitializeConnection
)DirectPlay3AImpl_InitializeConnection
,
5112 XCAST(SecureOpen
)DirectPlay3AImpl_SecureOpen
,
5113 XCAST(SendChatMessage
)DirectPlay3AImpl_SendChatMessage
,
5114 XCAST(SetGroupConnectionSettings
)DirectPlay3AImpl_SetGroupConnectionSettings
,
5115 XCAST(StartSession
)DirectPlay3AImpl_StartSession
,
5116 XCAST(GetGroupFlags
)DirectPlay3AImpl_GetGroupFlags
,
5117 XCAST(GetGroupParent
)DirectPlay3AImpl_GetGroupParent
,
5118 XCAST(GetPlayerAccount
)DirectPlay3AImpl_GetPlayerAccount
,
5119 XCAST(GetPlayerFlags
)DirectPlay3AImpl_GetPlayerFlags
,
5121 DirectPlay4AImpl_GetGroupOwner
,
5122 DirectPlay4AImpl_SetGroupOwner
,
5123 DirectPlay4AImpl_SendEx
,
5124 DirectPlay4AImpl_GetMessageQueue
,
5125 DirectPlay4AImpl_CancelMessage
,
5126 DirectPlay4AImpl_CancelPriority
5131 HRESULT
DP_GetSPPlayerData( IDirectPlay2Impl
* lpDP
,
5135 lpPlayerList lpPlayer
= DP_FindPlayer( lpDP
, idPlayer
);
5137 if( lpPlayer
== NULL
)
5139 return DPERR_INVALIDPLAYER
;
5142 *lplpData
= lpPlayer
->lpPData
->lpSPPlayerData
;
5148 HRESULT
DP_SetSPPlayerData( IDirectPlay2Impl
* lpDP
,
5152 lpPlayerList lpPlayer
= DP_FindPlayer( lpDP
, idPlayer
);
5154 if( lpPlayer
== NULL
)
5156 return DPERR_INVALIDPLAYER
;
5159 lpPlayer
->lpPData
->lpSPPlayerData
= lpData
;
5164 /***************************************************************************
5165 * DirectPlayEnumerate [DPLAYX.9]
5166 * DirectPlayEnumerateA [DPLAYX.2]
5168 * The pointer to the structure lpContext will be filled with the
5169 * appropriate data for each service offered by the OS. These services are
5170 * not necessarily available on this particular machine but are defined
5171 * as simple service providers under the "Service Providers" registry key.
5172 * This structure is then passed to lpEnumCallback for each of the different
5175 * This API is useful only for applications written using DirectX3 or
5176 * worse. It is superceeded by IDirectPlay3::EnumConnections which also
5177 * gives information on the actual connections.
5179 * defn of a service provider:
5180 * A dynamic-link library used by DirectPlay to communicate over a network.
5181 * The service provider contains all the network-specific code required
5182 * to send and receive messages. Online services and network operators can
5183 * supply service providers to use specialized hardware, protocols, communications
5184 * media, and network resources.
5186 * TODO: Allocate string buffer space from the heap (length from reg)
5187 * Pass real device driver numbers...
5188 * Get the GUID properly...
5190 HRESULT WINAPI
DirectPlayEnumerateA( LPDPENUMDPCALLBACKA lpEnumCallback
,
5195 LPCSTR searchSubKey
= "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
5197 DWORD sizeOfSubKeyName
=50;
5198 char subKeyName
[51];
5201 TRACE(": lpEnumCallback=%p lpContext=%p\n", lpEnumCallback
, lpContext
);
5203 if( !lpEnumCallback
|| !*lpEnumCallback
)
5205 return DPERR_INVALIDPARAMS
;
5208 /* Need to loop over the service providers in the registry */
5209 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE
, searchSubKey
,
5210 0, KEY_READ
, &hkResult
) != ERROR_SUCCESS
)
5212 /* Hmmm. Does this mean that there are no service providers? */
5213 ERR(": no service providers?\n");
5217 /* Traverse all the service providers we have available */
5219 RegEnumKeyExA( hkResult
, dwIndex
, subKeyName
, &sizeOfSubKeyName
,
5220 NULL
, NULL
, NULL
, &filetime
) != ERROR_NO_MORE_ITEMS
;
5221 ++dwIndex
, sizeOfSubKeyName
=50 )
5223 LPSTR majVerDataSubKey
= "dwReserved1";
5224 LPSTR minVerDataSubKey
= "dwReserved2";
5225 LPSTR guidDataSubKey
= "Guid";
5226 HKEY hkServiceProvider
;
5227 GUID serviceProviderGUID
;
5228 DWORD returnTypeGUID
, returnTypeReserved
, sizeOfReturnBuffer
= 50;
5229 char returnBuffer
[51];
5231 DWORD majVersionNum
, minVersionNum
= 0;
5233 TRACE(" this time through: %s\n", subKeyName
);
5235 /* Get a handle for this particular service provider */
5236 if( RegOpenKeyExA( hkResult
, subKeyName
, 0, KEY_READ
,
5237 &hkServiceProvider
) != ERROR_SUCCESS
)
5239 ERR(": what the heck is going on?\n" );
5243 /* Get the GUID, Device major number and device minor number
5244 * from the registry.
5246 if( RegQueryValueExA( hkServiceProvider
, guidDataSubKey
,
5247 NULL
, &returnTypeGUID
, returnBuffer
,
5248 &sizeOfReturnBuffer
) != ERROR_SUCCESS
)
5250 ERR(": missing GUID registry data members\n" );
5254 /* FIXME: Check return types to ensure we're interpreting data right */
5255 MultiByteToWideChar( CP_ACP
, 0, returnBuffer
, -1, buff
, sizeof(buff
)/sizeof(WCHAR
) );
5256 CLSIDFromString( (LPCOLESTR
)buff
, &serviceProviderGUID
);
5258 /* FIXME: Need to know which of dwReserved1 and dwReserved2 are maj and min */
5260 sizeOfReturnBuffer
= 50;
5261 if( RegQueryValueExA( hkServiceProvider
, majVerDataSubKey
,
5262 NULL
, &returnTypeReserved
, returnBuffer
,
5263 &sizeOfReturnBuffer
) != ERROR_SUCCESS
)
5265 ERR(": missing dwReserved1 registry data members\n") ;
5269 majVersionNum
= GET_DWORD( returnBuffer
);
5271 sizeOfReturnBuffer
= 50;
5272 if( RegQueryValueExA( hkServiceProvider
, minVerDataSubKey
,
5273 NULL
, &returnTypeReserved
, returnBuffer
,
5274 &sizeOfReturnBuffer
) != ERROR_SUCCESS
)
5276 ERR(": missing dwReserved2 registry data members\n") ;
5280 minVersionNum
= GET_DWORD( returnBuffer
);
5283 /* The enumeration will return FALSE if we are not to continue */
5284 if( !lpEnumCallback( &serviceProviderGUID
, subKeyName
,
5285 majVersionNum
, minVersionNum
, lpContext
) )
5287 WARN("lpEnumCallback returning FALSE\n" );
5296 /***************************************************************************
5297 * DirectPlayEnumerateW [DPLAYX.3]
5300 HRESULT WINAPI
DirectPlayEnumerateW( LPDPENUMDPCALLBACKW lpEnumCallback
, LPVOID lpContext
)
5305 return DPERR_OUTOFMEMORY
;
5309 typedef struct tagCreateEnum
5313 } CreateEnumData
, *lpCreateEnumData
;
5315 /* Find and copy the matching connection for the SP guid */
5316 static BOOL CALLBACK
cbDPCreateEnumConnections(
5318 LPVOID lpConnection
,
5319 DWORD dwConnectionSize
,
5324 lpCreateEnumData lpData
= (lpCreateEnumData
)lpContext
;
5326 if( IsEqualGUID( lpguidSP
, lpData
->lpGuid
) )
5328 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData
->lpGuid
) );
5330 lpData
->lpConn
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
5332 CopyMemory( lpData
->lpConn
, lpConnection
, dwConnectionSize
);
5334 /* Found the record that we were looking for */
5338 /* Haven't found what were looking for yet */
5343 /***************************************************************************
5344 * DirectPlayCreate [DPLAYX.1]
5347 HRESULT WINAPI DirectPlayCreate
5348 ( LPGUID lpGUID
, LPDIRECTPLAY2
*lplpDP
, IUnknown
*pUnk
)
5351 LPDIRECTPLAY3A lpDP3A
;
5352 CreateEnumData cbData
;
5354 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID
), lplpDP
, pUnk
);
5358 return CLASS_E_NOAGGREGATION
;
5361 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5362 give them an IDirectPlay2A object and hope that doesn't cause problems */
5363 if( DP_CreateInterface( &IID_IDirectPlay2A
, (LPVOID
*)lplpDP
) != DP_OK
)
5365 return DPERR_UNAVAILABLE
;
5368 if( IsEqualGUID( &GUID_NULL
, lpGUID
) )
5370 /* The GUID_NULL means don't bind a service provider. Just return the
5375 /* Bind the desired service provider since lpGUID is non NULL */
5376 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID
) );
5378 /* We're going to use a DP3 interface */
5379 hr
= IDirectPlayX_QueryInterface( *lplpDP
, &IID_IDirectPlay3A
,
5383 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr
) );
5387 cbData
.lpConn
= NULL
;
5388 cbData
.lpGuid
= lpGUID
;
5390 /* We were given a service provider, find info about it... */
5391 hr
= IDirectPlayX_EnumConnections( lpDP3A
, NULL
, cbDPCreateEnumConnections
,
5392 &cbData
, DPCONNECTION_DIRECTPLAY
);
5393 if( ( FAILED(hr
) ) ||
5394 ( cbData
.lpConn
== NULL
)
5397 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr
) );
5398 IDirectPlayX_Release( lpDP3A
);
5399 return DPERR_UNAVAILABLE
;
5402 /* Initialize the service provider */
5403 hr
= IDirectPlayX_InitializeConnection( lpDP3A
, cbData
.lpConn
, 0 );
5406 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr
) );
5407 HeapFree( GetProcessHeap(), 0, cbData
.lpConn
);
5408 IDirectPlayX_Release( lpDP3A
);
5412 /* Release our version of the interface now that we're done with it */
5413 IDirectPlayX_Release( lpDP3A
);
5414 HeapFree( GetProcessHeap(), 0, cbData
.lpConn
);