windows-nt/Source/XPSP1/NT/termsrv/remdsk/rds/t120/mst120/events.cpp
2020-09-26 16:20:57 +08:00

550 lines
15 KiB
C++

#include "precomp.h"
#include "events.hpp"
#include "ernccm.hpp"
#include "erncconf.hpp"
#include "erncvrsn.hpp"
#include "nccglbl.hpp"
extern PController g_pMCSController;
CWorkItem::~CWorkItem(void) { } // pure virtual
BOOL GetSecurityInfo(ConnectionHandle connection_handle, PBYTE pInfo, PDWORD pcbInfo);
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Implementation of Methods for CInviteIndWork
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
CInviteIndWork::
CInviteIndWork
(
PCONFERENCE _pConference,
LPCWSTR _wszCallerID,
CLogicalConnection * _pConEntry
)
:
CWorkItem(_pConference),
m_pConf(_pConference),
m_fSecure(_pConEntry->IsConnectionSecure())
{
DebugEntry(CInviteIndWork::CInviteIndWork);
// Take copy of caller ID.
// Note memory allocation failure proceeds with NULL ID.
m_pwszCallerID = ::My_strdupW(_wszCallerID);
DebugExitVOID(CInviteIndWork::CInviteIndWork);
}
CInviteIndWork::
~CInviteIndWork(void)
{
DebugEntry(CInviteIndWork::~CInviteIndWork);
//
// If we substituted transport security data for roster data,
// free that buffer now
//
delete m_pwszCallerID;
DebugExitVOID(CInviteIndWork::~CInviteIndWork);
}
void CInviteIndWork::
DoWork(void)
{
DebugEntry(CInviteIndWork::DoWork);
// Now we are actually processing the invite, validate that there
// are no other conferences of the same name, and, if not, block
// a conference of the same name by setting the conference to be active,
// and give invite request up to the UI.
PCONFERENCE pOtherConf = g_pNCConfMgr->GetConferenceFromName(m_pConf->GetName());
if (NULL == pOtherConf)
{
m_pConf->SetNotifyToDo(TRUE);
g_pCallbackInterface->OnIncomingInviteRequest((CONF_HANDLE) m_pConf,
GetCallerID(),
m_fSecure);
}
else
{
m_pConf->InviteResponse(UI_RC_CONFERENCE_ALREADY_EXISTS);
}
DebugExitVOID(CInviteIndWork::DoWork);
}
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Implementation of Methods for CJoinIndWork
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
CJoinIndWork::
CJoinIndWork
(
GCCResponseTag Tag,
PCONFERENCE _pConference,
LPCWSTR _wszCallerID,
CLogicalConnection *_pConEntry,
HRESULT *pRetCode
)
:
CWorkItem(_pConference),
m_nResponseTag(Tag),
m_pConf(_pConference),
m_pConEntry(_pConEntry)
{
DebugEntry(CJoinIndWork::CJoinIndWork);
*pRetCode = NO_ERROR;
#ifdef DEBUG
SOCKET socket_number;
g_pMCSController->FindSocketNumber(m_pConEntry->GetConnectionHandle(),&socket_number);
#endif
// Take copy of caller ID because T120
// implementation is not keeping its copy valid
// until the join response.
// Note that memory allocation failure proceeds with
// NULL caller ID.
m_pwszCallerID = ::My_strdupW(_wszCallerID);
DebugExitVOID(CJoinIndWork::CJoinIndWork);
}
CJoinIndWork::
~CJoinIndWork(void)
{
DebugEntry(CJoinIndWork::~CJoinIndWork);
delete m_pwszCallerID;
DebugExitVOID(CJoinIndWork::~CJoinIndWork);
}
void CJoinIndWork::
DoWork(void)
{
DebugEntry(CJoinIndWork::DoWork);
// Notify the core.
g_pCallbackInterface->OnIncomingJoinRequest((CONF_HANDLE) m_pConf,
m_pwszCallerID);
DebugExitVOID(CJoinIndWork::DoWork);
}
HRESULT CJoinIndWork::
Respond ( GCCResult _Result )
{
DebugEntry(CJoinIndWork::Respond);
// It is a response from the core.
HRESULT hr = ::GCCJoinResponseWrapper(m_nResponseTag,
NULL,
_Result,
m_pConf->GetID(),
0, NULL);
DebugExitHRESULT(CJoinIndWork::Respond, hr);
return hr;
}
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Implementation of Methods for CSequentialWorkList
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void CSequentialWorkList::
AddWorkItem ( CWorkItem *pWorkItem )
{
DebugEntry(CSequentialWorkList::AddWorkItem);
Append(pWorkItem);
// If first entry in list, then kick off handler.
if (1 == GetCount())
{
pWorkItem->DoWork();
}
DebugExitVOID(CSequentialWorkList::AddWorkItem);
}
void CSequentialWorkList::
RemoveWorkItem ( CWorkItem *pWorkItem )
{
DebugEntry(CSequentialWorkList::RemoveWorkItem);
if (pWorkItem)
{
// Make a note as to whether we are going to remove the head
// work item in the list.
BOOL bHeadItemRemoved = (pWorkItem == PeekHead());
// Remove work item from list and destroy it.
if (Remove(pWorkItem))
{
delete pWorkItem;
// If there are more entries in the list, and we removed the
// first one, then start the work of the next one in line.
// Note that before doing this, the pointer to the workitem
// was NULLed out (above) to prevent reentracy problems.
if (bHeadItemRemoved && !IsEmpty())
{
PeekHead()->DoWork();
}
}
else
{
ASSERT(! bHeadItemRemoved);
}
}
DebugExitVOID(CSequentialWorkList::RemoveWorkItem);
}
void CSequentialWorkList::
PurgeListEntriesByOwner ( DCRNCConference *pOwner )
{
CWorkItem *pWorkItem;
DebugEntry(CSequentialWorkList::PurgeListEntriesByOwner);
if (NULL != pOwner)
{
// Note that head entry is removed last to stop work being started
// on other entries in the list that are owned by pOwner.
// Check to ensure there is a head item in the list.
if (NULL != (pWorkItem = PeekHead()))
{
// Remember we are going to remove the head.
BOOL fHeadToRemove = pWorkItem->IsOwnedBy(pOwner);
// Walk remaining entries in the list removing them.
BOOL fMoreToRemove;
do
{
fMoreToRemove = FALSE;
Reset();
while (NULL != (pWorkItem = Iterate()))
{
if (pWorkItem->IsOwnedBy(pOwner))
{
Remove(pWorkItem);
delete pWorkItem;
fMoreToRemove = TRUE;
break;
}
}
}
while (fMoreToRemove);
// Now done removing all entries, including the head if needed...
if (fHeadToRemove && ! IsEmpty())
{
PeekHead()->DoWork();
}
}
}
DebugExitVOID(CSequentialWorkList::PurgeListEntriesByOwner);
}
void CSequentialWorkList::
DeleteList(void)
{
CWorkItem *pWorkItem;
while (NULL != (pWorkItem = Get()))
{
delete pWorkItem;
}
}
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Implementation of Methods for CQueryRemoteWork
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
CQueryRemoteWork::
CQueryRemoteWork
(
LPVOID pCallerContext,
GCCAsymmetryType eAsymType,
LPCSTR pcszNodeAddress,
BOOL fSecure,
HRESULT *pRetCode
)
:
CWorkItem(pCallerContext),
m_hGCCConnHandle(NULL),
m_apConfNames(NULL),
m_fRemoteIsMCU(FALSE),
m_eAsymType(eAsymType),
m_fSecure(fSecure),
m_apConfDescriptors(NULL)
{
DebugEntry(CQueryRemoteWork::CQueryRemoteWork);
char szAddress[RNC_MAX_NODE_STRING_LEN];
::BuildAddressFromNodeDetails((LPSTR) pcszNodeAddress, &szAddress[0]);
m_pszAddress = ::My_strdupA(&szAddress[0]);
m_hr = (NULL != m_pszAddress) ? NO_ERROR : UI_RC_OUT_OF_MEMORY;
*pRetCode = m_hr;
DebugExitVOID(CQueryRemoteWork::CQueryRemoteWork);
}
CQueryRemoteWork::
~CQueryRemoteWork(void)
{
LPWSTR *ppTempTargetName;
LPWSTR *ppTempTargetDescriptor;
DebugEntry(CQueryRemoteWork::~CQueryRemoteWork);
// Clean up memory allocated.
if (m_apConfNames)
{
ppTempTargetName = m_apConfNames;
while (*ppTempTargetName)
{
delete *(ppTempTargetName++);
}
delete [] m_apConfNames;
}
if (m_apConfDescriptors)
{
ppTempTargetDescriptor = m_apConfDescriptors;
while (*ppTempTargetDescriptor)
{
delete *(ppTempTargetDescriptor++);
}
delete [] m_apConfDescriptors;
}
delete m_pszAddress;
DebugExitVOID(CQueryRemoteWork::~CQueryRemoteWork);
}
void CQueryRemoteWork::
DoWork(void)
{
GCCError GCCrc;
GCCNodeType nodeType;
GCCAsymmetryIndicator asymmetry_indicator;
DebugEntry(CQueryRemoteWork::DoWork);
::LoadAnnouncePresenceParameters(&nodeType, NULL, NULL, NULL);
asymmetry_indicator.asymmetry_type = m_eAsymType;
asymmetry_indicator.random_number = 0;
if (asymmetry_indicator.asymmetry_type == GCC_ASYMMETRY_UNKNOWN)
{
m_nRandSeed = (int) ::GetTickCount();
m_LocalAsymIndicator.random_number = ((GenerateRand() << 16) + GenerateRand());
asymmetry_indicator.random_number = m_LocalAsymIndicator.random_number;
m_LocalAsymIndicator.asymmetry_type = GCC_ASYMMETRY_UNKNOWN;
m_fInUnknownQueryRequest = TRUE;
}
GCCrc = g_pIT120ControlSap->ConfQueryRequest(
nodeType,
&asymmetry_indicator,
NULL,
(TransportAddress) m_pszAddress,
m_fSecure,
0,
NULL,
&m_hGCCConnHandle);
TRACE_OUT(("GCC call: g_pIT120ControlSap->ConfQueryRequest, rc=%d", GCCrc));
if (NO_ERROR != (m_hr = ::GetGCCRCDetails(GCCrc)))
{
AsyncQueryRemoteResult();
}
DebugExitHRESULT(CQueryRemoteWork::DoWork, m_hr);
}
void CQueryRemoteWork::
HandleQueryConfirmation ( QueryConfirmMessage * pQueryMessage )
{
UINT NumberOfConferences;
GCCConferenceDescriptor ** ppConferenceDescriptor;
PWSTR * ppTempTargetName;
PWSTR ConferenceTextName;
GCCConferenceName * pGCCConferenceName;
PWSTR * ppTempTargetDescriptor;
PWSTR pwszConfDescriptor=NULL;
HRESULT hrTmp;
DebugEntry(CQueryRemoteWork::HandleQueryConfirmation);
// If no error, then package up information.
m_hr = ::GetGCCResultDetails(pQueryMessage->result);
if (NO_ERROR == m_hr)
{
m_fRemoteIsMCU = (pQueryMessage->node_type == GCC_MCU);
NumberOfConferences = pQueryMessage->number_of_descriptors;
DBG_SAVE_FILE_LINE
m_apConfNames = new PWSTR[NumberOfConferences + 1];
m_apConfDescriptors = new PWSTR[NumberOfConferences + 1];
if (!m_apConfNames || !m_apConfDescriptors)
{
m_hr = UI_RC_OUT_OF_MEMORY;
}
else
{
ppConferenceDescriptor = pQueryMessage->conference_descriptor_list;
ppTempTargetName = m_apConfNames;
ppTempTargetDescriptor = m_apConfDescriptors;
while (NumberOfConferences--)
{
pwszConfDescriptor = (*(ppConferenceDescriptor))->conference_descriptor;
pGCCConferenceName = &(*(ppConferenceDescriptor++))->conference_name;
if (pwszConfDescriptor != NULL)
{
pwszConfDescriptor = ::My_strdupW(pwszConfDescriptor);
}
ConferenceTextName = pGCCConferenceName->text_string;
if (ConferenceTextName != NULL)
{
ConferenceTextName = ::My_strdupW(ConferenceTextName);
if (!ConferenceTextName)
{
// Out of memory, give back what we have.
m_hr = UI_RC_OUT_OF_MEMORY;
break;
}
}
else
if (pGCCConferenceName->numeric_string != NULL)
{
ConferenceTextName = ::AnsiToUnicode((PCSTR)pGCCConferenceName->numeric_string);
if (!ConferenceTextName)
{
// Out of memory, give back what we have.
m_hr = UI_RC_OUT_OF_MEMORY;
break;
}
}
if (ConferenceTextName)
{
*(ppTempTargetName++) = ConferenceTextName;
*(ppTempTargetDescriptor++) = pwszConfDescriptor;
}
}
*ppTempTargetName = NULL;
*ppTempTargetDescriptor = NULL;
}
}
m_fInUnknownQueryRequest = FALSE;
hrTmp = m_hr;
// Propagate the result directly without posting a message.
SyncQueryRemoteResult();
DebugExitHRESULT(CQueryRemoteWork::HandleQueryConfirmation, hrTmp);
}
void CQueryRemoteWork::
SyncQueryRemoteResult(void)
{
DebugEntry(CQueryRemoteWork::SyncQueryRemoteResult);
// Let the user know the result of his request.
// The user is expected to call Release() after getting the result,
// if he wants to drop the line - and should for errors.
// Also, if the user is being called back before the inline code
// has filled in the handle, then fill it in here - see comments in
// DCRNCConferenceManager::QueryRemote for additional background.
g_pCallbackInterface->OnQueryRemoteResult(
m_pOwner,
m_hr,
m_fRemoteIsMCU,
m_apConfNames,
m_apConfDescriptors);
// If we are not inline, and this request made it into
// the sequential work item list,
// then remove from list (which will cause item to be deleted),
// otherwise, just delete item.
g_pQueryRemoteList->RemoveWorkItem(this);
DebugExitVOID(CQueryRemoteWork::SyncQueryRemoteResult);
}
void CQueryRemoteWork::
AsyncQueryRemoteResult(void)
{
g_pNCConfMgr->PostWndMsg(NCMSG_QUERY_REMOTE_FAILURE, (LPARAM) this);
}
int CQueryRemoteWork::
GenerateRand(void)
{ // code from CRT
return (((m_nRandSeed = m_nRandSeed * 214013L + 2531011L) >> 16) & 0x7fff);
}
HRESULT CQueryRemoteWorkList::
Cancel ( LPVOID pCallerContext )
{
HRESULT hr = S_FALSE; // if not found
CQueryRemoteWork *p;
Reset();
while (NULL != (p = Iterate()))
{
if (p->IsOwnedBy(pCallerContext))
{
// clean up the underlying plumbing.
g_pIT120ControlSap->CancelConfQueryRequest(p->GetConnectionHandle());
// clean up node controller data.
RemoveWorkItem(p);
hr = S_OK;
break;
}
}
return hr;
}