Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(25)

Side by Side Diff: chrome/installer/mini_installer/mini_installer.cc

Issue 365143002: mini_installer code cleanups (no functional changes). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: flip component logic Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 appropriate flags. 9 // 2) run the real installer (setup.exe) with appropriate flags.
10 // 10 //
11 // In order to be really small the app doesn't link against the CRT and 11 // In order to be really small the app doesn't link against the CRT and
12 // defines the following compiler/linker flags: 12 // defines the following compiler/linker flags:
13 // EnableIntrinsicFunctions="true" compiler: /Oi 13 // EnableIntrinsicFunctions="true" compiler: /Oi
14 // BasicRuntimeChecks="0" 14 // BasicRuntimeChecks="0"
15 // BufferSecurityCheck="false" compiler: /GS- 15 // BufferSecurityCheck="false" compiler: /GS-
16 // EntryPointSymbol="MainEntryPoint" linker: /ENTRY 16 // EntryPointSymbol="MainEntryPoint" linker: /ENTRY
17 // IgnoreAllDefaultLibraries="true" linker: /NODEFAULTLIB 17 // IgnoreAllDefaultLibraries="true" linker: /NODEFAULTLIB
18 // OptimizeForWindows98="1" liker: /OPT:NOWIN98 18 // OptimizeForWindows98="1" liker: /OPT:NOWIN98
19 // linker: /SAFESEH:NO 19 // linker: /SAFESEH:NO
20 20
21 // have the linker merge the sections, saving us ~500 bytes. 21 // have the linker merge the sections, saving us ~500 bytes.
22 #pragma comment(linker, "/MERGE:.rdata=.text") 22 #pragma comment(linker, "/MERGE:.rdata=.text")
23 23
24 #include <windows.h> 24 #include <windows.h>
25 #include <shellapi.h> 25 #include <shellapi.h>
26 26
27 #include "chrome/installer/mini_installer/appid.h" 27 #include "chrome/installer/mini_installer/appid.h"
28 #include "chrome/installer/mini_installer/configuration.h" 28 #include "chrome/installer/mini_installer/configuration.h"
29 #include "chrome/installer/mini_installer/decompress.h" 29 #include "chrome/installer/mini_installer/decompress.h"
30 #include "chrome/installer/mini_installer/mini_installer.h" 30 #include "chrome/installer/mini_installer/exit_code.h"
31 #include "chrome/installer/mini_installer/mini_installer_constants.h"
31 #include "chrome/installer/mini_installer/mini_string.h" 32 #include "chrome/installer/mini_installer/mini_string.h"
32 #include "chrome/installer/mini_installer/pe_resource.h" 33 #include "chrome/installer/mini_installer/pe_resource.h"
33 34
34 namespace mini_installer { 35 namespace mini_installer {
35 36
37 typedef DWORD ProcessExitCode;
36 typedef StackString<MAX_PATH> PathString; 38 typedef StackString<MAX_PATH> PathString;
37 typedef StackString<MAX_PATH * 4> CommandString; 39 typedef StackString<MAX_PATH * 4> CommandString;
38 40
39 // This structure passes data back and forth for the processing 41 // This structure passes data back and forth for the processing
40 // of resource callbacks. 42 // of resource callbacks.
41 struct Context { 43 struct Context {
42 // Input to the call back method. Specifies the dir to save resources. 44 // Input to the call back method. Specifies the dir to save resources.
43 const wchar_t* base_path; 45 const wchar_t* base_path;
44 // First output from call back method. Full path of Chrome archive. 46 // First output from call back method. Full path of Chrome archive.
45 PathString* chrome_resource_path; 47 PathString* chrome_resource_path;
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 key.ReadValue(value_name, value, size) == ERROR_SUCCESS) { 138 key.ReadValue(value_name, value, size) == ERROR_SUCCESS) {
137 return true; 139 return true;
138 } 140 }
139 return false; 141 return false;
140 } 142 }
141 143
142 // Opens the Google Update ClientState key for a product. 144 // Opens the Google Update ClientState key for a product.
143 bool OpenClientStateKey(HKEY root_key, const wchar_t* app_guid, REGSAM access, 145 bool OpenClientStateKey(HKEY root_key, const wchar_t* app_guid, REGSAM access,
144 RegKey* key) { 146 RegKey* key) {
145 PathString client_state_key; 147 PathString client_state_key;
146 return client_state_key.assign(kApRegistryKeyBase) && 148 return client_state_key.assign(kClientStateKeyBase) &&
147 client_state_key.append(app_guid) && 149 client_state_key.append(app_guid) &&
148 (key->Open(root_key, 150 (key->Open(root_key,
149 client_state_key.get(), 151 client_state_key.get(),
150 access | KEY_WOW64_32KEY) == ERROR_SUCCESS); 152 access | KEY_WOW64_32KEY) == ERROR_SUCCESS);
151 } 153 }
152 154
153 // This function sets the flag in registry to indicate that Google Update 155 // This function sets the flag in registry to indicate that Google Update
154 // should try full installer next time. If the current installer works, this 156 // should try full installer next time. If the current installer works, this
155 // flag is cleared by setup.exe at the end of install. The flag will by default 157 // flag is cleared by setup.exe at the end of install. The flag will by default
156 // be written to HKCU, but if --system-level is included in the command line, 158 // be written to HKCU, but if --system-level is included in the command line,
(...skipping 20 matching lines...) Expand all
177 // ClientState key in the registry. Only it need be modified. 179 // ClientState key in the registry. Only it need be modified.
178 // 3. Migrating a single-install into a multi-install. The product will have 180 // 3. Migrating a single-install into a multi-install. The product will have
179 // a ClientState key in the registry. Only it need be modified. 181 // a ClientState key in the registry. Only it need be modified.
180 // To handle all cases, we inspect the product's ClientState to see if it 182 // To handle all cases, we inspect the product's ClientState to see if it
181 // exists and its "ap" value does not contain "-multi". This is case 3, so we 183 // exists and its "ap" value does not contain "-multi". This is case 3, so we
182 // modify the product's ClientState. Otherwise, we check the 184 // modify the product's ClientState. Otherwise, we check the
183 // multi-installer's ClientState and modify it if it exists. 185 // multi-installer's ClientState and modify it if it exists.
184 if (configuration.is_multi_install()) { 186 if (configuration.is_multi_install()) {
185 if (OpenClientStateKey(root_key, app_guid, key_access, &key)) { 187 if (OpenClientStateKey(root_key, app_guid, key_access, &key)) {
186 // The product has a client state key. See if it's a single-install. 188 // The product has a client state key. See if it's a single-install.
187 ret = key.ReadValue(kApRegistryValueName, value.get(), value.capacity()); 189 ret = key.ReadValue(kApRegistryValue, value.get(), value.capacity());
188 if (ret != ERROR_FILE_NOT_FOUND && 190 if (ret != ERROR_FILE_NOT_FOUND &&
189 (ret != ERROR_SUCCESS || 191 (ret != ERROR_SUCCESS ||
190 FindTagInStr(value.get(), kMultiInstallTag, NULL))) { 192 FindTagInStr(value.get(), kMultiInstallTag, NULL))) {
191 // Error or case 2: modify the multi-installer's value. 193 // Error or case 2: modify the multi-installer's value.
192 key.Close(); 194 key.Close();
193 app_guid = google_update::kMultiInstallAppGuid; 195 app_guid = google_update::kMultiInstallAppGuid;
194 } // else case 3: modify this value. 196 } // else case 3: modify this value.
195 } else { 197 } else {
196 // case 1 or 2: modify the multi-installer's value. 198 // case 1 or 2: modify the multi-installer's value.
197 key.Close(); 199 key.Close();
198 app_guid = google_update::kMultiInstallAppGuid; 200 app_guid = google_update::kMultiInstallAppGuid;
199 } 201 }
200 } 202 }
201 203
202 if (!key.is_valid()) { 204 if (!key.is_valid()) {
203 if (!OpenClientStateKey(root_key, app_guid, key_access, &key)) 205 if (!OpenClientStateKey(root_key, app_guid, key_access, &key))
204 return; 206 return;
205 207
206 value.clear(); 208 value.clear();
207 ret = key.ReadValue(kApRegistryValueName, value.get(), value.capacity()); 209 ret = key.ReadValue(kApRegistryValue, value.get(), value.capacity());
208 } 210 }
209 211
210 // The conditions below are handling two cases: 212 // The conditions below are handling two cases:
211 // 1. When ap value is present, we want to add the required tag only if it is 213 // 1. When ap value is present, we want to add the required tag only if it is
212 // not present. 214 // not present.
213 // 2. When ap value is missing, we are going to create it with the required 215 // 2. When ap value is missing, we are going to create it with the required
214 // tag. 216 // tag.
215 if ((ret == ERROR_SUCCESS) || (ret == ERROR_FILE_NOT_FOUND)) { 217 if ((ret == ERROR_SUCCESS) || (ret == ERROR_FILE_NOT_FOUND)) {
216 if (ret == ERROR_FILE_NOT_FOUND) 218 if (ret == ERROR_FILE_NOT_FOUND)
217 value.clear(); 219 value.clear();
218 220
219 if (!StrEndsWith(value.get(), kFullInstallerSuffix) && 221 if (!StrEndsWith(value.get(), kFullInstallerSuffix) &&
220 value.append(kFullInstallerSuffix)) { 222 value.append(kFullInstallerSuffix)) {
221 key.WriteValue(kApRegistryValueName, value.get()); 223 key.WriteValue(kApRegistryValue, value.get());
222 } 224 }
223 } 225 }
224 } 226 }
225 227
226 // Gets the setup.exe path from Registry by looking the value of Uninstall 228 // Gets the setup.exe path from Registry by looking the value of Uninstall
227 // string. |size| is measured in wchar_t units. 229 // string. |size| is measured in wchar_t units.
228 bool GetSetupExePathForGuidFromRegistry(bool system_level, 230 bool GetSetupExePathForGuidFromRegistry(bool system_level,
229 const wchar_t* app_guid, 231 const wchar_t* app_guid,
230 wchar_t* path, 232 wchar_t* path,
231 size_t size) { 233 size_t size) {
232 const HKEY root_key = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 234 const HKEY root_key = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
233 RegKey key; 235 RegKey key;
234 return OpenClientStateKey(root_key, app_guid, KEY_QUERY_VALUE, &key) && 236 return OpenClientStateKey(root_key, app_guid, KEY_QUERY_VALUE, &key) &&
235 (key.ReadValue(kUninstallRegistryValueName, path, size) == ERROR_SUCCESS); 237 (key.ReadValue(kUninstallRegistryValue, path, size) == ERROR_SUCCESS);
236 } 238 }
237 239
238 // Gets the setup.exe path from Registry by looking the value of Uninstall 240 // Gets the setup.exe path from Registry by looking the value of Uninstall
239 // string. |size| is measured in wchar_t units. 241 // string. |size| is measured in wchar_t units.
240 bool GetSetupExePathFromRegistry(const Configuration& configuration, 242 bool GetSetupExePathFromRegistry(const Configuration& configuration,
241 wchar_t* path, 243 wchar_t* path,
242 size_t size) { 244 size_t size) {
243 bool system_level = configuration.is_system_level(); 245 bool system_level = configuration.is_system_level();
244 246
245 // If this is a multi install, first try looking in the binaries for the path. 247 // If this is a multi install, first try looking in the binaries for the path.
(...skipping 16 matching lines...) Expand all
262 return true; 264 return true;
263 } 265 }
264 if (configuration.has_app_host() && GetSetupExePathForGuidFromRegistry( 266 if (configuration.has_app_host() && GetSetupExePathForGuidFromRegistry(
265 system_level, google_update::kChromeAppHostAppGuid, path, size)) { 267 system_level, google_update::kChromeAppHostAppGuid, path, size)) {
266 return true; 268 return true;
267 } 269 }
268 270
269 return false; 271 return false;
270 } 272 }
271 273
272 // Calls CreateProcess with good default parameters and waits for the process 274 // Calls CreateProcess with good default parameters and waits for the process to
273 // to terminate returning the process exit code. 275 // terminate returning the process exit code. |exit_code|, if non-NULL, is
276 // populated with the process exit code.
274 bool RunProcessAndWait(const wchar_t* exe_path, wchar_t* cmdline, 277 bool RunProcessAndWait(const wchar_t* exe_path, wchar_t* cmdline,
275 int* exit_code) { 278 ProcessExitCode* exit_code) {
276 STARTUPINFOW si = {sizeof(si)}; 279 STARTUPINFOW si = {sizeof(si)};
277 PROCESS_INFORMATION pi = {0}; 280 PROCESS_INFORMATION pi = {0};
278 if (!::CreateProcess(exe_path, cmdline, NULL, NULL, FALSE, CREATE_NO_WINDOW, 281 if (!::CreateProcess(exe_path, cmdline, NULL, NULL, FALSE, CREATE_NO_WINDOW,
279 NULL, NULL, &si, &pi)) { 282 NULL, NULL, &si, &pi)) {
280 return false; 283 return false;
281 } 284 }
282 285
283 ::CloseHandle(pi.hThread); 286 ::CloseHandle(pi.hThread);
284 287
285 bool ret = true; 288 bool ret = true;
286 DWORD wr = ::WaitForSingleObject(pi.hProcess, INFINITE); 289 DWORD wr = ::WaitForSingleObject(pi.hProcess, INFINITE);
287 if (WAIT_OBJECT_0 != wr) { 290 if (WAIT_OBJECT_0 != wr) {
288 ret = false; 291 ret = false;
289 } else if (exit_code) { 292 } else if (exit_code) {
290 if (!::GetExitCodeProcess(pi.hProcess, 293 if (!::GetExitCodeProcess(pi.hProcess, exit_code))
291 reinterpret_cast<DWORD*>(exit_code))) {
292 ret = false; 294 ret = false;
293 }
294 } 295 }
295 296
296 ::CloseHandle(pi.hProcess); 297 ::CloseHandle(pi.hProcess);
297 298
298 return ret; 299 return ret;
299 } 300 }
300 301
301 // Append any command line params passed to mini_installer to the given buffer 302 // Append any command line params passed to mini_installer to the given buffer
302 // so that they can be passed on to setup.exe. We do not return any error from 303 // so that they can be passed on to setup.exe. We do not return any error from
303 // this method and simply skip making any changes in case of error. 304 // this method and simply skip making any changes in case of error.
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
345 (resource.Size() > kMaxResourceSize)) { 346 (resource.Size() > kMaxResourceSize)) {
346 return FALSE; 347 return FALSE;
347 } 348 }
348 349
349 PathString full_path; 350 PathString full_path;
350 if (!full_path.assign(ctx->base_path) || 351 if (!full_path.assign(ctx->base_path) ||
351 !full_path.append(name) || 352 !full_path.append(name) ||
352 !resource.WriteToDisk(full_path.get())) 353 !resource.WriteToDisk(full_path.get()))
353 return FALSE; 354 return FALSE;
354 355
355 if (StrStartsWith(name, kChromePrefix)) { 356 if (StrStartsWith(name, kChromeArchivePrefix)) {
356 if (!ctx->chrome_resource_path->assign(full_path.get())) 357 if (!ctx->chrome_resource_path->assign(full_path.get()))
357 return FALSE; 358 return FALSE;
358 } else if (StrStartsWith(name, kSetupPrefix)) { 359 } else if (StrStartsWith(name, kSetupPrefix)) {
359 if (!ctx->setup_resource_path->assign(full_path.get())) 360 if (!ctx->setup_resource_path->assign(full_path.get()))
360 return FALSE; 361 return FALSE;
361 } else { 362 } else {
362 // Resources should either start with 'chrome' or 'setup'. We don't handle 363 // Resources should either start with 'chrome' or 'setup'. We don't handle
363 // anything else. 364 // anything else.
364 return FALSE; 365 return FALSE;
365 } 366 }
366 367
367 return TRUE; 368 return TRUE;
368 } 369 }
369 370
370 // Finds and writes to disk resources of various types. Returns false 371 // Finds and writes to disk resources of various types. Returns false
371 // if there is a problem in writing any resource to disk. setup.exe resource 372 // if there is a problem in writing any resource to disk. setup.exe resource
372 // can come in one of three possible forms: 373 // can come in one of three possible forms:
373 // - Resource type 'B7', compressed using LZMA (*.7z) 374 // - Resource type 'B7', compressed using LZMA (*.7z)
374 // - Resource type 'BL', compressed using LZ (*.ex_) 375 // - Resource type 'BL', compressed using LZ (*.ex_)
375 // - Resource type 'BN', uncompressed (*.exe) 376 // - Resource type 'BN', uncompressed (*.exe)
376 // If setup.exe is present in more than one form, the precedence order is 377 // If setup.exe is present in more than one form, the precedence order is
377 // BN < BL < B7 378 // BN < BL < B7
378 // For more details see chrome/tools/build/win/create_installer_archive.py. 379 // For more details see chrome/tools/build/win/create_installer_archive.py.
379 bool UnpackBinaryResources(const Configuration& configuration, HMODULE module, 380 bool UnpackBinaryResources(const Configuration& configuration, HMODULE module,
380 const wchar_t* base_path, PathString* archive_path, 381 const wchar_t* base_path, PathString* archive_path,
381 PathString* setup_path) { 382 PathString* setup_path) {
382 // Generate the setup.exe path where we patch/uncompress setup resource. 383 // Generate the setup.exe path where we patch/uncompress setup resource.
383 PathString setup_dest_path; 384 PathString setup_dest_path;
384 if (!setup_dest_path.assign(base_path) || 385 if (!setup_dest_path.assign(base_path) ||
385 !setup_dest_path.append(kSetupName)) 386 !setup_dest_path.append(kSetupExe))
386 return false; 387 return false;
387 388
388 // Prepare the input to OnResourceFound method that needs a location where 389 // Prepare the input to OnResourceFound method that needs a location where
389 // it will write all the resources. 390 // it will write all the resources.
390 Context context = { 391 Context context = {
391 base_path, 392 base_path,
392 archive_path, 393 archive_path,
393 setup_path, 394 setup_path,
394 }; 395 };
395 396
396 // Get the resources of type 'B7' (7zip archive). 397 // Get the resources of type 'B7' (7zip archive).
397 // We need a chrome archive to do the installation. So if there 398 // We need a chrome archive to do the installation. So if there
398 // is a problem in fetching B7 resource, just return an error. 399 // is a problem in fetching B7 resource, just return an error.
399 if (!::EnumResourceNames(module, kLZMAResourceType, OnResourceFound, 400 if (!::EnumResourceNames(module, kLZMAResourceType, OnResourceFound,
400 reinterpret_cast<LONG_PTR>(&context)) || 401 reinterpret_cast<LONG_PTR>(&context)) ||
401 archive_path->length() == 0) 402 archive_path->length() == 0)
402 return false; 403 return false;
403 404
404 // If we found setup 'B7' resource, handle it. 405 // If we found setup 'B7' resource, handle it.
405 if (setup_path->length() > 0) { 406 if (setup_path->length() > 0) {
406 CommandString cmd_line; 407 CommandString cmd_line;
407 // Get the path to setup.exe first. 408 // Get the path to setup.exe first.
408 bool success = true; 409 bool success = true;
409 if (!GetSetupExePathFromRegistry(configuration, cmd_line.get(), 410 if (!GetSetupExePathFromRegistry(configuration, cmd_line.get(),
410 cmd_line.capacity()) || 411 cmd_line.capacity()) ||
412 !cmd_line.append(L" --") ||
411 !cmd_line.append(kCmdUpdateSetupExe) || 413 !cmd_line.append(kCmdUpdateSetupExe) ||
412 !cmd_line.append(L"=\"") || 414 !cmd_line.append(L"=\"") ||
413 !cmd_line.append(setup_path->get()) || 415 !cmd_line.append(setup_path->get()) ||
414 !cmd_line.append(L"\"") || 416 !cmd_line.append(L"\" --") ||
415 !cmd_line.append(kCmdNewSetupExe) || 417 !cmd_line.append(kCmdNewSetupExe) ||
416 !cmd_line.append(L"=\"") || 418 !cmd_line.append(L"=\"") ||
417 !cmd_line.append(setup_dest_path.get()) || 419 !cmd_line.append(setup_dest_path.get()) ||
418 !cmd_line.append(L"\"")) { 420 !cmd_line.append(L"\"")) {
419 success = false; 421 success = false;
420 } 422 }
421 423
422 // Get any command line option specified for mini_installer and pass them 424 // Get any command line option specified for mini_installer and pass them
423 // on to setup.exe. This is important since switches such as 425 // on to setup.exe. This is important since switches such as
424 // --multi-install and --chrome-frame affect where setup.exe will write 426 // --multi-install and --chrome-frame affect where setup.exe will write
425 // installer results for consumption by Google Update. 427 // installer results for consumption by Google Update.
426 AppendCommandLineFlags(configuration, &cmd_line); 428 AppendCommandLineFlags(configuration, &cmd_line);
427 429
428 int exit_code = 0; 430 ProcessExitCode exit_code = SUCCESS_EXIT_CODE;
429 if (success && 431 if (success &&
430 (!RunProcessAndWait(NULL, cmd_line.get(), &exit_code) || 432 (!RunProcessAndWait(NULL, cmd_line.get(), &exit_code) ||
431 exit_code != ERROR_SUCCESS)) { 433 exit_code != SUCCESS_EXIT_CODE)) {
432 success = false; 434 success = false;
433 } 435 }
434 436
435 if (!success) 437 if (!success)
436 DeleteFile(setup_path->get()); 438 DeleteFile(setup_path->get());
437 439
438 return success && setup_path->assign(setup_dest_path.get()); 440 return success && setup_path->assign(setup_dest_path.get());
439 } 441 }
440 442
441 // setup.exe wasn't sent as 'B7', lets see if it was sent as 'BL' 443 // setup.exe wasn't sent as 'B7', lets see if it was sent as 'BL'
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 ::DeleteFile(setup_dest_path.get()); 482 ::DeleteFile(setup_dest_path.get());
481 } 483 }
482 } 484 }
483 } 485 }
484 486
485 return setup_path->length() > 0; 487 return setup_path->length() > 0;
486 } 488 }
487 489
488 // Executes setup.exe, waits for it to finish and returns the exit code. 490 // Executes setup.exe, waits for it to finish and returns the exit code.
489 bool RunSetup(const Configuration& configuration, const wchar_t* archive_path, 491 bool RunSetup(const Configuration& configuration, const wchar_t* archive_path,
490 const wchar_t* setup_path, int* exit_code) { 492 const wchar_t* setup_path, ProcessExitCode* exit_code) {
491 // There could be three full paths in the command line for setup.exe (path 493 // There could be three full paths in the command line for setup.exe (path
492 // to exe itself, path to archive and path to log file), so we declare 494 // to exe itself, path to archive and path to log file), so we declare
493 // total size as three + one additional to hold command line options. 495 // total size as three + one additional to hold command line options.
494 CommandString cmd_line; 496 CommandString cmd_line;
495 497
496 // Get the path to setup.exe first. 498 // Get the path to setup.exe first.
497 if (::lstrlen(setup_path) > 0) { 499 if (::lstrlen(setup_path) > 0) {
498 if (!cmd_line.assign(L"\"") || 500 if (!cmd_line.assign(L"\"") ||
499 !cmd_line.append(setup_path) || 501 !cmd_line.append(setup_path) ||
500 !cmd_line.append(L"\"")) 502 !cmd_line.append(L"\""))
501 return false; 503 return false;
502 } else if (!GetSetupExePathFromRegistry(configuration, cmd_line.get(), 504 } else if (!GetSetupExePathFromRegistry(configuration, cmd_line.get(),
503 cmd_line.capacity())) { 505 cmd_line.capacity())) {
504 return false; 506 return false;
505 } 507 }
506 508
507 // Append the command line param for chrome archive file 509 // Append the command line param for chrome archive file
508 if (!cmd_line.append(kCmdInstallArchive) || 510 if (!cmd_line.append(L" --") ||
511 !cmd_line.append(kCmdInstallArchive) ||
509 !cmd_line.append(L"=\"") || 512 !cmd_line.append(L"=\"") ||
510 !cmd_line.append(archive_path) || 513 !cmd_line.append(archive_path) ||
511 !cmd_line.append(L"\"")) 514 !cmd_line.append(L"\""))
512 return false; 515 return false;
513 516
514 // Get any command line option specified for mini_installer and pass them 517 // Get any command line option specified for mini_installer and pass them
515 // on to setup.exe 518 // on to setup.exe
516 AppendCommandLineFlags(configuration, &cmd_line); 519 AppendCommandLineFlags(configuration, &cmd_line);
517 520
518 return RunProcessAndWait(NULL, cmd_line.get(), exit_code); 521 return RunProcessAndWait(NULL, cmd_line.get(), exit_code);
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
707 for (int i = 0; i < arraysize(kDirectoryPrefixes); ++i) { 710 for (int i = 0; i < arraysize(kDirectoryPrefixes); ++i) {
708 DeleteDirectoriesWithPrefix(temp.get(), kDirectoryPrefixes[i]); 711 DeleteDirectoriesWithPrefix(temp.get(), kDirectoryPrefixes[i]);
709 } 712 }
710 } 713 }
711 714
712 // Checks the command line for specific mini installer flags. 715 // Checks the command line for specific mini installer flags.
713 // If the function returns true, the command line has been processed and all 716 // If the function returns true, the command line has been processed and all
714 // required actions taken. The installer must exit and return the returned 717 // required actions taken. The installer must exit and return the returned
715 // |exit_code|. 718 // |exit_code|.
716 bool ProcessNonInstallOperations(const Configuration& configuration, 719 bool ProcessNonInstallOperations(const Configuration& configuration,
717 int* exit_code) { 720 ProcessExitCode* exit_code) {
718 bool ret = false; 721 bool ret = false;
719 722
720 switch (configuration.operation()) { 723 switch (configuration.operation()) {
721 case Configuration::CLEANUP: 724 case Configuration::CLEANUP:
722 // Cleanup has already taken place in DeleteOldChromeTempDirectories at 725 // Cleanup has already taken place in DeleteOldChromeTempDirectories at
723 // this point, so just tell our caller to exit early. 726 // this point, so just tell our caller to exit early.
724 *exit_code = 0; 727 *exit_code = SUCCESS_EXIT_CODE;
725 ret = true; 728 ret = true;
726 break; 729 break;
727 730
728 default: break; 731 default: break;
729 } 732 }
730 733
731 return ret; 734 return ret;
732 } 735 }
733 736
734 // Returns true if we should delete the temp files we create (default). 737 // Returns true if we should delete the temp files we create (default).
735 // Returns false iff the user has manually created a ChromeInstallerCleanup 738 // Returns false iff the user has manually created a ChromeInstallerCleanup
736 // string value in the registry under HKCU\\Software\\[Google|Chromium] 739 // string value in the registry under HKCU\\Software\\[Google|Chromium]
737 // and set its value to "0". That explicitly forbids the mini installer from 740 // and set its value to "0". That explicitly forbids the mini installer from
738 // deleting these files. 741 // deleting these files.
739 // Support for this has been publicly mentioned in troubleshooting tips so 742 // Support for this has been publicly mentioned in troubleshooting tips so
740 // we continue to support it. 743 // we continue to support it.
741 bool ShouldDeleteExtractedFiles() { 744 bool ShouldDeleteExtractedFiles() {
742 wchar_t value[2] = {0}; 745 wchar_t value[2] = {0};
743 if (ReadValueFromRegistry(HKEY_CURRENT_USER, kCleanupRegistryKey, 746 if (ReadValueFromRegistry(HKEY_CURRENT_USER, kCleanupRegistryKey,
744 kCleanupRegistryValueName, value, 747 kCleanupRegistryValue, value, arraysize(value)) &&
745 arraysize(value)) &&
746 value[0] == L'0') { 748 value[0] == L'0') {
747 return false; 749 return false;
748 } 750 }
749 751
750 return true; 752 return true;
751 } 753 }
752 754
753 // Main function. First gets a working dir, unpacks the resources and finally 755 // Main function. First gets a working dir, unpacks the resources and finally
754 // executes setup.exe to do the install/upgrade. 756 // executes setup.exe to do the install/upgrade.
755 int WMain(HMODULE module) { 757 ProcessExitCode WMain(HMODULE module) {
756 #if defined(COMPONENT_BUILD) 758 #if defined(COMPONENT_BUILD)
757 if (::GetEnvironmentVariable(L"MINI_INSTALLER_TEST", NULL, 0) == 0) { 759 if (::GetEnvironmentVariable(L"MINI_INSTALLER_TEST", NULL, 0) == 0) {
758 static const wchar_t kComponentBuildIncompatibleMessage[] = 760 static const wchar_t kComponentBuildIncompatibleMessage[] =
759 L"mini_installer.exe is incompatible with the component build, please" 761 L"mini_installer.exe is incompatible with the component build, please"
760 L" run setup.exe with the same command line instead. See" 762 L" run setup.exe with the same command line instead. See"
761 L" http://crbug.com/127233#c17 for details."; 763 L" http://crbug.com/127233#c17 for details.";
762 ::MessageBox(NULL, kComponentBuildIncompatibleMessage, NULL, MB_ICONERROR); 764 ::MessageBox(NULL, kComponentBuildIncompatibleMessage, NULL, MB_ICONERROR);
763 return 1; 765 return GENERIC_ERROR;
764 } 766 }
765 #endif 767 #endif
766 768
767 // Always start with deleting potential leftovers from previous installations. 769 // Always start with deleting potential leftovers from previous installations.
768 // This can make the difference between success and failure. We've seen 770 // This can make the difference between success and failure. We've seen
769 // many installations out in the field fail due to out of disk space problems 771 // many installations out in the field fail due to out of disk space problems
770 // so this could buy us some space. 772 // so this could buy us some space.
771 DeleteOldChromeTempDirectories(); 773 DeleteOldChromeTempDirectories();
772 774
773 // TODO(grt): Make the exit codes more granular so we know where the popular 775 // TODO(grt): Make the exit codes more granular so we know where the popular
774 // errors truly are. 776 // errors truly are.
775 int exit_code = 101; 777 ProcessExitCode exit_code = GENERIC_INITIALIZATION_FAILURE;
776 778
777 // Parse the command line. 779 // Parse the command line.
778 Configuration configuration; 780 Configuration configuration;
779 if (!configuration.Initialize()) 781 if (!configuration.Initialize())
780 return exit_code; 782 return exit_code;
781 783
782 if (configuration.query_component_build()) { 784 if (configuration.query_component_build()) {
783 // Exit immediately with an exit code of 1 to indicate component build and 0 785 // Exit immediately with a generic success exit code (0) to indicate
784 // to indicate static build. This is used by the tests in 786 // component build and a generic failure exit code (1) to indicate static
785 // /src/chrome/test/mini_installer/. 787 // build. This is used by the tests in /src/chrome/test/mini_installer/.
786 #if defined(COMPONENT_BUILD) 788 #if defined(COMPONENT_BUILD)
787 return 1; 789 return SUCCESS_EXIT_CODE;
788 #else 790 #else
789 return 0; 791 return GENERIC_ERROR;
790 #endif 792 #endif
791 } 793 }
792 794
793 // If the --cleanup switch was specified on the command line, then that means 795 // If the --cleanup switch was specified on the command line, then that means
794 // we should only do the cleanup and then exit. 796 // we should only do the cleanup and then exit.
795 if (ProcessNonInstallOperations(configuration, &exit_code)) 797 if (ProcessNonInstallOperations(configuration, &exit_code))
796 return exit_code; 798 return exit_code;
797 799
798 // First get a path where we can extract payload 800 // First get a path where we can extract payload
799 PathString base_path; 801 PathString base_path;
800 if (!GetWorkDir(module, &base_path)) 802 if (!GetWorkDir(module, &base_path))
801 return 101; 803 return GENERIC_INITIALIZATION_FAILURE;
802 804
803 #if defined(GOOGLE_CHROME_BUILD) 805 #if defined(GOOGLE_CHROME_BUILD)
804 // Set the magic suffix in registry to try full installer next time. We ignore 806 // Set the magic suffix in registry to try full installer next time. We ignore
805 // any errors here and we try to set the suffix for user level unless 807 // any errors here and we try to set the suffix for user level unless
806 // --system-level is on the command line in which case we set it for system 808 // --system-level is on the command line in which case we set it for system
807 // level instead. This only applies to the Google Chrome distribution. 809 // level instead. This only applies to the Google Chrome distribution.
808 SetInstallerFlags(configuration); 810 SetInstallerFlags(configuration);
809 #endif 811 #endif
810 812
811 PathString archive_path; 813 PathString archive_path;
812 PathString setup_path; 814 PathString setup_path;
813 if (!UnpackBinaryResources(configuration, module, base_path.get(), 815 if (!UnpackBinaryResources(configuration, module, base_path.get(),
814 &archive_path, &setup_path)) { 816 &archive_path, &setup_path)) {
815 exit_code = 102; 817 exit_code = GENERIC_UNPACKING_FAILURE;
816 } else { 818 } else {
817 // While unpacking the binaries, we paged in a whole bunch of memory that 819 // While unpacking the binaries, we paged in a whole bunch of memory that
818 // we don't need anymore. Let's give it back to the pool before running 820 // we don't need anymore. Let's give it back to the pool before running
819 // setup. 821 // setup.
820 ::SetProcessWorkingSetSize(::GetCurrentProcess(), -1, -1); 822 ::SetProcessWorkingSetSize(::GetCurrentProcess(), -1, -1);
821 if (!RunSetup(configuration, archive_path.get(), setup_path.get(), 823 if (!RunSetup(configuration, archive_path.get(), setup_path.get(),
822 &exit_code)) { 824 &exit_code)) {
823 exit_code = 103; 825 exit_code = GENERIC_SETUP_FAILURE;
824 } 826 }
825 } 827 }
826 828
827 if (ShouldDeleteExtractedFiles()) 829 if (ShouldDeleteExtractedFiles())
828 DeleteExtractedFiles(base_path.get(), archive_path.get(), setup_path.get()); 830 DeleteExtractedFiles(base_path.get(), archive_path.get(), setup_path.get());
829 831
830 return exit_code; 832 return exit_code;
831 } 833 }
832 834
833 } // namespace mini_installer 835 } // namespace mini_installer
834 836
835 int MainEntryPoint() { 837 int MainEntryPoint() {
836 int result = mini_installer::WMain(::GetModuleHandle(NULL)); 838 mini_installer::ProcessExitCode result =
839 mini_installer::WMain(::GetModuleHandle(NULL));
837 ::ExitProcess(result); 840 ::ExitProcess(result);
838 } 841 }
839 842
840 // VC Express editions don't come with the memset CRT obj file and linking to 843 // VC Express editions don't come with the memset CRT obj file and linking to
841 // the obj files between versions becomes a bit problematic. Therefore, 844 // the obj files between versions becomes a bit problematic. Therefore,
842 // simply implement memset. 845 // simply implement memset.
843 // 846 //
844 // This also avoids having to explicitly set the __sse2_available hack when 847 // This also avoids having to explicitly set the __sse2_available hack when
845 // linking with both the x64 and x86 obj files which is required when not 848 // linking with both the x64 and x86 obj files which is required when not
846 // linking with the std C lib in certain instances (including Chromium) with 849 // linking with the std C lib in certain instances (including Chromium) with
847 // MSVC. __sse2_available determines whether to use SSE2 intructions with 850 // MSVC. __sse2_available determines whether to use SSE2 intructions with
848 // std C lib routines, and is set by MSVC's std C lib implementation normally. 851 // std C lib routines, and is set by MSVC's std C lib implementation normally.
849 extern "C" { 852 extern "C" {
850 #pragma function(memset) 853 #pragma function(memset)
851 void* memset(void* dest, int c, size_t count) { 854 void* memset(void* dest, int c, size_t count) {
852 void* start = dest; 855 void* start = dest;
853 while (count--) { 856 while (count--) {
854 *reinterpret_cast<char*>(dest) = static_cast<char>(c); 857 *reinterpret_cast<char*>(dest) = static_cast<char>(c);
855 dest = reinterpret_cast<char*>(dest) + 1; 858 dest = reinterpret_cast<char*>(dest) + 1;
856 } 859 }
857 return start; 860 return start;
858 } 861 }
859 } // extern "C" 862 } // extern "C"
OLDNEW
« no previous file with comments | « chrome/installer/mini_installer/mini_installer.h ('k') | chrome/installer/mini_installer/mini_installer_constants.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698