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" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h" 37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/files/file_enumerator.h" 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h" 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/platform_file.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" 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/version.h" 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/pe_image.h" 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_handle.h" 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/test/pe_image_resources.h" 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/test/resource_loader.h" 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/test/resource_updater.h" 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/lzma_util.h" 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t k7zaExe[] = L"7za.exe"; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t k7zaPathRelative[] = L"..\\..\\third_party\\lzma_sdk\\Executable"; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kB7[] = L"B7"; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kBl[] = L"BL"; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kChrome7z[] = L"chrome.7z"; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kChromeBin[] = L"Chrome-bin"; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kChromePacked7z[] = L"chrome.packed.7z"; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kExe[] = L"exe"; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kExpandExe[] = L"expand.exe"; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kExtDll[] = L".dll"; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kExtExe[] = L".exe"; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kMakeCab[] = L"makecab.exe"; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kSetupEx_[] = L"setup.ex_"; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kSetupExe[] = L"setup.exe"; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kSwitch7zaPath[] = "7za_path"; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kTempDirPrefix[] = L"mini_installer_test_temp"; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A helper class for creating and cleaning a temporary directory. A temporary 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// directory is created in Initialize and destroyed (along with all of its 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// contents) when the guard instance is destroyed. 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ScopedTempDirectory { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedTempDirectory() { } 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~ScopedTempDirectory() { 797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!directory_.empty() && !base::DeleteFile(directory_, true)) { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Failed deleting temporary directory \"" 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << directory_.value() << "\""; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Creates a temporary directory. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool Initialize() { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(directory_.empty()); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!file_util::CreateNewTempDirectory(&kTempDirPrefix[0], &directory_)) { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Failed creating temporary directory."; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& directory() const { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!directory_.empty()); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return directory_; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath directory_; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ScopedTempDirectory); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; // class ScopedTempDirectory 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A helper class for manipulating a Chrome product version. 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ChromeVersion { 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static ChromeVersion FromHighLow(DWORD high, DWORD low) { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ChromeVersion(static_cast<ULONGLONG>(high) << 32 | 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<ULONGLONG>(low)); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static ChromeVersion FromString(const std::string& version_string) { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Version version(version_string); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(version.IsValid()); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<uint16>& c(version.components()); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ChromeVersion(static_cast<ULONGLONG>(c[0]) << 48 | 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<ULONGLONG>(c[1]) << 32 | 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<ULONGLONG>(c[2]) << 16 | 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<ULONGLONG>(c[3])); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChromeVersion() { } 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit ChromeVersion(ULONGLONG value) : version_(value) { } 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WORD major() const { return static_cast<WORD>(version_ >> 48); } 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WORD minor() const { return static_cast<WORD>(version_ >> 32); } 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WORD build() const { return static_cast<WORD>(version_ >> 16); } 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WORD patch() const { return static_cast<WORD>(version_); } 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD high() const { return static_cast<DWORD>(version_ >> 32); } 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD low() const { return static_cast<DWORD>(version_); } 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONGLONG value() const { return version_; } 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void set_value(ULONGLONG value) { version_ = value; } 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring ToString() const; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONGLONG version_; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; // class ChromeVersion 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::wstring ChromeVersion::ToString() const { 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t buffer[24]; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int string_len = 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swprintf_s(&buffer[0], arraysize(buffer), L"%hu.%hu.%hu.%hu", 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) major(), minor(), build(), patch()); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(-1, string_len); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(static_cast<int>(arraysize(buffer)), string_len); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::wstring(&buffer[0], string_len); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A read/write mapping of a file. 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: base::MemoryMappedFile is not used because it doesn't support 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// read/write mappings. Adding such support across all platforms for this 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Windows-only test code seems like overkill. 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MappedFile { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MappedFile() : size_(), mapping_(), view_() { } 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~MappedFile(); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool Initialize(base::PlatformFile file); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* data() const { return view_; } 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t size() const { return size_; } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t size_; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE mapping_; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* view_; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(MappedFile); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; // class MappedFile 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MappedFile::~MappedFile() { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (view_ != NULL) { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (UnmapViewOfFile(view_) == 0) { 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(DFATAL) << "MappedFile failed to unmap view."; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mapping_ != NULL) { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CloseHandle(mapping_) == 0) { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(DFATAL) << "Could not close file mapping handle."; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MappedFile::Initialize(base::PlatformFile file) { 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(mapping_ == NULL); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result = false; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PlatformFileInfo file_info; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::GetPlatformFileInfo(file, &file_info)) { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (file_info.size <= 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static_cast<int64>(std::numeric_limits<DWORD>::max())) { 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mapping_ = CreateFileMapping(file, NULL, PAGE_READWRITE, 0, 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<DWORD>(file_info.size), NULL); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mapping_ != NULL) { 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_ = MapViewOfFile(mapping_, FILE_MAP_WRITE, 0, 0, 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<size_t>(file_info.size)); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (view_ != NULL) { 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = true; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(DFATAL) << "MapViewOfFile failed"; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(DFATAL) << "CreateFileMapping failed"; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(DFATAL) << "Files larger than " << std::numeric_limits<DWORD>::max() 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " are not supported."; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(DFATAL) << "GetPlatformFileInfo failed"; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Calls CreateProcess with good default parameters and waits for the process 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to terminate returning the process exit code. 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RunProcessAndWait(const wchar_t* exe_path, const std::wstring& cmdline, 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* exit_code) { 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result = true; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ProcessHandle process; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::LaunchOptions options; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) options.wait = true; 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) options.start_hidden = true; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::LaunchProcess(cmdline, options, &process)) { 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (exit_code) { 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetExitCodeProcess(process, 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<DWORD*>(exit_code))) { 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(DFATAL) << "Failed getting the exit code for \"" 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << cmdline << "\"."; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = false; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(*exit_code, STILL_ACTIVE); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = false; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseHandle(process); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Retrieves the version number of |pe_file| from its version 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// resource, placing the value in |version|. Returns true on success. 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GetFileVersion(const base::FilePath& pe_file, ChromeVersion* version) { 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(version); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result = false; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) upgrade_test::ResourceLoader pe_file_loader; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::pair<const uint8*, DWORD> version_info_data; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pe_file_loader.Initialize(pe_file) && 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pe_file_loader.Load(VS_VERSION_INFO, reinterpret_cast<WORD>(RT_VERSION), 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &version_info_data)) { 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const VS_FIXEDFILEINFO* fixed_file_info; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UINT ver_info_len; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (VerQueryValue(version_info_data.first, L"\\", 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<void**>( 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const_cast<VS_FIXEDFILEINFO**>(&fixed_file_info)), 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &ver_info_len) != 0) { 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(sizeof(VS_FIXEDFILEINFO), static_cast<size_t>(ver_info_len)); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *version = ChromeVersion::FromHighLow(fixed_file_info->dwFileVersionMS, 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fixed_file_info->dwFileVersionLS); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = true; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "VerQueryValue failed to retrieve VS_FIXEDFILEINFO"; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Retrieves the version number of setup.exe in |work_dir| from its version 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// resource, placing the value in |version|. Returns true on success. 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GetSetupExeVersion(const base::FilePath& work_dir, 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ChromeVersion* version) { 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetFileVersion(work_dir.Append(&kSetupExe[0]), version); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Replace all occurrences in the sequence [|dest_first|, |dest_last) that 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// equals [|src_first|, |src_last) with the sequence at |replacement_first| of 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the same length. Returns true on success. If non-NULL, |replacements_made| 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is set to true/false accordingly. 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ReplaceAll(uint8* dest_first, uint8* dest_last, 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8* src_first, const uint8* src_last, 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8* replacement_first, bool* replacements_made) { 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result = true; 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool changed = false; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_first = std::search(dest_first, dest_last, src_first, src_last); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dest_first == dest_last) { 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) changed = true; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (memcpy_s(dest_first, dest_last - dest_first, 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) replacement_first, src_last - src_first) != 0) { 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = false; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_first += (src_last - src_first); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (true); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (replacements_made != NULL) { 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *replacements_made = changed; 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A context structure in support of our EnumResource_Fn callback. 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct VisitResourceContext { 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChromeVersion current_version; 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring current_version_str; 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChromeVersion new_version; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring new_version_str; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; // struct VisitResourceContext 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Replaces the old version with the new in a resource. A first pass is made to 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// replace the string form (e.g., "9.0.584.0"). If any replacements are made, a 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// second pass is made to replace the binary form (e.g., 0x0000024800000009). 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VisitResource(const upgrade_test::EntryPath& path, 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8* data, DWORD size, DWORD code_page, 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t context) { 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitResourceContext& ctx = *reinterpret_cast<VisitResourceContext*>(context); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Replace all occurrences of current_version_str with new_version_str 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool changing_version = false; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ReplaceAll( 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data, 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data + size, 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const uint8*>(ctx.current_version_str.c_str()), 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const uint8*>(ctx.current_version_str.c_str() + 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ctx.current_version_str.size() + 1), 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const uint8*>(ctx.new_version_str.c_str()), 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &changing_version) && 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) changing_version) { 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Replace all occurrences of current_version with new_version 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct VersionPair { 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD high; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD low; 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VersionPair cur_ver = { 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ctx.current_version.high(), ctx.current_version.low() 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VersionPair new_ver = { 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ctx.new_version.high(), ctx.new_version.low() 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReplaceAll(data, data + size, reinterpret_cast<const uint8*>(&cur_ver), 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const uint8*>(&cur_ver) + sizeof(cur_ver), 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const uint8*>(&new_ver), NULL); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Updates the version strings and numbers in all of |image_file|'s resources. 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool UpdateVersionIfMatch(const base::FilePath& image_file, 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitResourceContext* context) { 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!context || 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context->current_version_str.size() < context->new_version_str.size()) { 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result = false; 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ScopedHandle image_handle(base::CreatePlatformFile( 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_file, 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ | 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_EXCLUSIVE_READ | 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PLATFORM_FILE_EXCLUSIVE_WRITE), NULL, NULL)); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It turns out that the underlying CreateFile can fail due to unhelpful 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // security software locking the newly created DLL. So add a few brief 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // retries to help tests that use this pass on machines thusly encumbered. 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int retries = 3; 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!image_handle.IsValid() && retries-- > 0) { 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Failed to open \"" << image_file.value() << "\"." 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " Retrying " << retries << " more times."; 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Sleep(1000); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_handle.Set(base::CreatePlatformFile( 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_file, 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ | 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_EXCLUSIVE_READ | 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PLATFORM_FILE_EXCLUSIVE_WRITE), NULL, NULL)); 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (image_handle.IsValid()) { 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MappedFile image_mapping; 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (image_mapping.Initialize(image_handle)) { 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::PEImageAsData image( 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<HMODULE>(image_mapping.data())); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // PEImage class does not support other-architecture images. 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (image.GetNTHeaders()->OptionalHeader.Magic == 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IMAGE_NT_OPTIONAL_HDR_MAGIC) { 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = upgrade_test::EnumResources( 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image, &VisitResource, reinterpret_cast<uintptr_t>(context)); 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = true; 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(DFATAL) << "Failed to open \"" << image_file.value() << "\""; 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IncrementNewVersion(upgrade_test::Direction direction, 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitResourceContext* ctx) { 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ctx); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Figure out a past or future version with the same string length as this one 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // by decrementing or incrementing each component. 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LONGLONG incrementer = (direction == upgrade_test::PREVIOUS_VERSION ? -1 : 1); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (incrementer == 0) { 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Improbable version at the cusp of complete rollover"; 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ctx->new_version.set_value(ctx->current_version.value() + incrementer); 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ctx->new_version_str = ctx->new_version.ToString(); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) incrementer <<= 16; 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (ctx->new_version_str.size() != ctx->current_version_str.size()); 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Raises or lowers the version of all .exe and .dll files in |work_dir| as well 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as the |work-dir|\Chrome-bin\w.x.y.z directory. |original_version| and 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |new_version|, when non-NULL, are given the original and new version numbers 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// on success. 4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ApplyAlternateVersion(const base::FilePath& work_dir, 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) upgrade_test::Direction direction, 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring* original_version, 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring* new_version) { 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitResourceContext ctx; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetSetupExeVersion(work_dir, &ctx.current_version)) { 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ctx.current_version_str = ctx.current_version.ToString(); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IncrementNewVersion(direction, &ctx)) { 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Modify all .dll and .exe files with the current version. 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool doing_great = true; 437868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::FileEnumerator all_files(work_dir, true, base::FileEnumerator::FILES); 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath file = all_files.Next(); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (file.empty()) { 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring extension = file.Extension(); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (extension == &kExtExe[0] || extension == &kExtDll[0]) { 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) doing_great = UpdateVersionIfMatch(file, &ctx); 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (doing_great); 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Change the versioned directory. 4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath chrome_bin = work_dir.Append(&kChromeBin[0]); 451eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch doing_great = base::Move(chrome_bin.Append(ctx.current_version_str), 452eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch chrome_bin.Append(ctx.new_version_str)); 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (doing_great) { 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Report the version numbers if requested. 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (original_version != NULL) 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) original_version->assign(ctx.current_version_str); 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (new_version != NULL) 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_version->assign(ctx.new_version_str); 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return doing_great; 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the path to the directory holding the 7za executable. By default, it 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is assumed that the test resides in the tree's output directory, so the 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// relative path "..\..\third_party\lzma_sdk\Executable" is applied to the host 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// executable's directory. This can be overridden with the --7za_path 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// command-line switch. 4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath Get7zaPath() { 4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath l7za_path = 4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CommandLine::ForCurrentProcess()->GetSwitchValuePath( 4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &kSwitch7zaPath[0]); 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (l7za_path.empty()) { 4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath dir_exe; 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!PathService::Get(base::DIR_EXE, &dir_exe)) 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Failed getting directory of host executable"; 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l7za_path = dir_exe.Append(&k7zaPathRelative[0]); 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return l7za_path; 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool CreateArchive(const base::FilePath& output_file, 4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& input_path, 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int compression_level) { 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(compression_level == 0 || 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) compression_level >= 1 && compression_level <= 9 && 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (compression_level & 0x01) != 0); 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring command_line(1, L'"'); 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command_line 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(Get7zaPath().Append(&k7zaExe[0]).value()) 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(L"\" a -bd -t7z \"") 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(output_file.value()) 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(L"\" \"") 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(input_path.value()) 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(L"\" -mx") 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(1, L'0' + compression_level); 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int exit_code; 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!RunProcessAndWait(NULL, command_line, &exit_code)) 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (exit_code != 0) { 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << Get7zaPath().Append(&k7zaExe[0]).value() 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " exited with code " << exit_code 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " while creating " << output_file.value(); 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace upgrade_test { 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GenerateAlternateVersion(const base::FilePath& original_installer_path, 5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& target_path, 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Direction direction, 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring* original_version, 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring* new_version) { 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a temporary directory in which we'll do our work. 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedTempDirectory work_dir; 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!work_dir.Initialize()) 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Copy the original mini_installer. 5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath mini_installer = 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) work_dir.directory().Append(original_installer_path.BaseName()); 5287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!base::CopyFile(original_installer_path, mini_installer)) { 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Failed copying \"" << original_installer_path.value() 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "\" to \"" << mini_installer.value() << "\""; 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath setup_ex_ = work_dir.directory().Append(&kSetupEx_[0]); 5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath chrome_packed_7z = 5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) work_dir.directory().Append(&kChromePacked7z[0]); 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Load the original file and extract setup.ex_ and chrome.packed.7z 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResourceLoader resource_loader; 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::pair<const uint8*, DWORD> resource_data; 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!resource_loader.Initialize(mini_installer)) 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Write out setup.ex_ 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!resource_loader.Load(&kSetupEx_[0], &kBl[0], &resource_data)) 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int written = 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_util::WriteFile(setup_ex_, 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const char*>(resource_data.first), 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(resource_data.second)); 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (written != resource_data.second) { 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Failed writing \"" << setup_ex_.value() << "\""; 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Write out chrome.packed.7z 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!resource_loader.Load(&kChromePacked7z[0], &kB7[0], &resource_data)) 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) written = 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_util::WriteFile(chrome_packed_7z, 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const char*>(resource_data.first), 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(resource_data.second)); 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (written != resource_data.second) { 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Failed writing \"" << chrome_packed_7z.value() << "\""; 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Expand setup.ex_ 5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath setup_exe = setup_ex_.ReplaceExtension(&kExe[0]); 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring command_line; 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command_line.append(1, L'"') 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(&kExpandExe[0]) 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(L"\" \"") 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(setup_ex_.value()) 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(L"\" \"") 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(setup_exe.value()) 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(1, L'\"'); 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int exit_code; 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!RunProcessAndWait(NULL, command_line, &exit_code)) 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (exit_code != 0) { 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << &kExpandExe[0] << " exited with code " << exit_code; 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unpack chrome.packed.7z 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring chrome_7z_name; 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (LzmaUtil::UnPackArchive(chrome_packed_7z.value(), 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) work_dir.directory().value(), 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &chrome_7z_name) != NO_ERROR) { 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Failed unpacking \"" << chrome_packed_7z.value() << "\""; 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unpack chrome.7z 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (LzmaUtil::UnPackArchive(chrome_7z_name, work_dir.directory().value(), 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL) != NO_ERROR) { 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Failed unpacking \"" << chrome_7z_name << "\""; 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get rid of intermediate files 6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath chrome_7z(chrome_7z_name); 6067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!base::DeleteFile(chrome_7z, false) || 6077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch !base::DeleteFile(chrome_packed_7z, false) || 6087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch !base::DeleteFile(setup_ex_, false)) { 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Failed deleting intermediate files"; 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Increment the version in all files. 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ApplyAlternateVersion(work_dir.directory(), direction, original_version, 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_version); 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Pack up files into chrome.7z 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CreateArchive(chrome_7z, work_dir.directory().Append(&kChromeBin[0]), 0)) 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Compress chrome.7z into chrome.packed.7z 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CreateArchive(chrome_packed_7z, chrome_7z, 9)) 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Compress setup.exe into setup.ex_ 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command_line.assign(1, L'"') 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(&kMakeCab[0]) 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(L"\" /D CompressionType=LZX /L \"") 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(work_dir.directory().value()) 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(L"\" \"") 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .append(setup_exe.value()); 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!RunProcessAndWait(NULL, command_line, &exit_code)) 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (exit_code != 0) { 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << &kMakeCab[0] << " exited with code " << exit_code; 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Replace the mini_installer's setup.ex_ and chrome.packed.7z resources. 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResourceUpdater updater; 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!updater.Initialize(mini_installer) || 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !updater.Update(&kSetupEx_[0], &kBl[0], 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setup_ex_) || 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !updater.Update(&kChromePacked7z[0], &kB7[0], 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome_packed_7z) || 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !updater.Commit()) { 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Finally, move the updated mini_installer into place. 653eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return base::Move(mini_installer, target_path); 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GenerateAlternatePEFileVersion(const base::FilePath& original_file, 6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& target_file, 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Direction direction) { 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitResourceContext ctx; 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetFileVersion(original_file, &ctx.current_version)) { 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Failed reading version from \"" << original_file.value() 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "\""; 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ctx.current_version_str = ctx.current_version.ToString(); 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IncrementNewVersion(direction, &ctx)) { 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Failed to increment version from \"" 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << original_file.value() << "\""; 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Version new_version(WideToASCII(ctx.new_version_str)); 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GenerateSpecificPEFileVersion(original_file, target_file, new_version); 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GenerateSpecificPEFileVersion(const base::FilePath& original_file, 6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& target_file, 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Version& version) { 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First copy original_file to target_file. 6837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!base::CopyFile(original_file, target_file)) { 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Failed copying \"" << original_file.value() 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "\" to \"" << target_file.value() << "\""; 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitResourceContext ctx; 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetFileVersion(target_file, &ctx.current_version)) { 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Failed reading version from \"" << target_file.value() 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "\""; 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ctx.current_version_str = ctx.current_version.ToString(); 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ctx.new_version = ChromeVersion::FromString(version.GetString()); 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ctx.new_version_str = ctx.new_version.ToString(); 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return UpdateVersionIfMatch(target_file, &ctx); 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace upgrade_test 703