|
|
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Runtime.InteropServices;
- using System.Text.RegularExpressions;
- using System.Threading.Tasks;
- using Microsoft.Win32;
-
- namespace amecs
- {
- public enum RegistryOperation
- {
- Delete = 0,
- Add = 1
- }
-
- public class Reg
- {
- public class Key
- {
- public string KeyName { get; set; }
-
- //public Scope Scope { get; set; } = Scope.AllUsers;
- public RegistryOperation Operation { get; set; } = RegistryOperation.Delete;
-
- private List<RegistryKey> GetRoots()
- {
- var hive = KeyName.Split('\\').GetValue(0).ToString().ToUpper();
- var list = new List<RegistryKey>();
-
- list.Add(hive switch
- {
- "HKCU" => RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Default),
- "HKEY_CURRENT_USER" => RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Default),
- "HKLM" => RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default),
- "HKEY_LOCAL_MACHINE" => RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default),
- "HKCR" => RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView.Default),
- "HKEY_CLASSES_ROOT" => RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView.Default),
- "HKU" => RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default),
- "HKEY_USERS" => RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default),
- _ => throw new ArgumentException($"Key '{KeyName}' does not specify a valid registry hive.")
- });
- return list;
- }
-
- public string GetSubKey() => KeyName.Substring(KeyName.IndexOf('\\') + 1);
-
- public bool IsEqual()
- {
- try
- {
- var roots = GetRoots();
-
- foreach (var _root in roots)
- {
- var root = _root;
- var subKey = GetSubKey();
- var openedSubKey = root.OpenSubKey(subKey);
-
- if (Operation == RegistryOperation.Delete && openedSubKey != null)
- {
- return false;
- }
-
- if (Operation == RegistryOperation.Add && openedSubKey == null)
- {
- return false;
- }
- }
- } catch (Exception e)
- {
- return false;
- }
-
- return true;
- }
-
- public bool Apply()
- {
- var roots = GetRoots();
-
- foreach (var _root in roots)
- {
- var root = _root;
- var subKey = GetSubKey();
- var openedSubKey = root.OpenSubKey(subKey);
- if (openedSubKey != null) openedSubKey.Close();
-
-
- if (Operation == RegistryOperation.Add && openedSubKey == null)
- {
- root.CreateSubKey(subKey)?.Close();
- }
-
- if (Operation == RegistryOperation.Delete)
- {
- root.DeleteSubKeyTree(subKey, false);
- }
-
- root.Close();
- }
-
- return true;
- }
- }
-
-
- public enum RegistryValueOperation
- {
- Delete = 0,
- Add = 1,
-
- // This indicates to skip the action if the specified value does not already exist
- Set = 2
- }
-
- public enum RegistryValueType
- {
- REG_SZ = RegistryValueKind.String,
- REG_MULTI_SZ = RegistryValueKind.MultiString,
- REG_EXPAND_SZ = RegistryValueKind.ExpandString,
- REG_DWORD = RegistryValueKind.DWord,
- REG_QWORD = RegistryValueKind.QWord,
- REG_BINARY = RegistryValueKind.Binary,
- REG_NONE = RegistryValueKind.None,
- REG_UNKNOWN = RegistryValueKind.Unknown
- }
-
- public class Value
- {
- public string KeyName { get; set; }
-
- public string ValueName { get; set; } = "";
-
- public object? Data { get; set; }
-
- public RegistryValueType Type { get; set; }
-
- //public Scope Scope { get; set; } = Scope.AllUsers;
-
- public RegistryValueOperation Operation { get; set; } = RegistryValueOperation.Add;
-
- private List<RegistryKey> GetRoots()
- {
- var hive = KeyName.Split('\\').GetValue(0).ToString().ToUpper();
- var list = new List<RegistryKey>();
-
- list.Add(hive switch
- {
- "HKCU" => RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Default),
- "HKEY_CURRENT_USER" => RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Default),
- "HKLM" => RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default),
- "HKEY_LOCAL_MACHINE" => RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default),
- "HKCR" => RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView.Default),
- "HKEY_CLASSES_ROOT" => RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView.Default),
- "HKU" => RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default),
- "HKEY_USERS" => RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default),
- _ => throw new ArgumentException($"Key '{KeyName}' does not specify a valid registry hive.")
- });
- return list;
- }
-
- public string GetSubKey() => KeyName.Substring(KeyName.IndexOf('\\') + 1);
-
- public object? GetCurrentValue(RegistryKey root)
- {
- var subkey = GetSubKey();
- return Registry.GetValue(root.Name + "\\" + subkey, ValueName, null);
- }
-
- public static byte[] StringToByteArray(string hex)
- {
- return Enumerable.Range(0, hex.Length)
- .Where(x => x % 2 == 0)
- .Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
- .ToArray();
- }
-
- public bool IsEqual()
- {
- try
- {
- var roots = GetRoots();
-
- foreach (var _root in roots)
- {
- var root = _root;
- var subKey = GetSubKey();
-
- var openedSubKey = root.OpenSubKey(subKey);
-
- if (openedSubKey == null && (Operation == RegistryValueOperation.Set || Operation == RegistryValueOperation.Delete))
- continue;
- if (openedSubKey == null) return false;
-
- var value = openedSubKey.GetValue(ValueName);
-
- if (value == null)
- {
- if (Operation == RegistryValueOperation.Set || Operation == RegistryValueOperation.Delete)
- continue;
-
- return false;
- }
-
- if (Operation == RegistryValueOperation.Delete) return false;
-
- if (Data == null) return false;
-
-
- bool matches;
- try
- {
- matches = Type switch
- {
- RegistryValueType.REG_SZ =>
- Data.ToString() == value.ToString(),
- RegistryValueType.REG_EXPAND_SZ =>
- // RegistryValueOptions.DoNotExpandEnvironmentNames above did not seem to work.
- Environment.ExpandEnvironmentVariables(Data.ToString()) == value.ToString(),
- RegistryValueType.REG_MULTI_SZ =>
- Data.ToString() == "" ? ((string[])value).SequenceEqual(new string[] { }) : ((string[])value).SequenceEqual(Data.ToString().Split(new string[] { "\\0" }, StringSplitOptions.None)),
- RegistryValueType.REG_DWORD =>
- unchecked((int)Convert.ToUInt32(Data)) == (int)value,
- RegistryValueType.REG_QWORD =>
- Convert.ToUInt64(Data) == (ulong)value,
- RegistryValueType.REG_BINARY =>
- ((byte[])value).SequenceEqual(StringToByteArray(Data.ToString())),
- RegistryValueType.REG_NONE =>
- ((byte[])value).SequenceEqual(new byte[0]),
- RegistryValueType.REG_UNKNOWN =>
- Data.ToString() == value.ToString(),
- _ => throw new ArgumentException("Impossible.")
- };
- } catch (InvalidCastException)
- {
- matches = false;
- }
-
- if (!matches) return false;
- }
- } catch (Exception e)
- {
- return false;
- }
-
- return true;
- }
-
- public bool Apply()
- {
- var roots = GetRoots();
-
- foreach (var _root in roots)
- {
- var root = _root;
- var subKey = GetSubKey();
-
- if (GetCurrentValue(root) == Data) continue;
-
- var opened = root.OpenSubKey(subKey);
- if (opened == null && Operation == RegistryValueOperation.Set) continue;
- if (opened == null && Operation == RegistryValueOperation.Add) root.CreateSubKey(subKey)?.Close();
- if (opened != null) opened.Close();
-
- if (Operation == RegistryValueOperation.Delete)
- {
- var key = root.OpenSubKey(subKey, true);
- key?.DeleteValue(ValueName);
- key?.Close();
- root.Close();
- continue;
- }
-
- if (Type == RegistryValueType.REG_BINARY)
- {
- var data = StringToByteArray(Data.ToString());
-
- Registry.SetValue(root.Name + "\\" + subKey, ValueName, data, (RegistryValueKind)Type);
- }
- else if (Type == RegistryValueType.REG_DWORD)
- {
- // DWORD values using the highest bit set fail without this, for example '2962489444'.
- // See https://stackoverflow.com/questions/6608400/how-to-put-a-dword-in-the-registry-with-the-highest-bit-set;
- var value = unchecked((int)Convert.ToUInt32(Data));
- Registry.SetValue(root.Name + "\\" + subKey, ValueName, value, (RegistryValueKind)Type);
- }
- else if (Type == RegistryValueType.REG_QWORD)
- {
- Registry.SetValue(root.Name + "\\" + subKey, ValueName, Convert.ToUInt64(Data), (RegistryValueKind)Type);
- }
- else if (Type == RegistryValueType.REG_NONE)
- {
- byte[] none = new byte[0];
-
- Registry.SetValue(root.Name + "\\" + subKey, ValueName, none, (RegistryValueKind)Type);
- }
- else if (Type == RegistryValueType.REG_MULTI_SZ)
- {
- string[] data;
- if (Data.ToString() == "") data = new string[] { };
- else data = Data.ToString().Split(new string[] { "\\0" }, StringSplitOptions.None);
-
- Registry.SetValue(root.Name + "\\" + subKey, ValueName, data, (RegistryValueKind)Type);
- }
- else
- {
- Registry.SetValue(root.Name + "\\" + subKey, ValueName, Data, (RegistryValueKind)Type);
- }
-
- root.Close();
- }
-
- return true;
- }
- }
-
-
- [DllImport("advapi32.dll", SetLastError = true)]
- static extern int RegLoadKey(IntPtr hKey, string lpSubKey, string lpFile);
-
- [DllImport("advapi32.dll", SetLastError = true)]
- static extern int RegSaveKey(IntPtr hKey, string lpFile, uint securityAttrPtr = 0);
-
- [DllImport("advapi32.dll", SetLastError = true)]
- static extern int RegUnLoadKey(IntPtr hKey, string lpSubKey);
-
- [DllImport("ntdll.dll", SetLastError = true)]
- static extern IntPtr RtlAdjustPrivilege(int Privilege, bool bEnablePrivilege, bool IsThreadPrivilege, out bool PreviousValue);
-
- [DllImport("advapi32.dll")]
- static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, ref UInt64 lpLuid);
-
- [DllImport("advapi32.dll")]
- static extern bool LookupPrivilegeValue(IntPtr lpSystemName, string lpName, ref UInt64 lpLuid);
-
- public static void LoadDefaultUserHive()
- {
- var parentKey = RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default);
-
- IntPtr parentHandle = parentKey.Handle.DangerousGetHandle();
- AcquirePrivileges();
- RegLoadKey(parentHandle, "DefaultUserHive", Environment.ExpandEnvironmentVariables(@"%SYSTEMDRIVE%\Users\Default\NTUSER.dat"));
- parentKey.Close();
- }
-
- public static void UnloadDefaultUserHive()
- {
- var parentKey = RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default);
- AcquirePrivileges();
- RegUnLoadKey(parentKey.Handle.DangerousGetHandle(), "DefaultUserHive");
- parentKey.Close();
- }
-
- public static void AcquirePrivileges()
- {
- ulong luid = 0;
- bool throwaway;
- LookupPrivilegeValue(IntPtr.Zero, "SeRestorePrivilege", ref luid);
- RtlAdjustPrivilege((int)luid, true, true, out throwaway);
- LookupPrivilegeValue(IntPtr.Zero, "SeBackupPrivilege", ref luid);
- RtlAdjustPrivilege((int)luid, true, true, out throwaway);
- }
-
- public static void ReturnPrivileges()
- {
- ulong luid = 0;
- bool throwaway;
- LookupPrivilegeValue(IntPtr.Zero, "SeRestorePrivilege", ref luid);
- RtlAdjustPrivilege((int)luid, false, true, out throwaway);
- LookupPrivilegeValue(IntPtr.Zero, "SeBackupPrivilege", ref luid);
- RtlAdjustPrivilege((int)luid, false, true, out throwaway);
- }
- }
- }
|