Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // This file contains unit tests for PEImage.
      6 
      7 #include "testing/gtest/include/gtest/gtest.h"
      8 #include "base/pe_image.h"
      9 #include "base/win_util.h"
     10 
     11 // Just counts the number of invocations.
     12 bool ExportsCallback(const PEImage &image,
     13                      DWORD ordinal,
     14                      DWORD hint,
     15                      LPCSTR name,
     16                      PVOID function,
     17                      LPCSTR forward,
     18                      PVOID cookie) {
     19   int* count = reinterpret_cast<int*>(cookie);
     20   (*count)++;
     21   return true;
     22 }
     23 
     24 // Just counts the number of invocations.
     25 bool ImportsCallback(const PEImage &image,
     26                      LPCSTR module,
     27                      DWORD ordinal,
     28                      LPCSTR name,
     29                      DWORD hint,
     30                      PIMAGE_THUNK_DATA iat,
     31                      PVOID cookie) {
     32   int* count = reinterpret_cast<int*>(cookie);
     33   (*count)++;
     34   return true;
     35 }
     36 
     37 // Just counts the number of invocations.
     38 bool SectionsCallback(const PEImage &image,
     39                        PIMAGE_SECTION_HEADER header,
     40                        PVOID section_start,
     41                        DWORD section_size,
     42                        PVOID cookie) {
     43   int* count = reinterpret_cast<int*>(cookie);
     44   (*count)++;
     45   return true;
     46 }
     47 
     48 // Just counts the number of invocations.
     49 bool RelocsCallback(const PEImage &image,
     50                     WORD type,
     51                     PVOID address,
     52                     PVOID cookie) {
     53   int* count = reinterpret_cast<int*>(cookie);
     54   (*count)++;
     55   return true;
     56 }
     57 
     58 // Just counts the number of invocations.
     59 bool ImportChunksCallback(const PEImage &image,
     60                           LPCSTR module,
     61                           PIMAGE_THUNK_DATA name_table,
     62                           PIMAGE_THUNK_DATA iat,
     63                           PVOID cookie) {
     64   int* count = reinterpret_cast<int*>(cookie);
     65   (*count)++;
     66   return true;
     67 }
     68 
     69 // Just counts the number of invocations.
     70 bool DelayImportChunksCallback(const PEImage &image,
     71                                PImgDelayDescr delay_descriptor,
     72                                LPCSTR module,
     73                                PIMAGE_THUNK_DATA name_table,
     74                                PIMAGE_THUNK_DATA iat,
     75                                PIMAGE_THUNK_DATA bound_iat,
     76                                PIMAGE_THUNK_DATA unload_iat,
     77                                PVOID cookie) {
     78   int* count = reinterpret_cast<int*>(cookie);
     79   (*count)++;
     80   return true;
     81 }
     82 
     83 // We'll be using some known values for the tests.
     84 enum Value {
     85   sections = 0,
     86   imports_dlls,
     87   delay_dlls,
     88   exports,
     89   imports,
     90   delay_imports,
     91   relocs
     92 };
     93 
     94 // Retrieves the expected value from advapi32.dll based on the OS.
     95 int GetExpectedValue(Value value, DWORD os) {
     96   const int xp_delay_dlls = 2;
     97   const int xp_exports = 675;
     98   const int xp_imports = 422;
     99   const int xp_delay_imports = 8;
    100   const int xp_relocs = 9180;
    101   const int vista_delay_dlls = 4;
    102   const int vista_exports = 799;
    103   const int vista_imports = 476;
    104   const int vista_delay_imports = 24;
    105   const int vista_relocs = 10188;
    106   const int w2k_delay_dlls = 0;
    107   const int w2k_exports = 566;
    108   const int w2k_imports = 357;
    109   const int w2k_delay_imports = 0;
    110   const int w2k_relocs = 7388;
    111   const int win7_delay_dlls = 7;
    112   const int win7_exports = 806;
    113   const int win7_imports = 568;
    114   const int win7_delay_imports = 71;
    115   const int win7_relocs = 7812;
    116 
    117   // Contains the expected value, for each enumerated property (Value), and the
    118   // OS version: [Value][os_version]
    119   const int expected[][4] = {
    120     {4, 4, 4, 4},
    121     {3, 3, 3, 13},
    122     {w2k_delay_dlls, xp_delay_dlls, vista_delay_dlls, win7_delay_dlls},
    123     {w2k_exports, xp_exports, vista_exports, win7_exports},
    124     {w2k_imports, xp_imports, vista_imports, win7_imports},
    125     {w2k_delay_imports, xp_delay_imports,
    126      vista_delay_imports, win7_delay_imports},
    127     {w2k_relocs, xp_relocs, vista_relocs, win7_relocs}
    128   };
    129 
    130   if (value > relocs)
    131     return 0;
    132   if (50 == os)
    133     os = 0;  // 5.0
    134   else if (51 == os || 52 == os)
    135     os = 1;
    136   else if (os == 60)
    137     os = 2;  // 6.x
    138   else if (os >= 61)
    139     os = 3;
    140   else
    141     return 0;
    142 
    143   return expected[value][os];
    144 }
    145 
    146 // Tests that we are able to enumerate stuff from a PE file, and that
    147 // the actual number of items found is within the expected range.
    148 TEST(PEImageTest, EnumeratesPE) {
    149   // Windows Server 2003 is not supported as a test environment for this test.
    150   if (win_util::GetWinVersion() == win_util::WINVERSION_SERVER_2003)
    151     return;
    152   HMODULE module = LoadLibrary(L"advapi32.dll");
    153   ASSERT_TRUE(NULL != module);
    154 
    155   PEImage pe(module);
    156   int count = 0;
    157   EXPECT_TRUE(pe.VerifyMagic());
    158 
    159   DWORD os = pe.GetNTHeaders()->OptionalHeader.MajorOperatingSystemVersion;
    160   os = os * 10 + pe.GetNTHeaders()->OptionalHeader.MinorOperatingSystemVersion;
    161 
    162   pe.EnumSections(SectionsCallback, &count);
    163   EXPECT_EQ(GetExpectedValue(sections, os), count);
    164 
    165   count = 0;
    166   pe.EnumImportChunks(ImportChunksCallback, &count);
    167   EXPECT_EQ(GetExpectedValue(imports_dlls, os), count);
    168 
    169   count = 0;
    170   pe.EnumDelayImportChunks(DelayImportChunksCallback, &count);
    171   EXPECT_EQ(GetExpectedValue(delay_dlls, os), count);
    172 
    173   count = 0;
    174   pe.EnumExports(ExportsCallback, &count);
    175   EXPECT_GT(count, GetExpectedValue(exports, os) - 20);
    176   EXPECT_LT(count, GetExpectedValue(exports, os) + 100);
    177 
    178   count = 0;
    179   pe.EnumAllImports(ImportsCallback, &count);
    180   EXPECT_GT(count, GetExpectedValue(imports, os) - 20);
    181   EXPECT_LT(count, GetExpectedValue(imports, os) + 100);
    182 
    183   count = 0;
    184   pe.EnumAllDelayImports(ImportsCallback, &count);
    185   EXPECT_GT(count, GetExpectedValue(delay_imports, os) - 2);
    186   EXPECT_LT(count, GetExpectedValue(delay_imports, os) + 8);
    187 
    188   count = 0;
    189   pe.EnumRelocs(RelocsCallback, &count);
    190   EXPECT_GT(count, GetExpectedValue(relocs, os) - 150);
    191   EXPECT_LT(count, GetExpectedValue(relocs, os) + 1500);
    192 
    193   FreeLibrary(module);
    194 }
    195 
    196 // Tests that we can locate an specific exported symbol, by name and by ordinal.
    197 TEST(PEImageTest, RetrievesExports) {
    198   HMODULE module = LoadLibrary(L"advapi32.dll");
    199   ASSERT_TRUE(NULL != module);
    200 
    201   PEImage pe(module);
    202   WORD ordinal;
    203 
    204   EXPECT_TRUE(pe.GetProcOrdinal("RegEnumKeyExW", &ordinal));
    205 
    206   FARPROC address1 = pe.GetProcAddress("RegEnumKeyExW");
    207   FARPROC address2 = pe.GetProcAddress(reinterpret_cast<char*>(ordinal));
    208   EXPECT_TRUE(address1 != NULL);
    209   EXPECT_TRUE(address2 != NULL);
    210   EXPECT_TRUE(address1 == address2);
    211 
    212   FreeLibrary(module);
    213 }
    214