15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NOTE: This code is a legacy utility API for partners to check whether 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Chrome can be installed and launched. Recent updates are being made 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to add new functionality. These updates use code from Chromium, the old 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// coded against the win32 api directly. If you have an itch to shave a 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// yak, feel free to re-write the old code too. 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/gcapi/gcapi.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sddl.h> 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define STRSAFE_NO_DEPRECATE 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <windows.h> 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <strsafe.h> 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <tlhelp32.h> 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cstdlib> 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <iterator> 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits> 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/command_line.h" 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 28a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "base/process/launch.h" 297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string16.h" 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_util.h" 32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/registry.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_com_initializer.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_comptr.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_handle.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/gcapi/gcapi_omaha_experiment.h" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/gcapi/gcapi_reactivation.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/launcher_support/chrome_launcher_support.h" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/google_update_constants.h" 413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/installer/util/google_update_settings.h" 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/util_constants.h" 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/installer/util/wmi.h" 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_update/google_update_idl.h" 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::Time; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeDelta; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::win::RegKey; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::win::ScopedCOMInitializer; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::win::ScopedComPtr; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::win::ScopedHandle; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kChromeRegClientsKey[] = 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) L"Software\\Google\\Update\\Clients\\" 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) L"{8A69D345-D564-463c-AFF1-A69D9E530F96}"; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kChromeRegClientStateKey[] = 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) L"Software\\Google\\Update\\ClientState\\" 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) L"{8A69D345-D564-463c-AFF1-A69D9E530F96}"; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kChromeRegClientStateMediumKey[] = 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) L"Software\\Google\\Update\\ClientStateMedium\\" 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) L"{8A69D345-D564-463c-AFF1-A69D9E530F96}"; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kGCAPITempKey[] = L"Software\\Google\\GCAPITemp"; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kChromeRegLaunchCmd[] = L"InstallerSuccessLaunchCmdLine"; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kChromeRegLastLaunchCmd[] = L"LastInstallerSuccessLaunchCmdLine"; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kChromeRegVersion[] = L"pv"; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kNoChromeOfferUntil[] = 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) L"SOFTWARE\\Google\\No Chrome Offer Until"; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const wchar_t kC1FPendingKey[] = 743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) L"Software\\Google\\Common\\Rlz\\Events\\C"; 753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const wchar_t kC1FSentKey[] = 763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) L"Software\\Google\\Common\\Rlz\\StatefulEvents\\C"; 773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const wchar_t kC1FKey[] = L"C1F"; 783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const wchar_t kRelaunchBrandcodeValue[] = L"RelaunchBrandcode"; 803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const wchar_t kRelaunchAllowedAfterValue[] = L"RelaunchAllowedAfter"; 813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Prefix used to match the window class for Chrome windows. 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kChromeWindowClassPrefix[] = L"Chrome_WidgetWin_"; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Return the company name specified in the file version info resource. 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetCompanyName(const wchar_t* filename, wchar_t* buffer, DWORD out_len) { 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t file_version_info[8192]; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD handle = 0; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD buffer_size = 0; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer_size = ::GetFileVersionInfoSize(filename, &handle); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cannot stats the file or our buffer size is too small (very unlikely). 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (buffer_size == 0 || buffer_size > _countof(file_version_info)) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer_size = _countof(file_version_info); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(file_version_info, 0, buffer_size); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!::GetFileVersionInfo(filename, handle, buffer_size, file_version_info)) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD data_len = 0; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LPVOID data = NULL; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Retrieve the language and codepage code if exists. 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer_size = 0; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!::VerQueryValue(file_version_info, TEXT("\\VarFileInfo\\Translation"), 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<LPVOID *>(&data), reinterpret_cast<UINT *>(&data_len))) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (data_len != 4) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t info_name[256]; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD lang = 0; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Formulate the string to retrieve the company name of the specific 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // language codepage. 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(&lang, data, 4); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::StringCchPrintf(info_name, _countof(info_name), 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) L"\\StringFileInfo\\%02X%02X%02X%02X\\CompanyName", 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (lang & 0xff00)>>8, (lang & 0xff), (lang & 0xff000000)>>24, 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (lang & 0xff0000)>>16); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_len = 0; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!::VerQueryValue(file_version_info, info_name, 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<LPVOID *>(&data), reinterpret_cast<UINT *>(&data_len))) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (data_len <= 0 || data_len >= (out_len / sizeof(wchar_t))) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(buffer, 0, out_len); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::StringCchCopyN(buffer, 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (out_len / sizeof(wchar_t)), 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const wchar_t*>(data), 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_len); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Offsets the current date by |months|. |months| must be between 0 and 12. 1373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// The returned date is in the YYYYMMDD format. 1383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)DWORD FormatDateOffsetByMonths(int months) { 1393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(months >= 0 && months <= 12); 1403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) SYSTEMTIME now; 1423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) GetLocalTime(&now); 1433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) now.wMonth += months; 1443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (now.wMonth > 12) { 1453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) now.wMonth -= 12; 1463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) now.wYear += 1; 1473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return now.wYear * 10000 + now.wMonth * 100 + now.wDay; 1503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Return true if we can re-offer Chrome; false, otherwise. 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Each partner can only offer Chrome once every six months. 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CanReOfferChrome(BOOL set_flag) { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t filename[MAX_PATH+1]; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t company[MAX_PATH]; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we cannot retrieve the version info of the executable or company 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // name, we allow the Chrome to be offered because there is no past 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // history to be found. 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (::GetModuleFileName(NULL, filename, MAX_PATH) == 0) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetCompanyName(filename, company, sizeof(company))) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool can_re_offer = true; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD disposition = 0; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HKEY key = NULL; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (::RegCreateKeyEx(HKEY_LOCAL_MACHINE, kNoChromeOfferUntil, 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, &key, &disposition) == ERROR_SUCCESS) { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get today's date, and format it as YYYYMMDD numeric value. 1733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DWORD today = FormatDateOffsetByMonths(0); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cannot re-offer, if the timer already exists and is not expired yet. 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD value_type = REG_DWORD; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD value_data = 0; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD value_length = sizeof(DWORD); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (::RegQueryValueEx(key, company, 0, &value_type, 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<LPBYTE>(&value_data), 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &value_length) == ERROR_SUCCESS && 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) REG_DWORD == value_type && 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value_data > today) { 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The time has not expired, we cannot offer Chrome. 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) can_re_offer = false; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Delete the old or invalid value. 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::RegDeleteValue(key, company); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (set_flag) { 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set expiration date for offer as six months from today, 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // represented as a YYYYMMDD numeric value. 1923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DWORD value = FormatDateOffsetByMonths(6); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::RegSetValueEx(key, company, 0, REG_DWORD, (LPBYTE)&value, 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(DWORD)); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::RegCloseKey(key); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return can_re_offer; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool IsChromeInstalled(HKEY root_key) { 2053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) RegKey key; 206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return key.Open(root_key, 207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) kChromeRegClientsKey, 208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) KEY_READ | KEY_WOW64_32KEY) == ERROR_SUCCESS && 2093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) key.HasValue(kChromeRegVersion); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Returns true if the |subkey| in |root| has the kC1FKey entry set to 1. 2133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool RegKeyHasC1F(HKEY root, const wchar_t* subkey) { 2143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) RegKey key; 2153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DWORD value; 216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return key.Open(root, subkey, KEY_READ | KEY_WOW64_32KEY) == ERROR_SUCCESS && 2173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) key.ReadValueDW(kC1FKey, &value) == ERROR_SUCCESS && 2183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) value == static_cast<DWORD>(1); 2193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 2203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool IsC1FSent() { 2223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // The C1F RLZ key can either be in HKCU or in HKLM (the HKLM RLZ key is made 2233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // readable to all-users via rlz_lib::CreateMachineState()) and can either be 2243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // in sent or pending state. Return true if there is a match for any of these 2253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // 4 states. 2263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return RegKeyHasC1F(HKEY_CURRENT_USER, kC1FSentKey) || 2273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) RegKeyHasC1F(HKEY_CURRENT_USER, kC1FPendingKey) || 2283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) RegKeyHasC1F(HKEY_LOCAL_MACHINE, kC1FSentKey) || 2293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) RegKeyHasC1F(HKEY_LOCAL_MACHINE, kC1FPendingKey); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum WindowsVersion { 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VERSION_BELOW_XP_SP2, 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VERSION_XP_SP2_UP_TO_VISTA, // "but not including" 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VERSION_VISTA_OR_HIGHER, 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WindowsVersion GetWindowsVersion() { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSVERSIONINFOEX version_info = { sizeof version_info }; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&version_info)); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Windows Vista is version 6.0. 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (version_info.dwMajorVersion >= 6) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return VERSION_VISTA_OR_HIGHER; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Windows XP is version 5.1. (5.2 is Windows Server 2003/XP Pro x64.) 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((version_info.dwMajorVersion < 5) || (version_info.dwMinorVersion < 1)) 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return VERSION_BELOW_XP_SP2; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For XP itself, we only support SP2 and above. 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ((version_info.dwMinorVersion > 1) || 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (version_info.wServicePackMajor >= 2)) ? 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VERSION_XP_SP2_UP_TO_VISTA : VERSION_BELOW_XP_SP2; 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note this function should not be called on old Windows versions where these 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Windows API are not available. We always invoke this function after checking 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that current OS is Vista or later. 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VerifyAdminGroup() { 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PSID Group; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BOOL check = ::AllocateAndInitializeSid(&NtAuthority, 2, 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECURITY_BUILTIN_DOMAIN_RID, 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 0, 0, 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &Group); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (check) { 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!::CheckTokenMembership(NULL, Group, &check)) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) check = FALSE; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::FreeSid(Group); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (check == TRUE); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VerifyHKLMAccess() { 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t str[] = L"test"; 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result = false; 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD disposition = 0; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HKEY key = NULL; 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (::RegCreateKeyEx(HKEY_LOCAL_MACHINE, kGCAPITempKey, 0, NULL, 281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) REG_OPTION_NON_VOLATILE, 282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) KEY_READ | KEY_WRITE | KEY_WOW64_32KEY, NULL, 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &key, &disposition) == ERROR_SUCCESS) { 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (::RegSetValueEx(key, str, 0, REG_SZ, (LPBYTE)str, 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (DWORD)lstrlen(str)) == ERROR_SUCCESS) { 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = true; 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RegDeleteValue(key, str); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RegCloseKey(key); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we create the main key, delete the entire key. 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (disposition == REG_CREATED_NEW_KEY) 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RegDeleteKey(HKEY_LOCAL_MACHINE, kGCAPITempKey); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsRunningElevated() { 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This method should be called only for Vista or later. 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((GetWindowsVersion() < VERSION_VISTA_OR_HIGHER) || 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !VerifyAdminGroup()) 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE process_token; 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!::OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &process_token)) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TOKEN_ELEVATION_TYPE elevation_type = TokenElevationTypeDefault; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD size_returned = 0; 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!::GetTokenInformation(process_token, TokenElevationType, 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &elevation_type, sizeof(elevation_type), 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &size_returned)) { 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::CloseHandle(process_token); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::CloseHandle(process_token); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (elevation_type == TokenElevationTypeFull); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetUserIdForProcess(size_t pid, wchar_t** user_sid) { 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE process_handle = ::OpenProcess(PROCESS_QUERY_INFORMATION, TRUE, pid); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (process_handle == NULL) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE process_token; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result = false; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (::OpenProcessToken(process_handle, TOKEN_QUERY, &process_token)) { 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD size = 0; 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::GetTokenInformation(process_token, TokenUser, NULL, 0, &size); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER || 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::GetLastError() == ERROR_SUCCESS) { 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD actual_size = 0; 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BYTE* token_user = new BYTE[size]; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((::GetTokenInformation(process_token, TokenUser, token_user, size, 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &actual_size)) && 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (actual_size <= size)) { 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PSID sid = reinterpret_cast<TOKEN_USER*>(token_user)->User.Sid; 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (::ConvertSidToStringSid(sid, user_sid)) 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = true; 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete[] token_user; 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::CloseHandle(process_token); 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::CloseHandle(process_handle); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct SetWindowPosParams { 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x; 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int y; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int width; 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int height; 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD flags; 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HWND window_insert_after; 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success; 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<HWND> shunted_hwnds; 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL CALLBACK ChromeWindowEnumProc(HWND hwnd, LPARAM lparam) { 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t window_class[MAX_PATH] = {}; 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetWindowPosParams* params = reinterpret_cast<SetWindowPosParams*>(lparam); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!params->shunted_hwnds.count(hwnd) && 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::GetClassName(hwnd, window_class, arraysize(window_class)) && 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartsWith(window_class, kChromeWindowClassPrefix, false) && 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::SetWindowPos(hwnd, params->window_insert_after, params->x, 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params->y, params->width, params->height, params->flags)) { 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params->shunted_hwnds.insert(hwnd); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params->success = true; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return TRUE to ensure we hit all possible top-level Chrome windows as per 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http://msdn.microsoft.com/en-us/library/windows/desktop/ms633498.aspx 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns true and populates |chrome_exe_path| with the path to chrome.exe if 3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// a valid installation can be found. 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GetGoogleChromePath(base::FilePath* chrome_exe_path) { 3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HKEY install_key = HKEY_LOCAL_MACHINE; 3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!IsChromeInstalled(install_key)) { 3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) install_key = HKEY_CURRENT_USER; 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!IsChromeInstalled(install_key)) { 3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Now grab the uninstall string from the appropriate ClientState key 3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // and use that as the base for a path to chrome.exe. 3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *chrome_exe_path = 3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chrome_launcher_support::GetChromePathForInstallationLevel( 3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) install_key == HKEY_LOCAL_MACHINE ? 3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chrome_launcher_support::SYSTEM_LEVEL_INSTALLATION : 3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chrome_launcher_support::USER_LEVEL_INSTALLATION); 3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return !chrome_exe_path->empty(); 4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL __stdcall GoogleChromeCompatibilityCheck(BOOL set_flag, 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int shell_mode, 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD* reasons) { 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD local_reasons = 0; 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WindowsVersion windows_version = GetWindowsVersion(); 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // System requirements? 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (windows_version == VERSION_BELOW_XP_SP2) 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) local_reasons |= GCCC_ERROR_OSNOTSUPPORTED; 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsChromeInstalled(HKEY_LOCAL_MACHINE)) 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) local_reasons |= GCCC_ERROR_SYSTEMLEVELALREADYPRESENT; 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsChromeInstalled(HKEY_CURRENT_USER)) 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) local_reasons |= GCCC_ERROR_USERLEVELALREADYPRESENT; 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shell_mode == GCAPI_INVOKED_UAC_ELEVATION) { 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only check that we have HKLM write permissions if we specify that 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // GCAPI is being invoked from an elevated shell, or in admin mode 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!VerifyHKLMAccess()) { 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) local_reasons |= GCCC_ERROR_ACCESSDENIED; 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if ((windows_version == VERSION_VISTA_OR_HIGHER) && 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !VerifyAdminGroup()) { 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For Vista or later check for elevation since even for admin user we could 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be running in non-elevated mode. We require integrity level High. 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) local_reasons |= GCCC_ERROR_INTEGRITYLEVEL; 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Then only check whether we can re-offer, if everything else is OK. 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (local_reasons == 0 && !CanReOfferChrome(set_flag)) 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) local_reasons |= GCCC_ERROR_ALREADYOFFERED; 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Done. Copy/return results. 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (reasons != NULL) 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *reasons = local_reasons; 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (local_reasons == 0); 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL __stdcall LaunchGoogleChrome() { 4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath chrome_exe_path; 4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!GetGoogleChromePath(&chrome_exe_path)) 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedCOMInitializer com_initializer; 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (::CoInitializeSecurity(NULL, -1, NULL, NULL, 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RPC_C_AUTHN_LEVEL_PKT_PRIVACY, 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RPC_C_IMP_LEVEL_IDENTIFY, NULL, 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EOAC_DYNAMIC_CLOAKING, NULL) != S_OK) { 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool impersonation_success = false; 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsRunningElevated()) { 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t* curr_proc_sid; 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetUserIdForProcess(GetCurrentProcessId(), &curr_proc_sid)) { 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD pid = 0; 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::GetWindowThreadProcessId(::GetShellWindow(), &pid); 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pid <= 0) { 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::LocalFree(curr_proc_sid); 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t* exp_proc_sid; 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetUserIdForProcess(pid, &exp_proc_sid)) { 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (_wcsicmp(curr_proc_sid, exp_proc_sid) == 0) { 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedHandle process_handle( 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::OpenProcess(PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION, 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TRUE, 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pid)); 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (process_handle.IsValid()) { 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE process_token = NULL; 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE user_token = NULL; 4811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (::OpenProcessToken(process_handle.Get(), 4821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TOKEN_DUPLICATE | TOKEN_QUERY, 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &process_token) && 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::DuplicateTokenEx(process_token, 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TOKEN_IMPERSONATE | TOKEN_QUERY | 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE, 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, SecurityImpersonation, 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TokenPrimary, &user_token) && 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (::ImpersonateLoggedOnUser(user_token) != 0)) { 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) impersonation_success = true; 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (user_token) 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::CloseHandle(user_token); 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (process_token) 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::CloseHandle(process_token); 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::LocalFree(exp_proc_sid); 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::LocalFree(curr_proc_sid); 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!impersonation_success) { 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) CommandLine chrome_command(chrome_exe_path); 5086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ret = false; 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedComPtr<IProcessLauncher> ipl; 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SUCCEEDED(ipl.CreateInstance(__uuidof(ProcessLauncherClass), 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CLSCTX_LOCAL_SERVER))) { 5146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (SUCCEEDED(ipl->LaunchCmdLine( 5156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) chrome_command.GetCommandLineString().c_str()))) 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = true; 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ipl.Release(); 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Couldn't get Omaha's process launcher, Omaha may not be installed at 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // system level. Try just running Chrome instead. 5216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ret = base::LaunchProcess(chrome_command.GetCommandLineString(), 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::LaunchOptions(), 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL); 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (impersonation_success) 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::RevertToSelf(); 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret; 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL __stdcall LaunchGoogleChromeWithDimensions(int x, 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int y, 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int width, 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int height, 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool in_background) { 5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (in_background) { 5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath chrome_exe_path; 5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!GetGoogleChromePath(&chrome_exe_path)) 5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // When launching in the background, use WMI to ensure that chrome.exe is 5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // is not our child process. This prevents it from pushing itself to 5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // foreground. 5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CommandLine chrome_command(chrome_exe_path); 5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScopedCOMInitializer com_initializer; 5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!installer::WMIProcess::Launch(chrome_command.GetCommandLineString(), 5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NULL)) { 5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // For some reason WMI failed. Try and launch the old fashioned way, 5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // knowing that visual glitches will occur when the window pops up. 5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!LaunchGoogleChrome()) 5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!LaunchGoogleChrome()) 5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HWND hwnd_insert_after = in_background ? HWND_BOTTOM : NULL; 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD set_window_flags = in_background ? SWP_NOACTIVATE : SWP_NOZORDER; 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (x == -1 && y == -1) 5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_window_flags |= SWP_NOMOVE; 5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (width == -1 && height == -1) 5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_window_flags |= SWP_NOSIZE; 5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetWindowPosParams enum_params = { x, y, width, height, set_window_flags, 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hwnd_insert_after, false }; 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Chrome may have been launched, but the window may not have appeared 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // yet. Wait for it to appear for 10 seconds, but exit if it takes longer 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // than that. 5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int ms_elapsed = 0; 5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int timeout = 10000; 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool found_window = false; 5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (ms_elapsed < timeout) { 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Enum all top-level windows looking for Chrome windows. 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::EnumWindows(ChromeWindowEnumProc, reinterpret_cast<LPARAM>(&enum_params)); 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Give it five more seconds after finding the first window until we stop 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // shoving new windows into the background. 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!found_window && enum_params.success) { 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found_window = true; 5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) timeout = ms_elapsed + 5000; 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Sleep(10); 5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ms_elapsed += 10; 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return found_window; 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)BOOL __stdcall LaunchGoogleChromeInBackground() { 5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return LaunchGoogleChromeWithDimensions(-1, -1, -1, -1, true); 5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int __stdcall GoogleChromeDaysSinceLastRun() { 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int days_since_last_run = std::numeric_limits<int>::max(); 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsChromeInstalled(HKEY_LOCAL_MACHINE) || 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IsChromeInstalled(HKEY_CURRENT_USER)) { 605cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) RegKey client_state(HKEY_CURRENT_USER, 606cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) kChromeRegClientStateKey, 607cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) KEY_QUERY_VALUE | KEY_WOW64_32KEY); 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (client_state.Valid()) { 609116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::string16 last_run; 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 last_run_value = 0; 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (client_state.ReadValue(google_update::kRegLastRunTimeField, 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &last_run) == ERROR_SUCCESS && 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringToInt64(last_run, &last_run_value)) { 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time last_run_time = Time::FromInternalValue(last_run_value); 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta difference = Time::NowFromSystemTime() - last_run_time; 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can end up with negative numbers here, given changes in system 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // clock time or due to TimeDelta's int64 -> int truncation. 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int new_days_since_last_run = difference.InDays(); 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (new_days_since_last_run >= 0 && 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_days_since_last_run < days_since_last_run) { 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) days_since_last_run = new_days_since_last_run; 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (days_since_last_run == std::numeric_limits<int>::max()) { 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) days_since_last_run = -1; 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return days_since_last_run; 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL __stdcall CanOfferReactivation(const wchar_t* brand_code, 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int shell_mode, 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD* error_code) { 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(error_code); 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!brand_code) { 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_code) 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *error_code = REACTIVATE_ERROR_INVALID_INPUT; 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int days_since_last_run = GoogleChromeDaysSinceLastRun(); 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (days_since_last_run >= 0 && 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) days_since_last_run < kReactivationMinDaysDormant) { 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_code) 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *error_code = REACTIVATE_ERROR_NOTDORMANT; 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only run the code below when this function is invoked from a standard, 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // non-elevated cmd shell. This is because this section of code looks at 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // values in HKEY_CURRENT_USER, and we only want to look at the logged-in 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // user's HKCU, not the admin user's HKCU. 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shell_mode == GCAPI_INVOKED_STANDARD_SHELL) { 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsChromeInstalled(HKEY_LOCAL_MACHINE) && 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !IsChromeInstalled(HKEY_CURRENT_USER)) { 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_code) 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *error_code = REACTIVATE_ERROR_NOTINSTALLED; 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HasBeenReactivated()) { 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_code) 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *error_code = REACTIVATE_ERROR_ALREADY_REACTIVATED; 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciBOOL __stdcall ReactivateChrome(const wchar_t* brand_code, 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int shell_mode, 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD* error_code) { 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BOOL result = FALSE; 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CanOfferReactivation(brand_code, 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shell_mode, 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_code)) { 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SetReactivationBrandCode(brand_code, shell_mode)) { 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Currently set this as a best-effort thing. We return TRUE if 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reactivation succeeded regardless of the experiment label result. 6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetReactivationExperimentLabels(brand_code, shell_mode); 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = TRUE; 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_code) 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *error_code = REACTIVATE_ERROR_REACTIVATION_FAILED; 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 6983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)BOOL __stdcall CanOfferRelaunch(const wchar_t** partner_brandcode_list, 6993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int partner_brandcode_list_length, 7003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int shell_mode, 7013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DWORD* error_code) { 7023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(error_code); 7033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 7043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!partner_brandcode_list || partner_brandcode_list_length <= 0) { 7053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (error_code) 7063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *error_code = RELAUNCH_ERROR_INVALID_INPUT; 7073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return FALSE; 7083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 7093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 7103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // These conditions need to be satisfied for relaunch: 7113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // a) Chrome should be installed; 7123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!IsChromeInstalled(HKEY_LOCAL_MACHINE) && 7133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) (shell_mode != GCAPI_INVOKED_STANDARD_SHELL || 7143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) !IsChromeInstalled(HKEY_CURRENT_USER))) { 7153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (error_code) 7163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *error_code = RELAUNCH_ERROR_NOTINSTALLED; 7173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return FALSE; 7183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 7193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 7203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // b) the installed brandcode should belong to that partner (in 7213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // brandcode_list); 722116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::string16 installed_brandcode; 7233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) bool valid_brandcode = false; 7243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (GoogleUpdateSettings::GetBrand(&installed_brandcode)) { 7253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (int i = 0; i < partner_brandcode_list_length; ++i) { 7263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!_wcsicmp(installed_brandcode.c_str(), partner_brandcode_list[i])) { 7273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) valid_brandcode = true; 7283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) break; 7293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 7303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 7313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 7323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 7333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!valid_brandcode) { 7343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (error_code) 7353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *error_code = RELAUNCH_ERROR_INVALID_PARTNER; 7363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return FALSE; 7373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 7383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 7393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // c) C1F ping should not have been sent; 7403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (IsC1FSent()) { 7413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (error_code) 7423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *error_code = RELAUNCH_ERROR_PINGS_SENT; 7433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return FALSE; 7443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 7453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 7463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // d) a minimum period (30 days) must have passed since Chrome was last used; 7473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int days_since_last_run = GoogleChromeDaysSinceLastRun(); 7483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (days_since_last_run >= 0 && 7493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) days_since_last_run < kRelaunchMinDaysDormant) { 7503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (error_code) 7513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *error_code = RELAUNCH_ERROR_NOTDORMANT; 7523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return FALSE; 7533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 7543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 7553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // e) a minimum period (6 months) must have passed since the previous 7563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // relaunch offer for the current user; 7573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) RegKey key; 7583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DWORD min_relaunch_date; 759cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (key.Open(HKEY_CURRENT_USER, 760cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) kChromeRegClientStateKey, 761cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) KEY_QUERY_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS && 7623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) key.ReadValueDW(kRelaunchAllowedAfterValue, 7633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) &min_relaunch_date) == ERROR_SUCCESS && 7643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) FormatDateOffsetByMonths(0) < min_relaunch_date) { 7653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (error_code) 7663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *error_code = RELAUNCH_ERROR_ALREADY_RELAUNCHED; 7673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return FALSE; 7683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 7693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 7703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return TRUE; 7713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 7723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 7733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)BOOL __stdcall SetRelaunchOffered(const wchar_t** partner_brandcode_list, 7743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int partner_brandcode_list_length, 7753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const wchar_t* relaunch_brandcode, 7763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int shell_mode, 7773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DWORD* error_code) { 7783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!CanOfferRelaunch(partner_brandcode_list, partner_brandcode_list_length, 7793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) shell_mode, error_code)) 7803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return FALSE; 7813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 7823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Store the relaunched brand code and the minimum date for relaunch (6 months 7833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // from now), and set the Omaha experiment label. 7843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) RegKey key; 785cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (key.Create(HKEY_CURRENT_USER, 786cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) kChromeRegClientStateKey, 787cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) KEY_SET_VALUE | KEY_WOW64_32KEY) != ERROR_SUCCESS || 7883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) key.WriteValue(kRelaunchBrandcodeValue, 7893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) relaunch_brandcode) != ERROR_SUCCESS || 7903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) key.WriteValue(kRelaunchAllowedAfterValue, 7913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) FormatDateOffsetByMonths(6)) != ERROR_SUCCESS || 7923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) !SetRelaunchExperimentLabels(relaunch_brandcode, shell_mode)) { 7933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (error_code) 7943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *error_code = RELAUNCH_ERROR_RELAUNCH_FAILED; 7953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return FALSE; 7963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 7973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 7983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return TRUE; 7993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 800