15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2010 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file implements PEImage, a generic class to manipulate PE files.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file was adapted from GreenBorder's Code.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/pe_image.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace win {
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(_WIN64) && !defined(NACL_WIN64)
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TODO(jschuh): crbug.com/167707 Make sure this is ok.
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#pragma message ("Warning: \
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) This code is not tested on x64. Please make sure all the base unit tests\
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pass before doing any real work. The current unit tests don't test the\
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) differences between 32- and 64-bits implementations. Bugs may slip through.\
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) You need to improve the coverage before continuing.")
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Structure to perform imports enumerations.
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct EnumAllImportsStorage {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PEImage::EnumImportsFunction callback;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PVOID cookie;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Compare two strings byte by byte on an unsigned basis.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   if s1 == s2, return 0
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   if s1 < s2, return negative
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   if s1 > s2, return positive
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Exception if inputs are invalid.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int StrCmpByByte(LPCSTR s1, LPCSTR s2) {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (*s1 != '\0' && *s1 == *s2) {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++s1;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++s2;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (*reinterpret_cast<const unsigned char*>(s1) -
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *reinterpret_cast<const unsigned char*>(s2));
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Callback used to enumerate imports. See EnumImportChunksFunction.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProcessImportChunk(const PEImage &image, LPCSTR module,
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        PIMAGE_THUNK_DATA name_table,
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        PIMAGE_THUNK_DATA iat, PVOID cookie) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnumAllImportsStorage &storage = *reinterpret_cast<EnumAllImportsStorage*>(
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       cookie);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return image.EnumOneImportChunk(storage.callback, module, name_table, iat,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  storage.cookie);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Callback used to enumerate delay imports. See EnumDelayImportChunksFunction.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProcessDelayImportChunk(const PEImage &image,
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             PImgDelayDescr delay_descriptor,
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             LPCSTR module, PIMAGE_THUNK_DATA name_table,
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             PIMAGE_THUNK_DATA iat, PIMAGE_THUNK_DATA bound_iat,
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             PIMAGE_THUNK_DATA unload_iat, PVOID cookie) {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnumAllImportsStorage &storage = *reinterpret_cast<EnumAllImportsStorage*>(
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       cookie);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return image.EnumOneDelayImportChunk(storage.callback, delay_descriptor,
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       module, name_table, iat, bound_iat,
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       unload_iat, storage.cookie);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PEImage::set_module(HMODULE module) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  module_ = module;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PIMAGE_DOS_HEADER PEImage::GetDosHeader() const {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return reinterpret_cast<PIMAGE_DOS_HEADER>(module_);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PIMAGE_NT_HEADERS PEImage::GetNTHeaders() const {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PIMAGE_DOS_HEADER dos_header = GetDosHeader();
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return reinterpret_cast<PIMAGE_NT_HEADERS>(
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<char*>(dos_header) + dos_header->e_lfanew);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PIMAGE_SECTION_HEADER PEImage::GetSectionHeader(UINT section) const {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PIMAGE_NT_HEADERS nt_headers = GetNTHeaders();
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PIMAGE_SECTION_HEADER first_section = IMAGE_FIRST_SECTION(nt_headers);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (section < nt_headers->FileHeader.NumberOfSections)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return first_section + section;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WORD PEImage::GetNumSections() const {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetNTHeaders()->FileHeader.NumberOfSections;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DWORD PEImage::GetImageDirectoryEntrySize(UINT directory) const {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PIMAGE_NT_HEADERS nt_headers = GetNTHeaders();
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return nt_headers->OptionalHeader.DataDirectory[directory].Size;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PVOID PEImage::GetImageDirectoryEntryAddr(UINT directory) const {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PIMAGE_NT_HEADERS nt_headers = GetNTHeaders();
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return RVAToAddr(
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nt_headers->OptionalHeader.DataDirectory[directory].VirtualAddress);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PIMAGE_SECTION_HEADER PEImage::GetImageSectionFromAddr(PVOID address) const {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PBYTE target = reinterpret_cast<PBYTE>(address);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PIMAGE_SECTION_HEADER section;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (UINT i = 0; NULL != (section = GetSectionHeader(i)); i++) {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Don't use the virtual RVAToAddr.
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PBYTE start = reinterpret_cast<PBYTE>(
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      PEImage::RVAToAddr(section->VirtualAddress));
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DWORD size = section->Misc.VirtualSize;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((start <= target) && (start + size > target))
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return section;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PIMAGE_SECTION_HEADER PEImage::GetImageSectionHeaderByName(
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LPCSTR section_name) const {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NULL == section_name)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PIMAGE_SECTION_HEADER ret = NULL;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_sections = GetNumSections();
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < num_sections; i++) {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PIMAGE_SECTION_HEADER section = GetSectionHeader(i);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (0 == _strnicmp(reinterpret_cast<LPCSTR>(section->Name), section_name,
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       sizeof(section->Name))) {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ret = section;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ret;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PDWORD PEImage::GetExportEntry(LPCSTR name) const {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PIMAGE_EXPORT_DIRECTORY exports = GetExportDirectory();
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NULL == exports)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WORD ordinal = 0;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetProcOrdinal(name, &ordinal))
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PDWORD functions = reinterpret_cast<PDWORD>(
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         RVAToAddr(exports->AddressOfFunctions));
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return functions + ordinal - exports->Base;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FARPROC PEImage::GetProcAddress(LPCSTR function_name) const {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PDWORD export_entry = GetExportEntry(function_name);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NULL == export_entry)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PBYTE function = reinterpret_cast<PBYTE>(RVAToAddr(*export_entry));
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PBYTE exports = reinterpret_cast<PBYTE>(
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_EXPORT));
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_EXPORT);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check for forwarded exports as a special case.
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (exports <= function && exports + size > function)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma warning(push)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma warning(disable: 4312)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This cast generates a warning because it is 32 bit specific.
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return reinterpret_cast<FARPROC>(0xFFFFFFFF);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma warning(pop)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return reinterpret_cast<FARPROC>(function);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PEImage::GetProcOrdinal(LPCSTR function_name, WORD *ordinal) const {
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NULL == ordinal)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PIMAGE_EXPORT_DIRECTORY exports = GetExportDirectory();
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NULL == exports)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsOrdinal(function_name)) {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *ordinal = ToOrdinal(function_name);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PDWORD names = reinterpret_cast<PDWORD>(RVAToAddr(exports->AddressOfNames));
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PDWORD lower = names;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PDWORD upper = names + exports->NumberOfNames;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int cmp = -1;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Binary Search for the name.
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (lower != upper) {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PDWORD middle = lower + (upper - lower) / 2;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LPCSTR name = reinterpret_cast<LPCSTR>(RVAToAddr(*middle));
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This may be called by sandbox before MSVCRT dll loads, so can't use
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // CRT function here.
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cmp = StrCmpByByte(function_name, name);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (cmp == 0) {
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        lower = middle;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (cmp > 0)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        lower = middle + 1;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        upper = middle;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (cmp != 0)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PWORD ordinals = reinterpret_cast<PWORD>(
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         RVAToAddr(exports->AddressOfNameOrdinals));
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *ordinal = ordinals[lower - names] + static_cast<WORD>(exports->Base);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PEImage::EnumSections(EnumSectionsFunction callback, PVOID cookie) const {
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PIMAGE_NT_HEADERS nt_headers = GetNTHeaders();
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UINT num_sections = nt_headers->FileHeader.NumberOfSections;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PIMAGE_SECTION_HEADER section = GetSectionHeader(0);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (UINT i = 0; i < num_sections; i++, section++) {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PVOID section_start = RVAToAddr(section->VirtualAddress);
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DWORD size = section->Misc.VirtualSize;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!callback(*this, section, section_start, size, cookie))
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PEImage::EnumExports(EnumExportsFunction callback, PVOID cookie) const {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PVOID directory = GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_EXPORT);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_EXPORT);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if there are any exports at all.
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NULL == directory || 0 == size)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PIMAGE_EXPORT_DIRECTORY exports = reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>(
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        directory);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UINT ordinal_base = exports->Base;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UINT num_funcs = exports->NumberOfFunctions;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UINT num_names = exports->NumberOfNames;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PDWORD functions  = reinterpret_cast<PDWORD>(RVAToAddr(
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          exports->AddressOfFunctions));
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PDWORD names = reinterpret_cast<PDWORD>(RVAToAddr(exports->AddressOfNames));
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PWORD ordinals = reinterpret_cast<PWORD>(RVAToAddr(
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       exports->AddressOfNameOrdinals));
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (UINT count = 0; count < num_funcs; count++) {
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PVOID func = RVAToAddr(functions[count]);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (NULL == func)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check for a name.
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LPCSTR name = NULL;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UINT hint;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (hint = 0; hint < num_names; hint++) {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (ordinals[hint] == count) {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        name = reinterpret_cast<LPCSTR>(RVAToAddr(names[hint]));
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (name == NULL)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      hint = 0;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check for forwarded exports.
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LPCSTR forward = NULL;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (reinterpret_cast<char*>(func) >= reinterpret_cast<char*>(directory) &&
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reinterpret_cast<char*>(func) <= reinterpret_cast<char*>(directory) +
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            size) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      forward = reinterpret_cast<LPCSTR>(func);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      func = 0;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!callback(*this, ordinal_base + count, hint, name, func, forward,
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  cookie))
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PEImage::EnumRelocs(EnumRelocsFunction callback, PVOID cookie) const {
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PVOID directory = GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_BASERELOC);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_BASERELOC);
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PIMAGE_BASE_RELOCATION base = reinterpret_cast<PIMAGE_BASE_RELOCATION>(
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      directory);
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!directory)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  while (size >= sizeof(IMAGE_BASE_RELOCATION) && base->SizeOfBlock &&
3205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)         size >= base->SizeOfBlock) {
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PWORD reloc = reinterpret_cast<PWORD>(base + 1);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UINT num_relocs = (base->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) /
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sizeof(WORD);
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (UINT i = 0; i < num_relocs; i++, reloc++) {
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WORD type = *reloc >> 12;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PVOID address = RVAToAddr(base->VirtualAddress + (*reloc & 0x0FFF));
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!callback(*this, type, address, cookie))
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    size -= base->SizeOfBlock;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base = reinterpret_cast<PIMAGE_BASE_RELOCATION>(
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               reinterpret_cast<char*>(base) + base->SizeOfBlock);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PEImage::EnumImportChunks(EnumImportChunksFunction callback,
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               PVOID cookie) const {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_IMPORT);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PIMAGE_IMPORT_DESCRIPTOR import = GetFirstImportChunk();
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (import == NULL || size < sizeof(IMAGE_IMPORT_DESCRIPTOR))
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; import->FirstThunk; import++) {
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LPCSTR module_name = reinterpret_cast<LPCSTR>(RVAToAddr(import->Name));
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PIMAGE_THUNK_DATA name_table = reinterpret_cast<PIMAGE_THUNK_DATA>(
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       RVAToAddr(import->OriginalFirstThunk));
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PIMAGE_THUNK_DATA iat = reinterpret_cast<PIMAGE_THUNK_DATA>(
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                RVAToAddr(import->FirstThunk));
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!callback(*this, module_name, name_table, iat, cookie))
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PEImage::EnumOneImportChunk(EnumImportsFunction callback,
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 LPCSTR module_name,
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 PIMAGE_THUNK_DATA name_table,
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 PIMAGE_THUNK_DATA iat, PVOID cookie) const {
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NULL == name_table)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; name_table && name_table->u1.Ordinal; name_table++, iat++) {
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LPCSTR name = NULL;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WORD ordinal = 0;
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WORD hint = 0;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (IMAGE_SNAP_BY_ORDINAL(name_table->u1.Ordinal)) {
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ordinal = static_cast<WORD>(IMAGE_ORDINAL32(name_table->u1.Ordinal));
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PIMAGE_IMPORT_BY_NAME import = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          RVAToAddr(name_table->u1.ForwarderString));
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      hint = import->Hint;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      name = reinterpret_cast<LPCSTR>(&import->Name);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!callback(*this, module_name, ordinal, name, hint, iat, cookie))
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PEImage::EnumAllImports(EnumImportsFunction callback, PVOID cookie) const {
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnumAllImportsStorage temp = { callback, cookie };
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return EnumImportChunks(ProcessImportChunk, &temp);
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PEImage::EnumDelayImportChunks(EnumDelayImportChunksFunction callback,
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    PVOID cookie) const {
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PVOID directory = GetImageDirectoryEntryAddr(
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT);
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT);
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PImgDelayDescr delay_descriptor = reinterpret_cast<PImgDelayDescr>(directory);
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (directory == NULL || size == 0)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; delay_descriptor->rvaHmod; delay_descriptor++) {
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PIMAGE_THUNK_DATA name_table;
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PIMAGE_THUNK_DATA iat;
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PIMAGE_THUNK_DATA bound_iat;    // address of the optional bound IAT
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PIMAGE_THUNK_DATA unload_iat;   // address of optional copy of original IAT
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LPCSTR module_name;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // check if VC7-style imports, using RVAs instead of
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // VC6-style addresses.
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool rvas = (delay_descriptor->grAttrs & dlattrRva) != 0;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rvas) {
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      module_name = reinterpret_cast<LPCSTR>(
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        RVAToAddr(delay_descriptor->rvaDLLName));
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      name_table = reinterpret_cast<PIMAGE_THUNK_DATA>(
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       RVAToAddr(delay_descriptor->rvaINT));
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      iat = reinterpret_cast<PIMAGE_THUNK_DATA>(
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                RVAToAddr(delay_descriptor->rvaIAT));
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bound_iat = reinterpret_cast<PIMAGE_THUNK_DATA>(
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      RVAToAddr(delay_descriptor->rvaBoundIAT));
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unload_iat = reinterpret_cast<PIMAGE_THUNK_DATA>(
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       RVAToAddr(delay_descriptor->rvaUnloadIAT));
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma warning(push)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma warning(disable: 4312)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // These casts generate warnings because they are 32 bit specific.
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      module_name = reinterpret_cast<LPCSTR>(delay_descriptor->rvaDLLName);
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      name_table = reinterpret_cast<PIMAGE_THUNK_DATA>(
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       delay_descriptor->rvaINT);
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      iat = reinterpret_cast<PIMAGE_THUNK_DATA>(delay_descriptor->rvaIAT);
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bound_iat = reinterpret_cast<PIMAGE_THUNK_DATA>(
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      delay_descriptor->rvaBoundIAT);
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unload_iat = reinterpret_cast<PIMAGE_THUNK_DATA>(
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       delay_descriptor->rvaUnloadIAT);
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma warning(pop)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!callback(*this, delay_descriptor, module_name, name_table, iat,
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  bound_iat, unload_iat, cookie))
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PEImage::EnumOneDelayImportChunk(EnumImportsFunction callback,
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      PImgDelayDescr delay_descriptor,
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      LPCSTR module_name,
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      PIMAGE_THUNK_DATA name_table,
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      PIMAGE_THUNK_DATA iat,
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      PIMAGE_THUNK_DATA bound_iat,
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      PIMAGE_THUNK_DATA unload_iat,
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      PVOID cookie) const {
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNREFERENCED_PARAMETER(bound_iat);
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNREFERENCED_PARAMETER(unload_iat);
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; name_table->u1.Ordinal; name_table++, iat++) {
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LPCSTR name = NULL;
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WORD ordinal = 0;
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WORD hint = 0;
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (IMAGE_SNAP_BY_ORDINAL(name_table->u1.Ordinal)) {
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ordinal = static_cast<WORD>(IMAGE_ORDINAL32(name_table->u1.Ordinal));
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PIMAGE_IMPORT_BY_NAME import;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool rvas = (delay_descriptor->grAttrs & dlattrRva) != 0;
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (rvas) {
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        import = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     RVAToAddr(name_table->u1.ForwarderString));
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma warning(push)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma warning(disable: 4312)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // This cast generates a warning because it is 32 bit specific.
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        import = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     name_table->u1.ForwarderString);
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma warning(pop)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      hint = import->Hint;
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      name = reinterpret_cast<LPCSTR>(&import->Name);
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!callback(*this, module_name, ordinal, name, hint, iat, cookie))
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PEImage::EnumAllDelayImports(EnumImportsFunction callback,
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  PVOID cookie) const {
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnumAllImportsStorage temp = { callback, cookie };
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return EnumDelayImportChunks(ProcessDelayImportChunk, &temp);
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PEImage::VerifyMagic() const {
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PIMAGE_DOS_HEADER dos_header = GetDosHeader();
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PIMAGE_NT_HEADERS nt_headers = GetNTHeaders();
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (nt_headers->Signature != IMAGE_NT_SIGNATURE)
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (nt_headers->FileHeader.SizeOfOptionalHeader !=
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sizeof(IMAGE_OPTIONAL_HEADER))
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (nt_headers->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PEImage::ImageRVAToOnDiskOffset(DWORD rva, DWORD *on_disk_offset) const {
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LPVOID address = RVAToAddr(rva);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ImageAddrToOnDiskOffset(address, on_disk_offset);
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PEImage::ImageAddrToOnDiskOffset(LPVOID address,
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      DWORD *on_disk_offset) const {
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NULL == address)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the section that this address belongs to.
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PIMAGE_SECTION_HEADER section_header = GetImageSectionFromAddr(address);
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NULL == section_header)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma warning(push)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma warning(disable: 4311)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These casts generate warnings because they are 32 bit specific.
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't follow the virtual RVAToAddr, use the one on the base.
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD offset_within_section = reinterpret_cast<DWORD>(address) -
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    reinterpret_cast<DWORD>(PEImage::RVAToAddr(
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        section_header->VirtualAddress));
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma warning(pop)
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *on_disk_offset = section_header->PointerToRawData + offset_within_section;
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PVOID PEImage::RVAToAddr(DWORD rva) const {
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rva == 0)
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return reinterpret_cast<char*>(module_) + rva;
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PVOID PEImageAsData::RVAToAddr(DWORD rva) const {
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rva == 0)
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PVOID in_memory = PEImage::RVAToAddr(rva);
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD disk_offset;
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ImageAddrToOnDiskOffset(in_memory, &disk_offset))
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PEImage::RVAToAddr(disk_offset);
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace win
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
574