using ColorControl.Shared.Contracts.NVIDIA; using nspector.Common.Helper; using nspector.Common.Meta; using nspector.Native.NVAPI2; using System.Diagnostics; using System.Text.RegularExpressions; using nvw = nspector.Native.NVAPI2.NvapiDrsWrapper; namespace nspector.Common { public class DrsEvent : EventArgs { public string ProfileName { get; set; } public List>? Settings { get; set; } public bool Handled { get; set; } public bool Result { get; set; } } public class DrsSettingsService : DrsSettingsServiceBase { public event EventHandler? ApplySettings; public event EventHandler? RestoreSetting; public bool ExternalApplySettings => ApplySettings != null; const uint DRS_NGX_FORCE_DLAA = 0x10E41DF4; const uint DRS_NGX_SCALE_RATIO = 0x10E41DF5; private NVDRS_SETTING[] HiddenSettings = new[] { new NVDRS_SETTING { version = nvw.NVDRS_SETTING_VER, settingId = DRS_NGX_FORCE_DLAA, settingType = NVDRS_SETTING_TYPE.NVDRS_DWORD_TYPE, currentValue = new NVDRS_SETTING_UNION { dwordValue = 0u } }, new NVDRS_SETTING { version = nvw.NVDRS_SETTING_VER, settingId = DRS_NGX_SCALE_RATIO, settingType = NVDRS_SETTING_TYPE.NVDRS_DWORD_TYPE, currentValue = new NVDRS_SETTING_UNION { dwordValue = 0u } } }; public DrsSettingsService(DrsSettingsMetaService metaService, DrsDecrypterService decrpterService) : base(metaService, decrpterService) { _baseProfileSettingIds = InitBaseProfileSettingIds(); } private List InitBaseProfileSettingIds() { return DrsSession((hSession) => { var hBaseProfile = GetProfileHandle(hSession, ""); var baseProfileSettings = GetProfileSettings(hSession, hBaseProfile); return baseProfileSettings.Select(x => x.settingId).ToList(); }); } private readonly List _baseProfileSettingIds; private string GetDrsProgramPath() { var nvidiaInstallerFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"NVIDIA Corporation\Installer2"); var driverFolders = Directory.EnumerateDirectories(nvidiaInstallerFolder, "Display.Driver.*"); foreach (var folder in driverFolders) { var fiDbInstaller = new FileInfo(Path.Combine(folder, "dbInstaller.exe")); if (!fiDbInstaller.Exists) continue; var fviDbInstaller = FileVersionInfo.GetVersionInfo(fiDbInstaller.FullName); var fileversion = fviDbInstaller.FileVersion.Replace(".", ""); var driverver = DriverVersion.ToString().Replace(",", "").Replace(".", ""); if (fileversion.EndsWith(driverver)) return fiDbInstaller.DirectoryName; } return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"NVIDIA Corporation\Drs"); } private void RunDrsInitProcess() { var drsPath = GetDrsProgramPath(); var si = new ProcessStartInfo(); si.UseShellExecute = true; si.WorkingDirectory = drsPath; si.Arguments = "-init"; si.FileName = Path.Combine(drsPath, "dbInstaller.exe"); if (!AdminHelper.IsAdmin) si.Verb = "runas"; var p = Process.Start(si); p.WaitForExit(); } public void DeleteAllProfilesHard() { var tmpFile = TempFile.GetTempFileName(); try { File.WriteAllText(tmpFile, "BaseProfile \"Base Profile\"\r\nSelectedGlobalProfile \"Base Profile\"\r\nProfile \"Base Profile\"\r\nShowOn All\r\nProfileType Global\r\nEndProfile\r\n"); DrsSession((hSession) => { LoadSettingsFileEx(hSession, tmpFile); SaveSettings(hSession); }, forceNonGlobalSession: true, preventLoadSettings: true); } finally { if (File.Exists(tmpFile)) File.Delete(tmpFile); } } public void DeleteProfileHard(string profileName) { var tmpFileName = TempFile.GetTempFileName(); try { var tmpFileContent = ""; DrsSession((hSession) => { SaveSettingsFileEx(hSession, tmpFileName); tmpFileContent = File.ReadAllText(tmpFileName); string pattern = "(?\nProfile\\s\"" + Regex.Escape(profileName) + "\".*?EndProfile.*?\n)"; tmpFileContent = Regex.Replace(tmpFileContent, pattern, "", RegexOptions.Singleline); File.WriteAllText(tmpFileName, tmpFileContent); }); if (tmpFileContent != "") { DrsSession((hSession) => { LoadSettingsFileEx(hSession, tmpFileName); SaveSettings(hSession); }); } } finally { if (File.Exists(tmpFileName)) File.Delete(tmpFileName); } } public void DeleteProfile(string profileName) { DrsSession((hSession) => { var hProfile = GetProfileHandle(hSession, profileName); if (hProfile != IntPtr.Zero) { var nvRes = nvw.DRS_DeleteProfile(hSession, hProfile); if (nvRes != NvAPI_Status.NVAPI_OK) throw new NvapiException("DRS_DeleteProfile", nvRes); SaveSettings(hSession); } }); } public List GetProfileNames(ref string baseProfileName, bool enumProfiles = true) { var lstResult = new List(); var tmpBaseProfileName = baseProfileName; DrsSession((hSession) => { var hBase = GetProfileHandle(hSession, null); var baseProfile = GetProfileInfo(hSession, hBase); tmpBaseProfileName = baseProfile.profileName; lstResult.Add("_GLOBAL_DRIVER_PROFILE (" + tmpBaseProfileName + ")"); if (enumProfiles) { var profileHandles = EnumProfileHandles(hSession); foreach (IntPtr hProfile in profileHandles) { var profile = GetProfileInfo(hSession, hProfile); if (profile.isPredefined == 0 || profile.numOfApps > 0) { lstResult.Add(profile.profileName); } } } }); baseProfileName = tmpBaseProfileName; return lstResult; } public string? GetProfileNameByApps(string appName) { string? name = null; DrsSession((hSession) => { var profileHandles = EnumProfileHandles(hSession); foreach (IntPtr hProfile in profileHandles) { var apps = GetProfileApplications(hSession, hProfile, true); if (apps?.Any(a => a.appName.Equals(appName, StringComparison.OrdinalIgnoreCase)) == true) { var profile = GetProfileInfo(hSession, hProfile); name = profile.profileName; break; } } }); return name; } public List GetProfileNamesByApps(List appNames) { var profiles = new List(); DrsSession((hSession) => { var profileHandles = EnumProfileHandles(hSession); foreach (IntPtr hProfile in profileHandles) { var apps = GetProfileApplications(hSession, hProfile, true); if (apps?.Any(a => appNames.Any(pn => a.appName.Contains(pn, StringComparison.OrdinalIgnoreCase))) == true) { var profile = GetProfileInfo(hSession, hProfile); var nvProfile = new NvProfile { Name = profile.profileName, Apps = apps.Select(a => a.appName).ToList() }; profiles.Add(nvProfile); } } }); return profiles; } public void CreateProfile(string profileName, string? applicationName = null) { DrsSession((hSession) => { var hProfile = CreateProfile(hSession, profileName); if (applicationName != null) AddApplication(hSession, hProfile, applicationName); SaveSettings(hSession); }); } public void ResetAllProfilesInternal() { RunDrsInitProcess(); DrsSession((hSession) => { var nvRes = nvw.DRS_RestoreAllDefaults(hSession); if (nvRes != NvAPI_Status.NVAPI_OK) throw new NvapiException("DRS_RestoreAllDefaults", nvRes); SaveSettings(hSession); }); } public void ResetProfile(string profileName, out bool removeFromModified) { bool tmpRemoveFromModified = false; DrsSession((hSession) => { var hProfile = GetProfileHandle(hSession, profileName); var profile = GetProfileInfo(hSession, hProfile); if (profile.isPredefined == 1) { var nvRes = nvw.DRS_RestoreProfileDefault(hSession, hProfile); if (nvRes != NvAPI_Status.NVAPI_OK) throw new NvapiException("DRS_RestoreProfileDefault", nvRes); SaveSettings(hSession); tmpRemoveFromModified = true; } else if (profile.numOfSettings > 0) { int dropCount = 0; var settings = GetProfileSettings(hSession, hProfile); foreach (var setting in settings) { if (setting.settingLocation == NVDRS_SETTING_LOCATION.NVDRS_CURRENT_PROFILE_LOCATION) { if (nvw.DRS_DeleteProfileSetting(hSession, hProfile, setting.settingId) == NvAPI_Status.NVAPI_OK) { dropCount++; } } } if (dropCount > 0) { SaveSettings(hSession); } } }); removeFromModified = tmpRemoveFromModified; } public void ResetValue(string profileName, uint settingId, out bool removeFromModified) { var drsEvent = new DrsEvent { ProfileName = profileName, Settings = new List> { new(settingId, string.Empty) } }; RestoreSetting?.Invoke(this, drsEvent); if (drsEvent.Handled) { removeFromModified = false; return; } var tmpRemoveFromModified = false; DrsSession((hSession) => { var hProfile = GetProfileHandle(hSession, profileName); if (hProfile != IntPtr.Zero) { var nvRes = nvw.DRS_RestoreProfileDefaultSetting(hSession, hProfile, settingId); if (nvRes != NvAPI_Status.NVAPI_OK) throw new NvapiException("DRS_RestoreProfileDefaultSetting", nvRes); SaveSettings(hSession); var modifyCount = 0; var settings = GetProfileSettings(hSession, hProfile); foreach (var setting in settings) { if (setting.isCurrentPredefined == 0 && setting.settingLocation == NVDRS_SETTING_LOCATION.NVDRS_CURRENT_PROFILE_LOCATION) { modifyCount++; } } tmpRemoveFromModified = (modifyCount == 0); } }); removeFromModified = tmpRemoveFromModified; } public void DeleteValue(string profileName, uint settingId, out bool removeFromModified) { var tmpRemoveFromModified = false; DrsSession((hSession) => { var hProfile = GetProfileHandle(hSession, profileName); if (hProfile != IntPtr.Zero) { int dropCount = 0; var settings = GetProfileSettings(hSession, hProfile); foreach (var setting in settings) { if (setting.settingId != settingId) continue; if (setting.settingLocation == NVDRS_SETTING_LOCATION.NVDRS_CURRENT_PROFILE_LOCATION) { if (nvw.DRS_DeleteProfileSetting(hSession, hProfile, setting.settingId) == NvAPI_Status.NVAPI_OK) { dropCount++; break; } } } tmpRemoveFromModified = (dropCount == 0); SaveSettings(hSession); } }); removeFromModified = tmpRemoveFromModified; } public uint GetDwordValueFromProfile(string profileName, uint settingId, bool returnDefaultValue = false, bool forceDedicatedScope = false) { return DrsSession((hSession) => { var hProfile = GetProfileHandle(hSession, profileName); var dwordValue = ReadDwordValue(hSession, hProfile, settingId); if (dwordValue != null) return dwordValue.Value; else if (returnDefaultValue) return meta.GetSettingMeta(settingId).DefaultDwordValue; throw new NvapiException("DRS_GetSetting", NvAPI_Status.NVAPI_SETTING_NOT_FOUND); }); } public void SetDwordValueToProfile(string profileName, uint settingId, uint dwordValue) { DrsSession((hSession) => { var hProfile = GetProfileHandle(hSession, profileName); StoreDwordValue(hSession, hProfile, settingId, dwordValue); SaveSettings(hSession); }); } public int StoreSettingsToProfile(string profileName, List> settings) { var drsEvent = new DrsEvent { ProfileName = profileName, Settings = settings }; ApplySettings?.Invoke(this, drsEvent); if (drsEvent.Handled) { return 0; } DrsSessionScope.DestroyGlobalSession(); DrsSession((hSession) => { var hProfile = GetProfileHandle(hSession, profileName); foreach (var setting in settings) { var settingMeta = meta.GetSettingMeta(setting.Key); var settingType = settingMeta.SettingType; if (settingType == NVDRS_SETTING_TYPE.NVDRS_DWORD_TYPE) { var dword = DrsUtil.ParseDwordSettingValue(settingMeta, setting.Value); StoreDwordValue(hSession, hProfile, setting.Key, dword); } else if (settingType == NVDRS_SETTING_TYPE.NVDRS_WSTRING_TYPE) { var str = DrsUtil.ParseStringSettingValue(settingMeta, setting.Value); StoreStringValue(hSession, hProfile, setting.Key, str); } else if (settingType == NVDRS_SETTING_TYPE.NVDRS_BINARY_TYPE) { var bin = DrsUtil.ParseBinarySettingValue(settingMeta, setting.Value); StoreBinaryValue(hSession, hProfile, setting.Key, bin); } } SaveSettings(hSession); }); return 0; } private SettingItem CreateSettingItem(NVDRS_SETTING setting, bool useDefault = false) { var settingMeta = meta.GetSettingMeta(setting.settingId); //settingMeta.SettingType = setting.settingType; if (settingMeta.DwordValues == null) settingMeta.DwordValues = new List>(); if (settingMeta.StringValues == null) settingMeta.StringValues = new List>(); if (settingMeta.BinaryValues == null) settingMeta.BinaryValues = new List>(); var settingState = SettingState.NotAssiged; string valueRaw = ""; string valueText = ""; if (settingMeta.SettingType == NVDRS_SETTING_TYPE.NVDRS_DWORD_TYPE) { if (useDefault) { valueRaw = DrsUtil.GetDwordString(settingMeta.DefaultDwordValue); valueText = DrsUtil.GetDwordSettingValueName(settingMeta, settingMeta.DefaultDwordValue); } else if (setting.isCurrentPredefined == 1 && setting.isPredefinedValid == 1) { valueRaw = DrsUtil.GetDwordString(setting.predefinedValue.dwordValue); valueText = DrsUtil.GetDwordSettingValueName(settingMeta, setting.predefinedValue.dwordValue); if (setting.settingLocation == NVDRS_SETTING_LOCATION.NVDRS_CURRENT_PROFILE_LOCATION) settingState = SettingState.NvidiaSetting; else settingState = SettingState.GlobalSetting; } else { valueRaw = DrsUtil.GetDwordString(setting.currentValue.dwordValue); valueText = DrsUtil.GetDwordSettingValueName(settingMeta, setting.currentValue.dwordValue); if (setting.settingLocation == NVDRS_SETTING_LOCATION.NVDRS_CURRENT_PROFILE_LOCATION) settingState = SettingState.UserdefinedSetting; else settingState = SettingState.GlobalSetting; } } if (settingMeta.SettingType == NVDRS_SETTING_TYPE.NVDRS_WSTRING_TYPE) { if (useDefault) { valueRaw = settingMeta.DefaultStringValue; valueText = DrsUtil.GetStringSettingValueName(settingMeta, settingMeta.DefaultStringValue); } else if (setting.isCurrentPredefined == 1 && setting.isPredefinedValid == 1) { valueRaw = setting.predefinedValue.stringValue; valueText = DrsUtil.GetStringSettingValueName(settingMeta, setting.predefinedValue.stringValue); settingState = SettingState.NvidiaSetting; } else { valueRaw = setting.currentValue.stringValue; valueText = DrsUtil.GetStringSettingValueName(settingMeta, setting.currentValue.stringValue); if (setting.settingLocation == NVDRS_SETTING_LOCATION.NVDRS_CURRENT_PROFILE_LOCATION) settingState = SettingState.UserdefinedSetting; else settingState = SettingState.GlobalSetting; } } if (settingMeta.SettingType == NVDRS_SETTING_TYPE.NVDRS_BINARY_TYPE) { if (useDefault) { valueRaw = DrsUtil.GetBinaryString(settingMeta.DefaultBinaryValue); valueText = DrsUtil.GetBinarySettingValueName(settingMeta, settingMeta.DefaultBinaryValue); } else if (setting.isCurrentPredefined == 1 && setting.isPredefinedValid == 1) { valueRaw = DrsUtil.GetBinaryString(setting.predefinedValue.binaryValue); valueText = DrsUtil.GetBinarySettingValueName(settingMeta, setting.predefinedValue.binaryValue); settingState = SettingState.NvidiaSetting; } else { valueRaw = DrsUtil.GetBinaryString(setting.currentValue.binaryValue); valueText = DrsUtil.GetBinarySettingValueName(settingMeta, setting.currentValue.binaryValue); if (setting.settingLocation == NVDRS_SETTING_LOCATION.NVDRS_CURRENT_PROFILE_LOCATION) settingState = SettingState.UserdefinedSetting; else settingState = SettingState.GlobalSetting; } } return new SettingItem() { SettingId = setting.settingId, SettingText = settingMeta.SettingName, GroupName = settingMeta.GroupName, ValueRaw = valueRaw, ValueText = valueText, State = settingState, IsStringValue = settingMeta.SettingType == NVDRS_SETTING_TYPE.NVDRS_WSTRING_TYPE, IsApiExposed = settingMeta.IsApiExposed, }; } public List GetSettingsForProfile(string profileName, SettingViewMode viewMode, ref Dictionary? applications, bool skipApplications = false) { var result = new List(); var settingIds = meta.GetSettingIds(viewMode); var isBaseProfile = profileName.Contains("Base Profile", StringComparison.OrdinalIgnoreCase); settingIds.AddRange(_baseProfileSettingIds); settingIds = settingIds.Distinct().ToList(); applications = DrsSession((hSession) => { var hProfile = GetProfileHandle(hSession, profileName); var profileSettings = GetProfileSettings(hSession, hProfile); foreach (var profileSetting in profileSettings) { result.Add(CreateSettingItem(profileSetting)); if (settingIds.Contains(profileSetting.settingId)) settingIds.Remove(profileSetting.settingId); } foreach (var settingId in settingIds) { var setting = ReadSetting(hSession, hProfile, settingId, profileName); if (setting != null) result.Add(CreateSettingItem(setting.Value)); else { var dummySetting = new NVDRS_SETTING() { settingId = settingId }; result.Add(CreateSettingItem(dummySetting, true)); } } if (isBaseProfile) { var hiddenSettings = HiddenSettings.Where(hs => !result.Any(s => s.SettingId == hs.settingId)).ToList(); foreach (var hiddenSetting in hiddenSettings) { var setting = ReadSetting(hSession, hProfile, hiddenSetting.settingId); if (setting != null) { continue; } result.Add(CreateSettingItem(hiddenSetting)); } } else { result.RemoveAll(s => HiddenSettings.Any(hs => hs.settingId == s.SettingId)); } if (skipApplications) { return null; } return GetProfileApplications(hSession, hProfile) .Select(x => Tuple.Create(x.appName, GetApplicationFingerprint(x))).ToDictionary(x => x.Item2, x => x.Item1); }, !isBaseProfile); return result.OrderBy(x => x.SettingText).ThenBy(x => x.GroupName).ToList(); } public async Task> GetSettingsForProfileAsync(string profileName, SettingViewMode viewMode) { var result = default(List); await Task.Run(() => { var applications = default(Dictionary); result = GetSettingsForProfile(profileName, viewMode, ref applications, true); }); return result; } public void AddApplication(string profileName, string applicationName) { DrsSession((hSession) => { var hProfile = GetProfileHandle(hSession, profileName); AddApplication(hSession, hProfile, applicationName); SaveSettings(hSession); }); } public void RemoveApplication(string profileName, string applicationFingerprint) { DrsSession((hSession) => { var hProfile = GetProfileHandle(hSession, profileName); var applications = GetProfileApplications(hSession, hProfile); foreach (var app in applications) { if (GetApplicationFingerprint(app) != applicationFingerprint) continue; DeleteApplication(hSession, hProfile, app); break; } SaveSettings(hSession); }); } private string GetApplicationFingerprint(NVDRS_APPLICATION_V3 application) { return $"{application.appName}|{application.fileInFolder}|{application.userFriendlyName}|{application.launcher}"; } } }