You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
642 lines
21 KiB
642 lines
21 KiB
/*==========================================================================
|
|
*
|
|
* Copyright (C) 2000 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: Client.cpp
|
|
* Content: DNET client interface routines
|
|
*@@BEGIN_MSINTERNAL
|
|
* History:
|
|
* Date By Reason
|
|
* ==== == ======
|
|
* 07/21/99 mjn Created
|
|
* 01/06/99 mjn Moved NameTable stuff to NameTable.h
|
|
* 01/28/00 mjn Implemented ReturnBuffer in API
|
|
* 02/01/00 mjn Implemented GetCaps and SetCaps in API
|
|
* 02/15/00 mjn Implement INFO flags in SetClientInfo
|
|
* 02/18/00 mjn Converted DNADDRESS to IDirectPlayAddress8
|
|
* 03/17/00 rmt Added new caps functions
|
|
* 04/06/00 mjn Added GetServerAddress to API
|
|
* 04/16/00 mjn DNSendMessage uses CAsyncOp
|
|
* 04/17/00 rmt Added more param validation
|
|
* rmt Removed required for connection from Get/SetInfo / GetAddress
|
|
* 04/19/00 mjn Send API call accepts a range of DPN_BUFFER_DESCs and a count
|
|
* 04/20/00 mjn DN_Send() calls DN_SendTo() with DPNID=0
|
|
* 04/24/00 mjn Updated Group and Info operations to use CAsyncOp's
|
|
* 04/28/00 mjn Updated DN_GetHostSendQueueInfo() to use CAsyncOp's
|
|
* 05/03/00 mjn Use GetHostPlayerRef() rather than GetHostPlayer()
|
|
* 05/31/00 mjn Added operation specific SYNC flags
|
|
* 06/23/00 mjn Removed dwPriority from Send() API call
|
|
* 06/27/00 mjn Allow priorities to be specified to GetSendQueueInfo() API call
|
|
* 06/27/00 mjn Added DN_ClientConnect() (without pvPlayerContext)
|
|
* mjn Allow mix-n-match of priorities in GetSendQueueInfo() API call
|
|
* 07/09/00 mjn Cleaned up DN_SetClientInfo()
|
|
* 07/09/00 rmt Bug #38323 - RegisterLobby needs a DPNHANDLE parameter.
|
|
* 07/21/2000 RichGr IA64: Use %p format specifier for 32/64-bit pointers.
|
|
* 10/11/00 mjn Take locks for CNameTableEntry::PackInfo()
|
|
* 01/22/01 mjn Check for closing instead of disconnecting in DN_GetServerInfo()
|
|
* 07/24/01 mjn Added DPNBUILD_NOPARAMVAL compile flag
|
|
*@@END_MSINTERNAL
|
|
*
|
|
***************************************************************************/
|
|
|
|
#include "dncorei.h"
|
|
|
|
|
|
//**********************************************************************
|
|
// Constant definitions
|
|
//**********************************************************************
|
|
|
|
//**********************************************************************
|
|
// Macro definitions
|
|
//**********************************************************************
|
|
|
|
//**********************************************************************
|
|
// Structure definitions
|
|
//**********************************************************************
|
|
|
|
//**********************************************************************
|
|
// Variable definitions
|
|
//**********************************************************************
|
|
|
|
//
|
|
// define appropriate types since these interface functions take 'void*' arguments!!
|
|
//
|
|
typedef STDMETHODIMP ClientQueryInterface( IDirectPlay8Client *pInterface, DP8REFIID riid, LPVOID *ppvObj );
|
|
typedef STDMETHODIMP_(ULONG) ClientAddRef( IDirectPlay8Client *pInterface );
|
|
typedef STDMETHODIMP_(ULONG) ClientRelease( IDirectPlay8Client *pInterface );
|
|
typedef STDMETHODIMP ClientInitialize( IDirectPlay8Client *pInterface, LPVOID const lpvUserContext, const PFNDPNMESSAGEHANDLER lpfn, const DWORD dwFlags );
|
|
typedef STDMETHODIMP ClientEnumServiceProviders( IDirectPlay8Client *pInterface,const GUID *const pguidServiceProvider,const GUID *const pguidApplication,DPN_SERVICE_PROVIDER_INFO *const pSPInfoBuffer,DWORD *const pcbEnumData,DWORD *const pcReturned,const DWORD dwFlags );
|
|
typedef STDMETHODIMP ClientCancelAsyncOperation( IDirectPlay8Client *pInterface, const DPNHANDLE hAsyncHandle, const DWORD dwFlags );
|
|
typedef STDMETHODIMP ClientConnect( IDirectPlay8Client *pInterface,const DPN_APPLICATION_DESC *const pdnAppDesc,IDirectPlay8Address *const pHostAddr,IDirectPlay8Address *const pDeviceInfo,const DPN_SECURITY_DESC *const pdnSecurity,const DPN_SECURITY_CREDENTIALS *const pdnCredentials,const void *const pvUserConnectData,const DWORD dwUserConnectDataSize,void *const pvAsyncContext,DPNHANDLE *const phAsyncHandle,const DWORD dwFlags);
|
|
typedef STDMETHODIMP ClientGetApplicationDesc( IDirectPlay8Client *pInterface,DPN_APPLICATION_DESC *const pAppDescBuffer,DWORD *const lpcbDataSize,const DWORD dwFlags );
|
|
typedef STDMETHODIMP ClientClose(IDirectPlay8Client *pInterface,const DWORD dwFlags);
|
|
typedef STDMETHODIMP ClientEnumHosts( IDirectPlay8Client *pInterface,DPN_APPLICATION_DESC *const pApplicationDesc,IDirectPlay8Address *const dnaddrHost,IDirectPlay8Address *const dnaddrDeviceInfo,PVOID const pUserEnumData,const DWORD dwUserEnumDataSize,const DWORD dwRetryCount,const DWORD dwRetryInterval,const DWORD dwTimeOut,PVOID const pvUserContext,DPNHANDLE *const pAsyncHandle,const DWORD dwFlags );
|
|
typedef STDMETHODIMP ClientReturnBuffer( IDirectPlay8Client *pInterface, const DPNHANDLE hBufferHandle,const DWORD dwFlags);
|
|
typedef STDMETHODIMP ClientGetCaps(IDirectPlay8Client *pInterface,DPN_CAPS *const pdnCaps,const DWORD dwFlags);
|
|
typedef STDMETHODIMP ClientSetCaps(IDirectPlay8Client *pInterface,const DPN_CAPS *const pdnCaps,const DWORD dwFlags);
|
|
typedef STDMETHODIMP ClientSetSPCaps(IDirectPlay8Client *pInterface,const GUID * const pguidSP, const DPN_SP_CAPS *const pdpspCaps, const DWORD dwFlags );
|
|
typedef STDMETHODIMP ClientGetSPCaps(IDirectPlay8Client *pInterface,const GUID * const pguidSP, DPN_SP_CAPS *const pdpspCaps,const DWORD dwFlags);
|
|
typedef STDMETHODIMP ClientGetConnectionInfo(IDirectPlay8Client *pInterface,DPN_CONNECTION_INFO *const pdpConnectionInfo,const DWORD dwFlags);
|
|
typedef STDMETHODIMP ClientRegisterLobby(IDirectPlay8Client *pInterface,const DPNHANDLE dpnHandle,IDirectPlay8LobbiedApplication *const pIDP8LobbiedApplication,const DWORD dwFlags);
|
|
|
|
//
|
|
// VTable for client interface
|
|
//
|
|
IDirectPlay8ClientVtbl DN_ClientVtbl =
|
|
{
|
|
(ClientQueryInterface*) DN_QueryInterface,
|
|
(ClientAddRef*) DN_AddRef,
|
|
(ClientRelease*) DN_Release,
|
|
(ClientInitialize*) DN_Initialize,
|
|
(ClientEnumServiceProviders*) DN_EnumServiceProviders,
|
|
(ClientEnumHosts*) DN_EnumHosts,
|
|
(ClientCancelAsyncOperation*) DN_CancelAsyncOperation,
|
|
/*(ClientConnect*)*/ DN_ClientConnect,
|
|
DN_Send,
|
|
/*(ClientGetSendQueueInfo*)*/ DN_GetHostSendQueueInfo,
|
|
(ClientGetApplicationDesc*) DN_GetApplicationDesc,
|
|
DN_SetClientInfo,
|
|
DN_GetServerInfo,
|
|
DN_GetServerAddress,
|
|
(ClientClose*) DN_Close,
|
|
(ClientReturnBuffer*) DN_ReturnBuffer,
|
|
(ClientGetCaps*) DN_GetCaps,
|
|
(ClientSetCaps*) DN_SetCaps,
|
|
(ClientSetSPCaps*) DN_SetSPCaps,
|
|
(ClientGetSPCaps*) DN_GetSPCaps,
|
|
(ClientGetConnectionInfo*) DN_GetServerConnectionInfo,
|
|
(ClientRegisterLobby*) DN_RegisterLobby
|
|
};
|
|
|
|
//**********************************************************************
|
|
// Function prototypes
|
|
//**********************************************************************
|
|
|
|
//**********************************************************************
|
|
// Function definitions
|
|
//**********************************************************************
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DN_Send"
|
|
|
|
STDMETHODIMP DN_Send( IDirectPlay8Client *pInterface,
|
|
const DPN_BUFFER_DESC *const prgBufferDesc,
|
|
const DWORD cBufferDesc,
|
|
const DWORD dwTimeOut,
|
|
const PVOID pvAsyncContext,
|
|
DPNHANDLE *const phAsyncHandle,
|
|
const DWORD dwFlags)
|
|
{
|
|
return( DN_SendTo( pInterface,
|
|
0, // DN_SendTo should translate this call to the Host player
|
|
prgBufferDesc,
|
|
cBufferDesc,
|
|
dwTimeOut,
|
|
pvAsyncContext,
|
|
phAsyncHandle,
|
|
dwFlags ) );
|
|
}
|
|
|
|
|
|
// DN_ClientConnect
|
|
//
|
|
// Call DN_Connect, but with no PlayerContext
|
|
|
|
STDMETHODIMP DN_ClientConnect(IDirectPlay8Client *pInterface,
|
|
const DPN_APPLICATION_DESC *const pdnAppDesc,
|
|
IDirectPlay8Address *const pHostAddr,
|
|
IDirectPlay8Address *const pDeviceInfo,
|
|
const DPN_SECURITY_DESC *const pdnSecurity,
|
|
const DPN_SECURITY_CREDENTIALS *const pdnCredentials,
|
|
const void *const pvUserConnectData,
|
|
const DWORD dwUserConnectDataSize,
|
|
void *const pvAsyncContext,
|
|
DPNHANDLE *const phAsyncHandle,
|
|
const DWORD dwFlags)
|
|
{
|
|
return( DN_Connect( pInterface,
|
|
pdnAppDesc,
|
|
pHostAddr,
|
|
pDeviceInfo,
|
|
pdnSecurity,
|
|
pdnCredentials,
|
|
pvUserConnectData,
|
|
dwUserConnectDataSize,
|
|
NULL,
|
|
pvAsyncContext,
|
|
phAsyncHandle,
|
|
dwFlags ) );
|
|
}
|
|
|
|
|
|
// DN_SetClientInfo
|
|
//
|
|
// Set the info for the client player and propagate to server
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DN_SetClientInfo"
|
|
|
|
STDMETHODIMP DN_SetClientInfo(IDirectPlay8Client *pInterface,
|
|
const DPN_PLAYER_INFO *const pdpnPlayerInfo,
|
|
const PVOID pvAsyncContext,
|
|
DPNHANDLE *const phAsyncHandle,
|
|
const DWORD dwFlags)
|
|
{
|
|
DIRECTNETOBJECT *pdnObject;
|
|
HRESULT hResultCode;
|
|
DPNHANDLE hAsyncOp;
|
|
PWSTR pwszName;
|
|
DWORD dwNameSize;
|
|
PVOID pvData;
|
|
DWORD dwDataSize;
|
|
CNameTableEntry *pLocalPlayer;
|
|
BOOL fConnected;
|
|
|
|
DPFX(DPFPREP, 2,"Parameters: pInterface [0x%p], pdpnPlayerInfo [0x%p], pvAsyncContext [0x%p], phAsyncHandle [0x%p], dwFlags [0x%lx]",
|
|
pInterface,pdpnPlayerInfo,pvAsyncContext,phAsyncHandle,dwFlags);
|
|
|
|
pdnObject = (DIRECTNETOBJECT*) GET_OBJECT_FROM_INTERFACE(pInterface);
|
|
DNASSERT(pdnObject != NULL);
|
|
|
|
#ifndef DPNBUILD_NOPARAMVAL
|
|
if( pdnObject->dwFlags & DN_OBJECT_FLAG_PARAMVALIDATION )
|
|
{
|
|
if( FAILED( hResultCode = DN_ValidateSetClientInfo( pInterface , pdpnPlayerInfo, pvAsyncContext, phAsyncHandle, dwFlags ) ) )
|
|
{
|
|
DPFX(DPFPREP, 0, "Error validating setclientinfo params hr=[0x%lx]", hResultCode );
|
|
DPF_RETURN( hResultCode );
|
|
}
|
|
}
|
|
#endif // !DPNBUILD_NOPARAMVAL
|
|
|
|
// Check to ensure message handler registered
|
|
if (!(pdnObject->dwFlags & DN_OBJECT_FLAG_INITIALIZED))
|
|
{
|
|
DPFERR( "Object is not initialized" );
|
|
DPF_RETURN(DPNERR_UNINITIALIZED);
|
|
}
|
|
|
|
pLocalPlayer = NULL;
|
|
|
|
if ((pdpnPlayerInfo->dwInfoFlags & DPNINFO_NAME) && (pdpnPlayerInfo->pwszName))
|
|
{
|
|
pwszName = pdpnPlayerInfo->pwszName;
|
|
dwNameSize = (wcslen(pwszName) + 1) * sizeof(WCHAR);
|
|
}
|
|
else
|
|
{
|
|
pwszName = NULL;
|
|
dwNameSize = 0;
|
|
}
|
|
if ((pdpnPlayerInfo->dwInfoFlags & DPNINFO_DATA) && (pdpnPlayerInfo->pvData) && (pdpnPlayerInfo->dwDataSize))
|
|
{
|
|
pvData = pdpnPlayerInfo->pvData;
|
|
dwDataSize = pdpnPlayerInfo->dwDataSize;
|
|
}
|
|
else
|
|
{
|
|
pvData = NULL;
|
|
dwDataSize = 0;
|
|
}
|
|
|
|
//
|
|
// If we are connected, we will request the Host to update us.
|
|
// Otherwise, we will just update the DefaultPlayer.
|
|
//
|
|
DNEnterCriticalSection(&pdnObject->csDirectNetObject);
|
|
if (pdnObject->dwFlags & DN_OBJECT_FLAG_CONNECTED)
|
|
{
|
|
fConnected = TRUE;
|
|
}
|
|
else
|
|
{
|
|
fConnected = FALSE;
|
|
}
|
|
DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
|
|
if (fConnected)
|
|
{
|
|
if ((hResultCode = pdnObject->NameTable.GetLocalPlayerRef( &pLocalPlayer )) != DPN_OK)
|
|
{
|
|
DPFERR( "Could not get local player reference" );
|
|
DisplayDNError(0,hResultCode);
|
|
goto Failure;
|
|
}
|
|
|
|
DPFX(DPFPREP, 3,"Request host to update client info");
|
|
|
|
hResultCode = DNRequestUpdateInfo( pdnObject,
|
|
pLocalPlayer->GetDPNID(),
|
|
pwszName,
|
|
dwNameSize,
|
|
pvData,
|
|
dwDataSize,
|
|
pdpnPlayerInfo->dwInfoFlags,
|
|
pvAsyncContext,
|
|
&hAsyncOp,
|
|
dwFlags);
|
|
if (hResultCode != DPN_OK && hResultCode != DPNERR_PENDING)
|
|
{
|
|
DPFERR("Could not request host to update client info");
|
|
}
|
|
else
|
|
{
|
|
if (!(dwFlags & DPNSETCLIENTINFO_SYNC))
|
|
{
|
|
DPFX(DPFPREP, 3,"Async Handle [0x%lx]",hAsyncOp);
|
|
*phAsyncHandle = hAsyncOp;
|
|
}
|
|
}
|
|
|
|
pLocalPlayer->Release();
|
|
pLocalPlayer = NULL;
|
|
}
|
|
else
|
|
{
|
|
DNASSERT(pdnObject->NameTable.GetDefaultPlayer() != NULL);
|
|
|
|
// This function takes the lock internally
|
|
pdnObject->NameTable.GetDefaultPlayer()->UpdateEntryInfo(pwszName,dwNameSize,pvData,dwDataSize,pdpnPlayerInfo->dwInfoFlags, FALSE);
|
|
|
|
hResultCode = DPN_OK;
|
|
}
|
|
|
|
Exit:
|
|
DPFX(DPFPREP, 2,"Returning: [0x%lx]",hResultCode);
|
|
return(hResultCode);
|
|
|
|
Failure:
|
|
if (pLocalPlayer)
|
|
{
|
|
pLocalPlayer->Release();
|
|
pLocalPlayer = NULL;
|
|
}
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
// DN_GetServerInfo
|
|
//
|
|
// Retrieve server info from the local nametable.
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DN_GetServerInfo"
|
|
|
|
STDMETHODIMP DN_GetServerInfo(IDirectPlay8Client *pInterface,
|
|
DPN_PLAYER_INFO *const pdpnPlayerInfo,
|
|
DWORD *const pdwSize,
|
|
const DWORD dwFlags)
|
|
{
|
|
DIRECTNETOBJECT *pdnObject;
|
|
HRESULT hResultCode;
|
|
CPackedBuffer packedBuffer;
|
|
CNameTableEntry *pHostPlayer;
|
|
|
|
DPFX(DPFPREP, 3,"Parameters: pInterface [0x%p], pdpnPlayerInfo [0x%p], pdwSize [%p], dwFlags [0x%lx]",
|
|
pInterface,pdpnPlayerInfo,pdwSize,dwFlags);
|
|
|
|
pdnObject = (DIRECTNETOBJECT*) GET_OBJECT_FROM_INTERFACE(pInterface);
|
|
DNASSERT(pdnObject != NULL);
|
|
|
|
#ifndef DPNBUILD_NOPARAMVAL
|
|
if( pdnObject->dwFlags & DN_OBJECT_FLAG_PARAMVALIDATION )
|
|
{
|
|
if( FAILED( hResultCode = DN_ValidateGetServerInfo( pInterface , pdpnPlayerInfo, pdwSize, dwFlags ) ) )
|
|
{
|
|
DPFX(DPFPREP, 0, "Error validating get server info hr=[0x%lx]", hResultCode );
|
|
DPF_RETURN( hResultCode );
|
|
}
|
|
}
|
|
#endif // !DPNBUILD_NOPARAMVAL
|
|
|
|
// Check to ensure message handler registered
|
|
if (!(pdnObject->dwFlags & DN_OBJECT_FLAG_INITIALIZED))
|
|
{
|
|
DPFERR( "Object is not initialized" );
|
|
DPF_RETURN(DPNERR_UNINITIALIZED);
|
|
}
|
|
|
|
if( pdnObject->dwFlags & DN_OBJECT_FLAG_CONNECTING )
|
|
{
|
|
DPFERR("Object is connecting / starting to host" );
|
|
DPF_RETURN(DPNERR_CONNECTING);
|
|
}
|
|
|
|
if ( !(pdnObject->dwFlags & (DN_OBJECT_FLAG_CONNECTED | DN_OBJECT_FLAG_CLOSING | DN_OBJECT_FLAG_DISCONNECTING) ) )
|
|
{
|
|
DPFERR("You must be connected / disconnecting to use this function" );
|
|
DPF_RETURN(DPNERR_NOCONNECTION);
|
|
}
|
|
|
|
pHostPlayer = NULL;
|
|
|
|
if ((hResultCode = pdnObject->NameTable.GetHostPlayerRef(&pHostPlayer)) != DPN_OK)
|
|
{
|
|
DPFERR("Could not find Host player");
|
|
DisplayDNError(0,hResultCode);
|
|
goto Failure;
|
|
}
|
|
packedBuffer.Initialize(pdpnPlayerInfo,*pdwSize);
|
|
|
|
pHostPlayer->Lock();
|
|
hResultCode = pHostPlayer->PackInfo(&packedBuffer);
|
|
pHostPlayer->Unlock();
|
|
|
|
pHostPlayer->Release();
|
|
pHostPlayer = NULL;
|
|
|
|
if ((hResultCode == DPN_OK) || (hResultCode == DPNERR_BUFFERTOOSMALL))
|
|
{
|
|
*pdwSize = packedBuffer.GetSizeRequired();
|
|
}
|
|
|
|
Exit:
|
|
DPF_RETURN(hResultCode);
|
|
|
|
Failure:
|
|
if (pHostPlayer)
|
|
{
|
|
pHostPlayer->Release();
|
|
pHostPlayer = NULL;
|
|
}
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DN_GetHostSendQueueInfo"
|
|
|
|
STDMETHODIMP DN_GetHostSendQueueInfo(IDirectPlay8Client *pInterface,
|
|
DWORD *const pdwNumMsgs,
|
|
DWORD *const pdwNumBytes,
|
|
const DWORD dwFlags )
|
|
{
|
|
DIRECTNETOBJECT *pdnObject;
|
|
DWORD dwQueueFlags;
|
|
DWORD dwNumMsgs;
|
|
DWORD dwNumBytes;
|
|
CNameTableEntry *pNTEntry;
|
|
CConnection *pConnection;
|
|
HRESULT hResultCode;
|
|
|
|
DPFX(DPFPREP, 3,"Parameters : pInterface [0x%p], pdwNumMsgs [0x%p], pdwNumBytes [0x%p], dwFlags [0x%lx]",
|
|
pInterface,pdwNumMsgs,pdwNumBytes,dwFlags);
|
|
|
|
pdnObject = (DIRECTNETOBJECT*) GET_OBJECT_FROM_INTERFACE(pInterface);
|
|
DNASSERT(pdnObject != NULL);
|
|
|
|
#ifndef DPNBUILD_NOPARAMVAL
|
|
if( pdnObject->dwFlags & DN_OBJECT_FLAG_PARAMVALIDATION )
|
|
{
|
|
if( FAILED( hResultCode = DN_ValidateGetHostSendQueueInfo( pInterface , pdwNumMsgs, pdwNumBytes, dwFlags ) ) )
|
|
{
|
|
DPFX(DPFPREP, 0, "Error validating get server info hr=[0x%lx]", hResultCode );
|
|
DPF_RETURN( hResultCode );
|
|
}
|
|
}
|
|
#endif // !DPNBUILD_NOPARAMVAL
|
|
|
|
// Check to ensure message handler registered
|
|
if (!(pdnObject->dwFlags & DN_OBJECT_FLAG_INITIALIZED))
|
|
{
|
|
DPFERR( "Object is not initialized" );
|
|
DPF_RETURN(DPNERR_UNINITIALIZED);
|
|
}
|
|
|
|
if( pdnObject->dwFlags & DN_OBJECT_FLAG_CONNECTING )
|
|
{
|
|
DPFERR( "Object has not yet completed connecting / hosting" );
|
|
DPF_RETURN(DPNERR_CONNECTING);
|
|
}
|
|
|
|
if (!(pdnObject->dwFlags & DN_OBJECT_FLAG_CONNECTED) )
|
|
{
|
|
DPFERR("Object is not connected or hosting" );
|
|
DPF_RETURN(DPNERR_NOCONNECTION);
|
|
}
|
|
|
|
pNTEntry = NULL;
|
|
pConnection = NULL;
|
|
|
|
//
|
|
// Get CConnection object
|
|
//
|
|
#ifndef DPNBUILD_NOMULTICAST
|
|
if (pdnObject->dwFlags & DN_OBJECT_FLAG_MULTICAST)
|
|
{
|
|
DNEnterCriticalSection(&pdnObject->csDirectNetObject);
|
|
if (pdnObject->pMulticastSend != NULL)
|
|
{
|
|
pdnObject->pMulticastSend->AddRef();
|
|
pConnection = pdnObject->pMulticastSend;
|
|
}
|
|
else
|
|
{
|
|
pConnection = NULL;
|
|
}
|
|
DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
|
|
|
|
if (pConnection == NULL)
|
|
{
|
|
DPFERR( "Couldn't retrieve multicast send connection" );
|
|
hResultCode = DPNERR_INVALIDGROUP;
|
|
goto Failure;
|
|
}
|
|
}
|
|
else
|
|
#endif // ! DPNBUILD_NOMULTICAST
|
|
{
|
|
if ((hResultCode = pdnObject->NameTable.GetHostPlayerRef( &pNTEntry )) != DPN_OK)
|
|
{
|
|
DPFX(DPFPREP, 0,"Could not find Host Player in NameTable");
|
|
hResultCode = DPNERR_CONNECTIONLOST;
|
|
goto Failure;
|
|
}
|
|
if ((hResultCode = pNTEntry->GetConnectionRef( &pConnection )) != DPN_OK)
|
|
{
|
|
hResultCode = DPNERR_CONNECTIONLOST;
|
|
goto Failure;
|
|
}
|
|
pNTEntry->Release();
|
|
pNTEntry = NULL;
|
|
}
|
|
|
|
//
|
|
// Determine required queues
|
|
//
|
|
dwQueueFlags = dwFlags & (DPNGETSENDQUEUEINFO_PRIORITY_HIGH | DPNGETSENDQUEUEINFO_PRIORITY_NORMAL | DPNGETSENDQUEUEINFO_PRIORITY_LOW);
|
|
if (dwQueueFlags == 0)
|
|
{
|
|
dwQueueFlags = (DPNGETSENDQUEUEINFO_PRIORITY_HIGH | DPNGETSENDQUEUEINFO_PRIORITY_NORMAL | DPNGETSENDQUEUEINFO_PRIORITY_LOW);
|
|
}
|
|
|
|
//
|
|
// Extract required info
|
|
//
|
|
dwNumMsgs = 0;
|
|
dwNumBytes = 0;
|
|
pConnection->Lock();
|
|
if (dwQueueFlags & DPNGETSENDQUEUEINFO_PRIORITY_HIGH)
|
|
{
|
|
dwNumMsgs += pConnection->GetHighQueueNum();
|
|
dwNumBytes += pConnection->GetHighQueueBytes();
|
|
}
|
|
if (dwQueueFlags & DPNGETSENDQUEUEINFO_PRIORITY_NORMAL)
|
|
{
|
|
dwNumMsgs += pConnection->GetNormalQueueNum();
|
|
dwNumBytes += pConnection->GetNormalQueueBytes();
|
|
}
|
|
if (dwQueueFlags & DPNGETSENDQUEUEINFO_PRIORITY_LOW)
|
|
{
|
|
dwNumMsgs += pConnection->GetLowQueueNum();
|
|
dwNumBytes += pConnection->GetLowQueueBytes();
|
|
}
|
|
pConnection->Unlock();
|
|
pConnection->Release();
|
|
pConnection = NULL;
|
|
|
|
if (pdwNumMsgs)
|
|
{
|
|
*pdwNumMsgs = dwNumMsgs;
|
|
DPFX(DPFPREP, 3,"Setting: *pdwNumMsgs [%ld]",dwNumMsgs);
|
|
}
|
|
if (pdwNumBytes)
|
|
{
|
|
*pdwNumBytes = dwNumBytes;
|
|
DPFX(DPFPREP, 3,"Setting: *pdwNumBytes [%ld]",dwNumBytes);
|
|
}
|
|
|
|
hResultCode = DPN_OK;
|
|
|
|
Exit:
|
|
DPFX(DPFPREP, 2,"Returning: [0x%lx]",hResultCode);
|
|
return(hResultCode);
|
|
|
|
Failure:
|
|
if (pNTEntry)
|
|
{
|
|
pNTEntry->Release();
|
|
pNTEntry = NULL;
|
|
}
|
|
if (pConnection)
|
|
{
|
|
pConnection->Release();
|
|
pConnection = NULL;
|
|
}
|
|
goto Exit;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DN_GetServerAddress"
|
|
|
|
STDMETHODIMP DN_GetServerAddress(IDirectPlay8Client *pInterface,
|
|
IDirectPlay8Address **const ppAddress,
|
|
const DWORD dwFlags)
|
|
{
|
|
DIRECTNETOBJECT *pdnObject;
|
|
IDirectPlay8Address *pAddress;
|
|
HRESULT hResultCode;
|
|
CNameTableEntry *pHostPlayer;
|
|
|
|
DPFX(DPFPREP, 3,"Parameters : pInterface [0x%p], ppAddress [0x%p], dwFlags [0x%lx]",
|
|
pInterface,ppAddress,dwFlags);
|
|
|
|
pdnObject = (DIRECTNETOBJECT*) GET_OBJECT_FROM_INTERFACE(pInterface);
|
|
DNASSERT(pdnObject != NULL);
|
|
|
|
#ifndef DPNBUILD_NOPARAMVAL
|
|
if( pdnObject->dwFlags & DN_OBJECT_FLAG_PARAMVALIDATION )
|
|
{
|
|
if( FAILED( hResultCode = DN_ValidateGetServerAddress( pInterface,ppAddress,dwFlags ) ) )
|
|
{
|
|
DPFX(DPFPREP, 0, "Error validating get server info hr=[0x%lx]", hResultCode );
|
|
DPF_RETURN( hResultCode );
|
|
}
|
|
}
|
|
#endif // !DPNBUILD_NOPARAMVAL
|
|
|
|
// Check to ensure message handler registered
|
|
if (!(pdnObject->dwFlags & DN_OBJECT_FLAG_INITIALIZED))
|
|
{
|
|
DPFERR( "Object is not initialized" );
|
|
DPF_RETURN(DPNERR_UNINITIALIZED);
|
|
}
|
|
|
|
if( pdnObject->dwFlags & DN_OBJECT_FLAG_CONNECTING )
|
|
{
|
|
DPFERR("Object is connecting / starting to host" );
|
|
DPF_RETURN(DPNERR_CONNECTING);
|
|
}
|
|
|
|
if ( !(pdnObject->dwFlags & (DN_OBJECT_FLAG_CONNECTED | DN_OBJECT_FLAG_CLOSING | DN_OBJECT_FLAG_DISCONNECTING) ) )
|
|
{
|
|
DPFERR("You must be connected / disconnecting to use this function" );
|
|
DPF_RETURN(DPNERR_NOCONNECTION);
|
|
}
|
|
|
|
pHostPlayer = NULL;
|
|
|
|
if ((hResultCode = pdnObject->NameTable.GetHostPlayerRef( &pHostPlayer )) != DPN_OK)
|
|
{
|
|
DPFERR("Could not find Host player");
|
|
DisplayDNError(0,hResultCode);
|
|
goto Failure;
|
|
}
|
|
pAddress = pHostPlayer->GetAddress();
|
|
DNASSERT(pAddress != NULL);
|
|
hResultCode = IDirectPlay8Address_Duplicate(pAddress,ppAddress);
|
|
|
|
pHostPlayer->Release();
|
|
pHostPlayer = NULL;
|
|
|
|
Exit:
|
|
DPF_RETURN(hResultCode);
|
|
|
|
Failure:
|
|
if (pHostPlayer)
|
|
{
|
|
pHostPlayer->Release();
|
|
pHostPlayer = NULL;
|
|
}
|
|
goto Exit;
|
|
}
|