Skip to content

Commit

Permalink
fix a few more registry related problems/issues
Browse files Browse the repository at this point in the history
  • Loading branch information
gus33000 committed Apr 3, 2024
1 parent 33f3332 commit e974d98
Show file tree
Hide file tree
Showing 3 changed files with 240 additions and 188 deletions.
2 changes: 1 addition & 1 deletion DriverUpdater/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ private static void DriverUpdaterAction(string Definition, string DriverRepo, st
if (upgrade)
{
Logging.Log("Fixing potential registry left overs");
RegistryFixer.FixRegistryPaths(DevicePart);
RegistryLeftoverFixer.FixRegistryPaths(DevicePart);
}

Logging.Log("Enabling Cks");
Expand Down
222 changes: 35 additions & 187 deletions DriverUpdater/RegistryFixer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,21 @@ public static void FixLeftOvers(string DrivePath)
_ = ModifyRegistryForLeftOvers(Path.Combine(DrivePath, "Windows\\System32\\config\\SYSTEM"), Path.Combine(DrivePath, "Windows\\System32\\config\\SOFTWARE"));
}

private static bool IsMatching(string value)
{
return regex.IsMatch(value) && !IsAntiMatching(value);
}

private static bool IsAntiMatching(string value)
{
return antiRegex.IsMatch(value);
}

private static Match GetMatch(string value)
{
return regex.Match(value);
}

