From: Zebediah Figura z.figura12@gmail.com
Like all other verbs, the actual command line template is specified in the registry. The elevation seems to be hardcoded into shell32 for this specific verb.
The Foobar2000 installer requires administrator privileges, and elevates itself in this way.
Based on a patch by Michael Müller.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50727 --- dlls/shell32/shlexec.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-)
diff --git a/dlls/shell32/shlexec.c b/dlls/shell32/shlexec.c index eb9ca4a06df..f0dbb984103 100644 --- a/dlls/shell32/shlexec.c +++ b/dlls/shell32/shlexec.c @@ -293,6 +293,21 @@ static HRESULT SHELL_GetPathFromIDListForExecuteW(LPCITEMIDLIST pidl, LPWSTR psz return hr; }
+static HANDLE get_admin_token(void) +{ + TOKEN_ELEVATION_TYPE type; + TOKEN_LINKED_TOKEN linked; + DWORD size; + + if (!GetTokenInformation(GetCurrentThreadEffectiveToken(), TokenElevationType, &type, sizeof(type), &size) + || type == TokenElevationTypeFull) + return NULL; + + if (!GetTokenInformation(GetCurrentThreadEffectiveToken(), TokenLinkedToken, &linked, sizeof(linked), &size)) + return NULL; + return linked.LinkedToken; +} + /************************************************************************* * SHELL_ExecuteW [Internal] * @@ -306,6 +321,7 @@ static UINT_PTR SHELL_ExecuteW(const WCHAR *lpCmd, WCHAR *env, BOOL shWait, UINT gcdret = 0; WCHAR curdir[MAX_PATH]; DWORD dwCreationFlags; + HANDLE token = NULL;
TRACE("Execute %s from directory %s\n", debugstr_w(lpCmd), debugstr_w(psei->lpDirectory));
@@ -327,8 +343,12 @@ 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, - NULL, &startup, &info)) + + if (psei->lpVerb && !wcsicmp(psei->lpVerb, L"runas")) + token = get_admin_token(); + + if (CreateProcessAsUserW(token, NULL, (LPWSTR)lpCmd, NULL, NULL, FALSE, + dwCreationFlags, env, NULL, &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. */ @@ -348,6 +368,8 @@ static UINT_PTR SHELL_ExecuteW(const WCHAR *lpCmd, WCHAR *env, BOOL shWait, retval = ERROR_BAD_FORMAT; }
+ CloseHandle(token); + TRACE("returning %Iu\n", retval);
psei_out->hInstApp = (HINSTANCE)retval;