/****************************************************************************/ // ccfsm.cpp // // Call controller finite state machine code. // // Copyright (C) 1997-2000 Microsoft Corporation /****************************************************************************/ #include extern "C" { #define TRC_GROUP TRC_GROUP_CORE #define TRC_FILE "accfsm" #include #include #include } #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 */