diff --git a/CHANGELOG.TXT b/CHANGELOG.TXT
index 74951f683..270596ecf 100644
--- a/CHANGELOG.TXT
+++ b/CHANGELOG.TXT
@@ -1,3 +1,20 @@
+1.75.7005 (2017-04-27)
+
+Fixes:
+------
+#410: Update PuTTYNG to 0.68
+#434: Fix complier warnings CA1049 & CA2111
+#442: Fixed issue loading PuTTY sessions that have spaces in the name
+#502: Problems with ParentID for Duplicated Containers/Connections with SQL Connection Storage
+#514: Expanded property not saved/loaded properly from SQL
+#518: Exception when Importing File
+
+
+General Changes:
+----------------
+Minor code cleanup/optimizations/null checks
+
+
1.75.7003 (2017-03-24):
Fixes:
diff --git a/CREDITS.TXT b/CREDITS.TXT
index 2b5922afd..c902036a2 100644
--- a/CREDITS.TXT
+++ b/CREDITS.TXT
@@ -99,8 +99,8 @@ Copyright
Freely redistributable with attribution
http://www.dotnetmagic.com/magic_download.html
-PuTTY 0.67
-Copyright © 1997-2016 Simon Tatham
+PuTTY 0.68
+Copyright © 1997-2017 Simon Tatham
MIT License
http://www.chiark.greenend.org.uk/~sgtatham/putty/
diff --git a/InstallerProjects/Installer/Includes/Config.wxi b/InstallerProjects/Installer/Includes/Config.wxi
index e54e30ecd..4ce5e61ba 100644
--- a/InstallerProjects/Installer/Includes/Config.wxi
+++ b/InstallerProjects/Installer/Includes/Config.wxi
@@ -17,7 +17,7 @@
-
+
diff --git a/InstallerProjects/Installer/Localizations/en-US.wxl b/InstallerProjects/Installer/Localizations/en-US.wxl
index 6812f546e..0677bd9df 100644
--- a/InstallerProjects/Installer/Localizations/en-US.wxl
+++ b/InstallerProjects/Installer/Localizations/en-US.wxl
@@ -6,7 +6,7 @@
You need to be an administrator to install this product.
mRemoteNG requires Microsoft .NET Framework [REQUIREDDOTNETFRAMEWORKVERSION] or higher.
mRemoteNG requires Windows 7 SP1 or higher to run. Please update your operating system and try again.
- mRemoteNG requires RDP 8.0 or higher to run. Windows 7 users will need to install KB2592687
+ mRemoteNG requires RDP 8.0 or higher to run. Windows 7 users will need to install either KB2592687 (RDP 8.0) or KB2830477 (RDP 8.1)
mRemoteNG requires KB2574819 in order to create RDP connections. Windows 7 users will need to install this KB.
For mRemoteNG to run on Windows 7, it requires Service Pack 1 to be installed. Please install Service Pack 1 and try again.
diff --git a/InstallerProjects/Installer/mRemoteNGV1.wxs b/InstallerProjects/Installer/mRemoteNGV1.wxs
index 8bacd0b1e..b1d393574 100644
--- a/InstallerProjects/Installer/mRemoteNGV1.wxs
+++ b/InstallerProjects/Installer/mRemoteNGV1.wxs
@@ -67,7 +67,7 @@
= 602 OR VersionNT64 >= 602) OR ((VersionNT = 601 OR VersionNT64 = 601) AND (RDP_DTLS_UPDATE_INSTALLED = 1))]]>
-
+
= 602 OR VersionNT64 >= 602) OR ((VersionNT = 601 OR VersionNT64 = 601) AND (MINIMUM_RDP_VERSION_INSTALLED = 1))]]>
diff --git a/mRemoteNGTests/Config/Serializers/DataTableDeserializerTests.cs b/mRemoteNGTests/Config/Serializers/DataTableDeserializerTests.cs
new file mode 100644
index 000000000..b9fd42522
--- /dev/null
+++ b/mRemoteNGTests/Config/Serializers/DataTableDeserializerTests.cs
@@ -0,0 +1,55 @@
+using System.Data;
+using System.Linq;
+using mRemoteNG.Config.Serializers;
+using mRemoteNG.Connection;
+using mRemoteNG.Security;
+using mRemoteNG.Tree;
+using mRemoteNGTests.TestHelpers;
+using NUnit.Framework;
+
+namespace mRemoteNGTests.Config.Serializers
+{
+ public class DataTableDeserializerTests
+ {
+ private DataTableDeserializer _deserializer;
+
+ [SetUp]
+ public void Setup()
+ {
+
+ }
+
+
+ [Test]
+ public void WeCanDeserializeATree()
+ {
+ var model = CreateConnectionTreeModel();
+ var dataTable = CreateDataTable(model.RootNodes[0]);
+ _deserializer = new DataTableDeserializer(dataTable);
+ var output = _deserializer.Deserialize();
+ Assert.That(output.GetRecursiveChildList().Count(), Is.EqualTo(model.GetRecursiveChildList().Count()));
+ }
+
+ [Test]
+ public void WeCanDeserializeASingleEntry()
+ {
+ var dataTable = CreateDataTable(new ConnectionInfo());
+ _deserializer = new DataTableDeserializer(dataTable);
+ var output = _deserializer.Deserialize();
+ Assert.That(output.GetRecursiveChildList().Count(), Is.EqualTo(1));
+ }
+
+
+ private DataTable CreateDataTable(ConnectionInfo tableContent)
+ {
+ var serializer = new DataTableSerializer(new SaveFilter());
+ return serializer.Serialize(tableContent);
+ }
+
+ private ConnectionTreeModel CreateConnectionTreeModel()
+ {
+ var builder = new ConnectionTreeModelBuilder();
+ return builder.Build();
+ }
+ }
+}
\ No newline at end of file
diff --git a/mRemoteNGTests/Config/Serializers/DataTableSerializerTests.cs b/mRemoteNGTests/Config/Serializers/DataTableSerializerTests.cs
index a8a5f1f92..17bd78031 100644
--- a/mRemoteNGTests/Config/Serializers/DataTableSerializerTests.cs
+++ b/mRemoteNGTests/Config/Serializers/DataTableSerializerTests.cs
@@ -4,6 +4,7 @@ using mRemoteNG.Container;
using mRemoteNG.Security;
using mRemoteNG.Tree;
using mRemoteNG.Tree.Root;
+using mRemoteNGTests.TestHelpers;
using NUnit.Framework;
namespace mRemoteNGTests.Config.Serializers
@@ -20,13 +21,6 @@ namespace mRemoteNGTests.Config.Serializers
_dataTableSerializer = new DataTableSerializer(_saveFilter);
}
- [TearDown]
- public void Teardown()
- {
- _saveFilter = null;
- _dataTableSerializer = null;
- }
-
[Test]
public void AllItemsSerialized()
{
@@ -35,6 +29,14 @@ namespace mRemoteNGTests.Config.Serializers
Assert.That(dataTable.Rows.Count, Is.EqualTo(3));
}
+ [Test]
+ public void ReturnsEmptyDataTableWhenGivenEmptyConnectionTreeModel()
+ {
+ var model = new ConnectionTreeModel();
+ var dataTable = _dataTableSerializer.Serialize(model);
+ Assert.That(dataTable.Rows.Count, Is.EqualTo(0));
+ }
+
[Test]
public void UsernameSerializedWhenSaveSecurityAllowsIt()
{
@@ -109,20 +111,18 @@ namespace mRemoteNGTests.Config.Serializers
Assert.That(dataTable.Rows[0]["InheritUsername"], Is.False);
}
+ [Test]
+ public void CanSerializeEmptyConnectionInfo()
+ {
+ var dataTable = _dataTableSerializer.Serialize(new ConnectionInfo());
+ Assert.That(dataTable.Rows.Count, Is.EqualTo(1));
+ }
+
private ConnectionTreeModel CreateConnectionTreeModel()
{
- var model = new ConnectionTreeModel();
- var root = new RootNodeInfo(RootNodeType.Connection);
- var folder1 = new ContainerInfo {Name = "folder1", Username = "user1", Domain = "domain1", Password = "password1"};
- var con1 = new ConnectionInfo {Name = "Con1", Username = "user1", Domain = "domain1", Password = "password1" };
- var con2 = new ConnectionInfo {Name = "Con2", Username = "user2", Domain = "domain2", Password = "password2" };
-
- root.AddChild(folder1);
- root.AddChild(con2);
- folder1.AddChild(con1);
- model.AddRootNode(root);
- return model;
+ var builder = new ConnectionTreeModelBuilder();
+ return builder.Build();
}
}
}
\ No newline at end of file
diff --git a/mRemoteNGTests/TestHelpers/ConnectionTreeModelBuilder.cs b/mRemoteNGTests/TestHelpers/ConnectionTreeModelBuilder.cs
new file mode 100644
index 000000000..efe99b634
--- /dev/null
+++ b/mRemoteNGTests/TestHelpers/ConnectionTreeModelBuilder.cs
@@ -0,0 +1,25 @@
+using mRemoteNG.Connection;
+using mRemoteNG.Container;
+using mRemoteNG.Tree;
+using mRemoteNG.Tree.Root;
+
+namespace mRemoteNGTests.TestHelpers
+{
+ public class ConnectionTreeModelBuilder
+ {
+ public ConnectionTreeModel Build()
+ {
+ var model = new ConnectionTreeModel();
+ var root = new RootNodeInfo(RootNodeType.Connection);
+ var folder1 = new ContainerInfo { Name = "folder1", Username = "user1", Domain = "domain1", Password = "password1" };
+ var con1 = new ConnectionInfo { Name = "Con1", Username = "user1", Domain = "domain1", Password = "password1" };
+ var con2 = new ConnectionInfo { Name = "Con2", Username = "user2", Domain = "domain2", Password = "password2" };
+
+ root.AddChild(folder1);
+ root.AddChild(con2);
+ folder1.AddChild(con1);
+ model.AddRootNode(root);
+ return model;
+ }
+ }
+}
\ No newline at end of file
diff --git a/mRemoteNGTests/mRemoteNGTests.csproj b/mRemoteNGTests/mRemoteNGTests.csproj
index 7c2310353..3336bf9e4 100644
--- a/mRemoteNGTests/mRemoteNGTests.csproj
+++ b/mRemoteNGTests/mRemoteNGTests.csproj
@@ -111,6 +111,7 @@
+
@@ -129,6 +130,7 @@
+
diff --git a/mRemoteV1/App/NativeMethods.cs b/mRemoteV1/App/NativeMethods.cs
index 41127e1ee..44aa0b96f 100644
--- a/mRemoteV1/App/NativeMethods.cs
+++ b/mRemoteV1/App/NativeMethods.cs
@@ -1,6 +1,9 @@
using System;
using System.Drawing;
+using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
+using System.Text;
+
#pragma warning disable 169
namespace mRemoteNG.App
@@ -42,11 +45,17 @@ namespace mRemoteNG.App
internal static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
- internal static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, System.Text.StringBuilder lParam);
+ internal static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, StringBuilder lParam);
+
+ [DllImport("user32.dll", CharSet = CharSet.Unicode)]
+ internal static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, string lParam);
+
+ [DllImport("user32.dll", CharSet = CharSet.Unicode)]
+ internal static extern IntPtr SendMessage([In] IntPtr hWnd, [In] uint msg, [Out] StringBuilder wParam, [In] IntPtr lParam);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern IntPtr SetClipboardViewer(IntPtr hWndNewViewer);
-
+
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool SetForegroundWindow(IntPtr hWnd);
@@ -76,6 +85,10 @@ namespace mRemoteNG.App
[DllImport("user32", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)]
internal static extern bool SetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
+
+ [DllImport("kernel32", SetLastError = true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static extern bool CloseHandle(IntPtr handle);
#endregion
#region Structures
@@ -286,7 +299,10 @@ namespace mRemoteNG.App
public const int WA_ACTIVE = 0x1;
///
- ///
+ /// Sent to both the window being activated and the window being deactivated.
+ /// If the windows use the same input queue, the message is sent synchronously, first to the window procedure of the
+ /// top-level window being deactivated, then to the window procedure of the top-level window being activated. If the
+ /// windows use different input queues, the message is sent asynchronously, so the window is activated immediately.
///
public const int WA_CLICKACTIVE = 0x2;
#endregion
@@ -455,6 +471,12 @@ namespace mRemoteNG.App
public const int VK_C = 0x67;
#endregion
+ #region EM
+ public const uint ECM_FIRST = 0x1500;
+ public const uint EM_SETCUEBANNER = ECM_FIRST + 1;
+ public const uint EM_GETCUEBANNER = ECM_FIRST + 2;
+ #endregion
+
#region LB
public const int LB_ERR = -1;
public const int LB_SELECTSTRING = 0x18C;
diff --git a/mRemoteV1/Config/Putty/AbstractPuttySessionsProvider.cs b/mRemoteV1/Config/Putty/AbstractPuttySessionsProvider.cs
index cbd5d443c..dad5a27ca 100644
--- a/mRemoteV1/Config/Putty/AbstractPuttySessionsProvider.cs
+++ b/mRemoteV1/Config/Putty/AbstractPuttySessionsProvider.cs
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
+using System.Web;
using mRemoteNG.Connection;
using mRemoteNG.Tree.Root;
@@ -42,7 +43,8 @@ namespace mRemoteNG.Config.Putty
private IEnumerable GetSessionToRemove(IEnumerable sessionNamesFromProvider)
{
var currentlyKnownSessionNames = Sessions.Select(session => session.Name);
- var sessionNamesToRemove = currentlyKnownSessionNames.Except(sessionNamesFromProvider);
+ var normalizedSessionNames = sessionNamesFromProvider.Select(HttpUtility.UrlDecode);
+ var sessionNamesToRemove = currentlyKnownSessionNames.Except(normalizedSessionNames);
return Sessions.Where(session => sessionNamesToRemove.Contains(session.Name));
}
diff --git a/mRemoteV1/Config/Putty/PuttySessionsRegistryProvider.cs b/mRemoteV1/Config/Putty/PuttySessionsRegistryProvider.cs
index 402a32016..1aa2c931b 100644
--- a/mRemoteV1/Config/Putty/PuttySessionsRegistryProvider.cs
+++ b/mRemoteV1/Config/Putty/PuttySessionsRegistryProvider.cs
@@ -31,7 +31,7 @@ namespace mRemoteNG.Config.Putty
if (raw && !sessionNames.Contains("Default%20Settings"))
sessionNames.Insert(0, "Default%20Settings");
- else if (!sessionNames.Contains("Default Settings"))
+ else if (!raw && !sessionNames.Contains("Default Settings"))
sessionNames.Insert(0, "Default Settings");
return sessionNames.ToArray();
diff --git a/mRemoteV1/Config/Serializers/DataTableDeserializer.cs b/mRemoteV1/Config/Serializers/DataTableDeserializer.cs
index 5b6b4888d..31df1aa2b 100644
--- a/mRemoteV1/Config/Serializers/DataTableDeserializer.cs
+++ b/mRemoteV1/Config/Serializers/DataTableDeserializer.cs
@@ -43,10 +43,16 @@ namespace mRemoteNG.Config.Serializers
var nodeList = new List();
foreach (DataRow row in _dataTable.Rows)
{
- if ((string)row["Type"] == "Connection")
+ // ReSharper disable once SwitchStatementMissingSomeCases
+ switch ((string)row["Type"])
+ {
+ case "Connection":
nodeList.Add(DeserializeConnectionInfo(row));
- else if ((string)row["Type"] == "Container")
+ break;
+ case "Container":
nodeList.Add(DeserializeContainerInfo(row));
+ break;
+ }
}
return nodeList;
}
@@ -69,8 +75,15 @@ namespace mRemoteNG.Config.Serializers
{
connectionInfo.Name = (string)dataRow["Name"];
connectionInfo.ConstantID = (string)dataRow["ConstantID"];
+
+ // This throws a NPE - Parent is a connectionInfo object which will be null at this point.
+ // The Parent object is linked properly later in CreateNodeHierarchy()
//connectionInfo.Parent.ConstantID = (string)dataRow["ParentID"];
- //connectionInfo is ContainerInfo ? ((ContainerInfo)connectionInfo).IsExpanded.ToString() : "" = dataRow["Expanded"];
+
+ var info = connectionInfo as ContainerInfo;
+ if(info != null)
+ info.IsExpanded = (bool)dataRow["Expanded"];
+
connectionInfo.Description = (string)dataRow["Description"];
connectionInfo.Icon = (string)dataRow["Icon"];
connectionInfo.Panel = (string)dataRow["Panel"];
@@ -195,7 +208,7 @@ namespace mRemoteNG.Config.Serializers
var id = (string) row["ConstantID"];
var connectionInfo = connectionList.First(node => node.ConstantID == id);
var parentId = (string) row["ParentID"];
- if (parentId == "0")
+ if (parentId == "0" || connectionList.All(node => node.ConstantID != parentId))
rootNode.AddChild(connectionInfo);
else
(connectionList.First(node => node.ConstantID == parentId) as ContainerInfo)?.AddChild(connectionInfo);
diff --git a/mRemoteV1/Config/Serializers/DataTableSerializer.cs b/mRemoteV1/Config/Serializers/DataTableSerializer.cs
index 22a1ceb8f..21ddbee80 100644
--- a/mRemoteV1/Config/Serializers/DataTableSerializer.cs
+++ b/mRemoteV1/Config/Serializers/DataTableSerializer.cs
@@ -25,147 +25,162 @@ namespace mRemoteNG.Config.Serializers
public DataTable Serialize(ConnectionTreeModel connectionTreeModel)
{
- var rootNode = (RootNodeInfo)connectionTreeModel.RootNodes.First(node => node is RootNodeInfo);
- return Serialize(rootNode);
+ try
+ {
+ _dataTable = BuildTable();
+ _currentNodeIndex = 0;
+ var rootNode = connectionTreeModel.RootNodes.First(node => node is RootNodeInfo);
+ return Serialize(rootNode);
+ }
+ catch
+ {
+ return _dataTable;
+ }
}
public DataTable Serialize(ConnectionInfo serializationTarget)
{
- _dataTable = new DataTable(TableName);
- CreateSchema();
- SetPrimaryKey();
+ _dataTable = BuildTable();
_currentNodeIndex = 0;
SerializeNodesRecursive(serializationTarget);
return _dataTable;
}
- private void CreateSchema()
+ private DataTable BuildTable()
{
- // Note: these columns must be defined in the same order that they exist in the DB
- _dataTable.Columns.Add("ID", typeof(int));
- _dataTable.Columns[0].AutoIncrement = true;
- _dataTable.Columns.Add("ConstantID", typeof(string));
- _dataTable.Columns.Add("PositionID", typeof(int));
- _dataTable.Columns.Add("ParentID", typeof(string));
- _dataTable.Columns.Add("LastChange", typeof(SqlDateTime));
- _dataTable.Columns.Add("Name", typeof(string));
- _dataTable.Columns.Add("Type", typeof(string));
- _dataTable.Columns.Add("Expanded", typeof(bool));
- _dataTable.Columns.Add("Description", typeof(string));
- _dataTable.Columns.Add("Icon", typeof(string));
- _dataTable.Columns.Add("Panel", typeof(string));
- _dataTable.Columns.Add("Username", typeof(string));
- _dataTable.Columns.Add("DomainName", typeof(string));
- _dataTable.Columns.Add("Password", typeof(string));
- _dataTable.Columns.Add("Hostname", typeof(string));
- _dataTable.Columns.Add("Protocol", typeof(string));
- _dataTable.Columns.Add("PuttySession", typeof(string));
- _dataTable.Columns.Add("Port", typeof(int));
- _dataTable.Columns.Add("ConnectToConsole", typeof(bool));
- _dataTable.Columns.Add("UseCredSsp", typeof(bool));
- _dataTable.Columns.Add("RenderingEngine", typeof(string));
- _dataTable.Columns.Add("ICAEncryptionStrength", typeof(string));
- _dataTable.Columns.Add("RDPAuthenticationLevel", typeof(string));
- _dataTable.Columns.Add("Colors", typeof(string));
- _dataTable.Columns.Add("Resolution", typeof(string));
- _dataTable.Columns.Add("DisplayWallpaper", typeof(bool));
- _dataTable.Columns.Add("DisplayThemes", typeof(bool));
- _dataTable.Columns.Add("EnableFontSmoothing", typeof(bool));
- _dataTable.Columns.Add("EnableDesktopComposition", typeof(bool));
- _dataTable.Columns.Add("CacheBitmaps", typeof(bool));
- _dataTable.Columns.Add("RedirectDiskDrives", typeof(bool));
- _dataTable.Columns.Add("RedirectPorts", typeof(bool));
- _dataTable.Columns.Add("RedirectPrinters", typeof(bool));
- _dataTable.Columns.Add("RedirectSmartCards", typeof(bool));
- _dataTable.Columns.Add("RedirectSound", typeof(string));
- _dataTable.Columns.Add("RedirectKeys", typeof(bool));
- _dataTable.Columns.Add("Connected", typeof(bool));
- _dataTable.Columns.Add("PreExtApp", typeof(string));
- _dataTable.Columns.Add("PostExtApp", typeof(string));
- _dataTable.Columns.Add("MacAddress", typeof(string));
- _dataTable.Columns.Add("UserField", typeof(string));
- _dataTable.Columns.Add("ExtApp", typeof(string));
- _dataTable.Columns.Add("VNCCompression", typeof(string));
- _dataTable.Columns.Add("VNCEncoding", typeof(string));
- _dataTable.Columns.Add("VNCAuthMode", typeof(string));
- _dataTable.Columns.Add("VNCProxyType", typeof(string));
- _dataTable.Columns.Add("VNCProxyIP", typeof(string));
- _dataTable.Columns.Add("VNCProxyPort", typeof(int));
- _dataTable.Columns.Add("VNCProxyUsername", typeof(string));
- _dataTable.Columns.Add("VNCProxyPassword", typeof(string));
- _dataTable.Columns.Add("VNCColors", typeof(string));
- _dataTable.Columns.Add("VNCSmartSizeMode", typeof(string));
- _dataTable.Columns.Add("VNCViewOnly", typeof(bool));
- _dataTable.Columns.Add("RDGatewayUsageMethod", typeof(string));
- _dataTable.Columns.Add("RDGatewayHostname", typeof(string));
- _dataTable.Columns.Add("RDGatewayUseConnectionCredentials", typeof(string));
- _dataTable.Columns.Add("RDGatewayUsername", typeof(string));
- _dataTable.Columns.Add("RDGatewayPassword", typeof(string));
- _dataTable.Columns.Add("RDGatewayDomain", typeof(string));
- _dataTable.Columns.Add("InheritCacheBitmaps", typeof(bool));
- _dataTable.Columns.Add("InheritColors", typeof(bool));
- _dataTable.Columns.Add("InheritDescription", typeof(bool));
- _dataTable.Columns.Add("InheritDisplayThemes", typeof(bool));
- _dataTable.Columns.Add("InheritDisplayWallpaper", typeof(bool));
- _dataTable.Columns.Add("InheritEnableFontSmoothing", typeof(bool));
- _dataTable.Columns.Add("InheritEnableDesktopComposition", typeof(bool));
- _dataTable.Columns.Add("InheritDomain", typeof(bool));
- _dataTable.Columns.Add("InheritIcon", typeof(bool));
- _dataTable.Columns.Add("InheritPanel", typeof(bool));
- _dataTable.Columns.Add("InheritPassword", typeof(bool));
- _dataTable.Columns.Add("InheritPort", typeof(bool));
- _dataTable.Columns.Add("InheritProtocol", typeof(bool));
- _dataTable.Columns.Add("InheritPuttySession", typeof(bool));
- _dataTable.Columns.Add("InheritRedirectDiskDrives", typeof(bool));
- _dataTable.Columns.Add("InheritRedirectKeys", typeof(bool));
- _dataTable.Columns.Add("InheritRedirectPorts", typeof(bool));
- _dataTable.Columns.Add("InheritRedirectPrinters", typeof(bool));
- _dataTable.Columns.Add("InheritRedirectSmartCards", typeof(bool));
- _dataTable.Columns.Add("InheritRedirectSound", typeof(bool));
- _dataTable.Columns.Add("InheritResolution", typeof(bool));
- _dataTable.Columns.Add("InheritUseConsoleSession", typeof(bool));
- _dataTable.Columns.Add("InheritUseCredSsp", typeof(bool));
- _dataTable.Columns.Add("InheritRenderingEngine", typeof(bool));
- _dataTable.Columns.Add("InheritICAEncryptionStrength", typeof(bool));
- _dataTable.Columns.Add("InheritRDPAuthenticationLevel", typeof(bool));
- _dataTable.Columns.Add("InheritUsername", typeof(bool));
- _dataTable.Columns.Add("InheritPreExtApp", typeof(bool));
- _dataTable.Columns.Add("InheritPostExtApp", typeof(bool));
- _dataTable.Columns.Add("InheritMacAddress", typeof(bool));
- _dataTable.Columns.Add("InheritUserField", typeof(bool));
- _dataTable.Columns.Add("InheritExtApp", typeof(bool));
- _dataTable.Columns.Add("InheritVNCCompression", typeof(bool));
- _dataTable.Columns.Add("InheritVNCEncoding", typeof(bool));
- _dataTable.Columns.Add("InheritVNCAuthMode", typeof(bool));
- _dataTable.Columns.Add("InheritVNCProxyType", typeof(bool));
- _dataTable.Columns.Add("InheritVNCProxyIP", typeof(bool));
- _dataTable.Columns.Add("InheritVNCProxyPort", typeof(bool));
- _dataTable.Columns.Add("InheritVNCProxyUsername", typeof(bool));
- _dataTable.Columns.Add("InheritVNCProxyPassword", typeof(bool));
- _dataTable.Columns.Add("InheritVNCColors", typeof(bool));
- _dataTable.Columns.Add("InheritVNCSmartSizeMode", typeof(bool));
- _dataTable.Columns.Add("InheritVNCViewOnly", typeof(bool));
- _dataTable.Columns.Add("InheritRDGatewayUsageMethod", typeof(bool));
- _dataTable.Columns.Add("InheritRDGatewayHostname", typeof(bool));
- _dataTable.Columns.Add("InheritRDGatewayUseConnectionCredentials", typeof(bool));
- _dataTable.Columns.Add("InheritRDGatewayUsername", typeof(bool));
- _dataTable.Columns.Add("InheritRDGatewayPassword", typeof(bool));
- _dataTable.Columns.Add("InheritRDGatewayDomain", typeof(bool));
- _dataTable.Columns.Add("LoadBalanceInfo", typeof(string));
- _dataTable.Columns.Add("AutomaticResize", typeof(bool));
- _dataTable.Columns.Add("InheritLoadBalanceInfo", typeof(bool));
- _dataTable.Columns.Add("InheritAutomaticResize", typeof(bool));
- _dataTable.Columns.Add("RDPMinutesToIdleTimeout", typeof(int));
- _dataTable.Columns.Add("RDPAlertIdleTimeout", typeof(bool));
- _dataTable.Columns.Add("SoundQuality", typeof(string));
- _dataTable.Columns.Add("InheritRDPMinutesToIdleTimeout", typeof(bool));
- _dataTable.Columns.Add("InheritRDPAlertIdleTimeout", typeof(bool));
- _dataTable.Columns.Add("InheritSoundQuality", typeof(bool));
+ var dataTable = new DataTable(TableName);
+ CreateSchema(dataTable);
+ SetPrimaryKey(dataTable);
+ return dataTable;
}
- private void SetPrimaryKey()
+ private void CreateSchema(DataTable dataTable)
{
- _dataTable.PrimaryKey = new[] { _dataTable.Columns["ConstantID"] };
+ // Note: these columns must be defined in the same order that they exist in the DB
+ dataTable.Columns.Add("ID", typeof(int));
+ dataTable.Columns[0].AutoIncrement = true;
+ dataTable.Columns.Add("ConstantID", typeof(string));
+ dataTable.Columns.Add("PositionID", typeof(int));
+ dataTable.Columns.Add("ParentID", typeof(string));
+ dataTable.Columns.Add("LastChange", typeof(SqlDateTime));
+ dataTable.Columns.Add("Name", typeof(string));
+ dataTable.Columns.Add("Type", typeof(string));
+ dataTable.Columns.Add("Expanded", typeof(bool));
+ dataTable.Columns.Add("Description", typeof(string));
+ dataTable.Columns.Add("Icon", typeof(string));
+ dataTable.Columns.Add("Panel", typeof(string));
+ dataTable.Columns.Add("Username", typeof(string));
+ dataTable.Columns.Add("DomainName", typeof(string));
+ dataTable.Columns.Add("Password", typeof(string));
+ dataTable.Columns.Add("Hostname", typeof(string));
+ dataTable.Columns.Add("Protocol", typeof(string));
+ dataTable.Columns.Add("PuttySession", typeof(string));
+ dataTable.Columns.Add("Port", typeof(int));
+ dataTable.Columns.Add("ConnectToConsole", typeof(bool));
+ dataTable.Columns.Add("UseCredSsp", typeof(bool));
+ dataTable.Columns.Add("RenderingEngine", typeof(string));
+ dataTable.Columns.Add("ICAEncryptionStrength", typeof(string));
+ dataTable.Columns.Add("RDPAuthenticationLevel", typeof(string));
+ dataTable.Columns.Add("Colors", typeof(string));
+ dataTable.Columns.Add("Resolution", typeof(string));
+ dataTable.Columns.Add("DisplayWallpaper", typeof(bool));
+ dataTable.Columns.Add("DisplayThemes", typeof(bool));
+ dataTable.Columns.Add("EnableFontSmoothing", typeof(bool));
+ dataTable.Columns.Add("EnableDesktopComposition", typeof(bool));
+ dataTable.Columns.Add("CacheBitmaps", typeof(bool));
+ dataTable.Columns.Add("RedirectDiskDrives", typeof(bool));
+ dataTable.Columns.Add("RedirectPorts", typeof(bool));
+ dataTable.Columns.Add("RedirectPrinters", typeof(bool));
+ dataTable.Columns.Add("RedirectSmartCards", typeof(bool));
+ dataTable.Columns.Add("RedirectSound", typeof(string));
+ dataTable.Columns.Add("RedirectKeys", typeof(bool));
+ dataTable.Columns.Add("Connected", typeof(bool));
+ dataTable.Columns.Add("PreExtApp", typeof(string));
+ dataTable.Columns.Add("PostExtApp", typeof(string));
+ dataTable.Columns.Add("MacAddress", typeof(string));
+ dataTable.Columns.Add("UserField", typeof(string));
+ dataTable.Columns.Add("ExtApp", typeof(string));
+ dataTable.Columns.Add("VNCCompression", typeof(string));
+ dataTable.Columns.Add("VNCEncoding", typeof(string));
+ dataTable.Columns.Add("VNCAuthMode", typeof(string));
+ dataTable.Columns.Add("VNCProxyType", typeof(string));
+ dataTable.Columns.Add("VNCProxyIP", typeof(string));
+ dataTable.Columns.Add("VNCProxyPort", typeof(int));
+ dataTable.Columns.Add("VNCProxyUsername", typeof(string));
+ dataTable.Columns.Add("VNCProxyPassword", typeof(string));
+ dataTable.Columns.Add("VNCColors", typeof(string));
+ dataTable.Columns.Add("VNCSmartSizeMode", typeof(string));
+ dataTable.Columns.Add("VNCViewOnly", typeof(bool));
+ dataTable.Columns.Add("RDGatewayUsageMethod", typeof(string));
+ dataTable.Columns.Add("RDGatewayHostname", typeof(string));
+ dataTable.Columns.Add("RDGatewayUseConnectionCredentials", typeof(string));
+ dataTable.Columns.Add("RDGatewayUsername", typeof(string));
+ dataTable.Columns.Add("RDGatewayPassword", typeof(string));
+ dataTable.Columns.Add("RDGatewayDomain", typeof(string));
+ dataTable.Columns.Add("InheritCacheBitmaps", typeof(bool));
+ dataTable.Columns.Add("InheritColors", typeof(bool));
+ dataTable.Columns.Add("InheritDescription", typeof(bool));
+ dataTable.Columns.Add("InheritDisplayThemes", typeof(bool));
+ dataTable.Columns.Add("InheritDisplayWallpaper", typeof(bool));
+ dataTable.Columns.Add("InheritEnableFontSmoothing", typeof(bool));
+ dataTable.Columns.Add("InheritEnableDesktopComposition", typeof(bool));
+ dataTable.Columns.Add("InheritDomain", typeof(bool));
+ dataTable.Columns.Add("InheritIcon", typeof(bool));
+ dataTable.Columns.Add("InheritPanel", typeof(bool));
+ dataTable.Columns.Add("InheritPassword", typeof(bool));
+ dataTable.Columns.Add("InheritPort", typeof(bool));
+ dataTable.Columns.Add("InheritProtocol", typeof(bool));
+ dataTable.Columns.Add("InheritPuttySession", typeof(bool));
+ dataTable.Columns.Add("InheritRedirectDiskDrives", typeof(bool));
+ dataTable.Columns.Add("InheritRedirectKeys", typeof(bool));
+ dataTable.Columns.Add("InheritRedirectPorts", typeof(bool));
+ dataTable.Columns.Add("InheritRedirectPrinters", typeof(bool));
+ dataTable.Columns.Add("InheritRedirectSmartCards", typeof(bool));
+ dataTable.Columns.Add("InheritRedirectSound", typeof(bool));
+ dataTable.Columns.Add("InheritResolution", typeof(bool));
+ dataTable.Columns.Add("InheritUseConsoleSession", typeof(bool));
+ dataTable.Columns.Add("InheritUseCredSsp", typeof(bool));
+ dataTable.Columns.Add("InheritRenderingEngine", typeof(bool));
+ dataTable.Columns.Add("InheritICAEncryptionStrength", typeof(bool));
+ dataTable.Columns.Add("InheritRDPAuthenticationLevel", typeof(bool));
+ dataTable.Columns.Add("InheritUsername", typeof(bool));
+ dataTable.Columns.Add("InheritPreExtApp", typeof(bool));
+ dataTable.Columns.Add("InheritPostExtApp", typeof(bool));
+ dataTable.Columns.Add("InheritMacAddress", typeof(bool));
+ dataTable.Columns.Add("InheritUserField", typeof(bool));
+ dataTable.Columns.Add("InheritExtApp", typeof(bool));
+ dataTable.Columns.Add("InheritVNCCompression", typeof(bool));
+ dataTable.Columns.Add("InheritVNCEncoding", typeof(bool));
+ dataTable.Columns.Add("InheritVNCAuthMode", typeof(bool));
+ dataTable.Columns.Add("InheritVNCProxyType", typeof(bool));
+ dataTable.Columns.Add("InheritVNCProxyIP", typeof(bool));
+ dataTable.Columns.Add("InheritVNCProxyPort", typeof(bool));
+ dataTable.Columns.Add("InheritVNCProxyUsername", typeof(bool));
+ dataTable.Columns.Add("InheritVNCProxyPassword", typeof(bool));
+ dataTable.Columns.Add("InheritVNCColors", typeof(bool));
+ dataTable.Columns.Add("InheritVNCSmartSizeMode", typeof(bool));
+ dataTable.Columns.Add("InheritVNCViewOnly", typeof(bool));
+ dataTable.Columns.Add("InheritRDGatewayUsageMethod", typeof(bool));
+ dataTable.Columns.Add("InheritRDGatewayHostname", typeof(bool));
+ dataTable.Columns.Add("InheritRDGatewayUseConnectionCredentials", typeof(bool));
+ dataTable.Columns.Add("InheritRDGatewayUsername", typeof(bool));
+ dataTable.Columns.Add("InheritRDGatewayPassword", typeof(bool));
+ dataTable.Columns.Add("InheritRDGatewayDomain", typeof(bool));
+ dataTable.Columns.Add("LoadBalanceInfo", typeof(string));
+ dataTable.Columns.Add("AutomaticResize", typeof(bool));
+ dataTable.Columns.Add("InheritLoadBalanceInfo", typeof(bool));
+ dataTable.Columns.Add("InheritAutomaticResize", typeof(bool));
+ dataTable.Columns.Add("RDPMinutesToIdleTimeout", typeof(int));
+ dataTable.Columns.Add("RDPAlertIdleTimeout", typeof(bool));
+ dataTable.Columns.Add("SoundQuality", typeof(string));
+ dataTable.Columns.Add("InheritRDPMinutesToIdleTimeout", typeof(bool));
+ dataTable.Columns.Add("InheritRDPAlertIdleTimeout", typeof(bool));
+ dataTable.Columns.Add("InheritSoundQuality", typeof(bool));
+ }
+
+ private void SetPrimaryKey(DataTable dataTable)
+ {
+ dataTable.PrimaryKey = new[] { dataTable.Columns["ConstantID"] };
}
private void SerializeNodesRecursive(ConnectionInfo connectionInfo)
@@ -186,7 +201,7 @@ namespace mRemoteNG.Config.Serializers
dataRow["Name"] = connectionInfo.Name;
dataRow["Type"] = connectionInfo.GetTreeNodeType().ToString();
dataRow["ConstantID"] = connectionInfo.ConstantID;
- dataRow["ParentID"] = connectionInfo.Parent.ConstantID;
+ dataRow["ParentID"] = connectionInfo.Parent?.ConstantID ?? "";
dataRow["PositionID"] = _currentNodeIndex;
dataRow["LastChange"] = (SqlDateTime)DateTime.Now;
var info = connectionInfo as ContainerInfo;
diff --git a/mRemoteV1/Connection/ConnectionInfo.cs b/mRemoteV1/Connection/ConnectionInfo.cs
index 8d00dec50..76b006ae7 100644
--- a/mRemoteV1/Connection/ConnectionInfo.cs
+++ b/mRemoteV1/Connection/ConnectionInfo.cs
@@ -172,7 +172,7 @@ namespace mRemoteNG.Connection
{
var inheritType = Inheritance.GetType();
var inheritPropertyInfo = inheritType.GetProperty(propertyName);
- var inheritPropertyValue = Convert.ToBoolean(inheritPropertyInfo.GetValue(Inheritance, null));
+ var inheritPropertyValue = inheritPropertyInfo != null && Convert.ToBoolean(inheritPropertyInfo.GetValue(Inheritance, null));
return inheritPropertyValue;
}
@@ -180,15 +180,20 @@ namespace mRemoteNG.Connection
{
var connectionInfoType = Parent.GetType();
var parentPropertyInfo = connectionInfoType.GetProperty(propertyName);
+ if (parentPropertyInfo == null)
+ return default(TPropertyType); // shouldn't get here...
var parentPropertyValue = (TPropertyType)parentPropertyInfo.GetValue(Parent, null);
return parentPropertyValue;
+
+
}
private static int GetDefaultPort(ProtocolType protocol)
{
try
{
+ // ReSharper disable once SwitchStatementMissingSomeCases
switch (protocol)
{
case ProtocolType.RDP:
diff --git a/mRemoteV1/Properties/AssemblyInfo.cs b/mRemoteV1/Properties/AssemblyInfo.cs
index 47f6b26ce..263bd9277 100644
--- a/mRemoteV1/Properties/AssemblyInfo.cs
+++ b/mRemoteV1/Properties/AssemblyInfo.cs
@@ -33,7 +33,7 @@ using System.Runtime.InteropServices;
// by using the '*' as shown below:
//
-[assembly: AssemblyVersion("1.75.7003.*")]
+[assembly: AssemblyVersion("1.75.7005.*")]
[assembly:NeutralResourcesLanguageAttribute("en")]
diff --git a/mRemoteV1/Resources/PuTTYNG.exe b/mRemoteV1/Resources/PuTTYNG.exe
index 5749a78b6..0d9c7fc32 100644
Binary files a/mRemoteV1/Resources/PuTTYNG.exe and b/mRemoteV1/Resources/PuTTYNG.exe differ
diff --git a/mRemoteV1/Tools/Tools.SystemMenu.cs b/mRemoteV1/Tools/Tools.SystemMenu.cs
index fdee011fe..227c242a7 100644
--- a/mRemoteV1/Tools/Tools.SystemMenu.cs
+++ b/mRemoteV1/Tools/Tools.SystemMenu.cs
@@ -1,54 +1,92 @@
using System;
using System.Drawing;
-
+using mRemoteNG.App;
+using Microsoft.Win32.SafeHandles;
+// ReSharper disable MemberCanBeMadeStatic.Global
namespace mRemoteNG.Tools
{
- public class SystemMenu
- {
+ public sealed class SystemMenu : SafeHandleZeroOrMinusOneIsInvalid, IDisposable
+ {
[Flags]
public enum Flags
{
- MF_STRING = App.NativeMethods.MF_STRING,
- MF_SEPARATOR = App.NativeMethods.MF_SEPARATOR,
- MF_BYCOMMAND = App.NativeMethods.MF_BYCOMMAND,
- MF_BYPOSITION = App.NativeMethods.MF_BYPOSITION,
- MF_POPUP = App.NativeMethods.MF_POPUP,
- WM_SYSCOMMAND = App.NativeMethods.WM_SYSCOMMAND
+ MF_STRING = NativeMethods.MF_STRING,
+ MF_SEPARATOR = NativeMethods.MF_SEPARATOR,
+ MF_BYCOMMAND = NativeMethods.MF_BYCOMMAND,
+ MF_BYPOSITION = NativeMethods.MF_BYPOSITION,
+ MF_POPUP = NativeMethods.MF_POPUP,
+ WM_SYSCOMMAND = NativeMethods.WM_SYSCOMMAND
}
-
- public IntPtr SystemMenuHandle;
- public IntPtr FormHandle;
-
- public SystemMenu(IntPtr Handle)
+
+ private bool disposed;
+ internal IntPtr SystemMenuHandle;
+ private readonly IntPtr FormHandle;
+
+ public SystemMenu(IntPtr Handle) :base(true)
{
FormHandle = Handle;
- SystemMenuHandle = App.NativeMethods.GetSystemMenu(FormHandle, false);
- }
+ SystemMenuHandle = NativeMethods.GetSystemMenu(FormHandle, false);
+ SetHandle(SystemMenuHandle);
+ }
public void Reset()
{
- SystemMenuHandle = App.NativeMethods.GetSystemMenu(FormHandle, true);
+ SystemMenuHandle = NativeMethods.GetSystemMenu(FormHandle, true);
}
public void AppendMenuItem(IntPtr ParentMenu, Flags Flags, IntPtr ID, string Text)
{
- App.NativeMethods.AppendMenu(ParentMenu, (int)Flags, ID, Text);
+ NativeMethods.AppendMenu(ParentMenu, (int)Flags, ID, Text);
}
public IntPtr CreatePopupMenuItem()
{
- return App.NativeMethods.CreatePopupMenu();
+ return NativeMethods.CreatePopupMenu();
}
public bool InsertMenuItem(IntPtr SysMenu, int Position, Flags Flags, IntPtr SubMenu, string Text)
{
- return App.NativeMethods.InsertMenu(SysMenu, Position, (int)Flags, SubMenu, Text);
+ return NativeMethods.InsertMenu(SysMenu, Position, (int)Flags, SubMenu, Text);
}
public IntPtr SetBitmap(IntPtr Menu, int Position, Flags Flags, Bitmap Bitmap)
{
- return new IntPtr(Convert.ToInt32(App.NativeMethods.SetMenuItemBitmaps(Menu, Position, (int)Flags, Bitmap.GetHbitmap(), Bitmap.GetHbitmap())));
+ return new IntPtr(Convert.ToInt32(NativeMethods.SetMenuItemBitmaps(Menu, Position, (int)Flags, Bitmap.GetHbitmap(), Bitmap.GetHbitmap())));
}
- }
+
+ protected override bool ReleaseHandle()
+ {
+ return NativeMethods.CloseHandle(SystemMenuHandle);
+ }
+
+
+ /* If we don't have the finalizer, then we get this warning: https://msdn.microsoft.com/library/ms182329.aspx (CA2216: Disposable types should declare finalizer)
+ * If we DO have the finalizer, then we get this warning: https://msdn.microsoft.com/library/ms244737.aspx (CA1063: Implement IDisposable correctly)
+ *
+ * Since the handle is likely going to be in use for the entierty of the process, the finalizer isn't very important since when we're calling it
+ * the process is likely exiting. Leaks would be moot once it exits. CA2216 is the lesser of 2 evils as far as I can tell. Suppress.
+ ~SystemMenu()
+ {
+ Dispose(false);
+ }
+ */
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2216:DisposableTypesShouldDeclareFinalizer")]
+ public new void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposed) return;
+ if (!disposing) return;
+
+ ReleaseHandle();
+
+ disposed = true;
+ }
+ }
}
\ No newline at end of file
diff --git a/mRemoteV1/UI/Controls/ConnectionContextMenu.cs b/mRemoteV1/UI/Controls/ConnectionContextMenu.cs
index 9ff0f1457..fd51d65c2 100644
--- a/mRemoteV1/UI/Controls/ConnectionContextMenu.cs
+++ b/mRemoteV1/UI/Controls/ConnectionContextMenu.cs
@@ -717,7 +717,11 @@ namespace mRemoteNG.UI.Controls
private void OnImportFileClicked(object sender, EventArgs e)
{
- var selectedNodeAsContainer = _connectionTree.SelectedNode as ContainerInfo ?? _connectionTree.SelectedNode.Parent;
+ ContainerInfo selectedNodeAsContainer;
+ if (_connectionTree.SelectedNode == null)
+ selectedNodeAsContainer = Runtime.ConnectionTreeModel.RootNodes.First();
+ else
+ selectedNodeAsContainer = _connectionTree.SelectedNode as ContainerInfo ?? _connectionTree.SelectedNode.Parent;
Import.ImportFromFile(selectedNodeAsContainer);
}