diff --git a/src/modules/registrypreview/RegistryPreviewUI/MainWindow.Utilities.cs b/src/modules/registrypreview/RegistryPreviewUI/MainWindow.Utilities.cs index 7c7f08e073..3e89cf8069 100644 --- a/src/modules/registrypreview/RegistryPreviewUI/MainWindow.Utilities.cs +++ b/src/modules/registrypreview/RegistryPreviewUI/MainWindow.Utilities.cs @@ -237,18 +237,24 @@ namespace RegistryPreview // remove the - as we won't need it but it will get special treatment in the UI registryLine = registryLine.Remove(1, 1); + string imageName = DELETEDKEYIMAGE; + CheckKeyLineForBrackets(ref registryLine, ref imageName); + // this is a key, so remove the first [ and last ] registryLine = StripFirstAndLast(registryLine); // 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)) { + string imageName = KEYIMAGE; + CheckKeyLineForBrackets(ref registryLine, ref imageName); + // this is a key, so remove the first [ and last ] registryLine = StripFirstAndLast(registryLine); - treeViewNode = AddTextToTree(registryLine, KEYIMAGE); + treeViewNode = AddTextToTree(registryLine, imageName); } 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 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)) { value = StripFirstAndLast(value); @@ -329,6 +344,32 @@ namespace RegistryPreview registryValue.Type = "REG_MULTI_SZ"; 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 switch (registryValue.Type) @@ -366,6 +407,7 @@ namespace RegistryPreview } registryLine = registryLines[index]; + registryLine = ScanAndRemoveComments(registryLine); registryLine = registryLine.TrimStart(); value += registryLine; } @@ -373,10 +415,25 @@ namespace RegistryPreview // Clean out any escaped characters in the value, only for the preview value = StripEscapedCharacters(value); - // update the ListViewItem with this information - if (registryValue.Type != "ERROR") + // update the ListViewItem with the loaded value, based off REG value type + 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 @@ -400,7 +457,9 @@ namespace RegistryPreview // check to see if anything got parsed! 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); @@ -500,6 +559,7 @@ namespace RegistryPreview private TreeViewNode AddTextToTree(string keys, string image) { string[] individualKeys = keys.Split('\\'); + string fullPath = keys; TreeViewNode returnNewNode = null, newNode = null, previousNode = null; @@ -874,6 +934,9 @@ namespace RegistryPreview case KEYIMAGE: value = resourceLoader.GetString("ToolTipAddedKey"); break; + case ERRORIMAGE: + value = resourceLoader.GetString("ToolTipErrorKey"); + break; } return value; @@ -906,6 +969,73 @@ namespace RegistryPreview registryValue.ToolTipText = value; } + /// + /// Checks a Key line for the closing bracket and treat it as an error if it cannot be found + /// + 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; + } + } + } + + /// + /// 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 + /// + 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; + } + + /// + /// 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. + /// + 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; + } + /// /// Turns the Open Key button in the command bar on/off, depending on if a key is selected /// diff --git a/src/modules/registrypreview/RegistryPreviewUI/Strings/en-US/Resources.resw b/src/modules/registrypreview/RegistryPreviewUI/Strings/en-US/Resources.resw index de20d4c51d..d0b843f39f 100644 --- a/src/modules/registrypreview/RegistryPreviewUI/Strings/en-US/Resources.resw +++ b/src/modules/registrypreview/RegistryPreviewUI/Strings/en-US/Resources.resw @@ -153,6 +153,9 @@ Name + + No valid Keys were found + OK @@ -198,6 +201,9 @@ Value will be deleted + + Key couldn't be parsed + Value has a syntax error @@ -234,4 +240,7 @@ Registry Preview + + (zero-length binary value) + \ No newline at end of file