// // discodlg.cpp: disconnected dialog // // #include "stdafx.h" #define TRC_GROUP TRC_GROUP_UI #define TRC_FILE "disconnecteddlg" #include #include "discodlg.h" #include "sh.h" #include "contwnd.h" //For error code decoding #define DC_DEFINE_GLOBAL_ERROR_STRINGS 1 #include "tscerrs.h" // // Protocol errors // #include "rdperr.h" CDisconnectedDlg::CDisconnectedDlg( HWND hwndOwner, HINSTANCE hInst, CContainerWnd* pContWnd) : _pContWnd(pContWnd), _hInstance(hInst), _hwndOwner(hwndOwner) { DC_BEGIN_FN("CDisconnectedDlg"); TRC_ASSERT(_pContWnd, (TB,_T("_pContWnd not set\n"))); _disconnectReason = 0; _extendedDiscReason = exDiscReasonNoInfo; DC_END_FN(); } CDisconnectedDlg::~CDisconnectedDlg() { } #define MAX_DISCOMSG_LEN SH_DISCONNECT_RESOURCE_MAX_LENGTH*3 DCINT CDisconnectedDlg::DoModal() { DCINT retVal = 0; LPTSTR szOverallMsgString = NULL; INT_PTR rc = FALSE; DCUINT intRC; DC_BEGIN_FN("DoModal"); szOverallMsgString = (LPTSTR) LocalAlloc(LPTR, MAX_DISCOMSG_LEN*sizeof(TCHAR)); if (!szOverallMsgString) { return -1; } if (MapErrorToString(_hInstance, _disconnectReason, _extendedDiscReason, szOverallMsgString, MAX_DISCOMSG_LEN)) { TCHAR szDialogCaption[64]; intRC = LoadString(_hInstance, UI_IDS_DISCONNECTED_CAPTION, szDialogCaption, SIZECHAR(szDialogCaption)); if(0 == intRC) { TRC_SYSTEM_ERROR("LoadString"); TRC_ERR((TB, _T("Failed to load string ID:%u"), UI_IDS_DISCONNECTED_CAPTION)); szDialogCaption[0] = 0; } MessageBox( _hwndOwner, szOverallMsgString, szDialogCaption, #ifndef OS_WINCE MB_OK | MB_HELP | MB_ICONSTOP); #else MB_OK | MB_ICONSTOP); #endif // Do the cleanup. This is hackerific but has to happen // from here because the disconnect dialog could be initiated // in the context of the main dialog via a PostMessage // see comment in contwnd.cpp TRC_ASSERT(_pContWnd, (TB,_T("_pContWnd not set\n"))); if(_pContWnd) { _pContWnd->FinishDisconnect(); } } DC_END_FN(); if (szOverallMsgString) { LocalFree(szOverallMsgString); } return retVal; } //Returns error string for this message in szErrorMsg //szErrorMsg must be large enough to hold error string INT CDisconnectedDlg::MapErrorToString( HINSTANCE hInstance, INT disconnectReason, ExtendedDisconnectReasonCode extendedDisconnectReason, LPTSTR szErrorMsg, INT cchErrorMsgLen ) { UINT stringID = 0; UINT errorCode; int rc; TCHAR szDisconnectedString[SH_DISCONNECT_RESOURCE_MAX_LENGTH]; LPTSTR pszDebugErrorCodeText = _T(""); DC_BEGIN_FN("MapErrorToString"); TRC_NRM((TB, _T("Main disconnect reason code is:%u"), NL_GET_MAIN_REASON_CODE(disconnectReason))); TRC_ASSERT(szErrorMsg, (TB, _T("szErrorMsg is null"))); // // If extended disconnect reason is set we may // just be able to figure out the error right away // if(extendedDisconnectReason != exDiscReasonNoInfo) { switch(extendedDisconnectReason) { case exDiscReasonAPIInitiatedDisconnect: { //An RPC call on the server initiated the disconnect //most likely is that it was an admin tool that kicked //off the disconnect stringID = UI_IDS_DISCONNECT_REMOTE_BY_SERVER_TOOL; } break; case exDiscReasonAPIInitiatedLogoff: { //An RPC call on the server initiated the disconnect //most likely is that it was an admin tool that kicked //off the disconnect stringID = UI_IDS_LOGOFF_REMOTE_BY_SERVER; } break; case exDiscReasonServerIdleTimeout: { // Idle timeout expired on server stringID = UI_IDS_DISCONNECT_IDLE_TIMEOUT; } break; case exDiscReasonServerLogonTimeout: { // Total logon timeout expired on server stringID = UI_IDS_DISCONNECT_LOGON_TIMEOUT; } break; case exDiscReasonReplacedByOtherConnection: { TRC_NRM((TB, _T("Disconnected by other connection"))); stringID = UI_IDS_DISCONNECT_BYOTHERCONNECTION; } break; case exDiscReasonOutOfMemory: { // Server is out of memory stringID = UI_IDS_SERVER_OUT_OF_MEMORY; } break; case exDiscReasonServerDeniedConnection: { stringID = UI_IDS_SERVER_DENIED_CONNECTION; } break; case exDiscReasonServerDeniedConnectionFips: { stringID = UI_IDS_SERVER_DENIED_CONNECTION_FIPS; } break; case exDiscReasonLicenseInternal: { // Internal error in licensing protocol stringID = UI_IDS_LICENSE_INTERNAL; } break; case exDiscReasonLicenseNoLicenseServer: { // No license server available stringID = UI_IDS_LICENSE_NO_LICENSE_SERVER; } break; case exDiscReasonLicenseNoLicense: { // No license available for this client stringID = UI_IDS_LICENSE_NO_LICENSE; } break; case exDiscReasonLicenseErrClientMsg: { // Server got bad message from client stringID = UI_IDS_LICENSE_BAD_CLIENT_MSG; } break; case exDiscReasonLicenseHwidDoesntMatchLicense: { // HWID in license doesn't match the one sent stringID = UI_IDS_LICENSE_HWID_DOESNT_MATCH_LICENSE; } break; case exDiscReasonLicenseErrClientLicense: { // Server couldn't decode client license stringID = UI_IDS_LICENSE_BAD_CLIENT_LICENSE; } break; case exDiscReasonLicenseCantFinishProtocol: { // Server couldn't send final licensing packets stringID = UI_IDS_LICENSE_CANT_FINISH_PROTOCOL; } break; case exDiscReasonLicenseClientEndedProtocol: { // Client sent licensing error to server stringID = UI_IDS_LICENSE_CLIENT_ENDED_PROTOCOL; } break; case exDiscReasonLicenseErrClientEncryption: { // Server couldn't decrypt client message stringID = UI_IDS_LICENSE_BAD_CLIENT_ENCRYPTION; } break; case exDiscReasonLicenseCantUpgradeLicense: { // Client's license couldn't be upgraded stringID = UI_IDS_LICENSE_CANT_UPGRADE_LICENSE; } break; case exDiscReasonLicenseNoRemoteConnections: { // Server is in null mode - expired or not enough Per-CPU CALs stringID = UI_IDS_LICENSE_NO_REMOTE_CONNECTIONS; } break; default: { if(extendedDisconnectReason >= exDiscReasonProtocolRangeStart && extendedDisconnectReason <= exDiscReasonProtocolRangeEnd) { // // It's a protocol error detected (E.g rdpwd broke the link // because it detected an error). // // // For most of these we just return status codes, more common // ones get their own message // if (Log_RDP_ENC_DecryptFailed == (ULONG)(extendedDisconnectReason - exDiscReasonProtocolRangeStart)) { stringID = UI_IDS_SERVER_DECRYPTION_ERROR; } else { stringID = UI_IDS_PROTOCOL_ERROR_WITH_CODE; } } } break; } } // // If we still haven't got the string to load then // crack the error code to figure out which stringID to load // if(0 == stringID) { switch (NL_GET_MAIN_REASON_CODE(disconnectReason)) { case UI_DISCONNECT_ERROR: // ??08 { errorCode = NL_GET_ERR_CODE(disconnectReason); #ifdef DC_DEBUG // // Extra debugging info for this error // pszDebugErrorCodeText = (PDCTCHAR) uiUIErrorText[errorCode-1]; TRC_ALT((TB, _T("UI error occurred - cause:%#x '%s'"), errorCode, pszDebugErrorCodeText)); #endif /* DC_DEBUG */ switch (errorCode) { case UI_ERR_DISCONNECT_TIMEOUT: { TRC_NRM((TB, _T("Connection timed out"))); stringID = UI_IDS_CONNECTION_TIMEOUT; } break; case UI_ERR_GHBNFAILED: case UI_ERR_BADIPADDRESS: case UI_ERR_DNSLOOKUPFAILED: { TRC_NRM((TB, _T("Bad IP address"))); stringID = UI_IDS_BAD_SERVER_NAME; } break; case UI_ERR_ANSICONVERT: { TRC_NRM((TB, _T("An internal error has occurred."))); stringID = UI_IDS_ILLEGAL_SERVER_NAME; } break; case UI_ERR_NOTIMER: { /************************************************/ /* Failed to create a timer. */ /************************************************/ TRC_NRM((TB, _T("Failed to create a timer"))); stringID = UI_IDS_LOW_MEMORY; } break; case UI_ERR_LOOPBACK_CONSOLE_CONNECT: { TRC_NRM((TB, _T("Console loopback connect!!!"))); stringID = UI_IDS_CANNOT_LOOPBACK_CONNECT; } break; case UI_ERR_LICENSING_TIMEOUT: { TRC_NRM((TB, _T("Licensing timed out"))); stringID = UI_IDS_LICENSING_TIMEDOUT; } break; case UI_ERR_LICENSING_NEGOTIATION_FAIL: { TRC_NRM((TB, _T("Licensing negotiation failed"))); stringID = UI_IDS_LICENSING_NEGOT_FAILED; } break; case UI_ERR_DECOMPRESSION_FAILURE: { TRC_NRM((TB,_T("Client decompression failure"))); stringID = UI_IDS_CLIENT_DECOMPRESSION_FAILED; } break; case UI_ERR_UNEXPECTED_DISCONNECT: { TRC_NRM((TB,_T("Received 'UnexpectedDisconnect' code"))); stringID = UI_IDS_INTERNAL_ERROR; } break; default: { TRC_ABORT((TB, _T("Unrecognized UI error %#x"), errorCode)); stringID = UI_IDS_INTERNAL_ERROR; } break; } } break; case NL_DISCONNECT_REMOTE_BY_SERVER: // 0003 { //The server has remotely disconnected us TRC_NRM((TB, _T("Remote disconnection by server"))); //Unable to get more information stringID = UI_IDS_DISCONNECT_REMOTE_BY_SERVER; } break; case SL_DISCONNECT_ERROR: // ??06 { errorCode = NL_GET_ERR_CODE(disconnectReason); #ifdef DC_DEBUG /********************************************************/ /* Set up the error code text. */ /********************************************************/ pszDebugErrorCodeText = (PDCTCHAR) uiSLErrorText[errorCode-1]; TRC_ALT((TB, _T("SL error occurred - cause:%#x '%s'"), errorCode, pszDebugErrorCodeText)); #endif /* DC_DEBUG */ /********************************************************/ /* An SL error has occurred. Work out what the actual */ /* code is. */ /********************************************************/ switch (errorCode) { /****************************************************/ /* The following codes all map onto an "out of */ /* memory" string. */ /****************************************************/ case SL_ERR_NOMEMFORSENDUD: // 0106 case SL_ERR_NOMEMFORRECVUD: // 0206 case SL_ERR_NOMEMFORSECPACKET: // 0306 { TRC_NRM((TB, _T("Out of memory"))); stringID = UI_IDS_LOW_MEMORY; } break; /****************************************************/ /* The following codes all map onto a "security */ /* error" string. */ /****************************************************/ case SL_ERR_NOSECURITYUSERDATA: // 0406 case SL_ERR_INVALIDENCMETHOD: // 0506 case SL_ERR_INVALIDSRVRAND: // 0606 case SL_ERR_INVALIDSRVCERT: // 0706 case SL_ERR_GENSRVRANDFAILED: // 0806 case SL_ERR_MKSESSKEYFAILED: // 0906 case SL_ERR_ENCCLNTRANDFAILED: // 0A06 { TRC_NRM((TB, _T("Security error"))); stringID = UI_IDS_SECURITY_ERROR; } break; case SL_ERR_ENCRYPTFAILED: // 0B06 case SL_ERR_DECRYPTFAILED: // 0C06 { TRC_NRM((TB, _T("Encryption error"))); stringID = UI_IDS_ENCRYPTION_ERROR; } break; case SL_ERR_INVALIDPACKETFORMAT: // 0D06 { TRC_NRM((TB, _T("Invalid packet format"))); stringID = UI_IDS_PROTOCOL_ERROR; } break; case SL_ERR_INITFIPSFAILED: { TRC_NRM((TB, _T("Init FIPS encryption failed"))); stringID = UI_IDS_FIPS_ERROR; } break; default: { /************************************************/ /* Whoops - shouldn't get here. We should be */ /* capable of correctly decoding every error */ /* value. */ /************************************************/ TRC_ABORT((TB, _T("Unrecognized SL error code:%#x"), disconnectReason)); stringID = UI_IDS_INTERNAL_ERROR; } break; } } break; case NL_DISCONNECT_ERROR: // ??04 { #ifdef DC_DEBUG DCUINT lowByte; DCUINT highByte; #endif /* DC_DEBUG */ errorCode = NL_GET_ERR_CODE(disconnectReason); #ifdef DC_DEBUG /********************************************************/ /* Set up the error code text. */ /********************************************************/ highByte = errorCode >> 4; lowByte = (errorCode & 0xF) - 1; pszDebugErrorCodeText = (PDCTCHAR) uiNLErrorText[highByte][lowByte]; TRC_ALT((TB, _T("NL error occurred - cause:%u '%s'"), errorCode, pszDebugErrorCodeText)); #endif /* DC_DEBUG */ /********************************************************/ /* An NL error has occurred. Work out what the actual */ /* code is. */ /********************************************************/ switch (NL_GET_ERR_CODE(disconnectReason)) { /****************************************************/ /* The following codes all map onto a "bad IP */ /* address" string. */ /****************************************************/ case NL_ERR_TDDNSLOOKUPFAILED: // 0104 case NL_ERR_TDGHBNFAILED: // 0604 case NL_ERR_TDBADIPADDRESS: // 0804 { TRC_NRM((TB, _T("Bad IP address"))); stringID = UI_IDS_BAD_SERVER_NAME; } break; /****************************************************/ /* The following code maps onto a "connect failed" */ /* string. */ /****************************************************/ case NL_ERR_TDSKTCONNECTFAILED: // 0204 case NL_ERR_TDTIMEOUT: // 0704 case NL_ERR_NCATTACHUSERFAILED: // 3604 case NL_ERR_NCCHANNELJOINFAILED: // 3704 { TRC_NRM((TB, _T("Failed to establish a connection"))); stringID = UI_IDS_NOT_RESPONDING; } break; case NL_ERR_MCSNOUSERIDINAUC: // 2704 case NL_ERR_MCSNOCHANNELIDINCJC: // 2804 case NL_ERR_NCBADMCSRESULT: // 3104 case NL_ERR_NCNOUSERDATA: // 3304 case NL_ERR_NCINVALIDH221KEY: // 3404 case NL_ERR_NCNONETDATA: // 3504 case NL_ERR_NCJOINBADCHANNEL: // 3804 case NL_ERR_NCNOCOREDATA: // 3904 { TRC_NRM((TB, _T("Protocol Error"))); stringID = UI_IDS_CONNECT_FAILED_PROTOCOL; } break; /****************************************************/ /* The following codes all map onto a "network */ /* error has occurred" string. */ /****************************************************/ case NL_ERR_TDONCALLTOSEND: // 0304 case NL_ERR_TDONCALLTORECV: // 0404 { TRC_NRM((TB, _T("A network error has occurred"))); stringID = UI_IDS_NETWORK_ERROR; } break; case NL_ERR_XTBADTPKTVERSION: // 1104 case NL_ERR_XTBADHEADER: // 1204 case NL_ERR_XTUNEXPECTEDDATA: // 1304 case NL_ERR_MCSUNEXPECTEDPDU: // 2104 case NL_ERR_MCSNOTCRPDU: // 2204 case NL_ERR_MCSBADCRLENGTH: // 2304 case NL_ERR_MCSBADCRFIELDS: // 2404 case NL_ERR_MCSINVALIDPACKETFORMAT: // 2904 { TRC_NRM((TB, _T("A protocol error has occurred"))); stringID = UI_IDS_CLIENTSIDE_PROTOCOL_ERROR; } break; /****************************************************/ /* This code relates to an incompatible server */ /* version. */ /****************************************************/ case NL_ERR_MCSBADMCSREASON: // 2604 case NL_ERR_NCVERSIONMISMATCH: // 3A04 { TRC_NRM((TB, _T("Client/Server version mismatch"))); stringID = UI_IDS_VERSION_MISMATCH; } break; /****************************************************/ /* The following codes map onto an "illegal server */ /* name" string. */ /****************************************************/ case NL_ERR_TDANSICONVERT: // 0A04 { TRC_NRM((TB, _T("Couldn't convert name to ANSI"))); stringID = UI_IDS_ILLEGAL_SERVER_NAME; } break; case NL_ERR_TDFDCLOSE: // 0904 { TRC_NRM((TB, _T("Socket closed"))); stringID = UI_IDS_CONNECTION_BROKEN; } break; default: { /************************************************/ /* Woops - shouldn't get here. We should be */ /* capable of correctly decoding every error */ /* value. */ /************************************************/ TRC_ABORT((TB, _T("Unrecognized NL error code:%#x"), disconnectReason)); stringID = UI_IDS_INTERNAL_ERROR; } break; } } break; default: { /********************************************************/ /* Woops - shouldn't get here. We should be capable */ /* of correctly decoding every disconnection reason */ /* code. */ /********************************************************/ TRC_ABORT((TB, _T("Unexpected disconnect ID:%#x"), disconnectReason)); stringID = UI_IDS_INTERNAL_ERROR; } break; } } // // First of all get the textual version of the string - we have // just worked out which string we need to load. // rc = LoadString(hInstance, stringID, szDisconnectedString, SIZECHAR(szDisconnectedString)); if (0 == rc) { //Oops! Some problem with the resources. TRC_SYSTEM_ERROR("LoadString"); TRC_ERR((TB, _T("Failed to load string ID:%u"), stringID)); return FALSE; } if(UI_IDS_PROTOCOL_ERROR_WITH_CODE == stringID) { // // Need to add the specific protocol error // code to the string // DC_TSPRINTF(szErrorMsg, szDisconnectedString, extendedDisconnectReason); } else if (UI_IDS_CLIENTSIDE_PROTOCOL_ERROR == stringID) { // // Client side protocol error, add the appropriate // code to the string // DC_TSPRINTF(szErrorMsg, szDisconnectedString, disconnectReason); } else { // // Static error string (doesn't need codes appended) // _tcscpy(szErrorMsg, szDisconnectedString); } #ifdef DC_DEBUG // // In Check builds display the disconnect // codes as well as the debug disconnect reason string // TCHAR szDebugDisconnectInfo[128]; // Add the numerical reason code. _stprintf(szDebugDisconnectInfo, _T("DEBUG ONLY: Disconnect code: 0x%x - ") \ _T("Extended Disconnect code: 0x%x\n"), disconnectReason, extendedDisconnectReason); // // Add the error code text to the end of the string. // _tcscat(szErrorMsg, _T("\n\n")); _tcscat(szErrorMsg, szDebugDisconnectInfo); if (pszDebugErrorCodeText) { _tcscat(szErrorMsg, pszDebugErrorCodeText); } #endif DC_END_FN(); return TRUE; }