using System; using System.Collections.Generic; using System.Text; using System.Windows.Forms; namespace sharprd { public class RDPTabPage : RDTabPage { // No shadow is displayed for the cursor. const int TS_PERF_DISABLE_CURSOR_SHADOW = 0x00000020; // Cursor blinking is disabled. const int TS_PERF_DISABLE_CURSORSETTINGS = 0x00000040; // Full-window drag is disabled; only the window outline is displayed when the window is moved. const int TS_PERF_DISABLE_FULLWINDOWDRAG = 0x00000002; // Menu animations are disabled. const int TS_PERF_DISABLE_MENUANIMATIONS = 0x00000004; // No features are disabled. const int TS_PERF_DISABLE_NOTHING = 0x00000000; // Themes are disabled. const int TS_PERF_DISABLE_THEMING = 0x00000008; // Wallpaper on the desktop is not displayed. const int TS_PERF_DISABLE_WALLPAPER = 0x00000001; const int TS_PERF_ENABLE_FONT_SMOOTHING = 0x00000080; const int TS_PERF_ENABLE_DESKTOP_COMPOSITION = 0x00000100; private RdpClient rdp = null; private AxMSTSCLib.IMsTscAxEvents_OnDisconnectedEventHandler disconnectedEventHandler; private AxMSTSCLib.IMsTscAxEvents_OnDisconnectedEventHandler disconnectedForReconnectionEventHandler; public override bool Connected { get { return rdp.Connected == 1; } } protected override void OnCreateControl() { rdp = new RdpClient(); disconnectedEventHandler = new AxMSTSCLib.IMsTscAxEvents_OnDisconnectedEventHandler(OnDisconnected); disconnectedForReconnectionEventHandler = new AxMSTSCLib.IMsTscAxEvents_OnDisconnectedEventHandler(OnDisconnectedForReconnection); rdp.OnDisconnected += disconnectedEventHandler; rdp.OnConnecting += new EventHandler(OnConnecting); rdp.OnConnected += new EventHandler(OnConnected); this.Controls.Add(rdp); rdp.Dock = DockStyle.Fill; base.OnCreateControl(); } private void OnConnecting(object sender, EventArgs e) { connecting = true; Notify(this, new NotifyEventArgs(NotifyEventArgs.Actions.Connecting)); } private void OnConnected(object sender, EventArgs e) { connecting = false; Notify(this, new NotifyEventArgs(NotifyEventArgs.Actions.Connected)); } private void OnDisconnected(object sender, AxMSTSCLib.IMsTscAxEvents_OnDisconnectedEvent e) { connecting = false; Notify(this, new NotifyEventArgs(NotifyEventArgs.Actions.Disconnected)); ((TabControl)this.Parent).TabPages.Remove(this); } private void OnDisconnectedForReconnection(object sender, AxMSTSCLib.IMsTscAxEvents_OnDisconnectedEvent e) { connecting = false; Notify(this, new NotifyEventArgs(NotifyEventArgs.Actions.Disconnected)); rdp.Connect(); rdp.OnDisconnected -= disconnectedForReconnectionEventHandler; rdp.OnDisconnected += disconnectedEventHandler; } public override void Disconnect() { try { if (Connected) { rdp.Disconnect(); } } catch (Exception) { } } public RDPTabPage(RDConnection connection) : base(connection) { } public override void Connect() { connecting = true; MSTSCLib.IMsRdpClientAdvancedSettings5 settings = rdp.AdvancedSettings5 as MSTSCLib.IMsRdpClientAdvancedSettings5; MSTSCLib.IMsRdpClientAdvancedSettings6 advancedSettings = rdp.AdvancedSettings7 as MSTSCLib.IMsRdpClientAdvancedSettings6; string server = string.Empty; if (!string.IsNullOrEmpty(connection.Computer)) { if (connection.Computer.Contains(":")) { string[] tokens = connection.Computer.Split(new char[] { ':' }); server = tokens[0]; int port = 3389; if (int.TryParse(tokens[1], out port)) { settings.RDPPort = port; } } else { server = connection.Computer; } } rdp.Server = server; rdp.Domain = connection.Domain; rdp.UserName = connection.Username; if (!string.IsNullOrEmpty(connection.Password)) { settings.ClearTextPassword = Encryption.Decrypt(connection.Password); } settings.ConnectToServerConsole = connection.Console; if (connection.DisplayMode == RDConnection.DisplayModes.Fullscreen) { rdp.FullScreen = true; rdp.DesktopWidth = Screen.PrimaryScreen.Bounds.Width; rdp.DesktopHeight = Screen.PrimaryScreen.Bounds.Height; } else { settings.SmartSizing = true; } rdp.ColorDepth = (int)connection.ColorDepth; settings.DisplayConnectionBar = connection.DisplayConnectionBar; switch (connection.RemoteAudio) { case RDConnection.RemoteAudioConfiguration.PlayOnThisComputer: settings.AudioRedirectionMode = 0; break; case RDConnection.RemoteAudioConfiguration.DoNotPlay: settings.AudioRedirectionMode = 2; break; case RDConnection.RemoteAudioConfiguration.PlayOnRemoteComputer: settings.AudioRedirectionMode = 1; break; } settings.RedirectPrinters = connection.Printers; settings.RedirectClipboard = connection.Clipboard; settings.RedirectDrives = connection.Drives; if (!connection.DesktopBackground) settings.PerformanceFlags |= TS_PERF_DISABLE_WALLPAPER; if (connection.FontSmoothing) settings.PerformanceFlags |= TS_PERF_ENABLE_FONT_SMOOTHING; if (connection.DesktopComposition) settings.PerformanceFlags |= TS_PERF_ENABLE_DESKTOP_COMPOSITION; if (!connection.WindowContents) settings.PerformanceFlags |= TS_PERF_DISABLE_FULLWINDOWDRAG; if (!connection.MenuAnimation) settings.PerformanceFlags |= TS_PERF_DISABLE_MENUANIMATIONS; if (!connection.VisualStyles) settings.PerformanceFlags |= TS_PERF_DISABLE_THEMING; settings.BitmapPersistence = connection.PersistentBitmapCaching ? 1 : 0; rdp.Dock = DockStyle.Fill; if (connection.NLA) { //Default to EnableCredSsp and negotiate authentication level //If functionality not supported, we ignore the error and continue //Server Admins: Start of CredSSP/NLA warning section try { settings.AuthenticationLevel = 2; advancedSettings.EnableCredSspSupport = true; } catch { MessageBox.Show("Client not supported"); } //Server Admins: End of CredSSP/NLA warning section } rdp.OnDisconnected += new AxMSTSCLib.IMsTscAxEvents_OnDisconnectedEventHandler(rdp_OnDisconnected); try { rdp.Connect(); } catch (Exception ex) { MessageBox.Show(ex.Message); } ((TabControl)this.Parent).SelectTab(this); } void rdp_OnDisconnected(object sender, AxMSTSCLib.IMsTscAxEvents_OnDisconnectedEvent e) { string disconnectedReason = string.Empty; bool showMessage = false; switch (e.discReason) { case 0: disconnectedReason = "No information is available."; break; case 1: disconnectedReason = "Local disconnection."; break; case 2: disconnectedReason = "Remote disconnection by user."; break; case 3: disconnectedReason = "Remote disconnection by server."; break; case 260: disconnectedReason = "DNS name lookup failure."; break; case 262: disconnectedReason = "Out of memory."; break; case 264: disconnectedReason = "Connection timed out."; break; case 516: disconnectedReason = "Winsock socket connect failure."; break; case 518: disconnectedReason = "Out of memory."; break; case 520: disconnectedReason = "Host not found."; break; case 772: disconnectedReason = "Winsock send call failure."; break; case 774: disconnectedReason = "Out of memory."; break; case 776: disconnectedReason = "Invalid IP address specified."; break; case 1028: disconnectedReason = "Winsock recv call failure."; break; case 1030: disconnectedReason = "Invalid security data."; break; case 1032: disconnectedReason = "Internal error."; break; case 1286: disconnectedReason = "Invalid encryption method specified."; break; case 1288: disconnectedReason = "DNS lookup failed."; break; case 1540: disconnectedReason = "Failed to find the requested server, device, or host."; break; case 1542: disconnectedReason = "Invalid server security data."; break; case 1544: disconnectedReason = "Internal timer error."; break; case 1796: disconnectedReason = "Timeout occurred."; break; case 1798: disconnectedReason = "Failed to unpack server certificate."; break; case 2052: disconnectedReason = "Bad IP address specified."; break; case 2056: disconnectedReason = "Internal security error."; break; case 2308: disconnectedReason = "Socket closed."; break; case 2310: disconnectedReason = "Internal security error."; break; case 2312: disconnectedReason = "Licensing timeout."; break; case 2566: disconnectedReason = "Internal security error."; break; case 2822: disconnectedReason = "Encryption error."; break; case 2825: disconnectedReason = "The remote computer requires Network Level Authentication. Enable NLA in connection options"; showMessage = true; break; case 3078: disconnectedReason = "Decryption error."; break; default: disconnectedReason = string.Format("Unrecognized error: code {0}", e.discReason); break; } if (showMessage) { MessageBox.Show(disconnectedReason); } } public void Debug(object sender, AxMSTSCLib.IMsTscAxEvents_OnDisconnectedEvent e) { MessageBox.Show(e.discReason.ToString()); } public override void Reconnect() { if (Connected) { rdp.OnDisconnected -= disconnectedEventHandler; rdp.OnDisconnected += disconnectedForReconnectionEventHandler; rdp.Disconnect(); } } } }