Windows-Server-2003/termsrv/newclient/clshell/discodlg.cpp

742 lines
26 KiB
C++
Raw Permalink Normal View History

2024-08-04 01:28:15 +02:00
//
// discodlg.cpp: disconnected dialog
//
//
#include "stdafx.h"
#define TRC_GROUP TRC_GROUP_UI
#define TRC_FILE "disconnecteddlg"
#include <atrcapi.h>
#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;
}