14
14
CAppModule _Module;
15
15
16
16
static int Run (LPTSTR lpCmdLine);
17
+ static bool IsProcAdmin ();
18
+ static int RestartAsAdmin (LPTSTR lpCmdLine);
17
19
18
20
int WINAPI _tWinMain (HINSTANCE hInstance,
19
21
HINSTANCE /* hPrevInstance*/ ,
@@ -138,8 +140,12 @@ static int Run(LPTSTR lpCmdLine) {
138
140
constexpr bool silent = true ;
139
141
constexpr bool old_ime_support = false ;
140
142
bool uninstalling = !wcscmp (L" /u" , lpCmdLine);
141
- if (uninstalling)
142
- return uninstall (silent);
143
+ if (uninstalling) {
144
+ if (IsProcAdmin ())
145
+ return uninstall (silent);
146
+ else
147
+ return RestartAsAdmin (lpCmdLine);
148
+ }
143
149
144
150
if (!wcscmp (L" /ls" , lpCmdLine)) {
145
151
return SetRegKeyValue (HKEY_CURRENT_USER, L" Software\\ Rime\\ weasel" ,
@@ -177,6 +183,11 @@ static int Run(LPTSTR lpCmdLine) {
177
183
return SetRegKeyValue (HKEY_CURRENT_USER, L" Software\\ Rime\\ weasel" ,
178
184
L" UpdateChannel" , L" release" , REG_SZ);
179
185
}
186
+
187
+ if (!IsProcAdmin ()) {
188
+ return RestartAsAdmin (lpCmdLine);
189
+ }
190
+
180
191
bool hans = !wcscmp (L" /s" , lpCmdLine);
181
192
if (hans)
182
193
return install (false , silent, old_ime_support);
@@ -186,3 +197,44 @@ static int Run(LPTSTR lpCmdLine) {
186
197
bool installing = !wcscmp (L" /i" , lpCmdLine);
187
198
return CustomInstall (installing);
188
199
}
200
+
201
+ // https://learn.microsoft.com/zh-cn/windows/win32/api/securitybaseapi/nf-securitybaseapi-checktokenmembership
202
+ bool IsProcAdmin () {
203
+ BOOL b = FALSE ;
204
+ SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
205
+ PSID AdministratorsGroup;
206
+ b = AllocateAndInitializeSid (&NtAuthority, 2 , SECURITY_BUILTIN_DOMAIN_RID,
207
+ DOMAIN_ALIAS_RID_ADMINS, 0 , 0 , 0 , 0 , 0 , 0 ,
208
+ &AdministratorsGroup);
209
+
210
+ if (b) {
211
+ if (!CheckTokenMembership (NULL , AdministratorsGroup, &b)) {
212
+ b = FALSE ;
213
+ }
214
+ FreeSid (AdministratorsGroup);
215
+ }
216
+
217
+ return (b);
218
+ }
219
+
220
+ int RestartAsAdmin (LPTSTR lpCmdLine) {
221
+ SHELLEXECUTEINFO execInfo{0 };
222
+ TCHAR path[MAX_PATH];
223
+ GetModuleFileName (GetModuleHandle (NULL ), path, _countof (path));
224
+ execInfo.lpFile = path;
225
+ execInfo.lpParameters = lpCmdLine;
226
+ execInfo.lpVerb = _T (" runas" );
227
+ execInfo.cbSize = sizeof (execInfo);
228
+ execInfo.nShow = SW_SHOWNORMAL;
229
+ execInfo.fMask = SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS;
230
+ execInfo.hwnd = NULL ;
231
+ execInfo.hProcess = NULL ;
232
+ if (::ShellExecuteEx (&execInfo) && execInfo.hProcess != NULL ) {
233
+ ::WaitForSingleObject (execInfo.hProcess, INFINITE);
234
+ DWORD dwExitCode = 0 ;
235
+ ::GetExitCodeProcess (execInfo.hProcess, &dwExitCode);
236
+ ::CloseHandle (execInfo.hProcess);
237
+ return dwExitCode;
238
+ }
239
+ return -1 ;
240
+ }
0 commit comments