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