1731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This file implements PEImage, a generic class to manipulate PE files.
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This file was adapted from GreenBorder's Code.
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
8731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/win/pe_image.h"
9731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
10731df977c0511bca2206b5f333555b1205ff1f43Iain Merricknamespace base {
11731df977c0511bca2206b5f333555b1205ff1f43Iain Merricknamespace win {
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(_WIN64) && !defined(NACL_WIN64)
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TODO(rvargas): Bug 27218. Make sure this is ok.
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#error This code is not tested on x64. Please make sure all the base unit tests\
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pass before doing any real work. The current unit tests don't test the\
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott differences between 32- and 64-bits implementations. Bugs may slip through.\
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott You need to improve the coverage before continuing.
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Structure to perform imports enumerations.
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstruct EnumAllImportsStorage {
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PEImage::EnumImportsFunction callback;
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PVOID cookie;
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Compare two strings byte by byte on an unsigned basis.
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //   if s1 == s2, return 0
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //   if s1 < s2, return negative
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //   if s1 > s2, return positive
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Exception if inputs are invalid.
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int StrCmpByByte(LPCSTR s1, LPCSTR s2) {
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    while (*s1 != '\0' && *s1 == *s2) {
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ++s1;
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ++s2;
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return (*reinterpret_cast<const unsigned char*>(s1) -
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            *reinterpret_cast<const unsigned char*>(s2));
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Callback used to enumerate imports. See EnumImportChunksFunction.
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool ProcessImportChunk(const PEImage &image, LPCSTR module,
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        PIMAGE_THUNK_DATA name_table,
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        PIMAGE_THUNK_DATA iat, PVOID cookie) {
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EnumAllImportsStorage &storage = *reinterpret_cast<EnumAllImportsStorage*>(
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                       cookie);
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return image.EnumOneImportChunk(storage.callback, module, name_table, iat,
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                  storage.cookie);
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Callback used to enumerate delay imports. See EnumDelayImportChunksFunction.
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool ProcessDelayImportChunk(const PEImage &image,
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                             PImgDelayDescr delay_descriptor,
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                             LPCSTR module, PIMAGE_THUNK_DATA name_table,
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                             PIMAGE_THUNK_DATA iat, PIMAGE_THUNK_DATA bound_iat,
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                             PIMAGE_THUNK_DATA unload_iat, PVOID cookie) {
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EnumAllImportsStorage &storage = *reinterpret_cast<EnumAllImportsStorage*>(
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                       cookie);
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return image.EnumOneDelayImportChunk(storage.callback, delay_descriptor,
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                       module, name_table, iat, bound_iat,
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                       unload_iat, storage.cookie);
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid PEImage::set_module(HMODULE module) {
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  module_ = module;
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottPIMAGE_DOS_HEADER PEImage::GetDosHeader() const {
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return reinterpret_cast<PIMAGE_DOS_HEADER>(module_);
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottPIMAGE_NT_HEADERS PEImage::GetNTHeaders() const {
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PIMAGE_DOS_HEADER dos_header = GetDosHeader();
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return reinterpret_cast<PIMAGE_NT_HEADERS>(
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      reinterpret_cast<char*>(dos_header) + dos_header->e_lfanew);
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottPIMAGE_SECTION_HEADER PEImage::GetSectionHeader(UINT section) const {
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PIMAGE_NT_HEADERS nt_headers = GetNTHeaders();
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PIMAGE_SECTION_HEADER first_section = IMAGE_FIRST_SECTION(nt_headers);
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (section < nt_headers->FileHeader.NumberOfSections)
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return first_section + section;
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  else
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return NULL;
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottWORD PEImage::GetNumSections() const {
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return GetNTHeaders()->FileHeader.NumberOfSections;
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottDWORD PEImage::GetImageDirectoryEntrySize(UINT directory) const {
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PIMAGE_NT_HEADERS nt_headers = GetNTHeaders();
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return nt_headers->OptionalHeader.DataDirectory[directory].Size;
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottPVOID PEImage::GetImageDirectoryEntryAddr(UINT directory) const {
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PIMAGE_NT_HEADERS nt_headers = GetNTHeaders();
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return RVAToAddr(
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      nt_headers->OptionalHeader.DataDirectory[directory].VirtualAddress);
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottPIMAGE_SECTION_HEADER PEImage::GetImageSectionFromAddr(PVOID address) const {
114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PBYTE target = reinterpret_cast<PBYTE>(address);
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PIMAGE_SECTION_HEADER section;
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (UINT i = 0; NULL != (section = GetSectionHeader(i)); i++) {
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Don't use the virtual RVAToAddr.
119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    PBYTE start = reinterpret_cast<PBYTE>(
120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                      PEImage::RVAToAddr(section->VirtualAddress));
121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DWORD size = section->Misc.VirtualSize;
123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if ((start <= target) && (start + size > target))
125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return section;
126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return NULL;
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottPIMAGE_SECTION_HEADER PEImage::GetImageSectionHeaderByName(
132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LPCSTR section_name) const {
133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (NULL == section_name)
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return NULL;
135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PIMAGE_SECTION_HEADER ret = NULL;
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int num_sections = GetNumSections();
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 0; i < num_sections; i++) {
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    PIMAGE_SECTION_HEADER section = GetSectionHeader(i);
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (0 == _strnicmp(reinterpret_cast<LPCSTR>(section->Name), section_name,
142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                       sizeof(section->Name))) {
143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ret = section;
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return ret;
149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottPDWORD PEImage::GetExportEntry(LPCSTR name) const {
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PIMAGE_EXPORT_DIRECTORY exports = GetExportDirectory();
153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (NULL == exports)
155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return NULL;
156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  WORD ordinal = 0;
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!GetProcOrdinal(name, &ordinal))
159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return NULL;
160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PDWORD functions = reinterpret_cast<PDWORD>(
162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                         RVAToAddr(exports->AddressOfFunctions));
163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return functions + ordinal - exports->Base;
165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFARPROC PEImage::GetProcAddress(LPCSTR function_name) const {
168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PDWORD export_entry = GetExportEntry(function_name);
169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (NULL == export_entry)
170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return NULL;
171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PBYTE function = reinterpret_cast<PBYTE>(RVAToAddr(*export_entry));
173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PBYTE exports = reinterpret_cast<PBYTE>(
175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_EXPORT));
176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_EXPORT);
177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Check for forwarded exports as a special case.
179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (exports <= function && exports + size > function)
180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#pragma warning(push)
181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#pragma warning(disable: 4312)
182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // This cast generates a warning because it is 32 bit specific.
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return reinterpret_cast<FARPROC>(0xFFFFFFFF);
184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#pragma warning(pop)
185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return reinterpret_cast<FARPROC>(function);
187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool PEImage::GetProcOrdinal(LPCSTR function_name, WORD *ordinal) const {
190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (NULL == ordinal)
191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PIMAGE_EXPORT_DIRECTORY exports = GetExportDirectory();
194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (NULL == exports)
196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (IsOrdinal(function_name)) {
199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    *ordinal = ToOrdinal(function_name);
200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    PDWORD names = reinterpret_cast<PDWORD>(RVAToAddr(exports->AddressOfNames));
202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    PDWORD lower = names;
203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    PDWORD upper = names + exports->NumberOfNames;
204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int cmp = -1;
205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Binary Search for the name.
207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    while (lower != upper) {
208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      PDWORD middle = lower + (upper - lower) / 2;
209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      LPCSTR name = reinterpret_cast<LPCSTR>(RVAToAddr(*middle));
210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // This may be called by sandbox before MSVCRT dll loads, so can't use
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // CRT function here.
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      cmp = StrCmpByByte(function_name, name);
214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (cmp == 0) {
216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        lower = middle;
217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (cmp > 0)
221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        lower = middle + 1;
222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      else
223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        upper = middle;
224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (cmp != 0)
227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return false;
228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    PWORD ordinals = reinterpret_cast<PWORD>(
231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                         RVAToAddr(exports->AddressOfNameOrdinals));
232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    *ordinal = ordinals[lower - names] + static_cast<WORD>(exports->Base);
234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool PEImage::EnumSections(EnumSectionsFunction callback, PVOID cookie) const {
240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PIMAGE_NT_HEADERS nt_headers = GetNTHeaders();
241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  UINT num_sections = nt_headers->FileHeader.NumberOfSections;
242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PIMAGE_SECTION_HEADER section = GetSectionHeader(0);
243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (UINT i = 0; i < num_sections; i++, section++) {
245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    PVOID section_start = RVAToAddr(section->VirtualAddress);
246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DWORD size = section->Misc.VirtualSize;
247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!callback(*this, section, section_start, size, cookie))
249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return false;
250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool PEImage::EnumExports(EnumExportsFunction callback, PVOID cookie) const {
256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PVOID directory = GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_EXPORT);
257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_EXPORT);
258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Check if there are any exports at all.
260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (NULL == directory || 0 == size)
261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return true;
262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PIMAGE_EXPORT_DIRECTORY exports = reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>(
264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                        directory);
265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  UINT ordinal_base = exports->Base;
266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  UINT num_funcs = exports->NumberOfFunctions;
267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  UINT num_names = exports->NumberOfNames;
268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PDWORD functions  = reinterpret_cast<PDWORD>(RVAToAddr(
269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                          exports->AddressOfFunctions));
270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PDWORD names = reinterpret_cast<PDWORD>(RVAToAddr(exports->AddressOfNames));
271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PWORD ordinals = reinterpret_cast<PWORD>(RVAToAddr(
272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                       exports->AddressOfNameOrdinals));
273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (UINT count = 0; count < num_funcs; count++) {
275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    PVOID func = RVAToAddr(functions[count]);
276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (NULL == func)
277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      continue;
278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Check for a name.
280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LPCSTR name = NULL;
281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    UINT hint;
282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (hint = 0; hint < num_names; hint++) {
283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (ordinals[hint] == count) {
284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        name = reinterpret_cast<LPCSTR>(RVAToAddr(names[hint]));
285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (name == NULL)
290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      hint = 0;
291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Check for forwarded exports.
293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LPCSTR forward = NULL;
294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (reinterpret_cast<char*>(func) >= reinterpret_cast<char*>(directory) &&
295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        reinterpret_cast<char*>(func) <= reinterpret_cast<char*>(directory) +
296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            size) {
297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      forward = reinterpret_cast<LPCSTR>(func);
298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      func = 0;
299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!callback(*this, ordinal_base + count, hint, name, func, forward,
302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                  cookie))
303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return false;
304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool PEImage::EnumRelocs(EnumRelocsFunction callback, PVOID cookie) const {
310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PVOID directory = GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_BASERELOC);
311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_BASERELOC);
312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PIMAGE_BASE_RELOCATION base = reinterpret_cast<PIMAGE_BASE_RELOCATION>(
313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      directory);
314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (directory == NULL || size < sizeof(IMAGE_BASE_RELOCATION))
316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return true;
317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  while (base->SizeOfBlock) {
319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    PWORD reloc = reinterpret_cast<PWORD>(base + 1);
320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    UINT num_relocs = (base->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) /
321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        sizeof(WORD);
322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (UINT i = 0; i < num_relocs; i++, reloc++) {
324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      WORD type = *reloc >> 12;
325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      PVOID address = RVAToAddr(base->VirtualAddress + (*reloc & 0x0FFF));
326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (!callback(*this, type, address, cookie))
328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return false;
329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    base = reinterpret_cast<PIMAGE_BASE_RELOCATION>(
332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott               reinterpret_cast<char*>(base) + base->SizeOfBlock);
333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool PEImage::EnumImportChunks(EnumImportChunksFunction callback,
339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                               PVOID cookie) const {
340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_IMPORT);
341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PIMAGE_IMPORT_DESCRIPTOR import = GetFirstImportChunk();
342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (import == NULL || size < sizeof(IMAGE_IMPORT_DESCRIPTOR))
344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return true;
345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (; import->FirstThunk; import++) {
347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LPCSTR module_name = reinterpret_cast<LPCSTR>(RVAToAddr(import->Name));
348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    PIMAGE_THUNK_DATA name_table = reinterpret_cast<PIMAGE_THUNK_DATA>(
349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                       RVAToAddr(import->OriginalFirstThunk));
350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    PIMAGE_THUNK_DATA iat = reinterpret_cast<PIMAGE_THUNK_DATA>(
351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                RVAToAddr(import->FirstThunk));
352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!callback(*this, module_name, name_table, iat, cookie))
354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return false;
355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool PEImage::EnumOneImportChunk(EnumImportsFunction callback,
361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                 LPCSTR module_name,
362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                 PIMAGE_THUNK_DATA name_table,
363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                 PIMAGE_THUNK_DATA iat, PVOID cookie) const {
364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (NULL == name_table)
365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (; name_table && name_table->u1.Ordinal; name_table++, iat++) {
368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LPCSTR name = NULL;
369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    WORD ordinal = 0;
370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    WORD hint = 0;
371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (IMAGE_SNAP_BY_ORDINAL(name_table->u1.Ordinal)) {
373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ordinal = static_cast<WORD>(IMAGE_ORDINAL32(name_table->u1.Ordinal));
374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      PIMAGE_IMPORT_BY_NAME import = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(
376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          RVAToAddr(name_table->u1.ForwarderString));
377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      hint = import->Hint;
379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      name = reinterpret_cast<LPCSTR>(&import->Name);
380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!callback(*this, module_name, ordinal, name, hint, iat, cookie))
383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return false;
384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool PEImage::EnumAllImports(EnumImportsFunction callback, PVOID cookie) const {
390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EnumAllImportsStorage temp = { callback, cookie };
391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return EnumImportChunks(ProcessImportChunk, &temp);
392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool PEImage::EnumDelayImportChunks(EnumDelayImportChunksFunction callback,
395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                    PVOID cookie) const {
396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PVOID directory = GetImageDirectoryEntryAddr(
397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT);
398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT);
399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PImgDelayDescr delay_descriptor = reinterpret_cast<PImgDelayDescr>(directory);
400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (directory == NULL || size == 0)
402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return true;
403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (; delay_descriptor->rvaHmod; delay_descriptor++) {
405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    PIMAGE_THUNK_DATA name_table;
406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    PIMAGE_THUNK_DATA iat;
407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    PIMAGE_THUNK_DATA bound_iat;    // address of the optional bound IAT
408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    PIMAGE_THUNK_DATA unload_iat;   // address of optional copy of original IAT
409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LPCSTR module_name;
410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // check if VC7-style imports, using RVAs instead of
412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // VC6-style addresses.
413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    bool rvas = (delay_descriptor->grAttrs & dlattrRva) != 0;
414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (rvas) {
416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      module_name = reinterpret_cast<LPCSTR>(
417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        RVAToAddr(delay_descriptor->rvaDLLName));
418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      name_table = reinterpret_cast<PIMAGE_THUNK_DATA>(
419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                       RVAToAddr(delay_descriptor->rvaINT));
420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      iat = reinterpret_cast<PIMAGE_THUNK_DATA>(
421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                RVAToAddr(delay_descriptor->rvaIAT));
422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      bound_iat = reinterpret_cast<PIMAGE_THUNK_DATA>(
423c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                      RVAToAddr(delay_descriptor->rvaBoundIAT));
424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      unload_iat = reinterpret_cast<PIMAGE_THUNK_DATA>(
425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                       RVAToAddr(delay_descriptor->rvaUnloadIAT));
426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#pragma warning(push)
428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#pragma warning(disable: 4312)
429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // These casts generate warnings because they are 32 bit specific.
430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      module_name = reinterpret_cast<LPCSTR>(delay_descriptor->rvaDLLName);
431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      name_table = reinterpret_cast<PIMAGE_THUNK_DATA>(
432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                       delay_descriptor->rvaINT);
433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      iat = reinterpret_cast<PIMAGE_THUNK_DATA>(delay_descriptor->rvaIAT);
434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      bound_iat = reinterpret_cast<PIMAGE_THUNK_DATA>(
435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                      delay_descriptor->rvaBoundIAT);
436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      unload_iat = reinterpret_cast<PIMAGE_THUNK_DATA>(
437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                       delay_descriptor->rvaUnloadIAT);
438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#pragma warning(pop)
439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!callback(*this, delay_descriptor, module_name, name_table, iat,
442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                  bound_iat, unload_iat, cookie))
443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return false;
444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool PEImage::EnumOneDelayImportChunk(EnumImportsFunction callback,
450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                      PImgDelayDescr delay_descriptor,
451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                      LPCSTR module_name,
452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                      PIMAGE_THUNK_DATA name_table,
453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                      PIMAGE_THUNK_DATA iat,
454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                      PIMAGE_THUNK_DATA bound_iat,
455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                      PIMAGE_THUNK_DATA unload_iat,
456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                      PVOID cookie) const {
457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  UNREFERENCED_PARAMETER(bound_iat);
458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  UNREFERENCED_PARAMETER(unload_iat);
459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (; name_table->u1.Ordinal; name_table++, iat++) {
461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LPCSTR name = NULL;
462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    WORD ordinal = 0;
463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    WORD hint = 0;
464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (IMAGE_SNAP_BY_ORDINAL(name_table->u1.Ordinal)) {
466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ordinal = static_cast<WORD>(IMAGE_ORDINAL32(name_table->u1.Ordinal));
467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      PIMAGE_IMPORT_BY_NAME import;
469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      bool rvas = (delay_descriptor->grAttrs & dlattrRva) != 0;
470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (rvas) {
472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        import = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(
473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                     RVAToAddr(name_table->u1.ForwarderString));
474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      } else {
475c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#pragma warning(push)
476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#pragma warning(disable: 4312)
477c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // This cast generates a warning because it is 32 bit specific.
478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        import = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(
479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                     name_table->u1.ForwarderString);
480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#pragma warning(pop)
481c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      hint = import->Hint;
484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      name = reinterpret_cast<LPCSTR>(&import->Name);
485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!callback(*this, module_name, ordinal, name, hint, iat, cookie))
488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return false;
489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
491c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
492c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
493c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
494c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool PEImage::EnumAllDelayImports(EnumImportsFunction callback,
495c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                  PVOID cookie) const {
496c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EnumAllImportsStorage temp = { callback, cookie };
497c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return EnumDelayImportChunks(ProcessDelayImportChunk, &temp);
498c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
499c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
500c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool PEImage::VerifyMagic() const {
501c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PIMAGE_DOS_HEADER dos_header = GetDosHeader();
502c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
503c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
504c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
505c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PIMAGE_NT_HEADERS nt_headers = GetNTHeaders();
507c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
508c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (nt_headers->Signature != IMAGE_NT_SIGNATURE)
509c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
510c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (nt_headers->FileHeader.SizeOfOptionalHeader !=
512c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      sizeof(IMAGE_OPTIONAL_HEADER))
513c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
514c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (nt_headers->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
517c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
519c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
520c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
521c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool PEImage::ImageRVAToOnDiskOffset(DWORD rva, DWORD *on_disk_offset) const {
522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LPVOID address = RVAToAddr(rva);
523c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return ImageAddrToOnDiskOffset(address, on_disk_offset);
524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
526c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool PEImage::ImageAddrToOnDiskOffset(LPVOID address,
527c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                      DWORD *on_disk_offset) const {
528c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (NULL == address)
529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
530c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
531c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Get the section that this address belongs to.
532c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PIMAGE_SECTION_HEADER section_header = GetImageSectionFromAddr(address);
533c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (NULL == section_header)
534c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
535c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#pragma warning(push)
537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#pragma warning(disable: 4311)
538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // These casts generate warnings because they are 32 bit specific.
539c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Don't follow the virtual RVAToAddr, use the one on the base.
540c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DWORD offset_within_section = reinterpret_cast<DWORD>(address) -
541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                    reinterpret_cast<DWORD>(PEImage::RVAToAddr(
542c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                        section_header->VirtualAddress));
543c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#pragma warning(pop)
544c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
545c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  *on_disk_offset = section_header->PointerToRawData + offset_within_section;
546c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
547c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
548c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
549c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottPVOID PEImage::RVAToAddr(DWORD rva) const {
550c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (rva == 0)
551c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return NULL;
552c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
553c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return reinterpret_cast<char*>(module_) + rva;
554c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
555c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
556c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottPVOID PEImageAsData::RVAToAddr(DWORD rva) const {
557c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (rva == 0)
558c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return NULL;
559c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
560c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PVOID in_memory = PEImage::RVAToAddr(rva);
561201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  DWORD disk_offset;
562c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
563201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (!ImageAddrToOnDiskOffset(in_memory, &disk_offset))
564c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return NULL;
565c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
566201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return PEImage::RVAToAddr(disk_offset);
567c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
568731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
569731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}  // namespace win
570731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}  // namespace base
571