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