Skip to content

Commit 1809314

Browse files
committed
Enable shutdown privilege before calling PInvoke for shutdown and start
1 parent e93699b commit 1809314

File tree

2 files changed

+63
-7
lines changed

2 files changed

+63
-7
lines changed

Plugins/Flow.Launcher.Plugin.Sys/Main.cs

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22
using System.Collections.Generic;
33
using System.Diagnostics;
44
using System.IO;
5+
using System.Runtime.InteropServices;
56
using System.Windows;
67
using Flow.Launcher.Infrastructure;
78
using Flow.Launcher.Infrastructure.Logger;
89
using Flow.Launcher.Infrastructure.UserSettings;
910
using Flow.Launcher.Plugin.SharedCommands;
1011
using Windows.Win32;
1112
using Windows.Win32.Foundation;
13+
using Windows.Win32.Security;
1214
using Windows.Win32.System.Shutdown;
1315
using Application = System.Windows.Application;
1416
using Control = System.Windows.Controls.Control;
@@ -20,6 +22,8 @@ public class Main : IPlugin, ISettingProvider, IPluginI18n
2022
private PluginInitContext context;
2123
private Dictionary<string, string> KeywordTitleMappings = new Dictionary<string, string>();
2224

25+
private const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
26+
2327
public Control CreateSettingPanel()
2428
{
2529
var results = Commands();
@@ -100,6 +104,44 @@ public void Init(PluginInitContext context)
100104
};
101105
}
102106

107+
private static unsafe bool EnableShutdownPrivilege()
108+
{
109+
try
110+
{
111+
if (!PInvoke.OpenProcessToken(Process.GetCurrentProcess().SafeHandle, TOKEN_ACCESS_MASK.TOKEN_ADJUST_PRIVILEGES | TOKEN_ACCESS_MASK.TOKEN_QUERY, out var tokenHandle))
112+
{
113+
return false;
114+
}
115+
116+
if (!PInvoke.LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, out var luid))
117+
{
118+
return false;
119+
}
120+
121+
var privileges = new TOKEN_PRIVILEGES
122+
{
123+
PrivilegeCount = 1,
124+
Privileges = new() { e0 = new LUID_AND_ATTRIBUTES { Luid = luid, Attributes = TOKEN_PRIVILEGES_ATTRIBUTES.SE_PRIVILEGE_ENABLED } }
125+
};
126+
127+
if (!PInvoke.AdjustTokenPrivileges(tokenHandle, false, &privileges, 0, null, null))
128+
{
129+
return false;
130+
}
131+
132+
if (Marshal.GetLastWin32Error() != (int)WIN32_ERROR.NO_ERROR)
133+
{
134+
return false;
135+
}
136+
137+
return true;
138+
}
139+
catch (Exception)
140+
{
141+
return false;
142+
}
143+
}
144+
103145
private List<Result> Commands()
104146
{
105147
var results = new List<Result>();
@@ -125,8 +167,11 @@ private List<Result> Commands()
125167
// software updates, or other predefined reasons.
126168
// SHTDN_REASON_FLAG_PLANNED marks the shutdown as planned rather than an unexpected shutdown or failure
127169
if (result == MessageBoxResult.Yes)
128-
PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_SHUTDOWN | EXIT_WINDOWS_FLAGS.EWX_POWEROFF,
129-
SHUTDOWN_REASON.SHTDN_REASON_MAJOR_OTHER | SHUTDOWN_REASON.SHTDN_REASON_FLAG_PLANNED);
170+
if (EnableShutdownPrivilege())
171+
PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_SHUTDOWN | EXIT_WINDOWS_FLAGS.EWX_POWEROFF,
172+
SHUTDOWN_REASON.SHTDN_REASON_MAJOR_OTHER | SHUTDOWN_REASON.SHTDN_REASON_FLAG_PLANNED);
173+
else
174+
Process.Start("shutdown", "/s /t 0");
130175

131176
return true;
132177
}
@@ -145,8 +190,11 @@ private List<Result> Commands()
145190
MessageBoxButton.YesNo, MessageBoxImage.Warning);
146191

147192
if (result == MessageBoxResult.Yes)
148-
PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_REBOOT,
149-
SHUTDOWN_REASON.SHTDN_REASON_MAJOR_OTHER | SHUTDOWN_REASON.SHTDN_REASON_FLAG_PLANNED);
193+
if (EnableShutdownPrivilege())
194+
PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_REBOOT,
195+
SHUTDOWN_REASON.SHTDN_REASON_MAJOR_OTHER | SHUTDOWN_REASON.SHTDN_REASON_FLAG_PLANNED);
196+
else
197+
Process.Start("shutdown", "/r /t 0");
150198

151199
return true;
152200
}
@@ -165,8 +213,11 @@ private List<Result> Commands()
165213
MessageBoxButton.YesNo, MessageBoxImage.Warning);
166214

167215
if (result == MessageBoxResult.Yes)
168-
PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_REBOOT | EXIT_WINDOWS_FLAGS.EWX_BOOTOPTIONS,
169-
SHUTDOWN_REASON.SHTDN_REASON_MAJOR_OTHER | SHUTDOWN_REASON.SHTDN_REASON_FLAG_PLANNED);
216+
if (EnableShutdownPrivilege())
217+
PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_REBOOT | EXIT_WINDOWS_FLAGS.EWX_BOOTOPTIONS,
218+
SHUTDOWN_REASON.SHTDN_REASON_MAJOR_OTHER | SHUTDOWN_REASON.SHTDN_REASON_FLAG_PLANNED);
219+
else
220+
Process.Start("shutdown", "/r /o /t 0");
170221

171222
return true;
172223
}

Plugins/Flow.Launcher.Plugin.Sys/NativeMethods.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,9 @@ LockWorkStation
33
SHEmptyRecycleBin
44
S_OK
55
E_UNEXPECTED
6-
SetSuspendState
6+
SetSuspendState
7+
OpenProcessToken
8+
WIN32_ERROR
9+
LookupPrivilegeValue
10+
AdjustTokenPrivileges
11+
TOKEN_PRIVILEGES

0 commit comments

Comments
 (0)