using System; using System.Collections.Generic; using Microsoft.Win32; using ProtoBuf; namespace Server.Helper; public class RegistrySeeker { [ProtoContract] public class RegSeekerMatch { [ProtoMember(1)] public string Key { get; set; } [ProtoMember(2)] public RegValueData[] Data { get; set; } [ProtoMember(3)] public bool HasSubKeys { get; set; } public override string ToString() { return $"({Key}:{Data})"; } } [ProtoContract] public class RegValueData { [ProtoMember(1)] public string Name { get; set; } [ProtoMember(2)] public RegistryValueKind Kind { get; set; } [ProtoMember(3)] public byte[] Data { get; set; } } private readonly List _matches; public RegSeekerMatch[] Matches => _matches?.ToArray(); public RegistrySeeker() { _matches = new List(); } public void BeginSeeking(string rootKeyName) { if (!string.IsNullOrEmpty(rootKeyName)) { using (RegistryKey registryKey = GetRootKey(rootKeyName)) { if (registryKey != null && registryKey.Name != rootKeyName) { string name = rootKeyName.Substring(registryKey.Name.Length + 1); using RegistryKey registryKey2 = registryKey.OpenReadonlySubKeySafe(name); if (registryKey2 != null) { Seek(registryKey2); } return; } Seek(registryKey); return; } } Seek(null); } private void Seek(RegistryKey rootKey) { if (rootKey == null) { foreach (RegistryKey rootKey2 in GetRootKeys()) { ProcessKey(rootKey2, rootKey2.Name); } return; } Search(rootKey); } private void Search(RegistryKey rootKey) { string[] subKeyNames = rootKey.GetSubKeyNames(); foreach (string text in subKeyNames) { RegistryKey key = rootKey.OpenReadonlySubKeySafe(text); ProcessKey(key, text); } } private void ProcessKey(RegistryKey key, string keyName) { if (key != null) { List list = new List(); string[] valueNames = key.GetValueNames(); foreach (string name in valueNames) { RegistryValueKind valueKind = key.GetValueKind(name); object value = key.GetValue(name); list.Add(RegistryKeyHelper.CreateRegValueData(name, valueKind, value)); } AddMatch(keyName, RegistryKeyHelper.AddDefaultValue(list), key.SubKeyCount); } else { AddMatch(keyName, RegistryKeyHelper.GetDefaultValues(), 0); } } private void AddMatch(string key, RegValueData[] values, int subkeycount) { RegSeekerMatch item = new RegSeekerMatch { Key = key, Data = values, HasSubKeys = (subkeycount > 0) }; _matches.Add(item); } public static RegistryKey GetRootKey(string subkeyFullPath) { string[] array = subkeyFullPath.Split('\\'); try { return array[0] switch { "HKEY_CLASSES_ROOT" => RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView.Registry64), "HKEY_CURRENT_USER" => RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64), "HKEY_LOCAL_MACHINE" => RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64), "HKEY_USERS" => RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Registry64), "HKEY_CURRENT_CONFIG" => RegistryKey.OpenBaseKey(RegistryHive.CurrentConfig, RegistryView.Registry64), _ => throw new Exception("Invalid rootkey, could not be found."), }; } catch (SystemException) { throw new Exception("Unable to open root registry key, you do not have the needed permissions."); } catch (Exception ex2) { throw ex2; } } public static List GetRootKeys() { List list = new List(); try { list.Add(RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView.Registry64)); list.Add(RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64)); list.Add(RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64)); list.Add(RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Registry64)); list.Add(RegistryKey.OpenBaseKey(RegistryHive.CurrentConfig, RegistryView.Registry64)); return list; } catch (SystemException) { throw new Exception("Could not open root registry keys, you may not have the needed permission"); } catch (Exception ex2) { throw ex2; } } }