From 9fd8e8f9bb777165dff6d79ceb6a76afaa595369 Mon Sep 17 00:00:00 2001 From: Vincent Maas Date: Sat, 28 Oct 2023 14:53:17 +0200 Subject: [PATCH] fix Novideo, add Game launcher auto-apply, add some LG actions, move winapi/admin functions to designated services --- ColorControl/ColorControl.csproj | 7 +- ColorControl/CommandLineHandler.cs | 49 +- ColorControl/Forms/ElevatedForm.cs | 110 +-- ColorControl/MainForm.Designer.cs | 44 - ColorControl/MainForm.cs | 118 +-- ColorControl/Program.cs | 77 +- ColorControl/Services/AMD/AmdPanel.cs | 4 +- .../Services/Common/ServiceManager.cs | 110 ++- .../EventDispatcher/EventDispatcher.cs | 8 + .../EventDispatcher/ProcessEventDispatcher.cs | 4 +- .../GameLauncher/GamePanel.Designer.cs | 55 +- .../Services/GameLauncher/GamePanel.cs | 83 +- .../Services/GameLauncher/GamePanel.resx | 2 +- .../Services/GameLauncher/GamePreset.cs | 32 +- .../Services/GameLauncher/GameService.cs | 168 +++- .../GameLauncher/GameServiceConfig.cs | 11 + ColorControl/Services/LG/LgDevice.cs | 7 +- ColorControl/Services/LG/LgGameBar.cs | 2 +- ColorControl/Services/LG/LgPanel.cs | 4 +- ColorControl/Services/LG/LgService.cs | 28 +- .../Services/NVIDIA/NvInfoPanel.Designer.cs | 89 ++ ColorControl/Services/NVIDIA/NvInfoPanel.cs | 46 + ColorControl/Services/NVIDIA/NvInfoPanel.resx | 120 +++ .../Services/NVIDIA/NvPanel.Designer.cs | 54 +- ColorControl/Services/NVIDIA/NvPanel.cs | 37 +- ColorControl/Services/NVIDIA/NvPreset.cs | 16 +- ColorControl/Services/NVIDIA/NvService.cs | 109 ++- .../Services/Samsung/SamsungDevice.cs | 13 +- ColorControl/Services/Samsung/SamsungPanel.cs | 6 +- .../Services/Samsung/SamsungService.cs | 12 +- .../Svc/ColorControlBackgroundService.cs | 72 +- ColorControl/XForms/LogWindow.xaml.cs | 26 +- Nspector/Common/DrsSessionScope.cs | 3 +- Nspector/Common/DrsSettingsMetaService.cs | 8 +- Nspector/Common/DrsSettingsService.cs | 72 +- Nspector/Common/DrsSettingsServiceBase.cs | 38 +- Nspector/Native/NVAPI/NvapiDrsWrapper.cs | 42 +- Nspector/Native/NativeArrayHelper.cs | 14 +- Nspector/frmDrvSettings.Designer.cs | 889 +++++++++--------- Nspector/frmDrvSettings.cs | 35 +- Nspector/frmDrvSettings.resx | 669 ++++++++----- Nspector/nspector/Reference.xml | 12 + NvAPIWrapper/Display/Display.cs | 23 +- .../{AppContext.cs => GlobalContext.cs} | 11 +- Shared/Common/PipeUtils.cs | 30 +- Shared/Common/ProcessExtensions.cs | 5 +- Shared/Common/Utils.cs | 392 +------- Shared/Common/WOL.cs | 255 ----- Shared/Contracts/StartUpParams.cs | 139 +-- Shared/Contracts/Svc/SvcMessage.cs | 117 +-- Shared/Forms/MessageForms.cs | 26 + Shared/Native/WinApi.cs | 240 ++--- Shared/Services/AppContextProvider.cs | 6 +- Shared/Services/RpcClientService.cs | 72 ++ Shared/Services/RpcServerService.cs | 134 +++ Shared/Services/RpcService.cs | 23 - Shared/Services/WinApiAdminService.cs | 383 ++++++++ Shared/Services/WinApiService.cs | 83 ++ Shared/Services/WinElevatedProcessManager.cs | 108 +++ Shared/Services/WolService.cs | 256 +++++ novideo_srgb/MainViewModel.cs | 7 +- novideo_srgb/MainWindow.xaml.cs | 15 + novideo_srgb/MonitorData.cs | 11 +- 63 files changed, 3297 insertions(+), 2344 deletions(-) create mode 100644 ColorControl/Services/GameLauncher/GameServiceConfig.cs create mode 100644 ColorControl/Services/NVIDIA/NvInfoPanel.Designer.cs create mode 100644 ColorControl/Services/NVIDIA/NvInfoPanel.cs create mode 100644 ColorControl/Services/NVIDIA/NvInfoPanel.resx rename Shared/Common/{AppContext.cs => GlobalContext.cs} (76%) delete mode 100644 Shared/Common/WOL.cs create mode 100644 Shared/Services/RpcClientService.cs create mode 100644 Shared/Services/RpcServerService.cs delete mode 100644 Shared/Services/RpcService.cs create mode 100644 Shared/Services/WinApiAdminService.cs create mode 100644 Shared/Services/WinApiService.cs create mode 100644 Shared/Services/WinElevatedProcessManager.cs create mode 100644 Shared/Services/WolService.cs diff --git a/ColorControl/ColorControl.csproj b/ColorControl/ColorControl.csproj index ce06623..3531fbf 100644 --- a/ColorControl/ColorControl.csproj +++ b/ColorControl/ColorControl.csproj @@ -18,8 +18,8 @@ Maassoft Maassoft 0 - 9.6.4.0 - 9.6.4.0 + 9.7.0.0 + 9.7.0.0 false true false @@ -63,6 +63,9 @@ UserControl + + UserControl + UserControl diff --git a/ColorControl/CommandLineHandler.cs b/ColorControl/CommandLineHandler.cs index 6995308..5e1edc1 100644 --- a/ColorControl/CommandLineHandler.cs +++ b/ColorControl/CommandLineHandler.cs @@ -5,6 +5,7 @@ using ColorControl.Services.NVIDIA; using ColorControl.Services.Samsung; using ColorControl.Shared.Common; using ColorControl.Shared.Contracts; +using Microsoft.Extensions.DependencyInjection; using System; using System.Diagnostics; using System.Threading.Tasks; @@ -16,55 +17,11 @@ namespace ColorControl { public static async Task HandleStartupParams(StartUpParams startUpParams, Process existingProcess) { - if (startUpParams.ActivateChromeFontFix || startUpParams.DeactivateChromeFontFix) - { - Utils.InstallChromeFix(startUpParams.ActivateChromeFontFix, startUpParams.ChromeFontFixApplicationDataFolder); - return true; - } - if (startUpParams.EnableAutoStart || startUpParams.DisableAutoStart) - { - Utils.RegisterTask(Program.TS_TASKNAME, startUpParams.EnableAutoStart, startUpParams.AutoStartRunLevel); - return true; - } - if (startUpParams.SetProcessAffinity) - { - Utils.SetProcessAffinity(startUpParams.ProcessId, startUpParams.AffinityMask); - return true; - } - if (startUpParams.SetProcessPriority) - { - Utils.SetProcessPriority(startUpParams.ProcessId, startUpParams.PriorityClass); - return true; - } if (startUpParams.StartElevated) { StartElevated(); return true; } - if (startUpParams.SendWol) - { - return WOL.WakeFunction(startUpParams.WolMacAddress, startUpParams.WolIpAddress); - } - if (startUpParams.InstallService) - { - Utils.InstallService(); - return true; - } - if (startUpParams.UninstallService) - { - Utils.UninstallService(); - return true; - } - if (startUpParams.StartService) - { - Utils.StartService(); - return true; - } - if (startUpParams.StopService) - { - Utils.StopService(); - return true; - } var useConsole = startUpParams.NoGui || existingProcess != null; @@ -152,7 +109,9 @@ Options: { try { - Application.Run(new ElevatedForm()); + var elevatedForm = Program.ServiceProvider.GetRequiredService(); + + Application.Run(elevatedForm); } catch (Exception ex) { diff --git a/ColorControl/Forms/ElevatedForm.cs b/ColorControl/Forms/ElevatedForm.cs index 10b02ae..a2dcf2b 100644 --- a/ColorControl/Forms/ElevatedForm.cs +++ b/ColorControl/Forms/ElevatedForm.cs @@ -1,85 +1,53 @@ -using ColorControl.Shared.Contracts; -using ColorControl.Shared.Native; -using NWin32; +using ColorControl.Svc; using System; using System.Drawing; -using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; -namespace ColorControl.Forms +namespace ColorControl.Forms; + +public partial class ElevatedForm : Form { - public partial class ElevatedForm : Form + private ColorControlBackgroundService _backgroundService; + + public ElevatedForm(ColorControlBackgroundService backgroundService) { - public ElevatedForm() + InitializeComponent(); + + FormBorderStyle = FormBorderStyle.None; + ShowInTaskbar = false; + Load += ElevatedForm_Load; + Shown += ElevatedForm_Shown; + + Task.Run(CheckMutexAsync); + + _backgroundService = backgroundService; + _backgroundService.PipeName = "elevatedpipe"; + + Task.Run(async () => await _backgroundService.StartAsync(CancellationToken.None)); + } + + private void ElevatedForm_Shown(object sender, EventArgs e) + { + Hide(); + } + + protected void ElevatedForm_Load(object sender, EventArgs e) + { + Size = new Size(0, 0); + } + + private void CheckMutexAsync() + { + var mutex = new Mutex(false, Shared.Common.GlobalContext.CurrentContext.MutexId, out var created); + try { - InitializeComponent(); - - FormBorderStyle = FormBorderStyle.None; - ShowInTaskbar = false; - Load += ElevatedForm_Load; - Shown += ElevatedForm_Shown; - - var filterStatus = new WinApi.CHANGEFILTERSTRUCT(); - filterStatus.size = (uint)Marshal.SizeOf(filterStatus); - filterStatus.info = 0; - - WinApi.ChangeWindowMessageFilterEx(Handle, NativeConstants.WM_COPYDATA, WinApi.ChangeWindowMessageFilterExAction.Allow, ref filterStatus); - - Task.Run(CheckMutexAsync); + mutex.WaitOne(); } - - private void ElevatedForm_Shown(object sender, EventArgs e) + catch (AbandonedMutexException) { - Hide(); - } - - protected void ElevatedForm_Load(object sender, EventArgs e) - { - Size = new Size(0, 0); - } - - protected override void WndProc(ref Message m) - { - if (m.Msg == NativeConstants.WM_COPYDATA) - { - var container = (WinApi.COPYDATASTRUCT)m.GetLParam(typeof(WinApi.COPYDATASTRUCT)); - var message = Marshal.PtrToStringAnsi(container.lpData); - - HandleMessage(message); - } - - base.WndProc(ref m); - } - - private void HandleMessage(string message) - { - var args = message.Split(' '); - - var startUpParams = StartUpParams.Parse(args); - - try - { - var _ = CommandLineHandler.HandleStartupParams(startUpParams, null); - } - catch (Exception) - { - - } - } - - private void CheckMutexAsync() - { - var mutex = new Mutex(false, Shared.Common.AppContext.CurrentContext.MutexId, out var created); - try - { - mutex.WaitOne(); - } - catch (AbandonedMutexException) - { - } - BeginInvoke(Application.Exit); } + BeginInvoke(Application.Exit); } } diff --git a/ColorControl/MainForm.Designer.cs b/ColorControl/MainForm.Designer.cs index 9dbb87e..ce3e26e 100644 --- a/ColorControl/MainForm.Designer.cs +++ b/ColorControl/MainForm.Designer.cs @@ -59,9 +59,6 @@ chkStartMinimized = new System.Windows.Forms.CheckBox(); chkStartAfterLogin = new System.Windows.Forms.CheckBox(); tabInfo = new System.Windows.Forms.TabPage(); - grpNVIDIAInfo = new System.Windows.Forms.GroupBox(); - btnRefreshNVIDIAInfo = new System.Windows.Forms.Button(); - tvNVIDIAInfo = new System.Windows.Forms.TreeView(); groupBox3 = new System.Windows.Forms.GroupBox(); lbPlugins = new System.Windows.Forms.ListBox(); label7 = new System.Windows.Forms.Label(); @@ -73,7 +70,6 @@ grpMiscellaneousOptions.SuspendLayout(); grpGeneralOptions.SuspendLayout(); tabInfo.SuspendLayout(); - grpNVIDIAInfo.SuspendLayout(); groupBox3.SuspendLayout(); SuspendLayout(); // @@ -441,7 +437,6 @@ // // tabInfo // - tabInfo.Controls.Add(grpNVIDIAInfo); tabInfo.Controls.Add(groupBox3); tabInfo.Location = new System.Drawing.Point(4, 24); tabInfo.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); @@ -452,41 +447,6 @@ tabInfo.Text = "Info"; tabInfo.UseVisualStyleBackColor = true; // - // grpNVIDIAInfo - // - grpNVIDIAInfo.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; - grpNVIDIAInfo.Controls.Add(btnRefreshNVIDIAInfo); - grpNVIDIAInfo.Controls.Add(tvNVIDIAInfo); - grpNVIDIAInfo.Location = new System.Drawing.Point(463, 7); - grpNVIDIAInfo.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); - grpNVIDIAInfo.Name = "grpNVIDIAInfo"; - grpNVIDIAInfo.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3); - grpNVIDIAInfo.Size = new System.Drawing.Size(643, 511); - grpNVIDIAInfo.TabIndex = 4; - grpNVIDIAInfo.TabStop = false; - grpNVIDIAInfo.Text = "NVIDIA info"; - // - // btnRefreshNVIDIAInfo - // - btnRefreshNVIDIAInfo.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left; - btnRefreshNVIDIAInfo.Location = new System.Drawing.Point(7, 478); - btnRefreshNVIDIAInfo.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); - btnRefreshNVIDIAInfo.Name = "btnRefreshNVIDIAInfo"; - btnRefreshNVIDIAInfo.Size = new System.Drawing.Size(88, 27); - btnRefreshNVIDIAInfo.TabIndex = 1; - btnRefreshNVIDIAInfo.Text = "Refresh"; - btnRefreshNVIDIAInfo.UseVisualStyleBackColor = true; - btnRefreshNVIDIAInfo.Click += btnRefreshNVIDIAInfo_Click; - // - // tvNVIDIAInfo - // - tvNVIDIAInfo.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; - tvNVIDIAInfo.Location = new System.Drawing.Point(7, 22); - tvNVIDIAInfo.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); - tvNVIDIAInfo.Name = "tvNVIDIAInfo"; - tvNVIDIAInfo.Size = new System.Drawing.Size(628, 448); - tvNVIDIAInfo.TabIndex = 0; - // // groupBox3 // groupBox3.Controls.Add(lbPlugins); @@ -579,7 +539,6 @@ grpGeneralOptions.ResumeLayout(false); grpGeneralOptions.PerformLayout(); tabInfo.ResumeLayout(false); - grpNVIDIAInfo.ResumeLayout(false); groupBox3.ResumeLayout(false); groupBox3.PerformLayout(); ResumeLayout(false); @@ -597,9 +556,6 @@ private System.Windows.Forms.ListBox lbPlugins; private System.Windows.Forms.Label label7; private System.Windows.Forms.Label lblInfo; - private System.Windows.Forms.GroupBox grpNVIDIAInfo; - private System.Windows.Forms.TreeView tvNVIDIAInfo; - private System.Windows.Forms.Button btnRefreshNVIDIAInfo; private System.Windows.Forms.GroupBox grpMiscellaneousOptions; private System.Windows.Forms.CheckBox chkFixChromeFonts; private System.Windows.Forms.Label lblFixChromeFontsDescription; diff --git a/ColorControl/MainForm.cs b/ColorControl/MainForm.cs index 36f94d4..015ddd8 100644 --- a/ColorControl/MainForm.cs +++ b/ColorControl/MainForm.cs @@ -15,7 +15,6 @@ using Linearstar.Windows.RawInput; using Microsoft.Extensions.DependencyInjection; using NLog; using novideo_srgb; -using NvAPIWrapper.Display; using NWin32; using System; using System.Collections.Generic; @@ -39,10 +38,12 @@ namespace ColorControl private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); private readonly PowerEventDispatcher _powerEventDispatcher; private readonly ServiceManager _serviceManager; + private readonly IServiceProvider _serviceProvider; + private readonly WinApiAdminService _winApiAdminService; + private readonly WinApiService _winApiService; private string _dataDir; private NvPanel _nvPanel; - private NvDitherPanel _nvDitherPanel; private NotifyIcon _trayIcon; private bool _initialized = false; @@ -76,7 +77,8 @@ namespace ColorControl private Dictionary _shortcuts = new(); private Dictionary> _modules = new(); - public MainForm(AppContextProvider appContextProvider, PowerEventDispatcher powerEventDispatcher, ServiceManager serviceManager) + public MainForm(AppContextProvider appContextProvider, PowerEventDispatcher powerEventDispatcher, ServiceManager serviceManager, + IServiceProvider serviceProvider, WinApiAdminService winApiAdminService, WinApiService winApiService) { InitializeComponent(); @@ -87,6 +89,9 @@ namespace ColorControl _powerEventDispatcher = powerEventDispatcher; _serviceManager = serviceManager; + _serviceProvider = serviceProvider; + _winApiAdminService = winApiAdminService; + _winApiService = winApiService; _dataDir = Program.DataDir; _config = Program.Config; @@ -130,17 +135,17 @@ namespace ColorControl _trayIcon.ContextMenuStrip.Opened += trayIconContextMenu_Popup; _trayIcon.BalloonTipClicked += trayIconBalloonTip_Clicked; - chkStartAfterLogin.Checked = Utils.TaskExists(Program.TS_TASKNAME); + chkStartAfterLogin.Checked = _winApiService.TaskExists(Program.TS_TASKNAME); - chkFixChromeFonts.Enabled = Utils.IsChromeInstalled(); + chkFixChromeFonts.Enabled = _winApiService.IsChromeInstalled(); if (chkFixChromeFonts.Enabled) { - var fixInstalled = Utils.IsChromeFixInstalled(); + var fixInstalled = _winApiService.IsChromeFixInstalled(); if (_config.FixChromeFonts && !fixInstalled) { - Utils.ExecuteElevated(StartUpParams.ActivateChromeFontFixParam); + _winApiAdminService.InstallChromeFix(true, Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)); } - chkFixChromeFonts.Checked = Utils.IsChromeFixInstalled(); + chkFixChromeFonts.Checked = _winApiService.IsChromeFixInstalled(); } InitShortcut(SHORTCUTID_SCREENSAVER, _config.ScreenSaverShortcut, StartScreenSaver); @@ -230,12 +235,12 @@ namespace ColorControl var text = "Use Windows Service"; btnStartStopService.Enabled = true; - if (Utils.IsServiceRunning()) + if (_winApiService.IsServiceRunning()) { text += " (running)"; btnStartStopService.Text = "Stop"; } - else if (Utils.IsServiceInstalled()) + else if (_winApiService.IsServiceInstalled()) { text += " (installed, not running)"; btnStartStopService.Text = "Start"; @@ -256,11 +261,11 @@ namespace ColorControl { //throw new Exception("bla"); Logger.Debug("Initializing NVIDIA..."); - var appContextProvider = Program.ServiceProvider.GetRequiredService(); - _serviceManager.NvService = new NvService(appContextProvider); + var appContextProvider = _serviceProvider.GetRequiredService(); + _serviceManager.NvService = _serviceProvider.GetRequiredService(); Logger.Debug("Initializing NVIDIA...Done."); - var rpcService = Program.ServiceProvider.GetRequiredService(); + var rpcService = _serviceProvider.GetRequiredService(); _nvPanel = new NvPanel(_serviceManager.NvService, _trayIcon, Handle, appContextProvider, rpcService); _nvPanel.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; @@ -282,7 +287,7 @@ namespace ColorControl { try { - var appContextProvider = Program.ServiceProvider.GetRequiredService(); + var appContextProvider = _serviceProvider.GetRequiredService(); _serviceManager.AmdService = new AmdService(appContextProvider); _amdPanel = new AmdPanel(_serviceManager.AmdService, _trayIcon, Handle); @@ -305,7 +310,7 @@ namespace ColorControl { try { - _serviceManager.GameService = Program.ServiceProvider.GetRequiredService(); + _serviceManager.GameService = _serviceProvider.GetRequiredService(); _gamePanel = new GamePanel(_serviceManager.GameService, _serviceManager.NvService, _serviceManager.AmdService, _serviceManager.LgService, _serviceManager.SamsungService, _trayIcon, Handle); _gamePanel.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; @@ -336,7 +341,7 @@ namespace ColorControl { try { - _serviceManager.LgService = Program.ServiceProvider.GetRequiredService(); + _serviceManager.LgService = _serviceProvider.GetRequiredService(); _lgPanel = new LgPanel(_serviceManager.LgService, _serviceManager.NvService, _serviceManager.AmdService, _trayIcon, Handle); _lgPanel.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; @@ -360,7 +365,7 @@ namespace ColorControl { try { - _serviceManager.SamsungService = Program.ServiceProvider.GetRequiredService(); + _serviceManager.SamsungService = _serviceProvider.GetRequiredService(); //_serviceManager.SamsungService.Init(); @@ -387,7 +392,7 @@ namespace ColorControl Text = Application.ProductName + " " + Application.ProductVersion; - if (Utils.IsAdministrator()) + if (_winApiService.IsAdministrator()) { Text += " (administrator)"; } @@ -435,7 +440,7 @@ namespace ColorControl { if (_updateHtmlUrl != null) { - Utils.StartProcess(_updateHtmlUrl); + _winApiAdminService.StartProcess(_updateHtmlUrl); } } @@ -691,7 +696,7 @@ namespace ColorControl private void CheckElevationMethod() { - if (Utils.IsAdministrator()) + if (_winApiService.IsAdministrator()) { return; } @@ -703,15 +708,15 @@ namespace ColorControl return; } - if (_config.ElevationMethod == ElevationMethod.UseService && !Utils.IsServiceInstalled() && + if (_config.ElevationMethod == ElevationMethod.UseService && !_winApiService.IsServiceInstalled() && (MessageForms.QuestionYesNo("The elevation method is set to Windows Service but it is not installed. Do you want to install it now?") == DialogResult.Yes)) { - Utils.InstallService(); + _winApiAdminService.InstallService(); } - else if (_config.ElevationMethod == ElevationMethod.UseService && !Utils.IsServiceRunning() && + else if (_config.ElevationMethod == ElevationMethod.UseService && !_winApiService.IsServiceRunning() && (MessageForms.QuestionYesNo("The elevation method is set to Windows Service but it is not running. Do you want to start it now?") == DialogResult.Yes)) { - Utils.StartService(); + _winApiAdminService.StartService(); } return; @@ -764,7 +769,6 @@ NOTE: installing the service may cause a User Account Control popup."); { if (tcMain.SelectedTab == tabInfo) { - LoadInfo(); } else if (tcMain.SelectedTab == tabOptions) { @@ -786,26 +790,6 @@ NOTE: installing the service may cause a User Account Control popup."); } } - if (_serviceManager.NvService != null) - { - if (_nvDitherPanel == null) - { - _nvDitherPanel = new NvDitherPanel(_serviceManager.NvService); - - tabOptions.Controls.Add(_nvDitherPanel); - - _nvDitherPanel.Top = grpGeneralOptions.Top; - _nvDitherPanel.Left = grpGeneralOptions.Left + grpGeneralOptions.Width + 4; - _nvDitherPanel.Width = tabOptions.Width - _nvDitherPanel.Left - 4; - - _nvDitherPanel.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; - } - else - { - _nvDitherPanel.UpdateInfo(); - } - } - _initialized = false; try { @@ -944,24 +928,8 @@ NOTE: installing the service may cause a User Account Control popup."); await _samsungPanel?.ApplyPreset(preset); } - private void LoadInfo() - { - grpNVIDIAInfo.Visible = _serviceManager.NvService != null; - } - private void btnRefreshNVIDIAInfo_Click(object sender, EventArgs e) { - if (_serviceManager.NvService != null) - { - tvNVIDIAInfo.Nodes.Clear(); - var displays = Display.GetDisplays(); - for (var i = 0; i < displays.Length; i++) - { - var display = displays[i]; - var node = TreeNodeBuilder.CreateTree(display, $"Display[{i}]"); - tvNVIDIAInfo.Nodes.Add(node); - } - } } private void btnSetShortcutScreenSaver_Click(object sender, EventArgs e) @@ -1063,7 +1031,7 @@ NOTE: installing the service may cause a User Account Control popup."); { _updateHtmlUrl = latest.html_url.Value; - if (latest.assets != null && Utils.IsServiceRunning()) + if (latest.assets != null && _winApiService.IsServiceRunning()) { var asset = latest.assets[0]; _downloadUrl = asset.browser_download_url.Value; @@ -1196,8 +1164,6 @@ NOTE: installing the service may cause a User Account Control popup."); { _config.ElevationMethod = elevationMethod; - Utils.UseDedicatedElevatedProcess = _config.ElevationMethod == ElevationMethod.UseElevatedProcess; - var _ = _config.ElevationMethod switch { ElevationMethod.None => SetElevationMethodNone(), @@ -1217,7 +1183,7 @@ NOTE: installing the service may cause a User Account Control popup."); RegisterScheduledTask(); } - Utils.UninstallService(); + _winApiAdminService.UninstallService(); return true; } @@ -1230,16 +1196,16 @@ NOTE: installing the service may cause a User Account Control popup."); RegisterScheduledTask(); } - Utils.UninstallService(); + _winApiAdminService.UninstallService(); return true; } private bool SetElevationMethodUseService() { - Utils.InstallService(); + _winApiAdminService.InstallService(); - if (Utils.IsServiceInstalled()) + if (_winApiService.IsServiceInstalled()) { MessageForms.InfoOk("Service installed successfully."); return true; @@ -1257,14 +1223,14 @@ NOTE: installing the service may cause a User Account Control popup."); RegisterScheduledTask(); } - Utils.UninstallService(); + _winApiAdminService.UninstallService(); return true; } private void RegisterScheduledTask(bool enabled = true) { - Utils.RegisterTask(Program.TS_TASKNAME, enabled, _config.ElevationMethod == ElevationMethod.RunAsAdmin ? Microsoft.Win32.TaskScheduler.TaskRunLevel.Highest : Microsoft.Win32.TaskScheduler.TaskRunLevel.LUA); + _winApiAdminService.RegisterTask(Program.TS_TASKNAME, enabled, _config.ElevationMethod == ElevationMethod.RunAsAdmin ? Microsoft.Win32.TaskScheduler.TaskRunLevel.Highest : Microsoft.Win32.TaskScheduler.TaskRunLevel.LUA); } private void btnElevationInfo_Click(object sender, EventArgs e) @@ -1273,7 +1239,7 @@ NOTE: installing the service may cause a User Account Control popup."); NOTE: if ColorControl itself already runs as administrator this is indicated in the title: ColorControl {Application.ProductVersion} (administrator). -Currently ColorControl is {(Utils.IsAdministrator() ? "" : "not ")}running as administrator. +Currently ColorControl is {(_winApiService.IsAdministrator() ? "" : "not ")}running as administrator. "); } @@ -1286,11 +1252,11 @@ Currently ColorControl is {(Utils.IsAdministrator() ? "" : "not ")}running as ad if (start) { - Utils.StartService(); + _winApiAdminService.StartService(); } else { - Utils.StopService(); + _winApiAdminService.StopService(); } var wait = 1500; @@ -1299,7 +1265,7 @@ Currently ColorControl is {(Utils.IsAdministrator() ? "" : "not ")}running as ad { await Task.Delay(100); - if (start == Utils.IsServiceRunning()) + if (start == _winApiService.IsServiceRunning()) { break; } @@ -1376,11 +1342,9 @@ Currently ColorControl is {(Utils.IsAdministrator() ? "" : "not ")}running as ad { _config.FixChromeFonts = chkFixChromeFonts.Checked; - var param = chkFixChromeFonts.Checked ? StartUpParams.ActivateChromeFontFixParam : StartUpParams.DeactivateChromeFontFixParam; - var folder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); - Utils.ExecuteElevated($"{param} {folder}"); + _winApiAdminService.InstallChromeFix(chkFixChromeFonts.Checked, folder); } } diff --git a/ColorControl/Program.cs b/ColorControl/Program.cs index e0e16fd..f9d5ae5 100644 --- a/ColorControl/Program.cs +++ b/ColorControl/Program.cs @@ -1,13 +1,16 @@ -using ColorControl.Services.Common; +using ColorControl.Forms; +using ColorControl.Services.Common; using ColorControl.Services.EventDispatcher; using ColorControl.Services.GameLauncher; using ColorControl.Services.LG; +using ColorControl.Services.NVIDIA; using ColorControl.Services.Samsung; using ColorControl.Shared.Common; using ColorControl.Shared.Contracts; using ColorControl.Shared.Native; using ColorControl.Shared.Services; using ColorControl.Svc; +using ColorControl.XForms; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Newtonsoft.Json; @@ -31,7 +34,7 @@ namespace ColorControl public static string ConfigFilename { get; private set; } public static string LogFilename { get; private set; } public static Config Config { get; private set; } - public static Shared.Common.AppContext AppContext { get; private set; } + public static GlobalContext AppContext { get; private set; } public static bool IsRestarting { get; private set; } public static bool UserExit = false; @@ -59,27 +62,23 @@ namespace ColorControl //Utils.UpdateFiles(@"H:\temp\ColorControl\ColorControl", @"C:\Users\vinni\source\repos\ColorControl\ColorControl\bin\Debug\net6.0-windows10.0.20348.0"); //Utils.UnZipFile(@"H:\temp\ColorControl\ColorControl.zip", @"H:\temp\ColorControl\temp"); - var runAsService = args.Contains("--service") || Utils.IsAdministrator() && Process.GetCurrentProcess().Parent()?.ProcessName?.Equals("services", StringComparison.InvariantCultureIgnoreCase) == true; + var runAsService = args.Contains("--service") || WinApiService.IsAdministratorStatic() && Process.GetCurrentProcess().Parent()?.ProcessName?.Equals("services", StringComparison.InvariantCultureIgnoreCase) == true; + var runElevated = args.Contains("--elevated"); - InitLogger(runAsService); + InitLogger(runAsService, runElevated); Logger.Debug($"Using data path: {DataDir}"); //Logger.Debug("Parent process: " + Process.GetCurrentProcess().Parent()?.ProcessName); - var host = CreateHostBuilder().Build(); - ServiceProvider = host.Services; - - var appContextProvider = ServiceProvider.GetRequiredService(); - if (runAsService) { - AppContext = new Shared.Common.AppContext(null, new StartUpParams(), DataDir, _loggingRule); - appContextProvider.SetAppContext(AppContext); - await RunService(args); return; } + var host = CreateHostBuilder().Build(); + ServiceProvider = host.Services; + var mutexId = $"Global\\{typeof(MainForm).GUID}"; var currentDomain = AppDomain.CurrentDomain; @@ -90,16 +89,17 @@ namespace ColorControl LoadConfig(); + var appContextProvider = ServiceProvider.GetRequiredService(); + var startUpParams = StartUpParams.Parse(args); + + AppContext = new GlobalContext(Config, startUpParams, DataDir, _loggingRule, mutexId); + appContextProvider.SetAppContext(AppContext); + if (Config.UseGdiScaling) { Application.SetHighDpiMode(HighDpiMode.DpiUnawareGdiScaled); } - var startUpParams = StartUpParams.Parse(args); - - AppContext = new Shared.Common.AppContext(Config, startUpParams, DataDir, _loggingRule, mutexId); - appContextProvider.SetAppContext(AppContext); - var existingProcess = Utils.GetProcessByName("ColorControl"); try @@ -145,12 +145,26 @@ namespace ColorControl Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); + if (Debugger.IsAttached) + { + var winApiService = ServiceProvider.GetRequiredService(); + + if (winApiService.IsAdministrator()) + { + var backgroundService = ServiceProvider.GetRequiredService(); + backgroundService.PipeName = PipeUtils.ElevatedPipe; + + Task.Run(async () => await backgroundService.StartAsync(CancellationToken.None)); + } + } + _mainForm = ServiceProvider.GetRequiredService(); Application.Run(_mainForm); if (Debugger.IsAttached && !IsRestarting) { - Utils.StopService(); + var winApiAdminService = ServiceProvider.GetRequiredService(); + winApiAdminService.StopService(); } } catch (Exception ex) @@ -181,12 +195,12 @@ namespace ColorControl Environment.Exit(0); } - private static void InitLogger(bool runAsService) + private static void InitLogger(bool runAsService, bool runElevated) { var config = new LoggingConfiguration(); // Targets where to log to: File and Console - var logFileAppendix = runAsService ? "_svc" : ""; + var logFileAppendix = runAsService ? "_svc" : runElevated ? "_elevated" : ""; LogFilename = Path.Combine(DataDir, $"LogFile{logFileAppendix}.txt"); @@ -220,8 +234,6 @@ namespace ColorControl } Config ??= new Config(); - Utils.UseDedicatedElevatedProcess = Config.UseDedicatedElevatedProcess; - var minLogLevel = LogLevel.FromString(Config.LogLevel); if (minLogLevel != LogLevel.Trace) @@ -245,9 +257,9 @@ namespace ColorControl services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); - services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); - services.AddTransient(); }); } private static async Task RunService(string[] args) @@ -266,6 +278,12 @@ namespace ColorControl }) .Build(); + ServiceProvider = host.Services; + + var appContextProvider = ServiceProvider.GetRequiredService(); + AppContext = new GlobalContext(null, new StartUpParams(), DataDir, _loggingRule); + appContextProvider.SetAppContext(AppContext); + await host.RunAsync(); } @@ -273,6 +291,17 @@ namespace ColorControl { services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddTransient(); + services.AddTransient(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + + RpcServerService.ServiceTypes.Add(typeof(NvService)); } public static int EnumThreadWindows(IntPtr handle, IntPtr param) diff --git a/ColorControl/Services/AMD/AmdPanel.cs b/ColorControl/Services/AMD/AmdPanel.cs index db5973d..cee18e4 100644 --- a/ColorControl/Services/AMD/AmdPanel.cs +++ b/ColorControl/Services/AMD/AmdPanel.cs @@ -30,7 +30,7 @@ namespace ColorControl.Services.AMD _trayIcon = trayIcon; _mainHandle = handle; - _config = Shared.Common.AppContext.CurrentContext.Config; + _config = Shared.Common.GlobalContext.CurrentContext.Config; InitializeComponent(); @@ -127,7 +127,7 @@ namespace ColorControl.Services.AMD private async Task ApplyAmdPresetOnStartup(int attempts = 5) { - var startUpParams = Shared.Common.AppContext.CurrentContext.StartUpParams; + var startUpParams = Shared.Common.GlobalContext.CurrentContext.StartUpParams; var presetIdOrName = !string.IsNullOrEmpty(startUpParams.AmdPresetIdOrName) ? startUpParams.AmdPresetIdOrName : _config.AmdPresetId_ApplyOnStartup.ToString(); if (!string.IsNullOrEmpty(presetIdOrName)) diff --git a/ColorControl/Services/Common/ServiceManager.cs b/ColorControl/Services/Common/ServiceManager.cs index 5935686..9132e46 100644 --- a/ColorControl/Services/Common/ServiceManager.cs +++ b/ColorControl/Services/Common/ServiceManager.cs @@ -3,70 +3,76 @@ using ColorControl.Services.GameLauncher; using ColorControl.Services.LG; using ColorControl.Services.NVIDIA; using ColorControl.Services.Samsung; -using ColorControl.Shared.Common; +using ColorControl.Shared.Services; using System; using System.Linq; using System.Threading.Tasks; -namespace ColorControl.Services.Common +namespace ColorControl.Services.Common; + +public class ServiceManager { - public class ServiceManager + private readonly WinApiAdminService _winApiAdminService; + + internal NvService NvService { get; set; } + internal LgService LgService { get; set; } + internal AmdService AmdService { get; set; } + internal GameService GameService { get; set; } + internal SamsungService SamsungService { get; set; } + + public ServiceManager(WinApiAdminService winApiAdminService) { - internal NvService NvService { get; set; } - internal LgService LgService { get; set; } - internal AmdService AmdService { get; set; } - internal GameService GameService { get; set; } - internal SamsungService SamsungService { get; set; } + _winApiAdminService = winApiAdminService; + } - public async Task HandleExternalServiceAsync(string serviceName, string[] parameters) + public async Task HandleExternalServiceAsync(string serviceName, string[] parameters) + { + if (string.IsNullOrEmpty(serviceName) || parameters.Length == 0) { - if (string.IsNullOrEmpty(serviceName) || parameters.Length == 0) - { - return false; - } - - if (NvService != null && serviceName.Equals("NvPreset", StringComparison.OrdinalIgnoreCase)) - { - return await NvService.ApplyPreset(parameters[0]); - } - if (NvService != null && serviceName.Equals("GsyncEnabled", StringComparison.OrdinalIgnoreCase)) - { - return NvService.IsGsyncEnabled(); - } - if (AmdService != null && serviceName.Equals("AmdPreset", StringComparison.OrdinalIgnoreCase)) - { - return await AmdService.ApplyPreset(parameters[0]); - } - if (LgService != null && serviceName.Equals("LgPreset", StringComparison.OrdinalIgnoreCase)) - { - await LgService.ApplyPreset(parameters[0]); - - return true; - } - if (SamsungService != null && serviceName.Equals("SamsungPreset", StringComparison.OrdinalIgnoreCase)) - { - await SamsungService.ApplyPreset(parameters[0]); - - return true; - } - - if (serviceName.Equals("StartProgram", StringComparison.OrdinalIgnoreCase)) - { - Utils.StartProcess(parameters[0], parameters.Length > 1 ? string.Join(" ", parameters.Skip(1)) : null, setWorkingDir: true); - - return true; - } - return false; } - public void Save() + if (NvService != null && serviceName.Equals("NvPreset", StringComparison.OrdinalIgnoreCase)) { - NvService?.GlobalSave(); - AmdService?.GlobalSave(); - LgService?.GlobalSave(); - GameService?.GlobalSave(); - SamsungService?.GlobalSave(); + return await NvService.ApplyPreset(parameters[0]); } + if (NvService != null && serviceName.Equals("GsyncEnabled", StringComparison.OrdinalIgnoreCase)) + { + return NvService.IsGsyncEnabled(); + } + if (AmdService != null && serviceName.Equals("AmdPreset", StringComparison.OrdinalIgnoreCase)) + { + return await AmdService.ApplyPreset(parameters[0]); + } + if (LgService != null && serviceName.Equals("LgPreset", StringComparison.OrdinalIgnoreCase)) + { + await LgService.ApplyPreset(parameters[0]); + + return true; + } + if (SamsungService != null && serviceName.Equals("SamsungPreset", StringComparison.OrdinalIgnoreCase)) + { + await SamsungService.ApplyPreset(parameters[0]); + + return true; + } + + if (serviceName.Equals("StartProgram", StringComparison.OrdinalIgnoreCase)) + { + _winApiAdminService.StartProcess(parameters[0], parameters.Length > 1 ? string.Join(" ", parameters.Skip(1)) : null, setWorkingDir: true); + + return true; + } + + return false; + } + + public void Save() + { + NvService?.GlobalSave(); + AmdService?.GlobalSave(); + LgService?.GlobalSave(); + GameService?.GlobalSave(); + SamsungService?.GlobalSave(); } } diff --git a/ColorControl/Services/EventDispatcher/EventDispatcher.cs b/ColorControl/Services/EventDispatcher/EventDispatcher.cs index 71476da..38b1a07 100644 --- a/ColorControl/Services/EventDispatcher/EventDispatcher.cs +++ b/ColorControl/Services/EventDispatcher/EventDispatcher.cs @@ -16,6 +16,10 @@ public class EventDispatcher where T : EventArgs { eventHandlers.Add(eventName, eventHandler); } + else + { + eventHandlers[eventName] += eventHandler; + } } public void RegisterAsyncEventHandler(string eventName, AsyncEventHandler eventHandler) @@ -24,6 +28,10 @@ public class EventDispatcher where T : EventArgs { asyncEventHandlers.Add(eventName, eventHandler); } + else + { + asyncEventHandlers[eventName] += eventHandler; + } } public void UnregisterEventHandler(string eventName) diff --git a/ColorControl/Services/EventDispatcher/ProcessEventDispatcher.cs b/ColorControl/Services/EventDispatcher/ProcessEventDispatcher.cs index f24ef92..8069665 100644 --- a/ColorControl/Services/EventDispatcher/ProcessEventDispatcher.cs +++ b/ColorControl/Services/EventDispatcher/ProcessEventDispatcher.cs @@ -28,10 +28,10 @@ namespace ColorControl.Services.EventDispatcher { public const string Event_ProcessChanged = "ProcessChanged"; public bool IsRunning { get; set; } + public ProcessChangedEventArgs MonitorContext { get; private set; } protected static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); - private ProcessChangedEventArgs MonitorContext { get; set; } private AppContextProvider _appContextProvider { get; } public ProcessEventDispatcher(AppContextProvider appContextProvider) @@ -88,6 +88,8 @@ namespace ColorControl.Services.EventDispatcher { var processes = Process.GetProcesses(); + context.StartedProcesses = processes.Where(p => context.RunningProcesses?.Any(rp => rp.Id == p.Id) == false).ToList(); + context.StoppedProcesses = context.RunningProcesses?.Where(p => processes.Any(rp => rp.Id == p.Id) == false).ToList(); context.RunningProcesses = processes; context.IsNotificationDisabled = FormUtils.IsNotificationDisabled(); diff --git a/ColorControl/Services/GameLauncher/GamePanel.Designer.cs b/ColorControl/Services/GameLauncher/GamePanel.Designer.cs index 65b36be..e8c96ac 100644 --- a/ColorControl/Services/GameLauncher/GamePanel.Designer.cs +++ b/ColorControl/Services/GameLauncher/GamePanel.Designer.cs @@ -34,6 +34,7 @@ mnuGameOptions = new System.Windows.Forms.ContextMenuStrip(components); miGameProcessorAffinity = new System.Windows.Forms.ToolStripMenuItem(); miGameProcessPriority = new System.Windows.Forms.ToolStripMenuItem(); + miPresetNVIDIAProfileInspector = new System.Windows.Forms.ToolStripMenuItem(); chkGameQuickAccess = new System.Windows.Forms.CheckBox(); btnGameSettings = new System.Windows.Forms.Button(); mnuGameActions = new System.Windows.Forms.ContextMenuStrip(components); @@ -51,6 +52,7 @@ mnuGameNvidiaPresets = new System.Windows.Forms.ToolStripMenuItem(); mnuGameAmdPresets = new System.Windows.Forms.ToolStripMenuItem(); mnuGameLgPresets = new System.Windows.Forms.ToolStripMenuItem(); + mnuGameSamsungPresets = new System.Windows.Forms.ToolStripMenuItem(); mnuGameStartProgram = new System.Windows.Forms.ToolStripMenuItem(); label4 = new System.Windows.Forms.Label(); edtGameName = new System.Windows.Forms.TextBox(); @@ -60,7 +62,7 @@ btnGameAdd = new System.Windows.Forms.Button(); btnGameLaunch = new System.Windows.Forms.Button(); lvGamePresets = new System.Windows.Forms.ListView(); - mnuGameSamsungPresets = new System.Windows.Forms.ToolStripMenuItem(); + miGameOptionsAutoApplySettings = new System.Windows.Forms.ToolStripMenuItem(); mnuGameOptions.SuspendLayout(); mnuGameActions.SuspendLayout(); mnuGameAddStep.SuspendLayout(); @@ -96,24 +98,31 @@ // mnuGameOptions // mnuGameOptions.ImageScalingSize = new System.Drawing.Size(20, 20); - mnuGameOptions.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { miGameProcessorAffinity, miGameProcessPriority }); + mnuGameOptions.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { miGameProcessorAffinity, miGameProcessPriority, miPresetNVIDIAProfileInspector, miGameOptionsAutoApplySettings }); mnuGameOptions.Name = "mnuLgButtons"; - mnuGameOptions.Size = new System.Drawing.Size(166, 48); + mnuGameOptions.Size = new System.Drawing.Size(202, 114); // // miGameProcessorAffinity // miGameProcessorAffinity.Name = "miGameProcessorAffinity"; - miGameProcessorAffinity.Size = new System.Drawing.Size(165, 22); + miGameProcessorAffinity.Size = new System.Drawing.Size(201, 22); miGameProcessorAffinity.Text = "Processor affinity"; miGameProcessorAffinity.Click += btnGameProcessAffinity_Click; // // miGameProcessPriority // miGameProcessPriority.Name = "miGameProcessPriority"; - miGameProcessPriority.Size = new System.Drawing.Size(165, 22); + miGameProcessPriority.Size = new System.Drawing.Size(201, 22); miGameProcessPriority.Text = "Process priority"; miGameProcessPriority.Click += miGameProcessPriority_Click; // + // miPresetNVIDIAProfileInspector + // + miPresetNVIDIAProfileInspector.Name = "miPresetNVIDIAProfileInspector"; + miPresetNVIDIAProfileInspector.Size = new System.Drawing.Size(201, 22); + miPresetNVIDIAProfileInspector.Text = "NVIDIA Profile Inspector"; + miPresetNVIDIAProfileInspector.Click += miPresetNVIDIAProfileInspector_Click; + // // chkGameQuickAccess // chkGameQuickAccess.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left; @@ -145,21 +154,21 @@ mnuGameActions.ImageScalingSize = new System.Drawing.Size(20, 20); mnuGameActions.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { mnuGameNvInspector, miGameSetQuickAccessShortcut }); mnuGameActions.Name = "mnuLgButtons"; - mnuGameActions.Size = new System.Drawing.Size(212, 48); + mnuGameActions.Size = new System.Drawing.Size(202, 48); mnuGameActions.Opening += mnuGameActions_Opening; // // mnuGameNvInspector // mnuGameNvInspector.Name = "mnuGameNvInspector"; - mnuGameNvInspector.Size = new System.Drawing.Size(211, 22); + mnuGameNvInspector.Size = new System.Drawing.Size(201, 22); mnuGameNvInspector.Text = "NVIDIA Profile Inspector"; mnuGameNvInspector.Click += mnuGameNvInspector_Click; // // miGameSetQuickAccessShortcut // miGameSetQuickAccessShortcut.Name = "miGameSetQuickAccessShortcut"; - miGameSetQuickAccessShortcut.Size = new System.Drawing.Size(211, 22); - miGameSetQuickAccessShortcut.Text = "Set Quick Access Shortcut"; + miGameSetQuickAccessShortcut.Size = new System.Drawing.Size(201, 22); + miGameSetQuickAccessShortcut.Text = "Settings..."; miGameSetQuickAccessShortcut.Click += miGameSetQuickAccessShortcut_Click; // // chkGameRunAsAdmin @@ -261,31 +270,37 @@ mnuGameAddStep.ImageScalingSize = new System.Drawing.Size(20, 20); mnuGameAddStep.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { mnuGameNvidiaPresets, mnuGameAmdPresets, mnuGameLgPresets, mnuGameSamsungPresets, mnuGameStartProgram }); mnuGameAddStep.Name = "mnuLgButtons"; - mnuGameAddStep.Size = new System.Drawing.Size(181, 136); + mnuGameAddStep.Size = new System.Drawing.Size(164, 114); mnuGameAddStep.Opening += mnuGameAddStep_Opening; // // mnuGameNvidiaPresets // mnuGameNvidiaPresets.Name = "mnuGameNvidiaPresets"; - mnuGameNvidiaPresets.Size = new System.Drawing.Size(180, 22); + mnuGameNvidiaPresets.Size = new System.Drawing.Size(163, 22); mnuGameNvidiaPresets.Text = "NVIDIA presets"; // // mnuGameAmdPresets // mnuGameAmdPresets.Name = "mnuGameAmdPresets"; - mnuGameAmdPresets.Size = new System.Drawing.Size(180, 22); + mnuGameAmdPresets.Size = new System.Drawing.Size(163, 22); mnuGameAmdPresets.Text = "AMD presets"; // // mnuGameLgPresets // mnuGameLgPresets.Name = "mnuGameLgPresets"; - mnuGameLgPresets.Size = new System.Drawing.Size(180, 22); + mnuGameLgPresets.Size = new System.Drawing.Size(163, 22); mnuGameLgPresets.Text = "LG presets"; // + // mnuGameSamsungPresets + // + mnuGameSamsungPresets.Name = "mnuGameSamsungPresets"; + mnuGameSamsungPresets.Size = new System.Drawing.Size(163, 22); + mnuGameSamsungPresets.Text = "Samsung presets"; + // // mnuGameStartProgram // mnuGameStartProgram.Name = "mnuGameStartProgram"; - mnuGameStartProgram.Size = new System.Drawing.Size(180, 22); + mnuGameStartProgram.Size = new System.Drawing.Size(163, 22); mnuGameStartProgram.Text = "Start Program"; mnuGameStartProgram.Click += mnuGameStartProgram_Click; // @@ -379,6 +394,7 @@ lvGamePresets.AllowDrop = true; lvGamePresets.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; lvGamePresets.CheckBoxes = true; + lvGamePresets.ContextMenuStrip = mnuGameOptions; lvGamePresets.FullRowSelect = true; lvGamePresets.Location = new System.Drawing.Point(8, 8); lvGamePresets.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); @@ -396,11 +412,12 @@ lvGamePresets.DragEnter += lvGamePresets_DragEnter; lvGamePresets.DoubleClick += lvGamePresets_DoubleClick; // - // mnuGameSamsungPresets + // miGameOptionsAutoApplySettings // - mnuGameSamsungPresets.Name = "mnuGameSamsungPresets"; - mnuGameSamsungPresets.Size = new System.Drawing.Size(180, 22); - mnuGameSamsungPresets.Text = "Samsung presets"; + miGameOptionsAutoApplySettings.Name = "miGameOptionsAutoApplySettings"; + miGameOptionsAutoApplySettings.Size = new System.Drawing.Size(201, 22); + miGameOptionsAutoApplySettings.Text = "Auto apply settings..."; + miGameOptionsAutoApplySettings.Click += miGameOptionsAutoApplySettings_Click; // // GamePanel // @@ -470,5 +487,7 @@ private System.Windows.Forms.ToolStripMenuItem miGameProcessPriority; private System.Windows.Forms.ComboBox cbxGameStepType; private System.Windows.Forms.ToolStripMenuItem mnuGameSamsungPresets; + private System.Windows.Forms.ToolStripMenuItem miPresetNVIDIAProfileInspector; + private System.Windows.Forms.ToolStripMenuItem miGameOptionsAutoApplySettings; } } diff --git a/ColorControl/Services/GameLauncher/GamePanel.cs b/ColorControl/Services/GameLauncher/GamePanel.cs index c8b9742..a153796 100644 --- a/ColorControl/Services/GameLauncher/GamePanel.cs +++ b/ColorControl/Services/GameLauncher/GamePanel.cs @@ -43,7 +43,7 @@ namespace ColorControl.Services.GameLauncher _amdService = amdService; _lgService = lgService; _samsungService = samsungService; - _config = Shared.Common.AppContext.CurrentContext.Config; + _config = Shared.Common.GlobalContext.CurrentContext.Config; InitializeComponent(); @@ -139,7 +139,7 @@ namespace ColorControl.Services.GameLauncher var preset = GetSelectedGamePreset(); var enabled = preset != null; - FormUtils.EnableControls(this, enabled, new List { lvGamePresets, btnGameAdd }); + FormUtils.EnableControls(this, enabled, new List { lvGamePresets, btnGameAdd, btnGameSettings }); if (preset != null) { @@ -361,16 +361,44 @@ namespace ColorControl.Services.GameLauncher private void miGameSetQuickAccessShortcut_Click(object sender, EventArgs e) { - var shortcut = FormUtils.EditShortcut(_config.GameQuickAccessShortcut); + EditGameSettings(); + } - if (shortcut == null) + private void EditGameSettings() + { + var quickAccessField = new FieldDefinition + { + Label = "Quick Access shortcut", + FieldType = FieldType.Shortcut, + Value = _config.GameQuickAccessShortcut + }; + + var applyExternallyLaunched = new FieldDefinition + { + Label = "Apply presets when launching games externally", + SubLabel = "This will monitor processes and automatically apply the preset whenever a known game is launched", + FieldType = FieldType.CheckBox, + Value = _gameService.Config.ApplyExternallyLaunched + }; + + var values = MessageForms.ShowDialog("Game launcher settings", new[] { + quickAccessField, + applyExternallyLaunched + }); + if (!values.Any()) { return; } + var shortcut = (string)quickAccessField.Value; + _config.GameQuickAccessShortcut = shortcut; KeyboardShortcutManager.RegisterShortcut(SHORTCUTID_GAMEQA, _config.GameQuickAccessShortcut); + + _gameService.Config.ApplyExternallyLaunched = applyExternallyLaunched.ValueAsBool; + + UpdateInfo(); } private void mnuGameActions_Opening(object sender, CancelEventArgs e) @@ -490,5 +518,52 @@ namespace ColorControl.Services.GameLauncher { FormUtils.ListViewSort(sender, e); } + + private void miPresetNVIDIAProfileInspector_Click(object sender, EventArgs e) + { + var form = new frmDrvSettings(); + form.Show(); + + var preset = GetSelectedGamePreset(); + + var executable = Path.GetFileName(preset.Path); + + form.SetProfileByExecutable(executable); + } + + private void miGameOptionsAutoApplySettings_Click(object sender, EventArgs e) + { + var preset = GetSelectedGamePreset(); + + var allowAutoApplyField = new FieldDefinition + { + Label = "Allow this preset to be automatically executed when the process starts", + FieldType = FieldType.CheckBox, + Value = preset.AutoSettings.AllowAutoApply + }; + + var processActions = new[] { ProcessAutoAction.None, ProcessAutoAction.Suspend }.Select(t => Utils.GetDescription(t)); + + var processActionField = new FieldDefinition + { + Label = "Optional action to perform directly after the process starts", + SubLabel = "Temporarily suspending the process may help when enabling/disabling HDR or other settings", + FieldType = FieldType.DropDown, + Values = processActions, + Value = preset.AutoSettings.ProcessAutoAction + }; + + var values = MessageForms.ShowDialog("Auto apply settings", new[] { + allowAutoApplyField, + processActionField + }); + if (!values.Any()) + { + return; + } + + preset.AutoSettings.AllowAutoApply = allowAutoApplyField.ValueAsBool; + preset.AutoSettings.ProcessAutoAction = processActionField.ValueAsEnum(); + } } } diff --git a/ColorControl/Services/GameLauncher/GamePanel.resx b/ColorControl/Services/GameLauncher/GamePanel.resx index 568ff43..cb6c59a 100644 --- a/ColorControl/Services/GameLauncher/GamePanel.resx +++ b/ColorControl/Services/GameLauncher/GamePanel.resx @@ -18,7 +18,7 @@ System.Resources.ResXResourceReader, System.Windows.Forms, ... System.Resources.ResXResourceWriter, System.Windows.Forms, ... this is my long stringthis is a comment - Blue + Blue [base64 mime encoded serialized .NET Framework object] diff --git a/ColorControl/Services/GameLauncher/GamePreset.cs b/ColorControl/Services/GameLauncher/GamePreset.cs index 12f51e7..8dd6266 100644 --- a/ColorControl/Services/GameLauncher/GamePreset.cs +++ b/ColorControl/Services/GameLauncher/GamePreset.cs @@ -26,6 +26,19 @@ namespace ColorControl.Services.GameLauncher RealTime = NativeConstants.REALTIME_PRIORITY_CLASS } + public enum ProcessAutoAction + { + None = 0, + Suspend = 1, + Restart = 2 + } + + class AutoSettings + { + public bool AllowAutoApply { get; set; } + public ProcessAutoAction ProcessAutoAction { get; set; } + } + class GamePreset : PresetBase { public string Path { get; set; } @@ -36,12 +49,14 @@ namespace ColorControl.Services.GameLauncher public List FinalizeSteps { get; set; } public uint ProcessAffinityMask { get; set; } public uint ProcessPriorityClass { get; set; } + public AutoSettings AutoSettings { get; set; } public GamePreset() : base() { PreLaunchSteps = new List(); PostLaunchSteps = new List(); FinalizeSteps = new List(); + AutoSettings = new AutoSettings(); } public GamePreset(GamePreset preset) : this() @@ -73,15 +88,16 @@ namespace ColorControl.Services.GameLauncher public override List GetDisplayValues(Config config = null) { - var values = new List(); + var values = new List + { + name, + Path, + Parameters, - values.Add(name); - values.Add(Path); - values.Add(Parameters); - - values.Add(string.Join(", ", PreLaunchSteps)); - values.Add(string.Join(", ", PostLaunchSteps)); - values.Add(string.Join(", ", FinalizeSteps)); + string.Join(", ", PreLaunchSteps), + string.Join(", ", PostLaunchSteps), + string.Join(", ", FinalizeSteps) + }; return values; } diff --git a/ColorControl/Services/GameLauncher/GameService.cs b/ColorControl/Services/GameLauncher/GameService.cs index 88657e8..cf4db42 100644 --- a/ColorControl/Services/GameLauncher/GameService.cs +++ b/ColorControl/Services/GameLauncher/GameService.cs @@ -1,27 +1,120 @@ using ColorControl.Services.Common; +using ColorControl.Services.EventDispatcher; using ColorControl.Shared.Common; using ColorControl.Shared.Services; +using Newtonsoft.Json; +using System; using System.Collections.Generic; using System.Diagnostics; +using System.IO; using System.Linq; +using System.Threading; using System.Threading.Tasks; namespace ColorControl.Services.GameLauncher { class GameService : ServiceBase { - //private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); + private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); public override string ServiceName => "Game"; protected override string PresetsBaseFilename => "GamePresets.json"; + private ProcessEventDispatcher _processEventDispatcher; + private readonly WinApiAdminService _winApiAdminService; + private readonly WinApiService _winApiService; private ServiceManager _serviceManager; + private int _lastStartedProcessId; + private System.DateTime _lastStartedPresetDateTime = System.DateTime.MinValue; + private string _lastStartedProcessPath; + private string _configFilename; - public GameService(AppContextProvider appContextProvider, ServiceManager serviceManager) : base(appContextProvider) + public GameServiceConfig Config { get; private set; } + + public GameService(AppContextProvider appContextProvider, ServiceManager serviceManager, ProcessEventDispatcher processEventDispatcher, WinApiAdminService winApiAdminService, WinApiService winApiService) : base(appContextProvider) { + LoadConfig(); LoadPresets(); _serviceManager = serviceManager; + _processEventDispatcher = processEventDispatcher; + _winApiAdminService = winApiAdminService; + _winApiService = winApiService; + _processEventDispatcher.RegisterAsyncEventHandler(ProcessEventDispatcher.Event_ProcessChanged, ProcessChanged); + } + + private async Task ProcessChanged(object sender, ProcessChangedEventArgs e, CancellationToken token) + { + if (e.StartedProcesses?.Any() != true || !Config.ApplyExternallyLaunched) + { + return; + } + + if (_lastStartedPresetDateTime > System.DateTime.Now.AddSeconds(-5)) + { + return; + } + _lastStartedProcessId = 0; + + var startedProcesses = e.StartedProcesses; + + foreach (var startedProcess in startedProcesses) + { + try + { + if (await HandleStartedProcess(startedProcess)) + { + return; + } + } + catch (System.Exception) { } + } + } + + private async Task HandleStartedProcess(Process process) + { + GamePreset preset; + + if (_winApiService.IsAdministrator()) + { + var fileName = process.MainModule.FileName; + + preset = _presets.FirstOrDefault(p => fileName.Contains(Path.GetDirectoryName(p.Path), System.StringComparison.OrdinalIgnoreCase)); + } + else + { + var name = process.ProcessName.Replace("-Win64-Shipping", ""); + preset = _presets.FirstOrDefault(p => Path.GetFileName(p.Path).Contains(name, System.StringComparison.OrdinalIgnoreCase)); + } + + if (preset == null || !preset.AutoSettings.AllowAutoApply) + { + return false; + } + + if (_lastStartedProcessId != process.Id) + { + Logger.Debug($"Auto-starting preset {preset.name} for process {process.ProcessName}"); + + var mainThreadId = 0; + var suspended = false; + if (preset.AutoSettings.ProcessAutoAction == ProcessAutoAction.Suspend) + { + mainThreadId = _winApiAdminService.SuspendMainThread(process.Id); + suspended = true; + } + else if (preset.AutoSettings.ProcessAutoAction == ProcessAutoAction.Restart) + { + _winApiAdminService.StopProcess(process.Id); + process = null; + } + + var _ = ExecutePreset(preset, process, suspended ? mainThreadId : 0); + + return true; + } + + return false; } protected override List GetDefaultPresets() @@ -37,6 +130,7 @@ namespace ColorControl.Services.GameLauncher public void GlobalSave() { SavePresets(); + SaveConfig(); } public async Task ApplyPreset(string idOrName) @@ -57,17 +151,34 @@ namespace ColorControl.Services.GameLauncher return await ApplyPreset(preset, Program.AppContext); } - public async Task ApplyPreset(GamePreset preset, AppContext appContext) + public async Task ApplyPreset(GamePreset preset, GlobalContext _) + { + var result = await ExecutePreset(preset); + + _lastAppliedPreset = preset; + + PresetApplied(); + + return result; + } + + private async Task ExecutePreset(GamePreset preset, Process process = null, int resumeThreadId = default) { var result = true; await ExecuteSteps(preset.PreLaunchSteps); - Process process = null; - - if (!string.IsNullOrEmpty(preset.Path)) + if (process == null && !string.IsNullOrEmpty(preset.Path)) { - process = Utils.StartProcess(preset.Path, preset.Parameters, setWorkingDir: true, elevate: preset.RunAsAdministrator, affinityMask: preset.ProcessAffinityMask, priorityClass: preset.ProcessPriorityClass); + process = _winApiAdminService.StartProcess(preset.Path, preset.Parameters, setWorkingDir: true, elevate: preset.RunAsAdministrator, affinityMask: preset.ProcessAffinityMask, priorityClass: preset.ProcessPriorityClass); + + _lastStartedPresetDateTime = System.DateTime.Now; + _lastStartedProcessId = process.Id; + _lastStartedProcessPath = Path.GetDirectoryName(preset.Path); + } + else if (resumeThreadId != default) + { + _winApiAdminService.ResumeThread((uint)resumeThreadId); } await ExecuteSteps(preset.PostLaunchSteps); @@ -77,16 +188,27 @@ namespace ColorControl.Services.GameLauncher await ExecuteFinalizationStepsAsync(process, preset.FinalizeSteps); } - _lastAppliedPreset = preset; - - PresetApplied(); - return result; } private async Task ExecuteFinalizationStepsAsync(Process process, List finalizeSteps) { - await process.WaitForExitAsync(); + await Task.Delay(1000); + + try + { + if (process.HasExited) + { + return; + } + + await process.WaitForExitAsync(); + } + catch (Exception ex) + { + Logger.Error(ex); + return; + } await ExecuteSteps(finalizeSteps); } @@ -140,5 +262,27 @@ namespace ColorControl.Services.GameLauncher } } + + private void LoadConfig() + { + _configFilename = Path.Combine(_dataPath, "GameConfig.json"); + try + { + if (File.Exists(_configFilename)) + { + Config = JsonConvert.DeserializeObject(File.ReadAllText(_configFilename)); + } + } + catch (System.Exception ex) + { + Logger.Error($"LoadConfig: {ex.Message}"); + } + Config ??= new GameServiceConfig(); + } + + private void SaveConfig() + { + Utils.WriteObject(_configFilename, Config); + } } } diff --git a/ColorControl/Services/GameLauncher/GameServiceConfig.cs b/ColorControl/Services/GameLauncher/GameServiceConfig.cs new file mode 100644 index 0000000..f65dd71 --- /dev/null +++ b/ColorControl/Services/GameLauncher/GameServiceConfig.cs @@ -0,0 +1,11 @@ +namespace ColorControl.Services.GameLauncher +{ + class GameServiceConfig + { + public bool ApplyExternallyLaunched { get; set; } + + public GameServiceConfig() + { + } + } +} diff --git a/ColorControl/Services/LG/LgDevice.cs b/ColorControl/Services/LG/LgDevice.cs index 6a8f18d..e7a846a 100644 --- a/ColorControl/Services/LG/LgDevice.cs +++ b/ColorControl/Services/LG/LgDevice.cs @@ -1,5 +1,6 @@ using ColorControl.Services.Common; using ColorControl.Shared.Common; +using ColorControl.Shared.Services; using LgTv; using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; @@ -262,8 +263,10 @@ namespace ColorControl.Services.LG AddSetDeviceConfigAction("HDMI_4_icon", typeof(HdmiIcon), "HDMI 4 icon"); AddGenericPictureAction("soundMode", typeof(SoundMode), category: "sound", title: "Sound Mode"); + AddGenericPictureAction("smartSoundMode", typeof(OffToOn), category: "sound", title: "Adaptive Sound Control"); AddGenericPictureAction("soundOutput", typeof(SoundOutput), category: "sound", title: "Sound Output"); AddGenericPictureAction("autoVolume", typeof(OffToOn), category: "sound", title: "Auto Volume"); + AddGenericPictureAction("virtualSurround", typeof(OffToOn), category: "sound", title: "Virtual Surround"); //AddGenericPictureAction("enableToastPopup", typeof(OffToOn), category: "option", title: "enableToastPopup"); AddSetConfigAction("tv.conti.supportUsedTime", typeof(BoolFalseToTrue), title: "Total Power On Time"); @@ -917,7 +920,9 @@ namespace ColorControl.Services.LG if (MacAddress != null) { - result = WOL.WakeFunctionCheckAdmin(MacAddress, IpAddress); + var wolService = Program.ServiceProvider.GetRequiredService(); + + result = wolService.SendWol(MacAddress, IpAddress); _justWokeUp = true; } else diff --git a/ColorControl/Services/LG/LgGameBar.cs b/ColorControl/Services/LG/LgGameBar.cs index 0d33699..d8b2420 100644 --- a/ColorControl/Services/LG/LgGameBar.cs +++ b/ColorControl/Services/LG/LgGameBar.cs @@ -263,7 +263,7 @@ namespace ColorControl.Services.LG private void UpdateInfo() { lblTvName.Text = $"Device: {_lgDevice?.Name ?? "No tv selected"}"; - lblProcessName.Text = $"Current process: {_lgService.MonitorContext?.ForegroundProcess?.ProcessName ?? _lgService.MonitorContext?.LastFullScreenProcessName ?? "No full screen process"}"; + lblProcessName.Text = $"Current process: {_lgService.CurrentProcessEvent?.ForegroundProcess?.ProcessName ?? _lgService.CurrentProcessEvent?.LastFullScreenProcessName ?? "No full screen process"}"; UpdateValues(); } diff --git a/ColorControl/Services/LG/LgPanel.cs b/ColorControl/Services/LG/LgPanel.cs index 295d908..551ac9e 100644 --- a/ColorControl/Services/LG/LgPanel.cs +++ b/ColorControl/Services/LG/LgPanel.cs @@ -43,7 +43,7 @@ namespace ColorControl.Services.LG _trayIcon = trayIcon; _mainHandle = handle; - _config = Shared.Common.AppContext.CurrentContext.Config; + _config = Shared.Common.GlobalContext.CurrentContext.Config; InitializeComponent(); @@ -96,7 +96,7 @@ namespace ColorControl.Services.LG { FillLgDevices(); - var startUpParams = Shared.Common.AppContext.CurrentContext.StartUpParams; + var startUpParams = Shared.Common.GlobalContext.CurrentContext.StartUpParams; if (startUpParams.ExecuteLgPreset) { diff --git a/ColorControl/Services/LG/LgService.cs b/ColorControl/Services/LG/LgService.cs index 0130ea2..04a9368 100644 --- a/ColorControl/Services/LG/LgService.cs +++ b/ColorControl/Services/LG/LgService.cs @@ -22,19 +22,6 @@ namespace ColorControl.Services.LG { class LgService : ServiceBase { - internal class ProcessMonitorContext - { - public List Devices { get; set; } - public bool WasFullScreen { get; set; } - public Process[] StartedProcesses { get; set; } - public Process[] StoppedProcesses { get; set; } - public Process[] RunningProcesses { get; set; } - public bool IsNotificationDisabled { get; set; } - public Process ForegroundProcess { get; set; } - public bool ForegroundProcessIsFullScreen { get; set; } - public string LastFullScreenProcessName = string.Empty; - } - protected static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); public static string LgListAppsJson = "listApps.json"; @@ -56,7 +43,6 @@ namespace ColorControl.Services.LG public event EventHandler SelectedDeviceChangedEvent; public LgServiceConfig Config { get; private set; } - public ProcessMonitorContext MonitorContext { get; private set; } protected override string PresetsBaseFilename => "LgPresets.json"; @@ -75,9 +61,13 @@ namespace ColorControl.Services.LG private int _poweredOffByScreenSaverProcessId; private LgPreset _lastTriggeredPreset; private RestartDetector _restartDetector; + private readonly WinApiService _winApiService; + private readonly WinApiAdminService _winApiAdminService; private SynchronizationContext _syncContext; - public LgService(AppContextProvider appContextProvider, PowerEventDispatcher powerEventDispatcher, SessionSwitchDispatcher sessionSwitchDispatcher, ProcessEventDispatcher processEventDispatcher, ServiceManager serviceManager, RestartDetector restartDetector) : base(appContextProvider) + public ProcessChangedEventArgs CurrentProcessEvent => _processEventDispatcher?.MonitorContext; + + public LgService(AppContextProvider appContextProvider, PowerEventDispatcher powerEventDispatcher, SessionSwitchDispatcher sessionSwitchDispatcher, ProcessEventDispatcher processEventDispatcher, ServiceManager serviceManager, RestartDetector restartDetector, WinApiService winApiService, WinApiAdminService winApiAdminService) : base(appContextProvider) { _allowPowerOn = appContextProvider.GetAppContext().StartUpParams.RunningFromScheduledTask; _powerEventDispatcher = powerEventDispatcher; @@ -87,6 +77,8 @@ namespace ColorControl.Services.LG LgPreset.LgApps = _lgApps; _restartDetector = restartDetector; + _winApiService = winApiService; + _winApiAdminService = winApiAdminService; _syncContext = appContextProvider.GetAppContext().SynchronizationContext; LgTvApiCore.SyncContext = _syncContext; @@ -851,7 +843,7 @@ namespace ColorControl.Services.LG var standByScript = Path.Combine(Program.DataDir, "StandByScript.bat"); if (File.Exists(standByScript)) { - Utils.StartProcess(standByScript, hidden: true, wait: true); + _winApiAdminService.StartProcess(standByScript, hidden: true, wait: true); } } @@ -911,13 +903,13 @@ namespace ColorControl.Services.LG if (File.Exists(resumeScript)) { - Utils.StartProcess(resumeScript, hidden: true); + _winApiAdminService.StartProcess(resumeScript, hidden: true); } } private void SendConfigToService() { - if (!Utils.IsServiceRunning()) + if (!_winApiService.IsServiceRunning()) { return; } diff --git a/ColorControl/Services/NVIDIA/NvInfoPanel.Designer.cs b/ColorControl/Services/NVIDIA/NvInfoPanel.Designer.cs new file mode 100644 index 0000000..47cb9c3 --- /dev/null +++ b/ColorControl/Services/NVIDIA/NvInfoPanel.Designer.cs @@ -0,0 +1,89 @@ +namespace ColorControl.Services.NVIDIA +{ + partial class NvInfoPanel + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + grpNVIDIAInfo = new System.Windows.Forms.GroupBox(); + btnRefreshNVIDIAInfo = new System.Windows.Forms.Button(); + tvNVIDIAInfo = new System.Windows.Forms.TreeView(); + grpNVIDIAInfo.SuspendLayout(); + SuspendLayout(); + // + // grpNVIDIAInfo + // + grpNVIDIAInfo.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; + grpNVIDIAInfo.Controls.Add(btnRefreshNVIDIAInfo); + grpNVIDIAInfo.Controls.Add(tvNVIDIAInfo); + grpNVIDIAInfo.Location = new System.Drawing.Point(4, 3); + grpNVIDIAInfo.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + grpNVIDIAInfo.Name = "grpNVIDIAInfo"; + grpNVIDIAInfo.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3); + grpNVIDIAInfo.Size = new System.Drawing.Size(643, 547); + grpNVIDIAInfo.TabIndex = 5; + grpNVIDIAInfo.TabStop = false; + grpNVIDIAInfo.Text = "NVIDIA info"; + // + // btnRefreshNVIDIAInfo + // + btnRefreshNVIDIAInfo.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left; + btnRefreshNVIDIAInfo.Location = new System.Drawing.Point(8, 514); + btnRefreshNVIDIAInfo.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + btnRefreshNVIDIAInfo.Name = "btnRefreshNVIDIAInfo"; + btnRefreshNVIDIAInfo.Size = new System.Drawing.Size(88, 27); + btnRefreshNVIDIAInfo.TabIndex = 1; + btnRefreshNVIDIAInfo.Text = "Refresh"; + btnRefreshNVIDIAInfo.UseVisualStyleBackColor = true; + btnRefreshNVIDIAInfo.Click += btnRefreshNVIDIAInfo_Click; + // + // tvNVIDIAInfo + // + tvNVIDIAInfo.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; + tvNVIDIAInfo.Location = new System.Drawing.Point(8, 22); + tvNVIDIAInfo.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + tvNVIDIAInfo.Name = "tvNVIDIAInfo"; + tvNVIDIAInfo.Size = new System.Drawing.Size(627, 486); + tvNVIDIAInfo.TabIndex = 0; + // + // NvInfoPanel + // + AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + Controls.Add(grpNVIDIAInfo); + Name = "NvInfoPanel"; + Size = new System.Drawing.Size(654, 556); + grpNVIDIAInfo.ResumeLayout(false); + ResumeLayout(false); + } + + #endregion + + private System.Windows.Forms.GroupBox grpNVIDIAInfo; + private System.Windows.Forms.Button btnRefreshNVIDIAInfo; + private System.Windows.Forms.TreeView tvNVIDIAInfo; + } +} diff --git a/ColorControl/Services/NVIDIA/NvInfoPanel.cs b/ColorControl/Services/NVIDIA/NvInfoPanel.cs new file mode 100644 index 0000000..a617cf2 --- /dev/null +++ b/ColorControl/Services/NVIDIA/NvInfoPanel.cs @@ -0,0 +1,46 @@ +using ColorControl.Shared.Forms; +using NvAPIWrapper.Display; +using System.Windows.Forms; + +namespace ColorControl.Services.NVIDIA +{ + public partial class NvInfoPanel : UserControl, IModulePanel + { + private NvService _nvService; + + internal NvInfoPanel(NvService nvService) + { + _nvService = nvService; + + InitializeComponent(); + + if (DarkModeUtils.UseDarkMode) + { + grpNVIDIAInfo.ForeColor = FormUtils.CurrentForeColor; + } + + RefreshInfo(); + } + + public void UpdateInfo() + { + RefreshInfo(); + } + + private void btnRefreshNVIDIAInfo_Click(object sender, System.EventArgs e) + { + } + + private void RefreshInfo() + { + tvNVIDIAInfo.Nodes.Clear(); + var displays = Display.GetDisplays(); + for (var i = 0; i < displays.Length; i++) + { + var display = displays[i]; + var node = TreeNodeBuilder.CreateTree(display, $"Display[{i}]"); + tvNVIDIAInfo.Nodes.Add(node); + } + } + } +} diff --git a/ColorControl/Services/NVIDIA/NvInfoPanel.resx b/ColorControl/Services/NVIDIA/NvInfoPanel.resx new file mode 100644 index 0000000..a395bff --- /dev/null +++ b/ColorControl/Services/NVIDIA/NvInfoPanel.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/ColorControl/Services/NVIDIA/NvPanel.Designer.cs b/ColorControl/Services/NVIDIA/NvPanel.Designer.cs index 0a7c5e3..987376b 100644 --- a/ColorControl/Services/NVIDIA/NvPanel.Designer.cs +++ b/ColorControl/Services/NVIDIA/NvPanel.Designer.cs @@ -82,6 +82,8 @@ namespace ColorControl.Services.NVIDIA miNvDriverSettingsIncluded = new System.Windows.Forms.ToolStripMenuItem(); mnuNvOtherSettings = new System.Windows.Forms.ToolStripMenuItem(); miNvOtherIncluded = new System.Windows.Forms.ToolStripMenuItem(); + mnuNvHdmiSettings = new System.Windows.Forms.ToolStripMenuItem(); + miNvHdmiIncluded = new System.Windows.Forms.ToolStripMenuItem(); mnuNvOverclocking = new System.Windows.Forms.ToolStripMenuItem(); miNvOverclockingIncluded = new System.Windows.Forms.ToolStripMenuItem(); miNvCopyId = new System.Windows.Forms.ToolStripMenuItem(); @@ -91,9 +93,9 @@ namespace ColorControl.Services.NVIDIA miNvProfileInspector = new System.Windows.Forms.ToolStripMenuItem(); miNvNovideo = new System.Windows.Forms.ToolStripMenuItem(); miNvSettings = new System.Windows.Forms.ToolStripMenuItem(); + miNvTestDithering = new System.Windows.Forms.ToolStripMenuItem(); lvNvPresetsToolTip = new System.Windows.Forms.ToolTip(components); - mnuNvHdmiSettings = new System.Windows.Forms.ToolStripMenuItem(); - miNvHdmiIncluded = new System.Windows.Forms.ToolStripMenuItem(); + miNVIDIAInfo = new System.Windows.Forms.ToolStripMenuItem(); mnuNvPresets.SuspendLayout(); mnuNvSettings.SuspendLayout(); SuspendLayout(); @@ -326,7 +328,7 @@ namespace ColorControl.Services.NVIDIA mnuNvPresets.ImageScalingSize = new System.Drawing.Size(20, 20); mnuNvPresets.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { miNvApply, miNvPresetApplyOnStartup, tssNvPresetMenu, mnuNvDisplay, mnuNvPresetsColorSettings, mnuRefreshRate, mnuNvResolution, miNvPresetDithering, miNvHDR, mnuNvDriverSettings, mnuNvOtherSettings, mnuNvHdmiSettings, mnuNvOverclocking, miNvCopyId }); mnuNvPresets.Name = "mnuNvPresets"; - mnuNvPresets.Size = new System.Drawing.Size(185, 318); + mnuNvPresets.Size = new System.Drawing.Size(185, 296); mnuNvPresets.Opening += mnuNvPresets_Opening; // // miNvApply @@ -543,7 +545,7 @@ namespace ColorControl.Services.NVIDIA // miNvDriverSettingsIncluded // miNvDriverSettingsIncluded.Name = "miNvDriverSettingsIncluded"; - miNvDriverSettingsIncluded.Size = new System.Drawing.Size(180, 22); + miNvDriverSettingsIncluded.Size = new System.Drawing.Size(120, 22); miNvDriverSettingsIncluded.Text = "Included"; miNvDriverSettingsIncluded.Click += miNvDriverSettingsIncluded_Click; // @@ -557,10 +559,24 @@ namespace ColorControl.Services.NVIDIA // miNvOtherIncluded // miNvOtherIncluded.Name = "miNvOtherIncluded"; - miNvOtherIncluded.Size = new System.Drawing.Size(180, 22); + miNvOtherIncluded.Size = new System.Drawing.Size(120, 22); miNvOtherIncluded.Text = "Included"; miNvOtherIncluded.Click += miNvOtherIncluded_Click; // + // mnuNvHdmiSettings + // + mnuNvHdmiSettings.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { miNvHdmiIncluded }); + mnuNvHdmiSettings.Name = "mnuNvHdmiSettings"; + mnuNvHdmiSettings.Size = new System.Drawing.Size(184, 22); + mnuNvHdmiSettings.Text = "HDMI Settings"; + // + // miNvHdmiIncluded + // + miNvHdmiIncluded.Name = "miNvHdmiIncluded"; + miNvHdmiIncluded.Size = new System.Drawing.Size(120, 22); + miNvHdmiIncluded.Text = "Included"; + miNvHdmiIncluded.Click += miNvHdmiIncluded_Click; + // // mnuNvOverclocking // mnuNvOverclocking.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { miNvOverclockingIncluded }); @@ -571,7 +587,7 @@ namespace ColorControl.Services.NVIDIA // miNvOverclockingIncluded // miNvOverclockingIncluded.Name = "miNvOverclockingIncluded"; - miNvOverclockingIncluded.Size = new System.Drawing.Size(180, 22); + miNvOverclockingIncluded.Size = new System.Drawing.Size(120, 22); miNvOverclockingIncluded.Text = "Included"; miNvOverclockingIncluded.Click += miNvOverclockingIncluded_Click; // @@ -620,9 +636,9 @@ namespace ColorControl.Services.NVIDIA // mnuNvSettings // mnuNvSettings.ImageScalingSize = new System.Drawing.Size(20, 20); - mnuNvSettings.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { miNvProfileInspector, miNvNovideo, miNvSettings }); + mnuNvSettings.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { miNvProfileInspector, miNvNovideo, miNvSettings, miNvTestDithering, miNVIDIAInfo }); mnuNvSettings.Name = "mnuLgButtons"; - mnuNvSettings.Size = new System.Drawing.Size(202, 70); + mnuNvSettings.Size = new System.Drawing.Size(202, 136); // // miNvProfileInspector // @@ -645,19 +661,19 @@ namespace ColorControl.Services.NVIDIA miNvSettings.Text = "Settings"; miNvSettings.Click += miNvSettings_Click; // - // mnuNvHdmiSettings + // miNvTestDithering // - mnuNvHdmiSettings.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { miNvHdmiIncluded }); - mnuNvHdmiSettings.Name = "mnuNvHdmiSettings"; - mnuNvHdmiSettings.Size = new System.Drawing.Size(184, 22); - mnuNvHdmiSettings.Text = "HDMI Settings"; + miNvTestDithering.Name = "miNvTestDithering"; + miNvTestDithering.Size = new System.Drawing.Size(201, 22); + miNvTestDithering.Text = "Test dithering"; + miNvTestDithering.Click += miNvTestDithering_Click; // - // miNvHdmiIncluded + // miNVIDIAInfo // - miNvHdmiIncluded.Name = "miNvHdmiIncluded"; - miNvHdmiIncluded.Size = new System.Drawing.Size(180, 22); - miNvHdmiIncluded.Text = "Included"; - miNvHdmiIncluded.Click += miNvHdmiIncluded_Click; + miNVIDIAInfo.Name = "miNVIDIAInfo"; + miNVIDIAInfo.Size = new System.Drawing.Size(201, 22); + miNVIDIAInfo.Text = "NVIDIA Info"; + miNVIDIAInfo.Click += miNVIDIAInfo_Click; // // NvPanel // @@ -760,5 +776,7 @@ namespace ColorControl.Services.NVIDIA private System.Windows.Forms.ToolStripMenuItem miNvOtherIncluded; private System.Windows.Forms.ToolStripMenuItem mnuNvHdmiSettings; private System.Windows.Forms.ToolStripMenuItem miNvHdmiIncluded; + private System.Windows.Forms.ToolStripMenuItem miNvTestDithering; + private System.Windows.Forms.ToolStripMenuItem miNVIDIAInfo; } } diff --git a/ColorControl/Services/NVIDIA/NvPanel.cs b/ColorControl/Services/NVIDIA/NvPanel.cs index 7731bac..405505e 100644 --- a/ColorControl/Services/NVIDIA/NvPanel.cs +++ b/ColorControl/Services/NVIDIA/NvPanel.cs @@ -37,9 +37,9 @@ namespace ColorControl.Services.NVIDIA private readonly AppContextProvider _appContextProvider; private string _lastDisplayRefreshRates = string.Empty; private NotifyIcon _trayIcon; - private RpcService _rpcService; + private RpcClientService _rpcService; - public NvPanel(NvService nvService, NotifyIcon trayIcon, IntPtr handle, AppContextProvider appContextProvider, RpcService rpcService) + public NvPanel(NvService nvService, NotifyIcon trayIcon, IntPtr handle, AppContextProvider appContextProvider, RpcClientService rpcService) { _nvService = nvService; _trayIcon = trayIcon; @@ -287,17 +287,20 @@ namespace ColorControl.Services.NVIDIA { var preset = GetSelectedNvPreset(true); + var checkState = miNvPresetDitheringEnabled.CheckState; + var newCheckState = checkState == CheckState.Checked ? CheckState.Unchecked : checkState == CheckState.Unchecked ? CheckState.Indeterminate : CheckState.Checked; + if (preset.IsDisplayPreset) { - miNvPresetDitheringEnabled.Checked = !miNvPresetDitheringEnabled.Checked; + miNvPresetDitheringEnabled.CheckState = newCheckState; - _nvService.SetDithering(miNvPresetDitheringEnabled.Checked ? NvDitherState.Enabled : NvDitherState.Disabled); + _nvService.SetDithering(newCheckState == CheckState.Indeterminate ? NvDitherState.Auto : newCheckState == CheckState.Checked ? NvDitherState.Enabled : NvDitherState.Disabled); UpdateDisplayInfoItems(); return; } - preset.ditheringEnabled = !preset.ditheringEnabled; + preset.ditheringEnabled = checkState == CheckState.Indeterminate ? null : checkState == CheckState.Checked; AddOrUpdateItem(); } @@ -395,7 +398,7 @@ namespace ColorControl.Services.NVIDIA miNvPresetColorSettings.Checked = preset.applyColorData; miNvPresetApplyDithering.Checked = preset.applyDithering; - miNvPresetDitheringEnabled.Checked = preset.ditheringEnabled; + miNvPresetDitheringEnabled.CheckState = preset.ditheringEnabled == null ? CheckState.Indeterminate : preset.ditheringEnabled == true ? CheckState.Checked : CheckState.Unchecked; foreach (var item in mnuNvDitheringBitDepth.DropDownItems.OfType()) { @@ -1466,7 +1469,7 @@ namespace ColorControl.Services.NVIDIA return; } - _nvService.ApplyOverclocking(newSettings); + _nvService.ApplyOverclocking(new List { newSettings }); UpdateNvGpuInfo(); } @@ -1687,7 +1690,7 @@ namespace ColorControl.Services.NVIDIA private async Task ApplyNvPresetOnStartup(int attempts = 5) { - var startUpParams = Shared.Common.AppContext.CurrentContext.StartUpParams; + var startUpParams = Shared.Common.GlobalContext.CurrentContext.StartUpParams; var presetIdOrName = !string.IsNullOrEmpty(startUpParams.NvidiaPresetIdOrName) ? startUpParams.NvidiaPresetIdOrName : _config.NvPresetId_ApplyOnStartup.ToString(); @@ -1728,7 +1731,7 @@ namespace ColorControl.Services.NVIDIA if (preset.IsDisplayPreset) { - _nvService.SetDithering(preset.ditheringEnabled ? NvDitherState.Enabled : NvDitherState.Disabled, ditheringBits, preset.ditheringMode); + _nvService.SetDithering(preset.DitherState, ditheringBits, preset.ditheringMode); UpdateDisplayInfoItems(); return; @@ -1749,7 +1752,7 @@ namespace ColorControl.Services.NVIDIA if (preset.IsDisplayPreset) { - _nvService.SetDithering(preset.ditheringEnabled ? NvDitherState.Enabled : NvDitherState.Disabled, preset.ditheringBits, ditheringMode); + _nvService.SetDithering(preset.DitherState, preset.ditheringBits, ditheringMode); UpdateDisplayInfoItems(); return; @@ -1797,5 +1800,19 @@ namespace ColorControl.Services.NVIDIA AddOrUpdateItem(); } + + private void miNvTestDithering_Click(object sender, EventArgs e) + { + var panel = new NvDitherPanel(_nvService); + + MessageForms.ShowControl(panel, "Test dithering"); + } + + private void miNVIDIAInfo_Click(object sender, EventArgs e) + { + var panel = new NvInfoPanel(_nvService); + + MessageForms.ShowControl(panel, "NVIDIA Info"); + } } } diff --git a/ColorControl/Services/NVIDIA/NvPreset.cs b/ColorControl/Services/NVIDIA/NvPreset.cs index 95c5c01..1b1a396 100644 --- a/ColorControl/Services/NVIDIA/NvPreset.cs +++ b/ColorControl/Services/NVIDIA/NvPreset.cs @@ -23,7 +23,7 @@ namespace ColorControl.Services.NVIDIA public bool HDREnabled { get; set; } public bool toggleHDR { get; set; } public bool applyDithering { get; set; } - public bool ditheringEnabled { get; set; } + public bool? ditheringEnabled { get; set; } public bool applyRefreshRate { get; set; } public uint refreshRate { get; set; } public bool applyResolution { get; set; } @@ -49,6 +49,7 @@ namespace ColorControl.Services.NVIDIA public Display Display { get; set; } [JsonIgnore] public string InfoLine { get; set; } + public NvDitherState DitherState => ditheringEnabled.HasValue ? ditheringEnabled == true ? NvDitherState.Enabled : NvDitherState.Disabled : NvDitherState.Auto; public NvPreset() : base() { @@ -224,14 +225,19 @@ namespace ColorControl.Services.NVIDIA public string GetDitheringDescription(string disabledText = "Disabled") { - var dithering = ditheringEnabled ? string.Empty : disabledText; - if (ditheringEnabled) + if (ditheringEnabled == null && ditheringBits == 0 && ditheringMode == 0) + { + return "Auto: Disabled"; + } + + if (ditheringEnabled is null or true) { var ditherBitsDescription = ((NvDitherBits)ditheringBits).GetDescription(); var ditherModeDescription = ((NvDitherMode)ditheringMode).GetDescription(); - dithering = string.Format("{0} {1}", ditherBitsDescription, ditherModeDescription); + return string.Format("{0}{1} {2}", ditheringEnabled == null ? "Auto: " : "", ditherBitsDescription, ditherModeDescription); } - return dithering; + + return disabledText; } public string GetHdmiSettingsDescription() diff --git a/ColorControl/Services/NVIDIA/NvService.cs b/ColorControl/Services/NVIDIA/NvService.cs index de1fc11..7af7bb3 100644 --- a/ColorControl/Services/NVIDIA/NvService.cs +++ b/ColorControl/Services/NVIDIA/NvService.cs @@ -7,6 +7,7 @@ using ColorControl.Shared.Native; using ColorControl.Shared.Services; using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; +using novideo_srgb; using nspector.Common; using nspector.Common.Meta; using NvAPIWrapper.Display; @@ -143,11 +144,15 @@ namespace ColorControl.Services.NVIDIA DRS_RBAR_OPTIONS, DRS_RBAR_SIZE_LIMIT }; - + private readonly WinApiService _winApiService; + private readonly RpcClientService _rpcClientService; private static NvService ServiceInstance; - public NvService(AppContextProvider appContextProvider) : base(appContextProvider) + public NvService(AppContextProvider appContextProvider, WinApiService winApiService, RpcClientService rpcClientService) : base(appContextProvider) { + _winApiService = winApiService; + _rpcClientService = rpcClientService; + _rpcClientService.Name = nameof(NvService); NvPreset.NvService = this; AddJsonConverter(new ColorDataConverter()); @@ -159,9 +164,7 @@ namespace ColorControl.Services.NVIDIA { try { - var appContextProvider = Program.ServiceProvider.GetRequiredService(); - - var nvService = new NvService(appContextProvider); + var nvService = Program.ServiceProvider.GetRequiredService(); var result = await nvService.ApplyPreset(idOrName); @@ -315,6 +318,11 @@ namespace ColorControl.Services.NVIDIA if (applyHdr) { + if (newHdrEnabled && !hdrEnabled) + { + MainWindow.BeforeDisplaySettingsChange(); + } + SetHDRState(display, newHdrEnabled); } @@ -341,7 +349,7 @@ namespace ColorControl.Services.NVIDIA if (preset.applyDithering) { - if (!SetDithering(preset.ditheringEnabled ? NvDitherState.Enabled : NvDitherState.Disabled, preset: preset)) + if (!SetDithering(preset.DitherState, preset: preset)) { result = false; } @@ -364,19 +372,17 @@ namespace ColorControl.Services.NVIDIA return Task.FromResult(result); } - public bool ApplyOverclocking(NvGpuOcSettings setting) - { - return ApplyOverclocking(new List { setting }); - } - public bool ApplyOverclocking(List settings) { - if (!Utils.IsAdministrator()) + if (!_winApiService.IsAdministrator()) { - var result = PipeUtils.SendMessage(new SvcNvOverclockingMessage + var message = new SvcRpcSetNvOverclockingMessage { + MethodName = nameof(ApplyOverclocking), OverclockingSettings = settings - }); + }; + + var result = _rpcClientService.Call(message); if (result == null) { @@ -418,42 +424,26 @@ namespace ColorControl.Services.NVIDIA } } - public static void ApplyDriverSettings(string profileName, List> settings) + public void ApplyDriverSettings(string profileName, List> settings) { - CheckServiceInstance(); + RefreshProfileSettings(); - ServiceInstance._drs.StoreSettingsToProfile(profileName, settings); + _drs.StoreSettingsToProfile(profileName, settings); } - public static bool RestoreDriverSettings(string profileName, List> settings) + public bool RestoreDriverSettings(string profileName, List> settings) { - CheckServiceInstance(); - var result = false; foreach (var keyValuePair in settings) { var settingId = keyValuePair.Key; - ServiceInstance._drs.ResetValue(profileName, settingId, out result); + _drs.ResetValue(profileName, settingId, out result); } return result; } - public static NvService CheckServiceInstance() - { - if (ServiceInstance == null) - { - var appContextProvider = Program.ServiceProvider.GetRequiredService(); - - ServiceInstance = new NvService(appContextProvider); - ServiceInstance.Initialize(); - ServiceInstance.RefreshProfileSettings(); - } - - return ServiceInstance; - } - private void SetDriverSettings(Dictionary settings) { var convertedSettings = new List>(); @@ -853,6 +843,22 @@ namespace ColorControl.Services.NVIDIA //var display = GetCurrentDisplay(); //var displayDevice = display.DisplayDevice; + //var config = DisplayApi.GetDisplayConfig(); + + //var config1 = config[0]; + + //var pathInfo1 = config1.TargetsInfo.First(); + + //var details = pathInfo1.Details.Value; + + //var newDetails = new PathAdvancedTargetInfo(details.Rotation, Scaling.GPUScanOutToNative); + + //var newPathTargetInfo = new PathTargetInfoV2(pathInfo1.DisplayId, newDetails); + + //var newPathInfo = new PathInfoV2(new[] { newPathTargetInfo }, config1.SourceModeInfo); + + //DisplayApi.SetDisplayConfig(new IPathInfo[] { newPathInfo }, DisplayConfigFlags.SaveToPersistence); + //var info = DisplayApi.GetScanOutConfiguration(displayDevice.DisplayId); //var vertices = new float[] { @@ -1023,7 +1029,7 @@ namespace ColorControl.Services.NVIDIA } else { - preset.ditheringEnabled = ditherInfo.state != (int)NvDitherState.Disabled; + preset.ditheringEnabled = ditherInfo.state == 0 ? null : ditherInfo.state != (int)NvDitherState.Disabled; preset.ditheringBits = (uint)ditherInfo.bits; preset.ditheringMode = (uint)ditherInfo.mode; } @@ -1123,11 +1129,11 @@ namespace ColorControl.Services.NVIDIA _drs.GetProfileNames(ref _baseProfileName, false); - if (!Utils.IsAdministrator()) - { - _drs.ApplySettings += HandleDrsApplySettings; - _drs.RestoreSetting += HandleDrsRestoreSetting; - } + //if (!WinApiService.IsAdministratorStatic()) + //{ + _drs.ApplySettings += HandleDrsApplySettings; + _drs.RestoreSetting += HandleDrsRestoreSetting; + //} //SetGpuClocks(); @@ -1169,10 +1175,9 @@ namespace ColorControl.Services.NVIDIA private bool HasPrivilegesForUnexposedApis() { - return Utils.IsAdministrator() || _appContextProvider.GetAppContext()?.Config.ElevationMethod != ElevationMethod.UseService || _appContextProvider.GetAppContext()?.IsServiceRunning() != true; + return _winApiService.IsAdministrator() || !_winApiService.IsServiceRunning(); } - private void HandleDrsApplySettings(object sender, DrsEvent drsEvent) { if (HasPrivilegesForUnexposedApis()) @@ -1180,7 +1185,14 @@ namespace ColorControl.Services.NVIDIA return; } - PipeUtils.SendMessage(new SvcNvDriverSettingsMessage { ProfileName = drsEvent.ProfileName, DriverSettings = drsEvent.Settings }); + var message = new SvcRpcSetNvDriverSettingsMessage + { + MethodName = nameof(ApplyDriverSettings), + ProfileName = drsEvent.ProfileName, + DriverSettings = drsEvent.Settings + }; + + _rpcClientService.Call(message); drsEvent.Handled = true; } @@ -1192,7 +1204,14 @@ namespace ColorControl.Services.NVIDIA return; } - PipeUtils.SendMessage(new SvcNvDriverSettingsMessage(SvcMessageType.RestoreNvidiaDriverSetting) { ProfileName = drsEvent.ProfileName, DriverSettings = drsEvent.Settings }); + var message = new SvcRpcSetNvDriverSettingsMessage + { + MethodName = nameof(RestoreDriverSettings), + ProfileName = drsEvent.ProfileName, + DriverSettings = drsEvent.Settings + }; + + _rpcClientService.Call(message); drsEvent.Handled = true; } diff --git a/ColorControl/Services/Samsung/SamsungDevice.cs b/ColorControl/Services/Samsung/SamsungDevice.cs index 382d495..a300205 100644 --- a/ColorControl/Services/Samsung/SamsungDevice.cs +++ b/ColorControl/Services/Samsung/SamsungDevice.cs @@ -1,6 +1,7 @@ using ColorControl.Services.Common; using ColorControl.Shared.Common; using ColorControl.Shared.Forms; +using ColorControl.Shared.Services; using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; using NLog; @@ -114,7 +115,7 @@ namespace ColorControl.Services.Samsung AddInvokableAction("WOL", WakeAction); AddInvokableAction("ServiceMenu", ServiceMenuAction, true); - AddInternalPresetAction(new SamsungPreset("PictureOff", null, new[] { "KEY_AD:1200", "KEY_DOWN:300", "KEY_DOWN:300", "KEY_ENTER" })); + AddInternalPresetAction(new SamsungPreset("PictureOff", null, new[] { "KEY_AD:1400", "KEY_DOWN:200", "KEY_DOWN:200", "KEY_ENTER" })); AddInternalPresetAction(new SamsungPreset("PictureOn", null, new[] { "KEY_RETURN:1000", "KEY_RETURN", "KEY_RETURN" })); _serviceManager = Program.ServiceProvider.GetRequiredService(); @@ -328,7 +329,9 @@ namespace ColorControl.Services.Samsung if (MacAddress != null) { - result = WOL.WakeFunctionCheckAdmin(MacAddress, IpAddress); + var wolService = Program.ServiceProvider.GetRequiredService(); + + result = wolService.SendWol(MacAddress, IpAddress); } else { @@ -385,7 +388,7 @@ namespace ColorControl.Services.Samsung return $"{(IsDummy ? string.Empty : (IsCustom ? "Custom: " : "Auto detect: "))}{Name}{(!string.IsNullOrEmpty(IpAddress) ? ", " + IpAddress : string.Empty)}"; } - internal async Task ExecutePresetAsync(SamsungPreset preset, Shared.Common.AppContext appContext = null, SamsungServiceConfig config = null) + internal async Task ExecutePresetAsync(SamsungPreset preset, Shared.Common.GlobalContext appContext = null, SamsungServiceConfig config = null) { if (config == null) { @@ -463,7 +466,7 @@ namespace ColorControl.Services.Samsung return true; } - private async Task ExecuteStepsAsync(SamsungPreset preset, Shared.Common.AppContext appContext, SamsungServiceConfig config) + private async Task ExecuteStepsAsync(SamsungPreset preset, Shared.Common.GlobalContext appContext, SamsungServiceConfig config) { foreach (var step in preset.Steps) { @@ -521,7 +524,7 @@ namespace ColorControl.Services.Samsung } } - public async Task ExecuteActionAsync(InvokableAction action, string[] parameters, Shared.Common.AppContext appContext, SamsungServiceConfig config) + public async Task ExecuteActionAsync(InvokableAction action, string[] parameters, Shared.Common.GlobalContext appContext, SamsungServiceConfig config) { if (action.Preset != null) { diff --git a/ColorControl/Services/Samsung/SamsungPanel.cs b/ColorControl/Services/Samsung/SamsungPanel.cs index 9c20836..b33ccb5 100644 --- a/ColorControl/Services/Samsung/SamsungPanel.cs +++ b/ColorControl/Services/Samsung/SamsungPanel.cs @@ -38,7 +38,7 @@ namespace ColorControl.Services.Samsung _amdService = amdService; _mainHandle = handle; - _config = Shared.Common.AppContext.CurrentContext.Config; + _config = Shared.Common.GlobalContext.CurrentContext.Config; InitializeComponent(); @@ -94,7 +94,7 @@ namespace ColorControl.Services.Samsung { FillSamsungDevices(); - var startUpParams = Shared.Common.AppContext.CurrentContext.StartUpParams; + var startUpParams = Shared.Common.GlobalContext.CurrentContext.StartUpParams; if (startUpParams.ExecuteSamsungPreset) { @@ -1114,7 +1114,7 @@ Do you want to continue?"; return; } - await device.ExecuteActionAsync(action, null, Shared.Common.AppContext.CurrentContext, _samsungService.Config); + await device.ExecuteActionAsync(action, null, Shared.Common.GlobalContext.CurrentContext, _samsungService.Config); } } } diff --git a/ColorControl/Services/Samsung/SamsungService.cs b/ColorControl/Services/Samsung/SamsungService.cs index 9d127e7..1f3dc55 100644 --- a/ColorControl/Services/Samsung/SamsungService.cs +++ b/ColorControl/Services/Samsung/SamsungService.cs @@ -33,16 +33,17 @@ namespace ColorControl.Services.Samsung private readonly SessionSwitchDispatcher _sessionSwitchDispatcher; private readonly RestartDetector _restartDetector; private readonly ProcessEventDispatcher _processEventDispatcher; + private readonly WinApiAdminService _winApiAdminService; private string _configFilename; private bool _poweredOffByScreenSaver; private int _poweredOffByScreenSaverProcessId; private object _lastTriggeredPreset; private List _samsungApps = new List(); - private Shared.Common.AppContext _appContext; + private Shared.Common.GlobalContext _appContext; public List Devices { get; private set; } - public SamsungService(AppContextProvider appContextProvider, ServiceManager serviceManager, PowerEventDispatcher powerEventDispatcher, SessionSwitchDispatcher sessionSwitchDispatcher, RestartDetector restartDetector, ProcessEventDispatcher processEventDispatcher) : base(appContextProvider) + public SamsungService(AppContextProvider appContextProvider, ServiceManager serviceManager, PowerEventDispatcher powerEventDispatcher, SessionSwitchDispatcher sessionSwitchDispatcher, RestartDetector restartDetector, ProcessEventDispatcher processEventDispatcher, WinApiAdminService winApiAdminService) : base(appContextProvider) { _appContext = appContextProvider.GetAppContext(); _allowPowerOn = _appContext.StartUpParams.RunningFromScheduledTask; @@ -51,6 +52,7 @@ namespace ColorControl.Services.Samsung _sessionSwitchDispatcher = sessionSwitchDispatcher; _restartDetector = restartDetector; _processEventDispatcher = processEventDispatcher; + _winApiAdminService = winApiAdminService; SamTvConnection.SyncContext = _appContext.SynchronizationContext; LoadConfig(); @@ -267,7 +269,7 @@ namespace ColorControl.Services.Samsung return await ApplyPreset(preset, _appContext); } - private async Task ApplyPreset(SamsungPreset preset, Shared.Common.AppContext appContext) + private async Task ApplyPreset(SamsungPreset preset, Shared.Common.GlobalContext appContext) { var result = true; @@ -368,7 +370,7 @@ namespace ColorControl.Services.Samsung var standByScript = Path.Combine(Program.DataDir, "StandByScript.bat"); if (File.Exists(standByScript)) { - Utils.StartProcess(standByScript, hidden: true, wait: true); + _winApiAdminService.StartProcess(standByScript, hidden: true, wait: true); } } @@ -428,7 +430,7 @@ namespace ColorControl.Services.Samsung if (File.Exists(resumeScript)) { - Utils.StartProcess(resumeScript, hidden: true); + _winApiAdminService.StartProcess(resumeScript, hidden: true); } } diff --git a/ColorControl/Svc/ColorControlBackgroundService.cs b/ColorControl/Svc/ColorControlBackgroundService.cs index b4f0fd9..4bb9998 100644 --- a/ColorControl/Svc/ColorControlBackgroundService.cs +++ b/ColorControl/Svc/ColorControlBackgroundService.cs @@ -1,8 +1,8 @@ using ColorControl.Services.EventDispatcher; using ColorControl.Services.LG; -using ColorControl.Services.NVIDIA; using ColorControl.Shared.Common; using ColorControl.Shared.Contracts; +using ColorControl.Shared.Services; using Microsoft.Extensions.Hosting; using Newtonsoft.Json; using NLog; @@ -21,11 +21,19 @@ namespace ColorControl.Svc { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); private readonly SessionSwitchDispatcher _sessionSwitchDispatcher; + private readonly RpcServerService _rpcServerService; + private readonly WinApiAdminService _winApiAdminService; + private readonly WolService _wolService; private static string LgConfigFile = "LgConfig.json"; - public ColorControlBackgroundService(SessionSwitchDispatcher sessionSwitchDispatcher) + public string PipeName { get; set; } = PipeUtils.ServicePipe; + + public ColorControlBackgroundService(SessionSwitchDispatcher sessionSwitchDispatcher, RpcServerService rpcServerService, WinApiAdminService winApiAdminService, WolService wolService) { _sessionSwitchDispatcher = sessionSwitchDispatcher; + _rpcServerService = rpcServerService; + _winApiAdminService = winApiAdminService; + _wolService = wolService; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) @@ -37,7 +45,10 @@ namespace ColorControl.Svc //var lgService = new LgService(Program.DataDir, true); //lgService.InstallEventHandlers(true); - await WakeDevicesAsync(); + if (PipeName == PipeUtils.ServicePipe) + { + await WakeDevicesAsync(); + } var securityIdentifier = new SecurityIdentifier(WellKnownSidType.AuthenticatedUserSid, null); @@ -50,7 +61,7 @@ namespace ColorControl.Svc { Logger.Debug("WAITING FOR MESSAGE..."); - var pipeServer = NamedPipeServerStreamAcl.Create("testpipe", PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous, 1024, 1024, ps); + var pipeServer = NamedPipeServerStreamAcl.Create(PipeName, PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous, 1024, 1024, ps); await pipeServer.WaitForConnectionAsync(stoppingToken); @@ -113,39 +124,31 @@ namespace ColorControl.Svc SvcMessageType.SetLgConfig => HandleSetLgConfigMessage(message), SvcMessageType.GetLog => HandleGetLogMessage(message), SvcMessageType.ClearLog => HandleClearLogMessage(message), - SvcMessageType.ExecuteRpc => await HandleExecuteRpcCommand(message), - SvcMessageType.ExecuteRpcGeneric => await HandleExecuteRpcGenericCommand(JsonConvert.DeserializeObject(json)), + SvcMessageType.ExecuteRpcGeneric => await _rpcServerService.ExecuteRpcAsync(JsonConvert.DeserializeObject(json)), + SvcMessageType.ExecuteRpcGenericTyped => await HandleRpcTypedAsync(JsonConvert.DeserializeObject(json), json), SvcMessageType.ExecuteUpdate => await HandleExecuteUpdateCommandAsync(JsonConvert.DeserializeObject(json)), SvcMessageType.RestartAfterUpdate => HandleRestartAfterUpdateMessage(), - SvcMessageType.ApplyNvidiaDriverSettings => HandleNvDriverSettingsMessage(JsonConvert.DeserializeObject(json)), - SvcMessageType.RestoreNvidiaDriverSetting => HandleNvRestoreDriverSettingsMessage(JsonConvert.DeserializeObject(json)), - SvcMessageType.ApplyNvidiaOverclocking => HandleNvOverclockingMessage(JsonConvert.DeserializeObject(json)), _ => SvcResultMessage.FromResult(false, "Unexpected message type") }; return result; } - private async Task HandleExecuteRpcCommand(SvcMessage message) + private async Task HandleRpcTypedAsync(SvcRpcMessageTyped message, string json) { - var args = message.Data.Split(' '); + var typeName = message.TypeName; - var startUpParams = StartUpParams.Parse(args); + Logger.Debug($"TypeName: {typeName}"); - return SvcResultMessage.FromResult(await CommandLineHandler.HandleStartupParams(startUpParams, null)); - } + var type = Type.GetType($"ColorControl.Shared.Contracts.{typeName}, Shared"); - private async Task HandleExecuteRpcGenericCommand(SvcRpcMessage message) - { - var service = NvService.CheckServiceInstance(); + Logger.Debug($"Type: {type?.Name}"); - var method = service.GetType().GetMethod(message.MethodName); + var typedMessage = JsonConvert.DeserializeObject(json, type) as SvcRpcMessageTyped; - var result = method.Invoke(service, message.Arguments); + Logger.Debug($"Msg: {typedMessage?.MethodName}"); - var data = JsonConvert.SerializeObject(result); - - return SvcResultMessage.FromResult(data); + return await _rpcServerService.ExecuteRpcTypedAsync(typedMessage); } private SvcResultMessage HandleSetLgConfigMessage(SvcMessage message) @@ -201,28 +204,7 @@ namespace ColorControl.Svc private SvcResultMessage HandleRestartAfterUpdateMessage() { - Utils.StartProcess("cmd.exe", $@"/C net stop ""{Utils.SERVICE_NAME}"" && net start ""{Utils.SERVICE_NAME}""", true); - - return SvcResultMessage.FromResult(true); - } - - private SvcResultMessage HandleNvDriverSettingsMessage(SvcNvDriverSettingsMessage message) - { - NvService.ApplyDriverSettings(message.ProfileName, message.DriverSettings); - - return SvcResultMessage.FromResult(true); - } - - private SvcResultMessage HandleNvRestoreDriverSettingsMessage(SvcNvDriverSettingsMessage message) - { - var result = NvService.RestoreDriverSettings(message.ProfileName, message.DriverSettings); - - return SvcResultMessage.FromResult(result); - } - - private SvcResultMessage HandleNvOverclockingMessage(SvcNvOverclockingMessage message) - { - NvService.CheckServiceInstance().ApplyOverclocking(message.OverclockingSettings); + _winApiAdminService.StartProcess("cmd.exe", $@"/C net stop ""{Utils.SERVICE_NAME}"" && net start ""{Utils.SERVICE_NAME}""", true); return SvcResultMessage.FromResult(true); } @@ -252,7 +234,7 @@ namespace ColorControl.Svc { for (var i = 0; i < config.PowerOnRetries; i++) { - WOL.WakeFunction(wakeDevice.MacAddress, wakeDevice.IpAddress); + _wolService.SendWol(wakeDevice.MacAddress, wakeDevice.IpAddress); await Task.Delay(1000); diff --git a/ColorControl/XForms/LogWindow.xaml.cs b/ColorControl/XForms/LogWindow.xaml.cs index 28013c6..b7ae6ff 100644 --- a/ColorControl/XForms/LogWindow.xaml.cs +++ b/ColorControl/XForms/LogWindow.xaml.cs @@ -1,8 +1,10 @@ using ColorControl.Shared.Common; using ColorControl.Shared.Contracts; using ColorControl.Shared.Forms; +using ColorControl.Shared.Services; using ColorControl.Shared.XForms; using DJ; +using Microsoft.Extensions.DependencyInjection; using NLog; using System; using System.Collections.Generic; @@ -19,16 +21,18 @@ namespace ColorControl.XForms private static LogWindow _window; private int _logLevelIndex; + private readonly WinApiAdminService _winApiAdminService; public int LogLevelIndex { get => _logLevelIndex; set => _logLevelIndex = value; } - public LogWindow() + public LogWindow(WinApiAdminService winApiAdminService) { InitializeComponent(); - LogLevelIndex = LogLevel.FromString(Shared.Common.AppContext.CurrentContext.Config.LogLevel).Ordinal; + LogLevelIndex = LogLevel.FromString(GlobalContext.CurrentContext.Config.LogLevel).Ordinal; DataContext = this; + _winApiAdminService = winApiAdminService; } private void OnRequestNavigate(object sender, RequestNavigateEventArgs e) @@ -47,7 +51,7 @@ namespace ColorControl.XForms new Application(); } - _window ??= new LogWindow(); + _window ??= Program.ServiceProvider.GetRequiredService(); if (show) { @@ -77,7 +81,7 @@ namespace ColorControl.XForms private void RawLog_Click(object sender, RoutedEventArgs e) { - var context = Shared.Common.AppContext.CurrentContext; + var context = Shared.Common.GlobalContext.CurrentContext; string logFile; if (tabControl.SelectedIndex == 0) @@ -86,7 +90,9 @@ namespace ColorControl.XForms } else { - if (!Utils.IsServiceRunning()) + var winApiService = Program.ServiceProvider.GetRequiredService(); + + if (!winApiService.IsServiceRunning()) { MessageForms.WarningOk("Service is not running"); return; @@ -109,7 +115,7 @@ namespace ColorControl.XForms return; } - Utils.StartProcess(logFile); + _winApiAdminService.StartProcess(logFile); } private void LoadOlder_Click(object sender, RoutedEventArgs e) @@ -128,7 +134,7 @@ namespace ColorControl.XForms private void LogLevel_Changed(object sender, System.Windows.Controls.SelectionChangedEventArgs e) { - var context = Shared.Common.AppContext.CurrentContext; + var context = Shared.Common.GlobalContext.CurrentContext; var logLevel = LogLevel.FromOrdinal(_logLevelIndex); @@ -144,7 +150,7 @@ namespace ColorControl.XForms return; } - var context = Shared.Common.AppContext.CurrentContext; + var context = Shared.Common.GlobalContext.CurrentContext; var lines = LoadLog(); @@ -160,7 +166,9 @@ namespace ColorControl.XForms return Utils.ReadLines(Program.LogFilename); } - if (Utils.IsServiceRunning()) + var winApiService = Program.ServiceProvider.GetRequiredService(); + + if (winApiService.IsServiceRunning()) { var message = new SvcMessage { MessageType = SvcMessageType.GetLog }; diff --git a/Nspector/Common/DrsSessionScope.cs b/Nspector/Common/DrsSessionScope.cs index c228bb1..f947b74 100644 --- a/Nspector/Common/DrsSessionScope.cs +++ b/Nspector/Common/DrsSessionScope.cs @@ -1,5 +1,4 @@ using nspector.Native.NVAPI2; -using System; using nvw = nspector.Native.NVAPI2.NvapiDrsWrapper; namespace nspector.Common @@ -38,6 +37,8 @@ namespace nspector.Common if (nvRes != NvAPI_Status.NVAPI_OK) throw new NvapiException("DRS_LoadSettings", nvRes); } + + var dRes = nvw.DRS_DecryptSession(GlobalSession); } } diff --git a/Nspector/Common/DrsSettingsMetaService.cs b/Nspector/Common/DrsSettingsMetaService.cs index 754b464..098f9d1 100644 --- a/Nspector/Common/DrsSettingsMetaService.cs +++ b/Nspector/Common/DrsSettingsMetaService.cs @@ -380,13 +380,15 @@ namespace nspector.Common public SettingMeta GetSettingMeta(uint settingId, SettingViewMode viewMode = SettingViewMode.Normal) { - if (settingMetaCache.ContainsKey(settingId)) + var settingMeta = settingMetaCache.GetValueOrDefault(settingId); + + if (settingMeta != null) { - return PostProcessMeta(settingId, settingMetaCache[settingId], viewMode); + return PostProcessMeta(settingId, settingMeta, viewMode); } else { - var settingMeta = CreateSettingMeta(settingId); + settingMeta = CreateSettingMeta(settingId); settingMetaCache.Add(settingId, settingMeta); return PostProcessMeta(settingId, settingMeta, viewMode); } diff --git a/Nspector/Common/DrsSettingsService.cs b/Nspector/Common/DrsSettingsService.cs index c28987e..0b276cd 100644 --- a/Nspector/Common/DrsSettingsService.cs +++ b/Nspector/Common/DrsSettingsService.cs @@ -21,6 +21,29 @@ namespace nspector.Common 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) { @@ -180,6 +203,30 @@ namespace nspector.Common 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); + + if (apps.Any(a => a.appName.Equals(appName, StringComparison.OrdinalIgnoreCase))) + { + var profile = GetProfileInfo(hSession, hProfile); + name = profile.profileName; + + break; + } + } + }); + + return name; + } + public void CreateProfile(string profileName, string applicationName = null) { DrsSession((hSession) => @@ -541,7 +588,7 @@ namespace nspector.Common foreach (var settingId in settingIds) { - var setting = ReadSetting(hSession, hProfile, settingId); + var setting = ReadSetting(hSession, hProfile, settingId, profileName); if (setting != null) result.Add(CreateSettingItem(setting.Value)); else @@ -551,6 +598,29 @@ namespace nspector.Common } } + var isBaseProfile = profileName.Contains("Base Profile", StringComparison.OrdinalIgnoreCase); + + 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; diff --git a/Nspector/Common/DrsSettingsServiceBase.cs b/Nspector/Common/DrsSettingsServiceBase.cs index 8315cb2..2d3f5e2 100644 --- a/Nspector/Common/DrsSettingsServiceBase.cs +++ b/Nspector/Common/DrsSettingsServiceBase.cs @@ -63,6 +63,13 @@ namespace nspector.Common } else { + if (profileName.Contains("Base Profile", StringComparison.OrdinalIgnoreCase)) + { + var res = nvw.DRS_GetBaseProfile(hSession, ref hProfile); + + return hProfile; + } + var nvRes = nvw.DRS_FindProfileByName(hSession, new StringBuilder(profileName), ref hProfile); if (nvRes == NvAPI_Status.NVAPI_PROFILE_NOT_FOUND) @@ -174,7 +181,7 @@ namespace nspector.Common } - protected NVDRS_SETTING? ReadSetting(IntPtr hSession, IntPtr hProfile, uint settingId) + protected NVDRS_SETTING? ReadSetting(IntPtr hSession, IntPtr hProfile, uint settingId, string? profileName = null) { var newSetting = new NVDRS_SETTING() { @@ -190,8 +197,13 @@ namespace nspector.Common if (decrypter != null) { - var profile = GetProfileInfo(hSession, hProfile); - decrypter.DecryptSettingIfNeeded(profile.profileName, ref newSetting); + if (profileName == null) + { + var profile = GetProfileInfo(hSession, hProfile); + profileName = profile.profileName; + } + + decrypter.DecryptSettingIfNeeded(profileName, ref newSetting); } return newSetting; @@ -254,10 +266,13 @@ namespace nspector.Common protected List GetProfileSettings(IntPtr hSession, IntPtr hProfile, NVDRS_PROFILE profile = default(NVDRS_PROFILE)) { uint settingCount = 40; - var settings = new NVDRS_SETTING[settingCount]; - settings[0].version = NvapiDrsWrapper.NVDRS_SETTING_VER; - var esRes = NvapiDrsWrapper.DRS_EnumSettings(hSession, hProfile, 0, ref settingCount, ref settings); + NVDRS_SETTING[] settings; + + //var settings = new NVDRS_SETTING[settingCount]; + //settings[0].version = NvapiDrsWrapper.NVDRS_SETTING_VER; + + var esRes = NvapiDrsWrapper.DRS_EnumSettings(hSession, hProfile, 0, ref settingCount, out settings); if (esRes == NvAPI_Status.NVAPI_END_ENUMERATION) return new List(); @@ -282,11 +297,14 @@ namespace nspector.Common protected List GetProfileApplications(IntPtr hSession, IntPtr hProfile) { - uint appCount = 512; - var apps = new NVDRS_APPLICATION_V3[512]; - apps[0].version = NvapiDrsWrapper.NVDRS_APPLICATION_VER_V3; + uint appCount = 8; - var esRes = NvapiDrsWrapper.DRS_EnumApplications(hSession, hProfile, 0, ref appCount, ref apps); + NVDRS_APPLICATION_V3[] apps; + + //var apps = new NVDRS_APPLICATION_V3[8]; + //apps[0].version = NvapiDrsWrapper.NVDRS_APPLICATION_VER_V3; + + var esRes = NvapiDrsWrapper.DRS_EnumApplications(hSession, hProfile, 0, ref appCount, out apps); if (esRes == NvAPI_Status.NVAPI_END_ENUMERATION) return new List(); diff --git a/Nspector/Native/NVAPI/NvapiDrsWrapper.cs b/Nspector/Native/NVAPI/NvapiDrsWrapper.cs index 2541d85..d9604b1 100644 --- a/Nspector/Native/NVAPI/NvapiDrsWrapper.cs +++ b/Nspector/Native/NVAPI/NvapiDrsWrapper.cs @@ -489,6 +489,10 @@ namespace nspector.Native.NVAPI2 public delegate NvAPI_Status DRS_DestroySessionDelegate(IntPtr hSession); public static readonly DRS_DestroySessionDelegate DRS_DestroySession; + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate NvAPI_Status DRS_DecryptSessionDelegate(IntPtr hSession); + public static readonly DRS_DecryptSessionDelegate DRS_DecryptSession; + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate NvAPI_Status DRS_LoadSettingsDelegate(IntPtr hSession); public static readonly DRS_LoadSettingsDelegate DRS_LoadSettings; @@ -568,25 +572,39 @@ namespace nspector.Native.NVAPI2 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate NvAPI_Status DRS_EnumApplicationsDelegate(IntPtr hSession, IntPtr hProfile, uint startIndex, ref uint appCount, IntPtr pApplication); private static readonly DRS_EnumApplicationsDelegate DRS_EnumApplicationsInternal; - public static NvAPI_Status DRS_EnumApplications(IntPtr hSession, IntPtr hProfile, uint startIndex, ref uint appCount, ref TDrsAppVersion[] apps) + + + [ThreadStatic] + private static IntPtr pSettingsApps; + [ThreadStatic] + private static NVDRS_APPLICATION_V3[] drsApps; + + public static NvAPI_Status DRS_EnumApplications(IntPtr hSession, IntPtr hProfile, uint startIndex, ref uint appCount, out NVDRS_APPLICATION_V3[] apps) { NvAPI_Status res; - IntPtr pSettings; - NativeArrayHelper.SetArrayData(apps, out pSettings); + //IntPtr pSettings; + + if (pSettingsApps == IntPtr.Zero) + { + drsApps = new NVDRS_APPLICATION_V3[8]; + drsApps[0].version = NvapiDrsWrapper.NVDRS_APPLICATION_VER_V3; + NativeArrayHelper.SetArrayData(drsApps, out pSettingsApps); + } + + //NativeArrayHelper.SetArrayData(apps, out pSettingsApps); try { - res = DRS_EnumApplicationsInternal(hSession, hProfile, startIndex, ref appCount, pSettings); - apps = NativeArrayHelper.GetArrayData(pSettings, (int)appCount); + res = DRS_EnumApplicationsInternal(hSession, hProfile, startIndex, ref appCount, pSettingsApps); + apps = NativeArrayHelper.GetArrayData(pSettingsApps, (int)appCount); } finally { - Marshal.FreeHGlobal(pSettings); + //Marshal.FreeHGlobal(pSettings); } return res; } - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate NvAPI_Status DRS_FindApplicationByNameDelegate(IntPtr hSession, [MarshalAs(UnmanagedType.LPWStr, SizeConst = (int)NvapiDrsWrapper.NVAPI_UNICODE_STRING_MAX)] StringBuilder appName, ref IntPtr phProfile, ref NVDRS_APPLICATION_V3 pApplication); public static readonly DRS_FindApplicationByNameDelegate DRS_FindApplicationByName; @@ -616,14 +634,18 @@ namespace nspector.Native.NVAPI2 private static readonly DRS_EnumSettingsDelegate DRS_EnumSettingsInternal; [ThreadStatic] private static IntPtr pSettings; + [ThreadStatic] + private static NVDRS_SETTING[] drsSettings; - public static NvAPI_Status DRS_EnumSettings(IntPtr hSession, IntPtr hProfile, uint startIndex, ref uint settingsCount, ref NVDRS_SETTING[] settings) + public static NvAPI_Status DRS_EnumSettings(IntPtr hSession, IntPtr hProfile, uint startIndex, ref uint settingsCount, out NVDRS_SETTING[] settings) { NvAPI_Status res; if (pSettings == IntPtr.Zero) { - NativeArrayHelper.SetArrayData(settings, out pSettings); + drsSettings = new NVDRS_SETTING[settingsCount]; + drsSettings[0].version = NvapiDrsWrapper.NVDRS_SETTING_VER; + NativeArrayHelper.SetArrayData(drsSettings, out pSettings); } try { @@ -769,6 +791,8 @@ namespace nspector.Native.NVAPI2 GetDelegate(0xFA5F6134, out DRS_RestoreProfileDefault); GetDelegate(0x7DD5B261, out DRS_RestoreProfileDefaultSetting, 0x53F0381E); GetDelegate(0xDA8466A0, out DRS_GetBaseProfile); + + GetDelegate(0x8FC247B7, out DRS_DecryptSession); #endregion } } diff --git a/Nspector/Native/NativeArrayHelper.cs b/Nspector/Native/NativeArrayHelper.cs index cc85bf3..8545a19 100644 --- a/Nspector/Native/NativeArrayHelper.cs +++ b/Nspector/Native/NativeArrayHelper.cs @@ -11,16 +11,16 @@ namespace nspector.Native public static T[] GetArrayData(IntPtr sourcePointer, int itemCount) { - var lstResult = new List(itemCount); + var lstResult = new T[itemCount]; if (sourcePointer != IntPtr.Zero && itemCount > 0) { var sizeOfItem = Marshal.SizeOf(typeof(T)); for (int i = 0; i < itemCount; i++) { - lstResult.Add(GetArrayItemData(sourcePointer + (sizeOfItem * i))); + lstResult[i] = GetArrayItemData(sourcePointer + (sizeOfItem * i)); } } - return lstResult.ToArray(); + return lstResult; } public static void SetArrayData(T[] items, out IntPtr targetPointer) @@ -54,13 +54,5 @@ namespace nspector.Native targetPointer = IntPtr.Zero; } } - - public static void SetArrayItemData(T item, out IntPtr targetPointer) - { - var sizeOfItem = Marshal.SizeOf(typeof(T)); - targetPointer = Marshal.AllocHGlobal(sizeOfItem); - Marshal.StructureToPtr(item, targetPointer, true); - } - } } diff --git a/Nspector/frmDrvSettings.Designer.cs b/Nspector/frmDrvSettings.Designer.cs index 14d74a7..ccddabb 100644 --- a/Nspector/frmDrvSettings.Designer.cs +++ b/Nspector/frmDrvSettings.Designer.cs @@ -28,616 +28,583 @@ /// private void InitializeComponent() { - this.components = new System.ComponentModel.Container(); + components = new System.ComponentModel.Container(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmDrvSettings)); - this.ilListView = new System.Windows.Forms.ImageList(this.components); - this.pbMain = new System.Windows.Forms.ProgressBar(); - this.tsMain = new System.Windows.Forms.ToolStrip(); - this.tslProfiles = new System.Windows.Forms.ToolStripLabel(); - this.cbProfiles = new System.Windows.Forms.ToolStripComboBox(); - this.tsbModifiedProfiles = new System.Windows.Forms.ToolStripSplitButton(); - this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); - this.tsbRefreshProfile = new System.Windows.Forms.ToolStripButton(); - this.tsbRestoreProfile = new System.Windows.Forms.ToolStripButton(); - this.tsbCreateProfile = new System.Windows.Forms.ToolStripButton(); - this.tsbDeleteProfile = new System.Windows.Forms.ToolStripButton(); - this.tsSep2 = new System.Windows.Forms.ToolStripSeparator(); - this.tsbAddApplication = new System.Windows.Forms.ToolStripButton(); - this.tssbRemoveApplication = new System.Windows.Forms.ToolStripSplitButton(); - this.tsSep3 = new System.Windows.Forms.ToolStripSeparator(); - this.tsbExportProfiles = new System.Windows.Forms.ToolStripSplitButton(); - this.exportCurrentProfileOnlyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.exportCurrentProfileIncludingPredefinedSettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.exportUserdefinedProfilesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.exportAllProfilesNVIDIATextFormatToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.tsbImportProfiles = new System.Windows.Forms.ToolStripSplitButton(); - this.importProfilesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.importAllProfilesNVIDIATextFormatToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.tsSep4 = new System.Windows.Forms.ToolStripSeparator(); - this.tscbShowCustomSettingNamesOnly = new System.Windows.Forms.ToolStripButton(); - this.tsSep5 = new System.Windows.Forms.ToolStripSeparator(); - this.tscbShowScannedUnknownSettings = new System.Windows.Forms.ToolStripButton(); - this.tsbBitValueEditor = new System.Windows.Forms.ToolStripButton(); - this.tsSep6 = new System.Windows.Forms.ToolStripSeparator(); - this.tsbApplyProfile = new System.Windows.Forms.ToolStripButton(); - this.btnResetValue = new System.Windows.Forms.Button(); - this.lblApplications = new System.Windows.Forms.Label(); - this.toolStripButton5 = new System.Windows.Forms.ToolStripButton(); - this.toolStripLabel2 = new System.Windows.Forms.ToolStripLabel(); - this.toolStripButton6 = new System.Windows.Forms.ToolStripButton(); - this.ilCombo = new System.Windows.Forms.ImageList(this.components); - this.cbValues = new System.Windows.Forms.ComboBox(); - this.lblWidth96 = new System.Windows.Forms.Label(); - this.lblWidth330 = new System.Windows.Forms.Label(); - this.lblWidth16 = new System.Windows.Forms.Label(); - this.lblWidth30 = new System.Windows.Forms.Label(); - this.lvSettings = new nspector.ListViewEx(); - this.chSettingID = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.chSettingValue = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.chSettingValueHex = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.tbSettingDescription = new System.Windows.Forms.TextBox(); - this.pnlListview = new System.Windows.Forms.Panel(); - this.tsMain.SuspendLayout(); - this.pnlListview.SuspendLayout(); - this.SuspendLayout(); + ilListView = new ImageList(components); + pbMain = new ProgressBar(); + tsMain = new ToolStrip(); + tslProfiles = new ToolStripLabel(); + cbProfiles = new ToolStripComboBox(); + tsbModifiedProfiles = new ToolStripSplitButton(); + toolStripSeparator1 = new ToolStripSeparator(); + tsbRefreshProfile = new ToolStripButton(); + tsbRestoreProfile = new ToolStripButton(); + tsbCreateProfile = new ToolStripButton(); + tsbDeleteProfile = new ToolStripButton(); + tsSep2 = new ToolStripSeparator(); + tsbAddApplication = new ToolStripButton(); + tssbRemoveApplication = new ToolStripSplitButton(); + tsSep3 = new ToolStripSeparator(); + tsbExportProfiles = new ToolStripSplitButton(); + exportCurrentProfileOnlyToolStripMenuItem = new ToolStripMenuItem(); + exportCurrentProfileIncludingPredefinedSettingsToolStripMenuItem = new ToolStripMenuItem(); + exportUserdefinedProfilesToolStripMenuItem = new ToolStripMenuItem(); + exportAllProfilesNVIDIATextFormatToolStripMenuItem = new ToolStripMenuItem(); + tsbImportProfiles = new ToolStripSplitButton(); + importProfilesToolStripMenuItem = new ToolStripMenuItem(); + importAllProfilesNVIDIATextFormatToolStripMenuItem = new ToolStripMenuItem(); + tsSep4 = new ToolStripSeparator(); + tscbShowCustomSettingNamesOnly = new ToolStripButton(); + tsSep5 = new ToolStripSeparator(); + tscbShowScannedUnknownSettings = new ToolStripButton(); + tsbBitValueEditor = new ToolStripButton(); + tsSep6 = new ToolStripSeparator(); + tsbApplyProfile = new ToolStripButton(); + btnResetValue = new Button(); + lblApplications = new Label(); + toolStripButton5 = new ToolStripButton(); + toolStripLabel2 = new ToolStripLabel(); + toolStripButton6 = new ToolStripButton(); + ilCombo = new ImageList(components); + cbValues = new ComboBox(); + lblWidth96 = new Label(); + lblWidth330 = new Label(); + lblWidth16 = new Label(); + lblWidth30 = new Label(); + lvSettings = new ListViewEx(); + chSettingID = new ColumnHeader(); + chSettingValue = new ColumnHeader(); + chSettingValueHex = new ColumnHeader(); + tbSettingDescription = new TextBox(); + pnlListview = new Panel(); + tsMain.SuspendLayout(); + pnlListview.SuspendLayout(); + SuspendLayout(); // // ilListView // - this.ilListView.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("ilListView.ImageStream"))); - this.ilListView.TransparentColor = System.Drawing.Color.Transparent; - this.ilListView.Images.SetKeyName(0, "0_gear2.png"); - this.ilListView.Images.SetKeyName(1, "1_gear2_2.png"); - this.ilListView.Images.SetKeyName(2, "4_gear_nv2.png"); - this.ilListView.Images.SetKeyName(3, "6_gear_inherit.png"); + ilListView.ColorDepth = ColorDepth.Depth24Bit; + ilListView.ImageStream = (ImageListStreamer)resources.GetObject("ilListView.ImageStream"); + ilListView.TransparentColor = Color.Transparent; + ilListView.Images.SetKeyName(0, "0_gear2.png"); + ilListView.Images.SetKeyName(1, "1_gear2_2.png"); + ilListView.Images.SetKeyName(2, "4_gear_nv2.png"); + ilListView.Images.SetKeyName(3, "6_gear_inherit.png"); // // pbMain // - this.pbMain.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.pbMain.Location = new System.Drawing.Point(12, 475); - this.pbMain.Margin = new System.Windows.Forms.Padding(4); - this.pbMain.Name = "pbMain"; - this.pbMain.Size = new System.Drawing.Size(840, 9); - this.pbMain.TabIndex = 19; + pbMain.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; + pbMain.Location = new Point(14, 548); + pbMain.Margin = new Padding(5, 5, 5, 5); + pbMain.Name = "pbMain"; + pbMain.Size = new Size(980, 10); + pbMain.TabIndex = 19; // // tsMain // - this.tsMain.AllowMerge = false; - this.tsMain.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.tsMain.AutoSize = false; - this.tsMain.BackgroundImage = global::nspector.Properties.Resources.transparent16; - this.tsMain.CanOverflow = false; - this.tsMain.Dock = System.Windows.Forms.DockStyle.None; - this.tsMain.GripMargin = new System.Windows.Forms.Padding(0); - this.tsMain.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden; - this.tsMain.ImageScalingSize = new System.Drawing.Size(20, 20); - this.tsMain.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.tslProfiles, - this.cbProfiles, - this.tsbModifiedProfiles, - this.toolStripSeparator1, - this.tsbRefreshProfile, - this.tsbRestoreProfile, - this.tsbCreateProfile, - this.tsbDeleteProfile, - this.tsSep2, - this.tsbAddApplication, - this.tssbRemoveApplication, - this.tsSep3, - this.tsbExportProfiles, - this.tsbImportProfiles, - this.tsSep4, - this.tscbShowCustomSettingNamesOnly, - this.tsSep5, - this.tscbShowScannedUnknownSettings, - this.tsbBitValueEditor, - this.tsSep6, - this.tsbApplyProfile}); - this.tsMain.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.HorizontalStackWithOverflow; - this.tsMain.Location = new System.Drawing.Point(12, 4); - this.tsMain.Name = "tsMain"; - this.tsMain.RenderMode = System.Windows.Forms.ToolStripRenderMode.Professional; - this.tsMain.Size = new System.Drawing.Size(840, 25); - this.tsMain.TabIndex = 24; - this.tsMain.Text = "toolStrip1"; + tsMain.AllowMerge = false; + tsMain.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; + tsMain.AutoSize = false; + tsMain.BackgroundImage = (Image)resources.GetObject("tsMain.BackgroundImage"); + tsMain.CanOverflow = false; + tsMain.Dock = DockStyle.None; + tsMain.GripMargin = new Padding(0); + tsMain.GripStyle = ToolStripGripStyle.Hidden; + tsMain.ImageScalingSize = new Size(20, 20); + tsMain.Items.AddRange(new ToolStripItem[] { tslProfiles, cbProfiles, tsbModifiedProfiles, toolStripSeparator1, tsbRefreshProfile, tsbRestoreProfile, tsbCreateProfile, tsbDeleteProfile, tsSep2, tsbAddApplication, tssbRemoveApplication, tsSep3, tsbExportProfiles, tsbImportProfiles, tsSep4, tscbShowCustomSettingNamesOnly, tsSep5, tscbShowScannedUnknownSettings, tsbBitValueEditor, tsSep6, tsbApplyProfile }); + tsMain.LayoutStyle = ToolStripLayoutStyle.HorizontalStackWithOverflow; + tsMain.Location = new Point(14, 5); + tsMain.Name = "tsMain"; + tsMain.RenderMode = ToolStripRenderMode.Professional; + tsMain.Size = new Size(980, 29); + tsMain.TabIndex = 24; + tsMain.Text = "toolStrip1"; // // tslProfiles // - this.tslProfiles.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None; - this.tslProfiles.Margin = new System.Windows.Forms.Padding(0, 5, 10, 2); - this.tslProfiles.Name = "tslProfiles"; - this.tslProfiles.Size = new System.Drawing.Size(49, 18); - this.tslProfiles.Text = "Profiles:"; + tslProfiles.ImageScaling = ToolStripItemImageScaling.None; + tslProfiles.Margin = new Padding(0, 5, 10, 2); + tslProfiles.Name = "tslProfiles"; + tslProfiles.Size = new Size(49, 22); + tslProfiles.Text = "Profiles:"; // // cbProfiles // - this.cbProfiles.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.Suggest; - this.cbProfiles.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; - this.cbProfiles.AutoSize = false; - this.cbProfiles.DropDownWidth = 290; - this.cbProfiles.Margin = new System.Windows.Forms.Padding(1); - this.cbProfiles.MaxDropDownItems = 50; - this.cbProfiles.Name = "cbProfiles"; - this.cbProfiles.Size = new System.Drawing.Size(290, 23); - this.cbProfiles.SelectedIndexChanged += new System.EventHandler(this.cbProfiles_SelectedIndexChanged); - this.cbProfiles.TextChanged += new System.EventHandler(this.cbProfiles_TextChanged); + cbProfiles.AutoCompleteMode = AutoCompleteMode.Suggest; + cbProfiles.AutoCompleteSource = AutoCompleteSource.ListItems; + cbProfiles.AutoSize = false; + cbProfiles.DropDownWidth = 290; + cbProfiles.Margin = new Padding(1); + cbProfiles.MaxDropDownItems = 50; + cbProfiles.Name = "cbProfiles"; + cbProfiles.Size = new Size(338, 23); + cbProfiles.SelectedIndexChanged += cbProfiles_SelectedIndexChanged; + cbProfiles.TextChanged += cbProfiles_TextChanged; // // tsbModifiedProfiles // - this.tsbModifiedProfiles.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.tsbModifiedProfiles.Enabled = false; - this.tsbModifiedProfiles.Image = global::nspector.Properties.Resources.home_sm; - this.tsbModifiedProfiles.ImageTransparentColor = System.Drawing.Color.Magenta; - this.tsbModifiedProfiles.Name = "tsbModifiedProfiles"; - this.tsbModifiedProfiles.Size = new System.Drawing.Size(36, 22); - this.tsbModifiedProfiles.TextImageRelation = System.Windows.Forms.TextImageRelation.Overlay; - this.tsbModifiedProfiles.ToolTipText = "Back to global profile (Home) / User modified profiles"; - this.tsbModifiedProfiles.ButtonClick += new System.EventHandler(this.tsbModifiedProfiles_ButtonClick); - this.tsbModifiedProfiles.DropDownItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler(this.tsbModifiedProfiles_DropDownItemClicked); + tsbModifiedProfiles.DisplayStyle = ToolStripItemDisplayStyle.Image; + tsbModifiedProfiles.Enabled = false; + tsbModifiedProfiles.Image = (Image)resources.GetObject("tsbModifiedProfiles.Image"); + tsbModifiedProfiles.ImageTransparentColor = Color.Magenta; + tsbModifiedProfiles.Name = "tsbModifiedProfiles"; + tsbModifiedProfiles.Size = new Size(36, 26); + tsbModifiedProfiles.TextImageRelation = TextImageRelation.Overlay; + tsbModifiedProfiles.ToolTipText = "Back to global profile (Home) / User modified profiles"; + tsbModifiedProfiles.ButtonClick += tsbModifiedProfiles_ButtonClick; + tsbModifiedProfiles.DropDownItemClicked += tsbModifiedProfiles_DropDownItemClicked; // // toolStripSeparator1 // - this.toolStripSeparator1.Name = "toolStripSeparator1"; - this.toolStripSeparator1.Size = new System.Drawing.Size(6, 25); + toolStripSeparator1.Name = "toolStripSeparator1"; + toolStripSeparator1.Size = new Size(6, 29); // // tsbRefreshProfile // - this.tsbRefreshProfile.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.tsbRefreshProfile.Image = ((System.Drawing.Image)(resources.GetObject("tsbRefreshProfile.Image"))); - this.tsbRefreshProfile.ImageTransparentColor = System.Drawing.Color.Magenta; - this.tsbRefreshProfile.Name = "tsbRefreshProfile"; - this.tsbRefreshProfile.Size = new System.Drawing.Size(24, 22); - this.tsbRefreshProfile.Text = "Refresh current profile."; - this.tsbRefreshProfile.Click += new System.EventHandler(this.tsbRefreshProfile_Click); + tsbRefreshProfile.DisplayStyle = ToolStripItemDisplayStyle.Image; + tsbRefreshProfile.Image = (Image)resources.GetObject("tsbRefreshProfile.Image"); + tsbRefreshProfile.ImageTransparentColor = Color.Magenta; + tsbRefreshProfile.Name = "tsbRefreshProfile"; + tsbRefreshProfile.Size = new Size(24, 26); + tsbRefreshProfile.Text = "Refresh current profile."; + tsbRefreshProfile.Click += tsbRefreshProfile_Click; // // tsbRestoreProfile // - this.tsbRestoreProfile.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.tsbRestoreProfile.Image = ((System.Drawing.Image)(resources.GetObject("tsbRestoreProfile.Image"))); - this.tsbRestoreProfile.ImageTransparentColor = System.Drawing.Color.Magenta; - this.tsbRestoreProfile.Name = "tsbRestoreProfile"; - this.tsbRestoreProfile.Size = new System.Drawing.Size(24, 22); - this.tsbRestoreProfile.Text = "Restore current profile to NVIDIA defaults."; - this.tsbRestoreProfile.Click += new System.EventHandler(this.tsbRestoreProfile_Click); + tsbRestoreProfile.DisplayStyle = ToolStripItemDisplayStyle.Image; + tsbRestoreProfile.Image = (Image)resources.GetObject("tsbRestoreProfile.Image"); + tsbRestoreProfile.ImageTransparentColor = Color.Magenta; + tsbRestoreProfile.Name = "tsbRestoreProfile"; + tsbRestoreProfile.Size = new Size(24, 26); + tsbRestoreProfile.Text = "Restore current profile to NVIDIA defaults."; + tsbRestoreProfile.Click += tsbRestoreProfile_Click; // // tsbCreateProfile // - this.tsbCreateProfile.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.tsbCreateProfile.Image = ((System.Drawing.Image)(resources.GetObject("tsbCreateProfile.Image"))); - this.tsbCreateProfile.ImageTransparentColor = System.Drawing.Color.Magenta; - this.tsbCreateProfile.Name = "tsbCreateProfile"; - this.tsbCreateProfile.Size = new System.Drawing.Size(24, 22); - this.tsbCreateProfile.Text = "Create new profile"; - this.tsbCreateProfile.Click += new System.EventHandler(this.tsbCreateProfile_Click); + tsbCreateProfile.DisplayStyle = ToolStripItemDisplayStyle.Image; + tsbCreateProfile.Image = (Image)resources.GetObject("tsbCreateProfile.Image"); + tsbCreateProfile.ImageTransparentColor = Color.Magenta; + tsbCreateProfile.Name = "tsbCreateProfile"; + tsbCreateProfile.Size = new Size(24, 26); + tsbCreateProfile.Text = "Create new profile"; + tsbCreateProfile.Click += tsbCreateProfile_Click; // // tsbDeleteProfile // - this.tsbDeleteProfile.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.tsbDeleteProfile.Image = global::nspector.Properties.Resources.ieframe_1_18212; - this.tsbDeleteProfile.ImageTransparentColor = System.Drawing.Color.Magenta; - this.tsbDeleteProfile.Name = "tsbDeleteProfile"; - this.tsbDeleteProfile.Size = new System.Drawing.Size(24, 22); - this.tsbDeleteProfile.Text = "Delete current Profile"; - this.tsbDeleteProfile.Click += new System.EventHandler(this.tsbDeleteProfile_Click); + tsbDeleteProfile.DisplayStyle = ToolStripItemDisplayStyle.Image; + tsbDeleteProfile.Image = (Image)resources.GetObject("tsbDeleteProfile.Image"); + tsbDeleteProfile.ImageTransparentColor = Color.Magenta; + tsbDeleteProfile.Name = "tsbDeleteProfile"; + tsbDeleteProfile.Size = new Size(24, 26); + tsbDeleteProfile.Text = "Delete current Profile"; + tsbDeleteProfile.Click += tsbDeleteProfile_Click; // // tsSep2 // - this.tsSep2.Name = "tsSep2"; - this.tsSep2.Size = new System.Drawing.Size(6, 25); + tsSep2.Name = "tsSep2"; + tsSep2.Size = new Size(6, 29); // // tsbAddApplication // - this.tsbAddApplication.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.tsbAddApplication.Image = global::nspector.Properties.Resources.window_application_add; - this.tsbAddApplication.ImageTransparentColor = System.Drawing.Color.Magenta; - this.tsbAddApplication.Name = "tsbAddApplication"; - this.tsbAddApplication.Size = new System.Drawing.Size(24, 22); - this.tsbAddApplication.Text = "Add application to current profile."; - this.tsbAddApplication.Click += new System.EventHandler(this.tsbAddApplication_Click); + tsbAddApplication.DisplayStyle = ToolStripItemDisplayStyle.Image; + tsbAddApplication.Image = (Image)resources.GetObject("tsbAddApplication.Image"); + tsbAddApplication.ImageTransparentColor = Color.Magenta; + tsbAddApplication.Name = "tsbAddApplication"; + tsbAddApplication.Size = new Size(24, 26); + tsbAddApplication.Text = "Add application to current profile."; + tsbAddApplication.Click += tsbAddApplication_Click; // // tssbRemoveApplication // - this.tssbRemoveApplication.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.tssbRemoveApplication.Image = global::nspector.Properties.Resources.window_application_delete; - this.tssbRemoveApplication.ImageTransparentColor = System.Drawing.Color.Magenta; - this.tssbRemoveApplication.Name = "tssbRemoveApplication"; - this.tssbRemoveApplication.Size = new System.Drawing.Size(36, 22); - this.tssbRemoveApplication.Text = "Remove application from current profile"; - this.tssbRemoveApplication.DropDownItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler(this.tssbRemoveApplication_DropDownItemClicked); - this.tssbRemoveApplication.Click += new System.EventHandler(this.tssbRemoveApplication_Click); + tssbRemoveApplication.DisplayStyle = ToolStripItemDisplayStyle.Image; + tssbRemoveApplication.Image = (Image)resources.GetObject("tssbRemoveApplication.Image"); + tssbRemoveApplication.ImageTransparentColor = Color.Magenta; + tssbRemoveApplication.Name = "tssbRemoveApplication"; + tssbRemoveApplication.Size = new Size(36, 26); + tssbRemoveApplication.Text = "Remove application from current profile"; + tssbRemoveApplication.DropDownItemClicked += tssbRemoveApplication_DropDownItemClicked; + tssbRemoveApplication.Click += tssbRemoveApplication_Click; // // tsSep3 // - this.tsSep3.Name = "tsSep3"; - this.tsSep3.Size = new System.Drawing.Size(6, 25); + tsSep3.Name = "tsSep3"; + tsSep3.Size = new Size(6, 29); // // tsbExportProfiles // - this.tsbExportProfiles.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.tsbExportProfiles.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.exportCurrentProfileOnlyToolStripMenuItem, - this.exportCurrentProfileIncludingPredefinedSettingsToolStripMenuItem, - this.exportUserdefinedProfilesToolStripMenuItem, - this.exportAllProfilesNVIDIATextFormatToolStripMenuItem}); - this.tsbExportProfiles.Image = global::nspector.Properties.Resources.export1; - this.tsbExportProfiles.ImageTransparentColor = System.Drawing.Color.Magenta; - this.tsbExportProfiles.Name = "tsbExportProfiles"; - this.tsbExportProfiles.Size = new System.Drawing.Size(36, 22); - this.tsbExportProfiles.Text = "Export user defined profiles"; - this.tsbExportProfiles.Click += new System.EventHandler(this.tsbExportProfiles_Click); + tsbExportProfiles.DisplayStyle = ToolStripItemDisplayStyle.Image; + tsbExportProfiles.DropDownItems.AddRange(new ToolStripItem[] { exportCurrentProfileOnlyToolStripMenuItem, exportCurrentProfileIncludingPredefinedSettingsToolStripMenuItem, exportUserdefinedProfilesToolStripMenuItem, exportAllProfilesNVIDIATextFormatToolStripMenuItem }); + tsbExportProfiles.Image = (Image)resources.GetObject("tsbExportProfiles.Image"); + tsbExportProfiles.ImageTransparentColor = Color.Magenta; + tsbExportProfiles.Name = "tsbExportProfiles"; + tsbExportProfiles.Size = new Size(36, 26); + tsbExportProfiles.Text = "Export user defined profiles"; + tsbExportProfiles.Click += tsbExportProfiles_Click; // // exportCurrentProfileOnlyToolStripMenuItem // - this.exportCurrentProfileOnlyToolStripMenuItem.Name = "exportCurrentProfileOnlyToolStripMenuItem"; - this.exportCurrentProfileOnlyToolStripMenuItem.Size = new System.Drawing.Size(343, 22); - this.exportCurrentProfileOnlyToolStripMenuItem.Text = "Export current profile only"; - this.exportCurrentProfileOnlyToolStripMenuItem.Click += new System.EventHandler(this.exportCurrentProfileOnlyToolStripMenuItem_Click); + exportCurrentProfileOnlyToolStripMenuItem.Name = "exportCurrentProfileOnlyToolStripMenuItem"; + exportCurrentProfileOnlyToolStripMenuItem.Size = new Size(343, 22); + exportCurrentProfileOnlyToolStripMenuItem.Text = "Export current profile only"; + exportCurrentProfileOnlyToolStripMenuItem.Click += exportCurrentProfileOnlyToolStripMenuItem_Click; // // exportCurrentProfileIncludingPredefinedSettingsToolStripMenuItem // - this.exportCurrentProfileIncludingPredefinedSettingsToolStripMenuItem.Name = "exportCurrentProfileIncludingPredefinedSettingsToolStripMenuItem"; - this.exportCurrentProfileIncludingPredefinedSettingsToolStripMenuItem.Size = new System.Drawing.Size(343, 22); - this.exportCurrentProfileIncludingPredefinedSettingsToolStripMenuItem.Text = "Export current profile including predefined settings"; - this.exportCurrentProfileIncludingPredefinedSettingsToolStripMenuItem.Click += new System.EventHandler(this.exportCurrentProfileIncludingPredefinedSettingsToolStripMenuItem_Click); + exportCurrentProfileIncludingPredefinedSettingsToolStripMenuItem.Name = "exportCurrentProfileIncludingPredefinedSettingsToolStripMenuItem"; + exportCurrentProfileIncludingPredefinedSettingsToolStripMenuItem.Size = new Size(343, 22); + exportCurrentProfileIncludingPredefinedSettingsToolStripMenuItem.Text = "Export current profile including predefined settings"; + exportCurrentProfileIncludingPredefinedSettingsToolStripMenuItem.Click += exportCurrentProfileIncludingPredefinedSettingsToolStripMenuItem_Click; // // exportUserdefinedProfilesToolStripMenuItem // - this.exportUserdefinedProfilesToolStripMenuItem.Name = "exportUserdefinedProfilesToolStripMenuItem"; - this.exportUserdefinedProfilesToolStripMenuItem.Size = new System.Drawing.Size(343, 22); - this.exportUserdefinedProfilesToolStripMenuItem.Text = "Export all customized profiles"; - this.exportUserdefinedProfilesToolStripMenuItem.Click += new System.EventHandler(this.exportUserdefinedProfilesToolStripMenuItem_Click); + exportUserdefinedProfilesToolStripMenuItem.Name = "exportUserdefinedProfilesToolStripMenuItem"; + exportUserdefinedProfilesToolStripMenuItem.Size = new Size(343, 22); + exportUserdefinedProfilesToolStripMenuItem.Text = "Export all customized profiles"; + exportUserdefinedProfilesToolStripMenuItem.Click += exportUserdefinedProfilesToolStripMenuItem_Click; // // exportAllProfilesNVIDIATextFormatToolStripMenuItem // - this.exportAllProfilesNVIDIATextFormatToolStripMenuItem.Name = "exportAllProfilesNVIDIATextFormatToolStripMenuItem"; - this.exportAllProfilesNVIDIATextFormatToolStripMenuItem.Size = new System.Drawing.Size(343, 22); - this.exportAllProfilesNVIDIATextFormatToolStripMenuItem.Text = "Export all driver profiles (NVIDIA Text Format)"; - this.exportAllProfilesNVIDIATextFormatToolStripMenuItem.Click += new System.EventHandler(this.exportAllProfilesNVIDIATextFormatToolStripMenuItem_Click); + exportAllProfilesNVIDIATextFormatToolStripMenuItem.Name = "exportAllProfilesNVIDIATextFormatToolStripMenuItem"; + exportAllProfilesNVIDIATextFormatToolStripMenuItem.Size = new Size(343, 22); + exportAllProfilesNVIDIATextFormatToolStripMenuItem.Text = "Export all driver profiles (NVIDIA Text Format)"; + exportAllProfilesNVIDIATextFormatToolStripMenuItem.Click += exportAllProfilesNVIDIATextFormatToolStripMenuItem_Click; // // tsbImportProfiles // - this.tsbImportProfiles.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.tsbImportProfiles.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.importProfilesToolStripMenuItem, - this.importAllProfilesNVIDIATextFormatToolStripMenuItem}); - this.tsbImportProfiles.Image = global::nspector.Properties.Resources.import1; - this.tsbImportProfiles.ImageTransparentColor = System.Drawing.Color.Magenta; - this.tsbImportProfiles.Name = "tsbImportProfiles"; - this.tsbImportProfiles.Size = new System.Drawing.Size(36, 22); - this.tsbImportProfiles.Text = "Import user defined profiles"; - this.tsbImportProfiles.Click += new System.EventHandler(this.tsbImportProfiles_Click); + tsbImportProfiles.DisplayStyle = ToolStripItemDisplayStyle.Image; + tsbImportProfiles.DropDownItems.AddRange(new ToolStripItem[] { importProfilesToolStripMenuItem, importAllProfilesNVIDIATextFormatToolStripMenuItem }); + tsbImportProfiles.Image = (Image)resources.GetObject("tsbImportProfiles.Image"); + tsbImportProfiles.ImageTransparentColor = Color.Magenta; + tsbImportProfiles.Name = "tsbImportProfiles"; + tsbImportProfiles.Size = new Size(36, 26); + tsbImportProfiles.Text = "Import user defined profiles"; + tsbImportProfiles.Click += tsbImportProfiles_Click; // // importProfilesToolStripMenuItem // - this.importProfilesToolStripMenuItem.Name = "importProfilesToolStripMenuItem"; - this.importProfilesToolStripMenuItem.Size = new System.Drawing.Size(363, 22); - this.importProfilesToolStripMenuItem.Text = "Import profile(s)"; - this.importProfilesToolStripMenuItem.Click += new System.EventHandler(this.importProfilesToolStripMenuItem_Click); + importProfilesToolStripMenuItem.Name = "importProfilesToolStripMenuItem"; + importProfilesToolStripMenuItem.Size = new Size(363, 22); + importProfilesToolStripMenuItem.Text = "Import profile(s)"; + importProfilesToolStripMenuItem.Click += importProfilesToolStripMenuItem_Click; // // importAllProfilesNVIDIATextFormatToolStripMenuItem // - this.importAllProfilesNVIDIATextFormatToolStripMenuItem.Name = "importAllProfilesNVIDIATextFormatToolStripMenuItem"; - this.importAllProfilesNVIDIATextFormatToolStripMenuItem.Size = new System.Drawing.Size(363, 22); - this.importAllProfilesNVIDIATextFormatToolStripMenuItem.Text = "Import (replace) all driver profiles (NVIDIA Text Format)"; - this.importAllProfilesNVIDIATextFormatToolStripMenuItem.Click += new System.EventHandler(this.importAllProfilesNVIDIATextFormatToolStripMenuItem_Click); + importAllProfilesNVIDIATextFormatToolStripMenuItem.Name = "importAllProfilesNVIDIATextFormatToolStripMenuItem"; + importAllProfilesNVIDIATextFormatToolStripMenuItem.Size = new Size(363, 22); + importAllProfilesNVIDIATextFormatToolStripMenuItem.Text = "Import (replace) all driver profiles (NVIDIA Text Format)"; + importAllProfilesNVIDIATextFormatToolStripMenuItem.Click += importAllProfilesNVIDIATextFormatToolStripMenuItem_Click; // // tsSep4 // - this.tsSep4.Name = "tsSep4"; - this.tsSep4.Size = new System.Drawing.Size(6, 25); + tsSep4.Name = "tsSep4"; + tsSep4.Size = new Size(6, 29); // // tscbShowCustomSettingNamesOnly // - this.tscbShowCustomSettingNamesOnly.CheckOnClick = true; - this.tscbShowCustomSettingNamesOnly.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.tscbShowCustomSettingNamesOnly.Image = global::nspector.Properties.Resources.filter_user; - this.tscbShowCustomSettingNamesOnly.ImageTransparentColor = System.Drawing.Color.Magenta; - this.tscbShowCustomSettingNamesOnly.Name = "tscbShowCustomSettingNamesOnly"; - this.tscbShowCustomSettingNamesOnly.Size = new System.Drawing.Size(24, 22); - this.tscbShowCustomSettingNamesOnly.Text = "Show the settings and values from CustomSettingNames file only."; - this.tscbShowCustomSettingNamesOnly.CheckedChanged += new System.EventHandler(this.cbCustomSettingsOnly_CheckedChanged); + tscbShowCustomSettingNamesOnly.CheckOnClick = true; + tscbShowCustomSettingNamesOnly.DisplayStyle = ToolStripItemDisplayStyle.Image; + tscbShowCustomSettingNamesOnly.Image = (Image)resources.GetObject("tscbShowCustomSettingNamesOnly.Image"); + tscbShowCustomSettingNamesOnly.ImageTransparentColor = Color.Magenta; + tscbShowCustomSettingNamesOnly.Name = "tscbShowCustomSettingNamesOnly"; + tscbShowCustomSettingNamesOnly.Size = new Size(24, 26); + tscbShowCustomSettingNamesOnly.Text = "Show the settings and values from CustomSettingNames file only."; + tscbShowCustomSettingNamesOnly.CheckedChanged += cbCustomSettingsOnly_CheckedChanged; // // tsSep5 // - this.tsSep5.Name = "tsSep5"; - this.tsSep5.Size = new System.Drawing.Size(6, 25); + tsSep5.Name = "tsSep5"; + tsSep5.Size = new Size(6, 29); // // tscbShowScannedUnknownSettings // - this.tscbShowScannedUnknownSettings.CheckOnClick = true; - this.tscbShowScannedUnknownSettings.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.tscbShowScannedUnknownSettings.Enabled = false; - this.tscbShowScannedUnknownSettings.Image = global::nspector.Properties.Resources.find_set2; - this.tscbShowScannedUnknownSettings.ImageTransparentColor = System.Drawing.Color.Magenta; - this.tscbShowScannedUnknownSettings.Name = "tscbShowScannedUnknownSettings"; - this.tscbShowScannedUnknownSettings.Size = new System.Drawing.Size(24, 22); - this.tscbShowScannedUnknownSettings.Text = "Show unknown settings from NVIDIA predefined profiles"; - this.tscbShowScannedUnknownSettings.Click += new System.EventHandler(this.tscbShowScannedUnknownSettings_Click); + tscbShowScannedUnknownSettings.CheckOnClick = true; + tscbShowScannedUnknownSettings.DisplayStyle = ToolStripItemDisplayStyle.Image; + tscbShowScannedUnknownSettings.Enabled = false; + tscbShowScannedUnknownSettings.Image = (Image)resources.GetObject("tscbShowScannedUnknownSettings.Image"); + tscbShowScannedUnknownSettings.ImageTransparentColor = Color.Magenta; + tscbShowScannedUnknownSettings.Name = "tscbShowScannedUnknownSettings"; + tscbShowScannedUnknownSettings.Size = new Size(24, 26); + tscbShowScannedUnknownSettings.Text = "Show unknown settings from NVIDIA predefined profiles"; + tscbShowScannedUnknownSettings.Click += tscbShowScannedUnknownSettings_Click; // // tsbBitValueEditor // - this.tsbBitValueEditor.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.tsbBitValueEditor.Image = global::nspector.Properties.Resources.text_binary; - this.tsbBitValueEditor.ImageTransparentColor = System.Drawing.Color.Magenta; - this.tsbBitValueEditor.Name = "tsbBitValueEditor"; - this.tsbBitValueEditor.Size = new System.Drawing.Size(24, 22); - this.tsbBitValueEditor.Text = "Show bit value editor."; - this.tsbBitValueEditor.Click += new System.EventHandler(this.tsbBitValueEditor_Click); + tsbBitValueEditor.DisplayStyle = ToolStripItemDisplayStyle.Image; + tsbBitValueEditor.Image = (Image)resources.GetObject("tsbBitValueEditor.Image"); + tsbBitValueEditor.ImageTransparentColor = Color.Magenta; + tsbBitValueEditor.Name = "tsbBitValueEditor"; + tsbBitValueEditor.Size = new Size(24, 26); + tsbBitValueEditor.Text = "Show bit value editor."; + tsbBitValueEditor.Click += tsbBitValueEditor_Click; // // tsSep6 // - this.tsSep6.Name = "tsSep6"; - this.tsSep6.Size = new System.Drawing.Size(6, 25); + tsSep6.Name = "tsSep6"; + tsSep6.Size = new Size(6, 29); // // tsbApplyProfile // - this.tsbApplyProfile.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right; - this.tsbApplyProfile.Image = global::nspector.Properties.Resources.apply; - this.tsbApplyProfile.ImageTransparentColor = System.Drawing.Color.Magenta; - this.tsbApplyProfile.Name = "tsbApplyProfile"; - this.tsbApplyProfile.Overflow = System.Windows.Forms.ToolStripItemOverflow.Never; - this.tsbApplyProfile.Size = new System.Drawing.Size(109, 22); - this.tsbApplyProfile.Text = "Apply changes"; - this.tsbApplyProfile.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - this.tsbApplyProfile.Click += new System.EventHandler(this.tsbApplyProfile_Click); + tsbApplyProfile.Alignment = ToolStripItemAlignment.Right; + tsbApplyProfile.Image = (Image)resources.GetObject("tsbApplyProfile.Image"); + tsbApplyProfile.ImageTransparentColor = Color.Magenta; + tsbApplyProfile.Name = "tsbApplyProfile"; + tsbApplyProfile.Overflow = ToolStripItemOverflow.Never; + tsbApplyProfile.Size = new Size(109, 26); + tsbApplyProfile.Text = "Apply changes"; + tsbApplyProfile.TextAlign = ContentAlignment.MiddleRight; + tsbApplyProfile.Click += tsbApplyProfile_Click; // // btnResetValue // - this.btnResetValue.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.btnResetValue.Enabled = false; - this.btnResetValue.Image = global::nspector.Properties.Resources.nv_btn; - this.btnResetValue.Location = new System.Drawing.Point(732, 175); - this.btnResetValue.Margin = new System.Windows.Forms.Padding(0, 1, 0, 0); - this.btnResetValue.Name = "btnResetValue"; - this.btnResetValue.Size = new System.Drawing.Size(25, 19); - this.btnResetValue.TabIndex = 7; - this.btnResetValue.UseVisualStyleBackColor = true; - this.btnResetValue.Click += new System.EventHandler(this.btnResetValue_Click); + btnResetValue.Anchor = AnchorStyles.Top | AnchorStyles.Right; + btnResetValue.Enabled = false; + btnResetValue.Image = (Image)resources.GetObject("btnResetValue.Image"); + btnResetValue.Location = new Point(854, 202); + btnResetValue.Margin = new Padding(0, 1, 0, 0); + btnResetValue.Name = "btnResetValue"; + btnResetValue.Size = new Size(29, 22); + btnResetValue.TabIndex = 7; + btnResetValue.UseVisualStyleBackColor = true; + btnResetValue.Click += btnResetValue_Click; // // lblApplications // - this.lblApplications.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.lblApplications.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(118)))), ((int)(((byte)(185)))), ((int)(((byte)(0))))); - this.lblApplications.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; - this.lblApplications.ForeColor = System.Drawing.Color.White; - this.lblApplications.Location = new System.Drawing.Point(12, 32); - this.lblApplications.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); - this.lblApplications.Name = "lblApplications"; - this.lblApplications.Size = new System.Drawing.Size(840, 17); - this.lblApplications.TabIndex = 25; - this.lblApplications.Text = "fsagame.exe, bond.exe, herozero.exe"; + lblApplications.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; + lblApplications.BackColor = Color.FromArgb(118, 185, 0); + lblApplications.BorderStyle = BorderStyle.Fixed3D; + lblApplications.ForeColor = Color.White; + lblApplications.Location = new Point(14, 37); + lblApplications.Margin = new Padding(5, 0, 5, 0); + lblApplications.Name = "lblApplications"; + lblApplications.Size = new Size(980, 20); + lblApplications.TabIndex = 25; + lblApplications.Text = "fsagame.exe, bond.exe, herozero.exe"; // // toolStripButton5 // - this.toolStripButton5.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolStripButton5.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton5.Image"))); - this.toolStripButton5.ImageTransparentColor = System.Drawing.Color.Magenta; - this.toolStripButton5.Name = "toolStripButton5"; - this.toolStripButton5.Size = new System.Drawing.Size(23, 22); - this.toolStripButton5.Text = "toolStripButton5"; + toolStripButton5.DisplayStyle = ToolStripItemDisplayStyle.Image; + toolStripButton5.Image = (Image)resources.GetObject("toolStripButton5.Image"); + toolStripButton5.ImageTransparentColor = Color.Magenta; + toolStripButton5.Name = "toolStripButton5"; + toolStripButton5.Size = new Size(23, 22); + toolStripButton5.Text = "toolStripButton5"; // // toolStripLabel2 // - this.toolStripLabel2.Name = "toolStripLabel2"; - this.toolStripLabel2.Size = new System.Drawing.Size(86, 22); - this.toolStripLabel2.Text = "toolStripLabel2"; + toolStripLabel2.Name = "toolStripLabel2"; + toolStripLabel2.Size = new Size(86, 22); + toolStripLabel2.Text = "toolStripLabel2"; // // toolStripButton6 // - this.toolStripButton6.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolStripButton6.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton6.Image"))); - this.toolStripButton6.ImageTransparentColor = System.Drawing.Color.Magenta; - this.toolStripButton6.Name = "toolStripButton6"; - this.toolStripButton6.Size = new System.Drawing.Size(23, 22); - this.toolStripButton6.Text = "toolStripButton6"; + toolStripButton6.DisplayStyle = ToolStripItemDisplayStyle.Image; + toolStripButton6.Image = (Image)resources.GetObject("toolStripButton6.Image"); + toolStripButton6.ImageTransparentColor = Color.Magenta; + toolStripButton6.Name = "toolStripButton6"; + toolStripButton6.Size = new Size(23, 22); + toolStripButton6.Text = "toolStripButton6"; // // ilCombo // - this.ilCombo.ColorDepth = System.Windows.Forms.ColorDepth.Depth8Bit; - this.ilCombo.ImageSize = new System.Drawing.Size(16, 16); - this.ilCombo.TransparentColor = System.Drawing.Color.Transparent; + ilCombo.ColorDepth = ColorDepth.Depth8Bit; + ilCombo.ImageSize = new Size(16, 16); + ilCombo.TransparentColor = Color.Transparent; // // cbValues // - this.cbValues.BackColor = System.Drawing.SystemColors.Window; - this.cbValues.FormattingEnabled = true; - this.cbValues.Location = new System.Drawing.Point(524, 175); - this.cbValues.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); - this.cbValues.Name = "cbValues"; - this.cbValues.Size = new System.Drawing.Size(72, 21); - this.cbValues.TabIndex = 5; - this.cbValues.Visible = false; - this.cbValues.SelectedValueChanged += new System.EventHandler(this.cbValues_SelectedValueChanged); - this.cbValues.Leave += new System.EventHandler(this.cbValues_Leave); + cbValues.BackColor = SystemColors.Window; + cbValues.FormattingEnabled = true; + cbValues.Location = new Point(611, 202); + cbValues.Margin = new Padding(5, 0, 5, 0); + cbValues.Name = "cbValues"; + cbValues.Size = new Size(83, 23); + cbValues.TabIndex = 5; + cbValues.Visible = false; + cbValues.SelectedValueChanged += cbValues_SelectedValueChanged; + cbValues.Leave += cbValues_Leave; // // lblWidth96 // - this.lblWidth96.Location = new System.Drawing.Point(77, 233); - this.lblWidth96.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); - this.lblWidth96.Name = "lblWidth96"; - this.lblWidth96.Size = new System.Drawing.Size(96, 18); - this.lblWidth96.TabIndex = 77; - this.lblWidth96.Text = "96"; - this.lblWidth96.Visible = false; + lblWidth96.Location = new Point(90, 269); + lblWidth96.Margin = new Padding(5, 0, 5, 0); + lblWidth96.Name = "lblWidth96"; + lblWidth96.Size = new Size(112, 21); + lblWidth96.TabIndex = 77; + lblWidth96.Text = "96"; + lblWidth96.Visible = false; // // lblWidth330 // - this.lblWidth330.Location = new System.Drawing.Point(77, 210); - this.lblWidth330.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); - this.lblWidth330.Name = "lblWidth330"; - this.lblWidth330.Size = new System.Drawing.Size(330, 22); - this.lblWidth330.TabIndex = 78; - this.lblWidth330.Text = "330 (Helper Labels for DPI Scaling)"; - this.lblWidth330.Visible = false; + lblWidth330.Location = new Point(90, 242); + lblWidth330.Margin = new Padding(5, 0, 5, 0); + lblWidth330.Name = "lblWidth330"; + lblWidth330.Size = new Size(385, 25); + lblWidth330.TabIndex = 78; + lblWidth330.Text = "330 (Helper Labels for DPI Scaling)"; + lblWidth330.Visible = false; // // lblWidth16 // - this.lblWidth16.Location = new System.Drawing.Point(77, 269); - this.lblWidth16.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); - this.lblWidth16.Name = "lblWidth16"; - this.lblWidth16.Size = new System.Drawing.Size(16, 18); - this.lblWidth16.TabIndex = 79; - this.lblWidth16.Text = "16"; - this.lblWidth16.Visible = false; + lblWidth16.Location = new Point(90, 310); + lblWidth16.Margin = new Padding(5, 0, 5, 0); + lblWidth16.Name = "lblWidth16"; + lblWidth16.Size = new Size(19, 21); + lblWidth16.TabIndex = 79; + lblWidth16.Text = "16"; + lblWidth16.Visible = false; // // lblWidth30 // - this.lblWidth30.Location = new System.Drawing.Point(77, 251); - this.lblWidth30.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); - this.lblWidth30.Name = "lblWidth30"; - this.lblWidth30.Size = new System.Drawing.Size(30, 18); - this.lblWidth30.TabIndex = 80; - this.lblWidth30.Text = "30"; - this.lblWidth30.Visible = false; + lblWidth30.Location = new Point(90, 290); + lblWidth30.Margin = new Padding(5, 0, 5, 0); + lblWidth30.Name = "lblWidth30"; + lblWidth30.Size = new Size(35, 21); + lblWidth30.TabIndex = 80; + lblWidth30.Text = "30"; + lblWidth30.Visible = false; // // lvSettings // - this.lvSettings.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { - this.chSettingID, - this.chSettingValue, - this.chSettingValueHex}); - this.lvSettings.Dock = System.Windows.Forms.DockStyle.Fill; - this.lvSettings.FullRowSelect = true; - this.lvSettings.GridLines = true; - this.lvSettings.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None; - this.lvSettings.HideSelection = false; - this.lvSettings.Location = new System.Drawing.Point(0, 0); - this.lvSettings.Margin = new System.Windows.Forms.Padding(4); - this.lvSettings.MultiSelect = false; - this.lvSettings.Name = "lvSettings"; - this.lvSettings.ShowItemToolTips = true; - this.lvSettings.Size = new System.Drawing.Size(840, 372); - this.lvSettings.SmallImageList = this.ilListView; - this.lvSettings.TabIndex = 2; - this.lvSettings.UseCompatibleStateImageBehavior = false; - this.lvSettings.View = System.Windows.Forms.View.Details; - this.lvSettings.ColumnWidthChanging += new System.Windows.Forms.ColumnWidthChangingEventHandler(this.lvSettings_ColumnWidthChanging); - this.lvSettings.SelectedIndexChanged += new System.EventHandler(this.lvSettings_SelectedIndexChanged); - this.lvSettings.DoubleClick += new System.EventHandler(this.lvSettings_DoubleClick); - this.lvSettings.KeyDown += new System.Windows.Forms.KeyEventHandler(this.lvSettings_KeyDown); - this.lvSettings.Resize += new System.EventHandler(this.lvSettings_Resize); + lvSettings.Columns.AddRange(new ColumnHeader[] { chSettingID, chSettingValue, chSettingValueHex }); + lvSettings.Dock = DockStyle.Fill; + lvSettings.Font = new Font("Segoe UI", 8.25F, FontStyle.Regular, GraphicsUnit.Point); + lvSettings.FullRowSelect = true; + lvSettings.GridLines = true; + lvSettings.HeaderStyle = ColumnHeaderStyle.None; + lvSettings.Location = new Point(0, 0); + lvSettings.Margin = new Padding(5, 5, 5, 5); + lvSettings.MultiSelect = false; + lvSettings.Name = "lvSettings"; + lvSettings.ShowItemToolTips = true; + lvSettings.Size = new Size(980, 430); + lvSettings.SmallImageList = ilListView; + lvSettings.TabIndex = 2; + lvSettings.UseCompatibleStateImageBehavior = false; + lvSettings.View = View.Details; + lvSettings.ColumnWidthChanging += lvSettings_ColumnWidthChanging; + lvSettings.SelectedIndexChanged += lvSettings_SelectedIndexChanged; + lvSettings.DoubleClick += lvSettings_DoubleClick; + lvSettings.KeyDown += lvSettings_KeyDown; + lvSettings.Resize += lvSettings_Resize; // // chSettingID // - this.chSettingID.Text = "SettingID"; - this.chSettingID.Width = 330; + chSettingID.Text = "SettingID"; + chSettingID.Width = 330; // // chSettingValue // - this.chSettingValue.Text = "SettingValue"; - this.chSettingValue.Width = 340; + chSettingValue.Text = "SettingValue"; + chSettingValue.Width = 340; // // chSettingValueHex // - this.chSettingValueHex.Text = "SettingValueHex"; - this.chSettingValueHex.Width = 96; + chSettingValueHex.Text = "SettingValueHex"; + chSettingValueHex.Width = 96; // // tbSettingDescription // - this.tbSettingDescription.Dock = System.Windows.Forms.DockStyle.Bottom; - this.tbSettingDescription.Location = new System.Drawing.Point(0, 372); - this.tbSettingDescription.Multiline = true; - this.tbSettingDescription.Name = "tbSettingDescription"; - this.tbSettingDescription.ReadOnly = true; - this.tbSettingDescription.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; - this.tbSettingDescription.Size = new System.Drawing.Size(840, 44); - this.tbSettingDescription.TabIndex = 81; - this.tbSettingDescription.Visible = false; + tbSettingDescription.Dock = DockStyle.Bottom; + tbSettingDescription.Location = new Point(0, 430); + tbSettingDescription.Margin = new Padding(4, 3, 4, 3); + tbSettingDescription.Multiline = true; + tbSettingDescription.Name = "tbSettingDescription"; + tbSettingDescription.ReadOnly = true; + tbSettingDescription.ScrollBars = ScrollBars.Vertical; + tbSettingDescription.Size = new Size(980, 50); + tbSettingDescription.TabIndex = 81; + tbSettingDescription.Visible = false; // // pnlListview // - this.pnlListview.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.pnlListview.Controls.Add(this.lvSettings); - this.pnlListview.Controls.Add(this.tbSettingDescription); - this.pnlListview.Location = new System.Drawing.Point(12, 52); - this.pnlListview.Name = "pnlListview"; - this.pnlListview.Size = new System.Drawing.Size(840, 416); - this.pnlListview.TabIndex = 82; + pnlListview.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; + pnlListview.Controls.Add(lvSettings); + pnlListview.Controls.Add(tbSettingDescription); + pnlListview.Location = new Point(14, 60); + pnlListview.Margin = new Padding(4, 3, 4, 3); + pnlListview.Name = "pnlListview"; + pnlListview.Size = new Size(980, 480); + pnlListview.TabIndex = 82; // // frmDrvSettings // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(864, 492); - this.Controls.Add(this.pnlListview); - this.Controls.Add(this.lblWidth30); - this.Controls.Add(this.lblWidth16); - this.Controls.Add(this.lblWidth330); - this.Controls.Add(this.lblWidth96); - this.Controls.Add(this.lblApplications); - this.Controls.Add(this.tsMain); - this.Controls.Add(this.pbMain); - this.Controls.Add(this.btnResetValue); - this.Controls.Add(this.cbValues); - this.Margin = new System.Windows.Forms.Padding(4); - this.MinimumSize = new System.Drawing.Size(879, 346); - this.Name = "frmDrvSettings"; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; - this.Text = "nSpector - Driver Profile Settings"; - this.Activated += new System.EventHandler(this.frmDrvSettings_Activated); - this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.frmDrvSettings_FormClosed); - this.Load += new System.EventHandler(this.frmDrvSettings_Load); - this.Shown += new System.EventHandler(this.frmDrvSettings_Shown); - this.tsMain.ResumeLayout(false); - this.tsMain.PerformLayout(); - this.pnlListview.ResumeLayout(false); - this.pnlListview.PerformLayout(); - this.ResumeLayout(false); - + AutoScaleDimensions = new SizeF(7F, 15F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(1008, 568); + Controls.Add(pnlListview); + Controls.Add(lblWidth30); + Controls.Add(lblWidth16); + Controls.Add(lblWidth330); + Controls.Add(lblWidth96); + Controls.Add(lblApplications); + Controls.Add(tsMain); + Controls.Add(pbMain); + Controls.Add(btnResetValue); + Controls.Add(cbValues); + Margin = new Padding(5, 5, 5, 5); + MinimumSize = new Size(1023, 393); + Name = "frmDrvSettings"; + StartPosition = FormStartPosition.CenterParent; + Text = "nSpector - Driver Profile Settings"; + Activated += frmDrvSettings_Activated; + FormClosed += frmDrvSettings_FormClosed; + Load += frmDrvSettings_Load; + Shown += frmDrvSettings_Shown; + tsMain.ResumeLayout(false); + tsMain.PerformLayout(); + pnlListview.ResumeLayout(false); + pnlListview.PerformLayout(); + ResumeLayout(false); } #endregion private ListViewEx lvSettings; - private System.Windows.Forms.ColumnHeader chSettingID; - private System.Windows.Forms.ColumnHeader chSettingValue; - private System.Windows.Forms.ColumnHeader chSettingValueHex; - private System.Windows.Forms.ImageList ilListView; - private System.Windows.Forms.ComboBox cbValues; - private System.Windows.Forms.Button btnResetValue; - private System.Windows.Forms.ProgressBar pbMain; - private System.Windows.Forms.ToolStrip tsMain; - private System.Windows.Forms.ToolStripButton tsbRestoreProfile; - private System.Windows.Forms.ToolStripButton tsbApplyProfile; - private System.Windows.Forms.ToolStripButton tsbRefreshProfile; - private System.Windows.Forms.ToolStripSeparator tsSep3; - private System.Windows.Forms.ToolStripButton tsbBitValueEditor; - private System.Windows.Forms.ToolStripSeparator tsSep6; - private System.Windows.Forms.ToolStripButton tscbShowCustomSettingNamesOnly; - private System.Windows.Forms.ToolStripSeparator tsSep5; - private System.Windows.Forms.ToolStripButton tscbShowScannedUnknownSettings; - private System.Windows.Forms.ToolStripLabel tslProfiles; - private System.Windows.Forms.Label lblApplications; - private System.Windows.Forms.ToolStripButton toolStripButton5; - private System.Windows.Forms.ToolStripLabel toolStripLabel2; - private System.Windows.Forms.ToolStripButton toolStripButton6; - private System.Windows.Forms.ToolStripSeparator tsSep2; - private System.Windows.Forms.ToolStripButton tsbDeleteProfile; - private System.Windows.Forms.ToolStripButton tsbCreateProfile; - private System.Windows.Forms.ToolStripButton tsbAddApplication; - private System.Windows.Forms.ToolStripSplitButton tssbRemoveApplication; - private System.Windows.Forms.ToolStripSeparator tsSep4; - private System.Windows.Forms.ToolStripSplitButton tsbExportProfiles; - private System.Windows.Forms.ToolStripMenuItem exportCurrentProfileOnlyToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem exportUserdefinedProfilesToolStripMenuItem; - private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; - public System.Windows.Forms.ToolStripComboBox cbProfiles; - private System.Windows.Forms.ToolStripSplitButton tsbModifiedProfiles; - private System.Windows.Forms.ImageList ilCombo; - private System.Windows.Forms.ToolStripMenuItem exportAllProfilesNVIDIATextFormatToolStripMenuItem; - private System.Windows.Forms.ToolStripSplitButton tsbImportProfiles; - private System.Windows.Forms.ToolStripMenuItem importProfilesToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem importAllProfilesNVIDIATextFormatToolStripMenuItem; - private System.Windows.Forms.Label lblWidth96; - private System.Windows.Forms.Label lblWidth330; - private System.Windows.Forms.Label lblWidth16; - private System.Windows.Forms.Label lblWidth30; - private System.Windows.Forms.ToolStripMenuItem exportCurrentProfileIncludingPredefinedSettingsToolStripMenuItem; - private System.Windows.Forms.TextBox tbSettingDescription; - private System.Windows.Forms.Panel pnlListview; + private ColumnHeader chSettingID; + private ColumnHeader chSettingValue; + private ColumnHeader chSettingValueHex; + private ImageList ilListView; + private ComboBox cbValues; + private Button btnResetValue; + private ProgressBar pbMain; + private ToolStrip tsMain; + private ToolStripButton tsbRestoreProfile; + private ToolStripButton tsbApplyProfile; + private ToolStripButton tsbRefreshProfile; + private ToolStripSeparator tsSep3; + private ToolStripButton tsbBitValueEditor; + private ToolStripSeparator tsSep6; + private ToolStripButton tscbShowCustomSettingNamesOnly; + private ToolStripSeparator tsSep5; + private ToolStripButton tscbShowScannedUnknownSettings; + private ToolStripLabel tslProfiles; + private Label lblApplications; + private ToolStripButton toolStripButton5; + private ToolStripLabel toolStripLabel2; + private ToolStripButton toolStripButton6; + private ToolStripSeparator tsSep2; + private ToolStripButton tsbDeleteProfile; + private ToolStripButton tsbCreateProfile; + private ToolStripButton tsbAddApplication; + private ToolStripSplitButton tssbRemoveApplication; + private ToolStripSeparator tsSep4; + private ToolStripSplitButton tsbExportProfiles; + private ToolStripMenuItem exportCurrentProfileOnlyToolStripMenuItem; + private ToolStripMenuItem exportUserdefinedProfilesToolStripMenuItem; + private ToolStripSeparator toolStripSeparator1; + public ToolStripComboBox cbProfiles; + private ToolStripSplitButton tsbModifiedProfiles; + private ImageList ilCombo; + private ToolStripMenuItem exportAllProfilesNVIDIATextFormatToolStripMenuItem; + private ToolStripSplitButton tsbImportProfiles; + private ToolStripMenuItem importProfilesToolStripMenuItem; + private ToolStripMenuItem importAllProfilesNVIDIATextFormatToolStripMenuItem; + private Label lblWidth96; + private Label lblWidth330; + private Label lblWidth16; + private Label lblWidth30; + private ToolStripMenuItem exportCurrentProfileIncludingPredefinedSettingsToolStripMenuItem; + private TextBox tbSettingDescription; + private Panel pnlListview; } } \ No newline at end of file diff --git a/Nspector/frmDrvSettings.cs b/Nspector/frmDrvSettings.cs index c3e7cef..ea33596 100644 --- a/Nspector/frmDrvSettings.cs +++ b/Nspector/frmDrvSettings.cs @@ -19,6 +19,7 @@ namespace nspector private List _currentProfileSettingItems = new List(); private static bool _alreadyScannedForPredefinedSettings = false; + private static object[] _baseProfileNames; private IntPtr _taskbarParent = IntPtr.Zero; private bool _activated = false; private bool _isStartup = true; @@ -173,15 +174,16 @@ namespace nspector GC.Collect(); for (int i = 0; i < lvSettings.Items.Count; i++) { - if (lvSettings.Items[i].Text == lvSelection) + var item = lvSettings.Items[i]; + if (item.Text == lvSelection) { - lvSettings.Items[i].Selected = true; - lvSettings.Items[i].EnsureVisible(); + item.Selected = true; + item.EnsureVisible(); if (!cbProfiles.Focused) { lvSettings.Select(); - cbValues.Text = lvSettings.Items[i].SubItems[1].Text; + cbValues.Text = item.SubItems[1].Text; } break; } @@ -193,12 +195,33 @@ namespace nspector { cbProfiles.Items.Clear(); - var profileNames = _drs.GetProfileNames(ref _baseProfileName); - cbProfiles.Items.AddRange(profileNames.Cast().ToArray()); + if (_baseProfileNames != null) + { + cbProfiles.Items.AddRange(_baseProfileNames); + } + else + { + var profileNames = _drs.GetProfileNames(ref _baseProfileName); + _baseProfileNames = profileNames.Cast().ToArray(); + cbProfiles.Items.AddRange(_baseProfileNames); + } cbProfiles.Sorted = true; } + public void SetProfileByExecutable(string executable) + { + var profileName = _drs.GetProfileNameByApps(executable); + + if (profileName != null) + { + cbProfiles.SelectedIndex = cbProfiles.Items.IndexOf(profileName); + return; + } + + ShowCreateProfileDialog(Path.GetFileNameWithoutExtension(executable), executable); + } + private void MoveComboToItemAndFill() { if (lvSettings.SelectedItems.Count > 0) diff --git a/Nspector/frmDrvSettings.resx b/Nspector/frmDrvSettings.resx index 677e228..6c299b6 100644 --- a/Nspector/frmDrvSettings.resx +++ b/Nspector/frmDrvSettings.resx @@ -1,17 +1,17 @@  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 115, 17 - - - - AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w - LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 - ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADI - DAAAAk1TRnQBSQFMAgEBBAEAAcABBwHAAQcBEAEAARABAAT/ARkBAAj/AUIBTQE2BwABNgMAASgDAAFA - AwABIAMAAQEBAAEYBgABGP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/ADMAAcgBvQGvAacBkQF5BgAD/iEA - A+QD2gYAA/4hAAGXAcMBqwFMAZwBcAYAA/4hAAOmA2gGAAP+FQAB8gHxAfABqQGPAXQBzwHHAbwD/wG6 - AaUBjAGuAZQBeAHxAe8B7QHvAe0B6wGhAYgBbQHkAeAB2xIAA/UD3QPmA/8D4APeA/QD8wPaA+4SAAHt - AfIB7wE3AaEBZgGlAcwBtwP/AVgBsQGAATUBpgFoAekB8AHsAecB7wHqATwBlQFkAdQB4gHaEgAD7gNi - A7UD/wN6A2QD7APqA1oD2BIAAfMB8QHvAbwBoQGGAb4BogGHAb4BpQGIAbsBogGFAbwBogGEAagBlQGB - Aa0BlgF/Aa4BkgF3AegB5QHhEgAD9QnjBuIJ3gPwEgAB6wHyAe4BOgG1AXEBPAG2AXQBPgG3AXMBOgG1 - AXEBOgG1AXEBNwGmAWoBOAGoAWsBNAGkAWcB2QHnAd8SAAPuA3MDdgN0A3EDbwNxA20DZAPeDAAB9AHz - AfIB7wHsAekB6AHiAdwByQGyAZcB0wHCAa4BzgG8AaYBzAG6AaUBzAG5AaMBywG3AaIBygG3AaIBvgGn - AY8BxgG1AaMB5AHgAdsB4wHeAdoD/wMAA/YD8wPvA+cD7AbqCekG5AbuA/8DAAHvAfQB8QHiAe4B5wHM - AeYB1wFCAcMBfAFUAckBiQFOAccBhQFLAcYBggFLAcYBggFJAcUBgQFJAcUBgQE8AbsBdQF7Ab8BmgHT - AeIB2gHTAeAB2QP/AwAD8QPnA9cDhAOgA5cDlgmTA34DlgPYA9cD/wMAAcYBswGdAb4BqAGPAcwBtQGa - AdMBvwGrAdUBxQGyAccBsAGXAcMBrAGNAb8BpgGMAb8BpwGMAcUBrwGXAcYBswGdAbsBowGJAaIBiwFx - AY0BcwFXAeEB3QHYAwAD5QPkA+gD7APtA+cD5APiA+QG5wPjA9sD1APtAwABXQHCAYoBPAG7AXUBSAHE - AYEBVAHJAYkBWAHKAYsBQgHDAXwBQAG+AXgBQAG5AXYBOwG5AXQBQAHCAXsBQwHDAX0BOgG2AXIBMQGb - AWEBLAGAAVEB0QHeAdcDAAOOA30DhwOdA6UDhQN3A3gDeQOGA40DdwNfA0MD1QMAAekB5AHeAcYBrgGU - AdUBxAGtAc0BuQGlAcoBsAGYAeUB3gHXAfgB9wH2A/oB6AHiAdwBwQGpAY4BwAGoAY4BxAGuAZUBsQGZ - AYABzwHGAb0D+wMAA+8D5gPsA+oD5gPtA/kD+wPvBuQD5gPgA+cD/AMAAc4B5wHaAUABwgF8AVUByQGJ - AUwBxgGDAUcBxAF/AcMB4wHRAfQB9wH2AfkC+gHOAeYB2QFFAbkBeQE8AbwBdgE9AcEBeQE3AawBbAGt - AcsBuwH6AvsDAAPZA4IDnQOXA4YD0QP2A/oD2AN6A3wDgwNuA7YD+wMAAfcB9gH1AcgBsAGVAd4BzAG2 - AcsBtQGcAdQByQG6DAAB4gHdAdoBtwGgAY4BwwGwAaEBpQGSAYAB8AHuAewGAAP4A+cD7wboDAAD7gPj - A+gD3gPzBgAB8gH2AfQBQgHCAX0BYAHNAZEBRgHEAX8BmgHRAbMMAAHIAeMB1AE6AbYBcgFFAcQBfgE2 - AaMBaAHnAe8B6gYAA/QDggOnA4oDsQwAA9gDgQOWA3ID6gMAAc0BuQGiAcsBtAGZAeMBzQG3AecB1gHD - AbsBoQGFA/oMAAP6Ab8BpgGMAcwBuQGjAbwBogGEAa4BlAF4AacBkQF5A+cD6APwA/ID4QP7DAAD+wPi - A+kD4gPeA9oBXgHJAY4BRQHEAX4BYwHOAZMBbAHQAZkBPAG0AXMB+QL6DAAB+QL6AUABuQF2AUsBxgGC - AToBtQFxATUBpgFoAUwBnAFwA5IDhgOnA7YDcwP5DAAD+gN4A5MDbwNkA2gB1wHJAbgBzwG4AaIB5gHR - Ab0B7AHbAcoBugGhAYUC+QH4DAAB+AH3AfYBwwGsAY0BzAG6AaUBuwGiAYUBugGlAYwByAG9Aa8D6QPn - A/ED9APhA/oMAAP5A+QD6gPiA+AD5AGKAdMBqwFXAccBigFoAc8BlgFyAdIBnQE8AbIBcAH4AfkB+AwA - AfQB9wH2AUABvgF4AUsBxgGCAToBtQFxAVgBsQGAAZcBwwGrA6wDkgOvA74DcQP4DAAD9gN3A5YDcQN6 - A6YDAAP7AdwByQGzAewB3AHLAccBswGaAc4BxAG5DAAB5QHeAdcBxwGwAZcBzgG8AaYBvgGlAYgD/wYA - A/sD7QP0A+cD5QwAA+0D5wPqA+MD/wYAAfoC+wFeAcwBjwFyAdIBnQFCAcMBfAGoAckBtgwAAcMB4wHR - AUIBwwF8AU4BxwGFAT4BtwFzA/8GAAP7A6MDvwOIA7IMAAPRA4UDlwN0A/8GAAHxAe8B7AHZAcQBrQHv - Ad8BzgHfAc0BuwG2AaEBhQHOAcQBuQL5AfgD+gHUAckBugHKAbABmAHVAcUBsgHTAcIBrgG+AaIBhwHP - AccBvAYAA/QD7QP1A/AD4QPlA/oD+wPoA+YD7QPsA+MD5gYAAeUB8QHqAVkBygGNAXcB1AGhAWMBzgGT - ATwBsQFwAagByQG2AfgB+QH4AfkC+gGaAdEBswFHAcQBfwFYAcoBiwFUAckBiQE8AbYBdAGlAcwBtwYA - A+oDmwPCA64DcQOyA/gD+QOxA4YDpQOgA3YDtQYAAdYBxgGyAdABuAGdAdsBxQGwAfIB4gHSAeABzwG8 - AccBswGaAboBoQGFAbsBoQGFAcsBtQGcAc0BuQGlAdMBvwGrAckBsgGXAbwBoQGGAakBjwF0BgAD6APp - A+wD9gPwA+cG4QPoA+oD7APnA+MD3QYAAXsB0QGhAUkBxQGBAV0BywGOAXsB1QGkAWQBzgGUAUIBwwF8 - ATwBsgFwATwBtAFzAUYBxAF/AUwBxgGDAVQByQGJAUIBwwF8AToBtQFxATcBoQFmBgADowOKA6ADxwOv - A4gDcQNzA4oDlwOdA4QDcwNiBgAB8wHxAe8B8AHtAeoB8QHuAesB4gHOAboB7gHfAc0B7AHcAcsB7AHb - AcoB5wHWAcMB3gHMAbYB1QHEAa0BzAG1AZoB6AHiAdwB8wHxAe8B8gHxAfAGAAP1A/ID8wPwA/UG9APy - A+8D7APoA+8G9QYAAeoB8wHuAeEB7wHnAeMB8AHoAWQBzgGUAXUB0wGfAXIB0gGdAXIB0gGdAWwB0AGZ - AWABzQGRAVUByQGJAUgBxAGBAcwB5gHXAesB8gHuAe0B8gHvBgAD7gPoA+kDrAPAA78DvgO2A6cDnQOH - A9cG7gwAAfQB8wHxAdUBwAGnAdkBwwGqAdwByQGzAeYB0QG9AeMBzQG3AcgBsAGVAcYBrgGUAb4BqAGP - Ae8B7AHpEgAD9gPrA+wD7QPxA/AD5wPmA+QD8xIAAe0B9AHwAVIByAGHAVcByQGJAV4BzAGPAWgBzwGW - AWMBzgGTAUIBwgF9AUABwgF8ATwBuwF1AeIB7gHnEgAD8AOVA5gDowOvA6cGggN9A+cSAAH1AfQB8gHQ - Ab0BpAHgAdYBzAP7Ac8BuAGiAcsBtAGZAfcB9gH1AekB5AHeAcYBswGdAfQB8wHyEgAD9gPpA+sD+wPn - A+gD+APvA+UD9hIAAe4B9QHxAVsByQGNAasB3QHCAfoC+wFXAccBigFFAcQBfgHyAfYB9AHOAecB2gFd - AcIBigHvAfQB8RIAA/EDkgPEA/sDkgOGA/QD2QOOA/EVAAH9AvwD/gMAAdcByQG4Ac0BuQGiIQAD/QP+ - AwAD6QPnIQAD/AP+AwABigHTAasBXgHJAY4hAAP8A/4DAAOsA5IVAAFCAU0BPgcAAT4DAAEoAwABQAMA - ASADAAEBAQABAQYAAQEWAAP/gQAB/gFvAf4BbwH+AW8B/gFvAeABBwHgAQcB4AEHAeABBwHgAQcB4AEH - AeABBwHgAQcBgAEAAYABAAGAAQABgAEAAYABAAGAAQABgAEAAYABAAGAAQABgAEAAYABAAGAAQABgwHB - AYMBwQGDAcEBgwHBAQMBwAEDAcABAwHAAQMBwAEDAcABAwHAAQMBwAEDAcABgwHBAYMBwQGDAcEBgwHB - AYABAQGAAQEBgAEBAYABAQGAAQEBgAEBAYABAQGAAQEBgAEBAYABAQGAAQEBgAEBAeABBwHgAQcB4AEH - AeABBwHgAQcB4AEHAeABBwHgAQcB8gF/AfIBfwHyAX8B8gF/Cw== - - - - True - - - 217, 17 - - - True - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGgSURBVDhPrZPLSsNAFIb7BoKP4Upw5UoQBHfmMrG1olCa - pFoExY2KiHcRERFEwYUKglSQesFeQK2rFkFr0Y26MRAKpa2+QS+/MzGpaS114wdhQv7/nDknZ8bx7xDi - a+FFeYvnFU2QFHCcRxdEOcQTmTctjWHB4UgM2Wwe5XIZ+fwnko/PWF3bhiAqJzRRp2mtD0/U7oWlTbAK - Bj1jYO/vmo5SqYR44gG9fcPgiNpu2uvDkrCVEG+zIMkqcfqQuEuiWCwidhsHJ8qHhtEOLX2H9cxW81MF - nni7XP1+5PIfKBQKmJlbR1UrVnAul0O9JJa+fxAwPJehqx+fPdh6apPU6nZfY9Gk4SaWGDwN09FlsUfL - rIg2LB/z/NI5SW4bHZ9FJpPBy+sbnG4//Unfk7BjJalNbsBGEzwLIZ1OIxK9AXGqdCdZlSS1iel/HiB2 - OCTXEM4vItB1nc79HpPTK3APjBiHamJquXp09eCI0sGJyvH84gat4hqp1BM0TUMymcJRIEhLV3ZNa2ME - 4nXSCxQ1LhLrmVbAgnskudW0/BcOxxdQeE7WHAMG/AAAAABJRU5ErkJggg== - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFcSURBVDhP3VFNK0RhFL4/wNbM3PdcCgsfsbHDgkJKWPgD - ilJGNN73XEs/gbKUmvITuPc9d5iwYKfZyULZ26BkhTjnnXs1TWTNqafOx/M895z3ev84FsrwigQfvyGl - 1yNM1IyO4cQNrUKdqGFj1awmuGgWZnDC9Wouz8U1xnATkj+oE78HLVyWKPeAlH9EUkOa1FyzWOAxeVIS - JuxtRoVeERhS51zviLlsIHNjYRltW1ejWOChDdbqhEIfRoVbE0PZbXXoP3G/ygZFNyeYZ4xlwgzC9fAI - 7rmomUrQL01TyXekPUfSVo3zSSVXW3Ug75PNnEEpau+Uglff5XsnOH9D8reZuBJamOa6JvPQqkXhF89a - W9jw+MtAIiTVjRE88+AKY3/E5fKVGO74jC3hbMTBAPf2XT+FEzcGb7BqrH/KWNIUTLk34LX5V740Cn80 - yGKU4P07QTNS+t8Nz/sEkToIpLSWKNoAAAAASUVORK5CYII= - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEgSURBVDhP3Y/PKwRhHIf3f5g/wMWUlIuDUk5y5MCB3Dk4 - 7EUbBwdXJ3EXsksjidlk2x27NrXt5kdjlTQXbSFK2iaGaX7s491Zjppx5FNP7/et9/n0fmP/PFwu8JGd - 5OsaLdxpNIyVQPL1GcyDwWDmVsEx1sLLGvdHeLtduKVh/GIPTlbGPRvF3mmjXm0Vh8a9SEBGAl1gCMoS - j2p/uOyX5/AK4/i5bqgI8UrQPFUJO9mOr43gHk/9XOToy9QLCd4O+yAvxCb7gg0JK9WJqcWxTubDf+Kd - x0ERYkqwLliVeE8PRNufWhpnUxY7j2Fu92IlO3jOT+AqMk+lxfAS+6HI6/VW8NA5neVlb6g11zLcVNRo - v/gO1SXM3PTvpL+WWOwT04jC5H73kgIAAAAASUVORK5CYII= - - - - True - - - True - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG - YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9 - 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw - bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc - VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9 - c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32 - Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo - mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+ - kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D - TgDQASA1MVpwzwAAAABJRU5ErkJggg== - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG - YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9 - 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw - bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc - VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9 - c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32 - Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo - mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+ - kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D - TgDQASA1MVpwzwAAAABJRU5ErkJggg== - - - - 17, 17 - - - True - - - True - - - True - - - True - - - True - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 115, 17 + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAEZTeXN0ZW0uV2luZG93cy5Gb3JtcywgQ3VsdHVyZT1uZXV0cmFs + LCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAAAmU3lzdGVtLldpbmRvd3MuRm9ybXMu + SW1hZ2VMaXN0U3RyZWFtZXIBAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAyAwAAAJNU0Z0AUkBTAIBAQQB + AAHIAQcByAEHARABAAEQAQAE/wEZAQAI/wFCAU0BNgcAATYDAAEoAwABQAMAASADAAEBAQABGAYAARj/ + AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wAzAAHIAb0BrwGnAZEBeQYAA/4hAAPkA9oGAAP+IQABlwHDAasB + TAGcAXAGAAP+IQADpgNoBgAD/hUAAfIB8QHwAakBjwF0Ac8BxwG8A/8BugGlAYwBrgGUAXgB8QHvAe0B + 7wHtAesBoQGIAW0B5AHgAdsSAAP1A90D5gP/A+AD3gP0A/MD2gPuEgAB7QHyAe8BNwGhAWYBpQHMAbcD + /wFYAbEBgAE1AaYBaAHpAfAB7AHnAe8B6gE8AZUBZAHUAeIB2hIAA+4DYgO1A/8DegNkA+wD6gNaA9gS + AAHzAfEB7wG8AaEBhgG+AaIBhwG+AaUBiAG7AaIBhQG8AaIBhAGoAZUBgQGtAZYBfwGuAZIBdwHoAeUB + 4RIAA/UJ4wbiCd4D8BIAAesB8gHuAToBtQFxATwBtgF0AT4BtwFzAToBtQFxAToBtQFxATcBpgFqATgB + qAFrATQBpAFnAdkB5wHfEgAD7gNzA3YDdANxA28DcQNtA2QD3gwAAfQB8wHyAe8B7AHpAegB4gHcAckB + sgGXAdMBwgGuAc4BvAGmAcwBugGlAcwBuQGjAcsBtwGiAcoBtwGiAb4BpwGPAcYBtQGjAeQB4AHbAeMB + 3gHaA/8DAAP2A/MD7wPnA+wG6gnpBuQG7gP/AwAB7wH0AfEB4gHuAecBzAHmAdcBQgHDAXwBVAHJAYkB + TgHHAYUBSwHGAYIBSwHGAYIBSQHFAYEBSQHFAYEBPAG7AXUBewG/AZoB0wHiAdoB0wHgAdkD/wMAA/ED + 5wPXA4QDoAOXA5YJkwN+A5YD2APXA/8DAAHGAbMBnQG+AagBjwHMAbUBmgHTAb8BqwHVAcUBsgHHAbAB + lwHDAawBjQG/AaYBjAG/AacBjAHFAa8BlwHGAbMBnQG7AaMBiQGiAYsBcQGNAXMBVwHhAd0B2AMAA+UD + 5APoA+wD7QPnA+QD4gPkBucD4wPbA9QD7QMAAV0BwgGKATwBuwF1AUgBxAGBAVQByQGJAVgBygGLAUIB + wwF8AUABvgF4AUABuQF2ATsBuQF0AUABwgF7AUMBwwF9AToBtgFyATEBmwFhASwBgAFRAdEB3gHXAwAD + jgN9A4cDnQOlA4UDdwN4A3kDhgONA3cDXwNDA9UDAAHpAeQB3gHGAa4BlAHVAcQBrQHNAbkBpQHKAbAB + mAHlAd4B1wH4AfcB9gP6AegB4gHcAcEBqQGOAcABqAGOAcQBrgGVAbEBmQGAAc8BxgG9A/sDAAPvA+YD + 7APqA+YD7QP5A/sD7wbkA+YD4APnA/wDAAHOAecB2gFAAcIBfAFVAckBiQFMAcYBgwFHAcQBfwHDAeMB + 0QH0AfcB9gH5AvoBzgHmAdkBRQG5AXkBPAG8AXYBPQHBAXkBNwGsAWwBrQHLAbsB+gL7AwAD2QOCA50D + lwOGA9ED9gP6A9gDegN8A4MDbgO2A/sDAAH3AfYB9QHIAbABlQHeAcwBtgHLAbUBnAHUAckBugwAAeIB + 3QHaAbcBoAGOAcMBsAGhAaUBkgGAAfAB7gHsBgAD+APnA+8G6AwAA+4D4wPoA94D8wYAAfIB9gH0AUIB + wgF9AWABzQGRAUYBxAF/AZoB0QGzDAAByAHjAdQBOgG2AXIBRQHEAX4BNgGjAWgB5wHvAeoGAAP0A4ID + pwOKA7EMAAPYA4EDlgNyA+oDAAHNAbkBogHLAbQBmQHjAc0BtwHnAdYBwwG7AaEBhQP6DAAD+gG/AaYB + jAHMAbkBowG8AaIBhAGuAZQBeAGnAZEBeQPnA+gD8APyA+ED+wwAA/sD4gPpA+ID3gPaAV4ByQGOAUUB + xAF+AWMBzgGTAWwB0AGZATwBtAFzAfkC+gwAAfkC+gFAAbkBdgFLAcYBggE6AbUBcQE1AaYBaAFMAZwB + cAOSA4YDpwO2A3MD+QwAA/oDeAOTA28DZANoAdcByQG4Ac8BuAGiAeYB0QG9AewB2wHKAboBoQGFAvkB + +AwAAfgB9wH2AcMBrAGNAcwBugGlAbsBogGFAboBpQGMAcgBvQGvA+kD5wPxA/QD4QP6DAAD+QPkA+oD + 4gPgA+QBigHTAasBVwHHAYoBaAHPAZYBcgHSAZ0BPAGyAXAB+AH5AfgMAAH0AfcB9gFAAb4BeAFLAcYB + ggE6AbUBcQFYAbEBgAGXAcMBqwOsA5IDrwO+A3ED+AwAA/YDdwOWA3EDegOmAwAD+wHcAckBswHsAdwB + ywHHAbMBmgHOAcQBuQwAAeUB3gHXAccBsAGXAc4BvAGmAb4BpQGIA/8GAAP7A+0D9APnA+UMAAPtA+cD + 6gPjA/8GAAH6AvsBXgHMAY8BcgHSAZ0BQgHDAXwBqAHJAbYMAAHDAeMB0QFCAcMBfAFOAccBhQE+AbcB + cwP/BgAD+wOjA78DiAOyDAAD0QOFA5cDdAP/BgAB8QHvAewB2QHEAa0B7wHfAc4B3wHNAbsBtgGhAYUB + zgHEAbkC+QH4A/oB1AHJAboBygGwAZgB1QHFAbIB0wHCAa4BvgGiAYcBzwHHAbwGAAP0A+0D9QPwA+ED + 5QP6A/sD6APmA+0D7APjA+YGAAHlAfEB6gFZAcoBjQF3AdQBoQFjAc4BkwE8AbEBcAGoAckBtgH4AfkB + +AH5AvoBmgHRAbMBRwHEAX8BWAHKAYsBVAHJAYkBPAG2AXQBpQHMAbcGAAPqA5sDwgOuA3EDsgP4A/kD + sQOGA6UDoAN2A7UGAAHWAcYBsgHQAbgBnQHbAcUBsAHyAeIB0gHgAc8BvAHHAbMBmgG6AaEBhQG7AaEB + hQHLAbUBnAHNAbkBpQHTAb8BqwHJAbIBlwG8AaEBhgGpAY8BdAYAA+gD6QPsA/YD8APnBuED6APqA+wD + 5wPjA90GAAF7AdEBoQFJAcUBgQFdAcsBjgF7AdUBpAFkAc4BlAFCAcMBfAE8AbIBcAE8AbQBcwFGAcQB + fwFMAcYBgwFUAckBiQFCAcMBfAE6AbUBcQE3AaEBZgYAA6MDigOgA8cDrwOIA3EDcwOKA5cDnQOEA3MD + YgYAAfMB8QHvAfAB7QHqAfEB7gHrAeIBzgG6Ae4B3wHNAewB3AHLAewB2wHKAecB1gHDAd4BzAG2AdUB + xAGtAcwBtQGaAegB4gHcAfMB8QHvAfIB8QHwBgAD9QPyA/MD8AP1BvQD8gPvA+wD6APvBvUGAAHqAfMB + 7gHhAe8B5wHjAfAB6AFkAc4BlAF1AdMBnwFyAdIBnQFyAdIBnQFsAdABmQFgAc0BkQFVAckBiQFIAcQB + gQHMAeYB1wHrAfIB7gHtAfIB7wYAA+4D6APpA6wDwAO/A74DtgOnA50DhwPXBu4MAAH0AfMB8QHVAcAB + pwHZAcMBqgHcAckBswHmAdEBvQHjAc0BtwHIAbABlQHGAa4BlAG+AagBjwHvAewB6RIAA/YD6wPsA+0D + 8QPwA+cD5gPkA/MSAAHtAfQB8AFSAcgBhwFXAckBiQFeAcwBjwFoAc8BlgFjAc4BkwFCAcIBfQFAAcIB + fAE8AbsBdQHiAe4B5xIAA/ADlQOYA6MDrwOnBoIDfQPnEgAB9QH0AfIB0AG9AaQB4AHWAcwD+wHPAbgB + ogHLAbQBmQH3AfYB9QHpAeQB3gHGAbMBnQH0AfMB8hIAA/YD6QPrA/sD5wPoA/gD7wPlA/YSAAHuAfUB + 8QFbAckBjQGrAd0BwgH6AvsBVwHHAYoBRQHEAX4B8gH2AfQBzgHnAdoBXQHCAYoB7wH0AfESAAPxA5ID + xAP7A5IDhgP0A9kDjgPxFQAB/QL8A/4DAAHXAckBuAHNAbkBoiEAA/0D/gMAA+kD5yEAA/wD/gMAAYoB + 0wGrAV4ByQGOIQAD/AP+AwADrAOSFQABQgFNAT4HAAE+AwABKAMAAUADAAEgAwABAQEAAQEGAAEBFgAD + /4EAAf4BbwH+AW8B/gFvAf4BbwHgAQcB4AEHAeABBwHgAQcB4AEHAeABBwHgAQcB4AEHAYABAAGAAQAB + gAEAAYABAAGAAQABgAEAAYABAAGAAQABgAEAAYABAAGAAQABgAEAAYMBwQGDAcEBgwHBAYMBwQEDAcAB + AwHAAQMBwAEDAcABAwHAAQMBwAEDAcABAwHAAYMBwQGDAcEBgwHBAYMBwQGAAQEBgAEBAYABAQGAAQEB + gAEBAYABAQGAAQEBgAEBAYABAQGAAQEBgAEBAYABAQHgAQcB4AEHAeABBwHgAQcB4AEHAeABBwHgAQcB + 4AEHAfIBfwHyAX8B8gF/AfIBfws= + + + + True + + + 217, 17 + + + True + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAAANklEQVQ4T6XIsREAIAADIfdf + Oi5A4Z8FDWfbF2bBLJgFs2AWzIJZMAtmwSyYBbNgFsyC+W7nAsWt/R/ojsvuAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAKzSURBVDhPrZJJTBNhGIbnoCHehHgwJsREOGiILYsxBBE1 + YPCIshVjAInRYliCW0BpFcUom1BRWhYRkB0UgxGNZWdmqgW0hZIuyAgUhTCF0FJEBXltYTwJXvRNvtv3 + PHm/Pz/x32KId3Vgzrt/UYW4sMqw3SnKcDdnMspvkIoJYGkB/zi3tnFWcry3WNP80RPqjDp/x6dUuGe5 + vvoejF0NIE/56CkBz4NbXT8tx1wdFCd2zubv24wsn+0r43V5oCvvol16FcMvikFH+mopwZ6/SzQCl5Le + EB4MVdmgqjKglVeAUTShp/Qm9M9lUMQcGqKCN5CQAo8dVJBbv7YyC3RNJjSvH8MyOQTzhBofu2pBVqRD + 1yQFHXNY0xPmxuewtdjv6wrhyXXVOau17fDCtB6LM8NYmBrEHEPDIC9bk9ia0KcPasmTfHcOtwmi/HSG + 2lxQFbehb32CpTkGPy2jq/D8eC8Wx0hYDXKMyIvRXZoGQ3MRyGg/LYcThErIC+7MjZseVzZDp9Ui+kwC + jgSGQtneBPNYHzyDkrHr6AVkZmTBRBahsygVqnO8SA4niIHYvY7dkmhm5eskhrQGxF2+gwMBEehoLoPF + JvCKKMDWABlE6YVYVpWAKk2EJsnbicMJoqPw7LYOqZD5YR7D1OcJSPJlSLwkxoDtD3wz0sgrLgCx/wGu + iB9iqa8AdGkC7AyH/xbEMlbbq3+fGQGso8ACA4vhDUy6Nggu3gLBlyAhJQ/LvfdBP1pPIBMy88b3MH+i + MatrhUndDFN/PYzqdhBeeSB42YhPzsaSXbBeg06ZcNQy+hbm4S7MDr2C6cMzsO8qMaFuw6bAMhC+5Ui8 + LsWyUvKngK5LciKrk/vpxhss3Shm6QbR2tSnslSDmG0pF7Evy0RsW2Uqq6i/xpI1Kayd4fB/CUH8AppD + 2GmutIMCAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGgSURBVDhPrZPLSsNAFIb7BoKP4Upw5UoQBHfmMrG1olCa + pFoExY2KiHcRERFEwYUKglSQesFeQK2rFkFr0Y26MRAKpa2+QS+/MzGpaS114wdhQv7/nDknZ8bx7xDi + a+FFeYvnFU2QFHCcRxdEOcQTmTctjWHB4UgM2Wwe5XIZ+fwnko/PWF3bhiAqJzRRp2mtD0/U7oWlTbAK + Bj1jYO/vmo5SqYR44gG9fcPgiNpu2uvDkrCVEG+zIMkqcfqQuEuiWCwidhsHJ8qHhtEOLX2H9cxW81MF + nni7XP1+5PIfKBQKmJlbR1UrVnAul0O9JJa+fxAwPJehqx+fPdh6apPU6nZfY9Gk4SaWGDwN09FlsUfL + rIg2LB/z/NI5SW4bHZ9FJpPBy+sbnG4//Unfk7BjJalNbsBGEzwLIZ1OIxK9AXGqdCdZlSS1iel/HiB2 + OCTXEM4vItB1nc79HpPTK3APjBiHamJquXp09eCI0sGJyvH84gat4hqp1BM0TUMymcJRIEhLV3ZNa2ME + 4nXSCxQ1LhLrmVbAgnskudW0/BcOxxdQeE7WHAMG/AAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFcSURBVDhP3VFNK0RhFL4/wNbM3PdcCgsfsbHDgkJKWPgD + ilJGNN73XEs/gbKUmvITuPc9d5iwYKfZyULZ26BkhTjnnXs1TWTNqafOx/M895z3ev84FsrwigQfvyGl + 1yNM1IyO4cQNrUKdqGFj1awmuGgWZnDC9Wouz8U1xnATkj+oE78HLVyWKPeAlH9EUkOa1FyzWOAxeVIS + JuxtRoVeERhS51zviLlsIHNjYRltW1ejWOChDdbqhEIfRoVbE0PZbXXoP3G/ygZFNyeYZ4xlwgzC9fAI + 7rmomUrQL01TyXekPUfSVo3zSSVXW3Ug75PNnEEpau+Uglff5XsnOH9D8reZuBJamOa6JvPQqkXhF89a + W9jw+MtAIiTVjRE88+AKY3/E5fKVGO74jC3hbMTBAPf2XT+FEzcGb7BqrH/KWNIUTLk34LX5V740Cn80 + yGKU4P07QTNS+t8Nz/sEkToIpLSWKNoAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEgSURBVDhP3Y/PKwRhHIf3f5g/wMWUlIuDUk5y5MCB3Dk4 + 7EUbBwdXJ3EXsksjidlk2x27NrXt5kdjlTQXbSFK2iaGaX7s491Zjppx5FNP7/et9/n0fmP/PFwu8JGd + 5OsaLdxpNIyVQPL1GcyDwWDmVsEx1sLLGvdHeLtduKVh/GIPTlbGPRvF3mmjXm0Vh8a9SEBGAl1gCMoS + j2p/uOyX5/AK4/i5bqgI8UrQPFUJO9mOr43gHk/9XOToy9QLCd4O+yAvxCb7gg0JK9WJqcWxTubDf+Kd + x0ERYkqwLliVeE8PRNufWhpnUxY7j2Fu92IlO3jOT+AqMk+lxfAS+6HI6/VW8NA5neVlb6g11zLcVNRo + v/gO1SXM3PTvpL+WWOwT04jC5H73kgIAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFtSURBVDhP3ZJPSwJBGIfd2ZnddcWLiKC76sKgIHryQ/QZ + +h5FlhJGB79HBF09RIga5Z901xVTSKxYzEw2EIICDx6nKYYg1uxcD7yX5/3NvDPMuP4ZY4yXs1jMHicS + h0x98ZRIFKYYzx8jkSVTTugG9nM8TnqqagxTqfyHI/k8mCSTB1Y02p1gTMaKYn+GVzGjk/uK0u6EQsTU + tKtxOp29CYc3hsFg26LOUpTmNBp1nO4btxhnTZ+v8aBpbyO/v0vLvA+FFnc+X32iKLssth5LVbevvd5u + SxCIiRAZeDx9KxDYYu3fGcjyniFJvZYoEp2WIYr9oSxnWHs9uiTtVwAwmhAumqLYaQhC+5LnX8oANHqS + lGOx1egIFejiToXjSJnjLnQIM20Id4ocVz0CgJwAoPfc7gKLO6kiNK/wPCkBUK9BmGXaVROEXJHnR8e0 + 16AZpp2UIFyeQWifI+R4qlMANul1XusI/fyR/iIu1ztb44EJFA1Z/gAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVDhPrZPNSwJRFMXvP9auqH27Fv0HQQRhFC00LCIk + RRRMWiguhJCiheAHagqpJOIXD4wyRgUNdYwCBY1O7zk65Bhk0YEfc2d499zDHR79j84+lskB/ArRo4p/ + cGTmZ8E3NlE1cTW25sPSnzVgjE1RLDJkswx3dwzJJEMiwRCNMgSDDH4/mzXQqlqV4Xbfwum8QanUQbMJ + 1GpApQKUy+PEqjQG/f4ALleST39BLNaE2RyAJA3mN7i+ziKdlhEIVHn9gHi8hlyujtdXoNtVkswYDIcK + 3W4P5+cphEJ1XF09wOtlKBSeQVbiy+OYCO32Nwa9noLPl0I4XMXlZZk/n5DPN5DJ1ECnBEt/HXRMaLUA + Y1ZjIOIJrNYgb76Hx1PgsRvqVDohmN7WQAe81nP2Oaq4QaejYDD4eOwibLY4IpHSqFlMFs2H7VXsSSvY + qSyBdjQG4jcJ9PoL6HQe2O0hyPI76IgfNCpTRTPt8nqbs6kxEJv9iiQphrKsJBORdY+LoC1Co6HdwQ+X + aXR4MnWDlPepy/RnEX0CXRRDb0PokG0AAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHsSURBVDhPrZPfS1NhGMd33020ftyIpGAZbXVRLQtC6ia6 + 8R+oCd20uohgd104ZRiGMDMQzF/F7MfVjjBLs7PsWLPNk0PLHV7ZnNY2gtEohIqFQZ/OWWuwI8GKvvCF + l5f3+3me9+F9Lf9Hgz9OWwbgr2xkytI3BmLV+4RUgpT1m3otX51vFjYDhBAVjscFCwuC+XlBNCoIhwWK + IpBlweSk2AwwK5P5xOhohKGh52jaR3I5yGZhbQ0SiVLHZZkAhcKGHp7Tq68zM5Ojt/cJ6fRG9QBZjuuB + r8RiHxgfTyFJCUZGIn8G1D2A9afThE+eKlaPSgrywUO8C4b0e6fx+1/T0RHU5/KZVAqWl02Aqyq8qN0J + l48RafPy0HFUX+8n1NiIqmbp63uJz6fQ36+wsmIM3AS4FIYxmx3amlltroHz+wjXb0OdeMXwsEpXV4jO + zse43f5i+5pmArRMwdupZyj1W+GCnS9napi+eIVAYE4P3cXrncDjCeJ09hSrLy2ZAIPtd4g0WMFlA2cD + nN2NXGvl/ZtVkslvdHc/orX1Bi7XrWJ4cdEEuL/nALhtaId3MHukDlp2wTl93eQgn/81dWNwRutGOKY/ + 5wrAbNPxjLR9Cz7PbdrV79yzOwjstXF9LInVXzpsdsVn+mdZLD8BfTZF0/R8bMwAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIbSURBVDhPtdBfaFJRHAdwXzMW1EuswRa1go2psBg97WFv + 4WQ6VnmZ7mEb6KhIyUww/2wKUTCFa21sqxWOkJYSERh7qOGF6aU1cdBLM2okXMk5piR48w9+03FAorX2 + UB84L+d8v7/DOYL/RrnSenpkpXtdyYjS/UxzI9k+GM1ao3DgbfsXP2yYSA/jwptTi+ToYAaW2ziaH8IM + RvG4dBv9EUml53WTlBzv7/Jye9KRVqA2wJUbxEx5FDe5QXQ9a9oULxw/TGJ/NhSTsBQjLlsSvbiXuVQd + QmG2eBU9TAdED4/Ok9j+xC8azsqX2uBM9WFyZwT2rT7Yv1PoXDxRPrMglJDY72iaPjI+7hyeomffSZda + MPGtF/TOFbTOHULXg5NoudNQqq69/yIQCDyPxWI8wzCYnnuEzifHoHrfgbvZi2ieF+Dzp81KkktWgsEg + b7fbX5Jand/vL/M8D5ZlYTAYcGPsFq45x9A9KUJ4dQ1b29vIZrMIhULQarUVUqvz+Xx8PB5HIpFAsVgE + G2ExdX8avqc+bHzcQCQSgcPhgMlkgkqlKpFancvlWo1Go0ilUuA4DplMBoVCAbWhHo9nt2i1WqHX66FU + Kj+Q2q90Op3e6/X+yOVyyOfzqDEajbDZbLBYLFCr1TxFUddJfG8ymUxYvS0YDocrtQFms3n3zdVbX2k0 + GiGJ/Z1UKj3vdrs5uVz+VaFQnCPb/5pA8BMNdy5aS5fTsQAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIkSURBVDhPtdJdaJJRGAfw142IWd1FrUW7aNFF1GoF1cU2 + 6iIqs2mL0KUE3Sh2kYaJbfmFg1aQBkZrtYikkppWFtnHRqCUChviRUSbEDWHLmdTwfCdluefjgMjtnIE + /W6f//M853AO818cG2Cqdw82pNoCTWzr64YPmx+veUpLi2RkqvZ6Nxat3zvwgHRiy6NVhFYq2/Bi5ZOd + Q/Ufm4fWF3um23Ezp0Dt3RrQcmXr3Ctcl1MS0vNVREzxw7gyfYJU32BQ1cdIl/QzO2jsrziNr1aP66MH + oIsehHnyCLk0JSbdk22kabAuWXOfc4Hm/ox7h3P96PCm4rnP+6Cf4OFiqp1sfVlbXHqLcTNgODS2MJOp + ++Tou099h563FDon9sAY34965zLScrv5i1Vj3U5j87lcroFwOMz6fD70Xu1Fx9njaH1bh7UPlxPdm/Ng + v82QeCxOPB4PazQa3bRtjtPp/MmyLILBINRqNVSnzmCbrRGKfgVG/CNITiWRyWTg9Xohl8vnP6vD4WAj + kQii0SgKhQKCgSCulU7iuOfA2OgYAoEAzGYztFotJBLJD9o2x2KxDIdCISQSCcRiMaTTaeTzeZSH2my2 + 2Ua9Xg+VSgWRSPSetv1OqVSq7Hb7TDabRS6XQ5lGo4HBYIBOp4NUKmXFYvFpGl8Yn8/nlrZ5/H4/KQ/o + 6uqavXNp6zOZTMalscp4PN4uq9UaEwgE40KhcFE/8B8wzC+qySa+SK8LKwAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAJuSURBVDhPxY9NTNIBGIdta262TnXo2qpLh07ZlgfdtNVa + oumCFBlK+TXzE6Wc6fyHM2I6SKcYGpVkiqCZIhPTVAhCWyo5DaVIExIlnOlwoM38ZfTva6TXnvPzvPu9 + fv8fjnxSlSc3Ibf5DdhN48h+NIashlFkSIeR/uAl0iSDSK3TI1msRaKoH5eqepFQoQZTqEJcebvaj1BM + +OfIxtWyQSt2wvxpDRML6zDav6BcOQZ6WVsHjVD4e1ew5YaATOlIT6N+Bs4VNxzLbtg/e2Bd8mDa6cGo + xYF6RScKinnILuKDVSp9+iv+yfcjW3P7Hmrf/Y4X12Cyu9DVO4Bb3ELkpKfhXDgF8fGssq1k14/yD9gC + Q0DSHY1G0jfpjb2zZ50wa+Ww9YmhEeci4nQwAk+GPKNQKHvI7G+oW0cSKrt1Nd0T3p9HpmbxoqUCZpUQ + WnEWChjBuBBFaSMIYjeZ+EKrVuxlCTvxcWUDPcYPkFXmryvLE6Hg0nHzcvAqIzqSSqrbE8NrgXV5A+3G + BXCKuHMCVuC6MCUUV84ctkQxmftJbXuoJU2wu76ixbgI6g3JJDuBZuWE7sN1etBG9u0ngyEXM0NJ9d9E + F0sx79rEXd0YiHbDan2rZrOxNAlVCg3uDblQKjd6jhwPo5G6L5GFErx1uMFTPge/Ywb619MwOQHJkBuP + XzlQO2ADi2iwkLov4dfEw2evVg/HEnVLJa0mqPQWSLVzqBmw477GCkHnFDi1WpD69hw8GhQSlyfQiZoN + EPXaUKtfgqh/Hnzle6TwZG5S25mwiNgDMan552MzuI0MTpkuuUhkZuTwDYeOnTj1DdeVozI6609oAAAA + AElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAANWSURBVDhPdZNbTNJRHMf/bT70mFuvvbTWbd2xrYeeaj1X + W1msNYoUu9DNmgKCqEiW/iMuEmX8ESkFQf54QQVFILzQX1A0DStJMv0HZpartMzi1x+lFVt9trOzc/b7 + nv3O5+wgv5FbiFN38G6mDO9JV9YTgJq6d97Suy8Xaa20RMm/AYAV8VnbPqizeEehPTD5wTkUAU1r/4wC + 7wJRVVvmUuH/kNb3Hlc19VW3+McH/GMzYCVCUOsaBnNnEAzOQZCavR6Osr7yXGnNtkQkGYm5Z5ep80Ws + d/Q9KEyPFxn5KtFhOpN3TYi+VVaZobyyFq4L0XnWJe7+RCQZKU4cdQTImWZiFBh8lSiDcTIzT/bopdU/ + MRaamlsMkp/ARox8F4rR4JGDB7cmYn9QNhAQv7OBajtHKM7hopphgTMmf/055n07+20uGJ2D3jezgPdN + w0VOoeumzp6TJLbU2LUDs/V9MHuCcIUjHOPVjZsE7hhvZOrHE4t/esHon4X6wOef9tA8yGs9iyKFNlls + aY3rYtx2XBhPhEKxLRoW4OFBzEXOtzydhcDEAvjCX8D35hOona9BLLmbLLbogZUm1jnOyMzex4VlClA5 + SUAbn0Hb0AyEp7+BY5CkXiQ02TAQcaOWYPQ6XwxG11PgqxrenSvB1ib6QBCO0qI/yeZ9lOPEpMk7Drgv + uuijXsbQPhAanopxG8aBJVDU2i/k3+7X2XyQj7XaWSJsbyKOIOwS3XZBEcpSyBVQ1T4EjqEomDwjcKfO + ndcRie273zFWTqPRyou1djlmfQKFGhtkFVe+SsQRJIORscfaZF8ok6pi67bQcjV1LV87fM+hookYKZBg + 1Vs3b5SlZ/J2laqbByrMbuDKDZ3HstE1S2HmCeYGS11TJPwqDKmpqTKOSPLwLL8MsrL5kHVNAMycm/4b + NS7pLb2rX4l3g8zohvNi9cKhCyUshMFgrHpYpQ+QEySkpaV5qPM2/S3WRAnT2fygptrGGnvgnqULuHct + nfRcWe7hSzd2I1iF1hEhI0Cn0yep8AFqLH2uOHGxeapGUqhuthVoWoEnNzZflegjZwoxTqIEQap1euBx + uZCSksKmliuXd5eJi2WLKzeybxu2U8bD2Wj16tNCbPMxjmL9cgWC/AIp/hYHsS2RwgAAAABJRU5ErkJg + gg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGcSURBVDhPrZPpSwJRFMXn/y2ktGy3KNM00xapHn0IogKF + hIo2Iykpoxr6EFi0QUGRUkZ7aObJM+Pw1IIW+sHDYZhz7rn3PpV/w7ecUgdjafijz+iP3KM3nIJ3PgnP + zCXcoXN0BU/hmDyEfSwOkzWoFmQ6A6sPajzxjp+ye3RbasLKZPEEWD0DNi/yH10B+9fAUQo4vQXO7+RJ + p9OwDW6hIFcUxiYWh8DOJWDzCLT1CE3o6hNIPAE3L4DXL7RDg5aBmDRgz6TOJbCXBDq8As5eXUjBYz7g + 6xvgHxLayWQyaPJFpQEHRozYjEnx3asufCsbTzabRUN3RBpw2oSxO316ZYpZzUAI/Zm/uVwOdc6wNOCq + CKOzZ/bLyoaIFBuQWvuCNOCeCYfG6uy5PHY5lrZZaeAM5PeXh71zaEb14qrlCaqaQtLAPn6gvfyNgcka + kAbto3vaSxoY/X9HpXlCGrSO7Kq8nrwgPNwzV8Vpf8X65jEqqidK/w+tw9sqr2dz/wYavWuod6/A6lhC + TfsczLZpVDVOabFZ+ZP47yjKB3q7lEPomoQ8AAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAKqSURBVDhPY8AGVFQY2DUdxM1NQqQiQFjDRcxCRoaBEyqN + H6jZi9pET9LfVL7P9m3dEdf/VYfs/mevMX8f0KixVdtZ3AGqDDuwTZAraT8R9H/yueT/7ScC/zcc9fhf + e9gZbAgIZ60y+28eKVsNVY4KLCJlUkAau0+F/2886vm//ojb/+pDDv+BLvlfstP6f8Emy/85a83BhhgF + SWVCtUGAvKmoRMVBm899p6P/Nx3zBtuKrDlvg8X/nDXm/ws2W/5PWWD8H+jFH3Im/EpQ7QwMdinyTRPP + JoA1Vx60BWsGaYRpzlhm+v/Sq33/v//+DHZJ4mzD/1Yxcu0M9gwsDFpaojzRk/QO9J6O+l+x3/b/qeeb + /r/8+gDsiqyVZmAnX3l98D8I3Hl/5n/8DMP/YZ06/93yVY4oW4iqMCibCMomzTG8BAo0kI0HHi0BK371 + 9SE44C6/PgDm33p36n/MJP3/wS1aYAM8S1Wuq1oImYH9HzlB7yzI+SAXgGzcfGfS/6+/Pvx/8+3x/y+/ + 3v+/+uYw2O8h7dpgHNal89+7TPWSsq2IEQPIH865ystAcV68wxpsQPI8o/8rrjf+f/r51v8zz7f+z1hu + CrYVpBHkgqgJev/t0xRXShrziIADUd1O2A8URaAAAvk7daHx/6S5Rv/nXioEi4E0RvTogm0PbNQEG6Dp + KBIG1gwFTA6pitthIQ5yLiikQX6O6tf7H9EL1Nym/T+gAaLZPllhLzgGkIGCoYC8a77yVZALQAbETTOA + aAbaDHJ2ULMW2ED3QtU7cnr8ilBtqAAUI+bh0suA/v2ZMNMQHGVxUw3AGkPatH5bRsusAlkEVY4TMCqY + Ctjpeog3mYXLLAZhPU/xFnljflBGYoIoIQJISkpyyRoKS8noC0mL64lzQ4XRAAMDAPInffz2odmOAAAA + AElFTkSuQmCC + + + + True + + + + iVBORw0KGgoAAAANSUhEUgAAAA8AAAAJCAYAAADtj3ZXAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAAA50lEQVQoU3XRvSuGURgHYBY2 + mUxvlMl/oRT1TiaTTFZ5SmHgjSxCIYXB4GMRJXaSQcmuDAwYRFE+BhJx3TyPPG8Zrjqdc36n+75PRZIk + f9XRwhJnnPL5nyxUSSezbKX6GWCEPcrDTxGsZ4oTxuhmgmV2mKbICh/kwkPpZhvrbLDIIA3ExXi0Nl3n + wq280MM2vXQRFy6Yp4NdorpD4uw563mcB9pZ44A5hpnhkk0KNHHHb7iKSW4pscoVx8RjzTQSVR3xynfZ + mWqihRjUAjG4PuIH9jknQrmey9UwyjU3PJJN+Z23H8n9FxjlApHDfpvMAAAAAElFTkSuQmCC + + + + True + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG + YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9 + 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw + bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc + VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9 + c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32 + Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo + mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+ + kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D + TgDQASA1MVpwzwAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG + YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9 + 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw + bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc + VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9 + c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32 + Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo + mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+ + kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D + TgDQASA1MVpwzwAAAABJRU5ErkJggg== + + + + 17, 17 + + + True + + + True + + + True + + + True + + + True + \ No newline at end of file diff --git a/Nspector/nspector/Reference.xml b/Nspector/nspector/Reference.xml index 2ad36da..18a88ad 100644 --- a/Nspector/nspector/Reference.xml +++ b/Nspector/nspector/Reference.xml @@ -4971,5 +4971,17 @@ + + DLSS/DLAA: Force DLAA + 0x10E41DF4 + + 8 - Extra + + + DLSS/DLAA: Override Scale Ratio + 0x10E41DF5 + + 8 - Extra + diff --git a/NvAPIWrapper/Display/Display.cs b/NvAPIWrapper/Display/Display.cs index 4da92f7..02aab4a 100644 --- a/NvAPIWrapper/Display/Display.cs +++ b/NvAPIWrapper/Display/Display.cs @@ -1,12 +1,12 @@ -using System; -using System.Linq; -using NvAPIWrapper.GPU; +using NvAPIWrapper.GPU; using NvAPIWrapper.Native; using NvAPIWrapper.Native.Display; using NvAPIWrapper.Native.Display.Structures; using NvAPIWrapper.Native.Exceptions; using NvAPIWrapper.Native.GPU; using NvAPIWrapper.Native.Interfaces.Display; +using System; +using System.Linq; namespace NvAPIWrapper.Display { @@ -41,12 +41,25 @@ namespace NvAPIWrapper.Display get => new DVCInformation(Handle); } + + private DisplayDevice _displayDevice; + /// /// Gets corresponding DisplayDevice based on display name /// public DisplayDevice DisplayDevice { - get => new DisplayDevice(Name); + get + { + + if (_displayDevice == null) + { + _displayDevice = new DisplayDevice(Name); + + } + + return _displayDevice; + } } /// @@ -189,7 +202,7 @@ namespace NvAPIWrapper.Display return false; } - return Equals((Display) obj); + return Equals((Display)obj); } /// diff --git a/Shared/Common/AppContext.cs b/Shared/Common/GlobalContext.cs similarity index 76% rename from Shared/Common/AppContext.cs rename to Shared/Common/GlobalContext.cs index 27a5447..f7fcb0c 100644 --- a/Shared/Common/AppContext.cs +++ b/Shared/Common/GlobalContext.cs @@ -6,9 +6,9 @@ using System.ComponentModel; namespace ColorControl.Shared.Common { - public class AppContext + public class GlobalContext { - public static AppContext CurrentContext { get; private set; } + public static GlobalContext CurrentContext { get; private set; } public Config Config { get; private set; } @@ -19,7 +19,7 @@ namespace ColorControl.Shared.Common public DateTime StartTime { get; private set; } = DateTime.Now; public string MutexId { get; private set; } - public AppContext(Config config, StartUpParams startUpParams, string dataPath, LoggingRule loggingRule, string mutexId = null) + public GlobalContext(Config config, StartUpParams startUpParams, string dataPath, LoggingRule loggingRule, string mutexId = null) { Config = config; StartUpParams = startUpParams; @@ -30,11 +30,6 @@ namespace ColorControl.Shared.Common CurrentContext = this; } - public bool IsServiceRunning() - { - return Utils.IsServiceRunning(); - } - public void SetLogLevel(LogLevel logLevel) { Config.LogLevel = logLevel.ToString(); diff --git a/Shared/Common/PipeUtils.cs b/Shared/Common/PipeUtils.cs index 7a59201..b75ef94 100644 --- a/Shared/Common/PipeUtils.cs +++ b/Shared/Common/PipeUtils.cs @@ -7,11 +7,14 @@ namespace ColorControl.Shared.Common { public static class PipeUtils { + public const string ServicePipe = "servicepipe"; + public const string ElevatedPipe = "elevatedpipe"; + private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); - public static string SendMessage(string message, int timeout = 2000) + public static string SendMessage(string message, int timeout = 2000, string pipeName = ServicePipe) { - var pipeClient = new NamedPipeClientStream(".", "testpipe", PipeDirection.InOut, PipeOptions.None, TokenImpersonationLevel.None); + var pipeClient = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut, PipeOptions.None, TokenImpersonationLevel.None); try { pipeClient.Connect(timeout); @@ -61,37 +64,24 @@ namespace ColorControl.Shared.Common return SendMessage(message); } - public static bool? SendRpcMessage(string command) + public static T SendRpcMessage(SvcRpcMessage message, int timeout = 2000, string pipeName = ServicePipe) { - var message = new SvcMessage { MessageType = SvcMessageType.ExecuteRpc, Data = command }; - var messageJson = JsonConvert.SerializeObject(message); - var resultJson = SendMessage(messageJson); + var resultJson = SendMessage(messageJson, timeout, pipeName); if (resultJson == null) { - return null; + return default; } var resultMessage = JsonConvert.DeserializeObject(resultJson); - return resultMessage.Result; - } - - public static T SendRpcMessage(SvcRpcMessage message, int timeout = 2000) where T : class - { - var messageJson = JsonConvert.SerializeObject(message); - - var resultJson = SendMessage(messageJson, timeout); - - if (resultJson == null) + if (resultMessage?.Data == null) { - return null; + return default; } - var resultMessage = JsonConvert.DeserializeObject(resultJson); - var result = JsonConvert.DeserializeObject(resultMessage.Data); return result; diff --git a/Shared/Common/ProcessExtensions.cs b/Shared/Common/ProcessExtensions.cs index 70bab04..96b152d 100644 --- a/Shared/Common/ProcessExtensions.cs +++ b/Shared/Common/ProcessExtensions.cs @@ -1,4 +1,5 @@ -using System.ComponentModel; +using ColorControl.Shared.Services; +using System.ComponentModel; using System.Diagnostics; using System.Runtime.InteropServices; using static ColorControl.Shared.Native.WinApi; @@ -46,7 +47,7 @@ namespace ColorControl.Shared.Common public static Process Parent(this Process process, IEnumerable processes = null) { - if (Utils.IsAdministrator()) + if (WinApiService.IsAdministratorStatic()) { try { diff --git a/Shared/Common/Utils.cs b/Shared/Common/Utils.cs index 1de6909..8a33cc3 100644 --- a/Shared/Common/Utils.cs +++ b/Shared/Common/Utils.cs @@ -1,7 +1,4 @@ -using ColorControl.Shared.Contracts; -using ColorControl.Shared.Native; -using Microsoft.Win32; -using Microsoft.Win32.TaskScheduler; +using ColorControl.Shared.Native; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using NStandard; @@ -14,10 +11,7 @@ using System.IO.Compression; using System.Net.Http; using System.Net.NetworkInformation; using System.Reflection; -using System.Runtime.InteropServices; using System.Security.Cryptography; -using System.Security.Principal; -using System.ServiceProcess; using System.Text; using Windows.Devices.Enumeration; using Windows.Devices.Enumeration.Pnp; @@ -36,7 +30,6 @@ namespace ColorControl.Shared.Common public static Guid GUID_CONSOLE_DISPLAY_STATE = Guid.Parse("6FE69556-704A-47A0-8F24-C28D936FDA47"); public static bool ConsoleOpened { get; private set; } - public static bool UseDedicatedElevatedProcess = false; private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); @@ -111,168 +104,6 @@ The best and suggested method to provide this is via a Windows Service. Only whe return path; } - private static bool? _IsAdministrator; - - public static bool IsAdministrator() - { - if (_IsAdministrator.HasValue) - { - return _IsAdministrator.Value; - } - - var identity = WindowsIdentity.GetCurrent(); - var principal = new WindowsPrincipal(identity); - _IsAdministrator = principal.IsInRole(WindowsBuiltInRole.Administrator); - - return _IsAdministrator.Value; - } - - public static int ExecuteElevated(string args, bool wait = true, bool skipDedicated = false, bool skipService = false) - { - if (!skipService && IsServiceRunning()) - { - var result = PipeUtils.SendRpcMessage(args); - - if (result.HasValue) - { - return 0; - } - } - - if (UseDedicatedElevatedProcess && !skipDedicated) - { - CheckElevatedProcess(); - - WinApi.CopyData.Send(ElevatedProcessWindowHandle, 1, args); - - return 0; - } - - var fileName = Process.GetCurrentProcess().MainModule.FileName; - - var info = new ProcessStartInfo(fileName, args) - { - Verb = "runas", // indicates to elevate privileges - UseShellExecute = true, - }; - - var process = new Process - { - EnableRaisingEvents = true, // enable WaitForExit() - StartInfo = info - }; - try - { - process.Start(); - - if (wait) - { - process.WaitForExit(); // sleep calling process thread until evoked process exit - } - - return process.Id; - } - catch (Exception e) - { - Logger.Error("ExecuteElevated: " + e.Message); - } - return 0; - } - - private static nint ElevatedProcessWindowHandle = nint.Zero; - - public static void CheckElevatedProcess() - { - ElevatedProcessWindowHandle = NativeMethods.FindWindowW(null, "ElevatedForm"); - - if (ElevatedProcessWindowHandle == nint.Zero) - { - ExecuteElevated(StartUpParams.StartElevatedParam, false, true, true); - - var delay = 1000; - - while (delay >= 0) - { - Thread.Sleep(100); - - ElevatedProcessWindowHandle = NativeMethods.FindWindowW(null, "ElevatedForm"); - - if (ElevatedProcessWindowHandle != nint.Zero) - { - Thread.Sleep(500); - break; - } - - delay -= 100; - } - } - } - - public static bool IsChromeFixInstalled() - { - var key = Registry.ClassesRoot.OpenSubKey(@"ChromeHTML\shell\open\command"); - return key != null && key.GetValue(null).ToString().Contains("--disable-lcd-text"); - } - - public static bool InstallChromeFix(bool install, string applicationDataFolder) - { - var argument = "--disable-lcd-text"; - - var key = Registry.ClassesRoot.OpenSubKey(@"ChromeHTML\shell\open\command", true); - if (key != null) - { - var value = key.GetValue(null).ToString(); - value = value.Replace("chrome.exe\" " + argument + " --", "chrome.exe\" --"); - if (install) - { - value = value.Replace("chrome.exe\" --", "chrome.exe\" " + argument + " --"); - } - key.SetValue(null, value); - } - - var roamingFolder = applicationDataFolder ?? Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); - - UpdateShortcut(Path.Combine(roamingFolder, @"Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Google Chrome.lnk"), argument, !install); - UpdateShortcut(Path.Combine(roamingFolder, @"Microsoft\Internet Explorer\Quick Launch\Google Chrome.lnk"), argument, !install); - - var allUsersStartMenuFolder = Environment.GetFolderPath(Environment.SpecialFolder.CommonStartMenu); - UpdateShortcut(Path.Combine(allUsersStartMenuFolder, @"Programs\Google Chrome.lnk"), argument, !install); - - return true; - } - - public static bool IsChromeInstalled() - { - var key = Registry.ClassesRoot.OpenSubKey(@"ChromeHTML\shell\open\command"); - return key != null; - } - - public static bool UpdateShortcut(string path, string arguments, bool removeArguments = false) - { - if (File.Exists(path)) - { - IWshRuntimeLibrary.WshShell shell = new IWshRuntimeLibrary.WshShell(); - - IWshRuntimeLibrary.IWshShortcut shortcut = (IWshRuntimeLibrary.IWshShortcut)shell.CreateShortcut(path); - - shortcut.Arguments = shortcut.Arguments.Replace(arguments, ""); - if (!removeArguments) - { - if (!string.IsNullOrEmpty(shortcut.Arguments)) - { - shortcut.Arguments = shortcut.Arguments + " "; - } - shortcut.Arguments = shortcut.Arguments + arguments; - } - - // save it / create - shortcut.Save(); - - return true; - } - return false; - } - public static string[] GetDeviceProperty(PnpObject device, string propertyName) { object objValue; @@ -489,63 +320,6 @@ The best and suggested method to provide this is via a Windows Service. Only whe return list; } - public static void RegisterTask(string taskName, bool enabled, TaskRunLevel runLevel = TaskRunLevel.LUA) - { - if (!IsAdministrator()) - { - ExecuteElevated(enabled ? $"{StartUpParams.EnableAutoStartParam} {(int)runLevel}" : StartUpParams.DisableAutoStartParam, skipService: true); - return; - } - - var file = Process.GetCurrentProcess().MainModule.FileName; - var directory = Path.GetDirectoryName(file); - - try - { - using (TaskService ts = new TaskService()) - { - if (enabled) - { - var td = ts.NewTask(); - - td.RegistrationInfo.Description = "Start ColorControl"; - td.Principal.RunLevel = runLevel; - - td.Triggers.Add(new LogonTrigger { UserId = WindowsIdentity.GetCurrent().Name }); - - td.Actions.Add(new ExecAction(file, StartUpParams.RunningFromScheduledTaskParam, directory)); - - ts.RootFolder.RegisterTaskDefinition(taskName, td); - } - else - { - ts.RootFolder.DeleteTask(taskName, false); - } - } - } - catch (Exception e) - { - Logger.Error($"Could not create/delete task: {e.Message}"); - } - } - - public static bool TaskExists(string taskName) - { - using (TaskService ts = new TaskService()) - { - var task = ts.RootFolder.Tasks.FirstOrDefault(x => x.Name.Equals(taskName)); - - return task != null; - } - } - - public static void CheckWin32Error(string message) - { - var errorMessage = new Win32Exception(Marshal.GetLastWin32Error()).Message; - - throw new Exception($"{message}: {errorMessage}"); - } - public static bool OpenConsole() { if (ConsoleOpened) @@ -601,76 +375,6 @@ The best and suggested method to provide this is via a Windows Service. Only whe return null; } - public static Process StartProcess(string fileName, string arguments = null, bool hidden = false, bool wait = false, bool setWorkingDir = false, bool elevate = false, uint affinityMask = 0, uint priorityClass = 0) - { - var process = Process.Start(new ProcessStartInfo(fileName, arguments) - { - Verb = elevate ? "runas" : string.Empty, // indicates to elevate privileges - UseShellExecute = true, - WindowStyle = hidden ? ProcessWindowStyle.Hidden : ProcessWindowStyle.Normal, - WorkingDirectory = setWorkingDir ? Path.GetDirectoryName(fileName) : null - }); - - if (affinityMask > 0) - { - SetProcessAffinity(process.Id, affinityMask); - } - - if (priorityClass > 0 && priorityClass != NativeConstants.NORMAL_PRIORITY_CLASS) - { - SetProcessPriority(process.Id, priorityClass); - } - - if (wait) - { - process.WaitForExit(); - } - - return process; - } - - public static void SetProcessAffinity(int processId, uint affinityMask) - { - if (!IsAdministrator()) - { - ExecuteElevated($"{StartUpParams.SetProcessAffinityParam} {processId} {affinityMask}"); - - return; - } - - var hProcess = NativeMethods.OpenProcess(NativeConstants.PROCESS_ALL_ACCESS, false, (uint)processId); - - if (hProcess == nint.Zero) - { - CheckWin32Error($"Unable to set processor affinity on process {processId}"); - } - - NativeMethods.SetProcessAffinityMask(hProcess, affinityMask); - - //var AffinityMask = (long)process.ProcessorAffinity; - //AffinityMask &= 0x000F; // use only any of the first 4 available processors - //process.ProcessorAffinity = (IntPtr)AffinityMask; - } - - public static void SetProcessPriority(int processId, uint priorityClass) - { - if (!IsAdministrator()) - { - ExecuteElevated($"{StartUpParams.SetProcessPriorityParam} {processId} {priorityClass}"); - - return; - } - - var hProcess = NativeMethods.OpenProcess(NativeConstants.PROCESS_ALL_ACCESS, false, (uint)processId); - - if (hProcess == nint.Zero) - { - CheckWin32Error($"Unable to set process priority on process {processId}"); - } - - NativeMethods.SetPriorityClass(hProcess, priorityClass); - } - public static string GetResourceFile(string resourceName) { resourceName = "ColorControl.Resources." + resourceName; @@ -794,100 +498,6 @@ The best and suggested method to provide this is via a Windows Service. Only whe return str1.Trim().Replace(" ", string.Empty).Equals(str2.Trim().Replace(" ", string.Empty), StringComparison.OrdinalIgnoreCase); } - public static void StartService() - { - if (!IsAdministrator()) - { - ExecuteElevated(StartUpParams.StartServiceParam); - return; - } - - var controller = new ServiceController(SERVICE_NAME); - - if (controller.Status == ServiceControllerStatus.Stopped) - { - controller.Start(); - } - } - - public static void StopService() - { - if (!IsAdministrator()) - { - ExecuteElevated(StartUpParams.StopServiceParam); - return; - } - - var controller = new ServiceController(SERVICE_NAME); - - if (controller.Status == ServiceControllerStatus.Running) - { - controller.Stop(); - } - } - - public static bool IsServiceInstalled() - { - return GetServiceStatus() != 0; - } - - public static bool IsServiceRunning() - { - return GetServiceStatus() == ServiceControllerStatus.Running; - } - - public static ServiceControllerStatus GetServiceStatus() - { - var controller = new ServiceController(SERVICE_NAME); - - try - { - return controller.Status; - } - catch (Exception) - { - return 0; - } - } - - public static void InstallService() - { - if (!IsAdministrator()) - { - ExecuteElevated(StartUpParams.InstallServiceParam, skipService: true); - - return; - } - - - if (!IsServiceInstalled()) - { - StartProcess("sc.exe", @$"create ""{SERVICE_NAME}"" binpath=""{Process.GetCurrentProcess().MainModule.FileName}"" start=auto", wait: true); - StartProcess("sc.exe", @$"description ""{SERVICE_NAME}"" ""Executes tasks for Color Control that require elevation. If this service is stopped, functions like WOL might be impacted.""", wait: true); - } - - StartService(); - } - - public static void UninstallService() - { - if (!IsAdministrator()) - { - ExecuteElevated(StartUpParams.UninstallServiceParam, skipService: true); - - return; - } - - if (!IsServiceInstalled()) - { - return; - } - - StopService(); - - StartProcess("sc.exe", @$"delete ""{SERVICE_NAME}""", wait: true); - } - public static async Task PingHost(string nameOrAddress) { try diff --git a/Shared/Common/WOL.cs b/Shared/Common/WOL.cs deleted file mode 100644 index d5be2f0..0000000 --- a/Shared/Common/WOL.cs +++ /dev/null @@ -1,255 +0,0 @@ -using ColorControl.Shared.Contracts; -using NLog; -using System.Net; -using System.Net.NetworkInformation; -using System.Net.Sockets; -using Vanara.PInvoke; -using static Vanara.PInvoke.IpHlpApi; - -namespace ColorControl.Shared.Common -{ - public class WOL - { - private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - - private const string ArgumentExceptionInvalidMacAddressLength = "Invalid MAC address length."; - private const string ArgumentExceptionInvalidPasswordLength = "Invalid password length."; - private const int DefaultWolPort = 9; - - public static bool WakeFunction(string macAddress, string ipAddress = null) - { - return WakeFunctionToAllNics(macAddress, ipAddress); - } - - public static bool WakeFunctionCheckAdmin(string macAddress, string ipAddress = null) - { - if (Utils.IsAdministrator()) - { - return WakeFunction(macAddress, ipAddress); - } - - var result = PipeUtils.SendRpcMessage($"{StartUpParams.SendWakeOnLanParam} {macAddress} {ipAddress}"); - - // Execute local WOL anyway because pipe failed - if (!result.HasValue) - { - result = WakeFunction(macAddress, ipAddress); - } - - return result.Value; - } - - public static bool WakeFunctionToAllNics(string macAddress, string ipAddressString) - { - var result = false; - Logger.Debug($"Sending WOL packet to MAC-address {macAddress}"); - - try - { - var physicalAddress = PhysicalAddress.Parse(macAddress); - var addressBytes = physicalAddress.GetAddressBytes(); - var data = GetWolPacket(addressBytes); - var ipAddress = ipAddressString != null ? IPAddress.Parse(ipAddressString) : null; - - var interfaces = NetworkInterface.GetAllNetworkInterfaces(); - - foreach (var ni in interfaces) - { - if (ni.NetworkInterfaceType == NetworkInterfaceType.Loopback/* || ni.Name.Contains("VirtualBox") || ni.Name.Contains("vEthernet") || ni.Description.Contains("Virtual")*/) - { - continue; - } - Logger.Debug($"Found network: {ni.Name} ({ni.Description}), type: {ni.NetworkInterfaceType}"); - try - { - if (ni.SupportsMulticast && ni.GetIPProperties().GetIPv4Properties() == null) - { - continue; - } - - foreach (var uip in ni.GetIPProperties().UnicastAddresses) - { - if (uip.Address.ToString().StartsWith("169.254") || uip.Address.AddressFamily != AddressFamily.InterNetwork) - { - continue; - } - - Logger.Debug($"Broadcast WOL in network: {ni.Name} ({ni.Description}), local address: {uip.Address}, destination IP-address: {ipAddressString ?? "broadcast"}"); - - if (ipAddress != null && Utils.IsAdministrator()) - { - var localEP = new IPEndPoint(uip.Address, 0); - - SendWolToIpAddress(uip.Address, ipAddress, data, physicalAddress); - } - - BroadcastWol(uip.Address, IPAddress.Broadcast, data); - - var parts = uip.Address.ToString().Split(".").ToList(); - parts[3] = "0"; - var broadcastAddress = IPAddress.Parse(string.Join(".", parts)); - BroadcastWol(uip.Address, broadcastAddress, data); - - result = true; - } - } - catch (Exception ex) - { - Logger.Error($"WakeFunctionToAllNics: while sending to specific network: {ni.Name} ({ni.Description}): {ex.ToLogString()}"); - } - } - } - catch (Exception ex) - { - Logger.Error($"WakeFunctionToAllNics: {ex.ToLogString()}"); - } - - return result; - } - - /// is null. - /// The length of the array is not 6. - /// The length of the array is not 0 or 6. - private static byte[] GetWolPacket(byte[] macAddress, byte[] password = null) - { - if (macAddress == null) - throw new ArgumentNullException(nameof(macAddress)); - if (macAddress.Length != 6) - throw new ArgumentException(ArgumentExceptionInvalidMacAddressLength); - - password = password ?? new byte[0]; - if (password.Length != 0 && password.Length != 6) - throw new ArgumentException(ArgumentExceptionInvalidPasswordLength); - - var packet = new byte[17 * 6 + password.Length]; - - int offset, i; - for (offset = 0; offset < 6; ++offset) - packet[offset] = 0xFF; - - for (offset = 6; offset < 17 * 6; offset += 6) - for (i = 0; i < 6; ++i) - packet[i + offset] = macAddress[i]; - - if (password.Length > 0) - { - for (offset = 16 * 6 + 6; offset < 17 * 6 + password.Length; offset += 6) - for (i = 0; i < 6; ++i) - packet[i + offset] = password[i]; - } - return packet; - } - - private static void BroadcastWol(IPAddress localAddress, IPAddress broadCastAddress, byte[] data) - { - //var localEP = new IPEndPoint(localAddress, 0); - var udpc = new UdpClient(); - - udpc.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1); - //udpc.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontRoute, 1); - - var target = new IPEndPoint(broadCastAddress, DefaultWolPort); - - udpc.Send(data, data.Length, target); - } - - private static void SendWolToIpAddress(IPAddress localAddress, IPAddress remoteAddress, byte[] data, PhysicalAddress physicalAddress) - { - //var localEP = new IPEndPoint(localAddress, 0); - - var netLuid = CreateTransientLocalNetEntry(remoteAddress, physicalAddress); - try - { - var udpc = new UdpClient(); - udpc.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1); - - var target = new IPEndPoint(remoteAddress, DefaultWolPort); - - udpc.Send(data, data.Length, target); - } - finally - { - DeleteNetEntry(netLuid, remoteAddress); - } - } - - private static NET_LUID CreateTransientLocalNetEntry(IPAddress ipAddress, PhysicalAddress macAddress) - { - var ipBytes = ipAddress.GetAddressBytes(); - - var address = new Ws2_32.SOCKADDR_INET - { - si_family = Ws2_32.ADDRESS_FAMILY.AF_INET, - Ipv4 = new Ws2_32.SOCKADDR_IN(new Ws2_32.IN_ADDR(ipBytes), DefaultWolPort), - }; - - var net = new NET_LUID(); - var addr = new Ws2_32.SOCKADDR_INET(); - - MIB_IPFORWARD_ROW2 forwardRow; - var result = GetBestRoute2(net, 0, addr, address, 0, out forwardRow, out _); - - if (result != Win32Error.ERROR_SUCCESS) - { - Logger.Debug($"Cannot find best route: {result}"); - - var luidDummy = new NET_LUID(); - - return luidDummy; - } - var luid = forwardRow.InterfaceLuid; - - var macAddressBytes = macAddress.GetAddressBytes(); - var bytes = new byte[32]; - - macAddressBytes.CopyTo(bytes, 0); - - var row = new MIB_IPNET_ROW2 - { - Address = address, - InterfaceLuid = luid, - PhysicalAddress = bytes, - PhysicalAddressLength = 6 - }; - - result = CreateIpNetEntry2(ref row); - - if (result != Win32Error.ERROR_SUCCESS) - { - Logger.Debug($"Cannot create ip net entry: {result}"); - } - - return luid; - } - - private static void DeleteNetEntry(NET_LUID luid, IPAddress ipAddress) - { - if (luid.Value == 0) - { - return; - } - - var ipBytes = ipAddress.GetAddressBytes(); - - var address = new Ws2_32.SOCKADDR_INET - { - si_family = Ws2_32.ADDRESS_FAMILY.AF_INET, - Ipv4 = new Ws2_32.SOCKADDR_IN(new Ws2_32.IN_ADDR(ipBytes), DefaultWolPort) - - }; - - var row = new MIB_IPNET_ROW2 - { - Address = address, - InterfaceLuid = luid, - }; - - var result = DeleteIpNetEntry2(ref row); - - if (result != Win32Error.ERROR_SUCCESS) - { - Logger.Debug($"Cannot delete ip net entry: {result}"); - } - } - } -} \ No newline at end of file diff --git a/Shared/Contracts/StartUpParams.cs b/Shared/Contracts/StartUpParams.cs index b9bb6b9..7cb845f 100644 --- a/Shared/Contracts/StartUpParams.cs +++ b/Shared/Contracts/StartUpParams.cs @@ -1,13 +1,8 @@ -using ColorControl.Shared.Common; -using Microsoft.Win32.TaskScheduler; - -namespace ColorControl.Shared.Contracts +namespace ColorControl.Shared.Contracts { public class StartUpParams { public const string RunningFromScheduledTaskParam = "--scheduled"; - public const string ActivateChromeFontFixParam = "--activate-chrome-font-fix"; - public const string DeactivateChromeFontFixParam = "--deactivate-chrome-font-fix"; public const string ExecuteHelpParam = "--help"; public const string ExecuteNvidiaPresetParam = "--nvpreset"; public const string ExecuteAmdPresetParam = "--amdpreset"; @@ -15,21 +10,9 @@ namespace ColorControl.Shared.Contracts public const string ExecuteSamsungPresetParam = "--sampreset"; public const string NoDeviceRefreshParam = "--no-refresh"; public const string NoGuiParam = "--nogui"; - public const string EnableAutoStartParam = "--enable-auto-start"; - public const string DisableAutoStartParam = "--disable-auto-start"; - public const string SetProcessAffinityParam = "--set-process-affinity"; - public const string SetProcessPriorityParam = "--set-process-priority"; public const string StartElevatedParam = "--elevated"; - public const string SendWakeOnLanParam = "--send-wol"; - public const string InstallServiceParam = "--install-service"; - public const string UninstallServiceParam = "--uninstall-service"; - public const string StartServiceParam = "--start-service"; - public const string StopServiceParam = "--stop-service"; public bool RunningFromScheduledTask { get; private set; } - public bool ActivateChromeFontFix { get; private set; } - public bool DeactivateChromeFontFix { get; private set; } - public string ChromeFontFixApplicationDataFolder { get; private set; } public bool ExecuteHelp { get; private set; } public bool ExecuteNvidiaPreset { get; private set; } public string NvidiaPresetIdOrName { get; private set; } @@ -41,22 +24,7 @@ namespace ColorControl.Shared.Contracts public string SamsungPresetName { get; private set; } public bool NoDeviceRefresh { get; private set; } public bool NoGui { get; set; } - public bool EnableAutoStart { get; private set; } - public TaskRunLevel AutoStartRunLevel { get; private set; } = TaskRunLevel.LUA; - public bool DisableAutoStart { get; private set; } - public bool SetProcessAffinity { get; private set; } - public int ProcessId { get; private set; } - public uint AffinityMask { get; private set; } - public bool SetProcessPriority { get; private set; } - public uint PriorityClass { get; private set; } public bool StartElevated { get; private set; } - public bool SendWol { get; private set; } - public string WolMacAddress { get; private set; } - public string WolIpAddress { get; private set; } - public bool InstallService { get; private set; } - public bool UninstallService { get; private set; } - public bool StartService { get; private set; } - public bool StopService { get; private set; } public static StartUpParams Parse(IEnumerable args) { @@ -68,12 +36,6 @@ namespace ColorControl.Shared.Contracts { switch (parseNameParam) { - case ActivateChromeFontFixParam: - case DeactivateChromeFontFixParam: - { - settings.ChromeFontFixApplicationDataFolder = arg; - break; - } case ExecuteNvidiaPresetParam: { settings.NvidiaPresetIdOrName = arg; @@ -94,44 +56,6 @@ namespace ColorControl.Shared.Contracts settings.SamsungPresetName = arg; break; } - case SetProcessAffinityParam: - { - if (settings.ProcessId == 0) - { - settings.ProcessId = int.Parse(arg); - continue; - } - - settings.AffinityMask = uint.Parse(arg); - break; - } - case SetProcessPriorityParam: - { - if (settings.ProcessId == 0) - { - settings.ProcessId = int.Parse(arg); - continue; - } - - settings.PriorityClass = uint.Parse(arg); - break; - } - case SendWakeOnLanParam: - { - if (settings.WolMacAddress == null) - { - settings.WolMacAddress = arg; - continue; - } - - settings.WolIpAddress = arg; - break; - } - case EnableAutoStartParam: - { - settings.AutoStartRunLevel = (TaskRunLevel)Utils.ParseInt(arg, 0); - break; - } } parseNameParam = string.Empty; @@ -145,18 +69,6 @@ namespace ColorControl.Shared.Contracts settings.RunningFromScheduledTask = true; break; } - case ActivateChromeFontFixParam: - { - settings.ActivateChromeFontFix = true; - parseNameParam = ActivateChromeFontFixParam; - break; - } - case DeactivateChromeFontFixParam: - { - settings.DeactivateChromeFontFix = true; - parseNameParam = DeactivateChromeFontFixParam; - break; - } case ExecuteHelpParam: { settings.ExecuteHelp = true; @@ -192,60 +104,11 @@ namespace ColorControl.Shared.Contracts settings.NoGui = true; break; } - case EnableAutoStartParam: - { - settings.EnableAutoStart = true; - parseNameParam = EnableAutoStartParam; - break; - } - case DisableAutoStartParam: - { - settings.DisableAutoStart = true; - break; - } - case SetProcessAffinityParam: - { - settings.SetProcessAffinity = true; - parseNameParam = SetProcessAffinityParam; - break; - } - case SetProcessPriorityParam: - { - settings.SetProcessPriority = true; - parseNameParam = SetProcessPriorityParam; - break; - } case StartElevatedParam: { settings.StartElevated = true; break; } - case SendWakeOnLanParam: - { - settings.SendWol = true; - parseNameParam = SendWakeOnLanParam; - break; - } - case InstallServiceParam: - { - settings.InstallService = true; - break; - } - case UninstallServiceParam: - { - settings.UninstallService = true; - break; - } - case StartServiceParam: - { - settings.StartService = true; - break; - } - case StopServiceParam: - { - settings.StopService = true; - break; - } case NoDeviceRefreshParam: { settings.NoDeviceRefresh = true; diff --git a/Shared/Contracts/Svc/SvcMessage.cs b/Shared/Contracts/Svc/SvcMessage.cs index 6242494..d9261b5 100644 --- a/Shared/Contracts/Svc/SvcMessage.cs +++ b/Shared/Contracts/Svc/SvcMessage.cs @@ -1,70 +1,81 @@ using ColorControl.Shared.Contracts.NVIDIA; -namespace ColorControl.Shared.Contracts +namespace ColorControl.Shared.Contracts; + +public enum SvcMessageType { - public enum SvcMessageType + SetLgConfig = 1, + GetLog = 2, + ClearLog = 3, + ExecuteRpc = 10, + ExecuteRpcGeneric = 11, + ExecuteRpcGenericTyped = 12, + ExecuteUpdate = 20, + RestartAfterUpdate = 21, +} + +public class SvcMessage +{ + public SvcMessageType MessageType { get; set; } + + public string Data { get; set; } +} + +public class SvcInstallUpdateMessage : SvcMessage +{ + public SvcInstallUpdateMessage() { - SetLgConfig = 1, - GetLog = 2, - ClearLog = 3, - ExecuteRpc = 10, - ExecuteRpcGeneric = 11, - ExecuteUpdate = 20, - RestartAfterUpdate = 21, - ApplyNvidiaDriverSettings = 101, - RestoreNvidiaDriverSetting = 102, - ApplyNvidiaOverclocking = 110, + MessageType = SvcMessageType.ExecuteUpdate; } - public class SvcMessage - { - public SvcMessageType MessageType { get; set; } + public string DownloadUrl { get; set; } + public string ClientPath { get; set; } +} - public string Data { get; set; } +public class SvcRpcMessage : SvcMessage +{ + public SvcRpcMessage() + { + MessageType = SvcMessageType.ExecuteRpcGeneric; } - public class SvcInstallUpdateMessage : SvcMessage + private string _typeName; + public string TypeName { - public SvcInstallUpdateMessage() + get { - MessageType = SvcMessageType.ExecuteUpdate; - } + if (_typeName == null) + { + _typeName = GetType().Name; + } - public string DownloadUrl { get; set; } - public string ClientPath { get; set; } + return _typeName; + + } + set { _typeName = value; } } + public string ServiceName { get; set; } + public string MethodName { get; set; } + public object[] Arguments { get; set; } +} - public class SvcNvDriverSettingsMessage : SvcMessage +public class SvcRpcMessageTyped : SvcRpcMessage +{ + public SvcRpcMessageTyped() : base() { - public SvcNvDriverSettingsMessage(SvcMessageType messageType = SvcMessageType.ApplyNvidiaDriverSettings) - { - MessageType = messageType; - } - - public string ProfileName { get; set; } - - public List> DriverSettings { get; set; } - } - - public class SvcNvOverclockingMessage : SvcMessage - { - public SvcNvOverclockingMessage(SvcMessageType messageType = SvcMessageType.ApplyNvidiaOverclocking) - { - MessageType = messageType; - } - - public List OverclockingSettings { get; set; } - } - - public class SvcRpcMessage : SvcMessage - { - public SvcRpcMessage() - { - MessageType = SvcMessageType.ExecuteRpcGeneric; - } - - public string ServiceName { get; set; } - public string MethodName { get; set; } - public object[] Arguments { get; set; } + MessageType = SvcMessageType.ExecuteRpcGenericTyped; } } + +public class SvcRpcSetNvDriverSettingsMessage : SvcRpcMessageTyped +{ + public string ProfileName { get; set; } + + public List> DriverSettings { get; set; } +} + +public class SvcRpcSetNvOverclockingMessage : SvcRpcMessageTyped +{ + public List OverclockingSettings { get; set; } +} + diff --git a/Shared/Forms/MessageForms.cs b/Shared/Forms/MessageForms.cs index 9c6db94..af7f2b3 100644 --- a/Shared/Forms/MessageForms.cs +++ b/Shared/Forms/MessageForms.cs @@ -531,5 +531,31 @@ namespace ColorControl.Shared.Forms return prompt; } + + public static Form ShowControl(Control control, string title) + { + var prompt = new Form() + { + Icon = MainForm.Icon, + Text = title, + Width = 800, + Height = 400, + StartPosition = FormStartPosition.CenterScreen, + BackColor = FormUtils.CurrentBackColor, + ForeColor = FormUtils.CurrentForeColor, + }; + + prompt.Controls.Add(control); + + control.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; + control.Width = prompt.ClientRectangle.Width; + control.Height = prompt.ClientRectangle.Height; + + prompt.UpdateTheme(onlyIfDark: true); + + prompt.Show(MainForm); + + return prompt; + } } } \ No newline at end of file diff --git a/Shared/Native/WinApi.cs b/Shared/Native/WinApi.cs index 0b19929..5199063 100644 --- a/Shared/Native/WinApi.cs +++ b/Shared/Native/WinApi.cs @@ -1,170 +1,84 @@ using NWin32.NativeTypes; using System.Runtime.InteropServices; -namespace ColorControl.Shared.Native +namespace ColorControl.Shared.Native; + +public static class WinApi { - public static class WinApi + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct POWERBROADCAST_SETTING { - [StructLayout(LayoutKind.Sequential, Pack = 4)] - public struct POWERBROADCAST_SETTING - { - public Guid PowerSetting; - public uint DataLength; - public byte Data; - } - - [StructLayout(LayoutKind.Sequential)] - public struct COPYDATASTRUCT - { - public IntPtr dwData; // in C/C++ this is an UINT_PTR, not an UINT - public int cbData; - public IntPtr lpData; - } - - [StructLayout(LayoutKind.Sequential)] - public struct CopyData : IDisposable - { - [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] - static extern IntPtr SendMessageTimeout(IntPtr hWnd, uint Msg, IntPtr wParam, ref CopyData target, - SendMessageTimeoutFlags fuFlags, uint uTimeout, out UIntPtr lpdwResult); - - [Flags] - enum SendMessageTimeoutFlags : uint - { - SMTO_NORMAL = 0x0, - SMTO_BLOCK = 0x1, - SMTO_ABORTIFHUNG = 0x2, - SMTO_NOTIMEOUTIFNOTHUNG = 0x8 - } - const uint WM_COPYDATA = 0x4A; - - public IntPtr dwData; - public int cbData; - public IntPtr lpData; - - public void Dispose() - { - if (lpData != IntPtr.Zero) - { - Marshal.FreeCoTaskMem(lpData); - lpData = IntPtr.Zero; - cbData = 0; - } - } - public string AsAnsiString - { - get { return Marshal.PtrToStringAnsi(lpData, cbData); } - } - public string AsUnicodeString - { - get { return Marshal.PtrToStringUni(lpData); } - } - public static CopyData CreateForString(int dwData, string value, bool Unicode = false) - { - var result = new CopyData(); - result.dwData = (IntPtr)dwData; - result.lpData = Unicode ? Marshal.StringToCoTaskMemUni(value) : Marshal.StringToCoTaskMemAnsi(value); - result.cbData = value.Length + 2; - return result; - } - - public static UIntPtr Send(IntPtr targetHandle, int dwData, string value, uint timeoutMs = 1000, bool Unicode = false) - { - var cds = CreateForString(dwData, value, Unicode); - UIntPtr result; - SendMessageTimeout(targetHandle, WM_COPYDATA, IntPtr.Zero, ref cds, SendMessageTimeoutFlags.SMTO_NORMAL, timeoutMs, out result); - cds.Dispose(); - return result; - } - } - - public enum MessageFilterInfo : uint - { - None = 0, AlreadyAllowed = 1, AlreadyDisAllowed = 2, AllowedHigher = 3 - }; - - public enum ChangeWindowMessageFilterExAction : uint - { - Reset = 0, Allow = 1, DisAllow = 2 - }; - - [StructLayout(LayoutKind.Sequential)] - public struct CHANGEFILTERSTRUCT - { - public uint size; - public MessageFilterInfo info; - } - - [StructLayout(LayoutKind.Sequential)] - public struct ParentProcessUtilities - { - // These members must match PROCESS_BASIC_INFORMATION - internal IntPtr Reserved1; - internal IntPtr PebBaseAddress; - internal IntPtr Reserved2_0; - internal IntPtr Reserved2_1; - internal IntPtr UniqueProcessId; - internal IntPtr InheritedFromUniqueProcessId; - } - - public const int ENUM_CURRENT_SETTINGS = -1; - public const int ENUM_REGISTRY_SETTINGS = -2; - - public static int PBT_POWERSETTINGCHANGE = 32787; - - public delegate void PCREATE_PROCESS_NOTIFY_ROUTINE(IntPtr ParentId, IntPtr ProcessId, bool Create); - - [DllImport("user32.dll", SetLastError = true)] - public static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc); - - [DllImport("user32.dll")] - public static extern bool UnregisterHotKey(IntPtr hWnd, int id); - - [DllImport("user32.dll")] - public static extern bool EnumDisplaySettingsA(string deviceName, int modeNum, out DEVMODEA devMode); - - [DllImport("kernel32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool AllocConsole(); - - [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] - public static extern bool AttachConsole(int processId); - - [DllImport("kernel32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool FreeConsole(); - - [DllImport(@"User32", SetLastError = true)] - public static extern IntPtr RegisterPowerSettingNotification(IntPtr hRecipient, ref Guid PowerSettingGuid, Int32 Flags); - - [DllImport("User32.dll", SetLastError = true)] - public static extern bool UnregisterPowerSettingNotification(IntPtr hWnd); - - [DllImport("user32.dll", SetLastError = true)] - public static extern bool ChangeWindowMessageFilterEx(IntPtr hWnd, uint msg, ChangeWindowMessageFilterExAction action, ref CHANGEFILTERSTRUCT changeInfo); - - [DllImport("uxtheme.dll", CharSet = CharSet.Unicode)] - public static extern int SetWindowTheme(IntPtr hWnd, string pszSubAppName, string pszSubIdList); - - [DllImport("uxtheme.dll", CharSet = CharSet.Unicode, EntryPoint = "#104")] - public static extern int RefreshImmersiveColorPolicyState(); - - [DllImport("uxtheme.dll", CharSet = CharSet.Unicode, EntryPoint = "#133")] - public static extern int AllowDarkModeForWindow(IntPtr hWnd, bool allow); - - [DllImport("uxtheme.dll", CharSet = CharSet.Unicode, EntryPoint = "#135")] - public static extern int SetPreferredAppMode(int appMode); - - [DllImport("uxtheme.dll", EntryPoint = "#136")] - public static extern void FlushMenuThemes(); - - [DllImport("dwmapi.dll", PreserveSig = true)] - public static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize); - - [DllImport("ntdll.dll")] - public static extern int NtQueryInformationProcess(IntPtr processHandle, int processInformationClass, ref ParentProcessUtilities processInformation, int processInformationLength, out int returnLength); - - [DllImport("dwmapi.dll", EntryPoint = "#171")] - public static extern void DwmpSDRToHDRBoostPtr(IntPtr monitor, double brightness); + public Guid PowerSetting; + public uint DataLength; + public byte Data; } + + [StructLayout(LayoutKind.Sequential)] + public struct ParentProcessUtilities + { + // These members must match PROCESS_BASIC_INFORMATION + internal IntPtr Reserved1; + internal IntPtr PebBaseAddress; + internal IntPtr Reserved2_0; + internal IntPtr Reserved2_1; + internal IntPtr UniqueProcessId; + internal IntPtr InheritedFromUniqueProcessId; + } + + public const int ENUM_CURRENT_SETTINGS = -1; + public const int ENUM_REGISTRY_SETTINGS = -2; + + public static int PBT_POWERSETTINGCHANGE = 32787; + + public delegate void PCREATE_PROCESS_NOTIFY_ROUTINE(IntPtr ParentId, IntPtr ProcessId, bool Create); + + [DllImport("user32.dll", SetLastError = true)] + public static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc); + + [DllImport("user32.dll")] + public static extern bool UnregisterHotKey(IntPtr hWnd, int id); + + [DllImport("user32.dll")] + public static extern bool EnumDisplaySettingsA(string deviceName, int modeNum, out DEVMODEA devMode); + + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AllocConsole(); + + [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] + public static extern bool AttachConsole(int processId); + + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool FreeConsole(); + + [DllImport(@"User32", SetLastError = true)] + public static extern IntPtr RegisterPowerSettingNotification(IntPtr hRecipient, ref Guid PowerSettingGuid, Int32 Flags); + + [DllImport("User32.dll", SetLastError = true)] + public static extern bool UnregisterPowerSettingNotification(IntPtr hWnd); + + [DllImport("uxtheme.dll", CharSet = CharSet.Unicode)] + public static extern int SetWindowTheme(IntPtr hWnd, string pszSubAppName, string pszSubIdList); + + [DllImport("uxtheme.dll", CharSet = CharSet.Unicode, EntryPoint = "#104")] + public static extern int RefreshImmersiveColorPolicyState(); + + [DllImport("uxtheme.dll", CharSet = CharSet.Unicode, EntryPoint = "#133")] + public static extern int AllowDarkModeForWindow(IntPtr hWnd, bool allow); + + [DllImport("uxtheme.dll", CharSet = CharSet.Unicode, EntryPoint = "#135")] + public static extern int SetPreferredAppMode(int appMode); + + [DllImport("uxtheme.dll", EntryPoint = "#136")] + public static extern void FlushMenuThemes(); + + [DllImport("dwmapi.dll", PreserveSig = true)] + public static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize); + + [DllImport("ntdll.dll")] + public static extern int NtQueryInformationProcess(IntPtr processHandle, int processInformationClass, ref ParentProcessUtilities processInformation, int processInformationLength, out int returnLength); + + [DllImport("dwmapi.dll", EntryPoint = "#171")] + public static extern void DwmpSDRToHDRBoostPtr(IntPtr monitor, double brightness); } diff --git a/Shared/Services/AppContextProvider.cs b/Shared/Services/AppContextProvider.cs index 68a8d0b..ffdca56 100644 --- a/Shared/Services/AppContextProvider.cs +++ b/Shared/Services/AppContextProvider.cs @@ -2,14 +2,14 @@ { public class AppContextProvider { - private Common.AppContext _appContext; + private Common.GlobalContext _appContext; - public void SetAppContext(Common.AppContext appContext) + public void SetAppContext(Common.GlobalContext appContext) { _appContext = appContext; } - public Common.AppContext GetAppContext() + public Common.GlobalContext GetAppContext() { return _appContext; } diff --git a/Shared/Services/RpcClientService.cs b/Shared/Services/RpcClientService.cs new file mode 100644 index 0000000..fa20b55 --- /dev/null +++ b/Shared/Services/RpcClientService.cs @@ -0,0 +1,72 @@ +using ColorControl.Shared.Common; +using ColorControl.Shared.Contracts; +using System.Diagnostics; + +namespace ColorControl.Shared.Services; + +public class RpcClientService +{ + private readonly WinElevatedProcessManager _elevatedProcessManager; + private readonly WinApiService _winApiService; + private readonly RpcServerService _rpcServerService; + + public string Name { get; set; } + + public RpcClientService(WinElevatedProcessManager elevatedProcessManager, WinApiService winApiService, RpcServerService rpcServerService) + { + _elevatedProcessManager = elevatedProcessManager; + _winApiService = winApiService; + _rpcServerService = rpcServerService; + } + + public T Call(string method, params object[] arguments) + { + if (!_winApiService.IsServiceRunning()) + { + // Last resort: try via elevated process + return ExecuteViaElevatedProcess(method, arguments); + } + + var rpcMessage = new SvcRpcMessage + { + ServiceName = Name, + MethodName = method, + Arguments = arguments + }; + + //var json = JsonConvert.SerializeObject(rpcMessage); + //var msg = JsonConvert.DeserializeObject(json); + //var _ = _rpcServerService.ExecuteRpcAsync(msg); + //return default; + + return PipeUtils.SendRpcMessage(rpcMessage); + } + + public T Call(SvcRpcMessage message) + { + message.ServiceName = Name; + + if (Debugger.IsAttached) + { + return PipeUtils.SendRpcMessage(message, pipeName: PipeUtils.ElevatedPipe); + } + + if (!_winApiService.IsServiceRunning()) + { + // Last resort: try via elevated process + return ExecuteViaElevatedProcess(message); + } + + return PipeUtils.SendRpcMessage(message); + } + + private T ExecuteViaElevatedProcess(string method, params object[] arguments) + { + return _elevatedProcessManager.ExecuteElevated(method, arguments); + } + + private T ExecuteViaElevatedProcess(SvcRpcMessage message) + { + return _elevatedProcessManager.ExecuteElevated(message); + } +} diff --git a/Shared/Services/RpcServerService.cs b/Shared/Services/RpcServerService.cs new file mode 100644 index 0000000..b2a29f7 --- /dev/null +++ b/Shared/Services/RpcServerService.cs @@ -0,0 +1,134 @@ +using ColorControl.Shared.Contracts; +using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json; +using System.Reflection; + +namespace ColorControl.Shared.Services; + +public class RpcServerService +{ + private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); + + private readonly IServiceProvider _serviceProvider; + + public static List ServiceTypes = new List(); + + public RpcServerService(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + + public async Task ExecuteRpcAsync(SvcRpcMessage message) + { + try + { + var service = GetServiceInstance(message.ServiceName); + + var method = service.GetType().GetMethod(message.MethodName); + + var convertedArgs = new List(); + + var methodParams = method.GetParameters(); + for (var i = 0; i < message.Arguments.Length; i++) + { + var arg = message.Arguments[i]; + var methodParam = methodParams[i]; + + var convertedArg = ConvertArgument(arg, methodParam.ParameterType); + convertedArgs.Add(arg); + } + + Logger.Debug($"Executing RPC: {message.ServiceName}.{message.MethodName}({string.Join(", ", convertedArgs)})"); + + var result = method.Invoke(service, convertedArgs.ToArray()); + + var data = JsonConvert.SerializeObject(result); + + return SvcResultMessage.FromResult(data); + } + catch (Exception ex) + { + Logger.Error(ex, $"ExecuteRpcAsync: {ex.Message}"); + + return new SvcResultMessage { ErrorMessage = ex.Message, Result = false }; + } + } + + private object ConvertArgument(object arg, Type type) + { + if (arg.GetType() != type) + { + if (type.IsEnum) + { + return Enum.ToObject(type, arg); + } + + var convertedArg = Convert.ChangeType(arg, type); + return convertedArg; + } + + return arg; + + } + + public async Task ExecuteRpcTypedAsync(SvcRpcMessageTyped message) + { + try + { + var service = GetServiceInstance(message.ServiceName); + + var method = service.GetType().GetMethod(message.MethodName); + + var props = message.GetType().GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance); + var methodParams = method.GetParameters(); + + var convertedArgs = new List(); + var paramIndex = 0; + + foreach (var prop in props) + { + Logger.Debug($"Prop: {prop.Name}"); + + var arg = prop.GetValue(message); + var methodParam = methodParams[paramIndex]; + + var convertedArg = ConvertArgument(arg, methodParam.ParameterType); + convertedArgs.Add(arg); + + paramIndex++; + } + + Logger.Debug($"Executing RPC-typed: {message.ServiceName}.{message.MethodName}({string.Join(", ", convertedArgs)})"); + + var result = method.Invoke(service, convertedArgs.ToArray()); + + var data = JsonConvert.SerializeObject(result); + + return SvcResultMessage.FromResult(data); + } + catch (Exception ex) + { + Logger.Error(ex, $"ExecuteRpcTypedAsync: {ex.Message}"); + + return new SvcResultMessage { ErrorMessage = ex.Message, Result = false }; + } + } + + private object GetServiceInstance(string name) + { + var type = Type.GetType($"ColorControl.Shared.Services.{name}"); + + type ??= Type.GetType($"ColorControl.Services.NVIDIA.{name}"); + + type ??= ServiceTypes.FirstOrDefault(t => t.Name == name); + + if (type == null) + { + throw new InvalidOperationException($"Type not found: {name}"); + } + + var service = _serviceProvider.GetRequiredService(type); + + return service; + } +} diff --git a/Shared/Services/RpcService.cs b/Shared/Services/RpcService.cs deleted file mode 100644 index 7e12b72..0000000 --- a/Shared/Services/RpcService.cs +++ /dev/null @@ -1,23 +0,0 @@ -using ColorControl.Shared.Common; -using ColorControl.Shared.Contracts; - -namespace ColorControl.Shared.Services -{ - public class RpcService - { - public string Name { get; set; } - - public T Call(string method, params object[] arguments) where T : class - { - var rpcMessage = new SvcRpcMessage - { - ServiceName = Name, - MethodName = method, - Arguments = arguments - }; - - return PipeUtils.SendRpcMessage(rpcMessage); - } - - } -} diff --git a/Shared/Services/WinApiAdminService.cs b/Shared/Services/WinApiAdminService.cs new file mode 100644 index 0000000..536c98f --- /dev/null +++ b/Shared/Services/WinApiAdminService.cs @@ -0,0 +1,383 @@ +using ColorControl.Shared.Contracts; +using Microsoft.Win32; +using Microsoft.Win32.TaskScheduler; +using NWin32; +using System.ComponentModel; +using System.Diagnostics; +using System.IO; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security.Principal; +using System.ServiceProcess; + +namespace ColorControl.Shared.Services +{ + public class WinApiAdminService + { + private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); + public static string SERVICE_NAME = "Color Control Service"; + private readonly WinApiService _winApiService; + private RpcClientService _rpcService; + private readonly WinElevatedProcessManager _elevatedProcessManager; + private bool? _IsAdministrator; + + public WinApiAdminService(WinApiService winApiService, RpcClientService rpcService, WinElevatedProcessManager elevatedProcessManager) + { + _winApiService = winApiService; + _rpcService = rpcService; + _elevatedProcessManager = elevatedProcessManager; + _rpcService.Name = nameof(WinApiAdminService); + } + + public bool SuspendThread(uint threadId) + { + if (!_winApiService.IsAdministrator()) + { + return _rpcService.Call(nameof(SuspendThread), threadId); + } + + var handle = NativeMethods.OpenThread(NativeConstants.THREAD_ALL_ACCESS, false, threadId); + + try + { + var result = NativeMethods.SuspendThread(handle); + + return ProcessResult(result); + } + finally + { + NativeMethods.CloseHandle(handle); + } + } + + private int GetProcessMainThread(Process process) + { + var minStartTime = DateTime.MaxValue; + var mainThread = default(ProcessThread); + + for (var i = 0; i < process.Threads.Count; i++) + { + var thread = process.Threads[i]; + try + { + if (thread.StartTime < minStartTime) + { + mainThread = thread; + minStartTime = thread.StartTime; + } + } + catch { } + } + + return mainThread.Id; + } + + public int SuspendMainThread(int processId) + { + if (!_winApiService.IsAdministrator()) + { + return _rpcService.Call(nameof(SuspendMainThread), processId); + } + + var process = Process.GetProcessById(processId); + var threadId = GetProcessMainThread(process); + + if (SuspendThread((uint)threadId)) + { + return threadId; + } + + return 0; + } + + public bool ResumeThread(uint threadId) + { + if (!_winApiService.IsAdministrator()) + { + return _rpcService.Call(nameof(ResumeThread), threadId); + } + + var handle = NativeMethods.OpenThread(NativeConstants.THREAD_ALL_ACCESS, false, threadId); + + try + { + var result = NativeMethods.ResumeThread(handle); + + return ProcessResult(result); + } + finally + { + NativeMethods.CloseHandle(handle); + } + } + + public Process StartProcess(string fileName, string arguments = null, bool hidden = false, bool wait = false, bool setWorkingDir = false, bool elevate = false, uint affinityMask = 0, uint priorityClass = 0) + { + var process = Process.Start(new ProcessStartInfo(fileName, arguments) + { + Verb = elevate ? "runas" : string.Empty, // indicates to elevate privileges + UseShellExecute = true, + WindowStyle = hidden ? ProcessWindowStyle.Hidden : ProcessWindowStyle.Normal, + WorkingDirectory = setWorkingDir ? Path.GetDirectoryName(fileName) : null + }); + + if (affinityMask > 0) + { + SetProcessAffinity(process.Id, affinityMask); + } + + if (priorityClass > 0 && priorityClass != NativeConstants.NORMAL_PRIORITY_CLASS) + { + SetProcessPriority(process.Id, priorityClass); + } + + if (wait) + { + process.WaitForExit(); + } + + return process; + } + + public bool StopProcess(int processId) + { + if (!_winApiService.IsAdministrator()) + { + return _rpcService.Call(nameof(StopProcess), processId); + } + + var process = Process.GetProcessById(processId); + + if (process == null) + { + return false; + } + + process.Kill(); + + return true; + } + + public bool SetProcessAffinity(int processId, uint affinityMask) + { + if (!_winApiService.IsAdministrator()) + { + return _rpcService.Call(nameof(SetProcessAffinity), processId, affinityMask); + } + + var hProcess = NativeMethods.OpenProcess(NativeConstants.PROCESS_ALL_ACCESS, false, (uint)processId); + + if (hProcess == nint.Zero) + { + CheckWin32Error($"Unable to set processor affinity on process {processId}"); + return false; + } + + return NativeMethods.SetProcessAffinityMask(hProcess, affinityMask); + } + + public bool SetProcessPriority(int processId, uint priorityClass) + { + if (!_winApiService.IsAdministrator()) + { + return _rpcService.Call(nameof(SetProcessPriority), processId, priorityClass); + } + + var hProcess = NativeMethods.OpenProcess(NativeConstants.PROCESS_ALL_ACCESS, false, (uint)processId); + + if (hProcess == nint.Zero) + { + CheckWin32Error($"Unable to set process priority on process {processId}"); + return false; + } + + return NativeMethods.SetPriorityClass(hProcess, priorityClass); + } + + public void InstallService() + { + if (!_winApiService.IsAdministrator()) + { + _elevatedProcessManager.ExecuteElevated(nameof(InstallService)); + + return; + } + + + if (!_winApiService.IsServiceInstalled()) + { + StartProcess("sc.exe", @$"create ""{SERVICE_NAME}"" binpath=""{Process.GetCurrentProcess().MainModule.FileName}"" start=auto", wait: true); + StartProcess("sc.exe", @$"description ""{SERVICE_NAME}"" ""Executes tasks for Color Control that require elevation. If this service is stopped, functions like WOL might be impacted.""", wait: true); + } + + StartService(); + } + + public void UninstallService() + { + if (!_winApiService.IsAdministrator()) + { + _elevatedProcessManager.ExecuteElevated(nameof(UninstallService)); + + return; + } + + if (!_winApiService.IsServiceInstalled()) + { + return; + } + + StopService(); + + StartProcess("sc.exe", @$"delete ""{SERVICE_NAME}""", wait: true); + } + + public void StartService() + { + if (!_winApiService.IsAdministrator()) + { + _elevatedProcessManager.ExecuteElevated(nameof(StartService)); + return; + } + + var controller = new ServiceController(SERVICE_NAME); + + if (controller.Status == ServiceControllerStatus.Stopped) + { + controller.Start(); + } + } + + public void StopService() + { + if (!_winApiService.IsAdministrator()) + { + _elevatedProcessManager.ExecuteElevated(nameof(StopService)); + return; + } + + var controller = new ServiceController(SERVICE_NAME); + + if (controller.Status == ServiceControllerStatus.Running) + { + controller.Stop(); + } + } + + public bool InstallChromeFix(bool install, string applicationDataFolder) + { + if (!_winApiService.IsAdministrator()) + { + return _rpcService.Call(nameof(InstallChromeFix), new object[] { install, applicationDataFolder }); + } + + var argument = "--disable-lcd-text"; + + var key = Registry.ClassesRoot.OpenSubKey(@"ChromeHTML\shell\open\command", true); + if (key != null) + { + var value = key.GetValue(null).ToString(); + value = value.Replace("chrome.exe\" " + argument + " --", "chrome.exe\" --"); + if (install) + { + value = value.Replace("chrome.exe\" --", "chrome.exe\" " + argument + " --"); + } + key.SetValue(null, value); + } + + var roamingFolder = applicationDataFolder ?? Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + + UpdateShortcut(Path.Combine(roamingFolder, @"Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Google Chrome.lnk"), argument, !install); + UpdateShortcut(Path.Combine(roamingFolder, @"Microsoft\Internet Explorer\Quick Launch\Google Chrome.lnk"), argument, !install); + + var allUsersStartMenuFolder = Environment.GetFolderPath(Environment.SpecialFolder.CommonStartMenu); + UpdateShortcut(Path.Combine(allUsersStartMenuFolder, @"Programs\Google Chrome.lnk"), argument, !install); + + return true; + } + + public void RegisterTask(string taskName, bool enabled, TaskRunLevel runLevel = TaskRunLevel.LUA) + { + if (!_winApiService.IsAdministrator()) + { + _elevatedProcessManager.ExecuteElevated(nameof(RegisterTask), new object[] { taskName, enabled, runLevel }); + return; + } + + var file = Process.GetCurrentProcess().MainModule.FileName; + var directory = Path.GetDirectoryName(file); + + try + { + using (TaskService ts = new TaskService()) + { + if (enabled) + { + var td = ts.NewTask(); + + td.RegistrationInfo.Description = "Start ColorControl"; + td.Principal.RunLevel = runLevel; + + td.Triggers.Add(new LogonTrigger { UserId = WindowsIdentity.GetCurrent().Name }); + + td.Actions.Add(new ExecAction(file, StartUpParams.RunningFromScheduledTaskParam, directory)); + + ts.RootFolder.RegisterTaskDefinition(taskName, td); + } + else + { + ts.RootFolder.DeleteTask(taskName, false); + } + } + } + catch (Exception e) + { + Logger.Error($"Could not create/delete task: {e.Message}"); + } + } + + private static bool UpdateShortcut(string path, string arguments, bool removeArguments = false) + { + if (File.Exists(path)) + { + IWshRuntimeLibrary.WshShell shell = new IWshRuntimeLibrary.WshShell(); + + IWshRuntimeLibrary.IWshShortcut shortcut = (IWshRuntimeLibrary.IWshShortcut)shell.CreateShortcut(path); + + shortcut.Arguments = shortcut.Arguments.Replace(arguments, ""); + if (!removeArguments) + { + if (!string.IsNullOrEmpty(shortcut.Arguments)) + { + shortcut.Arguments = shortcut.Arguments + " "; + } + shortcut.Arguments = shortcut.Arguments + arguments; + } + + // save it / create + shortcut.Save(); + + return true; + } + return false; + } + + private static bool ProcessResult(uint result, [CallerMemberName] string callerName = "") + { + if (result != NativeConstants.ERROR_SUCCESS) + { + // Logging + Logger.Error("Error executing {CallerName}: error code {Result}", callerName, result); + } + + return result == NativeConstants.ERROR_SUCCESS; + } + + private static void CheckWin32Error(string message) + { + var errorMessage = new Win32Exception(Marshal.GetLastWin32Error()).Message; + + throw new Exception($"{message}: {errorMessage}"); + } + } +} diff --git a/Shared/Services/WinApiService.cs b/Shared/Services/WinApiService.cs new file mode 100644 index 0000000..13773f5 --- /dev/null +++ b/Shared/Services/WinApiService.cs @@ -0,0 +1,83 @@ +using Microsoft.Win32; +using Microsoft.Win32.TaskScheduler; +using System.Security.Principal; +using System.ServiceProcess; + +namespace ColorControl.Shared.Services; + +public class WinApiService +{ + private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); + public static string SERVICE_NAME = "Color Control Service"; + + private static bool? _IsAdministrator; + + public WinApiService() + { + } + + public static bool IsAdministratorStatic() + { + if (_IsAdministrator.HasValue) + { + return _IsAdministrator.Value; + } + + var identity = WindowsIdentity.GetCurrent(); + var principal = new WindowsPrincipal(identity); + _IsAdministrator = principal.IsInRole(WindowsBuiltInRole.Administrator); + + return _IsAdministrator.Value; + } + + public bool IsAdministrator() + { + return IsAdministratorStatic(); + } + + public bool IsServiceInstalled() + { + return GetServiceStatus() != 0; + } + + public bool IsServiceRunning() + { + return GetServiceStatus() == ServiceControllerStatus.Running; + } + + public bool IsChromeInstalled() + { + var key = Registry.ClassesRoot.OpenSubKey(@"ChromeHTML\shell\open\command"); + return key != null; + } + + public bool IsChromeFixInstalled() + { + var key = Registry.ClassesRoot.OpenSubKey(@"ChromeHTML\shell\open\command"); + return key != null && key.GetValue(null).ToString().Contains("--disable-lcd-text"); + } + + public bool TaskExists(string taskName) + { + using (TaskService ts = new TaskService()) + { + var task = ts.RootFolder.Tasks.FirstOrDefault(x => x.Name.Equals(taskName)); + + return task != null; + } + } + + private ServiceControllerStatus GetServiceStatus() + { + var controller = new ServiceController(SERVICE_NAME); + + try + { + return controller.Status; + } + catch (Exception) + { + return 0; + } + } +} diff --git a/Shared/Services/WinElevatedProcessManager.cs b/Shared/Services/WinElevatedProcessManager.cs new file mode 100644 index 0000000..92362e0 --- /dev/null +++ b/Shared/Services/WinElevatedProcessManager.cs @@ -0,0 +1,108 @@ +using ColorControl.Shared.Common; +using ColorControl.Shared.Contracts; +using NWin32; +using System.Diagnostics; + +namespace ColorControl.Shared.Services; + +public class WinElevatedProcessManager +{ + private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); + private bool UseDedicatedElevatedProcess = true; + + public WinElevatedProcessManager() + { + } + + public void ExecuteElevated(string method, params object[] arguments) + { + ExecuteElevated(method, arguments); + } + + public T ExecuteElevated(string method, params object[] arguments) + { + CheckElevatedProcess(); + + var rpcMessage = new SvcRpcMessage + { + ServiceName = nameof(WinApiAdminService), + MethodName = method, + Arguments = arguments + }; + + return PipeUtils.SendRpcMessage(rpcMessage, pipeName: PipeUtils.ElevatedPipe); + } + + public T ExecuteElevated(SvcRpcMessage message) + { + CheckElevatedProcess(); + + return PipeUtils.SendRpcMessage(message, pipeName: PipeUtils.ElevatedPipe); + } + + private int ExecuteDirect(string args, bool wait = true) + { + var fileName = Process.GetCurrentProcess().MainModule.FileName; + + var info = new ProcessStartInfo(fileName, args) + { + Verb = "runas", // indicates to elevate privileges + UseShellExecute = true, + }; + + var process = new Process + { + EnableRaisingEvents = true, // enable WaitForExit() + StartInfo = info + }; + try + { + process.Start(); + + if (wait) + { + process.WaitForExit(); // sleep calling process thread until evoked process exit + } + + return process.Id; + } + catch (Exception e) + { + Logger.Error("ExecuteElevated: " + e.Message); + } + return 0; + } + + + private static nint ElevatedProcessWindowHandle = nint.Zero; + + public void CheckElevatedProcess() + { + ElevatedProcessWindowHandle = NativeMethods.FindWindowW(null, "ElevatedForm"); + + if (ElevatedProcessWindowHandle != nint.Zero) + { + return; + } + + ExecuteDirect(StartUpParams.StartElevatedParam, false); + + var delay = 1000; + + while (delay >= 0) + { + Thread.Sleep(100); + + ElevatedProcessWindowHandle = NativeMethods.FindWindowW(null, "ElevatedForm"); + + if (ElevatedProcessWindowHandle != nint.Zero) + { + Thread.Sleep(500); + break; + } + + delay -= 100; + } + } + +} diff --git a/Shared/Services/WolService.cs b/Shared/Services/WolService.cs new file mode 100644 index 0000000..9666176 --- /dev/null +++ b/Shared/Services/WolService.cs @@ -0,0 +1,256 @@ +using ColorControl.Shared.Common; +using NLog; +using System.Net; +using System.Net.NetworkInformation; +using System.Net.Sockets; +using Vanara.PInvoke; +using static Vanara.PInvoke.IpHlpApi; + +namespace ColorControl.Shared.Services; + +public class WolService +{ + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + + private const string ArgumentExceptionInvalidMacAddressLength = "Invalid MAC address length."; + private const string ArgumentExceptionInvalidPasswordLength = "Invalid password length."; + private const int DefaultWolPort = 9; + + private readonly WinApiService _winApiService; + private readonly RpcClientService _rpcService; + + public WolService(WinApiService winApiService, RpcClientService rpcService) + { + _winApiService = winApiService; + _rpcService = rpcService; + _rpcService.Name = nameof(WolService); + } + + public bool SendWol(string macAddress, string ipAddress = null) + { + if (!_winApiService.IsAdministrator()) + { + if (_rpcService.Call("SendWol", macAddress, ipAddress)) + { + return true; + } + + // If RPC faield, execute local WOL anyway + } + + return WakeFunctionToAllNics(macAddress, ipAddress); + } + + private bool WakeFunctionToAllNics(string macAddress, string ipAddressString) + { + var result = false; + Logger.Debug($"Sending WOL packet to MAC-address {macAddress}"); + + try + { + var physicalAddress = PhysicalAddress.Parse(macAddress); + var addressBytes = physicalAddress.GetAddressBytes(); + var data = GetWolPacket(addressBytes); + var ipAddress = ipAddressString != null ? IPAddress.Parse(ipAddressString) : null; + + var interfaces = NetworkInterface.GetAllNetworkInterfaces(); + + foreach (var ni in interfaces) + { + if (ni.NetworkInterfaceType == NetworkInterfaceType.Loopback/* || ni.Name.Contains("VirtualBox") || ni.Name.Contains("vEthernet") || ni.Description.Contains("Virtual")*/) + { + continue; + } + Logger.Debug($"Found network: {ni.Name} ({ni.Description}), type: {ni.NetworkInterfaceType}"); + try + { + if (ni.SupportsMulticast && ni.GetIPProperties().GetIPv4Properties() == null) + { + continue; + } + + foreach (var uip in ni.GetIPProperties().UnicastAddresses) + { + if (uip.Address.ToString().StartsWith("169.254") || uip.Address.AddressFamily != AddressFamily.InterNetwork) + { + continue; + } + + Logger.Debug($"Broadcast WOL in network: {ni.Name} ({ni.Description}), local address: {uip.Address}, destination IP-address: {ipAddressString ?? "broadcast"}"); + + if (ipAddress != null && _winApiService.IsAdministrator()) + { + var localEP = new IPEndPoint(uip.Address, 0); + + SendWolToIpAddress(uip.Address, ipAddress, data, physicalAddress); + } + + BroadcastWol(uip.Address, IPAddress.Broadcast, data); + + var parts = uip.Address.ToString().Split(".").ToList(); + parts[3] = "0"; + var broadcastAddress = IPAddress.Parse(string.Join(".", parts)); + BroadcastWol(uip.Address, broadcastAddress, data); + + result = true; + } + } + catch (Exception ex) + { + Logger.Error($"WakeFunctionToAllNics: while sending to specific network: {ni.Name} ({ni.Description}): {ex.ToLogString()}"); + } + } + } + catch (Exception ex) + { + Logger.Error($"WakeFunctionToAllNics: {ex.ToLogString()}"); + } + + return result; + } + + /// is null. + /// The length of the array is not 6. + /// The length of the array is not 0 or 6. + private static byte[] GetWolPacket(byte[] macAddress, byte[] password = null) + { + if (macAddress == null) + throw new ArgumentNullException(nameof(macAddress)); + if (macAddress.Length != 6) + throw new ArgumentException(ArgumentExceptionInvalidMacAddressLength); + + password = password ?? new byte[0]; + if (password.Length != 0 && password.Length != 6) + throw new ArgumentException(ArgumentExceptionInvalidPasswordLength); + + var packet = new byte[17 * 6 + password.Length]; + + int offset, i; + for (offset = 0; offset < 6; ++offset) + packet[offset] = 0xFF; + + for (offset = 6; offset < 17 * 6; offset += 6) + for (i = 0; i < 6; ++i) + packet[i + offset] = macAddress[i]; + + if (password.Length > 0) + { + for (offset = 16 * 6 + 6; offset < 17 * 6 + password.Length; offset += 6) + for (i = 0; i < 6; ++i) + packet[i + offset] = password[i]; + } + return packet; + } + + private static void BroadcastWol(IPAddress localAddress, IPAddress broadCastAddress, byte[] data) + { + //var localEP = new IPEndPoint(localAddress, 0); + var udpc = new UdpClient(); + + udpc.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1); + //udpc.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontRoute, 1); + + var target = new IPEndPoint(broadCastAddress, DefaultWolPort); + + udpc.Send(data, data.Length, target); + } + + private static void SendWolToIpAddress(IPAddress localAddress, IPAddress remoteAddress, byte[] data, PhysicalAddress physicalAddress) + { + //var localEP = new IPEndPoint(localAddress, 0); + + var netLuid = CreateTransientLocalNetEntry(remoteAddress, physicalAddress); + try + { + var udpc = new UdpClient(); + udpc.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1); + + var target = new IPEndPoint(remoteAddress, DefaultWolPort); + + udpc.Send(data, data.Length, target); + } + finally + { + DeleteNetEntry(netLuid, remoteAddress); + } + } + + private static NET_LUID CreateTransientLocalNetEntry(IPAddress ipAddress, PhysicalAddress macAddress) + { + var ipBytes = ipAddress.GetAddressBytes(); + + var address = new Ws2_32.SOCKADDR_INET + { + si_family = Ws2_32.ADDRESS_FAMILY.AF_INET, + Ipv4 = new Ws2_32.SOCKADDR_IN(new Ws2_32.IN_ADDR(ipBytes), DefaultWolPort), + }; + + var net = new NET_LUID(); + var addr = new Ws2_32.SOCKADDR_INET(); + + MIB_IPFORWARD_ROW2 forwardRow; + var result = GetBestRoute2(net, 0, addr, address, 0, out forwardRow, out _); + + if (result != Win32Error.ERROR_SUCCESS) + { + Logger.Debug($"Cannot find best route: {result}"); + + var luidDummy = new NET_LUID(); + + return luidDummy; + } + var luid = forwardRow.InterfaceLuid; + + var macAddressBytes = macAddress.GetAddressBytes(); + var bytes = new byte[32]; + + macAddressBytes.CopyTo(bytes, 0); + + var row = new MIB_IPNET_ROW2 + { + Address = address, + InterfaceLuid = luid, + PhysicalAddress = bytes, + PhysicalAddressLength = 6 + }; + + result = CreateIpNetEntry2(ref row); + + if (result != Win32Error.ERROR_SUCCESS) + { + Logger.Debug($"Cannot create ip net entry: {result}"); + } + + return luid; + } + + private static void DeleteNetEntry(NET_LUID luid, IPAddress ipAddress) + { + if (luid.Value == 0) + { + return; + } + + var ipBytes = ipAddress.GetAddressBytes(); + + var address = new Ws2_32.SOCKADDR_INET + { + si_family = Ws2_32.ADDRESS_FAMILY.AF_INET, + Ipv4 = new Ws2_32.SOCKADDR_IN(new Ws2_32.IN_ADDR(ipBytes), DefaultWolPort) + + }; + + var row = new MIB_IPNET_ROW2 + { + Address = address, + InterfaceLuid = luid, + }; + + var result = DeleteIpNetEntry2(ref row); + + if (result != Win32Error.ERROR_SUCCESS) + { + Logger.Debug($"Cannot delete ip net entry: {result}"); + } + } +} \ No newline at end of file diff --git a/novideo_srgb/MainViewModel.cs b/novideo_srgb/MainViewModel.cs index aa1bbe1..f4e0a1b 100644 --- a/novideo_srgb/MainViewModel.cs +++ b/novideo_srgb/MainViewModel.cs @@ -22,7 +22,7 @@ namespace novideo_srgb UpdateMonitors(); } - private void UpdateMonitors() + public void UpdateMonitors(bool? forceClamp = null) { Monitors.Clear(); List config = null; @@ -66,12 +66,13 @@ namespace novideo_srgb foreach (var monitor in Monitors) { - monitor.ReapplyClamp(); + monitor.ReapplyClamp(forceClamp); } } - public void OnDisplaySettingsChanged(object sender, EventArgs e) + public async void OnDisplaySettingsChanged(object sender, EventArgs e) { + await Task.Delay(1000); UpdateMonitors(); } diff --git a/novideo_srgb/MainWindow.xaml.cs b/novideo_srgb/MainWindow.xaml.cs index 5e66ee7..3d7b21f 100644 --- a/novideo_srgb/MainWindow.xaml.cs +++ b/novideo_srgb/MainWindow.xaml.cs @@ -42,6 +42,21 @@ namespace novideo_srgb return _novideoWindow != null; } + public static void BeforeDisplaySettingsChange() + { + if (!IsInitialized()) + { + return; + } + + _novideoWindow.UpdateMonitors(); + } + + private void UpdateMonitors() + { + _viewModel.UpdateMonitors(false); + } + public static void UpdateContextMenu(ToolStripMenuItem parent) { if (_novideoWindow == null) diff --git a/novideo_srgb/MonitorData.cs b/novideo_srgb/MonitorData.cs index 12eb1de..c789525 100644 --- a/novideo_srgb/MonitorData.cs +++ b/novideo_srgb/MonitorData.cs @@ -75,9 +75,16 @@ namespace novideo_srgb private void UpdateClamp(bool doClamp) { + if (HdrActive) + { + _clamped = false; + return; + } + if (_clamped) { Novideo.DisableColorSpaceConversion(_output); + _clamped = Novideo.IsColorSpaceConversionActive(_output); } if (!doClamp) return; @@ -159,11 +166,11 @@ namespace novideo_srgb get => _clamped; } - public void ReapplyClamp() + public void ReapplyClamp(bool? forceClamp = null) { try { - var clamped = CanClamp && ClampSdr; + var clamped = CanClamp && ClampSdr && (!forceClamp.HasValue || forceClamp.Value); UpdateClamp(clamped); _clamped = clamped; OnPropertyChanged(nameof(CanClamp));