1 /*
2  * PROJECT:         ReactOS api tests
3  * LICENSE:         GPLv2+ - See COPYING in the top level directory
4  * PURPOSE:         Test to validate section flags in ntoskrnl
5  * PROGRAMMER:      Mark Jansen
6  */
7 
8 #include <apitest.h>
9 #include <strsafe.h>
10 
11 typedef struct KnownSections
12 {
13     const char* Name;
14     DWORD Required;
15     DWORD Disallowed;
16 } KnownSections;
17 
18 static struct KnownSections g_Sections[] = {
19     {
20         ".text",
21         IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_NOT_PAGED,
22         IMAGE_SCN_MEM_DISCARDABLE
23     },
24     {
25         ".data",
26         IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_NOT_PAGED,
27         IMAGE_SCN_MEM_DISCARDABLE
28     },
29     {
30         ".rsrc",
31         IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ,
32         IMAGE_SCN_MEM_DISCARDABLE
33     },
34     {
35         ".rdata",
36         IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ,
37         IMAGE_SCN_MEM_DISCARDABLE
38     },
39     {
40         ".reloc",
41         IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_MEM_READ,
42         0
43     },
44     {
45         "INIT",
46         IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ,
47         0
48     },
49     { NULL, 0 },
50 };
51 
52 static char* Chr2Str(DWORD value)
53 {
54     static char buf[512];
55     buf[0] = '\0';
56 #define IFX(x)      if( value & IMAGE_SCN_##x )\
57                     {\
58                         if(buf[0]) { StringCchCatA(buf, _countof(buf), "|" ); }\
59                         StringCchCatA(buf, _countof(buf), #x );\
60                         value &= ~(IMAGE_SCN_##x);\
61                     }
62     IFX(TYPE_NO_PAD);
63     IFX(CNT_CODE);
64     IFX(CNT_INITIALIZED_DATA);
65     IFX(CNT_UNINITIALIZED_DATA);
66     IFX(LNK_OTHER);
67     IFX(LNK_INFO);
68     IFX(LNK_REMOVE);
69     IFX(LNK_COMDAT);
70     //IFX(NO_DEFER_SPEC_EXC);
71     //IFX(GPREL);
72     IFX(MEM_FARDATA);
73     IFX(MEM_PURGEABLE);
74     IFX(MEM_16BIT);
75     IFX(MEM_LOCKED);
76     IFX(MEM_PRELOAD);
77     IFX(ALIGN_1BYTES);
78     IFX(ALIGN_2BYTES);
79     IFX(ALIGN_4BYTES);
80     IFX(ALIGN_8BYTES);
81     IFX(ALIGN_16BYTES);
82     IFX(ALIGN_32BYTES);
83     IFX(ALIGN_64BYTES);
84     //IFX(ALIGN_128BYTES);
85     //IFX(ALIGN_256BYTES);
86     //IFX(ALIGN_512BYTES);
87     //IFX(ALIGN_1024BYTES);
88     //IFX(ALIGN_2048BYTES);
89     //IFX(ALIGN_4096BYTES);
90     //IFX(ALIGN_8192BYTES);
91     IFX(LNK_NRELOC_OVFL);
92     IFX(MEM_DISCARDABLE);
93     IFX(MEM_NOT_CACHED);
94     IFX(MEM_NOT_PAGED);
95     IFX(MEM_SHARED);
96     IFX(MEM_EXECUTE);
97     IFX(MEM_READ);
98     IFX(MEM_WRITE);
99     if( value )
100     {
101         StringCchPrintfA(buf + strlen(buf), _countof(buf) - strlen(buf), "|0x%x", value);
102     }
103     return buf;
104 }
105 
106 
107 START_TEST(ntoskrnl_SectionFlags)
108 {
109     char buf[MAX_PATH];
110     HMODULE mod;
111     GetSystemDirectoryA(buf, _countof(buf));
112     StringCchCatA(buf, _countof(buf), "\\ntoskrnl.exe");
113 
114     mod = LoadLibraryExA( buf, NULL, LOAD_LIBRARY_AS_DATAFILE );
115     if( mod != NULL )
116     {
117         // we have to take into account that a datafile is not returned at the exact address it's loaded at.
118         PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)(((size_t)mod) & (~0xf));
119         PIMAGE_NT_HEADERS nt;
120         PIMAGE_SECTION_HEADER firstSection;
121         WORD numSections, n;
122 
123         if( dos->e_magic != IMAGE_DOS_SIGNATURE )
124         {
125             skip("Couldn't find ntoskrnl.exe dos header\n");
126             FreeLibrary(mod);
127             return;
128         }
129         nt = (PIMAGE_NT_HEADERS)( ((PBYTE)dos) + dos->e_lfanew );
130         if( nt->Signature != IMAGE_NT_SIGNATURE )
131         {
132             skip("Couldn't find ntoskrnl.exe nt header\n");
133             FreeLibrary(mod);
134             return;
135         }
136         firstSection = IMAGE_FIRST_SECTION(nt);
137         numSections = nt->FileHeader.NumberOfSections;
138         for( n = 0; n < numSections; ++n )
139         {
140             PIMAGE_SECTION_HEADER section = firstSection + n;
141             char name[9] = {0};
142             size_t i;
143             StringCchCopyNA(name, _countof(name), (PCSTR)section->Name, 8);
144 
145             for( i = 0; g_Sections[i].Name; ++i )
146             {
147                 if( !_strnicmp(name, g_Sections[i].Name, 8) )
148                 {
149                     if( g_Sections[i].Required )
150                     {
151                         DWORD Flags = g_Sections[i].Required & section->Characteristics;
152                         ok(Flags == g_Sections[i].Required,
153                             "Missing required Characteristics on %s: %s\n",
154                             name, Chr2Str(Flags ^ g_Sections[i].Required));
155                     }
156                     if( g_Sections[i].Disallowed )
157                     {
158                         DWORD Flags = g_Sections[i].Disallowed & section->Characteristics;
159                         ok(!Flags, "Disallowed section Characteristics on %s: %s\n",
160                             name, Chr2Str(section->Characteristics));
161                     }
162                     break;
163                 }
164             }
165         }
166         FreeLibrary(mod);
167     }
168     else
169     {
170         skip("Couldn't load ntoskrnl.exe as datafile\n");
171     }
172 }
173 
174