1 /*
2 * PROJECT: ReactOS api tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Test for LdrEnumResources
5 * PROGRAMMER: Timo Kreuzer
6 */
7
8 #include "precomp.h"
9
10 #include <pseh/pseh2.h>
11
12 typedef struct _TEST_RESOURCES
13 {
14 IMAGE_RESOURCE_DIRECTORY TypeDirectory;
15 IMAGE_RESOURCE_DIRECTORY_ENTRY TypeEntries[2];
16 IMAGE_RESOURCE_DIRECTORY Name1Directory;
17 IMAGE_RESOURCE_DIRECTORY_ENTRY Name1Entries[2];
18 IMAGE_RESOURCE_DIRECTORY Name2Directory;
19 IMAGE_RESOURCE_DIRECTORY_ENTRY Name2Entries[2];
20 IMAGE_RESOURCE_DIRECTORY Lang1Directory;
21 IMAGE_RESOURCE_DIRECTORY_ENTRY Lang1Entries[2];
22 IMAGE_RESOURCE_DIRECTORY Lang2Directory;
23 IMAGE_RESOURCE_DIRECTORY_ENTRY Lang2Entries[2];
24 IMAGE_RESOURCE_DIRECTORY Lang3Directory;
25 IMAGE_RESOURCE_DIRECTORY_ENTRY Lang3Entries[2];
26 IMAGE_RESOURCE_DIRECTORY Lang4Directory;
27 IMAGE_RESOURCE_DIRECTORY_ENTRY Lang4Entries[2];
28 IMAGE_RESOURCE_DATA_ENTRY DataEntries[8];
29 IMAGE_RESOURCE_DIRECTORY_STRING Name1String;
30 ULONG StringIndex;
31 WCHAR StringBuffer[20];
32 } TEST_RESOURCES, *PTEST_RESOURCES;
33
34 typedef struct _TEST_IMAGE
35 {
36 IMAGE_DOS_HEADER DosHeader;
37 IMAGE_NT_HEADERS NtHeaders;
38 IMAGE_SECTION_HEADER SectionHeaders[1];
39 TEST_RESOURCES Resources;
40 } TEST_IMAGE, *PTEST_IMAGE;
41
42 static
43 VOID
InitializeResourceDirectory(PIMAGE_RESOURCE_DIRECTORY ResourceDirectory,USHORT NumberOfNamedEntries,USHORT NumberOfIdEntries)44 InitializeResourceDirectory(
45 PIMAGE_RESOURCE_DIRECTORY ResourceDirectory,
46 USHORT NumberOfNamedEntries,
47 USHORT NumberOfIdEntries)
48 {
49 ResourceDirectory->Characteristics = 0;
50 ResourceDirectory->TimeDateStamp = 0;
51 ResourceDirectory->MajorVersion = 0;
52 ResourceDirectory->MinorVersion = 0;
53 ResourceDirectory->NumberOfNamedEntries = NumberOfNamedEntries;
54 ResourceDirectory->NumberOfIdEntries = NumberOfIdEntries;
55 }
56
57 static
58 VOID
InitializeNamedEntry(PTEST_RESOURCES Resource,PIMAGE_RESOURCE_DIRECTORY_ENTRY DirEntry,PWCHAR Name,PVOID Data)59 InitializeNamedEntry(
60 PTEST_RESOURCES Resource,
61 PIMAGE_RESOURCE_DIRECTORY_ENTRY DirEntry,
62 PWCHAR Name,
63 PVOID Data)
64 {
65 DirEntry->Name = Resource->StringIndex * 2 + FIELD_OFFSET(TEST_RESOURCES, StringBuffer);
66 DirEntry->NameIsString = 1;
67 DirEntry->OffsetToData = (PUCHAR)Data - (PUCHAR)Resource;
68 if (DirEntry < Resource->Lang1Entries)
69 DirEntry->DataIsDirectory = 1;
70 Resource->StringBuffer[Resource->StringIndex] = (USHORT)wcslen(Name);
71 wcscpy(&Resource->StringBuffer[Resource->StringIndex + 1], Name);
72 Resource->StringIndex += Resource->StringBuffer[Resource->StringIndex] * 2 + 1;
73 }
74
75 static
76 VOID
InitializeIdEntry(PTEST_RESOURCES Resource,PIMAGE_RESOURCE_DIRECTORY_ENTRY DirEntry,USHORT Id,PVOID Data)77 InitializeIdEntry(
78 PTEST_RESOURCES Resource,
79 PIMAGE_RESOURCE_DIRECTORY_ENTRY DirEntry,
80 USHORT Id,
81 PVOID Data)
82 {
83 DirEntry->Name = Id;
84 DirEntry->NameIsString = 0;
85 DirEntry->OffsetToData = (PUCHAR)Data - (PUCHAR)Resource;
86 if (DirEntry < Resource->Lang1Entries)
87 DirEntry->DataIsDirectory = 1;
88 }
89
90 static
91 VOID
InitializeDataEntry(PVOID ImageBase,PIMAGE_RESOURCE_DATA_ENTRY DataEntry,PVOID Data,ULONG Size)92 InitializeDataEntry(
93 PVOID ImageBase,
94 PIMAGE_RESOURCE_DATA_ENTRY DataEntry,
95 PVOID Data,
96 ULONG Size)
97 {
98
99 DataEntry->OffsetToData = (PUCHAR)Data - (PUCHAR)ImageBase;
100 DataEntry->Size = Size;
101 DataEntry->CodePage = 0;
102 DataEntry->Reserved = 0;
103 }
104
105 static
106 VOID
InitializeTestResource(PVOID ImageBase,PTEST_RESOURCES Resource)107 InitializeTestResource(
108 PVOID ImageBase,
109 PTEST_RESOURCES Resource)
110 {
111
112 memset(Resource->StringBuffer, 0, sizeof(Resource->StringBuffer));
113 Resource->StringIndex = 0;
114
115 InitializeResourceDirectory(&Resource->TypeDirectory, 0, 2);
116 InitializeIdEntry(Resource, &Resource->TypeEntries[0], 1, &Resource->Name1Directory);
117 InitializeIdEntry(Resource, &Resource->TypeEntries[1], 2, &Resource->Name2Directory);
118
119 InitializeResourceDirectory(&Resource->Name1Directory, 1, 1);
120 InitializeNamedEntry(Resource, &Resource->Name1Entries[0], L"TEST", &Resource->Lang1Directory);
121 InitializeIdEntry(Resource, &Resource->Name1Entries[1], 7, &Resource->Lang2Directory);
122
123 InitializeResourceDirectory(&Resource->Name2Directory, 2, 0);
124 InitializeNamedEntry(Resource, &Resource->Name2Entries[0], L"LOL", &Resource->Lang3Directory);
125 InitializeNamedEntry(Resource, &Resource->Name2Entries[1], L"xD", &Resource->Lang4Directory);
126
127 InitializeResourceDirectory(&Resource->Lang1Directory, 0, 2);
128 InitializeIdEntry(Resource, &Resource->Lang1Entries[0], 0x409, &Resource->DataEntries[0]);
129 InitializeIdEntry(Resource, &Resource->Lang1Entries[1], 0x407, &Resource->DataEntries[1]);
130
131 InitializeResourceDirectory(&Resource->Lang2Directory, 0, 2);
132 InitializeIdEntry(Resource, &Resource->Lang2Entries[0], 0x408, &Resource->DataEntries[2]);
133 InitializeIdEntry(Resource, &Resource->Lang2Entries[1], 0x406, &Resource->DataEntries[3]);
134
135 InitializeResourceDirectory(&Resource->Lang3Directory, 0, 2);
136 InitializeIdEntry(Resource, &Resource->Lang3Entries[0], 0x405, &Resource->DataEntries[4]);
137 InitializeIdEntry(Resource, &Resource->Lang3Entries[1], 0x403, &Resource->DataEntries[5]);
138
139 InitializeResourceDirectory(&Resource->Lang4Directory, 0, 2);
140 InitializeIdEntry(Resource, &Resource->Lang4Entries[0], 0x402, &Resource->DataEntries[6]);
141 InitializeIdEntry(Resource, &Resource->Lang4Entries[1], 0x404, &Resource->DataEntries[7]);
142
143 InitializeDataEntry(ImageBase, &Resource->DataEntries[0], Resource->StringBuffer + 0, 2);
144 InitializeDataEntry(ImageBase, &Resource->DataEntries[1], Resource->StringBuffer + 2, 4);
145 InitializeDataEntry(ImageBase, &Resource->DataEntries[2], Resource->StringBuffer + 4, 6);
146 InitializeDataEntry(ImageBase, &Resource->DataEntries[3], Resource->StringBuffer + 6, 8);
147 InitializeDataEntry(ImageBase, &Resource->DataEntries[4], Resource->StringBuffer + 8, 10);
148 InitializeDataEntry(ImageBase, &Resource->DataEntries[5], Resource->StringBuffer + 10, 12);
149 InitializeDataEntry(ImageBase, &Resource->DataEntries[6], Resource->StringBuffer + 12, 14);
150 InitializeDataEntry(ImageBase, &Resource->DataEntries[7], Resource->StringBuffer + 14, 16);
151
152 }
153
154 VOID
InitializeTestImage(PTEST_IMAGE TestImage)155 InitializeTestImage(
156 PTEST_IMAGE TestImage)
157 {
158 PIMAGE_DATA_DIRECTORY ResourceDirectory;
159
160 TestImage->DosHeader.e_magic = IMAGE_DOS_SIGNATURE;
161 TestImage->DosHeader.e_lfanew = sizeof(IMAGE_DOS_HEADER);
162
163 TestImage->NtHeaders.Signature = IMAGE_NT_SIGNATURE;
164
165 TestImage->NtHeaders.FileHeader.Machine = IMAGE_FILE_MACHINE_NATIVE;
166 TestImage->NtHeaders.FileHeader.NumberOfSections = 1;
167 TestImage->NtHeaders.FileHeader.TimeDateStamp = 0;
168 TestImage->NtHeaders.FileHeader.PointerToSymbolTable = 0;
169 TestImage->NtHeaders.FileHeader.NumberOfSymbols = 0;
170 TestImage->NtHeaders.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER);
171 TestImage->NtHeaders.FileHeader.Characteristics = 0;
172
173 #ifdef _WIN64
174 TestImage->NtHeaders.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR64_MAGIC;
175 #else
176 TestImage->NtHeaders.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR32_MAGIC;
177 #endif
178 TestImage->NtHeaders.OptionalHeader.ImageBase = (DWORD_PTR)TestImage;
179 TestImage->NtHeaders.OptionalHeader.SizeOfImage = sizeof(TEST_IMAGE);
180 TestImage->NtHeaders.OptionalHeader.SizeOfHeaders = sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS);
181 TestImage->NtHeaders.OptionalHeader.NumberOfRvaAndSizes = ARRAYSIZE(TestImage->NtHeaders.OptionalHeader.DataDirectory);
182
183 ResourceDirectory = &TestImage->NtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
184 ResourceDirectory->VirtualAddress = FIELD_OFFSET(TEST_IMAGE, Resources);
185 ResourceDirectory->Size = sizeof(TEST_RESOURCES);
186
187 strcpy((char*)TestImage->SectionHeaders[0].Name, ".rsrc");
188 TestImage->SectionHeaders[0].Misc.VirtualSize = sizeof(TEST_IMAGE);
189 TestImage->SectionHeaders[0].VirtualAddress = FIELD_OFFSET(TEST_IMAGE, Resources);
190 TestImage->SectionHeaders[0].SizeOfRawData = sizeof(TEST_IMAGE);
191 TestImage->SectionHeaders[0].PointerToRawData = FIELD_OFFSET(TEST_IMAGE, Resources);
192 TestImage->SectionHeaders[0].PointerToRelocations = 0;
193 TestImage->SectionHeaders[0].PointerToLinenumbers = 0;
194 TestImage->SectionHeaders[0].NumberOfRelocations = 0;
195 TestImage->SectionHeaders[0].NumberOfLinenumbers = 0;
196 TestImage->SectionHeaders[0].Characteristics = 0;
197
198 InitializeTestResource(TestImage, &TestImage->Resources);
199 }
200
201 #define ok_nwstr(str1, str2, count) \
202 ok(wcsncmp((PWCHAR)str1, (PWCHAR)str2, count) == 0, \
203 "string is wrong, expected: '%S', got '%S'\n", str1, str2); \
204
205 #define ok_enumres(_Res, _Type, _Name, _Lang, _Data, _Size) \
206 ok_dec((_Res)->Type, _Type); \
207 if ((ULONG_PTR)(_Name) > 0xFFFF) \
208 { \
209 ok_size_t(*(WORD*)((_Res)->Name), wcslen((PWCHAR)(_Name))); \
210 ok_nwstr((PWCHAR)((_Res)->Name + 2), (PWCHAR)_Name, *(WORD*)((_Res)->Name)); \
211 } \
212 else \
213 { \
214 ok_dec((_Res)->Name, (ULONG_PTR)_Name); \
215 } \
216 ok_hex((_Res)->Language, _Lang); \
217 ok_ptr((PVOID)(_Res)->Data, _Data); \
218 ok_dec((_Res)->Size, _Size); \
219 ok_dec((_Res)->Reserved, 0);
220
221 static
222 void
Test_Data(PTEST_IMAGE TestImage)223 Test_Data(PTEST_IMAGE TestImage)
224 {
225 LDR_RESOURCE_INFO ResourceInfo;
226 LDR_ENUM_RESOURCE_INFO EnumRes[8];
227 ULONG ResourceCount;
228 NTSTATUS Status;
229
230 InitializeTestImage(TestImage);
231
232 memset(EnumRes, 0xcc, sizeof(EnumRes));
233
234 ResourceInfo.Type = 1;
235 ResourceInfo.Name = 1;
236 ResourceInfo.Language = 0x408;
237 ResourceCount = 8;
238 Status = LdrEnumResources(TestImage, &ResourceInfo, 0, &ResourceCount, EnumRes);
239 ok_hex(Status, STATUS_SUCCESS);
240 ok_dec(ResourceCount, 8);
241
242 ok_ptr((PVOID)EnumRes[0].Data, TestImage->Resources.StringBuffer);
243 ok_dec(EnumRes[0].Size, 2);
244
245 ok_enumres(&EnumRes[0], 1, L"TEST", 0x409, TestImage->Resources.StringBuffer, 2)
246 ok_enumres(&EnumRes[1], 1, L"TEST", 0x407, TestImage->Resources.StringBuffer + 2, 4)
247 ok_enumres(&EnumRes[2], 1, 7, 0x408, TestImage->Resources.StringBuffer + 4, 6)
248 ok_enumres(&EnumRes[3], 1, 7, 0x406, TestImage->Resources.StringBuffer + 6, 8)
249 ok_enumres(&EnumRes[4], 2, L"LOL", 0x405, TestImage->Resources.StringBuffer + 8, 10)
250 ok_enumres(&EnumRes[5], 2, L"LOL", 0x403, TestImage->Resources.StringBuffer + 10, 12)
251 ok_enumres(&EnumRes[6], 2, L"xD", 0x402, TestImage->Resources.StringBuffer + 12, 14)
252 ok_enumres(&EnumRes[7], 2, L"xD", 0x404, TestImage->Resources.StringBuffer + 14, 16)
253
254 Status = LdrEnumResources(TestImage, &ResourceInfo, 1, &ResourceCount, EnumRes);
255 ok_hex(Status, STATUS_SUCCESS);
256 ok_dec(ResourceCount, 4);
257
258 }
259
260
261 static
262 void
Test_Parameters(PTEST_IMAGE TestImage)263 Test_Parameters(PTEST_IMAGE TestImage)
264 {
265 LDR_RESOURCE_INFO ResourceInfo;
266 LDR_ENUM_RESOURCE_INFO Resources[8];
267 ULONG ResourceCount;
268 NTSTATUS Status;
269
270 InitializeTestImage(TestImage);
271
272 ResourceInfo.Type = 6;
273 ResourceInfo.Name = 1;
274 ResourceInfo.Language = 0x409;
275
276 ResourceCount = 8;
277 Status = LdrEnumResources(TestImage, &ResourceInfo, 3, &ResourceCount, Resources);
278 ok_hex(Status, STATUS_SUCCESS);
279 ok_dec(ResourceCount, 0);
280
281 ResourceInfo.Type = 1;
282 ResourceInfo.Name = 7;
283 ResourceInfo.Language = 0x406;
284 ResourceCount = 8;
285 Status = LdrEnumResources(TestImage, &ResourceInfo, 0, &ResourceCount, Resources);
286 ok_hex(Status, STATUS_SUCCESS);
287 ok_dec(ResourceCount, 8);
288
289 ResourceCount = 8;
290 Status = LdrEnumResources(TestImage, &ResourceInfo, 1, &ResourceCount, Resources);
291 ok_hex(Status, STATUS_SUCCESS);
292 ok_dec(ResourceCount, 4);
293
294 ResourceCount = 8;
295 Status = LdrEnumResources(TestImage, &ResourceInfo, 2, &ResourceCount, Resources);
296 ok_hex(Status, STATUS_SUCCESS);
297 ok_dec(ResourceCount, 2);
298
299 ResourceCount = 8;
300 Status = LdrEnumResources(TestImage, &ResourceInfo, 3, &ResourceCount, Resources);
301 ok_hex(Status, STATUS_SUCCESS);
302 ok_dec(ResourceCount, 1);
303
304 ResourceCount = 8;
305 Status = LdrEnumResources(TestImage, &ResourceInfo, 99, &ResourceCount, Resources);
306 ok_hex(Status, STATUS_SUCCESS);
307 ok_dec(ResourceCount, 1);
308
309 ResourceCount = 0;
310 Status = LdrEnumResources(TestImage, &ResourceInfo, 0, &ResourceCount, Resources);
311 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
312 ok_dec(ResourceCount, 8);
313
314 ResourceCount = 7;
315 Status = LdrEnumResources(TestImage, &ResourceInfo, 0, &ResourceCount, Resources);
316 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
317 ok_dec(ResourceCount, 8);
318
319 ResourceCount = 8;
320 Status = LdrEnumResources(NULL, &ResourceInfo, 1, &ResourceCount, Resources);
321 ok_hex(Status, STATUS_RESOURCE_DATA_NOT_FOUND);
322 ok_dec(ResourceCount, 0);
323
324 ResourceCount = 8;
325 Status = LdrEnumResources(TestImage, &ResourceInfo, 1, &ResourceCount, NULL);
326 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
327 ok_dec(ResourceCount, 4);
328
329 ResourceCount = 8;
330 _SEH2_TRY
331 {
332 Status = LdrEnumResources(NULL, NULL, 0, NULL, NULL);
333 }
334 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
335 {
336 Status = 0xDeadC0de;
337 }
338 _SEH2_END
339 ok_hex(Status, 0xDeadC0de);
340
341 ResourceCount = 42;
342 _SEH2_TRY
343 {
344 Status = LdrEnumResources(TestImage, &ResourceInfo, 1, NULL, Resources);
345 }
346 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
347 {
348 Status = 0xDeadC0de;
349 }
350 _SEH2_END
351 ok_hex(Status, 0xDeadC0de);
352 ok_dec(ResourceCount, 42);
353
354 ResourceCount = 8;
355 Status = LdrEnumResources(TestImage + 2, &ResourceInfo, 1, &ResourceCount, NULL);
356 ok_hex(Status, STATUS_RESOURCE_DATA_NOT_FOUND);
357 ok_dec(ResourceCount, 0);
358
359 TestImage->Resources.TypeEntries[0].DataIsDirectory = 0;
360 Status = LdrEnumResources(TestImage, &ResourceInfo, 1, &ResourceCount, NULL);
361 ok_hex(Status, STATUS_INVALID_IMAGE_FORMAT);
362 ok_dec(ResourceCount, 0);
363
364 }
365
START_TEST(LdrEnumResources)366 START_TEST(LdrEnumResources)
367 {
368 TEST_IMAGE TestImage;
369 RtlZeroMemory(&TestImage, sizeof(TestImage));
370
371 Test_Parameters(&TestImage);
372 Test_Data(&TestImage);
373
374 }
375