15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The file contains the implementation of the mini_installer re-versioner. 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The main function (GenerateNextVersion) does the following in a temp dir: 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Extracts and unpacks setup.exe and the Chrome-bin folder from 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// mini_installer.exe. 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Inspects setup.exe to determine the current version. 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Runs through all .dll and .exe files: 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Replacing all occurrences of the Unicode version string in the files' 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// resources with the updated string. 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - For all resources in which the string substitution is made, the binary 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// form of the version is also replaced. 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Re-packs setup.exe and Chrome-bin. 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Inserts them into the target mini_installer.exe. 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This code assumes that the host program 1) initializes the process-wide 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CommandLine instance, and 2) resides in the output directory of a build 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// tree. When #2 is not the case, the --7za_path command-line switch may be 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// used to provide the (relative or absolute) path to the directory containing 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 7za.exe. 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/test/alternate_version_generator.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits> 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <sstream> 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility> 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/files/file.h" 37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/files/file_enumerator.h" 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h" 42a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "base/process/launch.h" 43a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "base/process/process_handle.h" 447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_util.h" 45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/version.h" 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/pe_image.h" 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_handle.h" 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/test/pe_image_resources.h" 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/test/resource_loader.h" 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/test/resource_updater.h" 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/lzma_util.h" 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t k7zaExe[] = L"7za.exe"; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t k7zaPathRelative[] = L"..\\..\\third_party\\lzma_sdk\\Executable"; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kB7[] = L"B7"; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kBl[] = L"BL"; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kChrome7z[] = L"chrome.7z"; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kChromeBin[] = L"Chrome-bin"; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kChromePacked7z[] = L"chrome.packed.7z"; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kExe[] = L"exe"; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kExpandExe[] = L"expand.exe"; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kExtDll[] = L".dll"; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kExtExe[] = L".exe"; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kMakeCab[] = L"makecab.exe"; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kSetupEx_[] = L"setup.ex_"; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kSetupExe[] = L"setup.exe"; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kSwitch7zaPath[] = "7za_path"; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kTempDirPrefix[] = L"mini_installer_test_temp"; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A helper class for creating and cleaning a temporary directory. A temporary 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// directory is created in Initialize and destroyed (along with all of its 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// contents) when the guard instance is destroyed. 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ScopedTempDirectory { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedTempDirectory() { } 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~ScopedTempDirectory() { 807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!directory_.empty() && !base::DeleteFile(directory_, true)) { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Failed deleting temporary directory \"" 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << directory_.value() << "\""; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Creates a temporary directory. 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool Initialize() { 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(directory_.empty()); 88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!base::CreateNewTempDirectory(&kTempDirPrefix[0], &directory_)) { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Failed creating temporary directory."; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& directory() const { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!directory_.empty()); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return directory_; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath directory_; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ScopedTempDirectory); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; // class ScopedTempDirectory 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A helper class for manipulating a Chrome product version. 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ChromeVersion { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static ChromeVersion FromHighLow(DWORD high, DWORD low) { 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ChromeVersion(static_cast<ULONGLONG>(high) << 32 | 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<ULONGLONG>(low)); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static ChromeVersion FromString(const std::string& version_string) { 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Version version(version_string); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(version.IsValid()); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<uint16>& c(version.components()); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ChromeVersion(static_cast<ULONGLONG>(c[0]) << 48 | 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<ULONGLONG>(c[1]) << 32 | 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<ULONGLONG>(c[2]) << 16 | 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<ULONGLONG>(c[3])); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChromeVersion() { } 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit ChromeVersion(ULONGLONG value) : version_(value) { } 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WORD major() const { return static_cast<WORD>(version_ >> 48); } 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WORD minor() const { return static_cast<WORD>(version_ >> 32); } 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WORD build() const { return static_cast<WORD>(version_ >> 16); } 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WORD patch() const { return static_cast<WORD>(version_); } 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD high() const { return static_cast<DWORD>(version_ >> 32); } 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD low() const { return static_cast<DWORD>(version_); } 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONGLONG value() const { return version_; } 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void set_value(ULONGLONG value) { version_ = value; } 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring ToString() const; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONGLONG version_; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; // class ChromeVersion 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::wstring ChromeVersion::ToString() const { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t buffer[24]; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int string_len = 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swprintf_s(&buffer[0], arraysize(buffer), L"%hu.%hu.%hu.%hu", 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) major(), minor(), build(), patch()); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(-1, string_len); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(static_cast<int>(arraysize(buffer)), string_len); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::wstring(&buffer[0], string_len); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A read/write mapping of a file. 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: base::MemoryMappedFile is not used because it doesn't support 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// read/write mappings. Adding such support across all platforms for this 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Windows-only test code seems like overkill. 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MappedFile { 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MappedFile() : size_(), mapping_(), view_() { } 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~MappedFile(); 155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool Initialize(base::File file); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* data() const { return view_; } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t size() const { return size_; } 158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t size_; 161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::File file_; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE mapping_; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* view_; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(MappedFile); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; // class MappedFile 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MappedFile::~MappedFile() { 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (view_ != NULL) { 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (UnmapViewOfFile(view_) == 0) { 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(DFATAL) << "MappedFile failed to unmap view."; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mapping_ != NULL) { 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CloseHandle(mapping_) == 0) { 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(DFATAL) << "Could not close file mapping handle."; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool MappedFile::Initialize(base::File file) { 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(mapping_ == NULL); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result = false; 183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::File::Info file_info; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (file.GetInfo(&file_info)) { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (file_info.size <= 187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static_cast<int64>(std::numeric_limits<DWORD>::max())) { 188a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) mapping_ = CreateFileMapping(file.GetPlatformFile(), NULL, PAGE_READWRITE, 189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 0, static_cast<DWORD>(file_info.size), NULL); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mapping_ != NULL) { 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_ = MapViewOfFile(mapping_, FILE_MAP_WRITE, 0, 0, 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<size_t>(file_info.size)); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (view_ != NULL) { 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = true; 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(DFATAL) << "MapViewOfFile failed"; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(DFATAL) << "CreateFileMapping failed"; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(DFATAL) << "Files larger than " << std::numeric_limits<DWORD>::max() 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " are not supported."; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 20646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) PLOG(DFATAL) << "file.GetInfo failed"; 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) file_ = file.Pass(); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Calls CreateProcess with good default parameters and waits for the process 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to terminate returning the process exit code. 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RunProcessAndWait(const wchar_t* exe_path, const std::wstring& cmdline, 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* exit_code) { 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result = true; 217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::win::ScopedHandle process; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::LaunchOptions options; 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) options.wait = true; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) options.start_hidden = true; 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::LaunchProcess(cmdline, options, &process)) { 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (exit_code) { 223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!GetExitCodeProcess(process.Get(), 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<DWORD*>(exit_code))) { 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(DFATAL) << "Failed getting the exit code for \"" 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << cmdline << "\"."; 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = false; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(*exit_code, STILL_ACTIVE); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = false; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Retrieves the version number of |pe_file| from its version 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// resource, placing the value in |version|. Returns true on success. 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GetFileVersion(const base::FilePath& pe_file, ChromeVersion* version) { 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(version); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result = false; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) upgrade_test::ResourceLoader pe_file_loader; 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::pair<const uint8*, DWORD> version_info_data; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pe_file_loader.Initialize(pe_file) && 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pe_file_loader.Load(VS_VERSION_INFO, reinterpret_cast<WORD>(RT_VERSION), 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &version_info_data)) { 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const VS_FIXEDFILEINFO* fixed_file_info; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UINT ver_info_len; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (VerQueryValue(version_info_data.first, L"\\", 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<void**>( 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const_cast<VS_FIXEDFILEINFO**>(&fixed_file_info)), 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &ver_info_len) != 0) { 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(sizeof(VS_FIXEDFILEINFO), static_cast<size_t>(ver_info_len)); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *version = ChromeVersion::FromHighLow(fixed_file_info->dwFileVersionMS, 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fixed_file_info->dwFileVersionLS); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = true; 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "VerQueryValue failed to retrieve VS_FIXEDFILEINFO"; 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Retrieves the version number of setup.exe in |work_dir| from its version 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// resource, placing the value in |version|. Returns true on success. 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GetSetupExeVersion(const base::FilePath& work_dir, 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ChromeVersion* version) { 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetFileVersion(work_dir.Append(&kSetupExe[0]), version); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Replace all occurrences in the sequence [|dest_first|, |dest_last) that 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// equals [|src_first|, |src_last) with the sequence at |replacement_first| of 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the same length. Returns true on success. If non-NULL, |replacements_made| 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is set to true/false accordingly. 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ReplaceAll(uint8* dest_first, uint8* dest_last, 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8* src_first, const uint8* src_last, 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8* replacement_first, bool* replacements_made) { 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result = true; 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool changed = false; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_first = std::search(dest_first, dest_last, src_first, src_last); 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dest_first == dest_last) { 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) changed = true; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (memcpy_s(dest_first, dest_last - dest_first, 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) replacement_first, src_last - src_first) != 0) { 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = false; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_first += (src_last - src_first); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (true); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (replacements_made != NULL) { 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *replacements_made = changed; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A context structure in support of our EnumResource_Fn callback. 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct VisitResourceContext { 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChromeVersion current_version; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring current_version_str; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChromeVersion new_version; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring new_version_str; 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; // struct VisitResourceContext 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Replaces the old version with the new in a resource. A first pass is made to 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// replace the string form (e.g., "9.0.584.0"). If any replacements are made, a 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// second pass is made to replace the binary form (e.g., 0x0000024800000009). 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VisitResource(const upgrade_test::EntryPath& path, 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8* data, DWORD size, DWORD code_page, 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t context) { 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitResourceContext& ctx = *reinterpret_cast<VisitResourceContext*>(context); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Replace all occurrences of current_version_str with new_version_str 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool changing_version = false; 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ReplaceAll( 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data, 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data + size, 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const uint8*>(ctx.current_version_str.c_str()), 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const uint8*>(ctx.current_version_str.c_str() + 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ctx.current_version_str.size() + 1), 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const uint8*>(ctx.new_version_str.c_str()), 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &changing_version) && 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) changing_version) { 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Replace all occurrences of current_version with new_version 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct VersionPair { 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD high; 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD low; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VersionPair cur_ver = { 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ctx.current_version.high(), ctx.current_version.low() 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VersionPair new_ver = { 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ctx.new_version.high(), ctx.new_version.low() 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReplaceAll(data, data + size, reinterpret_cast<const uint8*>(&cur_ver), 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const uint8*>(&cur_ver) + sizeof(cur_ver), 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const uint8*>(&new_ver), NULL); 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Updates the version strings and numbers in all of |image_file|'s resources. 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool UpdateVersionIfMatch(const base::FilePath& image_file, 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitResourceContext* context) { 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!context || 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context->current_version_str.size() < context->new_version_str.size()) { 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result = false; 359a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) uint32 flags = base::File::FLAG_OPEN | base::File::FLAG_READ | 360a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::File::FLAG_WRITE | base::File::FLAG_EXCLUSIVE_READ | 361a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::File::FLAG_EXCLUSIVE_WRITE; 362a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::File file(image_file, flags); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It turns out that the underlying CreateFile can fail due to unhelpful 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // security software locking the newly created DLL. So add a few brief 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // retries to help tests that use this pass on machines thusly encumbered. 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int retries = 3; 367a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) while (!file.IsValid() && retries-- > 0) { 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Failed to open \"" << image_file.value() << "\"." 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " Retrying " << retries << " more times."; 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Sleep(1000); 371a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) file.Initialize(image_file, flags); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 374a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (file.IsValid()) { 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MappedFile image_mapping; 376a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (image_mapping.Initialize(file.Pass())) { 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::PEImageAsData image( 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<HMODULE>(image_mapping.data())); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // PEImage class does not support other-architecture images. 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (image.GetNTHeaders()->OptionalHeader.Magic == 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IMAGE_NT_OPTIONAL_HDR_MAGIC) { 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = upgrade_test::EnumResources( 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image, &VisitResource, reinterpret_cast<uintptr_t>(context)); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = true; 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(DFATAL) << "Failed to open \"" << image_file.value() << "\""; 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IncrementNewVersion(upgrade_test::Direction direction, 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitResourceContext* ctx) { 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ctx); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Figure out a past or future version with the same string length as this one 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // by decrementing or incrementing each component. 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LONGLONG incrementer = (direction == upgrade_test::PREVIOUS_VERSION ? -1 : 1); 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (incrementer == 0) { 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Improbable version at the cusp of complete rollover"; 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ctx->new_version.set_value(ctx->current_version.value() + incrementer); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ctx->new_version_str = ctx->new_version.ToString(); 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) incrementer <<= 16; 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (ctx->new_version_str.size() != ctx->current_version_str.size()); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Raises or lowers the version of all .exe and .dll files in |work_dir| as well 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as the |work-dir|\Chrome-bin\w.x.y.z directory. |original_version| and 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |new_version|, when non-NULL, are given the original and new version numbers 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// on success. 4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ApplyAlternateVersion(const base::FilePath& work_dir, 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) upgrade_test::Direction direction, 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring* original_version, 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring* new_version) { 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitResourceContext ctx; 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetSetupExeVersion(work_dir, &ctx.current_version)) { 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ctx.current_version_str = ctx.current_version.ToString(); 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IncrementNewVersion(direction, &ctx)) { 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Modify all .dll and .exe files with the current version. 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool doing_great = true; 435868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::FileEnumerator all_files(work_dir, true, base::FileEnumerator::FILES); 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath file = all_files.Next(); 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (file.empty()) { 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring extension = file.Extension(); 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (extension == &kExtExe[0] || extension == &kExtDll[0]) { 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) doing_great = UpdateVersionIfMatch(file, &ctx); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (doing_great); 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Change the versioned directory. 4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath chrome_bin = work_dir.Append(&kChromeBin[0]); 449eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch doing_great = base::Move(chrome_bin.Append(ctx.current_version_str), 450eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch chrome_bin.Append(ctx.new_version_str)); 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (doing_great) { 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Report the version numbers if requested. 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (original_version != NULL) 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) original_version->assign(ctx.current_version_str); 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (new_version != NULL) 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_version->assign(ctx.new_version_str); 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return doing_great; 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the path to the directory holding the 7za executable. By default, it 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is assumed that the test resides in the tree's output directory, so the 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// relative path "..\..\third_party\lzma_sdk\Executable" is applied to the host 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// executable's directory. This can be overridden with the --7za_path 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// command-line switch. 4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath Get7zaPath() { 4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath l7za_path = 4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CommandLine::ForCurrentProcess()->GetSwitchValuePath( 4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &kSwitch7zaPath[0]); 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (l7za_path.empty()) { 4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath dir_exe; 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!PathService::Get(base::DIR_EXE, &dir_exe)) 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Failed getting directory of host executable"; 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l7za_path = dir_exe.Append(&k7zaPathRelative[0]); 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return l7za_path; 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool CreateArchive(const base::FilePath& output_file, 4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& input_path, 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int compression_level) { 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(compression_level == 0 || 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) compression_level >= 1 && compression_level <= 9 && 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (compression_level & 0x01) != 0); 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring command_line(1, L'"'); 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command_line 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(Get7zaPath().Append(&k7zaExe[0]).value()) 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(L"\" a -bd -t7z \"") 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(output_file.value()) 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(L"\" \"") 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(input_path.value()) 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(L"\" -mx") 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(1, L'0' + compression_level); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int exit_code; 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!RunProcessAndWait(NULL, command_line, &exit_code)) 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (exit_code != 0) { 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << Get7zaPath().Append(&k7zaExe[0]).value() 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " exited with code " << exit_code 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " while creating " << output_file.value(); 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace upgrade_test { 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GenerateAlternateVersion(const base::FilePath& original_installer_path, 5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& target_path, 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Direction direction, 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring* original_version, 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring* new_version) { 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a temporary directory in which we'll do our work. 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedTempDirectory work_dir; 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!work_dir.Initialize()) 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Copy the original mini_installer. 5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath mini_installer = 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) work_dir.directory().Append(original_installer_path.BaseName()); 5267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!base::CopyFile(original_installer_path, mini_installer)) { 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Failed copying \"" << original_installer_path.value() 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "\" to \"" << mini_installer.value() << "\""; 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath setup_ex_ = work_dir.directory().Append(&kSetupEx_[0]); 5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath chrome_packed_7z = 5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) work_dir.directory().Append(&kChromePacked7z[0]); 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Load the original file and extract setup.ex_ and chrome.packed.7z 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResourceLoader resource_loader; 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::pair<const uint8*, DWORD> resource_data; 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!resource_loader.Initialize(mini_installer)) 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Write out setup.ex_ 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!resource_loader.Load(&kSetupEx_[0], &kBl[0], &resource_data)) 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int written = 547a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::WriteFile(setup_ex_, 548a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) reinterpret_cast<const char*>(resource_data.first), 549a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static_cast<int>(resource_data.second)); 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (written != resource_data.second) { 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Failed writing \"" << setup_ex_.value() << "\""; 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Write out chrome.packed.7z 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!resource_loader.Load(&kChromePacked7z[0], &kB7[0], &resource_data)) 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) written = 559a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::WriteFile(chrome_packed_7z, 560a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) reinterpret_cast<const char*>(resource_data.first), 561a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static_cast<int>(resource_data.second)); 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (written != resource_data.second) { 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Failed writing \"" << chrome_packed_7z.value() << "\""; 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Expand setup.ex_ 5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath setup_exe = setup_ex_.ReplaceExtension(&kExe[0]); 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring command_line; 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command_line.append(1, L'"') 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(&kExpandExe[0]) 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(L"\" \"") 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(setup_ex_.value()) 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(L"\" \"") 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(setup_exe.value()) 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(1, L'\"'); 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int exit_code; 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!RunProcessAndWait(NULL, command_line, &exit_code)) 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (exit_code != 0) { 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << &kExpandExe[0] << " exited with code " << exit_code; 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unpack chrome.packed.7z 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring chrome_7z_name; 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (LzmaUtil::UnPackArchive(chrome_packed_7z.value(), 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) work_dir.directory().value(), 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &chrome_7z_name) != NO_ERROR) { 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Failed unpacking \"" << chrome_packed_7z.value() << "\""; 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unpack chrome.7z 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (LzmaUtil::UnPackArchive(chrome_7z_name, work_dir.directory().value(), 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL) != NO_ERROR) { 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Failed unpacking \"" << chrome_7z_name << "\""; 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get rid of intermediate files 6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath chrome_7z(chrome_7z_name); 6047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!base::DeleteFile(chrome_7z, false) || 6057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch !base::DeleteFile(chrome_packed_7z, false) || 6067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch !base::DeleteFile(setup_ex_, false)) { 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Failed deleting intermediate files"; 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Increment the version in all files. 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ApplyAlternateVersion(work_dir.directory(), direction, original_version, 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_version); 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Pack up files into chrome.7z 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CreateArchive(chrome_7z, work_dir.directory().Append(&kChromeBin[0]), 0)) 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Compress chrome.7z into chrome.packed.7z 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CreateArchive(chrome_packed_7z, chrome_7z, 9)) 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Compress setup.exe into setup.ex_ 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command_line.assign(1, L'"') 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(&kMakeCab[0]) 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(L"\" /D CompressionType=LZX /L \"") 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(work_dir.directory().value()) 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(L"\" \"") 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(setup_exe.value()); 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!RunProcessAndWait(NULL, command_line, &exit_code)) 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (exit_code != 0) { 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << &kMakeCab[0] << " exited with code " << exit_code; 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Replace the mini_installer's setup.ex_ and chrome.packed.7z resources. 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResourceUpdater updater; 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!updater.Initialize(mini_installer) || 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !updater.Update(&kSetupEx_[0], &kBl[0], 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setup_ex_) || 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !updater.Update(&kChromePacked7z[0], &kB7[0], 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome_packed_7z) || 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !updater.Commit()) { 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Finally, move the updated mini_installer into place. 651eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return base::Move(mini_installer, target_path); 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GenerateAlternatePEFileVersion(const base::FilePath& original_file, 6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& target_file, 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Direction direction) { 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitResourceContext ctx; 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetFileVersion(original_file, &ctx.current_version)) { 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Failed reading version from \"" << original_file.value() 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "\""; 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ctx.current_version_str = ctx.current_version.ToString(); 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IncrementNewVersion(direction, &ctx)) { 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Failed to increment version from \"" 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << original_file.value() << "\""; 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 671a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Version new_version(base::UTF16ToASCII(ctx.new_version_str)); 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GenerateSpecificPEFileVersion(original_file, target_file, new_version); 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GenerateSpecificPEFileVersion(const base::FilePath& original_file, 6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& target_file, 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Version& version) { 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First copy original_file to target_file. 6817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!base::CopyFile(original_file, target_file)) { 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Failed copying \"" << original_file.value() 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "\" to \"" << target_file.value() << "\""; 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitResourceContext ctx; 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetFileVersion(target_file, &ctx.current_version)) { 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Failed reading version from \"" << target_file.value() 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "\""; 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ctx.current_version_str = ctx.current_version.ToString(); 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ctx.new_version = ChromeVersion::FromString(version.GetString()); 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ctx.new_version_str = ctx.new_version.ToString(); 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return UpdateVersionIfMatch(target_file, &ctx); 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace upgrade_test 701