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 #define NONAMELESSSTRUCT
28 #define WIN32_NO_STATUS
33 #include "wine/test.h"
34 #include "delayloadhandler.h"
36 /* PROCESS_ALL_ACCESS in Vista+ PSDKs is incompatible with older Windows versions */
37 #define PROCESS_ALL_ACCESS_NT4 (PROCESS_ALL_ACCESS & ~0xf000)
39 #define ALIGN_SIZE(size, alignment) (((size) + (alignment - 1)) & ~((alignment - 1)))
41 struct PROCESS_BASIC_INFORMATION_PRIVATE
45 DWORD_PTR AffinityMask
;
46 DWORD_PTR BasePriority
;
47 ULONG_PTR UniqueProcessId
;
48 ULONG_PTR InheritedFromUniqueProcessId
;
51 static LONG
*child_failures
;
52 static WORD cb_count
, cb_count_sys
;
53 static DWORD page_size
;
54 static BOOL is_win64
= sizeof(void *) > sizeof(int);
57 static NTSTATUS (WINAPI
*pNtCreateSection
)(HANDLE
*, ACCESS_MASK
, const OBJECT_ATTRIBUTES
*,
58 const LARGE_INTEGER
*, ULONG
, ULONG
, HANDLE
);
59 static NTSTATUS (WINAPI
*pNtQuerySection
)(HANDLE
, SECTION_INFORMATION_CLASS
, void *, SIZE_T
, SIZE_T
*);
60 static NTSTATUS (WINAPI
*pNtMapViewOfSection
)(HANDLE
, HANDLE
, PVOID
*, ULONG_PTR
, SIZE_T
, const LARGE_INTEGER
*, SIZE_T
*, ULONG
, ULONG
, ULONG
);
61 static NTSTATUS (WINAPI
*pNtUnmapViewOfSection
)(HANDLE
, PVOID
);
62 static NTSTATUS (WINAPI
*pNtQueryInformationProcess
)(HANDLE
, PROCESSINFOCLASS
, PVOID
, ULONG
, PULONG
);
63 static NTSTATUS (WINAPI
*pNtSetInformationProcess
)(HANDLE
, PROCESSINFOCLASS
, PVOID
, ULONG
);
64 static NTSTATUS (WINAPI
*pNtTerminateProcess
)(HANDLE
, DWORD
);
65 static void (WINAPI
*pLdrShutdownProcess
)(void);
66 static BOOLEAN (WINAPI
*pRtlDllShutdownInProgress
)(void);
67 static NTSTATUS (WINAPI
*pNtAllocateVirtualMemory
)(HANDLE
, PVOID
*, ULONG_PTR
, SIZE_T
*, ULONG
, ULONG
);
68 static NTSTATUS (WINAPI
*pNtFreeVirtualMemory
)(HANDLE
, PVOID
*, SIZE_T
*, ULONG
);
69 static NTSTATUS (WINAPI
*pLdrLockLoaderLock
)(ULONG
, ULONG
*, ULONG_PTR
*);
70 static NTSTATUS (WINAPI
*pLdrUnlockLoaderLock
)(ULONG
, ULONG_PTR
);
71 static NTSTATUS (WINAPI
*pLdrLoadDll
)(LPCWSTR
,DWORD
,const UNICODE_STRING
*,HMODULE
*);
72 static NTSTATUS (WINAPI
*pLdrUnloadDll
)(HMODULE
);
73 static void (WINAPI
*pRtlInitUnicodeString
)(PUNICODE_STRING
,LPCWSTR
);
74 static void (WINAPI
*pRtlAcquirePebLock
)(void);
75 static void (WINAPI
*pRtlReleasePebLock
)(void);
76 static PVOID (WINAPI
*pResolveDelayLoadedAPI
)(PVOID
, PCIMAGE_DELAYLOAD_DESCRIPTOR
,
77 PDELAYLOAD_FAILURE_DLL_CALLBACK
,
78 PDELAYLOAD_FAILURE_SYSTEM_ROUTINE
,
79 PIMAGE_THUNK_DATA ThunkAddress
,ULONG
);
80 static PVOID (WINAPI
*pRtlImageDirectoryEntryToData
)(HMODULE
,BOOL
,WORD
,ULONG
*);
81 static PIMAGE_NT_HEADERS (WINAPI
*pRtlImageNtHeader
)(HMODULE
);
82 static DWORD (WINAPI
*pFlsAlloc
)(PFLS_CALLBACK_FUNCTION
);
83 static BOOL (WINAPI
*pFlsSetValue
)(DWORD
, PVOID
);
84 static PVOID (WINAPI
*pFlsGetValue
)(DWORD
);
85 static BOOL (WINAPI
*pFlsFree
)(DWORD
);
86 static BOOL (WINAPI
*pIsWow64Process
)(HANDLE
,PBOOL
);
87 static BOOL (WINAPI
*pWow64DisableWow64FsRedirection
)(void **);
88 static BOOL (WINAPI
*pWow64RevertWow64FsRedirection
)(void *);
89 static HMODULE (WINAPI
*pLoadPackagedLibrary
)(LPCWSTR lpwLibFileName
, DWORD Reserved
);
91 static PVOID
RVAToAddr(DWORD_PTR rva
, HMODULE module
)
95 return ((char*) module
) + rva
;
98 static IMAGE_DOS_HEADER dos_header
;
100 static const IMAGE_NT_HEADERS nt_header_template
=
102 IMAGE_NT_SIGNATURE
, /* Signature */
105 IMAGE_FILE_MACHINE_I386
, /* Machine */
106 #elif defined __x86_64__
107 IMAGE_FILE_MACHINE_AMD64
, /* Machine */
108 #elif defined __arm__
109 IMAGE_FILE_MACHINE_ARMNT
, /* Machine */
110 #elif defined __aarch64__
111 IMAGE_FILE_MACHINE_ARM64
, /* Machine */
113 # error You must specify the machine type
115 1, /* NumberOfSections */
116 0, /* TimeDateStamp */
117 0, /* PointerToSymbolTable */
118 0, /* NumberOfSymbols */
119 sizeof(IMAGE_OPTIONAL_HEADER
), /* SizeOfOptionalHeader */
120 IMAGE_FILE_EXECUTABLE_IMAGE
| IMAGE_FILE_DLL
/* Characteristics */
122 { IMAGE_NT_OPTIONAL_HDR_MAGIC
, /* Magic */
123 1, /* MajorLinkerVersion */
124 0, /* MinorLinkerVersion */
126 0, /* SizeOfInitializedData */
127 0, /* SizeOfUninitializedData */
128 0, /* AddressOfEntryPoint */
129 0x10, /* BaseOfCode, also serves as e_lfanew in the truncated MZ header */
133 0x10000000, /* ImageBase */
134 0, /* SectionAlignment */
135 0, /* FileAlignment */
136 4, /* MajorOperatingSystemVersion */
137 0, /* MinorOperatingSystemVersion */
138 1, /* MajorImageVersion */
139 0, /* MinorImageVersion */
140 4, /* MajorSubsystemVersion */
141 0, /* MinorSubsystemVersion */
142 0, /* Win32VersionValue */
143 sizeof(dos_header
) + sizeof(nt_header_template
) + sizeof(IMAGE_SECTION_HEADER
) + 0x1000, /* SizeOfImage */
144 sizeof(dos_header
) + sizeof(nt_header_template
), /* SizeOfHeaders */
146 IMAGE_SUBSYSTEM_WINDOWS_CUI
, /* Subsystem */
147 0, /* DllCharacteristics */
148 0, /* SizeOfStackReserve */
149 0, /* SizeOfStackCommit */
150 0, /* SizeOfHeapReserve */
151 0, /* SizeOfHeapCommit */
153 0, /* NumberOfRvaAndSizes */
154 { { 0 } } /* DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES] */
158 static IMAGE_SECTION_HEADER section
=
160 ".rodata", /* Name */
162 0, /* VirtualAddress */
163 0, /* SizeOfRawData */
164 0, /* PointerToRawData */
165 0, /* PointerToRelocations */
166 0, /* PointerToLinenumbers */
167 0, /* NumberOfRelocations */
168 0, /* NumberOfLinenumbers */
169 IMAGE_SCN_CNT_INITIALIZED_DATA
| IMAGE_SCN_MEM_READ
, /* Characteristics */
173 static const char filler
[0x1000];
174 static const char section_data
[0x10] = "section data";
176 /* return an alternate machine of the same 32/64 bitness */
177 static WORD
get_alt_machine( WORD orig_machine
)
179 switch (orig_machine
)
181 case IMAGE_FILE_MACHINE_I386
: return IMAGE_FILE_MACHINE_ARMNT
;
182 case IMAGE_FILE_MACHINE_AMD64
: return IMAGE_FILE_MACHINE_ARM64
;
183 case IMAGE_FILE_MACHINE_ARMNT
: return IMAGE_FILE_MACHINE_I386
;
184 case IMAGE_FILE_MACHINE_ARM64
: return IMAGE_FILE_MACHINE_AMD64
;
189 /* return the machine of the alternate 32/64 bitness */
190 static WORD
get_alt_bitness_machine( WORD orig_machine
)
192 switch (orig_machine
)
194 case IMAGE_FILE_MACHINE_I386
: return IMAGE_FILE_MACHINE_AMD64
;
195 case IMAGE_FILE_MACHINE_AMD64
: return IMAGE_FILE_MACHINE_I386
;
196 case IMAGE_FILE_MACHINE_ARMNT
: return IMAGE_FILE_MACHINE_ARM64
;
197 case IMAGE_FILE_MACHINE_ARM64
: return IMAGE_FILE_MACHINE_ARMNT
;
202 static DWORD
create_test_dll( const IMAGE_DOS_HEADER
*dos_header
, UINT dos_size
,
203 const IMAGE_NT_HEADERS
*nt_header
, char dll_name
[MAX_PATH
] )
205 char temp_path
[MAX_PATH
];
206 DWORD dummy
, size
, file_align
;
210 GetTempPathA(MAX_PATH
, temp_path
);
211 GetTempFileNameA(temp_path
, "ldr", 0, dll_name
);
213 hfile
= CreateFileA(dll_name
, GENERIC_WRITE
, FILE_SHARE_READ
, NULL
, CREATE_ALWAYS
, 0, 0);
214 ok( hfile
!= INVALID_HANDLE_VALUE
, "failed to create %s err %u\n", dll_name
, GetLastError() );
215 if (hfile
== INVALID_HANDLE_VALUE
) return 0;
217 SetLastError(0xdeadbeef);
218 ret
= WriteFile(hfile
, dos_header
, dos_size
, &dummy
, NULL
);
219 ok(ret
, "WriteFile error %d\n", GetLastError());
221 SetLastError(0xdeadbeef);
222 ret
= WriteFile(hfile
, nt_header
, sizeof(DWORD
) + sizeof(IMAGE_FILE_HEADER
), &dummy
, NULL
);
223 ok(ret
, "WriteFile error %d\n", GetLastError());
225 if (nt_header
->FileHeader
.SizeOfOptionalHeader
)
227 SetLastError(0xdeadbeef);
228 ret
= WriteFile(hfile
, &nt_header
->OptionalHeader
,
229 sizeof(IMAGE_OPTIONAL_HEADER
),
231 ok(ret
, "WriteFile error %d\n", GetLastError());
232 if (nt_header
->FileHeader
.SizeOfOptionalHeader
> sizeof(IMAGE_OPTIONAL_HEADER
))
234 file_align
= nt_header
->FileHeader
.SizeOfOptionalHeader
- sizeof(IMAGE_OPTIONAL_HEADER
);
235 assert(file_align
< sizeof(filler
));
236 SetLastError(0xdeadbeef);
237 ret
= WriteFile(hfile
, filler
, file_align
, &dummy
, NULL
);
238 ok(ret
, "WriteFile error %d\n", GetLastError());
242 assert(nt_header
->FileHeader
.NumberOfSections
<= 1);
243 if (nt_header
->FileHeader
.NumberOfSections
)
245 SetFilePointer(hfile
, dos_size
+ sizeof(DWORD
) + sizeof(IMAGE_FILE_HEADER
) + nt_header
->FileHeader
.SizeOfOptionalHeader
, NULL
, FILE_BEGIN
);
247 section
.SizeOfRawData
= 10;
249 if (nt_header
->OptionalHeader
.SectionAlignment
>= page_size
)
251 section
.PointerToRawData
= dos_size
;
252 section
.VirtualAddress
= nt_header
->OptionalHeader
.SectionAlignment
;
253 section
.Misc
.VirtualSize
= section
.SizeOfRawData
* 10;
257 section
.PointerToRawData
= nt_header
->OptionalHeader
.SizeOfHeaders
;
258 section
.VirtualAddress
= nt_header
->OptionalHeader
.SizeOfHeaders
;
259 section
.Misc
.VirtualSize
= 5;
262 SetLastError(0xdeadbeef);
263 ret
= WriteFile(hfile
, §ion
, sizeof(section
), &dummy
, NULL
);
264 ok(ret
, "WriteFile error %d\n", GetLastError());
267 SetLastError(0xdeadbeef);
268 ret
= WriteFile(hfile
, section_data
, sizeof(section_data
), &dummy
, NULL
);
269 ok(ret
, "WriteFile error %d\n", GetLastError());
272 /* Minimal PE image that Windows7+ is able to load: 268 bytes */
273 size
= GetFileSize(hfile
, NULL
);
276 file_align
= 268 - size
;
277 SetLastError(0xdeadbeef);
278 ret
= WriteFile(hfile
, filler
, file_align
, &dummy
, NULL
);
279 ok(ret
, "WriteFile error %d\n", GetLastError());
282 size
= GetFileSize(hfile
, NULL
);
287 static DWORD
create_test_dll_sections( const IMAGE_DOS_HEADER
*dos_header
, const IMAGE_NT_HEADERS
*nt_header
,
288 const IMAGE_SECTION_HEADER
*sections
, const void *section_data
,
289 char dll_name
[MAX_PATH
] )
291 char temp_path
[MAX_PATH
];
292 DWORD dummy
, i
, size
;
296 GetTempPathA(MAX_PATH
, temp_path
);
297 GetTempFileNameA(temp_path
, "ldr", 0, dll_name
);
299 hfile
= CreateFileA(dll_name
, GENERIC_WRITE
, FILE_SHARE_READ
, NULL
, CREATE_ALWAYS
, 0, 0);
300 ok( hfile
!= INVALID_HANDLE_VALUE
, "failed to create %s err %u\n", dll_name
, GetLastError() );
301 if (hfile
== INVALID_HANDLE_VALUE
) return 0;
303 SetLastError(0xdeadbeef);
304 ret
= WriteFile(hfile
, dos_header
, sizeof(*dos_header
), &dummy
, NULL
);
305 ok(ret
, "WriteFile error %d\n", GetLastError());
307 SetLastError(0xdeadbeef);
308 ret
= WriteFile(hfile
, nt_header
, offsetof(IMAGE_NT_HEADERS
, OptionalHeader
) + nt_header
->FileHeader
.SizeOfOptionalHeader
, &dummy
, NULL
);
309 ok(ret
, "WriteFile error %d\n", GetLastError());
311 SetLastError(0xdeadbeef);
312 ret
= WriteFile(hfile
, sections
, sizeof(*sections
) * nt_header
->FileHeader
.NumberOfSections
,
314 ok(ret
, "WriteFile error %d\n", GetLastError());
316 for (i
= 0; i
< nt_header
->FileHeader
.NumberOfSections
; i
++)
318 SetFilePointer(hfile
, sections
[i
].PointerToRawData
, NULL
, FILE_BEGIN
);
319 SetLastError(0xdeadbeef);
320 ret
= WriteFile(hfile
, section_data
, sections
[i
].SizeOfRawData
, &dummy
, NULL
);
321 ok(ret
, "WriteFile error %d\n", GetLastError());
323 size
= GetFileSize(hfile
, NULL
);
328 static BOOL
query_image_section( int id
, const char *dll_name
, const IMAGE_NT_HEADERS
*nt_header
,
329 const void *section_data
)
331 static BOOL is_winxp
;
332 SECTION_BASIC_INFORMATION info
;
333 SECTION_IMAGE_INFORMATION image
;
334 const IMAGE_COR20_HEADER
*cor_header
= NULL
;
335 SIZE_T info_size
= (SIZE_T
)0xdeadbeef << 16;
337 HANDLE file
, mapping
;
339 LARGE_INTEGER map_size
;
340 SIZE_T max_stack
, commit_stack
;
343 /* truncated header is not handled correctly in windows <= w2k3 */
346 file
= CreateFileA( dll_name
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_DELETE
,
347 NULL
, OPEN_EXISTING
, 0, 0 );
348 ok( file
!= INVALID_HANDLE_VALUE
, "%u: CreateFile error %d\n", id
, GetLastError() );
349 file_size
= GetFileSize( file
, NULL
);
351 status
= pNtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_MAP_READ
| SECTION_QUERY
,
352 NULL
, NULL
, PAGE_READONLY
, SEC_IMAGE
, file
);
353 ok( !status
, "%u: NtCreateSection failed err %x\n", id
, status
);
359 status
= pNtQuerySection( mapping
, SectionImageInformation
, &image
, sizeof(image
), &info_size
);
360 ok( !status
, "%u: NtQuerySection failed err %x\n", id
, status
);
361 ok( info_size
== sizeof(image
), "%u: NtQuerySection wrong size %lu\n", id
, info_size
);
362 if (nt_header
->OptionalHeader
.Magic
== (is_win64
? IMAGE_NT_OPTIONAL_HDR64_MAGIC
363 : IMAGE_NT_OPTIONAL_HDR32_MAGIC
))
365 max_stack
= nt_header
->OptionalHeader
.SizeOfStackReserve
;
366 commit_stack
= nt_header
->OptionalHeader
.SizeOfStackCommit
;
367 entry_point
= (char *)nt_header
->OptionalHeader
.ImageBase
+ nt_header
->OptionalHeader
.AddressOfEntryPoint
;
368 truncated
= nt_header
->FileHeader
.SizeOfOptionalHeader
< sizeof(IMAGE_OPTIONAL_HEADER
);
370 nt_header
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
&&
371 nt_header
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].Size
)
372 cor_header
= section_data
;
374 else if (nt_header
->OptionalHeader
.Magic
== IMAGE_NT_OPTIONAL_HDR64_MAGIC
)
376 const IMAGE_NT_HEADERS64
*nt64
= (const IMAGE_NT_HEADERS64
*)nt_header
;
377 max_stack
= 0x100000;
378 commit_stack
= 0x10000;
379 entry_point
= (void *)0x81231234;
380 truncated
= nt_header
->FileHeader
.SizeOfOptionalHeader
< sizeof(IMAGE_OPTIONAL_HEADER64
);
382 nt64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
&&
383 nt64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].Size
)
384 cor_header
= section_data
;
388 const IMAGE_NT_HEADERS32
*nt32
= (const IMAGE_NT_HEADERS32
*)nt_header
;
389 max_stack
= nt32
->OptionalHeader
.SizeOfStackReserve
;
390 commit_stack
= nt32
->OptionalHeader
.SizeOfStackCommit
;
391 entry_point
= (char *)(ULONG_PTR
)nt32
->OptionalHeader
.ImageBase
+ nt32
->OptionalHeader
.AddressOfEntryPoint
;
392 truncated
= nt_header
->FileHeader
.SizeOfOptionalHeader
< sizeof(IMAGE_OPTIONAL_HEADER32
);
394 nt32
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
&&
395 nt32
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].Size
)
396 cor_header
= section_data
;
398 ok( (char *)image
.TransferAddress
== (char *)entry_point
||
399 (S(U(image
)).ImageDynamicallyRelocated
&& LOWORD(image
.TransferAddress
) == LOWORD(entry_point
)),
400 "%u: TransferAddress wrong %p / %p (%08x)\n", id
,
401 image
.TransferAddress
, entry_point
, nt_header
->OptionalHeader
.AddressOfEntryPoint
);
402 ok( image
.ZeroBits
== 0, "%u: ZeroBits wrong %08x\n", id
, image
.ZeroBits
);
403 ok( image
.MaximumStackSize
== max_stack
|| broken(truncated
),
404 "%u: MaximumStackSize wrong %lx / %lx\n", id
, image
.MaximumStackSize
, max_stack
);
405 ok( image
.CommittedStackSize
== commit_stack
|| broken(truncated
),
406 "%u: CommittedStackSize wrong %lx / %lx\n", id
, image
.CommittedStackSize
, commit_stack
);
408 ok( !image
.SubSystemType
|| broken(truncated
),
409 "%u: SubSystemType wrong %08x / 00000000\n", id
, image
.SubSystemType
);
411 ok( image
.SubSystemType
== nt_header
->OptionalHeader
.Subsystem
,
412 "%u: SubSystemType wrong %08x / %08x\n", id
,
413 image
.SubSystemType
, nt_header
->OptionalHeader
.Subsystem
);
414 ok( image
.MinorSubsystemVersion
== nt_header
->OptionalHeader
.MinorSubsystemVersion
,
415 "%u: MinorSubsystemVersion wrong %04x / %04x\n", id
,
416 image
.MinorSubsystemVersion
, nt_header
->OptionalHeader
.MinorSubsystemVersion
);
417 ok( image
.MajorSubsystemVersion
== nt_header
->OptionalHeader
.MajorSubsystemVersion
,
418 "%u: MajorSubsystemVersion wrong %04x / %04x\n", id
,
419 image
.MajorSubsystemVersion
, nt_header
->OptionalHeader
.MajorSubsystemVersion
);
420 ok( image
.MajorOperatingSystemVersion
== nt_header
->OptionalHeader
.MajorOperatingSystemVersion
||
421 broken( !image
.MajorOperatingSystemVersion
), /* before win10 */
422 "%u: MajorOperatingSystemVersion wrong %04x / %04x\n", id
,
423 image
.MajorOperatingSystemVersion
, nt_header
->OptionalHeader
.MajorOperatingSystemVersion
);
424 ok( image
.MinorOperatingSystemVersion
== nt_header
->OptionalHeader
.MinorOperatingSystemVersion
,
425 "%u: MinorOperatingSystemVersion wrong %04x / %04x\n", id
,
426 image
.MinorOperatingSystemVersion
, nt_header
->OptionalHeader
.MinorOperatingSystemVersion
);
427 ok( image
.ImageCharacteristics
== nt_header
->FileHeader
.Characteristics
,
428 "%u: ImageCharacteristics wrong %04x / %04x\n", id
,
429 image
.ImageCharacteristics
, nt_header
->FileHeader
.Characteristics
);
430 ok( image
.DllCharacteristics
== nt_header
->OptionalHeader
.DllCharacteristics
|| broken(truncated
),
431 "%u: DllCharacteristics wrong %04x / %04x\n", id
,
432 image
.DllCharacteristics
, nt_header
->OptionalHeader
.DllCharacteristics
);
433 ok( image
.Machine
== nt_header
->FileHeader
.Machine
, "%u: Machine wrong %04x / %04x\n", id
,
434 image
.Machine
, nt_header
->FileHeader
.Machine
);
435 ok( image
.LoaderFlags
== (cor_header
!= NULL
), "%u: LoaderFlags wrong %08x\n", id
, image
.LoaderFlags
);
436 ok( image
.ImageFileSize
== file_size
|| broken(!image
.ImageFileSize
), /* winxpsp1 */
437 "%u: ImageFileSize wrong %08x / %08x\n", id
, image
.ImageFileSize
, file_size
);
438 ok( image
.CheckSum
== nt_header
->OptionalHeader
.CheckSum
|| broken(truncated
),
439 "%u: CheckSum wrong %08x / %08x\n", id
,
440 image
.CheckSum
, nt_header
->OptionalHeader
.CheckSum
);
442 if (nt_header
->OptionalHeader
.SizeOfCode
|| nt_header
->OptionalHeader
.AddressOfEntryPoint
)
443 ok( image
.ImageContainsCode
== TRUE
, "%u: ImageContainsCode wrong %u\n", id
,
444 image
.ImageContainsCode
);
445 else if ((nt_header
->OptionalHeader
.SectionAlignment
% page_size
) ||
446 (nt_header
->FileHeader
.NumberOfSections
== 1 &&
447 (section
.Characteristics
& IMAGE_SCN_MEM_EXECUTE
)))
448 ok( image
.ImageContainsCode
== TRUE
|| broken(!image
.ImageContainsCode
), /* <= win8 */
449 "%u: ImageContainsCode wrong %u\n", id
, image
.ImageContainsCode
);
451 ok( !image
.ImageContainsCode
, "%u: ImageContainsCode wrong %u\n", id
, image
.ImageContainsCode
);
454 (cor_header
->Flags
& COMIMAGE_FLAGS_ILONLY
) &&
455 (cor_header
->MajorRuntimeVersion
> 2 ||
456 (cor_header
->MajorRuntimeVersion
== 2 && cor_header
->MinorRuntimeVersion
>= 5)))
458 ok( S(U(image
)).ComPlusILOnly
|| broken(is_winxp
),
459 "%u: wrong ComPlusILOnly flags %02x\n", id
, U(image
).ImageFlags
);
460 if (nt_header
->OptionalHeader
.Magic
== IMAGE_NT_OPTIONAL_HDR32_MAGIC
&&
461 !(cor_header
->Flags
& COMIMAGE_FLAGS_32BITREQUIRED
))
462 ok( S(U(image
)).ComPlusNativeReady
|| broken(is_winxp
),
463 "%u: wrong ComPlusNativeReady flags %02x\n", id
, U(image
).ImageFlags
);
465 ok( !S(U(image
)).ComPlusNativeReady
,
466 "%u: wrong ComPlusNativeReady flags %02x\n", id
, U(image
).ImageFlags
);
467 if (nt_header
->OptionalHeader
.Magic
== IMAGE_NT_OPTIONAL_HDR32_MAGIC
&&
468 (cor_header
->Flags
& COMIMAGE_FLAGS_32BITPREFERRED
))
469 ok( S(U(image
)).ComPlusPrefer32bit
||
470 broken( !image
.MajorOperatingSystemVersion
), /* before win10 */
471 "%u: wrong ComPlusPrefer32bit flags %02x\n", id
, U(image
).ImageFlags
);
473 ok( !S(U(image
)).ComPlusPrefer32bit
, "%u: wrong ComPlusPrefer32bit flags %02x\n", id
, U(image
).ImageFlags
);
477 ok( !S(U(image
)).ComPlusILOnly
, "%u: wrong ComPlusILOnly flags %02x\n", id
, U(image
).ImageFlags
);
478 ok( !S(U(image
)).ComPlusNativeReady
, "%u: wrong ComPlusNativeReady flags %02x\n", id
, U(image
).ImageFlags
);
479 ok( !S(U(image
)).ComPlusPrefer32bit
, "%u: wrong ComPlusPrefer32bit flags %02x\n", id
, U(image
).ImageFlags
);
481 if (!(nt_header
->OptionalHeader
.SectionAlignment
% page_size
))
482 ok( !S(U(image
)).ImageMappedFlat
, "%u: wrong ImageMappedFlat flags %02x\n", id
, U(image
).ImageFlags
);
485 /* winxp doesn't support any of the loader flags */
486 if (!S(U(image
)).ImageMappedFlat
) is_winxp
= TRUE
;
487 ok( S(U(image
)).ImageMappedFlat
|| broken(is_winxp
),
488 "%u: wrong ImageMappedFlat flags %02x\n", id
, U(image
).ImageFlags
);
490 if (!(nt_header
->OptionalHeader
.DllCharacteristics
& IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
))
491 ok( !S(U(image
)).ImageDynamicallyRelocated
|| broken( S(U(image
)).ComPlusILOnly
), /* <= win7 */
492 "%u: wrong ImageDynamicallyRelocated flags %02x\n", id
, U(image
).ImageFlags
);
493 else if (image
.ImageContainsCode
&& !cor_header
)
494 ok( S(U(image
)).ImageDynamicallyRelocated
|| broken(is_winxp
),
495 "%u: wrong ImageDynamicallyRelocated flags %02x\n", id
, U(image
).ImageFlags
);
497 ok( !S(U(image
)).ImageDynamicallyRelocated
|| broken(TRUE
), /* <= win8 */
498 "%u: wrong ImageDynamicallyRelocated flags %02x\n", id
, U(image
).ImageFlags
);
499 ok( !S(U(image
)).BaseBelow4gb
, "%u: wrong BaseBelow4gb flags %02x\n", id
, U(image
).ImageFlags
);
501 map_size
.QuadPart
= (nt_header
->OptionalHeader
.SizeOfImage
+ page_size
- 1) & ~(page_size
- 1);
502 status
= pNtQuerySection( mapping
, SectionBasicInformation
, &info
, sizeof(info
), NULL
);
503 ok( !status
, "NtQuerySection failed err %x\n", status
);
504 ok( info
.Size
.QuadPart
== map_size
.QuadPart
, "NtQuerySection wrong size %x%08x / %x%08x\n",
505 info
.Size
.u
.HighPart
, info
.Size
.u
.LowPart
, map_size
.u
.HighPart
, map_size
.u
.LowPart
);
506 CloseHandle( mapping
);
508 map_size
.QuadPart
= (nt_header
->OptionalHeader
.SizeOfImage
+ page_size
- 1) & ~(page_size
- 1);
509 status
= pNtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_MAP_READ
| SECTION_QUERY
,
510 NULL
, &map_size
, PAGE_READONLY
, SEC_IMAGE
, file
);
511 ok( !status
, "%u: NtCreateSection failed err %x\n", id
, status
);
512 status
= pNtQuerySection( mapping
, SectionBasicInformation
, &info
, sizeof(info
), NULL
);
513 ok( !status
, "NtQuerySection failed err %x\n", status
);
514 ok( info
.Size
.QuadPart
== map_size
.QuadPart
, "NtQuerySection wrong size %x%08x / %x%08x\n",
515 info
.Size
.u
.HighPart
, info
.Size
.u
.LowPart
, map_size
.u
.HighPart
, map_size
.u
.LowPart
);
516 CloseHandle( mapping
);
519 status
= pNtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_MAP_READ
| SECTION_QUERY
,
520 NULL
, &map_size
, PAGE_READONLY
, SEC_IMAGE
, file
);
521 ok( status
== STATUS_SECTION_TOO_BIG
, "%u: NtCreateSection failed err %x\n", id
, status
);
523 SetFilePointerEx( file
, map_size
, NULL
, FILE_BEGIN
);
524 SetEndOfFile( file
);
525 status
= pNtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_MAP_READ
| SECTION_QUERY
,
526 NULL
, &map_size
, PAGE_READONLY
, SEC_IMAGE
, file
);
527 ok( status
== STATUS_SECTION_TOO_BIG
, "%u: NtCreateSection failed err %x\n", id
, status
);
529 map_size
.QuadPart
= 1;
530 status
= pNtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_MAP_READ
| SECTION_QUERY
,
531 NULL
, &map_size
, PAGE_READONLY
, SEC_IMAGE
, file
);
532 ok( !status
, "%u: NtCreateSection failed err %x\n", id
, status
);
533 status
= pNtQuerySection( mapping
, SectionBasicInformation
, &info
, sizeof(info
), NULL
);
534 ok( !status
, "NtQuerySection failed err %x\n", status
);
535 ok( info
.Size
.QuadPart
== map_size
.QuadPart
, "NtQuerySection wrong size %x%08x / %x%08x\n",
536 info
.Size
.u
.HighPart
, info
.Size
.u
.LowPart
, map_size
.u
.HighPart
, map_size
.u
.LowPart
);
537 CloseHandle( mapping
);
540 return image
.ImageContainsCode
&& (!cor_header
|| !(cor_header
->Flags
& COMIMAGE_FLAGS_ILONLY
));
543 static const WCHAR wldr_nameW
[] = {'w','l','d','r','t','e','s','t','.','d','l','l',0};
544 static WCHAR load_test_name
[MAX_PATH
], load_fallback_name
[MAX_PATH
];
545 static WCHAR load_path
[MAX_PATH
];
547 static void init_load_path( const char *fallback_dll
)
549 static const WCHAR pathW
[] = {'P','A','T','H',0};
550 static const WCHAR ldrW
[] = {'l','d','r',0};
551 static const WCHAR sepW
[] = {';',0};
552 static const WCHAR bsW
[] = {'\\',0};
553 WCHAR path
[MAX_PATH
];
555 GetTempPathW( MAX_PATH
, path
);
556 GetTempFileNameW( path
, ldrW
, 0, load_test_name
);
557 GetTempFileNameW( path
, ldrW
, 0, load_fallback_name
);
558 DeleteFileW( load_test_name
);
559 ok( CreateDirectoryW( load_test_name
, NULL
), "failed to create dir\n" );
560 DeleteFileW( load_fallback_name
);
561 ok( CreateDirectoryW( load_fallback_name
, NULL
), "failed to create dir\n" );
562 lstrcpyW( load_path
, load_test_name
);
563 lstrcatW( load_path
, sepW
);
564 lstrcatW( load_path
, load_fallback_name
);
565 lstrcatW( load_path
, sepW
);
566 GetEnvironmentVariableW( pathW
, load_path
+ lstrlenW(load_path
),
567 ARRAY_SIZE(load_path
) - lstrlenW(load_path
) );
568 lstrcatW( load_test_name
, bsW
);
569 lstrcatW( load_test_name
, wldr_nameW
);
570 lstrcatW( load_fallback_name
, bsW
);
571 lstrcatW( load_fallback_name
, wldr_nameW
);
572 MultiByteToWideChar( CP_ACP
, 0, fallback_dll
, -1, path
, MAX_PATH
);
573 MoveFileW( path
, load_fallback_name
);
576 static void delete_load_path(void)
580 DeleteFileW( load_test_name
);
581 for (p
= load_test_name
+ lstrlenW(load_test_name
) - 1; *p
!= '\\'; p
--) ;
583 RemoveDirectoryW( load_test_name
);
584 DeleteFileW( load_fallback_name
);
585 for (p
= load_fallback_name
+ lstrlenW(load_fallback_name
) - 1; *p
!= '\\'; p
--) ;
587 RemoveDirectoryW( load_fallback_name
);
590 static UINT
get_com_dir_size( const IMAGE_NT_HEADERS
*nt
)
592 if (nt
->OptionalHeader
.Magic
== IMAGE_NT_OPTIONAL_HDR32_MAGIC
)
593 return ((const IMAGE_NT_HEADERS32
*)nt
)->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].Size
;
595 return ((const IMAGE_NT_HEADERS64
*)nt
)->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].Size
;
598 /* helper to test image section mapping */
599 static NTSTATUS
map_image_section( const IMAGE_NT_HEADERS
*nt_header
, const IMAGE_SECTION_HEADER
*sections
,
600 const void *section_data
, int line
)
602 char dll_name
[MAX_PATH
];
603 WCHAR path
[MAX_PATH
];
607 NTSTATUS status
, expect_status
, ldr_status
;
609 BOOL has_code
= FALSE
, il_only
= FALSE
, want_32bit
= FALSE
, expect_fallback
= FALSE
, wrong_machine
= FALSE
;
610 HMODULE mod
= 0, ldr_mod
;
612 file_size
= create_test_dll_sections( &dos_header
, nt_header
, sections
, section_data
, dll_name
);
614 file
= CreateFileA(dll_name
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
615 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFile error %d\n", GetLastError());
617 size
.QuadPart
= file_size
;
618 status
= pNtCreateSection(&map
, STANDARD_RIGHTS_REQUIRED
| SECTION_MAP_READ
| SECTION_QUERY
,
619 NULL
, &size
, PAGE_READONLY
, SEC_IMAGE
, file
);
620 expect_status
= status
;
622 if (get_com_dir_size( nt_header
))
624 /* invalid COR20 header seems to corrupt internal loader state on Windows */
625 if (get_com_dir_size( nt_header
) < sizeof(IMAGE_COR20_HEADER
)) goto done
;
626 if (!((const IMAGE_COR20_HEADER
*)section_data
)->Flags
) goto done
;
631 SECTION_BASIC_INFORMATION info
;
632 SIZE_T info_size
= 0xdeadbeef;
633 NTSTATUS ret
= pNtQuerySection( map
, SectionBasicInformation
, &info
, sizeof(info
), &info_size
);
634 ok( !ret
, "NtQuerySection failed err %x\n", ret
);
635 ok( info_size
== sizeof(info
), "NtQuerySection wrong size %lu\n", info_size
);
636 ok( info
.Attributes
== (SEC_IMAGE
| SEC_FILE
), "NtQuerySection wrong attr %x\n", info
.Attributes
);
637 ok( info
.BaseAddress
== NULL
, "NtQuerySection wrong base %p\n", info
.BaseAddress
);
638 ok( info
.Size
.QuadPart
== file_size
, "NtQuerySection wrong size %x%08x / %08x\n",
639 info
.Size
.u
.HighPart
, info
.Size
.u
.LowPart
, file_size
);
640 has_code
= query_image_section( line
, dll_name
, nt_header
, section_data
);
642 if (get_com_dir_size( nt_header
))
644 const IMAGE_COR20_HEADER
*cor_header
= section_data
;
645 il_only
= (cor_header
->Flags
& COMIMAGE_FLAGS_ILONLY
) != 0;
646 if (il_only
) want_32bit
= (cor_header
->Flags
& COMIMAGE_FLAGS_32BITREQUIRED
) != 0;
649 SetLastError( 0xdeadbeef );
650 mod
= LoadLibraryExA( dll_name
, 0, DONT_RESOLVE_DLL_REFERENCES
);
651 /* test loading dll of wrong 32/64 bitness */
652 if (nt_header
->OptionalHeader
.Magic
== (is_win64
? IMAGE_NT_OPTIONAL_HDR32_MAGIC
653 : IMAGE_NT_OPTIONAL_HDR64_MAGIC
))
655 if (!has_code
&& is_win64
)
657 ok_(__FILE__
,line
)( mod
!= NULL
|| want_32bit
|| broken(il_only
), /* <= win7 */
658 "loading failed err %u\n", GetLastError() );
662 ok_(__FILE__
, line
)( !mod
, "loading succeeded\n" );
663 ok_(__FILE__
, line
)( GetLastError() == ERROR_BAD_EXE_FORMAT
, "wrong error %u\n", GetLastError() );
668 wrong_machine
= (nt_header
->FileHeader
.Machine
== get_alt_machine( nt_header_template
.FileHeader
.Machine
));
670 ok( mod
!= NULL
|| broken(il_only
) || /* <= win7 */
671 broken( wrong_machine
), /* win8 */
672 "%u: loading failed err %u\n", line
, GetLastError() );
673 if (!mod
&& wrong_machine
) expect_status
= STATUS_INVALID_IMAGE_FORMAT
;
675 if (mod
) FreeLibrary( mod
);
676 expect_fallback
= !mod
;
679 /* test fallback to another dll further in the load path */
681 MultiByteToWideChar( CP_ACP
, 0, dll_name
, -1, path
, MAX_PATH
);
682 CopyFileW( path
, load_test_name
, FALSE
);
683 pRtlInitUnicodeString( &name
, wldr_nameW
);
684 ldr_status
= pLdrLoadDll( load_path
, 0, &name
, &ldr_mod
);
687 GetModuleFileNameW( ldr_mod
, path
, MAX_PATH
);
688 if (!lstrcmpiW( path
, load_test_name
))
691 ok( !expect_fallback
, "%u: got test dll but expected fallback\n", line
);
693 ok( !expect_fallback
, "%u: got test dll but expected failure %x\n", line
, expect_status
);
695 else if (!lstrcmpiW( path
, load_fallback_name
))
697 trace( "%u: loaded fallback\n", line
);
699 ok( expect_fallback
||
700 /* win10 also falls back for 32-bit dll without code, even though it could be loaded */
701 (is_win64
&& !has_code
&&
702 nt_header
->OptionalHeader
.Magic
== IMAGE_NT_OPTIONAL_HDR32_MAGIC
),
703 "%u: got fallback but expected test dll\n", line
);
705 ok( broken(expect_status
== STATUS_INVALID_IMAGE_FORMAT
), /* <= vista */
706 "%u: got fallback but expected failure %x\n", line
, expect_status
);
708 else ok( 0, "%u: got unexpected path %s instead of %s\n", line
, wine_dbgstr_w(path
), wine_dbgstr_w(load_test_name
));
709 pLdrUnloadDll( ldr_mod
);
711 else if (ldr_status
== STATUS_DLL_INIT_FAILED
||
712 ldr_status
== STATUS_ACCESS_VIOLATION
||
713 ldr_status
== STATUS_ILLEGAL_INSTRUCTION
)
715 /* some dlls with invalid entry point will crash, but this means we loaded the test dll */
716 ok( !expect_fallback
, "%u: got test dll but expected fallback\n", line
);
720 ok( ldr_status
== expect_status
||
721 broken(il_only
&& !expect_status
&& ldr_status
== STATUS_INVALID_IMAGE_FORMAT
),
722 "%u: wrong status %x/%x\n", line
, ldr_status
, expect_status
);
723 ok( !expect_fallback
|| broken(il_only
) || broken(wrong_machine
),
724 "%u: failed with %x expected fallback\n", line
, ldr_status
);
728 if (map
) CloseHandle( map
);
730 DeleteFileA( dll_name
);
735 static void test_Loader(void)
737 static const struct test_data
739 DWORD size_of_dos_header
;
740 WORD number_of_sections
, size_of_optional_header
;
741 DWORD section_alignment
, file_alignment
;
742 DWORD size_of_image
, size_of_headers
;
743 DWORD errors
[4]; /* 0 means LoadLibrary should succeed */
746 { sizeof(dos_header
),
748 { ERROR_BAD_EXE_FORMAT
}
750 { sizeof(dos_header
),
751 1, sizeof(IMAGE_OPTIONAL_HEADER
), 0x1000, 0x1000,
752 sizeof(dos_header
) + sizeof(nt_header_template
) + sizeof(IMAGE_SECTION_HEADER
) + 0xe00,
753 sizeof(dos_header
) + sizeof(nt_header_template
) + sizeof(IMAGE_SECTION_HEADER
),
754 { ERROR_BAD_EXE_FORMAT
} /* XP doesn't like too small image size */
756 { sizeof(dos_header
),
757 1, sizeof(IMAGE_OPTIONAL_HEADER
), 0x1000, 0x1000,
758 sizeof(dos_header
) + sizeof(nt_header_template
) + sizeof(IMAGE_SECTION_HEADER
) + 0x1000,
759 sizeof(dos_header
) + sizeof(nt_header_template
) + sizeof(IMAGE_SECTION_HEADER
),
762 { sizeof(dos_header
),
763 1, sizeof(IMAGE_OPTIONAL_HEADER
), 0x1000, 0x1000,
768 { sizeof(dos_header
),
769 1, sizeof(IMAGE_OPTIONAL_HEADER
), 0x200, 0x200,
770 sizeof(dos_header
) + sizeof(nt_header_template
) + sizeof(IMAGE_SECTION_HEADER
) + 0x200,
771 sizeof(dos_header
) + sizeof(nt_header_template
) + sizeof(IMAGE_SECTION_HEADER
),
772 { ERROR_SUCCESS
, ERROR_INVALID_ADDRESS
} /* vista is more strict */
774 { sizeof(dos_header
),
775 1, sizeof(IMAGE_OPTIONAL_HEADER
), 0x200, 0x1000,
776 sizeof(dos_header
) + sizeof(nt_header_template
) + sizeof(IMAGE_SECTION_HEADER
) + 0x1000,
777 sizeof(dos_header
) + sizeof(nt_header_template
) + sizeof(IMAGE_SECTION_HEADER
),
778 { ERROR_BAD_EXE_FORMAT
} /* XP doesn't like alignments */
780 { sizeof(dos_header
),
781 1, sizeof(IMAGE_OPTIONAL_HEADER
), 0x1000, 0x200,
782 sizeof(dos_header
) + sizeof(nt_header_template
) + sizeof(IMAGE_SECTION_HEADER
) + 0x1000,
783 sizeof(dos_header
) + sizeof(nt_header_template
) + sizeof(IMAGE_SECTION_HEADER
),
786 { sizeof(dos_header
),
787 1, sizeof(IMAGE_OPTIONAL_HEADER
), 0x1000, 0x200,
788 sizeof(dos_header
) + sizeof(nt_header_template
) + sizeof(IMAGE_SECTION_HEADER
) + 0x1000,
792 /* Mandatory are all fields up to SizeOfHeaders, everything else
793 * is really optional (at least that's true for XP).
795 #if 0 /* 32-bit Windows 8 crashes inside of LoadLibrary */
796 { sizeof(dos_header
),
797 1, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER
, CheckSum
), 0x200, 0x200,
798 sizeof(dos_header
) + sizeof(DWORD
) + sizeof(IMAGE_FILE_HEADER
) + FIELD_OFFSET(IMAGE_OPTIONAL_HEADER
, CheckSum
) + sizeof(IMAGE_SECTION_HEADER
) + 0x10,
799 sizeof(dos_header
) + sizeof(DWORD
) + sizeof(IMAGE_FILE_HEADER
) + FIELD_OFFSET(IMAGE_OPTIONAL_HEADER
, CheckSum
) + sizeof(IMAGE_SECTION_HEADER
),
800 { ERROR_SUCCESS
, ERROR_BAD_EXE_FORMAT
, ERROR_INVALID_ADDRESS
,
804 { sizeof(dos_header
),
805 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER
, CheckSum
), 0x200, 0x200,
806 0xd0, /* beyond of the end of file */
807 0xc0, /* beyond of the end of file */
808 { ERROR_SUCCESS
, ERROR_BAD_EXE_FORMAT
} /* vista is more strict */
810 { sizeof(dos_header
),
811 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER
, CheckSum
), 0x200, 0x200,
814 { ERROR_SUCCESS
, ERROR_BAD_EXE_FORMAT
} /* vista is more strict */
816 { sizeof(dos_header
),
817 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER
, CheckSum
), 0x200, 0x200,
820 { ERROR_SUCCESS
, ERROR_BAD_EXE_FORMAT
} /* vista is more strict */
822 #if 0 /* not power of 2 alignments need more test cases */
823 { sizeof(dos_header
),
824 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER
, CheckSum
), 0x300, 0x300,
827 { ERROR_BAD_EXE_FORMAT
} /* alignment is not power of 2 */
830 { sizeof(dos_header
),
831 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER
, CheckSum
), 4, 4,
834 { ERROR_SUCCESS
, ERROR_BAD_EXE_FORMAT
} /* vista is more strict */
836 { sizeof(dos_header
),
837 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER
, CheckSum
), 1, 1,
840 { ERROR_SUCCESS
, ERROR_BAD_EXE_FORMAT
} /* vista is more strict */
842 { sizeof(dos_header
),
843 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER
, CheckSum
), 0x200, 0x200,
846 { ERROR_BAD_EXE_FORMAT
} /* image size == 0 -> failure */
848 /* the following data mimics the PE image which upack creates */
850 1, 0x148, 0x1000, 0x200,
851 sizeof(dos_header
) + sizeof(nt_header_template
) + sizeof(IMAGE_SECTION_HEADER
) + 0x1000,
855 /* Minimal PE image that XP is able to load: 92 bytes */
857 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER
, CheckSum
),
858 0x04 /* also serves as e_lfanew in the truncated MZ header */, 0x04,
861 { ERROR_SUCCESS
, ERROR_BAD_EXE_FORMAT
} /* vista is more strict */
863 /* Minimal PE image that Windows7 is able to load: 268 bytes */
865 0, 0xf0, /* optional header size just forces 0xf0 bytes to be written,
866 0 or another number don't change the behaviour, what really
867 matters is file size regardless of values in the headers */
868 0x04 /* also serves as e_lfanew in the truncated MZ header */, 0x04,
869 0x40, /* minimal image size that Windows7 accepts */
873 /* the following data mimics the PE image which 8k demos have */
876 0x04 /* also serves as e_lfanew in the truncated MZ header */, 0x04,
885 HMODULE hlib
, hlib_as_data_file
;
886 char dll_name
[MAX_PATH
];
890 WORD orig_machine
= nt_header_template
.FileHeader
.Machine
;
891 IMAGE_NT_HEADERS nt_header
;
892 IMAGE_COR20_HEADER cor_header
;
894 /* prevent displaying of the "Unable to load this DLL" message box */
895 SetErrorMode(SEM_FAILCRITICALERRORS
);
897 for (i
= 0; i
< ARRAY_SIZE(td
); i
++)
899 nt_header
= nt_header_template
;
900 nt_header
.FileHeader
.NumberOfSections
= td
[i
].number_of_sections
;
901 nt_header
.FileHeader
.SizeOfOptionalHeader
= td
[i
].size_of_optional_header
;
903 nt_header
.OptionalHeader
.SectionAlignment
= td
[i
].section_alignment
;
904 nt_header
.OptionalHeader
.FileAlignment
= td
[i
].file_alignment
;
905 nt_header
.OptionalHeader
.SizeOfImage
= td
[i
].size_of_image
;
906 nt_header
.OptionalHeader
.SizeOfHeaders
= td
[i
].size_of_headers
;
908 section
.Characteristics
= IMAGE_SCN_CNT_INITIALIZED_DATA
| IMAGE_SCN_MEM_READ
;
909 file_size
= create_test_dll( &dos_header
, td
[i
].size_of_dos_header
, &nt_header
, dll_name
);
911 SetLastError(0xdeadbeef);
912 hlib
= LoadLibraryA(dll_name
);
915 MEMORY_BASIC_INFORMATION info
;
918 ok( td
[i
].errors
[0] == ERROR_SUCCESS
, "%d: should have failed\n", i
);
920 SetLastError(0xdeadbeef);
921 size
= VirtualQuery(hlib
, &info
, sizeof(info
));
922 ok(size
== sizeof(info
),
923 "%d: VirtualQuery error %d\n", i
, GetLastError());
924 ok(info
.BaseAddress
== hlib
, "%d: %p != %p\n", i
, info
.BaseAddress
, hlib
);
925 ok(info
.AllocationBase
== hlib
, "%d: %p != %p\n", i
, info
.AllocationBase
, hlib
);
926 ok(info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i
, info
.AllocationProtect
);
927 ok(info
.RegionSize
== ALIGN_SIZE(nt_header
.OptionalHeader
.SizeOfImage
, page_size
), "%d: got %lx != expected %x\n",
928 i
, info
.RegionSize
, ALIGN_SIZE(nt_header
.OptionalHeader
.SizeOfImage
, page_size
));
929 ok(info
.State
== MEM_COMMIT
, "%d: %x != MEM_COMMIT\n", i
, info
.State
);
930 if (nt_header
.OptionalHeader
.SectionAlignment
< page_size
)
931 ok(info
.Protect
== PAGE_EXECUTE_WRITECOPY
, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i
, info
.Protect
);
933 ok(info
.Protect
== PAGE_READONLY
, "%d: %x != PAGE_READONLY\n", i
, info
.Protect
);
934 ok(info
.Type
== SEC_IMAGE
, "%d: %x != SEC_IMAGE\n", i
, info
.Type
);
936 SetLastError(0xdeadbeef);
937 ptr
= VirtualAlloc(hlib
, page_size
, MEM_COMMIT
, info
.Protect
);
938 ok(!ptr
, "%d: VirtualAlloc should fail\n", i
);
939 ok(GetLastError() == ERROR_ACCESS_DENIED
, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i
, GetLastError());
941 SetLastError(0xdeadbeef);
942 size
= VirtualQuery((char *)hlib
+ info
.RegionSize
, &info
, sizeof(info
));
943 ok(size
== sizeof(info
),
944 "%d: VirtualQuery error %d\n", i
, GetLastError());
945 if (nt_header
.OptionalHeader
.SectionAlignment
== page_size
||
946 nt_header
.OptionalHeader
.SectionAlignment
== nt_header
.OptionalHeader
.FileAlignment
)
948 ok(info
.BaseAddress
== (char *)hlib
+ ALIGN_SIZE(nt_header
.OptionalHeader
.SizeOfImage
, page_size
), "%d: got %p != expected %p\n",
949 i
, info
.BaseAddress
, (char *)hlib
+ ALIGN_SIZE(nt_header
.OptionalHeader
.SizeOfImage
, page_size
));
950 ok(info
.AllocationBase
== 0, "%d: %p != 0\n", i
, info
.AllocationBase
);
951 ok(info
.AllocationProtect
== 0, "%d: %x != 0\n", i
, info
.AllocationProtect
);
952 /*ok(info.RegionSize == not_practical_value, "%d: %lx != not_practical_value\n", i, info.RegionSize);*/
953 ok(info
.State
== MEM_FREE
, "%d: %x != MEM_FREE\n", i
, info
.State
);
954 ok(info
.Type
== 0, "%d: %x != 0\n", i
, info
.Type
);
955 ok(info
.Protect
== PAGE_NOACCESS
, "%d: %x != PAGE_NOACCESS\n", i
, info
.Protect
);
959 ok(info
.Protect
== PAGE_EXECUTE_WRITECOPY
, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i
, info
.Protect
);
960 ok(info
.BaseAddress
== hlib
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, hlib
);
961 ok(info
.AllocationBase
== hlib
, "%d: %p != %p\n", i
, info
.AllocationBase
, hlib
);
962 ok(info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i
, info
.AllocationProtect
);
963 ok(info
.RegionSize
== ALIGN_SIZE(file_size
, page_size
), "%d: got %lx != expected %x\n",
964 i
, info
.RegionSize
, ALIGN_SIZE(file_size
, page_size
));
965 ok(info
.State
== MEM_COMMIT
, "%d: %x != MEM_COMMIT\n", i
, info
.State
);
966 ok(info
.Protect
== PAGE_READONLY
, "%d: %x != PAGE_READONLY\n", i
, info
.Protect
);
967 ok(info
.Type
== SEC_IMAGE
, "%d: %x != SEC_IMAGE\n", i
, info
.Type
);
970 /* header: check the zeroing of alignment */
971 if (nt_header
.OptionalHeader
.SectionAlignment
>= page_size
)
975 start
= (const char *)hlib
+ nt_header
.OptionalHeader
.SizeOfHeaders
;
976 size
= ALIGN_SIZE((ULONG_PTR
)start
, page_size
) - (ULONG_PTR
)start
;
977 ok(!memcmp(start
, filler
, size
), "%d: header alignment is not cleared\n", i
);
980 if (nt_header
.FileHeader
.NumberOfSections
)
982 SetLastError(0xdeadbeef);
983 size
= VirtualQuery((char *)hlib
+ section
.VirtualAddress
, &info
, sizeof(info
));
984 ok(size
== sizeof(info
),
985 "%d: VirtualQuery error %d\n", i
, GetLastError());
986 if (nt_header
.OptionalHeader
.SectionAlignment
< page_size
)
988 ok(info
.BaseAddress
== hlib
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, hlib
);
989 ok(info
.RegionSize
== ALIGN_SIZE(nt_header
.OptionalHeader
.SizeOfImage
, page_size
), "%d: got %lx != expected %x\n",
990 i
, info
.RegionSize
, ALIGN_SIZE(nt_header
.OptionalHeader
.SizeOfImage
, page_size
));
991 ok(info
.Protect
== PAGE_EXECUTE_WRITECOPY
, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i
, info
.Protect
);
995 ok(info
.BaseAddress
== (char *)hlib
+ section
.VirtualAddress
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, (char *)hlib
+ section
.VirtualAddress
);
996 ok(info
.RegionSize
== ALIGN_SIZE(section
.Misc
.VirtualSize
, page_size
), "%d: got %lx != expected %x\n",
997 i
, info
.RegionSize
, ALIGN_SIZE(section
.Misc
.VirtualSize
, page_size
));
998 ok(info
.Protect
== PAGE_READONLY
, "%d: %x != PAGE_READONLY\n", i
, info
.Protect
);
1000 ok(info
.AllocationBase
== hlib
, "%d: %p != %p\n", i
, info
.AllocationBase
, hlib
);
1001 ok(info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i
, info
.AllocationProtect
);
1002 ok(info
.State
== MEM_COMMIT
, "%d: %x != MEM_COMMIT\n", i
, info
.State
);
1003 ok(info
.Type
== SEC_IMAGE
, "%d: %x != SEC_IMAGE\n", i
, info
.Type
);
1005 if (nt_header
.OptionalHeader
.SectionAlignment
>= page_size
)
1006 ok(!memcmp((const char *)hlib
+ section
.VirtualAddress
+ section
.PointerToRawData
, &nt_header
, section
.SizeOfRawData
), "wrong section data\n");
1008 ok(!memcmp((const char *)hlib
+ section
.PointerToRawData
, section_data
, section
.SizeOfRawData
), "wrong section data\n");
1010 /* check the zeroing of alignment */
1011 if (nt_header
.OptionalHeader
.SectionAlignment
>= page_size
)
1015 start
= (const char *)hlib
+ section
.VirtualAddress
+ section
.PointerToRawData
+ section
.SizeOfRawData
;
1016 size
= ALIGN_SIZE((ULONG_PTR
)start
, page_size
) - (ULONG_PTR
)start
;
1017 ok(memcmp(start
, filler
, size
), "%d: alignment should not be cleared\n", i
);
1020 SetLastError(0xdeadbeef);
1021 ptr
= VirtualAlloc((char *)hlib
+ section
.VirtualAddress
, page_size
, MEM_COMMIT
, info
.Protect
);
1022 ok(!ptr
, "%d: VirtualAlloc should fail\n", i
);
1023 ok(GetLastError() == ERROR_ACCESS_DENIED
|| GetLastError() == ERROR_INVALID_ADDRESS
,
1024 "%d: expected ERROR_ACCESS_DENIED, got %d\n", i
, GetLastError());
1027 SetLastError(0xdeadbeef);
1028 hlib_as_data_file
= LoadLibraryExA(dll_name
, 0, LOAD_LIBRARY_AS_DATAFILE
);
1029 ok(hlib_as_data_file
!= 0, "LoadLibraryEx error %u\n", GetLastError());
1030 ok(hlib_as_data_file
== hlib
, "hlib_as_file and hlib are different\n");
1032 SetLastError(0xdeadbeef);
1033 ret
= FreeLibrary(hlib
);
1034 ok(ret
, "FreeLibrary error %d\n", GetLastError());
1036 SetLastError(0xdeadbeef);
1037 hlib
= GetModuleHandleA(dll_name
);
1038 ok(hlib
!= 0, "GetModuleHandle error %u\n", GetLastError());
1040 SetLastError(0xdeadbeef);
1041 ret
= FreeLibrary(hlib_as_data_file
);
1042 ok(ret
, "FreeLibrary error %d\n", GetLastError());
1044 hlib
= GetModuleHandleA(dll_name
);
1045 ok(!hlib
, "GetModuleHandle should fail\n");
1047 SetLastError(0xdeadbeef);
1048 hlib_as_data_file
= LoadLibraryExA(dll_name
, 0, LOAD_LIBRARY_AS_DATAFILE
);
1049 ok(hlib_as_data_file
!= 0, "LoadLibraryEx error %u\n", GetLastError());
1050 ok(((ULONG_PTR
)hlib_as_data_file
& 3) == 1, "hlib_as_data_file got %p\n", hlib_as_data_file
);
1052 hlib
= GetModuleHandleA(dll_name
);
1053 ok(!hlib
, "GetModuleHandle should fail\n");
1055 SetLastError(0xdeadbeef);
1056 h
= CreateFileA( dll_name
, GENERIC_WRITE
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0 );
1057 ok( h
!= INVALID_HANDLE_VALUE
, "open failed err %u\n", GetLastError() );
1060 SetLastError(0xdeadbeef);
1061 ret
= FreeLibrary(hlib_as_data_file
);
1062 ok(ret
, "FreeLibrary error %d\n", GetLastError());
1064 SetLastError(0xdeadbeef);
1065 hlib_as_data_file
= LoadLibraryExA(dll_name
, 0, LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE
);
1066 if (!((ULONG_PTR
)hlib_as_data_file
& 3) || /* winxp */
1067 (!hlib_as_data_file
&& GetLastError() == ERROR_INVALID_PARAMETER
)) /* w2k3 */
1069 win_skip( "LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE not supported\n" );
1070 FreeLibrary(hlib_as_data_file
);
1074 ok(hlib_as_data_file
!= 0, "LoadLibraryEx error %u\n", GetLastError());
1076 SetLastError(0xdeadbeef);
1077 h
= CreateFileA( dll_name
, GENERIC_WRITE
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0 );
1078 ok( h
== INVALID_HANDLE_VALUE
, "open succeeded\n" );
1079 ok( GetLastError() == ERROR_SHARING_VIOLATION
, "wrong error %u\n", GetLastError() );
1082 SetLastError(0xdeadbeef);
1083 h
= CreateFileA( dll_name
, GENERIC_READ
| DELETE
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0 );
1084 ok( h
!= INVALID_HANDLE_VALUE
, "open failed err %u\n", GetLastError() );
1087 SetLastError(0xdeadbeef);
1088 ret
= FreeLibrary(hlib_as_data_file
);
1089 ok(ret
, "FreeLibrary error %d\n", GetLastError());
1092 SetLastError(0xdeadbeef);
1093 hlib_as_data_file
= LoadLibraryExA(dll_name
, 0, LOAD_LIBRARY_AS_IMAGE_RESOURCE
);
1094 if (!((ULONG_PTR
)hlib_as_data_file
& 3) || /* winxp */
1095 (!hlib_as_data_file
&& GetLastError() == ERROR_INVALID_PARAMETER
)) /* w2k3 */
1097 win_skip( "LOAD_LIBRARY_AS_IMAGE_RESOURCE not supported\n" );
1098 FreeLibrary(hlib_as_data_file
);
1102 ok(hlib_as_data_file
!= 0, "LoadLibraryEx error %u\n", GetLastError());
1103 ok(((ULONG_PTR
)hlib_as_data_file
& 3) == 2, "hlib_as_data_file got %p\n",
1106 hlib
= GetModuleHandleA(dll_name
);
1107 ok(!hlib
, "GetModuleHandle should fail\n");
1109 SetLastError(0xdeadbeef);
1110 ret
= FreeLibrary(hlib_as_data_file
);
1111 ok(ret
, "FreeLibrary error %d\n", GetLastError());
1114 SetLastError(0xdeadbeef);
1115 ret
= DeleteFileA(dll_name
);
1116 ok(ret
, "DeleteFile error %d\n", GetLastError());
1118 nt_header
.OptionalHeader
.AddressOfEntryPoint
= 0x12345678;
1119 file_size
= create_test_dll( &dos_header
, td
[i
].size_of_dos_header
, &nt_header
, dll_name
);
1122 ok(0, "could not create %s\n", dll_name
);
1126 query_image_section( i
, dll_name
, &nt_header
, NULL
);
1133 error_match
= FALSE
;
1134 for (error_index
= 0;
1135 ! error_match
&& error_index
< ARRAY_SIZE(td
[i
].errors
);
1138 error_match
= td
[i
].errors
[error_index
] == GetLastError();
1140 ok(error_match
, "%d: unexpected error %d\n", i
, GetLastError());
1143 SetLastError(0xdeadbeef);
1144 ret
= DeleteFileA(dll_name
);
1145 ok(ret
, "DeleteFile error %d\n", GetLastError());
1148 nt_header
= nt_header_template
;
1149 nt_header
.FileHeader
.NumberOfSections
= 1;
1150 nt_header
.FileHeader
.SizeOfOptionalHeader
= sizeof(IMAGE_OPTIONAL_HEADER
);
1152 nt_header
.OptionalHeader
.SectionAlignment
= page_size
;
1153 nt_header
.OptionalHeader
.DllCharacteristics
= IMAGE_DLLCHARACTERISTICS_NX_COMPAT
;
1154 nt_header
.OptionalHeader
.FileAlignment
= page_size
;
1155 nt_header
.OptionalHeader
.SizeOfHeaders
= sizeof(dos_header
) + sizeof(nt_header
) + sizeof(IMAGE_SECTION_HEADER
);
1156 nt_header
.OptionalHeader
.SizeOfImage
= sizeof(dos_header
) + sizeof(nt_header
) + sizeof(IMAGE_SECTION_HEADER
) + page_size
;
1158 section
.SizeOfRawData
= sizeof(section_data
);
1159 section
.PointerToRawData
= page_size
;
1160 section
.VirtualAddress
= page_size
;
1161 section
.Misc
.VirtualSize
= page_size
;
1163 create_test_dll_sections( &dos_header
, &nt_header
, §ion
, section_data
, dll_name
);
1164 init_load_path( dll_name
);
1166 nt_header
.OptionalHeader
.AddressOfEntryPoint
= 0x1234;
1167 status
= map_image_section( &nt_header
, §ion
, section_data
, __LINE__
);
1168 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1170 nt_header
.OptionalHeader
.DllCharacteristics
= IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
;
1171 status
= map_image_section( &nt_header
, §ion
, section_data
, __LINE__
);
1172 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1174 nt_header
.OptionalHeader
.SizeOfCode
= 0x1000;
1175 status
= map_image_section( &nt_header
, §ion
, section_data
, __LINE__
);
1176 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1177 nt_header
.OptionalHeader
.SizeOfCode
= 0;
1178 nt_header
.OptionalHeader
.DllCharacteristics
= IMAGE_DLLCHARACTERISTICS_NX_COMPAT
;
1180 dos_header
.e_magic
= 0;
1181 status
= map_image_section( &nt_header
, §ion
, section_data
, __LINE__
);
1182 ok( status
== STATUS_INVALID_IMAGE_NOT_MZ
, "NtCreateSection error %08x\n", status
);
1184 dos_header
.e_magic
= IMAGE_DOS_SIGNATURE
;
1185 nt_header
.Signature
= IMAGE_OS2_SIGNATURE
;
1186 status
= map_image_section( &nt_header
, §ion
, section_data
, __LINE__
);
1187 ok( status
== STATUS_INVALID_IMAGE_NE_FORMAT
, "NtCreateSection error %08x\n", status
);
1188 for (i
= 0; i
< 16; i
++)
1190 ((IMAGE_OS2_HEADER
*)&nt_header
)->ne_exetyp
= i
;
1191 status
= map_image_section( &nt_header
, §ion
, section_data
, __LINE__
);
1195 ok( status
== STATUS_INVALID_IMAGE_WIN_16
, "NtCreateSection %u error %08x\n", i
, status
);
1198 ok( status
== STATUS_INVALID_IMAGE_PROTECT
, "NtCreateSection %u error %08x\n", i
, status
);
1201 ok( status
== STATUS_INVALID_IMAGE_NE_FORMAT
, "NtCreateSection %u error %08x\n", i
, status
);
1205 ((IMAGE_OS2_HEADER
*)&nt_header
)->ne_exetyp
= ((IMAGE_OS2_HEADER
*)&nt_header_template
)->ne_exetyp
;
1207 dos_header
.e_lfanew
= 0x98760000;
1208 status
= map_image_section( &nt_header
, §ion
, section_data
, __LINE__
);
1209 ok( status
== STATUS_INVALID_IMAGE_PROTECT
, "NtCreateSection error %08x\n", status
);
1211 dos_header
.e_lfanew
= sizeof(dos_header
);
1212 nt_header
.Signature
= 0xdeadbeef;
1213 status
= map_image_section( &nt_header
, §ion
, section_data
, __LINE__
);
1214 ok( status
== STATUS_INVALID_IMAGE_PROTECT
, "NtCreateSection error %08x\n", status
);
1216 nt_header
.Signature
= IMAGE_NT_SIGNATURE
;
1217 nt_header
.OptionalHeader
.Magic
= 0xdead;
1218 status
= map_image_section( &nt_header
, §ion
, section_data
, __LINE__
);
1219 ok( status
== STATUS_INVALID_IMAGE_FORMAT
, "NtCreateSection error %08x\n", status
);
1221 nt_header
.OptionalHeader
.Magic
= IMAGE_NT_OPTIONAL_HDR_MAGIC
;
1222 nt_header
.FileHeader
.Machine
= 0xdead;
1223 status
= map_image_section( &nt_header
, §ion
, section_data
, __LINE__
);
1224 ok( status
== STATUS_INVALID_IMAGE_FORMAT
|| broken(status
== STATUS_SUCCESS
), /* win2k */
1225 "NtCreateSection error %08x\n", status
);
1227 nt_header
.FileHeader
.Machine
= IMAGE_FILE_MACHINE_UNKNOWN
;
1228 status
= map_image_section( &nt_header
, §ion
, section_data
, __LINE__
);
1229 ok( status
== STATUS_INVALID_IMAGE_FORMAT
|| broken(status
== STATUS_SUCCESS
), /* win2k */
1230 "NtCreateSection error %08x\n", status
);
1232 nt_header
.FileHeader
.Machine
= get_alt_machine( orig_machine
);
1233 status
= map_image_section( &nt_header
, §ion
, section_data
, __LINE__
);
1234 ok( status
== STATUS_INVALID_IMAGE_FORMAT
|| broken(status
== STATUS_SUCCESS
), /* win2k */
1235 "NtCreateSection error %08x\n", status
);
1237 nt_header
.FileHeader
.Machine
= get_alt_bitness_machine( orig_machine
);
1238 status
= map_image_section( &nt_header
, §ion
, section_data
, __LINE__
);
1239 ok( status
== STATUS_INVALID_IMAGE_FORMAT
|| broken(status
== STATUS_SUCCESS
), /* win2k */
1240 "NtCreateSection error %08x\n", status
);
1242 nt_header
.FileHeader
.Machine
= orig_machine
;
1243 nt_header
.OptionalHeader
.NumberOfRvaAndSizes
= IMAGE_NUMBEROF_DIRECTORY_ENTRIES
;
1244 nt_header
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
= page_size
;
1245 nt_header
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].Size
= sizeof(cor_header
);
1246 section
.SizeOfRawData
= sizeof(cor_header
);
1248 memset( &cor_header
, 0, sizeof(cor_header
) );
1249 cor_header
.cb
= sizeof(cor_header
);
1250 cor_header
.MajorRuntimeVersion
= 2;
1251 cor_header
.MinorRuntimeVersion
= 4;
1252 cor_header
.Flags
= COMIMAGE_FLAGS_ILONLY
;
1253 U(cor_header
).EntryPointToken
= 0xbeef;
1254 status
= map_image_section( &nt_header
, §ion
, &cor_header
, __LINE__
);
1255 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1257 cor_header
.MinorRuntimeVersion
= 5;
1258 status
= map_image_section( &nt_header
, §ion
, &cor_header
, __LINE__
);
1259 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1261 cor_header
.MajorRuntimeVersion
= 3;
1262 cor_header
.MinorRuntimeVersion
= 0;
1263 status
= map_image_section( &nt_header
, §ion
, &cor_header
, __LINE__
);
1264 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1266 cor_header
.Flags
= COMIMAGE_FLAGS_ILONLY
| COMIMAGE_FLAGS_32BITREQUIRED
;
1267 status
= map_image_section( &nt_header
, §ion
, &cor_header
, __LINE__
);
1268 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1270 cor_header
.Flags
= COMIMAGE_FLAGS_ILONLY
| COMIMAGE_FLAGS_32BITPREFERRED
;
1271 status
= map_image_section( &nt_header
, §ion
, &cor_header
, __LINE__
);
1272 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1274 cor_header
.Flags
= 0;
1275 status
= map_image_section( &nt_header
, §ion
, &cor_header
, __LINE__
);
1276 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1278 nt_header
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
= 1;
1279 nt_header
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].Size
= 1;
1280 status
= map_image_section( &nt_header
, §ion
, &cor_header
, __LINE__
);
1281 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1283 if (nt_header
.OptionalHeader
.Magic
== IMAGE_NT_OPTIONAL_HDR32_MAGIC
)
1285 IMAGE_NT_HEADERS64 nt64
;
1287 memset( &nt64
, 0, sizeof(nt64
) );
1288 nt64
.Signature
= IMAGE_NT_SIGNATURE
;
1289 nt64
.FileHeader
.Machine
= orig_machine
;
1290 nt64
.FileHeader
.NumberOfSections
= 1;
1291 nt64
.FileHeader
.SizeOfOptionalHeader
= sizeof(IMAGE_OPTIONAL_HEADER64
);
1292 nt64
.FileHeader
.Characteristics
= IMAGE_FILE_EXECUTABLE_IMAGE
| IMAGE_FILE_DLL
;
1293 nt64
.OptionalHeader
.Magic
= IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
1294 nt64
.OptionalHeader
.MajorLinkerVersion
= 1;
1295 nt64
.OptionalHeader
.SizeOfCode
= 0x1000;
1296 nt64
.OptionalHeader
.AddressOfEntryPoint
= 0x1000;
1297 nt64
.OptionalHeader
.ImageBase
= 0x10000000;
1298 nt64
.OptionalHeader
.SectionAlignment
= 0x1000;
1299 nt64
.OptionalHeader
.FileAlignment
= 0x1000;
1300 nt64
.OptionalHeader
.MajorOperatingSystemVersion
= 4;
1301 nt64
.OptionalHeader
.MajorImageVersion
= 1;
1302 nt64
.OptionalHeader
.MajorSubsystemVersion
= 4;
1303 nt64
.OptionalHeader
.SizeOfHeaders
= sizeof(dos_header
) + sizeof(nt64
) + sizeof(IMAGE_SECTION_HEADER
);
1304 nt64
.OptionalHeader
.SizeOfImage
= nt64
.OptionalHeader
.SizeOfHeaders
+ 0x1000;
1305 nt64
.OptionalHeader
.Subsystem
= IMAGE_SUBSYSTEM_WINDOWS_CUI
;
1306 nt64
.OptionalHeader
.SizeOfStackReserve
= 0x321000;
1307 nt64
.OptionalHeader
.SizeOfStackCommit
= 0x123000;
1308 section
.Characteristics
= IMAGE_SCN_CNT_CODE
| IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_EXECUTE
;
1310 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt64
, §ion
, section_data
, __LINE__
);
1311 ok( status
== (is_wow64
? STATUS_INVALID_IMAGE_FORMAT
: STATUS_INVALID_IMAGE_WIN_64
),
1312 "NtCreateSection error %08x\n", status
);
1314 switch (orig_machine
)
1316 case IMAGE_FILE_MACHINE_I386
: nt64
.FileHeader
.Machine
= IMAGE_FILE_MACHINE_ARM64
; break;
1317 case IMAGE_FILE_MACHINE_ARMNT
: nt64
.FileHeader
.Machine
= IMAGE_FILE_MACHINE_AMD64
; break;
1319 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt64
, §ion
, section_data
, __LINE__
);
1320 ok( status
== (is_wow64
? STATUS_INVALID_IMAGE_FORMAT
: STATUS_INVALID_IMAGE_WIN_64
),
1321 "NtCreateSection error %08x\n", status
);
1323 nt64
.FileHeader
.Machine
= get_alt_bitness_machine( orig_machine
);
1324 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt64
, §ion
, section_data
, __LINE__
);
1325 ok( status
== (is_wow64
? STATUS_SUCCESS
: STATUS_INVALID_IMAGE_WIN_64
),
1326 "NtCreateSection error %08x\n", status
);
1328 nt64
.OptionalHeader
.SizeOfCode
= 0;
1329 nt64
.OptionalHeader
.AddressOfEntryPoint
= 0x1000;
1330 section
.Characteristics
= IMAGE_SCN_MEM_READ
| IMAGE_SCN_CNT_CODE
;
1331 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt64
, §ion
, section_data
, __LINE__
);
1332 ok( status
== (is_wow64
? STATUS_SUCCESS
: STATUS_INVALID_IMAGE_WIN_64
),
1333 "NtCreateSection error %08x\n", status
);
1335 nt64
.OptionalHeader
.SizeOfCode
= 0;
1336 nt64
.OptionalHeader
.AddressOfEntryPoint
= 0;
1337 section
.Characteristics
= IMAGE_SCN_MEM_READ
| IMAGE_SCN_CNT_CODE
| IMAGE_SCN_MEM_EXECUTE
;
1338 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt64
, §ion
, section_data
, __LINE__
);
1339 ok( status
== (is_wow64
? STATUS_SUCCESS
: STATUS_INVALID_IMAGE_WIN_64
),
1340 "NtCreateSection error %08x\n", status
);
1342 nt64
.OptionalHeader
.SizeOfCode
= 0x1000;
1343 nt64
.OptionalHeader
.AddressOfEntryPoint
= 0;
1344 nt64
.OptionalHeader
.DllCharacteristics
= IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
;
1345 section
.Characteristics
= IMAGE_SCN_MEM_READ
| IMAGE_SCN_CNT_CODE
;
1346 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt64
, §ion
, section_data
, __LINE__
);
1347 ok( status
== (is_wow64
? STATUS_SUCCESS
: STATUS_INVALID_IMAGE_WIN_64
),
1348 "NtCreateSection error %08x\n", status
);
1350 nt64
.OptionalHeader
.SizeOfCode
= 0;
1351 nt64
.OptionalHeader
.AddressOfEntryPoint
= 0;
1352 section
.Characteristics
= IMAGE_SCN_MEM_READ
| IMAGE_SCN_CNT_CODE
;
1353 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt64
, §ion
, section_data
, __LINE__
);
1354 ok( status
== (is_wow64
? STATUS_SUCCESS
: STATUS_INVALID_IMAGE_WIN_64
),
1355 "NtCreateSection error %08x\n", status
);
1357 nt64
.OptionalHeader
.NumberOfRvaAndSizes
= IMAGE_NUMBEROF_DIRECTORY_ENTRIES
;
1358 nt64
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
= page_size
;
1359 nt64
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].Size
= sizeof(cor_header
);
1360 cor_header
.MajorRuntimeVersion
= 2;
1361 cor_header
.MinorRuntimeVersion
= 4;
1362 cor_header
.Flags
= COMIMAGE_FLAGS_ILONLY
;
1363 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt64
, §ion
, &cor_header
, __LINE__
);
1364 ok( status
== (is_wow64
? STATUS_SUCCESS
: STATUS_INVALID_IMAGE_WIN_64
),
1365 "NtCreateSection error %08x\n", status
);
1367 nt64
.OptionalHeader
.SizeOfCode
= 0x1000;
1368 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt64
, §ion
, &cor_header
, __LINE__
);
1369 ok( status
== (is_wow64
? STATUS_SUCCESS
: STATUS_INVALID_IMAGE_WIN_64
),
1370 "NtCreateSection error %08x\n", status
);
1372 cor_header
.MinorRuntimeVersion
= 5;
1373 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt64
, §ion
, &cor_header
, __LINE__
);
1374 ok( status
== (is_wow64
? STATUS_SUCCESS
: STATUS_INVALID_IMAGE_WIN_64
),
1375 "NtCreateSection error %08x\n", status
);
1377 cor_header
.Flags
= COMIMAGE_FLAGS_ILONLY
| COMIMAGE_FLAGS_32BITREQUIRED
;
1378 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt64
, §ion
, &cor_header
, __LINE__
);
1379 ok( status
== (is_wow64
? STATUS_SUCCESS
: STATUS_INVALID_IMAGE_WIN_64
),
1380 "NtCreateSection error %08x\n", status
);
1382 cor_header
.Flags
= COMIMAGE_FLAGS_ILONLY
| COMIMAGE_FLAGS_32BITPREFERRED
;
1383 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt64
, §ion
, &cor_header
, __LINE__
);
1384 ok( status
== (is_wow64
? STATUS_SUCCESS
: STATUS_INVALID_IMAGE_WIN_64
),
1385 "NtCreateSection error %08x\n", status
);
1387 cor_header
.Flags
= 0;
1388 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt64
, §ion
, &cor_header
, __LINE__
);
1389 ok( status
== (is_wow64
? STATUS_SUCCESS
: STATUS_INVALID_IMAGE_WIN_64
),
1390 "NtCreateSection error %08x\n", status
);
1392 nt_header
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
= 1;
1393 nt_header
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].Size
= 1;
1394 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt64
, §ion
, &cor_header
, __LINE__
);
1395 ok( status
== (is_wow64
? STATUS_SUCCESS
: STATUS_INVALID_IMAGE_WIN_64
),
1396 "NtCreateSection error %08x\n", status
);
1400 IMAGE_NT_HEADERS32 nt32
;
1402 memset( &nt32
, 0, sizeof(nt32
) );
1403 nt32
.Signature
= IMAGE_NT_SIGNATURE
;
1404 nt32
.FileHeader
.Machine
= orig_machine
;
1405 nt32
.FileHeader
.NumberOfSections
= 1;
1406 nt32
.FileHeader
.SizeOfOptionalHeader
= sizeof(IMAGE_OPTIONAL_HEADER32
);
1407 nt32
.FileHeader
.Characteristics
= IMAGE_FILE_EXECUTABLE_IMAGE
| IMAGE_FILE_DLL
;
1408 nt32
.OptionalHeader
.Magic
= IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
1409 nt32
.OptionalHeader
.MajorLinkerVersion
= 1;
1410 nt32
.OptionalHeader
.SizeOfCode
= 0x1000;
1411 nt32
.OptionalHeader
.AddressOfEntryPoint
= 0x1000;
1412 nt32
.OptionalHeader
.ImageBase
= 0x10000000;
1413 nt32
.OptionalHeader
.SectionAlignment
= 0x1000;
1414 nt32
.OptionalHeader
.FileAlignment
= 0x1000;
1415 nt32
.OptionalHeader
.MajorOperatingSystemVersion
= 4;
1416 nt32
.OptionalHeader
.MajorImageVersion
= 1;
1417 nt32
.OptionalHeader
.MajorSubsystemVersion
= 4;
1418 nt32
.OptionalHeader
.SizeOfHeaders
= sizeof(dos_header
) + sizeof(nt32
) + sizeof(IMAGE_SECTION_HEADER
);
1419 nt32
.OptionalHeader
.SizeOfImage
= nt32
.OptionalHeader
.SizeOfHeaders
+ 0x1000;
1420 nt32
.OptionalHeader
.Subsystem
= IMAGE_SUBSYSTEM_WINDOWS_CUI
;
1421 nt32
.OptionalHeader
.SizeOfStackReserve
= 0x321000;
1422 nt32
.OptionalHeader
.SizeOfStackCommit
= 0x123000;
1423 section
.Characteristics
= IMAGE_SCN_CNT_CODE
| IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_EXECUTE
;
1425 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt32
, §ion
, section_data
, __LINE__
);
1426 ok( status
== STATUS_INVALID_IMAGE_FORMAT
, "NtCreateSection error %08x\n", status
);
1428 switch (orig_machine
)
1430 case IMAGE_FILE_MACHINE_AMD64
: nt32
.FileHeader
.Machine
= IMAGE_FILE_MACHINE_ARMNT
; break;
1431 case IMAGE_FILE_MACHINE_ARM64
: nt32
.FileHeader
.Machine
= IMAGE_FILE_MACHINE_I386
; break;
1433 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt32
, §ion
, section_data
, __LINE__
);
1434 ok( status
== STATUS_INVALID_IMAGE_FORMAT
|| broken(!status
) /* win8 */,
1435 "NtCreateSection error %08x\n", status
);
1437 nt32
.FileHeader
.Machine
= get_alt_bitness_machine( orig_machine
);
1438 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt32
, §ion
, section_data
, __LINE__
);
1439 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1441 nt32
.OptionalHeader
.SizeOfCode
= 0;
1442 nt32
.OptionalHeader
.AddressOfEntryPoint
= 0x1000;
1443 section
.Characteristics
= IMAGE_SCN_MEM_READ
| IMAGE_SCN_CNT_CODE
;
1444 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt32
, §ion
, section_data
, __LINE__
);
1445 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1447 nt32
.OptionalHeader
.SizeOfCode
= 0;
1448 nt32
.OptionalHeader
.AddressOfEntryPoint
= 0;
1449 section
.Characteristics
= IMAGE_SCN_MEM_READ
| IMAGE_SCN_CNT_CODE
| IMAGE_SCN_MEM_EXECUTE
;
1450 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt32
, §ion
, section_data
, __LINE__
);
1451 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1453 nt32
.OptionalHeader
.SizeOfCode
= 0x1000;
1454 nt32
.OptionalHeader
.AddressOfEntryPoint
= 0;
1455 nt32
.OptionalHeader
.DllCharacteristics
= IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
;
1456 section
.Characteristics
= IMAGE_SCN_MEM_READ
| IMAGE_SCN_CNT_CODE
;
1457 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt32
, §ion
, section_data
, __LINE__
);
1458 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1460 nt32
.OptionalHeader
.SizeOfCode
= 0;
1461 nt32
.OptionalHeader
.AddressOfEntryPoint
= 0;
1462 section
.Characteristics
= IMAGE_SCN_MEM_READ
| IMAGE_SCN_CNT_CODE
;
1463 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt32
, §ion
, section_data
, __LINE__
);
1464 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1466 nt32
.OptionalHeader
.NumberOfRvaAndSizes
= IMAGE_NUMBEROF_DIRECTORY_ENTRIES
;
1467 nt32
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
= page_size
;
1468 nt32
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].Size
= sizeof(cor_header
);
1469 cor_header
.MajorRuntimeVersion
= 2;
1470 cor_header
.MinorRuntimeVersion
= 4;
1471 cor_header
.Flags
= COMIMAGE_FLAGS_ILONLY
;
1472 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt32
, §ion
, &cor_header
, __LINE__
);
1473 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1475 nt32
.OptionalHeader
.SizeOfCode
= 0x1000;
1476 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt32
, §ion
, &cor_header
, __LINE__
);
1477 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1479 cor_header
.MinorRuntimeVersion
= 5;
1480 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt32
, §ion
, &cor_header
, __LINE__
);
1481 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1483 cor_header
.Flags
= COMIMAGE_FLAGS_ILONLY
| COMIMAGE_FLAGS_32BITREQUIRED
;
1484 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt32
, §ion
, &cor_header
, __LINE__
);
1485 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1487 cor_header
.Flags
= COMIMAGE_FLAGS_ILONLY
| COMIMAGE_FLAGS_32BITPREFERRED
;
1488 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt32
, §ion
, &cor_header
, __LINE__
);
1489 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1491 cor_header
.Flags
= 0;
1492 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt32
, §ion
, &cor_header
, __LINE__
);
1493 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1495 nt_header
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
= 1;
1496 nt_header
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].Size
= 1;
1497 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt32
, §ion
, &cor_header
, __LINE__
);
1498 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1501 section
.Characteristics
= IMAGE_SCN_CNT_INITIALIZED_DATA
| IMAGE_SCN_MEM_READ
;
1505 static void test_filenames(void)
1507 IMAGE_NT_HEADERS nt_header
= nt_header_template
;
1508 char dll_name
[MAX_PATH
], long_path
[MAX_PATH
], short_path
[MAX_PATH
], buffer
[MAX_PATH
];
1512 nt_header
.FileHeader
.NumberOfSections
= 1;
1513 nt_header
.FileHeader
.SizeOfOptionalHeader
= sizeof(IMAGE_OPTIONAL_HEADER
);
1515 nt_header
.OptionalHeader
.SectionAlignment
= page_size
;
1516 nt_header
.OptionalHeader
.DllCharacteristics
= IMAGE_DLLCHARACTERISTICS_NX_COMPAT
;
1517 nt_header
.OptionalHeader
.FileAlignment
= page_size
;
1518 nt_header
.OptionalHeader
.SizeOfHeaders
= sizeof(dos_header
) + sizeof(nt_header
) + sizeof(IMAGE_SECTION_HEADER
);
1519 nt_header
.OptionalHeader
.SizeOfImage
= sizeof(dos_header
) + sizeof(nt_header
) + sizeof(IMAGE_SECTION_HEADER
) + page_size
;
1521 create_test_dll( &dos_header
, sizeof(dos_header
), &nt_header
, dll_name
);
1522 strcpy( long_path
, dll_name
);
1523 strcpy( strrchr( long_path
, '\\' ), "\\this-is-a-long-name.dll" );
1524 ret
= MoveFileA( dll_name
, long_path
);
1525 ok( ret
, "MoveFileA failed err %u\n", GetLastError() );
1526 GetShortPathNameA( long_path
, short_path
, MAX_PATH
);
1528 mod
= LoadLibraryA( short_path
);
1529 ok( mod
!= NULL
, "loading failed err %u\n", GetLastError() );
1530 GetModuleFileNameA( mod
, buffer
, MAX_PATH
);
1531 ok( !lstrcmpiA( buffer
, short_path
), "got wrong path %s / %s\n", buffer
, short_path
);
1532 mod2
= GetModuleHandleA( short_path
);
1533 ok( mod
== mod2
, "wrong module %p for %s\n", mod2
, short_path
);
1534 mod2
= GetModuleHandleA( long_path
);
1535 ok( mod
== mod2
, "wrong module %p for %s\n", mod2
, long_path
);
1536 mod2
= LoadLibraryA( long_path
);
1537 ok( mod2
!= NULL
, "loading failed err %u\n", GetLastError() );
1538 ok( mod
== mod2
, "library loaded twice\n" );
1539 GetModuleFileNameA( mod2
, buffer
, MAX_PATH
);
1540 ok( !lstrcmpiA( buffer
, short_path
), "got wrong path %s / %s\n", buffer
, short_path
);
1541 FreeLibrary( mod2
);
1544 mod
= LoadLibraryA( long_path
);
1545 ok( mod
!= NULL
, "loading failed err %u\n", GetLastError() );
1546 GetModuleFileNameA( mod
, buffer
, MAX_PATH
);
1547 ok( !lstrcmpiA( buffer
, long_path
), "got wrong path %s / %s\n", buffer
, long_path
);
1548 mod2
= GetModuleHandleA( short_path
);
1549 ok( mod
== mod2
, "wrong module %p for %s\n", mod2
, short_path
);
1550 mod2
= GetModuleHandleA( long_path
);
1551 ok( mod
== mod2
, "wrong module %p for %s\n", mod2
, long_path
);
1552 mod2
= LoadLibraryA( short_path
);
1553 ok( mod2
!= NULL
, "loading failed err %u\n", GetLastError() );
1554 ok( mod
== mod2
, "library loaded twice\n" );
1555 GetModuleFileNameA( mod2
, buffer
, MAX_PATH
);
1556 ok( !lstrcmpiA( buffer
, long_path
), "got wrong path %s / %s\n", buffer
, long_path
);
1557 FreeLibrary( mod2
);
1560 strcpy( dll_name
, long_path
);
1561 strcpy( strrchr( dll_name
, '\\' ), "\\this-is-another-name.dll" );
1562 ret
= CreateHardLinkA( dll_name
, long_path
, NULL
);
1563 ok( ret
, "CreateHardLinkA failed err %u\n", GetLastError() );
1566 mod
= LoadLibraryA( dll_name
);
1567 ok( mod
!= NULL
, "loading failed err %u\n", GetLastError() );
1568 GetModuleFileNameA( mod
, buffer
, MAX_PATH
);
1569 ok( !lstrcmpiA( buffer
, dll_name
), "got wrong path %s / %s\n", buffer
, dll_name
);
1570 mod2
= GetModuleHandleA( long_path
);
1571 ok( mod
== mod2
, "wrong module %p for %s\n", mod2
, long_path
);
1572 mod2
= LoadLibraryA( long_path
);
1573 ok( mod2
!= NULL
, "loading failed err %u\n", GetLastError() );
1574 ok( mod
== mod2
, "library loaded twice\n" );
1575 GetModuleFileNameA( mod2
, buffer
, MAX_PATH
);
1576 ok( !lstrcmpiA( buffer
, dll_name
), "got wrong path %s / %s\n", buffer
, short_path
);
1577 FreeLibrary( mod2
);
1579 DeleteFileA( dll_name
);
1581 DeleteFileA( long_path
);
1584 /* Verify linking style of import descriptors */
1585 static void test_ImportDescriptors(void)
1587 HMODULE kernel32_module
= NULL
;
1588 PIMAGE_DOS_HEADER d_header
;
1589 PIMAGE_NT_HEADERS nt_headers
;
1590 DWORD import_dir_size
;
1591 DWORD_PTR dir_offset
;
1592 PIMAGE_IMPORT_DESCRIPTOR import_chunk
;
1594 /* Load kernel32 module */
1595 kernel32_module
= GetModuleHandleA("kernel32.dll");
1596 assert( kernel32_module
!= NULL
);
1598 /* Get PE header info from module image */
1599 d_header
= (PIMAGE_DOS_HEADER
) kernel32_module
;
1600 nt_headers
= (PIMAGE_NT_HEADERS
) (((char*) d_header
) +
1601 d_header
->e_lfanew
);
1603 /* Get size of import entry directory */
1604 import_dir_size
= nt_headers
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].Size
;
1605 if (!import_dir_size
)
1607 skip("Unable to continue testing due to missing import directory.\n");
1611 /* Get address of first import chunk */
1612 dir_offset
= nt_headers
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
;
1613 import_chunk
= RVAToAddr(dir_offset
, kernel32_module
);
1614 ok(import_chunk
!= 0, "Invalid import_chunk: %p\n", import_chunk
);
1615 if (!import_chunk
) return;
1617 /* Iterate through import descriptors and verify set name,
1618 * OriginalFirstThunk, and FirstThunk. Core Windows DLLs, such as
1619 * kernel32.dll, don't use Borland-style linking, where the table of
1620 * imported names is stored directly in FirstThunk and overwritten
1621 * by the relocation, instead of being stored in OriginalFirstThunk.
1623 for (; import_chunk
->FirstThunk
; import_chunk
++)
1625 LPCSTR module_name
= RVAToAddr(import_chunk
->Name
, kernel32_module
);
1626 PIMAGE_THUNK_DATA name_table
= RVAToAddr(
1627 U(*import_chunk
).OriginalFirstThunk
, kernel32_module
);
1628 PIMAGE_THUNK_DATA iat
= RVAToAddr(
1629 import_chunk
->FirstThunk
, kernel32_module
);
1630 ok(module_name
!= NULL
, "Imported module name should not be NULL\n");
1631 ok(name_table
!= NULL
,
1632 "Name table for imported module %s should not be NULL\n",
1634 ok(iat
!= NULL
, "IAT for imported module %s should not be NULL\n",
1639 static void test_image_mapping(const char *dll_name
, DWORD scn_page_access
, BOOL is_dll
)
1643 LARGE_INTEGER offset
;
1645 void *addr1
, *addr2
;
1646 MEMORY_BASIC_INFORMATION info
;
1648 if (!pNtMapViewOfSection
) return;
1650 SetLastError(0xdeadbeef);
1651 hfile
= CreateFileA(dll_name
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
1652 ok(hfile
!= INVALID_HANDLE_VALUE
, "CreateFile error %d\n", GetLastError());
1654 SetLastError(0xdeadbeef);
1655 hmap
= CreateFileMappingW(hfile
, NULL
, PAGE_READONLY
| SEC_IMAGE
, 0, 0, 0);
1656 ok(hmap
!= 0, "CreateFileMapping error %d\n", GetLastError());
1658 offset
.u
.LowPart
= 0;
1659 offset
.u
.HighPart
= 0;
1663 status
= pNtMapViewOfSection(hmap
, GetCurrentProcess(), &addr1
, 0, 0, &offset
,
1664 &size
, 1 /* ViewShare */, 0, PAGE_READONLY
);
1665 ok(status
== STATUS_SUCCESS
, "NtMapViewOfSection error %x\n", status
);
1666 ok(addr1
!= 0, "mapped address should be valid\n");
1668 SetLastError(0xdeadbeef);
1669 size
= VirtualQuery((char *)addr1
+ section
.VirtualAddress
, &info
, sizeof(info
));
1670 ok(size
== sizeof(info
), "VirtualQuery error %d\n", GetLastError());
1671 ok(info
.BaseAddress
== (char *)addr1
+ section
.VirtualAddress
, "got %p != expected %p\n", info
.BaseAddress
, (char *)addr1
+ section
.VirtualAddress
);
1672 ok(info
.RegionSize
== page_size
, "got %#lx != expected %#x\n", info
.RegionSize
, page_size
);
1673 ok(info
.Protect
== scn_page_access
, "got %#x != expected %#x\n", info
.Protect
, scn_page_access
);
1674 ok(info
.AllocationBase
== addr1
, "%p != %p\n", info
.AllocationBase
, addr1
);
1675 ok(info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
, "%#x != PAGE_EXECUTE_WRITECOPY\n", info
.AllocationProtect
);
1676 ok(info
.State
== MEM_COMMIT
, "%#x != MEM_COMMIT\n", info
.State
);
1677 ok(info
.Type
== SEC_IMAGE
, "%#x != SEC_IMAGE\n", info
.Type
);
1681 status
= pNtMapViewOfSection(hmap
, GetCurrentProcess(), &addr2
, 0, 0, &offset
,
1682 &size
, 1 /* ViewShare */, 0, PAGE_READONLY
);
1683 ok(status
== STATUS_IMAGE_NOT_AT_BASE
, "expected STATUS_IMAGE_NOT_AT_BASE, got %x\n", status
);
1684 ok(addr2
!= 0, "mapped address should be valid\n");
1685 ok(addr2
!= addr1
, "mapped addresses should be different\n");
1687 SetLastError(0xdeadbeef);
1688 size
= VirtualQuery((char *)addr2
+ section
.VirtualAddress
, &info
, sizeof(info
));
1689 ok(size
== sizeof(info
), "VirtualQuery error %d\n", GetLastError());
1690 ok(info
.BaseAddress
== (char *)addr2
+ section
.VirtualAddress
, "got %p != expected %p\n", info
.BaseAddress
, (char *)addr2
+ section
.VirtualAddress
);
1691 ok(info
.RegionSize
== page_size
, "got %#lx != expected %#x\n", info
.RegionSize
, page_size
);
1692 ok(info
.Protect
== scn_page_access
, "got %#x != expected %#x\n", info
.Protect
, scn_page_access
);
1693 ok(info
.AllocationBase
== addr2
, "%p != %p\n", info
.AllocationBase
, addr2
);
1694 ok(info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
, "%#x != PAGE_EXECUTE_WRITECOPY\n", info
.AllocationProtect
);
1695 ok(info
.State
== MEM_COMMIT
, "%#x != MEM_COMMIT\n", info
.State
);
1696 ok(info
.Type
== SEC_IMAGE
, "%#x != SEC_IMAGE\n", info
.Type
);
1698 status
= pNtUnmapViewOfSection(GetCurrentProcess(), addr2
);
1699 ok(status
== STATUS_SUCCESS
, "NtUnmapViewOfSection error %x\n", status
);
1701 addr2
= MapViewOfFile(hmap
, 0, 0, 0, 0);
1702 ok(addr2
!= 0, "mapped address should be valid\n");
1703 ok(addr2
!= addr1
, "mapped addresses should be different\n");
1705 SetLastError(0xdeadbeef);
1706 size
= VirtualQuery((char *)addr2
+ section
.VirtualAddress
, &info
, sizeof(info
));
1707 ok(size
== sizeof(info
), "VirtualQuery error %d\n", GetLastError());
1708 ok(info
.BaseAddress
== (char *)addr2
+ section
.VirtualAddress
, "got %p != expected %p\n", info
.BaseAddress
, (char *)addr2
+ section
.VirtualAddress
);
1709 ok(info
.RegionSize
== page_size
, "got %#lx != expected %#x\n", info
.RegionSize
, page_size
);
1710 ok(info
.Protect
== scn_page_access
, "got %#x != expected %#x\n", info
.Protect
, scn_page_access
);
1711 ok(info
.AllocationBase
== addr2
, "%p != %p\n", info
.AllocationBase
, addr2
);
1712 ok(info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
, "%#x != PAGE_EXECUTE_WRITECOPY\n", info
.AllocationProtect
);
1713 ok(info
.State
== MEM_COMMIT
, "%#x != MEM_COMMIT\n", info
.State
);
1714 ok(info
.Type
== SEC_IMAGE
, "%#x != SEC_IMAGE\n", info
.Type
);
1716 UnmapViewOfFile(addr2
);
1718 SetLastError(0xdeadbeef);
1719 addr2
= LoadLibraryA(dll_name
);
1722 ok(!addr2
, "LoadLibrary should fail, is_dll %d\n", is_dll
);
1723 ok(GetLastError() == ERROR_INVALID_ADDRESS
, "expected ERROR_INVALID_ADDRESS, got %d\n", GetLastError());
1728 ok(addr2
!= 0, "LoadLibrary error %d, is_dll %d\n", GetLastError(), is_dll
);
1729 ok(addr2
!= addr1
, "mapped addresses should be different\n");
1731 SetLastError(0xdeadbeef);
1732 ret
= FreeLibrary(addr2
);
1733 ok(ret
, "FreeLibrary error %d\n", GetLastError());
1736 status
= pNtUnmapViewOfSection(GetCurrentProcess(), addr1
);
1737 ok(status
== STATUS_SUCCESS
, "NtUnmapViewOfSection error %x\n", status
);
1743 static BOOL
is_mem_writable(DWORD prot
)
1745 switch (prot
& 0xff)
1747 case PAGE_READWRITE
:
1748 case PAGE_WRITECOPY
:
1749 case PAGE_EXECUTE_READWRITE
:
1750 case PAGE_EXECUTE_WRITECOPY
:
1758 static void test_VirtualProtect(void *base
, void *section
)
1760 static const struct test_data
1762 DWORD prot_set
, prot_get
;
1765 { 0, 0 }, /* 0x00 */
1766 { PAGE_NOACCESS
, PAGE_NOACCESS
}, /* 0x01 */
1767 { PAGE_READONLY
, PAGE_READONLY
}, /* 0x02 */
1768 { PAGE_READONLY
| PAGE_NOACCESS
, 0 }, /* 0x03 */
1769 { PAGE_READWRITE
, PAGE_WRITECOPY
}, /* 0x04 */
1770 { PAGE_READWRITE
| PAGE_NOACCESS
, 0 }, /* 0x05 */
1771 { PAGE_READWRITE
| PAGE_READONLY
, 0 }, /* 0x06 */
1772 { PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, 0 }, /* 0x07 */
1773 { PAGE_WRITECOPY
, PAGE_WRITECOPY
}, /* 0x08 */
1774 { PAGE_WRITECOPY
| PAGE_NOACCESS
, 0 }, /* 0x09 */
1775 { PAGE_WRITECOPY
| PAGE_READONLY
, 0 }, /* 0x0a */
1776 { PAGE_WRITECOPY
| PAGE_NOACCESS
| PAGE_READONLY
, 0 }, /* 0x0b */
1777 { PAGE_WRITECOPY
| PAGE_READWRITE
, 0 }, /* 0x0c */
1778 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_NOACCESS
, 0 }, /* 0x0d */
1779 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
, 0 }, /* 0x0e */
1780 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, 0 }, /* 0x0f */
1782 { PAGE_EXECUTE
, PAGE_EXECUTE
}, /* 0x10 */
1783 { PAGE_EXECUTE_READ
, PAGE_EXECUTE_READ
}, /* 0x20 */
1784 { PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 }, /* 0x30 */
1785 { PAGE_EXECUTE_READWRITE
, PAGE_EXECUTE_WRITECOPY
}, /* 0x40 */
1786 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, 0 }, /* 0x50 */
1787 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, 0 }, /* 0x60 */
1788 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 }, /* 0x70 */
1789 { PAGE_EXECUTE_WRITECOPY
, PAGE_EXECUTE_WRITECOPY
}, /* 0x80 */
1790 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE
, 0 }, /* 0x90 */
1791 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
, 0 }, /* 0xa0 */
1792 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 }, /* 0xb0 */
1793 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
, 0 }, /* 0xc0 */
1794 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, 0 }, /* 0xd0 */
1795 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, 0 }, /* 0xe0 */
1796 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 } /* 0xf0 */
1798 DWORD ret
, orig_prot
, old_prot
, rw_prot
, exec_prot
, i
, j
;
1799 MEMORY_BASIC_INFORMATION info
;
1801 SetLastError(0xdeadbeef);
1802 ret
= VirtualProtect(section
, page_size
, PAGE_NOACCESS
, &old_prot
);
1803 ok(ret
, "VirtualProtect error %d\n", GetLastError());
1805 orig_prot
= old_prot
;
1807 for (i
= 0; i
< ARRAY_SIZE(td
); i
++)
1809 SetLastError(0xdeadbeef);
1810 ret
= VirtualQuery(section
, &info
, sizeof(info
));
1811 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
1812 ok(info
.BaseAddress
== section
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, section
);
1813 ok(info
.RegionSize
== page_size
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, page_size
);
1814 ok(info
.Protect
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, info
.Protect
);
1815 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
1816 ok(info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
, "%d: %#x != PAGE_EXECUTE_WRITECOPY\n", i
, info
.AllocationProtect
);
1817 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
1818 ok(info
.Type
== SEC_IMAGE
, "%d: %#x != SEC_IMAGE\n", i
, info
.Type
);
1820 old_prot
= 0xdeadbeef;
1821 SetLastError(0xdeadbeef);
1822 ret
= VirtualProtect(section
, page_size
, td
[i
].prot_set
, &old_prot
);
1825 ok(ret
, "%d: VirtualProtect error %d, requested prot %#x\n", i
, GetLastError(), td
[i
].prot_set
);
1826 ok(old_prot
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, old_prot
);
1828 SetLastError(0xdeadbeef);
1829 ret
= VirtualQuery(section
, &info
, sizeof(info
));
1830 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
1831 ok(info
.BaseAddress
== section
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, section
);
1832 ok(info
.RegionSize
== page_size
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, page_size
);
1833 ok(info
.Protect
== td
[i
].prot_get
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot_get
);
1834 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
1835 ok(info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
, "%d: %#x != PAGE_EXECUTE_WRITECOPY\n", i
, info
.AllocationProtect
);
1836 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
1837 ok(info
.Type
== SEC_IMAGE
, "%d: %#x != SEC_IMAGE\n", i
, info
.Type
);
1841 ok(!ret
, "%d: VirtualProtect should fail\n", i
);
1842 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
1845 old_prot
= 0xdeadbeef;
1846 SetLastError(0xdeadbeef);
1847 ret
= VirtualProtect(section
, page_size
, PAGE_NOACCESS
, &old_prot
);
1848 ok(ret
, "%d: VirtualProtect error %d\n", i
, GetLastError());
1850 ok(old_prot
== td
[i
].prot_get
, "%d: got %#x != expected %#x\n", i
, old_prot
, td
[i
].prot_get
);
1852 ok(old_prot
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, old_prot
);
1857 for (i
= 0; i
<= 4; i
++)
1861 for (j
= 0; j
<= 4; j
++)
1863 DWORD prot
= exec_prot
| rw_prot
;
1865 SetLastError(0xdeadbeef);
1866 ret
= VirtualProtect(section
, page_size
, prot
, &old_prot
);
1867 if ((rw_prot
&& exec_prot
) || (!rw_prot
&& !exec_prot
))
1869 ok(!ret
, "VirtualProtect(%02x) should fail\n", prot
);
1870 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1873 ok(ret
, "VirtualProtect(%02x) error %d\n", prot
, GetLastError());
1878 exec_prot
= 1 << (i
+ 4);
1881 SetLastError(0xdeadbeef);
1882 ret
= VirtualProtect(section
, page_size
, orig_prot
, &old_prot
);
1883 ok(ret
, "VirtualProtect error %d\n", GetLastError());
1886 static void test_section_access(void)
1888 static const struct test_data
1890 DWORD scn_file_access
, scn_page_access
, scn_page_access_after_write
;
1893 { 0, PAGE_NOACCESS
, 0 },
1894 { IMAGE_SCN_MEM_READ
, PAGE_READONLY
, 0 },
1895 { IMAGE_SCN_MEM_WRITE
, PAGE_WRITECOPY
, PAGE_READWRITE
},
1896 { IMAGE_SCN_MEM_EXECUTE
, PAGE_EXECUTE
, 0 },
1897 { IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_WRITE
, PAGE_WRITECOPY
, PAGE_READWRITE
},
1898 { IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_EXECUTE
, PAGE_EXECUTE_READ
},
1899 { IMAGE_SCN_MEM_WRITE
| IMAGE_SCN_MEM_EXECUTE
, PAGE_EXECUTE_WRITECOPY
, PAGE_EXECUTE_READWRITE
},
1900 { IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_WRITE
| IMAGE_SCN_MEM_EXECUTE
, PAGE_EXECUTE_WRITECOPY
, PAGE_EXECUTE_READWRITE
},
1902 { IMAGE_SCN_CNT_INITIALIZED_DATA
, PAGE_NOACCESS
, 0 },
1903 { IMAGE_SCN_CNT_INITIALIZED_DATA
| IMAGE_SCN_MEM_READ
, PAGE_READONLY
, 0 },
1904 { IMAGE_SCN_CNT_INITIALIZED_DATA
| IMAGE_SCN_MEM_WRITE
, PAGE_WRITECOPY
, PAGE_READWRITE
},
1905 { IMAGE_SCN_CNT_INITIALIZED_DATA
| IMAGE_SCN_MEM_EXECUTE
, PAGE_EXECUTE
, 0 },
1906 { IMAGE_SCN_CNT_INITIALIZED_DATA
| IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_WRITE
, PAGE_WRITECOPY
, PAGE_READWRITE
},
1907 { IMAGE_SCN_CNT_INITIALIZED_DATA
| IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_EXECUTE
, PAGE_EXECUTE_READ
, 0 },
1908 { IMAGE_SCN_CNT_INITIALIZED_DATA
| IMAGE_SCN_MEM_WRITE
| IMAGE_SCN_MEM_EXECUTE
, PAGE_EXECUTE_WRITECOPY
, PAGE_EXECUTE_READWRITE
},
1909 { IMAGE_SCN_CNT_INITIALIZED_DATA
| IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_WRITE
| IMAGE_SCN_MEM_EXECUTE
, PAGE_EXECUTE_WRITECOPY
, PAGE_EXECUTE_READWRITE
},
1911 { IMAGE_SCN_CNT_UNINITIALIZED_DATA
, PAGE_NOACCESS
, 0 },
1912 { IMAGE_SCN_CNT_UNINITIALIZED_DATA
| IMAGE_SCN_MEM_READ
, PAGE_READONLY
, 0 },
1913 { IMAGE_SCN_CNT_UNINITIALIZED_DATA
| IMAGE_SCN_MEM_WRITE
, PAGE_WRITECOPY
, PAGE_READWRITE
},
1914 { IMAGE_SCN_CNT_UNINITIALIZED_DATA
| IMAGE_SCN_MEM_EXECUTE
, PAGE_EXECUTE
, 0 },
1915 { IMAGE_SCN_CNT_UNINITIALIZED_DATA
| IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_WRITE
, PAGE_WRITECOPY
, PAGE_READWRITE
},
1916 { IMAGE_SCN_CNT_UNINITIALIZED_DATA
| IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_EXECUTE
, PAGE_EXECUTE_READ
, 0 },
1917 { IMAGE_SCN_CNT_UNINITIALIZED_DATA
| IMAGE_SCN_MEM_WRITE
| IMAGE_SCN_MEM_EXECUTE
, PAGE_EXECUTE_WRITECOPY
, PAGE_EXECUTE_READWRITE
},
1918 { IMAGE_SCN_CNT_UNINITIALIZED_DATA
| IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_WRITE
| IMAGE_SCN_MEM_EXECUTE
, PAGE_EXECUTE_WRITECOPY
, PAGE_EXECUTE_READWRITE
}
1922 DWORD dummy
, file_align
;
1925 char temp_path
[MAX_PATH
];
1926 char dll_name
[MAX_PATH
];
1928 MEMORY_BASIC_INFORMATION info
;
1930 PROCESS_INFORMATION pi
;
1933 /* prevent displaying of the "Unable to load this DLL" message box */
1934 SetErrorMode(SEM_FAILCRITICALERRORS
);
1936 GetTempPathA(MAX_PATH
, temp_path
);
1938 for (i
= 0; i
< ARRAY_SIZE(td
); i
++)
1940 IMAGE_NT_HEADERS nt_header
;
1942 GetTempFileNameA(temp_path
, "ldr", 0, dll_name
);
1944 /*trace("creating %s\n", dll_name);*/
1945 hfile
= CreateFileA(dll_name
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
1946 if (hfile
== INVALID_HANDLE_VALUE
)
1948 ok(0, "could not create %s\n", dll_name
);
1952 SetLastError(0xdeadbeef);
1953 ret
= WriteFile(hfile
, &dos_header
, sizeof(dos_header
), &dummy
, NULL
);
1954 ok(ret
, "WriteFile error %d\n", GetLastError());
1956 nt_header
= nt_header_template
;
1957 nt_header
.FileHeader
.NumberOfSections
= 1;
1958 nt_header
.FileHeader
.SizeOfOptionalHeader
= sizeof(IMAGE_OPTIONAL_HEADER
);
1959 nt_header
.FileHeader
.Characteristics
= IMAGE_FILE_EXECUTABLE_IMAGE
| IMAGE_FILE_DLL
| IMAGE_FILE_RELOCS_STRIPPED
;
1961 nt_header
.OptionalHeader
.SectionAlignment
= page_size
;
1962 nt_header
.OptionalHeader
.FileAlignment
= 0x200;
1963 nt_header
.OptionalHeader
.SizeOfImage
= sizeof(dos_header
) + sizeof(nt_header
) + sizeof(IMAGE_SECTION_HEADER
) + page_size
;
1964 nt_header
.OptionalHeader
.SizeOfHeaders
= sizeof(dos_header
) + sizeof(nt_header
) + sizeof(IMAGE_SECTION_HEADER
);
1965 SetLastError(0xdeadbeef);
1966 ret
= WriteFile(hfile
, &nt_header
, sizeof(DWORD
) + sizeof(IMAGE_FILE_HEADER
), &dummy
, NULL
);
1967 ok(ret
, "WriteFile error %d\n", GetLastError());
1968 SetLastError(0xdeadbeef);
1969 ret
= WriteFile(hfile
, &nt_header
.OptionalHeader
, sizeof(IMAGE_OPTIONAL_HEADER
), &dummy
, NULL
);
1970 ok(ret
, "WriteFile error %d\n", GetLastError());
1972 section
.SizeOfRawData
= sizeof(section_data
);
1973 section
.PointerToRawData
= nt_header
.OptionalHeader
.FileAlignment
;
1974 section
.VirtualAddress
= nt_header
.OptionalHeader
.SectionAlignment
;
1975 section
.Misc
.VirtualSize
= section
.SizeOfRawData
;
1976 section
.Characteristics
= td
[i
].scn_file_access
;
1977 SetLastError(0xdeadbeef);
1978 ret
= WriteFile(hfile
, §ion
, sizeof(section
), &dummy
, NULL
);
1979 ok(ret
, "WriteFile error %d\n", GetLastError());
1981 file_align
= nt_header
.OptionalHeader
.FileAlignment
- nt_header
.OptionalHeader
.SizeOfHeaders
;
1982 assert(file_align
< sizeof(filler
));
1983 SetLastError(0xdeadbeef);
1984 ret
= WriteFile(hfile
, filler
, file_align
, &dummy
, NULL
);
1985 ok(ret
, "WriteFile error %d\n", GetLastError());
1988 SetLastError(0xdeadbeef);
1989 ret
= WriteFile(hfile
, section_data
, sizeof(section_data
), &dummy
, NULL
);
1990 ok(ret
, "WriteFile error %d\n", GetLastError());
1994 SetLastError(0xdeadbeef);
1995 hlib
= LoadLibraryA(dll_name
);
1996 ok(hlib
!= 0, "LoadLibrary error %d\n", GetLastError());
1998 SetLastError(0xdeadbeef);
1999 size
= VirtualQuery((char *)hlib
+ section
.VirtualAddress
, &info
, sizeof(info
));
2000 ok(size
== sizeof(info
),
2001 "%d: VirtualQuery error %d\n", i
, GetLastError());
2002 ok(info
.BaseAddress
== (char *)hlib
+ section
.VirtualAddress
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, (char *)hlib
+ section
.VirtualAddress
);
2003 ok(info
.RegionSize
== page_size
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, page_size
);
2004 ok(info
.Protect
== td
[i
].scn_page_access
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].scn_page_access
);
2005 ok(info
.AllocationBase
== hlib
, "%d: %p != %p\n", i
, info
.AllocationBase
, hlib
);
2006 ok(info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
, "%d: %#x != PAGE_EXECUTE_WRITECOPY\n", i
, info
.AllocationProtect
);
2007 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
2008 ok(info
.Type
== SEC_IMAGE
, "%d: %#x != SEC_IMAGE\n", i
, info
.Type
);
2009 if (info
.Protect
!= PAGE_NOACCESS
)
2010 ok(!memcmp((const char *)info
.BaseAddress
, section_data
, section
.SizeOfRawData
), "wrong section data\n");
2012 test_VirtualProtect(hlib
, (char *)hlib
+ section
.VirtualAddress
);
2014 /* Windows changes the WRITECOPY to WRITE protection on an image section write (for a changed page only) */
2015 if (is_mem_writable(info
.Protect
))
2017 char *p
= info
.BaseAddress
;
2019 SetLastError(0xdeadbeef);
2020 size
= VirtualQuery((char *)hlib
+ section
.VirtualAddress
, &info
, sizeof(info
));
2021 ok(size
== sizeof(info
), "%d: VirtualQuery error %d\n", i
, GetLastError());
2022 /* FIXME: remove the condition below once Wine is fixed */
2023 todo_wine_if (info
.Protect
== PAGE_WRITECOPY
|| info
.Protect
== PAGE_EXECUTE_WRITECOPY
)
2024 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
);
2027 SetLastError(0xdeadbeef);
2028 ret
= FreeLibrary(hlib
);
2029 ok(ret
, "FreeLibrary error %d\n", GetLastError());
2031 test_image_mapping(dll_name
, td
[i
].scn_page_access
, TRUE
);
2033 /* reset IMAGE_FILE_DLL otherwise CreateProcess fails */
2034 nt_header
.FileHeader
.Characteristics
= IMAGE_FILE_EXECUTABLE_IMAGE
| IMAGE_FILE_RELOCS_STRIPPED
;
2035 SetLastError(0xdeadbeef);
2036 hfile
= CreateFileA(dll_name
, GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
2037 /* LoadLibrary called on an already memory-mapped file in
2038 * test_image_mapping() above leads to a file handle leak
2039 * under nt4, and inability to overwrite and delete the file
2040 * due to sharing violation error. Ignore it and skip the test,
2041 * but leave a not deletable temporary file.
2043 ok(hfile
!= INVALID_HANDLE_VALUE
|| broken(hfile
== INVALID_HANDLE_VALUE
) /* nt4 */,
2044 "CreateFile error %d\n", GetLastError());
2045 if (hfile
== INVALID_HANDLE_VALUE
) goto nt4_is_broken
;
2046 SetFilePointer(hfile
, sizeof(dos_header
), NULL
, FILE_BEGIN
);
2047 SetLastError(0xdeadbeef);
2048 ret
= WriteFile(hfile
, &nt_header
, sizeof(DWORD
) + sizeof(IMAGE_FILE_HEADER
), &dummy
, NULL
);
2049 ok(ret
, "WriteFile error %d\n", GetLastError());
2052 memset(&sti
, 0, sizeof(sti
));
2053 sti
.cb
= sizeof(sti
);
2054 SetLastError(0xdeadbeef);
2055 ret
= CreateProcessA(dll_name
, NULL
, NULL
, NULL
, FALSE
, CREATE_SUSPENDED
, NULL
, NULL
, &sti
, &pi
);
2056 ok(ret
, "CreateProcess() error %d\n", GetLastError());
2058 SetLastError(0xdeadbeef);
2059 size
= VirtualQueryEx(pi
.hProcess
, (char *)hlib
+ section
.VirtualAddress
, &info
, sizeof(info
));
2060 ok(size
== sizeof(info
),
2061 "%d: VirtualQuery error %d\n", i
, GetLastError());
2062 ok(info
.BaseAddress
== (char *)hlib
+ section
.VirtualAddress
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, (char *)hlib
+ section
.VirtualAddress
);
2063 ok(info
.RegionSize
== page_size
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, page_size
);
2064 ok(info
.Protect
== td
[i
].scn_page_access
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].scn_page_access
);
2065 ok(info
.AllocationBase
== hlib
, "%d: %p != %p\n", i
, info
.AllocationBase
, hlib
);
2066 ok(info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
, "%d: %#x != PAGE_EXECUTE_WRITECOPY\n", i
, info
.AllocationProtect
);
2067 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
2068 ok(info
.Type
== SEC_IMAGE
, "%d: %#x != SEC_IMAGE\n", i
, info
.Type
);
2069 if (info
.Protect
!= PAGE_NOACCESS
)
2071 SetLastError(0xdeadbeef);
2072 ret
= ReadProcessMemory(pi
.hProcess
, info
.BaseAddress
, buf
, section
.SizeOfRawData
, NULL
);
2073 ok(ret
, "ReadProcessMemory() error %d\n", GetLastError());
2074 ok(!memcmp(buf
, section_data
, section
.SizeOfRawData
), "wrong section data\n");
2077 SetLastError(0xdeadbeef);
2078 ret
= TerminateProcess(pi
.hProcess
, 0);
2079 ok(ret
, "TerminateProcess() error %d\n", GetLastError());
2080 ret
= WaitForSingleObject(pi
.hProcess
, 3000);
2081 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed: %x\n", ret
);
2083 CloseHandle(pi
.hThread
);
2084 CloseHandle(pi
.hProcess
);
2086 test_image_mapping(dll_name
, td
[i
].scn_page_access
, FALSE
);
2089 SetLastError(0xdeadbeef);
2090 ret
= DeleteFileA(dll_name
);
2091 ok(ret
|| broken(!ret
) /* nt4 */, "DeleteFile error %d\n", GetLastError());
2095 static void test_import_resolution(void)
2097 char temp_path
[MAX_PATH
];
2098 char dll_name
[MAX_PATH
];
2106 IMAGE_IMPORT_DESCRIPTOR descr
[2];
2107 IMAGE_THUNK_DATA original_thunks
[2];
2108 IMAGE_THUNK_DATA thunks
[2];
2110 struct { WORD hint
; char name
[32]; } function
;
2111 IMAGE_TLS_DIRECTORY tls
;
2115 IMAGE_NT_HEADERS nt
;
2116 IMAGE_SECTION_HEADER section
;
2119 for (test
= 0; test
< 3; test
++)
2121 #define DATA_RVA(ptr) (page_size + ((char *)(ptr) - (char *)&data))
2122 nt
= nt_header_template
;
2123 nt
.FileHeader
.NumberOfSections
= 1;
2124 nt
.FileHeader
.SizeOfOptionalHeader
= sizeof(IMAGE_OPTIONAL_HEADER
);
2125 nt
.FileHeader
.Characteristics
= IMAGE_FILE_EXECUTABLE_IMAGE
| IMAGE_FILE_32BIT_MACHINE
| IMAGE_FILE_RELOCS_STRIPPED
;
2126 if (test
!= 2) nt
.FileHeader
.Characteristics
|= IMAGE_FILE_DLL
;
2127 nt
.OptionalHeader
.SectionAlignment
= page_size
;
2128 nt
.OptionalHeader
.FileAlignment
= 0x200;
2129 nt
.OptionalHeader
.ImageBase
= 0x12340000;
2130 nt
.OptionalHeader
.SizeOfImage
= 2 * page_size
;
2131 nt
.OptionalHeader
.SizeOfHeaders
= nt
.OptionalHeader
.FileAlignment
;
2132 nt
.OptionalHeader
.NumberOfRvaAndSizes
= IMAGE_NUMBEROF_DIRECTORY_ENTRIES
;
2133 memset( nt
.OptionalHeader
.DataDirectory
, 0, sizeof(nt
.OptionalHeader
.DataDirectory
) );
2134 nt
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].Size
= sizeof(data
.descr
);
2135 nt
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
= DATA_RVA(data
.descr
);
2136 nt
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_TLS
].Size
= sizeof(data
.tls
);
2137 nt
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_TLS
].VirtualAddress
= DATA_RVA(&data
.tls
);
2139 memset( &data
, 0, sizeof(data
) );
2140 U(data
.descr
[0]).OriginalFirstThunk
= DATA_RVA( data
.original_thunks
);
2141 data
.descr
[0].FirstThunk
= DATA_RVA( data
.thunks
);
2142 data
.descr
[0].Name
= DATA_RVA( data
.module
);
2143 strcpy( data
.module
, "kernel32.dll" );
2144 strcpy( data
.function
.name
, "CreateEventA" );
2145 data
.original_thunks
[0].u1
.AddressOfData
= DATA_RVA( &data
.function
);
2146 data
.thunks
[0].u1
.AddressOfData
= 0xdeadbeef;
2148 data
.tls
.StartAddressOfRawData
= nt
.OptionalHeader
.ImageBase
+ DATA_RVA( data
.tls_data
);
2149 data
.tls
.EndAddressOfRawData
= data
.tls
.StartAddressOfRawData
+ sizeof(data
.tls_data
);
2150 data
.tls
.AddressOfIndex
= nt
.OptionalHeader
.ImageBase
+ DATA_RVA( &data
.tls_index
);
2151 strcpy( data
.tls_data
, "hello world" );
2152 data
.tls_index
= 9999;
2154 GetTempPathA(MAX_PATH
, temp_path
);
2155 GetTempFileNameA(temp_path
, "ldr", 0, dll_name
);
2157 hfile
= CreateFileA(dll_name
, GENERIC_WRITE
, FILE_SHARE_READ
, NULL
, CREATE_ALWAYS
, 0, 0);
2158 ok( hfile
!= INVALID_HANDLE_VALUE
, "creation failed\n" );
2160 memset( §ion
, 0, sizeof(section
) );
2161 memcpy( section
.Name
, ".text", sizeof(".text") );
2162 section
.PointerToRawData
= nt
.OptionalHeader
.FileAlignment
;
2163 section
.VirtualAddress
= nt
.OptionalHeader
.SectionAlignment
;
2164 section
.Misc
.VirtualSize
= sizeof(data
);
2165 section
.SizeOfRawData
= sizeof(data
);
2166 section
.Characteristics
= IMAGE_SCN_CNT_INITIALIZED_DATA
| IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_WRITE
;
2168 WriteFile(hfile
, &dos_header
, sizeof(dos_header
), &dummy
, NULL
);
2169 WriteFile(hfile
, &nt
, sizeof(nt
), &dummy
, NULL
);
2170 WriteFile(hfile
, §ion
, sizeof(section
), &dummy
, NULL
);
2172 SetFilePointer( hfile
, section
.PointerToRawData
, NULL
, SEEK_SET
);
2173 WriteFile(hfile
, &data
, sizeof(data
), &dummy
, NULL
);
2175 CloseHandle( hfile
);
2179 case 0: /* normal load */
2180 mod
= LoadLibraryA( dll_name
);
2181 ok( mod
!= NULL
, "failed to load err %u\n", GetLastError() );
2183 ptr
= (struct imports
*)((char *)mod
+ page_size
);
2184 expect
= GetProcAddress( GetModuleHandleA( data
.module
), data
.function
.name
);
2185 ok( (void *)ptr
->thunks
[0].u1
.Function
== expect
, "thunk %p instead of %p for %s.%s\n",
2186 (void *)ptr
->thunks
[0].u1
.Function
, expect
, data
.module
, data
.function
.name
);
2187 ok( ptr
->tls_index
< 32 || broken(ptr
->tls_index
== 9999), /* before vista */
2188 "wrong tls index %d\n", ptr
->tls_index
);
2189 if (ptr
->tls_index
!= 9999)
2191 str
= ((char **)NtCurrentTeb()->ThreadLocalStoragePointer
)[ptr
->tls_index
];
2192 ok( !strcmp( str
, "hello world" ), "wrong tls data '%s' at %p\n", str
, str
);
2196 case 1: /* load with DONT_RESOLVE_DLL_REFERENCES doesn't resolve imports */
2197 mod
= LoadLibraryExA( dll_name
, 0, DONT_RESOLVE_DLL_REFERENCES
);
2198 ok( mod
!= NULL
, "failed to load err %u\n", GetLastError() );
2200 ptr
= (struct imports
*)((char *)mod
+ page_size
);
2201 ok( ptr
->thunks
[0].u1
.Function
== 0xdeadbeef, "thunk resolved to %p for %s.%s\n",
2202 (void *)ptr
->thunks
[0].u1
.Function
, data
.module
, data
.function
.name
);
2203 ok( ptr
->tls_index
== 9999, "wrong tls index %d\n", ptr
->tls_index
);
2205 mod2
= LoadLibraryA( dll_name
);
2206 ok( mod2
== mod
, "loaded twice %p / %p\n", mod
, mod2
);
2207 ok( ptr
->thunks
[0].u1
.Function
== 0xdeadbeef, "thunk resolved to %p for %s.%s\n",
2208 (void *)ptr
->thunks
[0].u1
.Function
, data
.module
, data
.function
.name
);
2209 ok( ptr
->tls_index
== 9999, "wrong tls index %d\n", ptr
->tls_index
);
2210 FreeLibrary( mod2
);
2213 case 2: /* load without IMAGE_FILE_DLL doesn't resolve imports */
2214 mod
= LoadLibraryA( dll_name
);
2215 ok( mod
!= NULL
, "failed to load err %u\n", GetLastError() );
2217 ptr
= (struct imports
*)((char *)mod
+ page_size
);
2218 ok( ptr
->thunks
[0].u1
.Function
== 0xdeadbeef, "thunk resolved to %p for %s.%s\n",
2219 (void *)ptr
->thunks
[0].u1
.Function
, data
.module
, data
.function
.name
);
2220 ok( ptr
->tls_index
== 9999, "wrong tls index %d\n", ptr
->tls_index
);
2224 DeleteFileA( dll_name
);
2229 #define MAX_COUNT 10
2230 static HANDLE attached_thread
[MAX_COUNT
];
2231 static DWORD attached_thread_count
;
2232 static HANDLE event
, mutex
, semaphore
;
2233 static HANDLE stop_event
, loader_lock_event
, peb_lock_event
, heap_lock_event
, cs_lock_event
, ack_event
;
2234 static CRITICAL_SECTION cs_lock
;
2235 static int test_dll_phase
, inside_loader_lock
, inside_peb_lock
, inside_heap_lock
, inside_cs_lock
;
2236 static LONG fls_callback_count
;
2238 static DWORD WINAPI
mutex_thread_proc(void *param
)
2240 HANDLE wait_list
[5];
2243 ret
= WaitForSingleObject(mutex
, 0);
2244 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %#x\n", ret
);
2248 wait_list
[0] = stop_event
;
2249 wait_list
[1] = loader_lock_event
;
2250 wait_list
[2] = peb_lock_event
;
2251 wait_list
[3] = heap_lock_event
;
2252 wait_list
[4] = cs_lock_event
;
2254 trace("%04x: mutex_thread_proc: starting\n", GetCurrentThreadId());
2257 ret
= WaitForMultipleObjects(ARRAY_SIZE(wait_list
), wait_list
, FALSE
, 50);
2258 if (ret
== WAIT_OBJECT_0
) break;
2259 else if (ret
== WAIT_OBJECT_0
+ 1)
2261 ULONG_PTR loader_lock_magic
;
2262 trace("%04x: mutex_thread_proc: Entering loader lock\n", GetCurrentThreadId());
2263 ret
= pLdrLockLoaderLock(0, NULL
, &loader_lock_magic
);
2264 ok(!ret
, "LdrLockLoaderLock error %#x\n", ret
);
2265 inside_loader_lock
++;
2266 SetEvent(ack_event
);
2268 else if (ret
== WAIT_OBJECT_0
+ 2)
2270 trace("%04x: mutex_thread_proc: Entering PEB lock\n", GetCurrentThreadId());
2271 pRtlAcquirePebLock();
2273 SetEvent(ack_event
);
2275 else if (ret
== WAIT_OBJECT_0
+ 3)
2277 trace("%04x: mutex_thread_proc: Entering heap lock\n", GetCurrentThreadId());
2278 HeapLock(GetProcessHeap());
2280 SetEvent(ack_event
);
2282 else if (ret
== WAIT_OBJECT_0
+ 4)
2284 trace("%04x: mutex_thread_proc: Entering CS lock\n", GetCurrentThreadId());
2285 EnterCriticalSection(&cs_lock
);
2287 SetEvent(ack_event
);
2291 trace("%04x: mutex_thread_proc: exiting\n", GetCurrentThreadId());
2295 static DWORD WINAPI
semaphore_thread_proc(void *param
)
2299 ret
= WaitForSingleObject(semaphore
, 0);
2300 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %#x\n", ret
);
2306 if (winetest_debug
> 1)
2307 trace("%04x: semaphore_thread_proc: still alive\n", GetCurrentThreadId());
2308 if (WaitForSingleObject(stop_event
, 50) != WAIT_TIMEOUT
) break;
2311 trace("%04x: semaphore_thread_proc: exiting\n", GetCurrentThreadId());
2315 static DWORD WINAPI
noop_thread_proc(void *param
)
2319 LONG
*noop_thread_started
= param
;
2320 InterlockedIncrement(noop_thread_started
);
2323 trace("%04x: noop_thread_proc: exiting\n", GetCurrentThreadId());
2327 static VOID WINAPI
fls_callback(PVOID lpFlsData
)
2329 ok(lpFlsData
== (void*) 0x31415, "lpFlsData is %p, expected %p\n", lpFlsData
, (void*) 0x31415);
2330 InterlockedIncrement(&fls_callback_count
);
2333 static LIST_ENTRY
*fls_list_head
;
2335 static unsigned int check_linked_list(const LIST_ENTRY
*le
, const LIST_ENTRY
*search_entry
, unsigned int *index_found
)
2337 unsigned int count
= 0;
2342 for (entry
= le
->Flink
; entry
!= le
; entry
= entry
->Flink
)
2344 if (entry
== search_entry
)
2346 ok(*index_found
== ~0, "Duplicate list entry.\n");
2347 *index_found
= count
;
2354 static BOOL WINAPI
dll_entry_point(HINSTANCE hinst
, DWORD reason
, LPVOID param
)
2356 static LONG noop_thread_started
;
2357 static DWORD fls_index
= FLS_OUT_OF_INDEXES
, fls_index2
= FLS_OUT_OF_INDEXES
;
2358 static int fls_count
= 0;
2359 static int thread_detach_count
= 0;
2360 static int thread_count
;
2363 ok(!inside_loader_lock
, "inside_loader_lock should not be set\n");
2364 ok(!inside_peb_lock
, "inside_peb_lock should not be set\n");
2368 case DLL_PROCESS_ATTACH
:
2369 trace("dll: %p, DLL_PROCESS_ATTACH, %p\n", hinst
, param
);
2371 ret
= pRtlDllShutdownInProgress();
2372 ok(!ret
, "RtlDllShutdownInProgress returned %d\n", ret
);
2374 /* Set up the FLS slot, if FLS is available */
2379 ret
= pFlsAlloc(&fls_callback
);
2380 ok(ret
!= FLS_OUT_OF_INDEXES
, "FlsAlloc returned %d\n", ret
);
2382 SetLastError(0xdeadbeef);
2383 value
= pFlsGetValue(fls_index
);
2384 ok(!value
, "FlsGetValue returned %p, expected NULL\n", value
);
2385 ok(GetLastError() == ERROR_SUCCESS
, "FlsGetValue failed with error %u\n", GetLastError());
2386 bret
= pFlsSetValue(fls_index
, (void*) 0x31415);
2387 ok(bret
, "FlsSetValue failed\n");
2390 fls_index2
= pFlsAlloc(&fls_callback
);
2391 ok(fls_index2
!= FLS_OUT_OF_INDEXES
, "FlsAlloc returned %d\n", ret
);
2395 case DLL_PROCESS_DETACH
:
2397 DWORD code
, expected_code
, i
;
2398 HANDLE handle
, process
;
2401 LARGE_INTEGER offset
;
2404 trace("dll: %p, DLL_PROCESS_DETACH, %p\n", hinst
, param
);
2406 if (test_dll_phase
== 4 || test_dll_phase
== 5)
2408 ok(0, "dll_entry_point(DLL_PROCESS_DETACH) should not be called\n");
2412 /* The process should already deadlock at this point */
2413 if (test_dll_phase
== 6)
2415 /* In reality, code below never gets executed, probably some other
2416 * code tries to access process heap and deadlocks earlier, even XP
2417 * doesn't call the DLL entry point on process detach either.
2419 HeapLock(GetProcessHeap());
2421 ok(0, "dll_entry_point: process should already deadlock\n");
2424 else if (test_dll_phase
== 7)
2426 EnterCriticalSection(&cs_lock
);
2429 if (test_dll_phase
== 0 || test_dll_phase
== 1 || test_dll_phase
== 3 || test_dll_phase
== 7)
2430 ok(param
!= NULL
, "dll: param %p\n", param
);
2432 ok(!param
, "dll: param %p\n", param
);
2434 if (test_dll_phase
== 0 || test_dll_phase
== 1) expected_code
= 195;
2435 else if (test_dll_phase
== 3) expected_code
= 196;
2436 else if (test_dll_phase
== 7) expected_code
= 199;
2437 else expected_code
= STILL_ACTIVE
;
2439 if (test_dll_phase
== 3)
2441 ret
= pRtlDllShutdownInProgress();
2442 ok(ret
, "RtlDllShutdownInProgress returned %d\n", ret
);
2446 ret
= pRtlDllShutdownInProgress();
2448 /* FIXME: remove once Wine is fixed */
2449 todo_wine_if (!(expected_code
== STILL_ACTIVE
|| expected_code
== 196))
2450 ok(!ret
|| broken(ret
) /* before Vista */, "RtlDllShutdownInProgress returned %d\n", ret
);
2453 /* In the case that the process is terminating, FLS slots should still be accessible, but
2454 * the callback should be already run for this thread and the contents already NULL.
2455 * Note that this is broken for Win2k3, which runs the callbacks *after* the DLL entry
2456 * point has already run.
2458 if (param
&& pFlsGetValue
)
2461 SetLastError(0xdeadbeef);
2462 value
= pFlsGetValue(fls_index
);
2463 ok(broken(value
== (void*) 0x31415) || /* Win2k3 */
2464 value
== NULL
, "FlsGetValue returned %p, expected NULL\n", value
);
2465 ok(GetLastError() == ERROR_SUCCESS
, "FlsGetValue failed with error %u\n", GetLastError());
2466 ok(broken(fls_callback_count
== thread_detach_count
) || /* Win2k3 */
2467 fls_callback_count
== thread_detach_count
+ 1,
2468 "wrong FLS callback count %d, expected %d\n", fls_callback_count
, thread_detach_count
+ 1);
2473 /* Call FlsFree now and run the remaining callbacks from uncleanly terminated threads */
2474 ret
= pFlsFree(fls_index
);
2475 ok(ret
, "FlsFree failed with error %u\n", GetLastError());
2476 fls_index
= FLS_OUT_OF_INDEXES
;
2477 ok(fls_callback_count
== fls_count
,
2478 "wrong FLS callback count %d, expected %d\n", fls_callback_count
, fls_count
);
2481 ok(attached_thread_count
>= 2, "attached thread count should be >= 2\n");
2483 for (i
= 0; i
< attached_thread_count
; i
++)
2485 /* Calling GetExitCodeThread() without waiting for thread termination
2486 * leads to different results due to a race condition.
2488 if (expected_code
!= STILL_ACTIVE
)
2490 ret
= WaitForSingleObject(attached_thread
[i
], 1000);
2491 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %#x\n", ret
);
2493 ret
= GetExitCodeThread(attached_thread
[i
], &code
);
2494 trace("dll: GetExitCodeThread(%u) => %d,%u\n", i
, ret
, code
);
2495 ok(ret
== 1, "GetExitCodeThread returned %d, expected 1\n", ret
);
2496 ok(code
== expected_code
, "expected thread exit code %u, got %u\n", expected_code
, code
);
2499 ret
= WaitForSingleObject(event
, 0);
2500 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
2502 ret
= WaitForSingleObject(mutex
, 0);
2503 if (expected_code
== STILL_ACTIVE
)
2504 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
2506 ok(ret
== WAIT_ABANDONED
, "expected WAIT_ABANDONED, got %#x\n", ret
);
2508 /* semaphore is not abandoned on thread termination */
2509 ret
= WaitForSingleObject(semaphore
, 0);
2510 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
2512 if (expected_code
== STILL_ACTIVE
)
2514 ret
= WaitForSingleObject(attached_thread
[0], 0);
2515 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
2516 ret
= WaitForSingleObject(attached_thread
[1], 0);
2517 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
2521 ret
= WaitForSingleObject(attached_thread
[0], 0);
2522 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %#x\n", ret
);
2523 ret
= WaitForSingleObject(attached_thread
[1], 0);
2524 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %#x\n", ret
);
2527 /* win7 doesn't allow creating a thread during process shutdown but
2528 * earlier Windows versions allow it.
2530 noop_thread_started
= 0;
2531 SetLastError(0xdeadbeef);
2532 handle
= CreateThread(NULL
, 0, noop_thread_proc
, &noop_thread_started
, 0, &ret
);
2535 ok(!handle
|| broken(handle
!= 0) /* before win7 */, "CreateThread should fail\n");
2537 ok(GetLastError() == ERROR_ACCESS_DENIED
, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
2540 ret
= WaitForSingleObject(handle
, 1000);
2541 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
2542 CloseHandle(handle
);
2547 ok(handle
!= 0, "CreateThread error %d\n", GetLastError());
2548 ret
= WaitForSingleObject(handle
, 1000);
2549 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
2550 ok(!noop_thread_started
|| broken(noop_thread_started
) /* XP64 */, "thread shouldn't start yet\n");
2551 CloseHandle(handle
);
2554 SetLastError(0xdeadbeef);
2555 process
= OpenProcess(PROCESS_ALL_ACCESS_NT4
, FALSE
, GetCurrentProcessId());
2556 ok(process
!= NULL
, "OpenProcess error %d\n", GetLastError());
2558 noop_thread_started
= 0;
2559 SetLastError(0xdeadbeef);
2560 handle
= CreateRemoteThread(process
, NULL
, 0, noop_thread_proc
, &noop_thread_started
, 0, &ret
);
2563 ok(!handle
|| broken(handle
!= 0) /* before win7 */, "CreateRemoteThread should fail\n");
2565 ok(GetLastError() == ERROR_ACCESS_DENIED
, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
2568 ret
= WaitForSingleObject(handle
, 1000);
2569 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
2570 CloseHandle(handle
);
2575 ok(handle
!= 0, "CreateRemoteThread error %d\n", GetLastError());
2576 ret
= WaitForSingleObject(handle
, 1000);
2577 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
2578 ok(!noop_thread_started
|| broken(noop_thread_started
) /* XP64 */, "thread shouldn't start yet\n");
2579 CloseHandle(handle
);
2582 SetLastError(0xdeadbeef);
2583 handle
= CreateFileMappingW(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
2584 ok(handle
!= 0, "CreateFileMapping error %d\n", GetLastError());
2586 offset
.u
.LowPart
= 0;
2587 offset
.u
.HighPart
= 0;
2590 ret
= pNtMapViewOfSection(handle
, process
, &addr
, 0, 0, &offset
,
2591 &size
, 1 /* ViewShare */, 0, PAGE_READONLY
);
2592 ok(ret
== STATUS_SUCCESS
, "NtMapViewOfSection error %#x\n", ret
);
2593 ret
= pNtUnmapViewOfSection(process
, addr
);
2594 ok(ret
== STATUS_SUCCESS
, "NtUnmapViewOfSection error %#x\n", ret
);
2596 CloseHandle(handle
);
2597 CloseHandle(process
);
2599 handle
= GetModuleHandleA("winver.exe");
2600 ok(!handle
, "winver.exe shouldn't be loaded yet\n");
2601 SetLastError(0xdeadbeef);
2602 handle
= LoadLibraryA("winver.exe");
2603 ok(handle
!= 0, "LoadLibrary error %d\n", GetLastError());
2604 SetLastError(0xdeadbeef);
2605 ret
= FreeLibrary(handle
);
2606 ok(ret
, "FreeLibrary error %d\n", GetLastError());
2607 handle
= GetModuleHandleA("winver.exe");
2609 ok(handle
!= 0, "winver.exe should not be unloaded\n");
2612 ok(!handle
|| broken(handle
!= 0) /* before win7 */, "winver.exe should be unloaded\n");
2614 SetLastError(0xdeadbeef);
2615 ret
= WaitForDebugEvent(&de
, 0);
2616 ok(!ret
, "WaitForDebugEvent should fail\n");
2617 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
2619 SetLastError(0xdeadbeef);
2620 ret
= DebugActiveProcess(GetCurrentProcessId());
2621 ok(!ret
, "DebugActiveProcess should fail\n");
2622 ok(GetLastError() == ERROR_ACCESS_DENIED
, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
2624 SetLastError(0xdeadbeef);
2625 ret
= WaitForDebugEvent(&de
, 0);
2626 ok(!ret
, "WaitForDebugEvent should fail\n");
2627 ok(GetLastError() == ERROR_SEM_TIMEOUT
, "expected ERROR_SEM_TIMEOUT, got %d\n", GetLastError());
2629 if (test_dll_phase
== 2)
2631 trace("dll: call ExitProcess()\n");
2632 *child_failures
= winetest_get_failures();
2635 trace("dll: %p, DLL_PROCESS_DETACH, %p => DONE\n", hinst
, param
);
2638 case DLL_THREAD_ATTACH
:
2639 trace("dll: %p, DLL_THREAD_ATTACH, %p\n", hinst
, param
);
2643 ret
= pRtlDllShutdownInProgress();
2644 ok(!ret
, "RtlDllShutdownInProgress returned %d\n", ret
);
2646 if (attached_thread_count
< MAX_COUNT
)
2648 DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &attached_thread
[attached_thread_count
],
2649 0, TRUE
, DUPLICATE_SAME_ACCESS
);
2650 attached_thread_count
++;
2653 /* Make sure the FLS slot is empty, if FLS is available */
2658 SetLastError(0xdeadbeef);
2659 value
= pFlsGetValue(fls_index
);
2660 ok(!value
, "FlsGetValue returned %p, expected NULL\n", value
);
2661 ok(GetLastError() == ERROR_SUCCESS
, "FlsGetValue failed with error %u\n", GetLastError());
2662 ret
= pFlsSetValue(fls_index
, (void*) 0x31415);
2663 ok(ret
, "FlsSetValue failed\n");
2668 case DLL_THREAD_DETACH
:
2669 trace("dll: %p, DLL_THREAD_DETACH, %p\n", hinst
, param
);
2671 thread_detach_count
++;
2673 ret
= pRtlDllShutdownInProgress();
2674 /* win7 doesn't allow creating a thread during process shutdown but
2675 * earlier Windows versions allow it. In that case DLL_THREAD_DETACH is
2676 * sent on thread exit, but DLL_THREAD_ATTACH is never received.
2678 if (noop_thread_started
)
2679 ok(ret
, "RtlDllShutdownInProgress returned %d\n", ret
);
2681 ok(!ret
, "RtlDllShutdownInProgress returned %d\n", ret
);
2683 /* FLS data should already be destroyed, if FLS is available.
2684 * Note that this is broken for Win2k3, which runs the callbacks *after* the DLL entry
2685 * point has already run.
2687 if (pFlsGetValue
&& fls_index
!= FLS_OUT_OF_INDEXES
)
2689 unsigned int index
, count
;
2693 SetLastError(0xdeadbeef);
2694 value
= pFlsGetValue(fls_index
);
2695 ok(broken(value
== (void*) 0x31415) || /* Win2k3 */
2696 !value
, "FlsGetValue returned %p, expected NULL\n", value
);
2697 ok(GetLastError() == ERROR_SUCCESS
, "FlsGetValue failed with error %u\n", GetLastError());
2699 bret
= pFlsSetValue(fls_index2
, (void*) 0x31415);
2700 ok(bret
, "FlsSetValue failed\n");
2704 count
= check_linked_list(fls_list_head
, &NtCurrentTeb()->FlsSlots
->fls_list_entry
, &index
);
2705 ok(count
<= thread_count
, "Got unexpected count %u, thread_count %u.\n", count
, thread_count
);
2706 ok(index
== ~0, "Got unexpected index %u.\n", index
);
2712 trace("dll: %p, %d, %p\n", hinst
, reason
, param
);
2716 *child_failures
= winetest_get_failures();
2721 static void child_process(const char *dll_name
, DWORD target_offset
)
2724 DWORD ret
, dummy
, i
, code
, expected_code
;
2725 HANDLE file
, thread
, process
;
2727 struct PROCESS_BASIC_INFORMATION_PRIVATE pbi
;
2730 trace("phase %d: writing %p at %#x\n", test_dll_phase
, dll_entry_point
, target_offset
);
2734 fls_list_head
= NtCurrentTeb()->Peb
->FlsListHead
.Flink
? &NtCurrentTeb()->Peb
->FlsListHead
2735 : NtCurrentTeb()->FlsSlots
->fls_list_entry
.Flink
;
2738 SetLastError(0xdeadbeef);
2739 mutex
= CreateMutexW(NULL
, FALSE
, NULL
);
2740 ok(mutex
!= 0, "CreateMutex error %d\n", GetLastError());
2742 SetLastError(0xdeadbeef);
2743 semaphore
= CreateSemaphoreW(NULL
, 1, 1, NULL
);
2744 ok(semaphore
!= 0, "CreateSemaphore error %d\n", GetLastError());
2746 SetLastError(0xdeadbeef);
2747 event
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
2748 ok(event
!= 0, "CreateEvent error %d\n", GetLastError());
2750 SetLastError(0xdeadbeef);
2751 loader_lock_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
2752 ok(loader_lock_event
!= 0, "CreateEvent error %d\n", GetLastError());
2754 SetLastError(0xdeadbeef);
2755 peb_lock_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
2756 ok(peb_lock_event
!= 0, "CreateEvent error %d\n", GetLastError());
2758 SetLastError(0xdeadbeef);
2759 heap_lock_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
2760 ok(heap_lock_event
!= 0, "CreateEvent error %d\n", GetLastError());
2762 InitializeCriticalSection(&cs_lock
);
2763 SetLastError(0xdeadbeef);
2764 cs_lock_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
2765 ok(cs_lock_event
!= 0, "CreateEvent error %d\n", GetLastError());
2767 SetLastError(0xdeadbeef);
2768 ack_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
2769 ok(ack_event
!= 0, "CreateEvent error %d\n", GetLastError());
2771 file
= CreateFileA(dll_name
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
2772 if (file
== INVALID_HANDLE_VALUE
)
2774 ok(0, "could not open %s\n", dll_name
);
2777 SetFilePointer(file
, target_offset
, NULL
, FILE_BEGIN
);
2778 SetLastError(0xdeadbeef);
2779 target
= dll_entry_point
;
2780 ret
= WriteFile(file
, &target
, sizeof(target
), &dummy
, NULL
);
2781 ok(ret
, "WriteFile error %d\n", GetLastError());
2784 SetLastError(0xdeadbeef);
2785 hmod
= LoadLibraryA(dll_name
);
2786 ok(hmod
!= 0, "LoadLibrary error %d\n", GetLastError());
2788 SetLastError(0xdeadbeef);
2789 stop_event
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
2790 ok(stop_event
!= 0, "CreateEvent error %d\n", GetLastError());
2792 SetLastError(0xdeadbeef);
2793 thread
= CreateThread(NULL
, 0, mutex_thread_proc
, event
, 0, &dummy
);
2794 ok(thread
!= 0, "CreateThread error %d\n", GetLastError());
2795 WaitForSingleObject(event
, 3000);
2796 CloseHandle(thread
);
2800 SetLastError(0xdeadbeef);
2801 thread
= CreateThread(NULL
, 0, semaphore_thread_proc
, event
, 0, &dummy
);
2802 ok(thread
!= 0, "CreateThread error %d\n", GetLastError());
2803 WaitForSingleObject(event
, 3000);
2804 CloseHandle(thread
);
2809 ok(attached_thread_count
== 2, "attached thread count should be 2\n");
2810 for (i
= 0; i
< attached_thread_count
; i
++)
2812 ret
= GetExitCodeThread(attached_thread
[i
], &code
);
2813 trace("child: GetExitCodeThread(%u) => %d,%u\n", i
, ret
, code
);
2814 ok(ret
== 1, "GetExitCodeThread returned %d, expected 1\n", ret
);
2815 ok(code
== STILL_ACTIVE
, "expected thread exit code STILL_ACTIVE, got %u\n", code
);
2818 ret
= WaitForSingleObject(attached_thread
[0], 0);
2819 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
2820 ret
= WaitForSingleObject(attached_thread
[1], 0);
2821 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
2823 ret
= WaitForSingleObject(event
, 0);
2824 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
2825 ret
= WaitForSingleObject(mutex
, 0);
2826 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
2827 ret
= WaitForSingleObject(semaphore
, 0);
2828 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
2830 ret
= pRtlDllShutdownInProgress();
2831 ok(!ret
, "RtlDllShutdownInProgress returned %d\n", ret
);
2833 SetLastError(0xdeadbeef);
2834 process
= OpenProcess(PROCESS_ALL_ACCESS_NT4
, FALSE
, GetCurrentProcessId());
2835 ok(process
!= NULL
, "OpenProcess error %d\n", GetLastError());
2837 SetLastError(0xdeadbeef);
2838 ret
= TerminateProcess(0, 195);
2839 ok(!ret
, "TerminateProcess(0) should fail\n");
2840 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
2845 ret
= pNtSetInformationProcess(process
, ProcessAffinityMask
, &affinity
, sizeof(affinity
));
2846 ok(!ret
, "NtSetInformationProcess error %#x\n", ret
);
2848 switch (test_dll_phase
)
2851 ret
= pRtlDllShutdownInProgress();
2852 ok(!ret
, "RtlDllShutdownInProgress returned %d\n", ret
);
2854 trace("call NtTerminateProcess(0, 195)\n");
2855 ret
= pNtTerminateProcess(0, 195);
2856 ok(!ret
, "NtTerminateProcess error %#x\n", ret
);
2858 memset(&pbi
, 0, sizeof(pbi
));
2859 ret
= pNtQueryInformationProcess(process
, ProcessBasicInformation
, &pbi
, sizeof(pbi
), NULL
);
2860 ok(!ret
, "NtQueryInformationProcess error %#x\n", ret
);
2861 ok(pbi
.ExitStatus
== STILL_ACTIVE
|| pbi
.ExitStatus
== 195,
2862 "expected STILL_ACTIVE, got %lu\n", pbi
.ExitStatus
);
2864 ret
= pNtSetInformationProcess(process
, ProcessAffinityMask
, &affinity
, sizeof(affinity
));
2865 ok(!ret
, "NtSetInformationProcess error %#x\n", ret
);
2867 ret
= pRtlDllShutdownInProgress();
2868 ok(!ret
, "RtlDllShutdownInProgress returned %d\n", ret
);
2870 hmod
= GetModuleHandleA(dll_name
);
2871 ok(hmod
!= 0, "DLL should not be unloaded\n");
2873 SetLastError(0xdeadbeef);
2874 thread
= CreateThread(NULL
, 0, noop_thread_proc
, &dummy
, 0, &ret
);
2875 ok(!thread
|| broken(thread
!= 0) /* before win7 */, "CreateThread should fail\n");
2877 ok(GetLastError() == ERROR_ACCESS_DENIED
, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
2880 ret
= WaitForSingleObject(thread
, 1000);
2881 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %#x\n", ret
);
2882 CloseHandle(thread
);
2885 trace("call LdrShutdownProcess()\n");
2886 pLdrShutdownProcess();
2888 ret
= pRtlDllShutdownInProgress();
2889 ok(ret
, "RtlDllShutdownInProgress returned %d\n", ret
);
2891 hmod
= GetModuleHandleA(dll_name
);
2892 ok(hmod
!= 0, "DLL should not be unloaded\n");
2894 memset(&pbi
, 0, sizeof(pbi
));
2895 ret
= pNtQueryInformationProcess(process
, ProcessBasicInformation
, &pbi
, sizeof(pbi
), NULL
);
2896 ok(!ret
, "NtQueryInformationProcess error %#x\n", ret
);
2897 ok(pbi
.ExitStatus
== STILL_ACTIVE
|| pbi
.ExitStatus
== 195,
2898 "expected STILL_ACTIVE, got %lu\n", pbi
.ExitStatus
);
2900 ret
= pNtSetInformationProcess(process
, ProcessAffinityMask
, &affinity
, sizeof(affinity
));
2901 ok(!ret
, "NtSetInformationProcess error %#x\n", ret
);
2904 case 1: /* normal ExitProcess */
2905 ret
= pRtlDllShutdownInProgress();
2906 ok(!ret
, "RtlDllShutdownInProgress returned %d\n", ret
);
2909 case 2: /* ExitProcess will be called by the PROCESS_DETACH handler */
2910 ret
= pRtlDllShutdownInProgress();
2911 ok(!ret
, "RtlDllShutdownInProgress returned %d\n", ret
);
2913 trace("call FreeLibrary(%p)\n", hmod
);
2914 SetLastError(0xdeadbeef);
2915 ret
= FreeLibrary(hmod
);
2916 ok(ret
, "FreeLibrary error %d\n", GetLastError());
2917 hmod
= GetModuleHandleA(dll_name
);
2918 ok(!hmod
, "DLL should be unloaded\n");
2920 if (test_dll_phase
== 2)
2921 ok(0, "FreeLibrary+ExitProcess should never return\n");
2923 ret
= pRtlDllShutdownInProgress();
2924 ok(!ret
, "RtlDllShutdownInProgress returned %d\n", ret
);
2929 trace("signalling thread exit\n");
2930 SetEvent(stop_event
);
2934 trace("setting loader_lock_event\n");
2935 SetEvent(loader_lock_event
);
2936 WaitForSingleObject(ack_event
, 1000);
2937 ok(inside_loader_lock
!= 0, "inside_loader_lock is not set\n");
2939 /* calling NtTerminateProcess should not cause a deadlock */
2940 trace("call NtTerminateProcess(0, 198)\n");
2941 ret
= pNtTerminateProcess(0, 198);
2942 ok(!ret
, "NtTerminateProcess error %#x\n", ret
);
2944 *child_failures
= winetest_get_failures();
2946 /* Windows fails to release loader lock acquired from another thread,
2947 * so the LdrUnlockLoaderLock call fails here and ExitProcess deadlocks
2948 * later on, so NtTerminateProcess is used instead.
2950 trace("call NtTerminateProcess(GetCurrentProcess(), 198)\n");
2951 pNtTerminateProcess(GetCurrentProcess(), 198);
2952 ok(0, "NtTerminateProcess should not return\n");
2956 trace("setting peb_lock_event\n");
2957 SetEvent(peb_lock_event
);
2958 WaitForSingleObject(ack_event
, 1000);
2959 ok(inside_peb_lock
!= 0, "inside_peb_lock is not set\n");
2961 *child_failures
= winetest_get_failures();
2963 /* calling ExitProcess should cause a deadlock */
2964 trace("call ExitProcess(198)\n");
2966 ok(0, "ExitProcess should not return\n");
2970 trace("setting heap_lock_event\n");
2971 SetEvent(heap_lock_event
);
2972 WaitForSingleObject(ack_event
, 1000);
2973 ok(inside_heap_lock
!= 0, "inside_heap_lock is not set\n");
2975 *child_failures
= winetest_get_failures();
2977 /* calling ExitProcess should cause a deadlock */
2978 trace("call ExitProcess(1)\n");
2980 ok(0, "ExitProcess should not return\n");
2984 trace("setting cs_lock_event\n");
2985 SetEvent(cs_lock_event
);
2986 WaitForSingleObject(ack_event
, 1000);
2987 ok(inside_cs_lock
!= 0, "inside_cs_lock is not set\n");
2989 *child_failures
= winetest_get_failures();
2991 /* calling ExitProcess should not cause a deadlock */
2992 trace("call ExitProcess(199)\n");
2994 ok(0, "ExitProcess should not return\n");
3002 if (test_dll_phase
== 0) expected_code
= 195;
3003 else if (test_dll_phase
== 3) expected_code
= 196;
3004 else if (test_dll_phase
== 4) expected_code
= 198;
3005 else expected_code
= STILL_ACTIVE
;
3007 if (expected_code
== STILL_ACTIVE
)
3009 ret
= WaitForSingleObject(attached_thread
[0], 100);
3010 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
3011 ret
= WaitForSingleObject(attached_thread
[1], 100);
3012 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
3016 ret
= WaitForSingleObject(attached_thread
[0], 2000);
3017 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %#x\n", ret
);
3018 ret
= WaitForSingleObject(attached_thread
[1], 2000);
3019 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %#x\n", ret
);
3022 for (i
= 0; i
< attached_thread_count
; i
++)
3024 ret
= GetExitCodeThread(attached_thread
[i
], &code
);
3025 trace("child: GetExitCodeThread(%u) => %d,%u\n", i
, ret
, code
);
3026 ok(ret
== 1, "GetExitCodeThread returned %d, expected 1\n", ret
);
3027 ok(code
== expected_code
, "expected thread exit code %u, got %u\n", expected_code
, code
);
3030 *child_failures
= winetest_get_failures();
3032 trace("call ExitProcess(195)\n");
3036 static void test_ExitProcess(void)
3038 #if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
3039 #include "pshpack1.h"
3041 static struct section_data
3046 } section_data
= { { 0x48,0xb8 }, dll_entry_point
, { 0xff,0xe0 } };
3047 #elif defined(__i386__)
3048 static struct section_data
3053 } section_data
= { 0xb8, dll_entry_point
, { 0xff,0xe0 } };
3054 #elif defined(__aarch64__)
3055 static struct section_data
3057 DWORD ldr
; /* ldr x0,target */
3058 DWORD br
; /* br x0 */
3060 } section_data
= { 0x58000040, 0xd61f0000, dll_entry_point
};
3062 #include "poppack.h"
3063 DWORD dummy
, file_align
;
3064 HANDLE file
, thread
, process
, hmap
, hmap_dup
;
3065 char temp_path
[MAX_PATH
], dll_name
[MAX_PATH
], cmdline
[MAX_PATH
* 2];
3066 DWORD ret
, target_offset
, old_prot
;
3067 char **argv
, buf
[256];
3068 PROCESS_INFORMATION pi
;
3069 STARTUPINFOA si
= { sizeof(si
) };
3071 struct PROCESS_BASIC_INFORMATION_PRIVATE pbi
;
3072 MEMORY_BASIC_INFORMATION mbi
;
3075 LARGE_INTEGER offset
;
3077 IMAGE_NT_HEADERS nt_header
;
3079 if (!pRtlDllShutdownInProgress
)
3081 win_skip("RtlDllShutdownInProgress is not available on this platform (XP+)\n");
3084 if (!pNtQueryInformationProcess
|| !pNtSetInformationProcess
)
3086 win_skip("NtQueryInformationProcess/NtSetInformationProcess are not available on this platform\n");
3089 if (!pNtAllocateVirtualMemory
|| !pNtFreeVirtualMemory
)
3091 win_skip("NtAllocateVirtualMemory/NtFreeVirtualMemory are not available on this platform\n");
3095 /* prevent displaying of the "Unable to load this DLL" message box */
3096 SetErrorMode(SEM_FAILCRITICALERRORS
);
3098 GetTempPathA(MAX_PATH
, temp_path
);
3099 GetTempFileNameA(temp_path
, "ldr", 0, dll_name
);
3101 /*trace("creating %s\n", dll_name);*/
3102 file
= CreateFileA(dll_name
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
3103 if (file
== INVALID_HANDLE_VALUE
)
3105 ok(0, "could not create %s\n", dll_name
);
3109 SetLastError(0xdeadbeef);
3110 ret
= WriteFile(file
, &dos_header
, sizeof(dos_header
), &dummy
, NULL
);
3111 ok(ret
, "WriteFile error %d\n", GetLastError());
3113 nt_header
= nt_header_template
;
3114 nt_header
.FileHeader
.NumberOfSections
= 1;
3115 nt_header
.FileHeader
.SizeOfOptionalHeader
= sizeof(IMAGE_OPTIONAL_HEADER
);
3116 nt_header
.FileHeader
.Characteristics
= IMAGE_FILE_EXECUTABLE_IMAGE
| IMAGE_FILE_DLL
| IMAGE_FILE_RELOCS_STRIPPED
;
3118 nt_header
.OptionalHeader
.AddressOfEntryPoint
= 0x1000;
3119 nt_header
.OptionalHeader
.SectionAlignment
= 0x1000;
3120 nt_header
.OptionalHeader
.FileAlignment
= 0x200;
3121 nt_header
.OptionalHeader
.SizeOfImage
= sizeof(dos_header
) + sizeof(nt_header
) + sizeof(IMAGE_SECTION_HEADER
) + 0x1000;
3122 nt_header
.OptionalHeader
.SizeOfHeaders
= sizeof(dos_header
) + sizeof(nt_header
) + sizeof(IMAGE_SECTION_HEADER
);
3123 SetLastError(0xdeadbeef);
3124 ret
= WriteFile(file
, &nt_header
, sizeof(DWORD
) + sizeof(IMAGE_FILE_HEADER
), &dummy
, NULL
);
3125 ok(ret
, "WriteFile error %d\n", GetLastError());
3126 SetLastError(0xdeadbeef);
3127 ret
= WriteFile(file
, &nt_header
.OptionalHeader
, sizeof(IMAGE_OPTIONAL_HEADER
), &dummy
, NULL
);
3128 ok(ret
, "WriteFile error %d\n", GetLastError());
3130 section
.SizeOfRawData
= sizeof(section_data
);
3131 section
.PointerToRawData
= nt_header
.OptionalHeader
.FileAlignment
;
3132 section
.VirtualAddress
= nt_header
.OptionalHeader
.SectionAlignment
;
3133 section
.Misc
.VirtualSize
= sizeof(section_data
);
3134 section
.Characteristics
= IMAGE_SCN_CNT_CODE
| IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_EXECUTE
;
3135 SetLastError(0xdeadbeef);
3136 ret
= WriteFile(file
, §ion
, sizeof(section
), &dummy
, NULL
);
3137 ok(ret
, "WriteFile error %d\n", GetLastError());
3139 file_align
= nt_header
.OptionalHeader
.FileAlignment
- nt_header
.OptionalHeader
.SizeOfHeaders
;
3140 assert(file_align
< sizeof(filler
));
3141 SetLastError(0xdeadbeef);
3142 ret
= WriteFile(file
, filler
, file_align
, &dummy
, NULL
);
3143 ok(ret
, "WriteFile error %d\n", GetLastError());
3145 target_offset
= SetFilePointer(file
, 0, NULL
, FILE_CURRENT
) + FIELD_OFFSET(struct section_data
, target
);
3148 SetLastError(0xdeadbeef);
3149 ret
= WriteFile(file
, §ion_data
, sizeof(section_data
), &dummy
, NULL
);
3150 ok(ret
, "WriteFile error %d\n", GetLastError());
3154 winetest_get_mainargs(&argv
);
3157 *child_failures
= -1;
3158 sprintf(cmdline
, "\"%s\" loader %s %u 0", argv
[0], dll_name
, target_offset
);
3159 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
3160 ok(ret
, "CreateProcess(%s) error %d\n", cmdline
, GetLastError());
3161 ret
= WaitForSingleObject(pi
.hProcess
, 10000);
3162 ok(ret
== WAIT_OBJECT_0
, "child process failed to terminate\n");
3163 if (ret
!= WAIT_OBJECT_0
) TerminateProcess(pi
.hProcess
, 0);
3164 GetExitCodeProcess(pi
.hProcess
, &ret
);
3165 ok(ret
== 195, "expected exit code 195, got %u\n", ret
);
3166 if (*child_failures
)
3168 trace("%d failures in child process\n", *child_failures
);
3169 winetest_add_failures(*child_failures
);
3171 CloseHandle(pi
.hThread
);
3172 CloseHandle(pi
.hProcess
);
3175 *child_failures
= -1;
3176 sprintf(cmdline
, "\"%s\" loader %s %u 1", argv
[0], dll_name
, target_offset
);
3177 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
3178 ok(ret
, "CreateProcess(%s) error %d\n", cmdline
, GetLastError());
3179 ret
= WaitForSingleObject(pi
.hProcess
, 10000);
3180 ok(ret
== WAIT_OBJECT_0
, "child process failed to terminate\n");
3181 if (ret
!= WAIT_OBJECT_0
) TerminateProcess(pi
.hProcess
, 0);
3182 GetExitCodeProcess(pi
.hProcess
, &ret
);
3183 ok(ret
== 195, "expected exit code 195, got %u\n", ret
);
3184 if (*child_failures
)
3186 trace("%d failures in child process\n", *child_failures
);
3187 winetest_add_failures(*child_failures
);
3189 CloseHandle(pi
.hThread
);
3190 CloseHandle(pi
.hProcess
);
3193 *child_failures
= -1;
3194 sprintf(cmdline
, "\"%s\" loader %s %u 2", argv
[0], dll_name
, target_offset
);
3195 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
3196 ok(ret
, "CreateProcess(%s) error %d\n", cmdline
, GetLastError());
3197 ret
= WaitForSingleObject(pi
.hProcess
, 10000);
3198 ok(ret
== WAIT_OBJECT_0
, "child process failed to terminate\n");
3199 if (ret
!= WAIT_OBJECT_0
) TerminateProcess(pi
.hProcess
, 0);
3200 GetExitCodeProcess(pi
.hProcess
, &ret
);
3201 ok(ret
== 197, "expected exit code 197, got %u\n", ret
);
3202 if (*child_failures
)
3204 trace("%d failures in child process\n", *child_failures
);
3205 winetest_add_failures(*child_failures
);
3207 CloseHandle(pi
.hThread
);
3208 CloseHandle(pi
.hProcess
);
3211 *child_failures
= -1;
3212 sprintf(cmdline
, "\"%s\" loader %s %u 3", argv
[0], dll_name
, target_offset
);
3213 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
3214 ok(ret
, "CreateProcess(%s) error %d\n", cmdline
, GetLastError());
3215 ret
= WaitForSingleObject(pi
.hProcess
, 10000);
3216 ok(ret
== WAIT_OBJECT_0
, "child process failed to terminate\n");
3217 if (ret
!= WAIT_OBJECT_0
) TerminateProcess(pi
.hProcess
, 0);
3218 GetExitCodeProcess(pi
.hProcess
, &ret
);
3219 ok(ret
== 195, "expected exit code 195, got %u\n", ret
);
3220 if (*child_failures
)
3222 trace("%d failures in child process\n", *child_failures
);
3223 winetest_add_failures(*child_failures
);
3225 CloseHandle(pi
.hThread
);
3226 CloseHandle(pi
.hProcess
);
3229 if (pLdrLockLoaderLock
&& pLdrUnlockLoaderLock
)
3231 *child_failures
= -1;
3232 sprintf(cmdline
, "\"%s\" loader %s %u 4", argv
[0], dll_name
, target_offset
);
3233 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
3234 ok(ret
, "CreateProcess(%s) error %d\n", cmdline
, GetLastError());
3235 ret
= WaitForSingleObject(pi
.hProcess
, 10000);
3236 ok(ret
== WAIT_OBJECT_0
, "child process failed to terminate\n");
3237 if (ret
!= WAIT_OBJECT_0
) TerminateProcess(pi
.hProcess
, 0);
3238 GetExitCodeProcess(pi
.hProcess
, &ret
);
3239 ok(ret
== 198, "expected exit code 198, got %u\n", ret
);
3240 if (*child_failures
)
3242 trace("%d failures in child process\n", *child_failures
);
3243 winetest_add_failures(*child_failures
);
3245 CloseHandle(pi
.hThread
);
3246 CloseHandle(pi
.hProcess
);
3249 win_skip("LdrLockLoaderLock/LdrUnlockLoaderLock are not available on this platform\n");
3252 if (pRtlAcquirePebLock
&& pRtlReleasePebLock
)
3254 *child_failures
= -1;
3255 sprintf(cmdline
, "\"%s\" loader %s %u 5", argv
[0], dll_name
, target_offset
);
3256 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
3257 ok(ret
, "CreateProcess(%s) error %d\n", cmdline
, GetLastError());
3258 ret
= WaitForSingleObject(pi
.hProcess
, 5000);
3259 ok(ret
== WAIT_TIMEOUT
, "child process should fail to terminate\n");
3260 if (ret
!= WAIT_OBJECT_0
)
3262 trace("terminating child process\n");
3263 TerminateProcess(pi
.hProcess
, 199);
3265 ret
= WaitForSingleObject(pi
.hProcess
, 1000);
3266 ok(ret
== WAIT_OBJECT_0
, "child process failed to terminate\n");
3267 GetExitCodeProcess(pi
.hProcess
, &ret
);
3268 ok(ret
== 199, "expected exit code 199, got %u\n", ret
);
3269 if (*child_failures
)
3271 trace("%d failures in child process\n", *child_failures
);
3272 winetest_add_failures(*child_failures
);
3274 CloseHandle(pi
.hThread
);
3275 CloseHandle(pi
.hProcess
);
3278 win_skip("RtlAcquirePebLock/RtlReleasePebLock are not available on this platform\n");
3281 *child_failures
= -1;
3282 sprintf(cmdline
, "\"%s\" loader %s %u 6", argv
[0], dll_name
, target_offset
);
3283 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
3284 ok(ret
, "CreateProcess(%s) error %d\n", cmdline
, GetLastError());
3285 ret
= WaitForSingleObject(pi
.hProcess
, 5000);
3287 ok(ret
== WAIT_TIMEOUT
|| broken(ret
== WAIT_OBJECT_0
) /* XP */, "child process should fail to terminate\n");
3288 if (ret
!= WAIT_OBJECT_0
)
3290 trace("terminating child process\n");
3291 TerminateProcess(pi
.hProcess
, 201);
3293 ret
= WaitForSingleObject(pi
.hProcess
, 1000);
3294 ok(ret
== WAIT_OBJECT_0
, "child process failed to terminate\n");
3295 GetExitCodeProcess(pi
.hProcess
, &ret
);
3297 ok(ret
== 201 || broken(ret
== 1) /* XP */, "expected exit code 201, got %u\n", ret
);
3298 if (*child_failures
)
3300 trace("%d failures in child process\n", *child_failures
);
3301 winetest_add_failures(*child_failures
);
3303 CloseHandle(pi
.hThread
);
3304 CloseHandle(pi
.hProcess
);
3307 *child_failures
= -1;
3308 sprintf(cmdline
, "\"%s\" loader %s %u 7", argv
[0], dll_name
, target_offset
);
3309 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
3310 ok(ret
, "CreateProcess(%s) error %d\n", cmdline
, GetLastError());
3311 ret
= WaitForSingleObject(pi
.hProcess
, 5000);
3312 ok(ret
== WAIT_OBJECT_0
, "child process failed to terminate\n");
3313 if (ret
!= WAIT_OBJECT_0
)
3315 trace("terminating child process\n");
3316 TerminateProcess(pi
.hProcess
, 199);
3318 ret
= WaitForSingleObject(pi
.hProcess
, 1000);
3319 ok(ret
== WAIT_OBJECT_0
, "child process failed to terminate\n");
3320 GetExitCodeProcess(pi
.hProcess
, &ret
);
3321 ok(ret
== 199, "expected exit code 199, got %u\n", ret
);
3322 if (*child_failures
)
3324 trace("%d failures in child process\n", *child_failures
);
3325 winetest_add_failures(*child_failures
);
3327 CloseHandle(pi
.hThread
);
3328 CloseHandle(pi
.hProcess
);
3330 /* test remote process termination */
3331 SetLastError(0xdeadbeef);
3332 ret
= CreateProcessA(argv
[0], NULL
, NULL
, NULL
, FALSE
, CREATE_SUSPENDED
, NULL
, NULL
, &si
, &pi
);
3333 ok(ret
, "CreateProcess(%s) error %d\n", argv
[0], GetLastError());
3335 SetLastError(0xdeadbeef);
3336 addr
= VirtualAllocEx(pi
.hProcess
, NULL
, 4096, MEM_COMMIT
, PAGE_READWRITE
);
3337 ok(addr
!= NULL
, "VirtualAllocEx error %d\n", GetLastError());
3338 SetLastError(0xdeadbeef);
3339 ret
= VirtualProtectEx(pi
.hProcess
, addr
, 4096, PAGE_READONLY
, &old_prot
);
3340 ok(ret
, "VirtualProtectEx error %d\n", GetLastError());
3341 ok(old_prot
== PAGE_READWRITE
, "expected PAGE_READWRITE, got %#x\n", old_prot
);
3342 SetLastError(0xdeadbeef);
3343 size
= VirtualQueryEx(pi
.hProcess
, NULL
, &mbi
, sizeof(mbi
));
3344 ok(size
== sizeof(mbi
), "VirtualQueryEx error %d\n", GetLastError());
3346 SetLastError(0xdeadbeef);
3347 ret
= ReadProcessMemory(pi
.hProcess
, addr
, buf
, 4, &size
);
3348 ok(ret
, "ReadProcessMemory error %d\n", GetLastError());
3349 ok(size
== 4, "expected 4, got %lu\n", size
);
3351 SetLastError(0xdeadbeef);
3352 hmap
= CreateFileMappingW(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
3353 ok(hmap
!= 0, "CreateFileMapping error %d\n", GetLastError());
3355 SetLastError(0xdeadbeef);
3356 ret
= DuplicateHandle(GetCurrentProcess(), hmap
, pi
.hProcess
, &hmap_dup
,
3357 0, FALSE
, DUPLICATE_SAME_ACCESS
);
3358 ok(ret
, "DuplicateHandle error %d\n", GetLastError());
3360 offset
.u
.LowPart
= 0;
3361 offset
.u
.HighPart
= 0;
3364 ret
= pNtMapViewOfSection(hmap
, pi
.hProcess
, &addr
, 0, 0, &offset
,
3365 &size
, 1 /* ViewShare */, 0, PAGE_READONLY
);
3366 ok(!ret
, "NtMapViewOfSection error %#x\n", ret
);
3367 ret
= pNtUnmapViewOfSection(pi
.hProcess
, addr
);
3368 ok(!ret
, "NtUnmapViewOfSection error %#x\n", ret
);
3370 SetLastError(0xdeadbeef);
3371 thread
= CreateRemoteThread(pi
.hProcess
, NULL
, 0, (void *)0xdeadbeef, NULL
, CREATE_SUSPENDED
, &ret
);
3372 ok(thread
!= 0, "CreateRemoteThread error %d\n", GetLastError());
3373 SetLastError(0xdeadbeef);
3374 ctx
.ContextFlags
= CONTEXT_INTEGER
;
3375 ret
= GetThreadContext(thread
, &ctx
);
3376 ok(ret
, "GetThreadContext error %d\n", GetLastError());
3377 SetLastError(0xdeadbeef);
3378 ctx
.ContextFlags
= CONTEXT_INTEGER
;
3379 ret
= SetThreadContext(thread
, &ctx
);
3380 ok(ret
, "SetThreadContext error %d\n", GetLastError());
3381 SetLastError(0xdeadbeef);
3382 ret
= SetThreadPriority(thread
, 0);
3383 ok(ret
, "SetThreadPriority error %d\n", GetLastError());
3385 SetLastError(0xdeadbeef);
3386 ret
= TerminateThread(thread
, 199);
3387 ok(ret
, "TerminateThread error %d\n", GetLastError());
3388 /* Calling GetExitCodeThread() without waiting for thread termination
3389 * leads to different results due to a race condition.
3391 ret
= WaitForSingleObject(thread
, 1000);
3392 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed: %x\n", ret
);
3393 GetExitCodeThread(thread
, &ret
);
3394 ok(ret
== 199, "expected exit code 199, got %u\n", ret
);
3396 SetLastError(0xdeadbeef);
3397 ret
= TerminateProcess(pi
.hProcess
, 198);
3398 ok(ret
, "TerminateProcess error %d\n", GetLastError());
3399 /* Checking process state without waiting for process termination
3400 * leads to different results due to a race condition.
3402 ret
= WaitForSingleObject(pi
.hProcess
, 1000);
3403 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed: %x\n", ret
);
3405 SetLastError(0xdeadbeef);
3406 process
= OpenProcess(PROCESS_ALL_ACCESS_NT4
, FALSE
, pi
.dwProcessId
);
3407 ok(process
!= NULL
, "OpenProcess error %d\n", GetLastError());
3408 CloseHandle(process
);
3410 memset(&pbi
, 0, sizeof(pbi
));
3411 ret
= pNtQueryInformationProcess(pi
.hProcess
, ProcessBasicInformation
, &pbi
, sizeof(pbi
), NULL
);
3412 ok(!ret
, "NtQueryInformationProcess error %#x\n", ret
);
3413 ok(pbi
.ExitStatus
== 198, "expected 198, got %lu\n", pbi
.ExitStatus
);
3415 ret
= pNtSetInformationProcess(pi
.hProcess
, ProcessAffinityMask
, &affinity
, sizeof(affinity
));
3416 ok(ret
== STATUS_PROCESS_IS_TERMINATING
, "expected STATUS_PROCESS_IS_TERMINATING, got %#x\n", ret
);
3418 SetLastError(0xdeadbeef);
3419 ctx
.ContextFlags
= CONTEXT_INTEGER
;
3420 ret
= GetThreadContext(thread
, &ctx
);
3421 ok(!ret
|| broken(ret
) /* XP 64-bit */, "GetThreadContext should fail\n");
3423 ok(GetLastError() == ERROR_INVALID_PARAMETER
||
3424 GetLastError() == ERROR_GEN_FAILURE
/* win7 64-bit */ ||
3425 GetLastError() == ERROR_INVALID_FUNCTION
/* vista 64-bit */ ||
3426 GetLastError() == ERROR_ACCESS_DENIED
/* Win10 32-bit */,
3427 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3428 SetLastError(0xdeadbeef);
3429 ctx
.ContextFlags
= CONTEXT_INTEGER
;
3430 ret
= SetThreadContext(thread
, &ctx
);
3431 ok(!ret
|| broken(ret
) /* XP 64-bit */, "SetThreadContext should fail\n");
3433 ok(GetLastError() == ERROR_ACCESS_DENIED
||
3434 GetLastError() == ERROR_GEN_FAILURE
/* win7 64-bit */ ||
3435 GetLastError() == ERROR_INVALID_FUNCTION
/* vista 64-bit */,
3436 "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
3437 SetLastError(0xdeadbeef);
3438 ret
= SetThreadPriority(thread
, 0);
3439 ok(ret
, "SetThreadPriority error %d\n", GetLastError());
3440 CloseHandle(thread
);
3442 SetLastError(0xdeadbeef);
3443 ctx
.ContextFlags
= CONTEXT_INTEGER
;
3444 ret
= GetThreadContext(pi
.hThread
, &ctx
);
3445 ok(!ret
|| broken(ret
) /* XP 64-bit */, "GetThreadContext should fail\n");
3447 ok(GetLastError() == ERROR_INVALID_PARAMETER
||
3448 GetLastError() == ERROR_GEN_FAILURE
/* win7 64-bit */ ||
3449 GetLastError() == ERROR_INVALID_FUNCTION
/* vista 64-bit */ ||
3450 GetLastError() == ERROR_ACCESS_DENIED
/* Win10 32-bit */,
3451 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3452 SetLastError(0xdeadbeef);
3453 ctx
.ContextFlags
= CONTEXT_INTEGER
;
3454 ret
= SetThreadContext(pi
.hThread
, &ctx
);
3455 ok(!ret
|| broken(ret
) /* XP 64-bit */, "SetThreadContext should fail\n");
3457 ok(GetLastError() == ERROR_ACCESS_DENIED
||
3458 GetLastError() == ERROR_GEN_FAILURE
/* win7 64-bit */ ||
3459 GetLastError() == ERROR_INVALID_FUNCTION
/* vista 64-bit */,
3460 "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
3461 SetLastError(0xdeadbeef);
3462 ret
= VirtualProtectEx(pi
.hProcess
, addr
, 4096, PAGE_READWRITE
, &old_prot
);
3463 ok(!ret
, "VirtualProtectEx should fail\n");
3464 ok(GetLastError() == ERROR_ACCESS_DENIED
, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
3465 SetLastError(0xdeadbeef);
3467 ret
= ReadProcessMemory(pi
.hProcess
, addr
, buf
, 4, &size
);
3468 ok(!ret
, "ReadProcessMemory should fail\n");
3469 ok(GetLastError() == ERROR_PARTIAL_COPY
|| GetLastError() == ERROR_ACCESS_DENIED
,
3470 "expected ERROR_PARTIAL_COPY, got %d\n", GetLastError());
3471 ok(!size
, "expected 0, got %lu\n", size
);
3472 SetLastError(0xdeadbeef);
3473 ret
= VirtualFreeEx(pi
.hProcess
, addr
, 0, MEM_RELEASE
);
3474 ok(!ret
, "VirtualFreeEx should fail\n");
3475 ok(GetLastError() == ERROR_ACCESS_DENIED
, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
3476 SetLastError(0xdeadbeef);
3477 addr
= VirtualAllocEx(pi
.hProcess
, NULL
, 4096, MEM_COMMIT
, PAGE_READWRITE
);
3478 ok(!addr
, "VirtualAllocEx should fail\n");
3479 ok(GetLastError() == ERROR_ACCESS_DENIED
, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
3480 SetLastError(0xdeadbeef);
3481 size
= VirtualQueryEx(pi
.hProcess
, NULL
, &mbi
, sizeof(mbi
));
3482 ok(!size
, "VirtualQueryEx should fail\n");
3483 ok(GetLastError() == ERROR_ACCESS_DENIED
, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
3485 /* CloseHandle() call below leads to premature process termination
3486 * under some Windows versions.
3490 SetLastError(0xdeadbeef);
3491 ret
= CloseHandle(hmap_dup
);
3492 ok(ret
, "CloseHandle should not fail\n");
3495 SetLastError(0xdeadbeef);
3496 ret
= DuplicateHandle(GetCurrentProcess(), hmap
, pi
.hProcess
, &hmap_dup
,
3497 0, FALSE
, DUPLICATE_SAME_ACCESS
);
3498 ok(!ret
, "DuplicateHandle should fail\n");
3499 ok(GetLastError() == ERROR_ACCESS_DENIED
, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
3501 offset
.u
.LowPart
= 0;
3502 offset
.u
.HighPart
= 0;
3505 ret
= pNtMapViewOfSection(hmap
, pi
.hProcess
, &addr
, 0, 0, &offset
,
3506 &size
, 1 /* ViewShare */, 0, PAGE_READONLY
);
3507 ok(ret
== STATUS_PROCESS_IS_TERMINATING
, "expected STATUS_PROCESS_IS_TERMINATING, got %#x\n", ret
);
3509 SetLastError(0xdeadbeef);
3510 thread
= CreateRemoteThread(pi
.hProcess
, NULL
, 0, (void *)0xdeadbeef, NULL
, CREATE_SUSPENDED
, &ret
);
3511 ok(!thread
, "CreateRemoteThread should fail\n");
3512 ok(GetLastError() == ERROR_ACCESS_DENIED
, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
3514 SetLastError(0xdeadbeef);
3515 ret
= DebugActiveProcess(pi
.dwProcessId
);
3516 ok(!ret
, "DebugActiveProcess should fail\n");
3517 ok(GetLastError() == ERROR_ACCESS_DENIED
/* 64-bit */ || GetLastError() == ERROR_NOT_SUPPORTED
/* 32-bit */,
3518 "ERROR_ACCESS_DENIED, got %d\n", GetLastError());
3520 GetExitCodeProcess(pi
.hProcess
, &ret
);
3521 ok(ret
== 198 || broken(ret
!= 198) /* some 32-bit XP version in a VM returns random exit code */,
3522 "expected exit code 198, got %u\n", ret
);
3523 CloseHandle(pi
.hThread
);
3524 CloseHandle(pi
.hProcess
);
3526 ret
= DeleteFileA(dll_name
);
3527 ok(ret
, "DeleteFile error %d\n", GetLastError());
3529 skip("x86 specific ExitProcess test\n");
3533 static PVOID WINAPI
failuredllhook(ULONG ul
, DELAYLOAD_INFO
* pd
)
3535 ok(ul
== 4, "expected 4, got %u\n", ul
);
3536 ok(!!pd
, "no delayload info supplied\n");
3539 ok(pd
->Size
== sizeof(*pd
), "got %u\n", pd
->Size
);
3540 ok(!!pd
->DelayloadDescriptor
, "no DelayloadDescriptor supplied\n");
3541 if (pd
->DelayloadDescriptor
)
3543 ok(pd
->DelayloadDescriptor
->Attributes
.AllAttributes
== 1,
3544 "expected 1, got %u\n", pd
->DelayloadDescriptor
->Attributes
.AllAttributes
);
3545 ok(pd
->DelayloadDescriptor
->DllNameRVA
== 0x2000,
3546 "expected 0x2000, got %x\n", pd
->DelayloadDescriptor
->DllNameRVA
);
3547 ok(pd
->DelayloadDescriptor
->ModuleHandleRVA
== 0x201a,
3548 "expected 0x201a, got %x\n", pd
->DelayloadDescriptor
->ModuleHandleRVA
);
3549 ok(pd
->DelayloadDescriptor
->ImportAddressTableRVA
> pd
->DelayloadDescriptor
->ModuleHandleRVA
,
3550 "expected %x > %x\n", pd
->DelayloadDescriptor
->ImportAddressTableRVA
,
3551 pd
->DelayloadDescriptor
->ModuleHandleRVA
);
3552 ok(pd
->DelayloadDescriptor
->ImportNameTableRVA
> pd
->DelayloadDescriptor
->ImportAddressTableRVA
,
3553 "expected %x > %x\n", pd
->DelayloadDescriptor
->ImportNameTableRVA
,
3554 pd
->DelayloadDescriptor
->ImportAddressTableRVA
);
3555 ok(pd
->DelayloadDescriptor
->BoundImportAddressTableRVA
== 0,
3556 "expected 0, got %x\n", pd
->DelayloadDescriptor
->BoundImportAddressTableRVA
);
3557 ok(pd
->DelayloadDescriptor
->UnloadInformationTableRVA
== 0,
3558 "expected 0, got %x\n", pd
->DelayloadDescriptor
->UnloadInformationTableRVA
);
3559 ok(pd
->DelayloadDescriptor
->TimeDateStamp
== 0,
3560 "expected 0, got %x\n", pd
->DelayloadDescriptor
->TimeDateStamp
);
3563 ok(!!pd
->ThunkAddress
, "no ThunkAddress supplied\n");
3564 if (pd
->ThunkAddress
)
3565 ok(pd
->ThunkAddress
->u1
.Ordinal
, "no ThunkAddress value supplied\n");
3567 ok(!!pd
->TargetDllName
, "no TargetDllName supplied\n");
3568 if (pd
->TargetDllName
)
3569 ok(!strcmp(pd
->TargetDllName
, "secur32.dll"),
3570 "expected \"secur32.dll\", got \"%s\"\n", pd
->TargetDllName
);
3572 ok(pd
->TargetApiDescriptor
.ImportDescribedByName
== 0,
3573 "expected 0, got %x\n", pd
->TargetApiDescriptor
.ImportDescribedByName
);
3574 ok(pd
->TargetApiDescriptor
.Description
.Ordinal
== 0 ||
3575 pd
->TargetApiDescriptor
.Description
.Ordinal
== 999,
3576 "expected 0, got %x\n", pd
->TargetApiDescriptor
.Description
.Ordinal
);
3578 ok(!!pd
->TargetModuleBase
, "no TargetModuleBase supplied\n");
3579 ok(pd
->Unused
== NULL
, "expected NULL, got %p\n", pd
->Unused
);
3580 ok(pd
->LastError
, "no LastError supplied\n");
3583 return (void*)0xdeadbeef;
3586 static PVOID WINAPI
failuresyshook(const char *dll
, const char *function
)
3588 ok(!strcmp(dll
, "secur32.dll"), "wrong dll: %s\n", dll
);
3589 ok(!((ULONG_PTR
)function
>> 16), "expected ordinal, got %p\n", function
);
3591 return (void*)0x12345678;
3594 static void test_ResolveDelayLoadedAPI(void)
3596 static const char test_dll
[] = "secur32.dll";
3597 static const char test_func
[] = "SealMessage";
3598 char temp_path
[MAX_PATH
];
3599 char dll_name
[MAX_PATH
];
3600 IMAGE_DELAYLOAD_DESCRIPTOR idd
, *delaydir
;
3601 IMAGE_THUNK_DATA itd32
;
3604 DWORD dummy
, file_size
, i
;
3607 IMAGE_NT_HEADERS nt_header
;
3609 static const struct test_data
3620 FALSE
, IMAGE_ORDINAL_FLAG
| 2, TRUE
3623 FALSE
, IMAGE_ORDINAL_FLAG
| 5, TRUE
3626 FALSE
, IMAGE_ORDINAL_FLAG
| 0, FALSE
3629 FALSE
, IMAGE_ORDINAL_FLAG
| 999, FALSE
3633 if (!pResolveDelayLoadedAPI
)
3635 win_skip("ResolveDelayLoadedAPI is not available\n");
3639 if (0) /* crashes on native */
3641 SetLastError(0xdeadbeef);
3642 ok(!pResolveDelayLoadedAPI(NULL
, NULL
, NULL
, NULL
, NULL
, 0),
3643 "ResolveDelayLoadedAPI succeeded\n");
3644 ok(GetLastError() == 0xdeadbeef, "GetLastError changed to %x\n", GetLastError());
3647 SetLastError(0xdeadbeef);
3648 ok(!pResolveDelayLoadedAPI(NULL
, NULL
, failuredllhook
, NULL
, NULL
, 0),
3649 "ResolveDelayLoadedAPI succeeded\n");
3650 ok(GetLastError() == 0xdeadbeef, "GetLastError changed to %x\n", GetLastError());
3651 ok(cb_count
== 1, "Wrong callback count: %d\n", cb_count
);
3654 GetTempPathA(MAX_PATH
, temp_path
);
3655 GetTempFileNameA(temp_path
, "ldr", 0, dll_name
);
3656 trace("creating %s\n", dll_name
);
3657 hfile
= CreateFileA(dll_name
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
3658 if (hfile
== INVALID_HANDLE_VALUE
)
3660 ok(0, "could not create %s\n", dll_name
);
3664 SetLastError(0xdeadbeef);
3665 ret
= WriteFile(hfile
, &dos_header
, sizeof(dos_header
), &dummy
, NULL
);
3666 ok(ret
, "WriteFile error %d\n", GetLastError());
3668 nt_header
= nt_header_template
;
3669 nt_header
.FileHeader
.NumberOfSections
= 2;
3670 nt_header
.FileHeader
.SizeOfOptionalHeader
= sizeof(IMAGE_OPTIONAL_HEADER
);
3672 nt_header
.OptionalHeader
.SectionAlignment
= 0x1000;
3673 nt_header
.OptionalHeader
.FileAlignment
= 0x1000;
3674 nt_header
.OptionalHeader
.SizeOfImage
= sizeof(dos_header
) + sizeof(nt_header
) + sizeof(IMAGE_SECTION_HEADER
) + 0x2200;
3675 nt_header
.OptionalHeader
.SizeOfHeaders
= sizeof(dos_header
) + sizeof(nt_header
) + 2 * sizeof(IMAGE_SECTION_HEADER
);
3676 nt_header
.OptionalHeader
.NumberOfRvaAndSizes
= IMAGE_NUMBEROF_DIRECTORY_ENTRIES
;
3677 nt_header
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
].VirtualAddress
= 0x1000;
3678 nt_header
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
].Size
= 0x100;
3680 SetLastError(0xdeadbeef);
3681 ret
= WriteFile(hfile
, &nt_header
, sizeof(DWORD
) + sizeof(IMAGE_FILE_HEADER
), &dummy
, NULL
);
3682 ok(ret
, "WriteFile error %d\n", GetLastError());
3684 SetLastError(0xdeadbeef);
3685 ret
= WriteFile(hfile
, &nt_header
.OptionalHeader
, sizeof(IMAGE_OPTIONAL_HEADER
), &dummy
, NULL
);
3686 ok(ret
, "WriteFile error %d\n", GetLastError());
3689 section
.PointerToRawData
= nt_header
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
].VirtualAddress
;
3690 section
.VirtualAddress
= nt_header
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
].VirtualAddress
;
3691 section
.Misc
.VirtualSize
= 2 * sizeof(idd
);
3692 section
.SizeOfRawData
= section
.Misc
.VirtualSize
;
3693 section
.Characteristics
= IMAGE_SCN_CNT_INITIALIZED_DATA
| IMAGE_SCN_MEM_READ
;
3694 SetLastError(0xdeadbeef);
3695 ret
= WriteFile(hfile
, §ion
, sizeof(section
), &dummy
, NULL
);
3696 ok(ret
, "WriteFile error %d\n", GetLastError());
3698 section
.PointerToRawData
= 0x2000;
3699 section
.VirtualAddress
= 0x2000;
3701 section
.Misc
.VirtualSize
= sizeof(test_dll
) + sizeof(hint
) + sizeof(test_func
) + sizeof(HMODULE
) +
3702 2 * (i
+ 1) * sizeof(IMAGE_THUNK_DATA
);
3703 ok(section
.Misc
.VirtualSize
<= 0x1000, "Too much tests, add a new section!\n");
3704 section
.SizeOfRawData
= section
.Misc
.VirtualSize
;
3705 section
.Characteristics
= IMAGE_SCN_CNT_INITIALIZED_DATA
| IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_WRITE
;
3706 SetLastError(0xdeadbeef);
3707 ret
= WriteFile(hfile
, §ion
, sizeof(section
), &dummy
, NULL
);
3708 ok(ret
, "WriteFile error %d\n", GetLastError());
3710 /* fill up to delay data */
3711 SetFilePointer( hfile
, nt_header
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
].VirtualAddress
, NULL
, SEEK_SET
);
3714 idd
.Attributes
.AllAttributes
= 1;
3715 idd
.DllNameRVA
= 0x2000;
3716 idd
.ModuleHandleRVA
= idd
.DllNameRVA
+ sizeof(test_dll
) + sizeof(hint
) + sizeof(test_func
);
3717 idd
.ImportAddressTableRVA
= idd
.ModuleHandleRVA
+ sizeof(HMODULE
);
3718 idd
.ImportNameTableRVA
= idd
.ImportAddressTableRVA
+ (i
+ 1) * sizeof(IMAGE_THUNK_DATA
);
3719 idd
.BoundImportAddressTableRVA
= 0;
3720 idd
.UnloadInformationTableRVA
= 0;
3721 idd
.TimeDateStamp
= 0;
3723 SetLastError(0xdeadbeef);
3724 ret
= WriteFile(hfile
, &idd
, sizeof(idd
), &dummy
, NULL
);
3725 ok(ret
, "WriteFile error %d\n", GetLastError());
3727 SetLastError(0xdeadbeef);
3728 ret
= WriteFile(hfile
, filler
, sizeof(idd
), &dummy
, NULL
);
3729 ok(ret
, "WriteFile error %d\n", GetLastError());
3731 /* fill up to extended delay data */
3732 SetFilePointer( hfile
, idd
.DllNameRVA
, NULL
, SEEK_SET
);
3734 /* extended delay data */
3735 SetLastError(0xdeadbeef);
3736 ret
= WriteFile(hfile
, test_dll
, sizeof(test_dll
), &dummy
, NULL
);
3737 ok(ret
, "WriteFile error %d\n", GetLastError());
3739 SetLastError(0xdeadbeef);
3740 ret
= WriteFile(hfile
, &hint
, sizeof(hint
), &dummy
, NULL
);
3741 ok(ret
, "WriteFile error %d\n", GetLastError());
3743 SetLastError(0xdeadbeef);
3744 ret
= WriteFile(hfile
, test_func
, sizeof(test_func
), &dummy
, NULL
);
3745 ok(ret
, "WriteFile error %d\n", GetLastError());
3747 SetFilePointer( hfile
, idd
.ImportAddressTableRVA
, NULL
, SEEK_SET
);
3749 for (i
= 0; i
< ARRAY_SIZE(td
); i
++)
3751 /* 0x1a00 is an empty space between delay data and extended delay data, real thunks are not necessary */
3752 itd32
.u1
.Function
= nt_header
.OptionalHeader
.ImageBase
+ 0x1a00 + i
* 0x20;
3753 SetLastError(0xdeadbeef);
3754 ret
= WriteFile(hfile
, &itd32
, sizeof(itd32
), &dummy
, NULL
);
3755 ok(ret
, "WriteFile error %d\n", GetLastError());
3758 itd32
.u1
.Function
= 0;
3759 SetLastError(0xdeadbeef);
3760 ret
= WriteFile(hfile
, &itd32
, sizeof(itd32
), &dummy
, NULL
);
3761 ok(ret
, "WriteFile error %d\n", GetLastError());
3763 for (i
= 0; i
< ARRAY_SIZE(td
); i
++)
3766 itd32
.u1
.AddressOfData
= idd
.DllNameRVA
+ sizeof(test_dll
);
3768 itd32
.u1
.Ordinal
= td
[i
].ordinal
;
3769 SetLastError(0xdeadbeef);
3770 ret
= WriteFile(hfile
, &itd32
, sizeof(itd32
), &dummy
, NULL
);
3771 ok(ret
, "WriteFile error %d\n", GetLastError());
3774 itd32
.u1
.Ordinal
= 0;
3775 SetLastError(0xdeadbeef);
3776 ret
= WriteFile(hfile
, &itd32
, sizeof(itd32
), &dummy
, NULL
);
3777 ok(ret
, "WriteFile error %d\n", GetLastError());
3779 /* fill up to eof */
3780 SetFilePointer( hfile
, section
.VirtualAddress
+ section
.Misc
.VirtualSize
, NULL
, SEEK_SET
);
3781 SetEndOfFile( hfile
);
3784 SetLastError(0xdeadbeef);
3785 hlib
= LoadLibraryA(dll_name
);
3786 ok(hlib
!= NULL
, "LoadLibrary error %u\n", GetLastError());
3789 skip("couldn't load %s.\n", dll_name
);
3790 DeleteFileA(dll_name
);
3794 delaydir
= pRtlImageDirectoryEntryToData(hlib
, TRUE
, IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
, &file_size
);
3797 skip("haven't found section for delay import directory.\n");
3799 DeleteFileA(dll_name
);
3805 IMAGE_THUNK_DATA
*itdn
, *itda
;
3808 if (!delaydir
->DllNameRVA
||
3809 !delaydir
->ImportAddressTableRVA
||
3810 !delaydir
->ImportNameTableRVA
) break;
3812 itdn
= RVAToAddr(delaydir
->ImportNameTableRVA
, hlib
);
3813 itda
= RVAToAddr(delaydir
->ImportAddressTableRVA
, hlib
);
3814 htarget
= LoadLibraryA(RVAToAddr(delaydir
->DllNameRVA
, hlib
));
3816 for (i
= 0; i
< ARRAY_SIZE(td
); i
++)
3820 if (IMAGE_SNAP_BY_ORDINAL(itdn
[i
].u1
.Ordinal
))
3821 load
= (void *)GetProcAddress(htarget
, (LPSTR
)IMAGE_ORDINAL(itdn
[i
].u1
.Ordinal
));
3824 const IMAGE_IMPORT_BY_NAME
* iibn
= RVAToAddr(itdn
[i
].u1
.AddressOfData
, hlib
);
3825 load
= (void *)GetProcAddress(htarget
, (char*)iibn
->Name
);
3828 /* test without failure dll callback */
3829 cb_count
= cb_count_sys
= 0;
3830 ret
= pResolveDelayLoadedAPI(hlib
, delaydir
, NULL
, failuresyshook
, &itda
[i
], 0);
3833 ok(ret
!= NULL
, "Test %u: ResolveDelayLoadedAPI failed\n", i
);
3834 ok(ret
== load
, "Test %u: expected %p, got %p\n", i
, load
, ret
);
3835 ok(ret
== (void*)itda
[i
].u1
.AddressOfData
, "Test %u: expected %p, got %p\n",
3836 i
, ret
, (void*)itda
[i
].u1
.AddressOfData
);
3837 ok(!cb_count
, "Test %u: Wrong callback count: %d\n", i
, cb_count
);
3838 ok(!cb_count_sys
, "Test %u: Wrong sys callback count: %d\n", i
, cb_count_sys
);
3842 ok(ret
== (void*)0x12345678, "Test %u: ResolveDelayLoadedAPI succeeded with %p\n", i
, ret
);
3843 ok(!cb_count
, "Test %u: Wrong callback count: %d\n", i
, cb_count
);
3844 ok(cb_count_sys
== 1, "Test %u: Wrong sys callback count: %d\n", i
, cb_count_sys
);
3847 /* test with failure dll callback */
3848 cb_count
= cb_count_sys
= 0;
3849 ret
= pResolveDelayLoadedAPI(hlib
, delaydir
, failuredllhook
, failuresyshook
, &itda
[i
], 0);
3852 ok(ret
!= NULL
, "Test %u: ResolveDelayLoadedAPI failed\n", i
);
3853 ok(ret
== load
, "Test %u: expected %p, got %p\n", i
, load
, ret
);
3854 ok(ret
== (void*)itda
[i
].u1
.AddressOfData
, "Test %u: expected %p, got %p\n",
3855 i
, ret
, (void*)itda
[i
].u1
.AddressOfData
);
3856 ok(!cb_count
, "Test %u: Wrong callback count: %d\n", i
, cb_count
);
3857 ok(!cb_count_sys
, "Test %u: Wrong sys callback count: %d\n", i
, cb_count_sys
);
3861 if (ret
== (void*)0x12345678)
3863 /* Win10+ sometimes buffers the address of the stub function */
3864 ok(!cb_count
, "Test %u: Wrong callback count: %d\n", i
, cb_count
);
3865 ok(!cb_count_sys
, "Test %u: Wrong sys callback count: %d\n", i
, cb_count_sys
);
3867 else if (ret
== (void*)0xdeadbeef)
3869 ok(cb_count
== 1, "Test %u: Wrong callback count: %d\n", i
, cb_count
);
3870 ok(!cb_count_sys
, "Test %u: Wrong sys callback count: %d\n", i
, cb_count_sys
);
3873 ok(0, "Test %u: ResolveDelayLoadedAPI succeeded with %p\n", i
, ret
);
3880 trace("deleting %s\n", dll_name
);
3881 DeleteFileA(dll_name
);
3884 static void test_InMemoryOrderModuleList(void)
3886 PEB_LDR_DATA
*ldr
= NtCurrentTeb()->Peb
->LdrData
;
3887 LIST_ENTRY
*entry1
, *mark1
= &ldr
->InLoadOrderModuleList
;
3888 LIST_ENTRY
*entry2
, *mark2
= &ldr
->InMemoryOrderModuleList
;
3889 LDR_DATA_TABLE_ENTRY
*module1
, *module2
;
3891 ok(ldr
->Initialized
== TRUE
, "expected TRUE, got %u\n", ldr
->Initialized
);
3893 for (entry1
= mark1
->Flink
, entry2
= mark2
->Flink
;
3894 entry1
!= mark1
&& entry2
!= mark2
;
3895 entry1
= entry1
->Flink
, entry2
= entry2
->Flink
)
3897 module1
= CONTAINING_RECORD(entry1
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
3898 module2
= CONTAINING_RECORD(entry2
, LDR_DATA_TABLE_ENTRY
, InMemoryOrderLinks
);
3899 ok(module1
== module2
, "expected module1 == module2, got %p and %p\n", module1
, module2
);
3901 ok(entry1
== mark1
, "expected entry1 == mark1, got %p and %p\n", entry1
, mark1
);
3902 ok(entry2
== mark2
, "expected entry2 == mark2, got %p and %p\n", entry2
, mark2
);
3905 static void test_wow64_redirection_for_dll(const char *libname
)
3910 if (!GetModuleHandleA(libname
))
3912 lib
= LoadLibraryExA(libname
, NULL
, 0);
3913 ok (broken(lib
== NULL
) /* Vista/2008 */ ||
3914 lib
!= NULL
, "Loading %s should succeed with WOW64 redirection disabled\n", libname
);
3917 /* Win 7/2008R2 return the un-redirected path (i.e. c:\windows\system32\dwrite.dll), test loading it. */
3918 GetModuleFileNameA(lib
, buf
, sizeof(buf
));
3920 lib
= LoadLibraryExA(buf
, NULL
, 0);
3921 ok(lib
!= NULL
, "Loading %s from full path should succeed with WOW64 redirection disabled\n", libname
);
3928 skip("%s was already loaded in the process\n", libname
);
3932 static void test_wow64_redirection(void)
3939 /* Disable FS redirection, then test loading system libraries (pick ones that shouldn't
3940 * already be loaded in this process).
3942 ok(pWow64DisableWow64FsRedirection(&OldValue
), "Disabling FS redirection failed\n");
3943 test_wow64_redirection_for_dll("wlanapi.dll");
3944 test_wow64_redirection_for_dll("dxgi.dll");
3945 test_wow64_redirection_for_dll("dwrite.dll");
3946 ok(pWow64RevertWow64FsRedirection(OldValue
), "Re-enabling FS redirection failed\n");
3949 static void test_dll_file( const char *name
)
3951 HMODULE module
= GetModuleHandleA( name
);
3952 IMAGE_NT_HEADERS
*nt
, *nt_file
;
3953 IMAGE_SECTION_HEADER
*sec
, *sec_file
;
3954 char path
[MAX_PATH
];
3955 HANDLE file
, mapping
;
3959 GetModuleFileNameA( module
, path
, MAX_PATH
);
3960 file
= CreateFileA( path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0 );
3961 ok( file
!= INVALID_HANDLE_VALUE
, "can't open '%s': %u\n", path
, GetLastError() );
3963 mapping
= CreateFileMappingA( file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
3964 ok( mapping
!= NULL
, "%s: CreateFileMappingW failed err %u\n", name
, GetLastError() );
3965 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 0 );
3966 ok( ptr
!= NULL
, "%s: MapViewOfFile failed err %u\n", name
, GetLastError() );
3967 CloseHandle( mapping
);
3968 CloseHandle( file
);
3970 nt
= pRtlImageNtHeader( module
);
3971 nt_file
= pRtlImageNtHeader( ptr
);
3972 ok( nt_file
!= NULL
, "%s: invalid header\n", path
);
3973 #define OK_FIELD(x) ok( nt->x == nt_file->x, "%s:%u: wrong " #x " %x / %x\n", name, i, nt->x, nt_file->x )
3974 OK_FIELD( FileHeader
.NumberOfSections
);
3975 OK_FIELD( OptionalHeader
.AddressOfEntryPoint
);
3976 OK_FIELD( OptionalHeader
.NumberOfRvaAndSizes
);
3977 for (i
= 0; i
< nt
->OptionalHeader
.NumberOfRvaAndSizes
; i
++)
3979 OK_FIELD( OptionalHeader
.DataDirectory
[i
].VirtualAddress
);
3980 OK_FIELD( OptionalHeader
.DataDirectory
[i
].Size
);
3982 sec
= (IMAGE_SECTION_HEADER
*)((char *)&nt
->OptionalHeader
+ nt
->FileHeader
.SizeOfOptionalHeader
);
3983 sec_file
= (IMAGE_SECTION_HEADER
*)((char *)&nt_file
->OptionalHeader
+ nt_file
->FileHeader
.SizeOfOptionalHeader
);
3984 for (i
= 0; i
< nt
->FileHeader
.NumberOfSections
; i
++)
3985 ok( !memcmp( sec
+ i
, sec_file
+ i
, sizeof(*sec
) ), "%s: wrong section %d\n", name
, i
);
3986 UnmapViewOfFile( ptr
);
3990 static void test_LoadPackagedLibrary(void)
3994 if (!pLoadPackagedLibrary
)
3996 win_skip("LoadPackagedLibrary is not available.\n");
4000 SetLastError( 0xdeadbeef );
4001 h
= pLoadPackagedLibrary(L
"kernel32.dll", 0);
4002 ok(!h
&& GetLastError() == APPMODEL_ERROR_NO_PACKAGE
, "Got unexpected handle %p, GetLastError() %u.\n",
4010 HANDLE ntdll
, mapping
, kernel32
;
4013 ntdll
= GetModuleHandleA("ntdll.dll");
4014 kernel32
= GetModuleHandleA("kernel32.dll");
4015 pNtCreateSection
= (void *)GetProcAddress(ntdll
, "NtCreateSection");
4016 pNtQuerySection
= (void *)GetProcAddress(ntdll
, "NtQuerySection");
4017 pNtMapViewOfSection
= (void *)GetProcAddress(ntdll
, "NtMapViewOfSection");
4018 pNtUnmapViewOfSection
= (void *)GetProcAddress(ntdll
, "NtUnmapViewOfSection");
4019 pNtTerminateProcess
= (void *)GetProcAddress(ntdll
, "NtTerminateProcess");
4020 pNtQueryInformationProcess
= (void *)GetProcAddress(ntdll
, "NtQueryInformationProcess");
4021 pNtSetInformationProcess
= (void *)GetProcAddress(ntdll
, "NtSetInformationProcess");
4022 pLdrShutdownProcess
= (void *)GetProcAddress(ntdll
, "LdrShutdownProcess");
4023 pRtlDllShutdownInProgress
= (void *)GetProcAddress(ntdll
, "RtlDllShutdownInProgress");
4024 pNtAllocateVirtualMemory
= (void *)GetProcAddress(ntdll
, "NtAllocateVirtualMemory");
4025 pNtFreeVirtualMemory
= (void *)GetProcAddress(ntdll
, "NtFreeVirtualMemory");
4026 pLdrLockLoaderLock
= (void *)GetProcAddress(ntdll
, "LdrLockLoaderLock");
4027 pLdrUnlockLoaderLock
= (void *)GetProcAddress(ntdll
, "LdrUnlockLoaderLock");
4028 pLdrLoadDll
= (void *)GetProcAddress(ntdll
, "LdrLoadDll");
4029 pLdrUnloadDll
= (void *)GetProcAddress(ntdll
, "LdrUnloadDll");
4030 pRtlInitUnicodeString
= (void *)GetProcAddress(ntdll
, "RtlInitUnicodeString");
4031 pRtlAcquirePebLock
= (void *)GetProcAddress(ntdll
, "RtlAcquirePebLock");
4032 pRtlReleasePebLock
= (void *)GetProcAddress(ntdll
, "RtlReleasePebLock");
4033 pRtlImageDirectoryEntryToData
= (void *)GetProcAddress(ntdll
, "RtlImageDirectoryEntryToData");
4034 pRtlImageNtHeader
= (void *)GetProcAddress(ntdll
, "RtlImageNtHeader");
4035 pFlsAlloc
= (void *)GetProcAddress(kernel32
, "FlsAlloc");
4036 pFlsSetValue
= (void *)GetProcAddress(kernel32
, "FlsSetValue");
4037 pFlsGetValue
= (void *)GetProcAddress(kernel32
, "FlsGetValue");
4038 pFlsFree
= (void *)GetProcAddress(kernel32
, "FlsFree");
4039 pIsWow64Process
= (void *)GetProcAddress(kernel32
, "IsWow64Process");
4040 pWow64DisableWow64FsRedirection
= (void *)GetProcAddress(kernel32
, "Wow64DisableWow64FsRedirection");
4041 pWow64RevertWow64FsRedirection
= (void *)GetProcAddress(kernel32
, "Wow64RevertWow64FsRedirection");
4042 pResolveDelayLoadedAPI
= (void *)GetProcAddress(kernel32
, "ResolveDelayLoadedAPI");
4043 pLoadPackagedLibrary
= (void *)GetProcAddress(kernel32
, "LoadPackagedLibrary");
4045 if (pIsWow64Process
) pIsWow64Process( GetCurrentProcess(), &is_wow64
);
4046 GetSystemInfo( &si
);
4047 page_size
= si
.dwPageSize
;
4048 dos_header
.e_magic
= IMAGE_DOS_SIGNATURE
;
4049 dos_header
.e_lfanew
= sizeof(dos_header
);
4051 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, 4096, "winetest_loader");
4052 ok(mapping
!= 0, "CreateFileMapping failed\n");
4053 child_failures
= MapViewOfFile(mapping
, FILE_MAP_READ
|FILE_MAP_WRITE
, 0, 0, 4096);
4054 if (*child_failures
== -1)
4056 *child_failures
= 0;
4059 *child_failures
= -1;
4061 argc
= winetest_get_mainargs(&argv
);
4064 test_dll_phase
= atoi(argv
[4]);
4065 child_process(argv
[2], atol(argv
[3]));
4070 test_ResolveDelayLoadedAPI();
4071 test_ImportDescriptors();
4072 test_section_access();
4073 test_import_resolution();
4075 test_InMemoryOrderModuleList();
4076 test_LoadPackagedLibrary();
4077 test_wow64_redirection();
4078 test_dll_file( "ntdll.dll" );
4079 test_dll_file( "kernel32.dll" );
4080 test_dll_file( "advapi32.dll" );
4081 test_dll_file( "user32.dll" );
4082 /* loader test must be last, it can corrupt the internal loader state on Windows */