using System; using System.Collections.Generic; using System.Linq; using Flow.Launcher.Plugin.WindowsSettings.Classes; namespace Flow.Launcher.Plugin.WindowsSettings.Helper { /// /// Helper class to easier work with the version of the Windows OS /// internal static class UnsupportedSettingsHelper { private const string _keyPath = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"; private const string _keyNameBuild = "CurrentBuild"; private const string _keyNameBuildNumber = "CurrentBuildNumber"; /// /// Remove all of the given list that are not present on the current used Windows build. /// /// The list with to filter. /// A new list with that only contain present Windows settings for this OS. internal static IEnumerable FilterByBuild(in IEnumerable? settingsList) { if (settingsList is null) { return Enumerable.Empty(); } var currentBuild = GetNumericRegistryValue(_keyPath, _keyNameBuild); var currentBuildNumber = GetNumericRegistryValue(_keyPath, _keyNameBuildNumber); if (currentBuild != currentBuildNumber) { var usedValueName = currentBuild != uint.MinValue ? _keyNameBuild : _keyNameBuildNumber; var warningMessage = $"Detecting the Windows version in registry ({_keyPath}) leads to an inconclusive" + $" result ({_keyNameBuild}={currentBuild}, {_keyNameBuildNumber}={currentBuildNumber})!" + $" For resolving the conflict we use the value of '{usedValueName}'."; Log.Warn(warningMessage, typeof(UnsupportedSettingsHelper)); } var currentWindowsBuild = currentBuild != uint.MinValue ? currentBuild : currentBuildNumber; var filteredSettingsList = settingsList.Where(found => (found.DeprecatedInBuild == null || currentWindowsBuild < found.DeprecatedInBuild) && (found.IntroducedInBuild == null || currentWindowsBuild >= found.IntroducedInBuild)); filteredSettingsList = filteredSettingsList.OrderBy(found => found.Name); return filteredSettingsList; } /// /// Return a unsigned numeric value from given registry value name inside the given registry key. /// /// The registry key. /// The name of the registry value. /// A registry value or on error. private static uint GetNumericRegistryValue(in string registryKey, in string valueName) { object? registryValueData; try { registryValueData = Microsoft.Win32.Registry.GetValue(registryKey, valueName, uint.MinValue); } catch (Exception exception) { Log.Exception( $"Can't get registry value for '{valueName}'", exception, typeof(UnsupportedSettingsHelper)); return uint.MinValue; } return uint.TryParse(registryValueData as string, out var buildNumber) ? buildNumber : uint.MinValue; } } }