Home | History | Annotate | Download | only in chrome_elf
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome_elf/chrome_elf_util.h"
      6 
      7 #include <windows.h>
      8 
      9 #include "base/macros.h"
     10 #include "base/strings/string16.h"
     11 
     12 namespace {
     13 
     14 const wchar_t kRegPathClientState[] = L"Software\\Google\\Update\\ClientState";
     15 const wchar_t kRegPathClientStateMedium[] =
     16     L"Software\\Google\\Update\\ClientStateMedium";
     17 #if defined(GOOGLE_CHROME_BUILD)
     18 const wchar_t kRegPathChromePolicy[] = L"SOFTWARE\\Policies\\Google\\Chrome";
     19 #else
     20 const wchar_t kRegPathChromePolicy[] = L"SOFTWARE\\Policies\\Chromium";
     21 #endif  // defined(GOOGLE_CHROME_BUILD)
     22 
     23 const wchar_t kRegValueUsageStats[] = L"usagestats";
     24 const wchar_t kUninstallArgumentsField[] = L"UninstallArguments";
     25 const wchar_t kMetricsReportingEnabled[] =L"MetricsReportingEnabled";
     26 
     27 const wchar_t kAppGuidCanary[] =
     28     L"{4ea16ac7-fd5a-47c3-875b-dbf4a2008c20}";
     29 const wchar_t kAppGuidGoogleChrome[] =
     30     L"{8A69D345-D564-463c-AFF1-A69D9E530F96}";
     31 const wchar_t kAppGuidGoogleBinaries[] =
     32     L"{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D}";
     33 
     34 bool ReadKeyValueString(bool system_install, const wchar_t* key_path,
     35                         const wchar_t* guid, const wchar_t* value_to_read,
     36                         base::string16* value_out) {
     37   HKEY key = NULL;
     38   value_out->clear();
     39 
     40   base::string16 full_key_path(key_path);
     41   full_key_path.append(1, L'\\');
     42   full_key_path.append(guid);
     43 
     44   if (::RegOpenKeyEx(system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
     45                      full_key_path.c_str(), 0,
     46                      KEY_QUERY_VALUE | KEY_WOW64_32KEY, &key) !=
     47                      ERROR_SUCCESS) {
     48     return false;
     49   }
     50 
     51   const size_t kMaxStringLength = 1024;
     52   wchar_t raw_value[kMaxStringLength] = {};
     53   DWORD size = sizeof(raw_value);
     54   DWORD type = REG_SZ;
     55   LONG result = ::RegQueryValueEx(key, value_to_read, 0, &type,
     56                                   reinterpret_cast<LPBYTE>(raw_value), &size);
     57 
     58   if (result == ERROR_SUCCESS) {
     59     if (type != REG_SZ || (size & 1) != 0) {
     60       result = ERROR_NOT_SUPPORTED;
     61     } else if (size == 0) {
     62       *raw_value = L'\0';
     63     } else if (raw_value[size / sizeof(wchar_t) - 1] != L'\0') {
     64       if ((size / sizeof(wchar_t)) < kMaxStringLength)
     65         raw_value[size / sizeof(wchar_t)] = L'\0';
     66       else
     67         result = ERROR_MORE_DATA;
     68     }
     69   }
     70 
     71   if (result == ERROR_SUCCESS)
     72     *value_out = raw_value;
     73 
     74   ::RegCloseKey(key);
     75 
     76   return result == ERROR_SUCCESS;
     77 }
     78 
     79 bool ReadKeyValueDW(bool system_install, const wchar_t* key_path,
     80                     base::string16 guid, const wchar_t* value_to_read,
     81                     DWORD* value_out) {
     82   HKEY key = NULL;
     83   *value_out = 0;
     84 
     85   base::string16 full_key_path(key_path);
     86   full_key_path.append(1, L'\\');
     87   full_key_path.append(guid);
     88 
     89   if (::RegOpenKeyEx(system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
     90                      full_key_path.c_str(), 0,
     91                      KEY_QUERY_VALUE | KEY_WOW64_32KEY, &key) !=
     92                      ERROR_SUCCESS) {
     93     return false;
     94   }
     95 
     96   DWORD size = sizeof(*value_out);
     97   DWORD type = REG_DWORD;
     98   LONG result = ::RegQueryValueEx(key, value_to_read, 0, &type,
     99                                   reinterpret_cast<BYTE*>(value_out), &size);
    100 
    101   ::RegCloseKey(key);
    102 
    103   return result == ERROR_SUCCESS && size == sizeof(*value_out);
    104 }
    105 
    106 }  // namespace
    107 
    108 bool IsCanary(const wchar_t* exe_path) {
    109   return wcsstr(exe_path, L"Chrome SxS\\Application") != NULL;
    110 }
    111 
    112 bool IsSystemInstall(const wchar_t* exe_path) {
    113   wchar_t program_dir[MAX_PATH] = {};
    114   DWORD ret = ::GetEnvironmentVariable(L"PROGRAMFILES", program_dir,
    115                                        arraysize(program_dir));
    116   if (ret && ret < MAX_PATH && !wcsncmp(exe_path, program_dir, ret))
    117     return true;
    118 
    119   ret = ::GetEnvironmentVariable(L"PROGRAMFILES(X86)", program_dir,
    120                                  arraysize(program_dir));
    121   if (ret && ret < MAX_PATH && !wcsncmp(exe_path, program_dir, ret))
    122     return true;
    123 
    124   return false;
    125 }
    126 
    127 bool IsMultiInstall(bool is_system_install) {
    128   base::string16 args;
    129   if (!ReadKeyValueString(is_system_install, kRegPathClientState,
    130                           kAppGuidGoogleChrome, kUninstallArgumentsField,
    131                           &args)) {
    132     return false;
    133   }
    134   return args.find(L"--multi-install") != base::string16::npos;
    135 }
    136 
    137 bool AreUsageStatsEnabled(const wchar_t* exe_path) {
    138   bool enabled = true;
    139   bool controlled_by_policy = ReportingIsEnforcedByPolicy(&enabled);
    140 
    141   if (controlled_by_policy && !enabled)
    142     return false;
    143 
    144   bool system_install = IsSystemInstall(exe_path);
    145   base::string16 app_guid;
    146 
    147   if (IsCanary(exe_path)) {
    148     app_guid = kAppGuidCanary;
    149   } else {
    150     app_guid = IsMultiInstall(system_install) ? kAppGuidGoogleBinaries :
    151                                                 kAppGuidGoogleChrome;
    152   }
    153 
    154   DWORD out_value = 0;
    155   if (system_install &&
    156       ReadKeyValueDW(system_install, kRegPathClientStateMedium, app_guid,
    157                      kRegValueUsageStats, &out_value)) {
    158     return out_value == 1;
    159   }
    160 
    161   return ReadKeyValueDW(system_install, kRegPathClientState, app_guid,
    162                         kRegValueUsageStats, &out_value) && out_value == 1;
    163 }
    164 
    165 bool ReportingIsEnforcedByPolicy(bool* breakpad_enabled) {
    166   HKEY key = NULL;
    167   DWORD value = 0;
    168   BYTE* value_bytes = reinterpret_cast<BYTE*>(&value);
    169   DWORD size = sizeof(value);
    170   DWORD type = REG_DWORD;
    171 
    172   if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, kRegPathChromePolicy, 0,
    173                      KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) {
    174     if (::RegQueryValueEx(key, kMetricsReportingEnabled, 0, &type,
    175                           value_bytes, &size) == ERROR_SUCCESS) {
    176       *breakpad_enabled = value != 0;
    177     }
    178     ::RegCloseKey(key);
    179     return size == sizeof(value);
    180   }
    181 
    182   if (::RegOpenKeyEx(HKEY_CURRENT_USER, kRegPathChromePolicy, 0,
    183                      KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) {
    184     if (::RegQueryValueEx(key, kMetricsReportingEnabled, 0, &type,
    185                           value_bytes, &size) == ERROR_SUCCESS) {
    186       *breakpad_enabled = value != 0;
    187     }
    188     ::RegCloseKey(key);
    189     return size == sizeof(value);
    190   }
    191 
    192   return false;
    193 }
    194 
    195 bool IsNonBrowserProcess() {
    196   typedef bool (*IsSandboxedProcessFunc)();
    197   IsSandboxedProcessFunc is_sandboxed_process_func =
    198       reinterpret_cast<IsSandboxedProcessFunc>(
    199           GetProcAddress(GetModuleHandle(NULL), "IsSandboxedProcess"));
    200   bool is_sandboxed_process =
    201       is_sandboxed_process_func && is_sandboxed_process_func();
    202 
    203   // TODO(robertshield): Drop the command line check when we drop support for
    204   // enabling chrome_elf in unsandboxed processes.
    205   wchar_t* command_line = GetCommandLine();
    206   bool has_process_type_flag = command_line && wcsstr(command_line, L"--type");
    207 
    208   return (has_process_type_flag || is_sandboxed_process);
    209 }
    210