From cf24ca0854a5b0dca2055f0991fd9a932125c65e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Sat, 5 Aug 2017 02:03:20 +0200
Subject: shell32: Implement process elevation using runas verb.

---
 dlls/shell32/shlexec.c | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/dlls/shell32/shlexec.c b/dlls/shell32/shlexec.c
index 0cf112b6373..af50078dbca 100644
--- a/dlls/shell32/shlexec.c
+++ b/dlls/shell32/shlexec.c
@@ -50,6 +50,8 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(exec);
 
+extern HANDLE CDECL __wine_create_default_token(BOOL admin);
+
 static const WCHAR wszOpen[] = {'o','p','e','n',0};
 static const WCHAR wszExe[] = {'.','e','x','e',0};
 static const WCHAR wszILPtr[] = {':','%','p',0};
@@ -312,6 +314,8 @@ static HRESULT SHELL_GetPathFromIDListForExecuteW(LPCITEMIDLIST pidl, LPWSTR psz
 static UINT_PTR SHELL_ExecuteW(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
 			    const SHELLEXECUTEINFOW *psei, LPSHELLEXECUTEINFOW psei_out)
 {
+    static WCHAR runasW[] = {'r','u','n','a','s',0};
+    HANDLE token = NULL;
     STARTUPINFOW  startup;
     PROCESS_INFORMATION info;
     UINT_PTR retval = SE_ERR_NOASSOC;
@@ -344,8 +348,20 @@ static UINT_PTR SHELL_ExecuteW(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
     dwCreationFlags = CREATE_UNICODE_ENVIRONMENT;
     if (!(psei->fMask & SEE_MASK_NO_CONSOLE))
         dwCreationFlags |= CREATE_NEW_CONSOLE;
-    if (CreateProcessW(NULL, (LPWSTR)lpCmd, NULL, NULL, FALSE, dwCreationFlags, env,
-                       lpDirectory, &startup, &info))
+
+    /* Spawning a process with runas verb means that the process should be
+     * executed with admin rights. This function ignores the manifest data,
+     * and allows programs to elevate rights on-demand. On Windows a complex
+     * RPC menchanism is used, using CreateProcessAsUser would fail because
+     * it can only be used to drop rights. */
+    if (psei->lpVerb && !strcmpiW(psei->lpVerb, runasW))
+    {
+        if (!(token = __wine_create_default_token(TRUE)))
+            ERR("Failed to create admin token\n");
+    }
+
+    if (CreateProcessAsUserW(token, NULL, (LPWSTR)lpCmd, NULL, NULL, FALSE,
+                             dwCreationFlags, env, lpDirectory, &startup, &info))
     {
         /* Give 30 seconds to the app to come up, if desired. Probably only needed
            when starting app immediately before making a DDE connection. */
@@ -365,6 +381,8 @@ static UINT_PTR SHELL_ExecuteW(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
         retval = ERROR_BAD_FORMAT;
     }
 
+    if (token) CloseHandle(token);
+
     TRACE("returning %lu\n", retval);
 
     psei_out->hInstApp = (HINSTANCE)retval;
-- 
2.13.1

