Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // NOTE: This code is a legacy utility API for partners to check whether | |
| 6 // Chrome can be installed and launched. Recent updates are being made | |
| 7 // to add new functionality. These updates use code from Chromium, the old | |
| 8 // coded against the win32 api directly. If you have an itch to shave a | |
| 9 // yak, feel free to re-write the old code too. | |
| 10 | |
| 5 #include "chrome/installer/gcapi/gcapi.h" | 11 #include "chrome/installer/gcapi/gcapi.h" |
| 6 | 12 |
| 7 #include <atlbase.h> | 13 #include <atlbase.h> |
| 8 #include <atlcom.h> | 14 #include <atlcom.h> |
| 9 #include <windows.h> | |
| 10 #include <sddl.h> | 15 #include <sddl.h> |
| 11 #define STRSAFE_NO_DEPRECATE | 16 #define STRSAFE_NO_DEPRECATE |
| 12 #include <strsafe.h> | 17 #include <strsafe.h> |
| 13 #include <tlhelp32.h> | 18 #include <tlhelp32.h> |
| 19 #include <windows.h> | |
| 14 | 20 |
| 21 #include <algorithm> | |
| 15 #include <cstdlib> | 22 #include <cstdlib> |
| 23 #include <limits> | |
| 24 #include <string> | |
| 16 | 25 |
| 17 #include "google_update_idl.h" | 26 #include "base/basictypes.h" |
| 27 #include "base/string_number_conversions.h" | |
| 28 #include "base/time.h" | |
| 29 #include "base/win/registry.h" | |
| 30 #include "chrome/installer/util/google_update_constants.h" | |
| 31 | |
| 32 #include "google_update_idl.h" // NOLINT | |
| 18 | 33 |
| 19 namespace { | 34 namespace { |
| 20 | 35 |
| 21 const wchar_t kChromeRegClientsKey[] = | 36 const wchar_t kChromeRegClientsKey[] = |
| 22 L"Software\\Google\\Update\\Clients\\" | 37 L"Software\\Google\\Update\\Clients\\" |
| 23 L"{8A69D345-D564-463c-AFF1-A69D9E530F96}"; | 38 L"{8A69D345-D564-463c-AFF1-A69D9E530F96}"; |
| 24 const wchar_t kChromeRegClientStateKey[] = | 39 const wchar_t kChromeRegClientStateKey[] = |
| 25 L"Software\\Google\\Update\\ClientState\\" | 40 L"Software\\Google\\Update\\ClientState\\" |
| 26 L"{8A69D345-D564-463c-AFF1-A69D9E530F96}"; | 41 L"{8A69D345-D564-463c-AFF1-A69D9E530F96}"; |
| 42 const wchar_t kChromeRegClientStateMediumKey[] = | |
| 43 L"Software\\Google\\Update\\ClientStateMedium\\" | |
| 44 L"{8A69D345-D564-463c-AFF1-A69D9E530F96}"; | |
| 45 | |
| 27 const wchar_t kChromeRegLaunchCmd[] = L"InstallerSuccessLaunchCmdLine"; | 46 const wchar_t kChromeRegLaunchCmd[] = L"InstallerSuccessLaunchCmdLine"; |
| 28 const wchar_t kChromeRegLastLaunchCmd[] = L"LastInstallerSuccessLaunchCmdLine"; | 47 const wchar_t kChromeRegLastLaunchCmd[] = L"LastInstallerSuccessLaunchCmdLine"; |
| 29 const wchar_t kChromeRegVersion[] = L"pv"; | 48 const wchar_t kChromeRegVersion[] = L"pv"; |
| 30 const wchar_t kNoChromeOfferUntil[] = | 49 const wchar_t kNoChromeOfferUntil[] = |
| 31 L"SOFTWARE\\Google\\No Chrome Offer Until"; | 50 L"SOFTWARE\\Google\\No Chrome Offer Until"; |
| 32 | 51 |
| 33 // Return the company name specified in the file version info resource. | 52 // Return the company name specified in the file version info resource. |
| 34 bool GetCompanyName(const wchar_t* filename, wchar_t* buffer, DWORD out_len) { | 53 bool GetCompanyName(const wchar_t* filename, wchar_t* buffer, DWORD out_len) { |
| 35 wchar_t file_version_info[8192]; | 54 wchar_t file_version_info[8192]; |
| 36 DWORD handle = 0; | 55 DWORD handle = 0; |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 63 memcpy(&lang, data, 4); | 82 memcpy(&lang, data, 4); |
| 64 ::StringCchPrintf(info_name, _countof(info_name), | 83 ::StringCchPrintf(info_name, _countof(info_name), |
| 65 L"\\StringFileInfo\\%02X%02X%02X%02X\\CompanyName", | 84 L"\\StringFileInfo\\%02X%02X%02X%02X\\CompanyName", |
| 66 (lang & 0xff00)>>8, (lang & 0xff), (lang & 0xff000000)>>24, | 85 (lang & 0xff00)>>8, (lang & 0xff), (lang & 0xff000000)>>24, |
| 67 (lang & 0xff0000)>>16); | 86 (lang & 0xff0000)>>16); |
| 68 | 87 |
| 69 data_len = 0; | 88 data_len = 0; |
| 70 if (!::VerQueryValue(file_version_info, info_name, | 89 if (!::VerQueryValue(file_version_info, info_name, |
| 71 reinterpret_cast<LPVOID *>(&data), reinterpret_cast<UINT *>(&data_len))) | 90 reinterpret_cast<LPVOID *>(&data), reinterpret_cast<UINT *>(&data_len))) |
| 72 return false; | 91 return false; |
| 73 if (data_len <= 0 || data_len >= out_len) | 92 if (data_len <= 0 || data_len >= (out_len / sizeof(wchar_t))) |
| 74 return false; | 93 return false; |
| 75 | 94 |
| 76 memset(buffer, 0, out_len); | 95 memset(buffer, 0, out_len); |
| 77 ::StringCchCopyN(buffer, out_len, (const wchar_t*)data, data_len); | 96 ::StringCchCopyN(buffer, |
| 97 (out_len / sizeof(wchar_t)), | |
| 98 reinterpret_cast<const wchar_t*>(data), | |
| 99 data_len); | |
| 78 return true; | 100 return true; |
| 79 } | 101 } |
| 80 | 102 |
| 81 // Return true if we can re-offer Chrome; false, otherwise. | 103 // Return true if we can re-offer Chrome; false, otherwise. |
| 82 // Each partner can only offer Chrome once every six months. | 104 // Each partner can only offer Chrome once every six months. |
| 83 bool CanReOfferChrome(BOOL set_flag) { | 105 bool CanReOfferChrome(BOOL set_flag) { |
| 84 wchar_t filename[MAX_PATH+1]; | 106 wchar_t filename[MAX_PATH+1]; |
| 85 wchar_t company[MAX_PATH]; | 107 wchar_t company[MAX_PATH]; |
| 86 | 108 |
| 87 // If we cannot retrieve the version info of the executable or company | 109 // If we cannot retrieve the version info of the executable or company |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 133 } | 155 } |
| 134 | 156 |
| 135 ::RegCloseKey(key); | 157 ::RegCloseKey(key); |
| 136 } | 158 } |
| 137 | 159 |
| 138 return can_re_offer; | 160 return can_re_offer; |
| 139 } | 161 } |
| 140 | 162 |
| 141 // Helper function to read a value from registry. Returns true if value | 163 // Helper function to read a value from registry. Returns true if value |
| 142 // is read successfully and stored in parameter value. Returns false otherwise. | 164 // is read successfully and stored in parameter value. Returns false otherwise. |
| 143 bool ReadValueFromRegistry(HKEY root_key, const wchar_t *sub_key, | 165 bool ReadValueFromRegistry(HKEY root_key, const wchar_t* sub_key, |
| 144 const wchar_t *value_name, wchar_t *value, | 166 const wchar_t* value_name, wchar_t* value, |
| 145 size_t *size) { | 167 size_t* size) { |
| 146 HKEY key; | 168 HKEY key; |
| 147 if ((::RegOpenKeyEx(root_key, sub_key, NULL, | 169 if ((::RegOpenKeyEx(root_key, sub_key, NULL, |
| 148 KEY_READ, &key) == ERROR_SUCCESS) && | 170 KEY_READ, &key) == ERROR_SUCCESS) && |
| 149 (::RegQueryValueEx(key, value_name, NULL, NULL, | 171 (::RegQueryValueEx(key, value_name, NULL, NULL, |
| 150 reinterpret_cast<LPBYTE>(value), | 172 reinterpret_cast<LPBYTE>(value), |
| 151 reinterpret_cast<LPDWORD>(size)) == ERROR_SUCCESS)) { | 173 reinterpret_cast<LPDWORD>(size)) == ERROR_SUCCESS)) { |
| 152 ::RegCloseKey(key); | 174 ::RegCloseKey(key); |
| 153 return true; | 175 return true; |
| 154 } | 176 } |
| 155 return false; | 177 return false; |
| 156 } | 178 } |
| 157 | 179 |
| 158 bool IsChromeInstalled(HKEY root_key) { | 180 bool IsChromeInstalled(HKEY root_key) { |
| 159 wchar_t version[64]; | 181 wchar_t version[64]; |
| 160 size_t size = _countof(version); | 182 size_t size = _countof(version); |
| 161 return ReadValueFromRegistry(root_key, kChromeRegClientsKey, | 183 return ReadValueFromRegistry(root_key, kChromeRegClientsKey, |
| 162 kChromeRegVersion, version, &size); | 184 kChromeRegVersion, version, &size); |
| 163 } | 185 } |
| 164 | 186 |
| 165 enum WindowsVersion { | 187 enum WindowsVersion { |
| 166 VERSION_BELOW_XP_SP2, | 188 VERSION_BELOW_XP_SP2, |
| 167 VERSION_XP_SP2_UP_TO_VISTA, // "but not including" | 189 VERSION_XP_SP2_UP_TO_VISTA, // "but not including" |
| 168 VERSION_VISTA_OR_HIGHER, | 190 VERSION_VISTA_OR_HIGHER, |
| 169 }; | 191 }; |
| 170 WindowsVersion GetWindowsVersion() { | 192 WindowsVersion GetWindowsVersion() { |
| 171 OSVERSIONINFOEX version_info = { sizeof version_info }; | 193 OSVERSIONINFOEX version_info = { sizeof version_info }; |
| 172 GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&version_info)); | 194 GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&version_info)); |
| 173 | 195 |
| 174 // Windows Vista is version 6.0. | 196 // Windows Vista is version 6.0. |
| 175 if (version_info.dwMajorVersion >= 6) | 197 if (version_info.dwMajorVersion >= 6) |
| 176 return VERSION_VISTA_OR_HIGHER; | 198 return VERSION_VISTA_OR_HIGHER; |
| 177 | 199 |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 276 } | 298 } |
| 277 delete[] token_user; | 299 delete[] token_user; |
| 278 } | 300 } |
| 279 ::CloseHandle(process_token); | 301 ::CloseHandle(process_token); |
| 280 } | 302 } |
| 281 ::CloseHandle(process_handle); | 303 ::CloseHandle(process_handle); |
| 282 return result; | 304 return result; |
| 283 } | 305 } |
| 284 } // namespace | 306 } // namespace |
| 285 | 307 |
| 286 #pragma comment(linker, "/EXPORT:GoogleChromeCompatibilityCheck=_GoogleChromeCom patibilityCheck@8,PRIVATE") | 308 BOOL __stdcall GoogleChromeCompatibilityCheck(BOOL set_flag, DWORD* reasons) { |
| 287 DLLEXPORT BOOL __stdcall GoogleChromeCompatibilityCheck(BOOL set_flag, | |
| 288 DWORD *reasons) { | |
| 289 DWORD local_reasons = 0; | 309 DWORD local_reasons = 0; |
| 290 | 310 |
| 291 WindowsVersion windows_version = GetWindowsVersion(); | 311 WindowsVersion windows_version = GetWindowsVersion(); |
| 292 // System requirements? | 312 // System requirements? |
| 293 if (windows_version == VERSION_BELOW_XP_SP2) | 313 if (windows_version == VERSION_BELOW_XP_SP2) |
| 294 local_reasons |= GCCC_ERROR_OSNOTSUPPORTED; | 314 local_reasons |= GCCC_ERROR_OSNOTSUPPORTED; |
| 295 | 315 |
| 296 if (IsChromeInstalled(HKEY_LOCAL_MACHINE)) | 316 if (IsChromeInstalled(HKEY_LOCAL_MACHINE)) |
| 297 local_reasons |= GCCC_ERROR_SYSTEMLEVELALREADYPRESENT; | 317 local_reasons |= GCCC_ERROR_SYSTEMLEVELALREADYPRESENT; |
| 298 | 318 |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 312 if (local_reasons == 0 && !CanReOfferChrome(set_flag)) | 332 if (local_reasons == 0 && !CanReOfferChrome(set_flag)) |
| 313 local_reasons |= GCCC_ERROR_ALREADYOFFERED; | 333 local_reasons |= GCCC_ERROR_ALREADYOFFERED; |
| 314 | 334 |
| 315 // Done. Copy/return results. | 335 // Done. Copy/return results. |
| 316 if (reasons != NULL) | 336 if (reasons != NULL) |
| 317 *reasons = local_reasons; | 337 *reasons = local_reasons; |
| 318 | 338 |
| 319 return (local_reasons == 0); | 339 return (local_reasons == 0); |
| 320 } | 340 } |
| 321 | 341 |
| 322 #pragma comment(linker, "/EXPORT:LaunchGoogleChrome=_LaunchGoogleChrome@0,PRIVAT E") | 342 BOOL __stdcall LaunchGoogleChrome() { |
| 323 DLLEXPORT BOOL __stdcall LaunchGoogleChrome() { | |
| 324 wchar_t launch_cmd[MAX_PATH]; | 343 wchar_t launch_cmd[MAX_PATH]; |
| 325 size_t size = _countof(launch_cmd); | 344 size_t size = _countof(launch_cmd); |
| 326 if (!ReadValueFromRegistry(HKEY_LOCAL_MACHINE, kChromeRegClientStateKey, | 345 if (!ReadValueFromRegistry(HKEY_LOCAL_MACHINE, kChromeRegClientStateKey, |
| 327 kChromeRegLastLaunchCmd, launch_cmd, &size)) { | 346 kChromeRegLastLaunchCmd, launch_cmd, &size)) { |
| 328 size = _countof(launch_cmd); | 347 size = _countof(launch_cmd); |
| 329 if (!ReadValueFromRegistry(HKEY_LOCAL_MACHINE, kChromeRegClientStateKey, | 348 if (!ReadValueFromRegistry(HKEY_LOCAL_MACHINE, kChromeRegClientStateKey, |
| 330 kChromeRegLaunchCmd, launch_cmd, &size)) { | 349 kChromeRegLaunchCmd, launch_cmd, &size)) { |
| 331 return false; | 350 return false; |
| 332 } | 351 } |
| 333 } | 352 } |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 406 ret = true; | 425 ret = true; |
| 407 ipl.Release(); | 426 ipl.Release(); |
| 408 } | 427 } |
| 409 | 428 |
| 410 if (impersonation_success) | 429 if (impersonation_success) |
| 411 ::RevertToSelf(); | 430 ::RevertToSelf(); |
| 412 ::CoUninitialize(); | 431 ::CoUninitialize(); |
| 413 return ret; | 432 return ret; |
| 414 } | 433 } |
| 415 | 434 |
| 416 #pragma comment(linker, "/EXPORT:LaunchGoogleChromeWithDimensions=_LaunchGoogleC hromeWithDimensions@16,PRIVATE") | 435 BOOL __stdcall LaunchGoogleChromeWithDimensions(int x, |
| 417 DLLEXPORT BOOL __stdcall LaunchGoogleChromeWithDimensions(int x, | 436 int y, |
| 418 int y, | 437 int width, |
| 419 int width, | 438 int height) { |
| 420 int height) { | |
| 421 if (!LaunchGoogleChrome()) | 439 if (!LaunchGoogleChrome()) |
| 422 return false; | 440 return false; |
| 423 | 441 |
| 424 HWND handle = NULL; | 442 HWND handle = NULL; |
| 425 int seconds_elapsed = 0; | 443 int seconds_elapsed = 0; |
| 426 | 444 |
| 427 // Chrome may have been launched, but the window may not have appeared | 445 // Chrome may have been launched, but the window may not have appeared |
| 428 // yet. Wait for it to appear for 10 seconds, but exit if it takes longer | 446 // yet. Wait for it to appear for 10 seconds, but exit if it takes longer |
| 429 // than that. | 447 // than that. |
| 430 while (!handle && seconds_elapsed < 10) { | 448 while (!handle && seconds_elapsed < 10) { |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 444 // This loop iterates through all of the top-level Windows named | 462 // This loop iterates through all of the top-level Windows named |
| 445 // Chrome_WindowImpl_0, and looks for the first one with any children. | 463 // Chrome_WindowImpl_0, and looks for the first one with any children. |
| 446 while (handle && !FindWindowEx(handle, NULL, L"Chrome_WindowImpl_0", NULL)) { | 464 while (handle && !FindWindowEx(handle, NULL, L"Chrome_WindowImpl_0", NULL)) { |
| 447 // Get the next top-level Chrome window. | 465 // Get the next top-level Chrome window. |
| 448 handle = FindWindowEx(NULL, handle, L"Chrome_WindowImpl_0", NULL); | 466 handle = FindWindowEx(NULL, handle, L"Chrome_WindowImpl_0", NULL); |
| 449 } | 467 } |
| 450 | 468 |
| 451 return (handle && | 469 return (handle && |
| 452 SetWindowPos(handle, 0, x, y, width, height, SWP_NOZORDER)); | 470 SetWindowPos(handle, 0, x, y, width, height, SWP_NOZORDER)); |
| 453 } | 471 } |
| 472 | |
| 473 int __stdcall GoogleChromeDaysSinceLastRun() { | |
| 474 using base::win::RegKey; | |
| 475 using base::Time; | |
| 476 using base::TimeDelta; | |
| 477 | |
| 478 int days_since_last_run = std::numeric_limits<int>::max(); | |
| 479 | |
| 480 struct { | |
| 481 HKEY hive; | |
| 482 const wchar_t* path; | |
| 483 } reg_data[] = { | |
| 484 { HKEY_LOCAL_MACHINE, kChromeRegClientStateMediumKey }, | |
| 485 { HKEY_CURRENT_USER, kChromeRegClientStateKey } | |
| 486 }; | |
| 487 | |
| 488 for (int i = 0; i < arraysize(reg_data); ++i) { | |
| 489 RegKey client_state(reg_data[i].hive, reg_data[i].path, KEY_QUERY_VALUE); | |
|
grt (UTC plus 2)
2011/11/14 14:24:09
i think this is prone to flakiness since it doesn'
robertshield
2011/11/14 15:13:49
Done.
| |
| 490 if (client_state.Valid()) { | |
| 491 std::wstring last_run; | |
| 492 int64 last_run_value = 0; | |
| 493 if (client_state.ReadValue(google_update::kRegLastRunTimeField, | |
| 494 &last_run) == ERROR_SUCCESS && | |
| 495 base::StringToInt64(last_run, &last_run_value)) { | |
| 496 Time last_run_time = Time::FromInternalValue(last_run_value); | |
| 497 TimeDelta difference = Time::NowFromSystemTime() - last_run_time; | |
| 498 | |
| 499 // We can end up with negative numbers here, given changes in system | |
| 500 // clock time or due to TimeDelta's int64 -> int truncation. | |
| 501 int new_days_since_last_run = difference.InDays(); | |
| 502 if (new_days_since_last_run >= 0) { | |
|
grt (UTC plus 2)
2011/11/14 14:24:09
heh. now that you need this check anyway, i'd get
robertshield
2011/11/14 15:13:49
Done.
| |
| 503 days_since_last_run = std::min(days_since_last_run, | |
| 504 new_days_since_last_run); | |
| 505 } | |
| 506 } | |
| 507 } | |
| 508 } | |
| 509 | |
| 510 if (days_since_last_run == std::numeric_limits<int>::max()) { | |
| 511 days_since_last_run = -1; | |
| 512 } | |
| 513 | |
| 514 return days_since_last_run; | |
| 515 } | |
| OLD | NEW |