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 <ma...@apache.org>
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>

Reply via email to