|
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 |