| 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 acbdc260ac6c8ed2c744bb29a7e25897dc6d3d1f..3c1bba8667abfa212c15a63309aec64a1bc0fd73 100644
|
| --- a/chrome/installer/mini_installer/mini_installer.cc
|
| +++ b/chrome/installer/mini_installer/mini_installer.cc
|
| @@ -32,13 +32,27 @@
|
| #include "chrome/installer/mini_installer/mini_installer_constants.h"
|
| #include "chrome/installer/mini_installer/mini_string.h"
|
| #include "chrome/installer/mini_installer/pe_resource.h"
|
| +#include "chrome/installer/mini_installer/regkey.h"
|
|
|
| namespace mini_installer {
|
|
|
| -typedef DWORD ProcessExitCode;
|
| typedef StackString<MAX_PATH> PathString;
|
| typedef StackString<MAX_PATH * 4> CommandString;
|
|
|
| +struct ProcessExitResult {
|
| + DWORD exit_code;
|
| + DWORD windows_error;
|
| +
|
| + explicit ProcessExitResult(DWORD exit) : exit_code(exit), windows_error(0) {}
|
| + ProcessExitResult(DWORD exit, DWORD win)
|
| + : exit_code(exit), windows_error(win) {
|
| + }
|
| +
|
| + bool IsSuccess() {
|
| + return exit_code == SUCCESS_EXIT_CODE;
|
| + }
|
| +};
|
| +
|
| // This structure passes data back and forth for the processing
|
| // of resource callbacks.
|
| struct Context {
|
| @@ -50,167 +64,61 @@ struct Context {
|
| PathString* setup_resource_path;
|
| };
|
|
|
| -// A helper class used to manipulate the Windows registry. Typically, members
|
| -// return Windows last-error codes a la the Win32 registry API.
|
| -class RegKey {
|
| - public:
|
| - RegKey() : key_(NULL) { }
|
| - ~RegKey() { Close(); }
|
| -
|
| - // Opens the key named |sub_key| with given |access| rights. Returns
|
| - // ERROR_SUCCESS or some other error.
|
| - LONG Open(HKEY key, const wchar_t* sub_key, REGSAM access);
|
| -
|
| - // Returns true if a key is open.
|
| - bool is_valid() const { return key_ != NULL; }
|
| -
|
| - // Read a REG_SZ value from the registry into the memory indicated by |value|
|
| - // (of |value_size| wchar_t units). Returns ERROR_SUCCESS,
|
| - // ERROR_FILE_NOT_FOUND, ERROR_MORE_DATA, or some other error. |value| is
|
| - // guaranteed to be null-terminated on success.
|
| - LONG ReadValue(const wchar_t* value_name,
|
| - wchar_t* value,
|
| - size_t value_size) const;
|
| -
|
| - // Write a REG_SZ value to the registry. |value| must be null-terminated.
|
| - // Returns ERROR_SUCCESS or an error code.
|
| - LONG WriteValue(const wchar_t* value_name, const wchar_t* value);
|
| -
|
| - // Closes the key if it was open.
|
| - void Close();
|
| -
|
| - private:
|
| - RegKey(const RegKey&);
|
| - RegKey& operator=(const RegKey&);
|
| -
|
| - HKEY key_;
|
| -}; // class RegKey
|
| -
|
| -LONG RegKey::Open(HKEY key, const wchar_t* sub_key, REGSAM access) {
|
| - Close();
|
| - return ::RegOpenKeyEx(key, sub_key, NULL, access, &key_);
|
| -}
|
|
|
| -LONG RegKey::ReadValue(const wchar_t* value_name,
|
| - wchar_t* value,
|
| - size_t value_size) const {
|
| - DWORD type;
|
| - DWORD byte_length = static_cast<DWORD>(value_size * sizeof(wchar_t));
|
| - LONG result = ::RegQueryValueEx(key_, value_name, NULL, &type,
|
| - reinterpret_cast<BYTE*>(value),
|
| - &byte_length);
|
| - if (result == ERROR_SUCCESS) {
|
| - if (type != REG_SZ) {
|
| - result = ERROR_NOT_SUPPORTED;
|
| - } else if (byte_length == 0) {
|
| - *value = L'\0';
|
| - } else if (value[byte_length/sizeof(wchar_t) - 1] != L'\0') {
|
| - if ((byte_length / sizeof(wchar_t)) < value_size)
|
| - value[byte_length / sizeof(wchar_t)] = L'\0';
|
| - else
|
| - result = ERROR_MORE_DATA;
|
| - }
|
| - }
|
| - return result;
|
| -}
|
| +// 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) {
|
| + const HKEY root_key =
|
| + configuration.is_system_level() ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
|
| + const wchar_t* app_guid = configuration.chrome_app_guid();
|
| + const REGSAM key_access = KEY_QUERY_VALUE | KEY_SET_VALUE;
|
| + LONG ret = ERROR_SUCCESS;
|
|
|
| -LONG RegKey::WriteValue(const wchar_t* value_name, const wchar_t* value) {
|
| - return ::RegSetValueEx(key_, value_name, 0, REG_SZ,
|
| - reinterpret_cast<const BYTE*>(value),
|
| - (lstrlen(value) + 1) * sizeof(wchar_t));
|
| + return OpenClientStateKey(root_key, app_guid, key_access, key);
|
| }
|
|
|
| -void RegKey::Close() {
|
| - if (key_ != NULL) {
|
| - ::RegCloseKey(key_);
|
| - key_ = NULL;
|
| - }
|
| -}
|
| +// Writes install results into 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;
|
|
|
| -// Helper function to read a value from registry. Returns true if value
|
| -// is read successfully and stored in parameter value. Returns false otherwise.
|
| -// |size| is measured in wchar_t units.
|
| -bool ReadValueFromRegistry(HKEY root_key, const wchar_t *sub_key,
|
| - const wchar_t *value_name, wchar_t *value,
|
| - size_t size) {
|
| RegKey key;
|
| -
|
| - if (key.Open(root_key, sub_key, KEY_QUERY_VALUE) == ERROR_SUCCESS &&
|
| - key.ReadValue(value_name, value, size) == ERROR_SUCCESS) {
|
| - return true;
|
| + 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);
|
| + }
|
| + key.Close();
|
| }
|
| - return false;
|
| -}
|
| -
|
| -// Opens the Google Update ClientState key for a product. This finds only
|
| -// registry entries for Chrome; it does not support the Chromium registry
|
| -// layout.
|
| -bool OpenClientStateKey(HKEY root_key, const wchar_t* app_guid, REGSAM access,
|
| - RegKey* key) {
|
| - PathString client_state_key;
|
| - return client_state_key.assign(kClientStateKeyBase) &&
|
| - client_state_key.append(app_guid) &&
|
| - (key->Open(root_key,
|
| - client_state_key.get(),
|
| - access | KEY_WOW64_32KEY) == ERROR_SUCCESS);
|
| +#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. 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.
|
| -// TODO(grt): Write a unit test for this that uses registry virtualization.
|
| +// flag is cleared by setup.exe at the end of install.
|
| void SetInstallerFlags(const Configuration& configuration) {
|
| RegKey key;
|
| - const REGSAM key_access = KEY_QUERY_VALUE | KEY_SET_VALUE;
|
| - const HKEY root_key =
|
| - configuration.is_system_level() ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
|
| - // This is ignored if multi-install is true.
|
| - const wchar_t* app_guid =
|
| - configuration.has_chrome_frame() ?
|
| - google_update::kChromeFrameAppGuid :
|
| - configuration.chrome_app_guid();
|
| StackString<128> value;
|
| LONG ret = ERROR_SUCCESS;
|
|
|
| - // When multi_install is true, we are potentially:
|
| - // 1. Performing a multi-install of some product(s) on a clean machine.
|
| - // Neither the product(s) nor the multi-installer will have a ClientState
|
| - // key in the registry, so there is nothing to be done.
|
| - // 2. Upgrading an existing multi-install. The multi-installer will have a
|
| - // ClientState key in the registry. Only it need be modified.
|
| - // 3. Migrating a single-install into a multi-install. The product will have
|
| - // a ClientState key in the registry. Only it need be modified.
|
| - // To handle all cases, we inspect the product's ClientState to see if it
|
| - // exists and its "ap" value does not contain "-multi". This is case 3, so we
|
| - // modify the product's ClientState. Otherwise, we check the
|
| - // multi-installer's ClientState and modify it if it exists.
|
| - if (configuration.is_multi_install()) {
|
| - if (OpenClientStateKey(root_key, app_guid, key_access, &key)) {
|
| - // The product has a client state key. See if it's a single-install.
|
| - ret = key.ReadValue(kApRegistryValue, value.get(), value.capacity());
|
| - if (ret != ERROR_FILE_NOT_FOUND &&
|
| - (ret != ERROR_SUCCESS ||
|
| - FindTagInStr(value.get(), kMultiInstallTag, NULL))) {
|
| - // Error or case 2: modify the multi-installer's value.
|
| - key.Close();
|
| - app_guid = google_update::kMultiInstallAppGuid;
|
| - } // else case 3: modify this value.
|
| - } else {
|
| - // case 1 or 2: modify the multi-installer's value.
|
| - key.Close();
|
| - app_guid = google_update::kMultiInstallAppGuid;
|
| - }
|
| - }
|
| + if (!OpenInstallStateKey(configuration, &key))
|
| + return;
|
|
|
| - if (!key.is_valid()) {
|
| - if (!OpenClientStateKey(root_key, app_guid, key_access, &key))
|
| - return;
|
| -
|
| - value.clear();
|
| - ret = key.ReadValue(kApRegistryValue, value.get(), value.capacity());
|
| - }
|
| + 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
|
| @@ -223,43 +131,44 @@ void SetInstallerFlags(const Configuration& configuration) {
|
|
|
| if (!StrEndsWith(value.get(), kFullInstallerSuffix) &&
|
| value.append(kFullInstallerSuffix)) {
|
| - key.WriteValue(kApRegistryValue, value.get());
|
| + key.WriteSZValue(kApRegistryValue, value.get());
|
| }
|
| }
|
| }
|
|
|
| // Gets the setup.exe path from Registry by looking at the value of Uninstall
|
| // string. |size| is measured in wchar_t units.
|
| -ProcessExitCode GetSetupExePathForAppGuid(bool system_level,
|
| +ProcessExitResult GetSetupExePathForAppGuid(bool system_level,
|
| 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) ||
|
| - (key.ReadValue(kUninstallRegistryValue, path, size) != ERROR_SUCCESS)) {
|
| - return UNABLE_TO_FIND_REGISTRY_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);
|
| + if (result != ERROR_SUCCESS)
|
| + return ProcessExitResult(UNABLE_TO_FIND_REGISTRY_KEY, result);
|
|
|
| // Check that the path to the existing installer includes the expected
|
| // version number. It's not necessary for accuracy to verify before/after
|
| // delimiters.
|
| if (!SearchStringI(path, previous_version))
|
| - return PATCH_NOT_FOR_INSTALLED_VERSION;
|
| + return ProcessExitResult(PATCH_NOT_FOR_INSTALLED_VERSION);
|
|
|
| - return SUCCESS_EXIT_CODE;
|
| + return ProcessExitResult(SUCCESS_EXIT_CODE);
|
| }
|
|
|
| // Gets the path to setup.exe of the previous version. The overall path is found
|
| // 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.
|
| -ProcessExitCode GetPreviousSetupExePath(const Configuration& configuration,
|
| +ProcessExitResult GetPreviousSetupExePath(const Configuration& configuration,
|
| wchar_t* path,
|
| size_t size) {
|
| bool system_level = configuration.is_system_level();
|
| const wchar_t* previous_version = configuration.previous_version();
|
| - ProcessExitCode exit_code = GENERIC_ERROR;
|
| + 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()) {
|
| @@ -270,14 +179,14 @@ ProcessExitCode GetPreviousSetupExePath(const Configuration& configuration,
|
|
|
| // Failing that, look in Chrome Frame's client state key if --chrome-frame was
|
| // specified.
|
| - if (exit_code != SUCCESS_EXIT_CODE && configuration.has_chrome_frame()) {
|
| + if (!exit_code.IsSuccess() && configuration.has_chrome_frame()) {
|
| exit_code = GetSetupExePathForAppGuid(
|
| system_level, google_update::kChromeFrameAppGuid, previous_version,
|
| path, size);
|
| }
|
|
|
| // Make a last-ditch effort to look in the Chrome client state key.
|
| - if (exit_code != SUCCESS_EXIT_CODE) {
|
| + if (!exit_code.IsSuccess()) {
|
| exit_code = GetSetupExePathForAppGuid(
|
| system_level, configuration.chrome_app_guid(), previous_version,
|
| path, size);
|
| @@ -289,24 +198,28 @@ ProcessExitCode GetPreviousSetupExePath(const Configuration& configuration,
|
| // Calls CreateProcess with good default parameters and waits for the process to
|
| // terminate returning the process exit code. |exit_code|, if non-NULL, is
|
| // populated with the process exit code.
|
| -ProcessExitCode RunProcessAndWait(const wchar_t* exe_path, wchar_t* cmdline) {
|
| +ProcessExitResult RunProcessAndWait(const wchar_t* exe_path, wchar_t* cmdline) {
|
| STARTUPINFOW si = {sizeof(si)};
|
| PROCESS_INFORMATION pi = {0};
|
| if (!::CreateProcess(exe_path, cmdline, NULL, NULL, FALSE, CREATE_NO_WINDOW,
|
| NULL, NULL, &si, &pi)) {
|
| - return COULD_NOT_CREATE_PROCESS;
|
| + return ProcessExitResult(COULD_NOT_CREATE_PROCESS, ::GetLastError());
|
| }
|
|
|
| ::CloseHandle(pi.hThread);
|
|
|
| - ProcessExitCode exit_code = SUCCESS_EXIT_CODE;
|
| + DWORD exit_code = SUCCESS_EXIT_CODE;
|
| DWORD wr = ::WaitForSingleObject(pi.hProcess, INFINITE);
|
| - if (WAIT_OBJECT_0 != wr || !::GetExitCodeProcess(pi.hProcess, &exit_code))
|
| - exit_code = WAIT_FOR_PROCESS_FAILED;
|
| + if (WAIT_OBJECT_0 != wr || !::GetExitCodeProcess(pi.hProcess, &exit_code)) {
|
| + // Note: We've assumed that WAIT_OBJCT_0 != wr means a failure. The call
|
| + // could return a different object but since we never spawn more than one
|
| + // sub-process at a time that case should never happen.
|
| + return ProcessExitResult(WAIT_FOR_PROCESS_FAILED, ::GetLastError());
|
| + }
|
|
|
| ::CloseHandle(pi.hProcess);
|
|
|
| - return exit_code;
|
| + return ProcessExitResult(exit_code);
|
| }
|
|
|
| // Appends any command line params passed to mini_installer to the given buffer
|
| @@ -428,7 +341,7 @@ BOOL CALLBACK WriteResourceToDirectory(HMODULE module,
|
| // For component builds (where setup.ex_ is always used), all files stored as
|
| // uncompressed 'BN' resources are also extracted. This is generally the set of
|
| // DLLs/resources needed by setup.exe to run.
|
| -ProcessExitCode UnpackBinaryResources(const Configuration& configuration,
|
| +ProcessExitResult UnpackBinaryResources(const Configuration& configuration,
|
| HMODULE module, const wchar_t* base_path,
|
| PathString* archive_path,
|
| PathString* setup_path) {
|
| @@ -436,7 +349,7 @@ ProcessExitCode UnpackBinaryResources(const Configuration& configuration,
|
| PathString setup_dest_path;
|
| if (!setup_dest_path.assign(base_path) ||
|
| !setup_dest_path.append(kSetupExe))
|
| - return PATH_STRING_OVERFLOW;
|
| + return ProcessExitResult(PATH_STRING_OVERFLOW);
|
|
|
| // Prepare the input to OnResourceFound method that needs a location where
|
| // it will write all the resources.
|
| @@ -450,11 +363,15 @@ ProcessExitCode UnpackBinaryResources(const Configuration& configuration,
|
| // We need a chrome archive to do the installation. So if there
|
| // is a problem in fetching B7 resource, just return an error.
|
| if (!::EnumResourceNames(module, kLZMAResourceType, OnResourceFound,
|
| - reinterpret_cast<LONG_PTR>(&context)) ||
|
| - archive_path->length() == 0)
|
| - return UNABLE_TO_EXTRACT_CHROME_ARCHIVE;
|
| + reinterpret_cast<LONG_PTR>(&context))) {
|
| + return ProcessExitResult(UNABLE_TO_EXTRACT_CHROME_ARCHIVE,
|
| + ::GetLastError());
|
| + }
|
| + if (archive_path->length() == 0) {
|
| + return ProcessExitResult(UNABLE_TO_EXTRACT_CHROME_ARCHIVE);
|
| + }
|
|
|
| - ProcessExitCode exit_code = SUCCESS_EXIT_CODE;
|
| + ProcessExitResult exit_code = ProcessExitResult(SUCCESS_EXIT_CODE);
|
|
|
| // If we found setup 'B7' resource (used for differential updates), handle
|
| // it. Note that this is only for Chrome; Chromium installs are always
|
| @@ -465,7 +382,7 @@ ProcessExitCode UnpackBinaryResources(const Configuration& configuration,
|
| // Get the path to setup.exe first.
|
| exit_code = GetPreviousSetupExePath(configuration, exe_path.get(),
|
| exe_path.capacity());
|
| - if (exit_code == SUCCESS_EXIT_CODE) {
|
| + if (exit_code.IsSuccess()) {
|
| if (!cmd_line.append(exe_path.get()) ||
|
| !cmd_line.append(L" --") ||
|
| !cmd_line.append(kCmdUpdateSetupExe) ||
|
| @@ -476,7 +393,7 @@ ProcessExitCode UnpackBinaryResources(const Configuration& configuration,
|
| !cmd_line.append(L"=\"") ||
|
| !cmd_line.append(setup_dest_path.get()) ||
|
| !cmd_line.append(L"\"")) {
|
| - exit_code = COMMAND_STRING_OVERFLOW;
|
| + exit_code = ProcessExitResult(COMMAND_STRING_OVERFLOW);
|
| }
|
| }
|
|
|
| @@ -486,13 +403,13 @@ ProcessExitCode UnpackBinaryResources(const Configuration& configuration,
|
| // installer results for consumption by Google Update.
|
| AppendCommandLineFlags(configuration, &cmd_line);
|
|
|
| - if (exit_code == SUCCESS_EXIT_CODE)
|
| + if (exit_code.IsSuccess())
|
| exit_code = RunProcessAndWait(exe_path.get(), cmd_line.get());
|
|
|
| - if (exit_code != SUCCESS_EXIT_CODE)
|
| + if (!exit_code.IsSuccess())
|
| DeleteFile(setup_path->get());
|
| else if (!setup_path->assign(setup_dest_path.get()))
|
| - exit_code = PATH_STRING_OVERFLOW;
|
| + exit_code = ProcessExitResult(PATH_STRING_OVERFLOW);
|
|
|
| return exit_code;
|
| }
|
| @@ -501,8 +418,9 @@ ProcessExitCode UnpackBinaryResources(const Configuration& configuration,
|
| // (compressed setup).
|
| if (!::EnumResourceNames(module, kLZCResourceType, OnResourceFound,
|
| reinterpret_cast<LONG_PTR>(&context)) &&
|
| - ::GetLastError() != ERROR_RESOURCE_TYPE_NOT_FOUND)
|
| - return UNABLE_TO_EXTRACT_SETUP_B7;
|
| + ::GetLastError() != ERROR_RESOURCE_TYPE_NOT_FOUND) {
|
| + return ProcessExitResult(UNABLE_TO_EXTRACT_SETUP_B7, ::GetLastError());
|
| + }
|
|
|
| if (setup_path->length() > 0) {
|
| // Uncompress LZ compressed resource. Setup is packed with 'MSCF'
|
| @@ -513,17 +431,18 @@ ProcessExitCode UnpackBinaryResources(const Configuration& configuration,
|
| if (success) {
|
| if (!setup_path->assign(setup_dest_path.get())) {
|
| ::DeleteFile(setup_dest_path.get());
|
| - exit_code = PATH_STRING_OVERFLOW;
|
| + exit_code = ProcessExitResult(PATH_STRING_OVERFLOW);
|
| }
|
| } else {
|
| - exit_code = UNABLE_TO_EXTRACT_SETUP_EXE;
|
| + exit_code = ProcessExitResult(UNABLE_TO_EXTRACT_SETUP_EXE);
|
| }
|
|
|
| #if defined(COMPONENT_BUILD)
|
| // Extract the (uncompressed) modules required by setup.exe.
|
| if (!::EnumResourceNames(module, kBinResourceType, WriteResourceToDirectory,
|
| - reinterpret_cast<LONG_PTR>(base_path)))
|
| - return UNABLE_TO_EXTRACT_SETUP;
|
| + reinterpret_cast<LONG_PTR>(base_path))) {
|
| + return ProcessExitResult(UNABLE_TO_EXTRACT_SETUP, ::GetLastError());
|
| + }
|
| #endif
|
|
|
| return exit_code;
|
| @@ -535,8 +454,9 @@ ProcessExitCode UnpackBinaryResources(const Configuration& configuration,
|
| // it from create_installer_archive.py).
|
| if (!::EnumResourceNames(module, kBinResourceType, OnResourceFound,
|
| reinterpret_cast<LONG_PTR>(&context)) &&
|
| - ::GetLastError() != ERROR_RESOURCE_TYPE_NOT_FOUND)
|
| - return UNABLE_TO_EXTRACT_SETUP_BN;
|
| + ::GetLastError() != ERROR_RESOURCE_TYPE_NOT_FOUND) {
|
| + return ProcessExitResult(UNABLE_TO_EXTRACT_SETUP_BN, ::GetLastError());
|
| + }
|
|
|
| if (setup_path->length() > 0) {
|
| if (setup_path->comparei(setup_dest_path.get()) != 0) {
|
| @@ -551,13 +471,13 @@ ProcessExitCode UnpackBinaryResources(const Configuration& configuration,
|
| }
|
|
|
| if (setup_path->length() == 0)
|
| - exit_code = UNABLE_TO_EXTRACT_SETUP;
|
| + exit_code = ProcessExitResult(UNABLE_TO_EXTRACT_SETUP);
|
|
|
| return exit_code;
|
| }
|
|
|
| // Executes setup.exe, waits for it to finish and returns the exit code.
|
| -ProcessExitCode RunSetup(const Configuration& configuration,
|
| +ProcessExitResult RunSetup(const Configuration& configuration,
|
| const wchar_t* archive_path,
|
| const wchar_t* setup_path) {
|
| // There could be three full paths in the command line for setup.exe (path
|
| @@ -570,11 +490,11 @@ ProcessExitCode RunSetup(const Configuration& configuration,
|
| if (!cmd_line.assign(L"\"") ||
|
| !cmd_line.append(setup_path) ||
|
| !cmd_line.append(L"\""))
|
| - return COMMAND_STRING_OVERFLOW;
|
| + return ProcessExitResult(COMMAND_STRING_OVERFLOW);
|
| } else {
|
| - ProcessExitCode exit_code = GetPreviousSetupExePath(
|
| + ProcessExitResult exit_code = GetPreviousSetupExePath(
|
| configuration, cmd_line.get(), cmd_line.capacity());
|
| - if (exit_code != SUCCESS_EXIT_CODE)
|
| + if (!exit_code.IsSuccess())
|
| return exit_code;
|
| }
|
|
|
| @@ -590,7 +510,7 @@ ProcessExitCode RunSetup(const Configuration& configuration,
|
| !cmd_line.append(L"=\"") ||
|
| !cmd_line.append(archive_path) ||
|
| !cmd_line.append(L"\""))
|
| - return COMMAND_STRING_OVERFLOW;
|
| + return ProcessExitResult(COMMAND_STRING_OVERFLOW);
|
|
|
| // Append the command line param for chrome previous version.
|
| if (configuration.previous_version() &&
|
| @@ -599,7 +519,7 @@ ProcessExitCode RunSetup(const Configuration& configuration,
|
| !cmd_line.append(L"=\"") ||
|
| !cmd_line.append(configuration.previous_version()) ||
|
| !cmd_line.append(L"\""))) {
|
| - return COMMAND_STRING_OVERFLOW;
|
| + return ProcessExitResult(COMMAND_STRING_OVERFLOW);
|
| }
|
|
|
| // Get any command line option specified for mini_installer and pass them
|
| @@ -805,12 +725,12 @@ void DeleteOldChromeTempDirectories() {
|
| // required actions taken. The installer must exit and return the returned
|
| // |exit_code|.
|
| bool ProcessNonInstallOperations(const Configuration& configuration,
|
| - ProcessExitCode* exit_code) {
|
| + ProcessExitResult* exit_code) {
|
| switch (configuration.operation()) {
|
| case Configuration::CLEANUP:
|
| // Cleanup has already taken place in DeleteOldChromeTempDirectories at
|
| // this point, so just tell our caller to exit early.
|
| - *exit_code = SUCCESS_EXIT_CODE;
|
| + *exit_code = ProcessExitResult(SUCCESS_EXIT_CODE);
|
| return true;
|
|
|
| default:
|
| @@ -827,8 +747,8 @@ bool ProcessNonInstallOperations(const Configuration& configuration,
|
| // we continue to support it.
|
| bool ShouldDeleteExtractedFiles() {
|
| wchar_t value[2] = {0};
|
| - if (ReadValueFromRegistry(HKEY_CURRENT_USER, kCleanupRegistryKey,
|
| - kCleanupRegistryValue, value, _countof(value)) &&
|
| + if (RegKey::ReadSZValue(HKEY_CURRENT_USER, kCleanupRegistryKey,
|
| + kCleanupRegistryValue, value, _countof(value)) &&
|
| value[0] == L'0') {
|
| return false;
|
| }
|
| @@ -838,19 +758,19 @@ bool ShouldDeleteExtractedFiles() {
|
|
|
| // Main function. First gets a working dir, unpacks the resources and finally
|
| // executes setup.exe to do the install/upgrade.
|
| -ProcessExitCode WMain(HMODULE module) {
|
| +ProcessExitResult WMain(HMODULE module) {
|
| // Always start with deleting potential leftovers from previous installations.
|
| // This can make the difference between success and failure. We've seen
|
| // many installations out in the field fail due to out of disk space problems
|
| // so this could buy us some space.
|
| DeleteOldChromeTempDirectories();
|
|
|
| - ProcessExitCode exit_code = SUCCESS_EXIT_CODE;
|
| + ProcessExitResult exit_code = ProcessExitResult(SUCCESS_EXIT_CODE);
|
|
|
| // Parse configuration from the command line and resources.
|
| Configuration configuration;
|
| if (!configuration.Initialize(module))
|
| - return GENERIC_INITIALIZATION_FAILURE;
|
| + return ProcessExitResult(GENERIC_INITIALIZATION_FAILURE);
|
|
|
| // If the --cleanup switch was specified on the command line, then that means
|
| // we should only do the cleanup and then exit.
|
| @@ -860,7 +780,7 @@ ProcessExitCode WMain(HMODULE module) {
|
| // First get a path where we can extract payload
|
| PathString base_path;
|
| if (!GetWorkDir(module, &base_path))
|
| - return UNABLE_TO_GET_WORK_DIRECTORY;
|
| + return ProcessExitResult(UNABLE_TO_GET_WORK_DIRECTORY);
|
|
|
| #if defined(GOOGLE_CHROME_BUILD)
|
| // Set the magic suffix in registry to try full installer next time. We ignore
|
| @@ -880,21 +800,23 @@ ProcessExitCode WMain(HMODULE module) {
|
| // setup.
|
| ::SetProcessWorkingSetSize(::GetCurrentProcess(), -1, -1);
|
|
|
| - if (exit_code == SUCCESS_EXIT_CODE)
|
| + if (exit_code.IsSuccess())
|
| exit_code = RunSetup(configuration, archive_path.get(), setup_path.get());
|
|
|
| if (ShouldDeleteExtractedFiles())
|
| DeleteExtractedFiles(base_path.get(), archive_path.get(), setup_path.get());
|
|
|
| + WriteInstallResults(configuration, exit_code);
|
| return exit_code;
|
| }
|
|
|
| } // namespace mini_installer
|
|
|
| int MainEntryPoint() {
|
| - mini_installer::ProcessExitCode result =
|
| + mini_installer::ProcessExitResult result =
|
| mini_installer::WMain(::GetModuleHandle(NULL));
|
| - ::ExitProcess(result);
|
| +
|
| + ::ExitProcess(result.exit_code);
|
| }
|
|
|
| // VC Express editions don't come with the memset CRT obj file and linking to
|
|
|