This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-daemon.git
The following commit(s) were added to refs/heads/master by this push:
new 7219698 Refactoring UAC support so prunsrv does not always require
elevation
7219698 is described below
commit 7219698dfff088f12560970dd2d4468232a666fd
Author: Mark Thomas <[email protected]>
AuthorDate: Fri May 17 13:16:44 2024 +0100
Refactoring UAC support so prunsrv does not always require elevation
---
src/changes/changes.xml | 4 ++
src/native/windows/apps/prunsrv/prunsrv.c | 92 ++++++++++++++++++++++--
src/native/windows/apps/prunsrv/prunsrv.manifest | 4 --
3 files changed, 90 insertions(+), 10 deletions(-)
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 72d0b51..42515da 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -58,6 +58,10 @@
<action issue="DAEMON-463" dev="markt" type="fix" due-to="michaelo">
jsvc. Fix compilation issue with newer compilers.
</action>
+ <action dev="markt" type="fix">
+ Procrun. Refactor UAC support so that elevation is only requested for
+ actions that require administrator privileges.
+ </action>
<!-- Add -->
<action type="add" dev="markt">
Procrun. Add support for hybrid CRT builds.
diff --git a/src/native/windows/apps/prunsrv/prunsrv.c
b/src/native/windows/apps/prunsrv/prunsrv.c
index c4dc990..10323d4 100644
--- a/src/native/windows/apps/prunsrv/prunsrv.c
+++ b/src/native/windows/apps/prunsrv/prunsrv.c
@@ -1936,6 +1936,64 @@ BOOL docmdRunService(LPAPXCMDLINE lpCmdline)
return rv;
}
+BOOL isRunningAsAdministrator(BOOL *bElevated) {
+ BOOL rv = FALSE;
+ HANDLE hToken;
+ TOKEN_ELEVATION tokenInformation;
+ DWORD dwSize;
+
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
+ goto cleanup;
+ }
+
+ if (!GetTokenInformation(hToken, TokenElevation, &tokenInformation,
sizeof(tokenInformation), &dwSize)) {
+ goto cleanup;
+ }
+
+ *bElevated = tokenInformation.TokenIsElevated;
+ rv = TRUE;
+
+cleanup:
+ if (hToken) {
+ CloseHandle(hToken);
+ }
+ return rv;
+}
+
+BOOL restartCurrentProcessWithElevation(DWORD *dwExitCode) {
+ BOOL rv = FALSE;
+ TCHAR szPath[MAX_PATH];
+ SHELLEXECUTEINFO shellExecuteInfo;
+
+ SetLastError(0);
+ GetModuleFileName(NULL, szPath, MAX_PATH);
+ if (GetLastError()) {
+ goto cleanup;
+ }
+
+ shellExecuteInfo.cbSize = sizeof(SHELLEXECUTEINFO);
+ shellExecuteInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
+ shellExecuteInfo.hwnd = NULL;
+ shellExecuteInfo.lpVerb = L"runas";
+ shellExecuteInfo.lpFile = szPath;
+ shellExecuteInfo.lpParameters = PathGetArgs(GetCommandLine());
+ shellExecuteInfo.lpDirectory = NULL;
+ shellExecuteInfo.nShow = SW_SHOWNORMAL;
+ shellExecuteInfo.hInstApp = NULL;
+
+ if (!ShellExecuteEx(&shellExecuteInfo)) {
+ goto cleanup;
+ }
+ WaitForSingleObject(shellExecuteInfo.hProcess, INFINITE);
+ GetExitCodeProcess(shellExecuteInfo.hProcess, dwExitCode);
+
+ rv = TRUE;
+
+cleanup:
+ return rv;
+}
+
+
static const char *gSzProc[] = {
"",
"parse command line arguments",
@@ -2039,6 +2097,28 @@ void __cdecl main(int argc, char **argv)
t.wYear, t.wMonth, t.wDay,
t.wHour, t.wMinute, t.wSecond);
}
+
+ if (lpCmdline->dwCmdIndex > 2 && lpCmdline->dwCmdIndex < 8) {
+ /* Command requires elevation */
+ BOOL bElevated;
+ if (!isRunningAsAdministrator(&bElevated)) {
+ apxDisplayError(FALSE, NULL, 0, "Unable to determine if process
has administrator privileges. Continuing as if it has.\n");
+ } else {
+ if (!bElevated) {
+ DWORD dwExitCode;
+ if (!restartCurrentProcessWithElevation(&dwExitCode)) {
+ apxDisplayError(FALSE, NULL, 0, "Failed to elevate current
process.\n");
+ rv = lpCmdline->dwCmdIndex + 2;
+ } else {
+ if (dwExitCode) {
+ apxDisplayError(FALSE, NULL, 0, "Running from a
command prompt with administrative privileges may show further error
details.\n");
+ }
+ rv = dwExitCode;
+ }
+ goto cleanup;
+ }
+ }
+ }
switch (lpCmdline->dwCmdIndex) {
case 1: /* Run Service as console application */
if (!docmdDebugService(lpCmdline))
@@ -2048,23 +2128,23 @@ void __cdecl main(int argc, char **argv)
if (!docmdRunService(lpCmdline))
rv = 4;
break;
- case 3: /* Start service */
+ case 3: /* Start service - requires elevation */
if (!docmdStartService(lpCmdline))
rv = 5;
break;
- case 4: /* Stop Service */
+ case 4: /* Stop Service - requires elevation */
if (!docmdStopService(lpCmdline))
rv = 6;
break;
- case 5: /* Update Service parameters */
+ case 5: /* Update Service parameters - requires elevation */
if (!docmdUpdateService(lpCmdline))
rv = 7;
break;
- case 6: /* Install Service */
+ case 6: /* Install Service - requires elevation */
if (!docmdInstallService(lpCmdline))
rv = 8;
break;
- case 7: /* Delete Service */
+ case 7: /* Delete Service - requires elevation */
if (!docmdDeleteService(lpCmdline))
rv = 9;
break;
@@ -2095,7 +2175,7 @@ cleanup:
rv, gSzProc[ix]);
if (ix > 2 && !_service_mode) {
/* Print something to the user console */
- apxDisplayError(FALSE, NULL, 0, "Failed to %s.", gSzProc[ix]);
+ apxDisplayError(FALSE, NULL, 0, "Failed to %s.\n", gSzProc[ix]);
}
}
else
diff --git a/src/native/windows/apps/prunsrv/prunsrv.manifest
b/src/native/windows/apps/prunsrv/prunsrv.manifest
index 204a914..431c5d1 100644
--- a/src/native/windows/apps/prunsrv/prunsrv.manifest
+++ b/src/native/windows/apps/prunsrv/prunsrv.manifest
@@ -25,10 +25,6 @@
</dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
-<!-- Windows UAC support -->
-<requestedPrivileges>
-<requestedExecutionLevel level="requireAdministrator"
uiAccess="false"></requestedExecutionLevel>
-</requestedPrivileges>
</security>
</trustInfo>
</assembly>