OLD | NEW |
---|---|
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 // |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
52 | 52 |
53 // This structure passes data back and forth for the processing | 53 // This structure passes data back and forth for the processing |
54 // of resource callbacks. | 54 // of resource callbacks. |
55 struct Context { | 55 struct Context { |
56 // Input to the call back method. Specifies the dir to save resources. | 56 // Input to the call back method. Specifies the dir to save resources. |
57 const wchar_t* base_path; | 57 const wchar_t* base_path; |
58 // First output from call back method. Full path of Chrome archive. | 58 // First output from call back method. Full path of Chrome archive. |
59 PathString* chrome_resource_path; | 59 PathString* chrome_resource_path; |
60 // Second output from call back method. Full path of Setup archive/exe. | 60 // Second output from call back method. Full path of Setup archive/exe. |
61 PathString* setup_resource_path; | 61 PathString* setup_resource_path; |
62 #if defined(SYZYASAN) | |
63 PathString* syzyasan_resource_path; | |
64 #endif | |
62 }; | 65 }; |
63 | 66 |
64 // TODO(grt): Frame this in terms of whether or not the brand supports | 67 // TODO(grt): Frame this in terms of whether or not the brand supports |
65 // integation with Omaha, where Google Update is the Google-specific fork of | 68 // integation with Omaha, where Google Update is the Google-specific fork of |
66 // the open-source Omaha project. | 69 // the open-source Omaha project. |
67 #if defined(GOOGLE_CHROME_BUILD) | 70 #if defined(GOOGLE_CHROME_BUILD) |
68 // Opens the Google Update ClientState key. If |binaries| is false, opens the | 71 // Opens the Google Update ClientState key. If |binaries| is false, opens the |
69 // key for Google Chrome or Chrome SxS (canary). If |binaries| is true and an | 72 // key for Google Chrome or Chrome SxS (canary). If |binaries| is true and an |
70 // existing multi-install Chrome is being updated, opens the key for the | 73 // existing multi-install Chrome is being updated, opens the key for the |
71 // multi-install binaries; otherwise, returns false. | 74 // multi-install binaries; otherwise, returns false. |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
284 !full_path.append(name) || | 287 !full_path.append(name) || |
285 !resource.WriteToDisk(full_path.get())) | 288 !resource.WriteToDisk(full_path.get())) |
286 return FALSE; | 289 return FALSE; |
287 | 290 |
288 if (StrStartsWith(name, kChromeArchivePrefix)) { | 291 if (StrStartsWith(name, kChromeArchivePrefix)) { |
289 if (!ctx->chrome_resource_path->assign(full_path.get())) | 292 if (!ctx->chrome_resource_path->assign(full_path.get())) |
290 return FALSE; | 293 return FALSE; |
291 } else if (StrStartsWith(name, kSetupPrefix)) { | 294 } else if (StrStartsWith(name, kSetupPrefix)) { |
292 if (!ctx->setup_resource_path->assign(full_path.get())) | 295 if (!ctx->setup_resource_path->assign(full_path.get())) |
293 return FALSE; | 296 return FALSE; |
297 #if defined(SYZYASAN) | |
298 } else if (StrStartsWith(name, kSyzyAsanRuntimePrefix)) { | |
299 if (!ctx->syzyasan_resource_path->assign(full_path.get())) | |
300 return FALSE; | |
301 #endif | |
294 } else { | 302 } else { |
295 // Resources should either start with 'chrome' or 'setup'. We don't handle | 303 // Resources should either start with 'chrome' or 'setup'. We don't handle |
296 // anything else. | 304 // anything else. |
297 return FALSE; | 305 return FALSE; |
298 } | 306 } |
299 | 307 |
300 return TRUE; | 308 return TRUE; |
301 } | 309 } |
302 | 310 |
303 #if defined(COMPONENT_BUILD) | 311 #if defined(COMPONENT_BUILD) || defined(SYZYASAN) |
304 // An EnumResNameProc callback that writes the resource |name| to disk in the | 312 // An EnumResNameProc callback that writes the resource |name| to disk in the |
305 // directory |base_path_ptr| (which must end with a path separator). | 313 // directory |base_path_ptr| (which must end with a path separator). |
306 BOOL CALLBACK WriteResourceToDirectory(HMODULE module, | 314 BOOL CALLBACK WriteResourceToDirectory(HMODULE module, |
307 const wchar_t* type, | 315 const wchar_t* type, |
308 wchar_t* name, | 316 wchar_t* name, |
309 LONG_PTR base_path_ptr) { | 317 LONG_PTR base_path_ptr) { |
310 const wchar_t* base_path = reinterpret_cast<const wchar_t*>(base_path_ptr); | 318 const wchar_t* base_path = reinterpret_cast<const wchar_t*>(base_path_ptr); |
311 PathString full_path; | 319 PathString full_path; |
312 | 320 |
313 PEResource resource(name, type, module); | 321 PEResource resource(name, type, module); |
(...skipping 10 matching lines...) Expand all Loading... | |
324 // - Resource type 'B7', compressed using LZMA (*.7z) | 332 // - Resource type 'B7', compressed using LZMA (*.7z) |
325 // - Resource type 'BL', compressed using LZ (*.ex_) | 333 // - Resource type 'BL', compressed using LZ (*.ex_) |
326 // - Resource type 'BN', uncompressed (*.exe) | 334 // - Resource type 'BN', uncompressed (*.exe) |
327 // If setup.exe is present in more than one form, the precedence order is | 335 // If setup.exe is present in more than one form, the precedence order is |
328 // BN < BL < B7 | 336 // BN < BL < B7 |
329 // For more details see chrome/tools/build/win/create_installer_archive.py. | 337 // For more details see chrome/tools/build/win/create_installer_archive.py. |
330 // For component builds (where setup.ex_ is always used), all files stored as | 338 // For component builds (where setup.ex_ is always used), all files stored as |
331 // uncompressed 'BN' resources are also extracted. This is generally the set of | 339 // uncompressed 'BN' resources are also extracted. This is generally the set of |
332 // DLLs/resources needed by setup.exe to run. | 340 // DLLs/resources needed by setup.exe to run. |
333 ProcessExitResult UnpackBinaryResources(const Configuration& configuration, | 341 ProcessExitResult UnpackBinaryResources(const Configuration& configuration, |
334 HMODULE module, const wchar_t* base_path, | 342 HMODULE module, |
335 PathString* archive_path, | 343 Context* context) { |
336 PathString* setup_path) { | |
337 // Generate the setup.exe path where we patch/uncompress setup resource. | 344 // Generate the setup.exe path where we patch/uncompress setup resource. |
338 PathString setup_dest_path; | 345 PathString setup_dest_path; |
339 if (!setup_dest_path.assign(base_path) || | 346 if (!setup_dest_path.assign(context->base_path) || |
340 !setup_dest_path.append(kSetupExe)) | 347 !setup_dest_path.append(kSetupExe)) |
341 return ProcessExitResult(PATH_STRING_OVERFLOW); | 348 return ProcessExitResult(PATH_STRING_OVERFLOW); |
342 | 349 |
343 // Prepare the input to OnResourceFound method that needs a location where | |
344 // it will write all the resources. | |
345 Context context = { | |
346 base_path, | |
347 archive_path, | |
348 setup_path, | |
349 }; | |
350 | |
351 // Get the resources of type 'B7' (7zip archive). | 350 // Get the resources of type 'B7' (7zip archive). |
352 // We need a chrome archive to do the installation. So if there | 351 // We need a chrome archive to do the installation. So if there |
353 // is a problem in fetching B7 resource, just return an error. | 352 // is a problem in fetching B7 resource, just return an error. |
354 if (!::EnumResourceNames(module, kLZMAResourceType, OnResourceFound, | 353 if (!::EnumResourceNames(module, kLZMAResourceType, OnResourceFound, |
355 reinterpret_cast<LONG_PTR>(&context))) { | 354 reinterpret_cast<LONG_PTR>(context))) { |
356 return ProcessExitResult(UNABLE_TO_EXTRACT_CHROME_ARCHIVE, | 355 return ProcessExitResult(UNABLE_TO_EXTRACT_CHROME_ARCHIVE, |
357 ::GetLastError()); | 356 ::GetLastError()); |
358 } | 357 } |
359 if (archive_path->length() == 0) { | 358 if (context->chrome_resource_path->length() == 0) { |
360 return ProcessExitResult(UNABLE_TO_EXTRACT_CHROME_ARCHIVE); | 359 return ProcessExitResult(UNABLE_TO_EXTRACT_CHROME_ARCHIVE); |
361 } | 360 } |
362 | 361 |
363 ProcessExitResult exit_code = ProcessExitResult(SUCCESS_EXIT_CODE); | 362 ProcessExitResult exit_code = ProcessExitResult(SUCCESS_EXIT_CODE); |
364 | 363 |
365 // If we found setup 'B7' resource (used for differential updates), handle | 364 // If we found setup 'B7' resource (used for differential updates), handle |
366 // it. Note that this is only for Chrome; Chromium installs are always | 365 // it. Note that this is only for Chrome; Chromium installs are always |
367 // "full" installs. | 366 // "full" installs. |
368 if (setup_path->length() > 0) { | 367 if (context->setup_resource_path->length() > 0) { |
369 CommandString cmd_line; | 368 CommandString cmd_line; |
370 PathString exe_path; | 369 PathString exe_path; |
371 // Get the path to setup.exe first. | 370 // Get the path to setup.exe first. |
372 exit_code = GetPreviousSetupExePath(configuration, exe_path.get(), | 371 exit_code = GetPreviousSetupExePath(configuration, exe_path.get(), |
373 exe_path.capacity()); | 372 exe_path.capacity()); |
374 if (exit_code.IsSuccess()) { | 373 if (exit_code.IsSuccess()) { |
375 if (!cmd_line.append(exe_path.get()) || | 374 if (!cmd_line.append(exe_path.get()) || !cmd_line.append(L" --") || |
376 !cmd_line.append(L" --") || | 375 !cmd_line.append(kCmdUpdateSetupExe) || !cmd_line.append(L"=\"") || |
377 !cmd_line.append(kCmdUpdateSetupExe) || | 376 !cmd_line.append(context->setup_resource_path->get()) || |
378 !cmd_line.append(L"=\"") || | 377 !cmd_line.append(L"\" --") || !cmd_line.append(kCmdNewSetupExe) || |
379 !cmd_line.append(setup_path->get()) || | 378 !cmd_line.append(L"=\"") || !cmd_line.append(setup_dest_path.get()) || |
380 !cmd_line.append(L"\" --") || | |
381 !cmd_line.append(kCmdNewSetupExe) || | |
382 !cmd_line.append(L"=\"") || | |
383 !cmd_line.append(setup_dest_path.get()) || | |
384 !cmd_line.append(L"\"")) { | 379 !cmd_line.append(L"\"")) { |
385 exit_code = ProcessExitResult(COMMAND_STRING_OVERFLOW); | 380 exit_code = ProcessExitResult(COMMAND_STRING_OVERFLOW); |
386 } | 381 } |
387 } | 382 } |
388 | 383 |
389 // Get any command line option specified for mini_installer and pass them | 384 // Get any command line option specified for mini_installer and pass them |
390 // on to setup.exe. | 385 // on to setup.exe. |
391 AppendCommandLineFlags(configuration.command_line(), &cmd_line); | 386 AppendCommandLineFlags(configuration.command_line(), &cmd_line); |
392 | 387 |
393 if (exit_code.IsSuccess()) | 388 if (exit_code.IsSuccess()) |
394 exit_code = RunProcessAndWait(exe_path.get(), cmd_line.get()); | 389 exit_code = RunProcessAndWait(exe_path.get(), cmd_line.get()); |
395 | 390 |
396 if (!exit_code.IsSuccess()) | 391 if (!exit_code.IsSuccess()) |
397 DeleteFile(setup_path->get()); | 392 DeleteFile(context->setup_resource_path->get()); |
398 else if (!setup_path->assign(setup_dest_path.get())) | 393 else if (!context->setup_resource_path->assign(setup_dest_path.get())) |
399 exit_code = ProcessExitResult(PATH_STRING_OVERFLOW); | 394 exit_code = ProcessExitResult(PATH_STRING_OVERFLOW); |
400 | 395 |
401 return exit_code; | 396 return exit_code; |
402 } | 397 } |
403 | 398 |
404 // setup.exe wasn't sent as 'B7', lets see if it was sent as 'BL' | 399 // setup.exe wasn't sent as 'B7', lets see if it was sent as 'BL' |
405 // (compressed setup). | 400 // (compressed setup). |
406 if (!::EnumResourceNames(module, kLZCResourceType, OnResourceFound, | 401 if (!::EnumResourceNames(module, kLZCResourceType, OnResourceFound, |
407 reinterpret_cast<LONG_PTR>(&context))) { | 402 reinterpret_cast<LONG_PTR>(context))) { |
408 return ProcessExitResult(UNABLE_TO_EXTRACT_SETUP_BL, ::GetLastError()); | 403 return ProcessExitResult(UNABLE_TO_EXTRACT_SETUP_BL, ::GetLastError()); |
409 } | 404 } |
410 if (setup_path->length() == 0) { | 405 if (context->setup_resource_path->length() == 0) { |
411 // Neither setup_patch.packed.7z nor setup.ex_ was found. | 406 // Neither setup_patch.packed.7z nor setup.ex_ was found. |
412 return ProcessExitResult(UNABLE_TO_EXTRACT_SETUP); | 407 return ProcessExitResult(UNABLE_TO_EXTRACT_SETUP); |
413 } | 408 } |
414 | 409 |
415 // Uncompress LZ compressed resource. Setup is packed with 'MSCF' | 410 // Uncompress LZ compressed resource. Setup is packed with 'MSCF' |
416 // as opposed to old DOS way of 'SZDD'. Hence we don't use LZCopy. | 411 // as opposed to old DOS way of 'SZDD'. Hence we don't use LZCopy. |
417 bool success = | 412 bool success = mini_installer::Expand(context->setup_resource_path->get(), |
418 mini_installer::Expand(setup_path->get(), setup_dest_path.get()); | 413 setup_dest_path.get()); |
419 ::DeleteFile(setup_path->get()); | 414 ::DeleteFile(context->setup_resource_path->get()); |
420 if (success) { | 415 if (success) { |
421 if (!setup_path->assign(setup_dest_path.get())) { | 416 if (!context->setup_resource_path->assign(setup_dest_path.get())) { |
422 ::DeleteFile(setup_dest_path.get()); | 417 ::DeleteFile(setup_dest_path.get()); |
423 exit_code = ProcessExitResult(PATH_STRING_OVERFLOW); | 418 exit_code = ProcessExitResult(PATH_STRING_OVERFLOW); |
424 } | 419 } |
425 } else { | 420 } else { |
426 exit_code = ProcessExitResult(UNABLE_TO_EXTRACT_SETUP_EXE); | 421 exit_code = ProcessExitResult(UNABLE_TO_EXTRACT_SETUP_EXE); |
427 } | 422 } |
428 | 423 |
424 #if defined(SYZYASAN) | |
425 PathString syzyasan_dest_path; | |
426 if (!syzyasan_dest_path.assign(context->base_path) || | |
427 !syzyasan_dest_path.append(L"syzyasan_rtl.dll")) { | |
428 return ProcessExitResult(PATH_STRING_OVERFLOW); | |
429 } | |
430 success = mini_installer::Expand(context->syzyasan_resource_path->get(), | |
Sébastien Marchand
2017/04/05 21:07:02
This probably could be moved into a function, not
| |
431 syzyasan_dest_path.get()); | |
432 ::DeleteFile(context->syzyasan_resource_path->get()); | |
433 if (success) { | |
434 if (!context->syzyasan_resource_path->assign(syzyasan_dest_path.get())) { | |
435 ::DeleteFile(syzyasan_dest_path.get()); | |
436 exit_code = ProcessExitResult(PATH_STRING_OVERFLOW); | |
437 } | |
438 } else { | |
439 // TODO(sebmarchand): Add a new exit code for syzyasan_rtl.dll? | |
440 exit_code = ProcessExitResult(UNABLE_TO_EXTRACT_SETUP_EXE); | |
441 } | |
442 #endif | |
443 | |
429 #if defined(COMPONENT_BUILD) | 444 #if defined(COMPONENT_BUILD) |
430 if (exit_code.IsSuccess()) { | 445 if (exit_code.IsSuccess()) { |
431 // Extract the (uncompressed) modules required by setup.exe. | 446 // Extract the (uncompressed) modules required by setup.exe. |
432 if (!::EnumResourceNames(module, kBinResourceType, WriteResourceToDirectory, | 447 if (!::EnumResourceNames(module, kBinResourceType, WriteResourceToDirectory, |
433 reinterpret_cast<LONG_PTR>(base_path))) { | 448 reinterpret_cast<LONG_PTR>(base_path))) { |
434 return ProcessExitResult(UNABLE_TO_EXTRACT_SETUP, ::GetLastError()); | 449 return ProcessExitResult(UNABLE_TO_EXTRACT_SETUP, ::GetLastError()); |
435 } | 450 } |
436 } | 451 } |
437 #endif | 452 #endif |
438 | 453 |
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
837 // Set the magic suffix in registry to try full installer next time. We ignore | 852 // Set the magic suffix in registry to try full installer next time. We ignore |
838 // any errors here and we try to set the suffix for user level unless | 853 // any errors here and we try to set the suffix for user level unless |
839 // GoogleUpdateIsMachine=1 is present in the environment or --system-level is | 854 // GoogleUpdateIsMachine=1 is present in the environment or --system-level is |
840 // on the command line in which case we set it for system level instead. This | 855 // on the command line in which case we set it for system level instead. This |
841 // only applies to the Google Chrome distribution. | 856 // only applies to the Google Chrome distribution. |
842 SetInstallerFlags(configuration); | 857 SetInstallerFlags(configuration); |
843 #endif | 858 #endif |
844 | 859 |
845 PathString archive_path; | 860 PathString archive_path; |
846 PathString setup_path; | 861 PathString setup_path; |
847 exit_code = UnpackBinaryResources(configuration, module, base_path.get(), | 862 #if defined(SYZYASAN) |
848 &archive_path, &setup_path); | 863 PathString syzyasan_rtl_path; |
864 #endif | |
865 Context context = { | |
866 base_path.get(), | |
867 &archive_path, | |
868 &setup_path, | |
869 #if defined(SYZYASAN) | |
870 &syzyasan_rtl_path, | |
871 #endif | |
872 }; | |
873 exit_code = UnpackBinaryResources(configuration, module, &context); | |
849 | 874 |
850 // While unpacking the binaries, we paged in a whole bunch of memory that | 875 // While unpacking the binaries, we paged in a whole bunch of memory that |
851 // we don't need anymore. Let's give it back to the pool before running | 876 // we don't need anymore. Let's give it back to the pool before running |
852 // setup. | 877 // setup. |
853 ::SetProcessWorkingSetSize(::GetCurrentProcess(), (SIZE_T)-1, (SIZE_T)-1); | 878 ::SetProcessWorkingSetSize(::GetCurrentProcess(), (SIZE_T)-1, (SIZE_T)-1); |
854 | 879 |
855 if (exit_code.IsSuccess()) | 880 if (exit_code.IsSuccess()) |
856 exit_code = RunSetup(configuration, archive_path.get(), setup_path.get()); | 881 exit_code = RunSetup(configuration, archive_path.get(), setup_path.get()); |
857 | 882 |
858 if (ShouldDeleteExtractedFiles()) | 883 if (ShouldDeleteExtractedFiles()) |
859 DeleteExtractedFiles(base_path.get(), archive_path.get(), setup_path.get()); | 884 DeleteExtractedFiles(base_path.get(), archive_path.get(), setup_path.get()); |
860 | 885 |
861 #if defined(GOOGLE_CHROME_BUILD) | 886 #if defined(GOOGLE_CHROME_BUILD) |
862 WriteInstallResults(configuration, exit_code); | 887 WriteInstallResults(configuration, exit_code); |
863 #endif | 888 #endif |
864 | 889 |
865 return exit_code; | 890 return exit_code; |
866 } | 891 } |
867 | 892 |
868 } // namespace mini_installer | 893 } // namespace mini_installer |
OLD | NEW |