diff options
author | maruel@chromium.org <maruel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-05 12:46:38 +0000 |
---|---|---|
committer | maruel@chromium.org <maruel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-05 12:46:38 +0000 |
commit | f0a51fb571f46531025fa09240bbc3e1af925e84 (patch) | |
tree | 558b4f0e737fda4b9ab60f252c9c23b8a4ca523e /chrome/installer | |
parent | 6390be368205705f49ead3cec40396519f13b889 (diff) | |
download | chromium_src-f0a51fb571f46531025fa09240bbc3e1af925e84.zip chromium_src-f0a51fb571f46531025fa09240bbc3e1af925e84.tar.gz chromium_src-f0a51fb571f46531025fa09240bbc3e1af925e84.tar.bz2 |
Fixes CRLF and trailing white spaces.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@10982 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/installer')
-rw-r--r-- | chrome/installer/gcapi/gcapi.cc | 888 | ||||
-rw-r--r-- | chrome/installer/gcapi/gcapi.h | 6 | ||||
-rw-r--r-- | chrome/installer/gcapi/gcapi_test.cc | 6 | ||||
-rw-r--r-- | chrome/installer/gcapi/resource.h | 28 | ||||
-rw-r--r-- | chrome/installer/mini_installer/mini_installer.cc | 2 | ||||
-rw-r--r-- | chrome/installer/setup/main.cc | 2 | ||||
-rw-r--r-- | chrome/installer/util/copy_tree_work_item.cc | 2 | ||||
-rw-r--r-- | chrome/installer/util/html_dialog.h | 4 | ||||
-rw-r--r-- | chrome/installer/util/html_dialog_impl.cc | 6 | ||||
-rwxr-xr-x | chrome/installer/util/prebuild/create_string_rc.py | 4 | ||||
-rw-r--r-- | chrome/installer/util/util_constants.h | 4 |
11 files changed, 476 insertions, 476 deletions
diff --git a/chrome/installer/gcapi/gcapi.cc b/chrome/installer/gcapi/gcapi.cc index b3c12a5..3f4a226 100644 --- a/chrome/installer/gcapi/gcapi.cc +++ b/chrome/installer/gcapi/gcapi.cc @@ -1,444 +1,444 @@ -// Copyright (c) 2006-2008 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/installer/gcapi/gcapi.h"
-
-#include <atlbase.h>
-#include <atlcom.h>
-#include <windows.h>
-#include <sddl.h>
-#include <stdlib.h>
-#include <strsafe.h>
-#include <tlhelp32.h>
-
-#include "google_update_idl.h"
-
-namespace {
-
-const wchar_t kChromeRegClientsKey[] = L"Software\\Google\\Update\\Clients\\{8A69D345-D564-463c-AFF1-A69D9E530F96}";
-const wchar_t kChromeRegClientStateKey[] = L"Software\\Google\\Update\\ClientState\\{8A69D345-D564-463c-AFF1-A69D9E530F96}";
-const wchar_t kChromeRegLaunchCmd[] = L"InstallerSuccessLaunchCmdLine";
-const wchar_t kChromeRegLastLaunchCmd[] = L"LastInstallerSuccessLaunchCmdLine";
-const wchar_t kChromeRegVersion[] = L"pv";
-const wchar_t kNoChromeOfferUntil[] = L"SOFTWARE\\Google\\No Chrome Offer Until";
-
-// Remove any registry key with non-numeric value or with the numeric value
-// equal or less than today's date represented in YYYYMMDD form.
-void CleanUpRegistryValues() {
- HKEY key = NULL;
- if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, kNoChromeOfferUntil,
- 0, KEY_ALL_ACCESS, &key) != ERROR_SUCCESS)
- return;
-
- DWORD index = 0;
- wchar_t value_name[260];
- DWORD value_name_len = _countof(value_name);
- DWORD value_type = REG_DWORD;
- DWORD value_data = 0;
- DWORD value_len = sizeof(DWORD);
-
- // First, remove any value whose type is not DWORD.
- while (::RegEnumValue(key, index, value_name, &value_name_len, NULL,
- &value_type, NULL, &value_len) == ERROR_SUCCESS) {
- if (value_type == REG_DWORD)
- index++;
- else
- ::RegDeleteValue(key, value_name);
-
- value_name_len = _countof(value_name);
- value_type = REG_DWORD;
- value_len = sizeof(DWORD);
- }
-
- // Get today's date, and format it as YYYYMMDD numeric value.
- SYSTEMTIME now;
- ::GetLocalTime(&now);
- DWORD expiration_date = now.wYear * 10000 + now.wMonth * 100 + now.wDay;
-
- // Remove any DWORD value smaller than the number represent the
- // expiration date (YYYYMMDD).
- index = 0;
- while (::RegEnumValue(key, index, value_name, &value_name_len, NULL,
- &value_type, (LPBYTE) &value_data,
- &value_len) == ERROR_SUCCESS) {
- if (value_type == REG_DWORD && value_data > expiration_date)
- index++; // move on to next value.
- else
- ::RegDeleteValue(key, value_name); // delete this value.
-
- value_name_len = _countof(value_name);
- value_type = REG_DWORD;
- value_data = 0;
- value_len = sizeof(DWORD);
- }
-
- ::RegCloseKey(key);
-}
-
-// 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];
- DWORD handle = 0;
- DWORD buffer_size = 0;
-
- buffer_size = ::GetFileVersionInfoSize(filename, &handle);
- // Cannot stats the file or our buffer size is too small (very unlikely).
- if (buffer_size == 0 || buffer_size > _countof(file_version_info))
- return false;
-
- buffer_size = _countof(file_version_info);
- memset(file_version_info, 0, buffer_size);
- if (!::GetFileVersionInfo(filename, handle, buffer_size, file_version_info))
- return false;
-
- DWORD data_len = 0;
- LPVOID data = NULL;
- // Retrieve the language and codepage code if exists.
- buffer_size = 0;
- if (!::VerQueryValue(file_version_info, TEXT("\\VarFileInfo\\Translation"),
- reinterpret_cast<LPVOID *>(&data), reinterpret_cast<UINT *>(&data_len)))
- return false;
- if (data_len != 4)
- return false;
-
- wchar_t info_name[256];
- DWORD lang = 0;
- // Formulate the string to retrieve the company name of the specific
- // language codepage.
- memcpy(&lang, data, 4);
- ::StringCchPrintf(info_name, _countof(info_name),
- L"\\StringFileInfo\\%02X%02X%02X%02X\\CompanyName",
- (lang & 0xff00)>>8, (lang & 0xff), (lang & 0xff000000)>>24,
- (lang & 0xff0000)>>16);
-
- data_len = 0;
- if (!::VerQueryValue(file_version_info, info_name,
- reinterpret_cast<LPVOID *>(&data), reinterpret_cast<UINT *>(&data_len)))
- return false;
- if (data_len <= 0 || data_len >= out_len)
- return false;
-
- memset(buffer, 0, out_len);
- ::StringCchCopyN(buffer, out_len, (const wchar_t*)data, data_len);
- return true;
-}
-
-// Return true if we can re-offer Chrome; false, otherwise.
-// Each partner can only offer Chrome once every six months.
-bool CanReOfferChrome(BOOL set_flag) {
- wchar_t filename[MAX_PATH+1];
- wchar_t company[MAX_PATH];
-
- // If we cannot retrieve the version info of the executable or company
- // name, we allow the Chrome to be offered because there is no past
- // history to be found.
- if (::GetModuleFileName(NULL, filename, MAX_PATH) == 0)
- return true;
- if (!GetCompanyName(filename, company, sizeof(company)))
- return true;
-
- bool can_re_offer = true;
- DWORD disposition = 0;
- HKEY key = NULL;
- if (::RegCreateKeyEx(HKEY_LOCAL_MACHINE, kNoChromeOfferUntil,
- 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE,
- NULL, &key, &disposition) == ERROR_SUCCESS) {
- // Cannot re-offer, if the timer already exists and is not expired yet.
- if (::RegQueryValueEx(key, company, 0, 0, 0, 0) == ERROR_SUCCESS) {
- // The expired timers were already removed in CleanUpRegistryValues.
- // So if the key is not found, we can offer the Chrome.
- can_re_offer = false;
- } else if (set_flag) {
- // Set expiration date for offer as six months from today,
- // represented as a YYYYMMDD numeric value.
- SYSTEMTIME timer;
- ::GetLocalTime(&timer);
- timer.wMonth = timer.wMonth + 6;
- if (timer.wMonth > 12) {
- timer.wMonth = timer.wMonth - 12;
- timer.wYear = timer.wYear + 1;
- }
- DWORD value = timer.wYear * 10000 + timer.wMonth * 100 + timer.wDay;
- ::RegSetValueEx(key, company, 0, REG_DWORD, (LPBYTE)&value, sizeof(DWORD));
- }
-
- ::RegCloseKey(key);
- }
-
- return can_re_offer;
-}
-
-// Helper function to read a value from registry. Returns true if value
-// is read successfully and stored in parameter value. Returns false otherwise.
-bool ReadValueFromRegistry(HKEY root_key, const wchar_t *sub_key,
- const wchar_t *value_name, wchar_t *value,
- size_t *size) {
- HKEY key;
- if ((::RegOpenKeyEx(root_key, sub_key, NULL,
- KEY_READ, &key) == ERROR_SUCCESS) &&
- (::RegQueryValueEx(key, value_name, NULL, NULL,
- reinterpret_cast<LPBYTE>(value),
- reinterpret_cast<LPDWORD>(size)) == ERROR_SUCCESS)) {
- ::RegCloseKey(key);
- return true;
- }
- return false;
-}
-
-bool IsChromeInstalled(HKEY root_key) {
- wchar_t version[64];
- size_t size = _countof(version);
- if (ReadValueFromRegistry(root_key, kChromeRegClientsKey, kChromeRegVersion,
- version, &size))
- return true;
- return false;
-}
-
-bool IsWinXPSp1OrLater(bool* is_vista_or_later) {
- OSVERSIONINFOEX osviex = { sizeof(OSVERSIONINFOEX) };
- int r = ::GetVersionEx((LPOSVERSIONINFO)&osviex);
- // If this failed we're on Win9X or a pre NT4SP6 OS.
- if (!r)
- return false;
-
- if (osviex.dwMajorVersion < 5)
- return false;
-
- if (osviex.dwMajorVersion > 5) {
- *is_vista_or_later = true;
- return true; // way beyond Windows XP;
- }
-
- if (osviex.dwMinorVersion >= 1 && osviex.wServicePackMajor >= 1)
- return true; // Windows XP SP1 or better.
-
- return false; // Windows 2000, WinXP no Service Pack.
-}
-
-// Note this function should not be called on old Windows versions where these
-// Windows API are not available. We always invoke this function after checking
-// that current OS is Vista or later.
-bool VerifyAdminGroup() {
- SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
- PSID Group;
- BOOL check = ::AllocateAndInitializeSid(&NtAuthority, 2,
- SECURITY_BUILTIN_DOMAIN_RID,
- DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0,
- 0, 0, 0,
- &Group);
- if (check) {
- if (!::CheckTokenMembership(NULL, Group, &check))
- check = FALSE;
- }
- ::FreeSid(Group);
- return (check == TRUE);
-}
-
-bool VerifyHKLMAccess(const wchar_t* sub_key) {
- HKEY root = HKEY_LOCAL_MACHINE;
- wchar_t str[] = L"test";
- bool result = false;
- DWORD disposition = 0;
- HKEY key = NULL;
-
- if (::RegCreateKeyEx(root, sub_key, 0, NULL,
- REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL,
- &key, &disposition) == ERROR_SUCCESS) {
- if (::RegSetValueEx(key, str, 0, REG_SZ, (LPBYTE)str,
- (DWORD)lstrlen(str)) == ERROR_SUCCESS) {
- result = true;
- RegDeleteValue(key, str);
- }
-
- // If we create the main key, delete the entire key.
- if (disposition == REG_CREATED_NEW_KEY)
- RegDeleteKey(key, NULL);
-
- RegCloseKey(key);
- }
-
- return result;
-}
-
-bool IsRunningElevated() {
- // This method should be called only for Vista or later.
- bool is_vista_or_later = false;
- IsWinXPSp1OrLater(&is_vista_or_later);
- if (!is_vista_or_later || !VerifyAdminGroup())
- return false;
-
- HANDLE process_token;
- if (!::OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &process_token))
- return false;
-
- TOKEN_ELEVATION_TYPE elevation_type = TokenElevationTypeDefault;
- DWORD size_returned = 0;
- if (!::GetTokenInformation(process_token, TokenElevationType,
- &elevation_type, sizeof(elevation_type),
- &size_returned)) {
- ::CloseHandle(process_token);
- return false;
- }
-
- ::CloseHandle(process_token);
- return (elevation_type == TokenElevationTypeFull);
-}
-
-bool GetUserIdForProcess(size_t pid, wchar_t** user_sid) {
- HANDLE process_handle = ::OpenProcess(PROCESS_QUERY_INFORMATION, TRUE, pid);
- if (process_handle == NULL)
- return false;
-
- HANDLE process_token;
- bool result = false;
- if (::OpenProcessToken(process_handle, TOKEN_QUERY, &process_token)) {
- DWORD size = 0;
- ::GetTokenInformation(process_token, TokenUser, NULL, 0, &size);
- if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER ||
- ::GetLastError() == ERROR_SUCCESS) {
- DWORD actual_size = 0;
- BYTE* token_user = new BYTE[size];
- if ((::GetTokenInformation(process_token, TokenUser, token_user, size,
- &actual_size)) &&
- (actual_size <= size)) {
- PSID sid = reinterpret_cast<TOKEN_USER*>(token_user)->User.Sid;
- if (::ConvertSidToStringSid(sid, user_sid))
- result = true;
- }
- delete[] token_user;
- }
- ::CloseHandle(process_token);
- }
- ::CloseHandle(process_handle);
- return result;
-}
-} // namespace
-
-#pragma comment(linker, "/EXPORT:GoogleChromeCompatibilityCheck=_GoogleChromeCompatibilityCheck@8,PRIVATE")
-DLLEXPORT BOOL __stdcall GoogleChromeCompatibilityCheck(BOOL set_flag, DWORD *reasons) {
- DWORD local_reasons = 0;
-
- bool is_vista_or_later = false;
- // System requirements?
- if (!IsWinXPSp1OrLater(&is_vista_or_later))
- local_reasons |= GCCC_ERROR_OSNOTSUPPORTED;
-
- if (IsChromeInstalled(HKEY_LOCAL_MACHINE))
- local_reasons |= GCCC_ERROR_SYSTEMLEVELALREADYPRESENT;
-
- if (IsChromeInstalled(HKEY_CURRENT_USER))
- local_reasons |= GCCC_ERROR_USERLEVELALREADYPRESENT;
-
- if (!VerifyHKLMAccess(kChromeRegClientsKey)) {
- local_reasons |= GCCC_ERROR_ACCESSDENIED;
- } else if (is_vista_or_later && !VerifyAdminGroup()) {
- // For Vista or later check for elevation since even for admin user we could
- // be running in non-elevated mode. We require integrity level High.
- local_reasons |= GCCC_ERROR_INTEGRITYLEVEL;
- }
-
- // First clean up the registry keys left over previously.
- // Then only check whether we can re-offer, if everything else is OK.
- CleanUpRegistryValues();
- if (local_reasons == 0 && !CanReOfferChrome(set_flag))
- local_reasons |= GCCC_ERROR_ALREADYOFFERED;
-
- // Done. Copy/return results.
- if (reasons != NULL)
- *reasons = local_reasons;
-
- return (*reasons == 0);
-}
-
-#pragma comment(linker, "/EXPORT:LaunchGoogleChrome=_LaunchGoogleChrome@0,PRIVATE")
-DLLEXPORT 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)) {
- return false;
- }
- }
-
- HRESULT hr = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
- if (hr != S_OK) {
- if (hr == S_FALSE)
- ::CoUninitialize();
- return false;
- }
-
- 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;
- }
-
- bool impersonation_success = false;
- if (IsRunningElevated()) {
- wchar_t* curr_proc_sid;
- if (!GetUserIdForProcess(GetCurrentProcessId(), &curr_proc_sid)) {
- ::CoUninitialize();
- return false;
- }
-
- DWORD pid = 0;
- ::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) {
- HANDLE process_token;
- HANDLE user_token;
- if (::OpenProcessToken(process_handle, TOKEN_DUPLICATE | TOKEN_QUERY,
- &process_token) &&
- ::DuplicateTokenEx(process_token,
- TOKEN_IMPERSONATE | TOKEN_QUERY |
- TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE,
- NULL, SecurityImpersonation,
- TokenPrimary, &user_token) &&
- (::ImpersonateLoggedOnUser(user_token) != 0)) {
- impersonation_success = true;
- }
- ::CloseHandle(user_token);
- ::CloseHandle(process_token);
- ::CloseHandle(process_handle);
- }
- }
- ::LocalFree(exp_proc_sid);
- }
-
- ::LocalFree(curr_proc_sid);
- if (!impersonation_success) {
- ::CoUninitialize();
- return false;
- }
- }
-
- bool ret = false;
- CComPtr<IProcessLauncher> ipl;
- if (!FAILED(ipl.CoCreateInstance(__uuidof(ProcessLauncherClass), NULL,
- CLSCTX_LOCAL_SERVER))) {
- if (!FAILED(ipl->LaunchCmdLine(launch_cmd)))
- ret = true;
- ipl.Release();
- }
-
- if (impersonation_success)
- ::RevertToSelf();
- ::CoUninitialize();
- return ret;
-}
+// Copyright (c) 2006-2008 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/installer/gcapi/gcapi.h" + +#include <atlbase.h> +#include <atlcom.h> +#include <windows.h> +#include <sddl.h> +#include <stdlib.h> +#include <strsafe.h> +#include <tlhelp32.h> + +#include "google_update_idl.h" + +namespace { + +const wchar_t kChromeRegClientsKey[] = L"Software\\Google\\Update\\Clients\\{8A69D345-D564-463c-AFF1-A69D9E530F96}"; +const wchar_t kChromeRegClientStateKey[] = L"Software\\Google\\Update\\ClientState\\{8A69D345-D564-463c-AFF1-A69D9E530F96}"; +const wchar_t kChromeRegLaunchCmd[] = L"InstallerSuccessLaunchCmdLine"; +const wchar_t kChromeRegLastLaunchCmd[] = L"LastInstallerSuccessLaunchCmdLine"; +const wchar_t kChromeRegVersion[] = L"pv"; +const wchar_t kNoChromeOfferUntil[] = L"SOFTWARE\\Google\\No Chrome Offer Until"; + +// Remove any registry key with non-numeric value or with the numeric value +// equal or less than today's date represented in YYYYMMDD form. +void CleanUpRegistryValues() { + HKEY key = NULL; + if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, kNoChromeOfferUntil, + 0, KEY_ALL_ACCESS, &key) != ERROR_SUCCESS) + return; + + DWORD index = 0; + wchar_t value_name[260]; + DWORD value_name_len = _countof(value_name); + DWORD value_type = REG_DWORD; + DWORD value_data = 0; + DWORD value_len = sizeof(DWORD); + + // First, remove any value whose type is not DWORD. + while (::RegEnumValue(key, index, value_name, &value_name_len, NULL, + &value_type, NULL, &value_len) == ERROR_SUCCESS) { + if (value_type == REG_DWORD) + index++; + else + ::RegDeleteValue(key, value_name); + + value_name_len = _countof(value_name); + value_type = REG_DWORD; + value_len = sizeof(DWORD); + } + + // Get today's date, and format it as YYYYMMDD numeric value. + SYSTEMTIME now; + ::GetLocalTime(&now); + DWORD expiration_date = now.wYear * 10000 + now.wMonth * 100 + now.wDay; + + // Remove any DWORD value smaller than the number represent the + // expiration date (YYYYMMDD). + index = 0; + while (::RegEnumValue(key, index, value_name, &value_name_len, NULL, + &value_type, (LPBYTE) &value_data, + &value_len) == ERROR_SUCCESS) { + if (value_type == REG_DWORD && value_data > expiration_date) + index++; // move on to next value. + else + ::RegDeleteValue(key, value_name); // delete this value. + + value_name_len = _countof(value_name); + value_type = REG_DWORD; + value_data = 0; + value_len = sizeof(DWORD); + } + + ::RegCloseKey(key); +} + +// 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]; + DWORD handle = 0; + DWORD buffer_size = 0; + + buffer_size = ::GetFileVersionInfoSize(filename, &handle); + // Cannot stats the file or our buffer size is too small (very unlikely). + if (buffer_size == 0 || buffer_size > _countof(file_version_info)) + return false; + + buffer_size = _countof(file_version_info); + memset(file_version_info, 0, buffer_size); + if (!::GetFileVersionInfo(filename, handle, buffer_size, file_version_info)) + return false; + + DWORD data_len = 0; + LPVOID data = NULL; + // Retrieve the language and codepage code if exists. + buffer_size = 0; + if (!::VerQueryValue(file_version_info, TEXT("\\VarFileInfo\\Translation"), + reinterpret_cast<LPVOID *>(&data), reinterpret_cast<UINT *>(&data_len))) + return false; + if (data_len != 4) + return false; + + wchar_t info_name[256]; + DWORD lang = 0; + // Formulate the string to retrieve the company name of the specific + // language codepage. + memcpy(&lang, data, 4); + ::StringCchPrintf(info_name, _countof(info_name), + L"\\StringFileInfo\\%02X%02X%02X%02X\\CompanyName", + (lang & 0xff00)>>8, (lang & 0xff), (lang & 0xff000000)>>24, + (lang & 0xff0000)>>16); + + data_len = 0; + if (!::VerQueryValue(file_version_info, info_name, + reinterpret_cast<LPVOID *>(&data), reinterpret_cast<UINT *>(&data_len))) + return false; + if (data_len <= 0 || data_len >= out_len) + return false; + + memset(buffer, 0, out_len); + ::StringCchCopyN(buffer, out_len, (const wchar_t*)data, data_len); + return true; +} + +// Return true if we can re-offer Chrome; false, otherwise. +// Each partner can only offer Chrome once every six months. +bool CanReOfferChrome(BOOL set_flag) { + wchar_t filename[MAX_PATH+1]; + wchar_t company[MAX_PATH]; + + // If we cannot retrieve the version info of the executable or company + // name, we allow the Chrome to be offered because there is no past + // history to be found. + if (::GetModuleFileName(NULL, filename, MAX_PATH) == 0) + return true; + if (!GetCompanyName(filename, company, sizeof(company))) + return true; + + bool can_re_offer = true; + DWORD disposition = 0; + HKEY key = NULL; + if (::RegCreateKeyEx(HKEY_LOCAL_MACHINE, kNoChromeOfferUntil, + 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, + NULL, &key, &disposition) == ERROR_SUCCESS) { + // Cannot re-offer, if the timer already exists and is not expired yet. + if (::RegQueryValueEx(key, company, 0, 0, 0, 0) == ERROR_SUCCESS) { + // The expired timers were already removed in CleanUpRegistryValues. + // So if the key is not found, we can offer the Chrome. + can_re_offer = false; + } else if (set_flag) { + // Set expiration date for offer as six months from today, + // represented as a YYYYMMDD numeric value. + SYSTEMTIME timer; + ::GetLocalTime(&timer); + timer.wMonth = timer.wMonth + 6; + if (timer.wMonth > 12) { + timer.wMonth = timer.wMonth - 12; + timer.wYear = timer.wYear + 1; + } + DWORD value = timer.wYear * 10000 + timer.wMonth * 100 + timer.wDay; + ::RegSetValueEx(key, company, 0, REG_DWORD, (LPBYTE)&value, sizeof(DWORD)); + } + + ::RegCloseKey(key); + } + + return can_re_offer; +} + +// Helper function to read a value from registry. Returns true if value +// is read successfully and stored in parameter value. Returns false otherwise. +bool ReadValueFromRegistry(HKEY root_key, const wchar_t *sub_key, + const wchar_t *value_name, wchar_t *value, + size_t *size) { + HKEY key; + if ((::RegOpenKeyEx(root_key, sub_key, NULL, + KEY_READ, &key) == ERROR_SUCCESS) && + (::RegQueryValueEx(key, value_name, NULL, NULL, + reinterpret_cast<LPBYTE>(value), + reinterpret_cast<LPDWORD>(size)) == ERROR_SUCCESS)) { + ::RegCloseKey(key); + return true; + } + return false; +} + +bool IsChromeInstalled(HKEY root_key) { + wchar_t version[64]; + size_t size = _countof(version); + if (ReadValueFromRegistry(root_key, kChromeRegClientsKey, kChromeRegVersion, + version, &size)) + return true; + return false; +} + +bool IsWinXPSp1OrLater(bool* is_vista_or_later) { + OSVERSIONINFOEX osviex = { sizeof(OSVERSIONINFOEX) }; + int r = ::GetVersionEx((LPOSVERSIONINFO)&osviex); + // If this failed we're on Win9X or a pre NT4SP6 OS. + if (!r) + return false; + + if (osviex.dwMajorVersion < 5) + return false; + + if (osviex.dwMajorVersion > 5) { + *is_vista_or_later = true; + return true; // way beyond Windows XP; + } + + if (osviex.dwMinorVersion >= 1 && osviex.wServicePackMajor >= 1) + return true; // Windows XP SP1 or better. + + return false; // Windows 2000, WinXP no Service Pack. +} + +// Note this function should not be called on old Windows versions where these +// Windows API are not available. We always invoke this function after checking +// that current OS is Vista or later. +bool VerifyAdminGroup() { + SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; + PSID Group; + BOOL check = ::AllocateAndInitializeSid(&NtAuthority, 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, + 0, 0, 0, + &Group); + if (check) { + if (!::CheckTokenMembership(NULL, Group, &check)) + check = FALSE; + } + ::FreeSid(Group); + return (check == TRUE); +} + +bool VerifyHKLMAccess(const wchar_t* sub_key) { + HKEY root = HKEY_LOCAL_MACHINE; + wchar_t str[] = L"test"; + bool result = false; + DWORD disposition = 0; + HKEY key = NULL; + + if (::RegCreateKeyEx(root, sub_key, 0, NULL, + REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, + &key, &disposition) == ERROR_SUCCESS) { + if (::RegSetValueEx(key, str, 0, REG_SZ, (LPBYTE)str, + (DWORD)lstrlen(str)) == ERROR_SUCCESS) { + result = true; + RegDeleteValue(key, str); + } + + // If we create the main key, delete the entire key. + if (disposition == REG_CREATED_NEW_KEY) + RegDeleteKey(key, NULL); + + RegCloseKey(key); + } + + return result; +} + +bool IsRunningElevated() { + // This method should be called only for Vista or later. + bool is_vista_or_later = false; + IsWinXPSp1OrLater(&is_vista_or_later); + if (!is_vista_or_later || !VerifyAdminGroup()) + return false; + + HANDLE process_token; + if (!::OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &process_token)) + return false; + + TOKEN_ELEVATION_TYPE elevation_type = TokenElevationTypeDefault; + DWORD size_returned = 0; + if (!::GetTokenInformation(process_token, TokenElevationType, + &elevation_type, sizeof(elevation_type), + &size_returned)) { + ::CloseHandle(process_token); + return false; + } + + ::CloseHandle(process_token); + return (elevation_type == TokenElevationTypeFull); +} + +bool GetUserIdForProcess(size_t pid, wchar_t** user_sid) { + HANDLE process_handle = ::OpenProcess(PROCESS_QUERY_INFORMATION, TRUE, pid); + if (process_handle == NULL) + return false; + + HANDLE process_token; + bool result = false; + if (::OpenProcessToken(process_handle, TOKEN_QUERY, &process_token)) { + DWORD size = 0; + ::GetTokenInformation(process_token, TokenUser, NULL, 0, &size); + if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER || + ::GetLastError() == ERROR_SUCCESS) { + DWORD actual_size = 0; + BYTE* token_user = new BYTE[size]; + if ((::GetTokenInformation(process_token, TokenUser, token_user, size, + &actual_size)) && + (actual_size <= size)) { + PSID sid = reinterpret_cast<TOKEN_USER*>(token_user)->User.Sid; + if (::ConvertSidToStringSid(sid, user_sid)) + result = true; + } + delete[] token_user; + } + ::CloseHandle(process_token); + } + ::CloseHandle(process_handle); + return result; +} +} // namespace + +#pragma comment(linker, "/EXPORT:GoogleChromeCompatibilityCheck=_GoogleChromeCompatibilityCheck@8,PRIVATE") +DLLEXPORT BOOL __stdcall GoogleChromeCompatibilityCheck(BOOL set_flag, DWORD *reasons) { + DWORD local_reasons = 0; + + bool is_vista_or_later = false; + // System requirements? + if (!IsWinXPSp1OrLater(&is_vista_or_later)) + local_reasons |= GCCC_ERROR_OSNOTSUPPORTED; + + if (IsChromeInstalled(HKEY_LOCAL_MACHINE)) + local_reasons |= GCCC_ERROR_SYSTEMLEVELALREADYPRESENT; + + if (IsChromeInstalled(HKEY_CURRENT_USER)) + local_reasons |= GCCC_ERROR_USERLEVELALREADYPRESENT; + + if (!VerifyHKLMAccess(kChromeRegClientsKey)) { + local_reasons |= GCCC_ERROR_ACCESSDENIED; + } else if (is_vista_or_later && !VerifyAdminGroup()) { + // For Vista or later check for elevation since even for admin user we could + // be running in non-elevated mode. We require integrity level High. + local_reasons |= GCCC_ERROR_INTEGRITYLEVEL; + } + + // First clean up the registry keys left over previously. + // Then only check whether we can re-offer, if everything else is OK. + CleanUpRegistryValues(); + if (local_reasons == 0 && !CanReOfferChrome(set_flag)) + local_reasons |= GCCC_ERROR_ALREADYOFFERED; + + // Done. Copy/return results. + if (reasons != NULL) + *reasons = local_reasons; + + return (*reasons == 0); +} + +#pragma comment(linker, "/EXPORT:LaunchGoogleChrome=_LaunchGoogleChrome@0,PRIVATE") +DLLEXPORT 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)) { + return false; + } + } + + HRESULT hr = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + if (hr != S_OK) { + if (hr == S_FALSE) + ::CoUninitialize(); + return false; + } + + 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; + } + + bool impersonation_success = false; + if (IsRunningElevated()) { + wchar_t* curr_proc_sid; + if (!GetUserIdForProcess(GetCurrentProcessId(), &curr_proc_sid)) { + ::CoUninitialize(); + return false; + } + + DWORD pid = 0; + ::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) { + HANDLE process_token; + HANDLE user_token; + if (::OpenProcessToken(process_handle, TOKEN_DUPLICATE | TOKEN_QUERY, + &process_token) && + ::DuplicateTokenEx(process_token, + TOKEN_IMPERSONATE | TOKEN_QUERY | + TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE, + NULL, SecurityImpersonation, + TokenPrimary, &user_token) && + (::ImpersonateLoggedOnUser(user_token) != 0)) { + impersonation_success = true; + } + ::CloseHandle(user_token); + ::CloseHandle(process_token); + ::CloseHandle(process_handle); + } + } + ::LocalFree(exp_proc_sid); + } + + ::LocalFree(curr_proc_sid); + if (!impersonation_success) { + ::CoUninitialize(); + return false; + } + } + + bool ret = false; + CComPtr<IProcessLauncher> ipl; + if (!FAILED(ipl.CoCreateInstance(__uuidof(ProcessLauncherClass), NULL, + CLSCTX_LOCAL_SERVER))) { + if (!FAILED(ipl->LaunchCmdLine(launch_cmd))) + ret = true; + ipl.Release(); + } + + if (impersonation_success) + ::RevertToSelf(); + ::CoUninitialize(); + return ret; +} diff --git a/chrome/installer/gcapi/gcapi.h b/chrome/installer/gcapi/gcapi.h index 6ee4557..4d45d30 100644 --- a/chrome/installer/gcapi/gcapi.h +++ b/chrome/installer/gcapi/gcapi.h @@ -23,9 +23,9 @@ extern "C" { // for the reason, you can pass NULL for reasons. // set_flag indicates whether a flag should be set indicating that Chrome was // offered within the last six months; if passed FALSE, this method will not -// set the flag even if Chrome can be offered. If passed TRUE, this method +// set the flag even if Chrome can be offered. If passed TRUE, this method // will set the flag only if Chrome can be offered. -DLLEXPORT BOOL __stdcall GoogleChromeCompatibilityCheck(BOOL set_flag, +DLLEXPORT BOOL __stdcall GoogleChromeCompatibilityCheck(BOOL set_flag, DWORD *reasons); // This function launches Google Chrome after a successful install. Make @@ -36,6 +36,6 @@ DLLEXPORT BOOL __stdcall LaunchGoogleChrome(); // Funtion pointer type declarations to use with GetProcAddress. typedef BOOL (__stdcall * GCCC_CompatibilityCheck)(BOOL, DWORD *); typedef BOOL (__stdcall * GCCC_LaunchGC)(HANDLE *); -} // extern "C" +} // extern "C" #endif // # CHROME_INSTALLER_GCAPI_GCAPI_H_ diff --git a/chrome/installer/gcapi/gcapi_test.cc b/chrome/installer/gcapi/gcapi_test.cc index 268033d..838397cd 100644 --- a/chrome/installer/gcapi/gcapi_test.cc +++ b/chrome/installer/gcapi/gcapi_test.cc @@ -14,9 +14,9 @@ void call_statically() { // running this twice verifies that the first call does not set // a flag that would make the second fail. Thus, the results // of the two calls should be the same (no state should have changed) - result_flag_off = GoogleChromeCompatibilityCheck(FALSE, &reason); + result_flag_off = GoogleChromeCompatibilityCheck(FALSE, &reason); result_flag_on = GoogleChromeCompatibilityCheck(TRUE, &reason); - + if (result_flag_off != result_flag_on) printf("Registry key flag is not being set properly."); @@ -30,7 +30,7 @@ void call_dynamically() { printf("Couldn't load gcapi_dll.dll.\n"); return; } - + GCCC_CompatibilityCheck gccfn = (GCCC_CompatibilityCheck) GetProcAddress( module, "GoogleChromeCompatibilityCheck"); if (gccfn != NULL) { diff --git a/chrome/installer/gcapi/resource.h b/chrome/installer/gcapi/resource.h index 8295c6c..3b9f419 100644 --- a/chrome/installer/gcapi/resource.h +++ b/chrome/installer/gcapi/resource.h @@ -1,14 +1,14 @@ -//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by gcapi_test.rc
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 101
-#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1001
-#define _APS_NEXT_SYMED_VALUE 101
-#endif
-#endif
+//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by gcapi_test.rc + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/chrome/installer/mini_installer/mini_installer.cc b/chrome/installer/mini_installer/mini_installer.cc index d81c992..6c659be 100644 --- a/chrome/installer/mini_installer/mini_installer.cc +++ b/chrome/installer/mini_installer/mini_installer.cc @@ -405,7 +405,7 @@ int WMain(HMODULE module) { if (!RunSetup(have_upacked_setup, base_path, archive_name, &setup_exit_code)) { return setup_exit_code; - } + } wchar_t value[4]; if ((!ReadValueFromRegistry(HKEY_CURRENT_USER, kCleanupRegistryKey, diff --git a/chrome/installer/setup/main.cc b/chrome/installer/setup/main.cc index fd2404a..6a2a170 100644 --- a/chrome/installer/setup/main.cc +++ b/chrome/installer/setup/main.cc @@ -252,7 +252,7 @@ int GetInstallOptions(const CommandLine& cmd_line) { if (preferences & installer_util::MASTER_PROFILE_VERBOSE_LOGGING || cmd_line.HasSwitch(installer_util::switches::kVerboseLogging)) options |= installer_util::VERBOSE_LOGGING; - + return options; } diff --git a/chrome/installer/util/copy_tree_work_item.cc b/chrome/installer/util/copy_tree_work_item.cc index fc1d5e3..0b51f95 100644 --- a/chrome/installer/util/copy_tree_work_item.cc +++ b/chrome/installer/util/copy_tree_work_item.cc @@ -68,7 +68,7 @@ bool CopyTreeWorkItem::Do() { (overwrite_option_ == WorkItem::IF_NOT_PRESENT)) { // handle overwrite_option_ = IF_NOT_PRESENT case. return true; - } + } // In all cases that reach here, move dest to a backup path. if (dest_exist) { diff --git a/chrome/installer/util/html_dialog.h b/chrome/installer/util/html_dialog.h index 39b741d..46ed1c8 100644 --- a/chrome/installer/util/html_dialog.h +++ b/chrome/installer/util/html_dialog.h @@ -16,7 +16,7 @@ namespace installer { -// Interface for implementing a native HTML dialog. +// Interface for implementing a native HTML dialog. class HTMLDialog { public: enum DialogResult { @@ -44,7 +44,7 @@ class HTMLDialog { // in HTML so each native implementation needs to map the user action into // one of the 6 possible results of DialogResult. Important, call this // method only from the main (or UI) thread. - virtual DialogResult ShowModal(void* parent_window, + virtual DialogResult ShowModal(void* parent_window, CustomizationCallback* callback) = 0; // If the result of ShowModal() was EXTRA, the information is available diff --git a/chrome/installer/util/html_dialog_impl.cc b/chrome/installer/util/html_dialog_impl.cc index a758d42..8925016 100644 --- a/chrome/installer/util/html_dialog_impl.cc +++ b/chrome/installer/util/html_dialog_impl.cc @@ -32,7 +32,7 @@ namespace installer { // <input name="accept" type="checkbox" /> My cool option // <input name="submit" type="submit" value="[accept]" /> // </form> -// +// // function submit_it(f) { // if (f.accept.checked) { // window.returnValue = 1; <-- this matches HTML_DLG_ACCEPT @@ -85,7 +85,7 @@ HTMLDialogWin::CustomizationCallback* HTMLDialogWin::callback_ = NULL; // This hook function gets called for messages bound to the windows that // ShowHTMLDialog creates. We tell apart the top window because it has the -// system menu style. +// system menu style. LRESULT HTMLDialogWin::MsgFilter(int code, WPARAM wParam, LPARAM lParam) { static bool tweak_window = true; if (lParam && tweak_window) { @@ -113,7 +113,7 @@ bool HTMLDialogWin::InternalDoDialog(CustomizationCallback* callback, IMoniker *url_moniker = NULL; ::CreateURLMoniker(NULL, url_.c_str(), &url_moniker); - if (!url_moniker) + if (!url_moniker) return false; wchar_t* extra_args = NULL; diff --git a/chrome/installer/util/prebuild/create_string_rc.py b/chrome/installer/util/prebuild/create_string_rc.py index bb4e5a0..2c53380 100755 --- a/chrome/installer/util/prebuild/create_string_rc.py +++ b/chrome/installer/util/prebuild/create_string_rc.py @@ -150,7 +150,7 @@ def WriteHeaderFile(translated_strings, out_filename): """Writes a .h file with resource ids. This file can be included by the executable to refer to identifiers.""" lines = [] - + # Write the values for how the languages ids are offset. seen_languages = set() offset_id = 0 @@ -180,7 +180,7 @@ def WriteHeaderFile(translated_strings, out_filename): outfile.write('\n'.join(lines)) outfile.write('\n') # .rc files must end in a new line outfile.close() - + def main(argv): translated_strings = CollectTranslatedStrings() kFilebase = os.path.join(argv[1], 'installer_util_strings') diff --git a/chrome/installer/util/util_constants.h b/chrome/installer/util/util_constants.h index 246a50f..b9d7275 100644 --- a/chrome/installer/util/util_constants.h +++ b/chrome/installer/util/util_constants.h @@ -16,8 +16,8 @@ enum InstallStatus { INSTALL_REPAIRED, // Same version reinstalled for repair NEW_VERSION_UPDATED, // Chrome successfully updated to new version HIGHER_VERSION_EXISTS, // Higher version of Chrome already exists - USER_LEVEL_INSTALL_EXISTS, // User level install already exists - SYSTEM_LEVEL_INSTALL_EXISTS, // Machine level install already exists + USER_LEVEL_INSTALL_EXISTS, // User level install already exists + SYSTEM_LEVEL_INSTALL_EXISTS, // Machine level install already exists INSTALL_FAILED, // Install/update failed OS_NOT_SUPPORTED, // Current OS not supported OS_ERROR, // OS API call failed |