| Index: chrome/installer/gcapi/gcapi.cc
|
| ===================================================================
|
| --- chrome/installer/gcapi/gcapi.cc (revision 112456)
|
| +++ chrome/installer/gcapi/gcapi.cc (working copy)
|
| @@ -10,8 +10,6 @@
|
|
|
| #include "chrome/installer/gcapi/gcapi.h"
|
|
|
| -#include <atlbase.h>
|
| -#include <atlcom.h>
|
| #include <sddl.h>
|
| #define STRSAFE_NO_DEPRECATE
|
| #include <strsafe.h>
|
| @@ -23,13 +21,26 @@
|
| #include <string>
|
|
|
| #include "base/basictypes.h"
|
| +#include "base/file_path.h"
|
| +#include "base/file_util.h"
|
| #include "base/string_number_conversions.h"
|
| #include "base/time.h"
|
| #include "base/win/registry.h"
|
| +#include "base/win/scoped_com_initializer.h"
|
| +#include "base/win/scoped_comptr.h"
|
| +#include "base/win/scoped_handle.h"
|
| #include "chrome/installer/util/google_update_constants.h"
|
| +#include "chrome/installer/util/util_constants.h"
|
|
|
| #include "google_update_idl.h" // NOLINT
|
|
|
| +using base::Time;
|
| +using base::TimeDelta;
|
| +using base::win::RegKey;
|
| +using base::win::ScopedCOMInitializer;
|
| +using base::win::ScopedComPtr;
|
| +using base::win::ScopedHandle;
|
| +
|
| namespace {
|
|
|
| const wchar_t kChromeRegClientsKey[] =
|
| @@ -48,6 +59,8 @@
|
| const wchar_t kNoChromeOfferUntil[] =
|
| L"SOFTWARE\\Google\\No Chrome Offer Until";
|
|
|
| +const wchar_t kChromeWindowClass[] = L"Chrome_WidgetWin_0";
|
| +
|
| // Return the company name specified in the file version info resource.
|
| bool GetCompanyName(const wchar_t* filename, wchar_t* buffer, DWORD out_len) {
|
| wchar_t file_version_info[8192];
|
| @@ -339,29 +352,49 @@
|
| }
|
|
|
| BOOL __stdcall LaunchGoogleChrome() {
|
| - wchar_t launch_cmd[MAX_PATH];
|
| - size_t size = _countof(launch_cmd);
|
| - if (!ReadValueFromRegistry(HKEY_LOCAL_MACHINE, kChromeRegClientStateKey,
|
| - kChromeRegLastLaunchCmd, launch_cmd, &size)) {
|
| - size = _countof(launch_cmd);
|
| - if (!ReadValueFromRegistry(HKEY_LOCAL_MACHINE, kChromeRegClientStateKey,
|
| - kChromeRegLaunchCmd, launch_cmd, &size)) {
|
| + // Check to make sure we have a valid Chrome installation.
|
| + HKEY install_key = HKEY_LOCAL_MACHINE;
|
| + if (!IsChromeInstalled(install_key)) {
|
| + install_key = HKEY_CURRENT_USER;
|
| + if (!IsChromeInstalled(install_key)) {
|
| return false;
|
| }
|
| }
|
|
|
| - HRESULT hr = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
| - if (hr != S_OK) {
|
| - if (hr == S_FALSE)
|
| - ::CoUninitialize();
|
| + // Now grab the uninstall string from the appropriate ClientState key
|
| + // and use that as the base for a path to chrome.exe.
|
| + FilePath chrome_exe_path;
|
| + RegKey client_state(install_key, kChromeRegClientStateKey, KEY_QUERY_VALUE);
|
| + if (client_state.Valid()) {
|
| + std::wstring uninstall_string;
|
| + if (client_state.ReadValue(installer::kUninstallStringField,
|
| + &uninstall_string) == ERROR_SUCCESS) {
|
| + // The uninstall path contains the path to setup.exe which is two levels
|
| + // down from chrome.exe. Move up two levels (plus one to drop the file
|
| + // name) and look for chrome.exe from there.
|
| + FilePath uninstall_path(uninstall_string);
|
| + chrome_exe_path = uninstall_path.DirName()
|
| + .DirName()
|
| + .DirName()
|
| + .Append(installer::kChromeExe);
|
| + if (!file_util::PathExists(chrome_exe_path)) {
|
| + // By way of mild future proofing, look up one to see if there's a
|
| + // chrome.exe in the version directory
|
| + chrome_exe_path =
|
| + uninstall_path.DirName().DirName().Append(installer::kChromeExe);
|
| + }
|
| + }
|
| + }
|
| +
|
| + if (!file_util::PathExists(chrome_exe_path)) {
|
| return false;
|
| }
|
|
|
| + ScopedCOMInitializer com_initializer;
|
| if (::CoInitializeSecurity(NULL, -1, NULL, NULL,
|
| RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
|
| RPC_C_IMP_LEVEL_IDENTIFY, NULL,
|
| EOAC_DYNAMIC_CLOAKING, NULL) != S_OK) {
|
| - ::CoUninitialize();
|
| return false;
|
| }
|
|
|
| @@ -369,7 +402,6 @@
|
| if (IsRunningElevated()) {
|
| wchar_t* curr_proc_sid;
|
| if (!GetUserIdForProcess(GetCurrentProcessId(), &curr_proc_sid)) {
|
| - ::CoUninitialize();
|
| return false;
|
| }
|
|
|
| @@ -377,16 +409,17 @@
|
| ::GetWindowThreadProcessId(::GetShellWindow(), &pid);
|
| if (pid <= 0) {
|
| ::LocalFree(curr_proc_sid);
|
| - ::CoUninitialize();
|
| return false;
|
| }
|
|
|
| wchar_t* exp_proc_sid;
|
| if (GetUserIdForProcess(pid, &exp_proc_sid)) {
|
| if (_wcsicmp(curr_proc_sid, exp_proc_sid) == 0) {
|
| - HANDLE process_handle = ::OpenProcess(
|
| - PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION, TRUE, pid);
|
| - if (process_handle != NULL) {
|
| + ScopedHandle process_handle(
|
| + ::OpenProcess(PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION,
|
| + TRUE,
|
| + pid));
|
| + if (process_handle.IsValid()) {
|
| HANDLE process_token = NULL;
|
| HANDLE user_token = NULL;
|
| if (::OpenProcessToken(process_handle, TOKEN_DUPLICATE | TOKEN_QUERY,
|
| @@ -403,7 +436,6 @@
|
| ::CloseHandle(user_token);
|
| if (process_token)
|
| ::CloseHandle(process_token);
|
| - ::CloseHandle(process_handle);
|
| }
|
| }
|
| ::LocalFree(exp_proc_sid);
|
| @@ -411,30 +443,30 @@
|
|
|
| ::LocalFree(curr_proc_sid);
|
| if (!impersonation_success) {
|
| - ::CoUninitialize();
|
| return false;
|
| }
|
| }
|
|
|
| bool ret = false;
|
| - CComPtr<IProcessLauncher> ipl;
|
| - if (!FAILED(ipl.CoCreateInstance(__uuidof(ProcessLauncherClass), NULL,
|
| + ScopedComPtr<IProcessLauncher> ipl;
|
| + if (SUCCEEDED(ipl.CreateInstance(__uuidof(ProcessLauncherClass),
|
| + NULL,
|
| CLSCTX_LOCAL_SERVER))) {
|
| - if (!FAILED(ipl->LaunchCmdLine(launch_cmd)))
|
| + if (SUCCEEDED(ipl->LaunchCmdLine(chrome_exe_path.value().c_str())))
|
| ret = true;
|
| ipl.Release();
|
| }
|
|
|
| if (impersonation_success)
|
| ::RevertToSelf();
|
| - ::CoUninitialize();
|
| return ret;
|
| }
|
|
|
| BOOL __stdcall LaunchGoogleChromeWithDimensions(int x,
|
| int y,
|
| int width,
|
| - int height) {
|
| + int height,
|
| + bool in_background) {
|
| if (!LaunchGoogleChrome())
|
| return false;
|
|
|
| @@ -445,7 +477,7 @@
|
| // yet. Wait for it to appear for 10 seconds, but exit if it takes longer
|
| // than that.
|
| while (!handle && seconds_elapsed < 10) {
|
| - handle = FindWindowEx(NULL, handle, L"Chrome_WindowImpl_0", NULL);
|
| + handle = FindWindowEx(NULL, handle, kChromeWindowClass, NULL);
|
| if (!handle) {
|
| Sleep(1000);
|
| seconds_elapsed++;
|
| @@ -459,21 +491,21 @@
|
| // but we only want the window that has child windows.
|
|
|
| // This loop iterates through all of the top-level Windows named
|
| - // Chrome_WindowImpl_0, and looks for the first one with any children.
|
| - while (handle && !FindWindowEx(handle, NULL, L"Chrome_WindowImpl_0", NULL)) {
|
| + // kChromeWindowClass, and looks for the first one with any children.
|
| + while (handle && !FindWindowEx(handle, NULL, kChromeWindowClass, NULL)) {
|
| // Get the next top-level Chrome window.
|
| - handle = FindWindowEx(NULL, handle, L"Chrome_WindowImpl_0", NULL);
|
| + handle = FindWindowEx(NULL, handle, kChromeWindowClass, NULL);
|
| }
|
|
|
| + HWND set_window_hwnd_insert_after = in_background ? HWND_BOTTOM : NULL;
|
| + DWORD set_window_flags = in_background ? SWP_NOACTIVATE : SWP_NOZORDER;
|
| +
|
| return (handle &&
|
| - SetWindowPos(handle, 0, x, y, width, height, SWP_NOZORDER));
|
| + SetWindowPos(handle, set_window_hwnd_insert_after, x, y,
|
| + width, height, set_window_flags));
|
| }
|
|
|
| int __stdcall GoogleChromeDaysSinceLastRun() {
|
| - using base::win::RegKey;
|
| - using base::Time;
|
| - using base::TimeDelta;
|
| -
|
| int days_since_last_run = std::numeric_limits<int>::max();
|
|
|
| struct {
|
|
|