multiple RDP issues fixed

- fix scale of RDP session when moving between 4k and 1080 monitors etc.
- fix inefficient continuous RDP screen resizing while the window size is changed
- add a RDP version check before attempting to use each RDP version and properties
This commit is contained in:
BlueBlock
2023-03-21 12:23:59 -04:00
parent 5cbf1f1568
commit b0a8ccc5b6
6 changed files with 952 additions and 59 deletions

View File

@@ -0,0 +1,867 @@
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Timers;
using System.Windows.Forms;
using AxMSTSCLib;
using mRemoteNG.App;
using mRemoteNG.Messages;
using mRemoteNG.Properties;
using mRemoteNG.Security.SymmetricEncryption;
using mRemoteNG.Tools;
using mRemoteNG.UI;
using mRemoteNG.UI.Forms;
using mRemoteNG.UI.Tabs;
using MSTSCLib;
using mRemoteNG.Resources.Language;
using System.Runtime.Versioning;
using FileDialog = Microsoft.Win32.FileDialog;
namespace mRemoteNG.Connection.Protocol.RDP
{
[SupportedOSPlatform("windows")]
public class RdpProtocol : ProtocolBase, ISupportsViewOnly
{
/* RDP v8 requires Windows 7 with:
* https://support.microsoft.com/en-us/kb/2592687
* OR
* https://support.microsoft.com/en-us/kb/2923545
*
* Windows 8+ support RDP v8 out of the box.
*/
private MsRdpClient6NotSafeForScripting _rdpClient; // lowest version supported
protected virtual RdpVersion RdpProtocolVersion => RDP.RdpVersion.Rdc6;
protected ConnectionInfo connectionInfo;
protected Version RdpVersion;
private readonly DisplayProperties _displayProperties;
protected readonly FrmMain _frmMain = FrmMain.Default;
protected bool loginComplete;
private bool _redirectKeys;
private bool _alertOnIdleDisconnect;
protected uint DesktopScaleFactor => (uint)(_displayProperties.ResolutionScalingFactor.Width * 100);
protected readonly uint DeviceScaleFactor = 100;
protected readonly uint Orientation = 0;
private AxHost AxHost => (AxHost)Control;
#region Properties
public virtual bool SmartSize
{
get => _rdpClient.AdvancedSettings2.SmartSizing;
protected set => _rdpClient.AdvancedSettings2.SmartSizing = value;
}
public virtual bool Fullscreen
{
get => _rdpClient.FullScreen;
protected set => _rdpClient.FullScreen = value;
}
private bool RedirectKeys
{
set
{
_redirectKeys = value;
try
{
if (!_redirectKeys)
{
return;
}
Debug.Assert(Convert.ToBoolean(_rdpClient.SecuredSettingsEnabled));
IMsRdpClientSecuredSettings msRdpClientSecuredSettings = _rdpClient.SecuredSettings2;
msRdpClientSecuredSettings.KeyboardHookMode = 1; // Apply key combinations at the remote server.
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionStackTrace(Language.RdpSetRedirectKeysFailed, ex);
}
}
}
public bool LoadBalanceInfoUseUtf8 { get; set; }
public bool ViewOnly
{
get => !AxHost.Enabled;
set => AxHost.Enabled = !value;
}
#endregion
#region Constructors
public RdpProtocol()
{
_displayProperties = new DisplayProperties();
tmrReconnect.Elapsed += tmrReconnect_Elapsed;
}
#endregion
#region Public Methods
protected virtual AxHost CreateActiveXRdpClientControl()
{
return new AxMsRdpClient6NotSafeForScripting();
}
public override bool Initialize()
{
connectionInfo = InterfaceControl.Info;
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, $"Requesting RDP version: {connectionInfo.RdpVersion}. Using: {RdpProtocolVersion}");
Control = CreateActiveXRdpClientControl();
base.Initialize();
try
{
if (!InitializeActiveXControl()) return false;
RdpVersion = new Version(_rdpClient.Version);
if (RdpVersion < Versions.RDC61) return false; // only RDP versions 6.1 and greater are supported; minimum dll version checked, MSTSCLIB is not capable
SetRdpClientProperties();
return true;
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionStackTrace(Language.RdpSetPropsFailed, ex);
return false;
}
}
private bool InitializeActiveXControl()
{
try
{
Control.GotFocus += RdpClient_GotFocus;
Control.CreateControl();
while (!Control.Created)
{
Thread.Sleep(50);
Application.DoEvents();
}
Control.Anchor = AnchorStyles.None;
_rdpClient = (MsRdpClient6NotSafeForScripting)((AxHost)Control).GetOcx();
return true;
}
catch (COMException ex)
{
if (ex.Message.Contains("CLASS_E_CLASSNOTAVAILABLE"))
{
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, string.Format(Language.RdpProtocolVersionNotSupported, connectionInfo.RdpVersion));
}
else
{
Runtime.MessageCollector.AddExceptionMessage(Language.RdpControlCreationFailed, ex);
}
Control.Dispose();
return false;
}
}
public override bool Connect()
{
loginComplete = false;
SetEventHandlers();
try
{
_rdpClient.Connect();
base.Connect();
return true;
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionStackTrace(Language.ConnectionOpenFailed, ex);
}
return false;
}
public override void Disconnect()
{
try
{
_rdpClient.Disconnect();
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionStackTrace(Language.RdpDisconnectFailed, ex);
Close();
}
}
public void ToggleFullscreen()
{
try
{
Fullscreen = !Fullscreen;
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionStackTrace(Language.RdpToggleFullscreenFailed, ex);
}
}
public void ToggleSmartSize()
{
try
{
SmartSize = !SmartSize;
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionStackTrace(Language.RdpToggleSmartSizeFailed, ex);
}
}
/// <summary>
/// Toggles whether the RDP ActiveX control will capture and send input events to the remote host.
/// The local host will continue to receive data from the remote host regardless of this setting.
/// </summary>
public void ToggleViewOnly()
{
try
{
ViewOnly = !ViewOnly;
}
catch
{
Runtime.MessageCollector.AddMessage(MessageClass.WarningMsg, $"Could not toggle view only mode for host {connectionInfo.Hostname}");
}
}
public override void Focus()
{
try
{
if (Control.ContainsFocus == false)
{
Control.Focus();
}
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionStackTrace(Language.RdpFocusFailed, ex);
}
}
/// <summary>
/// Determines if this version of the RDP client
/// is supported on this machine.
/// </summary>
/// <returns></returns>
public bool RdpVersionSupported()
{
try
{
using var control = CreateActiveXRdpClientControl();
control.CreateControl();
return true;
}
catch
{
return false;
}
}
#endregion
#region Private Methods
protected static class Versions
{
// https://en.wikipedia.org/wiki/Remote_Desktop_Protocol
public static readonly Version RDC60 = new Version(6, 0, 6000);
public static readonly Version RDC61 = new Version(6, 0, 6001);
public static readonly Version RDC70 = new Version(6, 1, 7600);
public static readonly Version RDC80 = new Version(6, 2, 9200);
public static readonly Version RDC81 = new Version(6, 3, 9600);
public static readonly Version RDC100 = new Version(10, 0, 0);
}
private void SetRdpClientProperties()
{
// https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/clients/rdp-files
_rdpClient.Server = connectionInfo.Hostname;
SetCredentials();
SetResolution();
_rdpClient.FullScreenTitle = connectionInfo.Name;
_alertOnIdleDisconnect = connectionInfo.RDPAlertIdleTimeout;
_rdpClient.AdvancedSettings2.MinutesToIdleTimeout = connectionInfo.RDPMinutesToIdleTimeout;
#region Remote Desktop Services
_rdpClient.SecuredSettings2.StartProgram = connectionInfo.RDPStartProgram;
_rdpClient.SecuredSettings2.WorkDir = connectionInfo.RDPStartProgramWorkDir;
#endregion
//not user changeable
_rdpClient.AdvancedSettings2.GrabFocusOnConnect = true;
_rdpClient.AdvancedSettings3.EnableAutoReconnect = true;
_rdpClient.AdvancedSettings3.MaxReconnectAttempts = Settings.Default.RdpReconnectionCount;
_rdpClient.AdvancedSettings2.keepAliveInterval = 60000; //in milliseconds (10,000 = 10 seconds)
_rdpClient.AdvancedSettings5.AuthenticationLevel = 0;
_rdpClient.AdvancedSettings2.EncryptionEnabled = 1;
_rdpClient.AdvancedSettings2.overallConnectionTimeout = Settings.Default.ConRDPOverallConnectionTimeout;
_rdpClient.AdvancedSettings2.BitmapPeristence = Convert.ToInt32(connectionInfo.CacheBitmaps);
if (RdpVersion >= Versions.RDC61)
{
_rdpClient.AdvancedSettings7.EnableCredSspSupport = connectionInfo.UseCredSsp;
}
SetUseConsoleSession();
SetPort();
RedirectKeys = connectionInfo.RedirectKeys;
SetRedirection();
SetAuthenticationLevel();
SetLoadBalanceInfo();
SetRdGateway();
ViewOnly = Force.HasFlag(ConnectionInfo.Force.ViewOnly);
_rdpClient.ColorDepth = (int)connectionInfo.Colors;
SetPerformanceFlags();
_rdpClient.ConnectingText = Language.Connecting;
}
protected object GetExtendedProperty(string property)
{
try
{
// ReSharper disable once UseIndexedProperty
return ((IMsRdpExtendedSettings)_rdpClient).get_Property(property);
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionMessage($"Error getting extended RDP property '{property}'", ex, MessageClass.WarningMsg, false);
return null;
}
}
protected void SetExtendedProperty(string property, object value)
{
try
{
// ReSharper disable once UseIndexedProperty
((IMsRdpExtendedSettings)_rdpClient).set_Property(property, ref value);
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionMessage($"Error setting extended RDP property '{property}'", ex, MessageClass.WarningMsg, false);
}
}
private void SetRdGateway()
{
try
{
if (_rdpClient.TransportSettings.GatewayIsSupported == 0)
{
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, Language.RdpGatewayNotSupported, true);
return;
}
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, Language.RdpGatewayIsSupported, true);
if (connectionInfo.RDGatewayUsageMethod == RDGatewayUsageMethod.Never) return;
// USE GATEWAY
_rdpClient.TransportSettings.GatewayUsageMethod = (uint)connectionInfo.RDGatewayUsageMethod;
_rdpClient.TransportSettings.GatewayHostname = connectionInfo.RDGatewayHostname;
_rdpClient.TransportSettings.GatewayProfileUsageMethod = 1; // TSC_PROXY_PROFILE_MODE_EXPLICIT
if (connectionInfo.RDGatewayUseConnectionCredentials == RDGatewayUseConnectionCredentials.SmartCard)
{
_rdpClient.TransportSettings.GatewayCredsSource = 1; // TSC_PROXY_CREDS_MODE_SMARTCARD
}
if (RdpVersion < Versions.RDC61 || Force.HasFlag(ConnectionInfo.Force.NoCredentials)) return;
switch (connectionInfo.RDGatewayUseConnectionCredentials)
{
case RDGatewayUseConnectionCredentials.Yes:
_rdpClient.TransportSettings2.GatewayUsername = connectionInfo.Username;
_rdpClient.TransportSettings2.GatewayPassword = connectionInfo.Password;
_rdpClient.TransportSettings2.GatewayDomain = connectionInfo?.Domain;
break;
case RDGatewayUseConnectionCredentials.SmartCard:
_rdpClient.TransportSettings2.GatewayCredSharing = 0;
break;
default:
{
_rdpClient.TransportSettings2.GatewayCredSharing = 0;
var gwu = connectionInfo.RDGatewayUsername;
var gwp = connectionInfo.RDGatewayPassword;
var gwd = connectionInfo.RDGatewayDomain;
var pkey = "";
// access secret server api if necessary
if (InterfaceControl.Info.RDGatewayExternalCredentialProvider == ExternalCredentialProvider.DelineaSecretServer)
{
try
{
string RDGUserViaAPI = InterfaceControl.Info.RDGatewayUserViaAPI;
ExternalConnectors.DSS.SecretServerInterface.FetchSecretFromServer($"{RDGUserViaAPI}", out gwu, out gwp, out gwd, out pkey);
}
catch (Exception ex)
{
Event_ErrorOccured(this, "Secret Server Interface Error: " + ex.Message, 0);
}
}
_rdpClient.TransportSettings2.GatewayUsername = gwu;
_rdpClient.TransportSettings2.GatewayPassword = gwp;
_rdpClient.TransportSettings2.GatewayDomain = gwd;
break;
}
}
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionStackTrace(Language.RdpSetGatewayFailed, ex);
}
}
private void SetUseConsoleSession()
{
try
{
bool value;
if (Force.HasFlag(ConnectionInfo.Force.UseConsoleSession))
{
value = true;
}
else if (Force.HasFlag(ConnectionInfo.Force.DontUseConsoleSession))
{
value = false;
}
else
{
value = connectionInfo.UseConsoleSession;
}
if (RdpVersion >= Versions.RDC61)
{
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, string.Format(Language.RdpSetConsoleSwitch, RdpVersion), true);
_rdpClient.AdvancedSettings7.ConnectToAdministerServer = value;
}
else
{
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, $"{string.Format(Language.RdpSetConsoleSwitch, RdpVersion)}{Environment.NewLine}No longer supported in this RDP version. Reference: https://msdn.microsoft.com/en-us/library/aa380863(v=vs.85).aspx", true);
// ConnectToServerConsole is deprecated
//https://msdn.microsoft.com/en-us/library/aa380863(v=vs.85).aspx
//_rdpClient.AdvancedSettings2.ConnectToServerConsole = value;
}
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionStackTrace(Language.RdpSetConsoleSessionFailed, ex);
}
}
private void SetCredentials()
{
try
{
if (Force.HasFlag(ConnectionInfo.Force.NoCredentials))
{
return;
}
var userName = connectionInfo?.Username ?? "";
var password = connectionInfo?.Password ?? "";
var domain = connectionInfo?.Domain ?? "";
var userViaApi = connectionInfo?.UserViaAPI ?? "";
var pkey = "";
// access secret server api if necessary
if (InterfaceControl.Info.ExternalCredentialProvider == ExternalCredentialProvider.DelineaSecretServer)
{
try
{
ExternalConnectors.DSS.SecretServerInterface.FetchSecretFromServer($"{userViaApi}", out userName, out password, out domain, out pkey);
}
catch (Exception ex)
{
Event_ErrorOccured(this, "Secret Server Interface Error: " + ex.Message, 0);
}
}
if (string.IsNullOrEmpty(userName))
{
switch (Properties.OptionsCredentialsPage.Default.EmptyCredentials)
{
case "windows":
_rdpClient.UserName = Environment.UserName;
break;
case "custom" when !string.IsNullOrEmpty(Properties.OptionsCredentialsPage.Default.DefaultUsername):
_rdpClient.UserName = Properties.OptionsCredentialsPage.Default.DefaultUsername;
break;
case "custom":
try
{
ExternalConnectors.DSS.SecretServerInterface.FetchSecretFromServer(Properties.OptionsCredentialsPage.Default.UserViaAPIDefault, out userName, out password, out domain, out pkey);
_rdpClient.UserName = userName;
}
catch (Exception ex)
{
Event_ErrorOccured(this, "Secret Server Interface Error: " + ex.Message, 0);
}
break;
}
}
else
{
_rdpClient.UserName = userName;
}
if (string.IsNullOrEmpty(password))
{
if (Properties.OptionsCredentialsPage.Default.EmptyCredentials == "custom")
{
if (Properties.OptionsCredentialsPage.Default.DefaultPassword != "")
{
var cryptographyProvider = new LegacyRijndaelCryptographyProvider();
_rdpClient.AdvancedSettings2.ClearTextPassword = cryptographyProvider.Decrypt(Properties.OptionsCredentialsPage.Default.DefaultPassword, Runtime.EncryptionKey);
}
}
}
else
{
_rdpClient.AdvancedSettings2.ClearTextPassword = password;
}
if (string.IsNullOrEmpty(domain))
{
_rdpClient.Domain = Properties.OptionsCredentialsPage.Default.EmptyCredentials switch
{
"windows" => Environment.UserDomainName,
"custom" => Properties.OptionsCredentialsPage.Default.DefaultDomain,
_ => _rdpClient.Domain
};
}
else
{
_rdpClient.Domain = domain;
}
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionStackTrace(Language.RdpSetCredentialsFailed, ex);
}
}
private void SetResolution()
{
try
{
SetExtendedProperty("DesktopScaleFactor", DesktopScaleFactor);
SetExtendedProperty("DeviceScaleFactor", DeviceScaleFactor);
if (Force.HasFlag(ConnectionInfo.Force.Fullscreen))
{
_rdpClient.FullScreen = true;
_rdpClient.DesktopWidth = Screen.FromControl(_frmMain).Bounds.Width;
_rdpClient.DesktopHeight = Screen.FromControl(_frmMain).Bounds.Height;
return;
}
switch (InterfaceControl.Info.Resolution)
{
case RDPResolutions.FitToWindow:
case RDPResolutions.SmartSize:
{
_rdpClient.DesktopWidth = InterfaceControl.Size.Width;
_rdpClient.DesktopHeight = InterfaceControl.Size.Height;
if (InterfaceControl.Info.Resolution == RDPResolutions.SmartSize)
{
_rdpClient.AdvancedSettings2.SmartSizing = true;
}
break;
}
case RDPResolutions.Fullscreen:
_rdpClient.FullScreen = true;
_rdpClient.DesktopWidth = Screen.FromControl(_frmMain).Bounds.Width;
_rdpClient.DesktopHeight = Screen.FromControl(_frmMain).Bounds.Height;
break;
default:
{
var resolution = connectionInfo.Resolution.GetResolutionRectangle();
_rdpClient.DesktopWidth = resolution.Width;
_rdpClient.DesktopHeight = resolution.Height;
break;
}
}
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionStackTrace(Language.RdpSetResolutionFailed, ex);
}
}
private void SetPort()
{
try
{
if (connectionInfo.Port != (int)Defaults.Port)
{
_rdpClient.AdvancedSettings2.RDPPort = connectionInfo.Port;
}
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionStackTrace(Language.RdpSetPortFailed, ex);
}
}
private void SetRedirection()
{
try
{
_rdpClient.AdvancedSettings2.RedirectDrives = connectionInfo.RedirectDiskDrives;
_rdpClient.AdvancedSettings2.RedirectPorts = connectionInfo.RedirectPorts;
_rdpClient.AdvancedSettings2.RedirectPrinters = connectionInfo.RedirectPrinters;
_rdpClient.AdvancedSettings2.RedirectSmartCards = connectionInfo.RedirectSmartCards;
_rdpClient.SecuredSettings2.AudioRedirectionMode = (int)connectionInfo.RedirectSound;
_rdpClient.AdvancedSettings6.RedirectClipboard = connectionInfo.RedirectClipboard;
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionStackTrace(Language.RdpSetRedirectionFailed, ex);
}
}
private void SetPerformanceFlags()
{
try
{
var pFlags = 0;
if (connectionInfo.DisplayThemes == false)
pFlags += (int)RDPPerformanceFlags.DisableThemes;
if (connectionInfo.DisplayWallpaper == false)
pFlags += (int)RDPPerformanceFlags.DisableWallpaper;
if (connectionInfo.EnableFontSmoothing)
pFlags += (int)RDPPerformanceFlags.EnableFontSmoothing;
if (connectionInfo.EnableDesktopComposition)
pFlags += (int)RDPPerformanceFlags.EnableDesktopComposition;
if (connectionInfo.DisableFullWindowDrag)
pFlags += (int)RDPPerformanceFlags.DisableFullWindowDrag;
if (connectionInfo.DisableMenuAnimations)
pFlags += (int)RDPPerformanceFlags.DisableMenuAnimations;
if (connectionInfo.DisableCursorShadow)
pFlags += (int)RDPPerformanceFlags.DisableCursorShadow;
if (connectionInfo.DisableCursorBlinking)
pFlags += (int)RDPPerformanceFlags.DisableCursorBlinking;
_rdpClient.AdvancedSettings2.PerformanceFlags = pFlags;
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionStackTrace(Language.RdpSetPerformanceFlagsFailed, ex);
}
}
private void SetAuthenticationLevel()
{
try
{
_rdpClient.AdvancedSettings5.AuthenticationLevel = (uint)connectionInfo.RDPAuthenticationLevel;
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionStackTrace(Language.RdpSetAuthenticationLevelFailed, ex);
}
}
private void SetLoadBalanceInfo()
{
if (string.IsNullOrEmpty(connectionInfo.LoadBalanceInfo))
{
return;
}
try
{
_rdpClient.AdvancedSettings2.LoadBalanceInfo = LoadBalanceInfoUseUtf8
? new AzureLoadBalanceInfoEncoder().Encode(connectionInfo.LoadBalanceInfo)
: connectionInfo.LoadBalanceInfo;
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionStackTrace("Unable to set load balance info.", ex);
}
}
protected virtual void SetEventHandlers()
{
try
{
_rdpClient.OnConnecting += RDPEvent_OnConnecting;
_rdpClient.OnConnected += RDPEvent_OnConnected;
_rdpClient.OnLoginComplete += RDPEvent_OnLoginComplete;
_rdpClient.OnFatalError += RDPEvent_OnFatalError;
_rdpClient.OnDisconnected += RDPEvent_OnDisconnected;
_rdpClient.OnIdleTimeoutNotification += RDPEvent_OnIdleTimeoutNotification;
_rdpClient.OnLeaveFullScreenMode += RDPEvent_OnLeaveFullscreenMode;
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionStackTrace(Language.RdpSetEventHandlersFailed, ex);
}
}
#endregion
#region Private Events & Handlers
private void RDPEvent_OnIdleTimeoutNotification()
{
Close(); //Simply close the RDP Session if the idle timeout has been triggered.
if (!_alertOnIdleDisconnect) return;
MessageBox.Show($@"The {connectionInfo.Name} session was disconnected due to inactivity", @"Session Disconnected", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void RDPEvent_OnFatalError(int errorCode)
{
var errorMsg = RdpErrorCodes.GetError(errorCode);
Event_ErrorOccured(this, errorMsg, errorCode);
}
private void RDPEvent_OnDisconnected(int discReason)
{
const int UI_ERR_NORMAL_DISCONNECT = 0xB08;
if (discReason != UI_ERR_NORMAL_DISCONNECT)
{
var reason = _rdpClient.GetErrorDescription((uint)discReason, (uint)_rdpClient.ExtendedDisconnectReason);
Event_Disconnected(this, reason, discReason);
}
if (Properties.OptionsAdvancedPage.Default.ReconnectOnDisconnect)
{
ReconnectGroup = new ReconnectGroup();
ReconnectGroup.CloseClicked += Event_ReconnectGroupCloseClicked;
ReconnectGroup.Left = (int)((double)Control.Width / 2 - (double)ReconnectGroup.Width / 2);
ReconnectGroup.Top = (int)((double)Control.Height / 2 - (double)ReconnectGroup.Height / 2);
ReconnectGroup.Parent = Control;
ReconnectGroup.Show();
tmrReconnect.Enabled = true;
}
else
{
Close();
}
}
private void RDPEvent_OnConnecting()
{
Event_Connecting(this);
}
private void RDPEvent_OnConnected()
{
Event_Connected(this);
}
private void RDPEvent_OnLoginComplete()
{
loginComplete = true;
}
private void RDPEvent_OnLeaveFullscreenMode()
{
Fullscreen = false;
_leaveFullscreenEvent?.Invoke(this, EventArgs.Empty);
}
private void RdpClient_GotFocus(object sender, EventArgs e)
{
((ConnectionTab)Control.Parent.Parent).Focus();
}
#endregion
#region Public Events & Handlers
public delegate void LeaveFullscreenEventHandler(object sender, EventArgs e);
private LeaveFullscreenEventHandler _leaveFullscreenEvent;
public event LeaveFullscreenEventHandler LeaveFullscreen
{
add => _leaveFullscreenEvent = (LeaveFullscreenEventHandler)Delegate.Combine(_leaveFullscreenEvent, value);
remove => _leaveFullscreenEvent = (LeaveFullscreenEventHandler)Delegate.Remove(_leaveFullscreenEvent, value);
}
#endregion
#region Enums
public enum Defaults
{
Colors = RDPColors.Colors16Bit,
Sounds = RDPSounds.DoNotPlay,
Resolution = RDPResolutions.FitToWindow,
Port = 3389
}
#endregion
#region Reconnect Stuff
private void tmrReconnect_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
var srvReady = PortScanner.IsPortOpen(connectionInfo.Hostname, Convert.ToString(connectionInfo.Port));
ReconnectGroup.ServerReady = srvReady;
if (!ReconnectGroup.ReconnectWhenReady || !srvReady) return;
tmrReconnect.Enabled = false;
ReconnectGroup.DisposeReconnectGroup();
//SetProps()
_rdpClient.Connect();
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionMessage(
string.Format(Language.AutomaticReconnectError, connectionInfo.Hostname),
ex, MessageClass.WarningMsg, false);
}
}
#endregion
}
}

