mirror of
https://github.com/mRemoteNG/mRemoteNG.git
synced 2026-02-17 22:11:48 +08:00
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:
867
mRemoteNG/Connection/Protocol/RDP/RdpProtocol.cs
Normal file
867
mRemoteNG/Connection/Protocol/RDP/RdpProtocol.cs
Normal 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
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user