Index: chrome/installer/mini_installer/mini_installer.cc |
=================================================================== |
--- chrome/installer/mini_installer/mini_installer.cc (revision 70612) |
+++ chrome/installer/mini_installer/mini_installer.cc (working copy) |
@@ -67,8 +67,8 @@ |
// ERROR_SUCCESS or some other error. |
LONG Open(HKEY key, const wchar_t* sub_key, REGSAM access); |
- // Returns true if the is open. |
- bool IsOpen() const { return key_ != NULL; } |
+ // 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, |
@@ -178,7 +178,7 @@ |
// Function to check if a string (specified by str) ends with another string |
// (specified by end_str). |
-bool StrEndsWith(const wchar_t *str, const wchar_t *end_str) { |
+bool StrEndsWith(const wchar_t* str, const wchar_t* end_str) { |
if (str == NULL || end_str == NULL) |
return false; |
@@ -192,7 +192,7 @@ |
// Function to check if a string (specified by str) starts with another string |
// (specified by start_str). |
-bool StrStartsWith(const wchar_t *str, const wchar_t *start_str) { |
+bool StrStartsWith(const wchar_t* str, const wchar_t* start_str) { |
if (str == NULL || start_str == NULL) |
return false; |
@@ -204,6 +204,26 @@ |
return true; |
} |
+// Searches for |tag| within |str|. Returns true if |tag| is found and is |
+// immediately followed by '-' or is at the end of the string. If |position| |
+// is non-NULL, the location of the tag is returned in |*position| on success. |
+bool FindTagInStr(const wchar_t* str, |
+ const wchar_t* tag, |
+ const wchar_t** position) { |
+ int tag_length = ::lstrlen(tag); |
+ const wchar_t* scan = str; |
+ for (const wchar_t* tag_start = StrStrI(scan, tag); tag_start != NULL; |
+ tag_start = StrStrI(scan, tag)) { |
+ scan = tag_start + tag_length; |
+ if (*scan == L'-' || *scan == L'\0') { |
+ if (position != NULL) |
+ *position = tag_start; |
+ return true; |
+ } |
+ } |
+ return false; |
+} |
+ |
// 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. |
@@ -231,7 +251,7 @@ |
} |
// TODO(grt): Write a unit test for this that uses registry virtualization. |
-void SetFullInstallerFlagHelper(int args_num, const wchar_t* const* args) { |
+void SetInstallerFlagsHelper(int args_num, const wchar_t* const* args) { |
bool multi_install = false; |
RegKey key; |
const REGSAM key_access = KEY_QUERY_VALUE | KEY_SET_VALUE; |
@@ -268,19 +288,20 @@ |
// The app is installed. See if it's a single-install. |
ret = key.ReadValue(kApRegistryValueName, value, _countof(value)); |
if (ret != ERROR_FILE_NOT_FOUND && |
- (ret != ERROR_SUCCESS || StrStr(value, kMultiInstallTag) != NULL)) { |
- // Error or case 2: add "-full" to the multi-installer's value. |
+ (ret != ERROR_SUCCESS || |
+ FindTagInStr(value, kMultiInstallTag, NULL))) { |
+ // Error or case 2: modify the multi-installer's value. |
key.Close(); |
app_guid = google_update::kMultiInstallAppGuid; |
- } // else case 3: add "-full" to this value. |
+ } // else case 3: modify this value. |
} else { |
- // case 1 or 2: add "-full" to the multi-installer's value. |
+ // case 1 or 2: modify the multi-installer's value. |
key.Close(); |
app_guid = google_update::kMultiInstallAppGuid; |
} |
} |
- if (!key.IsOpen()) { |
+ if (!key.is_valid()) { |
if (!OpenClientStateKey(root_key, app_guid, key_access, &key)) |
return; |
@@ -288,14 +309,28 @@ |
} |
// The conditions below are handling two cases: |
- // 1. When ap key is present, we want to make sure it doesn't already end |
- // in -full and then append -full to it. |
- // 2. When ap key is missing, we are going to create it with value -full. |
+ // 1. When ap key is present, we want to add the required tags only if they |
+ // are not present. |
+ // 2. When ap key is missing, we are going to create it with the required |
+ // tags. |
if ((ret == ERROR_SUCCESS) || (ret == ERROR_FILE_NOT_FOUND)) { |
if (ret == ERROR_FILE_NOT_FOUND) |
value[0] = L'\0'; |
- if (!StrEndsWith(value, kFullInstallerSuffix) && |
+ bool success = true; |
+ |
+ if (multi_install && |
+ !FindTagInStr(value, kMultifailInstallerSuffix, NULL)) { |
+ // We want -multifail to immediately precede -full. Chop off the latter |
+ // if it's already present so that we can simply do two appends. |
+ if (StrEndsWith(value, kFullInstallerSuffix)) { |
+ int suffix_len = ::lstrlen(kFullInstallerSuffix); |
+ int value_len = ::lstrlen(value); |
+ value[value_len - suffix_len] = L'\0'; |
+ } |
+ success = SafeStrCat(value, _countof(value), kMultifailInstallerSuffix); |
+ } |
+ if (success && !StrEndsWith(value, kFullInstallerSuffix) && |
(SafeStrCat(value, _countof(value), kFullInstallerSuffix))) |
key.WriteValue(kApRegistryValueName, value); |
} |
@@ -306,12 +341,12 @@ |
// 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. |
-void SetFullInstallerFlag() { |
+void SetInstallerFlags() { |
int args_num; |
wchar_t* cmd_line = ::GetCommandLine(); |
wchar_t** args = ::CommandLineToArgvW(cmd_line, &args_num); |
- SetFullInstallerFlagHelper(args_num, args); |
+ SetInstallerFlagsHelper(args_num, args); |
::LocalFree(args); |
} |
@@ -649,8 +684,7 @@ |
// 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. |
- // TODO(grt): also add -multifail if --multi-install. |
- SetFullInstallerFlag(); |
+ SetInstallerFlags(); |
#endif |
wchar_t archive_path[MAX_PATH] = {0}; |
@@ -672,6 +706,7 @@ |
return exit_code; |
} |
+ |
} // namespace mini_installer |