Chromium Code Reviews| Index: chrome/installer/test/pe_image_resources.cc |
| =================================================================== |
| --- chrome/installer/test/pe_image_resources.cc (revision 0) |
| +++ chrome/installer/test/pe_image_resources.cc (revision 0) |
| @@ -0,0 +1,123 @@ |
| +// Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +// This file contains the implementation for an iterator over a portable |
| +// executable file's resources. |
| + |
| +#include "chrome/installer/test/pe_image_resources.h" |
| + |
| +#include "base/logging.h" |
| +#include "base/win/pe_image.h" |
| + |
| +namespace { |
| + |
| +// Performs a cast to type |T| of |data| iff |data_size| is sufficient to hold |
| +// an instance of type |T|. Returns true on success. |
| +template<class T> |
| +bool StructureAt(const uint8* data, size_t data_size, const T** structure) { |
| + if (sizeof(T) <= data_size) { |
| + *structure = reinterpret_cast<const T*>(data); |
| + return true; |
| + } |
| + return false; |
| +} |
| + |
| +// Recursive function for enumerating entries in an image's resource segment. |
| +// static |
| +bool EnumResourcesWorker( |
| + const base::win::PEImage& image, const uint8* tree_base, DWORD tree_size, |
| + DWORD directory_offset, upgrade_test::EntryPath &path, |
| + upgrade_test::EnumResource_Fn function, uintptr_t context) { |
|
tommi (sloooow) - chröme
2010/11/19 20:14:38
function -> callback
grt (UTC plus 2)
2010/11/22 17:53:29
Done.
|
| + bool success = true; |
| + const IMAGE_RESOURCE_DIRECTORY* resource_directory; |
| + |
| + if (!StructureAt(tree_base + directory_offset, tree_size - directory_offset, |
| + &resource_directory) || |
| + directory_offset + sizeof(IMAGE_RESOURCE_DIRECTORY) + |
| + (resource_directory->NumberOfNamedEntries + |
| + resource_directory->NumberOfIdEntries) * |
| + sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY) > tree_size) { |
| + LOG(DFATAL) << "Insufficient room in resource segment for directory entry."; |
| + return false; |
| + } |
| + |
| + for (const IMAGE_RESOURCE_DIRECTORY_ENTRY* scan = |
| + reinterpret_cast<const IMAGE_RESOURCE_DIRECTORY_ENTRY*>( |
| + tree_base + directory_offset + |
| + sizeof(IMAGE_RESOURCE_DIRECTORY)), |
| + *end = scan + resource_directory->NumberOfNamedEntries + |
| + resource_directory->NumberOfIdEntries; |
|
tommi (sloooow) - chröme
2010/11/19 20:14:38
that's a pretty big initialization of scan and end
grt (UTC plus 2)
2010/11/22 17:53:29
Done.
|
| + success && scan != end; ++scan) { |
| + if ((scan->NameIsString != 0) != |
| + (scan - reinterpret_cast<const IMAGE_RESOURCE_DIRECTORY_ENTRY*>( |
| + tree_base + directory_offset + |
| + sizeof(IMAGE_RESOURCE_DIRECTORY)) < |
| + resource_directory->NumberOfNamedEntries)) { |
| + LOG(DFATAL) << "Inconsistent number of named or numbered entries."; |
| + success = false; |
| + break; |
| + } |
| + if (scan->NameIsString) { |
| + const IMAGE_RESOURCE_DIR_STRING_U* dir_string; |
| + if (!StructureAt(tree_base + scan->NameOffset, |
| + tree_size - scan->NameOffset, &dir_string) || |
| + scan->NameOffset + sizeof(WORD) + |
| + dir_string->Length * sizeof(wchar_t) > tree_size) { |
| + LOG(DFATAL) << "Insufficient room in resource segment for entry name."; |
| + success = false; |
| + break; |
| + } |
| + path.push_back( |
| + upgrade_test::EntryId(std::wstring(&dir_string->NameString[0], |
| + dir_string->Length))); |
| + } else { |
| + path.push_back(upgrade_test::EntryId(scan->Id)); |
| + } |
| + if (scan->DataIsDirectory) { |
| + success = EnumResourcesWorker(image, tree_base, tree_size, |
| + scan->OffsetToDirectory, path, function, |
| + context); |
| + } else { |
| + const IMAGE_RESOURCE_DATA_ENTRY* data_entry; |
| + if (StructureAt(tree_base + scan->OffsetToData, |
| + tree_size - scan->OffsetToData, &data_entry) && |
| + reinterpret_cast<uint8*>( |
| + image.RVAToAddr(data_entry->OffsetToData)) + data_entry->Size <= |
| + tree_base + tree_size) { |
| + // Despite what winnt.h says, OffsetToData is an RVA. |
| + function( |
| + path, |
| + reinterpret_cast<uint8*>(image.RVAToAddr(data_entry->OffsetToData)), |
| + data_entry->Size, data_entry->CodePage, context); |
| + } else { |
| + LOG(DFATAL) << "Insufficient room in resource segment for data entry."; |
| + success = false; |
| + } |
| + } |
| + path.pop_back(); |
| + } |
| + |
| + return success; |
| +} |
| + |
| +} // namespace |
| + |
| +namespace upgrade_test { |
| + |
| +// static |
| +bool EnumResources(const base::win::PEImage& image, EnumResource_Fn function, |
|
tommi (sloooow) - chröme
2010/11/19 20:14:38
function -> callback
grt (UTC plus 2)
2010/11/22 17:53:29
Done.
|
| + uintptr_t context) { |
| + DWORD resources_size = |
| + image.GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_RESOURCE); |
| + if (resources_size != 0) { |
| + return EnumResourcesWorker( |
| + image, |
| + reinterpret_cast<uint8*>( |
| + image.GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_RESOURCE)), |
| + resources_size, 0, EntryPath(), function, context); |
| + } |
| + return true; |
| +} |
| + |
| +} // namespace upgrade_test |
| Property changes on: chrome\installer\test\pe_image_resources.cc |
| ___________________________________________________________________ |
| Added: svn:eol-style |
| + LF |