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,124 @@ |
+// 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 callback, uintptr_t context) { |
+ 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; |
+ } |
+ |
+ const IMAGE_RESOURCE_DIRECTORY_ENTRY* scan = |
+ reinterpret_cast<const IMAGE_RESOURCE_DIRECTORY_ENTRY*>( |
+ tree_base + directory_offset + |
+ sizeof(IMAGE_RESOURCE_DIRECTORY)); |
+ const IMAGE_RESOURCE_DIRECTORY_ENTRY* end = scan + |
+ resource_directory->NumberOfNamedEntries + |
+ resource_directory->NumberOfIdEntries; |
+ for (; 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, callback, |
+ 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. |
+ callback( |
+ 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 callback, |
+ 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(), callback, context); |
+ } |
+ return true; |
+} |
+ |
+} // namespace upgrade_test |
Property changes on: chrome\installer\test\pe_image_resources.cc |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |