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 |