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