private static void FixDriverStorePathsInRegistryValueForLeftOvers(RegistryKey registryKey, string registryValue)
{
// TODO:
Expand All @@ -31,9 +46,9 @@ private static void FixDriverStorePathsInRegistryValueForLeftOvers(RegistryKey r
{
string og = (string)registryKey.GetValue(registryValue);

if (regex.IsMatch(og) && !antiRegex.IsMatch(og))
if (IsMatching(og))
{
string currentValue = regex.Match(og).Value;
string currentValue = GetMatch(og).Value;

Logging.Log($"Deleting Value (String) {currentValue} in {registryKey.Name}\\{registryValue}");

Expand All @@ -51,9 +66,9 @@ private static void FixDriverStorePathsInRegistryValueForLeftOvers(RegistryKey r
{
string og = (string)registryKey.GetValue(registryValue);

if (regex.IsMatch(og) && !antiRegex.IsMatch(og))
if (IsMatching(og))
{
string currentValue = regex.Match(og).Value;
string currentValue = GetMatch(og).Value;

Logging.Log($"Deleting Value (Expand String) {currentValue} in {registryKey.Name}\\{registryValue}");

Expand All @@ -76,9 +91,9 @@ private static void FixDriverStorePathsInRegistryValueForLeftOvers(RegistryKey r

foreach (string og in ogvals)
{
if (regex.IsMatch(og) && !antiRegex.IsMatch(og))
if (IsMatching(og))
{
string currentValue = regex.Match(og).Value;
string currentValue = GetMatch(og).Value;

Logging.Log($"Deleting Value (Multi String) {currentValue} in {registryKey.Name}\\{registryValue}");
updated = true;
Expand All @@ -91,7 +106,7 @@ private static void FixDriverStorePathsInRegistryValueForLeftOvers(RegistryKey r

if (updated)
{
if (newVals.Any())
if (newVals.Count != 0)
{
registryKey.SetValue(registryValue, newVals.ToArray(), RegistryValueType.MultiString);
}
Expand All @@ -116,30 +131,39 @@ private static void CrawlInRegistryKeyForLeftOvers(RegistryKey registryKey)
{
if (registryKey != null)
{

foreach (string subRegistryValue in registryKey.GetValueNames())
{
if (regex.IsMatch(subRegistryValue) && !antiRegex.IsMatch(subRegistryValue))
if (IsMatching(subRegistryValue))
{
Logging.Log($"Deleting Value {registryKey.Name}\\{subRegistryValue}");
registryKey.DeleteValue(subRegistryValue);

continue;
}

if (IsAntiMatching(subRegistryValue))
{
continue;
}

FixDriverStorePathsInRegistryValueForLeftOvers(registryKey, subRegistryValue);
}

foreach (string subRegistryKey in registryKey.GetSubKeyNames())
{
if (regex.IsMatch(subRegistryKey) && !antiRegex.IsMatch(subRegistryKey))
if (IsMatching(subRegistryKey))
{
Logging.Log($"Deleting Sub Key Tree {registryKey.Name}\\{subRegistryKey}");
registryKey.DeleteSubKeyTree(subRegistryKey);

continue;
}

if (IsAntiMatching(subRegistryKey))
{
continue;
}

CrawlInRegistryKeyForLeftOvers(registryKey.OpenSubKey(subRegistryKey));
}
}
Expand Down Expand Up @@ -178,185 +202,9 @@ internal static bool ModifyRegistryForLeftOvers(string systemHivePath, string so
return true;
}

public static void FixRegistryPaths(string DrivePath)
{
// Windows DriverStore directory is located at \Windows\System32\DriverStore\FileRepository
// Drivers are named using the following way acpi.inf_amd64_f8b60f94eae135e9
// While the first and second parts of these names are straight forward (driver inf name + architecture),
// The other part is dependent on the driver signature and thus, if the driver changes, will change.
// Usually this isn't a problem but uninstalling drivers can often leave left overs in the registry, pointing to now incorrect paths
// More over, some drivers will crash if these paths are unfixed. Let's attempt to fix them here.

// First start by getting a list of all driver folder names right now.
string DriverStorePath = Path.Combine(DrivePath, "Windows\\System32\\DriverStore\\FileRepository");
string[] Folders = Directory.EnumerateDirectories(DriverStorePath).Where(x => Directory.EnumerateFiles(x, "*.cat").Any()).Select(x => x.Split('\\').Last()).ToArray();

// Now, create a new array of all folder names, but without the hash dependent part.
Regex[] folderRegexes = Folders.Select(BuildRegexForDriverStoreFolderName).ToArray();

// Now that this is done, process the hives.
_ = ModifyRegistry(Path.Combine(DrivePath, "Windows\\System32\\config\\SYSTEM"), Path.Combine(DrivePath, "Windows\\System32\\config\\SOFTWARE"), Folders, folderRegexes);
}

private static Regex BuildRegexForDriverStoreFolderName(string driverStoreFolderName)
{
string neutralDriverStoreFolderName = string.Join('_', driverStoreFolderName.Split('_')[..driverStoreFolderName.Count(y => y == '_')]) + '_';
string escapedNeutralDriverStoreFolderName = Regex.Escape(neutralDriverStoreFolderName);

return new Regex(escapedNeutralDriverStoreFolderName + "[a-fA-F0-9]{16}");
}

private static void FixDriverStorePathsInRegistryValue(RegistryKey registryKey, string registryValue, string[] currentDriverStoreNames, Regex[] folderRegexes)
{
if (registryKey?.GetValueNames().Any(x => x.Equals(registryValue, StringComparison.InvariantCultureIgnoreCase)) == true)
{
switch (registryKey.GetValueType(registryValue))
{
case RegistryValueType.String:
{
string og = (string)registryKey.GetValue(registryValue);

for (int i = 0; i < folderRegexes.Length; i++)
{
Regex regex = folderRegexes[i];
string matchingString = currentDriverStoreNames[i];

if (regex.IsMatch(og))
{
string currentValue = regex.Match(og).Value;

if (currentValue != matchingString)
{
Logging.Log($"Updated {currentValue} to {matchingString} in {registryKey.Name}\\{registryValue}");

og = og.Replace(currentValue, matchingString);
registryKey.SetValue(registryValue, og, RegistryValueType.String);
break;
}
}
}

break;
}
case RegistryValueType.ExpandString:
{
string og = (string)registryKey.GetValue(registryValue);

for (int i = 0; i < folderRegexes.Length; i++)
{
Regex regex = folderRegexes[i];
string matchingString = currentDriverStoreNames[i];

if (regex.IsMatch(og))
{
string currentValue = regex.Match(og).Value;

if (currentValue != matchingString)
{
Logging.Log($"Updated {currentValue} to {matchingString} in {registryKey.Name}\\{registryValue}");

og = og.Replace(currentValue, matchingString);
registryKey.SetValue(registryValue, og, RegistryValueType.ExpandString);
break;
}
}
}

break;
}
case RegistryValueType.MultiString:
{
string[] ogvals = (string[])registryKey.GetValue(registryValue);

bool updated = false;

for (int j = 0; j < ogvals.Length; j++)
{
string og = ogvals[j];

for (int i = 0; i < folderRegexes.Length; i++)
{
Regex regex = folderRegexes[i];
string matchingString = currentDriverStoreNames[i];

if (regex.IsMatch(og))
{
string currentValue = regex.Match(og).Value;

if (currentValue != matchingString)
{
Logging.Log($"Updated {currentValue} to {matchingString} in {registryKey.Name}\\{registryValue}");

og = og.Replace(currentValue, matchingString);
ogvals[j] = og;
updated = true;
break;
}
}
}
}

if (updated)
{
registryKey.SetValue(registryValue, ogvals, RegistryValueType.MultiString);
}

break;
}
}
}
}

private static void CrawlInRegistryKey(RegistryKey registryKey, string[] currentDriverStoreNames, Regex[] folderRegexes)
{
if (registryKey != null)
{
foreach (string subRegistryValue in registryKey.GetValueNames())
{
FixDriverStorePathsInRegistryValue(registryKey, subRegistryValue, currentDriverStoreNames, folderRegexes);
}
foreach (RegistryKey subRegistryKey in registryKey.SubKeys)
{
CrawlInRegistryKey(subRegistryKey, currentDriverStoreNames, folderRegexes);
}
}
}

internal static bool ModifyRegistry(string systemHivePath, string softwareHivePath, string[] currentDriverStoreNames, Regex[] folderRegexes)
{
try
{
using (RegistryHive hive = new(
File.Open(
systemHivePath,
FileMode.Open,
FileAccess.ReadWrite
), DiscUtils.Streams.Ownership.Dispose))
{
Logging.Log("Processing SYSTEM hive");
CrawlInRegistryKey(hive.Root, currentDriverStoreNames, folderRegexes);
}

using (RegistryHive hive = new(
File.Open(
softwareHivePath,
FileMode.Open,
FileAccess.ReadWrite
), DiscUtils.Streams.Ownership.Dispose))
{
Logging.Log("Processing SOFTWARE hive");
CrawlInRegistryKey(hive.Root, currentDriverStoreNames, folderRegexes);
}
}
catch
{
return false;
}
return true;
}

[GeneratedRegex("""(.*oem[0-9]+\.inf.*)|(.*(QCOM|MSHW|VEN_QCOM&DEV_|VEN_MSHW&DEV_|qcom|mshw|ven_qcom&dev_|ven_mshw&dev_)[0-9A-Fa-f]{4}.*)|(.*surface.*duo.*inf)|(.*\\qc.*)|(.*\\surface.*)""")]
private static partial Regex DeviceRegex();

[GeneratedRegex("""(.*(QCOM|qcom)((24[0-9A-Fa-f][0-9A-Fa-f])|(7002)|((FFE|ffe)[0-9A-Fa-f])).*)|(.*qcap.*)|(.*qcursext.*)|(.*hidspi.*)|(.*ufsstor.*)|(.*sdstor.*)|(.*sdbus.*)|(.*storufs.*)|(.*u..chipidea.*)|(.*u..synopsys.*)|(.*qc.*_i\.inf.*)""")]
private static partial Regex AntiDeviceRegex();
}
Expand Down
Loading

0 comments on commit e974d98

Please sign in to comment.