diff options
author | erikwright@chromium.org <erikwright@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-01-24 19:14:11 +0000 |
---|---|---|
committer | erikwright@chromium.org <erikwright@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-01-24 19:14:11 +0000 |
commit | efd97484dbba5faec394693002228a1f0e2c2f82 (patch) | |
tree | fcf94e84e1dc8213debb308fc4c405738eac3543 /chrome_frame/update_launcher.cc | |
parent | 30aa3ee0461f0475180d50d4adc4b925fe7e1315 (diff) | |
download | chromium_src-efd97484dbba5faec394693002228a1f0e2c2f82.zip chromium_src-efd97484dbba5faec394693002228a1f0e2c2f82.tar.gz chromium_src-efd97484dbba5faec394693002228a1f0e2c2f82.tar.bz2 |
When changing Ready Mode state from within an IE process, use chrome_launcher to invoke the ProcessLauncher, so as to not cause a UAC prompt (chrome_launcher is permitted via elevation policy).
BUG=None
TEST=Install GCF in Ready Mode on Vista, interact with it.
Review URL: http://codereview.chromium.org/6355011
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@72361 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame/update_launcher.cc')
-rw-r--r-- | chrome_frame/update_launcher.cc | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/chrome_frame/update_launcher.cc b/chrome_frame/update_launcher.cc new file mode 100644 index 0000000..2aff8ad --- /dev/null +++ b/chrome_frame/update_launcher.cc @@ -0,0 +1,94 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome_frame/update_launcher.h" + +#include <windows.h> +#include <Shellapi.h> + +#include "google_update_idl.h" // NOLINT + +namespace { + +const wchar_t kChromeFrameGuid[] = L"{8BA986DA-5100-405E-AA35-86F34A02ACBF}"; + +const DWORD kLaunchFailureExitCode = 0xFF; + +const wchar_t kUpdateCommandFlag[] = L"--update-cmd"; + +// Waits indefinitely for the provided process to exit. Returns the process's +// exit code, or kLaunchFailureExitCode if an error occurs in the waiting. +DWORD WaitForProcessExitCode(HANDLE handle) { + DWORD exit_code = 0; + + DWORD wait_result = ::WaitForSingleObject(handle, INFINITE); + + if (wait_result == WAIT_OBJECT_0 && ::GetExitCodeProcess(handle, &exit_code)) + return exit_code; + + return kLaunchFailureExitCode; +} + +} // namespace + +namespace update_launcher { + +std::wstring GetUpdateCommandFromArguments(const wchar_t* command_line) { + std::wstring command; + + if (command_line != NULL) { + int num_args = 0; + wchar_t** args = NULL; + args = ::CommandLineToArgvW(command_line, &num_args); + + if (args) { + if (num_args == 3 && _wcsicmp(args[1], kUpdateCommandFlag) == 0) + command = args[2]; + ::LocalFree(args); + } + } + + return command; +} + +// Because we do not have 'base' and all of its pretty RAII helpers, please +// ensure that this function only ever contains a single 'return', in order +// to reduce the chance of introducing a leak. +DWORD LaunchUpdateCommand(const std::wstring& command) { + DWORD exit_code = kLaunchFailureExitCode; + + HRESULT hr = ::CoInitialize(NULL); + + if (SUCCEEDED(hr)) { + IProcessLauncher* ipl = NULL; + HANDLE process = NULL; + + hr = ::CoCreateInstance(__uuidof(ProcessLauncherClass), NULL, + CLSCTX_ALL, __uuidof(IProcessLauncher), + reinterpret_cast<void**>(&ipl)); + + if (SUCCEEDED(hr)) { + ULONG_PTR phandle = NULL; + DWORD id = ::GetCurrentProcessId(); + + hr = ipl->LaunchCmdElevated(kChromeFrameGuid, + command.c_str(), id, &phandle); + if (SUCCEEDED(hr)) { + process = reinterpret_cast<HANDLE>(phandle); + exit_code = WaitForProcessExitCode(process); + } + } + + if (process) + ::CloseHandle(process); + if (ipl) + ipl->Release(); + + ::CoUninitialize(); + } + + return exit_code; +} + +} // namespace process_launcher |