Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2009 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 // mini_installer.exe is the first exe that is run when chrome is being | 5 // mini_installer.exe is the first exe that is run when chrome is being |
| 6 // installed or upgraded. It is designed to be extremely small (~5KB with no | 6 // installed or upgraded. It is designed to be extremely small (~5KB with no |
| 7 // extra resources linked) and it has two main jobs: | 7 // extra resources linked) and it has two main jobs: |
| 8 // 1) unpack the resources (possibly decompressing some) | 8 // 1) unpack the resources (possibly decompressing some) |
| 9 // 2) run the real installer (setup.exe) with appropiate flags. | 9 // 2) run the real installer (setup.exe) with appropiate flags. |
| 10 // | 10 // |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 120 return false; | 120 return false; |
| 121 | 121 |
| 122 for (int i = 0; start_str[i] != L'\0'; ++i) { | 122 for (int i = 0; start_str[i] != L'\0'; ++i) { |
| 123 if (!EqualASCIICharI(str[i], start_str[i])) | 123 if (!EqualASCIICharI(str[i], start_str[i])) |
| 124 return false; | 124 return false; |
| 125 } | 125 } |
| 126 | 126 |
| 127 return true; | 127 return true; |
| 128 } | 128 } |
| 129 | 129 |
| 130 // Function to check if a string (specified by str) contains another string | |
| 131 // (specified by sub_str). | |
| 132 bool StrContains(const wchar_t* str, const wchar_t *sub_str) { | |
|
tommi (sloooow) - chröme
2010/12/15 20:15:43
Use StrStr[I] instead?
wchar_t *
->
wchar_t*
robertshield
2010/12/15 20:25:45
delete me (me as in this function, not me as in Ro
grt (UTC plus 2)
2010/12/16 05:59:13
Replaced with a call to StrStr, thanks.
grt (UTC plus 2)
2010/12/16 05:59:13
Done.
| |
| 133 if (str == NULL || sub_str == NULL) | |
| 134 return false; | |
| 135 | |
| 136 for (const wchar_t* scan_str = str; *scan_str != L'\0'; ++scan_str) { | |
| 137 if (StrStartsWith(scan_str, sub_str)) | |
| 138 return true; | |
| 139 } | |
| 140 return false; | |
| 141 } | |
| 142 | |
| 130 // Helper function to read a value from registry. Returns true if value | 143 // Helper function to read a value from registry. Returns true if value |
| 131 // is read successfully and stored in parameter value. Returns false otherwise. | 144 // is read successfully and stored in parameter value. Returns false otherwise. |
| 132 bool ReadValueFromRegistry(HKEY root_key, const wchar_t *sub_key, | 145 bool ReadValueFromRegistry(HKEY root_key, const wchar_t *sub_key, |
| 133 const wchar_t *value_name, wchar_t *value, | 146 const wchar_t *value_name, wchar_t *value, |
| 134 size_t size) { | 147 size_t size) { |
| 135 HKEY key; | 148 HKEY key; |
| 136 if ((::RegOpenKeyEx(root_key, sub_key, NULL, | 149 if ((::RegOpenKeyEx(root_key, sub_key, NULL, |
| 137 KEY_READ, &key) == ERROR_SUCCESS) && | 150 KEY_READ, &key) == ERROR_SUCCESS) && |
| 138 (::RegQueryValueEx(key, value_name, NULL, NULL, | 151 (::RegQueryValueEx(key, value_name, NULL, NULL, |
| 139 reinterpret_cast<LPBYTE>(value), | 152 reinterpret_cast<LPBYTE>(value), |
| 140 reinterpret_cast<LPDWORD>(&size)) == ERROR_SUCCESS)) { | 153 reinterpret_cast<LPDWORD>(&size)) == ERROR_SUCCESS)) { |
| 141 ::RegCloseKey(key); | 154 ::RegCloseKey(key); |
| 142 return true; | 155 return true; |
| 143 } | 156 } |
| 144 return false; | 157 return false; |
| 145 } | 158 } |
| 146 | 159 |
| 147 // This function sets the flag in registry to indicate that Google Update | 160 // Opens the Google Update ClientState key for a product. |
| 148 // should try full installer next time. If the current installer works, this | 161 bool OpenClientStateKey(HKEY root_key, const wchar_t* app_guid, REGSAM access, |
| 149 // flag is cleared by setup.exe at the end of install. The flag will by default | 162 HKEY* key) { |
| 150 // be written to HKCU, but if --system-level is included in the command line, | 163 wchar_t client_state_key[128]; |
| 151 // it will be written to HKLM instead. | 164 |
| 152 void SetFullInstallerFlag() { | 165 return SafeStrCopy(client_state_key, _countof(client_state_key), |
|
tommi (sloooow) - chröme
2010/12/15 20:15:43
chrome code typically uses arraysize(). Can we us
grt (UTC plus 2)
2010/12/16 05:59:13
No due to dependency issues.
| |
| 153 HKEY key; | 166 kApRegistryKeyBase) && |
| 154 wchar_t ap_registry_key[128]; | 167 SafeStrCat(client_state_key, _countof(client_state_key), app_guid) && |
| 168 ::RegOpenKeyEx(root_key, client_state_key, NULL, access, key) == | |
| 169 ERROR_SUCCESS; | |
|
robertshield
2010/12/15 20:25:45
For readability, please include () around the last
grt (UTC plus 2)
2010/12/16 05:59:13
Done.
| |
| 170 } | |
| 171 | |
| 172 // TODO(grt): Write a unit test for this that uses registry virtualization. | |
| 173 void SetFullInstallerFlagHelper(int args_num, const wchar_t* const* args) { | |
| 174 bool multi_install = false; | |
| 175 HKEY key = 0; | |
| 155 const wchar_t* app_guid = google_update::kAppGuid; | 176 const wchar_t* app_guid = google_update::kAppGuid; |
| 156 HKEY root_key = HKEY_CURRENT_USER; | 177 HKEY root_key = HKEY_CURRENT_USER; |
| 178 wchar_t value[128]; | |
|
tommi (sloooow) - chröme
2010/12/15 20:17:28
zero initialize
grt (UTC plus 2)
2010/12/16 05:59:13
The old code didn't, so I'm inclined not to add it
| |
| 179 DWORD size = UINT_MAX; | |
| 180 LONG ret; | |
| 157 | 181 |
| 158 int args_num; | |
| 159 wchar_t* cmd_line = ::GetCommandLine(); | |
| 160 wchar_t** args = ::CommandLineToArgvW(cmd_line, &args_num); | |
| 161 for (int i = 1; i < args_num; ++i) { | 182 for (int i = 1; i < args_num; ++i) { |
| 162 if (0 == ::lstrcmpi(args[i], L"--chrome-sxs")) | 183 if (0 == ::lstrcmpi(args[i], L"--chrome-sxs")) |
| 163 app_guid = google_update::kSxSAppGuid; | 184 app_guid = google_update::kSxSAppGuid; |
| 164 else if (0 == ::lstrcmpi(args[i], L"--chrome-frame")) | 185 else if (0 == ::lstrcmpi(args[i], L"--chrome-frame")) |
| 165 app_guid = google_update::kChromeFrameAppGuid; | 186 app_guid = google_update::kChromeFrameAppGuid; |
| 187 else if (0 == ::lstrcmpi(args[i], L"--multi-install")) | |
| 188 multi_install = true; | |
| 166 else if (0 == ::lstrcmpi(args[i], L"--system-level")) | 189 else if (0 == ::lstrcmpi(args[i], L"--system-level")) |
| 167 root_key = HKEY_LOCAL_MACHINE; | 190 root_key = HKEY_LOCAL_MACHINE; |
| 168 } | 191 } |
| 169 | 192 |
| 170 if (!SafeStrCopy(ap_registry_key, _countof(ap_registry_key), | 193 // When multi_install is true, we are potentially: |
| 171 kApRegistryKeyBase) || | 194 // 1. Performing a multi-install of some product(s) on a clean machine. |
| 172 !SafeStrCat(ap_registry_key, _countof(ap_registry_key), | 195 // Neither the product(s) nor the multi-installer will have a ClientState |
| 173 app_guid)) { | 196 // key in the registry, so there is nothing to be done. |
| 174 return; | 197 // 2. Upgrading an existing multi-install. The multi-installer will have a |
| 198 // ClientState key in the registry. Only it need be modified. | |
| 199 // 3. Migrating a single-install into a multi-install. The product will have | |
| 200 // a ClientState key in the registry. Only it need be modified. | |
|
tommi (sloooow) - chröme
2010/12/15 20:15:43
is there a 4? :
Two products are installed, one i
grt (UTC plus 2)
2010/12/16 05:59:13
In this case, the single will only be migrated whe
| |
| 201 // To handle all cases, we inspect the product's ClientState to see if it | |
| 202 // exists and its "ap" value does not contain "-multi". This is case 3, so we | |
| 203 // modify the product's ClientState. Otherwise, we check the | |
| 204 // multi-installer's ClientState and modify it if it exists. | |
| 205 if (multi_install) { | |
| 206 if (OpenClientStateKey(root_key, app_guid, KEY_READ | KEY_SET_VALUE, | |
| 207 &key)) { | |
| 208 // The app is installed. See if it's a single-install. | |
| 209 size = _countof(value); | |
| 210 ret = ::RegQueryValueEx(key, kApRegistryValueName, NULL, NULL, | |
| 211 reinterpret_cast<LPBYTE>(value), &size); | |
| 212 if (ret == ERROR_FILE_NOT_FOUND) { | |
| 213 // case 3: add "-full" to this value. | |
| 214 *value = L'\0'; | |
| 215 } else if (ret != ERROR_SUCCESS || StrContains(value, kMultiInstallTag)) { | |
| 216 // Error or case 2: add "-full" to the multi-installer's value. | |
| 217 ::RegCloseKey(key); | |
| 218 key = 0; | |
| 219 app_guid = google_update::kMultiInstallAppGuid; | |
| 220 } // else case 3: add "-full" to this value. | |
| 221 } else { | |
| 222 // case 1 or 2: add "-full" to the multi-installer's value. | |
| 223 key = 0; | |
| 224 app_guid = google_update::kMultiInstallAppGuid; | |
| 225 } | |
| 175 } | 226 } |
| 176 if (::RegOpenKeyEx(root_key, ap_registry_key, NULL, | |
| 177 KEY_READ | KEY_SET_VALUE, &key) != ERROR_SUCCESS) | |
| 178 return; | |
| 179 | 227 |
| 180 wchar_t value[128]; | 228 if (key == 0) { |
|
tommi (sloooow) - chröme
2010/12/15 20:15:43
key == NULL
grt (UTC plus 2)
2010/12/16 05:59:13
Done.
| |
| 181 size_t size = _countof(value); | 229 if (!OpenClientStateKey(root_key, app_guid, KEY_READ | KEY_SET_VALUE, &key)) |
| 182 size_t buf_size = size; | 230 return; |
| 183 LONG ret = ::RegQueryValueEx(key, kApRegistryValueName, NULL, NULL, | 231 |
| 184 reinterpret_cast<LPBYTE>(value), | 232 size = _countof(value); |
| 185 reinterpret_cast<LPDWORD>(&size)); | 233 ret = ::RegQueryValueEx(key, kApRegistryValueName, NULL, NULL, |
| 234 reinterpret_cast<LPBYTE>(value), | |
| 235 reinterpret_cast<LPDWORD>(&size)); | |
| 236 } | |
| 186 | 237 |
| 187 // The conditions below are handling two cases: | 238 // The conditions below are handling two cases: |
| 188 // 1. When ap key is present, we want to make sure it doesn't already end | 239 // 1. When ap key is present, we want to make sure it doesn't already end |
| 189 // in -full and then append -full to it. | 240 // in -full and then append -full to it. |
| 190 // 2. When ap key is missing, we are going to create it with value -full. | 241 // 2. When ap key is missing, we are going to create it with value -full. |
| 191 if ((ret == ERROR_SUCCESS) || (ret == ERROR_FILE_NOT_FOUND)) { | 242 if ((ret == ERROR_SUCCESS) || (ret == ERROR_FILE_NOT_FOUND)) { |
| 192 if (ret == ERROR_FILE_NOT_FOUND) | 243 if (ret == ERROR_FILE_NOT_FOUND) |
| 193 value[0] = L'\0'; | 244 value[0] = L'\0'; |
| 194 | 245 |
| 195 if (!StrEndsWith(value, kFullInstallerSuffix) && | 246 if (!StrEndsWith(value, kFullInstallerSuffix) && |
| 196 (SafeStrCat(value, buf_size, kFullInstallerSuffix))) | 247 (SafeStrCat(value, _countof(value), kFullInstallerSuffix))) |
| 197 ::RegSetValueEx(key, kApRegistryValueName, 0, REG_SZ, | 248 ::RegSetValueEx(key, kApRegistryValueName, 0, REG_SZ, |
| 198 reinterpret_cast<LPBYTE>(value), | 249 reinterpret_cast<LPBYTE>(value), |
| 199 lstrlen(value) * sizeof(wchar_t)); | 250 lstrlen(value) * sizeof(wchar_t)); |
| 200 } | 251 } |
| 201 | 252 |
| 202 ::RegCloseKey(key); | 253 ::RegCloseKey(key); |
| 203 } | 254 } |
| 204 | 255 |
| 256 // This function sets the flag in registry to indicate that Google Update | |
| 257 // should try full installer next time. If the current installer works, this | |
| 258 // flag is cleared by setup.exe at the end of install. The flag will by default | |
| 259 // be written to HKCU, but if --system-level is included in the command line, | |
| 260 // it will be written to HKLM instead. | |
| 261 void SetFullInstallerFlag() { | |
| 262 int args_num; | |
| 263 wchar_t* cmd_line = ::GetCommandLine(); | |
| 264 wchar_t** args = ::CommandLineToArgvW(cmd_line, &args_num); | |
| 265 | |
| 266 SetFullInstallerFlagHelper(args_num, args); | |
| 267 | |
| 268 ::LocalFree(args); | |
| 269 } | |
| 270 | |
| 205 // Gets the setup.exe path from Registry by looking the value of Uninstall | 271 // Gets the setup.exe path from Registry by looking the value of Uninstall |
| 206 // string, strips the arguments for uninstall and returns only the full path | 272 // string, strips the arguments for uninstall and returns only the full path |
| 207 // to setup.exe. | 273 // to setup.exe. |
| 208 bool GetSetupExePathFromRegistry(wchar_t *path, size_t size) { | 274 bool GetSetupExePathFromRegistry(wchar_t *path, size_t size) { |
| 209 if (!ReadValueFromRegistry(HKEY_CURRENT_USER, kUninstallRegistryKey, | 275 if (!ReadValueFromRegistry(HKEY_CURRENT_USER, kUninstallRegistryKey, |
| 210 kUninstallRegistryValueName, path, size)) { | 276 kUninstallRegistryValueName, path, size)) { |
| 211 if (!ReadValueFromRegistry(HKEY_LOCAL_MACHINE, kUninstallRegistryKey, | 277 if (!ReadValueFromRegistry(HKEY_LOCAL_MACHINE, kUninstallRegistryKey, |
| 212 kUninstallRegistryValueName, path, size)) { | 278 kUninstallRegistryValueName, path, size)) { |
| 213 return false; | 279 return false; |
| 214 } | 280 } |
| (...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 556 | 622 |
| 557 return exit_code; | 623 return exit_code; |
| 558 } | 624 } |
| 559 } // namespace mini_installer | 625 } // namespace mini_installer |
| 560 | 626 |
| 561 | 627 |
| 562 int MainEntryPoint() { | 628 int MainEntryPoint() { |
| 563 int result = mini_installer::WMain(::GetModuleHandle(NULL)); | 629 int result = mini_installer::WMain(::GetModuleHandle(NULL)); |
| 564 ::ExitProcess(result); | 630 ::ExitProcess(result); |
| 565 } | 631 } |
| OLD | NEW |