OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // The file contains the implementation of the mini_installer re-versioner. | 5 // The file contains the implementation of the mini_installer re-versioner. |
6 // The main function (GenerateNextVersion) does the following in a temp dir: | 6 // The main function (GenerateNextVersion) does the following in a temp dir: |
7 // - Extracts and unpacks setup.exe and the Chrome-bin folder from | 7 // - Extracts and unpacks setup.exe and the Chrome-bin folder from |
8 // mini_installer.exe. | 8 // mini_installer.exe. |
9 // - Inspects setup.exe to determine the current version. | 9 // - Inspects setup.exe to determine the current version. |
10 // - Runs through all .dll and .exe files: | 10 // - Runs through all .dll and .exe files: |
11 // - Replacing all occurrences of the Unicode version string in the files' | 11 // - Replacing all occurrences of the Unicode version string in the files' |
12 // resources with the updated string. | 12 // resources with the updated string. |
13 // - For all resources in which the string substitution is made, the binary | 13 // - For all resources in which the string substitution is made, the binary |
14 // form of the version is also replaced. | 14 // form of the version is also replaced. |
15 // - Re-packs setup.exe and Chrome-bin. | 15 // - Re-packs setup.exe and Chrome-bin. |
16 // - Inserts them into the target mini_installer.exe. | 16 // - Inserts them into the target mini_installer.exe. |
17 // | 17 // |
18 // This code assumes that the host program 1) initializes the process-wide | 18 // This code assumes that the host program 1) initializes the process-wide |
19 // CommandLine instance, and 2) resides in the output directory of a build | 19 // CommandLine instance, and 2) resides in the output directory of a build |
20 // tree. When #2 is not the case, the --7za_path command-line switch may be | 20 // tree. When #2 is not the case, the --7za_path command-line switch may be |
21 // used to provide the (relative or absolute) path to the directory containing | 21 // used to provide the (relative or absolute) path to the directory containing |
22 // 7za.exe. | 22 // 7za.exe. |
23 | 23 |
24 #include "chrome/installer/test/alternate_version_generator.h" | 24 #include "chrome/installer/test/alternate_version_generator.h" |
25 | 25 |
26 #include <windows.h> | 26 #include <windows.h> |
| 27 #include <stddef.h> |
| 28 #include <stdint.h> |
27 | 29 |
28 #include <algorithm> | 30 #include <algorithm> |
29 #include <limits> | 31 #include <limits> |
30 #include <sstream> | 32 #include <sstream> |
31 #include <utility> | 33 #include <utility> |
32 #include <vector> | 34 #include <vector> |
33 | 35 |
34 #include "base/basictypes.h" | |
35 #include "base/command_line.h" | 36 #include "base/command_line.h" |
36 #include "base/files/file.h" | 37 #include "base/files/file.h" |
37 #include "base/files/file_enumerator.h" | 38 #include "base/files/file_enumerator.h" |
38 #include "base/files/file_path.h" | 39 #include "base/files/file_path.h" |
39 #include "base/files/file_util.h" | 40 #include "base/files/file_util.h" |
40 #include "base/logging.h" | 41 #include "base/logging.h" |
| 42 #include "base/macros.h" |
41 #include "base/path_service.h" | 43 #include "base/path_service.h" |
42 #include "base/process/launch.h" | 44 #include "base/process/launch.h" |
43 #include "base/process/process_handle.h" | 45 #include "base/process/process_handle.h" |
44 #include "base/strings/string_util.h" | 46 #include "base/strings/string_util.h" |
45 #include "base/strings/utf_string_conversions.h" | 47 #include "base/strings/utf_string_conversions.h" |
46 #include "base/version.h" | 48 #include "base/version.h" |
47 #include "base/win/pe_image.h" | 49 #include "base/win/pe_image.h" |
48 #include "base/win/scoped_handle.h" | 50 #include "base/win/scoped_handle.h" |
49 #include "chrome/installer/test/pe_image_resources.h" | 51 #include "chrome/installer/test/pe_image_resources.h" |
50 #include "chrome/installer/test/resource_loader.h" | 52 #include "chrome/installer/test/resource_loader.h" |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 } | 178 } |
177 } | 179 } |
178 | 180 |
179 bool MappedFile::Initialize(base::File file) { | 181 bool MappedFile::Initialize(base::File file) { |
180 DCHECK(mapping_ == NULL); | 182 DCHECK(mapping_ == NULL); |
181 bool result = false; | 183 bool result = false; |
182 base::File::Info file_info; | 184 base::File::Info file_info; |
183 | 185 |
184 if (file.GetInfo(&file_info)) { | 186 if (file.GetInfo(&file_info)) { |
185 if (file_info.size <= | 187 if (file_info.size <= |
186 static_cast<int64>(std::numeric_limits<DWORD>::max())) { | 188 static_cast<int64_t>(std::numeric_limits<DWORD>::max())) { |
187 mapping_ = CreateFileMapping(file.GetPlatformFile(), NULL, PAGE_READWRITE, | 189 mapping_ = CreateFileMapping(file.GetPlatformFile(), NULL, PAGE_READWRITE, |
188 0, static_cast<DWORD>(file_info.size), NULL); | 190 0, static_cast<DWORD>(file_info.size), NULL); |
189 if (mapping_ != NULL) { | 191 if (mapping_ != NULL) { |
190 view_ = MapViewOfFile(mapping_, FILE_MAP_WRITE, 0, 0, | 192 view_ = MapViewOfFile(mapping_, FILE_MAP_WRITE, 0, 0, |
191 static_cast<size_t>(file_info.size)); | 193 static_cast<size_t>(file_info.size)); |
192 if (view_ != NULL) { | 194 if (view_ != NULL) { |
193 result = true; | 195 result = true; |
194 } else { | 196 } else { |
195 PLOG(DFATAL) << "MapViewOfFile failed"; | 197 PLOG(DFATAL) << "MapViewOfFile failed"; |
196 } | 198 } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
234 | 236 |
235 return result; | 237 return result; |
236 } | 238 } |
237 | 239 |
238 // Retrieves the version number of |pe_file| from its version | 240 // Retrieves the version number of |pe_file| from its version |
239 // resource, placing the value in |version|. Returns true on success. | 241 // resource, placing the value in |version|. Returns true on success. |
240 bool GetFileVersion(const base::FilePath& pe_file, ChromeVersion* version) { | 242 bool GetFileVersion(const base::FilePath& pe_file, ChromeVersion* version) { |
241 DCHECK(version); | 243 DCHECK(version); |
242 bool result = false; | 244 bool result = false; |
243 upgrade_test::ResourceLoader pe_file_loader; | 245 upgrade_test::ResourceLoader pe_file_loader; |
244 std::pair<const uint8*, DWORD> version_info_data; | 246 std::pair<const uint8_t*, DWORD> version_info_data; |
245 | 247 |
246 if (pe_file_loader.Initialize(pe_file) && | 248 if (pe_file_loader.Initialize(pe_file) && |
247 pe_file_loader.Load( | 249 pe_file_loader.Load( |
248 VS_VERSION_INFO, | 250 VS_VERSION_INFO, |
249 static_cast<WORD>(reinterpret_cast<uintptr_t>(RT_VERSION)), | 251 static_cast<WORD>(reinterpret_cast<uintptr_t>(RT_VERSION)), |
250 &version_info_data)) { | 252 &version_info_data)) { |
251 const VS_FIXEDFILEINFO* fixed_file_info; | 253 const VS_FIXEDFILEINFO* fixed_file_info; |
252 UINT ver_info_len; | 254 UINT ver_info_len; |
253 if (VerQueryValue(version_info_data.first, L"\\", | 255 if (VerQueryValue(version_info_data.first, L"\\", |
254 reinterpret_cast<void**>( | 256 reinterpret_cast<void**>( |
(...skipping 16 matching lines...) Expand all Loading... |
271 bool GetSetupExeVersion(const base::FilePath& work_dir, | 273 bool GetSetupExeVersion(const base::FilePath& work_dir, |
272 ChromeVersion* version) { | 274 ChromeVersion* version) { |
273 return GetFileVersion(work_dir.Append(&kSetupExe[0]), version); | 275 return GetFileVersion(work_dir.Append(&kSetupExe[0]), version); |
274 } | 276 } |
275 | 277 |
276 | 278 |
277 // Replace all occurrences in the sequence [|dest_first|, |dest_last) that | 279 // Replace all occurrences in the sequence [|dest_first|, |dest_last) that |
278 // equals [|src_first|, |src_last) with the sequence at |replacement_first| of | 280 // equals [|src_first|, |src_last) with the sequence at |replacement_first| of |
279 // the same length. Returns true on success. If non-NULL, |replacements_made| | 281 // the same length. Returns true on success. If non-NULL, |replacements_made| |
280 // is set to true/false accordingly. | 282 // is set to true/false accordingly. |
281 bool ReplaceAll(uint8* dest_first, uint8* dest_last, | 283 bool ReplaceAll(uint8_t* dest_first, |
282 const uint8* src_first, const uint8* src_last, | 284 uint8_t* dest_last, |
283 const uint8* replacement_first, bool* replacements_made) { | 285 const uint8_t* src_first, |
| 286 const uint8_t* src_last, |
| 287 const uint8_t* replacement_first, |
| 288 bool* replacements_made) { |
284 bool result = true; | 289 bool result = true; |
285 bool changed = false; | 290 bool changed = false; |
286 do { | 291 do { |
287 dest_first = std::search(dest_first, dest_last, src_first, src_last); | 292 dest_first = std::search(dest_first, dest_last, src_first, src_last); |
288 if (dest_first == dest_last) { | 293 if (dest_first == dest_last) { |
289 break; | 294 break; |
290 } | 295 } |
291 changed = true; | 296 changed = true; |
292 if (memcpy_s(dest_first, dest_last - dest_first, | 297 if (memcpy_s(dest_first, dest_last - dest_first, |
293 replacement_first, src_last - src_first) != 0) { | 298 replacement_first, src_last - src_first) != 0) { |
(...skipping 15 matching lines...) Expand all Loading... |
309 ChromeVersion current_version; | 314 ChromeVersion current_version; |
310 std::wstring current_version_str; | 315 std::wstring current_version_str; |
311 ChromeVersion new_version; | 316 ChromeVersion new_version; |
312 std::wstring new_version_str; | 317 std::wstring new_version_str; |
313 }; // struct VisitResourceContext | 318 }; // struct VisitResourceContext |
314 | 319 |
315 // Replaces the old version with the new in a resource. A first pass is made to | 320 // Replaces the old version with the new in a resource. A first pass is made to |
316 // replace the string form (e.g., "9.0.584.0"). If any replacements are made, a | 321 // replace the string form (e.g., "9.0.584.0"). If any replacements are made, a |
317 // second pass is made to replace the binary form (e.g., 0x0000024800000009). | 322 // second pass is made to replace the binary form (e.g., 0x0000024800000009). |
318 void VisitResource(const upgrade_test::EntryPath& path, | 323 void VisitResource(const upgrade_test::EntryPath& path, |
319 uint8* data, DWORD size, DWORD code_page, | 324 uint8_t* data, |
| 325 DWORD size, |
| 326 DWORD code_page, |
320 uintptr_t context) { | 327 uintptr_t context) { |
321 VisitResourceContext& ctx = *reinterpret_cast<VisitResourceContext*>(context); | 328 VisitResourceContext& ctx = *reinterpret_cast<VisitResourceContext*>(context); |
322 | 329 |
323 // Replace all occurrences of current_version_str with new_version_str | 330 // Replace all occurrences of current_version_str with new_version_str |
324 bool changing_version = false; | 331 bool changing_version = false; |
325 if (ReplaceAll( | 332 if (ReplaceAll( |
326 data, | 333 data, data + size, |
327 data + size, | 334 reinterpret_cast<const uint8_t*>(ctx.current_version_str.c_str()), |
328 reinterpret_cast<const uint8*>(ctx.current_version_str.c_str()), | 335 reinterpret_cast<const uint8_t*>(ctx.current_version_str.c_str() + |
329 reinterpret_cast<const uint8*>(ctx.current_version_str.c_str() + | 336 ctx.current_version_str.size() + 1), |
330 ctx.current_version_str.size() + 1), | 337 reinterpret_cast<const uint8_t*>(ctx.new_version_str.c_str()), |
331 reinterpret_cast<const uint8*>(ctx.new_version_str.c_str()), | |
332 &changing_version) && | 338 &changing_version) && |
333 changing_version) { | 339 changing_version) { |
334 // Replace all occurrences of current_version with new_version | 340 // Replace all occurrences of current_version with new_version |
335 struct VersionPair { | 341 struct VersionPair { |
336 DWORD high; | 342 DWORD high; |
337 DWORD low; | 343 DWORD low; |
338 }; | 344 }; |
339 VersionPair cur_ver = { | 345 VersionPair cur_ver = { |
340 ctx.current_version.high(), ctx.current_version.low() | 346 ctx.current_version.high(), ctx.current_version.low() |
341 }; | 347 }; |
342 VersionPair new_ver = { | 348 VersionPair new_ver = { |
343 ctx.new_version.high(), ctx.new_version.low() | 349 ctx.new_version.high(), ctx.new_version.low() |
344 }; | 350 }; |
345 ReplaceAll(data, data + size, reinterpret_cast<const uint8*>(&cur_ver), | 351 ReplaceAll(data, data + size, reinterpret_cast<const uint8_t*>(&cur_ver), |
346 reinterpret_cast<const uint8*>(&cur_ver) + sizeof(cur_ver), | 352 reinterpret_cast<const uint8_t*>(&cur_ver) + sizeof(cur_ver), |
347 reinterpret_cast<const uint8*>(&new_ver), NULL); | 353 reinterpret_cast<const uint8_t*>(&new_ver), NULL); |
348 } | 354 } |
349 } | 355 } |
350 | 356 |
351 // Updates the version strings and numbers in all of |image_file|'s resources. | 357 // Updates the version strings and numbers in all of |image_file|'s resources. |
352 bool UpdateVersionIfMatch(const base::FilePath& image_file, | 358 bool UpdateVersionIfMatch(const base::FilePath& image_file, |
353 VisitResourceContext* context) { | 359 VisitResourceContext* context) { |
354 if (!context || | 360 if (!context || |
355 context->current_version_str.size() < context->new_version_str.size()) { | 361 context->current_version_str.size() < context->new_version_str.size()) { |
356 return false; | 362 return false; |
357 } | 363 } |
358 | 364 |
359 bool result = false; | 365 bool result = false; |
360 uint32 flags = base::File::FLAG_OPEN | base::File::FLAG_READ | | 366 uint32_t flags = base::File::FLAG_OPEN | base::File::FLAG_READ | |
361 base::File::FLAG_WRITE | base::File::FLAG_EXCLUSIVE_READ | | 367 base::File::FLAG_WRITE | base::File::FLAG_EXCLUSIVE_READ | |
362 base::File::FLAG_EXCLUSIVE_WRITE; | 368 base::File::FLAG_EXCLUSIVE_WRITE; |
363 base::File file(image_file, flags); | 369 base::File file(image_file, flags); |
364 // It turns out that the underlying CreateFile can fail due to unhelpful | 370 // It turns out that the underlying CreateFile can fail due to unhelpful |
365 // security software locking the newly created DLL. So add a few brief | 371 // security software locking the newly created DLL. So add a few brief |
366 // retries to help tests that use this pass on machines thusly encumbered. | 372 // retries to help tests that use this pass on machines thusly encumbered. |
367 int retries = 3; | 373 int retries = 3; |
368 while (!file.IsValid() && retries-- > 0) { | 374 while (!file.IsValid() && retries-- > 0) { |
369 LOG(WARNING) << "Failed to open \"" << image_file.value() << "\"." | 375 LOG(WARNING) << "Failed to open \"" << image_file.value() << "\"." |
370 << " Retrying " << retries << " more times."; | 376 << " Retrying " << retries << " more times."; |
371 Sleep(1000); | 377 Sleep(1000); |
372 file.Initialize(image_file, flags); | 378 file.Initialize(image_file, flags); |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
529 << "\" to \"" << mini_installer.value() << "\""; | 535 << "\" to \"" << mini_installer.value() << "\""; |
530 return false; | 536 return false; |
531 } | 537 } |
532 | 538 |
533 base::FilePath setup_ex_ = work_dir.directory().Append(&kSetupEx_[0]); | 539 base::FilePath setup_ex_ = work_dir.directory().Append(&kSetupEx_[0]); |
534 base::FilePath chrome_packed_7z = | 540 base::FilePath chrome_packed_7z = |
535 work_dir.directory().Append(&kChromePacked7z[0]); | 541 work_dir.directory().Append(&kChromePacked7z[0]); |
536 // Load the original file and extract setup.ex_ and chrome.packed.7z | 542 // Load the original file and extract setup.ex_ and chrome.packed.7z |
537 { | 543 { |
538 ResourceLoader resource_loader; | 544 ResourceLoader resource_loader; |
539 std::pair<const uint8*, DWORD> resource_data; | 545 std::pair<const uint8_t*, DWORD> resource_data; |
540 | 546 |
541 if (!resource_loader.Initialize(mini_installer)) | 547 if (!resource_loader.Initialize(mini_installer)) |
542 return false; | 548 return false; |
543 | 549 |
544 // Write out setup.ex_ | 550 // Write out setup.ex_ |
545 if (!resource_loader.Load(&kSetupEx_[0], &kBl[0], &resource_data)) | 551 if (!resource_loader.Load(&kSetupEx_[0], &kBl[0], &resource_data)) |
546 return false; | 552 return false; |
547 int written = | 553 int written = |
548 base::WriteFile(setup_ex_, | 554 base::WriteFile(setup_ex_, |
549 reinterpret_cast<const char*>(resource_data.first), | 555 reinterpret_cast<const char*>(resource_data.first), |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
692 return false; | 698 return false; |
693 } | 699 } |
694 ctx.current_version_str = ctx.current_version.ToString(); | 700 ctx.current_version_str = ctx.current_version.ToString(); |
695 ctx.new_version = ChromeVersion::FromString(version.GetString()); | 701 ctx.new_version = ChromeVersion::FromString(version.GetString()); |
696 ctx.new_version_str = ctx.new_version.ToString(); | 702 ctx.new_version_str = ctx.new_version.ToString(); |
697 | 703 |
698 return UpdateVersionIfMatch(target_file, &ctx); | 704 return UpdateVersionIfMatch(target_file, &ctx); |
699 } | 705 } |
700 | 706 |
701 } // namespace upgrade_test | 707 } // namespace upgrade_test |
OLD | NEW |