From 827b6edb38f58c5d7f94a19b0c690a1b9c1ce3f4 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 17 Feb 2025 23:12:46 +0800 Subject: [PATCH 1/7] Improve code quality --- Plugins/Flow.Launcher.Plugin.Sys/Main.cs | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs index 5bfc68ea613..374caa5111e 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs @@ -120,10 +120,9 @@ private List Commands() context.API.GetTranslation("flowlauncher_plugin_sys_dlgtext_shutdown_computer"), context.API.GetTranslation("flowlauncher_plugin_sys_shutdown_computer"), MessageBoxButton.YesNo, MessageBoxImage.Warning); + if (result == MessageBoxResult.Yes) - { Process.Start("shutdown", "/s /t 0"); - } return true; } @@ -140,10 +139,9 @@ private List Commands() context.API.GetTranslation("flowlauncher_plugin_sys_dlgtext_restart_computer"), context.API.GetTranslation("flowlauncher_plugin_sys_restart_computer"), MessageBoxButton.YesNo, MessageBoxImage.Warning); + if (result == MessageBoxResult.Yes) - { Process.Start("shutdown", "/r /t 0"); - } return true; } @@ -204,7 +202,11 @@ private List Commands() SubTitle = context.API.GetTranslation("flowlauncher_plugin_sys_sleep"), Glyph = new GlyphInfo (FontFamily:"/Resources/#Segoe Fluent Icons", Glyph:"\xec46"), IcoPath = "Images\\sleep.png", - Action = c => PInvoke.SetSuspendState(false, false, false) + Action = c => + { + PInvoke.SetSuspendState(false, false, false); + return true; + } }, new Result { @@ -231,10 +233,7 @@ private List Commands() Glyph = new GlyphInfo (FontFamily:"/Resources/#Segoe Fluent Icons", Glyph:"\xe773"), Action = c => { - { - System.Diagnostics.Process.Start("control.exe", "srchadmin.dll"); - } - + Process.Start("control.exe", "srchadmin.dll"); return true; } }, @@ -272,10 +271,7 @@ private List Commands() CopyText = recycleBinFolder, Action = c => { - { - System.Diagnostics.Process.Start("explorer", recycleBinFolder); - } - + Process.Start("explorer", recycleBinFolder); return true; } }, From ffa303825ef2a1523751f4aedc6a309726796b24 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 17 Feb 2025 23:22:06 +0800 Subject: [PATCH 2/7] Replace process commands with PInvoke --- Plugins/Flow.Launcher.Plugin.Sys/Main.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs index 374caa5111e..16c1b7f9124 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs @@ -122,7 +122,7 @@ private List Commands() MessageBoxButton.YesNo, MessageBoxImage.Warning); if (result == MessageBoxResult.Yes) - Process.Start("shutdown", "/s /t 0"); + PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_SHUTDOWN | EXIT_WINDOWS_FLAGS.EWX_POWEROFF, SHUTDOWN_REASON.SHTDN_REASON_NONE); return true; } @@ -141,7 +141,7 @@ private List Commands() MessageBoxButton.YesNo, MessageBoxImage.Warning); if (result == MessageBoxResult.Yes) - Process.Start("shutdown", "/r /t 0"); + PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_REBOOT, SHUTDOWN_REASON.SHTDN_REASON_NONE); return true; } @@ -160,7 +160,7 @@ private List Commands() MessageBoxButton.YesNo, MessageBoxImage.Warning); if (result == MessageBoxResult.Yes) - Process.Start("shutdown", "/r /o /t 0"); + PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_REBOOT | EXIT_WINDOWS_FLAGS.EWX_BOOTOPTIONS, SHUTDOWN_REASON.SHTDN_REASON_NONE); return true; } @@ -179,7 +179,7 @@ private List Commands() MessageBoxButton.YesNo, MessageBoxImage.Warning); if (result == MessageBoxResult.Yes) - PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_LOGOFF, 0); + PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_LOGOFF, SHUTDOWN_REASON.SHTDN_REASON_NONE); return true; } From e93699b37daaa1bedefd5e442413ea79dbe3204e Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 17 Feb 2025 23:37:20 +0800 Subject: [PATCH 3/7] Add shutdown reason --- Plugins/Flow.Launcher.Plugin.Sys/Main.cs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs index 16c1b7f9124..3199f50a242 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs @@ -121,8 +121,12 @@ private List Commands() context.API.GetTranslation("flowlauncher_plugin_sys_shutdown_computer"), MessageBoxButton.YesNo, MessageBoxImage.Warning); + // SHTDN_REASON_MAJOR_OTHER indicates a generic shutdown reason that isn't categorized under hardware failure, + // software updates, or other predefined reasons. + // SHTDN_REASON_FLAG_PLANNED marks the shutdown as planned rather than an unexpected shutdown or failure if (result == MessageBoxResult.Yes) - PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_SHUTDOWN | EXIT_WINDOWS_FLAGS.EWX_POWEROFF, SHUTDOWN_REASON.SHTDN_REASON_NONE); + PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_SHUTDOWN | EXIT_WINDOWS_FLAGS.EWX_POWEROFF, + SHUTDOWN_REASON.SHTDN_REASON_MAJOR_OTHER | SHUTDOWN_REASON.SHTDN_REASON_FLAG_PLANNED); return true; } @@ -141,7 +145,8 @@ private List Commands() MessageBoxButton.YesNo, MessageBoxImage.Warning); if (result == MessageBoxResult.Yes) - PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_REBOOT, SHUTDOWN_REASON.SHTDN_REASON_NONE); + PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_REBOOT, + SHUTDOWN_REASON.SHTDN_REASON_MAJOR_OTHER | SHUTDOWN_REASON.SHTDN_REASON_FLAG_PLANNED); return true; } @@ -160,7 +165,8 @@ private List Commands() MessageBoxButton.YesNo, MessageBoxImage.Warning); if (result == MessageBoxResult.Yes) - PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_REBOOT | EXIT_WINDOWS_FLAGS.EWX_BOOTOPTIONS, SHUTDOWN_REASON.SHTDN_REASON_NONE); + PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_REBOOT | EXIT_WINDOWS_FLAGS.EWX_BOOTOPTIONS, + SHUTDOWN_REASON.SHTDN_REASON_MAJOR_OTHER | SHUTDOWN_REASON.SHTDN_REASON_FLAG_PLANNED); return true; } @@ -179,7 +185,8 @@ private List Commands() MessageBoxButton.YesNo, MessageBoxImage.Warning); if (result == MessageBoxResult.Yes) - PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_LOGOFF, SHUTDOWN_REASON.SHTDN_REASON_NONE); + PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_LOGOFF, + SHUTDOWN_REASON.SHTDN_REASON_MAJOR_OTHER | SHUTDOWN_REASON.SHTDN_REASON_FLAG_PLANNED); return true; } From 18093148429abfaa94db92607984a53d97cde8cf Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 18 Feb 2025 00:08:15 +0800 Subject: [PATCH 4/7] Enable shutdown privilege before calling PInvoke for shutdown and start --- Plugins/Flow.Launcher.Plugin.Sys/Main.cs | 63 +++++++++++++++++-- .../NativeMethods.txt | 7 ++- 2 files changed, 63 insertions(+), 7 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs index 3199f50a242..7d3f66746da 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Runtime.InteropServices; using System.Windows; using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Logger; @@ -9,6 +10,7 @@ using Flow.Launcher.Plugin.SharedCommands; using Windows.Win32; using Windows.Win32.Foundation; +using Windows.Win32.Security; using Windows.Win32.System.Shutdown; using Application = System.Windows.Application; using Control = System.Windows.Controls.Control; @@ -20,6 +22,8 @@ public class Main : IPlugin, ISettingProvider, IPluginI18n private PluginInitContext context; private Dictionary KeywordTitleMappings = new Dictionary(); + private const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege"; + public Control CreateSettingPanel() { var results = Commands(); @@ -100,6 +104,44 @@ public void Init(PluginInitContext context) }; } + private static unsafe bool EnableShutdownPrivilege() + { + try + { + if (!PInvoke.OpenProcessToken(Process.GetCurrentProcess().SafeHandle, TOKEN_ACCESS_MASK.TOKEN_ADJUST_PRIVILEGES | TOKEN_ACCESS_MASK.TOKEN_QUERY, out var tokenHandle)) + { + return false; + } + + if (!PInvoke.LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, out var luid)) + { + return false; + } + + var privileges = new TOKEN_PRIVILEGES + { + PrivilegeCount = 1, + Privileges = new() { e0 = new LUID_AND_ATTRIBUTES { Luid = luid, Attributes = TOKEN_PRIVILEGES_ATTRIBUTES.SE_PRIVILEGE_ENABLED } } + }; + + if (!PInvoke.AdjustTokenPrivileges(tokenHandle, false, &privileges, 0, null, null)) + { + return false; + } + + if (Marshal.GetLastWin32Error() != (int)WIN32_ERROR.NO_ERROR) + { + return false; + } + + return true; + } + catch (Exception) + { + return false; + } + } + private List Commands() { var results = new List(); @@ -125,8 +167,11 @@ private List Commands() // software updates, or other predefined reasons. // SHTDN_REASON_FLAG_PLANNED marks the shutdown as planned rather than an unexpected shutdown or failure if (result == MessageBoxResult.Yes) - PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_SHUTDOWN | EXIT_WINDOWS_FLAGS.EWX_POWEROFF, - SHUTDOWN_REASON.SHTDN_REASON_MAJOR_OTHER | SHUTDOWN_REASON.SHTDN_REASON_FLAG_PLANNED); + if (EnableShutdownPrivilege()) + PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_SHUTDOWN | EXIT_WINDOWS_FLAGS.EWX_POWEROFF, + SHUTDOWN_REASON.SHTDN_REASON_MAJOR_OTHER | SHUTDOWN_REASON.SHTDN_REASON_FLAG_PLANNED); + else + Process.Start("shutdown", "/s /t 0"); return true; } @@ -145,8 +190,11 @@ private List Commands() MessageBoxButton.YesNo, MessageBoxImage.Warning); if (result == MessageBoxResult.Yes) - PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_REBOOT, - SHUTDOWN_REASON.SHTDN_REASON_MAJOR_OTHER | SHUTDOWN_REASON.SHTDN_REASON_FLAG_PLANNED); + if (EnableShutdownPrivilege()) + PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_REBOOT, + SHUTDOWN_REASON.SHTDN_REASON_MAJOR_OTHER | SHUTDOWN_REASON.SHTDN_REASON_FLAG_PLANNED); + else + Process.Start("shutdown", "/r /t 0"); return true; } @@ -165,8 +213,11 @@ private List Commands() MessageBoxButton.YesNo, MessageBoxImage.Warning); if (result == MessageBoxResult.Yes) - PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_REBOOT | EXIT_WINDOWS_FLAGS.EWX_BOOTOPTIONS, - SHUTDOWN_REASON.SHTDN_REASON_MAJOR_OTHER | SHUTDOWN_REASON.SHTDN_REASON_FLAG_PLANNED); + if (EnableShutdownPrivilege()) + PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_REBOOT | EXIT_WINDOWS_FLAGS.EWX_BOOTOPTIONS, + SHUTDOWN_REASON.SHTDN_REASON_MAJOR_OTHER | SHUTDOWN_REASON.SHTDN_REASON_FLAG_PLANNED); + else + Process.Start("shutdown", "/r /o /t 0"); return true; } diff --git a/Plugins/Flow.Launcher.Plugin.Sys/NativeMethods.txt b/Plugins/Flow.Launcher.Plugin.Sys/NativeMethods.txt index 8fcb6cae91e..6159c725b2c 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/NativeMethods.txt +++ b/Plugins/Flow.Launcher.Plugin.Sys/NativeMethods.txt @@ -3,4 +3,9 @@ LockWorkStation SHEmptyRecycleBin S_OK E_UNEXPECTED -SetSuspendState \ No newline at end of file +SetSuspendState +OpenProcessToken +WIN32_ERROR +LookupPrivilegeValue +AdjustTokenPrivileges +TOKEN_PRIVILEGES \ No newline at end of file From 648e3f268990c6da85eef377d5d1b5bc97dc438b Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 18 Feb 2025 11:07:18 +0800 Subject: [PATCH 5/7] Improve code quality --- Plugins/Flow.Launcher.Plugin.Sys/Main.cs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs index 7d3f66746da..f6117aab912 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs @@ -23,6 +23,9 @@ public class Main : IPlugin, ISettingProvider, IPluginI18n private Dictionary KeywordTitleMappings = new Dictionary(); private const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege"; + // SHTDN_REASON_MAJOR_OTHER indicates a generic shutdown reason that isn't categorized under hardware failure, software updates, or other predefined reasons. + // SHTDN_REASON_FLAG_PLANNED marks the shutdown as planned rather than an unexpected shutdown or failure + private const SHUTDOWN_REASON REASON = SHUTDOWN_REASON.SHTDN_REASON_MAJOR_OTHER | SHUTDOWN_REASON.SHTDN_REASON_FLAG_PLANNED; public Control CreateSettingPanel() { @@ -163,13 +166,9 @@ private List Commands() context.API.GetTranslation("flowlauncher_plugin_sys_shutdown_computer"), MessageBoxButton.YesNo, MessageBoxImage.Warning); - // SHTDN_REASON_MAJOR_OTHER indicates a generic shutdown reason that isn't categorized under hardware failure, - // software updates, or other predefined reasons. - // SHTDN_REASON_FLAG_PLANNED marks the shutdown as planned rather than an unexpected shutdown or failure if (result == MessageBoxResult.Yes) if (EnableShutdownPrivilege()) - PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_SHUTDOWN | EXIT_WINDOWS_FLAGS.EWX_POWEROFF, - SHUTDOWN_REASON.SHTDN_REASON_MAJOR_OTHER | SHUTDOWN_REASON.SHTDN_REASON_FLAG_PLANNED); + PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_SHUTDOWN | EXIT_WINDOWS_FLAGS.EWX_POWEROFF, REASON); else Process.Start("shutdown", "/s /t 0"); @@ -191,8 +190,7 @@ private List Commands() if (result == MessageBoxResult.Yes) if (EnableShutdownPrivilege()) - PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_REBOOT, - SHUTDOWN_REASON.SHTDN_REASON_MAJOR_OTHER | SHUTDOWN_REASON.SHTDN_REASON_FLAG_PLANNED); + PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_REBOOT, REASON); else Process.Start("shutdown", "/r /t 0"); @@ -214,8 +212,7 @@ private List Commands() if (result == MessageBoxResult.Yes) if (EnableShutdownPrivilege()) - PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_REBOOT | EXIT_WINDOWS_FLAGS.EWX_BOOTOPTIONS, - SHUTDOWN_REASON.SHTDN_REASON_MAJOR_OTHER | SHUTDOWN_REASON.SHTDN_REASON_FLAG_PLANNED); + PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_REBOOT | EXIT_WINDOWS_FLAGS.EWX_BOOTOPTIONS, REASON); else Process.Start("shutdown", "/r /o /t 0"); @@ -236,8 +233,7 @@ private List Commands() MessageBoxButton.YesNo, MessageBoxImage.Warning); if (result == MessageBoxResult.Yes) - PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_LOGOFF, - SHUTDOWN_REASON.SHTDN_REASON_MAJOR_OTHER | SHUTDOWN_REASON.SHTDN_REASON_FLAG_PLANNED); + PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_LOGOFF, REASON); return true; } From a065179d53aee2146e633e0bf2db2ad3ccd066f6 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 18 Feb 2025 11:12:33 +0800 Subject: [PATCH 6/7] Use PInvoke for const --- Plugins/Flow.Launcher.Plugin.Sys/Main.cs | 3 +-- Plugins/Flow.Launcher.Plugin.Sys/NativeMethods.txt | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs index f6117aab912..3bda99e7125 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs @@ -22,7 +22,6 @@ public class Main : IPlugin, ISettingProvider, IPluginI18n private PluginInitContext context; private Dictionary KeywordTitleMappings = new Dictionary(); - private const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege"; // SHTDN_REASON_MAJOR_OTHER indicates a generic shutdown reason that isn't categorized under hardware failure, software updates, or other predefined reasons. // SHTDN_REASON_FLAG_PLANNED marks the shutdown as planned rather than an unexpected shutdown or failure private const SHUTDOWN_REASON REASON = SHUTDOWN_REASON.SHTDN_REASON_MAJOR_OTHER | SHUTDOWN_REASON.SHTDN_REASON_FLAG_PLANNED; @@ -116,7 +115,7 @@ private static unsafe bool EnableShutdownPrivilege() return false; } - if (!PInvoke.LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, out var luid)) + if (!PInvoke.LookupPrivilegeValue(null, PInvoke.SE_SHUTDOWN_NAME, out var luid)) { return false; } diff --git a/Plugins/Flow.Launcher.Plugin.Sys/NativeMethods.txt b/Plugins/Flow.Launcher.Plugin.Sys/NativeMethods.txt index 6159c725b2c..4567e46a384 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/NativeMethods.txt +++ b/Plugins/Flow.Launcher.Plugin.Sys/NativeMethods.txt @@ -8,4 +8,5 @@ OpenProcessToken WIN32_ERROR LookupPrivilegeValue AdjustTokenPrivileges -TOKEN_PRIVILEGES \ No newline at end of file +TOKEN_PRIVILEGES +SE_SHUTDOWN_NAME \ No newline at end of file From 3bd4ca4105840ab4a679a21817148ade91660263 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 18 Feb 2025 11:17:45 +0800 Subject: [PATCH 7/7] Replace hiberate with PInvoke --- Plugins/Flow.Launcher.Plugin.Sys/Main.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs index 3bda99e7125..e81d70c5246 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs @@ -269,12 +269,7 @@ private List Commands() IcoPath = "Images\\hibernate.png", Action= c => { - var info = ShellCommand.SetProcessStartInfo("shutdown", arguments:"/h"); - info.WindowStyle = ProcessWindowStyle.Hidden; - info.UseShellExecute = true; - - ShellCommand.Execute(info); - + PInvoke.SetSuspendState(true, false, false); return true; } },