diff --git a/src/modules/registrypreview/RegistryPreviewUI/MainWindow.Utilities.cs b/src/modules/registrypreview/RegistryPreviewUI/MainWindow.Utilities.cs index 07f0837fdd08..bffaa7a3b66e 100644 --- a/src/modules/registrypreview/RegistryPreviewUI/MainWindow.Utilities.cs +++ b/src/modules/registrypreview/RegistryPreviewUI/MainWindow.Utilities.cs @@ -8,7 +8,9 @@ using System.Diagnostics; using System.Globalization; using System.IO; +using System.Linq; using System.Reflection; +using System.Text; using System.Threading.Tasks; using Microsoft.UI.Input; using Microsoft.UI.Xaml; @@ -413,21 +415,75 @@ private bool ParseRegistryFile(string filenameText) value += registryLine; } - // Clean out any escaped characters in the value, only for the preview - value = StripEscapedCharacters(value); - // update the ListViewItem with the loaded value, based off REG value type switch (registryValue.Type) { case "ERROR": // do nothing break; + case "REG_SZ": + if (value == "\"") + { + // Value is most likely missing an end quote + registryValue.Type = "ERROR"; + value = resourceLoader.GetString("InvalidString"); + } + else + { + for (int i = 1; i < value.Length; i++) + { + if (value[i - 1] == '\\') + { + // Only allow these escape characters + if (value[i] != '"' && value[i] != '\\') + { + registryValue.Type = "ERROR"; + value = resourceLoader.GetString("InvalidString"); + break; + } + + i++; + } + + if (value[i - 1] != '\\' && value[i] == '"') + { + // Don't allow non-escaped quotes + registryValue.Type = "ERROR"; + value = resourceLoader.GetString("InvalidString"); + break; + } + } + + if (registryValue.Type != "ERROR") + { + // Clean out any escaped characters in the value, only for the preview + value = StripEscapedCharacters(value); + } + } + + registryValue.Value = value; + break; case "REG_BINARY": case "REG_NONE": if (value.Length <= 0) { value = resourceLoader.GetString("ZeroLength"); } + else + { + try + { + // Hexes are usually two characters (00), it's invalid if less or more than 2 + var bytes = value.Split(',').Select( + c => c.Length == 2 ? byte.Parse(c, NumberStyles.HexNumber, CultureInfo.InvariantCulture) : throw null); + value = string.Join(' ', bytes.Select(b => b.ToString("x2", CultureInfo.CurrentCulture))); + } + catch + { + registryValue.Type = "ERROR"; + value = resourceLoader.GetString("InvalidBinary"); + } + } registryValue.Value = value; @@ -436,6 +492,19 @@ private bool ParseRegistryFile(string filenameText) if (value.Length <= 0) { registryValue.Type = "ERROR"; + value = resourceLoader.GetString("InvalidDword"); + } + else + { + if (uint.TryParse(value, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out uint dword)) + { + value = $"0x{dword:x8} ({dword})"; + } + else + { + registryValue.Type = "ERROR"; + value = resourceLoader.GetString("InvalidDword"); + } } registryValue.Value = value; @@ -444,8 +513,55 @@ private bool ParseRegistryFile(string filenameText) case "REG_QWORD": if (value.Length <= 0) { + registryValue.Type = "ERROR"; value = resourceLoader.GetString("InvalidQword"); } + else + { + try + { + // Hexes are usually two characters (00), it's invalid if less or more than 2 + var bytes = value.Split(',').Select( + c => c.Length == 2 ? byte.Parse(c, NumberStyles.HexNumber, CultureInfo.InvariantCulture) : throw null).ToArray(); + ulong qword = BitConverter.ToUInt64(bytes); + value = $"0x{qword:x8} ({qword})"; + } + catch + { + registryValue.Type = "ERROR"; + value = resourceLoader.GetString("InvalidQword"); + } + } + + registryValue.Value = value; + break; + case "REG_EXPAND_SZ": + case "REG_MULTI_SZ": + try + { + // Hexes are usually two characters (00), it's invalid if less or more than 2 + var bytes = value.Split(',').Select( + c => c.Length == 2 ? byte.Parse(c, NumberStyles.HexNumber, CultureInfo.InvariantCulture) : throw null).ToArray(); + + if (registryValue.Type == "REG_MULTI_SZ") + { + // Replace zeros (00,00) with spaces + for (int i = 0; i < bytes.Length; i += 2) + { + if (bytes[i] == 0 && bytes[i + 1] == 0) + { + bytes[i] = 0x20; + } + } + } + + value = Encoding.Unicode.GetString(bytes); + } + catch + { + registryValue.Type = "ERROR"; + value = resourceLoader.GetString("InvalidString"); + } registryValue.Value = value; break; @@ -1036,7 +1152,7 @@ private string ScanAndRemoveComments(string value) value = value.Remove(indexOf, value.Length - indexOf); } - return value; + return value.TrimEnd(); } /// diff --git a/src/modules/registrypreview/RegistryPreviewUI/RegistryValue.xaml.cs b/src/modules/registrypreview/RegistryPreviewUI/RegistryValue.xaml.cs index a7df53f1f829..161e9cbeddb2 100644 --- a/src/modules/registrypreview/RegistryPreviewUI/RegistryValue.xaml.cs +++ b/src/modules/registrypreview/RegistryPreviewUI/RegistryValue.xaml.cs @@ -33,7 +33,7 @@ public Uri ImageUri switch (Type) { case "REG_SZ": - case "REG_EXAND_SZ": + case "REG_EXPAND_SZ": case "REG_MULTI_SZ": return uriStringValue; case "ERROR": diff --git a/src/modules/registrypreview/RegistryPreviewUI/Strings/en-US/Resources.resw b/src/modules/registrypreview/RegistryPreviewUI/Strings/en-US/Resources.resw index 6b766a657023..d637b2e1871b 100644 --- a/src/modules/registrypreview/RegistryPreviewUI/Strings/en-US/Resources.resw +++ b/src/modules/registrypreview/RegistryPreviewUI/Strings/en-US/Resources.resw @@ -138,6 +138,12 @@ Registry files (*.reg) + + (Invalid binary value) + + + (Invalid DWORD (32-bit) value) + (Invalid QWORD (64-bit) value) @@ -147,6 +153,9 @@ File was not a Registry file + + (Invalid string value) + is larger than 10MB which is too large for this application. @@ -228,7 +237,7 @@ User Account Control - Value + Data Write to Registry