1002 lines
28 KiB
C++
1002 lines
28 KiB
C++
|
/*==========================================================================
|
||
|
*
|
||
|
* Copyright (C) 2000 Microsoft Corporation. All Rights Reserved.
|
||
|
*
|
||
|
* File: DPLConnect.cpp
|
||
|
* Content: DirectPlay Lobby Connection Functions
|
||
|
*@@BEGIN_MSINTERNAL
|
||
|
* History:
|
||
|
* Date By Reason
|
||
|
* ==== == ======
|
||
|
* 02/21/00 mjn Created
|
||
|
* 05/08/00 rmt Bug #33616 -- Does not run on Win9X
|
||
|
* 05/30/00 rmt Bug #35700 - ConnectApp(h), Release(h), Release(h) returns OK
|
||
|
* Added an additional release, handles were never getting destroyed
|
||
|
* 06/15/00 rmt Bug #33617 - Must provide method for providing automatic launch of DirectPlay instances
|
||
|
* 06/28/00 rmt Prefix Bug #38082
|
||
|
* 07/08/2000 rmt Bug #38725 - Need to provide method to detect if app was lobby launched
|
||
|
* rmt Bug #38757 - Callback messages for connections may return AFTER WaitForConnection returns
|
||
|
* rmt Bug #38755 - No way to specify player name in Connection Settings
|
||
|
* rmt Bug #38758 - DPLOBBY8.H has incorrect comments
|
||
|
* rmt Bug #38783 - pvUserApplicationContext is only partially implemented
|
||
|
* rmt Added DPLHANDLE_ALLCONNECTIONS and dwFlags (reserved field to couple of funcs).
|
||
|
* 08/05/2000 RichGr IA64: Use %p format specifier in DPFs for 32/64-bit pointers and handles.
|
||
|
* 08/18/2000 rmt Bug #42751 - DPLOBBY8: Prohibit more than one lobby client or lobby app per process
|
||
|
* 08/30/2000 rmt Bug #171827 - Prefix Bug
|
||
|
* 01/04/2001 rodtoll WinBug #94200 - Remove BUGBUGs from Code.
|
||
|
*@@END_MSINTERNAL
|
||
|
*
|
||
|
***************************************************************************/
|
||
|
|
||
|
#include "dnlobbyi.h"
|
||
|
|
||
|
|
||
|
//**********************************************************************
|
||
|
// Constant definitions
|
||
|
//**********************************************************************
|
||
|
|
||
|
//**********************************************************************
|
||
|
// Macro definitions
|
||
|
//**********************************************************************
|
||
|
|
||
|
//**********************************************************************
|
||
|
// Structure definitions
|
||
|
//**********************************************************************
|
||
|
|
||
|
//**********************************************************************
|
||
|
// Variable definitions
|
||
|
//**********************************************************************
|
||
|
|
||
|
//**********************************************************************
|
||
|
// Function prototypes
|
||
|
//**********************************************************************
|
||
|
|
||
|
//**********************************************************************
|
||
|
// Function definitions
|
||
|
//**********************************************************************
|
||
|
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "DPLConnectionNew"
|
||
|
|
||
|
HRESULT DPLConnectionNew(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
|
||
|
DPNHANDLE *const phConnect,
|
||
|
DPL_CONNECTION **const ppdplConnection)
|
||
|
{
|
||
|
HRESULT hResultCode;
|
||
|
DPL_CONNECTION *pdplConnection;
|
||
|
DPNHANDLE handle;
|
||
|
|
||
|
DPFX(DPFPREP, 3,"Parameters: phConnect [0x%p], ppdplConnection [0x%p]",phConnect,ppdplConnection);
|
||
|
|
||
|
if( ppdplConnection == NULL )
|
||
|
{
|
||
|
DPFERR( "ppdplConnection param is NULL -- this should not happen" );
|
||
|
DNASSERT( FALSE );
|
||
|
return DPNERR_GENERIC;
|
||
|
}
|
||
|
|
||
|
// Create connection entry
|
||
|
if ((pdplConnection = static_cast<DPL_CONNECTION*>(DNMalloc(sizeof(DPL_CONNECTION)))) == NULL)
|
||
|
{
|
||
|
DPFERR("Could not allocate Connection entry");
|
||
|
return(DPNERR_OUTOFMEMORY);
|
||
|
}
|
||
|
|
||
|
// Create connection handle
|
||
|
if ((hResultCode = H_Create(&pdpLobbyObject->hsHandles,
|
||
|
static_cast<void*>(pdplConnection),&handle)) != DPN_OK)
|
||
|
{
|
||
|
DPFERR("Could not create Connection handle");
|
||
|
DisplayDNError(0,hResultCode);
|
||
|
DNFree(pdplConnection);
|
||
|
return(hResultCode);
|
||
|
}
|
||
|
|
||
|
// Create connect event
|
||
|
pdplConnection->hConnectEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
||
|
if (pdplConnection->hConnectEvent == NULL)
|
||
|
{
|
||
|
DPFERR("Could not create connection connect event");
|
||
|
H_Destroy(&pdpLobbyObject->hsHandles,handle);
|
||
|
DNFree(pdplConnection);
|
||
|
return(DPNERR_OUTOFMEMORY);
|
||
|
}
|
||
|
|
||
|
// Initialize entry
|
||
|
pdplConnection->hConnect = handle;
|
||
|
pdplConnection->dwTargetPID = 0;
|
||
|
pdplConnection->pSendQueue = NULL;
|
||
|
pdplConnection->lRefCount = 1;
|
||
|
pdplConnection->pConnectionSettings = NULL;
|
||
|
pdplConnection->pvConnectContext = NULL;
|
||
|
|
||
|
if (DNInitializeCriticalSection( &pdplConnection->csLock ) == FALSE)
|
||
|
{
|
||
|
DPFERR("Could not initialize connection CS");
|
||
|
CloseHandle(pdplConnection->hConnectEvent);
|
||
|
H_Destroy(&pdpLobbyObject->hsHandles,handle);
|
||
|
DNFree(pdplConnection);
|
||
|
return(DPNERR_OUTOFMEMORY);
|
||
|
}
|
||
|
|
||
|
*phConnect = handle;
|
||
|
if (ppdplConnection != NULL)
|
||
|
*ppdplConnection = pdplConnection;
|
||
|
|
||
|
DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
|
||
|
return(hResultCode);
|
||
|
}
|
||
|
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "DPLConnectionFind"
|
||
|
|
||
|
HRESULT DPLConnectionFind(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
|
||
|
const DPNHANDLE hConnect,
|
||
|
DPL_CONNECTION **const ppdplConnection,
|
||
|
const BOOL bAddRef)
|
||
|
{
|
||
|
HRESULT hResultCode;
|
||
|
DPL_CONNECTION *pdplConnection;
|
||
|
|
||
|
DPFX(DPFPREP, 3,"Parameters: hConnect [0x%lx], ppdplConnection [0x%p], bAddRef [%ld]",
|
||
|
hConnect,ppdplConnection,bAddRef);
|
||
|
|
||
|
DNASSERT(pdpLobbyObject != NULL);
|
||
|
DNASSERT(hConnect != NULL);
|
||
|
DNASSERT(ppdplConnection != NULL);
|
||
|
|
||
|
if ((hResultCode = H_Retrieve(&pdpLobbyObject->hsHandles,hConnect,
|
||
|
reinterpret_cast<void**>(&pdplConnection))) != DPN_OK)
|
||
|
{
|
||
|
DPFERR("Could not retrieve handle");
|
||
|
return(hResultCode);
|
||
|
}
|
||
|
|
||
|
if (bAddRef)
|
||
|
{
|
||
|
InterlockedIncrement(&pdplConnection->lRefCount);
|
||
|
}
|
||
|
|
||
|
*ppdplConnection = pdplConnection;
|
||
|
|
||
|
DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
|
||
|
return(hResultCode);
|
||
|
}
|
||
|
|
||
|
// DPLConnectionGetConnectSettings
|
||
|
//
|
||
|
// This function gets the connection settings attached to the specified connection.
|
||
|
//
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "DPLConnectionGetConnectSettings"
|
||
|
HRESULT DPLConnectionGetConnectSettings( DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
|
||
|
DPNHANDLE const hConnect,
|
||
|
DPL_CONNECTION_SETTINGS * const pdplConnectSettings,
|
||
|
DWORD * const pdwDataSize )
|
||
|
{
|
||
|
HRESULT hResultCode;
|
||
|
DPL_CONNECTION *pdplConnection;
|
||
|
|
||
|
hResultCode = DPLConnectionFind(pdpLobbyObject, hConnect, &pdplConnection, TRUE );
|
||
|
|
||
|
if( FAILED( hResultCode ) )
|
||
|
{
|
||
|
DPFERR( "Unable to find specified connection" );
|
||
|
return hResultCode;
|
||
|
}
|
||
|
|
||
|
// Grab lock to keep people from interfering.
|
||
|
DNEnterCriticalSection( &pdplConnection->csLock );
|
||
|
|
||
|
if( !pdplConnection->pConnectionSettings )
|
||
|
{
|
||
|
*pdwDataSize = 0;
|
||
|
hResultCode = DPNERR_DOESNOTEXIST;
|
||
|
goto GETCONNECTIONSETTINGS_EXIT;
|
||
|
}
|
||
|
|
||
|
hResultCode = pdplConnection->pConnectionSettings->CopyToBuffer( (BYTE *) pdplConnectSettings, pdwDataSize );
|
||
|
|
||
|
GETCONNECTIONSETTINGS_EXIT:
|
||
|
|
||
|
DNLeaveCriticalSection( &pdplConnection->csLock );
|
||
|
|
||
|
// Release this function's reference
|
||
|
DPLConnectionRelease( pdpLobbyObject, hConnect );
|
||
|
|
||
|
return hResultCode;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
// DPLConnectionSetConnectSettings
|
||
|
//
|
||
|
// This function sets the connection settings attached to the specified connection.
|
||
|
//
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "DPLConnectionSetConnectSettings"
|
||
|
HRESULT DPLConnectionSetConnectSettings(
|
||
|
DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
|
||
|
const DPNHANDLE hConnect,
|
||
|
CConnectionSettings * pConnectionSettings )
|
||
|
{
|
||
|
HRESULT hResultCode;
|
||
|
DPL_CONNECTION *pdplConnection;
|
||
|
|
||
|
hResultCode = DPLConnectionFind(pdpLobbyObject, hConnect, &pdplConnection, TRUE );
|
||
|
|
||
|
if( FAILED( hResultCode ) )
|
||
|
{
|
||
|
DPFERR( "Unable to find specified connection" );
|
||
|
return hResultCode;
|
||
|
}
|
||
|
|
||
|
// Grab lock to prevent other people from interfering
|
||
|
DNEnterCriticalSection( &pdplConnection->csLock );
|
||
|
|
||
|
// Free old one if there is one
|
||
|
if( pdplConnection->pConnectionSettings )
|
||
|
{
|
||
|
delete pdplConnection->pConnectionSettings;
|
||
|
pdplConnection->pConnectionSettings = NULL;
|
||
|
}
|
||
|
|
||
|
pdplConnection->pConnectionSettings = pConnectionSettings;
|
||
|
|
||
|
hResultCode = DPN_OK;
|
||
|
|
||
|
DNLeaveCriticalSection( &pdplConnection->csLock );
|
||
|
|
||
|
DPLConnectionRelease( pdpLobbyObject, hConnect );
|
||
|
|
||
|
return DPN_OK;
|
||
|
}
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "DPLConnectionGetContext"
|
||
|
HRESULT DPLConnectionGetContext(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
|
||
|
const DPNHANDLE hConnection,
|
||
|
PVOID *ppvConnectContext )
|
||
|
{
|
||
|
HRESULT hResultCode;
|
||
|
DPL_CONNECTION *pdplConnection;
|
||
|
|
||
|
hResultCode = DPLConnectionFind(pdpLobbyObject, hConnection, &pdplConnection, TRUE );
|
||
|
|
||
|
if( FAILED( hResultCode ) )
|
||
|
{
|
||
|
*ppvConnectContext = NULL;
|
||
|
DPFERR( "Unable to find specified connection" );
|
||
|
return hResultCode;
|
||
|
}
|
||
|
|
||
|
// Set connection context for the found handle
|
||
|
DNEnterCriticalSection( &pdplConnection->csLock );
|
||
|
*ppvConnectContext = pdplConnection->pvConnectContext;
|
||
|
DNLeaveCriticalSection( &pdplConnection->csLock );
|
||
|
|
||
|
// Release our reference to the connection
|
||
|
DPLConnectionRelease( pdpLobbyObject, hConnection );
|
||
|
|
||
|
return DPN_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "DPLConnectionSetContext"
|
||
|
HRESULT DPLConnectionSetContext(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
|
||
|
const DPNHANDLE hConnection,
|
||
|
PVOID pvConnectContext )
|
||
|
{
|
||
|
HRESULT hResultCode;
|
||
|
DPL_CONNECTION *pdplConnection;
|
||
|
|
||
|
hResultCode = DPLConnectionFind(pdpLobbyObject, hConnection, &pdplConnection, TRUE );
|
||
|
|
||
|
if( FAILED( hResultCode ) )
|
||
|
{
|
||
|
DPFERR( "Unable to find specified connection" );
|
||
|
return hResultCode;
|
||
|
}
|
||
|
|
||
|
// Set connection context for the found handle
|
||
|
DNEnterCriticalSection( &pdplConnection->csLock );
|
||
|
pdplConnection->pvConnectContext = pvConnectContext;
|
||
|
DNLeaveCriticalSection( &pdplConnection->csLock );
|
||
|
|
||
|
// Release our reference to the connection
|
||
|
DPLConnectionRelease( pdpLobbyObject, hConnection );
|
||
|
|
||
|
return DPN_OK;
|
||
|
}
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "DPLConnectionRelease"
|
||
|
|
||
|
HRESULT DPLConnectionRelease(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
|
||
|
const DPNHANDLE hConnect)
|
||
|
{
|
||
|
HRESULT hResultCode;
|
||
|
DPL_CONNECTION *pdplConnection;
|
||
|
LONG lRefCount;
|
||
|
|
||
|
DPFX(DPFPREP, 3,"Parameters: hConnect [0x%lx]",hConnect);
|
||
|
|
||
|
if ((hResultCode = H_Retrieve(&pdpLobbyObject->hsHandles,hConnect,
|
||
|
reinterpret_cast<void**>(&pdplConnection))) != DPN_OK)
|
||
|
{
|
||
|
DPFERR("Could not retrieve connection");
|
||
|
DisplayDNError(0,hResultCode);
|
||
|
return(hResultCode);
|
||
|
}
|
||
|
|
||
|
if (InterlockedDecrement(&pdplConnection->lRefCount) == 0)
|
||
|
{
|
||
|
H_Destroy(&pdpLobbyObject->hsHandles,hConnect);
|
||
|
|
||
|
DPFX(DPFPREP, 5,"Freeing object");
|
||
|
if (pdplConnection->pSendQueue)
|
||
|
{
|
||
|
pdplConnection->pSendQueue->Close();
|
||
|
delete pdplConnection->pSendQueue;
|
||
|
pdplConnection->pSendQueue = NULL;
|
||
|
|
||
|
delete pdplConnection->pConnectionSettings;
|
||
|
pdplConnection->pConnectionSettings = NULL;
|
||
|
DNDeleteCriticalSection( &pdplConnection->csLock );
|
||
|
}
|
||
|
|
||
|
CloseHandle(pdplConnection->hConnectEvent);
|
||
|
|
||
|
DNFree(pdplConnection);
|
||
|
}
|
||
|
|
||
|
DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
|
||
|
return(hResultCode);
|
||
|
}
|
||
|
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "DPLConnectionConnect"
|
||
|
|
||
|
HRESULT DPLConnectionConnect(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
|
||
|
const DPNHANDLE hConnect,
|
||
|
const DWORD dwProcessId,
|
||
|
const BOOL fApplication )
|
||
|
{
|
||
|
HRESULT hResultCode;
|
||
|
DPL_CONNECTION *pdplConnection;
|
||
|
|
||
|
DPFX(DPFPREP, 3,"Parameters: hConnect [0x%lx], dwProcessId [0x%lx]",
|
||
|
hConnect,dwProcessId);
|
||
|
|
||
|
DNASSERT(pdpLobbyObject != NULL);
|
||
|
DNASSERT(hConnect != NULL);
|
||
|
DNASSERT(dwProcessId != 0);
|
||
|
|
||
|
if ((hResultCode = DPLConnectionFind(pdpLobbyObject,hConnect,&pdplConnection,TRUE)) != DPN_OK)
|
||
|
{
|
||
|
DPFERR("Could not find connection");
|
||
|
DisplayDNError(0,hResultCode);
|
||
|
return(hResultCode);
|
||
|
}
|
||
|
|
||
|
pdplConnection->pSendQueue = new CMessageQueue;
|
||
|
|
||
|
if( !pdplConnection->pSendQueue )
|
||
|
{
|
||
|
DPFERR("Could not allocate queue out of memory");
|
||
|
DPLConnectionRelease(pdpLobbyObject,hConnect);
|
||
|
hResultCode = DPNERR_OUTOFMEMORY;
|
||
|
return(hResultCode);
|
||
|
}
|
||
|
|
||
|
hResultCode = pdplConnection->pSendQueue->Open(dwProcessId,
|
||
|
(fApplication) ? DPL_MSGQ_OBJECT_SUFFIX_APPLICATION : DPL_MSGQ_OBJECT_SUFFIX_CLIENT,
|
||
|
DPL_MSGQ_SIZE,
|
||
|
0, INFINITE);
|
||
|
if (hResultCode != DPN_OK)
|
||
|
{
|
||
|
DPFERR("Could not open message queue");
|
||
|
DisplayDNError(0,hResultCode);
|
||
|
delete pdplConnection->pSendQueue;
|
||
|
pdplConnection->pSendQueue = NULL;
|
||
|
DPLConnectionRelease(pdpLobbyObject,hConnect);
|
||
|
return(hResultCode);
|
||
|
}
|
||
|
|
||
|
// Ensure other side is still connected to MsgQ
|
||
|
if (!pdplConnection->pSendQueue->IsReceiving())
|
||
|
{
|
||
|
DPFERR("Application is not receiving");
|
||
|
pdplConnection->pSendQueue->Close();
|
||
|
delete pdplConnection->pSendQueue;
|
||
|
pdplConnection->pSendQueue = NULL;
|
||
|
DPLConnectionRelease(pdpLobbyObject,hConnect);
|
||
|
return(DPNERR_DOESNOTEXIST);
|
||
|
}
|
||
|
|
||
|
DPLConnectionRelease(pdpLobbyObject,hConnect);
|
||
|
|
||
|
return(hResultCode);
|
||
|
}
|
||
|
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "DPLConnectionDisconnect"
|
||
|
|
||
|
HRESULT DPLConnectionDisconnect(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
|
||
|
const DPNHANDLE hConnect )
|
||
|
{
|
||
|
HRESULT hResultCode;
|
||
|
DPL_CONNECTION *pdplConnection;
|
||
|
DPL_INTERNAL_MESSAGE_DISCONNECT Msg;
|
||
|
|
||
|
DPFX(DPFPREP, 3,"Parameters: hConnect [0x%lx]",hConnect);
|
||
|
|
||
|
DNASSERT(pdpLobbyObject != NULL);
|
||
|
DNASSERT(hConnect != NULL);
|
||
|
|
||
|
if ((hResultCode = DPLConnectionFind(pdpLobbyObject,hConnect,&pdplConnection,TRUE)) != DPN_OK)
|
||
|
{
|
||
|
DPFERR("Could not find connection");
|
||
|
DisplayDNError(0,hResultCode);
|
||
|
return(hResultCode);
|
||
|
}
|
||
|
|
||
|
Msg.dwMsgId = DPL_MSGID_INTERNAL_DISCONNECT;
|
||
|
Msg.dwPID = pdpLobbyObject->dwPID;
|
||
|
|
||
|
hResultCode = pdplConnection->pSendQueue->Send(reinterpret_cast<BYTE*>(&Msg),
|
||
|
sizeof(DPL_INTERNAL_MESSAGE_DISCONNECT),INFINITE,DPL_MSGQ_MSGFLAGS_USER1,0);
|
||
|
|
||
|
// Release the reference for the Find above
|
||
|
DPLConnectionRelease(pdpLobbyObject,hConnect);
|
||
|
|
||
|
// Release the interface's reference
|
||
|
DPLConnectionRelease(pdpLobbyObject,hConnect);
|
||
|
|
||
|
DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
|
||
|
return(hResultCode);
|
||
|
}
|
||
|
|
||
|
|
||
|
// DPLConnectionEnum
|
||
|
//
|
||
|
// Enumerate outstanding connections
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "DPLConnectionEnum"
|
||
|
|
||
|
HRESULT DPLConnectionEnum(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
|
||
|
DPNHANDLE *const prghConnect,
|
||
|
DWORD *const pdwNum)
|
||
|
{
|
||
|
HRESULT hResultCode;
|
||
|
HRESULT hr;
|
||
|
|
||
|
DPFX(DPFPREP, 3,"Parameters: prghConnect [0x%p], pdwNum [0x%p]",prghConnect,pdwNum);
|
||
|
|
||
|
hr = H_Enum(&pdpLobbyObject->hsHandles,pdwNum,prghConnect);
|
||
|
if (hr == S_OK)
|
||
|
{
|
||
|
hResultCode = DPN_OK;
|
||
|
}
|
||
|
else if (hr == E_POINTER)
|
||
|
{
|
||
|
hResultCode = DPNERR_BUFFERTOOSMALL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hResultCode = DPNERR_GENERIC;
|
||
|
}
|
||
|
|
||
|
DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
|
||
|
return(hResultCode);
|
||
|
}
|
||
|
|
||
|
|
||
|
// DPLConnectionSendREQ
|
||
|
//
|
||
|
// Send a request to connect to another process.
|
||
|
// We will provide the handle of the current Connection to the other side
|
||
|
// to send back as the SenderContext with messages to the local process
|
||
|
// so that we can easily lookup info.
|
||
|
// We will also provide the local PID so the other side can connect to us
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "DPLConnectionSendREQ"
|
||
|
|
||
|
HRESULT DPLConnectionSendREQ(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
|
||
|
const DPNHANDLE hConnect,
|
||
|
const DWORD dwPID,
|
||
|
DPL_CONNECT_INFO *const pInfo)
|
||
|
{
|
||
|
HRESULT hResultCode;
|
||
|
DPL_CONNECTION *pdplConnection;
|
||
|
DPL_INTERNAL_MESSAGE_CONNECT_REQ *pMsg = NULL;
|
||
|
DWORD dwSize;
|
||
|
CPackedBuffer PackedBuffer;
|
||
|
DWORD dwConnectSettingsSize;
|
||
|
CConnectionSettings *pConnectSettings = NULL;
|
||
|
PBYTE pbTmpBuffer = NULL;
|
||
|
|
||
|
DPFX(DPFPREP, 3,"Parameters: hConnect [0x%lx]",hConnect);
|
||
|
|
||
|
DNASSERT(pdpLobbyObject != NULL);
|
||
|
DNASSERT(hConnect != NULL);
|
||
|
|
||
|
if ((hResultCode = DPLConnectionFind(pdpLobbyObject,hConnect,&pdplConnection,TRUE)) != DPN_OK)
|
||
|
{
|
||
|
DPFERR("Could not find connection");
|
||
|
DisplayDNError(0,hResultCode);
|
||
|
return(hResultCode);
|
||
|
}
|
||
|
|
||
|
if (!pdplConnection->pSendQueue->IsReceiving())
|
||
|
{
|
||
|
DPFERR("Other side is not receiving");
|
||
|
DPLConnectionRelease(pdpLobbyObject,hConnect);
|
||
|
return(DPNERR_DOESNOTEXIST);
|
||
|
}
|
||
|
|
||
|
DNEnterCriticalSection( &pdplConnection->csLock );
|
||
|
|
||
|
if( pInfo->pdplConnectionSettings )
|
||
|
{
|
||
|
pConnectSettings = new CConnectionSettings();
|
||
|
|
||
|
if( !pConnectSettings )
|
||
|
{
|
||
|
DPFERR("Error allocating memory");
|
||
|
hResultCode = DPNERR_OUTOFMEMORY;
|
||
|
goto CONNECTREQ_EXIT;
|
||
|
}
|
||
|
|
||
|
hResultCode = pConnectSettings->InitializeAndCopy( pInfo->pdplConnectionSettings );
|
||
|
|
||
|
if( FAILED( hResultCode ) )
|
||
|
{
|
||
|
DPFX(DPFPREP, 0, "Error copying settings hr [0x%x]", hResultCode );
|
||
|
goto CONNECTREQ_EXIT;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
PackedBuffer.Initialize( NULL, 0 );
|
||
|
|
||
|
// Determine size of message to send.
|
||
|
PackedBuffer.AddToFront(NULL,sizeof(DPL_INTERNAL_MESSAGE_CONNECT_REQ_HEADER));
|
||
|
|
||
|
// Add connect settings if they exist
|
||
|
if( pInfo->pdplConnectionSettings )
|
||
|
pConnectSettings->BuildWireStruct(&PackedBuffer);
|
||
|
|
||
|
// Add lobby connect data
|
||
|
PackedBuffer.AddToBack(NULL,pInfo->dwLobbyConnectDataSize);
|
||
|
|
||
|
pbTmpBuffer = new BYTE[PackedBuffer.GetSizeRequired()];
|
||
|
|
||
|
if( !pbTmpBuffer )
|
||
|
{
|
||
|
DPFERR("Error allocating memory" );
|
||
|
hResultCode = DPNERR_OUTOFMEMORY;
|
||
|
goto CONNECTREQ_EXIT;
|
||
|
}
|
||
|
|
||
|
pMsg = (DPL_INTERNAL_MESSAGE_CONNECT_REQ *) pbTmpBuffer;
|
||
|
|
||
|
PackedBuffer.Initialize( pMsg, PackedBuffer.GetSizeRequired() );
|
||
|
|
||
|
hResultCode = PackedBuffer.AddToFront( pMsg, sizeof( DPL_INTERNAL_MESSAGE_CONNECT_REQ_HEADER ) );
|
||
|
|
||
|
if( FAILED( hResultCode ) )
|
||
|
{
|
||
|
DPFX( DPFPREP, 0, "Internal error! hr [0x%x]", hResultCode );
|
||
|
goto CONNECTREQ_EXIT;
|
||
|
}
|
||
|
|
||
|
pMsg->dwMsgId = DPL_MSGID_INTERNAL_CONNECT_REQ;
|
||
|
pMsg->hSender = hConnect;
|
||
|
pMsg->dwSenderPID = dwPID;
|
||
|
|
||
|
if( pInfo->pdplConnectionSettings )
|
||
|
{
|
||
|
hResultCode = pConnectSettings->BuildWireStruct(&PackedBuffer);
|
||
|
|
||
|
if( FAILED( hResultCode ) )
|
||
|
{
|
||
|
DPFX( DPFPREP, 0, "Error building wire struct for settings hr [0x%x]", hResultCode );
|
||
|
goto CONNECTREQ_EXIT;
|
||
|
}
|
||
|
|
||
|
pMsg->dwConnectionSettingsSize = 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pMsg->dwConnectionSettingsSize = 0;
|
||
|
}
|
||
|
|
||
|
hResultCode = PackedBuffer.AddToBack(pInfo->pvLobbyConnectData, pInfo->dwLobbyConnectDataSize, FALSE);
|
||
|
|
||
|
if( FAILED( hResultCode ) )
|
||
|
{
|
||
|
DPFX( DPFPREP, 0, "Error adding connect data hr [0x%x]", hResultCode );
|
||
|
goto CONNECTREQ_EXIT;
|
||
|
}
|
||
|
|
||
|
pMsg->dwLobbyConnectDataOffset = PackedBuffer.GetTailOffset();
|
||
|
pMsg->dwLobbyConnectDataSize = pInfo->dwLobbyConnectDataSize;
|
||
|
|
||
|
hResultCode = DPLConnectionSetConnectSettings( pdpLobbyObject, hConnect,pConnectSettings );
|
||
|
|
||
|
if( FAILED( hResultCode ) )
|
||
|
{
|
||
|
DPFERR( "Could not set local copy of connection settings" );
|
||
|
goto CONNECTREQ_EXIT;
|
||
|
}
|
||
|
|
||
|
hResultCode = pdplConnection->pSendQueue->Send(reinterpret_cast<BYTE*>(pMsg),
|
||
|
PackedBuffer.GetSizeRequired(),
|
||
|
INFINITE,
|
||
|
DPL_MSGQ_MSGFLAGS_USER1,
|
||
|
0);
|
||
|
if (hResultCode != DPN_OK)
|
||
|
{
|
||
|
DPFERR("Could not send connect info");
|
||
|
goto CONNECTREQ_EXIT;
|
||
|
}
|
||
|
|
||
|
CONNECTREQ_EXIT:
|
||
|
|
||
|
DNLeaveCriticalSection( &pdplConnection->csLock );
|
||
|
|
||
|
if( pbTmpBuffer )
|
||
|
delete [] pbTmpBuffer;
|
||
|
|
||
|
DPLConnectionRelease(pdpLobbyObject,hConnect);
|
||
|
|
||
|
DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
|
||
|
|
||
|
if( FAILED( hResultCode ) )
|
||
|
{
|
||
|
if( pConnectSettings )
|
||
|
delete pConnectSettings;
|
||
|
}
|
||
|
|
||
|
return(hResultCode);
|
||
|
}
|
||
|
|
||
|
|
||
|
// DPLConnectionReceiveREQ
|
||
|
//
|
||
|
// Receive a request to connect.
|
||
|
// Attempt to connect to the requesting process using the PID supplied.
|
||
|
// Keep the supplied SenderContext for future sends directed at that process.
|
||
|
// Send a connect acknowledge
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "DPLConnectionReceiveREQ"
|
||
|
|
||
|
HRESULT DPLConnectionReceiveREQ(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
|
||
|
BYTE *const pBuffer)
|
||
|
{
|
||
|
HRESULT hResultCode;
|
||
|
DPNHANDLE handle;
|
||
|
DPL_CONNECTION *pdplConnection;
|
||
|
DPL_INTERNAL_MESSAGE_CONNECT_REQ *pMsg;
|
||
|
DPL_MESSAGE_CONNECT MsgConnect;
|
||
|
DPL_CONNECTION_SETTINGS *pSettingsBuffer = NULL;
|
||
|
DWORD dwSettingsBufferSize = 0;
|
||
|
BOOL fLobbyLaunching = FALSE;
|
||
|
CConnectionSettings *pConnectSettings = NULL;
|
||
|
BYTE *pbTmpBuffer = NULL;
|
||
|
|
||
|
|
||
|
DPFX(DPFPREP, 3,"Parameters: pBuffer [0x%p]",pBuffer);
|
||
|
|
||
|
DNASSERT(pdpLobbyObject != NULL);
|
||
|
DNASSERT(pBuffer != NULL);
|
||
|
|
||
|
pMsg = reinterpret_cast<DPL_INTERNAL_MESSAGE_CONNECT_REQ*>(pBuffer);
|
||
|
|
||
|
if ((hResultCode = DPLConnectionNew(pdpLobbyObject,&handle,&pdplConnection)) != DPN_OK)
|
||
|
{
|
||
|
DPFERR("Could not create new connection");
|
||
|
DisplayDNError(0,hResultCode);
|
||
|
return(hResultCode);
|
||
|
}
|
||
|
|
||
|
if ((hResultCode = DPLConnectionConnect(pdpLobbyObject,handle,pMsg->dwSenderPID,FALSE)) != DPN_OK)
|
||
|
{
|
||
|
DPFERR("Could not perform requested connection");
|
||
|
goto CONNECTRECVREQ_ERROR;
|
||
|
}
|
||
|
|
||
|
pdplConnection->pSendQueue->SetSenderHandle(pMsg->hSender);
|
||
|
pdplConnection->dwTargetPID = pMsg->dwSenderPID;
|
||
|
|
||
|
if ((hResultCode = DPLConnectionSendACK(pdpLobbyObject,handle)) != DPN_OK)
|
||
|
{
|
||
|
DPFERR("Could not send connection acknowledge");
|
||
|
goto CONNECTRECVREQ_ERROR;
|
||
|
}
|
||
|
|
||
|
if( pdpLobbyObject->dwFlags & DPL_OBJECT_FLAG_MULTICONNECT)
|
||
|
{
|
||
|
DPFX(DPFPREP, 1, "Multiconnect flag specified, returning app to available status" );
|
||
|
pdpLobbyObject->pReceiveQueue->MakeAvailable();
|
||
|
}
|
||
|
|
||
|
if( pMsg->dwConnectionSettingsSize )
|
||
|
{
|
||
|
pConnectSettings = new CConnectionSettings();
|
||
|
|
||
|
if( !pConnectSettings )
|
||
|
{
|
||
|
DPFERR("Error allocating structure");
|
||
|
hResultCode = DPNERR_OUTOFMEMORY;
|
||
|
goto CONNECTRECVREQ_ERROR;
|
||
|
}
|
||
|
|
||
|
hResultCode = pConnectSettings->Initialize( &pMsg->dplConnectionSettings, (UNALIGNED BYTE *) pMsg );
|
||
|
|
||
|
if( FAILED( hResultCode ) )
|
||
|
{
|
||
|
DPFX( DPFPREP, 0, "Error copying connection settings from wire hr=[0x%x]", hResultCode );
|
||
|
goto CONNECTRECVREQ_ERROR;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Update the local connection settings
|
||
|
hResultCode = DPLConnectionSetConnectSettings( pdpLobbyObject, handle, pConnectSettings );
|
||
|
|
||
|
if( FAILED( hResultCode ) )
|
||
|
{
|
||
|
DPFX( DPFPREP, 0, "Error setting connection settings from wire hr=[0x%x]", hResultCode );
|
||
|
goto CONNECTRECVREQ_ERROR;
|
||
|
}
|
||
|
|
||
|
// Indicate connection to application
|
||
|
MsgConnect.dwSize = sizeof(DPL_MESSAGE_CONNECT);
|
||
|
MsgConnect.hConnectId = handle;
|
||
|
|
||
|
if( pMsg->dwLobbyConnectDataSize )
|
||
|
{
|
||
|
// Got to copy the connect data locally to an aligned buffer to ensure alignment -- ack
|
||
|
pbTmpBuffer = new BYTE[pMsg->dwLobbyConnectDataSize];
|
||
|
|
||
|
if( !pbTmpBuffer )
|
||
|
{
|
||
|
DPFERR("Error allocating structure");
|
||
|
hResultCode = DPNERR_OUTOFMEMORY;
|
||
|
goto CONNECTRECVREQ_ERROR;
|
||
|
}
|
||
|
|
||
|
memcpy( pbTmpBuffer, pBuffer + pMsg->dwLobbyConnectDataOffset, pMsg->dwLobbyConnectDataSize );
|
||
|
MsgConnect.pvLobbyConnectData = pbTmpBuffer;
|
||
|
MsgConnect.dwLobbyConnectDataSize = pMsg->dwLobbyConnectDataSize;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
MsgConnect.pvLobbyConnectData = NULL;
|
||
|
MsgConnect.dwLobbyConnectDataSize = 0;
|
||
|
}
|
||
|
|
||
|
MsgConnect.pvConnectionContext = NULL;
|
||
|
|
||
|
if( pConnectSettings )
|
||
|
{
|
||
|
MsgConnect.pdplConnectionSettings = pConnectSettings->GetConnectionSettings();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
MsgConnect.pdplConnectionSettings = NULL;
|
||
|
}
|
||
|
|
||
|
// If we're lobby launching set the connect event before calling the message handler
|
||
|
// otherwise we may encounter deadlock then timeout if user blocks in callback
|
||
|
if( pdpLobbyObject->dwFlags & DPL_OBJECT_FLAG_LOOKINGFORLOBBYLAUNCH )
|
||
|
{
|
||
|
fLobbyLaunching = TRUE;
|
||
|
pdpLobbyObject->dpnhLaunchedConnection = handle;
|
||
|
}
|
||
|
|
||
|
hResultCode = (pdpLobbyObject->pfnMessageHandler)(pdpLobbyObject->pvUserContext,
|
||
|
DPL_MSGID_CONNECT,
|
||
|
reinterpret_cast<BYTE*>(&MsgConnect));
|
||
|
|
||
|
if( FAILED( hResultCode ) )
|
||
|
{
|
||
|
DPFX( DPFPREP, 0, "Error returned from user's callback -- ignoring hr [0x%x]", hResultCode );
|
||
|
}
|
||
|
|
||
|
// Set the context for this connection
|
||
|
DPLConnectionSetContext( pdpLobbyObject, handle, MsgConnect.pvConnectionContext );
|
||
|
|
||
|
if( pbTmpBuffer )
|
||
|
delete [] pbTmpBuffer;
|
||
|
|
||
|
// If we're looking for a lobby launch, set the dpnhLaunchedConnection to cache the connection handle
|
||
|
SetEvent(pdpLobbyObject->hConnectEvent);
|
||
|
|
||
|
DPFX(DPFPREP, 3,"Returning: [0x%lx]",DPN_OK);
|
||
|
return(DPN_OK);
|
||
|
|
||
|
CONNECTRECVREQ_ERROR:
|
||
|
|
||
|
if( pbTmpBuffer )
|
||
|
delete [] pbTmpBuffer;
|
||
|
|
||
|
if( pConnectSettings )
|
||
|
delete pConnectSettings;
|
||
|
|
||
|
DPLConnectionDisconnect(pdpLobbyObject,handle);
|
||
|
DPLConnectionRelease(pdpLobbyObject,handle);
|
||
|
|
||
|
DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
|
||
|
|
||
|
return(hResultCode);
|
||
|
|
||
|
}
|
||
|
|
||
|
// DPLConnectionSendACK
|
||
|
//
|
||
|
// Send a connect acknowledge.
|
||
|
// Provide the local handle for the connection to the other side for future
|
||
|
// sends to the local process
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "DPLConnectionSendACK"
|
||
|
|
||
|
HRESULT DPLConnectionSendACK(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
|
||
|
const DPNHANDLE hConnect)
|
||
|
{
|
||
|
HRESULT hResultCode;
|
||
|
DPL_CONNECTION *pdplConnection;
|
||
|
DPL_INTERNAL_MESSAGE_CONNECT_ACK Msg;
|
||
|
|
||
|
DPFX(DPFPREP, 3,"Parameters: hConnect [0x%lx]",hConnect);
|
||
|
|
||
|
DNASSERT(pdpLobbyObject != NULL);
|
||
|
DNASSERT(hConnect != NULL);
|
||
|
|
||
|
if ((hResultCode = DPLConnectionFind(pdpLobbyObject,hConnect,&pdplConnection,TRUE)) != DPN_OK)
|
||
|
{
|
||
|
DPFERR("Could not find connection");
|
||
|
DisplayDNError(0,hResultCode);
|
||
|
return(hResultCode);
|
||
|
}
|
||
|
|
||
|
Msg.dwMsgId = DPL_MSGID_INTERNAL_CONNECT_ACK;
|
||
|
Msg.hSender = hConnect;
|
||
|
|
||
|
hResultCode = pdplConnection->pSendQueue->Send(reinterpret_cast<BYTE*>(&Msg),
|
||
|
sizeof(DPL_INTERNAL_MESSAGE_CONNECT_ACK),
|
||
|
INFINITE,
|
||
|
DPL_MSGQ_MSGFLAGS_USER1,
|
||
|
0);
|
||
|
if (hResultCode != DPN_OK)
|
||
|
{
|
||
|
DPFERR("Could not send connection acknowledge");
|
||
|
DisplayDNError(0,hResultCode);
|
||
|
DPLConnectionRelease(pdpLobbyObject,hConnect);
|
||
|
return(hResultCode);
|
||
|
}
|
||
|
|
||
|
DPLConnectionRelease(pdpLobbyObject,hConnect);
|
||
|
|
||
|
hResultCode = DPN_OK;
|
||
|
|
||
|
DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
|
||
|
return(hResultCode);
|
||
|
}
|
||
|
|
||
|
|
||
|
// DPLConnectionReceiveACK
|
||
|
//
|
||
|
// Receive a connect acknowledge
|
||
|
// Keep the supplied SenderContext for future sends directed at that process.
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "DPLConnectionReceiveACK"
|
||
|
|
||
|
HRESULT DPLConnectionReceiveACK(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
|
||
|
const DPNHANDLE hSender,
|
||
|
BYTE *const pBuffer)
|
||
|
{
|
||
|
HRESULT hResultCode;
|
||
|
DPL_CONNECTION *pdplConnection;
|
||
|
DPL_INTERNAL_MESSAGE_CONNECT_ACK *pMsg;
|
||
|
|
||
|
DPFX(DPFPREP, 3,"Parameters: hSender [0x%lx], pBuffer [0x%p]",hSender,pBuffer);
|
||
|
|
||
|
DNASSERT(pdpLobbyObject != NULL);
|
||
|
DNASSERT(pBuffer != NULL);
|
||
|
|
||
|
pMsg = reinterpret_cast<DPL_INTERNAL_MESSAGE_CONNECT_ACK*>(pBuffer);
|
||
|
|
||
|
if ((hResultCode = DPLConnectionFind(pdpLobbyObject,hSender,&pdplConnection,TRUE)) != DPN_OK)
|
||
|
{
|
||
|
DPFERR("Could not find sender's connection");
|
||
|
DisplayDNError(0,hResultCode);
|
||
|
return(hResultCode);
|
||
|
}
|
||
|
|
||
|
pdplConnection->pSendQueue->SetSenderHandle(pMsg->hSender);
|
||
|
|
||
|
SetEvent(pdplConnection->hConnectEvent);
|
||
|
|
||
|
DPLConnectionRelease(pdpLobbyObject,hSender);
|
||
|
|
||
|
// Indicate that a connection was made by setting event
|
||
|
SetEvent(pdpLobbyObject->hConnectEvent);
|
||
|
|
||
|
hResultCode = DPN_OK;
|
||
|
|
||
|
DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
|
||
|
return(hResultCode);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// DPLConnectionReceiveDisconnect
|
||
|
//
|
||
|
// Receive a disconnect
|
||
|
// Terminate the connection
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "DPLConnectionReceiveDisconnect"
|
||
|
|
||
|
HRESULT DPLConnectionReceiveDisconnect(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
|
||
|
const DPNHANDLE hSender,
|
||
|
BYTE *const pBuffer,
|
||
|
const HRESULT hrDisconnectReason )
|
||
|
{
|
||
|
HRESULT hResultCode;
|
||
|
DPL_CONNECTION *pdplConnection;
|
||
|
DPL_MESSAGE_DISCONNECT MsgDisconnect;
|
||
|
|
||
|
DPFX(DPFPREP, 3,"Parameters: hSender [0x%lx]",hSender);
|
||
|
|
||
|
DNASSERT(pdpLobbyObject != NULL);
|
||
|
|
||
|
if ((hResultCode = DPLConnectionFind(pdpLobbyObject,hSender,&pdplConnection,TRUE)) != DPN_OK)
|
||
|
{
|
||
|
DPFERR("Could not find sender's connection");
|
||
|
DisplayDNError(0,hResultCode);
|
||
|
return(hResultCode);
|
||
|
}
|
||
|
|
||
|
// Indicate disconnect to user
|
||
|
MsgDisconnect.dwSize = sizeof(DPL_MESSAGE_DISCONNECT);
|
||
|
MsgDisconnect.hDisconnectId = hSender;
|
||
|
MsgDisconnect.hrReason = hrDisconnectReason;
|
||
|
|
||
|
// Return code is irrelevant, at this point we're going to indicate regardless
|
||
|
hResultCode = DPLConnectionGetContext( pdpLobbyObject, hSender, &MsgDisconnect.pvConnectionContext );
|
||
|
|
||
|
if( FAILED( hResultCode ) )
|
||
|
{
|
||
|
DPFX(DPFPREP, 0, "Error getting connection context for 0x%x hr=0x%x", hSender, hResultCode );
|
||
|
}
|
||
|
|
||
|
hResultCode = (pdpLobbyObject->pfnMessageHandler)(pdpLobbyObject->pvUserContext,
|
||
|
DPL_MSGID_DISCONNECT,
|
||
|
reinterpret_cast<BYTE*>(&MsgDisconnect));
|
||
|
|
||
|
// Fixed memory leak, DPLConnectionRelease will free the send queue
|
||
|
// pdplConnection->pSendQueue->Close();
|
||
|
// pdplConnection->pSendQueue = NULL;
|
||
|
|
||
|
DPLConnectionRelease(pdpLobbyObject,hSender);
|
||
|
|
||
|
DPLConnectionRelease(pdpLobbyObject,hSender);
|
||
|
|
||
|
hResultCode = DPN_OK;
|
||
|
|
||
|
DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
|
||
|
return(hResultCode);
|
||
|
}
|