Chromium Code Reviews| Index: chrome/installer/mini_installer/mini_installer.cc |
| diff --git a/chrome/installer/mini_installer/mini_installer.cc b/chrome/installer/mini_installer/mini_installer.cc |
| index 9656ca2ddbc8f49fe442d026ce749e863a3c8a0e..7ca6e9f122a78f44c34582afcd6ec7b7117f8c7b 100644 |
| --- a/chrome/installer/mini_installer/mini_installer.cc |
| +++ b/chrome/installer/mini_installer/mini_installer.cc |
| @@ -74,89 +74,99 @@ struct Context { |
| PathString* setup_resource_path; |
| }; |
| - |
| -// Opens the Google Update ClientState key for the current install |
| -// configuration. This includes locating the correct key in the face of |
| -// multi-install. The flag will by default be written to HKCU, but if |
| -// --system-level is included in the command line, it will be written to |
| -// HKLM instead. |
| -bool OpenInstallStateKey(const Configuration& configuration, RegKey* key) { |
| +#if defined(GOOGLE_CHROME_BUILD) |
| +// Opens the Google Update ClientState key. If |binaries| is false, opens the |
| +// key for Google Chrome or Chrome SxS (canary). If |binaries| is true and an |
| +// existing multi-install Chrome is being updated, opens the key for the |
| +// binaries; otherwise, returns false. |
| +bool OpenInstallStateKey(const Configuration& configuration, |
| + bool binaries, |
| + RegKey* key) { |
| + if (binaries && !configuration.is_updating_multi_chrome()) |
| + return false; |
| const HKEY root_key = |
| configuration.is_system_level() ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; |
| - const wchar_t* app_guid = configuration.chrome_app_guid(); |
| + const wchar_t* app_guid = binaries ? google_update::kMultiInstallAppGuid |
| + : configuration.chrome_app_guid(); |
| const REGSAM key_access = KEY_QUERY_VALUE | KEY_SET_VALUE; |
| - return OpenClientStateKey(root_key, app_guid, key_access, key); |
| + return OpenClientStateKey(root_key, app_guid, key_access, key) == |
| + ERROR_SUCCESS; |
| } |
| -// Writes install results into registry where it is read by Google Update. |
| +// Writes install results into the registry where it is read by Google Update. |
| // Don't write anything if there is already a result present, likely |
| // written by setup.exe. |
| void WriteInstallResults(const Configuration& configuration, |
| ProcessExitResult result) { |
| -#if defined(GOOGLE_CHROME_BUILD) |
| // Calls to setup.exe will write a "success" result if everything was good |
| // so we don't need to write anything from here. |
| if (result.IsSuccess()) |
| return; |
| - RegKey key; |
| - DWORD value; |
| - if (OpenInstallStateKey(configuration, &key)) { |
| - if (key.ReadDWValue(kInstallerResultRegistryValue, &value) |
| - != ERROR_SUCCESS || value == 0) { |
| - key.WriteDWValue(kInstallerResultRegistryValue, |
| - result.exit_code ? 1 /* FAILED_CUSTOM_ERROR */ |
| - : 0 /* SUCCESS */); |
| - key.WriteDWValue(kInstallerErrorRegistryValue, result.exit_code); |
| - key.WriteDWValue(kInstallerExtraCode1RegistryValue, result.windows_error); |
| + // Write the value in Chrome ClientState key and in the binaries' if an |
| + // existing multi-install Chrome is being updated. |
|
gab
2016/12/12 21:38:16
Is this because the cleanup is two phase? i.e. fir
grt (UTC plus 2)
2016/12/13 09:20:37
No, it's single phase. This is so that the results
gab
2016/12/14 16:33:38
Aaaah, I see, that's what I hadn't realized : on e
|
| + for (int i = 0; i < 2; ++i) { |
| + RegKey key; |
| + DWORD value; |
| + if (OpenInstallStateKey(configuration, i != 0, &key)) { |
| + if (key.ReadDWValue(kInstallerResultRegistryValue, &value) != |
| + ERROR_SUCCESS || |
| + value == 0) { |
| + key.WriteDWValue(kInstallerResultRegistryValue, |
| + result.exit_code ? 1 /* FAILED_CUSTOM_ERROR */ |
| + : 0 /* SUCCESS */); |
| + key.WriteDWValue(kInstallerErrorRegistryValue, result.exit_code); |
| + key.WriteDWValue(kInstallerExtraCode1RegistryValue, |
| + result.windows_error); |
| + } |
| } |
| - key.Close(); |
| } |
| -#endif |
| } |
| // This function sets the flag in registry to indicate that Google Update |
| // should try full installer next time. If the current installer works, this |
| // flag is cleared by setup.exe at the end of install. |
| void SetInstallerFlags(const Configuration& configuration) { |
| - RegKey key; |
| StackString<128> value; |
| - LONG ret = ERROR_SUCCESS; |
| - |
| - if (!OpenInstallStateKey(configuration, &key)) |
| - return; |
| - |
| - ret = key.ReadSZValue(kApRegistryValue, value.get(), value.capacity()); |
| - // The conditions below are handling two cases: |
| - // 1. When ap value is present, we want to add the required tag only if it is |
| - // not present. |
| - // 2. When ap value is missing, we are going to create it with the required |
| - // tag. |
| - if ((ret == ERROR_SUCCESS) || (ret == ERROR_FILE_NOT_FOUND)) { |
| - if (ret == ERROR_FILE_NOT_FOUND) |
| - value.clear(); |
| - |
| - if (!StrEndsWith(value.get(), kFullInstallerSuffix) && |
| - value.append(kFullInstallerSuffix)) { |
| - key.WriteSZValue(kApRegistryValue, value.get()); |
| + for (int i = 0; i < 2; ++i) { |
| + RegKey key; |
| + if (!OpenInstallStateKey(configuration, i != 0, &key)) |
| + continue; |
| + |
| + LONG ret = key.ReadSZValue(kApRegistryValue, value.get(), value.capacity()); |
| + |
| + // The conditions below are handling two cases: |
| + // 1. When ap value is present, we want to add the required tag only if it |
| + // is not present. |
| + // 2. When ap value is missing, we are going to create it with the required |
| + // tag. |
| + if ((ret == ERROR_SUCCESS) || (ret == ERROR_FILE_NOT_FOUND)) { |
| + if (ret == ERROR_FILE_NOT_FOUND) |
| + value.clear(); |
| + |
| + if (!StrEndsWith(value.get(), kFullInstallerSuffix) && |
| + value.append(kFullInstallerSuffix)) { |
| + key.WriteSZValue(kApRegistryValue, value.get()); |
| + } |
| } |
| } |
| } |
| +#endif // GOOGLE_CHROME_BUILD |
| // Gets the setup.exe path from Registry by looking at the value of Uninstall |
| // string. |size| is measured in wchar_t units. |
| ProcessExitResult GetSetupExePathForAppGuid(bool system_level, |
| - const wchar_t* app_guid, |
| - const wchar_t* previous_version, |
| - wchar_t* path, |
| - size_t size) { |
| + const wchar_t* app_guid, |
| + const wchar_t* previous_version, |
| + wchar_t* path, |
| + size_t size) { |
| const HKEY root_key = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; |
| RegKey key; |
| - if (!OpenClientStateKey(root_key, app_guid, KEY_QUERY_VALUE, &key)) |
| - return ProcessExitResult(UNABLE_TO_FIND_REGISTRY_KEY); |
| - DWORD result = key.ReadSZValue(kUninstallRegistryValue, path, size); |
| + LONG result = OpenClientStateKey(root_key, app_guid, KEY_QUERY_VALUE, &key); |
| + if (result == ERROR_SUCCESS) |
| + result = key.ReadSZValue(kUninstallRegistryValue, path, size); |
| if (result != ERROR_SUCCESS) |
| return ProcessExitResult(UNABLE_TO_FIND_REGISTRY_KEY, result); |
| @@ -173,24 +183,23 @@ ProcessExitResult GetSetupExePathForAppGuid(bool system_level, |
| // in the Uninstall string in the registry. A previous version number specified |
| // in |configuration| is used if available. |size| is measured in wchar_t units. |
| ProcessExitResult GetPreviousSetupExePath(const Configuration& configuration, |
| - wchar_t* path, |
| - size_t size) { |
| + wchar_t* path, |
| + size_t size) { |
| bool system_level = configuration.is_system_level(); |
| const wchar_t* previous_version = configuration.previous_version(); |
| ProcessExitResult exit_code = ProcessExitResult(GENERIC_ERROR); |
| - // If this is a multi install, first try looking in the binaries for the path. |
| - if (configuration.is_multi_install()) { |
| - exit_code = GetSetupExePathForAppGuid( |
| - system_level, google_update::kMultiInstallAppGuid, previous_version, |
| - path, size); |
| - } |
| - |
| - // Make a last-ditch effort to look in the Chrome client state key. |
| - if (!exit_code.IsSuccess()) { |
| - exit_code = GetSetupExePathForAppGuid( |
| - system_level, configuration.chrome_app_guid(), previous_version, |
| - path, size); |
| + // Check Chrome's ClientState key for the path to setup.exe. This will have |
| + // the correct path for all well-functioning installs. |
| + exit_code = |
| + GetSetupExePathForAppGuid(system_level, configuration.chrome_app_guid(), |
| + previous_version, path, size); |
| + |
| + // Failing that, check the binaries if updating multi-install Chrome. |
| + if (!exit_code.IsSuccess() && configuration.is_updating_multi_chrome()) { |
| + exit_code = GetSetupExePathForAppGuid(system_level, |
| + google_update::kMultiInstallAppGuid, |
| + previous_version, path, size); |
| } |
| return exit_code; |
| @@ -451,8 +460,8 @@ ProcessExitResult UnpackBinaryResources(const Configuration& configuration, |
| // Executes setup.exe, waits for it to finish and returns the exit code. |
| ProcessExitResult RunSetup(const Configuration& configuration, |
| - const wchar_t* archive_path, |
| - const wchar_t* setup_path) { |
| + const wchar_t* archive_path, |
| + const wchar_t* setup_path) { |
| // There could be three full paths in the command line for setup.exe (path |
| // to exe itself, path to archive and path to log file), so we declare |
| // total size as three + one additional to hold command line options. |
| @@ -848,8 +857,9 @@ ProcessExitResult WMain(HMODULE module) { |
| #if defined(GOOGLE_CHROME_BUILD) |
| // Set the magic suffix in registry to try full installer next time. We ignore |
| // any errors here and we try to set the suffix for user level unless |
| - // --system-level is on the command line in which case we set it for system |
| - // level instead. This only applies to the Google Chrome distribution. |
| + // GoogleUpdateIsMachine=1 is present in the environment or --system-level is |
| + // on the command line in which case we set it for system level instead. This |
| + // only applies to the Google Chrome distribution. |
| SetInstallerFlags(configuration); |
| #endif |
| @@ -869,7 +879,10 @@ ProcessExitResult WMain(HMODULE module) { |
| if (ShouldDeleteExtractedFiles()) |
| DeleteExtractedFiles(base_path.get(), archive_path.get(), setup_path.get()); |
| +#if defined(GOOGLE_CHROME_BUILD) |
| WriteInstallResults(configuration, exit_code); |
| +#endif |
| + |
| return exit_code; |
| } |