--- trunk/reactos/lib/dplayx/dplay.c 2005-10-27 22:05:46 UTC (rev 18810)
+++ trunk/reactos/lib/dplayx/dplay.c 2005-10-27 22:10:33 UTC (rev 18811)
@@ -0,0 +1,5451 @@
+/* Direct Play 2,3,4 Implementation
+ *
+ * Copyright 1998,1999,2000,2001 - Peter Hunnisett
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdarg.h>
+#include <string.h>
+
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+#include "windef.h"
+#include "winerror.h"
+#include "winbase.h"
+#include "winnt.h"
+#include "winreg.h"
+#include "winnls.h"
+#include "wine/unicode.h"
+#include "wine/debug.h"
+
+#include "dpinit.h"
+#include "dplayx_global.h"
+#include "name_server.h"
+#include "dplayx_queue.h"
+#include "dplaysp.h"
+#include "dplay_global.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dplay);
+
+/* FIXME: Should this be externed? */
+extern HRESULT DPL_CreateCompoundAddress
+( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
+ LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
+
+
+/* Local function prototypes */
+static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid );
+static lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* iface, LPDPID lpid,
+ LPDPNAME lpName, DWORD dwFlags,
+ HANDLE hEvent, BOOL bAnsi );
+static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi );
+static void DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
+ LPVOID lpData, DWORD dwDataSize );
+
+static lpGroupData DP_CreateGroup( IDirectPlay2AImpl* iface, LPDPID lpid,
+ LPDPNAME lpName, DWORD dwFlags,
+ DPID idParent, BOOL bAnsi );
+static void DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
+ LPVOID lpData, DWORD dwDataSize );
+static void DP_DeleteDPNameStruct( LPDPNAME lpDPName );
+static void DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid );
+static BOOL CALLBACK cbDeletePlayerFromAllGroups( DPID dpId,
+ DWORD dwPlayerType,
+ LPCDPNAME lpName,
+ DWORD dwFlags,
+ LPVOID lpContext );
+static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid );
+static BOOL CALLBACK cbRemoveGroupOrPlayer( DPID dpId, DWORD dwPlayerType,
+ LPCDPNAME lpName, DWORD dwFlags,
+ LPVOID lpContext );
+static void DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid );
+
+/* Forward declarations of virtual tables */
+static const IDirectPlay2Vtbl directPlay2AVT;
+static const IDirectPlay3Vtbl directPlay3AVT;
+static const IDirectPlay4Vtbl directPlay4AVT;
+
+static const IDirectPlay2Vtbl directPlay2WVT;
+static const IDirectPlay3Vtbl directPlay3WVT;
+static const IDirectPlay4Vtbl directPlay4WVT;
+
+/* Helper methods for player/group interfaces */
+static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
+ ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
+ DPID idPlayer, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_CreatePlayer
+ ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, LPDPID lpidPlayer,
+ LPDPNAME lpPlayerName, HANDLE hEvent, LPVOID lpData,
+ DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_DestroyGroup
+ ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_DestroyPlayer
+ ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_EnumGroupPlayers
+ ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
+ LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
+ LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_EnumGroups
+ ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
+ LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
+ LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_EnumPlayers
+ ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
+ LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
+ LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_GetGroupData
+ ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
+ LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_GetGroupName
+ ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
+ LPDWORD lpdwDataSize, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_GetPlayerData
+ ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
+ LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_GetPlayerName
+ ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
+ LPDWORD lpdwDataSize, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_SetGroupName
+ ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
+ DWORD dwFlags, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_SetPlayerData
+ ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
+ DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_SetPlayerName
+ ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
+ DWORD dwFlags, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_AddGroupToGroup
+ ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
+static HRESULT WINAPI DP_IF_CreateGroup
+ ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
+ LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
+ DWORD dwFlags, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_CreateGroupInGroup
+ ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
+ LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
+ DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_AddPlayerToGroup
+ ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
+ DPID idPlayer, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
+ ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
+static HRESULT WINAPI DP_SetSessionDesc
+ ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
+ DWORD dwFlags, BOOL bInitial, BOOL bAnsi );
+static HRESULT WINAPI DP_SecureOpen
+ ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
+ LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
+ BOOL bAnsi );
+static HRESULT WINAPI DP_SendEx
+ ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
+ LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
+ LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_Receive
+ ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
+ DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_GetMessageQueue
+ ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
+ LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi );
+static HRESULT WINAPI DP_SP_SendEx
+ ( IDirectPlay2Impl* This, DWORD dwFlags,
+ LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
+ LPVOID lpContext, LPDWORD lpdwMsgID );
+static HRESULT WINAPI DP_IF_SetGroupData
+ ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
+ DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_GetPlayerCaps
+ ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
+ DWORD dwFlags );
+static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_CancelMessage
+ ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
+ DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_EnumGroupsInGroup
+ ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
+ LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
+ LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_GetGroupParent
+ ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
+ BOOL bAnsi );
+static HRESULT WINAPI DP_IF_GetCaps
+ ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags );
+static HRESULT WINAPI DP_IF_EnumSessions
+ ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
+ LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
+ LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_InitializeConnection
+ ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi );
+static BOOL CALLBACK cbDPCreateEnumConnections( LPCGUID lpguidSP,
+ LPVOID lpConnection, DWORD dwConnectionSize, LPCDPNAME lpName,
+ DWORD dwFlags, LPVOID lpContext );
+static BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
+ LPDWORD lpdwBufSize );
+
+
+
+static inline DPID DP_NextObjectId(void);
+static DPID DP_GetRemoteNextObjectId(void);
+
+
+static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc,
+ LPCDPSESSIONDESC2 srcSessDesc, BOOL bAnsi );
+
+
+static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp );
+static HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider );
+static HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hServiceProvider );
+
+
+
+
+
+
+#define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */
+#define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported
+ we don't have to change much */
+#define DPID_NAME_SERVER 0x19a9d65b /* Don't ask me why */
+
+/* Strip out dwFlag values which cannot be sent in the CREATEGROUP msg */
+#define DPMSG_CREATEGROUP_DWFLAGS(x) ( (x) & DPGROUP_HIDDEN )
+
+/* Strip out all dwFlags values for CREATEPLAYER msg */
+#define DPMSG_CREATEPLAYER_DWFLAGS(x) 0
+
+static LONG kludgePlayerGroupId = 1000;
+
+/* ------------------------------------------------------------------ */
+
+
+static BOOL DP_CreateIUnknown( LPVOID lpDP )
+{
+ IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;
+
+ This->unk = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->unk) ) );
+ if ( This->unk == NULL )
+ {
+ return FALSE;
+ }
+
+ InitializeCriticalSection( &This->unk->DP_lock );
+
+ return TRUE;
+}
+
+static BOOL DP_DestroyIUnknown( LPVOID lpDP )
+{
+ IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;
+
+ DeleteCriticalSection( &This->unk->DP_lock );
+ HeapFree( GetProcessHeap(), 0, This->unk );
+
+ return TRUE;
+}
+
+static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
+{
+ IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;
+
+ This->dp2 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp2) ) );
+ if ( This->dp2 == NULL )
+ {
+ return FALSE;
+ }
+
+ This->dp2->bConnectionOpen = FALSE;
+
+ This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
+
+ This->dp2->bHostInterface = FALSE;
+
+ DPQ_INIT(This->dp2->receiveMsgs);
+ DPQ_INIT(This->dp2->sendMsgs);
+ DPQ_INIT(This->dp2->replysExpected);
+
+ if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
+ {
+ /* FIXME: Memory leak */
+ return FALSE;
+ }
+
+ /* Provide an initial session desc with nothing in it */
+ This->dp2->lpSessionDesc = HeapAlloc( GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ sizeof( *This->dp2->lpSessionDesc ) );
+ if( This->dp2->lpSessionDesc == NULL )
+ {
+ /* FIXME: Memory leak */
+ return FALSE;
+ }
+ This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc );
+
+ /* We are emulating a dp 6 implementation */
+ This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION;
+
+ This->dp2->spData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof( *This->dp2->spData.lpCB ) );
+ This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB );
+ This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION;
+
+ /* This is the pointer to the service provider */
+ if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP,
+ (LPVOID*)&This->dp2->spData.lpISP, This ) )
+ )
+ {
+ /* FIXME: Memory leak */
+ return FALSE;
+ }
+
+ /* Setup lobby provider information */
+ This->dp2->dplspData.dwSPVersion = DPSP_MAJORVERSION;
+ This->dp2->dplspData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof( *This->dp2->dplspData.lpCB ) );
+ This->dp2->dplspData.lpCB->dwSize = sizeof( *This->dp2->dplspData.lpCB );
+
+ if( FAILED( DPLSP_CreateInterface( &IID_IDPLobbySP,
+ (LPVOID*)&This->dp2->dplspData.lpISP, This ) )
+ )
+ {
+ /* FIXME: Memory leak */
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* Definition of the global function in dplayx_queue.h. #
+ * FIXME: Would it be better to have a dplayx_queue.c for this function? */
+DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
+{
+ HeapFree( GetProcessHeap(), 0, elem );
+}
+
+/* Function to delete the list of groups with this interface. Needs to
+ * delete the group and player lists associated with this group as well
+ * as the group data associated with this group. It should not delete
+ * player data as that is shared with the top player list and will be
+ * deleted with that.
+ */
+DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList );
+DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList )
+{
+ DPQ_DELETEQ( elem->lpGData->groups, groups,
+ lpGroupList, cbDeleteElemFromHeap );
+ DPQ_DELETEQ( elem->lpGData->players, players,
+ lpPlayerList, cbDeleteElemFromHeap );
+ HeapFree( GetProcessHeap(), 0, elem->lpGData );
+ HeapFree( GetProcessHeap(), 0, elem );
+}
+
+/* Function to delete the list of players with this interface. Needs to
+ * delete the player data for all players as well.
+ */
+DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList );
+DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList )
+{
+ HeapFree( GetProcessHeap(), 0, elem->lpPData );
+ HeapFree( GetProcessHeap(), 0, elem );
+}
+
+static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
+{
+ IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;
+
+ if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
+ {
+ TerminateThread( This->dp2->hEnumSessionThread, 0 );
+ CloseHandle( This->dp2->hEnumSessionThread );
+ }
+
+ /* Finish with the SP - have it shutdown */
+ if( This->dp2->spData.lpCB->ShutdownEx )
+ {
+ DPSP_SHUTDOWNDATA data;
+
+ TRACE( "Calling SP ShutdownEx\n" );
+
+ data.lpISP = This->dp2->spData.lpISP;
+
+ (*This->dp2->spData.lpCB->ShutdownEx)( &data );
+ }
+ else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
+ {
+ TRACE( "Calling obsolete SP Shutdown\n" );
+ (*This->dp2->spData.lpCB->Shutdown)();
+ }
+
+ /* Unload the SP (if it exists) */
+ if( This->dp2->hServiceProvider != 0 )
+ {
+ FreeLibrary( This->dp2->hServiceProvider );
+ }
+
+ /* Unload the Lobby Provider (if it exists) */
+ if( This->dp2->hDPLobbyProvider != 0 )
+ {
+ FreeLibrary( This->dp2->hDPLobbyProvider );
+ }
+
+#if 0
+ DPQ_DELETEQ( This->dp2->players, players, lpPlayerList, cbDeletePlayerElem );
+ DPQ_DELETEQ( This->dp2->groups, groups, lpGroupList, cbDeleteGroupsElem );
+#endif
+
+ /* FIXME: Need to delete receive and send msgs queue contents */
+
+ NS_DeleteSessionCache( This->dp2->lpNameServerData );
+
+ HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
+
+ IDirectPlaySP_Release( This->dp2->spData.lpISP );
+
+ /* Delete the contents */
+ HeapFree( GetProcessHeap(), 0, This->dp2 );
+
+ return TRUE;
+}
+
+static BOOL DP_CreateDirectPlay3( LPVOID lpDP )
+{
+ IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;
+
+ This->dp3 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp3) ) );
+ if ( This->dp3 == NULL )
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static BOOL DP_DestroyDirectPlay3( LPVOID lpDP )
+{
+ IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;
+
+ /* Delete the contents */
+ HeapFree( GetProcessHeap(), 0, This->dp3 );
+
+ return TRUE;
+}
+
+static BOOL DP_CreateDirectPlay4( LPVOID lpDP )
+{
+ IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)lpDP;
+
+ This->dp4 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp4) ) );
+ if ( This->dp4 == NULL )
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static BOOL DP_DestroyDirectPlay4( LPVOID lpDP )
+{
+ IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;
+
+ /* Delete the contents */
+ HeapFree( GetProcessHeap(), 0, This->dp4 );
+
+ return TRUE;
+}
+
+
+/* Create a new interface */
+extern
+HRESULT DP_CreateInterface
+ ( REFIID riid, LPVOID* ppvObj )
+{
+ TRACE( " for %s\n", debugstr_guid( riid ) );
+
+ *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof( IDirectPlay2Impl ) );
+
+ if( *ppvObj == NULL )
+ {
+ return DPERR_OUTOFMEMORY;
+ }
+
+ if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
+ {
+ IDirectPlay2Impl *This = (IDirectPlay2Impl *)*ppvObj;
+ This->lpVtbl = &directPlay2WVT;
+ }
+ else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
+ {
+ IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)*ppvObj;
+ This->lpVtbl = &directPlay2AVT;
+ }
+ else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
+ {
+ IDirectPlay3Impl *This = (IDirectPlay3Impl *)*ppvObj;
+ This->lpVtbl = &directPlay3WVT;
+ }
+ else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
+ {
+ IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)*ppvObj;
+ This->lpVtbl = &directPlay3AVT;
+ }
+ else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
+ {
+ IDirectPlay4Impl *This = (IDirectPlay4Impl *)*ppvObj;
+ This->lpVtbl = &directPlay4WVT;
+ }
+ else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
+ {
+ IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)*ppvObj;
+ This->lpVtbl = &directPlay4AVT;
+ }
+ else
+ {
+ /* Unsupported interface */
+ HeapFree( GetProcessHeap(), 0, *ppvObj );
+ *ppvObj = NULL;
+
+ return E_NOINTERFACE;
+ }
+
+ /* Initialize it */
+ if ( DP_CreateIUnknown( *ppvObj ) &&
+ DP_CreateDirectPlay2( *ppvObj ) &&
+ DP_CreateDirectPlay3( *ppvObj ) &&
+ DP_CreateDirectPlay4( *ppvObj )
+ )
+ {
+ IDirectPlayX_AddRef( (LPDIRECTPLAY2A)*ppvObj );
+
+ return S_OK;
+ }
+
+ /* Initialize failed, destroy it */
+ DP_DestroyDirectPlay4( *ppvObj );
+ DP_DestroyDirectPlay3( *ppvObj );
+ DP_DestroyDirectPlay2( *ppvObj );
+ DP_DestroyIUnknown( *ppvObj );
+
+ HeapFree( GetProcessHeap(), 0, *ppvObj );
+
+ *ppvObj = NULL;
+ return DPERR_NOMEMORY;
+}
+
+
+/* Direct Play methods */
+
+/* Shared between all dplay types */
+static HRESULT WINAPI DP_QueryInterface
+ ( LPDIRECTPLAY2 iface, REFIID riid, LPVOID* ppvObj )
+{
+ IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
+ TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
+
+ *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof( *This ) );
+
+ if( *ppvObj == NULL )
+ {
+ return DPERR_OUTOFMEMORY;
+ }
+
+ CopyMemory( *ppvObj, This, sizeof( *This ) );
+ (*(IDirectPlay2Impl**)ppvObj)->ulInterfaceRef = 0;
+
+ if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
+ {
+ IDirectPlay2Impl *This = (IDirectPlay2Impl *)*ppvObj;
+ This->lpVtbl = &directPlay2WVT;
+ }
+ else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
+ {
+ IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)*ppvObj;
+ This->lpVtbl = &directPlay2AVT;
+ }
+ else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
+ {
+ IDirectPlay3Impl *This = (IDirectPlay3Impl *)*ppvObj;
+ This->lpVtbl = &directPlay3WVT;
+ }
+ else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
+ {
+ IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)*ppvObj;
+ This->lpVtbl = &directPlay3AVT;
+ }
+ else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
+ {
+ IDirectPlay4Impl *This = (IDirectPlay4Impl *)*ppvObj;
+ This->lpVtbl = &directPlay4WVT;
+ }
+ else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
+ {
+ IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)*ppvObj;
+ This->lpVtbl = &directPlay4AVT;
+ }
+ else
+ {
+ /* Unsupported interface */
+ HeapFree( GetProcessHeap(), 0, *ppvObj );
+ *ppvObj = NULL;
+
+ return E_NOINTERFACE;
+ }
+
+ IDirectPlayX_AddRef( (LPDIRECTPLAY2)*ppvObj );
+
+ return S_OK;
+}
+
+/* Shared between all dplay types */
+static ULONG WINAPI DP_AddRef
+ ( LPDIRECTPLAY3 iface )
+{
+ ULONG ulInterfaceRefCount, ulObjRefCount;
+ IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
+
+ ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
+ ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
+
+ TRACE( "ref count incremented to %lu:%lu for %p\n",
+ ulInterfaceRefCount, ulObjRefCount, This );
+
+ return ulObjRefCount;
+}
+
+static ULONG WINAPI DP_Release
+( LPDIRECTPLAY3 iface )
+{
+ ULONG ulInterfaceRefCount, ulObjRefCount;
+
+ IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
+
+ ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
+ ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
+
+ TRACE( "ref count decremented to %lu:%lu for %p\n",
+ ulInterfaceRefCount, ulObjRefCount, This );
+
+ /* Deallocate if this is the last reference to the object */
+ if( ulObjRefCount == 0 )
+ {
+ /* If we're destroying the object, this must be the last ref
+ of the last interface */
+ DP_DestroyDirectPlay4( This );
+ DP_DestroyDirectPlay3( This );
+ DP_DestroyDirectPlay2( This );
+ DP_DestroyIUnknown( This );
+ }
+
+ /* Deallocate the interface */
+ if( ulInterfaceRefCount == 0 )
+ {
+ HeapFree( GetProcessHeap(), 0, This );
+ }
+
+ return ulObjRefCount;
+}
+
+static inline DPID DP_NextObjectId(void)
+{
+ return (DPID)InterlockedIncrement( &kludgePlayerGroupId );
+}
+
+/* *lplpReply will be non NULL iff there is something to reply */
+HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpcMessageBody,
+ DWORD dwMessageBodySize, LPCVOID lpcMessageHeader,
+ WORD wCommandId, WORD wVersion,
+ LPVOID* lplpReply, LPDWORD lpdwMsgSize )
+{
+ TRACE( "(%p)->(%p,0x%08lx,%p,%u,%u)\n",
+ This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId,
+ wVersion );
+
+ switch( wCommandId )
+ {
+ /* Name server needs to handle this request */
+ case DPMSGCMD_ENUMSESSIONSREQUEST:
+ {
+ /* Reply expected */
+ NS_ReplyToEnumSessionsRequest( lpcMessageBody, lplpReply, lpdwMsgSize, This );
+
+ break;
+ }
+
+ /* Name server needs to handle this request */
+ case DPMSGCMD_ENUMSESSIONSREPLY:
+ {
+ /* No reply expected */
+ NS_AddRemoteComputerAsNameServer( lpcMessageHeader,
+ This->dp2->spData.dwSPHeaderSize,
+ (LPDPMSG_ENUMSESSIONSREPLY)lpcMessageBody,
+ This->dp2->lpNameServerData );
+ break;
+ }
+
+ case DPMSGCMD_REQUESTNEWPLAYERID:
+ {
+ LPCDPMSG_REQUESTNEWPLAYERID lpcMsg =
+ (LPCDPMSG_REQUESTNEWPLAYERID)lpcMessageBody;
+
+ LPDPMSG_NEWPLAYERIDREPLY lpReply;
+
+ *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
+
+ *lplpReply = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, *lpdwMsgSize );
+
+ FIXME( "Ignoring dwFlags 0x%08lx in request msg\n",
+ lpcMsg->dwFlags );
+
+ /* Setup the reply */
+ lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) +
+ This->dp2->spData.dwSPHeaderSize );
+
+ lpReply->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
+ lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY;
+ lpReply->envelope.wVersion = DPMSGVER_DP6;
+
[truncated at 1000 lines; 12987 more skipped]