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"
28 #define NONAMELESSUNION
29 #define NONAMELESSSTRUCT
36 #include "wine/unicode.h"
38 #include "wine/debug.h"
41 #include "dplayx_global.h"
42 #include "name_server.h"
43 #include "dplayx_queue.h"
45 #include "dplay_global.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(dplay);
49 /* FIXME: Should this be externed? */
50 extern HRESULT DPL_CreateCompoundAddress
51 ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
52 LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
55 /* Local function prototypes */
56 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid );
57 static lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* iface, LPDPID lpid,
58 LPDPNAME lpName, DWORD dwFlags,
59 HANDLE hEvent, BOOL bAnsi );
60 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi );
61 static void DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
62 LPVOID lpData, DWORD dwDataSize );
64 static lpGroupData DP_CreateGroup( IDirectPlay2AImpl* iface, LPDPID lpid,
65 LPDPNAME lpName, DWORD dwFlags,
66 DPID idParent, BOOL bAnsi );
67 static void DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
68 LPVOID lpData, DWORD dwDataSize );
69 static void DP_DeleteDPNameStruct( LPDPNAME lpDPName );
70 static void DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid );
71 static BOOL CALLBACK cbDeletePlayerFromAllGroups( DPID dpId,
76 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid );
77 static BOOL CALLBACK cbRemoveGroupOrPlayer( DPID dpId, DWORD dwPlayerType,
78 LPCDPNAME lpName, DWORD dwFlags,
80 static void DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid );
82 /* Helper methods for player/group interfaces */
83 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
84 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
85 DPID idPlayer, BOOL bAnsi );
86 static HRESULT WINAPI DP_IF_CreatePlayer
87 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, LPDPID lpidPlayer,
88 LPDPNAME lpPlayerName, HANDLE hEvent, LPVOID lpData,
89 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
90 static HRESULT WINAPI DP_IF_DestroyGroup
91 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi );
92 static HRESULT WINAPI DP_IF_DestroyPlayer
93 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi );
94 static HRESULT WINAPI DP_IF_EnumGroupPlayers
95 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
96 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
97 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
98 static HRESULT WINAPI DP_IF_EnumGroups
99 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
100 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
101 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
102 static HRESULT WINAPI DP_IF_EnumPlayers
103 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
104 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
105 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
106 static HRESULT WINAPI DP_IF_GetGroupData
107 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
108 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
109 static HRESULT WINAPI DP_IF_GetGroupName
110 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
111 LPDWORD lpdwDataSize, BOOL bAnsi );
112 static HRESULT WINAPI DP_IF_GetPlayerData
113 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
114 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
115 static HRESULT WINAPI DP_IF_GetPlayerName
116 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
117 LPDWORD lpdwDataSize, BOOL bAnsi );
118 static HRESULT WINAPI DP_IF_SetGroupName
119 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
120 DWORD dwFlags, BOOL bAnsi );
121 static HRESULT WINAPI DP_IF_SetPlayerData
122 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
123 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
124 static HRESULT WINAPI DP_IF_SetPlayerName
125 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
126 DWORD dwFlags, BOOL bAnsi );
127 static HRESULT WINAPI DP_IF_AddGroupToGroup
128 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
129 static HRESULT WINAPI DP_IF_CreateGroup
130 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
131 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
132 DWORD dwFlags, BOOL bAnsi );
133 static HRESULT WINAPI DP_IF_CreateGroupInGroup
134 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
135 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
136 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
137 static HRESULT WINAPI DP_IF_AddPlayerToGroup
138 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
139 DPID idPlayer, BOOL bAnsi );
140 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
141 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
142 static HRESULT WINAPI DP_SetSessionDesc
143 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
144 DWORD dwFlags, BOOL bInitial, BOOL bAnsi );
145 static HRESULT WINAPI DP_SecureOpen
146 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
147 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
149 static HRESULT WINAPI DP_SendEx
150 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
151 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
152 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi );
153 static HRESULT WINAPI DP_IF_Receive
154 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
155 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi );
156 static HRESULT WINAPI DP_IF_GetMessageQueue
157 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
158 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi );
159 static HRESULT WINAPI DP_SP_SendEx
160 ( IDirectPlay2Impl* This, DWORD dwFlags,
161 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
162 LPVOID lpContext, LPDWORD lpdwMsgID );
163 static HRESULT WINAPI DP_IF_SetGroupData
164 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
165 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
166 static HRESULT WINAPI DP_IF_GetPlayerCaps
167 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
169 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi );
170 static HRESULT WINAPI DP_IF_CancelMessage
171 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
172 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi );
173 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
174 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
175 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
176 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
177 static HRESULT WINAPI DP_IF_GetGroupParent
178 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
180 static HRESULT WINAPI DP_IF_GetCaps
181 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags );
182 static HRESULT WINAPI DP_IF_EnumSessions
183 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
184 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
185 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
186 static HRESULT WINAPI DP_IF_InitializeConnection
187 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi );
188 static BOOL CALLBACK cbDPCreateEnumConnections( LPCGUID lpguidSP,
189 LPVOID lpConnection, DWORD dwConnectionSize, LPCDPNAME lpName,
190 DWORD dwFlags, LPVOID lpContext );
191 static BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
192 LPDWORD lpdwBufSize );
196 static inline DPID DP_NextObjectId(void);
197 static DPID DP_GetRemoteNextObjectId(void);
200 static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc,
201 LPCDPSESSIONDESC2 srcSessDesc, BOOL bAnsi );
204 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp );
205 static HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider );
206 static HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hServiceProvider );
213 #define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */
214 #define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported
215 we don't have to change much */
216 #define DPID_NAME_SERVER 0x19a9d65b /* Don't ask me why */
218 /* Strip out dwFlag values which cannot be sent in the CREATEGROUP msg */
219 #define DPMSG_CREATEGROUP_DWFLAGS(x) ( (x) & DPGROUP_HIDDEN )
221 /* Strip out all dwFlags values for CREATEPLAYER msg */
222 #define DPMSG_CREATEPLAYER_DWFLAGS(x) 0
224 static DWORD kludgePlayerGroupId = 1000;
226 /* ------------------------------------------------------------------ */
229 static BOOL DP_CreateIUnknown( LPVOID lpDP )
231 ICOM_THIS(IDirectPlay2AImpl,lpDP);
233 This->unk = (DirectPlayIUnknownData*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
234 sizeof( *(This->unk) ) );
235 if ( This->unk == NULL )
240 InitializeCriticalSection( &This->unk->DP_lock );
245 static BOOL DP_DestroyIUnknown( LPVOID lpDP )
247 ICOM_THIS(IDirectPlay2AImpl,lpDP);
249 DeleteCriticalSection( &This->unk->DP_lock );
250 HeapFree( GetProcessHeap(), 0, This->unk );
255 static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
257 ICOM_THIS(IDirectPlay2AImpl,lpDP);
259 This->dp2 = (DirectPlay2Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
260 sizeof( *(This->dp2) ) );
261 if ( This->dp2 == NULL )
266 This->dp2->bConnectionOpen = FALSE;
268 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
270 This->dp2->bHostInterface = FALSE;
272 DPQ_INIT(This->dp2->receiveMsgs);
273 DPQ_INIT(This->dp2->sendMsgs);
274 DPQ_INIT(This->dp2->replysExpected);
276 if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
278 /* FIXME: Memory leak */
282 /* Provide an initial session desc with nothing in it */
283 This->dp2->lpSessionDesc = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
285 sizeof( *This->dp2->lpSessionDesc ) );
286 if( This->dp2->lpSessionDesc == NULL )
288 /* FIXME: Memory leak */
291 This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc );
293 /* We are a emulating a dp 6 implementation */
294 This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION;
296 This->dp2->spData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
297 sizeof( *This->dp2->spData.lpCB ) );
298 This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB );
299 This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION;
301 /* This is the pointer to the service provider */
302 if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP,
303 (LPVOID*)&This->dp2->spData.lpISP, This ) )
306 /* FIXME: Memory leak */
310 /* Setup lobby provider information */
311 This->dp2->dplspData.dwSPVersion = DPSP_MAJORVERSION;
312 This->dp2->dplspData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
313 sizeof( *This->dp2->dplspData.lpCB ) );
314 This->dp2->dplspData.lpCB->dwSize = sizeof( *This->dp2->dplspData.lpCB );
316 if( FAILED( DPLSP_CreateInterface( &IID_IDPLobbySP,
317 (LPVOID*)&This->dp2->dplspData.lpISP, This ) )
320 /* FIXME: Memory leak */
327 /* Definition of the global function in dplayx_queue.h. #
328 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
329 DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
331 HeapFree( GetProcessHeap(), 0, elem );
334 /* Function to delete the list of groups with this interface. Needs to
335 * delete the group and player lists associated with this group as well
336 * as the group data associated with this group. It should not delete
337 * player data as that is shared with the top player list and will be
340 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList );
341 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList )
343 DPQ_DELETEQ( elem->lpGData->groups, groups,
344 lpGroupList, cbDeleteElemFromHeap );
345 DPQ_DELETEQ( elem->lpGData->players, players,
346 lpPlayerList, cbDeleteElemFromHeap );
347 HeapFree( GetProcessHeap(), 0, elem->lpGData );
348 HeapFree( GetProcessHeap(), 0, elem );
351 /* Function to delete the list of players with this interface. Needs to
352 * delete the player data for all players as well.
354 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList );
355 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList )
357 HeapFree( GetProcessHeap(), 0, elem->lpPData );
358 HeapFree( GetProcessHeap(), 0, elem );
361 static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
363 ICOM_THIS(IDirectPlay2AImpl,lpDP);
365 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
367 TerminateThread( This->dp2->hEnumSessionThread, 0 );
368 CloseHandle( This->dp2->hEnumSessionThread );
371 /* Finish with the SP - have it shutdown */
372 if( This->dp2->spData.lpCB->ShutdownEx )
374 DPSP_SHUTDOWNDATA data;
376 TRACE( "Calling SP ShutdownEx\n" );
378 data.lpISP = This->dp2->spData.lpISP;
380 (*This->dp2->spData.lpCB->ShutdownEx)( &data );
382 else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
384 TRACE( "Calling obsolete SP Shutdown\n" );
385 (*This->dp2->spData.lpCB->Shutdown)();
388 /* Unload the SP (if it exists) */
389 if( This->dp2->hServiceProvider != 0 )
391 FreeLibrary( This->dp2->hServiceProvider );
394 /* Unload the Lobby Provider (if it exists) */
395 if( This->dp2->hDPLobbyProvider != 0 )
397 FreeLibrary( This->dp2->hDPLobbyProvider );
401 DPQ_DELETEQ( This->dp2->players, players, lpPlayerList, cbDeletePlayerElem );
402 DPQ_DELETEQ( This->dp2->groups, groups, lpGroupList, cbDeleteGroupsElem );
405 /* FIXME: Need to delete receive and send msgs queue contents */
407 NS_DeleteSessionCache( This->dp2->lpNameServerData );
409 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
411 IDirectPlaySP_Release( This->dp2->spData.lpISP );
413 /* Delete the contents */
414 HeapFree( GetProcessHeap(), 0, This->dp2 );
419 static BOOL DP_CreateDirectPlay3( LPVOID lpDP )
421 ICOM_THIS(IDirectPlay3AImpl,lpDP);
423 This->dp3 = (DirectPlay3Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
424 sizeof( *(This->dp3) ) );
425 if ( This->dp3 == NULL )
433 static BOOL DP_DestroyDirectPlay3( LPVOID lpDP )
435 ICOM_THIS(IDirectPlay3AImpl,lpDP);
437 /* Delete the contents */
438 HeapFree( GetProcessHeap(), 0, This->dp3 );
443 static BOOL DP_CreateDirectPlay4( LPVOID lpDP )
445 ICOM_THIS(IDirectPlay4AImpl,lpDP);
447 This->dp4 = (DirectPlay4Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
448 sizeof( *(This->dp4) ) );
449 if ( This->dp4 == NULL )
457 static BOOL DP_DestroyDirectPlay4( LPVOID lpDP )
459 ICOM_THIS(IDirectPlay3AImpl,lpDP);
461 /* Delete the contents */
462 HeapFree( GetProcessHeap(), 0, This->dp4 );
468 /* Create a new interface */
470 HRESULT DP_CreateInterface
471 ( REFIID riid, LPVOID* ppvObj )
473 TRACE( " for %s\n", debugstr_guid( riid ) );
475 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
476 sizeof( IDirectPlay2Impl ) );
478 if( *ppvObj == NULL )
480 return DPERR_OUTOFMEMORY;
483 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
485 ICOM_THIS(IDirectPlay2Impl,*ppvObj);
486 This->lpVtbl = &directPlay2WVT;
488 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
490 ICOM_THIS(IDirectPlay2AImpl,*ppvObj);
491 This->lpVtbl = &directPlay2AVT;
493 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
495 ICOM_THIS(IDirectPlay3Impl,*ppvObj);
496 This->lpVtbl = &directPlay3WVT;
498 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
500 ICOM_THIS(IDirectPlay3AImpl,*ppvObj);
501 This->lpVtbl = &directPlay3AVT;
503 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
505 ICOM_THIS(IDirectPlay4Impl,*ppvObj);
506 This->lpVtbl = &directPlay4WVT;
508 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
510 ICOM_THIS(IDirectPlay4AImpl,*ppvObj);
511 This->lpVtbl = &directPlay4AVT;
515 /* Unsupported interface */
516 HeapFree( GetProcessHeap(), 0, *ppvObj );
519 return E_NOINTERFACE;
523 if ( DP_CreateIUnknown( *ppvObj ) &&
524 DP_CreateDirectPlay2( *ppvObj ) &&
525 DP_CreateDirectPlay3( *ppvObj ) &&
526 DP_CreateDirectPlay4( *ppvObj )
529 IDirectPlayX_AddRef( (LPDIRECTPLAY2A)*ppvObj );
534 /* Initialize failed, destroy it */
535 DP_DestroyDirectPlay4( *ppvObj );
536 DP_DestroyDirectPlay3( *ppvObj );
537 DP_DestroyDirectPlay2( *ppvObj );
538 DP_DestroyIUnknown( *ppvObj );
540 HeapFree( GetProcessHeap(), 0, *ppvObj );
543 return DPERR_NOMEMORY;
547 /* Direct Play methods */
549 /* Shared between all dplay types */
550 static HRESULT WINAPI DP_QueryInterface
551 ( LPDIRECTPLAY2 iface, REFIID riid, LPVOID* ppvObj )
553 ICOM_THIS(IDirectPlay2Impl,iface);
554 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
556 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
559 if( *ppvObj == NULL )
561 return DPERR_OUTOFMEMORY;
564 CopyMemory( *ppvObj, This, sizeof( *This ) );
565 (*(IDirectPlay2Impl**)ppvObj)->ulInterfaceRef = 0;
567 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
569 ICOM_THIS(IDirectPlay2Impl,*ppvObj);
570 This->lpVtbl = &directPlay2WVT;
572 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
574 ICOM_THIS(IDirectPlay2AImpl,*ppvObj);
575 This->lpVtbl = &directPlay2AVT;
577 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
579 ICOM_THIS(IDirectPlay3Impl,*ppvObj);
580 This->lpVtbl = &directPlay3WVT;
582 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
584 ICOM_THIS(IDirectPlay3AImpl,*ppvObj);
585 This->lpVtbl = &directPlay3AVT;
587 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
589 ICOM_THIS(IDirectPlay4Impl,*ppvObj);
590 This->lpVtbl = &directPlay4WVT;
592 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
594 ICOM_THIS(IDirectPlay4AImpl,*ppvObj);
595 This->lpVtbl = &directPlay4AVT;
599 /* Unsupported interface */
600 HeapFree( GetProcessHeap(), 0, *ppvObj );
603 return E_NOINTERFACE;
606 IDirectPlayX_AddRef( (LPDIRECTPLAY2)*ppvObj );
611 /* Shared between all dplay types */
612 static ULONG WINAPI DP_AddRef
613 ( LPDIRECTPLAY3 iface )
615 ULONG ulInterfaceRefCount, ulObjRefCount;
616 ICOM_THIS(IDirectPlay3Impl,iface);
618 ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
619 ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
621 TRACE( "ref count incremented to %lu:%lu for %p\n",
622 ulInterfaceRefCount, ulObjRefCount, This );
624 return ulObjRefCount;
627 static ULONG WINAPI DP_Release
628 ( LPDIRECTPLAY3 iface )
630 ULONG ulInterfaceRefCount, ulObjRefCount;
632 ICOM_THIS(IDirectPlay3Impl,iface);
634 ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
635 ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
637 TRACE( "ref count decremented to %lu:%lu for %p\n",
638 ulInterfaceRefCount, ulObjRefCount, This );
640 /* Deallocate if this is the last reference to the object */
641 if( ulObjRefCount == 0 )
643 /* If we're destroying the object, this must be the last ref
644 of the last interface */
645 DP_DestroyDirectPlay4( This );
646 DP_DestroyDirectPlay3( This );
647 DP_DestroyDirectPlay2( This );
648 DP_DestroyIUnknown( This );
651 /* Deallocate the interface */
652 if( ulInterfaceRefCount == 0 )
654 HeapFree( GetProcessHeap(), 0, This );
657 return ulObjRefCount;
660 static inline DPID DP_NextObjectId(void)
662 return (DPID)InterlockedIncrement( &kludgePlayerGroupId );
665 /* *lplpReply will be non NULL iff there is something to reply */
666 HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpcMessageBody,
667 DWORD dwMessageBodySize, LPCVOID lpcMessageHeader,
668 WORD wCommandId, WORD wVersion,
669 LPVOID* lplpReply, LPDWORD lpdwMsgSize )
671 TRACE( "(%p)->(%p,0x%08lx,%p,%u,%u)\n",
672 This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId,
677 /* Name server needs to handle this request */
678 case DPMSGCMD_ENUMSESSIONSREQUEST:
681 NS_ReplyToEnumSessionsRequest( lpcMessageBody, lplpReply, lpdwMsgSize, This );
686 /* Name server needs to handle this request */
687 case DPMSGCMD_ENUMSESSIONSREPLY:
689 /* No reply expected */
690 NS_AddRemoteComputerAsNameServer( lpcMessageHeader,
691 This->dp2->spData.dwSPHeaderSize,
692 (LPDPMSG_ENUMSESSIONSREPLY)lpcMessageBody,
693 This->dp2->lpNameServerData );
697 case DPMSGCMD_REQUESTNEWPLAYERID:
699 LPCDPMSG_REQUESTNEWPLAYERID lpcMsg =
700 (LPCDPMSG_REQUESTNEWPLAYERID)lpcMessageBody;
702 LPDPMSG_NEWPLAYERIDREPLY lpReply;
704 *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
706 *lplpReply = (LPDPMSG_NEWPLAYERIDREPLY)HeapAlloc( GetProcessHeap(),
710 FIXME( "Ignoring dwFlags 0x%08lx in request msg\n",
713 /* Setup the reply */
714 lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) +
715 This->dp2->spData.dwSPHeaderSize );
717 lpReply->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
718 lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY;
719 lpReply->envelope.wVersion = DPMSGVER_DP6;
721 lpReply->dpidNewPlayerId = DP_NextObjectId();
723 TRACE( "Allocating new playerid 0x%08lx from remote request\n",
724 lpReply->dpidNewPlayerId );
729 case DPMSGCMD_GETNAMETABLEREPLY:
730 case DPMSGCMD_NEWPLAYERIDREPLY:
734 if( wCommandId == DPMSGCMD_NEWPLAYERIDREPLY )
737 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
743 case DPMSGCMD_JUSTENVELOPE:
745 TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08lx\n", lpcMessageHeader, ((LPDWORD)lpcMessageHeader)[1] );
746 NS_SetLocalAddr( This->dp2->lpNameServerData, lpcMessageHeader, 20 );
747 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
751 case DPMSGCMD_FORWARDADDPLAYER:
757 TRACE( "Sending message to self to get my addr\n" );
758 DP_MSG_ToSelf( This, 1 ); /* This is a hack right now */
763 case DPMSGCMD_FORWARDADDPLAYERNACK:
765 DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
771 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
777 /* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */
783 static HRESULT WINAPI DP_IF_AddPlayerToGroup
784 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
785 DPID idPlayer, BOOL bAnsi )
788 lpPlayerList lpPList;
789 lpPlayerList lpNewPList;
791 TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
792 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
795 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
797 return DPERR_INVALIDGROUP;
800 /* Find the player */
801 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
803 return DPERR_INVALIDPLAYER;
806 /* Create a player list (ie "shortcut" ) */
807 lpNewPList = (lpPlayerList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
808 sizeof( *lpNewPList ) );
809 if( lpNewPList == NULL )
811 return DPERR_CANTADDPLAYER;
814 /* Add the shortcut */
815 lpPList->lpPData->uRef++;
816 lpNewPList->lpPData = lpPList->lpPData;
818 /* Add the player to the list of players for this group */
819 DPQ_INSERT(lpGData->players,lpNewPList,players);
821 /* Let the SP know that we've added a player to the group */
822 if( This->dp2->spData.lpCB->AddPlayerToGroup )
824 DPSP_ADDPLAYERTOGROUPDATA data;
826 TRACE( "Calling SP AddPlayerToGroup\n" );
828 data.idPlayer = idPlayer;
829 data.idGroup = idGroup;
830 data.lpISP = This->dp2->spData.lpISP;
832 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
835 /* Inform all other peers of the addition of player to the group. If there are
836 * no peers keep this event quiet.
837 * Also, if this event was the result of another machine sending it to us,
838 * don't bother rebroadcasting it.
840 if( ( lpMsgHdr == NULL ) &&
841 This->dp2->lpSessionDesc &&
842 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
844 DPMSG_ADDPLAYERTOGROUP msg;
845 msg.dwType = DPSYS_ADDPLAYERTOGROUP;
847 msg.dpIdGroup = idGroup;
848 msg.dpIdPlayer = idPlayer;
850 /* FIXME: Correct to just use send effectively? */
851 /* FIXME: Should size include data w/ message or just message "header" */
852 /* FIXME: Check return code */
853 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
859 static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
860 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
862 ICOM_THIS(IDirectPlay2Impl,iface);
863 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, TRUE );
866 static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
867 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
869 ICOM_THIS(IDirectPlay2Impl,iface);
870 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, FALSE );
873 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi )
877 TRACE("(%p)->(%u)\n", This, bAnsi );
879 /* FIXME: Need to find a new host I assume (how?) */
880 /* FIXME: Need to destroy all local groups */
881 /* FIXME: Need to migrate all remotely visible players to the new host */
883 /* Invoke the SP callback to inform of session close */
884 if( This->dp2->spData.lpCB->CloseEx )
888 TRACE( "Calling SP CloseEx\n" );
890 data.lpISP = This->dp2->spData.lpISP;
892 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
895 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
897 TRACE( "Calling SP Close (obsolete interface)\n" );
899 hr = (*This->dp2->spData.lpCB->Close)();
905 static HRESULT WINAPI DirectPlay2AImpl_Close
906 ( LPDIRECTPLAY2A iface )
908 ICOM_THIS(IDirectPlay2Impl,iface);
909 return DP_IF_Close( This, TRUE );
912 static HRESULT WINAPI DirectPlay2WImpl_Close
913 ( LPDIRECTPLAY2 iface )
915 ICOM_THIS(IDirectPlay2Impl,iface);
916 return DP_IF_Close( This, FALSE );
920 lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, LPDPID lpid,
921 LPDPNAME lpName, DWORD dwFlags,
922 DPID idParent, BOOL bAnsi )
926 /* Allocate the new space and add to end of high level group list */
927 lpGData = (lpGroupData) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
928 sizeof( *lpGData ) );
930 if( lpGData == NULL )
935 DPQ_INIT(lpGData->groups);
936 DPQ_INIT(lpGData->players);
938 /* Set the desired player ID - no sanity checking to see if it exists */
939 lpGData->dpid = *lpid;
941 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
943 /* FIXME: Should we check that the parent exists? */
944 lpGData->parent = idParent;
946 /* FIXME: Should we validate the dwFlags? */
947 lpGData->dwFlags = dwFlags;
949 TRACE( "Created group id 0x%08lx\n", *lpid );
954 /* This method assumes that all links to it are already deleted */
956 DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid )
960 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
962 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
964 if( lpGList == NULL )
966 ERR( "DPID 0x%08lx not found\n", dpid );
970 if( --(lpGList->lpGData->uRef) )
972 FIXME( "Why is this not the last reference to group?\n" );
977 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
978 HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
980 /* Remove and Delete Player List object */
981 HeapFree( GetProcessHeap(), 0, lpGList );
985 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid )
987 lpGroupList lpGroups;
989 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
991 if( dpid == DPID_SYSTEM_GROUP )
993 return This->dp2->lpSysGroup;
997 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
1000 if( lpGroups == NULL )
1005 return lpGroups->lpGData;
1008 static HRESULT WINAPI DP_IF_CreateGroup
1009 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
1010 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
1011 DWORD dwFlags, BOOL bAnsi )
1013 lpGroupData lpGData;
1015 TRACE( "(%p)->(%p,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
1016 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
1019 /* If the name is not specified, we must provide one */
1020 if( DPID_UNKNOWN == *lpidGroup )
1022 /* If we are the name server, we decide on the group ids. If not, we
1023 * must ask for one before attempting a creation.
1025 if( This->dp2->bHostInterface )
1027 *lpidGroup = DP_NextObjectId();
1031 *lpidGroup = DP_GetRemoteNextObjectId();
1035 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
1036 DPID_NOPARENT_GROUP, bAnsi );
1038 if( lpGData == NULL )
1040 return DPERR_CANTADDPLAYER; /* yes player not group */
1043 if( DPID_SYSTEM_GROUP == *lpidGroup )
1045 This->dp2->lpSysGroup = lpGData;
1046 TRACE( "Inserting system group\n" );
1050 /* Insert into the system group */
1051 lpGroupList lpGroup = (lpGroupList) HeapAlloc( GetProcessHeap(),
1053 sizeof( *lpGroup ) );
1054 lpGroup->lpGData = lpGData;
1056 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
1059 /* Something is now referencing this data */
1062 /* Set all the important stuff for the group */
1063 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
1065 /* FIXME: We should only create the system group if GetCaps returns
1066 * DPCAPS_GROUPOPTIMIZED.
1069 /* Let the SP know that we've created this group */
1070 if( This->dp2->spData.lpCB->CreateGroup )
1072 DPSP_CREATEGROUPDATA data;
1073 DWORD dwCreateFlags = 0;
1075 TRACE( "Calling SP CreateGroup\n" );
1077 if( *lpidGroup == DPID_NOPARENT_GROUP )
1078 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
1080 if( lpMsgHdr == NULL )
1081 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1083 if( dwFlags & DPGROUP_HIDDEN )
1084 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
1086 data.idGroup = *lpidGroup;
1087 data.dwFlags = dwCreateFlags;
1088 data.lpSPMessageHeader = lpMsgHdr;
1089 data.lpISP = This->dp2->spData.lpISP;
1091 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1094 /* Inform all other peers of the creation of a new group. If there are
1095 * no peers keep this event quiet.
1096 * Also if this message was sent to us, don't rebroadcast.
1098 if( ( lpMsgHdr == NULL ) &&
1099 This->dp2->lpSessionDesc &&
1100 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1102 DPMSG_CREATEPLAYERORGROUP msg;
1103 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1105 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1106 msg.dpId = *lpidGroup;
1107 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1108 msg.lpData = lpData;
1109 msg.dwDataSize = dwDataSize;
1110 msg.dpnName = *lpGroupName;
1111 msg.dpIdParent = DPID_NOPARENT_GROUP;
1112 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
1114 /* FIXME: Correct to just use send effectively? */
1115 /* FIXME: Should size include data w/ message or just message "header" */
1116 /* FIXME: Check return code */
1117 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
1118 0, 0, NULL, NULL, bAnsi );
1124 static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
1125 ( LPDIRECTPLAY2A iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1126 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1128 *lpidGroup = DPID_UNKNOWN;
1130 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1131 lpGroupName, lpData, dwDataSize, dwFlags, TRUE );
1134 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
1135 ( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1136 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1138 *lpidGroup = DPID_UNKNOWN;
1140 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1141 lpGroupName, lpData, dwDataSize, dwFlags, FALSE );
1146 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
1147 LPVOID lpData, DWORD dwDataSize )
1149 /* Clear out the data with this player */
1150 if( ( dwFlags & DPSET_LOCAL ) &&
1151 ( lpGData->dwLocalDataSize != 0 )
1154 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
1155 lpGData->lpLocalData = NULL;
1156 lpGData->dwLocalDataSize = 0;
1158 if( ( dwFlags & DPSET_REMOTE ) &&
1159 ( lpGData->dwRemoteDataSize != 0 )
1162 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
1163 lpGData->lpRemoteData = NULL;
1164 lpGData->dwRemoteDataSize = 0;
1167 /* Reallocate for new data */
1168 if( lpData != NULL )
1170 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1171 sizeof( dwDataSize ) );
1172 CopyMemory( lpNewData, lpData, dwDataSize );
1174 if( dwFlags & DPSET_REMOTE )
1176 lpGData->lpRemoteData = lpNewData;
1177 lpGData->dwRemoteDataSize = dwDataSize;
1180 if( dwFlags & DPSET_LOCAL )
1182 lpGData->lpLocalData = lpData;
1183 lpGData->dwLocalDataSize = dwDataSize;
1189 /* This function will just create the storage for the new player. */
1191 lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid,
1192 LPDPNAME lpName, DWORD dwFlags,
1193 HANDLE hEvent, BOOL bAnsi )
1195 lpPlayerData lpPData;
1197 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
1199 /* Allocate the storage for the player and associate it with list element */
1200 lpPData = (lpPlayerData) HeapAlloc( GetProcessHeap(),
1202 sizeof( *lpPData ) );
1203 if( lpPData == NULL )
1208 /* Set the desired player ID */
1209 lpPData->dpid = *lpid;
1211 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
1213 lpPData->dwFlags = dwFlags;
1215 /* If we were given an event handle, duplicate it */
1218 if( !DuplicateHandle( GetCurrentProcess(), hEvent,
1219 GetCurrentProcess(), &lpPData->hEvent,
1220 0, FALSE, DUPLICATE_SAME_ACCESS )
1223 /* FIXME: Memory leak */
1224 ERR( "Can't duplicate player msg handle %p\n", hEvent );
1228 /* Initialize the SP data section */
1229 lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData();
1231 TRACE( "Created player id 0x%08lx\n", *lpid );
1236 /* Delete the contents of the DPNAME struct */
1238 DP_DeleteDPNameStruct( LPDPNAME lpDPName )
1240 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u1.lpszShortNameA );
1241 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u2.lpszLongNameA );
1244 /* This method assumes that all links to it are already deleted */
1246 DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid )
1248 lpPlayerList lpPList;
1250 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
1252 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1254 if( lpPList == NULL )
1256 ERR( "DPID 0x%08lx not found\n", dpid );
1260 /* Verify that this is the last reference to the data */
1261 if( --(lpPList->lpPData->uRef) )
1263 FIXME( "Why is this not the last reference to player?\n" );
1268 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1270 CloseHandle( lpPList->lpPData->hEvent );
1271 HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
1273 /* Delete Player List object */
1274 HeapFree( GetProcessHeap(), 0, lpPList );
1277 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid )
1279 lpPlayerList lpPlayers;
1281 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
1283 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1288 /* Basic area for Dst must already be allocated */
1289 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi )
1293 ZeroMemory( lpDst, sizeof( *lpDst ) );
1294 lpDst->dwSize = sizeof( *lpDst );
1298 if( lpSrc->dwSize != sizeof( *lpSrc) )
1303 /* Delete any existing pointers */
1304 if( lpDst->u1.lpszShortNameA )
1306 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1309 if( lpDst->u2.lpszLongNameA )
1311 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1314 /* Copy as required */
1315 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1319 if( lpSrc->u1.lpszShortNameA )
1321 lpDst->u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), 0,
1322 strlen(lpSrc->u1.lpszShortNameA)+1 );
1323 strcpy( lpDst->u1.lpszShortNameA, lpSrc->u1.lpszShortNameA );
1325 if( lpSrc->u2.lpszLongNameA )
1327 lpDst->u2.lpszLongNameA = HeapAlloc( GetProcessHeap(), 0,
1328 strlen(lpSrc->u2.lpszLongNameA)+1 );
1329 strcpy( lpDst->u2.lpszLongNameA, lpSrc->u2.lpszLongNameA );
1334 if( lpSrc->u1.lpszShortNameA )
1336 lpDst->u1.lpszShortName = HeapAlloc( GetProcessHeap(), 0,
1337 (strlenW(lpSrc->u1.lpszShortName)+1)*sizeof(WCHAR) );
1338 strcpyW( lpDst->u1.lpszShortName, lpSrc->u1.lpszShortName );
1340 if( lpSrc->u2.lpszLongNameA )
1342 lpDst->u2.lpszLongName = HeapAlloc( GetProcessHeap(), 0,
1343 (strlenW(lpSrc->u2.lpszLongName)+1)*sizeof(WCHAR) );
1344 strcpyW( lpDst->u2.lpszLongName, lpSrc->u2.lpszLongName );
1352 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
1353 LPVOID lpData, DWORD dwDataSize )
1355 /* Clear out the data with this player */
1356 if( ( dwFlags & DPSET_LOCAL ) &&
1357 ( lpPData->dwLocalDataSize != 0 )
1360 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
1361 lpPData->lpLocalData = NULL;
1362 lpPData->dwLocalDataSize = 0;
1364 if( ( dwFlags & DPSET_REMOTE ) &&
1365 ( lpPData->dwRemoteDataSize != 0 )
1368 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
1369 lpPData->lpRemoteData = NULL;
1370 lpPData->dwRemoteDataSize = 0;
1373 /* Reallocate for new data */
1374 if( lpData != NULL )
1376 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1377 sizeof( dwDataSize ) );
1378 CopyMemory( lpNewData, lpData, dwDataSize );
1380 if( dwFlags & DPSET_REMOTE )
1382 lpPData->lpRemoteData = lpNewData;
1383 lpPData->dwRemoteDataSize = dwDataSize;
1386 if( dwFlags & DPSET_LOCAL )
1388 lpPData->lpLocalData = lpData;
1389 lpPData->dwLocalDataSize = dwDataSize;
1395 static HRESULT WINAPI DP_IF_CreatePlayer
1396 ( IDirectPlay2Impl* This,
1397 LPVOID lpMsgHdr, /* NULL for local creation, non NULL for remote creation */
1399 LPDPNAME lpPlayerName,
1407 lpPlayerData lpPData;
1408 lpPlayerList lpPList;
1409 DWORD dwCreateFlags = 0;
1411 TRACE( "(%p)->(%p,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
1412 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1413 dwDataSize, dwFlags, bAnsi );
1417 dwFlags = DPPLAYER_SPECTATOR;
1420 if( lpidPlayer == NULL )
1422 return DPERR_INVALIDPARAMS;
1426 /* Determine the creation flags for the player. These will be passed
1427 * to the name server if requesting a player id and to the SP when
1428 * informing it of the player creation
1431 if( dwFlags & DPPLAYER_SERVERPLAYER )
1433 if( *lpidPlayer == DPID_SERVERPLAYER )
1435 /* Server player for the host interface */
1436 dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
1438 else if( *lpidPlayer == DPID_NAME_SERVER )
1440 /* Name server - master of everything */
1441 dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
1445 /* Server player for a non host interface */
1446 dwCreateFlags |= DPLAYI_PLAYER_SYSPLAYER;
1450 if( lpMsgHdr == NULL )
1451 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1454 /* Verify we know how to handle all the flags */
1455 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1456 ( dwFlags & DPPLAYER_SPECTATOR )
1460 /* Assume non fatal failure */
1461 ERR( "unknown dwFlags = 0x%08lx\n", dwFlags );
1464 /* If the name is not specified, we must provide one */
1465 if( *lpidPlayer == DPID_UNKNOWN )
1467 /* If we are the session master, we dish out the group/player ids */
1468 if( This->dp2->bHostInterface )
1470 *lpidPlayer = DP_NextObjectId();
1474 hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer );
1478 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1485 /* FIXME: Would be nice to perhaps verify that we don't already have
1490 /* FIXME: Should we be storing these dwFlags or the creation ones? */
1491 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwFlags,
1494 if( lpPData == NULL )
1496 return DPERR_CANTADDPLAYER;
1499 /* Create the list object and link it in */
1500 lpPList = (lpPlayerList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1501 sizeof( *lpPList ) );
1502 if( lpPList == NULL )
1504 FIXME( "Memory leak\n" );
1505 return DPERR_CANTADDPLAYER;
1509 lpPList->lpPData = lpPData;
1511 /* Add the player to the system group */
1512 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1514 /* Update the information and send it to all players in the session */
1515 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
1517 /* Let the SP know that we've created this player */
1518 if( This->dp2->spData.lpCB->CreatePlayer )
1520 DPSP_CREATEPLAYERDATA data;
1522 data.idPlayer = *lpidPlayer;
1523 data.dwFlags = dwCreateFlags;
1524 data.lpSPMessageHeader = lpMsgHdr;
1525 data.lpISP = This->dp2->spData.lpISP;
1527 TRACE( "Calling SP CreatePlayer 0x%08lx: dwFlags: 0x%08lx lpMsgHdr: %p\n",
1528 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
1530 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1535 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1539 /* Now let the SP know that this player is a member of the system group */
1540 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1542 DPSP_ADDPLAYERTOGROUPDATA data;
1544 data.idPlayer = *lpidPlayer;
1545 data.idGroup = DPID_SYSTEM_GROUP;
1546 data.lpISP = This->dp2->spData.lpISP;
1548 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1550 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1555 ERR( "Failed to add player to sys group with sp: %s\n",
1556 DPLAYX_HresultToString(hr) );
1561 if( This->dp2->bHostInterface == FALSE )
1563 /* Let the name server know about the creation of this player */
1564 /* FIXME: Is this only to be done for the creation of a server player or
1565 * is this used for regular players? If only for server players, move
1566 * this call to DP_SecureOpen(...);
1569 TRACE( "Sending message to self to get my addr\n" );
1570 DP_MSG_ToSelf( This, *lpidPlayer ); /* This is a hack right now */
1573 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
1576 /* Inform all other peers of the creation of a new player. If there are
1577 * no peers keep this quiet.
1578 * Also, if this was a remote event, no need to rebroadcast it.
1580 if( ( lpMsgHdr == NULL ) &&
1581 This->dp2->lpSessionDesc &&
1582 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1584 DPMSG_CREATEPLAYERORGROUP msg;
1585 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1587 msg.dwPlayerType = DPPLAYERTYPE_PLAYER;
1588 msg.dpId = *lpidPlayer;
1589 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */
1590 msg.lpData = lpData;
1591 msg.dwDataSize = dwDataSize;
1592 msg.dpnName = *lpPlayerName;
1593 msg.dpIdParent = DPID_NOPARENT_GROUP;
1594 msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
1596 /* FIXME: Correct to just use send effectively? */
1597 /* FIXME: Should size include data w/ message or just message "header" */
1598 /* FIXME: Check return code */
1599 hr = DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
1600 sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
1607 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
1608 ( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1609 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1611 ICOM_THIS(IDirectPlay2Impl,iface);
1613 if( dwFlags & DPPLAYER_SERVERPLAYER )
1615 *lpidPlayer = DPID_SERVERPLAYER;
1619 *lpidPlayer = DPID_UNKNOWN;
1622 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1623 lpData, dwDataSize, dwFlags, TRUE );
1626 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
1627 ( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1628 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1630 ICOM_THIS(IDirectPlay2Impl,iface);
1632 if( dwFlags & DPPLAYER_SERVERPLAYER )
1634 *lpidPlayer = DPID_SERVERPLAYER;
1638 *lpidPlayer = DPID_UNKNOWN;
1641 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1642 lpData, dwDataSize, dwFlags, FALSE );
1645 static DPID DP_GetRemoteNextObjectId(void)
1650 return DP_NextObjectId();
1653 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
1654 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
1655 DPID idPlayer, BOOL bAnsi )
1659 lpGroupData lpGData;
1660 lpPlayerList lpPList;
1662 TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
1663 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
1665 /* Find the group */
1666 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1668 return DPERR_INVALIDGROUP;
1671 /* Find the player */
1672 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
1674 return DPERR_INVALIDPLAYER;
1677 /* Remove the player shortcut from the group */
1678 DPQ_REMOVE_ENTRY( lpGData->players, players, lpPData->dpid, ==, idPlayer, lpPList );
1680 if( lpPList == NULL )
1682 return DPERR_INVALIDPLAYER;
1685 /* One less reference */
1686 lpPList->lpPData->uRef--;
1688 /* Delete the Player List element */
1689 HeapFree( GetProcessHeap(), 0, lpPList );
1691 /* Inform the SP if they care */
1692 if( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1694 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1696 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1698 data.idPlayer = idPlayer;
1699 data.idGroup = idGroup;
1700 data.lpISP = This->dp2->spData.lpISP;
1702 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1705 /* Need to send a DELETEPLAYERFROMGROUP message */
1706 FIXME( "Need to send a message\n" );
1711 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
1712 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
1714 ICOM_THIS(IDirectPlay2Impl,iface);
1715 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, TRUE );
1718 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
1719 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
1721 ICOM_THIS(IDirectPlay2Impl,iface);
1722 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, FALSE );
1725 typedef struct _DPRGOPContext
1727 IDirectPlay3Impl* This;
1730 } DPRGOPContext, *lpDPRGOPContext;
1732 static BOOL CALLBACK
1733 cbRemoveGroupOrPlayer(
1740 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1742 TRACE( "Removing element:0x%08lx (type:0x%08lx) from element:0x%08lx\n",
1743 dpId, dwPlayerType, lpCtxt->idGroup );
1745 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1747 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt->This, lpCtxt->idGroup,
1752 ERR( "Unable to delete group 0x%08lx from group 0x%08lx\n",
1753 dpId, lpCtxt->idGroup );
1758 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl*)lpCtxt->This,
1759 NULL, lpCtxt->idGroup,
1760 dpId, lpCtxt->bAnsi )
1764 ERR( "Unable to delete player 0x%08lx from grp 0x%08lx\n",
1765 dpId, lpCtxt->idGroup );
1769 return TRUE; /* Continue enumeration */
1772 static HRESULT WINAPI DP_IF_DestroyGroup
1773 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi )
1775 lpGroupData lpGData;
1776 DPRGOPContext context;
1778 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
1779 This, lpMsgHdr, idGroup, bAnsi );
1781 /* Find the group */
1782 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1784 return DPERR_INVALIDPLAYER; /* yes player */
1787 context.This = (IDirectPlay3Impl*)This;
1788 context.bAnsi = bAnsi;
1789 context.idGroup = idGroup;
1791 /* Remove all players that this group has */
1792 DP_IF_EnumGroupPlayers( This, idGroup, NULL,
1793 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1795 /* Remove all links to groups that this group has since this is dp3 */
1796 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This, idGroup, NULL,
1797 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1799 /* Remove this group from the parent group - if it has one */
1800 if( ( idGroup != DPID_SYSTEM_GROUP ) &&
1801 ( lpGData->parent != DPID_SYSTEM_GROUP )
1804 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl*)This, lpGData->parent,
1808 /* Now delete this group data and list from the system group */
1809 DP_DeleteGroup( This, idGroup );
1811 /* Let the SP know that we've destroyed this group */
1812 if( This->dp2->spData.lpCB->DeleteGroup )
1814 DPSP_DELETEGROUPDATA data;
1816 FIXME( "data.dwFlags is incorrect\n" );
1818 data.idGroup = idGroup;
1820 data.lpISP = This->dp2->spData.lpISP;
1822 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1825 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1830 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
1831 ( LPDIRECTPLAY2A iface, DPID idGroup )
1833 ICOM_THIS(IDirectPlay2Impl,iface);
1834 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
1837 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
1838 ( LPDIRECTPLAY2 iface, DPID idGroup )
1840 ICOM_THIS(IDirectPlay2Impl,iface);
1841 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
1844 typedef struct _DPFAGContext
1846 IDirectPlay2Impl* This;
1849 } DPFAGContext, *lpDPFAGContext;
1851 static HRESULT WINAPI DP_IF_DestroyPlayer
1852 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi )
1854 DPFAGContext cbContext;
1856 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
1857 This, lpMsgHdr, idPlayer, bAnsi );
1859 if( DP_FindPlayer( This, idPlayer ) == NULL )
1861 return DPERR_INVALIDPLAYER;
1864 /* FIXME: If the player is remote, we must be the host to delete this */
1866 cbContext.This = This;
1867 cbContext.idPlayer = idPlayer;
1868 cbContext.bAnsi = bAnsi;
1870 /* Find each group and call DeletePlayerFromGroup if the player is a
1871 member of the group */
1872 DP_IF_EnumGroups( This, NULL, cbDeletePlayerFromAllGroups,
1873 (LPVOID)&cbContext, DPENUMGROUPS_ALL, bAnsi );
1875 /* Now delete player and player list from the sys group */
1876 DP_DeletePlayer( This, idPlayer );
1878 /* Let the SP know that we've destroyed this group */
1879 if( This->dp2->spData.lpCB->DeletePlayer )
1881 DPSP_DELETEPLAYERDATA data;
1883 FIXME( "data.dwFlags is incorrect\n" );
1885 data.idPlayer = idPlayer;
1887 data.lpISP = This->dp2->spData.lpISP;
1889 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
1892 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
1897 static BOOL CALLBACK
1898 cbDeletePlayerFromAllGroups(
1905 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
1907 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1909 DP_IF_DeletePlayerFromGroup( lpCtxt->This, NULL, dpId, lpCtxt->idPlayer,
1912 /* Enumerate all groups in this group since this will normally only
1913 * be called for top level groups
1915 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)lpCtxt->This,
1917 cbDeletePlayerFromAllGroups,
1918 (LPVOID)lpContext, DPENUMGROUPS_ALL,
1924 ERR( "Group callback has dwPlayerType = 0x%08lx\n", dwPlayerType );
1930 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
1931 ( LPDIRECTPLAY2A iface, DPID idPlayer )
1933 ICOM_THIS(IDirectPlay2Impl,iface);
1934 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
1937 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
1938 ( LPDIRECTPLAY2 iface, DPID idPlayer )
1940 ICOM_THIS(IDirectPlay2Impl,iface);
1941 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
1944 static HRESULT WINAPI DP_IF_EnumGroupPlayers
1945 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
1946 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1947 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1949 lpGroupData lpGData;
1950 lpPlayerList lpPList;
1952 FIXME("(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
1953 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
1954 lpContext, dwFlags, bAnsi );
1956 /* Find the group */
1957 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1959 return DPERR_INVALIDGROUP;
1962 if( DPQ_IS_EMPTY( lpGData->players ) )
1967 lpPList = DPQ_FIRST( lpGData->players );
1969 /* Walk the players in this group */
1972 /* We do not enum the name server or app server as they are of no
1973 * concequence to the end user.
1975 if( ( lpPList->lpPData->dpid != DPID_NAME_SERVER ) &&
1976 ( lpPList->lpPData->dpid != DPID_SERVERPLAYER )
1980 /* FIXME: Need to add stuff for dwFlags checking */
1982 if( !lpEnumPlayersCallback2( lpPList->lpPData->dpid, DPPLAYERTYPE_PLAYER,
1983 &lpPList->lpPData->name,
1984 lpPList->lpPData->dwFlags,
1988 /* User requested break */
1993 if( DPQ_IS_ENDOFLIST( lpPList->players ) )
1998 lpPList = DPQ_NEXT( lpPList->players );
2004 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
2005 ( LPDIRECTPLAY2A iface, DPID idGroup, LPGUID lpguidInstance,
2006 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2007 LPVOID lpContext, DWORD dwFlags )
2009 ICOM_THIS(IDirectPlay2Impl,iface);
2010 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2011 lpEnumPlayersCallback2, lpContext,
2015 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
2016 ( LPDIRECTPLAY2 iface, DPID idGroup, LPGUID lpguidInstance,
2017 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2018 LPVOID lpContext, DWORD dwFlags )
2020 ICOM_THIS(IDirectPlay2Impl,iface);
2021 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2022 lpEnumPlayersCallback2, lpContext,
2026 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2027 static HRESULT WINAPI DP_IF_EnumGroups
2028 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2029 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2030 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2032 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This,
2033 DPID_SYSTEM_GROUP, lpguidInstance,
2034 lpEnumPlayersCallback2, lpContext,
2038 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
2039 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2040 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2041 LPVOID lpContext, DWORD dwFlags )
2043 ICOM_THIS(IDirectPlay2Impl,iface);
2044 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2045 lpContext, dwFlags, TRUE );
2048 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
2049 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2050 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2051 LPVOID lpContext, DWORD dwFlags )
2053 ICOM_THIS(IDirectPlay2Impl,iface);
2054 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2055 lpContext, dwFlags, FALSE );
2058 static HRESULT WINAPI DP_IF_EnumPlayers
2059 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2060 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2061 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2063 return DP_IF_EnumGroupPlayers( This, DPID_SYSTEM_GROUP, lpguidInstance,
2064 lpEnumPlayersCallback2, lpContext,
2068 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
2069 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2070 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2071 LPVOID lpContext, DWORD dwFlags )
2073 ICOM_THIS(IDirectPlay2Impl,iface);
2074 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2075 lpContext, dwFlags, TRUE );
2078 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
2079 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2080 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2081 LPVOID lpContext, DWORD dwFlags )
2083 ICOM_THIS(IDirectPlay2Impl,iface);
2084 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2085 lpContext, dwFlags, FALSE );
2088 /* This function should call the registered callback function that the user
2089 passed into EnumSessions for each entry available.
2091 static void DP_InvokeEnumSessionCallbacks
2092 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2097 LPDPSESSIONDESC2 lpSessionDesc;
2099 FIXME( ": not checking for conditions\n" );
2101 /* Not sure if this should be pruning but it's convenient */
2102 NS_PruneSessionCache( lpNSInfo );
2104 NS_ResetSessionEnumeration( lpNSInfo );
2106 /* Enumerate all sessions */
2107 /* FIXME: Need to indicate ANSI */
2108 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2110 TRACE( "EnumSessionsCallback2 invoked\n" );
2111 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2117 /* Invoke one last time to indicate that there is no more to come */
2118 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2121 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2123 EnumSessionAsyncCallbackData* data = (EnumSessionAsyncCallbackData*)lpContext;
2124 HANDLE hSuicideRequest = data->hSuicideRequest;
2125 DWORD dwTimeout = data->dwTimeout;
2127 TRACE( "Thread started with timeout = 0x%08lx\n", dwTimeout );
2133 /* Sleep up to dwTimeout waiting for request to terminate thread */
2134 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2136 TRACE( "Thread terminating on terminate request\n" );
2140 /* Now resend the enum request */
2141 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2142 data->dwEnumSessionFlags,
2147 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2148 /* FIXME: Should we kill this thread? How to inform the main thread? */
2153 TRACE( "Thread terminating\n" );
2155 /* Clean up the thread data */
2156 CloseHandle( hSuicideRequest );
2157 HeapFree( GetProcessHeap(), 0, lpContext );
2159 /* FIXME: Need to have some notification to main app thread that this is
2160 * dead. It would serve two purposes. 1) allow sync on termination
2161 * so that we don't actually send something to ourselves when we
2162 * become name server (race condition) and 2) so that if we die
2163 * abnormally something else will be able to tell.
2169 static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
2171 /* Does a thread exist? If so we were doing an async enum session */
2172 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2174 TRACE( "Killing EnumSession thread %p\n",
2175 This->dp2->hEnumSessionThread );
2177 /* Request that the thread kill itself nicely */
2178 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2179 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2181 /* We no longer need to know about the thread */
2182 CloseHandle( This->dp2->hEnumSessionThread );
2184 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2188 static HRESULT WINAPI DP_IF_EnumSessions
2189 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2190 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2191 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2195 TRACE( "(%p)->(%p,0x%08lx,%p,%p,0x%08lx,%u)\n",
2196 This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags,
2199 /* Can't enumerate if the interface is already open */
2200 if( This->dp2->bConnectionOpen )
2202 return DPERR_GENERIC;
2206 /* The loading of a lobby provider _seems_ to require a backdoor loading
2207 * of the service provider to also associate with this DP object. This is
2208 * because the app doesn't seem to have to call EnumConnections and
2209 * InitializeConnection for the SP before calling this method. As such
2210 * we'll do their dirty work for them with a quick hack so as to always
2211 * load the TCP/IP service provider.
2213 * The correct solution would seem to involve creating a dialog box which
2214 * contains the possible SPs. These dialog boxes most likely follow SDK
2217 if( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
2219 LPVOID lpConnection;
2222 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2224 if( !DP_BuildSPCompoundAddr( (LPGUID)&DPSPGUID_TCPIP, &lpConnection, &dwSize ) )
2226 ERR( "Can't build compound addr\n" );
2227 return DPERR_GENERIC;
2230 hr = DP_IF_InitializeConnection( (IDirectPlay3Impl*)This, lpConnection,
2237 /* Free up the address buffer */
2238 HeapFree( GetProcessHeap(), 0, lpConnection );
2240 /* The SP is now initialized */
2241 This->dp2->bSPInitialized = TRUE;
2246 /* Use the service provider default? */
2247 if( dwTimeout == 0 )
2250 spCaps.dwSize = sizeof( spCaps );
2252 DP_IF_GetCaps( This, &spCaps, 0 );
2253 dwTimeout = spCaps.dwTimeout;
2255 /* The service provider doesn't provide one either! */
2256 if( dwTimeout == 0 )
2258 /* Provide the TCP/IP default */
2259 dwTimeout = DPMSG_WAIT_5_SECS;
2263 if( dwFlags & DPENUMSESSIONS_STOPASYNC )
2265 DP_KillEnumSessionThread( This );
2269 /* FIXME: Interface locking sucks in this method */
2270 if( ( dwFlags & DPENUMSESSIONS_ASYNC ) )
2272 /* Enumerate everything presently in the local session cache */
2273 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2274 This->dp2->lpNameServerData, dwTimeout,
2278 /* See if we've already created a thread to service this interface */
2279 if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2283 /* Send the first enum request inline since the user may cancel a dialog
2284 * if one is presented. Also, may also have a connecting return code.
2286 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2287 dwFlags, &This->dp2->spData );
2291 EnumSessionAsyncCallbackData* lpData
2292 = (EnumSessionAsyncCallbackData*)HeapAlloc( GetProcessHeap(),
2294 sizeof( *lpData ) );
2295 /* FIXME: need to kill the thread on object deletion */
2296 lpData->lpSpData = &This->dp2->spData;
2298 CopyMemory( &lpData->requestGuid, &lpsd->guidApplication, sizeof(GUID) );
2299 lpData->dwEnumSessionFlags = dwFlags;
2300 lpData->dwTimeout = dwTimeout;
2302 This->dp2->hKillEnumSessionThreadEvent =
2303 CreateEventA( NULL, TRUE, FALSE, NULL );
2305 if( !DuplicateHandle( GetCurrentProcess(),
2306 This->dp2->hKillEnumSessionThreadEvent,
2307 GetCurrentProcess(),
2308 &lpData->hSuicideRequest,
2309 0, FALSE, DUPLICATE_SAME_ACCESS )
2312 ERR( "Can't duplicate thread killing handle\n" );
2315 TRACE( ": creating EnumSessionsRequest thread\n" );
2317 This->dp2->hEnumSessionThread = CreateThread( NULL,
2319 DP_EnumSessionsSendAsyncRequestThread,
2328 /* Invalidate the session cache for the interface */
2329 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2331 /* Send the broadcast for session enumeration */
2332 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2334 &This->dp2->spData );
2337 SleepEx( dwTimeout, FALSE );
2339 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2340 This->dp2->lpNameServerData, dwTimeout,
2347 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2348 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2349 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2350 LPVOID lpContext, DWORD dwFlags )
2352 ICOM_THIS(IDirectPlay2Impl,iface);
2353 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2354 lpContext, dwFlags, TRUE );
2357 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2358 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2359 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2360 LPVOID lpContext, DWORD dwFlags )
2362 ICOM_THIS(IDirectPlay2Impl,iface);
2363 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2364 lpContext, dwFlags, FALSE );
2367 static HRESULT WINAPI DP_IF_GetPlayerCaps
2368 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
2371 DPSP_GETCAPSDATA data;
2373 TRACE("(%p)->(0x%08lx,%p,0x%08lx)\n", This, idPlayer, lpDPCaps, dwFlags);
2375 /* Query the service provider */
2376 data.idPlayer = idPlayer;
2377 data.dwFlags = dwFlags;
2378 data.lpCaps = lpDPCaps;
2379 data.lpISP = This->dp2->spData.lpISP;
2381 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2384 static HRESULT WINAPI DP_IF_GetCaps
2385 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags )
2387 return DP_IF_GetPlayerCaps( This, DPID_ALLPLAYERS, lpDPCaps, dwFlags );
2390 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2391 ( LPDIRECTPLAY2A iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2393 ICOM_THIS(IDirectPlay2Impl,iface);
2394 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2397 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2398 ( LPDIRECTPLAY2 iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2400 ICOM_THIS(IDirectPlay2Impl,iface);
2401 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2404 static HRESULT WINAPI DP_IF_GetGroupData
2405 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2406 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2408 lpGroupData lpGData;
2409 DWORD dwRequiredBufferSize;
2410 LPVOID lpCopyDataFrom;
2412 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
2413 This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi );
2415 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2417 return DPERR_INVALIDGROUP;
2420 /* How much buffer is required? */
2421 if( dwFlags & DPSET_REMOTE )
2423 dwRequiredBufferSize = lpGData->dwRemoteDataSize;
2424 lpCopyDataFrom = lpGData->lpRemoteData;
2426 else if( dwFlags & DPSET_LOCAL )
2428 dwRequiredBufferSize = lpGData->dwLocalDataSize;
2429 lpCopyDataFrom = lpGData->lpLocalData;
2433 ERR( "Neither local or remote data requested!?!\n" );
2434 dwRequiredBufferSize = 0;
2435 lpCopyDataFrom = NULL;
2438 /* Is the user requesting to know how big a buffer is required? */
2439 if( ( lpData == NULL ) ||
2440 ( *lpdwDataSize < dwRequiredBufferSize )
2443 *lpdwDataSize = dwRequiredBufferSize;
2444 return DPERR_BUFFERTOOSMALL;
2447 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2452 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2453 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2454 LPDWORD lpdwDataSize, DWORD dwFlags )
2456 ICOM_THIS(IDirectPlay2Impl,iface);
2457 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2461 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2462 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2463 LPDWORD lpdwDataSize, DWORD dwFlags )
2465 ICOM_THIS(IDirectPlay2Impl,iface);
2466 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2470 static HRESULT WINAPI DP_IF_GetGroupName
2471 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2472 LPDWORD lpdwDataSize, BOOL bAnsi )
2474 lpGroupData lpGData;
2475 LPDPNAME lpName = (LPDPNAME)lpData;
2476 DWORD dwRequiredDataSize;
2478 FIXME("(%p)->(0x%08lx,%p,%p,%u) ANSI ignored\n",
2479 This, idGroup, lpData, lpdwDataSize, bAnsi );
2481 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2483 return DPERR_INVALIDGROUP;
2486 dwRequiredDataSize = lpGData->name.dwSize;
2488 if( lpGData->name.u1.lpszShortNameA )
2490 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
2493 if( lpGData->name.u2.lpszLongNameA )
2495 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
2498 if( ( lpData == NULL ) ||
2499 ( *lpdwDataSize < dwRequiredDataSize )
2502 *lpdwDataSize = dwRequiredDataSize;
2503 return DPERR_BUFFERTOOSMALL;
2506 /* Copy the structure */
2507 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2509 if( lpGData->name.u1.lpszShortNameA )
2511 strcpy( ((BYTE*)lpName)+lpGData->name.dwSize,
2512 lpGData->name.u1.lpszShortNameA );
2516 lpName->u1.lpszShortNameA = NULL;
2519 if( lpGData->name.u1.lpszShortNameA )
2521 strcpy( ((BYTE*)lpName)+lpGData->name.dwSize,
2522 lpGData->name.u2.lpszLongNameA );
2526 lpName->u2.lpszLongNameA = NULL;
2532 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2533 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2534 LPDWORD lpdwDataSize )
2536 ICOM_THIS(IDirectPlay2Impl,iface);
2537 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2540 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2541 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2542 LPDWORD lpdwDataSize )
2544 ICOM_THIS(IDirectPlay2Impl,iface);
2545 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2548 static HRESULT WINAPI DP_IF_GetMessageCount
2549 ( IDirectPlay2Impl* This, DPID idPlayer,
2550 LPDWORD lpdwCount, BOOL bAnsi )
2552 FIXME("(%p)->(0x%08lx,%p,%u): stub\n", This, idPlayer, lpdwCount, bAnsi );
2553 return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer,
2554 DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL,
2558 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2559 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDWORD lpdwCount )
2561 ICOM_THIS(IDirectPlay2Impl,iface);
2562 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, TRUE );
2565 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2566 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDWORD lpdwCount )
2568 ICOM_THIS(IDirectPlay2Impl,iface);
2569 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, FALSE );
2572 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2573 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2575 ICOM_THIS(IDirectPlay2Impl,iface);
2576 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2580 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2581 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2583 ICOM_THIS(IDirectPlay2Impl,iface);
2584 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2588 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2589 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2592 ICOM_THIS(IDirectPlay2Impl,iface);
2593 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2596 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2597 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2600 ICOM_THIS(IDirectPlay2Impl,iface);
2601 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2604 static HRESULT WINAPI DP_IF_GetPlayerData
2605 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2606 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2608 lpPlayerList lpPList;
2609 DWORD dwRequiredBufferSize;
2610 LPVOID lpCopyDataFrom;
2612 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
2613 This, idPlayer, lpData, lpdwDataSize, dwFlags, bAnsi );
2615 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2617 return DPERR_INVALIDPLAYER;
2620 /* How much buffer is required? */
2621 if( dwFlags & DPSET_REMOTE )
2623 dwRequiredBufferSize = lpPList->lpPData->dwRemoteDataSize;
2624 lpCopyDataFrom = lpPList->lpPData->lpRemoteData;
2626 else if( dwFlags & DPSET_LOCAL )
2628 dwRequiredBufferSize = lpPList->lpPData->dwLocalDataSize;
2629 lpCopyDataFrom = lpPList->lpPData->lpLocalData;
2633 ERR( "Neither local or remote data requested!?!\n" );
2634 dwRequiredBufferSize = 0;
2635 lpCopyDataFrom = NULL;
2638 /* Is the user requesting to know how big a buffer is required? */
2639 if( ( lpData == NULL ) ||
2640 ( *lpdwDataSize < dwRequiredBufferSize )
2643 *lpdwDataSize = dwRequiredBufferSize;
2644 return DPERR_BUFFERTOOSMALL;
2647 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2652 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2653 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2654 LPDWORD lpdwDataSize, DWORD dwFlags )
2656 ICOM_THIS(IDirectPlay2Impl,iface);
2657 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2661 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2662 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2663 LPDWORD lpdwDataSize, DWORD dwFlags )
2665 ICOM_THIS(IDirectPlay2Impl,iface);
2666 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2670 static HRESULT WINAPI DP_IF_GetPlayerName
2671 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2672 LPDWORD lpdwDataSize, BOOL bAnsi )
2674 lpPlayerList lpPList;
2675 LPDPNAME lpName = (LPDPNAME)lpData;
2676 DWORD dwRequiredDataSize;
2678 FIXME( "(%p)->(0x%08lx,%p,%p,%u): ANSI \n",
2679 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2681 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2683 return DPERR_INVALIDPLAYER;
2686 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
2688 if( lpPList->lpPData->name.u1.lpszShortNameA )
2690 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
2693 if( lpPList->lpPData->name.u2.lpszLongNameA )
2695 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
2698 if( ( lpData == NULL ) ||
2699 ( *lpdwDataSize < dwRequiredDataSize )
2702 *lpdwDataSize = dwRequiredDataSize;
2703 return DPERR_BUFFERTOOSMALL;
2706 /* Copy the structure */
2707 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
2709 if( lpPList->lpPData->name.u1.lpszShortNameA )
2711 strcpy( ((BYTE*)lpName)+lpPList->lpPData->name.dwSize,
2712 lpPList->lpPData->name.u1.lpszShortNameA );
2716 lpName->u1.lpszShortNameA = NULL;
2719 if( lpPList->lpPData->name.u1.lpszShortNameA )
2721 strcpy( ((BYTE*)lpName)+lpPList->lpPData->name.dwSize,
2722 lpPList->lpPData->name.u2.lpszLongNameA );
2726 lpName->u2.lpszLongNameA = NULL;
2732 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2733 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2734 LPDWORD lpdwDataSize )
2736 ICOM_THIS(IDirectPlay2Impl,iface);
2737 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
2740 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2741 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2742 LPDWORD lpdwDataSize )
2744 ICOM_THIS(IDirectPlay2Impl,iface);
2745 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
2748 static HRESULT WINAPI DP_GetSessionDesc
2749 ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize,
2752 DWORD dwRequiredSize;
2754 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
2756 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
2758 return DPERR_INVALIDPARAMS;
2761 /* FIXME: Get from This->dp2->lpSessionDesc */
2762 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
2764 if ( ( lpData == NULL ) ||
2765 ( *lpdwDataSize < dwRequiredSize )
2768 *lpdwDataSize = dwRequiredSize;
2769 return DPERR_BUFFERTOOSMALL;
2772 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
2777 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
2778 ( LPDIRECTPLAY2A iface, LPVOID lpData, LPDWORD lpdwDataSize )
2780 ICOM_THIS(IDirectPlay2Impl,iface);
2781 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2784 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
2785 ( LPDIRECTPLAY2 iface, LPVOID lpData, LPDWORD lpdwDataSize )
2787 ICOM_THIS(IDirectPlay2Impl,iface);
2788 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2791 /* Intended only for COM compatibility. Always returns an error. */
2792 static HRESULT WINAPI DirectPlay2AImpl_Initialize
2793 ( LPDIRECTPLAY2A iface, LPGUID lpGUID )
2795 ICOM_THIS(IDirectPlay2Impl,iface);
2796 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2797 return DPERR_ALREADYINITIALIZED;
2800 /* Intended only for COM compatibility. Always returns an error. */
2801 static HRESULT WINAPI DirectPlay2WImpl_Initialize
2802 ( LPDIRECTPLAY2 iface, LPGUID lpGUID )
2804 ICOM_THIS(IDirectPlay2Impl,iface);
2805 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2806 return DPERR_ALREADYINITIALIZED;
2810 static HRESULT WINAPI DP_SecureOpen
2811 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
2812 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
2817 FIXME( "(%p)->(%p,0x%08lx,%p,%p): partial stub\n",
2818 This, lpsd, dwFlags, lpSecurity, lpCredentials );
2820 if( This->dp2->bConnectionOpen )
2822 TRACE( ": rejecting already open connection.\n" );
2823 return DPERR_ALREADYINITIALIZED;
2826 /* If we're enumerating, kill the thread */
2827 DP_KillEnumSessionThread( This );
2829 if( dwFlags & DPOPEN_CREATE )
2831 /* Rightoo - this computer is the host and the local computer needs to be
2832 the name server so that others can join this session */
2833 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
2835 This->dp2->bHostInterface = TRUE;
2837 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
2840 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
2845 /* Invoke the conditional callback for the service provider */
2846 if( This->dp2->spData.lpCB->Open )
2850 FIXME( "Not all data fields are correct. Need new parameter\n" );
2852 data.bCreate = (dwFlags & DPOPEN_CREATE ) ? TRUE : FALSE;
2853 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
2854 : NS_GetNSAddr( This->dp2->lpNameServerData );
2855 data.lpISP = This->dp2->spData.lpISP;
2856 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) ? TRUE : FALSE;
2857 data.dwOpenFlags = dwFlags;
2858 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
2860 hr = (*This->dp2->spData.lpCB->Open)(&data);
2863 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
2869 /* Create the system group of which everything is a part of */
2870 DPID systemGroup = DPID_SYSTEM_GROUP;
2872 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
2877 if( dwFlags & DPOPEN_JOIN )
2879 DPID dpidServerId = DPID_UNKNOWN;
2881 /* Create the server player for this interface. This way we can receive
2882 * messages for this session.
2884 /* FIXME: I suppose that we should be setting an event for a receive
2885 * type of thing. That way the messaging thread could know to wake
2886 * up. DPlay would then trigger the hEvent for the player the
2887 * message is directed to.
2889 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
2891 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
2894 else if( dwFlags & DPOPEN_CREATE )
2896 DPID dpidNameServerId = DPID_NAME_SERVER;
2898 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
2899 0, DPPLAYER_SERVERPLAYER, bAnsi );
2904 ERR( "Couldn't create name server/system player: %s\n",
2905 DPLAYX_HresultToString(hr) );
2911 static HRESULT WINAPI DirectPlay2AImpl_Open
2912 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2914 ICOM_THIS(IDirectPlay2Impl,iface);
2915 TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags );
2916 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, TRUE );
2919 static HRESULT WINAPI DirectPlay2WImpl_Open
2920 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2922 ICOM_THIS(IDirectPlay2Impl,iface);
2923 TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags );
2924 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, FALSE );
2927 static HRESULT WINAPI DP_IF_Receive
2928 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
2929 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi )
2931 LPDPMSG lpMsg = NULL;
2933 FIXME( "(%p)->(%p,%p,0x%08lx,%p,%p,%u): stub\n",
2934 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
2938 dwFlags = DPRECEIVE_ALL;
2941 /* If the lpData is NULL, we must be peeking the message */
2942 if( ( lpData == NULL ) &&
2943 !( dwFlags & DPRECEIVE_PEEK )
2946 return DPERR_INVALIDPARAMS;
2949 if( dwFlags & DPRECEIVE_ALL )
2951 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
2953 if( !( dwFlags & DPRECEIVE_PEEK ) )
2955 FIXME( "Remove from queue\n" );
2958 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
2959 ( dwFlags & DPRECEIVE_FROMPLAYER )
2962 FIXME( "Find matching message 0x%08lx\n", dwFlags );
2966 ERR( "Hmmm..dwFlags 0x%08lx\n", dwFlags );
2971 return DPERR_NOMESSAGES;
2974 /* Copy into the provided buffer */
2975 CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
2980 static HRESULT WINAPI DirectPlay2AImpl_Receive
2981 ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo,
2982 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
2984 ICOM_THIS(IDirectPlay2Impl,iface);
2985 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
2986 lpData, lpdwDataSize, TRUE );
2989 static HRESULT WINAPI DirectPlay2WImpl_Receive
2990 ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo,
2991 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
2993 ICOM_THIS(IDirectPlay2Impl,iface);
2994 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
2995 lpData, lpdwDataSize, FALSE );
2998 static HRESULT WINAPI DirectPlay2AImpl_Send
2999 ( LPDIRECTPLAY2A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3001 ICOM_THIS(IDirectPlay2Impl,iface);
3002 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3003 0, 0, NULL, NULL, TRUE );
3006 static HRESULT WINAPI DirectPlay2WImpl_Send
3007 ( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
3009 ICOM_THIS(IDirectPlay2Impl,iface);
3010 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
3011 0, 0, NULL, NULL, FALSE );
3014 static HRESULT WINAPI DP_IF_SetGroupData
3015 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
3016 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3018 lpGroupData lpGData;
3020 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
3021 This, idGroup, lpData, dwDataSize, dwFlags, bAnsi );
3023 /* Parameter check */
3024 if( ( lpData == NULL ) &&
3028 return DPERR_INVALIDPARAMS;
3031 /* Find the pointer to the data for this player */
3032 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3034 return DPERR_INVALIDOBJECT;
3037 if( dwFlags & DPSET_REMOTE )
3039 FIXME( "Was this group created by this interface?\n" );
3040 /* FIXME: If this is a remote update need to allow it but not
3045 DP_SetGroupData( lpGData, dwFlags, lpData, dwDataSize );
3047 /* FIXME: Only send a message if this group is local to the session otherwise
3048 * it will have been rejected above
3050 if( dwFlags & DPSET_REMOTE )
3052 FIXME( "Send msg?\n" );
3058 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
3059 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
3060 DWORD dwDataSize, DWORD dwFlags )
3062 ICOM_THIS(IDirectPlay2Impl,iface);
3063 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, TRUE );
3066 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
3067 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
3068 DWORD dwDataSize, DWORD dwFlags )
3070 ICOM_THIS(IDirectPlay2Impl,iface);
3071 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, FALSE );
3074 static HRESULT WINAPI DP_IF_SetGroupName
3075 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
3076 DWORD dwFlags, BOOL bAnsi )
3078 lpGroupData lpGData;
3080 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n", This, idGroup,
3081 lpGroupName, dwFlags, bAnsi );
3083 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3085 return DPERR_INVALIDGROUP;
3088 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
3090 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3091 FIXME( "Message not sent and dwFlags ignored\n" );
3096 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
3097 ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName,
3100 ICOM_THIS(IDirectPlay2Impl,iface);
3101 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
3104 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
3105 ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName,
3108 ICOM_THIS(IDirectPlay2Impl,iface);
3109 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
3112 static HRESULT WINAPI DP_IF_SetPlayerData
3113 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
3114 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3116 lpPlayerList lpPList;
3118 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
3119 This, idPlayer, lpData, dwDataSize, dwFlags, bAnsi );
3121 /* Parameter check */
3122 if( ( lpData == NULL ) &&
3126 return DPERR_INVALIDPARAMS;
3129 /* Find the pointer to the data for this player */
3130 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3132 return DPERR_INVALIDPLAYER;
3135 if( dwFlags & DPSET_REMOTE )
3137 FIXME( "Was this group created by this interface?\n" );
3138 /* FIXME: If this is a remote update need to allow it but not
3143 DP_SetPlayerData( lpPList->lpPData, dwFlags, lpData, dwDataSize );
3145 if( dwFlags & DPSET_REMOTE )
3147 FIXME( "Send msg?\n" );
3153 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3154 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
3155 DWORD dwDataSize, DWORD dwFlags )
3157 ICOM_THIS(IDirectPlay2Impl,iface);
3158 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3162 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3163 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
3164 DWORD dwDataSize, DWORD dwFlags )
3166 ICOM_THIS(IDirectPlay2Impl,iface);
3167 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3171 static HRESULT WINAPI DP_IF_SetPlayerName
3172 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
3173 DWORD dwFlags, BOOL bAnsi )
3175 lpPlayerList lpPList;
3177 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n",
3178 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3180 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3182 return DPERR_INVALIDGROUP;
3185 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3187 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3188 FIXME( "Message not sent and dwFlags ignored\n" );
3193 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3194 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName,
3197 ICOM_THIS(IDirectPlay2Impl,iface);
3198 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3201 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3202 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName,
3205 ICOM_THIS(IDirectPlay2Impl,iface);
3206 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3209 static HRESULT WINAPI DP_SetSessionDesc
3210 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
3211 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3213 DWORD dwRequiredSize;
3214 LPDPSESSIONDESC2 lpTempSessDesc;
3216 TRACE( "(%p)->(%p,0x%08lx,%u,%u)\n",
3217 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3221 return DPERR_INVALIDPARAMS;
3224 /* Only the host is allowed to update the session desc */
3225 if( !This->dp2->bHostInterface )
3227 return DPERR_ACCESSDENIED;
3230 /* FIXME: Copy into This->dp2->lpSessionDesc */
3231 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3232 lpTempSessDesc = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
3236 if( lpTempSessDesc == NULL )
3238 return DPERR_OUTOFMEMORY;
3242 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3244 This->dp2->lpSessionDesc = lpTempSessDesc;
3247 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3249 /* If this is an external invocation of the interface, we should be
3250 * letting everyone know that things have changed. Otherwise this is
3251 * just an initialization and it doesn't need to be propagated.
3255 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3261 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3262 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3264 ICOM_THIS(IDirectPlay2Impl,iface);
3265 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3268 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3269 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3271 ICOM_THIS(IDirectPlay2Impl,iface);
3272 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3275 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3276 DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3280 if( lpSessDesc == NULL )
3282 /* Hmmm..don't need any size? */
3283 ERR( "NULL lpSessDesc\n" );
3287 dwSize += sizeof( *lpSessDesc );
3291 if( lpSessDesc->u1.lpszSessionNameA )
3293 dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1;
3296 if( lpSessDesc->u2.lpszPasswordA )
3298 dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1;
3303 if( lpSessDesc->u1.lpszSessionName )
3305 dwSize += sizeof( WCHAR ) *
3306 ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 );
3309 if( lpSessDesc->u2.lpszPassword )
3311 dwSize += sizeof( WCHAR ) *
3312 ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 );
3319 /* Assumes that contugous buffers are already allocated. */
3320 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3321 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3323 BYTE* lpStartOfFreeSpace;
3325 if( lpSessionDest == NULL )
3327 ERR( "NULL lpSessionDest\n" );
3331 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3333 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3337 if( lpSessionSrc->u1.lpszSessionNameA )
3339 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3340 lpSessionDest->u1.lpszSessionNameA );
3341 lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3342 lpStartOfFreeSpace +=
3343 lstrlenA( (LPSTR)lpSessionDest->u1.lpszSessionNameA ) + 1;
3346 if( lpSessionSrc->u2.lpszPasswordA )
3348 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3349 lpSessionDest->u2.lpszPasswordA );
3350 lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3351 lpStartOfFreeSpace +=
3352 lstrlenA( (LPSTR)lpSessionDest->u2.lpszPasswordA ) + 1;
3357 if( lpSessionSrc->u1.lpszSessionName )
3359 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3360 lpSessionDest->u1.lpszSessionName );
3361 lpSessionDest->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3362 lpStartOfFreeSpace += sizeof(WCHAR) *
3363 ( lstrlenW( (LPWSTR)lpSessionDest->u1.lpszSessionName ) + 1 );
3366 if( lpSessionSrc->u2.lpszPassword )
3368 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3369 lpSessionDest->u2.lpszPassword );
3370 lpSessionDest->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3371 lpStartOfFreeSpace += sizeof(WCHAR) *
3372 ( lstrlenW( (LPWSTR)lpSessionDest->u2.lpszPassword ) + 1 );
3378 static HRESULT WINAPI DP_IF_AddGroupToGroup
3379 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3381 lpGroupData lpGParentData;
3382 lpGroupData lpGData;
3383 lpGroupList lpNewGList;
3385 TRACE( "(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup );
3387 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3389 return DPERR_INVALIDGROUP;
3392 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3394 return DPERR_INVALIDGROUP;
3397 /* Create a player list (ie "shortcut" ) */
3398 lpNewGList = (lpGroupList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3399 sizeof( *lpNewGList ) );
3400 if( lpNewGList == NULL )
3402 return DPERR_CANTADDPLAYER;
3405 /* Add the shortcut */
3407 lpNewGList->lpGData = lpGData;
3409 /* Add the player to the list of players for this group */
3410 DPQ_INSERT( lpGData->groups, lpNewGList, groups );
3412 /* Send a ADDGROUPTOGROUP message */
3413 FIXME( "Not sending message\n" );
3418 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3419 ( LPDIRECTPLAY3A iface, DPID idParentGroup, DPID idGroup )
3421 ICOM_THIS(IDirectPlay3Impl,iface);
3422 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3425 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3426 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3428 ICOM_THIS(IDirectPlay3Impl,iface);
3429 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3432 static HRESULT WINAPI DP_IF_CreateGroupInGroup
3433 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
3434 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
3435 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3437 lpGroupData lpGParentData;
3438 lpGroupList lpGList;
3439 lpGroupData lpGData;
3441 TRACE( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
3442 This, idParentGroup, lpidGroup, lpGroupName, lpData,
3443 dwDataSize, dwFlags, bAnsi );
3445 /* Verify that the specified parent is valid */
3446 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This,
3447 idParentGroup ) ) == NULL
3450 return DPERR_INVALIDGROUP;
3453 lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName,
3454 dwFlags, idParentGroup, bAnsi );
3456 if( lpGData == NULL )
3458 return DPERR_CANTADDPLAYER; /* yes player not group */
3461 /* Something else is referencing this data */
3464 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
3466 /* The list has now been inserted into the interface group list. We now
3467 need to put a "shortcut" to this group in the parent group */
3468 lpGList = (lpGroupList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3469 sizeof( *lpGList ) );
3470 if( lpGList == NULL )
3472 FIXME( "Memory leak\n" );
3473 return DPERR_CANTADDPLAYER; /* yes player not group */
3476 lpGList->lpGData = lpGData;
3478 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
3480 /* Let the SP know that we've created this group */
3481 if( This->dp2->spData.lpCB->CreateGroup )
3483 DPSP_CREATEGROUPDATA data;
3485 TRACE( "Calling SP CreateGroup\n" );
3487 data.idGroup = *lpidGroup;
3488 data.dwFlags = dwFlags;
3489 data.lpSPMessageHeader = lpMsgHdr;
3490 data.lpISP = This->dp2->spData.lpISP;
3492 (*This->dp2->spData.lpCB->CreateGroup)( &data );
3495 /* Inform all other peers of the creation of a new group. If there are
3496 * no peers keep this quiet.
3498 if( This->dp2->lpSessionDesc &&
3499 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
3501 DPMSG_CREATEPLAYERORGROUP msg;
3503 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
3504 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
3505 msg.dpId = *lpidGroup;
3506 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
3507 msg.lpData = lpData;
3508 msg.dwDataSize = dwDataSize;
3509 msg.dpnName = *lpGroupName;
3511 /* FIXME: Correct to just use send effectively? */
3512 /* FIXME: Should size include data w/ message or just message "header" */
3513 /* FIXME: Check return code */
3514 DP_SendEx( (IDirectPlay2Impl*)This,
3515 DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
3516 0, 0, NULL, NULL, bAnsi );
3522 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3523 ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup,
3524 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3527 ICOM_THIS(IDirectPlay3Impl,iface);
3529 *lpidGroup = DPID_UNKNOWN;
3531 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3532 lpGroupName, lpData, dwDataSize, dwFlags,
3536 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3537 ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup,
3538 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3541 ICOM_THIS(IDirectPlay3Impl,iface);
3543 *lpidGroup = DPID_UNKNOWN;
3545 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3546 lpGroupName, lpData, dwDataSize,
3550 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
3551 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3553 lpGroupList lpGList;
3554 lpGroupData lpGParentData;
3556 TRACE("(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup );
3558 /* Is the parent group valid? */
3559 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3561 return DPERR_INVALIDGROUP;
3564 /* Remove the group from the parent group queue */
3565 DPQ_REMOVE_ENTRY( lpGParentData->groups, groups, lpGData->dpid, ==, idGroup, lpGList );
3567 if( lpGList == NULL )
3569 return DPERR_INVALIDGROUP;
3572 /* Decrement the ref count */
3573 lpGList->lpGData->uRef--;
3575 /* Free up the list item */
3576 HeapFree( GetProcessHeap(), 0, lpGList );
3578 /* Should send a DELETEGROUPFROMGROUP message */
3579 FIXME( "message not sent\n" );
3584 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3585 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3587 ICOM_THIS(IDirectPlay3Impl,iface);
3588 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3591 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3592 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3594 ICOM_THIS(IDirectPlay3Impl,iface);
3595 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3599 BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
3600 LPDWORD lpdwBufSize )
3602 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3605 dpCompoundAddress.dwDataSize = sizeof( GUID );
3606 memcpy( &dpCompoundAddress.guidDataType, &DPAID_ServiceProvider,
3608 dpCompoundAddress.lpData = lpcSpGuid;
3610 *lplpAddrBuf = NULL;
3613 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3614 lpdwBufSize, TRUE );
3616 if( hr != DPERR_BUFFERTOOSMALL )
3618 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3622 /* Now allocate the buffer */
3623 *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3626 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3627 lpdwBufSize, TRUE );
3630 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3637 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
3638 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3640 ICOM_THIS(IDirectPlay3Impl,iface);
3641 TRACE("(%p)->(%p,%p,%p,0x%08lx)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3643 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
3646 dwFlags = DPCONNECTION_DIRECTPLAY;
3649 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
3650 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) )
3653 return DPERR_INVALIDFLAGS;
3656 if( !lpEnumCallback || !*lpEnumCallback )
3658 return DPERR_INVALIDPARAMS;
3661 /* Enumerate DirectPlay service providers */
3662 if( dwFlags & DPCONNECTION_DIRECTPLAY )
3665 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3666 LPSTR guidDataSubKey = "Guid";
3667 char subKeyName[51];
3668 DWORD dwIndex, sizeOfSubKeyName=50;
3671 /* Need to loop over the service providers in the registry */
3672 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3673 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3675 /* Hmmm. Does this mean that there are no service providers? */
3676 ERR(": no service providers?\n");
3681 /* Traverse all the service providers we have available */
3683 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3684 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3685 ++dwIndex, sizeOfSubKeyName=51 )
3688 HKEY hkServiceProvider;
3689 GUID serviceProviderGUID;
3690 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3691 char returnBuffer[51];
3696 LPVOID lpAddressBuffer = NULL;
3697 DWORD dwAddressBufferSize = 0;
3699 TRACE(" this time through: %s\n", subKeyName );
3701 /* Get a handle for this particular service provider */
3702 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3703 &hkServiceProvider ) != ERROR_SUCCESS )
3705 ERR(": what the heck is going on?\n" );
3709 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3710 NULL, &returnTypeGUID, returnBuffer,
3711 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3713 ERR(": missing GUID registry data members\n" );
3717 /* FIXME: Check return types to ensure we're interpreting data right */
3718 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3719 CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
3720 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3722 /* Fill in the DPNAME struct for the service provider */
3723 dpName.dwSize = sizeof( dpName );
3725 dpName.u1.lpszShortNameA = subKeyName;
3726 dpName.u2.lpszLongNameA = NULL;
3728 /* Create the compound address for the service provider.
3729 * NOTE: This is a gruesome architectural scar right now. DP
3730 * uses DPL and DPL uses DP. Nasty stuff. This may be why the
3731 * native dll just gets around this little bit by allocating an
3732 * 80 byte buffer which isn't even filled with a valid compound
3733 * address. Oh well. Creating a proper compound address is the
3734 * way to go anyways despite this method taking slightly more
3735 * heap space and realtime :) */
3737 bBuildPass = DP_BuildSPCompoundAddr( &serviceProviderGUID,
3739 &dwAddressBufferSize );
3742 ERR( "Can't build compound addr\n" );
3743 return DPERR_GENERIC;
3746 /* The enumeration will return FALSE if we are not to continue */
3747 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3748 &dpName, DPCONNECTION_DIRECTPLAY, lpContext ) )
3755 /* Enumerate DirectPlayLobby service providers */
3756 if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY )
3759 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3760 LPSTR guidDataSubKey = "Guid";
3761 char subKeyName[51];
3762 DWORD dwIndex, sizeOfSubKeyName=50;
3765 /* Need to loop over the service providers in the registry */
3766 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3767 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3769 /* Hmmm. Does this mean that there are no service providers? */
3770 ERR(": no service providers?\n");
3775 /* Traverse all the lobby providers we have available */
3777 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3778 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3779 ++dwIndex, sizeOfSubKeyName=51 )
3782 HKEY hkServiceProvider;
3783 GUID serviceProviderGUID;
3784 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3785 char returnBuffer[51];
3790 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3791 LPVOID lpAddressBuffer = NULL;
3792 DWORD dwAddressBufferSize = 0;
3794 TRACE(" this time through: %s\n", subKeyName );
3796 /* Get a handle for this particular service provider */
3797 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3798 &hkServiceProvider ) != ERROR_SUCCESS )
3800 ERR(": what the heck is going on?\n" );
3804 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3805 NULL, &returnTypeGUID, returnBuffer,
3806 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3808 ERR(": missing GUID registry data members\n" );
3812 /* FIXME: Check return types to ensure we're interpreting data right */
3813 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3814 CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
3815 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3817 /* Fill in the DPNAME struct for the service provider */
3818 dpName.dwSize = sizeof( dpName );
3820 dpName.u1.lpszShortNameA = subKeyName;
3821 dpName.u2.lpszLongNameA = NULL;
3823 /* Create the compound address for the service provider.
3824 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
3825 nast stuff. This may be why the native dll just gets around this little bit by
3826 allocating an 80 byte buffer which isn't even a filled with a valid compound
3827 address. Oh well. Creating a proper compound address is the way to go anyways
3828 despite this method taking slightly more heap space and realtime :) */
3830 dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
3831 dpCompoundAddress.dwDataSize = sizeof( GUID );
3832 dpCompoundAddress.lpData = &serviceProviderGUID;
3834 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3835 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
3837 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3841 /* Now allocate the buffer */
3842 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
3844 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3845 &dwAddressBufferSize, TRUE ) ) != DP_OK )
3847 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3851 /* The enumeration will return FALSE if we are not to continue */
3852 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3853 &dpName, DPCONNECTION_DIRECTPLAYLOBBY, lpContext ) )
3863 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
3864 ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3866 ICOM_THIS(IDirectPlay3Impl,iface);
3867 FIXME("(%p)->(%p,%p,%p,0x%08lx): stub\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3871 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
3872 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
3873 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
3874 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
3876 lpGroupList lpGList;
3877 lpGroupData lpGData;
3879 FIXME( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
3880 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
3881 lpContext, dwFlags, bAnsi );
3883 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3885 return DPERR_INVALIDGROUP;
3888 if( DPQ_IS_EMPTY( lpGData->groups ) )
3893 lpGList = DPQ_FIRST( lpGData->groups );
3897 /* FIXME: Should check dwFlags for match here */
3899 if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP,
3900 &lpGList->lpGData->name, dwFlags,
3903 return DP_OK; /* User requested break */
3906 if( DPQ_IS_ENDOFLIST( lpGList->groups ) )
3911 lpGList = DPQ_NEXT( lpGList->groups );
3918 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
3919 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3920 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3923 ICOM_THIS(IDirectPlay3Impl,iface);
3924 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3925 lpEnumPlayersCallback2, lpContext, dwFlags,
3929 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
3930 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3931 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3934 ICOM_THIS(IDirectPlay3Impl,iface);
3935 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3936 lpEnumPlayersCallback2, lpContext, dwFlags,
3940 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
3941 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3943 ICOM_THIS(IDirectPlay3Impl,iface);
3944 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3948 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
3949 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3951 ICOM_THIS(IDirectPlay3Impl,iface);
3952 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3956 BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
3957 REFGUID guidDataType,
3962 /* Looking for the GUID of the provider to load */
3963 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
3964 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
3967 TRACE( "Found SP/LP (%s) %s (data size = 0x%08lx)\n",
3968 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
3970 if( dwDataSize != sizeof( GUID ) )
3972 ERR( "Invalid sp/lp guid size 0x%08lx\n", dwDataSize );
3975 memcpy( lpContext, lpData, dwDataSize );
3977 /* There shouldn't be more than 1 GUID/compound address */
3981 /* Still waiting for what we want */
3986 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
3987 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
3990 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3991 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3992 LPCSTR guidDataSubKey = "Guid";
3993 LPCSTR majVerDataSubKey = "dwReserved1";
3994 LPCSTR minVerDataSubKey = "dwReserved2";
3995 LPCSTR pathSubKey = "Path";
3997 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
3999 /* FIXME: Cloned code with a quick hack. */
4000 for( i=0; i<2; i++ )
4003 LPCSTR searchSubKey;
4004 char subKeyName[51];
4005 DWORD dwIndex, sizeOfSubKeyName=50;
4008 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
4009 *lpbIsDpSp = (i == 0) ? TRUE : FALSE;
4012 /* Need to loop over the service providers in the registry */
4013 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4014 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4016 /* Hmmm. Does this mean that there are no service providers? */
4017 ERR(": no service providers?\n");
4021 /* Traverse all the service providers we have available */
4023 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4024 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4025 ++dwIndex, sizeOfSubKeyName=51 )
4028 HKEY hkServiceProvider;
4029 GUID serviceProviderGUID;
4030 DWORD returnType, sizeOfReturnBuffer = 255;
4031 char returnBuffer[256];
4035 TRACE(" this time through: %s\n", subKeyName );
4037 /* Get a handle for this particular service provider */
4038 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4039 &hkServiceProvider ) != ERROR_SUCCESS )
4041 ERR(": what the heck is going on?\n" );
4045 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4046 NULL, &returnType, returnBuffer,
4047 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4049 ERR(": missing GUID registry data members\n" );
4053 /* FIXME: Check return types to ensure we're interpreting data right */
4054 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4055 CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
4056 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4058 /* Determine if this is the Service Provider that the user asked for */
4059 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
4064 if( i == 0 ) /* DP SP */
4066 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
4067 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
4068 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
4071 sizeOfReturnBuffer = 255;
4073 /* Get dwReserved1 */
4074 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
4075 NULL, &returnType, returnBuffer,
4076 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4078 ERR(": missing dwReserved1 registry data members\n") ;
4083 memcpy( &lpSpData->dwReserved1, returnBuffer, sizeof(lpSpData->dwReserved1) );
4085 sizeOfReturnBuffer = 255;
4087 /* Get dwReserved2 */
4088 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4089 NULL, &returnType, returnBuffer,
4090 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4092 ERR(": missing dwReserved1 registry data members\n") ;
4097 memcpy( &lpSpData->dwReserved2, returnBuffer, sizeof(lpSpData->dwReserved2) );
4099 sizeOfReturnBuffer = 255;
4101 /* Get the path for this service provider */
4102 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
4103 NULL, NULL, returnBuffer,
4104 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
4106 ERR(": missing PATH registry data members: 0x%08lx\n", dwTemp );
4110 TRACE( "Loading %s\n", returnBuffer );
4111 return LoadLibraryA( returnBuffer );
4119 HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider )
4122 LPDPSP_SPINIT SPInit;
4124 /* Initialize the service provider by calling SPInit */
4125 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4127 if( SPInit == NULL )
4129 ERR( "Service provider doesn't provide SPInit interface?\n" );
4130 FreeLibrary( hServiceProvider );
4131 return DPERR_UNAVAILABLE;
4134 TRACE( "Calling SPInit (DP SP entry point)\n" );
4136 hr = (*SPInit)( &This->dp2->spData );
4140 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4141 FreeLibrary( hServiceProvider );
4145 /* FIXME: Need to verify the sanity of the returned callback table
4146 * using IsBadCodePtr */
4147 This->dp2->bSPInitialized = TRUE;
4149 /* This interface is now initialized as a DP object */
4150 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
4152 /* Store the handle of the module so that we can unload it later */
4153 This->dp2->hServiceProvider = hServiceProvider;
4159 HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hLobbyProvider )
4162 LPSP_INIT DPLSPInit;
4164 /* Initialize the service provider by calling SPInit */
4165 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
4167 if( DPLSPInit == NULL )
4169 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4170 FreeLibrary( hLobbyProvider );
4171 return DPERR_UNAVAILABLE;
4174 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4176 hr = (*DPLSPInit)( &This->dp2->dplspData );
4180 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4181 FreeLibrary( hLobbyProvider );
4185 /* FIXME: Need to verify the sanity of the returned callback table
4186 * using IsBadCodePtr */
4188 This->dp2->bDPLSPInitialized = TRUE;
4190 /* This interface is now initialized as a lobby object */
4191 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
4193 /* Store the handle of the module so that we can unload it later */
4194 This->dp2->hDPLobbyProvider = hLobbyProvider;
4199 static HRESULT WINAPI DP_IF_InitializeConnection
4200 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi )
4202 HMODULE hServiceProvider;
4205 const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
4206 BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4208 TRACE("(%p)->(%p,0x%08lx,%u)\n", This, lpConnection, dwFlags, bAnsi );
4212 return DPERR_INVALIDFLAGS;
4215 /* Find out what the requested SP is and how large this buffer is */
4216 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
4217 dwAddrSize, &guidSP );
4221 ERR( "Invalid compound address?\n" );
4222 return DPERR_UNAVAILABLE;
4225 /* Load the service provider */
4226 hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp );
4228 if( hServiceProvider == 0 )
4230 ERR( "Unable to load service provider\n" );
4231 return DPERR_UNAVAILABLE;
4236 /* Fill in what we can of the Service Provider required information.
4237 * The rest was be done in DP_LoadSP
4239 This->dp2->spData.lpAddress = lpConnection;
4240 This->dp2->spData.dwAddressSize = dwAddrSize;
4241 This->dp2->spData.lpGuid = &guidSP;
4243 hr = DP_InitializeDPSP( This, hServiceProvider );
4247 This->dp2->dplspData.lpAddress = lpConnection;
4249 hr = DP_InitializeDPLSP( This, hServiceProvider );
4260 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4261 ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
4263 ICOM_THIS(IDirectPlay3Impl,iface);
4265 /* This may not be externally invoked once either an SP or LP is initialized */
4266 if( This->dp2->connectionInitialized != NO_PROVIDER )
4268 return DPERR_ALREADYINITIALIZED;
4271 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE );
4274 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4275 ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
4277 ICOM_THIS(IDirectPlay3Impl,iface);
4279 /* This may not be externally invoked once either an SP or LP is initialized */
4280 if( This->dp2->connectionInitialized != NO_PROVIDER )
4282 return DPERR_ALREADYINITIALIZED;
4285 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE );
4288 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4289 ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4290 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4292 ICOM_THIS(IDirectPlay2Impl,iface); /* Yes a dp 2 interface */
4293 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4296 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4297 ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4298 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4300 ICOM_THIS(IDirectPlay2Impl,iface); /* Yes a dp 2 interface */
4301 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4304 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4305 ( LPDIRECTPLAY3A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4307 ICOM_THIS(IDirectPlay3Impl,iface);
4308 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4312 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4313 ( LPDIRECTPLAY3 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4315 ICOM_THIS(IDirectPlay3Impl,iface);
4316 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4320 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4321 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4323 ICOM_THIS(IDirectPlay3Impl,iface);
4324 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4328 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4329 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4331 ICOM_THIS(IDirectPlay3Impl,iface);
4332 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4336 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4337 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup )
4339 ICOM_THIS(IDirectPlay3Impl,iface);
4340 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
4344 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4345 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup )
4347 ICOM_THIS(IDirectPlay3Impl,iface);
4348 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
4352 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4353 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDWORD lpdwFlags )
4355 ICOM_THIS(IDirectPlay3Impl,iface);
4356 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
4360 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4361 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDWORD lpdwFlags )
4363 ICOM_THIS(IDirectPlay3Impl,iface);
4364 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
4368 static HRESULT WINAPI DP_IF_GetGroupParent
4369 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
4372 lpGroupData lpGData;
4374 TRACE("(%p)->(0x%08lx,%p,%u)\n", This, idGroup, lpidGroup, bAnsi );
4376 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4378 return DPERR_INVALIDGROUP;
4381 *lpidGroup = lpGData->dpid;
4386 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4387 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
4389 ICOM_THIS(IDirectPlay3Impl,iface);
4390 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE );
4392 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4393 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
4395 ICOM_THIS(IDirectPlay3Impl,iface);
4396 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE );
4399 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4400 ( LPDIRECTPLAY3A iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4402 ICOM_THIS(IDirectPlay3Impl,iface);
4403 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4407 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4408 ( LPDIRECTPLAY3 iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4410 ICOM_THIS(IDirectPlay3Impl,iface);
4411 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4415 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4416 ( LPDIRECTPLAY3A iface, DPID idPlayer, LPDWORD lpdwFlags )
4418 ICOM_THIS(IDirectPlay3Impl,iface);
4419 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
4423 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4424 ( LPDIRECTPLAY3 iface, DPID idPlayer, LPDWORD lpdwFlags )
4426 ICOM_THIS(IDirectPlay3Impl,iface);
4427 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
4431 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4432 ( LPDIRECTPLAY4A iface, DPID idGroup, LPDPID lpidGroupOwner )
4434 ICOM_THIS(IDirectPlay4Impl,iface);
4435 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
4439 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4440 ( LPDIRECTPLAY4 iface, DPID idGroup, LPDPID lpidGroupOwner )
4442 ICOM_THIS(IDirectPlay4Impl,iface);
4443 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
4447 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4448 ( LPDIRECTPLAY4A iface, DPID idGroup , DPID idGroupOwner )
4450 ICOM_THIS(IDirectPlay4Impl,iface);
4451 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
4455 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4456 ( LPDIRECTPLAY4 iface, DPID idGroup , DPID idGroupOwner )
4458 ICOM_THIS(IDirectPlay4Impl,iface);
4459 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
4463 static HRESULT WINAPI DP_SendEx
4464 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4465 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4466 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi )
4468 lpPlayerList lpPList;
4469 lpGroupData lpGData;
4470 BOOL bValidDestination = FALSE;
4472 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx,0x%08lx,0x%08lx,%p,%p,%u)"
4474 This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority,
4475 dwTimeout, lpContext, lpdwMsgID, bAnsi );
4477 /* FIXME: Add parameter checking */
4478 /* FIXME: First call to this needs to aquire a message id which will be
4479 * used for multiple sends
4482 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4484 /* Verify that the message is being sent from a valid local player. The
4485 * from player may be anonymous DPID_UNKNOWN
4487 if( idFrom != DPID_UNKNOWN )
4489 if( ( lpPList = DP_FindPlayer( This, idFrom ) ) == NULL )
4491 WARN( "INFO: Invalid from player 0x%08lx\n", idFrom );
4492 return DPERR_INVALIDPLAYER;
4496 /* Verify that the message is being sent to a valid player, group or to
4497 * everyone. If it's valid, send it to those players.
4499 if( idTo == DPID_ALLPLAYERS )
4501 bValidDestination = TRUE;
4503 /* See if SP has the ability to multicast. If so, use it */
4504 if( This->dp2->spData.lpCB->SendToGroupEx )
4506 FIXME( "Use group sendex to group 0\n" );
4508 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4510 FIXME( "Use obsolete group send to group 0\n" );
4512 else /* No multicast, multiplicate */
4514 /* Send to all players we know about */
4515 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4519 if( ( !bValidDestination ) &&
4520 ( DP_FindPlayer( This, idTo ) != NULL )
4523 bValidDestination = TRUE;
4525 /* Have the service provider send this message */
4526 /* FIXME: Could optimize for local interface sends */
4527 return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority,
4528 dwTimeout, lpContext, lpdwMsgID );
4531 if( ( !bValidDestination ) &&
4532 ( ( lpGData = DP_FindAnyGroup( This, idTo ) ) != NULL )
4535 bValidDestination = TRUE;
4537 /* See if SP has the ability to multicast. If so, use it */
4538 if( This->dp2->spData.lpCB->SendToGroupEx )
4540 FIXME( "Use group sendex\n" );
4542 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4544 FIXME( "Use obsolete group send to group\n" );
4546 else /* No multicast, multiplicate */
4548 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4556 This->dp2->hReplyEvent = CreateEventA( NULL, FALSE, FALSE, NULL );
4558 dwWaitReturn = WaitForSingleObject( hReplyEvent, dwTimeout );
4559 if( dwWaitReturn != WAIT_OBJECT_0 )
4561 ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
4567 if( !bValidDestination )
4569 return DPERR_INVALIDPLAYER;
4573 /* FIXME: Should return what the send returned */
4579 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4580 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4581 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4582 LPVOID lpContext, LPDWORD lpdwMsgID )
4584 ICOM_THIS(IDirectPlay2Impl,iface); /* yes downcast to 2 */
4585 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4586 dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE );
4589 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4590 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4591 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4592 LPVOID lpContext, LPDWORD lpdwMsgID )
4594 ICOM_THIS(IDirectPlay2Impl,iface); /* yes downcast to 2 */
4595 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4596 dwPriority, dwTimeout, lpContext, lpdwMsgID, FALSE );
4599 static HRESULT WINAPI DP_SP_SendEx
4600 ( IDirectPlay2Impl* This, DWORD dwFlags,
4601 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4602 LPVOID lpContext, LPDWORD lpdwMsgID )
4606 FIXME( ": stub\n" );
4608 /* FIXME: This queuing should only be for async messages */
4610 lpMElem = (LPDPMSG)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4611 sizeof( *lpMElem ) );
4612 lpMElem->msg = (DPMSG_GENERIC*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4615 CopyMemory( lpMElem->msg, lpData, dwDataSize );
4617 /* FIXME: Need to queue based on priority */
4618 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
4623 static HRESULT WINAPI DP_IF_GetMessageQueue
4624 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4625 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi )
4629 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,%p,%u): semi stub\n",
4630 This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi );
4632 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4633 /* FIXME: What about sends which are not immediate? */
4635 if( This->dp2->spData.lpCB->GetMessageQueue )
4637 DPSP_GETMESSAGEQUEUEDATA data;
4639 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4641 /* FIXME: None of this is documented :( */
4643 data.lpISP = This->dp2->spData.lpISP;
4644 data.dwFlags = dwFlags;
4645 data.idFrom = idFrom;
4647 data.lpdwNumMsgs = lpdwNumMsgs;
4648 data.lpdwNumBytes = lpdwNumBytes;
4650 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
4654 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4660 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4661 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4662 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4664 ICOM_THIS(IDirectPlay4Impl,iface);
4665 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4666 lpdwNumBytes, TRUE );
4669 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4670 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4671 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4673 ICOM_THIS(IDirectPlay4Impl,iface);
4674 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4675 lpdwNumBytes, FALSE );
4678 static HRESULT WINAPI DP_IF_CancelMessage
4679 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
4680 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi )
4684 FIXME( "(%p)->(0x%08lx,0x%08lx,%u): semi stub\n",
4685 This, dwMsgID, dwFlags, bAnsi );
4687 if( This->dp2->spData.lpCB->Cancel )
4689 DPSP_CANCELDATA data;
4691 TRACE( "Calling SP Cancel\n" );
4693 /* FIXME: Undocumented callback */
4695 data.lpISP = This->dp2->spData.lpISP;
4696 data.dwFlags = dwFlags;
4697 data.lprglpvSPMsgID = NULL;
4698 data.cSPMsgID = dwMsgID;
4699 data.dwMinPriority = dwMinPriority;
4700 data.dwMaxPriority = dwMaxPriority;
4702 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
4706 FIXME( "SP doesn't implement Cancel\n" );
4712 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
4713 ( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags )
4715 ICOM_THIS(IDirectPlay4Impl,iface);
4719 return DPERR_INVALIDFLAGS;
4724 dwFlags |= DPCANCELSEND_ALL;
4727 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE );
4730 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
4731 ( LPDIRECTPLAY4 iface, DWORD dwMsgID, DWORD dwFlags )
4733 ICOM_THIS(IDirectPlay4Impl,iface);
4737 return DPERR_INVALIDFLAGS;
4742 dwFlags |= DPCANCELSEND_ALL;
4745 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, FALSE );
4748 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
4749 ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4752 ICOM_THIS(IDirectPlay4Impl,iface);
4756 return DPERR_INVALIDFLAGS;
4759 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4760 dwMaxPriority, TRUE );
4763 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
4764 ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4767 ICOM_THIS(IDirectPlay4Impl,iface);
4771 return DPERR_INVALIDFLAGS;
4774 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4775 dwMaxPriority, FALSE );
4778 /* Note: Hack so we can reuse the old functions without compiler warnings */
4779 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4780 # define XCAST(fun) (typeof(directPlay2WVT.fun))
4782 # define XCAST(fun) (void*)
4785 static ICOM_VTABLE(IDirectPlay2) directPlay2WVT =
4787 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4788 XCAST(QueryInterface)DP_QueryInterface,
4789 XCAST(AddRef)DP_AddRef,
4790 XCAST(Release)DP_Release,
4792 DirectPlay2WImpl_AddPlayerToGroup,
4793 DirectPlay2WImpl_Close,
4794 DirectPlay2WImpl_CreateGroup,
4795 DirectPlay2WImpl_CreatePlayer,
4796 DirectPlay2WImpl_DeletePlayerFromGroup,
4797 DirectPlay2WImpl_DestroyGroup,
4798 DirectPlay2WImpl_DestroyPlayer,
4799 DirectPlay2WImpl_EnumGroupPlayers,
4800 DirectPlay2WImpl_EnumGroups,
4801 DirectPlay2WImpl_EnumPlayers,
4802 DirectPlay2WImpl_EnumSessions,
4803 DirectPlay2WImpl_GetCaps,
4804 DirectPlay2WImpl_GetGroupData,
4805 DirectPlay2WImpl_GetGroupName,
4806 DirectPlay2WImpl_GetMessageCount,
4807 DirectPlay2WImpl_GetPlayerAddress,
4808 DirectPlay2WImpl_GetPlayerCaps,
4809 DirectPlay2WImpl_GetPlayerData,
4810 DirectPlay2WImpl_GetPlayerName,
4811 DirectPlay2WImpl_GetSessionDesc,
4812 DirectPlay2WImpl_Initialize,
4813 DirectPlay2WImpl_Open,
4814 DirectPlay2WImpl_Receive,
4815 DirectPlay2WImpl_Send,
4816 DirectPlay2WImpl_SetGroupData,
4817 DirectPlay2WImpl_SetGroupName,
4818 DirectPlay2WImpl_SetPlayerData,
4819 DirectPlay2WImpl_SetPlayerName,
4820 DirectPlay2WImpl_SetSessionDesc
4824 /* Note: Hack so we can reuse the old functions without compiler warnings */
4825 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4826 # define XCAST(fun) (typeof(directPlay2AVT.fun))
4828 # define XCAST(fun) (void*)
4831 static ICOM_VTABLE(IDirectPlay2) directPlay2AVT =
4833 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4834 XCAST(QueryInterface)DP_QueryInterface,
4835 XCAST(AddRef)DP_AddRef,
4836 XCAST(Release)DP_Release,
4838 DirectPlay2AImpl_AddPlayerToGroup,
4839 DirectPlay2AImpl_Close,
4840 DirectPlay2AImpl_CreateGroup,
4841 DirectPlay2AImpl_CreatePlayer,
4842 DirectPlay2AImpl_DeletePlayerFromGroup,
4843 DirectPlay2AImpl_DestroyGroup,
4844 DirectPlay2AImpl_DestroyPlayer,
4845 DirectPlay2AImpl_EnumGroupPlayers,
4846 DirectPlay2AImpl_EnumGroups,
4847 DirectPlay2AImpl_EnumPlayers,
4848 DirectPlay2AImpl_EnumSessions,
4849 DirectPlay2AImpl_GetCaps,
4850 DirectPlay2AImpl_GetGroupData,
4851 DirectPlay2AImpl_GetGroupName,
4852 DirectPlay2AImpl_GetMessageCount,
4853 DirectPlay2AImpl_GetPlayerAddress,
4854 DirectPlay2AImpl_GetPlayerCaps,
4855 DirectPlay2AImpl_GetPlayerData,
4856 DirectPlay2AImpl_GetPlayerName,
4857 DirectPlay2AImpl_GetSessionDesc,
4858 DirectPlay2AImpl_Initialize,
4859 DirectPlay2AImpl_Open,
4860 DirectPlay2AImpl_Receive,
4861 DirectPlay2AImpl_Send,
4862 DirectPlay2AImpl_SetGroupData,
4863 DirectPlay2AImpl_SetGroupName,
4864 DirectPlay2AImpl_SetPlayerData,
4865 DirectPlay2AImpl_SetPlayerName,
4866 DirectPlay2AImpl_SetSessionDesc
4871 /* Note: Hack so we can reuse the old functions without compiler warnings */
4872 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4873 # define XCAST(fun) (typeof(directPlay3AVT.fun))
4875 # define XCAST(fun) (void*)
4878 static ICOM_VTABLE(IDirectPlay3) directPlay3AVT =
4880 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4881 XCAST(QueryInterface)DP_QueryInterface,
4882 XCAST(AddRef)DP_AddRef,
4883 XCAST(Release)DP_Release,
4885 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
4886 XCAST(Close)DirectPlay2AImpl_Close,
4887 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
4888 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
4889 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
4890 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
4891 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
4892 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
4893 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
4894 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
4895 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
4896 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
4897 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
4898 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
4899 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
4900 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
4901 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
4902 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
4903 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
4904 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
4905 XCAST(Initialize)DirectPlay2AImpl_Initialize,
4906 XCAST(Open)DirectPlay2AImpl_Open,
4907 XCAST(Receive)DirectPlay2AImpl_Receive,
4908 XCAST(Send)DirectPlay2AImpl_Send,
4909 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
4910 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
4911 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
4912 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
4913 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
4915 DirectPlay3AImpl_AddGroupToGroup,
4916 DirectPlay3AImpl_CreateGroupInGroup,
4917 DirectPlay3AImpl_DeleteGroupFromGroup,
4918 DirectPlay3AImpl_EnumConnections,
4919 DirectPlay3AImpl_EnumGroupsInGroup,
4920 DirectPlay3AImpl_GetGroupConnectionSettings,
4921 DirectPlay3AImpl_InitializeConnection,
4922 DirectPlay3AImpl_SecureOpen,
4923 DirectPlay3AImpl_SendChatMessage,
4924 DirectPlay3AImpl_SetGroupConnectionSettings,
4925 DirectPlay3AImpl_StartSession,
4926 DirectPlay3AImpl_GetGroupFlags,
4927 DirectPlay3AImpl_GetGroupParent,
4928 DirectPlay3AImpl_GetPlayerAccount,
4929 DirectPlay3AImpl_GetPlayerFlags
4933 /* Note: Hack so we can reuse the old functions without compiler warnings */
4934 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4935 # define XCAST(fun) (typeof(directPlay3WVT.fun))
4937 # define XCAST(fun) (void*)
4939 static ICOM_VTABLE(IDirectPlay3) directPlay3WVT =
4941 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4942 XCAST(QueryInterface)DP_QueryInterface,
4943 XCAST(AddRef)DP_AddRef,
4944 XCAST(Release)DP_Release,
4946 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
4947 XCAST(Close)DirectPlay2WImpl_Close,
4948 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
4949 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
4950 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
4951 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
4952 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
4953 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
4954 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
4955 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
4956 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
4957 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
4958 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
4959 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
4960 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
4961 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
4962 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
4963 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
4964 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
4965 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
4966 XCAST(Initialize)DirectPlay2WImpl_Initialize,
4967 XCAST(Open)DirectPlay2WImpl_Open,
4968 XCAST(Receive)DirectPlay2WImpl_Receive,
4969 XCAST(Send)DirectPlay2WImpl_Send,
4970 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
4971 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
4972 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
4973 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
4974 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
4976 DirectPlay3WImpl_AddGroupToGroup,
4977 DirectPlay3WImpl_CreateGroupInGroup,
4978 DirectPlay3WImpl_DeleteGroupFromGroup,
4979 DirectPlay3WImpl_EnumConnections,
4980 DirectPlay3WImpl_EnumGroupsInGroup,
4981 DirectPlay3WImpl_GetGroupConnectionSettings,
4982 DirectPlay3WImpl_InitializeConnection,
4983 DirectPlay3WImpl_SecureOpen,
4984 DirectPlay3WImpl_SendChatMessage,
4985 DirectPlay3WImpl_SetGroupConnectionSettings,
4986 DirectPlay3WImpl_StartSession,
4987 DirectPlay3WImpl_GetGroupFlags,
4988 DirectPlay3WImpl_GetGroupParent,
4989 DirectPlay3WImpl_GetPlayerAccount,
4990 DirectPlay3WImpl_GetPlayerFlags
4994 /* Note: Hack so we can reuse the old functions without compiler warnings */
4995 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4996 # define XCAST(fun) (typeof(directPlay4WVT.fun))
4998 # define XCAST(fun) (void*)
5000 static ICOM_VTABLE(IDirectPlay4) directPlay4WVT =
5002 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5003 XCAST(QueryInterface)DP_QueryInterface,
5004 XCAST(AddRef)DP_AddRef,
5005 XCAST(Release)DP_Release,
5007 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
5008 XCAST(Close)DirectPlay2WImpl_Close,
5009 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
5010 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
5011 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
5012 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
5013 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5014 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5015 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5016 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5017 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5018 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5019 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5020 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5021 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5022 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5023 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5024 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5025 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5026 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5027 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5028 XCAST(Open)DirectPlay2WImpl_Open,
5029 XCAST(Receive)DirectPlay2WImpl_Receive,
5030 XCAST(Send)DirectPlay2WImpl_Send,
5031 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5032 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5033 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5034 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5035 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5037 XCAST(AddGroupToGroup)DirectPlay3WImpl_AddGroupToGroup,
5038 XCAST(CreateGroupInGroup)DirectPlay3WImpl_CreateGroupInGroup,
5039 XCAST(DeleteGroupFromGroup)DirectPlay3WImpl_DeleteGroupFromGroup,
5040 XCAST(EnumConnections)DirectPlay3WImpl_EnumConnections,
5041 XCAST(EnumGroupsInGroup)DirectPlay3WImpl_EnumGroupsInGroup,
5042 XCAST(GetGroupConnectionSettings)DirectPlay3WImpl_GetGroupConnectionSettings,
5043 XCAST(InitializeConnection)DirectPlay3WImpl_InitializeConnection,
5044 XCAST(SecureOpen)DirectPlay3WImpl_SecureOpen,
5045 XCAST(SendChatMessage)DirectPlay3WImpl_SendChatMessage,
5046 XCAST(SetGroupConnectionSettings)DirectPlay3WImpl_SetGroupConnectionSettings,
5047 XCAST(StartSession)DirectPlay3WImpl_StartSession,
5048 XCAST(GetGroupFlags)DirectPlay3WImpl_GetGroupFlags,
5049 XCAST(GetGroupParent)DirectPlay3WImpl_GetGroupParent,
5050 XCAST(GetPlayerAccount)DirectPlay3WImpl_GetPlayerAccount,
5051 XCAST(GetPlayerFlags)DirectPlay3WImpl_GetPlayerFlags,
5053 DirectPlay4WImpl_GetGroupOwner,
5054 DirectPlay4WImpl_SetGroupOwner,
5055 DirectPlay4WImpl_SendEx,
5056 DirectPlay4WImpl_GetMessageQueue,
5057 DirectPlay4WImpl_CancelMessage,
5058 DirectPlay4WImpl_CancelPriority
5063 /* Note: Hack so we can reuse the old functions without compiler warnings */
5064 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5065 # define XCAST(fun) (typeof(directPlay4AVT.fun))
5067 # define XCAST(fun) (void*)
5069 static ICOM_VTABLE(IDirectPlay4) directPlay4AVT =
5071 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5072 XCAST(QueryInterface)DP_QueryInterface,
5073 XCAST(AddRef)DP_AddRef,
5074 XCAST(Release)DP_Release,
5076 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
5077 XCAST(Close)DirectPlay2AImpl_Close,
5078 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
5079 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
5080 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
5081 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
5082 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
5083 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
5084 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
5085 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
5086 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
5087 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
5088 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
5089 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
5090 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5091 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5092 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5093 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5094 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5095 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5096 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5097 XCAST(Open)DirectPlay2AImpl_Open,
5098 XCAST(Receive)DirectPlay2AImpl_Receive,
5099 XCAST(Send)DirectPlay2AImpl_Send,
5100 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5101 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5102 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5103 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5104 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5106 XCAST(AddGroupToGroup)DirectPlay3AImpl_AddGroupToGroup,
5107 XCAST(CreateGroupInGroup)DirectPlay3AImpl_CreateGroupInGroup,
5108 XCAST(DeleteGroupFromGroup)DirectPlay3AImpl_DeleteGroupFromGroup,
5109 XCAST(EnumConnections)DirectPlay3AImpl_EnumConnections,
5110 XCAST(EnumGroupsInGroup)DirectPlay3AImpl_EnumGroupsInGroup,
5111 XCAST(GetGroupConnectionSettings)DirectPlay3AImpl_GetGroupConnectionSettings,
5112 XCAST(InitializeConnection)DirectPlay3AImpl_InitializeConnection,
5113 XCAST(SecureOpen)DirectPlay3AImpl_SecureOpen,
5114 XCAST(SendChatMessage)DirectPlay3AImpl_SendChatMessage,
5115 XCAST(SetGroupConnectionSettings)DirectPlay3AImpl_SetGroupConnectionSettings,
5116 XCAST(StartSession)DirectPlay3AImpl_StartSession,
5117 XCAST(GetGroupFlags)DirectPlay3AImpl_GetGroupFlags,
5118 XCAST(GetGroupParent)DirectPlay3AImpl_GetGroupParent,
5119 XCAST(GetPlayerAccount)DirectPlay3AImpl_GetPlayerAccount,
5120 XCAST(GetPlayerFlags)DirectPlay3AImpl_GetPlayerFlags,
5122 DirectPlay4AImpl_GetGroupOwner,
5123 DirectPlay4AImpl_SetGroupOwner,
5124 DirectPlay4AImpl_SendEx,
5125 DirectPlay4AImpl_GetMessageQueue,
5126 DirectPlay4AImpl_CancelMessage,
5127 DirectPlay4AImpl_CancelPriority
5132 HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP,
5136 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5138 if( lpPlayer == NULL )
5140 return DPERR_INVALIDPLAYER;
5143 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
5149 HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP,
5153 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5155 if( lpPlayer == NULL )
5157 return DPERR_INVALIDPLAYER;
5160 lpPlayer->lpPData->lpSPPlayerData = lpData;
5165 /***************************************************************************
5166 * DirectPlayEnumerate [DPLAYX.9]
5167 * DirectPlayEnumerateA [DPLAYX.2]
5169 * The pointer to the structure lpContext will be filled with the
5170 * appropriate data for each service offered by the OS. These services are
5171 * not necessarily available on this particular machine but are defined
5172 * as simple service providers under the "Service Providers" registry key.
5173 * This structure is then passed to lpEnumCallback for each of the different
5176 * This API is useful only for applications written using DirectX3 or
5177 * worse. It is superseded by IDirectPlay3::EnumConnections which also
5178 * gives information on the actual connections.
5180 * defn of a service provider:
5181 * A dynamic-link library used by DirectPlay to communicate over a network.
5182 * The service provider contains all the network-specific code required
5183 * to send and receive messages. Online services and network operators can
5184 * supply service providers to use specialized hardware, protocols, communications
5185 * media, and network resources.
5187 * TODO: Allocate string buffer space from the heap (length from reg)
5188 * Pass real device driver numbers...
5189 * Get the GUID properly...
5191 HRESULT WINAPI DirectPlayEnumerateA( LPDPENUMDPCALLBACKA lpEnumCallback,
5196 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
5198 DWORD sizeOfSubKeyName=50;
5199 char subKeyName[51];
5202 TRACE(": lpEnumCallback=%p lpContext=%p\n", lpEnumCallback, lpContext );
5204 if( !lpEnumCallback || !*lpEnumCallback )
5206 return DPERR_INVALIDPARAMS;
5209 /* Need to loop over the service providers in the registry */
5210 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
5211 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
5213 /* Hmmm. Does this mean that there are no service providers? */
5214 ERR(": no service providers?\n");
5215 return DPERR_NOSERVICEPROVIDER;
5218 /* Traverse all the service providers we have available */
5220 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
5221 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
5222 ++dwIndex, sizeOfSubKeyName=50 )
5224 LPSTR majVerDataSubKey = "dwReserved1";
5225 LPSTR minVerDataSubKey = "dwReserved2";
5226 LPSTR guidDataSubKey = "Guid";
5227 HKEY hkServiceProvider;
5228 GUID serviceProviderGUID;
5229 DWORD returnTypeGUID, returnTypeReserved, sizeOfReturnBuffer = 50;
5230 char returnBuffer[51];
5232 DWORD majVersionNum , minVersionNum = 0;
5234 TRACE(" this time through: %s\n", subKeyName );
5236 /* Get a handle for this particular service provider */
5237 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
5238 &hkServiceProvider ) != ERROR_SUCCESS )
5240 ERR(": what the heck is going on?\n" );
5244 /* Get the GUID, Device major number and device minor number
5245 * from the registry.
5247 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
5248 NULL, &returnTypeGUID, returnBuffer,
5249 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5251 ERR(": missing GUID registry data members\n" );
5255 /* FIXME: Check return types to ensure we're interpreting data right */
5256 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
5257 CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
5259 /* FIXME: Need to know which of dwReserved1 and dwReserved2 are maj and min */
5261 sizeOfReturnBuffer = 50;
5262 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
5263 NULL, &returnTypeReserved, returnBuffer,
5264 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5266 ERR(": missing dwReserved1 registry data members\n") ;
5269 memcpy( &majVersionNum, returnBuffer, sizeof(majVersionNum) );
5271 sizeOfReturnBuffer = 50;
5272 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
5273 NULL, &returnTypeReserved, returnBuffer,
5274 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5276 ERR(": missing dwReserved2 registry data members\n") ;
5279 memcpy( &minVersionNum, returnBuffer, sizeof(minVersionNum) );
5282 /* The enumeration will return FALSE if we are not to continue */
5283 if( !lpEnumCallback( &serviceProviderGUID , subKeyName,
5284 majVersionNum, minVersionNum, lpContext ) )
5286 WARN("lpEnumCallback returning FALSE\n" );
5295 /***************************************************************************
5296 * DirectPlayEnumerateW [DPLAYX.3]
5299 HRESULT WINAPI DirectPlayEnumerateW( LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5304 return DPERR_OUTOFMEMORY;
5308 typedef struct tagCreateEnum
5312 } CreateEnumData, *lpCreateEnumData;
5314 /* Find and copy the matching connection for the SP guid */
5315 static BOOL CALLBACK cbDPCreateEnumConnections(
5317 LPVOID lpConnection,
5318 DWORD dwConnectionSize,
5323 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5325 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5327 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5329 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5331 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5333 /* Found the record that we were looking for */
5337 /* Haven't found what were looking for yet */
5342 /***************************************************************************
5343 * DirectPlayCreate [DPLAYX.1]
5346 HRESULT WINAPI DirectPlayCreate
5347 ( LPGUID lpGUID, LPDIRECTPLAY2 *lplpDP, IUnknown *pUnk)
5350 LPDIRECTPLAY3A lpDP3A;
5351 CreateEnumData cbData;
5353 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5357 return CLASS_E_NOAGGREGATION;
5360 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5361 give them an IDirectPlay2A object and hope that doesn't cause problems */
5362 if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
5364 return DPERR_UNAVAILABLE;
5367 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
5369 /* The GUID_NULL means don't bind a service provider. Just return the
5374 /* Bind the desired service provider since lpGUID is non NULL */
5375 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
5377 /* We're going to use a DP3 interface */
5378 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
5382 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
5386 cbData.lpConn = NULL;
5387 cbData.lpGuid = lpGUID;
5389 /* We were given a service provider, find info about it... */
5390 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
5391 &cbData, DPCONNECTION_DIRECTPLAY );
5392 if( ( FAILED(hr) ) ||
5393 ( cbData.lpConn == NULL )
5396 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
5397 IDirectPlayX_Release( lpDP3A );
5398 return DPERR_UNAVAILABLE;
5401 /* Initialize the service provider */
5402 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
5405 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
5406 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5407 IDirectPlayX_Release( lpDP3A );
5411 /* Release our version of the interface now that we're done with it */
5412 IDirectPlayX_Release( lpDP3A );
5413 HeapFree( GetProcessHeap(), 0, cbData.lpConn );