| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/app/image_pre_reader_win.h" | 5 #include "chrome/app/image_pre_reader_win.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 #include <algorithm> | 8 #include <algorithm> |
| 9 #include <limits> | 9 #include <limits> |
| 10 #include <vector> | 10 #include <vector> |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 220 if (!file.IsValid()) | 220 if (!file.IsValid()) |
| 221 return false; | 221 return false; |
| 222 | 222 |
| 223 // Allocate a resizable buffer for the headers. We initially reserve as much | 223 // Allocate a resizable buffer for the headers. We initially reserve as much |
| 224 // space as we typically see as the header size for chrome.dll and other | 224 // space as we typically see as the header size for chrome.dll and other |
| 225 // PE images. | 225 // PE images. |
| 226 std::vector<uint8> headers; | 226 std::vector<uint8> headers; |
| 227 headers.reserve(kMinHeaderBufferSize); | 227 headers.reserve(kMinHeaderBufferSize); |
| 228 | 228 |
| 229 // Read, hopefully, all of the headers. | 229 // Read, hopefully, all of the headers. |
| 230 if (!ReadMissingBytes(file, &headers, kMinHeaderBufferSize)) | 230 if (!ReadMissingBytes(file.Get(), &headers, kMinHeaderBufferSize)) |
| 231 return false; | 231 return false; |
| 232 | 232 |
| 233 // The DOS header starts at offset 0 and allows us to get the offset of the | 233 // The DOS header starts at offset 0 and allows us to get the offset of the |
| 234 // NT headers. Let's ensure we've read enough to capture the NT headers. | 234 // NT headers. Let's ensure we've read enough to capture the NT headers. |
| 235 size_t nt_headers_start = | 235 size_t nt_headers_start = |
| 236 reinterpret_cast<IMAGE_DOS_HEADER*>(&headers[0])->e_lfanew; | 236 reinterpret_cast<IMAGE_DOS_HEADER*>(&headers[0])->e_lfanew; |
| 237 size_t nt_headers_end = nt_headers_start + sizeof(IMAGE_NT_HEADERS); | 237 size_t nt_headers_end = nt_headers_start + sizeof(IMAGE_NT_HEADERS); |
| 238 if (!ReadMissingBytes(file, &headers, nt_headers_end)) | 238 if (!ReadMissingBytes(file.Get(), &headers, nt_headers_end)) |
| 239 return false; | 239 return false; |
| 240 | 240 |
| 241 // Now that we've got the NT headers we can get the total header size, | 241 // Now that we've got the NT headers we can get the total header size, |
| 242 // including all of the section headers. Let's ensure we've read enough | 242 // including all of the section headers. Let's ensure we've read enough |
| 243 // to capture all of the header data. | 243 // to capture all of the header data. |
| 244 size_t size_of_headers = reinterpret_cast<IMAGE_NT_HEADERS*>( | 244 size_t size_of_headers = reinterpret_cast<IMAGE_NT_HEADERS*>( |
| 245 &headers[nt_headers_start])->OptionalHeader.SizeOfHeaders; | 245 &headers[nt_headers_start])->OptionalHeader.SizeOfHeaders; |
| 246 if (!ReadMissingBytes(file, &headers, size_of_headers)) | 246 if (!ReadMissingBytes(file.Get(), &headers, size_of_headers)) |
| 247 return false; | 247 return false; |
| 248 | 248 |
| 249 // Now we have all of the headers. This is enough to let us use the PEImage | 249 // Now we have all of the headers. This is enough to let us use the PEImage |
| 250 // wrapper to query the structure of the image. | 250 // wrapper to query the structure of the image. |
| 251 base::win::PEImage pe_image(reinterpret_cast<HMODULE>(&headers[0])); | 251 base::win::PEImage pe_image(reinterpret_cast<HMODULE>(&headers[0])); |
| 252 CHECK(pe_image.VerifyMagic()); | 252 CHECK(pe_image.VerifyMagic()); |
| 253 | 253 |
| 254 // Allocate a buffer to hold the pre-read bytes. | 254 // Allocate a buffer to hold the pre-read bytes. |
| 255 scoped_ptr<uint8, VirtualFreeDeleter> buffer( | 255 scoped_ptr<uint8, VirtualFreeDeleter> buffer( |
| 256 static_cast<uint8*>( | 256 static_cast<uint8*>( |
| 257 ::VirtualAlloc(NULL, max_chunk_size, MEM_COMMIT, PAGE_READWRITE))); | 257 ::VirtualAlloc(NULL, max_chunk_size, MEM_COMMIT, PAGE_READWRITE))); |
| 258 if (buffer.get() == NULL) | 258 if (buffer.get() == NULL) |
| 259 return false; | 259 return false; |
| 260 | 260 |
| 261 // Iterate over each section, reading in a percentage of each. | 261 // Iterate over each section, reading in a percentage of each. |
| 262 const IMAGE_SECTION_HEADER* section = NULL; | 262 const IMAGE_SECTION_HEADER* section = NULL; |
| 263 for (UINT i = 0; (section = pe_image.GetSectionHeader(i)) != NULL; ++i) { | 263 for (UINT i = 0; (section = pe_image.GetSectionHeader(i)) != NULL; ++i) { |
| 264 CHECK_LE(reinterpret_cast<const uint8*>(section + 1), | 264 CHECK_LE(reinterpret_cast<const uint8*>(section + 1), |
| 265 &headers[0] + headers.size()); | 265 &headers[0] + headers.size()); |
| 266 if (!ReadThroughSection( | 266 if (!ReadThroughSection(file.Get(), section, percentage, buffer.get(), |
| 267 file, section, percentage, buffer.get(), max_chunk_size)) | 267 max_chunk_size)) { |
| 268 return false; | 268 return false; |
| 269 } |
| 269 } | 270 } |
| 270 | 271 |
| 271 // We're done. | 272 // We're done. |
| 272 return true; | 273 return true; |
| 273 } | 274 } |
| 274 | 275 |
| 275 bool ImagePreReader::PartialPreReadImageInMemory(const wchar_t* file_path, | 276 bool ImagePreReader::PartialPreReadImageInMemory(const wchar_t* file_path, |
| 276 size_t percentage) { | 277 size_t percentage) { |
| 277 // TODO(rogerm): change this to have the number of bytes pre-read per | 278 // TODO(rogerm): change this to have the number of bytes pre-read per |
| 278 // section be driven by a static table within the PE file (defaulting to | 279 // section be driven by a static table within the PE file (defaulting to |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 350 LPVOID buffer = ::VirtualAlloc(NULL, | 351 LPVOID buffer = ::VirtualAlloc(NULL, |
| 351 actual_step_size, | 352 actual_step_size, |
| 352 MEM_COMMIT, | 353 MEM_COMMIT, |
| 353 PAGE_READWRITE); | 354 PAGE_READWRITE); |
| 354 | 355 |
| 355 if (buffer == NULL) | 356 if (buffer == NULL) |
| 356 return false; | 357 return false; |
| 357 | 358 |
| 358 DWORD len; | 359 DWORD len; |
| 359 size_t total_read = 0; | 360 size_t total_read = 0; |
| 360 while (::ReadFile(file, buffer, actual_step_size, &len, NULL) && | 361 while (::ReadFile(file.Get(), buffer, actual_step_size, &len, NULL) && |
| 361 len > 0 && | 362 len > 0 && |
| 362 (size_to_read ? total_read < size_to_read : true)) { | 363 (size_to_read ? total_read < size_to_read : true)) { |
| 363 total_read += static_cast<size_t>(len); | 364 total_read += static_cast<size_t>(len); |
| 364 } | 365 } |
| 365 ::VirtualFree(buffer, 0, MEM_RELEASE); | 366 ::VirtualFree(buffer, 0, MEM_RELEASE); |
| 366 } else { | 367 } else { |
| 367 // WinXP branch. Here, reading the DLL from disk doesn't do | 368 // WinXP branch. Here, reading the DLL from disk doesn't do |
| 368 // what we want so instead we pull the pages into memory by loading | 369 // what we want so instead we pull the pages into memory by loading |
| 369 // the DLL and touching pages at a stride. We use the system's page | 370 // the DLL and touching pages at a stride. We use the system's page |
| 370 // size as the stride, ignoring the passed in step_size, to make sure | 371 // size as the stride, ignoring the passed in step_size, to make sure |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 411 // Vista+ branch. On these OSes, we warm up the Image by reading its | 412 // Vista+ branch. On these OSes, we warm up the Image by reading its |
| 412 // file off the disk. | 413 // file off the disk. |
| 413 return PartialPreReadImageOnDisk(file_path, percentage, max_chunk_size); | 414 return PartialPreReadImageOnDisk(file_path, percentage, max_chunk_size); |
| 414 } | 415 } |
| 415 | 416 |
| 416 // WinXP branch. For XP, reading the image from disk doesn't do what we want | 417 // WinXP branch. For XP, reading the image from disk doesn't do what we want |
| 417 // so instead we pull the pages into memory by loading the DLL and touching | 418 // so instead we pull the pages into memory by loading the DLL and touching |
| 418 // initialized pages at a stride. | 419 // initialized pages at a stride. |
| 419 return PartialPreReadImageInMemory(file_path, percentage); | 420 return PartialPreReadImageInMemory(file_path, percentage); |
| 420 } | 421 } |
| OLD | NEW |