View File

@@ -1,25 +1,27 @@
using System.Runtime.Versioning;
using System.Windows.Forms;
using AxMSTSCLib;
using MSTSCLib;
namespace mRemoteNG.Connection.Protocol.RDP
{
[SupportedOSPlatform("windows")]
public class RdpProtocol10 : RdpProtocol9
{
private MsRdpClient10NotSafeForScripting RdpClient10 => (MsRdpClient10NotSafeForScripting)((AxHost)Control).GetOcx();
protected override RdpVersion RdpProtocolVersion => RdpVersion.Rdc10;
protected override RdpVersion RdpProtocolVersion => RDP.RdpVersion.Rdc10;
protected override AxHost CreateActiveXRdpClientControl()
{
return new AxMsRdpClient10NotSafeForScripting();
return new AxMsRdpClient11NotSafeForScripting();
}
protected override void UpdateSessionDisplaySettings(uint width, uint height)
public override bool Initialize()
{
RdpClient10.UpdateSessionDisplaySettings(width, height, width, height, 0, 1, 1);
if (!base.Initialize())
return false;
if (RdpVersion < Versions.RDC100) return false; // minimum dll version checked, loaded MSTSCLIB dll version is not capable
return true;
}
}

View File

@@ -1,25 +1,26 @@
using System.Runtime.Versioning;
using System.Windows.Forms;
using AxMSTSCLib;
using MSTSCLib;
namespace mRemoteNG.Connection.Protocol.RDP
{
[SupportedOSPlatform("windows")]
public class RdpProtocol11 : RdpProtocol10
{
private MsRdpClient11NotSafeForScripting RdpClient11 => (MsRdpClient11NotSafeForScripting)((AxHost)Control).GetOcx();
protected override RdpVersion RdpProtocolVersion => RdpVersion.Rdc11;
protected override RdpVersion RdpProtocolVersion => RDP.RdpVersion.Rdc11;
protected override AxHost CreateActiveXRdpClientControl()
{
return new AxMsRdpClient11NotSafeForScripting();
}
protected override void UpdateSessionDisplaySettings(uint width, uint height)
public override bool Initialize()
{
RdpClient11.UpdateSessionDisplaySettings(width, height, width, height, 0, 1, 1);
if (!base.Initialize())
return false;
if (RdpVersion < Versions.RDC100) return false; // minimum dll version checked, loaded MSTSCLIB dll version is not capable
return true;
}
}

View File

@@ -9,9 +9,10 @@ using System.Runtime.Versioning;
namespace mRemoteNG.Connection.Protocol.RDP
{
[SupportedOSPlatform("windows")]
public class RdpProtocol7 : RdpProtocol6
public class RdpProtocol7 : RdpProtocol
{
protected override RdpVersion RdpProtocolVersion => RdpVersion.Rdc7;
private MsRdpClient7NotSafeForScripting RdpClient7 => (MsRdpClient7NotSafeForScripting)((AxHost)Control).GetOcx();
protected override RdpVersion RdpProtocolVersion => RDP.RdpVersion.Rdc7;
public override bool Initialize()
{
@@ -20,20 +21,21 @@ namespace mRemoteNG.Connection.Protocol.RDP
try
{
var rdpClient7 = (MsRdpClient7NotSafeForScripting)((AxHost) Control).GetOcx();
rdpClient7.AdvancedSettings8.AudioQualityMode = (uint)connectionInfo.SoundQuality;
rdpClient7.AdvancedSettings8.AudioCaptureRedirectionMode = connectionInfo.RedirectAudioCapture;
rdpClient7.AdvancedSettings8.NetworkConnectionType = (int)RdpNetworkConnectionType.Modem;
if (RdpVersion < Versions.RDC70) return false; // loaded MSTSCLIB dll version is not capable
RdpClient7.AdvancedSettings8.AudioQualityMode = (uint)connectionInfo.SoundQuality;
RdpClient7.AdvancedSettings8.AudioCaptureRedirectionMode = connectionInfo.RedirectAudioCapture;
RdpClient7.AdvancedSettings8.NetworkConnectionType = (int)RdpNetworkConnectionType.Modem;
if (connectionInfo.UseVmId)
{
SetExtendedProperty("DisableCredentialsDelegation", true);
rdpClient7.AdvancedSettings7.AuthenticationServiceClass = "Microsoft Virtual Console Service";
rdpClient7.AdvancedSettings8.EnableCredSspSupport = true;
rdpClient7.AdvancedSettings8.NegotiateSecurityLayer = false;
rdpClient7.AdvancedSettings7.PCB = $"{connectionInfo.VmId}";
RdpClient7.AdvancedSettings7.AuthenticationServiceClass = "Microsoft Virtual Console Service";
RdpClient7.AdvancedSettings8.EnableCredSspSupport = true;
RdpClient7.AdvancedSettings8.NegotiateSecurityLayer = false;
RdpClient7.AdvancedSettings7.PCB = $"{connectionInfo.VmId}";
if (connectionInfo.UseEnhancedMode)
rdpClient7.AdvancedSettings7.PCB += ";EnhancedMode=1";
RdpClient7.AdvancedSettings7.PCB += ";EnhancedMode=1";
}
}
catch (Exception ex)
@@ -47,7 +49,8 @@ namespace mRemoteNG.Connection.Protocol.RDP
protected override AxHost CreateActiveXRdpClientControl()
{
return new AxMsRdpClient7NotSafeForScripting();
return new AxMsRdpClient11NotSafeForScripting();
}
}
}

View File

@@ -21,18 +21,28 @@ namespace mRemoteNG.Connection.Protocol.RDP
public class RdpProtocol8 : RdpProtocol7
{
private MsRdpClient8NotSafeForScripting RdpClient8 => (MsRdpClient8NotSafeForScripting)((AxHost)Control).GetOcx();
private Size _controlBeginningSize;
protected override RdpVersion RdpProtocolVersion => RdpVersion.Rdc8;
protected override RdpVersion RdpProtocolVersion => RDP.RdpVersion.Rdc8;
public override bool SmartSize
public override bool Initialize()
{
get => base.SmartSize;
protected set
if (!base.Initialize())
return false;
if (RdpVersion < Versions.RDC81) return false; // minimum dll version checked, loaded MSTSCLIB dll version is not capable
// https://learn.microsoft.com/en-us/windows/win32/termserv/imsrdpextendedsettings-property
if (connectionInfo.UseRestrictedAdmin)
{
base.SmartSize = value;
DoResizeClient();
SetExtendedProperty("RestrictedLogon", true);
}
else if (connectionInfo.UseRCG)
{
SetExtendedProperty("DisableCredentialsDelegation", true);
SetExtendedProperty("RedirectedAuthentication", true);
}
return true;
}
public override bool Fullscreen
@@ -45,28 +55,17 @@ namespace mRemoteNG.Connection.Protocol.RDP
}
}
public override void ResizeBegin(object sender, EventArgs e)
protected override void Resize(object sender, EventArgs e)
{
_controlBeginningSize = Control.Size;
if (_frmMain.PreviousWindowState == _frmMain.WindowState) return;
DoResizeControl();
DoResizeClient();
}
public override void Resize(object sender, EventArgs e)
{
if (DoResizeControl() && _controlBeginningSize.IsEmpty)
{
DoResizeClient();
}
base.Resize(sender, e);
}
public override void ResizeEnd(object sender, EventArgs e)
protected override void ResizeEnd(object sender, EventArgs e)
{
DoResizeControl();
if (!(Control.Size == _controlBeginningSize))
{
DoResizeClient();
}
_controlBeginningSize = Size.Empty;
DoResizeClient();
}
protected override AxHost CreateActiveXRdpClientControl()
@@ -94,10 +93,19 @@ namespace mRemoteNG.Connection.Protocol.RDP
try
{
//var q1 = Screen.FromControl(Control).Bounds.Size;
//var q2 = Control.Size;
var size = Fullscreen
? Screen.FromControl(Control).Bounds.Size
: Control.Size;
//size = Screen.FromControl(Control).Bounds.Size;
UpdateSessionDisplaySettings((uint)size.Width, (uint)size.Height);
//size = Control.Size;
//UpdateSessionDisplaySettings((uint)size.Width, (uint)size.Height);
}
catch (Exception ex)
{
@@ -117,10 +125,8 @@ namespace mRemoteNG.Connection.Protocol.RDP
Control.Size = InterfaceControl.Size;
return true;
}
else
{
return false;
}
return false;
}
protected virtual void UpdateSessionDisplaySettings(uint width, uint height)

View File

@@ -1,5 +1,4 @@
using System;
using System.Runtime.Versioning;
using System.Runtime.Versioning;
using System.Windows.Forms;
using AxMSTSCLib;
using MSTSCLib;
@@ -11,7 +10,22 @@ namespace mRemoteNG.Connection.Protocol.RDP
{
private MsRdpClient9NotSafeForScripting RdpClient9 => (MsRdpClient9NotSafeForScripting)((AxHost)Control).GetOcx();
protected override RdpVersion RdpProtocolVersion => RdpVersion.Rdc9;
protected override RdpVersion RdpProtocolVersion => RDP.RdpVersion.Rdc9;
public RdpProtocol9()
{
_frmMain.ResizeEnd += ResizeEnd;
}
public override bool Initialize()
{
if (!base.Initialize())
return false;
if (RdpVersion < Versions.RDC81) return false; // minimum dll version checked, loaded MSTSCLIB dll version is not capable
return true;
}
protected override AxHost CreateActiveXRdpClientControl()
{
@@ -20,7 +34,7 @@ namespace mRemoteNG.Connection.Protocol.RDP
protected override void UpdateSessionDisplaySettings(uint width, uint height)
{
RdpClient9.UpdateSessionDisplaySettings(width, height, width, height, 0, 1, 1);
RdpClient9.UpdateSessionDisplaySettings(width, height, width, height, Orientation, DesktopScaleFactor, DeviceScaleFactor);
}
}