kernel32/tests: A couple spelling fixes in a comment.
[wine.git] / dlls / kernel32 / tests / loader.c
blob7267fad490fad9bb31554729a3edb6afed66ab8a
1 /*
2 * Unit test suite for the PE loader.
4 * Copyright 2006,2011 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 #define NONAMELESSUNION
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <assert.h>
26 #include "ntstatus.h"
27 #define WIN32_NO_STATUS
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winternl.h"
31 #include "wine/test.h"
32 #include "delayloadhandler.h"
34 /* PROCESS_ALL_ACCESS in Vista+ PSDKs is incompatible with older Windows versions */
35 #define PROCESS_ALL_ACCESS_NT4 (PROCESS_ALL_ACCESS & ~0xf000)
37 #define ALIGN_SIZE(size, alignment) (((size) + (alignment - 1)) & ~((alignment - 1)))
39 struct PROCESS_BASIC_INFORMATION_PRIVATE
41 DWORD_PTR ExitStatus;
42 PPEB PebBaseAddress;
43 DWORD_PTR AffinityMask;
44 DWORD_PTR BasePriority;
45 ULONG_PTR UniqueProcessId;
46 ULONG_PTR InheritedFromUniqueProcessId;
49 static LONG *child_failures;
50 static WORD cb_count;
51 static DWORD page_size;
53 static NTSTATUS (WINAPI *pNtCreateSection)(HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *,
54 const LARGE_INTEGER *, ULONG, ULONG, HANDLE );
55 static NTSTATUS (WINAPI *pNtQuerySection)(HANDLE, SECTION_INFORMATION_CLASS, void *, SIZE_T, SIZE_T *);
56 static NTSTATUS (WINAPI *pNtMapViewOfSection)(HANDLE, HANDLE, PVOID *, ULONG, SIZE_T, const LARGE_INTEGER *, SIZE_T *, ULONG, ULONG, ULONG);
57 static NTSTATUS (WINAPI *pNtUnmapViewOfSection)(HANDLE, PVOID);
58 static NTSTATUS (WINAPI *pNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);
59 static NTSTATUS (WINAPI *pNtSetInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG);
60 static NTSTATUS (WINAPI *pNtTerminateProcess)(HANDLE, DWORD);
61 static void (WINAPI *pLdrShutdownProcess)(void);
62 static BOOLEAN (WINAPI *pRtlDllShutdownInProgress)(void);
63 static NTSTATUS (WINAPI *pNtAllocateVirtualMemory)(HANDLE, PVOID *, ULONG, SIZE_T *, ULONG, ULONG);
64 static NTSTATUS (WINAPI *pNtFreeVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG);
65 static NTSTATUS (WINAPI *pLdrLockLoaderLock)(ULONG, ULONG *, ULONG_PTR *);
66 static NTSTATUS (WINAPI *pLdrUnlockLoaderLock)(ULONG, ULONG_PTR);
67 static void (WINAPI *pRtlAcquirePebLock)(void);
68 static void (WINAPI *pRtlReleasePebLock)(void);
69 static PVOID (WINAPI *pResolveDelayLoadedAPI)(PVOID, PCIMAGE_DELAYLOAD_DESCRIPTOR,
70 PDELAYLOAD_FAILURE_DLL_CALLBACK, PVOID,
71 PIMAGE_THUNK_DATA ThunkAddress,ULONG);
72 static PVOID (WINAPI *pRtlImageDirectoryEntryToData)(HMODULE,BOOL,WORD,ULONG *);
73 static DWORD (WINAPI *pFlsAlloc)(PFLS_CALLBACK_FUNCTION);
74 static BOOL (WINAPI *pFlsSetValue)(DWORD, PVOID);
75 static PVOID (WINAPI *pFlsGetValue)(DWORD);
76 static BOOL (WINAPI *pFlsFree)(DWORD);
77 static BOOL (WINAPI *pIsWow64Process)(HANDLE,PBOOL);
79 static PVOID RVAToAddr(DWORD_PTR rva, HMODULE module)
81 if (rva == 0)
82 return NULL;
83 return ((char*) module) + rva;
86 static IMAGE_DOS_HEADER dos_header;
88 static const IMAGE_NT_HEADERS nt_header_template =
90 IMAGE_NT_SIGNATURE, /* Signature */
92 #if defined __i386__
93 IMAGE_FILE_MACHINE_I386, /* Machine */
94 #elif defined __x86_64__
95 IMAGE_FILE_MACHINE_AMD64, /* Machine */
96 #elif defined __powerpc__
97 IMAGE_FILE_MACHINE_POWERPC, /* Machine */
98 #elif defined __arm__
99 IMAGE_FILE_MACHINE_ARMNT, /* Machine */
100 #elif defined __aarch64__
101 IMAGE_FILE_MACHINE_ARM64, /* Machine */
102 #else
103 # error You must specify the machine type
104 #endif
105 1, /* NumberOfSections */
106 0, /* TimeDateStamp */
107 0, /* PointerToSymbolTable */
108 0, /* NumberOfSymbols */
109 sizeof(IMAGE_OPTIONAL_HEADER), /* SizeOfOptionalHeader */
110 IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL /* Characteristics */
112 { IMAGE_NT_OPTIONAL_HDR_MAGIC, /* Magic */
113 1, /* MajorLinkerVersion */
114 0, /* MinorLinkerVersion */
115 0, /* SizeOfCode */
116 0, /* SizeOfInitializedData */
117 0, /* SizeOfUninitializedData */
118 0, /* AddressOfEntryPoint */
119 0x10, /* BaseOfCode, also serves as e_lfanew in the truncated MZ header */
120 #ifndef _WIN64
121 0, /* BaseOfData */
122 #endif
123 0x10000000, /* ImageBase */
124 0, /* SectionAlignment */
125 0, /* FileAlignment */
126 4, /* MajorOperatingSystemVersion */
127 0, /* MinorOperatingSystemVersion */
128 1, /* MajorImageVersion */
129 0, /* MinorImageVersion */
130 4, /* MajorSubsystemVersion */
131 0, /* MinorSubsystemVersion */
132 0, /* Win32VersionValue */
133 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0x1000, /* SizeOfImage */
134 sizeof(dos_header) + sizeof(nt_header_template), /* SizeOfHeaders */
135 0, /* CheckSum */
136 IMAGE_SUBSYSTEM_WINDOWS_CUI, /* Subsystem */
137 0, /* DllCharacteristics */
138 0, /* SizeOfStackReserve */
139 0, /* SizeOfStackCommit */
140 0, /* SizeOfHeapReserve */
141 0, /* SizeOfHeapCommit */
142 0, /* LoaderFlags */
143 0, /* NumberOfRvaAndSizes */
144 { { 0 } } /* DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES] */
148 static IMAGE_SECTION_HEADER section =
150 ".rodata", /* Name */
151 { 0 }, /* Misc */
152 0, /* VirtualAddress */
153 0, /* SizeOfRawData */
154 0, /* PointerToRawData */
155 0, /* PointerToRelocations */
156 0, /* PointerToLinenumbers */
157 0, /* NumberOfRelocations */
158 0, /* NumberOfLinenumbers */
159 IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ, /* Characteristics */
163 static const char filler[0x1000];
164 static const char section_data[0x10] = "section data";
166 static DWORD create_test_dll( const IMAGE_DOS_HEADER *dos_header, UINT dos_size,
167 const IMAGE_NT_HEADERS *nt_header, char dll_name[MAX_PATH] )
169 char temp_path[MAX_PATH];
170 DWORD dummy, size, file_align;
171 HANDLE hfile;
172 BOOL ret;
174 GetTempPathA(MAX_PATH, temp_path);
175 GetTempFileNameA(temp_path, "ldr", 0, dll_name);
177 hfile = CreateFileA(dll_name, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, 0);
178 ok( hfile != INVALID_HANDLE_VALUE, "failed to create %s err %u\n", dll_name, GetLastError() );
179 if (hfile == INVALID_HANDLE_VALUE) return 0;
181 SetLastError(0xdeadbeef);
182 ret = WriteFile(hfile, dos_header, dos_size, &dummy, NULL);
183 ok(ret, "WriteFile error %d\n", GetLastError());
185 SetLastError(0xdeadbeef);
186 ret = WriteFile(hfile, nt_header, sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER), &dummy, NULL);
187 ok(ret, "WriteFile error %d\n", GetLastError());
189 if (nt_header->FileHeader.SizeOfOptionalHeader)
191 SetLastError(0xdeadbeef);
192 ret = WriteFile(hfile, &nt_header->OptionalHeader,
193 min(nt_header->FileHeader.SizeOfOptionalHeader, sizeof(IMAGE_OPTIONAL_HEADER)),
194 &dummy, NULL);
195 ok(ret, "WriteFile error %d\n", GetLastError());
196 if (nt_header->FileHeader.SizeOfOptionalHeader > sizeof(IMAGE_OPTIONAL_HEADER))
198 file_align = nt_header->FileHeader.SizeOfOptionalHeader - sizeof(IMAGE_OPTIONAL_HEADER);
199 assert(file_align < sizeof(filler));
200 SetLastError(0xdeadbeef);
201 ret = WriteFile(hfile, filler, file_align, &dummy, NULL);
202 ok(ret, "WriteFile error %d\n", GetLastError());
206 assert(nt_header->FileHeader.NumberOfSections <= 1);
207 if (nt_header->FileHeader.NumberOfSections)
209 section.SizeOfRawData = 10;
211 if (nt_header->OptionalHeader.SectionAlignment >= page_size)
213 section.PointerToRawData = dos_size;
214 section.VirtualAddress = nt_header->OptionalHeader.SectionAlignment;
215 section.Misc.VirtualSize = section.SizeOfRawData * 10;
217 else
219 section.PointerToRawData = nt_header->OptionalHeader.SizeOfHeaders;
220 section.VirtualAddress = nt_header->OptionalHeader.SizeOfHeaders;
221 section.Misc.VirtualSize = 5;
224 SetLastError(0xdeadbeef);
225 ret = WriteFile(hfile, &section, sizeof(section), &dummy, NULL);
226 ok(ret, "WriteFile error %d\n", GetLastError());
228 /* section data */
229 SetLastError(0xdeadbeef);
230 ret = WriteFile(hfile, section_data, sizeof(section_data), &dummy, NULL);
231 ok(ret, "WriteFile error %d\n", GetLastError());
233 size = GetFileSize(hfile, NULL);
234 CloseHandle(hfile);
235 return size;
238 static BOOL query_image_section( int id, const char *dll_name, const IMAGE_NT_HEADERS *nt_header )
240 SECTION_BASIC_INFORMATION info;
241 SECTION_IMAGE_INFORMATION image;
242 SIZE_T info_size = (SIZE_T)0xdeadbeef << 16;
243 NTSTATUS status;
244 HANDLE file, mapping;
245 ULONG file_size;
246 LARGE_INTEGER map_size;
247 SIZE_T max_stack, commit_stack;
248 void *entry_point;
250 /* truncated header is not handled correctly in windows <= w2k3 */
251 BOOL truncated;
253 file = CreateFileA( dll_name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE,
254 NULL, OPEN_EXISTING, 0, 0 );
255 ok( file != INVALID_HANDLE_VALUE, "%u: CreateFile error %d\n", id, GetLastError() );
256 file_size = GetFileSize( file, NULL );
258 status = pNtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_MAP_READ | SECTION_QUERY,
259 NULL, NULL, PAGE_READONLY, SEC_IMAGE, file );
260 ok( !status, "%u: NtCreateSection failed err %x\n", id, status );
261 if (status)
263 CloseHandle( file );
264 return FALSE;
266 status = pNtQuerySection( mapping, SectionImageInformation, &image, sizeof(image), &info_size );
267 ok( !status, "%u: NtQuerySection failed err %x\n", id, status );
268 ok( info_size == sizeof(image), "%u: NtQuerySection wrong size %lu\n", id, info_size );
269 if (nt_header->OptionalHeader.Magic == (sizeof(void *) > sizeof(int) ? IMAGE_NT_OPTIONAL_HDR64_MAGIC
270 : IMAGE_NT_OPTIONAL_HDR32_MAGIC))
272 max_stack = nt_header->OptionalHeader.SizeOfStackReserve;
273 commit_stack = nt_header->OptionalHeader.SizeOfStackCommit;
274 entry_point = (char *)nt_header->OptionalHeader.ImageBase + nt_header->OptionalHeader.AddressOfEntryPoint;
275 truncated = nt_header->FileHeader.SizeOfOptionalHeader < sizeof(IMAGE_OPTIONAL_HEADER);
277 else if (nt_header->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
279 max_stack = 0x100000;
280 commit_stack = 0x10000;
281 entry_point = (void *)0x81231234;
282 truncated = nt_header->FileHeader.SizeOfOptionalHeader < sizeof(IMAGE_OPTIONAL_HEADER64);
284 else
286 const IMAGE_NT_HEADERS32 *nt32 = (const IMAGE_NT_HEADERS32 *)nt_header;
287 max_stack = nt32->OptionalHeader.SizeOfStackReserve;
288 commit_stack = nt32->OptionalHeader.SizeOfStackCommit;
289 entry_point = (char *)(ULONG_PTR)nt32->OptionalHeader.ImageBase + nt32->OptionalHeader.AddressOfEntryPoint;
290 truncated = nt_header->FileHeader.SizeOfOptionalHeader < sizeof(IMAGE_OPTIONAL_HEADER32);
292 ok( (char *)image.TransferAddress == (char *)entry_point,
293 "%u: TransferAddress wrong %p / %p (%08x)\n", id,
294 image.TransferAddress, entry_point, nt_header->OptionalHeader.AddressOfEntryPoint );
295 ok( image.ZeroBits == 0, "%u: ZeroBits wrong %08x\n", id, image.ZeroBits );
296 ok( image.MaximumStackSize == max_stack || broken(truncated),
297 "%u: MaximumStackSize wrong %lx / %lx\n", id, image.MaximumStackSize, max_stack );
298 ok( image.CommittedStackSize == commit_stack || broken(truncated),
299 "%u: CommittedStackSize wrong %lx / %lx\n", id, image.CommittedStackSize, commit_stack );
300 if (truncated)
301 ok( !image.SubSystemType || broken(truncated),
302 "%u: SubSystemType wrong %08x / 00000000\n", id, image.SubSystemType );
303 else
304 ok( image.SubSystemType == nt_header->OptionalHeader.Subsystem,
305 "%u: SubSystemType wrong %08x / %08x\n", id,
306 image.SubSystemType, nt_header->OptionalHeader.Subsystem );
307 ok( image.SubsystemVersionLow == nt_header->OptionalHeader.MinorSubsystemVersion,
308 "%u: SubsystemVersionLow wrong %04x / %04x\n", id,
309 image.SubsystemVersionLow, nt_header->OptionalHeader.MinorSubsystemVersion );
310 ok( image.SubsystemVersionHigh == nt_header->OptionalHeader.MajorSubsystemVersion,
311 "%u: SubsystemVersionHigh wrong %04x / %04x\n", id,
312 image.SubsystemVersionHigh, nt_header->OptionalHeader.MajorSubsystemVersion );
313 ok( image.ImageCharacteristics == nt_header->FileHeader.Characteristics,
314 "%u: ImageCharacteristics wrong %04x / %04x\n", id,
315 image.ImageCharacteristics, nt_header->FileHeader.Characteristics );
316 ok( image.DllCharacteristics == nt_header->OptionalHeader.DllCharacteristics || broken(truncated),
317 "%u: DllCharacteristics wrong %04x / %04x\n", id,
318 image.DllCharacteristics, nt_header->OptionalHeader.DllCharacteristics );
319 ok( image.Machine == nt_header->FileHeader.Machine, "%u: Machine wrong %04x / %04x\n", id,
320 image.Machine, nt_header->FileHeader.Machine );
321 ok( image.LoaderFlags == nt_header->OptionalHeader.LoaderFlags,
322 "%u: LoaderFlags wrong %08x / %08x\n", id,
323 image.LoaderFlags, nt_header->OptionalHeader.LoaderFlags );
324 ok( image.ImageFileSize == file_size || broken(!image.ImageFileSize), /* winxpsp1 */
325 "%u: ImageFileSize wrong %08x / %08x\n", id, image.ImageFileSize, file_size );
326 ok( image.CheckSum == nt_header->OptionalHeader.CheckSum, "%u: CheckSum wrong %08x / %08x\n", id,
327 image.CheckSum, nt_header->OptionalHeader.CheckSum );
328 if (nt_header->OptionalHeader.SizeOfCode || nt_header->OptionalHeader.AddressOfEntryPoint)
329 todo_wine
330 ok( image.ImageContainsCode == TRUE, "%u: ImageContainsCode wrong %u\n", id,
331 image.ImageContainsCode );
332 else if ((nt_header->OptionalHeader.SectionAlignment % page_size) ||
333 (nt_header->FileHeader.NumberOfSections == 1 &&
334 (section.Characteristics & IMAGE_SCN_MEM_EXECUTE)))
335 todo_wine
336 ok( image.ImageContainsCode == TRUE || broken(!image.ImageContainsCode), /* <= win8 */
337 "%u: ImageContainsCode wrong %u\n", id, image.ImageContainsCode );
338 else
339 ok( !image.ImageContainsCode, "%u: ImageContainsCode wrong %u\n", id, image.ImageContainsCode );
340 /* FIXME: needs more work: */
341 /* image.GpValue */
342 /* image.ImageFlags */
344 map_size.QuadPart = (nt_header->OptionalHeader.SizeOfImage + page_size - 1) & ~(page_size - 1);
345 status = pNtQuerySection( mapping, SectionBasicInformation, &info, sizeof(info), NULL );
346 ok( !status, "NtQuerySection failed err %x\n", status );
347 ok( info.Size.QuadPart == map_size.QuadPart, "NtQuerySection wrong size %x%08x / %x%08x\n",
348 info.Size.u.HighPart, info.Size.u.LowPart, map_size.u.HighPart, map_size.u.LowPart );
349 CloseHandle( mapping );
351 map_size.QuadPart = (nt_header->OptionalHeader.SizeOfImage + page_size - 1) & ~(page_size - 1);
352 status = pNtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_MAP_READ | SECTION_QUERY,
353 NULL, &map_size, PAGE_READONLY, SEC_IMAGE, file );
354 ok( !status, "%u: NtCreateSection failed err %x\n", id, status );
355 status = pNtQuerySection( mapping, SectionBasicInformation, &info, sizeof(info), NULL );
356 ok( !status, "NtQuerySection failed err %x\n", status );
357 ok( info.Size.QuadPart == map_size.QuadPart, "NtQuerySection wrong size %x%08x / %x%08x\n",
358 info.Size.u.HighPart, info.Size.u.LowPart, map_size.u.HighPart, map_size.u.LowPart );
359 CloseHandle( mapping );
361 map_size.QuadPart++;
362 status = pNtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_MAP_READ | SECTION_QUERY,
363 NULL, &map_size, PAGE_READONLY, SEC_IMAGE, file );
364 ok( status == STATUS_SECTION_TOO_BIG, "%u: NtCreateSection failed err %x\n", id, status );
366 SetFilePointerEx( file, map_size, NULL, FILE_BEGIN );
367 SetEndOfFile( file );
368 status = pNtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_MAP_READ | SECTION_QUERY,
369 NULL, &map_size, PAGE_READONLY, SEC_IMAGE, file );
370 ok( status == STATUS_SECTION_TOO_BIG, "%u: NtCreateSection failed err %x\n", id, status );
372 map_size.QuadPart = 1;
373 status = pNtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_MAP_READ | SECTION_QUERY,
374 NULL, &map_size, PAGE_READONLY, SEC_IMAGE, file );
375 ok( !status, "%u: NtCreateSection failed err %x\n", id, status );
376 status = pNtQuerySection( mapping, SectionBasicInformation, &info, sizeof(info), NULL );
377 ok( !status, "NtQuerySection failed err %x\n", status );
378 ok( info.Size.QuadPart == map_size.QuadPart, "NtQuerySection wrong size %x%08x / %x%08x\n",
379 info.Size.u.HighPart, info.Size.u.LowPart, map_size.u.HighPart, map_size.u.LowPart );
380 CloseHandle( mapping );
382 CloseHandle( file );
383 return image.ImageContainsCode;
386 /* helper to test image section mapping */
387 static NTSTATUS map_image_section( const IMAGE_NT_HEADERS *nt_header, int line )
389 char dll_name[MAX_PATH];
390 LARGE_INTEGER size;
391 HANDLE file, map;
392 NTSTATUS status;
393 ULONG file_size;
394 BOOL has_code;
395 HMODULE mod;
397 file_size = create_test_dll( &dos_header, sizeof(dos_header), nt_header, dll_name );
399 file = CreateFileA(dll_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
400 ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
402 size.QuadPart = file_size;
403 status = pNtCreateSection(&map, STANDARD_RIGHTS_REQUIRED | SECTION_MAP_READ | SECTION_QUERY,
404 NULL, &size, PAGE_READONLY, SEC_IMAGE, file );
405 if (!status)
407 SECTION_BASIC_INFORMATION info;
408 SIZE_T info_size = 0xdeadbeef;
409 NTSTATUS ret = pNtQuerySection( map, SectionBasicInformation, &info, sizeof(info), &info_size );
410 ok( !ret, "NtQuerySection failed err %x\n", ret );
411 ok( info_size == sizeof(info), "NtQuerySection wrong size %lu\n", info_size );
412 ok( info.Attributes == (SEC_IMAGE | SEC_FILE), "NtQuerySection wrong attr %x\n", info.Attributes );
413 ok( info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", info.BaseAddress );
414 ok( info.Size.QuadPart == file_size, "NtQuerySection wrong size %x%08x / %08x\n",
415 info.Size.u.HighPart, info.Size.u.LowPart, file_size );
416 has_code = query_image_section( line, dll_name, nt_header );
417 /* test loading dll of wrong 32/64 bitness */
418 if (nt_header->OptionalHeader.Magic == (sizeof(void *) > sizeof(int) ? IMAGE_NT_OPTIONAL_HDR32_MAGIC
419 : IMAGE_NT_OPTIONAL_HDR64_MAGIC))
421 SetLastError( 0xdeadbeef );
422 mod = LoadLibraryExA( dll_name, 0, DONT_RESOLVE_DLL_REFERENCES );
423 if (!has_code && nt_header->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
425 ok( mod != NULL, "%u: loading failed err %u\n", line, GetLastError() );
427 else
429 ok( !mod, "%u: loading succeeded\n", line );
430 ok( GetLastError() == ERROR_BAD_EXE_FORMAT, "%u: wrong error %u\n", line, GetLastError() );
432 if (mod) FreeLibrary( mod );
435 if (map) CloseHandle( map );
436 CloseHandle( file );
437 DeleteFileA( dll_name );
438 return status;
442 static void test_Loader(void)
444 static const struct test_data
446 DWORD size_of_dos_header;
447 WORD number_of_sections, size_of_optional_header;
448 DWORD section_alignment, file_alignment;
449 DWORD size_of_image, size_of_headers;
450 DWORD errors[4]; /* 0 means LoadLibrary should succeed */
451 } td[] =
453 { sizeof(dos_header),
454 1, 0, 0, 0, 0, 0,
455 { ERROR_BAD_EXE_FORMAT }
457 { sizeof(dos_header),
458 1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x1000,
459 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0xe00,
460 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER),
461 { ERROR_BAD_EXE_FORMAT } /* XP doesn't like too small image size */
463 { sizeof(dos_header),
464 1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x1000,
465 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0x1000,
466 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER),
467 { ERROR_SUCCESS }
469 { sizeof(dos_header),
470 1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x1000,
471 0x1f00,
472 0x1000,
473 { ERROR_SUCCESS }
475 { sizeof(dos_header),
476 1, sizeof(IMAGE_OPTIONAL_HEADER), 0x200, 0x200,
477 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0x200,
478 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER),
479 { ERROR_SUCCESS, ERROR_INVALID_ADDRESS } /* vista is more strict */
481 { sizeof(dos_header),
482 1, sizeof(IMAGE_OPTIONAL_HEADER), 0x200, 0x1000,
483 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0x1000,
484 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER),
485 { ERROR_BAD_EXE_FORMAT } /* XP doesn't like alignments */
487 { sizeof(dos_header),
488 1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x200,
489 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0x1000,
490 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER),
491 { ERROR_SUCCESS }
493 { sizeof(dos_header),
494 1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x200,
495 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0x1000,
496 0x200,
497 { ERROR_SUCCESS }
499 /* Mandatory are all fields up to SizeOfHeaders, everything else
500 * is really optional (at least that's true for XP).
502 { sizeof(dos_header),
503 1, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200,
504 sizeof(dos_header) + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum) + sizeof(IMAGE_SECTION_HEADER) + 0x10,
505 sizeof(dos_header) + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum) + sizeof(IMAGE_SECTION_HEADER),
506 { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT, ERROR_INVALID_ADDRESS,
507 ERROR_NOACCESS }
509 { sizeof(dos_header),
510 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200,
511 0xd0, /* beyond of the end of file */
512 0xc0, /* beyond of the end of file */
513 { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */
515 { sizeof(dos_header),
516 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200,
517 0x1000,
519 { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */
521 { sizeof(dos_header),
522 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200,
525 { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */
527 #if 0 /* not power of 2 alignments need more test cases */
528 { sizeof(dos_header),
529 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x300, 0x300,
532 { ERROR_BAD_EXE_FORMAT } /* alignment is not power of 2 */
534 #endif
535 { sizeof(dos_header),
536 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 4, 4,
539 { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */
541 { sizeof(dos_header),
542 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 1, 1,
545 { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */
547 { sizeof(dos_header),
548 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200,
551 { ERROR_BAD_EXE_FORMAT } /* image size == 0 -> failure */
553 /* the following data mimics the PE image which upack creates */
554 { 0x10,
555 1, 0x148, 0x1000, 0x200,
556 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0x1000,
557 0x200,
558 { ERROR_SUCCESS }
560 /* Minimal PE image that XP is able to load: 92 bytes */
561 { 0x04,
562 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum),
563 0x04 /* also serves as e_lfanew in the truncated MZ header */, 0x04,
566 { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */
568 /* Minimal PE image that Windows7 is able to load: 268 bytes */
569 { 0x04,
570 0, 0xf0, /* optional header size just forces 0xf0 bytes to be written,
571 0 or another number don't change the behaviour, what really
572 matters is file size regardless of values in the headers */
573 0x04 /* also serves as e_lfanew in the truncated MZ header */, 0x04,
574 0x40, /* minimal image size that Windows7 accepts */
576 { ERROR_SUCCESS }
579 int i;
580 DWORD file_size;
581 HANDLE h;
582 HMODULE hlib, hlib_as_data_file;
583 char dll_name[MAX_PATH];
584 SIZE_T size;
585 BOOL ret;
586 NTSTATUS status;
587 WORD orig_machine = nt_header_template.FileHeader.Machine;
588 IMAGE_NT_HEADERS nt_header;
590 /* prevent displaying of the "Unable to load this DLL" message box */
591 SetErrorMode(SEM_FAILCRITICALERRORS);
593 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
595 nt_header = nt_header_template;
596 nt_header.FileHeader.NumberOfSections = td[i].number_of_sections;
597 nt_header.FileHeader.SizeOfOptionalHeader = td[i].size_of_optional_header;
599 nt_header.OptionalHeader.SectionAlignment = td[i].section_alignment;
600 nt_header.OptionalHeader.FileAlignment = td[i].file_alignment;
601 nt_header.OptionalHeader.SizeOfImage = td[i].size_of_image;
602 nt_header.OptionalHeader.SizeOfHeaders = td[i].size_of_headers;
604 file_size = create_test_dll( &dos_header, td[i].size_of_dos_header, &nt_header, dll_name );
606 SetLastError(0xdeadbeef);
607 hlib = LoadLibraryA(dll_name);
608 if (hlib)
610 MEMORY_BASIC_INFORMATION info;
611 void *ptr;
613 ok( td[i].errors[0] == ERROR_SUCCESS, "%d: should have failed\n", i );
615 SetLastError(0xdeadbeef);
616 size = VirtualQuery(hlib, &info, sizeof(info));
617 ok(size == sizeof(info),
618 "%d: VirtualQuery error %d\n", i, GetLastError());
619 ok(info.BaseAddress == hlib, "%d: %p != %p\n", i, info.BaseAddress, hlib);
620 ok(info.AllocationBase == hlib, "%d: %p != %p\n", i, info.AllocationBase, hlib);
621 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect);
622 ok(info.RegionSize == ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, page_size), "%d: got %lx != expected %x\n",
623 i, info.RegionSize, ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, page_size));
624 ok(info.State == MEM_COMMIT, "%d: %x != MEM_COMMIT\n", i, info.State);
625 if (nt_header.OptionalHeader.SectionAlignment < page_size)
626 ok(info.Protect == PAGE_EXECUTE_WRITECOPY, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i, info.Protect);
627 else
628 ok(info.Protect == PAGE_READONLY, "%d: %x != PAGE_READONLY\n", i, info.Protect);
629 ok(info.Type == SEC_IMAGE, "%d: %x != SEC_IMAGE\n", i, info.Type);
631 SetLastError(0xdeadbeef);
632 ptr = VirtualAlloc(hlib, page_size, MEM_COMMIT, info.Protect);
633 ok(!ptr, "%d: VirtualAlloc should fail\n", i);
634 ok(GetLastError() == ERROR_ACCESS_DENIED, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i, GetLastError());
636 SetLastError(0xdeadbeef);
637 size = VirtualQuery((char *)hlib + info.RegionSize, &info, sizeof(info));
638 ok(size == sizeof(info),
639 "%d: VirtualQuery error %d\n", i, GetLastError());
640 if (nt_header.OptionalHeader.SectionAlignment == page_size ||
641 nt_header.OptionalHeader.SectionAlignment == nt_header.OptionalHeader.FileAlignment)
643 ok(info.BaseAddress == (char *)hlib + ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, page_size), "%d: got %p != expected %p\n",
644 i, info.BaseAddress, (char *)hlib + ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, page_size));
645 ok(info.AllocationBase == 0, "%d: %p != 0\n", i, info.AllocationBase);
646 ok(info.AllocationProtect == 0, "%d: %x != 0\n", i, info.AllocationProtect);
647 /*ok(info.RegionSize == not_practical_value, "%d: %lx != not_practical_value\n", i, info.RegionSize);*/
648 ok(info.State == MEM_FREE, "%d: %x != MEM_FREE\n", i, info.State);
649 ok(info.Type == 0, "%d: %x != 0\n", i, info.Type);
650 ok(info.Protect == PAGE_NOACCESS, "%d: %x != PAGE_NOACCESS\n", i, info.Protect);
652 else
654 ok(info.Protect == PAGE_EXECUTE_WRITECOPY, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i, info.Protect);
655 ok(info.BaseAddress == hlib, "%d: got %p != expected %p\n", i, info.BaseAddress, hlib);
656 ok(info.AllocationBase == hlib, "%d: %p != %p\n", i, info.AllocationBase, hlib);
657 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect);
658 ok(info.RegionSize == ALIGN_SIZE(file_size, page_size), "%d: got %lx != expected %x\n",
659 i, info.RegionSize, ALIGN_SIZE(file_size, page_size));
660 ok(info.State == MEM_COMMIT, "%d: %x != MEM_COMMIT\n", i, info.State);
661 ok(info.Protect == PAGE_READONLY, "%d: %x != PAGE_READONLY\n", i, info.Protect);
662 ok(info.Type == SEC_IMAGE, "%d: %x != SEC_IMAGE\n", i, info.Type);
665 /* header: check the zeroing of alignment */
666 if (nt_header.OptionalHeader.SectionAlignment >= page_size)
668 const char *start;
670 start = (const char *)hlib + nt_header.OptionalHeader.SizeOfHeaders;
671 size = ALIGN_SIZE((ULONG_PTR)start, page_size) - (ULONG_PTR)start;
672 ok(!memcmp(start, filler, size), "%d: header alignment is not cleared\n", i);
675 if (nt_header.FileHeader.NumberOfSections)
677 SetLastError(0xdeadbeef);
678 size = VirtualQuery((char *)hlib + section.VirtualAddress, &info, sizeof(info));
679 ok(size == sizeof(info),
680 "%d: VirtualQuery error %d\n", i, GetLastError());
681 if (nt_header.OptionalHeader.SectionAlignment < page_size)
683 ok(info.BaseAddress == hlib, "%d: got %p != expected %p\n", i, info.BaseAddress, hlib);
684 ok(info.RegionSize == ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, page_size), "%d: got %lx != expected %x\n",
685 i, info.RegionSize, ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, page_size));
686 ok(info.Protect == PAGE_EXECUTE_WRITECOPY, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i, info.Protect);
688 else
690 ok(info.BaseAddress == (char *)hlib + section.VirtualAddress, "%d: got %p != expected %p\n", i, info.BaseAddress, (char *)hlib + section.VirtualAddress);
691 ok(info.RegionSize == ALIGN_SIZE(section.Misc.VirtualSize, page_size), "%d: got %lx != expected %x\n",
692 i, info.RegionSize, ALIGN_SIZE(section.Misc.VirtualSize, page_size));
693 ok(info.Protect == PAGE_READONLY, "%d: %x != PAGE_READONLY\n", i, info.Protect);
695 ok(info.AllocationBase == hlib, "%d: %p != %p\n", i, info.AllocationBase, hlib);
696 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect);
697 ok(info.State == MEM_COMMIT, "%d: %x != MEM_COMMIT\n", i, info.State);
698 ok(info.Type == SEC_IMAGE, "%d: %x != SEC_IMAGE\n", i, info.Type);
700 if (nt_header.OptionalHeader.SectionAlignment >= page_size)
701 ok(!memcmp((const char *)hlib + section.VirtualAddress + section.PointerToRawData, &nt_header, section.SizeOfRawData), "wrong section data\n");
702 else
703 ok(!memcmp((const char *)hlib + section.PointerToRawData, section_data, section.SizeOfRawData), "wrong section data\n");
705 /* check the zeroing of alignment */
706 if (nt_header.OptionalHeader.SectionAlignment >= page_size)
708 const char *start;
710 start = (const char *)hlib + section.VirtualAddress + section.PointerToRawData + section.SizeOfRawData;
711 size = ALIGN_SIZE((ULONG_PTR)start, page_size) - (ULONG_PTR)start;
712 ok(memcmp(start, filler, size), "%d: alignment should not be cleared\n", i);
715 SetLastError(0xdeadbeef);
716 ptr = VirtualAlloc((char *)hlib + section.VirtualAddress, page_size, MEM_COMMIT, info.Protect);
717 ok(!ptr, "%d: VirtualAlloc should fail\n", i);
718 ok(GetLastError() == ERROR_ACCESS_DENIED || GetLastError() == ERROR_INVALID_ADDRESS,
719 "%d: expected ERROR_ACCESS_DENIED, got %d\n", i, GetLastError());
722 SetLastError(0xdeadbeef);
723 hlib_as_data_file = LoadLibraryExA(dll_name, 0, LOAD_LIBRARY_AS_DATAFILE);
724 ok(hlib_as_data_file != 0, "LoadLibraryEx error %u\n", GetLastError());
725 ok(hlib_as_data_file == hlib, "hlib_as_file and hlib are different\n");
727 SetLastError(0xdeadbeef);
728 ret = FreeLibrary(hlib);
729 ok(ret, "FreeLibrary error %d\n", GetLastError());
731 SetLastError(0xdeadbeef);
732 hlib = GetModuleHandleA(dll_name);
733 ok(hlib != 0, "GetModuleHandle error %u\n", GetLastError());
735 SetLastError(0xdeadbeef);
736 ret = FreeLibrary(hlib_as_data_file);
737 ok(ret, "FreeLibrary error %d\n", GetLastError());
739 hlib = GetModuleHandleA(dll_name);
740 ok(!hlib, "GetModuleHandle should fail\n");
742 SetLastError(0xdeadbeef);
743 hlib_as_data_file = LoadLibraryExA(dll_name, 0, LOAD_LIBRARY_AS_DATAFILE);
744 ok(hlib_as_data_file != 0, "LoadLibraryEx error %u\n", GetLastError());
745 ok((ULONG_PTR)hlib_as_data_file & 1, "hlib_as_data_file is even\n");
747 hlib = GetModuleHandleA(dll_name);
748 ok(!hlib, "GetModuleHandle should fail\n");
750 SetLastError(0xdeadbeef);
751 h = CreateFileA( dll_name, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
752 ok( h != INVALID_HANDLE_VALUE, "open failed err %u\n", GetLastError() );
753 CloseHandle( h );
755 SetLastError(0xdeadbeef);
756 ret = FreeLibrary(hlib_as_data_file);
757 ok(ret, "FreeLibrary error %d\n", GetLastError());
759 SetLastError(0xdeadbeef);
760 hlib_as_data_file = LoadLibraryExA(dll_name, 0, LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE);
761 if (!((ULONG_PTR)hlib_as_data_file & 1) || /* winxp */
762 (!hlib_as_data_file && GetLastError() == ERROR_INVALID_PARAMETER)) /* w2k3 */
764 win_skip( "LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE not supported\n" );
765 FreeLibrary(hlib_as_data_file);
767 else
769 ok(hlib_as_data_file != 0, "LoadLibraryEx error %u\n", GetLastError());
771 SetLastError(0xdeadbeef);
772 h = CreateFileA( dll_name, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
773 todo_wine ok( h == INVALID_HANDLE_VALUE, "open succeeded\n" );
774 todo_wine ok( GetLastError() == ERROR_SHARING_VIOLATION, "wrong error %u\n", GetLastError() );
775 CloseHandle( h );
777 SetLastError(0xdeadbeef);
778 ret = FreeLibrary(hlib_as_data_file);
779 ok(ret, "FreeLibrary error %d\n", GetLastError());
782 query_image_section( i, dll_name, &nt_header );
784 else
786 BOOL error_match;
787 int error_index;
789 error_match = FALSE;
790 for (error_index = 0;
791 ! error_match && error_index < sizeof(td[i].errors) / sizeof(DWORD);
792 error_index++)
794 error_match = td[i].errors[error_index] == GetLastError();
796 ok(error_match, "%d: unexpected error %d\n", i, GetLastError());
799 SetLastError(0xdeadbeef);
800 ret = DeleteFileA(dll_name);
801 ok(ret, "DeleteFile error %d\n", GetLastError());
804 nt_header = nt_header_template;
805 nt_header.FileHeader.NumberOfSections = 1;
806 nt_header.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER);
808 nt_header.OptionalHeader.SectionAlignment = page_size;
809 nt_header.OptionalHeader.AddressOfEntryPoint = 0x1234;
810 nt_header.OptionalHeader.DllCharacteristics = IMAGE_DLLCHARACTERISTICS_NX_COMPAT;
811 nt_header.OptionalHeader.FileAlignment = page_size;
812 nt_header.OptionalHeader.SizeOfHeaders = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER);
813 nt_header.OptionalHeader.SizeOfImage = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + page_size;
815 status = map_image_section( &nt_header, __LINE__ );
816 ok( status == STATUS_SUCCESS, "NtCreateSection error %08x\n", status );
818 dos_header.e_magic = 0;
819 status = map_image_section( &nt_header, __LINE__ );
820 ok( status == STATUS_INVALID_IMAGE_NOT_MZ, "NtCreateSection error %08x\n", status );
822 dos_header.e_magic = IMAGE_DOS_SIGNATURE;
823 nt_header.Signature = IMAGE_OS2_SIGNATURE;
824 status = map_image_section( &nt_header, __LINE__ );
825 ok( status == STATUS_INVALID_IMAGE_NE_FORMAT, "NtCreateSection error %08x\n", status );
827 nt_header.Signature = 0xdeadbeef;
828 status = map_image_section( &nt_header, __LINE__ );
829 ok( status == STATUS_INVALID_IMAGE_PROTECT, "NtCreateSection error %08x\n", status );
831 nt_header.Signature = IMAGE_NT_SIGNATURE;
832 nt_header.OptionalHeader.Magic = 0xdead;
833 status = map_image_section( &nt_header, __LINE__ );
834 ok( status == STATUS_INVALID_IMAGE_FORMAT, "NtCreateSection error %08x\n", status );
836 nt_header.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR_MAGIC;
837 nt_header.FileHeader.Machine = 0xdead;
838 status = map_image_section( &nt_header, __LINE__ );
839 ok( status == STATUS_INVALID_IMAGE_FORMAT || broken(status == STATUS_SUCCESS), /* win2k */
840 "NtCreateSection error %08x\n", status );
842 nt_header.FileHeader.Machine = IMAGE_FILE_MACHINE_UNKNOWN;
843 status = map_image_section( &nt_header, __LINE__ );
844 ok( status == STATUS_INVALID_IMAGE_FORMAT || broken(status == STATUS_SUCCESS), /* win2k */
845 "NtCreateSection error %08x\n", status );
847 switch (orig_machine)
849 case IMAGE_FILE_MACHINE_I386: nt_header.FileHeader.Machine = IMAGE_FILE_MACHINE_AMD64; break;
850 case IMAGE_FILE_MACHINE_AMD64: nt_header.FileHeader.Machine = IMAGE_FILE_MACHINE_I386; break;
851 case IMAGE_FILE_MACHINE_ARMNT: nt_header.FileHeader.Machine = IMAGE_FILE_MACHINE_ARM64; break;
852 case IMAGE_FILE_MACHINE_ARM64: nt_header.FileHeader.Machine = IMAGE_FILE_MACHINE_ARMNT; break;
854 status = map_image_section( &nt_header, __LINE__ );
855 ok( status == STATUS_INVALID_IMAGE_FORMAT || broken(status == STATUS_SUCCESS), /* win2k */
856 "NtCreateSection error %08x\n", status );
858 if (nt_header.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
860 IMAGE_NT_HEADERS64 nt64;
861 BOOL is_wow64 = FALSE;
863 if (pIsWow64Process) pIsWow64Process( GetCurrentProcess(), &is_wow64 );
864 memset( &nt64, 0, sizeof(nt64) );
865 nt64.Signature = IMAGE_NT_SIGNATURE;
866 nt64.FileHeader.Machine = orig_machine;
867 nt64.FileHeader.NumberOfSections = 1;
868 nt64.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER64);
869 nt64.FileHeader.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL;
870 nt64.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR64_MAGIC;
871 nt64.OptionalHeader.MajorLinkerVersion = 1;
872 nt64.OptionalHeader.SizeOfCode = 0x1000;
873 nt64.OptionalHeader.AddressOfEntryPoint = 0x1000;
874 nt64.OptionalHeader.ImageBase = 0x10000000;
875 nt64.OptionalHeader.SectionAlignment = 0x1000;
876 nt64.OptionalHeader.FileAlignment = 0x1000;
877 nt64.OptionalHeader.MajorOperatingSystemVersion = 4;
878 nt64.OptionalHeader.MajorImageVersion = 1;
879 nt64.OptionalHeader.MajorSubsystemVersion = 4;
880 nt64.OptionalHeader.SizeOfHeaders = sizeof(dos_header) + sizeof(nt64) + sizeof(IMAGE_SECTION_HEADER);
881 nt64.OptionalHeader.SizeOfImage = nt64.OptionalHeader.SizeOfHeaders + 0x1000;
882 nt64.OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
883 nt64.OptionalHeader.SizeOfStackReserve = 0x321000;
884 nt64.OptionalHeader.SizeOfStackCommit = 0x123000;
885 section.Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE;
887 status = map_image_section( (IMAGE_NT_HEADERS *)&nt64, __LINE__ );
888 todo_wine_if(!is_wow64)
889 ok( status == (is_wow64 ? STATUS_INVALID_IMAGE_FORMAT : STATUS_INVALID_IMAGE_WIN_64),
890 "NtCreateSection error %08x\n", status );
892 switch (orig_machine)
894 case IMAGE_FILE_MACHINE_I386: nt64.FileHeader.Machine = IMAGE_FILE_MACHINE_ARM64; break;
895 case IMAGE_FILE_MACHINE_ARMNT: nt64.FileHeader.Machine = IMAGE_FILE_MACHINE_AMD64; break;
897 status = map_image_section( (IMAGE_NT_HEADERS *)&nt64, __LINE__ );
898 todo_wine_if(!is_wow64)
899 ok( status == (is_wow64 ? STATUS_INVALID_IMAGE_FORMAT : STATUS_INVALID_IMAGE_WIN_64),
900 "NtCreateSection error %08x\n", status );
902 nt64.FileHeader.Machine = nt_header.FileHeader.Machine;
903 status = map_image_section( (IMAGE_NT_HEADERS *)&nt64, __LINE__ );
904 todo_wine
905 ok( status == (is_wow64 ? STATUS_SUCCESS : STATUS_INVALID_IMAGE_WIN_64),
906 "NtCreateSection error %08x\n", status );
908 nt64.OptionalHeader.SizeOfCode = 0;
909 nt64.OptionalHeader.AddressOfEntryPoint = 0x1000;
910 section.Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE;
911 status = map_image_section( (IMAGE_NT_HEADERS *)&nt64, __LINE__ );
912 todo_wine
913 ok( status == (is_wow64 ? STATUS_SUCCESS : STATUS_INVALID_IMAGE_WIN_64),
914 "NtCreateSection error %08x\n", status );
916 nt64.OptionalHeader.SizeOfCode = 0;
917 nt64.OptionalHeader.AddressOfEntryPoint = 0;
918 section.Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE;
919 status = map_image_section( (IMAGE_NT_HEADERS *)&nt64, __LINE__ );
920 todo_wine
921 ok( status == (is_wow64 ? STATUS_SUCCESS : STATUS_INVALID_IMAGE_WIN_64),
922 "NtCreateSection error %08x\n", status );
924 nt64.OptionalHeader.SizeOfCode = 0x1000;
925 nt64.OptionalHeader.AddressOfEntryPoint = 0;
926 section.Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE;
927 status = map_image_section( (IMAGE_NT_HEADERS *)&nt64, __LINE__ );
928 todo_wine
929 ok( status == (is_wow64 ? STATUS_SUCCESS : STATUS_INVALID_IMAGE_WIN_64),
930 "NtCreateSection error %08x\n", status );
932 nt64.OptionalHeader.SizeOfCode = 0;
933 nt64.OptionalHeader.AddressOfEntryPoint = 0;
934 section.Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE;
935 status = map_image_section( (IMAGE_NT_HEADERS *)&nt64, __LINE__ );
936 todo_wine
937 ok( status == (is_wow64 ? STATUS_SUCCESS : STATUS_INVALID_IMAGE_WIN_64),
938 "NtCreateSection error %08x\n", status );
940 else
942 IMAGE_NT_HEADERS32 nt32;
944 memset( &nt32, 0, sizeof(nt32) );
945 nt32.Signature = IMAGE_NT_SIGNATURE;
946 nt32.FileHeader.Machine = orig_machine;
947 nt32.FileHeader.NumberOfSections = 1;
948 nt32.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER32);
949 nt32.FileHeader.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL;
950 nt32.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR32_MAGIC;
951 nt32.OptionalHeader.MajorLinkerVersion = 1;
952 nt32.OptionalHeader.SizeOfCode = 0x1000;
953 nt32.OptionalHeader.AddressOfEntryPoint = 0x1000;
954 nt32.OptionalHeader.ImageBase = 0x10000000;
955 nt32.OptionalHeader.SectionAlignment = 0x1000;
956 nt32.OptionalHeader.FileAlignment = 0x1000;
957 nt32.OptionalHeader.MajorOperatingSystemVersion = 4;
958 nt32.OptionalHeader.MajorImageVersion = 1;
959 nt32.OptionalHeader.MajorSubsystemVersion = 4;
960 nt32.OptionalHeader.SizeOfHeaders = sizeof(dos_header) + sizeof(nt32) + sizeof(IMAGE_SECTION_HEADER);
961 nt32.OptionalHeader.SizeOfImage = nt32.OptionalHeader.SizeOfHeaders + 0x1000;
962 nt32.OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
963 nt32.OptionalHeader.SizeOfStackReserve = 0x321000;
964 nt32.OptionalHeader.SizeOfStackCommit = 0x123000;
965 section.Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE;
967 status = map_image_section( (IMAGE_NT_HEADERS *)&nt32, __LINE__ );
968 ok( status == STATUS_INVALID_IMAGE_FORMAT, "NtCreateSection error %08x\n", status );
970 switch (orig_machine)
972 case IMAGE_FILE_MACHINE_AMD64: nt32.FileHeader.Machine = IMAGE_FILE_MACHINE_ARMNT; break;
973 case IMAGE_FILE_MACHINE_ARM64: nt32.FileHeader.Machine = IMAGE_FILE_MACHINE_I386; break;
975 status = map_image_section( (IMAGE_NT_HEADERS *)&nt32, __LINE__ );
976 ok( status == STATUS_INVALID_IMAGE_FORMAT || broken(!status) /* win8 */,
977 "NtCreateSection error %08x\n", status );
979 nt32.FileHeader.Machine = nt_header.FileHeader.Machine;
980 status = map_image_section( (IMAGE_NT_HEADERS *)&nt32, __LINE__ );
981 todo_wine
982 ok( status == STATUS_SUCCESS, "NtCreateSection error %08x\n", status );
984 nt32.OptionalHeader.SizeOfCode = 0;
985 nt32.OptionalHeader.AddressOfEntryPoint = 0x1000;
986 section.Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE;
987 status = map_image_section( (IMAGE_NT_HEADERS *)&nt32, __LINE__ );
988 todo_wine
989 ok( status == STATUS_SUCCESS, "NtCreateSection error %08x\n", status );
991 nt32.OptionalHeader.SizeOfCode = 0;
992 nt32.OptionalHeader.AddressOfEntryPoint = 0;
993 section.Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE;
994 status = map_image_section( (IMAGE_NT_HEADERS *)&nt32, __LINE__ );
995 todo_wine
996 ok( status == STATUS_SUCCESS, "NtCreateSection error %08x\n", status );
998 nt32.OptionalHeader.SizeOfCode = 0x1000;
999 nt32.OptionalHeader.AddressOfEntryPoint = 0;
1000 section.Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE;
1001 status = map_image_section( (IMAGE_NT_HEADERS *)&nt32, __LINE__ );
1002 todo_wine
1003 ok( status == STATUS_SUCCESS, "NtCreateSection error %08x\n", status );
1005 nt32.OptionalHeader.SizeOfCode = 0;
1006 nt32.OptionalHeader.AddressOfEntryPoint = 0;
1007 section.Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE;
1008 status = map_image_section( (IMAGE_NT_HEADERS *)&nt32, __LINE__ );
1009 todo_wine
1010 ok( status == STATUS_SUCCESS, "NtCreateSection error %08x\n", status );
1013 nt_header.FileHeader.Machine = orig_machine; /* restore it for the next tests */
1014 section.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;
1017 /* Verify linking style of import descriptors */
1018 static void test_ImportDescriptors(void)
1020 HMODULE kernel32_module = NULL;
1021 PIMAGE_DOS_HEADER d_header;
1022 PIMAGE_NT_HEADERS nt_headers;
1023 DWORD import_dir_size;
1024 DWORD_PTR dir_offset;
1025 PIMAGE_IMPORT_DESCRIPTOR import_chunk;
1027 /* Load kernel32 module */
1028 kernel32_module = GetModuleHandleA("kernel32.dll");
1029 assert( kernel32_module != NULL );
1031 /* Get PE header info from module image */
1032 d_header = (PIMAGE_DOS_HEADER) kernel32_module;
1033 nt_headers = (PIMAGE_NT_HEADERS) (((char*) d_header) +
1034 d_header->e_lfanew);
1036 /* Get size of import entry directory */
1037 import_dir_size = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
1038 if (!import_dir_size)
1040 skip("Unable to continue testing due to missing import directory.\n");
1041 return;
1044 /* Get address of first import chunk */
1045 dir_offset = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
1046 import_chunk = RVAToAddr(dir_offset, kernel32_module);
1047 ok(import_chunk != 0, "Invalid import_chunk: %p\n", import_chunk);
1048 if (!import_chunk) return;
1050 /* Iterate through import descriptors and verify set name,
1051 * OriginalFirstThunk, and FirstThunk. Core Windows DLLs, such as
1052 * kernel32.dll, don't use Borland-style linking, where the table of
1053 * imported names is stored directly in FirstThunk and overwritten
1054 * by the relocation, instead of being stored in OriginalFirstThunk.
1055 * */
1056 for (; import_chunk->FirstThunk; import_chunk++)
1058 LPCSTR module_name = RVAToAddr(import_chunk->Name, kernel32_module);
1059 PIMAGE_THUNK_DATA name_table = RVAToAddr(
1060 U(*import_chunk).OriginalFirstThunk, kernel32_module);
1061 PIMAGE_THUNK_DATA iat = RVAToAddr(
1062 import_chunk->FirstThunk, kernel32_module);
1063 ok(module_name != NULL, "Imported module name should not be NULL\n");
1064 ok(name_table != NULL,
1065 "Name table for imported module %s should not be NULL\n",
1066 module_name);
1067 ok(iat != NULL, "IAT for imported module %s should not be NULL\n",
1068 module_name);
1072 static void test_image_mapping(const char *dll_name, DWORD scn_page_access, BOOL is_dll)
1074 HANDLE hfile, hmap;
1075 NTSTATUS status;
1076 LARGE_INTEGER offset;
1077 SIZE_T size;
1078 void *addr1, *addr2;
1079 MEMORY_BASIC_INFORMATION info;
1081 if (!pNtMapViewOfSection) return;
1083 SetLastError(0xdeadbeef);
1084 hfile = CreateFileA(dll_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1085 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
1087 SetLastError(0xdeadbeef);
1088 hmap = CreateFileMappingW(hfile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, 0);
1089 ok(hmap != 0, "CreateFileMapping error %d\n", GetLastError());
1091 offset.u.LowPart = 0;
1092 offset.u.HighPart = 0;
1094 addr1 = NULL;
1095 size = 0;
1096 status = pNtMapViewOfSection(hmap, GetCurrentProcess(), &addr1, 0, 0, &offset,
1097 &size, 1 /* ViewShare */, 0, PAGE_READONLY);
1098 ok(status == STATUS_SUCCESS, "NtMapViewOfSection error %x\n", status);
1099 ok(addr1 != 0, "mapped address should be valid\n");
1101 SetLastError(0xdeadbeef);
1102 size = VirtualQuery((char *)addr1 + section.VirtualAddress, &info, sizeof(info));
1103 ok(size == sizeof(info), "VirtualQuery error %d\n", GetLastError());
1104 ok(info.BaseAddress == (char *)addr1 + section.VirtualAddress, "got %p != expected %p\n", info.BaseAddress, (char *)addr1 + section.VirtualAddress);
1105 ok(info.RegionSize == page_size, "got %#lx != expected %#x\n", info.RegionSize, page_size);
1106 ok(info.Protect == scn_page_access, "got %#x != expected %#x\n", info.Protect, scn_page_access);
1107 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
1108 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%#x != PAGE_EXECUTE_WRITECOPY\n", info.AllocationProtect);
1109 ok(info.State == MEM_COMMIT, "%#x != MEM_COMMIT\n", info.State);
1110 ok(info.Type == SEC_IMAGE, "%#x != SEC_IMAGE\n", info.Type);
1112 addr2 = NULL;
1113 size = 0;
1114 status = pNtMapViewOfSection(hmap, GetCurrentProcess(), &addr2, 0, 0, &offset,
1115 &size, 1 /* ViewShare */, 0, PAGE_READONLY);
1116 ok(status == STATUS_IMAGE_NOT_AT_BASE, "expected STATUS_IMAGE_NOT_AT_BASE, got %x\n", status);
1117 ok(addr2 != 0, "mapped address should be valid\n");
1118 ok(addr2 != addr1, "mapped addresses should be different\n");
1120 SetLastError(0xdeadbeef);
1121 size = VirtualQuery((char *)addr2 + section.VirtualAddress, &info, sizeof(info));
1122 ok(size == sizeof(info), "VirtualQuery error %d\n", GetLastError());
1123 ok(info.BaseAddress == (char *)addr2 + section.VirtualAddress, "got %p != expected %p\n", info.BaseAddress, (char *)addr2 + section.VirtualAddress);
1124 ok(info.RegionSize == page_size, "got %#lx != expected %#x\n", info.RegionSize, page_size);
1125 ok(info.Protect == scn_page_access, "got %#x != expected %#x\n", info.Protect, scn_page_access);
1126 ok(info.AllocationBase == addr2, "%p != %p\n", info.AllocationBase, addr2);
1127 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%#x != PAGE_EXECUTE_WRITECOPY\n", info.AllocationProtect);
1128 ok(info.State == MEM_COMMIT, "%#x != MEM_COMMIT\n", info.State);
1129 ok(info.Type == SEC_IMAGE, "%#x != SEC_IMAGE\n", info.Type);
1131 status = pNtUnmapViewOfSection(GetCurrentProcess(), addr2);
1132 ok(status == STATUS_SUCCESS, "NtUnmapViewOfSection error %x\n", status);
1134 addr2 = MapViewOfFile(hmap, 0, 0, 0, 0);
1135 ok(addr2 != 0, "mapped address should be valid\n");
1136 ok(addr2 != addr1, "mapped addresses should be different\n");
1138 SetLastError(0xdeadbeef);
1139 size = VirtualQuery((char *)addr2 + section.VirtualAddress, &info, sizeof(info));
1140 ok(size == sizeof(info), "VirtualQuery error %d\n", GetLastError());
1141 ok(info.BaseAddress == (char *)addr2 + section.VirtualAddress, "got %p != expected %p\n", info.BaseAddress, (char *)addr2 + section.VirtualAddress);
1142 ok(info.RegionSize == page_size, "got %#lx != expected %#x\n", info.RegionSize, page_size);
1143 ok(info.Protect == scn_page_access, "got %#x != expected %#x\n", info.Protect, scn_page_access);
1144 ok(info.AllocationBase == addr2, "%p != %p\n", info.AllocationBase, addr2);
1145 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%#x != PAGE_EXECUTE_WRITECOPY\n", info.AllocationProtect);
1146 ok(info.State == MEM_COMMIT, "%#x != MEM_COMMIT\n", info.State);
1147 ok(info.Type == SEC_IMAGE, "%#x != SEC_IMAGE\n", info.Type);
1149 UnmapViewOfFile(addr2);
1151 SetLastError(0xdeadbeef);
1152 addr2 = LoadLibraryA(dll_name);
1153 if (is_dll)
1155 ok(!addr2, "LoadLibrary should fail, is_dll %d\n", is_dll);
1156 ok(GetLastError() == ERROR_INVALID_ADDRESS, "expected ERROR_INVALID_ADDRESS, got %d\n", GetLastError());
1158 else
1160 BOOL ret;
1161 ok(addr2 != 0, "LoadLibrary error %d, is_dll %d\n", GetLastError(), is_dll);
1162 ok(addr2 != addr1, "mapped addresses should be different\n");
1164 SetLastError(0xdeadbeef);
1165 ret = FreeLibrary(addr2);
1166 ok(ret, "FreeLibrary error %d\n", GetLastError());
1169 status = pNtUnmapViewOfSection(GetCurrentProcess(), addr1);
1170 ok(status == STATUS_SUCCESS, "NtUnmapViewOfSection error %x\n", status);
1172 CloseHandle(hmap);
1173 CloseHandle(hfile);
1176 static BOOL is_mem_writable(DWORD prot)
1178 switch (prot & 0xff)
1180 case PAGE_READWRITE:
1181 case PAGE_WRITECOPY:
1182 case PAGE_EXECUTE_READWRITE:
1183 case PAGE_EXECUTE_WRITECOPY:
1184 return TRUE;
1186 default:
1187 return FALSE;
1191 static void test_VirtualProtect(void *base, void *section)
1193 static const struct test_data
1195 DWORD prot_set, prot_get;
1196 } td[] =
1198 { 0, 0 }, /* 0x00 */
1199 { PAGE_NOACCESS, PAGE_NOACCESS }, /* 0x01 */
1200 { PAGE_READONLY, PAGE_READONLY }, /* 0x02 */
1201 { PAGE_READONLY | PAGE_NOACCESS, 0 }, /* 0x03 */
1202 { PAGE_READWRITE, PAGE_WRITECOPY }, /* 0x04 */
1203 { PAGE_READWRITE | PAGE_NOACCESS, 0 }, /* 0x05 */
1204 { PAGE_READWRITE | PAGE_READONLY, 0 }, /* 0x06 */
1205 { PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, 0 }, /* 0x07 */
1206 { PAGE_WRITECOPY, PAGE_WRITECOPY }, /* 0x08 */
1207 { PAGE_WRITECOPY | PAGE_NOACCESS, 0 }, /* 0x09 */
1208 { PAGE_WRITECOPY | PAGE_READONLY, 0 }, /* 0x0a */
1209 { PAGE_WRITECOPY | PAGE_NOACCESS | PAGE_READONLY, 0 }, /* 0x0b */
1210 { PAGE_WRITECOPY | PAGE_READWRITE, 0 }, /* 0x0c */
1211 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_NOACCESS, 0 }, /* 0x0d */
1212 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY, 0 }, /* 0x0e */
1213 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, 0 }, /* 0x0f */
1215 { PAGE_EXECUTE, PAGE_EXECUTE }, /* 0x10 */
1216 { PAGE_EXECUTE_READ, PAGE_EXECUTE_READ }, /* 0x20 */
1217 { PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 }, /* 0x30 */
1218 { PAGE_EXECUTE_READWRITE, PAGE_EXECUTE_WRITECOPY }, /* 0x40 */
1219 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, 0 }, /* 0x50 */
1220 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, 0 }, /* 0x60 */
1221 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 }, /* 0x70 */
1222 { PAGE_EXECUTE_WRITECOPY, PAGE_EXECUTE_WRITECOPY }, /* 0x80 */
1223 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE, 0 }, /* 0x90 */
1224 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ, 0 }, /* 0xa0 */
1225 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 }, /* 0xb0 */
1226 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE, 0 }, /* 0xc0 */
1227 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, 0 }, /* 0xd0 */
1228 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, 0 }, /* 0xe0 */
1229 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 } /* 0xf0 */
1231 DWORD ret, orig_prot, old_prot, rw_prot, exec_prot, i, j;
1232 MEMORY_BASIC_INFORMATION info;
1234 SetLastError(0xdeadbeef);
1235 ret = VirtualProtect(section, page_size, PAGE_NOACCESS, &old_prot);
1236 ok(ret, "VirtualProtect error %d\n", GetLastError());
1238 orig_prot = old_prot;
1240 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
1242 SetLastError(0xdeadbeef);
1243 ret = VirtualQuery(section, &info, sizeof(info));
1244 ok(ret, "VirtualQuery failed %d\n", GetLastError());
1245 ok(info.BaseAddress == section, "%d: got %p != expected %p\n", i, info.BaseAddress, section);
1246 ok(info.RegionSize == page_size, "%d: got %#lx != expected %#x\n", i, info.RegionSize, page_size);
1247 ok(info.Protect == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, info.Protect);
1248 ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base);
1249 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%d: %#x != PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect);
1250 ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State);
1251 ok(info.Type == SEC_IMAGE, "%d: %#x != SEC_IMAGE\n", i, info.Type);
1253 old_prot = 0xdeadbeef;
1254 SetLastError(0xdeadbeef);
1255 ret = VirtualProtect(section, page_size, td[i].prot_set, &old_prot);
1256 if (td[i].prot_get)
1258 ok(ret, "%d: VirtualProtect error %d, requested prot %#x\n", i, GetLastError(), td[i].prot_set);
1259 ok(old_prot == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, old_prot);
1261 SetLastError(0xdeadbeef);
1262 ret = VirtualQuery(section, &info, sizeof(info));
1263 ok(ret, "VirtualQuery failed %d\n", GetLastError());
1264 ok(info.BaseAddress == section, "%d: got %p != expected %p\n", i, info.BaseAddress, section);
1265 ok(info.RegionSize == page_size, "%d: got %#lx != expected %#x\n", i, info.RegionSize, page_size);
1266 ok(info.Protect == td[i].prot_get, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot_get);
1267 ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base);
1268 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%d: %#x != PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect);
1269 ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State);
1270 ok(info.Type == SEC_IMAGE, "%d: %#x != SEC_IMAGE\n", i, info.Type);
1272 else
1274 ok(!ret, "%d: VirtualProtect should fail\n", i);
1275 ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError());
1278 old_prot = 0xdeadbeef;
1279 SetLastError(0xdeadbeef);
1280 ret = VirtualProtect(section, page_size, PAGE_NOACCESS, &old_prot);
1281 ok(ret, "%d: VirtualProtect error %d\n", i, GetLastError());
1282 if (td[i].prot_get)
1283 ok(old_prot == td[i].prot_get, "%d: got %#x != expected %#x\n", i, old_prot, td[i].prot_get);
1284 else
1285 ok(old_prot == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, old_prot);
1288 exec_prot = 0;
1290 for (i = 0; i <= 4; i++)
1292 rw_prot = 0;
1294 for (j = 0; j <= 4; j++)
1296 DWORD prot = exec_prot | rw_prot;
1298 SetLastError(0xdeadbeef);
1299 ret = VirtualProtect(section, page_size, prot, &old_prot);
1300 if ((rw_prot && exec_prot) || (!rw_prot && !exec_prot))
1302 ok(!ret, "VirtualProtect(%02x) should fail\n", prot);
1303 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1305 else
1306 ok(ret, "VirtualProtect(%02x) error %d\n", prot, GetLastError());
1308 rw_prot = 1 << j;
1311 exec_prot = 1 << (i + 4);
1314 SetLastError(0xdeadbeef);
1315 ret = VirtualProtect(section, page_size, orig_prot, &old_prot);
1316 ok(ret, "VirtualProtect error %d\n", GetLastError());
1319 static void test_section_access(void)
1321 static const struct test_data
1323 DWORD scn_file_access, scn_page_access, scn_page_access_after_write;
1324 } td[] =
1326 { 0, PAGE_NOACCESS, 0 },
1327 { IMAGE_SCN_MEM_READ, PAGE_READONLY, 0 },
1328 { IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY, PAGE_READWRITE },
1329 { IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE, 0 },
1330 { IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY, PAGE_READWRITE },
1331 { IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_READ },
1332 { IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY, PAGE_EXECUTE_READWRITE },
1333 { IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY, PAGE_EXECUTE_READWRITE },
1335 { IMAGE_SCN_CNT_INITIALIZED_DATA, PAGE_NOACCESS, 0 },
1336 { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ, PAGE_READONLY, 0 },
1337 { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY, PAGE_READWRITE },
1338 { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE, 0 },
1339 { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY, PAGE_READWRITE },
1340 { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_READ, 0 },
1341 { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY, PAGE_EXECUTE_READWRITE },
1342 { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY, PAGE_EXECUTE_READWRITE },
1344 { IMAGE_SCN_CNT_UNINITIALIZED_DATA, PAGE_NOACCESS, 0 },
1345 { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ, PAGE_READONLY, 0 },
1346 { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY, PAGE_READWRITE },
1347 { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE, 0 },
1348 { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY, PAGE_READWRITE },
1349 { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_READ, 0 },
1350 { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY, PAGE_EXECUTE_READWRITE },
1351 { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY, PAGE_EXECUTE_READWRITE }
1353 char buf[256];
1354 int i;
1355 DWORD dummy, file_align;
1356 HANDLE hfile;
1357 HMODULE hlib;
1358 char temp_path[MAX_PATH];
1359 char dll_name[MAX_PATH];
1360 SIZE_T size;
1361 MEMORY_BASIC_INFORMATION info;
1362 STARTUPINFOA sti;
1363 PROCESS_INFORMATION pi;
1364 DWORD ret;
1366 /* prevent displaying of the "Unable to load this DLL" message box */
1367 SetErrorMode(SEM_FAILCRITICALERRORS);
1369 GetTempPathA(MAX_PATH, temp_path);
1371 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
1373 IMAGE_NT_HEADERS nt_header;
1375 GetTempFileNameA(temp_path, "ldr", 0, dll_name);
1377 /*trace("creating %s\n", dll_name);*/
1378 hfile = CreateFileA(dll_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
1379 if (hfile == INVALID_HANDLE_VALUE)
1381 ok(0, "could not create %s\n", dll_name);
1382 return;
1385 SetLastError(0xdeadbeef);
1386 ret = WriteFile(hfile, &dos_header, sizeof(dos_header), &dummy, NULL);
1387 ok(ret, "WriteFile error %d\n", GetLastError());
1389 nt_header = nt_header_template;
1390 nt_header.FileHeader.NumberOfSections = 1;
1391 nt_header.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER);
1392 nt_header.FileHeader.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL | IMAGE_FILE_RELOCS_STRIPPED;
1394 nt_header.OptionalHeader.SectionAlignment = page_size;
1395 nt_header.OptionalHeader.FileAlignment = 0x200;
1396 nt_header.OptionalHeader.SizeOfImage = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + page_size;
1397 nt_header.OptionalHeader.SizeOfHeaders = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER);
1398 SetLastError(0xdeadbeef);
1399 ret = WriteFile(hfile, &nt_header, sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER), &dummy, NULL);
1400 ok(ret, "WriteFile error %d\n", GetLastError());
1401 SetLastError(0xdeadbeef);
1402 ret = WriteFile(hfile, &nt_header.OptionalHeader, sizeof(IMAGE_OPTIONAL_HEADER), &dummy, NULL);
1403 ok(ret, "WriteFile error %d\n", GetLastError());
1405 section.SizeOfRawData = sizeof(section_data);
1406 section.PointerToRawData = nt_header.OptionalHeader.FileAlignment;
1407 section.VirtualAddress = nt_header.OptionalHeader.SectionAlignment;
1408 section.Misc.VirtualSize = section.SizeOfRawData;
1409 section.Characteristics = td[i].scn_file_access;
1410 SetLastError(0xdeadbeef);
1411 ret = WriteFile(hfile, &section, sizeof(section), &dummy, NULL);
1412 ok(ret, "WriteFile error %d\n", GetLastError());
1414 file_align = nt_header.OptionalHeader.FileAlignment - nt_header.OptionalHeader.SizeOfHeaders;
1415 assert(file_align < sizeof(filler));
1416 SetLastError(0xdeadbeef);
1417 ret = WriteFile(hfile, filler, file_align, &dummy, NULL);
1418 ok(ret, "WriteFile error %d\n", GetLastError());
1420 /* section data */
1421 SetLastError(0xdeadbeef);
1422 ret = WriteFile(hfile, section_data, sizeof(section_data), &dummy, NULL);
1423 ok(ret, "WriteFile error %d\n", GetLastError());
1425 CloseHandle(hfile);
1427 SetLastError(0xdeadbeef);
1428 hlib = LoadLibraryA(dll_name);
1429 ok(hlib != 0, "LoadLibrary error %d\n", GetLastError());
1431 SetLastError(0xdeadbeef);
1432 size = VirtualQuery((char *)hlib + section.VirtualAddress, &info, sizeof(info));
1433 ok(size == sizeof(info),
1434 "%d: VirtualQuery error %d\n", i, GetLastError());
1435 ok(info.BaseAddress == (char *)hlib + section.VirtualAddress, "%d: got %p != expected %p\n", i, info.BaseAddress, (char *)hlib + section.VirtualAddress);
1436 ok(info.RegionSize == page_size, "%d: got %#lx != expected %#x\n", i, info.RegionSize, page_size);
1437 ok(info.Protect == td[i].scn_page_access, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].scn_page_access);
1438 ok(info.AllocationBase == hlib, "%d: %p != %p\n", i, info.AllocationBase, hlib);
1439 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%d: %#x != PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect);
1440 ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State);
1441 ok(info.Type == SEC_IMAGE, "%d: %#x != SEC_IMAGE\n", i, info.Type);
1442 if (info.Protect != PAGE_NOACCESS)
1443 ok(!memcmp((const char *)info.BaseAddress, section_data, section.SizeOfRawData), "wrong section data\n");
1445 test_VirtualProtect(hlib, (char *)hlib + section.VirtualAddress);
1447 /* Windows changes the WRITECOPY to WRITE protection on an image section write (for a changed page only) */
1448 if (is_mem_writable(info.Protect))
1450 char *p = info.BaseAddress;
1451 *p = 0xfe;
1452 SetLastError(0xdeadbeef);
1453 size = VirtualQuery((char *)hlib + section.VirtualAddress, &info, sizeof(info));
1454 ok(size == sizeof(info), "%d: VirtualQuery error %d\n", i, GetLastError());
1455 /* FIXME: remove the condition below once Wine is fixed */
1456 todo_wine_if (info.Protect == PAGE_WRITECOPY || info.Protect == PAGE_EXECUTE_WRITECOPY)
1457 ok(info.Protect == td[i].scn_page_access_after_write, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].scn_page_access_after_write);
1460 SetLastError(0xdeadbeef);
1461 ret = FreeLibrary(hlib);
1462 ok(ret, "FreeLibrary error %d\n", GetLastError());
1464 test_image_mapping(dll_name, td[i].scn_page_access, TRUE);
1466 /* reset IMAGE_FILE_DLL otherwise CreateProcess fails */
1467 nt_header.FileHeader.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_RELOCS_STRIPPED;
1468 SetLastError(0xdeadbeef);
1469 hfile = CreateFileA(dll_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1470 /* LoadLibrary called on an already memory-mapped file in
1471 * test_image_mapping() above leads to a file handle leak
1472 * under nt4, and inability to overwrite and delete the file
1473 * due to sharing violation error. Ignore it and skip the test,
1474 * but leave a not deletable temporary file.
1476 ok(hfile != INVALID_HANDLE_VALUE || broken(hfile == INVALID_HANDLE_VALUE) /* nt4 */,
1477 "CreateFile error %d\n", GetLastError());
1478 if (hfile == INVALID_HANDLE_VALUE) goto nt4_is_broken;
1479 SetFilePointer(hfile, sizeof(dos_header), NULL, FILE_BEGIN);
1480 SetLastError(0xdeadbeef);
1481 ret = WriteFile(hfile, &nt_header, sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER), &dummy, NULL);
1482 ok(ret, "WriteFile error %d\n", GetLastError());
1483 CloseHandle(hfile);
1485 memset(&sti, 0, sizeof(sti));
1486 sti.cb = sizeof(sti);
1487 SetLastError(0xdeadbeef);
1488 ret = CreateProcessA(dll_name, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &sti, &pi);
1489 ok(ret, "CreateProcess() error %d\n", GetLastError());
1491 SetLastError(0xdeadbeef);
1492 size = VirtualQueryEx(pi.hProcess, (char *)hlib + section.VirtualAddress, &info, sizeof(info));
1493 ok(size == sizeof(info),
1494 "%d: VirtualQuery error %d\n", i, GetLastError());
1495 ok(info.BaseAddress == (char *)hlib + section.VirtualAddress, "%d: got %p != expected %p\n", i, info.BaseAddress, (char *)hlib + section.VirtualAddress);
1496 ok(info.RegionSize == page_size, "%d: got %#lx != expected %#x\n", i, info.RegionSize, page_size);
1497 ok(info.Protect == td[i].scn_page_access, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].scn_page_access);
1498 ok(info.AllocationBase == hlib, "%d: %p != %p\n", i, info.AllocationBase, hlib);
1499 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%d: %#x != PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect);
1500 ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State);
1501 ok(info.Type == SEC_IMAGE, "%d: %#x != SEC_IMAGE\n", i, info.Type);
1502 if (info.Protect != PAGE_NOACCESS)
1504 SetLastError(0xdeadbeef);
1505 ret = ReadProcessMemory(pi.hProcess, info.BaseAddress, buf, section.SizeOfRawData, NULL);
1506 ok(ret, "ReadProcessMemory() error %d\n", GetLastError());
1507 ok(!memcmp(buf, section_data, section.SizeOfRawData), "wrong section data\n");
1510 SetLastError(0xdeadbeef);
1511 ret = TerminateProcess(pi.hProcess, 0);
1512 ok(ret, "TerminateProcess() error %d\n", GetLastError());
1513 ret = WaitForSingleObject(pi.hProcess, 3000);
1514 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed: %x\n", ret);
1516 CloseHandle(pi.hThread);
1517 CloseHandle(pi.hProcess);
1519 test_image_mapping(dll_name, td[i].scn_page_access, FALSE);
1521 nt4_is_broken:
1522 SetLastError(0xdeadbeef);
1523 ret = DeleteFileA(dll_name);
1524 ok(ret || broken(!ret) /* nt4 */, "DeleteFile error %d\n", GetLastError());
1528 static void test_import_resolution(void)
1530 char temp_path[MAX_PATH];
1531 char dll_name[MAX_PATH];
1532 DWORD dummy;
1533 void *expect;
1534 char *str;
1535 HANDLE hfile;
1536 HMODULE mod, mod2;
1537 struct imports
1539 IMAGE_IMPORT_DESCRIPTOR descr[2];
1540 IMAGE_THUNK_DATA original_thunks[2];
1541 IMAGE_THUNK_DATA thunks[2];
1542 char module[16];
1543 struct { WORD hint; char name[32]; } function;
1544 IMAGE_TLS_DIRECTORY tls;
1545 char tls_data[16];
1546 SHORT tls_index;
1547 } data, *ptr;
1548 IMAGE_NT_HEADERS nt;
1549 IMAGE_SECTION_HEADER section;
1550 int test;
1552 for (test = 0; test < 3; test++)
1554 #define DATA_RVA(ptr) (page_size + ((char *)(ptr) - (char *)&data))
1555 nt = nt_header_template;
1556 nt.FileHeader.NumberOfSections = 1;
1557 nt.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER);
1558 nt.FileHeader.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_RELOCS_STRIPPED;
1559 if (test != 2) nt.FileHeader.Characteristics |= IMAGE_FILE_DLL;
1560 nt.OptionalHeader.SectionAlignment = page_size;
1561 nt.OptionalHeader.FileAlignment = 0x200;
1562 nt.OptionalHeader.ImageBase = 0x12340000;
1563 nt.OptionalHeader.SizeOfImage = 2 * page_size;
1564 nt.OptionalHeader.SizeOfHeaders = nt.OptionalHeader.FileAlignment;
1565 nt.OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
1566 memset( nt.OptionalHeader.DataDirectory, 0, sizeof(nt.OptionalHeader.DataDirectory) );
1567 nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = sizeof(data.descr);
1568 nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = DATA_RVA(data.descr);
1569 nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size = sizeof(data.tls);
1570 nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress = DATA_RVA(&data.tls);
1572 memset( &data, 0, sizeof(data) );
1573 data.descr[0].u.OriginalFirstThunk = DATA_RVA( data.original_thunks );
1574 data.descr[0].FirstThunk = DATA_RVA( data.thunks );
1575 data.descr[0].Name = DATA_RVA( data.module );
1576 strcpy( data.module, "kernel32.dll" );
1577 strcpy( data.function.name, "CreateEventA" );
1578 data.original_thunks[0].u1.AddressOfData = DATA_RVA( &data.function );
1579 data.thunks[0].u1.AddressOfData = 0xdeadbeef;
1581 data.tls.StartAddressOfRawData = nt.OptionalHeader.ImageBase + DATA_RVA( data.tls_data );
1582 data.tls.EndAddressOfRawData = data.tls.StartAddressOfRawData + sizeof(data.tls_data);
1583 data.tls.AddressOfIndex = nt.OptionalHeader.ImageBase + DATA_RVA( &data.tls_index );
1584 strcpy( data.tls_data, "hello world" );
1585 data.tls_index = 9999;
1587 GetTempPathA(MAX_PATH, temp_path);
1588 GetTempFileNameA(temp_path, "ldr", 0, dll_name);
1590 hfile = CreateFileA(dll_name, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, 0);
1591 ok( hfile != INVALID_HANDLE_VALUE, "creation failed\n" );
1593 memset( &section, 0, sizeof(section) );
1594 memcpy( section.Name, ".text", sizeof(".text") );
1595 section.PointerToRawData = nt.OptionalHeader.FileAlignment;
1596 section.VirtualAddress = nt.OptionalHeader.SectionAlignment;
1597 section.Misc.VirtualSize = sizeof(data);
1598 section.SizeOfRawData = sizeof(data);
1599 section.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
1601 WriteFile(hfile, &dos_header, sizeof(dos_header), &dummy, NULL);
1602 WriteFile(hfile, &nt, sizeof(nt), &dummy, NULL);
1603 WriteFile(hfile, &section, sizeof(section), &dummy, NULL);
1605 SetFilePointer( hfile, section.PointerToRawData, NULL, SEEK_SET );
1606 WriteFile(hfile, &data, sizeof(data), &dummy, NULL);
1608 CloseHandle( hfile );
1610 switch (test)
1612 case 0: /* normal load */
1613 mod = LoadLibraryA( dll_name );
1614 ok( mod != NULL, "failed to load err %u\n", GetLastError() );
1615 if (!mod) break;
1616 ptr = (struct imports *)((char *)mod + page_size);
1617 expect = GetProcAddress( GetModuleHandleA( data.module ), data.function.name );
1618 ok( (void *)ptr->thunks[0].u1.Function == expect, "thunk %p instead of %p for %s.%s\n",
1619 (void *)ptr->thunks[0].u1.Function, expect, data.module, data.function.name );
1620 ok( ptr->tls_index < 32 || broken(ptr->tls_index == 9999), /* before vista */
1621 "wrong tls index %d\n", ptr->tls_index );
1622 if (ptr->tls_index != 9999)
1624 str = ((char **)NtCurrentTeb()->ThreadLocalStoragePointer)[ptr->tls_index];
1625 ok( !strcmp( str, "hello world" ), "wrong tls data '%s' at %p\n", str, str );
1627 FreeLibrary( mod );
1628 break;
1629 case 1: /* load with DONT_RESOLVE_DLL_REFERENCES doesn't resolve imports */
1630 mod = LoadLibraryExA( dll_name, 0, DONT_RESOLVE_DLL_REFERENCES );
1631 ok( mod != NULL, "failed to load err %u\n", GetLastError() );
1632 if (!mod) break;
1633 ptr = (struct imports *)((char *)mod + page_size);
1634 ok( ptr->thunks[0].u1.Function == 0xdeadbeef, "thunk resolved to %p for %s.%s\n",
1635 (void *)ptr->thunks[0].u1.Function, data.module, data.function.name );
1636 ok( ptr->tls_index == 9999, "wrong tls index %d\n", ptr->tls_index );
1638 mod2 = LoadLibraryA( dll_name );
1639 ok( mod2 == mod, "loaded twice %p / %p\n", mod, mod2 );
1640 ok( ptr->thunks[0].u1.Function == 0xdeadbeef, "thunk resolved to %p for %s.%s\n",
1641 (void *)ptr->thunks[0].u1.Function, data.module, data.function.name );
1642 ok( ptr->tls_index == 9999, "wrong tls index %d\n", ptr->tls_index );
1643 FreeLibrary( mod2 );
1644 FreeLibrary( mod );
1645 break;
1646 case 2: /* load without IMAGE_FILE_DLL doesn't resolve imports */
1647 mod = LoadLibraryA( dll_name );
1648 ok( mod != NULL, "failed to load err %u\n", GetLastError() );
1649 if (!mod) break;
1650 ptr = (struct imports *)((char *)mod + page_size);
1651 ok( ptr->thunks[0].u1.Function == 0xdeadbeef, "thunk resolved to %p for %s.%s\n",
1652 (void *)ptr->thunks[0].u1.Function, data.module, data.function.name );
1653 ok( ptr->tls_index == 9999, "wrong tls index %d\n", ptr->tls_index );
1654 FreeLibrary( mod );
1655 break;
1657 DeleteFileA( dll_name );
1658 #undef DATA_RVA
1662 #define MAX_COUNT 10
1663 static HANDLE attached_thread[MAX_COUNT];
1664 static DWORD attached_thread_count;
1665 HANDLE stop_event, event, mutex, semaphore, loader_lock_event, peb_lock_event, heap_lock_event, ack_event;
1666 static int test_dll_phase, inside_loader_lock, inside_peb_lock, inside_heap_lock;
1667 static LONG fls_callback_count;
1669 static DWORD WINAPI mutex_thread_proc(void *param)
1671 HANDLE wait_list[4];
1672 DWORD ret;
1674 ret = WaitForSingleObject(mutex, 0);
1675 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %#x\n", ret);
1677 SetEvent(param);
1679 wait_list[0] = stop_event;
1680 wait_list[1] = loader_lock_event;
1681 wait_list[2] = peb_lock_event;
1682 wait_list[3] = heap_lock_event;
1684 trace("%04x: mutex_thread_proc: starting\n", GetCurrentThreadId());
1685 while (1)
1687 ret = WaitForMultipleObjects(sizeof(wait_list)/sizeof(wait_list[0]), wait_list, FALSE, 50);
1688 if (ret == WAIT_OBJECT_0) break;
1689 else if (ret == WAIT_OBJECT_0 + 1)
1691 ULONG_PTR loader_lock_magic;
1692 trace("%04x: mutex_thread_proc: Entering loader lock\n", GetCurrentThreadId());
1693 ret = pLdrLockLoaderLock(0, NULL, &loader_lock_magic);
1694 ok(!ret, "LdrLockLoaderLock error %#x\n", ret);
1695 inside_loader_lock++;
1696 SetEvent(ack_event);
1698 else if (ret == WAIT_OBJECT_0 + 2)
1700 trace("%04x: mutex_thread_proc: Entering PEB lock\n", GetCurrentThreadId());
1701 pRtlAcquirePebLock();
1702 inside_peb_lock++;
1703 SetEvent(ack_event);
1705 else if (ret == WAIT_OBJECT_0 + 3)
1707 trace("%04x: mutex_thread_proc: Entering heap lock\n", GetCurrentThreadId());
1708 HeapLock(GetProcessHeap());
1709 inside_heap_lock++;
1710 SetEvent(ack_event);
1714 trace("%04x: mutex_thread_proc: exiting\n", GetCurrentThreadId());
1715 return 196;
1718 static DWORD WINAPI semaphore_thread_proc(void *param)
1720 DWORD ret;
1722 ret = WaitForSingleObject(semaphore, 0);
1723 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %#x\n", ret);
1725 SetEvent(param);
1727 while (1)
1729 if (winetest_debug > 1)
1730 trace("%04x: semaphore_thread_proc: still alive\n", GetCurrentThreadId());
1731 if (WaitForSingleObject(stop_event, 50) != WAIT_TIMEOUT) break;
1734 trace("%04x: semaphore_thread_proc: exiting\n", GetCurrentThreadId());
1735 return 196;
1738 static DWORD WINAPI noop_thread_proc(void *param)
1740 if (param)
1742 LONG *noop_thread_started = param;
1743 InterlockedIncrement(noop_thread_started);
1746 trace("%04x: noop_thread_proc: exiting\n", GetCurrentThreadId());
1747 return 195;
1750 static VOID WINAPI fls_callback(PVOID lpFlsData)
1752 ok(lpFlsData == (void*) 0x31415, "lpFlsData is %p, expected %p\n", lpFlsData, (void*) 0x31415);
1753 InterlockedIncrement(&fls_callback_count);
1756 static BOOL WINAPI dll_entry_point(HINSTANCE hinst, DWORD reason, LPVOID param)
1758 static LONG noop_thread_started;
1759 static DWORD fls_index = FLS_OUT_OF_INDEXES;
1760 static int fls_count = 0;
1761 static int thread_detach_count = 0;
1762 DWORD ret;
1764 ok(!inside_loader_lock, "inside_loader_lock should not be set\n");
1765 ok(!inside_peb_lock, "inside_peb_lock should not be set\n");
1767 switch (reason)
1769 case DLL_PROCESS_ATTACH:
1770 trace("dll: %p, DLL_PROCESS_ATTACH, %p\n", hinst, param);
1772 ret = pRtlDllShutdownInProgress();
1773 ok(!ret, "RtlDllShutdownInProgress returned %d\n", ret);
1775 /* Set up the FLS slot, if FLS is available */
1776 if (pFlsGetValue)
1778 void* value;
1779 BOOL bret;
1780 ret = pFlsAlloc(&fls_callback);
1781 ok(ret != FLS_OUT_OF_INDEXES, "FlsAlloc returned %d\n", ret);
1782 fls_index = ret;
1783 SetLastError(0xdeadbeef);
1784 value = pFlsGetValue(fls_index);
1785 ok(!value, "FlsGetValue returned %p, expected NULL\n", value);
1786 ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %u\n", GetLastError());
1787 bret = pFlsSetValue(fls_index, (void*) 0x31415);
1788 ok(bret, "FlsSetValue failed\n");
1789 fls_count++;
1792 break;
1793 case DLL_PROCESS_DETACH:
1795 DWORD code, expected_code, i;
1796 HANDLE handle, process;
1797 void *addr;
1798 SIZE_T size;
1799 LARGE_INTEGER offset;
1800 DEBUG_EVENT de;
1802 trace("dll: %p, DLL_PROCESS_DETACH, %p\n", hinst, param);
1804 if (test_dll_phase == 4 || test_dll_phase == 5)
1806 ok(0, "dll_entry_point(DLL_PROCESS_DETACH) should not be called\n");
1807 break;
1810 /* The process should already deadlock at this point */
1811 if (test_dll_phase == 6)
1813 /* In reality, code below never gets executed, probably some other
1814 * code tries to access process heap and deadlocks earlier, even XP
1815 * doesn't call the DLL entry point on process detach either.
1817 HeapLock(GetProcessHeap());
1818 ok(0, "dll_entry_point: process should already deadlock\n");
1819 break;
1822 if (test_dll_phase == 0 || test_dll_phase == 1 || test_dll_phase == 3)
1823 ok(param != NULL, "dll: param %p\n", param);
1824 else
1825 ok(!param, "dll: param %p\n", param);
1827 if (test_dll_phase == 0 || test_dll_phase == 1) expected_code = 195;
1828 else if (test_dll_phase == 3) expected_code = 196;
1829 else expected_code = STILL_ACTIVE;
1831 if (test_dll_phase == 3)
1833 ret = pRtlDllShutdownInProgress();
1834 ok(ret, "RtlDllShutdownInProgress returned %d\n", ret);
1836 else
1838 ret = pRtlDllShutdownInProgress();
1840 /* FIXME: remove once Wine is fixed */
1841 todo_wine_if (!(expected_code == STILL_ACTIVE || expected_code == 196))
1842 ok(!ret || broken(ret) /* before Vista */, "RtlDllShutdownInProgress returned %d\n", ret);
1845 /* In the case that the process is terminating, FLS slots should still be accessible, but
1846 * the callback should be already run for this thread and the contents already NULL.
1847 * Note that this is broken for Win2k3, which runs the callbacks *after* the DLL entry
1848 * point has already run.
1850 if (param && pFlsGetValue)
1852 void* value;
1853 SetLastError(0xdeadbeef);
1854 value = pFlsGetValue(fls_index);
1855 todo_wine
1857 ok(broken(value == (void*) 0x31415) || /* Win2k3 */
1858 value == NULL, "FlsGetValue returned %p, expected NULL\n", value);
1860 ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %u\n", GetLastError());
1861 todo_wine
1863 ok(broken(fls_callback_count == thread_detach_count) || /* Win2k3 */
1864 fls_callback_count == thread_detach_count + 1,
1865 "wrong FLS callback count %d, expected %d\n", fls_callback_count, thread_detach_count + 1);
1868 if (pFlsFree)
1870 BOOL ret;
1871 /* Call FlsFree now and run the remaining callbacks from uncleanly terminated threads */
1872 ret = pFlsFree(fls_index);
1873 ok(ret, "FlsFree failed with error %u\n", GetLastError());
1874 fls_index = FLS_OUT_OF_INDEXES;
1875 todo_wine
1877 ok(fls_callback_count == fls_count,
1878 "wrong FLS callback count %d, expected %d\n", fls_callback_count, fls_count);
1882 ok(attached_thread_count >= 2, "attached thread count should be >= 2\n");
1884 for (i = 0; i < attached_thread_count; i++)
1886 /* Calling GetExitCodeThread() without waiting for thread termination
1887 * leads to different results due to a race condition.
1889 if (expected_code != STILL_ACTIVE)
1891 ret = WaitForSingleObject(attached_thread[i], 1000);
1892 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %#x\n", ret);
1894 ret = GetExitCodeThread(attached_thread[i], &code);
1895 trace("dll: GetExitCodeThread(%u) => %d,%u\n", i, ret, code);
1896 ok(ret == 1, "GetExitCodeThread returned %d, expected 1\n", ret);
1897 ok(code == expected_code, "expected thread exit code %u, got %u\n", expected_code, code);
1900 ret = WaitForSingleObject(event, 0);
1901 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret);
1903 ret = WaitForSingleObject(mutex, 0);
1904 if (expected_code == STILL_ACTIVE)
1905 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret);
1906 else
1907 ok(ret == WAIT_ABANDONED, "expected WAIT_ABANDONED, got %#x\n", ret);
1909 /* semaphore is not abandoned on thread termination */
1910 ret = WaitForSingleObject(semaphore, 0);
1911 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret);
1913 if (expected_code == STILL_ACTIVE)
1915 ret = WaitForSingleObject(attached_thread[0], 0);
1916 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret);
1917 ret = WaitForSingleObject(attached_thread[1], 0);
1918 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret);
1920 else
1922 ret = WaitForSingleObject(attached_thread[0], 0);
1923 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %#x\n", ret);
1924 ret = WaitForSingleObject(attached_thread[1], 0);
1925 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %#x\n", ret);
1928 /* win7 doesn't allow creating a thread during process shutdown but
1929 * earlier Windows versions allow it.
1931 noop_thread_started = 0;
1932 SetLastError(0xdeadbeef);
1933 handle = CreateThread(NULL, 0, noop_thread_proc, &noop_thread_started, 0, &ret);
1934 if (param)
1936 ok(!handle || broken(handle != 0) /* before win7 */, "CreateThread should fail\n");
1937 if (!handle)
1938 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1939 else
1941 ret = WaitForSingleObject(handle, 1000);
1942 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret);
1943 CloseHandle(handle);
1946 else
1948 ok(handle != 0, "CreateThread error %d\n", GetLastError());
1949 ret = WaitForSingleObject(handle, 1000);
1950 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret);
1951 ok(!noop_thread_started || broken(noop_thread_started) /* XP64 */, "thread shouldn't start yet\n");
1952 CloseHandle(handle);
1955 SetLastError(0xdeadbeef);
1956 process = OpenProcess(PROCESS_ALL_ACCESS_NT4, FALSE, GetCurrentProcessId());
1957 ok(process != NULL, "OpenProcess error %d\n", GetLastError());
1959 noop_thread_started = 0;
1960 SetLastError(0xdeadbeef);
1961 handle = CreateRemoteThread(process, NULL, 0, noop_thread_proc, &noop_thread_started, 0, &ret);
1962 if (param)
1964 ok(!handle || broken(handle != 0) /* before win7 */, "CreateRemoteThread should fail\n");
1965 if (!handle)
1966 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1967 else
1969 ret = WaitForSingleObject(handle, 1000);
1970 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret);
1971 CloseHandle(handle);
1974 else
1976 ok(handle != 0, "CreateRemoteThread error %d\n", GetLastError());
1977 ret = WaitForSingleObject(handle, 1000);
1978 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret);
1979 ok(!noop_thread_started || broken(noop_thread_started) /* XP64 */, "thread shouldn't start yet\n");
1980 CloseHandle(handle);
1983 SetLastError(0xdeadbeef);
1984 handle = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, NULL);
1985 ok(handle != 0, "CreateFileMapping error %d\n", GetLastError());
1987 offset.u.LowPart = 0;
1988 offset.u.HighPart = 0;
1989 addr = NULL;
1990 size = 0;
1991 ret = pNtMapViewOfSection(handle, process, &addr, 0, 0, &offset,
1992 &size, 1 /* ViewShare */, 0, PAGE_READONLY);
1993 ok(ret == STATUS_SUCCESS, "NtMapViewOfSection error %#x\n", ret);
1994 ret = pNtUnmapViewOfSection(process, addr);
1995 ok(ret == STATUS_SUCCESS, "NtUnmapViewOfSection error %#x\n", ret);
1997 CloseHandle(handle);
1998 CloseHandle(process);
2000 handle = GetModuleHandleA("winver.exe");
2001 ok(!handle, "winver.exe shouldn't be loaded yet\n");
2002 SetLastError(0xdeadbeef);
2003 handle = LoadLibraryA("winver.exe");
2004 ok(handle != 0, "LoadLibrary error %d\n", GetLastError());
2005 SetLastError(0xdeadbeef);
2006 ret = FreeLibrary(handle);
2007 ok(ret, "FreeLibrary error %d\n", GetLastError());
2008 handle = GetModuleHandleA("winver.exe");
2009 if (param)
2010 ok(handle != 0, "winver.exe should not be unloaded\n");
2011 else
2012 todo_wine
2013 ok(!handle || broken(handle != 0) /* before win7 */, "winver.exe should be unloaded\n");
2015 SetLastError(0xdeadbeef);
2016 ret = WaitForDebugEvent(&de, 0);
2017 ok(!ret, "WaitForDebugEvent should fail\n");
2018 todo_wine
2019 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
2021 SetLastError(0xdeadbeef);
2022 ret = DebugActiveProcess(GetCurrentProcessId());
2023 ok(!ret, "DebugActiveProcess should fail\n");
2024 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
2026 SetLastError(0xdeadbeef);
2027 ret = WaitForDebugEvent(&de, 0);
2028 ok(!ret, "WaitForDebugEvent should fail\n");
2029 ok(GetLastError() == ERROR_SEM_TIMEOUT, "expected ERROR_SEM_TIMEOUT, got %d\n", GetLastError());
2031 if (test_dll_phase == 2)
2033 trace("dll: call ExitProcess()\n");
2034 *child_failures = winetest_get_failures();
2035 ExitProcess(197);
2037 trace("dll: %p, DLL_PROCESS_DETACH, %p => DONE\n", hinst, param);
2038 break;
2040 case DLL_THREAD_ATTACH:
2041 trace("dll: %p, DLL_THREAD_ATTACH, %p\n", hinst, param);
2043 ret = pRtlDllShutdownInProgress();
2044 ok(!ret, "RtlDllShutdownInProgress returned %d\n", ret);
2046 if (attached_thread_count < MAX_COUNT)
2048 DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &attached_thread[attached_thread_count],
2049 0, TRUE, DUPLICATE_SAME_ACCESS);
2050 attached_thread_count++;
2053 /* Make sure the FLS slot is empty, if FLS is available */
2054 if (pFlsGetValue)
2056 void* value;
2057 BOOL ret;
2058 SetLastError(0xdeadbeef);
2059 value = pFlsGetValue(fls_index);
2060 ok(!value, "FlsGetValue returned %p, expected NULL\n", value);
2061 todo_wine
2062 ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %u\n", GetLastError());
2063 ret = pFlsSetValue(fls_index, (void*) 0x31415);
2064 ok(ret, "FlsSetValue failed\n");
2065 fls_count++;
2068 break;
2069 case DLL_THREAD_DETACH:
2070 trace("dll: %p, DLL_THREAD_DETACH, %p\n", hinst, param);
2071 thread_detach_count++;
2073 ret = pRtlDllShutdownInProgress();
2074 /* win7 doesn't allow creating a thread during process shutdown but
2075 * earlier Windows versions allow it. In that case DLL_THREAD_DETACH is
2076 * sent on thread exit, but DLL_THREAD_ATTACH is never received.
2078 if (noop_thread_started)
2079 ok(ret, "RtlDllShutdownInProgress returned %d\n", ret);
2080 else
2081 ok(!ret, "RtlDllShutdownInProgress returned %d\n", ret);
2083 /* FLS data should already be destroyed, if FLS is available.
2084 * Note that this is broken for Win2k3, which runs the callbacks *after* the DLL entry
2085 * point has already run.
2087 if (pFlsGetValue && fls_index != FLS_OUT_OF_INDEXES)
2089 void* value;
2090 SetLastError(0xdeadbeef);
2091 value = pFlsGetValue(fls_index);
2092 todo_wine
2094 ok(broken(value == (void*) 0x31415) || /* Win2k3 */
2095 !value, "FlsGetValue returned %p, expected NULL\n", value);
2097 ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %u\n", GetLastError());
2100 break;
2101 default:
2102 trace("dll: %p, %d, %p\n", hinst, reason, param);
2103 break;
2106 *child_failures = winetest_get_failures();
2108 return TRUE;
2111 static void child_process(const char *dll_name, DWORD target_offset)
2113 void *target;
2114 DWORD ret, dummy, i, code, expected_code;
2115 HANDLE file, thread, process;
2116 HMODULE hmod;
2117 struct PROCESS_BASIC_INFORMATION_PRIVATE pbi;
2118 DWORD_PTR affinity;
2120 trace("phase %d: writing %p at %#x\n", test_dll_phase, dll_entry_point, target_offset);
2122 SetLastError(0xdeadbeef);
2123 mutex = CreateMutexW(NULL, FALSE, NULL);
2124 ok(mutex != 0, "CreateMutex error %d\n", GetLastError());
2126 SetLastError(0xdeadbeef);
2127 semaphore = CreateSemaphoreW(NULL, 1, 1, NULL);
2128 ok(semaphore != 0, "CreateSemaphore error %d\n", GetLastError());
2130 SetLastError(0xdeadbeef);
2131 event = CreateEventW(NULL, TRUE, FALSE, NULL);
2132 ok(event != 0, "CreateEvent error %d\n", GetLastError());
2134 SetLastError(0xdeadbeef);
2135 loader_lock_event = CreateEventW(NULL, FALSE, FALSE, NULL);
2136 ok(loader_lock_event != 0, "CreateEvent error %d\n", GetLastError());
2138 SetLastError(0xdeadbeef);
2139 peb_lock_event = CreateEventW(NULL, FALSE, FALSE, NULL);
2140 ok(peb_lock_event != 0, "CreateEvent error %d\n", GetLastError());
2142 SetLastError(0xdeadbeef);
2143 heap_lock_event = CreateEventW(NULL, FALSE, FALSE, NULL);
2144 ok(heap_lock_event != 0, "CreateEvent error %d\n", GetLastError());
2146 SetLastError(0xdeadbeef);
2147 ack_event = CreateEventW(NULL, FALSE, FALSE, NULL);
2148 ok(ack_event != 0, "CreateEvent error %d\n", GetLastError());
2150 file = CreateFileA(dll_name, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
2151 if (file == INVALID_HANDLE_VALUE)
2153 ok(0, "could not open %s\n", dll_name);
2154 return;
2156 SetFilePointer(file, target_offset, NULL, FILE_BEGIN);
2157 SetLastError(0xdeadbeef);
2158 target = dll_entry_point;
2159 ret = WriteFile(file, &target, sizeof(target), &dummy, NULL);
2160 ok(ret, "WriteFile error %d\n", GetLastError());
2161 CloseHandle(file);
2163 SetLastError(0xdeadbeef);
2164 hmod = LoadLibraryA(dll_name);
2165 ok(hmod != 0, "LoadLibrary error %d\n", GetLastError());
2167 SetLastError(0xdeadbeef);
2168 stop_event = CreateEventW(NULL, TRUE, FALSE, NULL);
2169 ok(stop_event != 0, "CreateEvent error %d\n", GetLastError());
2171 SetLastError(0xdeadbeef);
2172 thread = CreateThread(NULL, 0, mutex_thread_proc, event, 0, &dummy);
2173 ok(thread != 0, "CreateThread error %d\n", GetLastError());
2174 WaitForSingleObject(event, 3000);
2175 CloseHandle(thread);
2177 ResetEvent(event);
2179 SetLastError(0xdeadbeef);
2180 thread = CreateThread(NULL, 0, semaphore_thread_proc, event, 0, &dummy);
2181 ok(thread != 0, "CreateThread error %d\n", GetLastError());
2182 WaitForSingleObject(event, 3000);
2183 CloseHandle(thread);
2185 ResetEvent(event);
2186 Sleep(100);
2188 ok(attached_thread_count == 2, "attached thread count should be 2\n");
2189 for (i = 0; i < attached_thread_count; i++)
2191 ret = GetExitCodeThread(attached_thread[i], &code);
2192 trace("child: GetExitCodeThread(%u) => %d,%u\n", i, ret, code);
2193 ok(ret == 1, "GetExitCodeThread returned %d, expected 1\n", ret);
2194 ok(code == STILL_ACTIVE, "expected thread exit code STILL_ACTIVE, got %u\n", code);
2197 ret = WaitForSingleObject(attached_thread[0], 0);
2198 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret);
2199 ret = WaitForSingleObject(attached_thread[1], 0);
2200 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret);
2202 ret = WaitForSingleObject(event, 0);
2203 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret);
2204 ret = WaitForSingleObject(mutex, 0);
2205 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret);
2206 ret = WaitForSingleObject(semaphore, 0);
2207 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret);
2209 ret = pRtlDllShutdownInProgress();
2210 ok(!ret, "RtlDllShutdownInProgress returned %d\n", ret);
2212 SetLastError(0xdeadbeef);
2213 process = OpenProcess(PROCESS_ALL_ACCESS_NT4, FALSE, GetCurrentProcessId());
2214 ok(process != NULL, "OpenProcess error %d\n", GetLastError());
2216 SetLastError(0xdeadbeef);
2217 ret = TerminateProcess(0, 195);
2218 ok(!ret, "TerminateProcess(0) should fail\n");
2219 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
2221 Sleep(100);
2223 affinity = 1;
2224 ret = pNtSetInformationProcess(process, ProcessAffinityMask, &affinity, sizeof(affinity));
2225 ok(!ret, "NtSetInformationProcess error %#x\n", ret);
2227 switch (test_dll_phase)
2229 case 0:
2230 ret = pRtlDllShutdownInProgress();
2231 ok(!ret, "RtlDllShutdownInProgress returned %d\n", ret);
2233 trace("call NtTerminateProcess(0, 195)\n");
2234 ret = pNtTerminateProcess(0, 195);
2235 ok(!ret, "NtTerminateProcess error %#x\n", ret);
2237 memset(&pbi, 0, sizeof(pbi));
2238 ret = pNtQueryInformationProcess(process, ProcessBasicInformation, &pbi, sizeof(pbi), NULL);
2239 ok(!ret, "NtQueryInformationProcess error %#x\n", ret);
2240 ok(pbi.ExitStatus == STILL_ACTIVE || pbi.ExitStatus == 195,
2241 "expected STILL_ACTIVE, got %lu\n", pbi.ExitStatus);
2242 affinity = 1;
2243 ret = pNtSetInformationProcess(process, ProcessAffinityMask, &affinity, sizeof(affinity));
2244 ok(!ret, "NtSetInformationProcess error %#x\n", ret);
2246 ret = pRtlDllShutdownInProgress();
2247 ok(!ret, "RtlDllShutdownInProgress returned %d\n", ret);
2249 hmod = GetModuleHandleA(dll_name);
2250 ok(hmod != 0, "DLL should not be unloaded\n");
2252 SetLastError(0xdeadbeef);
2253 thread = CreateThread(NULL, 0, noop_thread_proc, &dummy, 0, &ret);
2254 ok(!thread || broken(thread != 0) /* before win7 */, "CreateThread should fail\n");
2255 if (!thread)
2256 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
2257 else
2259 ret = WaitForSingleObject(thread, 1000);
2260 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %#x\n", ret);
2261 CloseHandle(thread);
2264 trace("call LdrShutdownProcess()\n");
2265 pLdrShutdownProcess();
2267 ret = pRtlDllShutdownInProgress();
2268 ok(ret, "RtlDllShutdownInProgress returned %d\n", ret);
2270 hmod = GetModuleHandleA(dll_name);
2271 ok(hmod != 0, "DLL should not be unloaded\n");
2273 memset(&pbi, 0, sizeof(pbi));
2274 ret = pNtQueryInformationProcess(process, ProcessBasicInformation, &pbi, sizeof(pbi), NULL);
2275 ok(!ret, "NtQueryInformationProcess error %#x\n", ret);
2276 ok(pbi.ExitStatus == STILL_ACTIVE || pbi.ExitStatus == 195,
2277 "expected STILL_ACTIVE, got %lu\n", pbi.ExitStatus);
2278 affinity = 1;
2279 ret = pNtSetInformationProcess(process, ProcessAffinityMask, &affinity, sizeof(affinity));
2280 ok(!ret, "NtSetInformationProcess error %#x\n", ret);
2281 break;
2283 case 1: /* normal ExitProcess */
2284 ret = pRtlDllShutdownInProgress();
2285 ok(!ret, "RtlDllShutdownInProgress returned %d\n", ret);
2286 break;
2288 case 2: /* ExitProcess will be called by the PROCESS_DETACH handler */
2289 ret = pRtlDllShutdownInProgress();
2290 ok(!ret, "RtlDllShutdownInProgress returned %d\n", ret);
2292 trace("call FreeLibrary(%p)\n", hmod);
2293 SetLastError(0xdeadbeef);
2294 ret = FreeLibrary(hmod);
2295 ok(ret, "FreeLibrary error %d\n", GetLastError());
2296 hmod = GetModuleHandleA(dll_name);
2297 ok(!hmod, "DLL should be unloaded\n");
2299 if (test_dll_phase == 2)
2300 ok(0, "FreeLibrary+ExitProcess should never return\n");
2302 ret = pRtlDllShutdownInProgress();
2303 ok(!ret, "RtlDllShutdownInProgress returned %d\n", ret);
2305 break;
2307 case 3:
2308 trace("signalling thread exit\n");
2309 SetEvent(stop_event);
2310 break;
2312 case 4:
2313 trace("setting loader_lock_event\n");
2314 SetEvent(loader_lock_event);
2315 WaitForSingleObject(ack_event, 1000);
2316 ok(inside_loader_lock != 0, "inside_loader_lock is not set\n");
2318 /* calling NtTerminateProcess should not cause a deadlock */
2319 trace("call NtTerminateProcess(0, 198)\n");
2320 ret = pNtTerminateProcess(0, 198);
2321 ok(!ret, "NtTerminateProcess error %#x\n", ret);
2323 *child_failures = winetest_get_failures();
2325 /* Windows fails to release loader lock acquired from another thread,
2326 * so the LdrUnlockLoaderLock call fails here and ExitProcess deadlocks
2327 * later on, so NtTerminateProcess is used instead.
2329 trace("call NtTerminateProcess(GetCurrentProcess(), 198)\n");
2330 pNtTerminateProcess(GetCurrentProcess(), 198);
2331 ok(0, "NtTerminateProcess should not return\n");
2332 break;
2334 case 5:
2335 trace("setting peb_lock_event\n");
2336 SetEvent(peb_lock_event);
2337 WaitForSingleObject(ack_event, 1000);
2338 ok(inside_peb_lock != 0, "inside_peb_lock is not set\n");
2340 *child_failures = winetest_get_failures();
2342 /* calling ExitProcess should cause a deadlock */
2343 trace("call ExitProcess(198)\n");
2344 ExitProcess(198);
2345 ok(0, "ExitProcess should not return\n");
2346 break;
2348 case 6:
2349 trace("setting heap_lock_event\n");
2350 SetEvent(heap_lock_event);
2351 WaitForSingleObject(ack_event, 1000);
2352 ok(inside_heap_lock != 0, "inside_heap_lock is not set\n");
2354 *child_failures = winetest_get_failures();
2356 /* calling ExitProcess should cause a deadlock */
2357 trace("call ExitProcess(1)\n");
2358 ExitProcess(1);
2359 ok(0, "ExitProcess should not return\n");
2360 break;
2362 default:
2363 assert(0);
2364 break;
2367 if (test_dll_phase == 0) expected_code = 195;
2368 else if (test_dll_phase == 3) expected_code = 196;
2369 else if (test_dll_phase == 4) expected_code = 198;
2370 else expected_code = STILL_ACTIVE;
2372 if (expected_code == STILL_ACTIVE)
2374 ret = WaitForSingleObject(attached_thread[0], 100);
2375 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret);
2376 ret = WaitForSingleObject(attached_thread[1], 100);
2377 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret);
2379 else
2381 ret = WaitForSingleObject(attached_thread[0], 2000);
2382 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %#x\n", ret);
2383 ret = WaitForSingleObject(attached_thread[1], 2000);
2384 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %#x\n", ret);
2387 for (i = 0; i < attached_thread_count; i++)
2389 ret = GetExitCodeThread(attached_thread[i], &code);
2390 trace("child: GetExitCodeThread(%u) => %d,%u\n", i, ret, code);
2391 ok(ret == 1, "GetExitCodeThread returned %d, expected 1\n", ret);
2392 ok(code == expected_code, "expected thread exit code %u, got %u\n", expected_code, code);
2395 *child_failures = winetest_get_failures();
2397 trace("call ExitProcess(195)\n");
2398 ExitProcess(195);
2401 static void test_ExitProcess(void)
2403 #include "pshpack1.h"
2404 #ifdef __x86_64__
2405 static struct section_data
2407 BYTE mov_rax[2];
2408 void *target;
2409 BYTE jmp_rax[2];
2410 } section_data = { { 0x48,0xb8 }, dll_entry_point, { 0xff,0xe0 } };
2411 #else
2412 static struct section_data
2414 BYTE mov_eax;
2415 void *target;
2416 BYTE jmp_eax[2];
2417 } section_data = { 0xb8, dll_entry_point, { 0xff,0xe0 } };
2418 #endif
2419 #include "poppack.h"
2420 DWORD dummy, file_align;
2421 HANDLE file, thread, process, hmap, hmap_dup;
2422 char temp_path[MAX_PATH], dll_name[MAX_PATH], cmdline[MAX_PATH * 2];
2423 DWORD ret, target_offset, old_prot;
2424 char **argv, buf[256];
2425 PROCESS_INFORMATION pi;
2426 STARTUPINFOA si = { sizeof(si) };
2427 CONTEXT ctx;
2428 struct PROCESS_BASIC_INFORMATION_PRIVATE pbi;
2429 MEMORY_BASIC_INFORMATION mbi;
2430 DWORD_PTR affinity;
2431 void *addr;
2432 LARGE_INTEGER offset;
2433 SIZE_T size;
2434 IMAGE_NT_HEADERS nt_header;
2436 #if !defined(__i386__) && !defined(__x86_64__)
2437 skip("x86 specific ExitProcess test\n");
2438 return;
2439 #endif
2441 if (!pRtlDllShutdownInProgress)
2443 win_skip("RtlDllShutdownInProgress is not available on this platform (XP+)\n");
2444 return;
2446 if (!pNtQueryInformationProcess || !pNtSetInformationProcess)
2448 win_skip("NtQueryInformationProcess/NtSetInformationProcess are not available on this platform\n");
2449 return;
2451 if (!pNtAllocateVirtualMemory || !pNtFreeVirtualMemory)
2453 win_skip("NtAllocateVirtualMemory/NtFreeVirtualMemory are not available on this platform\n");
2454 return;
2457 /* prevent displaying of the "Unable to load this DLL" message box */
2458 SetErrorMode(SEM_FAILCRITICALERRORS);
2460 GetTempPathA(MAX_PATH, temp_path);
2461 GetTempFileNameA(temp_path, "ldr", 0, dll_name);
2463 /*trace("creating %s\n", dll_name);*/
2464 file = CreateFileA(dll_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
2465 if (file == INVALID_HANDLE_VALUE)
2467 ok(0, "could not create %s\n", dll_name);
2468 return;
2471 SetLastError(0xdeadbeef);
2472 ret = WriteFile(file, &dos_header, sizeof(dos_header), &dummy, NULL);
2473 ok(ret, "WriteFile error %d\n", GetLastError());
2475 nt_header = nt_header_template;
2476 nt_header.FileHeader.NumberOfSections = 1;
2477 nt_header.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER);
2478 nt_header.FileHeader.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL | IMAGE_FILE_RELOCS_STRIPPED;
2480 nt_header.OptionalHeader.AddressOfEntryPoint = 0x1000;
2481 nt_header.OptionalHeader.SectionAlignment = 0x1000;
2482 nt_header.OptionalHeader.FileAlignment = 0x200;
2483 nt_header.OptionalHeader.SizeOfImage = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x1000;
2484 nt_header.OptionalHeader.SizeOfHeaders = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER);
2485 SetLastError(0xdeadbeef);
2486 ret = WriteFile(file, &nt_header, sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER), &dummy, NULL);
2487 ok(ret, "WriteFile error %d\n", GetLastError());
2488 SetLastError(0xdeadbeef);
2489 ret = WriteFile(file, &nt_header.OptionalHeader, sizeof(IMAGE_OPTIONAL_HEADER), &dummy, NULL);
2490 ok(ret, "WriteFile error %d\n", GetLastError());
2492 section.SizeOfRawData = sizeof(section_data);
2493 section.PointerToRawData = nt_header.OptionalHeader.FileAlignment;
2494 section.VirtualAddress = nt_header.OptionalHeader.SectionAlignment;
2495 section.Misc.VirtualSize = sizeof(section_data);
2496 section.Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE;
2497 SetLastError(0xdeadbeef);
2498 ret = WriteFile(file, &section, sizeof(section), &dummy, NULL);
2499 ok(ret, "WriteFile error %d\n", GetLastError());
2501 file_align = nt_header.OptionalHeader.FileAlignment - nt_header.OptionalHeader.SizeOfHeaders;
2502 assert(file_align < sizeof(filler));
2503 SetLastError(0xdeadbeef);
2504 ret = WriteFile(file, filler, file_align, &dummy, NULL);
2505 ok(ret, "WriteFile error %d\n", GetLastError());
2507 target_offset = SetFilePointer(file, 0, NULL, FILE_CURRENT) + FIELD_OFFSET(struct section_data, target);
2509 /* section data */
2510 SetLastError(0xdeadbeef);
2511 ret = WriteFile(file, &section_data, sizeof(section_data), &dummy, NULL);
2512 ok(ret, "WriteFile error %d\n", GetLastError());
2514 CloseHandle(file);
2516 winetest_get_mainargs(&argv);
2518 /* phase 0 */
2519 *child_failures = -1;
2520 sprintf(cmdline, "\"%s\" loader %s %u 0", argv[0], dll_name, target_offset);
2521 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
2522 ok(ret, "CreateProcess(%s) error %d\n", cmdline, GetLastError());
2523 ret = WaitForSingleObject(pi.hProcess, 10000);
2524 ok(ret == WAIT_OBJECT_0, "child process failed to terminate\n");
2525 if (ret != WAIT_OBJECT_0) TerminateProcess(pi.hProcess, 0);
2526 GetExitCodeProcess(pi.hProcess, &ret);
2527 ok(ret == 195, "expected exit code 195, got %u\n", ret);
2528 if (*child_failures)
2530 trace("%d failures in child process\n", *child_failures);
2531 winetest_add_failures(*child_failures);
2533 CloseHandle(pi.hThread);
2534 CloseHandle(pi.hProcess);
2536 /* phase 1 */
2537 *child_failures = -1;
2538 sprintf(cmdline, "\"%s\" loader %s %u 1", argv[0], dll_name, target_offset);
2539 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
2540 ok(ret, "CreateProcess(%s) error %d\n", cmdline, GetLastError());
2541 ret = WaitForSingleObject(pi.hProcess, 10000);
2542 ok(ret == WAIT_OBJECT_0, "child process failed to terminate\n");
2543 if (ret != WAIT_OBJECT_0) TerminateProcess(pi.hProcess, 0);
2544 GetExitCodeProcess(pi.hProcess, &ret);
2545 ok(ret == 195, "expected exit code 195, got %u\n", ret);
2546 if (*child_failures)
2548 trace("%d failures in child process\n", *child_failures);
2549 winetest_add_failures(*child_failures);
2551 CloseHandle(pi.hThread);
2552 CloseHandle(pi.hProcess);
2554 /* phase 2 */
2555 *child_failures = -1;
2556 sprintf(cmdline, "\"%s\" loader %s %u 2", argv[0], dll_name, target_offset);
2557 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
2558 ok(ret, "CreateProcess(%s) error %d\n", cmdline, GetLastError());
2559 ret = WaitForSingleObject(pi.hProcess, 10000);
2560 ok(ret == WAIT_OBJECT_0, "child process failed to terminate\n");
2561 if (ret != WAIT_OBJECT_0) TerminateProcess(pi.hProcess, 0);
2562 GetExitCodeProcess(pi.hProcess, &ret);
2563 ok(ret == 197, "expected exit code 197, got %u\n", ret);
2564 if (*child_failures)
2566 trace("%d failures in child process\n", *child_failures);
2567 winetest_add_failures(*child_failures);
2569 CloseHandle(pi.hThread);
2570 CloseHandle(pi.hProcess);
2572 /* phase 3 */
2573 *child_failures = -1;
2574 sprintf(cmdline, "\"%s\" loader %s %u 3", argv[0], dll_name, target_offset);
2575 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
2576 ok(ret, "CreateProcess(%s) error %d\n", cmdline, GetLastError());
2577 ret = WaitForSingleObject(pi.hProcess, 10000);
2578 ok(ret == WAIT_OBJECT_0, "child process failed to terminate\n");
2579 if (ret != WAIT_OBJECT_0) TerminateProcess(pi.hProcess, 0);
2580 GetExitCodeProcess(pi.hProcess, &ret);
2581 ok(ret == 195, "expected exit code 195, got %u\n", ret);
2582 if (*child_failures)
2584 trace("%d failures in child process\n", *child_failures);
2585 winetest_add_failures(*child_failures);
2587 CloseHandle(pi.hThread);
2588 CloseHandle(pi.hProcess);
2590 /* phase 4 */
2591 if (pLdrLockLoaderLock && pLdrUnlockLoaderLock)
2593 *child_failures = -1;
2594 sprintf(cmdline, "\"%s\" loader %s %u 4", argv[0], dll_name, target_offset);
2595 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
2596 ok(ret, "CreateProcess(%s) error %d\n", cmdline, GetLastError());
2597 ret = WaitForSingleObject(pi.hProcess, 10000);
2598 ok(ret == WAIT_OBJECT_0, "child process failed to terminate\n");
2599 if (ret != WAIT_OBJECT_0) TerminateProcess(pi.hProcess, 0);
2600 GetExitCodeProcess(pi.hProcess, &ret);
2601 ok(ret == 198, "expected exit code 198, got %u\n", ret);
2602 if (*child_failures)
2604 trace("%d failures in child process\n", *child_failures);
2605 winetest_add_failures(*child_failures);
2607 CloseHandle(pi.hThread);
2608 CloseHandle(pi.hProcess);
2610 else
2611 win_skip("LdrLockLoaderLock/LdrUnlockLoaderLock are not available on this platform\n");
2613 /* phase 5 */
2614 if (pRtlAcquirePebLock && pRtlReleasePebLock)
2616 *child_failures = -1;
2617 sprintf(cmdline, "\"%s\" loader %s %u 5", argv[0], dll_name, target_offset);
2618 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
2619 ok(ret, "CreateProcess(%s) error %d\n", cmdline, GetLastError());
2620 ret = WaitForSingleObject(pi.hProcess, 5000);
2621 ok(ret == WAIT_TIMEOUT, "child process should fail to terminate\n");
2622 if (ret != WAIT_OBJECT_0)
2624 trace("terminating child process\n");
2625 TerminateProcess(pi.hProcess, 199);
2627 ret = WaitForSingleObject(pi.hProcess, 1000);
2628 ok(ret == WAIT_OBJECT_0, "child process failed to terminate\n");
2629 GetExitCodeProcess(pi.hProcess, &ret);
2630 ok(ret == 199, "expected exit code 199, got %u\n", ret);
2631 if (*child_failures)
2633 trace("%d failures in child process\n", *child_failures);
2634 winetest_add_failures(*child_failures);
2636 CloseHandle(pi.hThread);
2637 CloseHandle(pi.hProcess);
2639 else
2640 win_skip("RtlAcquirePebLock/RtlReleasePebLock are not available on this platform\n");
2642 /* phase 6 */
2643 *child_failures = -1;
2644 sprintf(cmdline, "\"%s\" loader %s %u 6", argv[0], dll_name, target_offset);
2645 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
2646 ok(ret, "CreateProcess(%s) error %d\n", cmdline, GetLastError());
2647 ret = WaitForSingleObject(pi.hProcess, 5000);
2648 ok(ret == WAIT_TIMEOUT || broken(ret == WAIT_OBJECT_0) /* XP */, "child process should fail to terminate\n");
2649 if (ret != WAIT_OBJECT_0)
2651 trace("terminating child process\n");
2652 TerminateProcess(pi.hProcess, 201);
2654 ret = WaitForSingleObject(pi.hProcess, 1000);
2655 ok(ret == WAIT_OBJECT_0, "child process failed to terminate\n");
2656 GetExitCodeProcess(pi.hProcess, &ret);
2657 ok(ret == 201 || broken(ret == 1) /* XP */, "expected exit code 201, got %u\n", ret);
2658 if (*child_failures)
2660 trace("%d failures in child process\n", *child_failures);
2661 winetest_add_failures(*child_failures);
2663 CloseHandle(pi.hThread);
2664 CloseHandle(pi.hProcess);
2666 /* test remote process termination */
2667 SetLastError(0xdeadbeef);
2668 ret = CreateProcessA(argv[0], NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi);
2669 ok(ret, "CreateProcess(%s) error %d\n", argv[0], GetLastError());
2671 SetLastError(0xdeadbeef);
2672 addr = VirtualAllocEx(pi.hProcess, NULL, 4096, MEM_COMMIT, PAGE_READWRITE);
2673 ok(addr != NULL, "VirtualAllocEx error %d\n", GetLastError());
2674 SetLastError(0xdeadbeef);
2675 ret = VirtualProtectEx(pi.hProcess, addr, 4096, PAGE_READONLY, &old_prot);
2676 ok(ret, "VirtualProtectEx error %d\n", GetLastError());
2677 ok(old_prot == PAGE_READWRITE, "expected PAGE_READWRITE, got %#x\n", old_prot);
2678 SetLastError(0xdeadbeef);
2679 size = VirtualQueryEx(pi.hProcess, NULL, &mbi, sizeof(mbi));
2680 ok(size == sizeof(mbi), "VirtualQueryEx error %d\n", GetLastError());
2682 SetLastError(0xdeadbeef);
2683 ret = ReadProcessMemory(pi.hProcess, addr, buf, 4, &size);
2684 ok(ret, "ReadProcessMemory error %d\n", GetLastError());
2685 ok(size == 4, "expected 4, got %lu\n", size);
2687 SetLastError(0xdeadbeef);
2688 hmap = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, NULL);
2689 ok(hmap != 0, "CreateFileMapping error %d\n", GetLastError());
2691 SetLastError(0xdeadbeef);
2692 ret = DuplicateHandle(GetCurrentProcess(), hmap, pi.hProcess, &hmap_dup,
2693 0, FALSE, DUPLICATE_SAME_ACCESS);
2694 ok(ret, "DuplicateHandle error %d\n", GetLastError());
2696 offset.u.LowPart = 0;
2697 offset.u.HighPart = 0;
2698 addr = NULL;
2699 size = 0;
2700 ret = pNtMapViewOfSection(hmap, pi.hProcess, &addr, 0, 0, &offset,
2701 &size, 1 /* ViewShare */, 0, PAGE_READONLY);
2702 ok(!ret, "NtMapViewOfSection error %#x\n", ret);
2703 ret = pNtUnmapViewOfSection(pi.hProcess, addr);
2704 ok(!ret, "NtUnmapViewOfSection error %#x\n", ret);
2706 SetLastError(0xdeadbeef);
2707 thread = CreateRemoteThread(pi.hProcess, NULL, 0, (void *)0xdeadbeef, NULL, CREATE_SUSPENDED, &ret);
2708 ok(thread != 0, "CreateRemoteThread error %d\n", GetLastError());
2709 SetLastError(0xdeadbeef);
2710 ctx.ContextFlags = CONTEXT_INTEGER;
2711 ret = GetThreadContext(thread, &ctx);
2712 ok(ret, "GetThreadContext error %d\n", GetLastError());
2713 SetLastError(0xdeadbeef);
2714 ctx.ContextFlags = CONTEXT_INTEGER;
2715 ret = SetThreadContext(thread, &ctx);
2716 ok(ret, "SetThreadContext error %d\n", GetLastError());
2717 SetLastError(0xdeadbeef);
2718 ret = SetThreadPriority(thread, 0);
2719 ok(ret, "SetThreadPriority error %d\n", GetLastError());
2721 SetLastError(0xdeadbeef);
2722 ret = TerminateThread(thread, 199);
2723 ok(ret, "TerminateThread error %d\n", GetLastError());
2724 /* Calling GetExitCodeThread() without waiting for thread termination
2725 * leads to different results due to a race condition.
2727 ret = WaitForSingleObject(thread, 1000);
2728 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed: %x\n", ret);
2729 GetExitCodeThread(thread, &ret);
2730 ok(ret == 199, "expected exit code 199, got %u\n", ret);
2732 SetLastError(0xdeadbeef);
2733 ret = TerminateProcess(pi.hProcess, 198);
2734 ok(ret, "TerminateProcess error %d\n", GetLastError());
2735 /* Checking process state without waiting for process termination
2736 * leads to different results due to a race condition.
2738 ret = WaitForSingleObject(pi.hProcess, 1000);
2739 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed: %x\n", ret);
2741 SetLastError(0xdeadbeef);
2742 process = OpenProcess(PROCESS_ALL_ACCESS_NT4, FALSE, pi.dwProcessId);
2743 ok(process != NULL, "OpenProcess error %d\n", GetLastError());
2744 CloseHandle(process);
2746 memset(&pbi, 0, sizeof(pbi));
2747 ret = pNtQueryInformationProcess(pi.hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), NULL);
2748 ok(!ret, "NtQueryInformationProcess error %#x\n", ret);
2749 ok(pbi.ExitStatus == 198, "expected 198, got %lu\n", pbi.ExitStatus);
2750 affinity = 1;
2751 ret = pNtSetInformationProcess(pi.hProcess, ProcessAffinityMask, &affinity, sizeof(affinity));
2752 ok(ret == STATUS_PROCESS_IS_TERMINATING, "expected STATUS_PROCESS_IS_TERMINATING, got %#x\n", ret);
2754 SetLastError(0xdeadbeef);
2755 ctx.ContextFlags = CONTEXT_INTEGER;
2756 ret = GetThreadContext(thread, &ctx);
2757 ok(!ret || broken(ret) /* XP 64-bit */, "GetThreadContext should fail\n");
2758 if (!ret)
2759 ok(GetLastError() == ERROR_INVALID_PARAMETER ||
2760 GetLastError() == ERROR_GEN_FAILURE /* win7 64-bit */ ||
2761 GetLastError() == ERROR_INVALID_FUNCTION /* vista 64-bit */,
2762 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2763 SetLastError(0xdeadbeef);
2764 ctx.ContextFlags = CONTEXT_INTEGER;
2765 ret = SetThreadContext(thread, &ctx);
2766 ok(!ret || broken(ret) /* XP 64-bit */, "SetThreadContext should fail\n");
2767 if (!ret)
2768 ok(GetLastError() == ERROR_ACCESS_DENIED ||
2769 GetLastError() == ERROR_GEN_FAILURE /* win7 64-bit */ ||
2770 GetLastError() == ERROR_INVALID_FUNCTION /* vista 64-bit */,
2771 "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
2772 SetLastError(0xdeadbeef);
2773 ret = SetThreadPriority(thread, 0);
2774 ok(ret, "SetThreadPriority error %d\n", GetLastError());
2775 CloseHandle(thread);
2777 SetLastError(0xdeadbeef);
2778 ctx.ContextFlags = CONTEXT_INTEGER;
2779 ret = GetThreadContext(pi.hThread, &ctx);
2780 ok(!ret || broken(ret) /* XP 64-bit */, "GetThreadContext should fail\n");
2781 if (!ret)
2782 ok(GetLastError() == ERROR_INVALID_PARAMETER ||
2783 GetLastError() == ERROR_GEN_FAILURE /* win7 64-bit */ ||
2784 GetLastError() == ERROR_INVALID_FUNCTION /* vista 64-bit */,
2785 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2786 SetLastError(0xdeadbeef);
2787 ctx.ContextFlags = CONTEXT_INTEGER;
2788 ret = SetThreadContext(pi.hThread, &ctx);
2789 ok(!ret || broken(ret) /* XP 64-bit */, "SetThreadContext should fail\n");
2790 if (!ret)
2791 ok(GetLastError() == ERROR_ACCESS_DENIED ||
2792 GetLastError() == ERROR_GEN_FAILURE /* win7 64-bit */ ||
2793 GetLastError() == ERROR_INVALID_FUNCTION /* vista 64-bit */,
2794 "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
2795 SetLastError(0xdeadbeef);
2796 ret = VirtualProtectEx(pi.hProcess, addr, 4096, PAGE_READWRITE, &old_prot);
2797 ok(!ret, "VirtualProtectEx should fail\n");
2798 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
2799 SetLastError(0xdeadbeef);
2800 size = 0;
2801 ret = ReadProcessMemory(pi.hProcess, addr, buf, 4, &size);
2802 ok(!ret, "ReadProcessMemory should fail\n");
2803 ok(GetLastError() == ERROR_PARTIAL_COPY || GetLastError() == ERROR_ACCESS_DENIED,
2804 "expected ERROR_PARTIAL_COPY, got %d\n", GetLastError());
2805 ok(!size, "expected 0, got %lu\n", size);
2806 SetLastError(0xdeadbeef);
2807 ret = VirtualFreeEx(pi.hProcess, addr, 0, MEM_RELEASE);
2808 ok(!ret, "VirtualFreeEx should fail\n");
2809 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
2810 SetLastError(0xdeadbeef);
2811 addr = VirtualAllocEx(pi.hProcess, NULL, 4096, MEM_COMMIT, PAGE_READWRITE);
2812 ok(!addr, "VirtualAllocEx should fail\n");
2813 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
2814 SetLastError(0xdeadbeef);
2815 size = VirtualQueryEx(pi.hProcess, NULL, &mbi, sizeof(mbi));
2816 ok(!size, "VirtualQueryEx should fail\n");
2817 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
2819 /* CloseHandle() call below leads to premature process termination
2820 * under some Windows versions.
2822 if (0)
2824 SetLastError(0xdeadbeef);
2825 ret = CloseHandle(hmap_dup);
2826 ok(ret, "CloseHandle should not fail\n");
2829 SetLastError(0xdeadbeef);
2830 ret = DuplicateHandle(GetCurrentProcess(), hmap, pi.hProcess, &hmap_dup,
2831 0, FALSE, DUPLICATE_SAME_ACCESS);
2832 ok(!ret, "DuplicateHandle should fail\n");
2833 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
2835 offset.u.LowPart = 0;
2836 offset.u.HighPart = 0;
2837 addr = NULL;
2838 size = 0;
2839 ret = pNtMapViewOfSection(hmap, pi.hProcess, &addr, 0, 0, &offset,
2840 &size, 1 /* ViewShare */, 0, PAGE_READONLY);
2841 ok(ret == STATUS_PROCESS_IS_TERMINATING, "expected STATUS_PROCESS_IS_TERMINATING, got %#x\n", ret);
2843 SetLastError(0xdeadbeef);
2844 thread = CreateRemoteThread(pi.hProcess, NULL, 0, (void *)0xdeadbeef, NULL, CREATE_SUSPENDED, &ret);
2845 ok(!thread, "CreateRemoteThread should fail\n");
2846 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
2848 SetLastError(0xdeadbeef);
2849 ret = DebugActiveProcess(pi.dwProcessId);
2850 ok(!ret, "DebugActiveProcess should fail\n");
2851 ok(GetLastError() == ERROR_ACCESS_DENIED /* 64-bit */ || GetLastError() == ERROR_NOT_SUPPORTED /* 32-bit */,
2852 "ERROR_ACCESS_DENIED, got %d\n", GetLastError());
2854 GetExitCodeProcess(pi.hProcess, &ret);
2855 ok(ret == 198 || broken(ret != 198) /* some 32-bit XP version in a VM returns random exit code */,
2856 "expected exit code 198, got %u\n", ret);
2857 CloseHandle(pi.hThread);
2858 CloseHandle(pi.hProcess);
2860 ret = DeleteFileA(dll_name);
2861 ok(ret, "DeleteFile error %d\n", GetLastError());
2864 static PVOID WINAPI failuredllhook(ULONG ul, DELAYLOAD_INFO* pd)
2866 ok(ul == 4, "expected 4, got %u\n", ul);
2867 ok(!!pd, "no delayload info supplied\n");
2868 if (pd)
2870 ok(pd->Size == sizeof(*pd), "got %u\n", pd->Size);
2871 ok(!!pd->DelayloadDescriptor, "no DelayloadDescriptor supplied\n");
2872 if (pd->DelayloadDescriptor)
2874 ok(pd->DelayloadDescriptor->Attributes.AllAttributes == 1,
2875 "expected 1, got %u\n", pd->DelayloadDescriptor->Attributes.AllAttributes);
2876 ok(pd->DelayloadDescriptor->DllNameRVA == 0x2000,
2877 "expected 0x2000, got %x\n", pd->DelayloadDescriptor->DllNameRVA);
2878 ok(pd->DelayloadDescriptor->ModuleHandleRVA == 0x201a,
2879 "expected 0x201a, got %x\n", pd->DelayloadDescriptor->ModuleHandleRVA);
2880 ok(pd->DelayloadDescriptor->ImportAddressTableRVA > pd->DelayloadDescriptor->ModuleHandleRVA,
2881 "expected %x > %x\n", pd->DelayloadDescriptor->ImportAddressTableRVA,
2882 pd->DelayloadDescriptor->ModuleHandleRVA);
2883 ok(pd->DelayloadDescriptor->ImportNameTableRVA > pd->DelayloadDescriptor->ImportAddressTableRVA,
2884 "expected %x > %x\n", pd->DelayloadDescriptor->ImportNameTableRVA,
2885 pd->DelayloadDescriptor->ImportAddressTableRVA);
2886 ok(pd->DelayloadDescriptor->BoundImportAddressTableRVA == 0,
2887 "expected 0, got %x\n", pd->DelayloadDescriptor->BoundImportAddressTableRVA);
2888 ok(pd->DelayloadDescriptor->UnloadInformationTableRVA == 0,
2889 "expected 0, got %x\n", pd->DelayloadDescriptor->UnloadInformationTableRVA);
2890 ok(pd->DelayloadDescriptor->TimeDateStamp == 0,
2891 "expected 0, got %x\n", pd->DelayloadDescriptor->TimeDateStamp);
2894 ok(!!pd->ThunkAddress, "no ThunkAddress supplied\n");
2895 if (pd->ThunkAddress)
2896 ok(pd->ThunkAddress->u1.Ordinal, "no ThunkAddress value supplied\n");
2898 ok(!!pd->TargetDllName, "no TargetDllName supplied\n");
2899 if (pd->TargetDllName)
2900 ok(!strcmp(pd->TargetDllName, "secur32.dll"),
2901 "expected \"secur32.dll\", got \"%s\"\n", pd->TargetDllName);
2903 ok(pd->TargetApiDescriptor.ImportDescribedByName == 0,
2904 "expected 0, got %x\n", pd->TargetApiDescriptor.ImportDescribedByName);
2905 ok(pd->TargetApiDescriptor.Description.Ordinal == 0 ||
2906 pd->TargetApiDescriptor.Description.Ordinal == 999,
2907 "expected 0, got %x\n", pd->TargetApiDescriptor.Description.Ordinal);
2909 ok(!!pd->TargetModuleBase, "no TargetModuleBase supplied\n");
2910 ok(pd->Unused == NULL, "expected NULL, got %p\n", pd->Unused);
2911 ok(pd->LastError, "no LastError supplied\n");
2913 cb_count++;
2914 return (void*)0xdeadbeef;
2917 static void test_ResolveDelayLoadedAPI(void)
2919 static const char test_dll[] = "secur32.dll";
2920 static const char test_func[] = "SealMessage";
2921 char temp_path[MAX_PATH];
2922 char dll_name[MAX_PATH];
2923 IMAGE_DELAYLOAD_DESCRIPTOR idd, *delaydir;
2924 IMAGE_THUNK_DATA itd32;
2925 HANDLE hfile;
2926 HMODULE hlib;
2927 DWORD dummy, file_size, i;
2928 WORD hint = 0;
2929 BOOL ret;
2930 IMAGE_NT_HEADERS nt_header;
2932 static const struct test_data
2934 BOOL func;
2935 UINT_PTR ordinal;
2936 BOOL succeeds;
2937 } td[] =
2940 TRUE, 0, TRUE
2943 FALSE, IMAGE_ORDINAL_FLAG | 2, TRUE
2946 FALSE, IMAGE_ORDINAL_FLAG | 5, TRUE
2949 FALSE, IMAGE_ORDINAL_FLAG | 0, FALSE
2952 FALSE, IMAGE_ORDINAL_FLAG | 999, FALSE
2956 if (!pResolveDelayLoadedAPI)
2958 win_skip("ResolveDelayLoadedAPI is not available\n");
2959 return;
2962 if (0) /* crashes on native */
2964 SetLastError(0xdeadbeef);
2965 ok(!pResolveDelayLoadedAPI(NULL, NULL, NULL, NULL, NULL, 0),
2966 "ResolveDelayLoadedAPI succeeded\n");
2967 ok(GetLastError() == 0xdeadbeef, "GetLastError changed to %x\n", GetLastError());
2969 cb_count = 0;
2970 SetLastError(0xdeadbeef);
2971 ok(!pResolveDelayLoadedAPI(NULL, NULL, failuredllhook, NULL, NULL, 0),
2972 "ResolveDelayLoadedAPI succeeded\n");
2973 ok(GetLastError() == 0xdeadbeef, "GetLastError changed to %x\n", GetLastError());
2974 ok(cb_count == 1, "Wrong callback count: %d\n", cb_count);
2977 GetTempPathA(MAX_PATH, temp_path);
2978 GetTempFileNameA(temp_path, "ldr", 0, dll_name);
2979 trace("creating %s\n", dll_name);
2980 hfile = CreateFileA(dll_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
2981 if (hfile == INVALID_HANDLE_VALUE)
2983 ok(0, "could not create %s\n", dll_name);
2984 return;
2987 SetLastError(0xdeadbeef);
2988 ret = WriteFile(hfile, &dos_header, sizeof(dos_header), &dummy, NULL);
2989 ok(ret, "WriteFile error %d\n", GetLastError());
2991 nt_header = nt_header_template;
2992 nt_header.FileHeader.NumberOfSections = 2;
2993 nt_header.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER);
2995 nt_header.OptionalHeader.SectionAlignment = 0x1000;
2996 nt_header.OptionalHeader.FileAlignment = 0x1000;
2997 nt_header.OptionalHeader.SizeOfImage = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x2200;
2998 nt_header.OptionalHeader.SizeOfHeaders = sizeof(dos_header) + sizeof(nt_header) + 2 * sizeof(IMAGE_SECTION_HEADER);
2999 nt_header.OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
3000 nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress = 0x1000;
3001 nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].Size = 0x100;
3003 SetLastError(0xdeadbeef);
3004 ret = WriteFile(hfile, &nt_header, sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER), &dummy, NULL);
3005 ok(ret, "WriteFile error %d\n", GetLastError());
3007 SetLastError(0xdeadbeef);
3008 ret = WriteFile(hfile, &nt_header.OptionalHeader, sizeof(IMAGE_OPTIONAL_HEADER), &dummy, NULL);
3009 ok(ret, "WriteFile error %d\n", GetLastError());
3011 /* sections */
3012 section.PointerToRawData = nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress;
3013 section.VirtualAddress = nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress;
3014 section.Misc.VirtualSize = 2 * sizeof(idd);
3015 section.SizeOfRawData = section.Misc.VirtualSize;
3016 section.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;
3017 SetLastError(0xdeadbeef);
3018 ret = WriteFile(hfile, &section, sizeof(section), &dummy, NULL);
3019 ok(ret, "WriteFile error %d\n", GetLastError());
3021 section.PointerToRawData = 0x2000;
3022 section.VirtualAddress = 0x2000;
3023 i = sizeof(td)/sizeof(td[0]);
3024 section.Misc.VirtualSize = sizeof(test_dll) + sizeof(hint) + sizeof(test_func) + sizeof(HMODULE) +
3025 2 * (i + 1) * sizeof(IMAGE_THUNK_DATA);
3026 ok(section.Misc.VirtualSize <= 0x1000, "Too much tests, add a new section!\n");
3027 section.SizeOfRawData = section.Misc.VirtualSize;
3028 section.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
3029 SetLastError(0xdeadbeef);
3030 ret = WriteFile(hfile, &section, sizeof(section), &dummy, NULL);
3031 ok(ret, "WriteFile error %d\n", GetLastError());
3033 /* fill up to delay data */
3034 SetFilePointer( hfile, nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress, NULL, SEEK_SET );
3036 /* delay data */
3037 idd.Attributes.AllAttributes = 1;
3038 idd.DllNameRVA = 0x2000;
3039 idd.ModuleHandleRVA = idd.DllNameRVA + sizeof(test_dll) + sizeof(hint) + sizeof(test_func);
3040 idd.ImportAddressTableRVA = idd.ModuleHandleRVA + sizeof(HMODULE);
3041 idd.ImportNameTableRVA = idd.ImportAddressTableRVA + (i + 1) * sizeof(IMAGE_THUNK_DATA);
3042 idd.BoundImportAddressTableRVA = 0;
3043 idd.UnloadInformationTableRVA = 0;
3044 idd.TimeDateStamp = 0;
3046 SetLastError(0xdeadbeef);
3047 ret = WriteFile(hfile, &idd, sizeof(idd), &dummy, NULL);
3048 ok(ret, "WriteFile error %d\n", GetLastError());
3050 SetLastError(0xdeadbeef);
3051 ret = WriteFile(hfile, filler, sizeof(idd), &dummy, NULL);
3052 ok(ret, "WriteFile error %d\n", GetLastError());
3054 /* fill up to extended delay data */
3055 SetFilePointer( hfile, idd.DllNameRVA, NULL, SEEK_SET );
3057 /* extended delay data */
3058 SetLastError(0xdeadbeef);
3059 ret = WriteFile(hfile, test_dll, sizeof(test_dll), &dummy, NULL);
3060 ok(ret, "WriteFile error %d\n", GetLastError());
3062 SetLastError(0xdeadbeef);
3063 ret = WriteFile(hfile, &hint, sizeof(hint), &dummy, NULL);
3064 ok(ret, "WriteFile error %d\n", GetLastError());
3066 SetLastError(0xdeadbeef);
3067 ret = WriteFile(hfile, test_func, sizeof(test_func), &dummy, NULL);
3068 ok(ret, "WriteFile error %d\n", GetLastError());
3070 SetFilePointer( hfile, idd.ImportAddressTableRVA, NULL, SEEK_SET );
3072 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3074 /* 0x1a00 is an empty space between delay data and extended delay data, real thunks are not necessary */
3075 itd32.u1.Function = nt_header.OptionalHeader.ImageBase + 0x1a00 + i * 0x20;
3076 SetLastError(0xdeadbeef);
3077 ret = WriteFile(hfile, &itd32, sizeof(itd32), &dummy, NULL);
3078 ok(ret, "WriteFile error %d\n", GetLastError());
3081 itd32.u1.Function = 0;
3082 SetLastError(0xdeadbeef);
3083 ret = WriteFile(hfile, &itd32, sizeof(itd32), &dummy, NULL);
3084 ok(ret, "WriteFile error %d\n", GetLastError());
3086 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3088 if (td[i].func)
3089 itd32.u1.AddressOfData = idd.DllNameRVA + sizeof(test_dll);
3090 else
3091 itd32.u1.Ordinal = td[i].ordinal;
3092 SetLastError(0xdeadbeef);
3093 ret = WriteFile(hfile, &itd32, sizeof(itd32), &dummy, NULL);
3094 ok(ret, "WriteFile error %d\n", GetLastError());
3097 itd32.u1.Ordinal = 0;
3098 SetLastError(0xdeadbeef);
3099 ret = WriteFile(hfile, &itd32, sizeof(itd32), &dummy, NULL);
3100 ok(ret, "WriteFile error %d\n", GetLastError());
3102 /* fill up to eof */
3103 SetFilePointer( hfile, section.VirtualAddress + section.Misc.VirtualSize, NULL, SEEK_SET );
3104 SetEndOfFile( hfile );
3105 CloseHandle(hfile);
3107 SetLastError(0xdeadbeef);
3108 hlib = LoadLibraryA(dll_name);
3109 ok(hlib != NULL, "LoadLibrary error %u\n", GetLastError());
3110 if (!hlib)
3112 skip("couldn't load %s.\n", dll_name);
3113 DeleteFileA(dll_name);
3114 return;
3117 delaydir = pRtlImageDirectoryEntryToData(hlib, TRUE, IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT, &file_size);
3118 if (!delaydir)
3120 skip("haven't found section for delay import directory.\n");
3121 FreeLibrary(hlib);
3122 DeleteFileA(dll_name);
3123 return;
3126 for (;;)
3128 IMAGE_THUNK_DATA *itdn, *itda;
3129 HMODULE htarget;
3131 if (!delaydir->DllNameRVA ||
3132 !delaydir->ImportAddressTableRVA ||
3133 !delaydir->ImportNameTableRVA) break;
3135 itdn = RVAToAddr(delaydir->ImportNameTableRVA, hlib);
3136 itda = RVAToAddr(delaydir->ImportAddressTableRVA, hlib);
3137 htarget = LoadLibraryA(RVAToAddr(delaydir->DllNameRVA, hlib));
3139 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3141 void *ret, *load;
3143 if (IMAGE_SNAP_BY_ORDINAL(itdn[i].u1.Ordinal))
3144 load = (void *)GetProcAddress(htarget, (LPSTR)IMAGE_ORDINAL(itdn[i].u1.Ordinal));
3145 else
3147 const IMAGE_IMPORT_BY_NAME* iibn = RVAToAddr(itdn[i].u1.AddressOfData, hlib);
3148 load = (void *)GetProcAddress(htarget, (char*)iibn->Name);
3151 cb_count = 0;
3152 ret = pResolveDelayLoadedAPI(hlib, delaydir, failuredllhook, NULL, &itda[i], 0);
3153 if (td[i].succeeds)
3155 ok(ret != NULL, "Test %u: ResolveDelayLoadedAPI failed\n", i);
3156 ok(ret == load, "Test %u: expected %p, got %p\n", i, load, ret);
3157 ok(ret == (void*)itda[i].u1.AddressOfData, "Test %u: expected %p, got %p\n",
3158 i, ret, (void*)itda[i].u1.AddressOfData);
3159 ok(!cb_count, "Test %u: Wrong callback count: %d\n", i, cb_count);
3161 else
3163 ok(ret == (void*)0xdeadbeef, "Test %u: ResolveDelayLoadedAPI succeeded with %p\n", i, ret);
3164 ok(cb_count, "Test %u: Wrong callback count: %d\n", i, cb_count);
3167 delaydir++;
3170 FreeLibrary(hlib);
3171 trace("deleting %s\n", dll_name);
3172 DeleteFileA(dll_name);
3175 static void test_InMemoryOrderModuleList(void)
3177 PEB_LDR_DATA *ldr = NtCurrentTeb()->Peb->LdrData;
3178 LIST_ENTRY *entry1, *mark1 = &ldr->InLoadOrderModuleList;
3179 LIST_ENTRY *entry2, *mark2 = &ldr->InMemoryOrderModuleList;
3180 LDR_MODULE *module1, *module2;
3182 ok(ldr->Initialized == TRUE, "expected TRUE, got %u\n", ldr->Initialized);
3184 for (entry1 = mark1->Flink, entry2 = mark2->Flink;
3185 entry1 != mark1 && entry2 != mark2;
3186 entry1 = entry1->Flink, entry2 = entry2->Flink)
3188 module1 = CONTAINING_RECORD(entry1, LDR_MODULE, InLoadOrderModuleList);
3189 module2 = CONTAINING_RECORD(entry2, LDR_MODULE, InMemoryOrderModuleList);
3190 ok(module1 == module2, "expected module1 == module2, got %p and %p\n", module1, module2);
3192 ok(entry1 == mark1, "expected entry1 == mark1, got %p and %p\n", entry1, mark1);
3193 ok(entry2 == mark2, "expected entry2 == mark2, got %p and %p\n", entry2, mark2);
3196 START_TEST(loader)
3198 int argc;
3199 char **argv;
3200 HANDLE ntdll, mapping, kernel32;
3201 SYSTEM_INFO si;
3203 ntdll = GetModuleHandleA("ntdll.dll");
3204 kernel32 = GetModuleHandleA("kernel32.dll");
3205 pNtCreateSection = (void *)GetProcAddress(ntdll, "NtCreateSection");
3206 pNtQuerySection = (void *)GetProcAddress(ntdll, "NtQuerySection");
3207 pNtMapViewOfSection = (void *)GetProcAddress(ntdll, "NtMapViewOfSection");
3208 pNtUnmapViewOfSection = (void *)GetProcAddress(ntdll, "NtUnmapViewOfSection");
3209 pNtTerminateProcess = (void *)GetProcAddress(ntdll, "NtTerminateProcess");
3210 pNtQueryInformationProcess = (void *)GetProcAddress(ntdll, "NtQueryInformationProcess");
3211 pNtSetInformationProcess = (void *)GetProcAddress(ntdll, "NtSetInformationProcess");
3212 pLdrShutdownProcess = (void *)GetProcAddress(ntdll, "LdrShutdownProcess");
3213 pRtlDllShutdownInProgress = (void *)GetProcAddress(ntdll, "RtlDllShutdownInProgress");
3214 pNtAllocateVirtualMemory = (void *)GetProcAddress(ntdll, "NtAllocateVirtualMemory");
3215 pNtFreeVirtualMemory = (void *)GetProcAddress(ntdll, "NtFreeVirtualMemory");
3216 pLdrLockLoaderLock = (void *)GetProcAddress(ntdll, "LdrLockLoaderLock");
3217 pLdrUnlockLoaderLock = (void *)GetProcAddress(ntdll, "LdrUnlockLoaderLock");
3218 pRtlAcquirePebLock = (void *)GetProcAddress(ntdll, "RtlAcquirePebLock");
3219 pRtlReleasePebLock = (void *)GetProcAddress(ntdll, "RtlReleasePebLock");
3220 pRtlImageDirectoryEntryToData = (void *)GetProcAddress(ntdll, "RtlImageDirectoryEntryToData");
3221 pFlsAlloc = (void *)GetProcAddress(kernel32, "FlsAlloc");
3222 pFlsSetValue = (void *)GetProcAddress(kernel32, "FlsSetValue");
3223 pFlsGetValue = (void *)GetProcAddress(kernel32, "FlsGetValue");
3224 pFlsFree = (void *)GetProcAddress(kernel32, "FlsFree");
3225 pIsWow64Process = (void *)GetProcAddress(kernel32, "IsWow64Process");
3226 pResolveDelayLoadedAPI = (void *)GetProcAddress(kernel32, "ResolveDelayLoadedAPI");
3228 GetSystemInfo( &si );
3229 page_size = si.dwPageSize;
3230 dos_header.e_magic = IMAGE_DOS_SIGNATURE;
3231 dos_header.e_lfanew = sizeof(dos_header);
3233 mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, "winetest_loader");
3234 ok(mapping != 0, "CreateFileMapping failed\n");
3235 child_failures = MapViewOfFile(mapping, FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, 4096);
3236 if (*child_failures == -1)
3238 *child_failures = 0;
3240 else
3241 *child_failures = -1;
3243 argc = winetest_get_mainargs(&argv);
3244 if (argc > 4)
3246 test_dll_phase = atoi(argv[4]);
3247 child_process(argv[2], atol(argv[3]));
3248 return;
3251 test_Loader();
3252 test_ResolveDelayLoadedAPI();
3253 test_ImportDescriptors();
3254 test_section_access();
3255 test_import_resolution();
3256 test_ExitProcess();
3257 test_InMemoryOrderModuleList();