PageRenderTime 25ms CodeModel.GetById 38ms RepoModel.GetById 0ms app.codeStats 0ms

/Terminals/Connections/RDPConnection.cs

#
C# | 567 lines | 444 code | 78 blank | 45 comment | 45 complexity | ebb0aaaace5822e65b509f9afbc3d904 MD5 | raw file
Possible License(s): GPL-2.0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.Windows.Forms;
  5. using AxMSTSCLib;
  6. using System.IO;
  7. using System.Runtime.InteropServices;
  8. using Terminals.Configuration;
  9. //http://msdn.microsoft.com/en-us/library/aa381172(v=vs.85).aspx
  10. //http://msdn.microsoft.com/en-us/library/aa380838(v=VS.85).aspx
  11. //http://msdn.microsoft.com/en-us/library/aa380847(v=VS.85).aspx
  12. //http://msdn.microsoft.com/en-us/library/bb892063(v=VS.85).aspx
  13. //http://msdn.microsoft.com/en-us/library/ee338625(v=VS.85).aspx
  14. namespace Terminals.Connections
  15. {
  16. internal class RDPConnection : Connection
  17. {
  18. private MSTSCLib.IMsRdpClientNonScriptable4 _nonScriptable;
  19. private AxMsRdpClient6 _axMsRdpClient = null;
  20. public delegate void Disconnected(RDPConnection Connection);
  21. public event Disconnected OnDisconnected;
  22. public delegate void ConnectionEstablish(RDPConnection Connection);
  23. public event ConnectionEstablish OnConnected;
  24. public AxMsRdpClient6 AxMsRdpClient
  25. {
  26. get
  27. {
  28. return _axMsRdpClient;
  29. }
  30. }
  31. private void SHCopyFiles(string[] sourceFiles, string destinationFolder)
  32. {
  33. SHFileOperationWrapper fo = new SHFileOperationWrapper();
  34. List<string> destinationFiles = new List<string>();
  35. foreach (string sourceFile in sourceFiles)
  36. {
  37. destinationFiles.Add(Path.Combine(destinationFolder, Path.GetFileName(sourceFile)));
  38. }
  39. fo.Operation = SHFileOperationWrapper.FileOperations.FO_COPY;
  40. fo.OwnerWindow = this.Handle;
  41. fo.SourceFiles = sourceFiles;
  42. fo.DestFiles = destinationFiles.ToArray();
  43. fo.DoOperation();
  44. }
  45. #region IConnection Members
  46. public override bool Connected
  47. {
  48. get
  49. {
  50. return Convert.ToBoolean(_axMsRdpClient.Connected);
  51. }
  52. }
  53. public override void ChangeDesktopSize(DesktopSize desktopSize)
  54. {
  55. Size size = ConnectionManager.GetSize(this, Favorite);
  56. try
  57. {
  58. switch (desktopSize)
  59. {
  60. case DesktopSize.AutoScale:
  61. case DesktopSize.FitToWindow:
  62. this._axMsRdpClient.AdvancedSettings3.SmartSizing = true;
  63. break;
  64. case DesktopSize.FullScreen:
  65. _axMsRdpClient.FullScreen = true;
  66. break;
  67. }
  68. _axMsRdpClient.DesktopWidth = size.Width;
  69. _axMsRdpClient.DesktopHeight = size.Height;
  70. }
  71. catch(Exception exc)
  72. {
  73. Logging.Log.Error("Error trying to set the desktop dimensions",exc);
  74. }
  75. }
  76. public override bool Connect()
  77. {
  78. try
  79. {
  80. _axMsRdpClient = new AxMsRdpClient6();
  81. }
  82. catch (Exception exc)
  83. {
  84. String msg = "Please update your RDP client to at least version 6.";
  85. Logging.Log.Info(msg, exc);
  86. MessageBox.Show(msg);
  87. return false;
  88. }
  89. try
  90. {
  91. Controls.Add(_axMsRdpClient);
  92. _axMsRdpClient.BringToFront();
  93. this.BringToFront();
  94. _axMsRdpClient.Parent = TerminalTabPage;
  95. this.Parent = TerminalTabPage;
  96. _axMsRdpClient.AllowDrop = true;
  97. ((Control)_axMsRdpClient).DragEnter += new DragEventHandler(axMsRdpClient2_DragEnter);
  98. ((Control)_axMsRdpClient).DragDrop += new DragEventHandler(axMsRdpClient2_DragDrop);
  99. _axMsRdpClient.OnConnected += new EventHandler(axMsRdpClient2_OnConnected);
  100. _axMsRdpClient.Dock = DockStyle.Fill;
  101. _nonScriptable = (_axMsRdpClient.GetOcx() as MSTSCLib.IMsRdpClientNonScriptable4);
  102. ChangeDesktopSize(Favorite.DesktopSize);
  103. try
  104. {
  105. //if(Favorite.DesktopSize == DesktopSize.AutoScale) axMsRdpClient2.AdvancedSettings3.SmartSizing = true;
  106. //axMsRdpClient2.DesktopWidth = width;
  107. //axMsRdpClient2.DesktopHeight = height;
  108. switch(Favorite.Colors)
  109. {
  110. case Colors.Bits8:
  111. _axMsRdpClient.ColorDepth = 8;
  112. break;
  113. case Colors.Bit16:
  114. _axMsRdpClient.ColorDepth = 16;
  115. break;
  116. case Colors.Bits24:
  117. _axMsRdpClient.ColorDepth = 24;
  118. break;
  119. case Colors.Bits32:
  120. _axMsRdpClient.ColorDepth = 32;
  121. break;
  122. }
  123. _axMsRdpClient.ConnectingText = "Connecting. Please wait...";
  124. _axMsRdpClient.DisconnectedText = "Disconnecting...";
  125. if (Favorite.RedirectedDrives.Count > 0 && Favorite.RedirectedDrives[0].Equals("true"))
  126. {
  127. _axMsRdpClient.AdvancedSettings2.RedirectDrives = true;
  128. }
  129. else
  130. {
  131. for (int i = 0; i < _nonScriptable.DriveCollection.DriveCount; i++)
  132. {
  133. MSTSCLib.IMsRdpDrive drive = _nonScriptable.DriveCollection.get_DriveByIndex((uint)i);
  134. foreach (string str in Favorite.RedirectedDrives)
  135. if (drive.Name.IndexOf(str) > -1)
  136. drive.RedirectionState = true;
  137. }
  138. }
  139. //advanced settings
  140. //bool, 0 is false, other is true
  141. if(Favorite.AllowBackgroundInput)
  142. _axMsRdpClient.AdvancedSettings.allowBackgroundInput = -1;
  143. if(Favorite.BitmapPeristence)
  144. _axMsRdpClient.AdvancedSettings.BitmapPeristence = -1;
  145. if(Favorite.EnableCompression)
  146. _axMsRdpClient.AdvancedSettings.Compress = -1;
  147. if(Favorite.AcceleratorPassthrough)
  148. _axMsRdpClient.AdvancedSettings2.AcceleratorPassthrough = -1;
  149. if(Favorite.DisableControlAltDelete)
  150. _axMsRdpClient.AdvancedSettings2.DisableCtrlAltDel = -1;
  151. if(Favorite.DisplayConnectionBar)
  152. _axMsRdpClient.AdvancedSettings2.DisplayConnectionBar = true;
  153. if(Favorite.DoubleClickDetect)
  154. _axMsRdpClient.AdvancedSettings2.DoubleClickDetect = -1;
  155. if(Favorite.DisableWindowsKey)
  156. _axMsRdpClient.AdvancedSettings2.EnableWindowsKey = -1;
  157. if(Favorite.EnableEncryption)
  158. _axMsRdpClient.AdvancedSettings2.EncryptionEnabled = -1;
  159. if(Favorite.GrabFocusOnConnect)
  160. _axMsRdpClient.AdvancedSettings2.GrabFocusOnConnect = true;
  161. if(Favorite.EnableSecuritySettings)
  162. {
  163. if(Favorite.SecurityFullScreen)
  164. _axMsRdpClient.SecuredSettings2.FullScreen = -1;
  165. _axMsRdpClient.SecuredSettings2.StartProgram = Favorite.SecurityStartProgram;
  166. _axMsRdpClient.SecuredSettings2.WorkDir = Favorite.SecurityWorkingFolder;
  167. }
  168. _axMsRdpClient.AdvancedSettings2.MinutesToIdleTimeout = Favorite.IdleTimeout;
  169. try
  170. {
  171. int timeout = Favorite.OverallTimeout;
  172. if(timeout > 600) timeout = 10;
  173. if(timeout <= 0) timeout = 10;
  174. _axMsRdpClient.AdvancedSettings2.overallConnectionTimeout = timeout;
  175. timeout = Favorite.ConnectionTimeout;
  176. if(timeout > 600) timeout = 10;
  177. if(timeout <= 0) timeout = 10;
  178. _axMsRdpClient.AdvancedSettings2.singleConnectionTimeout = timeout;
  179. timeout = Favorite.ShutdownTimeout;
  180. if(timeout > 600) timeout = 10;
  181. if(timeout <= 0) timeout = 10;
  182. _axMsRdpClient.AdvancedSettings2.shutdownTimeout = timeout;
  183. //axMsRdpClient2.AdvancedSettings2.PinConnectionBar;
  184. //axMsRdpClient2.AdvancedSettings2.TransportType;
  185. //axMsRdpClient2.AdvancedSettings2.WinceFixedPalette;
  186. //axMsRdpClient2.AdvancedSettings3.CanAutoReconnect = Favorite.CanAutoReconnect;
  187. }
  188. catch(Exception exc)
  189. {
  190. Logging.Log.Error("Error when trying to set timeout values.", exc);
  191. }
  192. _axMsRdpClient.AdvancedSettings3.RedirectPorts = Favorite.RedirectPorts;
  193. _axMsRdpClient.AdvancedSettings3.RedirectPrinters = Favorite.RedirectPrinters;
  194. _axMsRdpClient.AdvancedSettings3.RedirectSmartCards = Favorite.RedirectSmartCards;
  195. _axMsRdpClient.AdvancedSettings3.PerformanceFlags = Favorite.PerformanceFlags;
  196. /*
  197. TS_PERF_DISABLE_CURSOR_SHADOW
  198. 0x00000020
  199. No shadow is displayed for the cursor.
  200. TS_PERF_DISABLE_CURSORSETTINGS
  201. 0x00000040
  202. Cursor blinking is disabled.
  203. TS_PERF_DISABLE_FULLWINDOWDRAG
  204. 0x00000002
  205. Full-window drag is disabled; only the window outline is displayed when the window is moved.
  206. TS_PERF_DISABLE_MENUANIMATIONS
  207. 0x00000004
  208. Menu animations are disabled.
  209. TS_PERF_DISABLE_NOTHING
  210. 0x00000000
  211. No features are disabled.
  212. TS_PERF_DISABLE_THEMING
  213. 0x00000008
  214. Themes are disabled.
  215. TS_PERF_DISABLE_WALLPAPER
  216. 0x00000001
  217. Wallpaper on the desktop is not displayed.
  218. TS_PERF_ENABLE_FONT_SMOOTHING 0x00000080
  219. TS_PERF_ENABLE_DESKTOP_COMPOSITION 0x00000100
  220. */
  221. _axMsRdpClient.AdvancedSettings6.RedirectClipboard = Favorite.RedirectClipboard;
  222. _axMsRdpClient.AdvancedSettings6.RedirectDevices = Favorite.RedirectDevices;
  223. _axMsRdpClient.AdvancedSettings6.ConnectionBarShowMinimizeButton = false;
  224. _axMsRdpClient.AdvancedSettings6.ConnectionBarShowPinButton = false;
  225. _axMsRdpClient.AdvancedSettings6.ConnectionBarShowRestoreButton = false;
  226. // Terminal Server Gateway Settings
  227. _axMsRdpClient.TransportSettings.GatewayUsageMethod = (uint)Favorite.TsgwUsageMethod;
  228. _axMsRdpClient.TransportSettings.GatewayCredsSource = (uint)Favorite.TsgwCredsSource;
  229. _axMsRdpClient.TransportSettings.GatewayHostname = Favorite.TsgwHostname;
  230. _axMsRdpClient.TransportSettings2.GatewayDomain = Favorite.TsgwDomain;
  231. _axMsRdpClient.TransportSettings2.GatewayProfileUsageMethod = 1;
  232. if (Favorite.TsgwSeparateLogin)
  233. {
  234. _axMsRdpClient.TransportSettings2.GatewayUsername = Favorite.TsgwUsername;
  235. _axMsRdpClient.TransportSettings2.GatewayPassword = Favorite.TsgwPassword;
  236. }
  237. else
  238. {
  239. _axMsRdpClient.TransportSettings2.GatewayUsername = Favorite.UserName;
  240. _axMsRdpClient.TransportSettings2.GatewayPassword = Favorite.Password;
  241. }
  242. if (Favorite.EnableTLSAuthentication)
  243. _axMsRdpClient.AdvancedSettings5.AuthenticationLevel = 2;
  244. _nonScriptable.EnableCredSspSupport = Favorite.EnableNLAAuthentication;
  245. _axMsRdpClient.SecuredSettings2.AudioRedirectionMode = (int)Favorite.Sounds;
  246. string domainName = Favorite.DomainName;
  247. if(string.IsNullOrEmpty(domainName))
  248. domainName = Settings.DefaultDomain;
  249. string pass = Favorite.Password;
  250. if (string.IsNullOrEmpty(pass))
  251. pass = Settings.DefaultPassword;
  252. string userName = Favorite.UserName;
  253. if (string.IsNullOrEmpty(userName))
  254. userName = Settings.DefaultUsername;
  255. _axMsRdpClient.UserName = userName;
  256. _axMsRdpClient.Domain = domainName;
  257. try
  258. {
  259. if(!String.IsNullOrEmpty(pass))
  260. {
  261. if(_nonScriptable != null)
  262. _nonScriptable.ClearTextPassword = pass;
  263. }
  264. }
  265. catch(Exception exc)
  266. {
  267. Logging.Log.Error("Error when trying to set the ClearTextPassword on the nonScriptable mstsc object", exc);
  268. }
  269. _axMsRdpClient.Server = Favorite.ServerName;
  270. _axMsRdpClient.AdvancedSettings3.RDPPort = Favorite.Port;
  271. _axMsRdpClient.AdvancedSettings3.ContainerHandledFullScreen = -1;
  272. _axMsRdpClient.AdvancedSettings3.DisplayConnectionBar = Favorite.DisplayConnectionBar;
  273. // Use ConnectToServerConsole or ConnectToAdministerServer based on implementation
  274. _axMsRdpClient.AdvancedSettings7.ConnectToAdministerServer = Favorite.ConnectToConsole;
  275. _axMsRdpClient.AdvancedSettings3.ConnectToServerConsole = Favorite.ConnectToConsole;
  276. _axMsRdpClient.OnRequestGoFullScreen += new EventHandler(axMsTscAx_OnRequestGoFullScreen);
  277. _axMsRdpClient.OnRequestLeaveFullScreen += new EventHandler(axMsTscAx_OnRequestLeaveFullScreen);
  278. _axMsRdpClient.OnDisconnected += new IMsTscAxEvents_OnDisconnectedEventHandler(axMsTscAx_OnDisconnected);
  279. _axMsRdpClient.OnWarning += new IMsTscAxEvents_OnWarningEventHandler(axMsRdpClient2_OnWarning);
  280. _axMsRdpClient.OnFatalError += new IMsTscAxEvents_OnFatalErrorEventHandler(axMsRdpClient2_OnFatalError);
  281. _axMsRdpClient.OnLogonError += new IMsTscAxEvents_OnLogonErrorEventHandler(_axMsRdpClient_OnLogonError);
  282. Text = "Connecting to RDP Server...";
  283. _axMsRdpClient.FullScreen = true;
  284. }
  285. catch(Exception exc)
  286. {
  287. Logging.Log.Info("There was an exception setting an RDP Value.", exc);
  288. }
  289. _axMsRdpClient.Connect();
  290. return true;
  291. }
  292. catch(Exception exc)
  293. {
  294. Logging.Log.Fatal("Connecting to RDP", exc);
  295. return false;
  296. }
  297. }
  298. public override void Disconnect()
  299. {
  300. try
  301. {
  302. _axMsRdpClient.Disconnect();
  303. }
  304. catch(Exception e)
  305. {
  306. Logging.Log.Info("Error on Disconnect RDP", e);
  307. }
  308. }
  309. private void axMsRdpClient2_OnConnected(object sender, EventArgs e)
  310. {
  311. if (OnConnected != null) OnConnected(this);
  312. }
  313. #endregion
  314. #region Private event
  315. private void axMsRdpClient2_DragDrop(object sender, DragEventArgs e)
  316. {
  317. string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
  318. string desktopShare = ParentForm.GetDesktopShare();
  319. if (String.IsNullOrEmpty(desktopShare))
  320. {
  321. MessageBox.Show(this, "A Desktop Share was not defined for this connection.\n" +
  322. "Please define a share in the connection properties window (under the Local Resources tab)."
  323. , "Terminals", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
  324. }
  325. else
  326. {
  327. SHCopyFiles(files, desktopShare);
  328. }
  329. }
  330. private void axMsRdpClient2_DragEnter(object sender, DragEventArgs e)
  331. {
  332. if(e.Data.GetDataPresent(DataFormats.FileDrop, false))
  333. e.Effect = DragDropEffects.Copy;
  334. else
  335. e.Effect = DragDropEffects.None;
  336. }
  337. private void axMsTscAx_OnRequestLeaveFullScreen(object sender, EventArgs e)
  338. {
  339. ParentForm.tsbGrabInput.Checked = false;
  340. ParentForm.UpdateControls();
  341. Native.Methods.PostMessage(new HandleRef(this, this.Handle), MainForm.WM_LEAVING_FULLSCREEN, IntPtr.Zero, IntPtr.Zero);
  342. }
  343. private void axMsTscAx_OnRequestGoFullScreen(object sender, EventArgs e)
  344. {
  345. ParentForm.tsbGrabInput.Checked = true;
  346. ParentForm.UpdateControls();
  347. }
  348. private void axMsTscAx_OnDisconnected(object sender, IMsTscAxEvents_OnDisconnectedEvent e)
  349. {
  350. AxMsRdpClient6 client = (AxMsRdpClient6)sender;
  351. switch (e.discReason)
  352. {
  353. case 1:
  354. case 2:
  355. case 3:
  356. // These are normal disconnects and not considered errors.
  357. break;
  358. default:
  359. string error = client.GetErrorDescription((uint)e.discReason, (uint)client.ExtendedDisconnectReason);
  360. if ((error != null) && (error.Length > 0))
  361. MessageBox.Show(this, String.Format("Error connecting to {0}\n\n{1}", client.Server, error), Program.Info.TitleVersion, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
  362. break;
  363. }
  364. if (ParentForm.InvokeRequired)
  365. {
  366. InvokeCloseTabPage d = new InvokeCloseTabPage(CloseTabPage);
  367. this.Invoke(d, new object[] { client.Parent });
  368. }
  369. else
  370. {
  371. CloseTabPage(client.Parent);
  372. }
  373. if(OnDisconnected != null) OnDisconnected(this);
  374. }
  375. private void axMsRdpClient2_OnFatalError(object sender, IMsTscAxEvents_OnFatalErrorEvent e)
  376. {
  377. string msg = "";
  378. switch (e.errorCode)
  379. {
  380. case 0:
  381. msg = "An unknown error has occurred.";
  382. break;
  383. case 1:
  384. msg = "Internal error code 1.";
  385. break;
  386. case 2:
  387. msg = "An out-of-memory error has occurred.";
  388. break;
  389. case 3:
  390. msg = "A window-creation error has occurred.";
  391. break;
  392. case 4:
  393. msg = "Internal error code 2.";
  394. break;
  395. case 5:
  396. msg = "Internal error code 3. This is not a valid state.";
  397. break;
  398. case 6:
  399. msg = "Internal error code 4.";
  400. break;
  401. case 7:
  402. msg = "An unrecoverable error has occurred during client connection.";
  403. break;
  404. case 100:
  405. msg = "Winsock initialization error.";
  406. break;
  407. default:
  408. msg = "An unknown error.";
  409. break;
  410. }
  411. string finalMsg = string.Format("There was a fatal error returned from the RDP Connection, details:\n\nError Code:{0}\n\nError Description:{1}", e.errorCode, msg);
  412. System.Windows.Forms.MessageBox.Show(finalMsg);
  413. Logging.Log.Fatal(finalMsg);
  414. }
  415. private void axMsRdpClient2_OnWarning(object sender, IMsTscAxEvents_OnWarningEvent e)
  416. {
  417. string msg = "";
  418. switch (e.warningCode)
  419. {
  420. case 1:
  421. msg = "Bitmap cache is corrupt.";
  422. break;
  423. default:
  424. msg = "An unknown warning";
  425. break;
  426. }
  427. string finalMsg = string.Format("There was a warning returned from the RDP Connection, details:\n\nWarning Code:{0}\n\nWarning Description:{1}", e.warningCode, msg);
  428. //System.Windows.Forms.MessageBox.Show(finalMsg);
  429. Logging.Log.Warn(finalMsg);
  430. }
  431. private void _axMsRdpClient_OnLogonError(object sender, IMsTscAxEvents_OnLogonErrorEvent e)
  432. {
  433. string msg = "";
  434. switch (e.lError)
  435. {
  436. case -5:
  437. msg = "Winlogon is displaying the Session Contention dialog box.";
  438. break;
  439. case -2:
  440. msg = "Winlogon is continuing with the logon process.";
  441. break;
  442. case -3:
  443. msg = "Winlogon is ending silently.";
  444. break;
  445. case -6:
  446. msg = "Winlogon is displaying the No Permissions dialog box.";
  447. break;
  448. case -7:
  449. msg = "Winlogon is displaying the Disconnect Refused dialog box.";
  450. break;
  451. case -4:
  452. msg = "Winlogon is displaying the Reconnect dialog box.";
  453. break;
  454. case -1:
  455. msg = "The user was denied access.";
  456. break;
  457. case 0:
  458. msg = "The logon failed because the logon credentials are not valid.";
  459. break;
  460. case 2:
  461. msg = "Another logon or post-logon error occurred. The Remote Desktop client displays a logon screen to the user.";
  462. break;
  463. case 1:
  464. msg = "The password is expired. The user must update their password to continue logging on.";
  465. break;
  466. case 3:
  467. msg = "The Remote Desktop client displays a dialog box that contains important information for the user.";
  468. break;
  469. case -1073741714:
  470. msg = "The user name and authentication information are valid, but authentication was blocked due to restrictions on the user account, such as time-of-day restrictions.";
  471. break;
  472. case -1073741715:
  473. msg = "The attempted logon is not valid. This is due to either an incorrect user name or incorrect authentication information.";
  474. break;
  475. case -1073741276:
  476. msg = "The password is expired. The user must update their password to continue logging on.";
  477. break;
  478. default:
  479. msg = "An unknown error.";
  480. break;
  481. }
  482. string finalMsg = string.Format("There was a logon error returned from the RDP Connection, details:\n\nLogon Code:{0}\n\nLogon Description:{1}", e.lError, msg);
  483. //System.Windows.Forms.MessageBox.Show(finalMsg);
  484. Logging.Log.Error(finalMsg);
  485. }
  486. #endregion
  487. }
  488. }