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.
498 lines
19 KiB
498 lines
19 KiB
/*==========================================================================
|
|
*
|
|
* Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: Server.cpp
|
|
* Content: DNET server interface routines
|
|
*@@BEGIN_MSINTERNAL
|
|
* History:
|
|
* Date By Reason
|
|
* ==== == ======
|
|
* 07/21/99 mjn Created
|
|
* 12/23/99 mjn Hand all NameTable update sends from Host to worker thread
|
|
* 12/28/99 mjn Moved Async Op stuff to Async.h
|
|
* 01/06/00 mjn Moved NameTable stuff to NameTable.h
|
|
* 01/14/00 mjn Added pvUserContext to Host API call
|
|
* 01/16/00 mjn Moved User callback stuff to User.h
|
|
* 01/22/00 mjn Implemented DestroyClient in API
|
|
* 01/28/00 mjn Implemented ReturnBuffer in API
|
|
* 02/01/00 mjn Implemented GetCaps and SetCaps in API
|
|
* 02/01/00 mjn Implement Player/Group context values
|
|
* 02/15/00 mjn Use INFO flags in SetServerInfo and return context in GetClientInfo
|
|
* 02/17/00 mjn Implemented GetPlayerContext and GetGroupContext
|
|
* 03/17/00 rmt Added new caps functions
|
|
* 04/04/00 mjn Added TerminateSession to API
|
|
* 04/05/00 mjn Modified DestroyClient
|
|
* 04/06/00 mjn Added GetClientAddress to API
|
|
* mjn Added GetHostAddress to API
|
|
* 04/18/00 rmt Added additional paramtere validation
|
|
* 04/19/00 mjn SendTo API call accepts a range of DPN_BUFFER_DESCs and a count
|
|
* 04/24/00 mjn Updated Group and Info operations to use CAsyncOp's
|
|
* 05/31/00 mjn Added operation specific SYNC flags
|
|
* 06/23/00 mjn Removed dwPriority from SendTo() API call
|
|
* 07/09/00 mjn Cleaned up DN_SetServerInfo()
|
|
* 07/09/00 rmt Bug #38323 - RegisterLobby needs a DPNHANDLE parameter.
|
|
* 08/05/00 RichGr IA64: Use %p format specifier in DPFs for 32/64-bit pointers and handles.
|
|
* 10/11/00 mjn Take locks for CNameTableEntry::PackInfo()
|
|
* mjn Check deleted list in DN_GetClientInfo()
|
|
* 01/22/01 mjn Check closing instead of disconnecting in DN_GetClientInfo()
|
|
* 07/24/01 mjn Added DPNBUILD_NOPARAMVAL compile flag
|
|
*@@END_MSINTERNAL
|
|
*
|
|
***************************************************************************/
|
|
|
|
#include "dncorei.h"
|
|
|
|
#ifndef DPNBUILD_NOSERVER
|
|
|
|
//**********************************************************************
|
|
// Constant definitions
|
|
//**********************************************************************
|
|
|
|
//**********************************************************************
|
|
// Macro definitions
|
|
//**********************************************************************
|
|
|
|
//**********************************************************************
|
|
// Structure definitions
|
|
//**********************************************************************
|
|
|
|
//**********************************************************************
|
|
// Variable definitions
|
|
//**********************************************************************
|
|
|
|
typedef STDMETHODIMP ServerQueryInterface( IDirectPlay8Server *pInterface, DP8REFIID riid, LPVOID *ppvObj );
|
|
typedef STDMETHODIMP_(ULONG) ServerAddRef( IDirectPlay8Server *pInterface );
|
|
typedef STDMETHODIMP_(ULONG) ServerRelease( IDirectPlay8Server *pInterface );
|
|
typedef STDMETHODIMP ServerInitialize( IDirectPlay8Server *pInterface, LPVOID const lpvUserContext, const PFNDPNMESSAGEHANDLER lpfn, const DWORD dwFlags );
|
|
typedef STDMETHODIMP ServerEnumServiceProviders( IDirectPlay8Server *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 ServerCancelAsyncOperation( IDirectPlay8Server *pInterface, const DPNHANDLE hAsyncHandle, const DWORD dwFlags );
|
|
typedef STDMETHODIMP ServerGetSendQueueInfo( IDirectPlay8Server *pInterface, const DPNID dpnid,DWORD *const lpdwNumMsgs, DWORD *const lpdwNumBytes, const DWORD dwFlags );
|
|
typedef STDMETHODIMP ServerGetApplicationDesc( IDirectPlay8Server *pInterface,DPN_APPLICATION_DESC *const pAppDescBuffer,DWORD *const lpcbDataSize,const DWORD dwFlags );
|
|
typedef STDMETHODIMP ServerSetApplicationDesc( IDirectPlay8Server *pInterface, const DPN_APPLICATION_DESC *const lpad, const DWORD dwFlags );
|
|
typedef STDMETHODIMP ServerGetHostAddress( IDirectPlay8Server *pInterface, IDirectPlay8Address **const prgpAddress, DWORD *const pcAddress,const DWORD dwFlags);
|
|
typedef STDMETHODIMP ServerHost( IDirectPlay8Server *pInterface,const DPN_APPLICATION_DESC *const pdnAppDesc,IDirectPlay8Address **const prgpDeviceInfo,const DWORD cDeviceInfo,const DPN_SECURITY_DESC *const pdnSecurity,const DPN_SECURITY_CREDENTIALS *const pdnCredentials,void *const pvPlayerContext,const DWORD dwFlags);
|
|
typedef STDMETHODIMP ServerSendTo( IDirectPlay8Server *pInterface, const DPNID dnid, const DPN_BUFFER_DESC *const prgBufferDesc,const DWORD cBufferDesc,const DWORD dwTimeOut, void *const pvAsyncContext, DPNHANDLE *const phAsyncHandle, const DWORD dwFlags);
|
|
typedef STDMETHODIMP ServerCreateGroup( IDirectPlay8Server *pInterface, const DPN_GROUP_INFO *const pdpnGroupInfo,void *const pvGroupContext,void *const pvAsyncContext,DPNHANDLE *const phAsyncHandle,const DWORD dwFlags);
|
|
typedef STDMETHODIMP ServerDestroyGroup( IDirectPlay8Server *pInterface, const DPNID idGroup,PVOID const pvUserContext,DPNHANDLE *const lpAsyncHandle,const DWORD dwFlags);
|
|
typedef STDMETHODIMP ServerAddClientToGroup( IDirectPlay8Server *pInterface, const DPNID idGroup, const DPNID idClient,PVOID const pvUserContext,DPNHANDLE *const lpAsyncHandle,const DWORD dwFlags);
|
|
typedef STDMETHODIMP ServerRemoveClientFromGroup( IDirectPlay8Server *pInterface, const DPNID idGroup, const DPNID idClient,PVOID const pvUserContext,DPNHANDLE *const lpAsyncHandle,const DWORD dwFlags);
|
|
typedef STDMETHODIMP ServerSetGroupInfo(IDirectPlay8Server *pInterface, const DPNID dpnid,DPN_GROUP_INFO *const pdpnGroupInfo,PVOID const pvAsyncContext,DPNHANDLE *const phAsyncHandle, const DWORD dwFlags);
|
|
typedef STDMETHODIMP ServerGetGroupInfo(IDirectPlay8Server *pInterface, const DPNID dpnid,DPN_GROUP_INFO *const pdpnGroupInfo,DWORD *const pdwSize,const DWORD dwFlags);
|
|
typedef STDMETHODIMP ServerEnumClientsAndGroups( IDirectPlay8Server *pInterface, DPNID *const lprgdnid, DWORD *const lpcdnid, const DWORD dwFlags );
|
|
typedef STDMETHODIMP ServerEnumGroupMembers( IDirectPlay8Server *pInterface, const DPNID dnid, DPNID *const lprgdnid, DWORD *const lpcdnid, const DWORD dwFlags );
|
|
typedef STDMETHODIMP ServerClose( IDirectPlay8Server *pInterface,const DWORD dwFlags);
|
|
typedef STDMETHODIMP ServerDestroyClient( IDirectPlay8Server *pInterface,const DPNID dnid,const void *const pvDestroyData,const DWORD dwDestroyDataSize,const DWORD dwFlags);
|
|
typedef STDMETHODIMP ServerReturnBuffer( IDirectPlay8Server *pInterface, const DPNHANDLE hBufferHandle,const DWORD dwFlags);
|
|
typedef STDMETHODIMP ServerGetCaps(IDirectPlay8Server *pInterface,DPN_CAPS *const pdnCaps,const DWORD dwFlags);
|
|
typedef STDMETHODIMP ServerSetCaps(IDirectPlay8Server *pInterface,const DPN_CAPS *const pdnCaps,const DWORD dwFlags);
|
|
typedef STDMETHODIMP ServerGetPlayerContext(IDirectPlay8Server *pInterface,const DPNID dpnid,PVOID *const ppvPlayerContext,const DWORD dwFlags);
|
|
typedef STDMETHODIMP ServerGetGroupContext(IDirectPlay8Server *pInterface,const DPNID dpnid,PVOID *const ppvGroupContext,const DWORD dwFlags);
|
|
typedef STDMETHODIMP ServerSetSPCaps(IDirectPlay8Server *pInterface,const GUID * const pguidSP, const DPN_SP_CAPS *const pdpspCaps, const DWORD dwFlags );
|
|
typedef STDMETHODIMP ServerGetSPCaps(IDirectPlay8Server *pInterface,const GUID * const pguidSP, DPN_SP_CAPS *const pdpspCaps,const DWORD dwFlags);
|
|
typedef STDMETHODIMP ServerGetConnectionInfo(IDirectPlay8Server *pInterface,const DPNID dpnid, DPN_CONNECTION_INFO *const pdpConnectionInfo,const DWORD dwFlags);
|
|
typedef STDMETHODIMP ServerRegisterLobby(IDirectPlay8Server *pInterface,const DPNHANDLE dpnHandle,IDirectPlay8LobbiedApplication *const pIDP8LobbiedApplication,const DWORD dwFlags);
|
|
|
|
//
|
|
// VTable for server interface
|
|
//
|
|
IDirectPlay8ServerVtbl DN_ServerVtbl =
|
|
{
|
|
(ServerQueryInterface*) DN_QueryInterface,
|
|
(ServerAddRef*) DN_AddRef,
|
|
(ServerRelease*) DN_Release,
|
|
(ServerInitialize*) DN_Initialize,
|
|
(ServerEnumServiceProviders*) DN_EnumServiceProviders,
|
|
(ServerCancelAsyncOperation*) DN_CancelAsyncOperation,
|
|
(ServerGetSendQueueInfo*) DN_GetSendQueueInfo,
|
|
(ServerGetApplicationDesc*) DN_GetApplicationDesc,
|
|
DN_SetServerInfo,
|
|
DN_GetClientInfo,
|
|
DN_GetClientAddress,
|
|
(ServerGetHostAddress*) DN_GetHostAddress,
|
|
(ServerSetApplicationDesc*) DN_SetApplicationDesc,
|
|
(ServerHost*) DN_Host,
|
|
(ServerSendTo*) DN_SendTo,
|
|
(ServerCreateGroup*) DN_CreateGroup,
|
|
(ServerDestroyGroup*) DN_DestroyGroup,
|
|
(ServerAddClientToGroup*) DN_AddClientToGroup,
|
|
(ServerRemoveClientFromGroup*) DN_RemoveClientFromGroup,
|
|
(ServerSetGroupInfo*) DN_SetGroupInfo,
|
|
(ServerGetGroupInfo*) DN_GetGroupInfo,
|
|
(ServerEnumClientsAndGroups*) DN_EnumClientsAndGroups,
|
|
(ServerEnumGroupMembers*) DN_EnumGroupMembers,
|
|
(ServerClose*) DN_Close,
|
|
(ServerDestroyClient*) DN_DestroyPlayer,
|
|
(ServerReturnBuffer*) DN_ReturnBuffer,
|
|
(ServerGetPlayerContext*) DN_GetPlayerContext,
|
|
(ServerGetGroupContext*) DN_GetGroupContext,
|
|
(ServerGetCaps*) DN_GetCaps,
|
|
(ServerSetCaps*) DN_SetCaps,
|
|
(ServerSetSPCaps*) DN_SetSPCaps,
|
|
(ServerGetSPCaps*) DN_GetSPCaps,
|
|
(ServerGetConnectionInfo*) DN_GetConnectionInfo,
|
|
(ServerRegisterLobby*) DN_RegisterLobby
|
|
};
|
|
|
|
//**********************************************************************
|
|
// Function prototypes
|
|
//**********************************************************************
|
|
|
|
//**********************************************************************
|
|
// Function definitions
|
|
//**********************************************************************
|
|
|
|
// DN_SetServerInfo
|
|
//
|
|
// Set the info for the server and propagate to client players
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DN_SetServerInfo"
|
|
|
|
STDMETHODIMP DN_SetServerInfo(IDirectPlay8Server *pInterface,
|
|
const DPN_PLAYER_INFO *const pdpnPlayerInfo,
|
|
PVOID const 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_ValidateSetServerInfo( pInterface , pdpnPlayerInfo, pvAsyncContext, phAsyncHandle, dwFlags ) ) )
|
|
{
|
|
DPFX(DPFPREP, 0, "Error validating setserverinfo 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 update our entry.
|
|
// 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,"Host is updating server info");
|
|
|
|
hResultCode = DNHostUpdateInfo( pdnObject,
|
|
pLocalPlayer->GetDPNID(),
|
|
pwszName,
|
|
dwNameSize,
|
|
pvData,
|
|
dwDataSize,
|
|
pdpnPlayerInfo->dwInfoFlags,
|
|
pvAsyncContext,
|
|
pLocalPlayer->GetDPNID(),
|
|
0,
|
|
&hAsyncOp,
|
|
dwFlags );
|
|
if ((hResultCode != DPN_OK) && (hResultCode != DPNERR_PENDING))
|
|
{
|
|
DPFERR("Could not request host to update group");
|
|
}
|
|
else
|
|
{
|
|
if (!(dwFlags & DPNSETSERVERINFO_SYNC))
|
|
{
|
|
DPFX(DPFPREP, 3,"Async Handle [0x%lx]",hAsyncOp);
|
|
*phAsyncHandle = hAsyncOp;
|
|
|
|
//
|
|
// Release Async HANDLE since this operation has already completed (!)
|
|
//
|
|
CAsyncOp* pAsyncOp;
|
|
if (SUCCEEDED(pdnObject->HandleTable.Destroy( hAsyncOp, (PVOID*)&pAsyncOp )))
|
|
{
|
|
// Release the HandleTable reference
|
|
pAsyncOp->Release();
|
|
}
|
|
pAsyncOp = NULL;
|
|
hAsyncOp = 0;
|
|
}
|
|
}
|
|
|
|
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_GetClientInfo
|
|
//
|
|
// Retrieve client info from the local nametable.
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DN_GetClientInfo"
|
|
|
|
STDMETHODIMP DN_GetClientInfo(IDirectPlay8Server *pInterface,
|
|
const DPNID dpnid,
|
|
DPN_PLAYER_INFO *const pdpnPlayerInfo,
|
|
DWORD *const pdwSize,
|
|
const DWORD dwFlags)
|
|
{
|
|
DIRECTNETOBJECT *pdnObject;
|
|
CNameTableEntry *pNTEntry;
|
|
CPackedBuffer packedBuffer;
|
|
HRESULT hResultCode;
|
|
|
|
DPFX(DPFPREP, 2,"Parameters: dpnid [0x%lx], pdpnPlayerInfo [0x%p], dwFlags [0x%lx]",
|
|
dpnid,pdpnPlayerInfo,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_ValidateGetClientInfo( pInterface , dpnid, pdpnPlayerInfo, pdwSize, dwFlags ) ) )
|
|
{
|
|
DPFX(DPFPREP, 0, "Error validating getclientinfo 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);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
pNTEntry = NULL;
|
|
|
|
if ((hResultCode = pdnObject->NameTable.FindEntry(dpnid,&pNTEntry)) != DPN_OK)
|
|
{
|
|
DPFERR("Could not retrieve name table entry");
|
|
DisplayDNError(0,hResultCode);
|
|
|
|
//
|
|
// Try deleted list
|
|
//
|
|
if ((hResultCode = pdnObject->NameTable.FindDeletedEntry(dpnid,&pNTEntry)) != DPN_OK)
|
|
{
|
|
DPFERR("Could not find player in deleted list either");
|
|
DisplayDNError(0,hResultCode);
|
|
hResultCode = DPNERR_INVALIDPLAYER;
|
|
goto Failure;
|
|
}
|
|
}
|
|
packedBuffer.Initialize(pdpnPlayerInfo,*pdwSize);
|
|
|
|
pNTEntry->Lock();
|
|
if (pNTEntry->IsGroup() || pNTEntry->IsHost())
|
|
{
|
|
DPFERR( "Specified ID is invalid" );
|
|
pNTEntry->Unlock();
|
|
hResultCode = DPNERR_INVALIDPLAYER;
|
|
goto Failure;
|
|
}
|
|
|
|
hResultCode = pNTEntry->PackInfo(&packedBuffer);
|
|
|
|
pNTEntry->Unlock();
|
|
pNTEntry->Release();
|
|
pNTEntry = NULL;
|
|
|
|
if ((hResultCode == DPN_OK) || (hResultCode == DPNERR_BUFFERTOOSMALL))
|
|
{
|
|
*pdwSize = packedBuffer.GetSizeRequired();
|
|
}
|
|
|
|
Exit:
|
|
DPFX(DPFPREP, 2,"Returning: [0x%lx]",hResultCode);
|
|
return(hResultCode);
|
|
|
|
Failure:
|
|
if (pNTEntry)
|
|
{
|
|
pNTEntry->Release();
|
|
pNTEntry = NULL;
|
|
}
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DN_GetClientAddress"
|
|
|
|
STDMETHODIMP DN_GetClientAddress(IDirectPlay8Server *pInterface,
|
|
const DPNID dpnid,
|
|
IDirectPlay8Address **const ppAddress,
|
|
const DWORD dwFlags)
|
|
{
|
|
DIRECTNETOBJECT *pdnObject;
|
|
CNameTableEntry *pNTEntry;
|
|
IDirectPlay8Address *pAddress;
|
|
HRESULT hResultCode;
|
|
|
|
DPFX(DPFPREP, 2,"Parameters : pInterface [0x%p], dpnid [0x%lx], ppAddress [0x%p], dwFlags [0x%lx]",
|
|
pInterface,dpnid,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_ValidateGetClientAddress( pInterface , dpnid, ppAddress, dwFlags ) ) )
|
|
{
|
|
DPFX(DPFPREP, 0, "Error validating getclientaddress 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);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
pNTEntry = NULL;
|
|
pAddress = NULL;
|
|
|
|
if ((hResultCode = pdnObject->NameTable.FindEntry(dpnid,&pNTEntry)) != DPN_OK)
|
|
{
|
|
DPFERR("Could not find NameTableEntry");
|
|
DisplayDNError(0,hResultCode);
|
|
hResultCode = DPNERR_INVALIDPLAYER;
|
|
goto Failure;
|
|
}
|
|
|
|
if ((pNTEntry->GetAddress() == NULL) || (pNTEntry->IsGroup()) || !pNTEntry->IsAvailable())
|
|
{
|
|
DPFERR( "Specified player is not valid" );
|
|
hResultCode = DPNERR_INVALIDPLAYER;
|
|
goto Failure;
|
|
}
|
|
|
|
hResultCode = IDirectPlay8Address_Duplicate(pNTEntry->GetAddress(),ppAddress);
|
|
|
|
pNTEntry->Release();
|
|
pNTEntry = NULL;
|
|
|
|
Exit:
|
|
DPFX(DPFPREP, 2,"Returning: [0x%lx]",hResultCode);
|
|
return(hResultCode);
|
|
|
|
Failure:
|
|
if (pNTEntry)
|
|
{
|
|
pNTEntry->Release();
|
|
pNTEntry = NULL;
|
|
}
|
|
|
|
goto Exit;
|
|
}
|
|
|
|
#endif // DPNBUILD_NOSERVER
|