|
|
/****************************************************************************/ // ccfsm.cpp
//
// Call controller finite state machine code.
//
// Copyright (C) 1997-2000 Microsoft Corporation
/****************************************************************************/
#include <adcg.h>
extern "C" { #define TRC_GROUP TRC_GROUP_CORE
#define TRC_FILE "accfsm"
#include <atrcapi.h>
#include <aver.h>
#include <winsock.h>
}
#include "cd.h"
#include "cc.h"
#include "aco.h"
#include "fs.h"
#include "ih.h"
#include "sl.h"
#include "wui.h"
#include "autil.h"
#include "or.h"
#include "uh.h"
#define REG_WINDOWS_KEY TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion")
/****************************************************************************/ // CCEnableShareRecvCmpnts
//
// Called after sending ConfirmActivePDU to server to activate receive-thread
// components.
/****************************************************************************/ inline void DCINTERNAL CCC::CCEnableShareRecvCmpnts(void) { DC_BEGIN_FN("CCEnableShareRecvCmpnts");
// The following components expect to be called in the receiver thread
// context - but we are in the sender thread context. Thus we need to
// decouple the calls to these functions.
// Note that we have to wait for completion of UH_Enable since it will
// prepare the bitmap cache capabilities for the ConfirmActivePDU.
TRC_NRM((TB, _T("Decoupling calls to CM/UH_Enable"))); _pCd->CD_DecoupleSyncNotification(CD_RCV_COMPONENT, _pCm, CD_NOTIFICATION_FUNC(CCM,CM_Enable), 0); _pCd->CD_DecoupleSyncNotification(CD_RCV_COMPONENT, _pUh, CD_NOTIFICATION_FUNC(CUH,UH_Enable), 0);
DC_END_FN(); } /* CCEnableShareRecvCmpnts */
/****************************************************************************/ // CCDisableShareRecvCmpnts
//
// Disables the recv-side share components. Called on receipt of a
// DisableAllPDU from the server. Note that although this is the end of a
// share, it may not be the end of the session, since if the server is
// reconnecting a DemandActivePDU will be sent soon after this.
/****************************************************************************/ inline void DCINTERNAL CCC::CCDisableShareRecvCmpnts(void) { DC_BEGIN_FN("CCDisableShareRecvCmpnts");
/************************************************************************/ /* The following components expect to be called in the receiver thread */ /* context - but we are in the sender thread context. Thus we need */ /* to decouple the calls to these functions. */ /************************************************************************/ TRC_NRM((TB, _T("Decoupling calls to CM/UH_Disable"))); _pCd->CD_DecoupleSyncNotification(CD_RCV_COMPONENT, _pCm, CD_NOTIFICATION_FUNC(CCM,CM_Disable), 0); _pCd->CD_DecoupleSyncNotification(CD_RCV_COMPONENT, _pUh, CD_NOTIFICATION_FUNC(CUH,UH_Disable), 0); DC_END_FN(); } /* CCDisableShareRecvCmpnts */
/****************************************************************************/ // CCDisconnectShareRecvCmpnts
//
// Disconnects the recv-side share components. Called on session end,
// indicates cleanup should occur.
/****************************************************************************/ inline void DCINTERNAL CCC::CCDisconnectShareRecvCmpnts(void) { DC_BEGIN_FN("CCDisableShareRecvCmpnts");
/************************************************************************/ /* The following components expect to be called in the receiver thread */ /* context - but we are in the sender thread context. Thus we need */ /* to decouple the calls to these functions. */ /************************************************************************/ TRC_NRM((TB, _T("Decoupling calls to CM/UH_Disable"))); _pCd->CD_DecoupleSyncNotification(CD_RCV_COMPONENT, _pCm, CD_NOTIFICATION_FUNC(CCM,CM_Disable), 0); _pCd->CD_DecoupleSyncNotification(CD_RCV_COMPONENT, _pUh, CD_NOTIFICATION_FUNC(CUH,UH_Disconnect), 0);
DC_END_FN(); } /* CCDisconnectShareRecvCmpnts */
/****************************************************************************/ // CCEnableShareSendCmpnts
//
// Enables the send-side share components. Called after sending
// ConfirmActivePDU (containing client capabilities) to the server.
/****************************************************************************/ inline void DCINTERNAL CCC::CCEnableShareSendCmpnts(void) { DC_BEGIN_FN("CCEnableShareSendCmpnts");
// The following components expect to be called in the sender thread
// context - which is the context we're currently in. So we can just
// call the functions directly.
TRC_NRM((TB, _T("Calling IH/FS/FC/OR_Enable"))); _pIh->IH_Enable();
// Enable fonts. This becomes an empty function now because we only
// send a zero font PDU from UH.
_pFs->FS_Enable();
// UH_Enable() is called when the DemandActivePDU is received, but the
// persistent bitmap cache keys need to be sent after the sync and control
// PDUs at this time. Call within the send thread context because that is
// where this code expects to be called.
// The PersistentKey PDUs have to be sent out before Font PDUs in the protocol.
// So font list is sent out from UH code after persistent keys.
_pUh->UH_SendPersistentKeysAndFontList();
_pOr->OR_Enable();
DC_END_FN(); } /* CCEnableShareSendCmpnts */
/****************************************************************************/ /* Name: CCDisableShareSendCmpnts */ /* */ /* Purpose: Disables the send-side share components. */ /****************************************************************************/ inline void DCINTERNAL CCC::CCDisableShareSendCmpnts(void) { DC_BEGIN_FN("CCDisableShareSendCmpnts");
// The following components expect to be called in the sender thread
// context - which is what we are in - so we can just call these
// functions directly.
TRC_NRM((TB, _T("Calling OR/IH/FC/FS_Disable"))); _pOr->OR_Disable(); _pIh->IH_Disable();
_pFs->FS_Disable();
DC_END_FN(); } /* CCDisableShareSendCmpnts */
/****************************************************************************/ /* CC FSM */ /* */ /* EVENTS STATES */ /* 0 CC_EVT_STARTCONNECT 0 CC_DISCONNECTED */ /* 1 CC_EVT_ONCONNECTOK 1 CC_CONNECTPENDING */ /* 2 CC_EVT_ONDEMANDACTIVE 2 CC_WAITINGFORDMNDACT */ /* 3 CC_EVT_SENTOK 3 CC_SENDINGCONFIRMACTIVEPDU1 */ /* 4 CC_EVT_ONBUFFERAVAILABLE 4 CC_SENDINGSYNCPDU1 */ /* 5 CC_EVT_ONDEACTIVATEALL 5 CC_SENDINGCOOPCONTROL */ /* 6 CC_EVT_DISCONNECT 6 CC_SENDINGGRANTCONTROL */ /* 7 CC_EVT_ONDISCONNECTED 7 CC_CONNECTED */ /* 8 CC_EVT_SHUTDOWN 8 CC_SENDING_SHUTDOWNPDU */ /* 9 CC_EVT_ONSHUTDOWNDENIED 9 CC_SENT_SHUTDOWNPDU */ /*10 CC_EVT_DISCONNECT_AND_EXIT 10 CC_PENDING_SHUTDOWN */ /* */ /* Stt | 0 1 2 3 4 5 6 7 8 9 10 */ /* ========================================================= */ /* Evt | */ /* 0 | 1A / / / / / / / / / / */ /* | */ /* 1 | - 2- / / / / / / / / - */ /* | */ /* 2 | - / 3B / / / / / / / - */ /* | */ /* 3 | / / / 4D 5G 6J 7K / 9- / / */ /* | */ /* 4 | - - - -C -F -I -J - -Z - - */ /* | */ /* 5 | - / / / / / / 2M 10P 10P - */ /* | */ /* 6 | - -P -P -P -P -P -P -P -P -P - */ /* | */ /* 7 | / 0Y 0Y 0Y 0Y 0Y 0Y 0Y 0T 0T 0T */ /* | */ /* 8 | -V 10P 10P 10P 10P 10P 10P 8Z - - - */ /* | */ /* 9 | - / / / / / / / / 7W - */ /* | */ /* 10 | -V 10P 10P 10P 10P 10P 10P 10P 10P 10P - */ /* */ /* '/' = illegal event/state combination */ /* '-' = no action */ /****************************************************************************/ const FSM_ENTRY ccFSM[CC_FSM_INPUTS][CC_FSM_STATES] = { /* CC_EVT_STARTCONNECT */ {{CC_CONNECTPENDING, ACT_A}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}},
/* CC_EVT_CONNECTOK */ {{CC_DISCONNECTED, ACT_NO}, {CC_WAITINGFORDEMANDACTIVE, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {CC_PENDING_SHUTDOWN, ACT_NO}},
/* CC_EVENT_DEMAND_ACTIVE */ {{CC_DISCONNECTED, ACT_NO}, {STATE_INVALID, ACT_NO}, {CC_SENDINGCONFIRMACTIVE1, ACT_B}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {CC_PENDING_SHUTDOWN, ACT_NO}},
/* CC_EVENT_SEND_OK */ {{STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {CC_SENDINGSYNC1, ACT_F}, {CC_SENDINGCOOPCONTROL, ACT_I}, {CC_SENDINGGRANTCONTROL, ACT_J}, {CC_CONNECTED, ACT_K}, {STATE_INVALID, ACT_NO}, {CC_SENT_SHUTDOWNPDU, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}},
/* CC_EVENT_BUFFER_AVAILABLE */ {{CC_DISCONNECTED, ACT_NO}, {CC_CONNECTPENDING, ACT_NO}, {CC_WAITINGFORDEMANDACTIVE, ACT_NO}, {CC_SENDINGCONFIRMACTIVE1, ACT_C}, {CC_SENDINGSYNC1, ACT_F}, {CC_SENDINGCOOPCONTROL, ACT_I}, {CC_SENDINGGRANTCONTROL, ACT_J}, {CC_CONNECTED, ACT_NO}, {CC_SENDING_SHUTDOWNPDU, ACT_Z}, {CC_SENT_SHUTDOWNPDU, ACT_NO}, {CC_PENDING_SHUTDOWN, ACT_NO}},
/* CC_EVENT_DEACTIVATEALL */ {{CC_DISCONNECTED, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {CC_WAITINGFORDEMANDACTIVE, ACT_M}, {CC_PENDING_SHUTDOWN, ACT_P}, {CC_PENDING_SHUTDOWN, ACT_P}, {CC_PENDING_SHUTDOWN, ACT_NO}},
/* CC_EVENT_DISCONNECT */ {{CC_DISCONNECTED, ACT_NO}, {CC_CONNECTPENDING, ACT_P}, {CC_WAITINGFORDEMANDACTIVE, ACT_P}, {CC_SENDINGCONFIRMACTIVE1, ACT_P}, {CC_SENDINGSYNC1, ACT_P}, {CC_SENDINGCOOPCONTROL, ACT_P}, {CC_SENDINGGRANTCONTROL, ACT_P}, {CC_CONNECTED, ACT_P}, {CC_SENDING_SHUTDOWNPDU, ACT_P}, {CC_SENT_SHUTDOWNPDU, ACT_P}, {CC_PENDING_SHUTDOWN, ACT_NO}},
/* CC_EVENT_ONDISCONNECTED */ {{STATE_INVALID, ACT_NO}, {CC_DISCONNECTED, ACT_Y}, {CC_DISCONNECTED, ACT_Y}, {CC_DISCONNECTED, ACT_Y}, {CC_DISCONNECTED, ACT_Y}, {CC_DISCONNECTED, ACT_Y}, {CC_DISCONNECTED, ACT_Y}, {CC_DISCONNECTED, ACT_Y}, {CC_DISCONNECTED, ACT_T}, {CC_DISCONNECTED, ACT_T}, {CC_DISCONNECTED, ACT_T}},
/* CC_EVENT_SHUTDOWN */ {{CC_DISCONNECTED, ACT_V}, {CC_PENDING_SHUTDOWN, ACT_P}, {CC_PENDING_SHUTDOWN, ACT_P}, {CC_PENDING_SHUTDOWN, ACT_P}, {CC_PENDING_SHUTDOWN, ACT_P}, {CC_PENDING_SHUTDOWN, ACT_P}, {CC_PENDING_SHUTDOWN, ACT_P}, {CC_SENDING_SHUTDOWNPDU, ACT_Z}, {CC_SENDING_SHUTDOWNPDU, ACT_NO}, {CC_SENT_SHUTDOWNPDU, ACT_NO}, {CC_PENDING_SHUTDOWN, ACT_NO}},
/* CC_EVENT_ON_SHUTDOWN_DENIED */ {{CC_DISCONNECTED, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {STATE_INVALID, ACT_NO}, {CC_CONNECTED, ACT_W}, {CC_PENDING_SHUTDOWN, ACT_NO}},
/* CC_EVENT_DISCONNECT_AND_EXIT */ {{CC_DISCONNECTED, ACT_V}, {CC_PENDING_SHUTDOWN, ACT_P}, {CC_PENDING_SHUTDOWN, ACT_P}, {CC_PENDING_SHUTDOWN, ACT_P}, {CC_PENDING_SHUTDOWN, ACT_P}, {CC_PENDING_SHUTDOWN, ACT_P}, {CC_PENDING_SHUTDOWN, ACT_P}, {CC_PENDING_SHUTDOWN, ACT_P}, {CC_PENDING_SHUTDOWN, ACT_P}, {CC_PENDING_SHUTDOWN, ACT_P}, {CC_PENDING_SHUTDOWN, ACT_NO}} };
/****************************************************************************/ // CCFSMProc
//
// Runs the CC finite state machine based on event inputs.
/****************************************************************************/ void DCINTERNAL CCC::CCFSMProc(unsigned event, ULONG_PTR data, DCUINT dataLen) { BOOL sendRc = TRUE; unsigned action = 0; PCONNECTSTRUCT pConnect; DCSIZE desktopSize; HRESULT hr;
DC_BEGIN_FN("CCFSMProc");
TRC_ASSERT(((0==data && 0==dataLen) || (0!=data && 0!=dataLen)), (TB, _T("data and dataLen should both be set or NULL")));
// Run the FSM.
EXECUTE_FSM(ccFSM, event, _CC.fsmState, action, eventString, stateString);
switch (action) { case ACT_A: { BYTE UserData[sizeof(RNS_UD_CS_CORE) + sizeof(TS_UD_CS_CLUSTER)]; RNS_UD_CS_CORE *pCoreData; TS_UD_CS_CLUSTER *pClusterData; TCHAR CompName[sizeof(pCoreData->clientName) / sizeof(UINT16)];
TRC_NRM((TB, _T("ACT_A: begin connection process")));
//
// Flag that safe checksum settings have not been set yet
// allowing them to be set on the first capabilities negotiation
// we don't allow them to be reconfigured as it's a per-link
// setting rather than something that needs to be reconfigured
// when shadowing.
//
_CC.fSafeChecksumSettingsSet = FALSE;
// We create here two different GCC user data sub-blocks (core
// and cluster). Memset the entire space and create sub-pointers
// for the individual parts.
memset(UserData, 0, sizeof(UserData)); pCoreData = (RNS_UD_CS_CORE *)UserData; pClusterData = (TS_UD_CS_CLUSTER *) (UserData + sizeof(RNS_UD_CS_CORE));
// Incomplete Connect - need to break out address.
pConnect = (PCONNECTSTRUCT)data; TRC_ASSERT((pConnect != NULL), (TB, _T("No connection data")));
// Start creating the core data.
pCoreData->header.type = RNS_UD_CS_CORE_ID; pCoreData->header.length = sizeof(RNS_UD_CS_CORE); pCoreData->version = RNS_UD_VERSION;
pCoreData->desktopWidth = pConnect->desktopWidth; pCoreData->desktopHeight = pConnect->desktopHeight;
//Indicate early support for error info PDU
//We can't do this during caps negotiation because
//that happens after licensing which could make use
//of this PDU.
//
pCoreData->earlyCapabilityFlags = RNS_UD_CS_SUPPORT_ERRINFO_PDU;
// Add desktop size to combined caps structure.
_ccCombinedCapabilities.bitmapCapabilitySet.desktopWidth = pConnect->desktopWidth; _ccCombinedCapabilities.bitmapCapabilitySet.desktopHeight = pConnect->desktopHeight;
// Pass the desktop size to UT.
desktopSize.width = pConnect->desktopWidth; desktopSize.height = pConnect->desktopHeight; _pUi->UI_SetDesktopSize(&desktopSize);
// Call UH_SetConnectOptions with the connect flags. This call
// must happen after the desktop size has been sent to UT.
// Make sure that we haven't set any flags in the high word, as
// these will get dropped if DCUINT is 16 bits.
TRC_ASSERT((0 == HIWORD(pConnect->connectFlags)), (TB, _T("Set flags in high word"))); _pCd->CD_DecoupleSimpleNotification(CD_RCV_COMPONENT, _pUh, CD_NOTIFICATION_FUNC(CUH,UH_SetConnectOptions), (ULONG_PTR)pConnect->connectFlags);
#ifdef DC_HICOLOR
pCoreData->colorDepth = RNS_UD_COLOR_8BPP;
// Set up the full hicolor support. We advertise support for
// all the depths we can manage; if we don't then get the depth
// the UI actually asked for, well, it can end the connection
// if it so chooses.
// Note that Win16 can only support 15bpp if running in a
// suitable screen mode.
pCoreData->supportedColorDepths = RNS_UD_15BPP_SUPPORT | RNS_UD_16BPP_SUPPORT | RNS_UD_24BPP_SUPPORT; #endif
switch (pConnect->colorDepthID) { // The Server supports both 4bpp & 8bpp Clients. However,
// a beta2 Server supported only 8bpp, and rejected Clients
// specifying 4bpp.
//
// Therefore, always set colorDepth (the beta2 field) to
// 8bpp, and set postBeta2ColorDepth (the new field) to the
// real value.
#ifndef DC_HICOLOR
// Always set preferredBitsPerPixel to 8, as that is the
// protocol color depth that we expect, irrespective of the
// display color depth.
#endif
case CO_BITSPERPEL4: #ifndef DC_HICOLOR
pCoreData->colorDepth = RNS_UD_COLOR_8BPP; #endif
pCoreData->postBeta2ColorDepth = RNS_UD_COLOR_4BPP; #ifdef DC_HICOLOR
pCoreData->highColorDepth = 4; #endif
_ccCombinedCapabilities.bitmapCapabilitySet .preferredBitsPerPixel = 8; _pUi->UI_SetColorDepth(4); break;
case CO_BITSPERPEL8: #ifndef DC_HICOLOR
pCoreData->colorDepth = RNS_UD_COLOR_8BPP; #endif
pCoreData->postBeta2ColorDepth = RNS_UD_COLOR_8BPP; #ifdef DC_HICOLOR
pCoreData->highColorDepth = 8; #endif
_ccCombinedCapabilities.bitmapCapabilitySet .preferredBitsPerPixel = 8; _pUi->UI_SetColorDepth(8); break;
#ifdef DC_HICOLOR
case CO_BITSPERPEL24: pCoreData->postBeta2ColorDepth = RNS_UD_COLOR_8BPP; pCoreData->highColorDepth = 24; _ccCombinedCapabilities.bitmapCapabilitySet. preferredBitsPerPixel = 24; _pUi->UI_SetColorDepth(24); break;
case CO_BITSPERPEL15: pCoreData->postBeta2ColorDepth = RNS_UD_COLOR_8BPP; pCoreData->highColorDepth = 15; _ccCombinedCapabilities.bitmapCapabilitySet. preferredBitsPerPixel = 15; _pUi->UI_SetColorDepth(15); break;
case CO_BITSPERPEL16: pCoreData->postBeta2ColorDepth = RNS_UD_COLOR_8BPP; pCoreData->highColorDepth = 16; _ccCombinedCapabilities.bitmapCapabilitySet. preferredBitsPerPixel = 16; _pUi->UI_SetColorDepth(16); break; #endif
default: TRC_ABORT((TB, _T("Unsupported color depth %d"), pConnect->colorDepthID)); break; }
// SAS sequence.
pCoreData->SASSequence = pConnect->sasSequence;
// The keyboard information is passed to the Server in both the
// userdata and the T.128 capabilites.
pCoreData->keyboardLayout = pConnect->keyboardLayout;
TRC_NRM((TB, _T("Set Caps kbdtype %#lx"), pCoreData->keyboardLayout)); _ccCombinedCapabilities.inputCapabilitySet.keyboardLayout = pCoreData->keyboardLayout;
// The keyboard sub type information is passed to the Server in
// both the userdata and the T.128 capabilites.
pCoreData->keyboardType = pConnect->keyboardType; pCoreData->keyboardSubType = pConnect->keyboardSubType; pCoreData->keyboardFunctionKey = pConnect->keyboardFunctionKey;
TRC_NRM((TB, _T("Set Caps kbd type %#lx sub type %#lx func key %#lx"), pCoreData->keyboardType, pCoreData->keyboardSubType, pCoreData->keyboardFunctionKey)); _ccCombinedCapabilities.inputCapabilitySet.keyboardType = pCoreData->keyboardType; _ccCombinedCapabilities.inputCapabilitySet.keyboardSubType = pCoreData->keyboardSubType; _ccCombinedCapabilities.inputCapabilitySet.keyboardFunctionKey = pCoreData->keyboardFunctionKey;
// The IME file name information is passed to the Server in
// both the userdata and the T.128 capabilites.
#ifdef UNICODE
hr = StringCchCopy(pCoreData->imeFileName, SIZE_TCHARS(pCoreData->imeFileName), pConnect->imeFileName); if (SUCCEEDED(hr)) { hr = StringCchCopy( _ccCombinedCapabilities.inputCapabilitySet.imeFileName, SIZE_TCHARS(_ccCombinedCapabilities.inputCapabilitySet.imeFileName), pCoreData->imeFileName); }
//
// Failure is not fatal just zero out the IME filenames
//
if (FAILED(hr)) { ZeroMemory(pCoreData->imeFileName, sizeof(pCoreData->imeFileName)); ZeroMemory( _ccCombinedCapabilities.inputCapabilitySet.imeFileName, sizeof(_ccCombinedCapabilities.inputCapabilitySet.imeFileName)); } #else
// Manually translate the character array into the Unicode buffer.
// ASCII only.
{ int i = 0; while (pConnect->imeFileName[i] && i < TS_MAX_IMEFILENAME) { pCoreData->imeFileName[i] = _ccCombinedCapabilities.inputCapabilitySet. imeFileName[i] = (UINT16)pConnect->imeFileName[i]; i++; } pCoreData->imeFileName[i] = 0; _ccCombinedCapabilities.inputCapabilitySet.imeFileName[i] = 0; } #endif
// Client build #.
pCoreData->clientBuild = DCVER_BUILD_NUMBER;
// Client computer name. gethostname() returns a full domain-
// type name which we need to parse to take only the machine
// name up to the first dot.
pCoreData->clientName[0] = 0;
//new core field added for beta3 Whistler
pCoreData->clientDigProductId[0] = 0; { //get the digital product id from the registry
HKEY hKey = NULL; if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_WINDOWS_KEY, 0, KEY_READ, &hKey) == ERROR_SUCCESS ) { //failure not fatal; we can use the computername in the worst case.
DWORD dwType = REG_SZ; DWORD dwSize = sizeof( pCoreData->clientDigProductId ); RegQueryValueEx( hKey, _T("ProductId"), NULL, &dwType, (LPBYTE)pCoreData->clientDigProductId, &dwSize ); if (hKey) RegCloseKey( hKey ); hKey = NULL; }
if (_pUt->UT_GetComputerName(CompName, sizeof(CompName) / sizeof(TCHAR))) { #ifdef UNICODE
TRC_NRM((TB, _T("Sending unicode client computername"))); hr = StringCchCopy(pCoreData->clientName, SIZE_TCHARS(pCoreData->clientName), CompName); if (FAILED(hr)) { TRC_ERR((TB,_T("Compname string copy failed: 0x%x"), hr)); } #else // UNICODE
#ifdef OS_WIN32
{ ULONG ulRetVal;
TRC_NRM((TB, _T("Translating and sending unicode client ") "computername"));
ulRetVal = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, CompName, -1, pCoreData->clientName, sizeof(pCoreData->clientName) / sizeof(pCoreData->clientName[0])); pCoreData->clientName[ulRetVal] = 0; } #else // !OS_WIN32
// Manually translate the character array into the
// Unicode buffer.
// This will only work for code page 1252, so
// non-latin Win3.11 clients that use non-Latin
// computer names will come as a random jumble of high
// ANSI characters. Fix this next time.
int i = 0; while (CompName[i]) { pCoreData->clientName[i] = (DCUINT16)CompName[i]; i++; } pCoreData->clientName[i] = 0; #endif // OS_WIN32
#endif // UNICODE
} }
// New core data fields added post Win2000 beta 3
pCoreData->clientProductId = 1; pCoreData->serialNumber = 0;
// Now set up the clustering data. We indicate that the client
// supports redirection (TS_SERVER_REDIRECT_PDU). If we are in the
// midst of a redirection, we set up the session ID fields.
pClusterData->header.type = TS_UD_CS_CLUSTER_ID; pClusterData->header.length = sizeof(TS_UD_CS_CLUSTER); pClusterData->Flags = TS_CLUSTER_REDIRECTION_SUPPORTED;
pClusterData->Flags &= ~TS_CLUSTER_REDIRECTION_VERSION; pClusterData->Flags |= TS_CLUSTER_REDIRECTION_VERSION4 << 2;
if(_pUi->UI_GetConnectToServerConsole()) { pClusterData->Flags |= TS_CLUSTER_REDIRECTED_SESSIONID_FIELD_VALID; //Console is session ID 0
pClusterData->RedirectedSessionID = 0; } else if (_pUi->UI_GetDoRedirection()) { // redirection for purposes other than connecting to console
// e.g load balancing
pClusterData->Flags |= TS_CLUSTER_REDIRECTED_SESSIONID_FIELD_VALID; pClusterData->RedirectedSessionID = _pUi->UI_GetRedirectionSessionID(); _pUi->UI_ClearDoRedirection(); }
if (_pUi->UI_GetUseSmartcardLogon()) { pClusterData->Flags |= TS_CLUSTER_REDIRECTED_SMARTCARD; }
_pSl->SL_Connect(pConnect->bInitiateConnect, pConnect->RNSAddress, pConnect->transportType, SL_PROTOCOL_T128, UserData, sizeof(RNS_UD_CS_CORE) + sizeof(TS_UD_CS_CLUSTER)); } break;
case ACT_B: { TRC_NRM((TB, _T("ACT_B: DemandActive - send ConfirmActive")));
/****************************************************************/ /* The server is requesting that we start a share. The last */ /* thing we do in this action is reply to the server with a */ /* confirm active and once the server receives it */ /* we are in a share as far as the server is concerned so now */ /* is the time to store connection information. Call */ /* CCShareStart to do this. */ /****************************************************************/ TRC_ASSERT((data != 0), (TB, _T("No data!"))); BOOL fUseSafeChecksum = FALSE; if (SUCCEEDED(CCShareStart((PTS_DEMAND_ACTIVE_PDU)data, dataLen, &fUseSafeChecksum))) { /****************************************************************/ // We also need to enable the share recv-side components at
// this time. This neds to be done on the receiver thread. Note
// that we don't enable the send-side components until we've sent
// all the sync/control PDUs to the server - this keeps things
// cleaner.
/****************************************************************/ CCEnableShareRecvCmpnts();
/****************************************************************/ /* Build and send Confirm active on low prioity */ /****************************************************************/ CCBuildShareHeaders();
TRC_NRM((TB,_T("Sending ConfirmActivePDU")));
if (!_CC.fSafeChecksumSettingsSet) { _pSl->SL_SetEncSafeChecksumSC(fUseSafeChecksum); }
CCSendPDU(CC_TYPE_CONFIRMACTIVE, CC_SEND_FLAGS_CONFIRM, TS_CA_NON_DATA_SIZE + TS_MAX_SOURCEDESCRIPTOR + sizeof(CC_COMBINED_CAPABILITIES), TS_LOWPRIORITY);
if (!_CC.fSafeChecksumSettingsSet) { //
// Notify SL, separate calls for send and recv thread to prevent
// races
//
_pCd->CD_DecoupleSimpleNotification( CD_SND_COMPONENT, _pSl, CD_NOTIFICATION_FUNC(CSL,SL_SetEncSafeChecksumCS), fUseSafeChecksum ); }
//
// Flag that checksum settings are set and don't allow
// them to be reset until the next connection
//
_CC.fSafeChecksumSettingsSet = TRUE;
/****************************************************************/ /* Inform the UI that we received DemandActivePDU. */ /****************************************************************/ _pCd->CD_DecoupleSyncNotification( CD_UI_COMPONENT, _pUi, CD_NOTIFICATION_FUNC(CUI,UI_OnDemandActivePDU), 0 ); } } break;
case ACT_C: { TRC_ALT((TB, _T("ACT_C: retry send of lowPri ConfirmActive")));
/****************************************************************/ /* Build and send Confirm active on low prioity */ /****************************************************************/ CCBuildShareHeaders();
CCSendPDU(CC_TYPE_CONFIRMACTIVE, CC_SEND_FLAGS_CONFIRM, TS_CA_NON_DATA_SIZE + TS_MAX_SOURCEDESCRIPTOR + sizeof(CC_COMBINED_CAPABILITIES), TS_LOWPRIORITY); } break;
case ACT_F: { TRC_NRM((TB, _T("ACT_F: Send synchronize PDU (1)"))); CCSendPDU(CC_TYPE_SYNCHRONIZE, CC_SEND_FLAGS_OTHER, TS_SYNC_PDU_SIZE, TS_LOWPRIORITY); } break;
case ACT_I: { TRC_NRM((TB, _T("ACT_I: Send co-operate control PDU"))); CCSendPDU(CC_TYPE_COOPCONTROL, CC_SEND_FLAGS_DATA, TS_CONTROL_PDU_SIZE, TS_MEDPRIORITY); } break;
case ACT_J: { TRC_NRM((TB, _T("ACT_J: Send request control PDU"))); CCSendPDU(CC_TYPE_REQUESTCONTROL, CC_SEND_FLAGS_DATA, TS_CONTROL_PDU_SIZE, TS_MEDPRIORITY); } break;
case ACT_K: { TRC_NRM((TB, _T("ACT_K: Share has been created - connection OK")));
/****************************************************************/ /* Enable the share send components. */ /****************************************************************/ CCEnableShareSendCmpnts();
/****************************************************************/ /* Inform the UI that the connection is now complete. */ /****************************************************************/ _pCd->CD_DecoupleSimpleNotification(CD_UI_COMPONENT, _pUi, CD_NOTIFICATION_FUNC(CUI,UI_OnConnected), (ULONG_PTR) 0); } break;
case ACT_M: { TRC_NRM((TB, _T("ACT_M: clearing up after share termination")));
/****************************************************************/ // The share has been terminated by the server so disable all
// the share components. Note that if the session is reconnected
// on the server we are not actually disconnecting since we could
// receive a DemandActivePDU and start the share again.
/****************************************************************/ CCDisableShareSendCmpnts(); CCDisableShareRecvCmpnts(); CCShareEnd();
/****************************************************************/ /* Inform the UI that we received DeactivateAllPDU. Do it */ /* synchronously so it's processed before any disconnection. */ /****************************************************************/ _pCd->CD_DecoupleSyncNotification(CD_UI_COMPONENT, _pUi, CD_NOTIFICATION_FUNC(CUI,UI_OnDeactivateAllPDU), 0);
} break;
case ACT_P: { /****************************************************************/ /* Disconnect */ /****************************************************************/ TRC_NRM((TB, _T("ACT_P: disconnect"))); _pSl->SL_Disconnect(); } break;
case ACT_T: { TRC_NRM((TB, _T("ACT_T: disable components and inform UI")));
/****************************************************************/ /* We need to disable all the share components. */ /****************************************************************/ CCDisableShareSendCmpnts(); CCDisconnectShareRecvCmpnts(); CCShareEnd();
/****************************************************************/ /* Reset the client MCS ID and the channel ID. */ /****************************************************************/ _pUi->UI_SetClientMCSID(0); _pUi->UI_SetChannelID(0);
/****************************************************************/ /* Inform UI that shutdown is OK */ /****************************************************************/ TRC_DBG((TB, _T("ACT_T: calling UI_OnShutDown(SUCCESS)"))); _pCd->CD_DecoupleSimpleNotification(CD_UI_COMPONENT, _pUi, CD_NOTIFICATION_FUNC(CUI,UI_OnShutDown), (ULONG_PTR) UI_SHUTDOWN_SUCCESS); } break;
case ACT_V: { TRC_NRM((TB, _T("ACT_V: calling UI_OnShutDown(success)")));
/****************************************************************/ /* Inform UI that shutdown is OK */ /****************************************************************/ _pCd->CD_DecoupleSimpleNotification(CD_UI_COMPONENT, _pUi, CD_NOTIFICATION_FUNC(CUI,UI_OnShutDown), (ULONG_PTR) UI_SHUTDOWN_SUCCESS); } break;
case ACT_W: { TRC_NRM((TB, _T("ACT_W: calling UI_OnShutDown(failure)")));
/****************************************************************/ /* Inform UI that shutdown has been denied */ /****************************************************************/ _pCd->CD_DecoupleSimpleNotification(CD_UI_COMPONENT, _pUi, CD_NOTIFICATION_FUNC(CUI,UI_OnShutDown), (ULONG_PTR) UI_SHUTDOWN_FAILURE); } break;
case ACT_Y: { TRC_NRM((TB, _T("ACT_Y: disconnection")));
/****************************************************************/ /* We need to disable all the share components. */ /****************************************************************/ CCDisableShareSendCmpnts(); CCDisconnectShareRecvCmpnts(); CCShareEnd();
/****************************************************************/ /* Connection has been lost, so we can safely reset the */ /* client MCS ID and the channel ID. */ /****************************************************************/ _pUi->UI_SetClientMCSID(0); _pUi->UI_SetChannelID(0);
/****************************************************************/ /* Pass the UI the disconnect reason code. This reason code */ /* should not occupy more than 16 bits. */ /****************************************************************/ TRC_ASSERT((HIWORD(data) == 0), (TB, _T("Disconnect reason code bigger then 16 bits %#x"), HIWORD(data)));
_pCd->CD_DecoupleSimpleNotification(CD_UI_COMPONENT, _pUi, CD_NOTIFICATION_FUNC(CUI,UI_OnDisconnected), data); } break;
case ACT_Z: { TRC_DBG((TB, _T("ACT_Z: sending ShutDownPDU")));
/****************************************************************/ /* Send Shutdown PDU */ /****************************************************************/ CCSendPDU(CC_TYPE_SHUTDOWNREQ, CC_SEND_FLAGS_DATA, TS_SHUTDOWN_REQ_PDU_SIZE, TS_HIGHPRIORITY); } break;
case ACT_NO: { TRC_NRM((TB, _T("ACT_NO: Doing nothing"))); } break;
default: { TRC_ABORT((TB, _T("Invalid action %u"), action)); } break; }
DC_END_FN(); } /* CC_FSMProc */
/****************************************************************************/ /* Name: CCBuildConfirmActive */ /* */ /* Purpose: Fills _CC.pBuffer and _CC.packetLen with a ConfirmActivePDU */ /* and its length */ /****************************************************************************/ void DCINTERNAL CCC::CCBuildConfirmActivePDU() { PTS_CONFIRM_ACTIVE_PDU pConfirmActivePDU; PBYTE pCombinedCapabilities;
DC_BEGIN_FN("CCBuildConfirmActivePDU");
pConfirmActivePDU = (PTS_CONFIRM_ACTIVE_PDU)_CC.pBuffer; pConfirmActivePDU->shareControlHeader = _CC.shareControlHeader;
pConfirmActivePDU->shareControlHeader.pduType = TS_PDUTYPE_CONFIRMACTIVEPDU | TS_PROTOCOL_VERSION; pConfirmActivePDU->shareID = _pUi->UI_GetShareID(); pConfirmActivePDU->originatorID = _pUi->UI_GetServerMCSID();
/************************************************************************/ /* Note: source descriptor is a NULL-terminated string. */ /************************************************************************/ pConfirmActivePDU->lengthSourceDescriptor = (DCUINT16) DC_ASTRBYTELEN(CC_DUCATI_NAME); pConfirmActivePDU->lengthCombinedCapabilities = sizeof(CC_COMBINED_CAPABILITIES);
TS_CTRLPKT_LEN(pConfirmActivePDU) = (DCUINT16)(pConfirmActivePDU->lengthSourceDescriptor + pConfirmActivePDU->lengthCombinedCapabilities + TS_CA_NON_DATA_SIZE); _CC.packetLen = TS_CTRLPKT_LEN(pConfirmActivePDU); TRC_ASSERT((CC_BUFSIZE >= _CC.packetLen), (TB,_T("CC Buffer not large enough")));
StringCbCopyA((PCHAR)pConfirmActivePDU->data, sizeof(pConfirmActivePDU->data), CC_DUCATI_NAME);
/************************************************************************/ /* Copy the Combined Caps. */ /************************************************************************/ pCombinedCapabilities = pConfirmActivePDU->data + DC_ASTRBYTELEN(CC_DUCATI_NAME);
DC_MEMCPY(pCombinedCapabilities, &_ccCombinedCapabilities, sizeof( CC_COMBINED_CAPABILITIES));
DC_END_FN(); } /* CCBuildConfirmActive */
/****************************************************************************/ /* Name: CCBuildSyncPDU */ /* */ /* Purpose: Fills _CC.pBuffer and _CC.packetLen with a SynchronizePDU */ /* and its length */ /****************************************************************************/ void DCINTERNAL CCC::CCBuildSyncPDU() { PTS_SYNCHRONIZE_PDU pSyncPDU;
DC_BEGIN_FN("CCBuildSyncPDU");
pSyncPDU = (PTS_SYNCHRONIZE_PDU) _CC.pBuffer; pSyncPDU->shareDataHeader = _CC.shareDataHeader;
_CC.packetLen = TS_SYNC_PDU_SIZE; TRC_ASSERT((CC_BUFSIZE >= _CC.packetLen), (TB,_T("CC Buffer not large enough")));
TS_DATAPKT_LEN(pSyncPDU) = TS_SYNC_PDU_SIZE; pSyncPDU->shareDataHeader.shareControlHeader.pduType = TS_PDUTYPE_DATAPDU | TS_PROTOCOL_VERSION; TS_UNCOMP_LEN(pSyncPDU) = TS_SYNC_UNCOMP_LEN; pSyncPDU->shareDataHeader.pduType2 = TS_PDUTYPE2_SYNCHRONIZE;
pSyncPDU->messageType = TS_SYNCMSGTYPE_SYNC; pSyncPDU->targetUser = _pUi->UI_GetServerMCSID();
DC_END_FN(); } /* CCBuildSync */
/****************************************************************************/ /* Name: CCBuildShutdownReqPDU */ /* */ /* Purpose: Fills _CC.pBuffer and _CC.packetLen with a ShutdownReqPDU */ /* and its length */ /****************************************************************************/ void DCINTERNAL CCC::CCBuildShutdownReqPDU() { PTS_SHUTDOWN_REQ_PDU pShutdownPDU;
DC_BEGIN_FN("CCBuildShutdownReqPDU");
pShutdownPDU = (PTS_SHUTDOWN_REQ_PDU) _CC.pBuffer; pShutdownPDU->shareDataHeader = _CC.shareDataHeader;
_CC.packetLen = TS_SHUTDOWN_REQ_PDU_SIZE; TRC_ASSERT((CC_BUFSIZE >= _CC.packetLen), (TB,_T("CC Buffer not large enough")));
TS_DATAPKT_LEN(pShutdownPDU) = TS_SHUTDOWN_REQ_PDU_SIZE; pShutdownPDU->shareDataHeader.shareControlHeader.pduType = TS_PDUTYPE_DATAPDU | TS_PROTOCOL_VERSION; TS_UNCOMP_LEN(pShutdownPDU) = TS_SHUTDOWN_REQ_UNCOMP_LEN; pShutdownPDU->shareDataHeader.pduType2 = TS_PDUTYPE2_SHUTDOWN_REQUEST;
DC_END_FN(); } /* CCBuildShutdownReqPDU */
/****************************************************************************/ /* Name: CCBuildCoopControlPDU */ /* */ /* Purpose: Fills _CC.pBuffer and _CC.packetLen with a CoopControlPDU */ /* and its length */ /****************************************************************************/ void DCINTERNAL CCC::CCBuildCoopControlPDU() { PTS_CONTROL_PDU pControlPDU;
DC_BEGIN_FN("CCBuildCoopControlPDU");
pControlPDU = (TS_CONTROL_PDU*) _CC.pBuffer; pControlPDU->shareDataHeader = _CC.shareDataHeader;
_CC.packetLen = TS_CONTROL_PDU_SIZE; TRC_ASSERT((CC_BUFSIZE >= _CC.packetLen),\ (TB,_T("CC Buffer not large enough")));
TS_DATAPKT_LEN(pControlPDU) = TS_CONTROL_PDU_SIZE; pControlPDU->shareDataHeader.shareControlHeader.pduType = TS_PDUTYPE_DATAPDU | TS_PROTOCOL_VERSION; TS_UNCOMP_LEN(pControlPDU) = TS_CONTROL_UNCOMP_LEN; pControlPDU->shareDataHeader.pduType2 = TS_PDUTYPE2_CONTROL;
pControlPDU->action = TS_CTRLACTION_COOPERATE; pControlPDU->grantId = 0; pControlPDU->controlId = 0;
DC_END_FN(); } /* CCBuildCoopControl */
/****************************************************************************/ /* Name: CCSendPDU */ /* */ /* Purpose: Fills and sends a specified PDU on agiven priority */ /****************************************************************************/ void DCINTERNAL CCC::CCSendPDU( unsigned pduTypeToSend, unsigned flags, unsigned size, unsigned priority) { SL_BUFHND bufHandle;
DC_BEGIN_FN("CCSendPDU");
if (!_pSl->SL_GetBuffer(size, &_CC.pBuffer, &bufHandle)) { // Buffer not available so can't send, try later.
TRC_ALT((TB, _T("Fail to get buffer for type %u"), pduTypeToSend)); DC_QUIT; }
switch (pduTypeToSend) { case CC_TYPE_CONFIRMACTIVE: { TRC_DBG((TB, _T("CCSendPDU handling Confirm Active PDU"))); CCBuildConfirmActivePDU(); } break;
case CC_TYPE_SYNCHRONIZE: { CCBuildSyncPDU(); } break;
case CC_TYPE_COOPCONTROL: { CCBuildCoopControlPDU(); } break;
case CC_TYPE_REQUESTCONTROL: { CCBuildRequestControlPDU(); } break;
case CC_TYPE_SHUTDOWNREQ: { CCBuildShutdownReqPDU(); } break;
default: { TRC_ABORT((TB,_T("Bad PDU type"))); } break; }
_pSl->SL_SendPacket(_CC.pBuffer, _CC.packetLen, flags, bufHandle, _pUi->UI_GetClientMCSID(), _pUi->UI_GetChannelID(), priority);
_CC.pBuffer = NULL;
CCFSMProc(CC_EVT_SENTOK, 0, 0);
DC_EXIT_POINT: DC_END_FN(); } /* CCSendPDU */
/****************************************************************************/ /* Name: CCBuildRequestControlPDU */ /* */ /* Purpose: Fills _CC.pBuffer and _CC.packetLen with a RequestControlPDU */ /* and its length */ /****************************************************************************/ void DCINTERNAL CCC::CCBuildRequestControlPDU() { TS_CONTROL_PDU * pControlPDU;
DC_BEGIN_FN("CCBuildRequestControlPDU");
pControlPDU = (PTS_CONTROL_PDU) _CC.pBuffer; pControlPDU->shareDataHeader = _CC.shareDataHeader;
_CC.packetLen = TS_CONTROL_PDU_SIZE; TRC_ASSERT((CC_BUFSIZE >= _CC.packetLen),\ (TB,_T("CC Buffer not large enough")));
pControlPDU->shareDataHeader.shareControlHeader.pduType = TS_PDUTYPE_DATAPDU | TS_PROTOCOL_VERSION; TS_DATAPKT_LEN(pControlPDU) = TS_CONTROL_PDU_SIZE; TS_UNCOMP_LEN(pControlPDU) = TS_CONTROL_UNCOMP_LEN; pControlPDU->shareDataHeader.pduType2 = TS_PDUTYPE2_CONTROL;
pControlPDU->action = TS_CTRLACTION_REQUEST_CONTROL; pControlPDU->grantId = 0; pControlPDU->controlId = 0;
DC_END_FN(); } /* CCBuildRequestControl */
/****************************************************************************/ /* Name: CCBuildShareHeaders */ /* */ /* Purpose: Fills in Core ShareControl and ShareData headers */ /****************************************************************************/ void DCINTERNAL CCC::CCBuildShareHeaders() { DC_BEGIN_FN("CCBuildShareHeaders");
_CC.shareControlHeader.totalLength = 0; /* sender sets this */ _CC.shareControlHeader.pduType = 0; /* sender sets this */ _CC.shareControlHeader.pduSource = _pUi->UI_GetClientMCSID();
_CC.shareDataHeader.shareControlHeader = _CC.shareControlHeader; _CC.shareDataHeader.shareID = _pUi->UI_GetShareID(); _CC.shareDataHeader.pad1 = 0; _CC.shareDataHeader.streamID = TS_STREAM_LOW; _CC.shareDataHeader.uncompressedLength = 0; /* sender sets this */ _CC.shareDataHeader.pduType2 = 0; /* sender sets this */ _CC.shareDataHeader.generalCompressedType = 0; _CC.shareDataHeader.generalCompressedLength= 0;
DC_END_FN(); } /* CCBuildShareHeaders */
/****************************************************************************/ /* Name: CCShareStart */ /* */ /* Purpose: Called when a share is established. */ /****************************************************************************/ HRESULT DCINTERNAL CCC::CCShareStart(PTS_DEMAND_ACTIVE_PDU pPDU, DCUINT dataLen, PBOOL pfSecureChecksum) { HRESULT hrc = S_OK; UINT32 sessionId; PTS_INPUT_CAPABILITYSET pInputCaps; PTS_ORDER_CAPABILITYSET pOrderCaps; DCSIZE desktopSize; PTS_BITMAP_CAPABILITYSET pBitmapCaps; PTS_VIRTUALCHANNEL_CAPABILITYSET pVCCaps = NULL; PTS_DRAW_GDIPLUS_CAPABILITYSET pDrawGdipCaps = NULL;
DC_BEGIN_FN("CCShareStart");
TRC_ASSERT((pPDU != NULL), (TB, _T("Null demand active PDU")));
/************************************************************************/ /* SECURITY: We verified that this PDU has at least enough data for the */ /* TS_DEMAND_ACTIVE_PDU struct in aco.cpp!CO_OnPacketReceived. */ /************************************************************************/
/************************************************************************/ /* Keep a copy of the server's share ID. */ /************************************************************************/ TRC_NRM((TB, _T("Save shareID %#x"), pPDU->shareID)); _pUi->UI_SetShareID(pPDU->shareID);
/************************************************************************/ /* Let UT know about the server's MCS user ID. */ /************************************************************************/ _pUi->UI_SetServerMCSID(pPDU->shareControlHeader.pduSource);
/************************************************************************/ /* Verify that the capabilities offset is within the PDU, and the cap */ /* length fits within the PDU. Throughout this function, UT_GetCapsSet */ /* is called with pointers to the caps and the caps length. */ /* */ /* Also, note that the last 4 bytes of this PDU can be the sessionId, */ /* but if someone's going to send the cap length as garbage, there's no */ /* reason to force the cap length to end 4 bytes before the packet end. */ /************************************************************************/ if (!IsContainedMemory(pPDU, dataLen, pPDU->data + pPDU->lengthSourceDescriptor, pPDU->lengthCombinedCapabilities)) { TRC_ABORT((TB, _T("Capabilities (%u) is larger than packet size"), pPDU->lengthCombinedCapabilities)); _pSl->SLSetReasonAndDisconnect(SL_ERR_INVALIDPACKETFORMAT); hrc = E_ABORT; DC_QUIT; }
PTS_GENERAL_CAPABILITYSET pGeneralCaps; pGeneralCaps = (PTS_GENERAL_CAPABILITYSET) _pUt->UT_GetCapsSet( pPDU->lengthCombinedCapabilities, (PTS_COMBINED_CAPABILITIES)(pPDU->data + pPDU->lengthSourceDescriptor), TS_CAPSETTYPE_GENERAL); TRC_ASSERT((pGeneralCaps != NULL),(TB,_T("General capabilities not found"))); //
// A word about the safe checksum fix:
// The feature is a fix to salt the checksum with a running counter
// The problem is that checksumming plaintext leaves us vulnerable
// to frequency analysis of the checksums (since input packets for the same
// scancode will return the same checksum).
//
// To negotiate caps for this encryption setting
// a handshake must occur where one side requests the feature and the other side
// ackownledges it before you can start encrypting in the new way. The packets
// also have a bit set in the security header identifying which type of checksum
// is in effect.
//
// If the server advertises support for receiving C->S newly checksummed data
// then acknowlege it here, this completes the handshake any further data
// transfers to the server will now checksum the encrypted bytes.
//
// Also the server can now start sending us data in the checksummed encrypted format
//
if (pGeneralCaps && pGeneralCaps->extraFlags & TS_ENC_SECURE_CHECKSUM) { _ccCombinedCapabilities.generalCapabilitySet.extraFlags |= TS_ENC_SECURE_CHECKSUM; *pfSecureChecksum = TRUE; } else { _ccCombinedCapabilities.generalCapabilitySet.extraFlags &= ~TS_ENC_SECURE_CHECKSUM; *pfSecureChecksum = FALSE; }
/************************************************************************/ /* If the call supports shadowing of sessions bigger than our current */ /* desktop size, then we'd better take note of the returned size */ /************************************************************************/ pBitmapCaps = (PTS_BITMAP_CAPABILITYSET) _pUt->UT_GetCapsSet( pPDU->lengthCombinedCapabilities, (PTS_COMBINED_CAPABILITIES)(pPDU->data + pPDU->lengthSourceDescriptor), TS_CAPSETTYPE_BITMAP); TRC_ASSERT((pBitmapCaps != NULL),(TB,_T("Bitmap capabilities not found"))); if (pBitmapCaps && pBitmapCaps->desktopResizeFlag == TS_CAPSFLAG_SUPPORTED) { TRC_ALT((TB, _T("New desktop size %u x %u"), pBitmapCaps->desktopWidth, pBitmapCaps->desktopHeight));
/********************************************************************/ /* Pass the desktop size to UT - it will be picked up in UH_Enable */ /********************************************************************/ desktopSize.width = pBitmapCaps->desktopWidth; desktopSize.height = pBitmapCaps->desktopHeight; _pUi->UI_OnDesktopSizeChange(&desktopSize);
/********************************************************************/ /* And notify the client */ /********************************************************************/ PostMessage(_pUi->UI_GetUIMainWindow(), WM_DESKTOPSIZECHANGE, 0, MAKELPARAM(desktopSize.width, desktopSize.height) ); }
#ifdef DC_HICOLOR
/************************************************************************/ /* Set up the returned color depth */ /************************************************************************/ if( pBitmapCaps ) { TRC_ALT((TB, _T("Server returned %u bpp"), pBitmapCaps->preferredBitsPerPixel)); _pUi->UI_SetColorDepth(pBitmapCaps->preferredBitsPerPixel); } #endif
/************************************************************************/ /* Pass the input capabilities to IH. */ /************************************************************************/ pInputCaps = (PTS_INPUT_CAPABILITYSET)_pUt->UT_GetCapsSet( pPDU->lengthCombinedCapabilities, (PTS_COMBINED_CAPABILITIES)(pPDU->data + pPDU->lengthSourceDescriptor), TS_CAPSETTYPE_INPUT); TRC_ASSERT((pInputCaps != NULL),(TB,_T("Input capabilities not found"))); if (pInputCaps != NULL) _pIh->IH_ProcessInputCaps(pInputCaps);
/************************************************************************/ /* The orders caps go to UH. */ /************************************************************************/ pOrderCaps = (PTS_ORDER_CAPABILITYSET)_pUt->UT_GetCapsSet( pPDU->lengthCombinedCapabilities, (PTS_COMBINED_CAPABILITIES)(pPDU->data + pPDU->lengthSourceDescriptor), TS_CAPSETTYPE_ORDER); TRC_ASSERT((pOrderCaps != NULL),(TB,_T("Order capabilities not found"))); if (pOrderCaps != NULL) _pUh->UH_ProcessServerCaps(pOrderCaps);
/************************************************************************/ // Send the bitmap cache HOSTSUPPORT caps to UH, whether or not present.
/************************************************************************/ _pUh->UH_ProcessBCHostSupportCaps( (PTS_BITMAPCACHE_CAPABILITYSET_HOSTSUPPORT)_pUt->UT_GetCapsSet( pPDU->lengthCombinedCapabilities, (PTS_COMBINED_CAPABILITIES)(pPDU->data + pPDU->lengthSourceDescriptor), TS_CAPSETTYPE_BITMAPCACHE_HOSTSUPPORT));
//
// Get virtual channel caps
//
pVCCaps = (PTS_VIRTUALCHANNEL_CAPABILITYSET)_pUt->UT_GetCapsSet( pPDU->lengthCombinedCapabilities, (PTS_COMBINED_CAPABILITIES)(pPDU->data + pPDU->lengthSourceDescriptor), TS_CAPSETTYPE_VIRTUALCHANNEL); if(pVCCaps) { //Inform VC layer of the capabilities
_pCChan->SetCapabilities(pVCCaps->vccaps1); } else { //No VCCaps, could be an older server. Set default caps
_pCChan->SetCapabilities(TS_VCCAPS_DEFAULT); }
//
// Get draw gdiplus caps
//
pDrawGdipCaps = (PTS_DRAW_GDIPLUS_CAPABILITYSET)_pUt->UT_GetCapsSet( pPDU->lengthCombinedCapabilities, (PTS_COMBINED_CAPABILITIES)(pPDU->data + pPDU->lengthSourceDescriptor), TS_CAPSETTYPE_DRAWGDIPLUS); if (pDrawGdipCaps) { _pUh->UH_SetServerGdipSupportLevel(pDrawGdipCaps->drawGdiplusSupportLevel); } else { _pUh->UH_SetServerGdipSupportLevel(TS_DRAW_GDIPLUS_DEFAULT); }
/************************************************************************/ /* Set SessionId */ /************************************************************************/ if (pPDU->shareControlHeader.totalLength > (sizeof(TS_DEMAND_ACTIVE_PDU) - 1 + pPDU->lengthSourceDescriptor + pPDU->lengthCombinedCapabilities)) { memcpy(&sessionId, pPDU->data + pPDU->lengthSourceDescriptor + pPDU->lengthCombinedCapabilities, sizeof(sessionId)); TRC_ALT((TB, _T("Session ID: %ld"), sessionId)); } else { sessionId = 0; TRC_ALT((TB, _T("Session ID is zero"), sessionId)); }
_pUi->UI_SetSessionId(sessionId);
DC_EXIT_POINT: DC_END_FN(); return(hrc); } /* CCShareStart */
/****************************************************************************/ /* Name: CCShareEnd */ /* */ /* Purpose: Called when a share ends. */ /****************************************************************************/ void DCINTERNAL CCC::CCShareEnd() { DC_BEGIN_FN("CCShareEnd");
// Reset ServerMCSID and ChannelID.
TRC_NRM((TB, _T("Resetting ServerMCSID and ChannelID"))); _pUi->UI_SetServerMCSID(0);
// Finally reset the share ID.
TRC_NRM((TB, _T("Resetting ShareID"))); _pUi->UI_SetShareID(0);
DC_END_FN(); } /* CCShareEnd */
|