mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-10 05:06:36 +02:00
[Registry Preview] Better parsing for Keys and Values (#25537)
* Better parsing for keys * Minor source fixes Adds a local comment that didn't get saved on a new proc; also adds ERRORIMAGE to the spellcheck expected list. * Better value parsing * Adding support for REG_NONE * Thank you, File Merging tool! * Encore, file merging tool! * Added check for HKEY_ root Note: HKCU shortcuts don't seem to import successfully in the Editor. * Update MainWindow.Utilities.cs Better checking for the root of a Key.
This commit is contained in:
@@ -237,18 +237,24 @@ namespace RegistryPreview
|
|||||||
// remove the - as we won't need it but it will get special treatment in the UI
|
// remove the - as we won't need it but it will get special treatment in the UI
|
||||||
registryLine = registryLine.Remove(1, 1);
|
registryLine = registryLine.Remove(1, 1);
|
||||||
|
|
||||||
|
string imageName = DELETEDKEYIMAGE;
|
||||||
|
CheckKeyLineForBrackets(ref registryLine, ref imageName);
|
||||||
|
|
||||||
// this is a key, so remove the first [ and last ]
|
// this is a key, so remove the first [ and last ]
|
||||||
registryLine = StripFirstAndLast(registryLine);
|
registryLine = StripFirstAndLast(registryLine);
|
||||||
|
|
||||||
// do not track the result of this node, since it should have no children
|
// do not track the result of this node, since it should have no children
|
||||||
AddTextToTree(registryLine, DELETEDKEYIMAGE);
|
AddTextToTree(registryLine, imageName);
|
||||||
}
|
}
|
||||||
else if (registryLine.StartsWith("[", StringComparison.InvariantCulture))
|
else if (registryLine.StartsWith("[", StringComparison.InvariantCulture))
|
||||||
{
|
{
|
||||||
|
string imageName = KEYIMAGE;
|
||||||
|
CheckKeyLineForBrackets(ref registryLine, ref imageName);
|
||||||
|
|
||||||
// this is a key, so remove the first [ and last ]
|
// this is a key, so remove the first [ and last ]
|
||||||
registryLine = StripFirstAndLast(registryLine);
|
registryLine = StripFirstAndLast(registryLine);
|
||||||
|
|
||||||
treeViewNode = AddTextToTree(registryLine, KEYIMAGE);
|
treeViewNode = AddTextToTree(registryLine, imageName);
|
||||||
}
|
}
|
||||||
else if (registryLine.StartsWith("\"", StringComparison.InvariantCulture) && registryLine.EndsWith("=-", StringComparison.InvariantCulture))
|
else if (registryLine.StartsWith("\"", StringComparison.InvariantCulture) && registryLine.EndsWith("=-", StringComparison.InvariantCulture))
|
||||||
{
|
{
|
||||||
@@ -293,7 +299,16 @@ namespace RegistryPreview
|
|||||||
// Create a new listview item that will be used to display the value
|
// Create a new listview item that will be used to display the value
|
||||||
registryValue = new RegistryValue(name, "REG_SZ", string.Empty);
|
registryValue = new RegistryValue(name, "REG_SZ", string.Empty);
|
||||||
|
|
||||||
// if the first and last character is a " then this is a string value; get rid of the first and last "
|
// if the first character is a " then this is a string value, so find the last most " which will avoid comments
|
||||||
|
if (value.StartsWith("\"", StringComparison.InvariantCulture))
|
||||||
|
{
|
||||||
|
int last = value.LastIndexOf("\"", StringComparison.InvariantCulture);
|
||||||
|
if (last >= 0)
|
||||||
|
{
|
||||||
|
value = value.Substring(0, last + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (value.StartsWith("\"", StringComparison.InvariantCulture) && value.EndsWith("\"", StringComparison.InvariantCulture))
|
if (value.StartsWith("\"", StringComparison.InvariantCulture) && value.EndsWith("\"", StringComparison.InvariantCulture))
|
||||||
{
|
{
|
||||||
value = StripFirstAndLast(value);
|
value = StripFirstAndLast(value);
|
||||||
@@ -329,6 +344,32 @@ namespace RegistryPreview
|
|||||||
registryValue.Type = "REG_MULTI_SZ";
|
registryValue.Type = "REG_MULTI_SZ";
|
||||||
value = value.Replace("hex(7):", string.Empty);
|
value = value.Replace("hex(7):", string.Empty);
|
||||||
}
|
}
|
||||||
|
else if (value.StartsWith("hex(0):", StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
registryValue.Type = "REG_NONE";
|
||||||
|
value = value.Replace("hex(0):", string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
// special casing for various key types
|
||||||
|
switch (registryValue.Type)
|
||||||
|
{
|
||||||
|
case "REG_SZ":
|
||||||
|
case "ERROR":
|
||||||
|
|
||||||
|
// no special handling for these two
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// check to see if a continuation marker is the first character
|
||||||
|
if (value == @"\")
|
||||||
|
{
|
||||||
|
// pad the value, so the parsing below is triggered
|
||||||
|
value = @",\";
|
||||||
|
}
|
||||||
|
|
||||||
|
value = ScanAndRemoveComments(value);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Parse for the case where a \ is added immediately after hex is declared
|
// Parse for the case where a \ is added immediately after hex is declared
|
||||||
switch (registryValue.Type)
|
switch (registryValue.Type)
|
||||||
@@ -366,6 +407,7 @@ namespace RegistryPreview
|
|||||||
}
|
}
|
||||||
|
|
||||||
registryLine = registryLines[index];
|
registryLine = registryLines[index];
|
||||||
|
registryLine = ScanAndRemoveComments(registryLine);
|
||||||
registryLine = registryLine.TrimStart();
|
registryLine = registryLine.TrimStart();
|
||||||
value += registryLine;
|
value += registryLine;
|
||||||
}
|
}
|
||||||
@@ -373,10 +415,25 @@ namespace RegistryPreview
|
|||||||
// Clean out any escaped characters in the value, only for the preview
|
// Clean out any escaped characters in the value, only for the preview
|
||||||
value = StripEscapedCharacters(value);
|
value = StripEscapedCharacters(value);
|
||||||
|
|
||||||
// update the ListViewItem with this information
|
// update the ListViewItem with the loaded value, based off REG value type
|
||||||
if (registryValue.Type != "ERROR")
|
switch (registryValue.Type)
|
||||||
{
|
{
|
||||||
registryValue.Value = value;
|
case "ERROR":
|
||||||
|
// do nothing
|
||||||
|
break;
|
||||||
|
case "REG_BINARY":
|
||||||
|
case "REG_NONE":
|
||||||
|
if (value.Length <= 0)
|
||||||
|
{
|
||||||
|
value = resourceLoader.GetString("ZeroLength");
|
||||||
|
}
|
||||||
|
|
||||||
|
registryValue.Value = value;
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
registryValue.Value = value;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update the ToolTip
|
// update the ToolTip
|
||||||
@@ -400,7 +457,9 @@ namespace RegistryPreview
|
|||||||
// check to see if anything got parsed!
|
// check to see if anything got parsed!
|
||||||
if (treeView.RootNodes.Count <= 0)
|
if (treeView.RootNodes.Count <= 0)
|
||||||
{
|
{
|
||||||
ShowMessageBox(APPNAME, App.AppFilename + resourceLoader.GetString("InvalidRegistryFile"), resourceLoader.GetString("OkButtonText"));
|
AddTextToTree(resourceLoader.GetString("NoNodesFoundInFile"), ERRORIMAGE);
|
||||||
|
|
||||||
|
// ShowMessageBox(APPNAME, App.AppFilename + resourceLoader.GetString("InvalidRegistryFile"), resourceLoader.GetString("OkButtonText"));
|
||||||
}
|
}
|
||||||
|
|
||||||
ChangeCursor(gridPreview, false);
|
ChangeCursor(gridPreview, false);
|
||||||
@@ -500,6 +559,7 @@ namespace RegistryPreview
|
|||||||
private TreeViewNode AddTextToTree(string keys, string image)
|
private TreeViewNode AddTextToTree(string keys, string image)
|
||||||
{
|
{
|
||||||
string[] individualKeys = keys.Split('\\');
|
string[] individualKeys = keys.Split('\\');
|
||||||
|
|
||||||
string fullPath = keys;
|
string fullPath = keys;
|
||||||
TreeViewNode returnNewNode = null, newNode = null, previousNode = null;
|
TreeViewNode returnNewNode = null, newNode = null, previousNode = null;
|
||||||
|
|
||||||
@@ -874,6 +934,9 @@ namespace RegistryPreview
|
|||||||
case KEYIMAGE:
|
case KEYIMAGE:
|
||||||
value = resourceLoader.GetString("ToolTipAddedKey");
|
value = resourceLoader.GetString("ToolTipAddedKey");
|
||||||
break;
|
break;
|
||||||
|
case ERRORIMAGE:
|
||||||
|
value = resourceLoader.GetString("ToolTipErrorKey");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
@@ -906,6 +969,73 @@ namespace RegistryPreview
|
|||||||
registryValue.ToolTipText = value;
|
registryValue.ToolTipText = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks a Key line for the closing bracket and treat it as an error if it cannot be found
|
||||||
|
/// </summary>
|
||||||
|
private void CheckKeyLineForBrackets(ref string registryLine, ref string imageName)
|
||||||
|
{
|
||||||
|
// following the current behavior of the registry editor, find the last ] and treat everything else as ignorable
|
||||||
|
int lastBracket = registryLine.LastIndexOf(']');
|
||||||
|
if (lastBracket == -1)
|
||||||
|
{
|
||||||
|
// since we don't have a last bracket yet, add an extra space and continue processing
|
||||||
|
registryLine += " ";
|
||||||
|
imageName = ERRORIMAGE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// having found the last ] and there is text after it, drop the rest of the string on the floor
|
||||||
|
if (lastBracket < registryLine.Length - 1)
|
||||||
|
{
|
||||||
|
registryLine = registryLine.Substring(0, lastBracket + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CheckForKnownGoodBranches(registryLine) == false)
|
||||||
|
{
|
||||||
|
imageName = ERRORIMAGE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Takes a binary registry value, sees if it has a ; and dumps the rest of the line - this does not work for REG_SZ values
|
||||||
|
/// </summary>
|
||||||
|
private string ScanAndRemoveComments(string value)
|
||||||
|
{
|
||||||
|
// scan for comments and remove them
|
||||||
|
int indexOf = value.IndexOf(";", StringComparison.InvariantCulture);
|
||||||
|
if (indexOf > -1)
|
||||||
|
{
|
||||||
|
// presume that there is nothing following the start of the comment
|
||||||
|
value = value.Remove(indexOf, value.Length - indexOf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Make sure the root of a full path start with one of the five "hard coded" roots. Throw an error for the branch if it doesn't.
|
||||||
|
/// </summary>
|
||||||
|
private bool CheckForKnownGoodBranches(string key)
|
||||||
|
{
|
||||||
|
if ((key.StartsWith("[HKEY_CLASSES_ROOT]", StringComparison.InvariantCultureIgnoreCase) == false &&
|
||||||
|
key.StartsWith("[HKEY_CURRENT_USER]", StringComparison.InvariantCultureIgnoreCase) == false &&
|
||||||
|
key.StartsWith("[HKEY_USERS]", StringComparison.InvariantCultureIgnoreCase) == false &&
|
||||||
|
key.StartsWith("[HKEY_LOCAL_MACHINE]", StringComparison.InvariantCultureIgnoreCase) == false &&
|
||||||
|
key.StartsWith("[HKEY_CURRENT_CONFIG]", StringComparison.InvariantCultureIgnoreCase) == false)
|
||||||
|
&&
|
||||||
|
(key.StartsWith(@"[HKEY_CLASSES_ROOT\", StringComparison.InvariantCultureIgnoreCase) == false &&
|
||||||
|
key.StartsWith(@"[HKEY_CURRENT_USER\", StringComparison.InvariantCultureIgnoreCase) == false &&
|
||||||
|
key.StartsWith(@"[HKEY_USERS\", StringComparison.InvariantCultureIgnoreCase) == false &&
|
||||||
|
key.StartsWith(@"[HKEY_LOCAL_MACHINE\", StringComparison.InvariantCultureIgnoreCase) == false &&
|
||||||
|
key.StartsWith(@"[HKEY_CURRENT_CONFIG\", StringComparison.InvariantCultureIgnoreCase) == false))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Turns the Open Key button in the command bar on/off, depending on if a key is selected
|
/// Turns the Open Key button in the command bar on/off, depending on if a key is selected
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -153,6 +153,9 @@
|
|||||||
<data name="NameColumn.Header" xml:space="preserve">
|
<data name="NameColumn.Header" xml:space="preserve">
|
||||||
<value>Name</value>
|
<value>Name</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="NoNodesFoundInFile" xml:space="preserve">
|
||||||
|
<value>No valid Keys were found</value>
|
||||||
|
</data>
|
||||||
<data name="OkButtonText" xml:space="preserve">
|
<data name="OkButtonText" xml:space="preserve">
|
||||||
<value>OK</value>
|
<value>OK</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -198,6 +201,9 @@
|
|||||||
<data name="ToolTipDeletedValue" xml:space="preserve">
|
<data name="ToolTipDeletedValue" xml:space="preserve">
|
||||||
<value>Value will be deleted</value>
|
<value>Value will be deleted</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ToolTipErrorKey" xml:space="preserve">
|
||||||
|
<value>Key couldn't be parsed</value>
|
||||||
|
</data>
|
||||||
<data name="ToolTipErrorValue" xml:space="preserve">
|
<data name="ToolTipErrorValue" xml:space="preserve">
|
||||||
<value>Value has a syntax error</value>
|
<value>Value has a syntax error</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -234,4 +240,7 @@
|
|||||||
<data name="YesNoCancelDialogTitle" xml:space="preserve">
|
<data name="YesNoCancelDialogTitle" xml:space="preserve">
|
||||||
<value>Registry Preview</value>
|
<value>Registry Preview</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ZeroLength" xml:space="preserve">
|
||||||
|
<value>(zero-length binary value)</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
Reference in New Issue
Block a user