Chromium Code Reviews
|
| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 // This file contains the implementation for an iterator over a portable | |
| 6 // executable file's resources. | |
| 7 | |
| 8 #include "chrome/installer/test/pe_image_resources.h" | |
| 9 | |
| 10 #include "base/logging.h" | |
| 11 #include "base/win/pe_image.h" | |
| 12 | |
| 13 namespace { | |
| 14 | |
| 15 // Performs a cast to type |T| of |data| iff |data_size| is sufficient to hold | |
| 16 // an instance of type |T|. Returns true on success. | |
| 17 template<class T> | |
| 18 bool StructureAt(const uint8* data, size_t data_size, const T** structure) { | |
| 19 if (sizeof(T) <= data_size) { | |
| 20 *structure = reinterpret_cast<const T*>(data); | |
| 21 return true; | |
| 22 } | |
| 23 return false; | |
| 24 } | |
| 25 | |
| 26 // Recursive function for enumerating entries in an image's resource segment. | |
| 27 // static | |
| 28 bool EnumResourcesWorker( | |
| 29 const base::win::PEImage& image, const uint8* tree_base, DWORD tree_size, | |
| 30 DWORD directory_offset, upgrade_test::EntryPath &path, | |
| 31 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.
| |
| 32 bool success = true; | |
| 33 const IMAGE_RESOURCE_DIRECTORY* resource_directory; | |
| 34 | |
| 35 if (!StructureAt(tree_base + directory_offset, tree_size - directory_offset, | |
| 36 &resource_directory) || | |
| 37 directory_offset + sizeof(IMAGE_RESOURCE_DIRECTORY) + | |
| 38 (resource_directory->NumberOfNamedEntries + | |
| 39 resource_directory->NumberOfIdEntries) * | |
| 40 sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY) > tree_size) { | |
| 41 LOG(DFATAL) << "Insufficient room in resource segment for directory entry."; | |
| 42 return false; | |
| 43 } | |
| 44 | |
| 45 for (const IMAGE_RESOURCE_DIRECTORY_ENTRY* scan = | |
| 46 reinterpret_cast<const IMAGE_RESOURCE_DIRECTORY_ENTRY*>( | |
| 47 tree_base + directory_offset + | |
| 48 sizeof(IMAGE_RESOURCE_DIRECTORY)), | |
| 49 *end = scan + resource_directory->NumberOfNamedEntries + | |
| 50 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.
| |
| 51 success && scan != end; ++scan) { | |
| 52 if ((scan->NameIsString != 0) != | |
| 53 (scan - reinterpret_cast<const IMAGE_RESOURCE_DIRECTORY_ENTRY*>( | |
| 54 tree_base + directory_offset + | |
| 55 sizeof(IMAGE_RESOURCE_DIRECTORY)) < | |
| 56 resource_directory->NumberOfNamedEntries)) { | |
| 57 LOG(DFATAL) << "Inconsistent number of named or numbered entries."; | |
| 58 success = false; | |
| 59 break; | |
| 60 } | |
| 61 if (scan->NameIsString) { | |
| 62 const IMAGE_RESOURCE_DIR_STRING_U* dir_string; | |
| 63 if (!StructureAt(tree_base + scan->NameOffset, | |
| 64 tree_size - scan->NameOffset, &dir_string) || | |
| 65 scan->NameOffset + sizeof(WORD) + | |
| 66 dir_string->Length * sizeof(wchar_t) > tree_size) { | |
| 67 LOG(DFATAL) << "Insufficient room in resource segment for entry name."; | |
| 68 success = false; | |
| 69 break; | |
| 70 } | |
| 71 path.push_back( | |
| 72 upgrade_test::EntryId(std::wstring(&dir_string->NameString[0], | |
| 73 dir_string->Length))); | |
| 74 } else { | |
| 75 path.push_back(upgrade_test::EntryId(scan->Id)); | |
| 76 } | |
| 77 if (scan->DataIsDirectory) { | |
| 78 success = EnumResourcesWorker(image, tree_base, tree_size, | |
| 79 scan->OffsetToDirectory, path, function, | |
| 80 context); | |
| 81 } else { | |
| 82 const IMAGE_RESOURCE_DATA_ENTRY* data_entry; | |
| 83 if (StructureAt(tree_base + scan->OffsetToData, | |
| 84 tree_size - scan->OffsetToData, &data_entry) && | |
| 85 reinterpret_cast<uint8*>( | |
| 86 image.RVAToAddr(data_entry->OffsetToData)) + data_entry->Size <= | |
| 87 tree_base + tree_size) { | |
| 88 // Despite what winnt.h says, OffsetToData is an RVA. | |
| 89 function( | |
| 90 path, | |
| 91 reinterpret_cast<uint8*>(image.RVAToAddr(data_entry->OffsetToData)), | |
| 92 data_entry->Size, data_entry->CodePage, context); | |
| 93 } else { | |
| 94 LOG(DFATAL) << "Insufficient room in resource segment for data entry."; | |
| 95 success = false; | |
| 96 } | |
| 97 } | |
| 98 path.pop_back(); | |
| 99 } | |
| 100 | |
| 101 return success; | |
| 102 } | |
| 103 | |
| 104 } // namespace | |
| 105 | |
| 106 namespace upgrade_test { | |
| 107 | |
| 108 // static | |
| 109 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.
| |
| 110 uintptr_t context) { | |
| 111 DWORD resources_size = | |
| 112 image.GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_RESOURCE); | |
| 113 if (resources_size != 0) { | |
| 114 return EnumResourcesWorker( | |
| 115 image, | |
| 116 reinterpret_cast<uint8*>( | |
| 117 image.GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_RESOURCE)), | |
| 118 resources_size, 0, EntryPath(), function, context); | |
| 119 } | |
| 120 return true; | |
| 121 } | |
| 122 | |
| 123 } // namespace upgrade_test | |
| OLD | NEW |