// ------------------------------------------------------------------ // Cree le node racine dans le RegistryTree. // Retourne Null si la racine est un WrongNode (sans enfants) // ------------------------------------------------------------------ private RegistryItem CreateRootNode(string rootpath) { if (rootpath == string.Empty) { // Vérification : HKLM RegistryItem WrongNode = new RegistryItem("HKLM is not allowed. Try a smaller subtree.", "node"); RegistryTree.Add(WrongNode); return(null); } else if (rootpath.Equals("SECURITY")) { // Vérification : HKLM\SECURITY RegistryItem WrongNode = new RegistryItem("SECURITY subtree is not accessible (reserved access).", "node"); RegistryTree.Add(WrongNode); return(null); } else { // Les vérifications sont OK: On crée le node Racine RegistryItem RacineNode = new RegistryItem(rootpath, "node"); RegistryTree.Add(RacineNode); this.AddToNodeTable(RacineNode, RacineNode.Name); // On memorise le Level de ce Node base.RacineNodeLevel = rootpath.Split('\\').Length; return(RacineNode); } }
// -------------------------------------------- // Ajout d'un sous-item (key ou Node) // -------------------------------------------- public void AddSubItem(RegistryItem subnode) { // On ajoute le subnode à la liste de children SubTitems SubItem.Add(subnode); // On s'enregistre comme parent du subnode subnode.Parent = this; }
// ------------------------------------------------------------------ // Attache le node fourni à son parent. Fonction rapide, si on connait deja le Parent. // ------------------------------------------------------------------ protected void AttachToParentNode(RegistryItem node, RegistryItem parentnode) { if (parentnode is RegistryItem) { parentnode.AddSubItem(node); } }
// ------------------------------------------------------------------ // Attache le node fourni à son parent. On retrouve le parent grace au dictionnaire. // ------------------------------------------------------------------ protected void AttachToParentNode(RegistryItem node, string parentpath) { if (parentpath == string.Empty) { return; } // On cherche le Node Parent dans la table RegistryItem parentNode = this.GetFromNodeTable(parentpath); // Si on le trouve: on lui attache le node if (parentNode != null) { parentNode.AddSubItem(node); } // Si on ne trouve pas le Parent: on en crée un, et on le rattache à son propre parent (grand-parent) else { // On crée un nouveau Node pour le Parent string parentName = this.GetNodeNameFromPath(parentpath); parentNode = new RegistryItem(parentName, "node"); // On le met dans le dictionnaire this.AddToNodeTable(parentNode, parentpath); // On le rattache à son propre parent (le parent du parent) string greatParentPath = GetParentPath(parentpath); this.AttachToParentNode(parentNode, greatParentPath); } }
// ------------------------------------------------------------------ // Cree un Item dans le RegistryTree pour cette Value // ------------------------------------------------------------------ private RegistryItem CreateRegistryKeyFromHive(string keyName, string keyKind, string keyValue) { string KeyDType; if (keyKind.Equals("String", StringComparison.CurrentCultureIgnoreCase)) { KeyDType = "SZ"; } else if (keyKind.Equals("MultiString", StringComparison.CurrentCultureIgnoreCase)) { KeyDType = "MULTI_SZ"; } else if (keyKind.Equals("DWord", StringComparison.CurrentCultureIgnoreCase)) { KeyDType = "DWORD"; } else if (keyKind.Equals("Binary", StringComparison.CurrentCultureIgnoreCase)) { KeyDType = "HEX"; keyValue = "HEX VALUE"; } else { KeyDType = keyKind; keyValue = "unrecognized type"; } KeyDType = "REG_" + KeyDType; // On cree la Key RegistryItem newKey = base.CreateRegistryKey(keyName, KeyDType, keyValue); return(newKey); }
// ------------------------------------------------------------------ // Ajoute le node au dictionnaire // ------------------------------------------------------------------ protected void AddToNodeTable(RegistryItem node, string nodepath) { nodepath = nodepath.ToUpper(); if (!NodepathTable.ContainsKey(nodepath)) { NodepathTable[nodepath] = node; } }
// -------------------------------------------- // Retourne TRUE si le nom ou la valeur de l'item contient le mot recherché (sans tenir compte de la casse) // -------------------------------------------- private bool Predicat(RegistryItem item) { string UpperName = item.Name.ToUpper(); string UpperValue = item.Value.ToUpper(); if (UpperName.Contains(this.SearchedWord) || UpperValue.Contains(this.SearchedWord)) { return(true); } else { return(false); } }
// ------------------------------------------------------------------ // Cree un Item dans le RegistryTree pour les lignes de fichier du type: // Lignes du type: "ErrorLogSizeInKb" = dword:000186A0 // Lignes du type: "Application" = "" // ------------------------------------------------------------------ private RegistryItem CreateRegistryKeyFromFileLine(string keyNameTypeValue) { string[] separator = { "\"" }; // tableau des séparateur. on n'a besoin que d'un seul. string[] splittedString = keyNameTypeValue.Split(separator, 2, StringSplitOptions.RemoveEmptyEntries); string keyName = splittedString[0]; string keyDType = string.Empty; string keyValue = string.Empty; // le reste est alors soit ="string", soit =type:valeur string reste = splittedString[1].Trim('='); if (reste.StartsWith("\"") && reste.EndsWith("\"")) { // Type String. Ex: "valeur" keyDType = "SZ"; keyValue = reste.Trim('"');; } else { int typeSeparatorPos = reste.IndexOf(':'); if (typeSeparatorPos > 0) { keyDType = reste.Substring(0, typeSeparatorPos); string keyRawValue = reste.Substring(typeSeparatorPos + 1); if (keyDType.Equals("dword")) { // Ex: dword:000186A0 string hexValue = "0x" + keyRawValue; // hexa UInt32 intValue = Convert.ToUInt32(hexValue, 16); // on convertit en decimal keyValue = Convert.ToString(intValue); // on convertit en string } else if (keyDType.StartsWith("hex")) { // Ex: hex:0f,be,5a,8d,69,cc,21,0b,67,38,d5,88,27,61,47,9a,24,bc,72,e9,75 keyValue = "HEX VALUE"; } else { keyValue = "unrecognized type"; } } } keyDType = "REG_" + keyDType; // On cree la Key RegistryItem newKey = base.CreateRegistryKey(keyName, keyDType, keyValue); // On incrémente nos compteurs internes TableStats[keyName.Length] += 1; return(newKey); }
// ------------------------------------------------------------------------- // Pour les tests, ce bouton remplit le RegistryTree // ------------------------------------------------------------------------- private void FillRegistryTree(object sender, RoutedEventArgs e) { RegistryItem N1 = new RegistryItem("Node 1", "node"); RegistryItem K1 = new RegistryItem("clef 1", "dword") { Value = "0001" }; RegistryItem K2 = new RegistryItem("clef 2", "dword") { Value = "0002" }; N1.AddSubItem(K1); N1.AddSubItem(K2); RegistryTree1.Add(N1); RegistryItem N2 = new RegistryItem("Node 2", "node"); RegistryItem K3 = new RegistryItem("clef 3", "dword") { Value = "0003" }; N2.AddSubItem(K3); RegistryTree1.Add(N2); RegistryItem N3 = new RegistryItem("SubNode 3", "node"); RegistryItem K4 = new RegistryItem("clef 4", "dword") { Value = "0004" }; N3.AddSubItem(K4); N2.AddSubItem(N3); RegistryItem K5 = new RegistryItem("clef 5", "dword") { Value = "0005" }; RegistryItem K6 = new RegistryItem("clef 6", "dword") { Value = "0006" }; RegistryItem N4 = new RegistryItem("SubNode 4", "node"); N4.AddSubItem(K5); N4.AddSubItem(K6); N2.AddSubItem(N4); DropZone.Visibility = Visibility.Hidden; TreeView1.Visibility = Visibility.Visible; }
// ------------------------------------------------------------------ // Fonction recursive: on lui donne un Node, elle retourne la liste de ses nodes Children // ------------------------------------------------------------------ private List <RegistryItem> BuildNodeList(RegistryItem item) { List <RegistryItem> liste = new List <RegistryItem>(); foreach (RegistryItem child in item.SubItem) { // ajoute les enfants du node courant à liste liste.AddRange(child.SubItem); // Ajoute à la liste les enfants de chaque Child liste.AddRange(this.BuildNodeList(child)); } return(liste); // La liste est détruite chaque fois que l'on sort de la méthode, // mais après qu'elle ait été retournée à la methode appelante (ré-entrance) }
// ------------------------------------------------------------------ // Parcourt de toute la base de registres // Enregistre l'arborescence dans un RegistryTree // Enregistre la liste des Nodes dans un Dictionnaire // ------------------------------------------------------------------ public void ParseHive(string rootPath) { // Si le chemein commence par HKLM, on l'enlève (pour les appels aux fonctions Microsoft) if (rootPath.StartsWith(@"HKLM\")) { rootPath = rootPath.Substring(5, rootPath.Length - 5); } // On commence par vider la collection et le dictionnaire InitParser(); // On cree le node Racine RegistryItem RootNode = this.CreateRootNode(rootPath); // On parcourt le subtree de la base de registres, en commençant par le Node Racine this.CreateChildNodes(RootNode, rootPath); }
// ------------------------------------------------------------------ // Cree un nouveau node et l'ajoute au dictionnaire. // ------------------------------------------------------------------ protected RegistryItem CreateRegistryNode(string nodepath) { string nodeName = this.GetNodeNameFromPath(nodepath); RegistryItem NewNode = new RegistryItem(nodeName, "node"); AddToNodeTable(NewNode, nodepath); NbNodes++; // On determine le Level de ce Node int NodeLevel = nodepath.Split('\\').Length; if (NodeLevel > this._HighestNodeLevel) { this._HighestNodeLevel = NodeLevel; } return(NewNode); }
// ------------------------------------------------------------------ // Cree une nouvelle key // ------------------------------------------------------------------ protected RegistryItem CreateRegistryKey(string keyName, string keyDType, string keyValue) { RegistryItem newKey = new RegistryItem(keyName, keyDType.ToUpper()); if (keyValue.Length > 50) { keyValue = keyValue.Substring(0, 50) + "..."; // On tronque à 50 chars } newKey.Value = keyValue; // Si cette Key possède une unité préférée, on la prend en compte newKey.UserFriendlyUnit = PreferedUnits.GetValue(keyName); newKey.UpdateUserFriendyValue(); // On incrémente nos compteurs internes NbKeys++; return(newKey); }
// ------------------------------------------------------------------------- // Construit une liste des Nodes conduisant à l'Item donné // ------------------------------------------------------------------------- private List <RegistryItem> BuildPathToNode(RegistryItem item) { List <RegistryItem> PathToItem = new List <RegistryItem> { }; if (item != null) { RegistryItem Curseur = item; while (Curseur.Parent is RegistryItem) { PathToItem.Add(Curseur.Parent); Curseur = Curseur.Parent; } PathToItem.Reverse(); } return(PathToItem); }
// ------------------------------------------------------------------------- // Example: Traverse le TreeView pour trouver le TreeViewItem qui correspond à l'item donné. // Pour le premier appel, utiliser: parent = TreeView1 // Exemple d'utilisation: on peut appliquer ExpandSubtree() sur le tvi retourné. // ----------------------------------------------------------------------------------- private TreeViewItem TestFunction(ItemsControl parent, object item) { // Check whether the selected item is a direct child of the parent ItemsControl. TreeViewItem tvi = parent.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem; if (tvi == null) { // Si tvi est nul, c'est que l'item donné n'est pas un child direct du parent. // Donc on verifie pour s'il est un child de l'un des Items enfants du parent. foreach (object child in parent.Items) { // pour chaque enfant du Parent // si ce n'est pas un node: on passe RegistryItem CurrentChild = child as RegistryItem; if (CurrentChild.DType != "node") { continue; } // Si c'est un node: on récupère son TVI TreeViewItem childItem = parent.ItemContainerGenerator.ContainerFromItem(child) as TreeViewItem; if (childItem != null) { // Check the next level for the appropriate item. tvi = TestFunction(childItem, item); } } } else { // le tvi est un child direct de ce parent, donc ont peut expandre le parent TreeViewItem t = parent as TreeViewItem; if (t is TreeViewItem) { t.IsExpanded = true; } } return(tvi); }
// ------------------------------------------------------------------------- // Click sur le bouton ChangeUnit d'un Registry Key du Registry Tree // ------------------------------------------------------------------------- private void Bt_ChangeUnit_Click(object sender, RoutedEventArgs e) { // On retrouve l'item en cours du TreeView var UnitButton = sender as Button; // DataContext renvoie le DataSource du Control RegistryItem Item = UnitButton.DataContext as RegistryItem; // 3 méthodes possibles pour faire un refresh du binding // ((TextBox)sender).GetBindingExpression(ComboBox.TextProperty).UpdateSource(); // Update le DataSource en fonction du Control // ((ComboBox)sender).GetBindingExpression(ComboBox.ItemsSourceProperty).UpdateTarget(); // Update le Control en fonction du DataSource // OnPropertyChanged("Property"); // Style PlainStyle = Application.Current.Resources["PlainStyle"] as Style; // Style OutlinedStyle = Application.Current.Resources["OutlinedStyle"] as Style; // On modifie son unité préférée Item.ChangeToNextUnit(UnitDictionnary); // On raffraichit le texte du bouton "btUfUnit" UnitButton.GetBindingExpression(Button.ContentProperty).UpdateTarget(); // On raffraichit le texte de son frère TextBlock "lbUfValue" var StackP = UnitButton.Parent as StackPanel; var TextB = StackP.Children[3] as TextBlock; TextB.GetBindingExpression(TextBlock.TextProperty).UpdateTarget(); }
// ------------------------------------------------------------------------- // Bouton FIND (barre de recherche) // ------------------------------------------------------------------------- private void Bt_Search_Click(object sender, RoutedEventArgs e) { // On deselectionne les TreeItems pouvant être déjà sélectionnés if ((SearchedWordResults != null) && (SearchedWordResults.Count > 0)) { if (SearchedWordResults[SearchedWordResultsIndex] is RegistryItem) { SearchedWordResults[SearchedWordResultsIndex].IsSelected = false; } } if (SearchedWordIsDirty) // Si on vient de cliquer sur FIND, *après* avoir modifié le SearchedWord { // On lance la recherche Pu_Working.IsOpen = true; // Popup sablier this.SearchedWord = Tb_SearchedWord.Text.ToUpper(); // On recupère la liste des RegistryItems correspondant à la recherche this.SearchedWordResults = Parser1.NodeList.FindAll(Predicat); // On change quelques textes switch (this.SearchedWordResults.Count) { case 0: Lb_SearchedWordCount.Text = "no item found"; Bt_Search.Content = "Find"; break; case 1: Lb_SearchedWordCount.Text = "1 item found"; Bt_Search.Content = "Find"; break; default: Lb_SearchedWordCount.Text = "1/" + this.SearchedWordResults.Count.ToString(); Bt_Search.Content = "Next"; break; } // On sélectionne le premier RegistryItem de la liste this.SearchedWordResultsIndex = 0; this.SearchDirection = 1; } else if ((SearchedWordResults != null) && (SearchedWordResults.Count > 0)) // Si on vient de cliquer sur FIND, *sans* avoir modifié le SearchedWord { // on déselectionne l'item précédent if (SearchedWordResults[SearchedWordResultsIndex] is RegistryItem) { SearchedWordResults[SearchedWordResultsIndex].IsSelected = false; } // On incrémente l'index SearchedWordResultsIndex += SearchDirection; // Vérification des bornes if (SearchedWordResultsIndex < 0) { SearchedWordResultsIndex = SearchedWordResults.Count - 1; } if (SearchedWordResultsIndex >= SearchedWordResults.Count) { SearchedWordResultsIndex = 0; } // On met à jour le No de l'item affiché dans le compteur Lb_SearchedWordCount.Text = (SearchedWordResultsIndex + 1).ToString() + "/" + SearchedWordResults.Count.ToString(); } if (SearchedWordResultsIndex < SearchedWordResults.Count) { RegistryItem Item = SearchedWordResults[SearchedWordResultsIndex]; // On deploie le TreeView jusquà l'item List <RegistryItem> PathToNode = new List <RegistryItem> { }; PathToNode = this.BuildPathToNode(Item); this.ExpandPath(PathToNode); PathToNode.Clear(); // On surligne l'item if (Item is RegistryItem) { Item.IsSelected = true; } } Pu_Working.IsOpen = false; // Popup sablier OFF this.SearchedWordIsDirty = false; Bt_SearchDirection.IsPopupOpen = true; // Affiche les boutons UP/DOWN }
// ------------------------------------------------------------------ // Parse le fichier REG // Enregistre l'arborescence dans un RegistryTree // Enregistre la liste des Nodes dans un Dictionnaire // ------------------------------------------------------------------ public void ParseFile(string fileName) { // On commence par vider la collection et le dictionnaire InitParser(); AverageLabelLength = 0; ModalLabelLength = 0; Array.Clear(TableStats, 0, TableStats.Length); // Vérification if (!fileName.EndsWith(".reg")) { RegistryItem WrongNode = new RegistryItem("Not a REG file", "node"); RegistryTree.Add(WrongNode); return; } // On lit le fichier et on met tout dans une très longue string. // fileName = "E:\\source\\repos\\RegFineViewer\\_example1.reg"; StreamReader streamFile = new StreamReader(File.Open(fileName, FileMode.OpenOrCreate)); string fichier = streamFile.ReadToEnd(); streamFile.Close(); // On decoupe le fichier en un tableau de lignes string[] lignes = fichier.Split('\r', '\n'); // Vérification if (lignes.Length > 50000) { RegistryItem WrongNode = new RegistryItem("The file contains too many lines (max 10.000).", "node"); RegistryTree.Add(WrongNode); return; } // On crée un Node Racine RegistryItem currentNode = new RegistryItem("root", "node"); RegistryTree.Add(currentNode); bool firstNode = true; // On parcourt le tableau des lignes du fichier for (int i = 0; i < lignes.Length; i++) { string ligne = lignes[i]; // On ignore la ligne d'entete if (ligne.StartsWith("Windows Registry Editor")) { } // On ignore les lignes vides else if (ligne.Equals("")) { } // Lignes de type [path\to\node] else if (ligne.StartsWith("[") && ligne.EndsWith("]")) { string nodePath = ligne.Trim('[', ']'); string parentPath = GetParentPath(nodePath); // ---------------------------------------------------------------------- // S'il s'agit du premier node // ---------------------------------------------------------------------- // Le node racine du treeView est le parent du premier node du fichier REG if (firstNode) { if (parentPath != "") { // Pour ce node racine, son nom est le chemin complet du parent currentNode.Name = parentPath; } else { // sauf si le nom du parent est vide... currentNode.Name = nodePath; } // On met le node Racine dans le dictionnaire AddToNodeTable(currentNode, currentNode.Name); // On memorise le Level de ce Node RacineNodeLevel = nodePath.Split('\\').Length - 1; firstNode = false; } // on cree un nouveau node currentNode = CreateRegistryNode(nodePath); // On le rattache à son parent AttachToParentNode(currentNode, parentPath); // on comptabilise sa longueur dans les statistiques TableStats[currentNode.Name.Length] += 1; } // Lignes du type: "ErrorLogSizeInKb" = dword:000186A0 // Lignes du type: "Application" = "" else if (ligne.StartsWith("\"")) { // Si on n'a pas de node courant, on passe. Ca ne devrait pas arriver. if (currentNode != null) { // On cree une Key RegistryItem newKey = CreateRegistryKeyFromFileLine(ligne); // On la rattache au Node courant currentNode.AddSubItem(newKey); } } // Autres cas else { } } }
// ------------------------------------------------------------------ // Cree les Nodes SubKeys et les Values du Node donné // C'est un peut redondant de donner le node et le path, mais ça évite de le recalculer à chaque fois. // ------------------------------------------------------------------ private void CreateChildNodes(RegistryItem ParentNode, string ParentPath) { RegistryKey rk; if (ParentNode == null) { return; } try { rk = Registry.LocalMachine.OpenSubKey(ParentPath); } catch (Exception ex) { RegistryItem WrongNode = new RegistryItem("This registry cannot be read (" + ex.Message + ").", "node"); RegistryTree.Add(WrongNode); return; } if (rk == null) { RegistryItem WrongNode = new RegistryItem("This registry was found null (" + ParentPath + ").", "node"); RegistryTree.Add(WrongNode); return; } string[] SubKeysArray = rk.GetSubKeyNames(); string[] ValuesArray = rk.GetValueNames(); // Traitement des Subkeys: on les ajoute dans l'arborescence foreach (string SubKeyName in SubKeysArray) { // on cree un nouveau node pour chaque SubKey string nodePath = ParentPath + @"\" + SubKeyName; RegistryItem NewNode = base.CreateRegistryNode(nodePath); // On met le node dans le dictionnaire base.AddToNodeTable(NewNode, SubKeyName); // On le rattache à son parent base.AttachToParentNode(NewNode, ParentNode); // On traite ses enfants (recursivité) this.CreateChildNodes(NewNode, nodePath); } // Traitement des Values: on les ajoute dans l'arborescence foreach (string ValueName in ValuesArray) { // On recupère toutes les infos sur cette value string ValueKind = string.Empty; string Value = string.Empty; try { ValueKind = rk.GetValueKind(ValueName).ToString(); } catch (NullReferenceException) { ValueKind = string.Empty; } try { Value = rk.GetValue(ValueName).ToString(); } catch (NullReferenceException) { Value = string.Empty; } // On cree une Key RegistryItem newKey = this.CreateRegistryKeyFromHive(ValueName, ValueKind, Value); // On la rattache à son parent base.AttachToParentNode(newKey, ParentNode); } }