kernel32/tests: Support alternate results in the loader test on Vista.
[wine/multimedia.git] / dlls / kernel32 / tests / loader.c
blob37f4c928da9a7f695f7fd31167e7b03ae1a98524
1 /*
2 * Unit test suite for the PE loader.
4 * Copyright 2006 Dmitry Timoshkov
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
22 #include <assert.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "wine/test.h"
28 #define ALIGN_SIZE(size, alignment) (((size) + (alignment - 1)) & ~((alignment - 1)))
30 static PVOID RVAToAddr(DWORD_PTR rva, HMODULE module)
32 if (rva == 0)
33 return NULL;
34 return ((char*) module) + rva;
37 static const struct
39 WORD e_magic; /* 00: MZ Header signature */
40 WORD unused[29];
41 DWORD e_lfanew; /* 3c: Offset to extended header */
42 } dos_header =
44 IMAGE_DOS_SIGNATURE, { 0 }, sizeof(dos_header)
47 static IMAGE_NT_HEADERS nt_header =
49 IMAGE_NT_SIGNATURE, /* Signature */
51 #if defined __i386__
52 IMAGE_FILE_MACHINE_I386, /* Machine */
53 #elif defined __x86_64__
54 IMAGE_FILE_MACHINE_AMD64, /* Machine */
55 #else
56 # error You must specify the machine type
57 #endif
58 1, /* NumberOfSections */
59 0, /* TimeDateStamp */
60 0, /* PointerToSymbolTable */
61 0, /* NumberOfSymbols */
62 sizeof(IMAGE_OPTIONAL_HEADER), /* SizeOfOptionalHeader */
63 IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL /* Characteristics */
65 { IMAGE_NT_OPTIONAL_HDR_MAGIC, /* Magic */
66 1, /* MajorLinkerVersion */
67 0, /* MinorLinkerVersion */
68 0, /* SizeOfCode */
69 0, /* SizeOfInitializedData */
70 0, /* SizeOfUninitializedData */
71 0, /* AddressOfEntryPoint */
72 0x10, /* BaseOfCode, also serves as e_lfanew in the truncated MZ header */
73 0, /* BaseOfData */
74 0x10000000, /* ImageBase */
75 0, /* SectionAlignment */
76 0, /* FileAlignment */
77 4, /* MajorOperatingSystemVersion */
78 0, /* MinorOperatingSystemVersion */
79 1, /* MajorImageVersion */
80 0, /* MinorImageVersion */
81 4, /* MajorSubsystemVersion */
82 0, /* MinorSubsystemVersion */
83 0, /* Win32VersionValue */
84 sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x1000, /* SizeOfImage */
85 sizeof(dos_header) + sizeof(nt_header), /* SizeOfHeaders */
86 0, /* CheckSum */
87 IMAGE_SUBSYSTEM_WINDOWS_CUI, /* Subsystem */
88 0, /* DllCharacteristics */
89 0, /* SizeOfStackReserve */
90 0, /* SizeOfStackCommit */
91 0, /* SizeOfHeapReserve */
92 0, /* SizeOfHeapCommit */
93 0, /* LoaderFlags */
94 0, /* NumberOfRvaAndSizes */
95 { { 0 } } /* DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES] */
99 static IMAGE_SECTION_HEADER section =
101 ".rodata", /* Name */
102 { 0x10 }, /* Misc */
103 0, /* VirtualAddress */
104 0x0a, /* SizeOfRawData */
105 0, /* PointerToRawData */
106 0, /* PointerToRelocations */
107 0, /* PointerToLinenumbers */
108 0, /* NumberOfRelocations */
109 0, /* NumberOfLinenumbers */
110 IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ, /* Characteristics */
113 static void test_Loader(void)
115 static const struct test_data
117 const void *dos_header;
118 DWORD size_of_dos_header;
119 WORD number_of_sections, size_of_optional_header;
120 DWORD section_alignment, file_alignment;
121 DWORD size_of_image, size_of_headers;
122 DWORD error; /* 0 means LoadLibrary should succeed */
123 DWORD alt_error; /* alternate error */
124 } td[] =
126 { &dos_header, sizeof(dos_header),
127 1, 0, 0, 0, 0, 0,
128 ERROR_BAD_EXE_FORMAT
130 { &dos_header, sizeof(dos_header),
131 1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x1000,
132 sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0xe00,
133 sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER),
134 ERROR_BAD_EXE_FORMAT /* XP doesn't like too small image size */
136 { &dos_header, sizeof(dos_header),
137 1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x1000,
138 sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x1000,
139 sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER),
140 ERROR_SUCCESS
142 { &dos_header, sizeof(dos_header),
143 1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x1000,
144 0x1f00,
145 0x1000,
146 ERROR_SUCCESS
148 { &dos_header, sizeof(dos_header),
149 1, sizeof(IMAGE_OPTIONAL_HEADER), 0x200, 0x200,
150 sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x200,
151 sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER),
152 ERROR_SUCCESS, ERROR_INVALID_ADDRESS /* vista is more strict */
154 { &dos_header, sizeof(dos_header),
155 1, sizeof(IMAGE_OPTIONAL_HEADER), 0x200, 0x1000,
156 sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x1000,
157 sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER),
158 ERROR_BAD_EXE_FORMAT /* XP doesn't like alignments */
160 { &dos_header, sizeof(dos_header),
161 1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x200,
162 sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x1000,
163 sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER),
164 ERROR_SUCCESS
166 { &dos_header, sizeof(dos_header),
167 1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x200,
168 sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x1000,
169 0x200,
170 ERROR_SUCCESS
172 /* Mandatory are all fields up to SizeOfHeaders, everything else
173 * is really optional (at least that's true for XP).
175 { &dos_header, sizeof(dos_header),
176 1, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200,
177 sizeof(dos_header) + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum) + sizeof(IMAGE_SECTION_HEADER) + 0x10,
178 sizeof(dos_header) + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum) + sizeof(IMAGE_SECTION_HEADER),
179 ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT /* vista is more strict */
181 { &dos_header, sizeof(dos_header),
182 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200,
183 0xd0, /* beyond of the end of file */
184 0xc0, /* beyond of the end of file */
185 ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT /* vista is more strict */
187 { &dos_header, sizeof(dos_header),
188 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200,
189 0x1000,
191 ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT /* vista is more strict */
193 { &dos_header, sizeof(dos_header),
194 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200,
197 ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT /* vista is more strict */
199 #if 0 /* not power of 2 alignments need more test cases */
200 { &dos_header, sizeof(dos_header),
201 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x300, 0x300,
204 ERROR_BAD_EXE_FORMAT /* alignment is not power of 2 */
206 #endif
207 { &dos_header, sizeof(dos_header),
208 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 4, 4,
211 ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT /* vista is more strict */
213 { &dos_header, sizeof(dos_header),
214 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 1, 1,
217 ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT /* vista is more strict */
219 { &dos_header, sizeof(dos_header),
220 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200,
223 ERROR_BAD_EXE_FORMAT /* image size == 0 -> failure */
225 /* the following data mimics the PE image which upack creates */
226 { &dos_header, 0x10,
227 1, 0x148, 0x1000, 0x200,
228 sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x1000,
229 0x200,
230 ERROR_SUCCESS
232 /* Minimal PE image that XP is able to load: 92 bytes */
233 { &dos_header, 0x04,
234 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum),
235 0x04 /* also serves as e_lfanew in the truncated MZ header */, 0x04,
238 ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT /* vista is more strict */
241 static const char filler[0x1000];
242 static const char section_data[0x10] = "section data";
243 int i;
244 DWORD dummy, file_size, file_align;
245 HANDLE hfile;
246 HMODULE hlib, hlib_as_data_file;
247 SYSTEM_INFO si;
248 char temp_path[MAX_PATH];
249 char dll_name[MAX_PATH];
251 GetSystemInfo(&si);
252 trace("system page size 0x%04x\n", si.dwPageSize);
254 /* prevent displaying of the "Unable to load this DLL" message box */
255 SetErrorMode(SEM_FAILCRITICALERRORS);
257 GetTempPath(MAX_PATH, temp_path);
259 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
261 GetTempFileName(temp_path, "ldr", 0, dll_name);
263 /*trace("creating %s\n", dll_name);*/
264 hfile = CreateFileA(dll_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
265 if (hfile == INVALID_HANDLE_VALUE)
267 ok(0, "could not create %s\n", dll_name);
268 break;
271 SetLastError(0xdeadbeef);
272 ok(WriteFile(hfile, td[i].dos_header, td[i].size_of_dos_header, &dummy, NULL),
273 "WriteFile error %d\n", GetLastError());
275 nt_header.FileHeader.NumberOfSections = td[i].number_of_sections;
276 nt_header.FileHeader.SizeOfOptionalHeader = td[i].size_of_optional_header;
278 nt_header.OptionalHeader.SectionAlignment = td[i].section_alignment;
279 nt_header.OptionalHeader.FileAlignment = td[i].file_alignment;
280 nt_header.OptionalHeader.SizeOfImage = td[i].size_of_image;
281 nt_header.OptionalHeader.SizeOfHeaders = td[i].size_of_headers;
282 SetLastError(0xdeadbeef);
283 ok(WriteFile(hfile, &nt_header, sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER), &dummy, NULL),
284 "WriteFile error %d\n", GetLastError());
286 if (nt_header.FileHeader.SizeOfOptionalHeader)
288 SetLastError(0xdeadbeef);
289 ok(WriteFile(hfile, &nt_header.OptionalHeader,
290 min(nt_header.FileHeader.SizeOfOptionalHeader, sizeof(IMAGE_OPTIONAL_HEADER)),
291 &dummy, NULL),
292 "WriteFile error %d\n", GetLastError());
293 if (nt_header.FileHeader.SizeOfOptionalHeader > sizeof(IMAGE_OPTIONAL_HEADER))
295 file_align = nt_header.FileHeader.SizeOfOptionalHeader - sizeof(IMAGE_OPTIONAL_HEADER);
296 assert(file_align < sizeof(filler));
297 SetLastError(0xdeadbeef);
298 ok(WriteFile(hfile, filler, file_align, &dummy, NULL),
299 "WriteFile error %d\n", GetLastError());
303 assert(nt_header.FileHeader.NumberOfSections <= 1);
304 if (nt_header.FileHeader.NumberOfSections)
306 if (nt_header.OptionalHeader.SectionAlignment >= si.dwPageSize)
308 section.PointerToRawData = td[i].size_of_dos_header;
309 section.VirtualAddress = nt_header.OptionalHeader.SectionAlignment;
310 section.Misc.VirtualSize = section.SizeOfRawData * 10;
312 else
314 section.PointerToRawData = nt_header.OptionalHeader.SizeOfHeaders;
315 section.VirtualAddress = nt_header.OptionalHeader.SizeOfHeaders;
316 section.Misc.VirtualSize = 5;
319 SetLastError(0xdeadbeef);
320 ok(WriteFile(hfile, &section, sizeof(section), &dummy, NULL),
321 "WriteFile error %d\n", GetLastError());
323 /* section data */
324 SetLastError(0xdeadbeef);
325 ok(WriteFile(hfile, section_data, sizeof(section_data), &dummy, NULL),
326 "WriteFile error %d\n", GetLastError());
329 file_size = GetFileSize(hfile, NULL);
330 CloseHandle(hfile);
332 SetLastError(0xdeadbeef);
333 hlib = LoadLibrary(dll_name);
334 if (hlib)
336 MEMORY_BASIC_INFORMATION info;
338 ok( td[i].error == ERROR_SUCCESS, "%d: should have failed\n", i );
340 SetLastError(0xdeadbeef);
341 ok(VirtualQuery(hlib, &info, sizeof(info)) == sizeof(info),
342 "%d: VirtualQuery error %d\n", i, GetLastError());
343 ok(info.BaseAddress == hlib, "%d: %p != %p\n", i, info.BaseAddress, hlib);
344 ok(info.AllocationBase == hlib, "%d: %p != %p\n", i, info.AllocationBase, hlib);
345 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect);
346 ok(info.RegionSize == ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, si.dwPageSize), "%d: got %lx != expected %x\n",
347 i, info.RegionSize, ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, si.dwPageSize));
348 ok(info.State == MEM_COMMIT, "%d: %x != MEM_COMMIT\n", i, info.State);
349 if (nt_header.OptionalHeader.SectionAlignment < si.dwPageSize)
350 ok(info.Protect == PAGE_EXECUTE_WRITECOPY, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i, info.Protect);
351 else
352 ok(info.Protect == PAGE_READONLY, "%d: %x != PAGE_READONLY\n", i, info.Protect);
353 ok(info.Type == SEC_IMAGE, "%d: %x != SEC_IMAGE\n", i, info.Type);
355 SetLastError(0xdeadbeef);
356 ok(VirtualQuery((char *)hlib + info.RegionSize, &info, sizeof(info)) == sizeof(info),
357 "%d: VirtualQuery error %d\n", i, GetLastError());
358 if (nt_header.OptionalHeader.SectionAlignment == si.dwPageSize ||
359 nt_header.OptionalHeader.SectionAlignment == nt_header.OptionalHeader.FileAlignment)
361 ok(info.BaseAddress == (char *)hlib + ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, si.dwPageSize), "%d: got %p != expected %p\n",
362 i, info.BaseAddress, (char *)hlib + ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, si.dwPageSize));
363 ok(info.AllocationBase == 0, "%d: %p != 0\n", i, info.AllocationBase);
364 ok(info.AllocationProtect == 0, "%d: %x != 0\n", i, info.AllocationProtect);
365 /*ok(info.RegionSize == not_practical_value, "%d: %lx != not_practical_value\n", i, info.RegionSize);*/
366 ok(info.State == MEM_FREE, "%d: %x != MEM_FREE\n", i, info.State);
367 ok(info.Type == 0, "%d: %x != 0\n", i, info.Type);
368 ok(info.Protect == PAGE_NOACCESS, "%d: %x != PAGE_NOACCESS\n", i, info.Protect);
370 else
372 ok(info.Protect == PAGE_EXECUTE_WRITECOPY, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i, info.Protect);
373 ok(info.BaseAddress == hlib, "%d: got %p != expected %p\n", i, info.BaseAddress, hlib);
374 ok(info.AllocationBase == hlib, "%d: %p != %p\n", i, info.AllocationBase, hlib);
375 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect);
376 ok(info.RegionSize == ALIGN_SIZE(file_size, si.dwPageSize), "%d: got %lx != expected %x\n",
377 i, info.RegionSize, ALIGN_SIZE(file_size, si.dwPageSize));
378 ok(info.State == MEM_COMMIT, "%d: %x != MEM_COMMIT\n", i, info.State);
379 ok(info.Protect == PAGE_READONLY, "%d: %x != PAGE_READONLY\n", i, info.Protect);
380 ok(info.Type == SEC_IMAGE, "%d: %x != SEC_IMAGE\n", i, info.Type);
383 /* header: check the zeroing of alignment */
384 if (nt_header.OptionalHeader.SectionAlignment >= si.dwPageSize)
386 const char *start;
387 int size;
389 start = (const char *)hlib + nt_header.OptionalHeader.SizeOfHeaders;
390 size = ALIGN_SIZE((ULONG_PTR)start, si.dwPageSize) - (ULONG_PTR)start;
391 ok(!memcmp(start, filler, size), "%d: header alignment is not cleared\n", i);
394 if (nt_header.FileHeader.NumberOfSections)
396 SetLastError(0xdeadbeef);
397 ok(VirtualQuery((char *)hlib + section.VirtualAddress, &info, sizeof(info)) == sizeof(info),
398 "%d: VirtualQuery error %d\n", i, GetLastError());
399 if (nt_header.OptionalHeader.SectionAlignment < si.dwPageSize)
401 ok(info.BaseAddress == (char *)hlib, "%d: got %p != expected %p\n", i, info.BaseAddress, (char *)hlib);
402 ok(info.RegionSize == ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, si.dwPageSize), "%d: got %lx != expected %x\n",
403 i, info.RegionSize, ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, si.dwPageSize));
404 ok(info.Protect == PAGE_EXECUTE_WRITECOPY, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i, info.Protect);
406 else
408 ok(info.BaseAddress == (char *)hlib + section.VirtualAddress, "%d: got %p != expected %p\n", i, info.BaseAddress, (char *)hlib + section.VirtualAddress);
409 ok(info.RegionSize == ALIGN_SIZE(section.Misc.VirtualSize, si.dwPageSize), "%d: got %lx != expected %x\n",
410 i, info.RegionSize, ALIGN_SIZE(section.Misc.VirtualSize, si.dwPageSize));
411 ok(info.Protect == PAGE_READONLY, "%d: %x != PAGE_READONLY\n", i, info.Protect);
413 ok(info.AllocationBase == hlib, "%d: %p != %p\n", i, info.AllocationBase, hlib);
414 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect);
415 ok(info.State == MEM_COMMIT, "%d: %x != MEM_COMMIT\n", i, info.State);
416 ok(info.Type == SEC_IMAGE, "%d: %x != SEC_IMAGE\n", i, info.Type);
418 if (nt_header.OptionalHeader.SectionAlignment >= si.dwPageSize)
419 ok(!memcmp((const char *)hlib + section.VirtualAddress + section.PointerToRawData, &nt_header, section.SizeOfRawData), "wrong section data\n");
420 else
421 ok(!memcmp((const char *)hlib + section.PointerToRawData, section_data, section.SizeOfRawData), "wrong section data\n");
423 /* check the zeroing of alignment */
424 if (nt_header.OptionalHeader.SectionAlignment >= si.dwPageSize)
426 const char *start;
427 int size;
429 start = (const char *)hlib + section.VirtualAddress + section.PointerToRawData + section.SizeOfRawData;
430 size = ALIGN_SIZE((ULONG_PTR)start, si.dwPageSize) - (ULONG_PTR)start;
431 ok(memcmp(start, filler, size), "%d: alignment should not be cleared\n", i);
435 SetLastError(0xdeadbeef);
436 hlib_as_data_file = LoadLibraryEx(dll_name, 0, LOAD_LIBRARY_AS_DATAFILE);
437 ok(hlib_as_data_file != 0, "LoadLibraryEx error %u\n", GetLastError());
438 ok(hlib_as_data_file == hlib, "hlib_as_file and hlib are different\n");
440 SetLastError(0xdeadbeef);
441 ok(FreeLibrary(hlib), "FreeLibrary error %d\n", GetLastError());
443 SetLastError(0xdeadbeef);
444 hlib = GetModuleHandle(dll_name);
445 ok(hlib != 0, "GetModuleHandle error %u\n", GetLastError());
447 SetLastError(0xdeadbeef);
448 ok(FreeLibrary(hlib_as_data_file), "FreeLibrary error %d\n", GetLastError());
450 hlib = GetModuleHandle(dll_name);
451 ok(!hlib, "GetModuleHandle should fail\n");
453 SetLastError(0xdeadbeef);
454 hlib_as_data_file = LoadLibraryEx(dll_name, 0, LOAD_LIBRARY_AS_DATAFILE);
455 ok(hlib_as_data_file != 0, "LoadLibraryEx error %u\n", GetLastError());
456 ok((ULONG_PTR)hlib_as_data_file & 1, "hlib_as_data_file is even\n");
458 hlib = GetModuleHandle(dll_name);
459 ok(!hlib, "GetModuleHandle should fail\n");
461 SetLastError(0xdeadbeef);
462 ok(FreeLibrary(hlib_as_data_file), "FreeLibrary error %d\n", GetLastError());
464 else
466 ok(td[i].error || td[i].alt_error, "%d: LoadLibrary should succeed\n", i);
468 if (GetLastError() == ERROR_GEN_FAILURE) /* Win9x, broken behaviour */
470 trace("skipping the loader test on Win9x\n");
471 DeleteFile(dll_name);
472 return;
475 ok(td[i].error == GetLastError() || td[i].alt_error == GetLastError(),
476 "%d: expected error %d or %d, got %d\n",
477 i, td[i].error, td[i].alt_error, GetLastError());
480 SetLastError(0xdeadbeef);
481 ok(DeleteFile(dll_name), "DeleteFile error %d\n", GetLastError());
485 /* Verify linking style of import descriptors */
486 static void test_ImportDescriptors(void)
488 HMODULE kernel32_module = NULL;
489 PIMAGE_DOS_HEADER d_header;
490 PIMAGE_NT_HEADERS nt_headers;
491 DWORD import_dir_size;
492 DWORD_PTR dir_offset;
493 PIMAGE_IMPORT_DESCRIPTOR import_chunk;
495 /* Load kernel32 module */
496 kernel32_module = GetModuleHandleA("kernel32.dll");
497 assert( kernel32_module != NULL );
499 /* Get PE header info from module image */
500 d_header = (PIMAGE_DOS_HEADER) kernel32_module;
501 nt_headers = (PIMAGE_NT_HEADERS) (((char*) d_header) +
502 d_header->e_lfanew);
504 /* Get size of import entry directory */
505 import_dir_size = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
506 if (!import_dir_size)
508 skip("Unable to continue testing due to missing import directory.\n");
509 return;
512 /* Get address of first import chunk */
513 dir_offset = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
514 import_chunk = RVAToAddr(dir_offset, kernel32_module);
515 ok(import_chunk != 0, "Invalid import_chunk: %p\n", import_chunk);
516 if (!import_chunk) return;
518 /* Iterate through import descriptors and verify set name,
519 * OriginalFirstThunk, and FirstThunk. Core Windows DLLs, such as
520 * kernel32.dll, don't use Borland-style linking, where the table of
521 * imported names is stored directly in FirstThunk and overwritten
522 * by the relocation, instead of being stored in OriginalFirstThunk.
523 * */
524 for (; import_chunk->FirstThunk; import_chunk++)
526 LPCSTR module_name = (LPCSTR) RVAToAddr(
527 import_chunk->Name, kernel32_module);
528 PIMAGE_THUNK_DATA name_table = (PIMAGE_THUNK_DATA) RVAToAddr(
529 import_chunk->OriginalFirstThunk, kernel32_module);
530 PIMAGE_THUNK_DATA iat = (PIMAGE_THUNK_DATA) RVAToAddr(
531 import_chunk->FirstThunk, kernel32_module);
532 ok(module_name != NULL, "Imported module name should not be NULL\n");
533 ok(name_table != NULL,
534 "Name table for imported module %s should not be NULL\n",
535 module_name);
536 ok(iat != NULL, "IAT for imported module %s should not be NULL\n",
537 module_name);
541 START_TEST(loader)
543 test_Loader();
544 test_ImportDescriptors();