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