Skip to content

Commit

Permalink
[Registry Preview] Better preview in data grid like in Regedit (micro…
Browse files Browse the repository at this point in the history
…soft#28488)

* Fix typo

* Better data grid preview like regedit

* Fix sorting of resource strings

* Add error icons back in

* Remove comments then trim whitespace

* Better string detection
  • Loading branch information
dillydylann committed Sep 21, 2023
1 parent e545291 commit 1de6c7d
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 6 deletions.
124 changes: 120 additions & 4 deletions src/modules/registrypreview/RegistryPreviewUI/MainWindow.Utilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -1036,7 +1152,7 @@ private string ScanAndRemoveComments(string value)
value = value.Remove(indexOf, value.Length - indexOf);
}

return value;
return value.TrimEnd();
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,12 @@
<data name="FilterRegistryName" xml:space="preserve">
<value>Registry files (*.reg)</value>
</data>
<data name="InvalidBinary" xml:space="preserve">
<value>(Invalid binary value)</value>
</data>
<data name="InvalidDword" xml:space="preserve">
<value>(Invalid DWORD (32-bit) value)</value>
</data>
<data name="InvalidQword" xml:space="preserve">
<value>(Invalid QWORD (64-bit) value)</value>
</data>
Expand All @@ -147,6 +153,9 @@
<data name="InvalidRegistryFileTitle" xml:space="preserve">
<value>File was not a Registry file</value>
</data>
<data name="InvalidString" xml:space="preserve">
<value>(Invalid string value)</value>
</data>
<data name="LargeRegistryFile" xml:space="preserve">
<value> is larger than 10MB which is too large for this application.</value>
</data>
Expand Down Expand Up @@ -228,7 +237,7 @@
<value>User Account Control</value>
</data>
<data name="ValueColumn.Header" xml:space="preserve">
<value>Value</value>
<value>Data</value>
</data>
<data name="WriteButton.Label" xml:space="preserve">
<value>Write to Registry</value>
Expand Down

0 comments on commit 1de6c7d

Please sign in to comment.