From 5515b65ca26cba48ee887cb8a0d28ad4b172819b Mon Sep 17 00:00:00 2001 From: WindyValley <2519087323@qq.com> Date: Sun, 13 Oct 2024 11:25:15 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=BB=98=E8=AE=A4=E5=90=AF=E5=8A=A8?= =?UTF-8?q?=E4=B8=8D=E8=AF=B7=E6=B1=82=E7=AE=A1=E7=90=86=E5=91=98=E6=9D=83?= =?UTF-8?q?=E9=99=90=EF=BC=8C=E5=BF=85=E8=A6=81=E6=97=B6=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E5=91=98=E6=9D=83=E9=99=90=E9=87=8D=E5=90=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 写 HKCU 的命令不需要管理员权限,工程文件里的 RequireAdministrator 改为 AsInvoker - 调用 uninstall 和 install/CustomInstall 前判断一下进程的状态, 如果不是管理就提权重启 --- WeaselSetup/WeaselSetup.cpp | 57 +++++++++++++++++++++++++++++++-- WeaselSetup/WeaselSetup.vcxproj | 4 +-- WeaselSetup/xmake.lua | 2 +- 3 files changed, 58 insertions(+), 5 deletions(-) diff --git a/WeaselSetup/WeaselSetup.cpp b/WeaselSetup/WeaselSetup.cpp index 259af11f7..c330d2f77 100644 --- a/WeaselSetup/WeaselSetup.cpp +++ b/WeaselSetup/WeaselSetup.cpp @@ -14,6 +14,8 @@ CAppModule _Module; static int Run(LPTSTR lpCmdLine); +static bool IsProcAdmin(); +static int RestartAsAdmin(LPTSTR lpCmdLine); int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, @@ -138,8 +140,12 @@ static int Run(LPTSTR lpCmdLine) { constexpr bool silent = true; constexpr bool old_ime_support = false; bool uninstalling = !wcscmp(L"/u", lpCmdLine); - if (uninstalling) - return uninstall(silent); + if (uninstalling) { + if (IsProcAdmin()) + return uninstall(silent); + else + RestartAsAdmin(lpCmdLine); + } if (!wcscmp(L"/ls", lpCmdLine)) { return SetRegKeyValue(HKEY_CURRENT_USER, L"Software\\Rime\\weasel", @@ -177,6 +183,12 @@ static int Run(LPTSTR lpCmdLine) { return SetRegKeyValue(HKEY_CURRENT_USER, L"Software\\Rime\\weasel", L"UpdateChannel", L"release", REG_SZ); } + + if (!IsProcAdmin()) + { + return RestartAsAdmin(lpCmdLine); + } + bool hans = !wcscmp(L"/s", lpCmdLine); if (hans) return install(false, silent, old_ime_support); @@ -186,3 +198,44 @@ static int Run(LPTSTR lpCmdLine) { bool installing = !wcscmp(L"/i", lpCmdLine); return CustomInstall(installing); } + +// https://learn.microsoft.com/zh-cn/windows/win32/api/securitybaseapi/nf-securitybaseapi-checktokenmembership +bool IsProcAdmin() { + BOOL b = FALSE; + SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; + PSID AdministratorsGroup; + b = AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, + &AdministratorsGroup); + + if (b) { + if (!CheckTokenMembership(NULL, AdministratorsGroup, &b)) { + b = FALSE; + } + FreeSid(AdministratorsGroup); + } + + return (b); +} + +int RestartAsAdmin(LPTSTR lpCmdLine) { + SHELLEXECUTEINFO execInfo{0}; + TCHAR path[MAX_PATH]; + GetModuleFileName(GetModuleHandle(NULL), path, _countof(path)); + execInfo.lpFile = path; + execInfo.lpParameters = lpCmdLine; + execInfo.lpVerb = _T("runas"); + execInfo.cbSize = sizeof(execInfo); + execInfo.nShow = SW_SHOWNORMAL; + execInfo.fMask = SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS; + execInfo.hwnd = NULL; + execInfo.hProcess = NULL; + if (::ShellExecuteEx(&execInfo) && execInfo.hProcess != NULL) { + ::WaitForSingleObject(execInfo.hProcess, INFINITE); + DWORD dwExitCode = 0; + ::GetExitCodeProcess(execInfo.hProcess, &dwExitCode); + ::CloseHandle(execInfo.hProcess); + return dwExitCode; + } + return -1; +} diff --git a/WeaselSetup/WeaselSetup.vcxproj b/WeaselSetup/WeaselSetup.vcxproj index 5a2c76763..632bb0114 100644 --- a/WeaselSetup/WeaselSetup.vcxproj +++ b/WeaselSetup/WeaselSetup.vcxproj @@ -108,7 +108,7 @@ true Imm32.lib;Kernel32.lib;%(AdditionalDependencies) $(SolutionDir)output\$(ProjectName)$(TargetExt) - RequireAdministrator + AsInvoker @@ -155,4 +155,4 @@ - + \ No newline at end of file diff --git a/WeaselSetup/xmake.lua b/WeaselSetup/xmake.lua index 49439e8bd..865392e46 100644 --- a/WeaselSetup/xmake.lua +++ b/WeaselSetup/xmake.lua @@ -4,7 +4,7 @@ target("WeaselSetup") add_rules("add_rcfiles", "use_weaselconstants", "subwin") add_links("imm32", "kernel32") - set_policy("windows.manifest.uac", "admin") + set_policy("windows.manifest.uac", "invoker") add_files("$(projectdir)/PerMonitorHighDPIAware.manifest") add_ldflags("/DEBUG /OPT:REF /OPT:ICF /LARGEADDRESSAWARE /ERRORREPORT:QUEUE")