Wine starts processes non-elevated since e92ba2de43d7afbe0704b11b29f7c30f44dfaeca but some installers exit prematurely when not elevated.
The elevation mechanism is taken from 8cc22a60c304fc1398fab1ce8413b2b81fc2ccec.
Would this be an acceptable extension?
From: Roman Pišl rpisl@seznam.cz
Wine starts processes non-elevated since e92ba2de43d7afbe0704b11b29f7c30f44dfaeca but some installers exit prematurely when not elevated.
The elevation mechanism is taken from 8cc22a60c304fc1398fab1ce8413b2b81fc2ccec. --- programs/start/Makefile.in | 2 +- programs/start/start.c | 32 ++++++++++++++++++++++++++++---- programs/start/start.rc | 1 + 3 files changed, 30 insertions(+), 5 deletions(-)
diff --git a/programs/start/Makefile.in b/programs/start/Makefile.in index 927c4f3259f..f858ecca2a0 100644 --- a/programs/start/Makefile.in +++ b/programs/start/Makefile.in @@ -1,5 +1,5 @@ MODULE = start.exe -IMPORTS = shell32 user32 +IMPORTS = advapi32 shell32 user32
EXTRADLLFLAGS = -mconsole -municode
diff --git a/programs/start/start.c b/programs/start/start.c index c2e5850c291..a3a3c812208 100644 --- a/programs/start/start.c +++ b/programs/start/start.c @@ -195,6 +195,21 @@ static WCHAR *build_command_line( WCHAR **wargv ) return ret; }
+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; +} + static WCHAR *get_parent_dir(WCHAR* path) { WCHAR *last_slash; @@ -489,6 +504,8 @@ static void parse_command_line( int argc, WCHAR *argv[] ) unix_mode = TRUE; break; } + else if (is_option(argv[i], L"/elevate")) + opts.sei.lpVerb = L"runas"; else if (is_option(argv[i], L"/exec")) { opts.creation_flags = 0; opts.sei.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NO_CONSOLE | SEE_MASK_FLAG_NO_UI; @@ -559,6 +576,7 @@ int __cdecl wmain (int argc, WCHAR *argv[])
if (GetBinaryTypeW(opts.sei.lpFile, &binary_type)) { WCHAR *commandline; + HANDLE token = NULL; STARTUPINFOEXW si = {{ sizeof(si.StartupInfo) }}; PROCESS_INFORMATION process_information; int len = lstrlenW(opts.sei.lpFile) + 4 + lstrlenW(opts.sei.lpParameters); @@ -584,12 +602,18 @@ int __cdecl wmain (int argc, WCHAR *argv[]) si.StartupInfo.dwFlags |= STARTF_USESHOWWINDOW; si.StartupInfo.lpTitle = opts.title;
- if (!CreateProcessW( opts.sei.lpFile, commandline, NULL, NULL, opts.cp_inherit, - opts.creation_flags, NULL, opts.sei.lpDirectory, - &si.StartupInfo, &process_information )) + if (!wcsicmp(opts.sei.lpVerb, L"runas")) + token = get_admin_token(); + + if (!CreateProcessAsUserW(token, opts.sei.lpFile, commandline, NULL, NULL, opts.cp_inherit, + opts.creation_flags, NULL, opts.sei.lpDirectory, + &si.StartupInfo, &process_information )) { - fatal_string_error(STRING_EXECFAIL, GetLastError(), opts.sei.lpFile); + fatal_string_error(STRING_EXECFAIL, GetLastError(), opts.sei.lpFile); } + + CloseHandle(token); + opts.sei.hProcess = process_information.hProcess; goto done; } diff --git a/programs/start/start.rc b/programs/start/start.rc index 2a3f3e2ab61..eb7f4ad457f 100644 --- a/programs/start/start.rc +++ b/programs/start/start.rc @@ -51,6 +51,7 @@ Options:\n\ /wait Wait for the program to finish, then exit with its exit code.\n\ /unix Use a Unix filename and start the file like Windows Explorer.\n\ /exec Exec the specified file (for internal Wine usage).\n\ +/elevate Start the program with administrator privileges.\n\ /ProgIDOpen Open a document using the specified progID.\n\ /? Display this help and exit.\n"