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