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
32 #include "wine/test.h"
33 #include "delayloadhandler.h"
35 /* PROCESS_ALL_ACCESS in Vista+ PSDKs is incompatible with older Windows versions */
36 #define PROCESS_ALL_ACCESS_NT4 (PROCESS_ALL_ACCESS & ~0xf000)
38 #define ALIGN_SIZE(size, alignment) (((size) + (alignment - 1)) & ~((alignment - 1)))
40 struct PROCESS_BASIC_INFORMATION_PRIVATE
44 DWORD_PTR AffinityMask
;
45 DWORD_PTR BasePriority
;
46 ULONG_PTR UniqueProcessId
;
47 ULONG_PTR InheritedFromUniqueProcessId
;
50 static LONG
*child_failures
;
52 static DWORD page_size
;
53 static BOOL is_win64
= sizeof(void *) > sizeof(int);
56 static NTSTATUS (WINAPI
*pNtCreateSection
)(HANDLE
*, ACCESS_MASK
, const OBJECT_ATTRIBUTES
*,
57 const LARGE_INTEGER
*, ULONG
, ULONG
, HANDLE
);
58 static NTSTATUS (WINAPI
*pNtQuerySection
)(HANDLE
, SECTION_INFORMATION_CLASS
, void *, SIZE_T
, SIZE_T
*);
59 static NTSTATUS (WINAPI
*pNtMapViewOfSection
)(HANDLE
, HANDLE
, PVOID
*, ULONG
, SIZE_T
, const LARGE_INTEGER
*, SIZE_T
*, ULONG
, ULONG
, ULONG
);
60 static NTSTATUS (WINAPI
*pNtUnmapViewOfSection
)(HANDLE
, PVOID
);
61 static NTSTATUS (WINAPI
*pNtQueryInformationProcess
)(HANDLE
, PROCESSINFOCLASS
, PVOID
, ULONG
, PULONG
);
62 static NTSTATUS (WINAPI
*pNtSetInformationProcess
)(HANDLE
, PROCESSINFOCLASS
, PVOID
, ULONG
);
63 static NTSTATUS (WINAPI
*pNtTerminateProcess
)(HANDLE
, DWORD
);
64 static void (WINAPI
*pLdrShutdownProcess
)(void);
65 static BOOLEAN (WINAPI
*pRtlDllShutdownInProgress
)(void);
66 static NTSTATUS (WINAPI
*pNtAllocateVirtualMemory
)(HANDLE
, PVOID
*, ULONG
, SIZE_T
*, ULONG
, ULONG
);
67 static NTSTATUS (WINAPI
*pNtFreeVirtualMemory
)(HANDLE
, PVOID
*, SIZE_T
*, ULONG
);
68 static NTSTATUS (WINAPI
*pLdrLockLoaderLock
)(ULONG
, ULONG
*, ULONG_PTR
*);
69 static NTSTATUS (WINAPI
*pLdrUnlockLoaderLock
)(ULONG
, ULONG_PTR
);
70 static void (WINAPI
*pRtlAcquirePebLock
)(void);
71 static void (WINAPI
*pRtlReleasePebLock
)(void);
72 static PVOID (WINAPI
*pResolveDelayLoadedAPI
)(PVOID
, PCIMAGE_DELAYLOAD_DESCRIPTOR
,
73 PDELAYLOAD_FAILURE_DLL_CALLBACK
, PVOID
,
74 PIMAGE_THUNK_DATA ThunkAddress
,ULONG
);
75 static PVOID (WINAPI
*pRtlImageDirectoryEntryToData
)(HMODULE
,BOOL
,WORD
,ULONG
*);
76 static DWORD (WINAPI
*pFlsAlloc
)(PFLS_CALLBACK_FUNCTION
);
77 static BOOL (WINAPI
*pFlsSetValue
)(DWORD
, PVOID
);
78 static PVOID (WINAPI
*pFlsGetValue
)(DWORD
);
79 static BOOL (WINAPI
*pFlsFree
)(DWORD
);
80 static BOOL (WINAPI
*pIsWow64Process
)(HANDLE
,PBOOL
);
82 static PVOID
RVAToAddr(DWORD_PTR rva
, HMODULE module
)
86 return ((char*) module
) + rva
;
89 static IMAGE_DOS_HEADER dos_header
;
91 static const IMAGE_NT_HEADERS nt_header_template
=
93 IMAGE_NT_SIGNATURE
, /* Signature */
96 IMAGE_FILE_MACHINE_I386
, /* Machine */
97 #elif defined __x86_64__
98 IMAGE_FILE_MACHINE_AMD64
, /* Machine */
99 #elif defined __powerpc__
100 IMAGE_FILE_MACHINE_POWERPC
, /* Machine */
101 #elif defined __arm__
102 IMAGE_FILE_MACHINE_ARMNT
, /* Machine */
103 #elif defined __aarch64__
104 IMAGE_FILE_MACHINE_ARM64
, /* Machine */
106 # error You must specify the machine type
108 1, /* NumberOfSections */
109 0, /* TimeDateStamp */
110 0, /* PointerToSymbolTable */
111 0, /* NumberOfSymbols */
112 sizeof(IMAGE_OPTIONAL_HEADER
), /* SizeOfOptionalHeader */
113 IMAGE_FILE_EXECUTABLE_IMAGE
| IMAGE_FILE_DLL
/* Characteristics */
115 { IMAGE_NT_OPTIONAL_HDR_MAGIC
, /* Magic */
116 1, /* MajorLinkerVersion */
117 0, /* MinorLinkerVersion */
119 0, /* SizeOfInitializedData */
120 0, /* SizeOfUninitializedData */
121 0, /* AddressOfEntryPoint */
122 0x10, /* BaseOfCode, also serves as e_lfanew in the truncated MZ header */
126 0x10000000, /* ImageBase */
127 0, /* SectionAlignment */
128 0, /* FileAlignment */
129 4, /* MajorOperatingSystemVersion */
130 0, /* MinorOperatingSystemVersion */
131 1, /* MajorImageVersion */
132 0, /* MinorImageVersion */
133 4, /* MajorSubsystemVersion */
134 0, /* MinorSubsystemVersion */
135 0, /* Win32VersionValue */
136 sizeof(dos_header
) + sizeof(nt_header_template
) + sizeof(IMAGE_SECTION_HEADER
) + 0x1000, /* SizeOfImage */
137 sizeof(dos_header
) + sizeof(nt_header_template
), /* SizeOfHeaders */
139 IMAGE_SUBSYSTEM_WINDOWS_CUI
, /* Subsystem */
140 0, /* DllCharacteristics */
141 0, /* SizeOfStackReserve */
142 0, /* SizeOfStackCommit */
143 0, /* SizeOfHeapReserve */
144 0, /* SizeOfHeapCommit */
146 0, /* NumberOfRvaAndSizes */
147 { { 0 } } /* DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES] */
151 static IMAGE_SECTION_HEADER section
=
153 ".rodata", /* Name */
155 0, /* VirtualAddress */
156 0, /* SizeOfRawData */
157 0, /* PointerToRawData */
158 0, /* PointerToRelocations */
159 0, /* PointerToLinenumbers */
160 0, /* NumberOfRelocations */
161 0, /* NumberOfLinenumbers */
162 IMAGE_SCN_CNT_INITIALIZED_DATA
| IMAGE_SCN_MEM_READ
, /* Characteristics */
166 static const char filler
[0x1000];
167 static const char section_data
[0x10] = "section data";
169 static DWORD
create_test_dll( const IMAGE_DOS_HEADER
*dos_header
, UINT dos_size
,
170 const IMAGE_NT_HEADERS
*nt_header
, char dll_name
[MAX_PATH
] )
172 char temp_path
[MAX_PATH
];
173 DWORD dummy
, size
, file_align
;
177 GetTempPathA(MAX_PATH
, temp_path
);
178 GetTempFileNameA(temp_path
, "ldr", 0, dll_name
);
180 hfile
= CreateFileA(dll_name
, GENERIC_WRITE
, FILE_SHARE_READ
, NULL
, CREATE_ALWAYS
, 0, 0);
181 ok( hfile
!= INVALID_HANDLE_VALUE
, "failed to create %s err %u\n", dll_name
, GetLastError() );
182 if (hfile
== INVALID_HANDLE_VALUE
) return 0;
184 SetLastError(0xdeadbeef);
185 ret
= WriteFile(hfile
, dos_header
, dos_size
, &dummy
, NULL
);
186 ok(ret
, "WriteFile error %d\n", GetLastError());
188 SetLastError(0xdeadbeef);
189 ret
= WriteFile(hfile
, nt_header
, sizeof(DWORD
) + sizeof(IMAGE_FILE_HEADER
), &dummy
, NULL
);
190 ok(ret
, "WriteFile error %d\n", GetLastError());
192 if (nt_header
->FileHeader
.SizeOfOptionalHeader
)
194 SetLastError(0xdeadbeef);
195 ret
= WriteFile(hfile
, &nt_header
->OptionalHeader
,
196 min(nt_header
->FileHeader
.SizeOfOptionalHeader
, sizeof(IMAGE_OPTIONAL_HEADER
)),
198 ok(ret
, "WriteFile error %d\n", GetLastError());
199 if (nt_header
->FileHeader
.SizeOfOptionalHeader
> sizeof(IMAGE_OPTIONAL_HEADER
))
201 file_align
= nt_header
->FileHeader
.SizeOfOptionalHeader
- sizeof(IMAGE_OPTIONAL_HEADER
);
202 assert(file_align
< sizeof(filler
));
203 SetLastError(0xdeadbeef);
204 ret
= WriteFile(hfile
, filler
, file_align
, &dummy
, NULL
);
205 ok(ret
, "WriteFile error %d\n", GetLastError());
209 assert(nt_header
->FileHeader
.NumberOfSections
<= 1);
210 if (nt_header
->FileHeader
.NumberOfSections
)
212 section
.SizeOfRawData
= 10;
214 if (nt_header
->OptionalHeader
.SectionAlignment
>= page_size
)
216 section
.PointerToRawData
= dos_size
;
217 section
.VirtualAddress
= nt_header
->OptionalHeader
.SectionAlignment
;
218 section
.Misc
.VirtualSize
= section
.SizeOfRawData
* 10;
222 section
.PointerToRawData
= nt_header
->OptionalHeader
.SizeOfHeaders
;
223 section
.VirtualAddress
= nt_header
->OptionalHeader
.SizeOfHeaders
;
224 section
.Misc
.VirtualSize
= 5;
227 SetLastError(0xdeadbeef);
228 ret
= WriteFile(hfile
, §ion
, sizeof(section
), &dummy
, NULL
);
229 ok(ret
, "WriteFile error %d\n", GetLastError());
232 SetLastError(0xdeadbeef);
233 ret
= WriteFile(hfile
, section_data
, sizeof(section_data
), &dummy
, NULL
);
234 ok(ret
, "WriteFile error %d\n", GetLastError());
236 size
= GetFileSize(hfile
, NULL
);
241 static DWORD
create_test_dll_sections( const IMAGE_DOS_HEADER
*dos_header
, const IMAGE_NT_HEADERS
*nt_header
,
242 const IMAGE_SECTION_HEADER
*sections
, const void *section_data
,
243 char dll_name
[MAX_PATH
] )
245 char temp_path
[MAX_PATH
];
246 DWORD dummy
, i
, size
;
250 GetTempPathA(MAX_PATH
, temp_path
);
251 GetTempFileNameA(temp_path
, "ldr", 0, dll_name
);
253 hfile
= CreateFileA(dll_name
, GENERIC_WRITE
, FILE_SHARE_READ
, NULL
, CREATE_ALWAYS
, 0, 0);
254 ok( hfile
!= INVALID_HANDLE_VALUE
, "failed to create %s err %u\n", dll_name
, GetLastError() );
255 if (hfile
== INVALID_HANDLE_VALUE
) return 0;
257 SetLastError(0xdeadbeef);
258 ret
= WriteFile(hfile
, dos_header
, sizeof(*dos_header
), &dummy
, NULL
);
259 ok(ret
, "WriteFile error %d\n", GetLastError());
261 SetLastError(0xdeadbeef);
262 ret
= WriteFile(hfile
, nt_header
, offsetof(IMAGE_NT_HEADERS
, OptionalHeader
) + nt_header
->FileHeader
.SizeOfOptionalHeader
, &dummy
, NULL
);
263 ok(ret
, "WriteFile error %d\n", GetLastError());
265 SetLastError(0xdeadbeef);
266 ret
= WriteFile(hfile
, sections
, sizeof(*sections
) * nt_header
->FileHeader
.NumberOfSections
,
268 ok(ret
, "WriteFile error %d\n", GetLastError());
270 for (i
= 0; i
< nt_header
->FileHeader
.NumberOfSections
; i
++)
272 SetFilePointer(hfile
, sections
[i
].PointerToRawData
, NULL
, FILE_BEGIN
);
273 SetLastError(0xdeadbeef);
274 ret
= WriteFile(hfile
, section_data
, sections
[i
].SizeOfRawData
, &dummy
, NULL
);
275 ok(ret
, "WriteFile error %d\n", GetLastError());
277 size
= GetFileSize(hfile
, NULL
);
282 static BOOL
query_image_section( int id
, const char *dll_name
, const IMAGE_NT_HEADERS
*nt_header
,
283 const void *section_data
)
285 static BOOL is_winxp
;
286 SECTION_BASIC_INFORMATION info
;
287 SECTION_IMAGE_INFORMATION image
;
288 const IMAGE_COR20_HEADER
*cor_header
= NULL
;
289 SIZE_T info_size
= (SIZE_T
)0xdeadbeef << 16;
291 HANDLE file
, mapping
;
293 LARGE_INTEGER map_size
;
294 SIZE_T max_stack
, commit_stack
;
297 /* truncated header is not handled correctly in windows <= w2k3 */
300 file
= CreateFileA( dll_name
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_DELETE
,
301 NULL
, OPEN_EXISTING
, 0, 0 );
302 ok( file
!= INVALID_HANDLE_VALUE
, "%u: CreateFile error %d\n", id
, GetLastError() );
303 file_size
= GetFileSize( file
, NULL
);
305 status
= pNtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_MAP_READ
| SECTION_QUERY
,
306 NULL
, NULL
, PAGE_READONLY
, SEC_IMAGE
, file
);
307 ok( !status
, "%u: NtCreateSection failed err %x\n", id
, status
);
313 status
= pNtQuerySection( mapping
, SectionImageInformation
, &image
, sizeof(image
), &info_size
);
314 ok( !status
, "%u: NtQuerySection failed err %x\n", id
, status
);
315 ok( info_size
== sizeof(image
), "%u: NtQuerySection wrong size %lu\n", id
, info_size
);
316 if (nt_header
->OptionalHeader
.Magic
== (is_win64
? IMAGE_NT_OPTIONAL_HDR64_MAGIC
317 : IMAGE_NT_OPTIONAL_HDR32_MAGIC
))
319 max_stack
= nt_header
->OptionalHeader
.SizeOfStackReserve
;
320 commit_stack
= nt_header
->OptionalHeader
.SizeOfStackCommit
;
321 entry_point
= (char *)nt_header
->OptionalHeader
.ImageBase
+ nt_header
->OptionalHeader
.AddressOfEntryPoint
;
322 truncated
= nt_header
->FileHeader
.SizeOfOptionalHeader
< sizeof(IMAGE_OPTIONAL_HEADER
);
324 nt_header
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
&&
325 nt_header
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].Size
)
326 cor_header
= section_data
;
328 else if (nt_header
->OptionalHeader
.Magic
== IMAGE_NT_OPTIONAL_HDR64_MAGIC
)
330 const IMAGE_NT_HEADERS64
*nt64
= (const IMAGE_NT_HEADERS64
*)nt_header
;
331 max_stack
= 0x100000;
332 commit_stack
= 0x10000;
333 entry_point
= (void *)0x81231234;
334 truncated
= nt_header
->FileHeader
.SizeOfOptionalHeader
< sizeof(IMAGE_OPTIONAL_HEADER64
);
336 nt64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
&&
337 nt64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].Size
)
338 cor_header
= section_data
;
342 const IMAGE_NT_HEADERS32
*nt32
= (const IMAGE_NT_HEADERS32
*)nt_header
;
343 max_stack
= nt32
->OptionalHeader
.SizeOfStackReserve
;
344 commit_stack
= nt32
->OptionalHeader
.SizeOfStackCommit
;
345 entry_point
= (char *)(ULONG_PTR
)nt32
->OptionalHeader
.ImageBase
+ nt32
->OptionalHeader
.AddressOfEntryPoint
;
346 truncated
= nt_header
->FileHeader
.SizeOfOptionalHeader
< sizeof(IMAGE_OPTIONAL_HEADER32
);
348 nt32
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
&&
349 nt32
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].Size
)
350 cor_header
= section_data
;
352 ok( (char *)image
.TransferAddress
== (char *)entry_point
||
353 (S(U(image
)).ImageDynamicallyRelocated
&& LOWORD(image
.TransferAddress
) == LOWORD(entry_point
)),
354 "%u: TransferAddress wrong %p / %p (%08x)\n", id
,
355 image
.TransferAddress
, entry_point
, nt_header
->OptionalHeader
.AddressOfEntryPoint
);
356 ok( image
.ZeroBits
== 0, "%u: ZeroBits wrong %08x\n", id
, image
.ZeroBits
);
357 ok( image
.MaximumStackSize
== max_stack
|| broken(truncated
),
358 "%u: MaximumStackSize wrong %lx / %lx\n", id
, image
.MaximumStackSize
, max_stack
);
359 ok( image
.CommittedStackSize
== commit_stack
|| broken(truncated
),
360 "%u: CommittedStackSize wrong %lx / %lx\n", id
, image
.CommittedStackSize
, commit_stack
);
362 ok( !image
.SubSystemType
|| broken(truncated
),
363 "%u: SubSystemType wrong %08x / 00000000\n", id
, image
.SubSystemType
);
365 ok( image
.SubSystemType
== nt_header
->OptionalHeader
.Subsystem
,
366 "%u: SubSystemType wrong %08x / %08x\n", id
,
367 image
.SubSystemType
, nt_header
->OptionalHeader
.Subsystem
);
368 ok( image
.SubsystemVersionLow
== nt_header
->OptionalHeader
.MinorSubsystemVersion
,
369 "%u: SubsystemVersionLow wrong %04x / %04x\n", id
,
370 image
.SubsystemVersionLow
, nt_header
->OptionalHeader
.MinorSubsystemVersion
);
371 ok( image
.SubsystemVersionHigh
== nt_header
->OptionalHeader
.MajorSubsystemVersion
,
372 "%u: SubsystemVersionHigh wrong %04x / %04x\n", id
,
373 image
.SubsystemVersionHigh
, nt_header
->OptionalHeader
.MajorSubsystemVersion
);
374 ok( image
.ImageCharacteristics
== nt_header
->FileHeader
.Characteristics
,
375 "%u: ImageCharacteristics wrong %04x / %04x\n", id
,
376 image
.ImageCharacteristics
, nt_header
->FileHeader
.Characteristics
);
377 ok( image
.DllCharacteristics
== nt_header
->OptionalHeader
.DllCharacteristics
|| broken(truncated
),
378 "%u: DllCharacteristics wrong %04x / %04x\n", id
,
379 image
.DllCharacteristics
, nt_header
->OptionalHeader
.DllCharacteristics
);
380 ok( image
.Machine
== nt_header
->FileHeader
.Machine
, "%u: Machine wrong %04x / %04x\n", id
,
381 image
.Machine
, nt_header
->FileHeader
.Machine
);
382 ok( image
.LoaderFlags
== (cor_header
!= NULL
), "%u: LoaderFlags wrong %08x\n", id
, image
.LoaderFlags
);
383 ok( image
.ImageFileSize
== file_size
|| broken(!image
.ImageFileSize
), /* winxpsp1 */
384 "%u: ImageFileSize wrong %08x / %08x\n", id
, image
.ImageFileSize
, file_size
);
385 ok( image
.CheckSum
== nt_header
->OptionalHeader
.CheckSum
, "%u: CheckSum wrong %08x / %08x\n", id
,
386 image
.CheckSum
, nt_header
->OptionalHeader
.CheckSum
);
388 if (nt_header
->OptionalHeader
.SizeOfCode
|| nt_header
->OptionalHeader
.AddressOfEntryPoint
)
389 ok( image
.ImageContainsCode
== TRUE
, "%u: ImageContainsCode wrong %u\n", id
,
390 image
.ImageContainsCode
);
391 else if ((nt_header
->OptionalHeader
.SectionAlignment
% page_size
) ||
392 (nt_header
->FileHeader
.NumberOfSections
== 1 &&
393 (section
.Characteristics
& IMAGE_SCN_MEM_EXECUTE
)))
394 ok( image
.ImageContainsCode
== TRUE
|| broken(!image
.ImageContainsCode
), /* <= win8 */
395 "%u: ImageContainsCode wrong %u\n", id
, image
.ImageContainsCode
);
397 ok( !image
.ImageContainsCode
, "%u: ImageContainsCode wrong %u\n", id
, image
.ImageContainsCode
);
400 (cor_header
->Flags
& COMIMAGE_FLAGS_ILONLY
) &&
401 (cor_header
->MajorRuntimeVersion
> 2 ||
402 (cor_header
->MajorRuntimeVersion
== 2 && cor_header
->MinorRuntimeVersion
>= 5)))
404 ok( S(U(image
)).ComPlusILOnly
|| broken(is_winxp
),
405 "%u: wrong ComPlusILOnly flags %02x\n", id
, U(image
).ImageFlags
);
406 if (nt_header
->OptionalHeader
.Magic
== IMAGE_NT_OPTIONAL_HDR32_MAGIC
&&
407 !(cor_header
->Flags
& COMIMAGE_FLAGS_32BITREQUIRED
))
408 ok( S(U(image
)).ComPlusNativeReady
|| broken(is_winxp
),
409 "%u: wrong ComPlusNativeReady flags %02x\n", id
, U(image
).ImageFlags
);
411 ok( !S(U(image
)).ComPlusNativeReady
,
412 "%u: wrong ComPlusNativeReady flags %02x\n", id
, U(image
).ImageFlags
);
416 ok( !S(U(image
)).ComPlusILOnly
, "%u: wrong ComPlusILOnly flags %02x\n", id
, U(image
).ImageFlags
);
417 ok( !S(U(image
)).ComPlusNativeReady
, "%u: wrong ComPlusNativeReady flags %02x\n", id
, U(image
).ImageFlags
);
419 if (!(nt_header
->OptionalHeader
.SectionAlignment
% page_size
))
420 ok( !S(U(image
)).ImageMappedFlat
, "%u: wrong ImageMappedFlat flags %02x\n", id
, U(image
).ImageFlags
);
423 /* winxp doesn't support any of the loader flags */
424 if (!S(U(image
)).ImageMappedFlat
) is_winxp
= TRUE
;
425 ok( S(U(image
)).ImageMappedFlat
|| broken(is_winxp
),
426 "%u: wrong ImageMappedFlat flags %02x\n", id
, U(image
).ImageFlags
);
428 if (!(nt_header
->OptionalHeader
.DllCharacteristics
& IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
))
429 ok( !S(U(image
)).ImageDynamicallyRelocated
|| broken( S(U(image
)).ComPlusILOnly
), /* <= win7 */
430 "%u: wrong ImageDynamicallyRelocated flags %02x\n", id
, U(image
).ImageFlags
);
431 else if (image
.ImageContainsCode
&& !cor_header
)
432 ok( S(U(image
)).ImageDynamicallyRelocated
|| broken(is_winxp
),
433 "%u: wrong ImageDynamicallyRelocated flags %02x\n", id
, U(image
).ImageFlags
);
435 ok( !S(U(image
)).ImageDynamicallyRelocated
|| broken(TRUE
), /* <= win8 */
436 "%u: wrong ImageDynamicallyRelocated flags %02x\n", id
, U(image
).ImageFlags
);
437 ok( !S(U(image
)).BaseBelow4gb
, "%u: wrong BaseBelow4gb flags %02x\n", id
, U(image
).ImageFlags
);
439 /* FIXME: needs more work: */
442 map_size
.QuadPart
= (nt_header
->OptionalHeader
.SizeOfImage
+ page_size
- 1) & ~(page_size
- 1);
443 status
= pNtQuerySection( mapping
, SectionBasicInformation
, &info
, sizeof(info
), NULL
);
444 ok( !status
, "NtQuerySection failed err %x\n", status
);
445 ok( info
.Size
.QuadPart
== map_size
.QuadPart
, "NtQuerySection wrong size %x%08x / %x%08x\n",
446 info
.Size
.u
.HighPart
, info
.Size
.u
.LowPart
, map_size
.u
.HighPart
, map_size
.u
.LowPart
);
447 CloseHandle( mapping
);
449 map_size
.QuadPart
= (nt_header
->OptionalHeader
.SizeOfImage
+ page_size
- 1) & ~(page_size
- 1);
450 status
= pNtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_MAP_READ
| SECTION_QUERY
,
451 NULL
, &map_size
, PAGE_READONLY
, SEC_IMAGE
, file
);
452 ok( !status
, "%u: NtCreateSection failed err %x\n", id
, status
);
453 status
= pNtQuerySection( mapping
, SectionBasicInformation
, &info
, sizeof(info
), NULL
);
454 ok( !status
, "NtQuerySection failed err %x\n", status
);
455 ok( info
.Size
.QuadPart
== map_size
.QuadPart
, "NtQuerySection wrong size %x%08x / %x%08x\n",
456 info
.Size
.u
.HighPart
, info
.Size
.u
.LowPart
, map_size
.u
.HighPart
, map_size
.u
.LowPart
);
457 CloseHandle( mapping
);
460 status
= pNtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_MAP_READ
| SECTION_QUERY
,
461 NULL
, &map_size
, PAGE_READONLY
, SEC_IMAGE
, file
);
462 ok( status
== STATUS_SECTION_TOO_BIG
, "%u: NtCreateSection failed err %x\n", id
, status
);
464 SetFilePointerEx( file
, map_size
, NULL
, FILE_BEGIN
);
465 SetEndOfFile( file
);
466 status
= pNtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_MAP_READ
| SECTION_QUERY
,
467 NULL
, &map_size
, PAGE_READONLY
, SEC_IMAGE
, file
);
468 ok( status
== STATUS_SECTION_TOO_BIG
, "%u: NtCreateSection failed err %x\n", id
, status
);
470 map_size
.QuadPart
= 1;
471 status
= pNtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_MAP_READ
| SECTION_QUERY
,
472 NULL
, &map_size
, PAGE_READONLY
, SEC_IMAGE
, file
);
473 ok( !status
, "%u: NtCreateSection failed err %x\n", id
, status
);
474 status
= pNtQuerySection( mapping
, SectionBasicInformation
, &info
, sizeof(info
), NULL
);
475 ok( !status
, "NtQuerySection failed err %x\n", status
);
476 ok( info
.Size
.QuadPart
== map_size
.QuadPart
, "NtQuerySection wrong size %x%08x / %x%08x\n",
477 info
.Size
.u
.HighPart
, info
.Size
.u
.LowPart
, map_size
.u
.HighPart
, map_size
.u
.LowPart
);
478 CloseHandle( mapping
);
481 return image
.ImageContainsCode
&& (!cor_header
|| !(cor_header
->Flags
& COMIMAGE_FLAGS_ILONLY
));
484 /* helper to test image section mapping */
485 static NTSTATUS
map_image_section( const IMAGE_NT_HEADERS
*nt_header
, const IMAGE_SECTION_HEADER
*sections
,
486 const void *section_data
, int line
)
488 char dll_name
[MAX_PATH
];
496 file_size
= create_test_dll_sections( &dos_header
, nt_header
, sections
, section_data
, dll_name
);
498 file
= CreateFileA(dll_name
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
499 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFile error %d\n", GetLastError());
501 size
.QuadPart
= file_size
;
502 status
= pNtCreateSection(&map
, STANDARD_RIGHTS_REQUIRED
| SECTION_MAP_READ
| SECTION_QUERY
,
503 NULL
, &size
, PAGE_READONLY
, SEC_IMAGE
, file
);
506 SECTION_BASIC_INFORMATION info
;
507 SIZE_T info_size
= 0xdeadbeef;
508 NTSTATUS ret
= pNtQuerySection( map
, SectionBasicInformation
, &info
, sizeof(info
), &info_size
);
509 ok( !ret
, "NtQuerySection failed err %x\n", ret
);
510 ok( info_size
== sizeof(info
), "NtQuerySection wrong size %lu\n", info_size
);
511 ok( info
.Attributes
== (SEC_IMAGE
| SEC_FILE
), "NtQuerySection wrong attr %x\n", info
.Attributes
);
512 ok( info
.BaseAddress
== NULL
, "NtQuerySection wrong base %p\n", info
.BaseAddress
);
513 ok( info
.Size
.QuadPart
== file_size
, "NtQuerySection wrong size %x%08x / %08x\n",
514 info
.Size
.u
.HighPart
, info
.Size
.u
.LowPart
, file_size
);
515 has_code
= query_image_section( line
, dll_name
, nt_header
, section_data
);
516 /* test loading dll of wrong 32/64 bitness */
517 if (nt_header
->OptionalHeader
.Magic
== (is_win64
? IMAGE_NT_OPTIONAL_HDR32_MAGIC
518 : IMAGE_NT_OPTIONAL_HDR64_MAGIC
))
520 SetLastError( 0xdeadbeef );
521 mod
= LoadLibraryExA( dll_name
, 0, DONT_RESOLVE_DLL_REFERENCES
);
522 if (!has_code
&& nt_header
->OptionalHeader
.Magic
== IMAGE_NT_OPTIONAL_HDR32_MAGIC
)
524 BOOL il_only
= FALSE
;
525 if (((const IMAGE_NT_HEADERS32
*)nt_header
)->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
)
527 const IMAGE_COR20_HEADER
*cor_header
= section_data
;
528 il_only
= (cor_header
->Flags
& COMIMAGE_FLAGS_ILONLY
) != 0;
530 ok( mod
!= NULL
|| broken(il_only
), /* <= win7 */
531 "%u: loading failed err %u\n", line
, GetLastError() );
535 ok( !mod
, "%u: loading succeeded\n", line
);
536 ok( GetLastError() == ERROR_BAD_EXE_FORMAT
, "%u: wrong error %u\n", line
, GetLastError() );
538 if (mod
) FreeLibrary( mod
);
541 if (map
) CloseHandle( map
);
543 DeleteFileA( dll_name
);
548 static void test_Loader(void)
550 static const struct test_data
552 DWORD size_of_dos_header
;
553 WORD number_of_sections
, size_of_optional_header
;
554 DWORD section_alignment
, file_alignment
;
555 DWORD size_of_image
, size_of_headers
;
556 DWORD errors
[4]; /* 0 means LoadLibrary should succeed */
559 { sizeof(dos_header
),
561 { ERROR_BAD_EXE_FORMAT
}
563 { sizeof(dos_header
),
564 1, sizeof(IMAGE_OPTIONAL_HEADER
), 0x1000, 0x1000,
565 sizeof(dos_header
) + sizeof(nt_header_template
) + sizeof(IMAGE_SECTION_HEADER
) + 0xe00,
566 sizeof(dos_header
) + sizeof(nt_header_template
) + sizeof(IMAGE_SECTION_HEADER
),
567 { ERROR_BAD_EXE_FORMAT
} /* XP doesn't like too small image size */
569 { sizeof(dos_header
),
570 1, sizeof(IMAGE_OPTIONAL_HEADER
), 0x1000, 0x1000,
571 sizeof(dos_header
) + sizeof(nt_header_template
) + sizeof(IMAGE_SECTION_HEADER
) + 0x1000,
572 sizeof(dos_header
) + sizeof(nt_header_template
) + sizeof(IMAGE_SECTION_HEADER
),
575 { sizeof(dos_header
),
576 1, sizeof(IMAGE_OPTIONAL_HEADER
), 0x1000, 0x1000,
581 { sizeof(dos_header
),
582 1, sizeof(IMAGE_OPTIONAL_HEADER
), 0x200, 0x200,
583 sizeof(dos_header
) + sizeof(nt_header_template
) + sizeof(IMAGE_SECTION_HEADER
) + 0x200,
584 sizeof(dos_header
) + sizeof(nt_header_template
) + sizeof(IMAGE_SECTION_HEADER
),
585 { ERROR_SUCCESS
, ERROR_INVALID_ADDRESS
} /* vista is more strict */
587 { sizeof(dos_header
),
588 1, sizeof(IMAGE_OPTIONAL_HEADER
), 0x200, 0x1000,
589 sizeof(dos_header
) + sizeof(nt_header_template
) + sizeof(IMAGE_SECTION_HEADER
) + 0x1000,
590 sizeof(dos_header
) + sizeof(nt_header_template
) + sizeof(IMAGE_SECTION_HEADER
),
591 { ERROR_BAD_EXE_FORMAT
} /* XP doesn't like alignments */
593 { sizeof(dos_header
),
594 1, sizeof(IMAGE_OPTIONAL_HEADER
), 0x1000, 0x200,
595 sizeof(dos_header
) + sizeof(nt_header_template
) + sizeof(IMAGE_SECTION_HEADER
) + 0x1000,
596 sizeof(dos_header
) + sizeof(nt_header_template
) + sizeof(IMAGE_SECTION_HEADER
),
599 { sizeof(dos_header
),
600 1, sizeof(IMAGE_OPTIONAL_HEADER
), 0x1000, 0x200,
601 sizeof(dos_header
) + sizeof(nt_header_template
) + sizeof(IMAGE_SECTION_HEADER
) + 0x1000,
605 /* Mandatory are all fields up to SizeOfHeaders, everything else
606 * is really optional (at least that's true for XP).
608 { sizeof(dos_header
),
609 1, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER
, CheckSum
), 0x200, 0x200,
610 sizeof(dos_header
) + sizeof(DWORD
) + sizeof(IMAGE_FILE_HEADER
) + FIELD_OFFSET(IMAGE_OPTIONAL_HEADER
, CheckSum
) + sizeof(IMAGE_SECTION_HEADER
) + 0x10,
611 sizeof(dos_header
) + sizeof(DWORD
) + sizeof(IMAGE_FILE_HEADER
) + FIELD_OFFSET(IMAGE_OPTIONAL_HEADER
, CheckSum
) + sizeof(IMAGE_SECTION_HEADER
),
612 { ERROR_SUCCESS
, ERROR_BAD_EXE_FORMAT
, ERROR_INVALID_ADDRESS
,
615 { sizeof(dos_header
),
616 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER
, CheckSum
), 0x200, 0x200,
617 0xd0, /* beyond of the end of file */
618 0xc0, /* beyond of the end of file */
619 { ERROR_SUCCESS
, ERROR_BAD_EXE_FORMAT
} /* vista is more strict */
621 { sizeof(dos_header
),
622 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER
, CheckSum
), 0x200, 0x200,
625 { ERROR_SUCCESS
, ERROR_BAD_EXE_FORMAT
} /* vista is more strict */
627 { sizeof(dos_header
),
628 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER
, CheckSum
), 0x200, 0x200,
631 { ERROR_SUCCESS
, ERROR_BAD_EXE_FORMAT
} /* vista is more strict */
633 #if 0 /* not power of 2 alignments need more test cases */
634 { sizeof(dos_header
),
635 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER
, CheckSum
), 0x300, 0x300,
638 { ERROR_BAD_EXE_FORMAT
} /* alignment is not power of 2 */
641 { sizeof(dos_header
),
642 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER
, CheckSum
), 4, 4,
645 { ERROR_SUCCESS
, ERROR_BAD_EXE_FORMAT
} /* vista is more strict */
647 { sizeof(dos_header
),
648 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER
, CheckSum
), 1, 1,
651 { ERROR_SUCCESS
, ERROR_BAD_EXE_FORMAT
} /* vista is more strict */
653 { sizeof(dos_header
),
654 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER
, CheckSum
), 0x200, 0x200,
657 { ERROR_BAD_EXE_FORMAT
} /* image size == 0 -> failure */
659 /* the following data mimics the PE image which upack creates */
661 1, 0x148, 0x1000, 0x200,
662 sizeof(dos_header
) + sizeof(nt_header_template
) + sizeof(IMAGE_SECTION_HEADER
) + 0x1000,
666 /* Minimal PE image that XP is able to load: 92 bytes */
668 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER
, CheckSum
),
669 0x04 /* also serves as e_lfanew in the truncated MZ header */, 0x04,
672 { ERROR_SUCCESS
, ERROR_BAD_EXE_FORMAT
} /* vista is more strict */
674 /* Minimal PE image that Windows7 is able to load: 268 bytes */
676 0, 0xf0, /* optional header size just forces 0xf0 bytes to be written,
677 0 or another number don't change the behaviour, what really
678 matters is file size regardless of values in the headers */
679 0x04 /* also serves as e_lfanew in the truncated MZ header */, 0x04,
680 0x40, /* minimal image size that Windows7 accepts */
688 HMODULE hlib
, hlib_as_data_file
;
689 char dll_name
[MAX_PATH
];
693 WORD alt_machine
, orig_machine
= nt_header_template
.FileHeader
.Machine
;
694 IMAGE_NT_HEADERS nt_header
;
695 IMAGE_COR20_HEADER cor_header
;
697 /* prevent displaying of the "Unable to load this DLL" message box */
698 SetErrorMode(SEM_FAILCRITICALERRORS
);
700 for (i
= 0; i
< ARRAY_SIZE(td
); i
++)
702 nt_header
= nt_header_template
;
703 nt_header
.FileHeader
.NumberOfSections
= td
[i
].number_of_sections
;
704 nt_header
.FileHeader
.SizeOfOptionalHeader
= td
[i
].size_of_optional_header
;
706 nt_header
.OptionalHeader
.SectionAlignment
= td
[i
].section_alignment
;
707 nt_header
.OptionalHeader
.FileAlignment
= td
[i
].file_alignment
;
708 nt_header
.OptionalHeader
.SizeOfImage
= td
[i
].size_of_image
;
709 nt_header
.OptionalHeader
.SizeOfHeaders
= td
[i
].size_of_headers
;
711 file_size
= create_test_dll( &dos_header
, td
[i
].size_of_dos_header
, &nt_header
, dll_name
);
713 SetLastError(0xdeadbeef);
714 hlib
= LoadLibraryA(dll_name
);
717 MEMORY_BASIC_INFORMATION info
;
720 ok( td
[i
].errors
[0] == ERROR_SUCCESS
, "%d: should have failed\n", i
);
722 SetLastError(0xdeadbeef);
723 size
= VirtualQuery(hlib
, &info
, sizeof(info
));
724 ok(size
== sizeof(info
),
725 "%d: VirtualQuery error %d\n", i
, GetLastError());
726 ok(info
.BaseAddress
== hlib
, "%d: %p != %p\n", i
, info
.BaseAddress
, hlib
);
727 ok(info
.AllocationBase
== hlib
, "%d: %p != %p\n", i
, info
.AllocationBase
, hlib
);
728 ok(info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i
, info
.AllocationProtect
);
729 ok(info
.RegionSize
== ALIGN_SIZE(nt_header
.OptionalHeader
.SizeOfImage
, page_size
), "%d: got %lx != expected %x\n",
730 i
, info
.RegionSize
, ALIGN_SIZE(nt_header
.OptionalHeader
.SizeOfImage
, page_size
));
731 ok(info
.State
== MEM_COMMIT
, "%d: %x != MEM_COMMIT\n", i
, info
.State
);
732 if (nt_header
.OptionalHeader
.SectionAlignment
< page_size
)
733 ok(info
.Protect
== PAGE_EXECUTE_WRITECOPY
, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i
, info
.Protect
);
735 ok(info
.Protect
== PAGE_READONLY
, "%d: %x != PAGE_READONLY\n", i
, info
.Protect
);
736 ok(info
.Type
== SEC_IMAGE
, "%d: %x != SEC_IMAGE\n", i
, info
.Type
);
738 SetLastError(0xdeadbeef);
739 ptr
= VirtualAlloc(hlib
, page_size
, MEM_COMMIT
, info
.Protect
);
740 ok(!ptr
, "%d: VirtualAlloc should fail\n", i
);
741 ok(GetLastError() == ERROR_ACCESS_DENIED
, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i
, GetLastError());
743 SetLastError(0xdeadbeef);
744 size
= VirtualQuery((char *)hlib
+ info
.RegionSize
, &info
, sizeof(info
));
745 ok(size
== sizeof(info
),
746 "%d: VirtualQuery error %d\n", i
, GetLastError());
747 if (nt_header
.OptionalHeader
.SectionAlignment
== page_size
||
748 nt_header
.OptionalHeader
.SectionAlignment
== nt_header
.OptionalHeader
.FileAlignment
)
750 ok(info
.BaseAddress
== (char *)hlib
+ ALIGN_SIZE(nt_header
.OptionalHeader
.SizeOfImage
, page_size
), "%d: got %p != expected %p\n",
751 i
, info
.BaseAddress
, (char *)hlib
+ ALIGN_SIZE(nt_header
.OptionalHeader
.SizeOfImage
, page_size
));
752 ok(info
.AllocationBase
== 0, "%d: %p != 0\n", i
, info
.AllocationBase
);
753 ok(info
.AllocationProtect
== 0, "%d: %x != 0\n", i
, info
.AllocationProtect
);
754 /*ok(info.RegionSize == not_practical_value, "%d: %lx != not_practical_value\n", i, info.RegionSize);*/
755 ok(info
.State
== MEM_FREE
, "%d: %x != MEM_FREE\n", i
, info
.State
);
756 ok(info
.Type
== 0, "%d: %x != 0\n", i
, info
.Type
);
757 ok(info
.Protect
== PAGE_NOACCESS
, "%d: %x != PAGE_NOACCESS\n", i
, info
.Protect
);
761 ok(info
.Protect
== PAGE_EXECUTE_WRITECOPY
, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i
, info
.Protect
);
762 ok(info
.BaseAddress
== hlib
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, hlib
);
763 ok(info
.AllocationBase
== hlib
, "%d: %p != %p\n", i
, info
.AllocationBase
, hlib
);
764 ok(info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i
, info
.AllocationProtect
);
765 ok(info
.RegionSize
== ALIGN_SIZE(file_size
, page_size
), "%d: got %lx != expected %x\n",
766 i
, info
.RegionSize
, ALIGN_SIZE(file_size
, page_size
));
767 ok(info
.State
== MEM_COMMIT
, "%d: %x != MEM_COMMIT\n", i
, info
.State
);
768 ok(info
.Protect
== PAGE_READONLY
, "%d: %x != PAGE_READONLY\n", i
, info
.Protect
);
769 ok(info
.Type
== SEC_IMAGE
, "%d: %x != SEC_IMAGE\n", i
, info
.Type
);
772 /* header: check the zeroing of alignment */
773 if (nt_header
.OptionalHeader
.SectionAlignment
>= page_size
)
777 start
= (const char *)hlib
+ nt_header
.OptionalHeader
.SizeOfHeaders
;
778 size
= ALIGN_SIZE((ULONG_PTR
)start
, page_size
) - (ULONG_PTR
)start
;
779 ok(!memcmp(start
, filler
, size
), "%d: header alignment is not cleared\n", i
);
782 if (nt_header
.FileHeader
.NumberOfSections
)
784 SetLastError(0xdeadbeef);
785 size
= VirtualQuery((char *)hlib
+ section
.VirtualAddress
, &info
, sizeof(info
));
786 ok(size
== sizeof(info
),
787 "%d: VirtualQuery error %d\n", i
, GetLastError());
788 if (nt_header
.OptionalHeader
.SectionAlignment
< page_size
)
790 ok(info
.BaseAddress
== hlib
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, hlib
);
791 ok(info
.RegionSize
== ALIGN_SIZE(nt_header
.OptionalHeader
.SizeOfImage
, page_size
), "%d: got %lx != expected %x\n",
792 i
, info
.RegionSize
, ALIGN_SIZE(nt_header
.OptionalHeader
.SizeOfImage
, page_size
));
793 ok(info
.Protect
== PAGE_EXECUTE_WRITECOPY
, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i
, info
.Protect
);
797 ok(info
.BaseAddress
== (char *)hlib
+ section
.VirtualAddress
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, (char *)hlib
+ section
.VirtualAddress
);
798 ok(info
.RegionSize
== ALIGN_SIZE(section
.Misc
.VirtualSize
, page_size
), "%d: got %lx != expected %x\n",
799 i
, info
.RegionSize
, ALIGN_SIZE(section
.Misc
.VirtualSize
, page_size
));
800 ok(info
.Protect
== PAGE_READONLY
, "%d: %x != PAGE_READONLY\n", i
, info
.Protect
);
802 ok(info
.AllocationBase
== hlib
, "%d: %p != %p\n", i
, info
.AllocationBase
, hlib
);
803 ok(info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i
, info
.AllocationProtect
);
804 ok(info
.State
== MEM_COMMIT
, "%d: %x != MEM_COMMIT\n", i
, info
.State
);
805 ok(info
.Type
== SEC_IMAGE
, "%d: %x != SEC_IMAGE\n", i
, info
.Type
);
807 if (nt_header
.OptionalHeader
.SectionAlignment
>= page_size
)
808 ok(!memcmp((const char *)hlib
+ section
.VirtualAddress
+ section
.PointerToRawData
, &nt_header
, section
.SizeOfRawData
), "wrong section data\n");
810 ok(!memcmp((const char *)hlib
+ section
.PointerToRawData
, section_data
, section
.SizeOfRawData
), "wrong section data\n");
812 /* check the zeroing of alignment */
813 if (nt_header
.OptionalHeader
.SectionAlignment
>= page_size
)
817 start
= (const char *)hlib
+ section
.VirtualAddress
+ section
.PointerToRawData
+ section
.SizeOfRawData
;
818 size
= ALIGN_SIZE((ULONG_PTR
)start
, page_size
) - (ULONG_PTR
)start
;
819 ok(memcmp(start
, filler
, size
), "%d: alignment should not be cleared\n", i
);
822 SetLastError(0xdeadbeef);
823 ptr
= VirtualAlloc((char *)hlib
+ section
.VirtualAddress
, page_size
, MEM_COMMIT
, info
.Protect
);
824 ok(!ptr
, "%d: VirtualAlloc should fail\n", i
);
825 ok(GetLastError() == ERROR_ACCESS_DENIED
|| GetLastError() == ERROR_INVALID_ADDRESS
,
826 "%d: expected ERROR_ACCESS_DENIED, got %d\n", i
, GetLastError());
829 SetLastError(0xdeadbeef);
830 hlib_as_data_file
= LoadLibraryExA(dll_name
, 0, LOAD_LIBRARY_AS_DATAFILE
);
831 ok(hlib_as_data_file
!= 0, "LoadLibraryEx error %u\n", GetLastError());
832 ok(hlib_as_data_file
== hlib
, "hlib_as_file and hlib are different\n");
834 SetLastError(0xdeadbeef);
835 ret
= FreeLibrary(hlib
);
836 ok(ret
, "FreeLibrary error %d\n", GetLastError());
838 SetLastError(0xdeadbeef);
839 hlib
= GetModuleHandleA(dll_name
);
840 ok(hlib
!= 0, "GetModuleHandle error %u\n", GetLastError());
842 SetLastError(0xdeadbeef);
843 ret
= FreeLibrary(hlib_as_data_file
);
844 ok(ret
, "FreeLibrary error %d\n", GetLastError());
846 hlib
= GetModuleHandleA(dll_name
);
847 ok(!hlib
, "GetModuleHandle should fail\n");
849 SetLastError(0xdeadbeef);
850 hlib_as_data_file
= LoadLibraryExA(dll_name
, 0, LOAD_LIBRARY_AS_DATAFILE
);
851 ok(hlib_as_data_file
!= 0, "LoadLibraryEx error %u\n", GetLastError());
852 ok(((ULONG_PTR
)hlib_as_data_file
& 3) == 1, "hlib_as_data_file got %p\n", hlib_as_data_file
);
854 hlib
= GetModuleHandleA(dll_name
);
855 ok(!hlib
, "GetModuleHandle should fail\n");
857 SetLastError(0xdeadbeef);
858 h
= CreateFileA( dll_name
, GENERIC_WRITE
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0 );
859 ok( h
!= INVALID_HANDLE_VALUE
, "open failed err %u\n", GetLastError() );
862 SetLastError(0xdeadbeef);
863 ret
= FreeLibrary(hlib_as_data_file
);
864 ok(ret
, "FreeLibrary error %d\n", GetLastError());
866 SetLastError(0xdeadbeef);
867 hlib_as_data_file
= LoadLibraryExA(dll_name
, 0, LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE
);
868 if (!((ULONG_PTR
)hlib_as_data_file
& 3) || /* winxp */
869 (!hlib_as_data_file
&& GetLastError() == ERROR_INVALID_PARAMETER
)) /* w2k3 */
871 win_skip( "LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE not supported\n" );
872 FreeLibrary(hlib_as_data_file
);
876 ok(hlib_as_data_file
!= 0, "LoadLibraryEx error %u\n", GetLastError());
878 SetLastError(0xdeadbeef);
879 h
= CreateFileA( dll_name
, GENERIC_WRITE
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0 );
880 ok( h
== INVALID_HANDLE_VALUE
, "open succeeded\n" );
881 ok( GetLastError() == ERROR_SHARING_VIOLATION
, "wrong error %u\n", GetLastError() );
884 SetLastError(0xdeadbeef);
885 h
= CreateFileA( dll_name
, GENERIC_READ
| DELETE
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0 );
886 ok( h
!= INVALID_HANDLE_VALUE
, "open failed err %u\n", GetLastError() );
889 SetLastError(0xdeadbeef);
890 ret
= FreeLibrary(hlib_as_data_file
);
891 ok(ret
, "FreeLibrary error %d\n", GetLastError());
894 SetLastError(0xdeadbeef);
895 hlib_as_data_file
= LoadLibraryExA(dll_name
, 0, LOAD_LIBRARY_AS_IMAGE_RESOURCE
);
896 if (!((ULONG_PTR
)hlib_as_data_file
& 3) || /* winxp */
897 (!hlib_as_data_file
&& GetLastError() == ERROR_INVALID_PARAMETER
)) /* w2k3 */
899 win_skip( "LOAD_LIBRARY_AS_IMAGE_RESOURCE not supported\n" );
900 FreeLibrary(hlib_as_data_file
);
904 ok(hlib_as_data_file
!= 0, "LoadLibraryEx error %u\n", GetLastError());
905 ok(((ULONG_PTR
)hlib_as_data_file
& 3) == 2, "hlib_as_data_file got %p\n",
908 hlib
= GetModuleHandleA(dll_name
);
909 ok(!hlib
, "GetModuleHandle should fail\n");
911 SetLastError(0xdeadbeef);
912 ret
= FreeLibrary(hlib_as_data_file
);
913 ok(ret
, "FreeLibrary error %d\n", GetLastError());
916 query_image_section( i
, dll_name
, &nt_header
, NULL
);
924 for (error_index
= 0;
925 ! error_match
&& error_index
< ARRAY_SIZE(td
[i
].errors
);
928 error_match
= td
[i
].errors
[error_index
] == GetLastError();
930 ok(error_match
, "%d: unexpected error %d\n", i
, GetLastError());
933 SetLastError(0xdeadbeef);
934 ret
= DeleteFileA(dll_name
);
935 ok(ret
, "DeleteFile error %d\n", GetLastError());
938 nt_header
= nt_header_template
;
939 nt_header
.FileHeader
.NumberOfSections
= 1;
940 nt_header
.FileHeader
.SizeOfOptionalHeader
= sizeof(IMAGE_OPTIONAL_HEADER
);
942 nt_header
.OptionalHeader
.SectionAlignment
= page_size
;
943 nt_header
.OptionalHeader
.AddressOfEntryPoint
= 0x1234;
944 nt_header
.OptionalHeader
.DllCharacteristics
= IMAGE_DLLCHARACTERISTICS_NX_COMPAT
;
945 nt_header
.OptionalHeader
.FileAlignment
= page_size
;
946 nt_header
.OptionalHeader
.SizeOfHeaders
= sizeof(dos_header
) + sizeof(nt_header
) + sizeof(IMAGE_SECTION_HEADER
);
947 nt_header
.OptionalHeader
.SizeOfImage
= sizeof(dos_header
) + sizeof(nt_header
) + sizeof(IMAGE_SECTION_HEADER
) + page_size
;
949 section
.SizeOfRawData
= sizeof(section_data
);
950 section
.PointerToRawData
= page_size
;
951 section
.VirtualAddress
= page_size
;
952 section
.Misc
.VirtualSize
= page_size
;
954 status
= map_image_section( &nt_header
, §ion
, section_data
, __LINE__
);
955 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
957 nt_header
.OptionalHeader
.DllCharacteristics
= IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
;
958 status
= map_image_section( &nt_header
, §ion
, section_data
, __LINE__
);
959 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
961 nt_header
.OptionalHeader
.SizeOfCode
= 0x1000;
962 status
= map_image_section( &nt_header
, §ion
, section_data
, __LINE__
);
963 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
964 nt_header
.OptionalHeader
.SizeOfCode
= 0;
965 nt_header
.OptionalHeader
.DllCharacteristics
= IMAGE_DLLCHARACTERISTICS_NX_COMPAT
;
967 dos_header
.e_magic
= 0;
968 status
= map_image_section( &nt_header
, §ion
, section_data
, __LINE__
);
969 ok( status
== STATUS_INVALID_IMAGE_NOT_MZ
, "NtCreateSection error %08x\n", status
);
971 dos_header
.e_magic
= IMAGE_DOS_SIGNATURE
;
972 nt_header
.Signature
= IMAGE_OS2_SIGNATURE
;
973 status
= map_image_section( &nt_header
, §ion
, section_data
, __LINE__
);
974 ok( status
== STATUS_INVALID_IMAGE_NE_FORMAT
, "NtCreateSection error %08x\n", status
);
975 for (i
= 0; i
< 16; i
++)
977 ((IMAGE_OS2_HEADER
*)&nt_header
)->ne_exetyp
= i
;
978 status
= map_image_section( &nt_header
, §ion
, section_data
, __LINE__
);
982 ok( status
== STATUS_INVALID_IMAGE_WIN_16
, "NtCreateSection %u error %08x\n", i
, status
);
985 ok( status
== STATUS_INVALID_IMAGE_PROTECT
, "NtCreateSection %u error %08x\n", i
, status
);
988 ok( status
== STATUS_INVALID_IMAGE_NE_FORMAT
, "NtCreateSection %u error %08x\n", i
, status
);
992 ((IMAGE_OS2_HEADER
*)&nt_header
)->ne_exetyp
= ((IMAGE_OS2_HEADER
*)&nt_header_template
)->ne_exetyp
;
994 nt_header
.Signature
= 0xdeadbeef;
995 status
= map_image_section( &nt_header
, §ion
, section_data
, __LINE__
);
996 ok( status
== STATUS_INVALID_IMAGE_PROTECT
, "NtCreateSection error %08x\n", status
);
998 nt_header
.Signature
= IMAGE_NT_SIGNATURE
;
999 nt_header
.OptionalHeader
.Magic
= 0xdead;
1000 status
= map_image_section( &nt_header
, §ion
, section_data
, __LINE__
);
1001 ok( status
== STATUS_INVALID_IMAGE_FORMAT
, "NtCreateSection error %08x\n", status
);
1003 nt_header
.OptionalHeader
.Magic
= IMAGE_NT_OPTIONAL_HDR_MAGIC
;
1004 nt_header
.FileHeader
.Machine
= 0xdead;
1005 status
= map_image_section( &nt_header
, §ion
, section_data
, __LINE__
);
1006 ok( status
== STATUS_INVALID_IMAGE_FORMAT
|| broken(status
== STATUS_SUCCESS
), /* win2k */
1007 "NtCreateSection error %08x\n", status
);
1009 nt_header
.FileHeader
.Machine
= IMAGE_FILE_MACHINE_UNKNOWN
;
1010 status
= map_image_section( &nt_header
, §ion
, section_data
, __LINE__
);
1011 ok( status
== STATUS_INVALID_IMAGE_FORMAT
|| broken(status
== STATUS_SUCCESS
), /* win2k */
1012 "NtCreateSection error %08x\n", status
);
1014 switch (orig_machine
)
1016 case IMAGE_FILE_MACHINE_I386
: alt_machine
= IMAGE_FILE_MACHINE_ARMNT
; break;
1017 case IMAGE_FILE_MACHINE_AMD64
: alt_machine
= IMAGE_FILE_MACHINE_ARM64
; break;
1018 case IMAGE_FILE_MACHINE_ARMNT
: alt_machine
= IMAGE_FILE_MACHINE_I386
; break;
1019 case IMAGE_FILE_MACHINE_ARM64
: alt_machine
= IMAGE_FILE_MACHINE_AMD64
; break;
1021 nt_header
.FileHeader
.Machine
= alt_machine
;
1022 status
= map_image_section( &nt_header
, §ion
, section_data
, __LINE__
);
1023 ok( status
== STATUS_INVALID_IMAGE_FORMAT
|| broken(status
== STATUS_SUCCESS
), /* win2k */
1024 "NtCreateSection error %08x\n", status
);
1026 switch (orig_machine
)
1028 case IMAGE_FILE_MACHINE_I386
: alt_machine
= IMAGE_FILE_MACHINE_AMD64
; break;
1029 case IMAGE_FILE_MACHINE_AMD64
: alt_machine
= IMAGE_FILE_MACHINE_I386
; break;
1030 case IMAGE_FILE_MACHINE_ARMNT
: alt_machine
= IMAGE_FILE_MACHINE_ARM64
; break;
1031 case IMAGE_FILE_MACHINE_ARM64
: alt_machine
= IMAGE_FILE_MACHINE_ARMNT
; break;
1033 nt_header
.FileHeader
.Machine
= alt_machine
;
1034 status
= map_image_section( &nt_header
, §ion
, section_data
, __LINE__
);
1035 ok( status
== STATUS_INVALID_IMAGE_FORMAT
|| broken(status
== STATUS_SUCCESS
), /* win2k */
1036 "NtCreateSection error %08x\n", status
);
1038 nt_header
.FileHeader
.Machine
= orig_machine
;
1039 nt_header
.OptionalHeader
.NumberOfRvaAndSizes
= IMAGE_NUMBEROF_DIRECTORY_ENTRIES
;
1040 nt_header
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
= page_size
;
1041 nt_header
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].Size
= sizeof(cor_header
);
1042 section
.SizeOfRawData
= sizeof(cor_header
);
1044 memset( &cor_header
, 0, sizeof(cor_header
) );
1045 cor_header
.cb
= sizeof(cor_header
);
1046 cor_header
.MajorRuntimeVersion
= 2;
1047 cor_header
.MinorRuntimeVersion
= 4;
1048 cor_header
.Flags
= COMIMAGE_FLAGS_ILONLY
;
1049 U(cor_header
).EntryPointToken
= 0xbeef;
1050 status
= map_image_section( &nt_header
, §ion
, &cor_header
, __LINE__
);
1051 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1053 cor_header
.MinorRuntimeVersion
= 5;
1054 status
= map_image_section( &nt_header
, §ion
, &cor_header
, __LINE__
);
1055 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1057 cor_header
.MajorRuntimeVersion
= 3;
1058 cor_header
.MinorRuntimeVersion
= 0;
1059 status
= map_image_section( &nt_header
, §ion
, &cor_header
, __LINE__
);
1060 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1062 cor_header
.Flags
= COMIMAGE_FLAGS_ILONLY
| COMIMAGE_FLAGS_32BITREQUIRED
;
1063 status
= map_image_section( &nt_header
, §ion
, &cor_header
, __LINE__
);
1064 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1066 cor_header
.Flags
= COMIMAGE_FLAGS_ILONLY
| COMIMAGE_FLAGS_32BITPREFERRED
;
1067 status
= map_image_section( &nt_header
, §ion
, &cor_header
, __LINE__
);
1068 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1070 cor_header
.Flags
= 0;
1071 status
= map_image_section( &nt_header
, §ion
, &cor_header
, __LINE__
);
1072 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1074 nt_header
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
= 1;
1075 nt_header
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].Size
= 1;
1076 status
= map_image_section( &nt_header
, §ion
, &cor_header
, __LINE__
);
1077 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1079 if (nt_header
.OptionalHeader
.Magic
== IMAGE_NT_OPTIONAL_HDR32_MAGIC
)
1081 IMAGE_NT_HEADERS64 nt64
;
1083 memset( &nt64
, 0, sizeof(nt64
) );
1084 nt64
.Signature
= IMAGE_NT_SIGNATURE
;
1085 nt64
.FileHeader
.Machine
= orig_machine
;
1086 nt64
.FileHeader
.NumberOfSections
= 1;
1087 nt64
.FileHeader
.SizeOfOptionalHeader
= sizeof(IMAGE_OPTIONAL_HEADER64
);
1088 nt64
.FileHeader
.Characteristics
= IMAGE_FILE_EXECUTABLE_IMAGE
| IMAGE_FILE_DLL
;
1089 nt64
.OptionalHeader
.Magic
= IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
1090 nt64
.OptionalHeader
.MajorLinkerVersion
= 1;
1091 nt64
.OptionalHeader
.SizeOfCode
= 0x1000;
1092 nt64
.OptionalHeader
.AddressOfEntryPoint
= 0x1000;
1093 nt64
.OptionalHeader
.ImageBase
= 0x10000000;
1094 nt64
.OptionalHeader
.SectionAlignment
= 0x1000;
1095 nt64
.OptionalHeader
.FileAlignment
= 0x1000;
1096 nt64
.OptionalHeader
.MajorOperatingSystemVersion
= 4;
1097 nt64
.OptionalHeader
.MajorImageVersion
= 1;
1098 nt64
.OptionalHeader
.MajorSubsystemVersion
= 4;
1099 nt64
.OptionalHeader
.SizeOfHeaders
= sizeof(dos_header
) + sizeof(nt64
) + sizeof(IMAGE_SECTION_HEADER
);
1100 nt64
.OptionalHeader
.SizeOfImage
= nt64
.OptionalHeader
.SizeOfHeaders
+ 0x1000;
1101 nt64
.OptionalHeader
.Subsystem
= IMAGE_SUBSYSTEM_WINDOWS_CUI
;
1102 nt64
.OptionalHeader
.SizeOfStackReserve
= 0x321000;
1103 nt64
.OptionalHeader
.SizeOfStackCommit
= 0x123000;
1104 section
.Characteristics
= IMAGE_SCN_CNT_CODE
| IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_EXECUTE
;
1106 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt64
, §ion
, section_data
, __LINE__
);
1107 ok( status
== (is_wow64
? STATUS_INVALID_IMAGE_FORMAT
: STATUS_INVALID_IMAGE_WIN_64
),
1108 "NtCreateSection error %08x\n", status
);
1110 switch (orig_machine
)
1112 case IMAGE_FILE_MACHINE_I386
: nt64
.FileHeader
.Machine
= IMAGE_FILE_MACHINE_ARM64
; break;
1113 case IMAGE_FILE_MACHINE_ARMNT
: nt64
.FileHeader
.Machine
= IMAGE_FILE_MACHINE_AMD64
; break;
1115 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt64
, §ion
, section_data
, __LINE__
);
1116 ok( status
== (is_wow64
? STATUS_INVALID_IMAGE_FORMAT
: STATUS_INVALID_IMAGE_WIN_64
),
1117 "NtCreateSection error %08x\n", status
);
1119 nt64
.FileHeader
.Machine
= alt_machine
;
1120 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt64
, §ion
, section_data
, __LINE__
);
1121 ok( status
== (is_wow64
? STATUS_SUCCESS
: STATUS_INVALID_IMAGE_WIN_64
),
1122 "NtCreateSection error %08x\n", status
);
1124 nt64
.OptionalHeader
.SizeOfCode
= 0;
1125 nt64
.OptionalHeader
.AddressOfEntryPoint
= 0x1000;
1126 section
.Characteristics
= IMAGE_SCN_MEM_READ
| IMAGE_SCN_CNT_CODE
;
1127 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt64
, §ion
, section_data
, __LINE__
);
1128 ok( status
== (is_wow64
? STATUS_SUCCESS
: STATUS_INVALID_IMAGE_WIN_64
),
1129 "NtCreateSection error %08x\n", status
);
1131 nt64
.OptionalHeader
.SizeOfCode
= 0;
1132 nt64
.OptionalHeader
.AddressOfEntryPoint
= 0;
1133 section
.Characteristics
= IMAGE_SCN_MEM_READ
| IMAGE_SCN_CNT_CODE
| IMAGE_SCN_MEM_EXECUTE
;
1134 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt64
, §ion
, section_data
, __LINE__
);
1135 ok( status
== (is_wow64
? STATUS_SUCCESS
: STATUS_INVALID_IMAGE_WIN_64
),
1136 "NtCreateSection error %08x\n", status
);
1138 nt64
.OptionalHeader
.SizeOfCode
= 0x1000;
1139 nt64
.OptionalHeader
.AddressOfEntryPoint
= 0;
1140 nt64
.OptionalHeader
.DllCharacteristics
= IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
;
1141 section
.Characteristics
= IMAGE_SCN_MEM_READ
| IMAGE_SCN_CNT_CODE
;
1142 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt64
, §ion
, section_data
, __LINE__
);
1143 ok( status
== (is_wow64
? STATUS_SUCCESS
: STATUS_INVALID_IMAGE_WIN_64
),
1144 "NtCreateSection error %08x\n", status
);
1146 nt64
.OptionalHeader
.SizeOfCode
= 0;
1147 nt64
.OptionalHeader
.AddressOfEntryPoint
= 0;
1148 section
.Characteristics
= IMAGE_SCN_MEM_READ
| IMAGE_SCN_CNT_CODE
;
1149 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt64
, §ion
, section_data
, __LINE__
);
1150 ok( status
== (is_wow64
? STATUS_SUCCESS
: STATUS_INVALID_IMAGE_WIN_64
),
1151 "NtCreateSection error %08x\n", status
);
1153 nt64
.OptionalHeader
.NumberOfRvaAndSizes
= IMAGE_NUMBEROF_DIRECTORY_ENTRIES
;
1154 nt64
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
= page_size
;
1155 nt64
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].Size
= sizeof(cor_header
);
1156 cor_header
.MajorRuntimeVersion
= 2;
1157 cor_header
.MinorRuntimeVersion
= 4;
1158 cor_header
.Flags
= COMIMAGE_FLAGS_ILONLY
;
1159 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt64
, §ion
, &cor_header
, __LINE__
);
1160 ok( status
== (is_wow64
? STATUS_SUCCESS
: STATUS_INVALID_IMAGE_WIN_64
),
1161 "NtCreateSection error %08x\n", status
);
1163 nt64
.OptionalHeader
.SizeOfCode
= 0x1000;
1164 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt64
, §ion
, &cor_header
, __LINE__
);
1165 ok( status
== (is_wow64
? STATUS_SUCCESS
: STATUS_INVALID_IMAGE_WIN_64
),
1166 "NtCreateSection error %08x\n", status
);
1168 cor_header
.MinorRuntimeVersion
= 5;
1169 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt64
, §ion
, &cor_header
, __LINE__
);
1170 ok( status
== (is_wow64
? STATUS_SUCCESS
: STATUS_INVALID_IMAGE_WIN_64
),
1171 "NtCreateSection error %08x\n", status
);
1173 cor_header
.Flags
= COMIMAGE_FLAGS_ILONLY
| COMIMAGE_FLAGS_32BITREQUIRED
;
1174 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt64
, §ion
, &cor_header
, __LINE__
);
1175 ok( status
== (is_wow64
? STATUS_SUCCESS
: STATUS_INVALID_IMAGE_WIN_64
),
1176 "NtCreateSection error %08x\n", status
);
1178 cor_header
.Flags
= COMIMAGE_FLAGS_ILONLY
| COMIMAGE_FLAGS_32BITPREFERRED
;
1179 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt64
, §ion
, &cor_header
, __LINE__
);
1180 ok( status
== (is_wow64
? STATUS_SUCCESS
: STATUS_INVALID_IMAGE_WIN_64
),
1181 "NtCreateSection error %08x\n", status
);
1183 cor_header
.Flags
= 0;
1184 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt64
, §ion
, &cor_header
, __LINE__
);
1185 ok( status
== (is_wow64
? STATUS_SUCCESS
: STATUS_INVALID_IMAGE_WIN_64
),
1186 "NtCreateSection error %08x\n", status
);
1188 nt_header
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
= 1;
1189 nt_header
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].Size
= 1;
1190 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt64
, §ion
, &cor_header
, __LINE__
);
1191 ok( status
== (is_wow64
? STATUS_SUCCESS
: STATUS_INVALID_IMAGE_WIN_64
),
1192 "NtCreateSection error %08x\n", status
);
1196 IMAGE_NT_HEADERS32 nt32
;
1198 memset( &nt32
, 0, sizeof(nt32
) );
1199 nt32
.Signature
= IMAGE_NT_SIGNATURE
;
1200 nt32
.FileHeader
.Machine
= orig_machine
;
1201 nt32
.FileHeader
.NumberOfSections
= 1;
1202 nt32
.FileHeader
.SizeOfOptionalHeader
= sizeof(IMAGE_OPTIONAL_HEADER32
);
1203 nt32
.FileHeader
.Characteristics
= IMAGE_FILE_EXECUTABLE_IMAGE
| IMAGE_FILE_DLL
;
1204 nt32
.OptionalHeader
.Magic
= IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
1205 nt32
.OptionalHeader
.MajorLinkerVersion
= 1;
1206 nt32
.OptionalHeader
.SizeOfCode
= 0x1000;
1207 nt32
.OptionalHeader
.AddressOfEntryPoint
= 0x1000;
1208 nt32
.OptionalHeader
.ImageBase
= 0x10000000;
1209 nt32
.OptionalHeader
.SectionAlignment
= 0x1000;
1210 nt32
.OptionalHeader
.FileAlignment
= 0x1000;
1211 nt32
.OptionalHeader
.MajorOperatingSystemVersion
= 4;
1212 nt32
.OptionalHeader
.MajorImageVersion
= 1;
1213 nt32
.OptionalHeader
.MajorSubsystemVersion
= 4;
1214 nt32
.OptionalHeader
.SizeOfHeaders
= sizeof(dos_header
) + sizeof(nt32
) + sizeof(IMAGE_SECTION_HEADER
);
1215 nt32
.OptionalHeader
.SizeOfImage
= nt32
.OptionalHeader
.SizeOfHeaders
+ 0x1000;
1216 nt32
.OptionalHeader
.Subsystem
= IMAGE_SUBSYSTEM_WINDOWS_CUI
;
1217 nt32
.OptionalHeader
.SizeOfStackReserve
= 0x321000;
1218 nt32
.OptionalHeader
.SizeOfStackCommit
= 0x123000;
1219 section
.Characteristics
= IMAGE_SCN_CNT_CODE
| IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_EXECUTE
;
1221 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt32
, §ion
, section_data
, __LINE__
);
1222 ok( status
== STATUS_INVALID_IMAGE_FORMAT
, "NtCreateSection error %08x\n", status
);
1224 switch (orig_machine
)
1226 case IMAGE_FILE_MACHINE_AMD64
: nt32
.FileHeader
.Machine
= IMAGE_FILE_MACHINE_ARMNT
; break;
1227 case IMAGE_FILE_MACHINE_ARM64
: nt32
.FileHeader
.Machine
= IMAGE_FILE_MACHINE_I386
; break;
1229 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt32
, §ion
, section_data
, __LINE__
);
1230 ok( status
== STATUS_INVALID_IMAGE_FORMAT
|| broken(!status
) /* win8 */,
1231 "NtCreateSection error %08x\n", status
);
1233 nt32
.FileHeader
.Machine
= alt_machine
;
1234 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt32
, §ion
, section_data
, __LINE__
);
1235 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1237 nt32
.OptionalHeader
.SizeOfCode
= 0;
1238 nt32
.OptionalHeader
.AddressOfEntryPoint
= 0x1000;
1239 section
.Characteristics
= IMAGE_SCN_MEM_READ
| IMAGE_SCN_CNT_CODE
;
1240 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt32
, §ion
, section_data
, __LINE__
);
1241 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1243 nt32
.OptionalHeader
.SizeOfCode
= 0;
1244 nt32
.OptionalHeader
.AddressOfEntryPoint
= 0;
1245 section
.Characteristics
= IMAGE_SCN_MEM_READ
| IMAGE_SCN_CNT_CODE
| IMAGE_SCN_MEM_EXECUTE
;
1246 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt32
, §ion
, section_data
, __LINE__
);
1247 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1249 nt32
.OptionalHeader
.SizeOfCode
= 0x1000;
1250 nt32
.OptionalHeader
.AddressOfEntryPoint
= 0;
1251 nt32
.OptionalHeader
.DllCharacteristics
= IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
;
1252 section
.Characteristics
= IMAGE_SCN_MEM_READ
| IMAGE_SCN_CNT_CODE
;
1253 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt32
, §ion
, section_data
, __LINE__
);
1254 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1256 nt32
.OptionalHeader
.SizeOfCode
= 0;
1257 nt32
.OptionalHeader
.AddressOfEntryPoint
= 0;
1258 section
.Characteristics
= IMAGE_SCN_MEM_READ
| IMAGE_SCN_CNT_CODE
;
1259 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt32
, §ion
, section_data
, __LINE__
);
1260 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1262 nt32
.OptionalHeader
.NumberOfRvaAndSizes
= IMAGE_NUMBEROF_DIRECTORY_ENTRIES
;
1263 nt32
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
= page_size
;
1264 nt32
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].Size
= sizeof(cor_header
);
1265 cor_header
.MajorRuntimeVersion
= 2;
1266 cor_header
.MinorRuntimeVersion
= 4;
1267 cor_header
.Flags
= COMIMAGE_FLAGS_ILONLY
;
1268 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt32
, §ion
, &cor_header
, __LINE__
);
1269 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1271 nt32
.OptionalHeader
.SizeOfCode
= 0x1000;
1272 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt32
, §ion
, &cor_header
, __LINE__
);
1273 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1275 cor_header
.MinorRuntimeVersion
= 5;
1276 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt32
, §ion
, &cor_header
, __LINE__
);
1277 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1279 cor_header
.Flags
= COMIMAGE_FLAGS_ILONLY
| COMIMAGE_FLAGS_32BITREQUIRED
;
1280 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt32
, §ion
, &cor_header
, __LINE__
);
1281 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1283 cor_header
.Flags
= COMIMAGE_FLAGS_ILONLY
| COMIMAGE_FLAGS_32BITPREFERRED
;
1284 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt32
, §ion
, &cor_header
, __LINE__
);
1285 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1287 cor_header
.Flags
= 0;
1288 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt32
, §ion
, &cor_header
, __LINE__
);
1289 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1291 nt_header
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
= 1;
1292 nt_header
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].Size
= 1;
1293 status
= map_image_section( (IMAGE_NT_HEADERS
*)&nt32
, §ion
, &cor_header
, __LINE__
);
1294 ok( status
== STATUS_SUCCESS
, "NtCreateSection error %08x\n", status
);
1297 section
.Characteristics
= IMAGE_SCN_CNT_INITIALIZED_DATA
| IMAGE_SCN_MEM_READ
;
1300 static void test_filenames(void)
1302 IMAGE_NT_HEADERS nt_header
= nt_header_template
;
1303 char dll_name
[MAX_PATH
], long_path
[MAX_PATH
], short_path
[MAX_PATH
], buffer
[MAX_PATH
];
1307 nt_header
.FileHeader
.NumberOfSections
= 1;
1308 nt_header
.FileHeader
.SizeOfOptionalHeader
= sizeof(IMAGE_OPTIONAL_HEADER
);
1310 nt_header
.OptionalHeader
.SectionAlignment
= page_size
;
1311 nt_header
.OptionalHeader
.DllCharacteristics
= IMAGE_DLLCHARACTERISTICS_NX_COMPAT
;
1312 nt_header
.OptionalHeader
.FileAlignment
= page_size
;
1313 nt_header
.OptionalHeader
.SizeOfHeaders
= sizeof(dos_header
) + sizeof(nt_header
) + sizeof(IMAGE_SECTION_HEADER
);
1314 nt_header
.OptionalHeader
.SizeOfImage
= sizeof(dos_header
) + sizeof(nt_header
) + sizeof(IMAGE_SECTION_HEADER
) + page_size
;
1316 create_test_dll( &dos_header
, sizeof(dos_header
), &nt_header
, dll_name
);
1317 strcpy( long_path
, dll_name
);
1318 strcpy( strrchr( long_path
, '\\' ), "\\this-is-a-long-name.dll" );
1319 ret
= MoveFileA( dll_name
, long_path
);
1320 ok( ret
, "MoveFileA failed err %u\n", GetLastError() );
1321 GetShortPathNameA( long_path
, short_path
, MAX_PATH
);
1323 mod
= LoadLibraryA( short_path
);
1324 ok( mod
!= NULL
, "loading failed err %u\n", GetLastError() );
1325 GetModuleFileNameA( mod
, buffer
, MAX_PATH
);
1326 ok( !lstrcmpiA( buffer
, short_path
), "got wrong path %s / %s\n", buffer
, short_path
);
1327 mod2
= GetModuleHandleA( short_path
);
1328 ok( mod
== mod2
, "wrong module %p for %s\n", mod2
, short_path
);
1329 mod2
= GetModuleHandleA( long_path
);
1330 ok( mod
== mod2
, "wrong module %p for %s\n", mod2
, long_path
);
1331 mod2
= LoadLibraryA( long_path
);
1332 ok( mod2
!= NULL
, "loading failed err %u\n", GetLastError() );
1333 ok( mod
== mod2
, "library loaded twice\n" );
1334 GetModuleFileNameA( mod2
, buffer
, MAX_PATH
);
1335 ok( !lstrcmpiA( buffer
, short_path
), "got wrong path %s / %s\n", buffer
, short_path
);
1336 FreeLibrary( mod2
);
1339 mod
= LoadLibraryA( long_path
);
1340 ok( mod
!= NULL
, "loading failed err %u\n", GetLastError() );
1341 GetModuleFileNameA( mod
, buffer
, MAX_PATH
);
1342 ok( !lstrcmpiA( buffer
, long_path
), "got wrong path %s / %s\n", buffer
, long_path
);
1343 mod2
= GetModuleHandleA( short_path
);
1344 ok( mod
== mod2
, "wrong module %p for %s\n", mod2
, short_path
);
1345 mod2
= GetModuleHandleA( long_path
);
1346 ok( mod
== mod2
, "wrong module %p for %s\n", mod2
, long_path
);
1347 mod2
= LoadLibraryA( short_path
);
1348 ok( mod2
!= NULL
, "loading failed err %u\n", GetLastError() );
1349 ok( mod
== mod2
, "library loaded twice\n" );
1350 GetModuleFileNameA( mod2
, buffer
, MAX_PATH
);
1351 ok( !lstrcmpiA( buffer
, long_path
), "got wrong path %s / %s\n", buffer
, long_path
);
1352 FreeLibrary( mod2
);
1355 strcpy( dll_name
, long_path
);
1356 strcpy( strrchr( dll_name
, '\\' ), "\\this-is-another-name.dll" );
1357 ret
= CreateHardLinkA( dll_name
, long_path
, NULL
);
1358 ok( ret
, "CreateHardLinkA failed err %u\n", GetLastError() );
1361 mod
= LoadLibraryA( dll_name
);
1362 ok( mod
!= NULL
, "loading failed err %u\n", GetLastError() );
1363 GetModuleFileNameA( mod
, buffer
, MAX_PATH
);
1364 ok( !lstrcmpiA( buffer
, dll_name
), "got wrong path %s / %s\n", buffer
, dll_name
);
1365 mod2
= GetModuleHandleA( long_path
);
1366 ok( mod
== mod2
, "wrong module %p for %s\n", mod2
, long_path
);
1367 mod2
= LoadLibraryA( long_path
);
1368 ok( mod2
!= NULL
, "loading failed err %u\n", GetLastError() );
1369 ok( mod
== mod2
, "library loaded twice\n" );
1370 GetModuleFileNameA( mod2
, buffer
, MAX_PATH
);
1371 ok( !lstrcmpiA( buffer
, dll_name
), "got wrong path %s / %s\n", buffer
, short_path
);
1372 FreeLibrary( mod2
);
1374 DeleteFileA( dll_name
);
1376 DeleteFileA( long_path
);
1379 /* Verify linking style of import descriptors */
1380 static void test_ImportDescriptors(void)
1382 HMODULE kernel32_module
= NULL
;
1383 PIMAGE_DOS_HEADER d_header
;
1384 PIMAGE_NT_HEADERS nt_headers
;
1385 DWORD import_dir_size
;
1386 DWORD_PTR dir_offset
;
1387 PIMAGE_IMPORT_DESCRIPTOR import_chunk
;
1389 /* Load kernel32 module */
1390 kernel32_module
= GetModuleHandleA("kernel32.dll");
1391 assert( kernel32_module
!= NULL
);
1393 /* Get PE header info from module image */
1394 d_header
= (PIMAGE_DOS_HEADER
) kernel32_module
;
1395 nt_headers
= (PIMAGE_NT_HEADERS
) (((char*) d_header
) +
1396 d_header
->e_lfanew
);
1398 /* Get size of import entry directory */
1399 import_dir_size
= nt_headers
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].Size
;
1400 if (!import_dir_size
)
1402 skip("Unable to continue testing due to missing import directory.\n");
1406 /* Get address of first import chunk */
1407 dir_offset
= nt_headers
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
;
1408 import_chunk
= RVAToAddr(dir_offset
, kernel32_module
);
1409 ok(import_chunk
!= 0, "Invalid import_chunk: %p\n", import_chunk
);
1410 if (!import_chunk
) return;
1412 /* Iterate through import descriptors and verify set name,
1413 * OriginalFirstThunk, and FirstThunk. Core Windows DLLs, such as
1414 * kernel32.dll, don't use Borland-style linking, where the table of
1415 * imported names is stored directly in FirstThunk and overwritten
1416 * by the relocation, instead of being stored in OriginalFirstThunk.
1418 for (; import_chunk
->FirstThunk
; import_chunk
++)
1420 LPCSTR module_name
= RVAToAddr(import_chunk
->Name
, kernel32_module
);
1421 PIMAGE_THUNK_DATA name_table
= RVAToAddr(
1422 U(*import_chunk
).OriginalFirstThunk
, kernel32_module
);
1423 PIMAGE_THUNK_DATA iat
= RVAToAddr(
1424 import_chunk
->FirstThunk
, kernel32_module
);
1425 ok(module_name
!= NULL
, "Imported module name should not be NULL\n");
1426 ok(name_table
!= NULL
,
1427 "Name table for imported module %s should not be NULL\n",
1429 ok(iat
!= NULL
, "IAT for imported module %s should not be NULL\n",
1434 static void test_image_mapping(const char *dll_name
, DWORD scn_page_access
, BOOL is_dll
)
1438 LARGE_INTEGER offset
;
1440 void *addr1
, *addr2
;
1441 MEMORY_BASIC_INFORMATION info
;
1443 if (!pNtMapViewOfSection
) return;
1445 SetLastError(0xdeadbeef);
1446 hfile
= CreateFileA(dll_name
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
1447 ok(hfile
!= INVALID_HANDLE_VALUE
, "CreateFile error %d\n", GetLastError());
1449 SetLastError(0xdeadbeef);
1450 hmap
= CreateFileMappingW(hfile
, NULL
, PAGE_READONLY
| SEC_IMAGE
, 0, 0, 0);
1451 ok(hmap
!= 0, "CreateFileMapping error %d\n", GetLastError());
1453 offset
.u
.LowPart
= 0;
1454 offset
.u
.HighPart
= 0;
1458 status
= pNtMapViewOfSection(hmap
, GetCurrentProcess(), &addr1
, 0, 0, &offset
,
1459 &size
, 1 /* ViewShare */, 0, PAGE_READONLY
);
1460 ok(status
== STATUS_SUCCESS
, "NtMapViewOfSection error %x\n", status
);
1461 ok(addr1
!= 0, "mapped address should be valid\n");
1463 SetLastError(0xdeadbeef);
1464 size
= VirtualQuery((char *)addr1
+ section
.VirtualAddress
, &info
, sizeof(info
));
1465 ok(size
== sizeof(info
), "VirtualQuery error %d\n", GetLastError());
1466 ok(info
.BaseAddress
== (char *)addr1
+ section
.VirtualAddress
, "got %p != expected %p\n", info
.BaseAddress
, (char *)addr1
+ section
.VirtualAddress
);
1467 ok(info
.RegionSize
== page_size
, "got %#lx != expected %#x\n", info
.RegionSize
, page_size
);
1468 ok(info
.Protect
== scn_page_access
, "got %#x != expected %#x\n", info
.Protect
, scn_page_access
);
1469 ok(info
.AllocationBase
== addr1
, "%p != %p\n", info
.AllocationBase
, addr1
);
1470 ok(info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
, "%#x != PAGE_EXECUTE_WRITECOPY\n", info
.AllocationProtect
);
1471 ok(info
.State
== MEM_COMMIT
, "%#x != MEM_COMMIT\n", info
.State
);
1472 ok(info
.Type
== SEC_IMAGE
, "%#x != SEC_IMAGE\n", info
.Type
);
1476 status
= pNtMapViewOfSection(hmap
, GetCurrentProcess(), &addr2
, 0, 0, &offset
,
1477 &size
, 1 /* ViewShare */, 0, PAGE_READONLY
);
1478 ok(status
== STATUS_IMAGE_NOT_AT_BASE
, "expected STATUS_IMAGE_NOT_AT_BASE, got %x\n", status
);
1479 ok(addr2
!= 0, "mapped address should be valid\n");
1480 ok(addr2
!= addr1
, "mapped addresses should be different\n");
1482 SetLastError(0xdeadbeef);
1483 size
= VirtualQuery((char *)addr2
+ section
.VirtualAddress
, &info
, sizeof(info
));
1484 ok(size
== sizeof(info
), "VirtualQuery error %d\n", GetLastError());
1485 ok(info
.BaseAddress
== (char *)addr2
+ section
.VirtualAddress
, "got %p != expected %p\n", info
.BaseAddress
, (char *)addr2
+ section
.VirtualAddress
);
1486 ok(info
.RegionSize
== page_size
, "got %#lx != expected %#x\n", info
.RegionSize
, page_size
);
1487 ok(info
.Protect
== scn_page_access
, "got %#x != expected %#x\n", info
.Protect
, scn_page_access
);
1488 ok(info
.AllocationBase
== addr2
, "%p != %p\n", info
.AllocationBase
, addr2
);
1489 ok(info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
, "%#x != PAGE_EXECUTE_WRITECOPY\n", info
.AllocationProtect
);
1490 ok(info
.State
== MEM_COMMIT
, "%#x != MEM_COMMIT\n", info
.State
);
1491 ok(info
.Type
== SEC_IMAGE
, "%#x != SEC_IMAGE\n", info
.Type
);
1493 status
= pNtUnmapViewOfSection(GetCurrentProcess(), addr2
);
1494 ok(status
== STATUS_SUCCESS
, "NtUnmapViewOfSection error %x\n", status
);
1496 addr2
= MapViewOfFile(hmap
, 0, 0, 0, 0);
1497 ok(addr2
!= 0, "mapped address should be valid\n");
1498 ok(addr2
!= addr1
, "mapped addresses should be different\n");
1500 SetLastError(0xdeadbeef);
1501 size
= VirtualQuery((char *)addr2
+ section
.VirtualAddress
, &info
, sizeof(info
));
1502 ok(size
== sizeof(info
), "VirtualQuery error %d\n", GetLastError());
1503 ok(info
.BaseAddress
== (char *)addr2
+ section
.VirtualAddress
, "got %p != expected %p\n", info
.BaseAddress
, (char *)addr2
+ section
.VirtualAddress
);
1504 ok(info
.RegionSize
== page_size
, "got %#lx != expected %#x\n", info
.RegionSize
, page_size
);
1505 ok(info
.Protect
== scn_page_access
, "got %#x != expected %#x\n", info
.Protect
, scn_page_access
);
1506 ok(info
.AllocationBase
== addr2
, "%p != %p\n", info
.AllocationBase
, addr2
);
1507 ok(info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
, "%#x != PAGE_EXECUTE_WRITECOPY\n", info
.AllocationProtect
);
1508 ok(info
.State
== MEM_COMMIT
, "%#x != MEM_COMMIT\n", info
.State
);
1509 ok(info
.Type
== SEC_IMAGE
, "%#x != SEC_IMAGE\n", info
.Type
);
1511 UnmapViewOfFile(addr2
);
1513 SetLastError(0xdeadbeef);
1514 addr2
= LoadLibraryA(dll_name
);
1517 ok(!addr2
, "LoadLibrary should fail, is_dll %d\n", is_dll
);
1518 ok(GetLastError() == ERROR_INVALID_ADDRESS
, "expected ERROR_INVALID_ADDRESS, got %d\n", GetLastError());
1523 ok(addr2
!= 0, "LoadLibrary error %d, is_dll %d\n", GetLastError(), is_dll
);
1524 ok(addr2
!= addr1
, "mapped addresses should be different\n");
1526 SetLastError(0xdeadbeef);
1527 ret
= FreeLibrary(addr2
);
1528 ok(ret
, "FreeLibrary error %d\n", GetLastError());
1531 status
= pNtUnmapViewOfSection(GetCurrentProcess(), addr1
);
1532 ok(status
== STATUS_SUCCESS
, "NtUnmapViewOfSection error %x\n", status
);
1538 static BOOL
is_mem_writable(DWORD prot
)
1540 switch (prot
& 0xff)
1542 case PAGE_READWRITE
:
1543 case PAGE_WRITECOPY
:
1544 case PAGE_EXECUTE_READWRITE
:
1545 case PAGE_EXECUTE_WRITECOPY
:
1553 static void test_VirtualProtect(void *base
, void *section
)
1555 static const struct test_data
1557 DWORD prot_set
, prot_get
;
1560 { 0, 0 }, /* 0x00 */
1561 { PAGE_NOACCESS
, PAGE_NOACCESS
}, /* 0x01 */
1562 { PAGE_READONLY
, PAGE_READONLY
}, /* 0x02 */
1563 { PAGE_READONLY
| PAGE_NOACCESS
, 0 }, /* 0x03 */
1564 { PAGE_READWRITE
, PAGE_WRITECOPY
}, /* 0x04 */
1565 { PAGE_READWRITE
| PAGE_NOACCESS
, 0 }, /* 0x05 */
1566 { PAGE_READWRITE
| PAGE_READONLY
, 0 }, /* 0x06 */
1567 { PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, 0 }, /* 0x07 */
1568 { PAGE_WRITECOPY
, PAGE_WRITECOPY
}, /* 0x08 */
1569 { PAGE_WRITECOPY
| PAGE_NOACCESS
, 0 }, /* 0x09 */
1570 { PAGE_WRITECOPY
| PAGE_READONLY
, 0 }, /* 0x0a */
1571 { PAGE_WRITECOPY
| PAGE_NOACCESS
| PAGE_READONLY
, 0 }, /* 0x0b */
1572 { PAGE_WRITECOPY
| PAGE_READWRITE
, 0 }, /* 0x0c */
1573 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_NOACCESS
, 0 }, /* 0x0d */
1574 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
, 0 }, /* 0x0e */
1575 { PAGE_WRITECOPY
| PAGE_READWRITE
| PAGE_READONLY
| PAGE_NOACCESS
, 0 }, /* 0x0f */
1577 { PAGE_EXECUTE
, PAGE_EXECUTE
}, /* 0x10 */
1578 { PAGE_EXECUTE_READ
, PAGE_EXECUTE_READ
}, /* 0x20 */
1579 { PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 }, /* 0x30 */
1580 { PAGE_EXECUTE_READWRITE
, PAGE_EXECUTE_WRITECOPY
}, /* 0x40 */
1581 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, 0 }, /* 0x50 */
1582 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, 0 }, /* 0x60 */
1583 { PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 }, /* 0x70 */
1584 { PAGE_EXECUTE_WRITECOPY
, PAGE_EXECUTE_WRITECOPY
}, /* 0x80 */
1585 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE
, 0 }, /* 0x90 */
1586 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
, 0 }, /* 0xa0 */
1587 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 }, /* 0xb0 */
1588 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
, 0 }, /* 0xc0 */
1589 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE
, 0 }, /* 0xd0 */
1590 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
, 0 }, /* 0xe0 */
1591 { PAGE_EXECUTE_WRITECOPY
| PAGE_EXECUTE_READWRITE
| PAGE_EXECUTE_READ
| PAGE_EXECUTE
, 0 } /* 0xf0 */
1593 DWORD ret
, orig_prot
, old_prot
, rw_prot
, exec_prot
, i
, j
;
1594 MEMORY_BASIC_INFORMATION info
;
1596 SetLastError(0xdeadbeef);
1597 ret
= VirtualProtect(section
, page_size
, PAGE_NOACCESS
, &old_prot
);
1598 ok(ret
, "VirtualProtect error %d\n", GetLastError());
1600 orig_prot
= old_prot
;
1602 for (i
= 0; i
< ARRAY_SIZE(td
); i
++)
1604 SetLastError(0xdeadbeef);
1605 ret
= VirtualQuery(section
, &info
, sizeof(info
));
1606 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
1607 ok(info
.BaseAddress
== section
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, section
);
1608 ok(info
.RegionSize
== page_size
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, page_size
);
1609 ok(info
.Protect
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, info
.Protect
);
1610 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
1611 ok(info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
, "%d: %#x != PAGE_EXECUTE_WRITECOPY\n", i
, info
.AllocationProtect
);
1612 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
1613 ok(info
.Type
== SEC_IMAGE
, "%d: %#x != SEC_IMAGE\n", i
, info
.Type
);
1615 old_prot
= 0xdeadbeef;
1616 SetLastError(0xdeadbeef);
1617 ret
= VirtualProtect(section
, page_size
, td
[i
].prot_set
, &old_prot
);
1620 ok(ret
, "%d: VirtualProtect error %d, requested prot %#x\n", i
, GetLastError(), td
[i
].prot_set
);
1621 ok(old_prot
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, old_prot
);
1623 SetLastError(0xdeadbeef);
1624 ret
= VirtualQuery(section
, &info
, sizeof(info
));
1625 ok(ret
, "VirtualQuery failed %d\n", GetLastError());
1626 ok(info
.BaseAddress
== section
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, section
);
1627 ok(info
.RegionSize
== page_size
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, page_size
);
1628 ok(info
.Protect
== td
[i
].prot_get
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].prot_get
);
1629 ok(info
.AllocationBase
== base
, "%d: %p != %p\n", i
, info
.AllocationBase
, base
);
1630 ok(info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
, "%d: %#x != PAGE_EXECUTE_WRITECOPY\n", i
, info
.AllocationProtect
);
1631 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
1632 ok(info
.Type
== SEC_IMAGE
, "%d: %#x != SEC_IMAGE\n", i
, info
.Type
);
1636 ok(!ret
, "%d: VirtualProtect should fail\n", i
);
1637 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i
, GetLastError());
1640 old_prot
= 0xdeadbeef;
1641 SetLastError(0xdeadbeef);
1642 ret
= VirtualProtect(section
, page_size
, PAGE_NOACCESS
, &old_prot
);
1643 ok(ret
, "%d: VirtualProtect error %d\n", i
, GetLastError());
1645 ok(old_prot
== td
[i
].prot_get
, "%d: got %#x != expected %#x\n", i
, old_prot
, td
[i
].prot_get
);
1647 ok(old_prot
== PAGE_NOACCESS
, "%d: got %#x != expected PAGE_NOACCESS\n", i
, old_prot
);
1652 for (i
= 0; i
<= 4; i
++)
1656 for (j
= 0; j
<= 4; j
++)
1658 DWORD prot
= exec_prot
| rw_prot
;
1660 SetLastError(0xdeadbeef);
1661 ret
= VirtualProtect(section
, page_size
, prot
, &old_prot
);
1662 if ((rw_prot
&& exec_prot
) || (!rw_prot
&& !exec_prot
))
1664 ok(!ret
, "VirtualProtect(%02x) should fail\n", prot
);
1665 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1668 ok(ret
, "VirtualProtect(%02x) error %d\n", prot
, GetLastError());
1673 exec_prot
= 1 << (i
+ 4);
1676 SetLastError(0xdeadbeef);
1677 ret
= VirtualProtect(section
, page_size
, orig_prot
, &old_prot
);
1678 ok(ret
, "VirtualProtect error %d\n", GetLastError());
1681 static void test_section_access(void)
1683 static const struct test_data
1685 DWORD scn_file_access
, scn_page_access
, scn_page_access_after_write
;
1688 { 0, PAGE_NOACCESS
, 0 },
1689 { IMAGE_SCN_MEM_READ
, PAGE_READONLY
, 0 },
1690 { IMAGE_SCN_MEM_WRITE
, PAGE_WRITECOPY
, PAGE_READWRITE
},
1691 { IMAGE_SCN_MEM_EXECUTE
, PAGE_EXECUTE
, 0 },
1692 { IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_WRITE
, PAGE_WRITECOPY
, PAGE_READWRITE
},
1693 { IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_EXECUTE
, PAGE_EXECUTE_READ
},
1694 { IMAGE_SCN_MEM_WRITE
| IMAGE_SCN_MEM_EXECUTE
, PAGE_EXECUTE_WRITECOPY
, PAGE_EXECUTE_READWRITE
},
1695 { IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_WRITE
| IMAGE_SCN_MEM_EXECUTE
, PAGE_EXECUTE_WRITECOPY
, PAGE_EXECUTE_READWRITE
},
1697 { IMAGE_SCN_CNT_INITIALIZED_DATA
, PAGE_NOACCESS
, 0 },
1698 { IMAGE_SCN_CNT_INITIALIZED_DATA
| IMAGE_SCN_MEM_READ
, PAGE_READONLY
, 0 },
1699 { IMAGE_SCN_CNT_INITIALIZED_DATA
| IMAGE_SCN_MEM_WRITE
, PAGE_WRITECOPY
, PAGE_READWRITE
},
1700 { IMAGE_SCN_CNT_INITIALIZED_DATA
| IMAGE_SCN_MEM_EXECUTE
, PAGE_EXECUTE
, 0 },
1701 { IMAGE_SCN_CNT_INITIALIZED_DATA
| IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_WRITE
, PAGE_WRITECOPY
, PAGE_READWRITE
},
1702 { IMAGE_SCN_CNT_INITIALIZED_DATA
| IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_EXECUTE
, PAGE_EXECUTE_READ
, 0 },
1703 { IMAGE_SCN_CNT_INITIALIZED_DATA
| IMAGE_SCN_MEM_WRITE
| IMAGE_SCN_MEM_EXECUTE
, PAGE_EXECUTE_WRITECOPY
, PAGE_EXECUTE_READWRITE
},
1704 { IMAGE_SCN_CNT_INITIALIZED_DATA
| IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_WRITE
| IMAGE_SCN_MEM_EXECUTE
, PAGE_EXECUTE_WRITECOPY
, PAGE_EXECUTE_READWRITE
},
1706 { IMAGE_SCN_CNT_UNINITIALIZED_DATA
, PAGE_NOACCESS
, 0 },
1707 { IMAGE_SCN_CNT_UNINITIALIZED_DATA
| IMAGE_SCN_MEM_READ
, PAGE_READONLY
, 0 },
1708 { IMAGE_SCN_CNT_UNINITIALIZED_DATA
| IMAGE_SCN_MEM_WRITE
, PAGE_WRITECOPY
, PAGE_READWRITE
},
1709 { IMAGE_SCN_CNT_UNINITIALIZED_DATA
| IMAGE_SCN_MEM_EXECUTE
, PAGE_EXECUTE
, 0 },
1710 { IMAGE_SCN_CNT_UNINITIALIZED_DATA
| IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_WRITE
, PAGE_WRITECOPY
, PAGE_READWRITE
},
1711 { IMAGE_SCN_CNT_UNINITIALIZED_DATA
| IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_EXECUTE
, PAGE_EXECUTE_READ
, 0 },
1712 { IMAGE_SCN_CNT_UNINITIALIZED_DATA
| IMAGE_SCN_MEM_WRITE
| IMAGE_SCN_MEM_EXECUTE
, PAGE_EXECUTE_WRITECOPY
, PAGE_EXECUTE_READWRITE
},
1713 { IMAGE_SCN_CNT_UNINITIALIZED_DATA
| IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_WRITE
| IMAGE_SCN_MEM_EXECUTE
, PAGE_EXECUTE_WRITECOPY
, PAGE_EXECUTE_READWRITE
}
1717 DWORD dummy
, file_align
;
1720 char temp_path
[MAX_PATH
];
1721 char dll_name
[MAX_PATH
];
1723 MEMORY_BASIC_INFORMATION info
;
1725 PROCESS_INFORMATION pi
;
1728 /* prevent displaying of the "Unable to load this DLL" message box */
1729 SetErrorMode(SEM_FAILCRITICALERRORS
);
1731 GetTempPathA(MAX_PATH
, temp_path
);
1733 for (i
= 0; i
< ARRAY_SIZE(td
); i
++)
1735 IMAGE_NT_HEADERS nt_header
;
1737 GetTempFileNameA(temp_path
, "ldr", 0, dll_name
);
1739 /*trace("creating %s\n", dll_name);*/
1740 hfile
= CreateFileA(dll_name
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
1741 if (hfile
== INVALID_HANDLE_VALUE
)
1743 ok(0, "could not create %s\n", dll_name
);
1747 SetLastError(0xdeadbeef);
1748 ret
= WriteFile(hfile
, &dos_header
, sizeof(dos_header
), &dummy
, NULL
);
1749 ok(ret
, "WriteFile error %d\n", GetLastError());
1751 nt_header
= nt_header_template
;
1752 nt_header
.FileHeader
.NumberOfSections
= 1;
1753 nt_header
.FileHeader
.SizeOfOptionalHeader
= sizeof(IMAGE_OPTIONAL_HEADER
);
1754 nt_header
.FileHeader
.Characteristics
= IMAGE_FILE_EXECUTABLE_IMAGE
| IMAGE_FILE_DLL
| IMAGE_FILE_RELOCS_STRIPPED
;
1756 nt_header
.OptionalHeader
.SectionAlignment
= page_size
;
1757 nt_header
.OptionalHeader
.FileAlignment
= 0x200;
1758 nt_header
.OptionalHeader
.SizeOfImage
= sizeof(dos_header
) + sizeof(nt_header
) + sizeof(IMAGE_SECTION_HEADER
) + page_size
;
1759 nt_header
.OptionalHeader
.SizeOfHeaders
= sizeof(dos_header
) + sizeof(nt_header
) + sizeof(IMAGE_SECTION_HEADER
);
1760 SetLastError(0xdeadbeef);
1761 ret
= WriteFile(hfile
, &nt_header
, sizeof(DWORD
) + sizeof(IMAGE_FILE_HEADER
), &dummy
, NULL
);
1762 ok(ret
, "WriteFile error %d\n", GetLastError());
1763 SetLastError(0xdeadbeef);
1764 ret
= WriteFile(hfile
, &nt_header
.OptionalHeader
, sizeof(IMAGE_OPTIONAL_HEADER
), &dummy
, NULL
);
1765 ok(ret
, "WriteFile error %d\n", GetLastError());
1767 section
.SizeOfRawData
= sizeof(section_data
);
1768 section
.PointerToRawData
= nt_header
.OptionalHeader
.FileAlignment
;
1769 section
.VirtualAddress
= nt_header
.OptionalHeader
.SectionAlignment
;
1770 section
.Misc
.VirtualSize
= section
.SizeOfRawData
;
1771 section
.Characteristics
= td
[i
].scn_file_access
;
1772 SetLastError(0xdeadbeef);
1773 ret
= WriteFile(hfile
, §ion
, sizeof(section
), &dummy
, NULL
);
1774 ok(ret
, "WriteFile error %d\n", GetLastError());
1776 file_align
= nt_header
.OptionalHeader
.FileAlignment
- nt_header
.OptionalHeader
.SizeOfHeaders
;
1777 assert(file_align
< sizeof(filler
));
1778 SetLastError(0xdeadbeef);
1779 ret
= WriteFile(hfile
, filler
, file_align
, &dummy
, NULL
);
1780 ok(ret
, "WriteFile error %d\n", GetLastError());
1783 SetLastError(0xdeadbeef);
1784 ret
= WriteFile(hfile
, section_data
, sizeof(section_data
), &dummy
, NULL
);
1785 ok(ret
, "WriteFile error %d\n", GetLastError());
1789 SetLastError(0xdeadbeef);
1790 hlib
= LoadLibraryA(dll_name
);
1791 ok(hlib
!= 0, "LoadLibrary error %d\n", GetLastError());
1793 SetLastError(0xdeadbeef);
1794 size
= VirtualQuery((char *)hlib
+ section
.VirtualAddress
, &info
, sizeof(info
));
1795 ok(size
== sizeof(info
),
1796 "%d: VirtualQuery error %d\n", i
, GetLastError());
1797 ok(info
.BaseAddress
== (char *)hlib
+ section
.VirtualAddress
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, (char *)hlib
+ section
.VirtualAddress
);
1798 ok(info
.RegionSize
== page_size
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, page_size
);
1799 ok(info
.Protect
== td
[i
].scn_page_access
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].scn_page_access
);
1800 ok(info
.AllocationBase
== hlib
, "%d: %p != %p\n", i
, info
.AllocationBase
, hlib
);
1801 ok(info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
, "%d: %#x != PAGE_EXECUTE_WRITECOPY\n", i
, info
.AllocationProtect
);
1802 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
1803 ok(info
.Type
== SEC_IMAGE
, "%d: %#x != SEC_IMAGE\n", i
, info
.Type
);
1804 if (info
.Protect
!= PAGE_NOACCESS
)
1805 ok(!memcmp((const char *)info
.BaseAddress
, section_data
, section
.SizeOfRawData
), "wrong section data\n");
1807 test_VirtualProtect(hlib
, (char *)hlib
+ section
.VirtualAddress
);
1809 /* Windows changes the WRITECOPY to WRITE protection on an image section write (for a changed page only) */
1810 if (is_mem_writable(info
.Protect
))
1812 char *p
= info
.BaseAddress
;
1814 SetLastError(0xdeadbeef);
1815 size
= VirtualQuery((char *)hlib
+ section
.VirtualAddress
, &info
, sizeof(info
));
1816 ok(size
== sizeof(info
), "%d: VirtualQuery error %d\n", i
, GetLastError());
1817 /* FIXME: remove the condition below once Wine is fixed */
1818 todo_wine_if (info
.Protect
== PAGE_WRITECOPY
|| info
.Protect
== PAGE_EXECUTE_WRITECOPY
)
1819 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
);
1822 SetLastError(0xdeadbeef);
1823 ret
= FreeLibrary(hlib
);
1824 ok(ret
, "FreeLibrary error %d\n", GetLastError());
1826 test_image_mapping(dll_name
, td
[i
].scn_page_access
, TRUE
);
1828 /* reset IMAGE_FILE_DLL otherwise CreateProcess fails */
1829 nt_header
.FileHeader
.Characteristics
= IMAGE_FILE_EXECUTABLE_IMAGE
| IMAGE_FILE_RELOCS_STRIPPED
;
1830 SetLastError(0xdeadbeef);
1831 hfile
= CreateFileA(dll_name
, GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
1832 /* LoadLibrary called on an already memory-mapped file in
1833 * test_image_mapping() above leads to a file handle leak
1834 * under nt4, and inability to overwrite and delete the file
1835 * due to sharing violation error. Ignore it and skip the test,
1836 * but leave a not deletable temporary file.
1838 ok(hfile
!= INVALID_HANDLE_VALUE
|| broken(hfile
== INVALID_HANDLE_VALUE
) /* nt4 */,
1839 "CreateFile error %d\n", GetLastError());
1840 if (hfile
== INVALID_HANDLE_VALUE
) goto nt4_is_broken
;
1841 SetFilePointer(hfile
, sizeof(dos_header
), NULL
, FILE_BEGIN
);
1842 SetLastError(0xdeadbeef);
1843 ret
= WriteFile(hfile
, &nt_header
, sizeof(DWORD
) + sizeof(IMAGE_FILE_HEADER
), &dummy
, NULL
);
1844 ok(ret
, "WriteFile error %d\n", GetLastError());
1847 memset(&sti
, 0, sizeof(sti
));
1848 sti
.cb
= sizeof(sti
);
1849 SetLastError(0xdeadbeef);
1850 ret
= CreateProcessA(dll_name
, NULL
, NULL
, NULL
, FALSE
, CREATE_SUSPENDED
, NULL
, NULL
, &sti
, &pi
);
1851 ok(ret
, "CreateProcess() error %d\n", GetLastError());
1853 SetLastError(0xdeadbeef);
1854 size
= VirtualQueryEx(pi
.hProcess
, (char *)hlib
+ section
.VirtualAddress
, &info
, sizeof(info
));
1855 ok(size
== sizeof(info
),
1856 "%d: VirtualQuery error %d\n", i
, GetLastError());
1857 ok(info
.BaseAddress
== (char *)hlib
+ section
.VirtualAddress
, "%d: got %p != expected %p\n", i
, info
.BaseAddress
, (char *)hlib
+ section
.VirtualAddress
);
1858 ok(info
.RegionSize
== page_size
, "%d: got %#lx != expected %#x\n", i
, info
.RegionSize
, page_size
);
1859 ok(info
.Protect
== td
[i
].scn_page_access
, "%d: got %#x != expected %#x\n", i
, info
.Protect
, td
[i
].scn_page_access
);
1860 ok(info
.AllocationBase
== hlib
, "%d: %p != %p\n", i
, info
.AllocationBase
, hlib
);
1861 ok(info
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
, "%d: %#x != PAGE_EXECUTE_WRITECOPY\n", i
, info
.AllocationProtect
);
1862 ok(info
.State
== MEM_COMMIT
, "%d: %#x != MEM_COMMIT\n", i
, info
.State
);
1863 ok(info
.Type
== SEC_IMAGE
, "%d: %#x != SEC_IMAGE\n", i
, info
.Type
);
1864 if (info
.Protect
!= PAGE_NOACCESS
)
1866 SetLastError(0xdeadbeef);
1867 ret
= ReadProcessMemory(pi
.hProcess
, info
.BaseAddress
, buf
, section
.SizeOfRawData
, NULL
);
1868 ok(ret
, "ReadProcessMemory() error %d\n", GetLastError());
1869 ok(!memcmp(buf
, section_data
, section
.SizeOfRawData
), "wrong section data\n");
1872 SetLastError(0xdeadbeef);
1873 ret
= TerminateProcess(pi
.hProcess
, 0);
1874 ok(ret
, "TerminateProcess() error %d\n", GetLastError());
1875 ret
= WaitForSingleObject(pi
.hProcess
, 3000);
1876 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed: %x\n", ret
);
1878 CloseHandle(pi
.hThread
);
1879 CloseHandle(pi
.hProcess
);
1881 test_image_mapping(dll_name
, td
[i
].scn_page_access
, FALSE
);
1884 SetLastError(0xdeadbeef);
1885 ret
= DeleteFileA(dll_name
);
1886 ok(ret
|| broken(!ret
) /* nt4 */, "DeleteFile error %d\n", GetLastError());
1890 static void test_import_resolution(void)
1892 char temp_path
[MAX_PATH
];
1893 char dll_name
[MAX_PATH
];
1901 IMAGE_IMPORT_DESCRIPTOR descr
[2];
1902 IMAGE_THUNK_DATA original_thunks
[2];
1903 IMAGE_THUNK_DATA thunks
[2];
1905 struct { WORD hint
; char name
[32]; } function
;
1906 IMAGE_TLS_DIRECTORY tls
;
1910 IMAGE_NT_HEADERS nt
;
1911 IMAGE_SECTION_HEADER section
;
1914 for (test
= 0; test
< 3; test
++)
1916 #define DATA_RVA(ptr) (page_size + ((char *)(ptr) - (char *)&data))
1917 nt
= nt_header_template
;
1918 nt
.FileHeader
.NumberOfSections
= 1;
1919 nt
.FileHeader
.SizeOfOptionalHeader
= sizeof(IMAGE_OPTIONAL_HEADER
);
1920 nt
.FileHeader
.Characteristics
= IMAGE_FILE_EXECUTABLE_IMAGE
| IMAGE_FILE_32BIT_MACHINE
| IMAGE_FILE_RELOCS_STRIPPED
;
1921 if (test
!= 2) nt
.FileHeader
.Characteristics
|= IMAGE_FILE_DLL
;
1922 nt
.OptionalHeader
.SectionAlignment
= page_size
;
1923 nt
.OptionalHeader
.FileAlignment
= 0x200;
1924 nt
.OptionalHeader
.ImageBase
= 0x12340000;
1925 nt
.OptionalHeader
.SizeOfImage
= 2 * page_size
;
1926 nt
.OptionalHeader
.SizeOfHeaders
= nt
.OptionalHeader
.FileAlignment
;
1927 nt
.OptionalHeader
.NumberOfRvaAndSizes
= IMAGE_NUMBEROF_DIRECTORY_ENTRIES
;
1928 memset( nt
.OptionalHeader
.DataDirectory
, 0, sizeof(nt
.OptionalHeader
.DataDirectory
) );
1929 nt
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].Size
= sizeof(data
.descr
);
1930 nt
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
= DATA_RVA(data
.descr
);
1931 nt
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_TLS
].Size
= sizeof(data
.tls
);
1932 nt
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_TLS
].VirtualAddress
= DATA_RVA(&data
.tls
);
1934 memset( &data
, 0, sizeof(data
) );
1935 U(data
.descr
[0]).OriginalFirstThunk
= DATA_RVA( data
.original_thunks
);
1936 data
.descr
[0].FirstThunk
= DATA_RVA( data
.thunks
);
1937 data
.descr
[0].Name
= DATA_RVA( data
.module
);
1938 strcpy( data
.module
, "kernel32.dll" );
1939 strcpy( data
.function
.name
, "CreateEventA" );
1940 data
.original_thunks
[0].u1
.AddressOfData
= DATA_RVA( &data
.function
);
1941 data
.thunks
[0].u1
.AddressOfData
= 0xdeadbeef;
1943 data
.tls
.StartAddressOfRawData
= nt
.OptionalHeader
.ImageBase
+ DATA_RVA( data
.tls_data
);
1944 data
.tls
.EndAddressOfRawData
= data
.tls
.StartAddressOfRawData
+ sizeof(data
.tls_data
);
1945 data
.tls
.AddressOfIndex
= nt
.OptionalHeader
.ImageBase
+ DATA_RVA( &data
.tls_index
);
1946 strcpy( data
.tls_data
, "hello world" );
1947 data
.tls_index
= 9999;
1949 GetTempPathA(MAX_PATH
, temp_path
);
1950 GetTempFileNameA(temp_path
, "ldr", 0, dll_name
);
1952 hfile
= CreateFileA(dll_name
, GENERIC_WRITE
, FILE_SHARE_READ
, NULL
, CREATE_ALWAYS
, 0, 0);
1953 ok( hfile
!= INVALID_HANDLE_VALUE
, "creation failed\n" );
1955 memset( §ion
, 0, sizeof(section
) );
1956 memcpy( section
.Name
, ".text", sizeof(".text") );
1957 section
.PointerToRawData
= nt
.OptionalHeader
.FileAlignment
;
1958 section
.VirtualAddress
= nt
.OptionalHeader
.SectionAlignment
;
1959 section
.Misc
.VirtualSize
= sizeof(data
);
1960 section
.SizeOfRawData
= sizeof(data
);
1961 section
.Characteristics
= IMAGE_SCN_CNT_INITIALIZED_DATA
| IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_WRITE
;
1963 WriteFile(hfile
, &dos_header
, sizeof(dos_header
), &dummy
, NULL
);
1964 WriteFile(hfile
, &nt
, sizeof(nt
), &dummy
, NULL
);
1965 WriteFile(hfile
, §ion
, sizeof(section
), &dummy
, NULL
);
1967 SetFilePointer( hfile
, section
.PointerToRawData
, NULL
, SEEK_SET
);
1968 WriteFile(hfile
, &data
, sizeof(data
), &dummy
, NULL
);
1970 CloseHandle( hfile
);
1974 case 0: /* normal load */
1975 mod
= LoadLibraryA( dll_name
);
1976 ok( mod
!= NULL
, "failed to load err %u\n", GetLastError() );
1978 ptr
= (struct imports
*)((char *)mod
+ page_size
);
1979 expect
= GetProcAddress( GetModuleHandleA( data
.module
), data
.function
.name
);
1980 ok( (void *)ptr
->thunks
[0].u1
.Function
== expect
, "thunk %p instead of %p for %s.%s\n",
1981 (void *)ptr
->thunks
[0].u1
.Function
, expect
, data
.module
, data
.function
.name
);
1982 ok( ptr
->tls_index
< 32 || broken(ptr
->tls_index
== 9999), /* before vista */
1983 "wrong tls index %d\n", ptr
->tls_index
);
1984 if (ptr
->tls_index
!= 9999)
1986 str
= ((char **)NtCurrentTeb()->ThreadLocalStoragePointer
)[ptr
->tls_index
];
1987 ok( !strcmp( str
, "hello world" ), "wrong tls data '%s' at %p\n", str
, str
);
1991 case 1: /* load with DONT_RESOLVE_DLL_REFERENCES doesn't resolve imports */
1992 mod
= LoadLibraryExA( dll_name
, 0, DONT_RESOLVE_DLL_REFERENCES
);
1993 ok( mod
!= NULL
, "failed to load err %u\n", GetLastError() );
1995 ptr
= (struct imports
*)((char *)mod
+ page_size
);
1996 ok( ptr
->thunks
[0].u1
.Function
== 0xdeadbeef, "thunk resolved to %p for %s.%s\n",
1997 (void *)ptr
->thunks
[0].u1
.Function
, data
.module
, data
.function
.name
);
1998 ok( ptr
->tls_index
== 9999, "wrong tls index %d\n", ptr
->tls_index
);
2000 mod2
= LoadLibraryA( dll_name
);
2001 ok( mod2
== mod
, "loaded twice %p / %p\n", mod
, mod2
);
2002 ok( ptr
->thunks
[0].u1
.Function
== 0xdeadbeef, "thunk resolved to %p for %s.%s\n",
2003 (void *)ptr
->thunks
[0].u1
.Function
, data
.module
, data
.function
.name
);
2004 ok( ptr
->tls_index
== 9999, "wrong tls index %d\n", ptr
->tls_index
);
2005 FreeLibrary( mod2
);
2008 case 2: /* load without IMAGE_FILE_DLL doesn't resolve imports */
2009 mod
= LoadLibraryA( dll_name
);
2010 ok( mod
!= NULL
, "failed to load err %u\n", GetLastError() );
2012 ptr
= (struct imports
*)((char *)mod
+ page_size
);
2013 ok( ptr
->thunks
[0].u1
.Function
== 0xdeadbeef, "thunk resolved to %p for %s.%s\n",
2014 (void *)ptr
->thunks
[0].u1
.Function
, data
.module
, data
.function
.name
);
2015 ok( ptr
->tls_index
== 9999, "wrong tls index %d\n", ptr
->tls_index
);
2019 DeleteFileA( dll_name
);
2024 #define MAX_COUNT 10
2025 static HANDLE attached_thread
[MAX_COUNT
];
2026 static DWORD attached_thread_count
;
2027 static HANDLE event
, mutex
, semaphore
;
2028 static HANDLE stop_event
, loader_lock_event
, peb_lock_event
, heap_lock_event
, cs_lock_event
, ack_event
;
2029 static CRITICAL_SECTION cs_lock
;
2030 static int test_dll_phase
, inside_loader_lock
, inside_peb_lock
, inside_heap_lock
, inside_cs_lock
;
2031 static LONG fls_callback_count
;
2033 static DWORD WINAPI
mutex_thread_proc(void *param
)
2035 HANDLE wait_list
[5];
2038 ret
= WaitForSingleObject(mutex
, 0);
2039 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %#x\n", ret
);
2043 wait_list
[0] = stop_event
;
2044 wait_list
[1] = loader_lock_event
;
2045 wait_list
[2] = peb_lock_event
;
2046 wait_list
[3] = heap_lock_event
;
2047 wait_list
[4] = cs_lock_event
;
2049 trace("%04x: mutex_thread_proc: starting\n", GetCurrentThreadId());
2052 ret
= WaitForMultipleObjects(ARRAY_SIZE(wait_list
), wait_list
, FALSE
, 50);
2053 if (ret
== WAIT_OBJECT_0
) break;
2054 else if (ret
== WAIT_OBJECT_0
+ 1)
2056 ULONG_PTR loader_lock_magic
;
2057 trace("%04x: mutex_thread_proc: Entering loader lock\n", GetCurrentThreadId());
2058 ret
= pLdrLockLoaderLock(0, NULL
, &loader_lock_magic
);
2059 ok(!ret
, "LdrLockLoaderLock error %#x\n", ret
);
2060 inside_loader_lock
++;
2061 SetEvent(ack_event
);
2063 else if (ret
== WAIT_OBJECT_0
+ 2)
2065 trace("%04x: mutex_thread_proc: Entering PEB lock\n", GetCurrentThreadId());
2066 pRtlAcquirePebLock();
2068 SetEvent(ack_event
);
2070 else if (ret
== WAIT_OBJECT_0
+ 3)
2072 trace("%04x: mutex_thread_proc: Entering heap lock\n", GetCurrentThreadId());
2073 HeapLock(GetProcessHeap());
2075 SetEvent(ack_event
);
2077 else if (ret
== WAIT_OBJECT_0
+ 4)
2079 trace("%04x: mutex_thread_proc: Entering CS lock\n", GetCurrentThreadId());
2080 EnterCriticalSection(&cs_lock
);
2082 SetEvent(ack_event
);
2086 trace("%04x: mutex_thread_proc: exiting\n", GetCurrentThreadId());
2090 static DWORD WINAPI
semaphore_thread_proc(void *param
)
2094 ret
= WaitForSingleObject(semaphore
, 0);
2095 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %#x\n", ret
);
2101 if (winetest_debug
> 1)
2102 trace("%04x: semaphore_thread_proc: still alive\n", GetCurrentThreadId());
2103 if (WaitForSingleObject(stop_event
, 50) != WAIT_TIMEOUT
) break;
2106 trace("%04x: semaphore_thread_proc: exiting\n", GetCurrentThreadId());
2110 static DWORD WINAPI
noop_thread_proc(void *param
)
2114 LONG
*noop_thread_started
= param
;
2115 InterlockedIncrement(noop_thread_started
);
2118 trace("%04x: noop_thread_proc: exiting\n", GetCurrentThreadId());
2122 static VOID WINAPI
fls_callback(PVOID lpFlsData
)
2124 ok(lpFlsData
== (void*) 0x31415, "lpFlsData is %p, expected %p\n", lpFlsData
, (void*) 0x31415);
2125 InterlockedIncrement(&fls_callback_count
);
2128 static BOOL WINAPI
dll_entry_point(HINSTANCE hinst
, DWORD reason
, LPVOID param
)
2130 static LONG noop_thread_started
;
2131 static DWORD fls_index
= FLS_OUT_OF_INDEXES
;
2132 static int fls_count
= 0;
2133 static int thread_detach_count
= 0;
2136 ok(!inside_loader_lock
, "inside_loader_lock should not be set\n");
2137 ok(!inside_peb_lock
, "inside_peb_lock should not be set\n");
2141 case DLL_PROCESS_ATTACH
:
2142 trace("dll: %p, DLL_PROCESS_ATTACH, %p\n", hinst
, param
);
2144 ret
= pRtlDllShutdownInProgress();
2145 ok(!ret
, "RtlDllShutdownInProgress returned %d\n", ret
);
2147 /* Set up the FLS slot, if FLS is available */
2152 ret
= pFlsAlloc(&fls_callback
);
2153 ok(ret
!= FLS_OUT_OF_INDEXES
, "FlsAlloc returned %d\n", ret
);
2155 SetLastError(0xdeadbeef);
2156 value
= pFlsGetValue(fls_index
);
2157 ok(!value
, "FlsGetValue returned %p, expected NULL\n", value
);
2158 ok(GetLastError() == ERROR_SUCCESS
, "FlsGetValue failed with error %u\n", GetLastError());
2159 bret
= pFlsSetValue(fls_index
, (void*) 0x31415);
2160 ok(bret
, "FlsSetValue failed\n");
2165 case DLL_PROCESS_DETACH
:
2167 DWORD code
, expected_code
, i
;
2168 HANDLE handle
, process
;
2171 LARGE_INTEGER offset
;
2174 trace("dll: %p, DLL_PROCESS_DETACH, %p\n", hinst
, param
);
2176 if (test_dll_phase
== 4 || test_dll_phase
== 5)
2178 ok(0, "dll_entry_point(DLL_PROCESS_DETACH) should not be called\n");
2182 /* The process should already deadlock at this point */
2183 if (test_dll_phase
== 6)
2185 /* In reality, code below never gets executed, probably some other
2186 * code tries to access process heap and deadlocks earlier, even XP
2187 * doesn't call the DLL entry point on process detach either.
2189 HeapLock(GetProcessHeap());
2191 ok(0, "dll_entry_point: process should already deadlock\n");
2194 else if (test_dll_phase
== 7)
2196 EnterCriticalSection(&cs_lock
);
2199 if (test_dll_phase
== 0 || test_dll_phase
== 1 || test_dll_phase
== 3 || test_dll_phase
== 7)
2200 ok(param
!= NULL
, "dll: param %p\n", param
);
2202 ok(!param
, "dll: param %p\n", param
);
2204 if (test_dll_phase
== 0 || test_dll_phase
== 1) expected_code
= 195;
2205 else if (test_dll_phase
== 3) expected_code
= 196;
2206 else if (test_dll_phase
== 7) expected_code
= 199;
2207 else expected_code
= STILL_ACTIVE
;
2209 if (test_dll_phase
== 3)
2211 ret
= pRtlDllShutdownInProgress();
2212 ok(ret
, "RtlDllShutdownInProgress returned %d\n", ret
);
2216 ret
= pRtlDllShutdownInProgress();
2218 /* FIXME: remove once Wine is fixed */
2219 todo_wine_if (!(expected_code
== STILL_ACTIVE
|| expected_code
== 196))
2220 ok(!ret
|| broken(ret
) /* before Vista */, "RtlDllShutdownInProgress returned %d\n", ret
);
2223 /* In the case that the process is terminating, FLS slots should still be accessible, but
2224 * the callback should be already run for this thread and the contents already NULL.
2225 * Note that this is broken for Win2k3, which runs the callbacks *after* the DLL entry
2226 * point has already run.
2228 if (param
&& pFlsGetValue
)
2231 SetLastError(0xdeadbeef);
2232 value
= pFlsGetValue(fls_index
);
2235 ok(broken(value
== (void*) 0x31415) || /* Win2k3 */
2236 value
== NULL
, "FlsGetValue returned %p, expected NULL\n", value
);
2238 ok(GetLastError() == ERROR_SUCCESS
, "FlsGetValue failed with error %u\n", GetLastError());
2241 ok(broken(fls_callback_count
== thread_detach_count
) || /* Win2k3 */
2242 fls_callback_count
== thread_detach_count
+ 1,
2243 "wrong FLS callback count %d, expected %d\n", fls_callback_count
, thread_detach_count
+ 1);
2249 /* Call FlsFree now and run the remaining callbacks from uncleanly terminated threads */
2250 ret
= pFlsFree(fls_index
);
2251 ok(ret
, "FlsFree failed with error %u\n", GetLastError());
2252 fls_index
= FLS_OUT_OF_INDEXES
;
2255 ok(fls_callback_count
== fls_count
,
2256 "wrong FLS callback count %d, expected %d\n", fls_callback_count
, fls_count
);
2260 ok(attached_thread_count
>= 2, "attached thread count should be >= 2\n");
2262 for (i
= 0; i
< attached_thread_count
; i
++)
2264 /* Calling GetExitCodeThread() without waiting for thread termination
2265 * leads to different results due to a race condition.
2267 if (expected_code
!= STILL_ACTIVE
)
2269 ret
= WaitForSingleObject(attached_thread
[i
], 1000);
2270 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %#x\n", ret
);
2272 ret
= GetExitCodeThread(attached_thread
[i
], &code
);
2273 trace("dll: GetExitCodeThread(%u) => %d,%u\n", i
, ret
, code
);
2274 ok(ret
== 1, "GetExitCodeThread returned %d, expected 1\n", ret
);
2275 ok(code
== expected_code
, "expected thread exit code %u, got %u\n", expected_code
, code
);
2278 ret
= WaitForSingleObject(event
, 0);
2279 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
2281 ret
= WaitForSingleObject(mutex
, 0);
2282 if (expected_code
== STILL_ACTIVE
)
2283 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
2285 ok(ret
== WAIT_ABANDONED
, "expected WAIT_ABANDONED, got %#x\n", ret
);
2287 /* semaphore is not abandoned on thread termination */
2288 ret
= WaitForSingleObject(semaphore
, 0);
2289 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
2291 if (expected_code
== STILL_ACTIVE
)
2293 ret
= WaitForSingleObject(attached_thread
[0], 0);
2294 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
2295 ret
= WaitForSingleObject(attached_thread
[1], 0);
2296 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
2300 ret
= WaitForSingleObject(attached_thread
[0], 0);
2301 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %#x\n", ret
);
2302 ret
= WaitForSingleObject(attached_thread
[1], 0);
2303 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %#x\n", ret
);
2306 /* win7 doesn't allow creating a thread during process shutdown but
2307 * earlier Windows versions allow it.
2309 noop_thread_started
= 0;
2310 SetLastError(0xdeadbeef);
2311 handle
= CreateThread(NULL
, 0, noop_thread_proc
, &noop_thread_started
, 0, &ret
);
2314 ok(!handle
|| broken(handle
!= 0) /* before win7 */, "CreateThread should fail\n");
2316 ok(GetLastError() == ERROR_ACCESS_DENIED
, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
2319 ret
= WaitForSingleObject(handle
, 1000);
2320 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
2321 CloseHandle(handle
);
2326 ok(handle
!= 0, "CreateThread error %d\n", GetLastError());
2327 ret
= WaitForSingleObject(handle
, 1000);
2328 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
2329 ok(!noop_thread_started
|| broken(noop_thread_started
) /* XP64 */, "thread shouldn't start yet\n");
2330 CloseHandle(handle
);
2333 SetLastError(0xdeadbeef);
2334 process
= OpenProcess(PROCESS_ALL_ACCESS_NT4
, FALSE
, GetCurrentProcessId());
2335 ok(process
!= NULL
, "OpenProcess error %d\n", GetLastError());
2337 noop_thread_started
= 0;
2338 SetLastError(0xdeadbeef);
2339 handle
= CreateRemoteThread(process
, NULL
, 0, noop_thread_proc
, &noop_thread_started
, 0, &ret
);
2342 ok(!handle
|| broken(handle
!= 0) /* before win7 */, "CreateRemoteThread should fail\n");
2344 ok(GetLastError() == ERROR_ACCESS_DENIED
, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
2347 ret
= WaitForSingleObject(handle
, 1000);
2348 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
2349 CloseHandle(handle
);
2354 ok(handle
!= 0, "CreateRemoteThread error %d\n", GetLastError());
2355 ret
= WaitForSingleObject(handle
, 1000);
2356 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
2357 ok(!noop_thread_started
|| broken(noop_thread_started
) /* XP64 */, "thread shouldn't start yet\n");
2358 CloseHandle(handle
);
2361 SetLastError(0xdeadbeef);
2362 handle
= CreateFileMappingW(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
2363 ok(handle
!= 0, "CreateFileMapping error %d\n", GetLastError());
2365 offset
.u
.LowPart
= 0;
2366 offset
.u
.HighPart
= 0;
2369 ret
= pNtMapViewOfSection(handle
, process
, &addr
, 0, 0, &offset
,
2370 &size
, 1 /* ViewShare */, 0, PAGE_READONLY
);
2371 ok(ret
== STATUS_SUCCESS
, "NtMapViewOfSection error %#x\n", ret
);
2372 ret
= pNtUnmapViewOfSection(process
, addr
);
2373 ok(ret
== STATUS_SUCCESS
, "NtUnmapViewOfSection error %#x\n", ret
);
2375 CloseHandle(handle
);
2376 CloseHandle(process
);
2378 handle
= GetModuleHandleA("winver.exe");
2379 ok(!handle
, "winver.exe shouldn't be loaded yet\n");
2380 SetLastError(0xdeadbeef);
2381 handle
= LoadLibraryA("winver.exe");
2382 ok(handle
!= 0, "LoadLibrary error %d\n", GetLastError());
2383 SetLastError(0xdeadbeef);
2384 ret
= FreeLibrary(handle
);
2385 ok(ret
, "FreeLibrary error %d\n", GetLastError());
2386 handle
= GetModuleHandleA("winver.exe");
2388 ok(handle
!= 0, "winver.exe should not be unloaded\n");
2391 ok(!handle
|| broken(handle
!= 0) /* before win7 */, "winver.exe should be unloaded\n");
2393 SetLastError(0xdeadbeef);
2394 ret
= WaitForDebugEvent(&de
, 0);
2395 ok(!ret
, "WaitForDebugEvent should fail\n");
2397 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
2399 SetLastError(0xdeadbeef);
2400 ret
= DebugActiveProcess(GetCurrentProcessId());
2401 ok(!ret
, "DebugActiveProcess should fail\n");
2402 ok(GetLastError() == ERROR_ACCESS_DENIED
, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
2404 SetLastError(0xdeadbeef);
2405 ret
= WaitForDebugEvent(&de
, 0);
2406 ok(!ret
, "WaitForDebugEvent should fail\n");
2407 ok(GetLastError() == ERROR_SEM_TIMEOUT
, "expected ERROR_SEM_TIMEOUT, got %d\n", GetLastError());
2409 if (test_dll_phase
== 2)
2411 trace("dll: call ExitProcess()\n");
2412 *child_failures
= winetest_get_failures();
2415 trace("dll: %p, DLL_PROCESS_DETACH, %p => DONE\n", hinst
, param
);
2418 case DLL_THREAD_ATTACH
:
2419 trace("dll: %p, DLL_THREAD_ATTACH, %p\n", hinst
, param
);
2421 ret
= pRtlDllShutdownInProgress();
2422 ok(!ret
, "RtlDllShutdownInProgress returned %d\n", ret
);
2424 if (attached_thread_count
< MAX_COUNT
)
2426 DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &attached_thread
[attached_thread_count
],
2427 0, TRUE
, DUPLICATE_SAME_ACCESS
);
2428 attached_thread_count
++;
2431 /* Make sure the FLS slot is empty, if FLS is available */
2436 SetLastError(0xdeadbeef);
2437 value
= pFlsGetValue(fls_index
);
2438 ok(!value
, "FlsGetValue returned %p, expected NULL\n", value
);
2440 ok(GetLastError() == ERROR_SUCCESS
, "FlsGetValue failed with error %u\n", GetLastError());
2441 ret
= pFlsSetValue(fls_index
, (void*) 0x31415);
2442 ok(ret
, "FlsSetValue failed\n");
2447 case DLL_THREAD_DETACH
:
2448 trace("dll: %p, DLL_THREAD_DETACH, %p\n", hinst
, param
);
2449 thread_detach_count
++;
2451 ret
= pRtlDllShutdownInProgress();
2452 /* win7 doesn't allow creating a thread during process shutdown but
2453 * earlier Windows versions allow it. In that case DLL_THREAD_DETACH is
2454 * sent on thread exit, but DLL_THREAD_ATTACH is never received.
2456 if (noop_thread_started
)
2457 ok(ret
, "RtlDllShutdownInProgress returned %d\n", ret
);
2459 ok(!ret
, "RtlDllShutdownInProgress returned %d\n", ret
);
2461 /* FLS data should already be destroyed, if FLS is available.
2462 * Note that this is broken for Win2k3, which runs the callbacks *after* the DLL entry
2463 * point has already run.
2465 if (pFlsGetValue
&& fls_index
!= FLS_OUT_OF_INDEXES
)
2468 SetLastError(0xdeadbeef);
2469 value
= pFlsGetValue(fls_index
);
2472 ok(broken(value
== (void*) 0x31415) || /* Win2k3 */
2473 !value
, "FlsGetValue returned %p, expected NULL\n", value
);
2475 ok(GetLastError() == ERROR_SUCCESS
, "FlsGetValue failed with error %u\n", GetLastError());
2480 trace("dll: %p, %d, %p\n", hinst
, reason
, param
);
2484 *child_failures
= winetest_get_failures();
2489 static void child_process(const char *dll_name
, DWORD target_offset
)
2492 DWORD ret
, dummy
, i
, code
, expected_code
;
2493 HANDLE file
, thread
, process
;
2495 struct PROCESS_BASIC_INFORMATION_PRIVATE pbi
;
2498 trace("phase %d: writing %p at %#x\n", test_dll_phase
, dll_entry_point
, target_offset
);
2500 SetLastError(0xdeadbeef);
2501 mutex
= CreateMutexW(NULL
, FALSE
, NULL
);
2502 ok(mutex
!= 0, "CreateMutex error %d\n", GetLastError());
2504 SetLastError(0xdeadbeef);
2505 semaphore
= CreateSemaphoreW(NULL
, 1, 1, NULL
);
2506 ok(semaphore
!= 0, "CreateSemaphore error %d\n", GetLastError());
2508 SetLastError(0xdeadbeef);
2509 event
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
2510 ok(event
!= 0, "CreateEvent error %d\n", GetLastError());
2512 SetLastError(0xdeadbeef);
2513 loader_lock_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
2514 ok(loader_lock_event
!= 0, "CreateEvent error %d\n", GetLastError());
2516 SetLastError(0xdeadbeef);
2517 peb_lock_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
2518 ok(peb_lock_event
!= 0, "CreateEvent error %d\n", GetLastError());
2520 SetLastError(0xdeadbeef);
2521 heap_lock_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
2522 ok(heap_lock_event
!= 0, "CreateEvent error %d\n", GetLastError());
2524 InitializeCriticalSection(&cs_lock
);
2525 SetLastError(0xdeadbeef);
2526 cs_lock_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
2527 ok(cs_lock_event
!= 0, "CreateEvent error %d\n", GetLastError());
2529 SetLastError(0xdeadbeef);
2530 ack_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
2531 ok(ack_event
!= 0, "CreateEvent error %d\n", GetLastError());
2533 file
= CreateFileA(dll_name
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
2534 if (file
== INVALID_HANDLE_VALUE
)
2536 ok(0, "could not open %s\n", dll_name
);
2539 SetFilePointer(file
, target_offset
, NULL
, FILE_BEGIN
);
2540 SetLastError(0xdeadbeef);
2541 target
= dll_entry_point
;
2542 ret
= WriteFile(file
, &target
, sizeof(target
), &dummy
, NULL
);
2543 ok(ret
, "WriteFile error %d\n", GetLastError());
2546 SetLastError(0xdeadbeef);
2547 hmod
= LoadLibraryA(dll_name
);
2548 ok(hmod
!= 0, "LoadLibrary error %d\n", GetLastError());
2550 SetLastError(0xdeadbeef);
2551 stop_event
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
2552 ok(stop_event
!= 0, "CreateEvent error %d\n", GetLastError());
2554 SetLastError(0xdeadbeef);
2555 thread
= CreateThread(NULL
, 0, mutex_thread_proc
, event
, 0, &dummy
);
2556 ok(thread
!= 0, "CreateThread error %d\n", GetLastError());
2557 WaitForSingleObject(event
, 3000);
2558 CloseHandle(thread
);
2562 SetLastError(0xdeadbeef);
2563 thread
= CreateThread(NULL
, 0, semaphore_thread_proc
, event
, 0, &dummy
);
2564 ok(thread
!= 0, "CreateThread error %d\n", GetLastError());
2565 WaitForSingleObject(event
, 3000);
2566 CloseHandle(thread
);
2571 ok(attached_thread_count
== 2, "attached thread count should be 2\n");
2572 for (i
= 0; i
< attached_thread_count
; i
++)
2574 ret
= GetExitCodeThread(attached_thread
[i
], &code
);
2575 trace("child: GetExitCodeThread(%u) => %d,%u\n", i
, ret
, code
);
2576 ok(ret
== 1, "GetExitCodeThread returned %d, expected 1\n", ret
);
2577 ok(code
== STILL_ACTIVE
, "expected thread exit code STILL_ACTIVE, got %u\n", code
);
2580 ret
= WaitForSingleObject(attached_thread
[0], 0);
2581 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
2582 ret
= WaitForSingleObject(attached_thread
[1], 0);
2583 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
2585 ret
= WaitForSingleObject(event
, 0);
2586 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
2587 ret
= WaitForSingleObject(mutex
, 0);
2588 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
2589 ret
= WaitForSingleObject(semaphore
, 0);
2590 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
2592 ret
= pRtlDllShutdownInProgress();
2593 ok(!ret
, "RtlDllShutdownInProgress returned %d\n", ret
);
2595 SetLastError(0xdeadbeef);
2596 process
= OpenProcess(PROCESS_ALL_ACCESS_NT4
, FALSE
, GetCurrentProcessId());
2597 ok(process
!= NULL
, "OpenProcess error %d\n", GetLastError());
2599 SetLastError(0xdeadbeef);
2600 ret
= TerminateProcess(0, 195);
2601 ok(!ret
, "TerminateProcess(0) should fail\n");
2602 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
2607 ret
= pNtSetInformationProcess(process
, ProcessAffinityMask
, &affinity
, sizeof(affinity
));
2608 ok(!ret
, "NtSetInformationProcess error %#x\n", ret
);
2610 switch (test_dll_phase
)
2613 ret
= pRtlDllShutdownInProgress();
2614 ok(!ret
, "RtlDllShutdownInProgress returned %d\n", ret
);
2616 trace("call NtTerminateProcess(0, 195)\n");
2617 ret
= pNtTerminateProcess(0, 195);
2618 ok(!ret
, "NtTerminateProcess error %#x\n", ret
);
2620 memset(&pbi
, 0, sizeof(pbi
));
2621 ret
= pNtQueryInformationProcess(process
, ProcessBasicInformation
, &pbi
, sizeof(pbi
), NULL
);
2622 ok(!ret
, "NtQueryInformationProcess error %#x\n", ret
);
2623 ok(pbi
.ExitStatus
== STILL_ACTIVE
|| pbi
.ExitStatus
== 195,
2624 "expected STILL_ACTIVE, got %lu\n", pbi
.ExitStatus
);
2626 ret
= pNtSetInformationProcess(process
, ProcessAffinityMask
, &affinity
, sizeof(affinity
));
2627 ok(!ret
, "NtSetInformationProcess error %#x\n", ret
);
2629 ret
= pRtlDllShutdownInProgress();
2630 ok(!ret
, "RtlDllShutdownInProgress returned %d\n", ret
);
2632 hmod
= GetModuleHandleA(dll_name
);
2633 ok(hmod
!= 0, "DLL should not be unloaded\n");
2635 SetLastError(0xdeadbeef);
2636 thread
= CreateThread(NULL
, 0, noop_thread_proc
, &dummy
, 0, &ret
);
2637 ok(!thread
|| broken(thread
!= 0) /* before win7 */, "CreateThread should fail\n");
2639 ok(GetLastError() == ERROR_ACCESS_DENIED
, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
2642 ret
= WaitForSingleObject(thread
, 1000);
2643 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %#x\n", ret
);
2644 CloseHandle(thread
);
2647 trace("call LdrShutdownProcess()\n");
2648 pLdrShutdownProcess();
2650 ret
= pRtlDllShutdownInProgress();
2651 ok(ret
, "RtlDllShutdownInProgress returned %d\n", ret
);
2653 hmod
= GetModuleHandleA(dll_name
);
2654 ok(hmod
!= 0, "DLL should not be unloaded\n");
2656 memset(&pbi
, 0, sizeof(pbi
));
2657 ret
= pNtQueryInformationProcess(process
, ProcessBasicInformation
, &pbi
, sizeof(pbi
), NULL
);
2658 ok(!ret
, "NtQueryInformationProcess error %#x\n", ret
);
2659 ok(pbi
.ExitStatus
== STILL_ACTIVE
|| pbi
.ExitStatus
== 195,
2660 "expected STILL_ACTIVE, got %lu\n", pbi
.ExitStatus
);
2662 ret
= pNtSetInformationProcess(process
, ProcessAffinityMask
, &affinity
, sizeof(affinity
));
2663 ok(!ret
, "NtSetInformationProcess error %#x\n", ret
);
2666 case 1: /* normal ExitProcess */
2667 ret
= pRtlDllShutdownInProgress();
2668 ok(!ret
, "RtlDllShutdownInProgress returned %d\n", ret
);
2671 case 2: /* ExitProcess will be called by the PROCESS_DETACH handler */
2672 ret
= pRtlDllShutdownInProgress();
2673 ok(!ret
, "RtlDllShutdownInProgress returned %d\n", ret
);
2675 trace("call FreeLibrary(%p)\n", hmod
);
2676 SetLastError(0xdeadbeef);
2677 ret
= FreeLibrary(hmod
);
2678 ok(ret
, "FreeLibrary error %d\n", GetLastError());
2679 hmod
= GetModuleHandleA(dll_name
);
2680 ok(!hmod
, "DLL should be unloaded\n");
2682 if (test_dll_phase
== 2)
2683 ok(0, "FreeLibrary+ExitProcess should never return\n");
2685 ret
= pRtlDllShutdownInProgress();
2686 ok(!ret
, "RtlDllShutdownInProgress returned %d\n", ret
);
2691 trace("signalling thread exit\n");
2692 SetEvent(stop_event
);
2696 trace("setting loader_lock_event\n");
2697 SetEvent(loader_lock_event
);
2698 WaitForSingleObject(ack_event
, 1000);
2699 ok(inside_loader_lock
!= 0, "inside_loader_lock is not set\n");
2701 /* calling NtTerminateProcess should not cause a deadlock */
2702 trace("call NtTerminateProcess(0, 198)\n");
2703 ret
= pNtTerminateProcess(0, 198);
2704 ok(!ret
, "NtTerminateProcess error %#x\n", ret
);
2706 *child_failures
= winetest_get_failures();
2708 /* Windows fails to release loader lock acquired from another thread,
2709 * so the LdrUnlockLoaderLock call fails here and ExitProcess deadlocks
2710 * later on, so NtTerminateProcess is used instead.
2712 trace("call NtTerminateProcess(GetCurrentProcess(), 198)\n");
2713 pNtTerminateProcess(GetCurrentProcess(), 198);
2714 ok(0, "NtTerminateProcess should not return\n");
2718 trace("setting peb_lock_event\n");
2719 SetEvent(peb_lock_event
);
2720 WaitForSingleObject(ack_event
, 1000);
2721 ok(inside_peb_lock
!= 0, "inside_peb_lock is not set\n");
2723 *child_failures
= winetest_get_failures();
2725 /* calling ExitProcess should cause a deadlock */
2726 trace("call ExitProcess(198)\n");
2728 ok(0, "ExitProcess should not return\n");
2732 trace("setting heap_lock_event\n");
2733 SetEvent(heap_lock_event
);
2734 WaitForSingleObject(ack_event
, 1000);
2735 ok(inside_heap_lock
!= 0, "inside_heap_lock is not set\n");
2737 *child_failures
= winetest_get_failures();
2739 /* calling ExitProcess should cause a deadlock */
2740 trace("call ExitProcess(1)\n");
2742 ok(0, "ExitProcess should not return\n");
2746 trace("setting cs_lock_event\n");
2747 SetEvent(cs_lock_event
);
2748 WaitForSingleObject(ack_event
, 1000);
2749 ok(inside_cs_lock
!= 0, "inside_cs_lock is not set\n");
2751 *child_failures
= winetest_get_failures();
2753 /* calling ExitProcess should not cause a deadlock */
2754 trace("call ExitProcess(199)\n");
2756 ok(0, "ExitProcess should not return\n");
2764 if (test_dll_phase
== 0) expected_code
= 195;
2765 else if (test_dll_phase
== 3) expected_code
= 196;
2766 else if (test_dll_phase
== 4) expected_code
= 198;
2767 else expected_code
= STILL_ACTIVE
;
2769 if (expected_code
== STILL_ACTIVE
)
2771 ret
= WaitForSingleObject(attached_thread
[0], 100);
2772 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
2773 ret
= WaitForSingleObject(attached_thread
[1], 100);
2774 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %#x\n", ret
);
2778 ret
= WaitForSingleObject(attached_thread
[0], 2000);
2779 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %#x\n", ret
);
2780 ret
= WaitForSingleObject(attached_thread
[1], 2000);
2781 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %#x\n", ret
);
2784 for (i
= 0; i
< attached_thread_count
; i
++)
2786 ret
= GetExitCodeThread(attached_thread
[i
], &code
);
2787 trace("child: GetExitCodeThread(%u) => %d,%u\n", i
, ret
, code
);
2788 ok(ret
== 1, "GetExitCodeThread returned %d, expected 1\n", ret
);
2789 ok(code
== expected_code
, "expected thread exit code %u, got %u\n", expected_code
, code
);
2792 *child_failures
= winetest_get_failures();
2794 trace("call ExitProcess(195)\n");
2798 static void test_ExitProcess(void)
2800 #include "pshpack1.h"
2802 static struct section_data
2807 } section_data
= { { 0x48,0xb8 }, dll_entry_point
, { 0xff,0xe0 } };
2809 static struct section_data
2814 } section_data
= { 0xb8, dll_entry_point
, { 0xff,0xe0 } };
2816 #include "poppack.h"
2817 DWORD dummy
, file_align
;
2818 HANDLE file
, thread
, process
, hmap
, hmap_dup
;
2819 char temp_path
[MAX_PATH
], dll_name
[MAX_PATH
], cmdline
[MAX_PATH
* 2];
2820 DWORD ret
, target_offset
, old_prot
;
2821 char **argv
, buf
[256];
2822 PROCESS_INFORMATION pi
;
2823 STARTUPINFOA si
= { sizeof(si
) };
2825 struct PROCESS_BASIC_INFORMATION_PRIVATE pbi
;
2826 MEMORY_BASIC_INFORMATION mbi
;
2829 LARGE_INTEGER offset
;
2831 IMAGE_NT_HEADERS nt_header
;
2833 #if !defined(__i386__) && !defined(__x86_64__)
2834 skip("x86 specific ExitProcess test\n");
2838 if (!pRtlDllShutdownInProgress
)
2840 win_skip("RtlDllShutdownInProgress is not available on this platform (XP+)\n");
2843 if (!pNtQueryInformationProcess
|| !pNtSetInformationProcess
)
2845 win_skip("NtQueryInformationProcess/NtSetInformationProcess are not available on this platform\n");
2848 if (!pNtAllocateVirtualMemory
|| !pNtFreeVirtualMemory
)
2850 win_skip("NtAllocateVirtualMemory/NtFreeVirtualMemory are not available on this platform\n");
2854 /* prevent displaying of the "Unable to load this DLL" message box */
2855 SetErrorMode(SEM_FAILCRITICALERRORS
);
2857 GetTempPathA(MAX_PATH
, temp_path
);
2858 GetTempFileNameA(temp_path
, "ldr", 0, dll_name
);
2860 /*trace("creating %s\n", dll_name);*/
2861 file
= CreateFileA(dll_name
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
2862 if (file
== INVALID_HANDLE_VALUE
)
2864 ok(0, "could not create %s\n", dll_name
);
2868 SetLastError(0xdeadbeef);
2869 ret
= WriteFile(file
, &dos_header
, sizeof(dos_header
), &dummy
, NULL
);
2870 ok(ret
, "WriteFile error %d\n", GetLastError());
2872 nt_header
= nt_header_template
;
2873 nt_header
.FileHeader
.NumberOfSections
= 1;
2874 nt_header
.FileHeader
.SizeOfOptionalHeader
= sizeof(IMAGE_OPTIONAL_HEADER
);
2875 nt_header
.FileHeader
.Characteristics
= IMAGE_FILE_EXECUTABLE_IMAGE
| IMAGE_FILE_DLL
| IMAGE_FILE_RELOCS_STRIPPED
;
2877 nt_header
.OptionalHeader
.AddressOfEntryPoint
= 0x1000;
2878 nt_header
.OptionalHeader
.SectionAlignment
= 0x1000;
2879 nt_header
.OptionalHeader
.FileAlignment
= 0x200;
2880 nt_header
.OptionalHeader
.SizeOfImage
= sizeof(dos_header
) + sizeof(nt_header
) + sizeof(IMAGE_SECTION_HEADER
) + 0x1000;
2881 nt_header
.OptionalHeader
.SizeOfHeaders
= sizeof(dos_header
) + sizeof(nt_header
) + sizeof(IMAGE_SECTION_HEADER
);
2882 SetLastError(0xdeadbeef);
2883 ret
= WriteFile(file
, &nt_header
, sizeof(DWORD
) + sizeof(IMAGE_FILE_HEADER
), &dummy
, NULL
);
2884 ok(ret
, "WriteFile error %d\n", GetLastError());
2885 SetLastError(0xdeadbeef);
2886 ret
= WriteFile(file
, &nt_header
.OptionalHeader
, sizeof(IMAGE_OPTIONAL_HEADER
), &dummy
, NULL
);
2887 ok(ret
, "WriteFile error %d\n", GetLastError());
2889 section
.SizeOfRawData
= sizeof(section_data
);
2890 section
.PointerToRawData
= nt_header
.OptionalHeader
.FileAlignment
;
2891 section
.VirtualAddress
= nt_header
.OptionalHeader
.SectionAlignment
;
2892 section
.Misc
.VirtualSize
= sizeof(section_data
);
2893 section
.Characteristics
= IMAGE_SCN_CNT_CODE
| IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_EXECUTE
;
2894 SetLastError(0xdeadbeef);
2895 ret
= WriteFile(file
, §ion
, sizeof(section
), &dummy
, NULL
);
2896 ok(ret
, "WriteFile error %d\n", GetLastError());
2898 file_align
= nt_header
.OptionalHeader
.FileAlignment
- nt_header
.OptionalHeader
.SizeOfHeaders
;
2899 assert(file_align
< sizeof(filler
));
2900 SetLastError(0xdeadbeef);
2901 ret
= WriteFile(file
, filler
, file_align
, &dummy
, NULL
);
2902 ok(ret
, "WriteFile error %d\n", GetLastError());
2904 target_offset
= SetFilePointer(file
, 0, NULL
, FILE_CURRENT
) + FIELD_OFFSET(struct section_data
, target
);
2907 SetLastError(0xdeadbeef);
2908 ret
= WriteFile(file
, §ion_data
, sizeof(section_data
), &dummy
, NULL
);
2909 ok(ret
, "WriteFile error %d\n", GetLastError());
2913 winetest_get_mainargs(&argv
);
2916 *child_failures
= -1;
2917 sprintf(cmdline
, "\"%s\" loader %s %u 0", argv
[0], dll_name
, target_offset
);
2918 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
2919 ok(ret
, "CreateProcess(%s) error %d\n", cmdline
, GetLastError());
2920 ret
= WaitForSingleObject(pi
.hProcess
, 10000);
2921 ok(ret
== WAIT_OBJECT_0
, "child process failed to terminate\n");
2922 if (ret
!= WAIT_OBJECT_0
) TerminateProcess(pi
.hProcess
, 0);
2923 GetExitCodeProcess(pi
.hProcess
, &ret
);
2924 ok(ret
== 195, "expected exit code 195, got %u\n", ret
);
2925 if (*child_failures
)
2927 trace("%d failures in child process\n", *child_failures
);
2928 winetest_add_failures(*child_failures
);
2930 CloseHandle(pi
.hThread
);
2931 CloseHandle(pi
.hProcess
);
2934 *child_failures
= -1;
2935 sprintf(cmdline
, "\"%s\" loader %s %u 1", argv
[0], dll_name
, target_offset
);
2936 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
2937 ok(ret
, "CreateProcess(%s) error %d\n", cmdline
, GetLastError());
2938 ret
= WaitForSingleObject(pi
.hProcess
, 10000);
2939 ok(ret
== WAIT_OBJECT_0
, "child process failed to terminate\n");
2940 if (ret
!= WAIT_OBJECT_0
) TerminateProcess(pi
.hProcess
, 0);
2941 GetExitCodeProcess(pi
.hProcess
, &ret
);
2942 ok(ret
== 195, "expected exit code 195, got %u\n", ret
);
2943 if (*child_failures
)
2945 trace("%d failures in child process\n", *child_failures
);
2946 winetest_add_failures(*child_failures
);
2948 CloseHandle(pi
.hThread
);
2949 CloseHandle(pi
.hProcess
);
2952 *child_failures
= -1;
2953 sprintf(cmdline
, "\"%s\" loader %s %u 2", argv
[0], dll_name
, target_offset
);
2954 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
2955 ok(ret
, "CreateProcess(%s) error %d\n", cmdline
, GetLastError());
2956 ret
= WaitForSingleObject(pi
.hProcess
, 10000);
2957 ok(ret
== WAIT_OBJECT_0
, "child process failed to terminate\n");
2958 if (ret
!= WAIT_OBJECT_0
) TerminateProcess(pi
.hProcess
, 0);
2959 GetExitCodeProcess(pi
.hProcess
, &ret
);
2960 ok(ret
== 197, "expected exit code 197, got %u\n", ret
);
2961 if (*child_failures
)
2963 trace("%d failures in child process\n", *child_failures
);
2964 winetest_add_failures(*child_failures
);
2966 CloseHandle(pi
.hThread
);
2967 CloseHandle(pi
.hProcess
);
2970 *child_failures
= -1;
2971 sprintf(cmdline
, "\"%s\" loader %s %u 3", argv
[0], dll_name
, target_offset
);
2972 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
2973 ok(ret
, "CreateProcess(%s) error %d\n", cmdline
, GetLastError());
2974 ret
= WaitForSingleObject(pi
.hProcess
, 10000);
2975 ok(ret
== WAIT_OBJECT_0
, "child process failed to terminate\n");
2976 if (ret
!= WAIT_OBJECT_0
) TerminateProcess(pi
.hProcess
, 0);
2977 GetExitCodeProcess(pi
.hProcess
, &ret
);
2978 ok(ret
== 195, "expected exit code 195, got %u\n", ret
);
2979 if (*child_failures
)
2981 trace("%d failures in child process\n", *child_failures
);
2982 winetest_add_failures(*child_failures
);
2984 CloseHandle(pi
.hThread
);
2985 CloseHandle(pi
.hProcess
);
2988 if (pLdrLockLoaderLock
&& pLdrUnlockLoaderLock
)
2990 *child_failures
= -1;
2991 sprintf(cmdline
, "\"%s\" loader %s %u 4", argv
[0], dll_name
, target_offset
);
2992 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
2993 ok(ret
, "CreateProcess(%s) error %d\n", cmdline
, GetLastError());
2994 ret
= WaitForSingleObject(pi
.hProcess
, 10000);
2995 ok(ret
== WAIT_OBJECT_0
, "child process failed to terminate\n");
2996 if (ret
!= WAIT_OBJECT_0
) TerminateProcess(pi
.hProcess
, 0);
2997 GetExitCodeProcess(pi
.hProcess
, &ret
);
2998 ok(ret
== 198, "expected exit code 198, got %u\n", ret
);
2999 if (*child_failures
)
3001 trace("%d failures in child process\n", *child_failures
);
3002 winetest_add_failures(*child_failures
);
3004 CloseHandle(pi
.hThread
);
3005 CloseHandle(pi
.hProcess
);
3008 win_skip("LdrLockLoaderLock/LdrUnlockLoaderLock are not available on this platform\n");
3011 if (pRtlAcquirePebLock
&& pRtlReleasePebLock
)
3013 *child_failures
= -1;
3014 sprintf(cmdline
, "\"%s\" loader %s %u 5", argv
[0], dll_name
, target_offset
);
3015 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
3016 ok(ret
, "CreateProcess(%s) error %d\n", cmdline
, GetLastError());
3017 ret
= WaitForSingleObject(pi
.hProcess
, 5000);
3018 ok(ret
== WAIT_TIMEOUT
, "child process should fail to terminate\n");
3019 if (ret
!= WAIT_OBJECT_0
)
3021 trace("terminating child process\n");
3022 TerminateProcess(pi
.hProcess
, 199);
3024 ret
= WaitForSingleObject(pi
.hProcess
, 1000);
3025 ok(ret
== WAIT_OBJECT_0
, "child process failed to terminate\n");
3026 GetExitCodeProcess(pi
.hProcess
, &ret
);
3027 ok(ret
== 199, "expected exit code 199, got %u\n", ret
);
3028 if (*child_failures
)
3030 trace("%d failures in child process\n", *child_failures
);
3031 winetest_add_failures(*child_failures
);
3033 CloseHandle(pi
.hThread
);
3034 CloseHandle(pi
.hProcess
);
3037 win_skip("RtlAcquirePebLock/RtlReleasePebLock are not available on this platform\n");
3040 *child_failures
= -1;
3041 sprintf(cmdline
, "\"%s\" loader %s %u 6", argv
[0], dll_name
, target_offset
);
3042 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
3043 ok(ret
, "CreateProcess(%s) error %d\n", cmdline
, GetLastError());
3044 ret
= WaitForSingleObject(pi
.hProcess
, 5000);
3046 ok(ret
== WAIT_TIMEOUT
|| broken(ret
== WAIT_OBJECT_0
) /* XP */, "child process should fail to terminate\n");
3047 if (ret
!= WAIT_OBJECT_0
)
3049 trace("terminating child process\n");
3050 TerminateProcess(pi
.hProcess
, 201);
3052 ret
= WaitForSingleObject(pi
.hProcess
, 1000);
3053 ok(ret
== WAIT_OBJECT_0
, "child process failed to terminate\n");
3054 GetExitCodeProcess(pi
.hProcess
, &ret
);
3056 ok(ret
== 201 || broken(ret
== 1) /* XP */, "expected exit code 201, got %u\n", ret
);
3057 if (*child_failures
)
3059 trace("%d failures in child process\n", *child_failures
);
3060 winetest_add_failures(*child_failures
);
3062 CloseHandle(pi
.hThread
);
3063 CloseHandle(pi
.hProcess
);
3066 *child_failures
= -1;
3067 sprintf(cmdline
, "\"%s\" loader %s %u 7", argv
[0], dll_name
, target_offset
);
3068 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
3069 ok(ret
, "CreateProcess(%s) error %d\n", cmdline
, GetLastError());
3070 ret
= WaitForSingleObject(pi
.hProcess
, 5000);
3071 ok(ret
== WAIT_OBJECT_0
, "child process failed to terminate\n");
3072 if (ret
!= WAIT_OBJECT_0
)
3074 trace("terminating child process\n");
3075 TerminateProcess(pi
.hProcess
, 199);
3077 ret
= WaitForSingleObject(pi
.hProcess
, 1000);
3078 ok(ret
== WAIT_OBJECT_0
, "child process failed to terminate\n");
3079 GetExitCodeProcess(pi
.hProcess
, &ret
);
3080 ok(ret
== 199, "expected exit code 199, got %u\n", ret
);
3081 if (*child_failures
)
3083 trace("%d failures in child process\n", *child_failures
);
3084 winetest_add_failures(*child_failures
);
3086 CloseHandle(pi
.hThread
);
3087 CloseHandle(pi
.hProcess
);
3089 /* test remote process termination */
3090 SetLastError(0xdeadbeef);
3091 ret
= CreateProcessA(argv
[0], NULL
, NULL
, NULL
, FALSE
, CREATE_SUSPENDED
, NULL
, NULL
, &si
, &pi
);
3092 ok(ret
, "CreateProcess(%s) error %d\n", argv
[0], GetLastError());
3094 SetLastError(0xdeadbeef);
3095 addr
= VirtualAllocEx(pi
.hProcess
, NULL
, 4096, MEM_COMMIT
, PAGE_READWRITE
);
3096 ok(addr
!= NULL
, "VirtualAllocEx error %d\n", GetLastError());
3097 SetLastError(0xdeadbeef);
3098 ret
= VirtualProtectEx(pi
.hProcess
, addr
, 4096, PAGE_READONLY
, &old_prot
);
3099 ok(ret
, "VirtualProtectEx error %d\n", GetLastError());
3100 ok(old_prot
== PAGE_READWRITE
, "expected PAGE_READWRITE, got %#x\n", old_prot
);
3101 SetLastError(0xdeadbeef);
3102 size
= VirtualQueryEx(pi
.hProcess
, NULL
, &mbi
, sizeof(mbi
));
3103 ok(size
== sizeof(mbi
), "VirtualQueryEx error %d\n", GetLastError());
3105 SetLastError(0xdeadbeef);
3106 ret
= ReadProcessMemory(pi
.hProcess
, addr
, buf
, 4, &size
);
3107 ok(ret
, "ReadProcessMemory error %d\n", GetLastError());
3108 ok(size
== 4, "expected 4, got %lu\n", size
);
3110 SetLastError(0xdeadbeef);
3111 hmap
= CreateFileMappingW(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, 4096, NULL
);
3112 ok(hmap
!= 0, "CreateFileMapping error %d\n", GetLastError());
3114 SetLastError(0xdeadbeef);
3115 ret
= DuplicateHandle(GetCurrentProcess(), hmap
, pi
.hProcess
, &hmap_dup
,
3116 0, FALSE
, DUPLICATE_SAME_ACCESS
);
3117 ok(ret
, "DuplicateHandle error %d\n", GetLastError());
3119 offset
.u
.LowPart
= 0;
3120 offset
.u
.HighPart
= 0;
3123 ret
= pNtMapViewOfSection(hmap
, pi
.hProcess
, &addr
, 0, 0, &offset
,
3124 &size
, 1 /* ViewShare */, 0, PAGE_READONLY
);
3125 ok(!ret
, "NtMapViewOfSection error %#x\n", ret
);
3126 ret
= pNtUnmapViewOfSection(pi
.hProcess
, addr
);
3127 ok(!ret
, "NtUnmapViewOfSection error %#x\n", ret
);
3129 SetLastError(0xdeadbeef);
3130 thread
= CreateRemoteThread(pi
.hProcess
, NULL
, 0, (void *)0xdeadbeef, NULL
, CREATE_SUSPENDED
, &ret
);
3131 ok(thread
!= 0, "CreateRemoteThread error %d\n", GetLastError());
3132 SetLastError(0xdeadbeef);
3133 ctx
.ContextFlags
= CONTEXT_INTEGER
;
3134 ret
= GetThreadContext(thread
, &ctx
);
3135 ok(ret
, "GetThreadContext error %d\n", GetLastError());
3136 SetLastError(0xdeadbeef);
3137 ctx
.ContextFlags
= CONTEXT_INTEGER
;
3138 ret
= SetThreadContext(thread
, &ctx
);
3139 ok(ret
, "SetThreadContext error %d\n", GetLastError());
3140 SetLastError(0xdeadbeef);
3141 ret
= SetThreadPriority(thread
, 0);
3142 ok(ret
, "SetThreadPriority error %d\n", GetLastError());
3144 SetLastError(0xdeadbeef);
3145 ret
= TerminateThread(thread
, 199);
3146 ok(ret
, "TerminateThread error %d\n", GetLastError());
3147 /* Calling GetExitCodeThread() without waiting for thread termination
3148 * leads to different results due to a race condition.
3150 ret
= WaitForSingleObject(thread
, 1000);
3151 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed: %x\n", ret
);
3152 GetExitCodeThread(thread
, &ret
);
3153 ok(ret
== 199, "expected exit code 199, got %u\n", ret
);
3155 SetLastError(0xdeadbeef);
3156 ret
= TerminateProcess(pi
.hProcess
, 198);
3157 ok(ret
, "TerminateProcess error %d\n", GetLastError());
3158 /* Checking process state without waiting for process termination
3159 * leads to different results due to a race condition.
3161 ret
= WaitForSingleObject(pi
.hProcess
, 1000);
3162 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed: %x\n", ret
);
3164 SetLastError(0xdeadbeef);
3165 process
= OpenProcess(PROCESS_ALL_ACCESS_NT4
, FALSE
, pi
.dwProcessId
);
3166 ok(process
!= NULL
, "OpenProcess error %d\n", GetLastError());
3167 CloseHandle(process
);
3169 memset(&pbi
, 0, sizeof(pbi
));
3170 ret
= pNtQueryInformationProcess(pi
.hProcess
, ProcessBasicInformation
, &pbi
, sizeof(pbi
), NULL
);
3171 ok(!ret
, "NtQueryInformationProcess error %#x\n", ret
);
3172 ok(pbi
.ExitStatus
== 198, "expected 198, got %lu\n", pbi
.ExitStatus
);
3174 ret
= pNtSetInformationProcess(pi
.hProcess
, ProcessAffinityMask
, &affinity
, sizeof(affinity
));
3175 ok(ret
== STATUS_PROCESS_IS_TERMINATING
, "expected STATUS_PROCESS_IS_TERMINATING, got %#x\n", ret
);
3177 SetLastError(0xdeadbeef);
3178 ctx
.ContextFlags
= CONTEXT_INTEGER
;
3179 ret
= GetThreadContext(thread
, &ctx
);
3180 ok(!ret
|| broken(ret
) /* XP 64-bit */, "GetThreadContext should fail\n");
3182 ok(GetLastError() == ERROR_INVALID_PARAMETER
||
3183 GetLastError() == ERROR_GEN_FAILURE
/* win7 64-bit */ ||
3184 GetLastError() == ERROR_INVALID_FUNCTION
/* vista 64-bit */ ||
3185 GetLastError() == ERROR_ACCESS_DENIED
/* Win10 32-bit */,
3186 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3187 SetLastError(0xdeadbeef);
3188 ctx
.ContextFlags
= CONTEXT_INTEGER
;
3189 ret
= SetThreadContext(thread
, &ctx
);
3190 ok(!ret
|| broken(ret
) /* XP 64-bit */, "SetThreadContext should fail\n");
3192 ok(GetLastError() == ERROR_ACCESS_DENIED
||
3193 GetLastError() == ERROR_GEN_FAILURE
/* win7 64-bit */ ||
3194 GetLastError() == ERROR_INVALID_FUNCTION
/* vista 64-bit */,
3195 "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
3196 SetLastError(0xdeadbeef);
3197 ret
= SetThreadPriority(thread
, 0);
3198 ok(ret
, "SetThreadPriority error %d\n", GetLastError());
3199 CloseHandle(thread
);
3201 SetLastError(0xdeadbeef);
3202 ctx
.ContextFlags
= CONTEXT_INTEGER
;
3203 ret
= GetThreadContext(pi
.hThread
, &ctx
);
3204 ok(!ret
|| broken(ret
) /* XP 64-bit */, "GetThreadContext should fail\n");
3206 ok(GetLastError() == ERROR_INVALID_PARAMETER
||
3207 GetLastError() == ERROR_GEN_FAILURE
/* win7 64-bit */ ||
3208 GetLastError() == ERROR_INVALID_FUNCTION
/* vista 64-bit */ ||
3209 GetLastError() == ERROR_ACCESS_DENIED
/* Win10 32-bit */,
3210 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3211 SetLastError(0xdeadbeef);
3212 ctx
.ContextFlags
= CONTEXT_INTEGER
;
3213 ret
= SetThreadContext(pi
.hThread
, &ctx
);
3214 ok(!ret
|| broken(ret
) /* XP 64-bit */, "SetThreadContext should fail\n");
3216 ok(GetLastError() == ERROR_ACCESS_DENIED
||
3217 GetLastError() == ERROR_GEN_FAILURE
/* win7 64-bit */ ||
3218 GetLastError() == ERROR_INVALID_FUNCTION
/* vista 64-bit */,
3219 "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
3220 SetLastError(0xdeadbeef);
3221 ret
= VirtualProtectEx(pi
.hProcess
, addr
, 4096, PAGE_READWRITE
, &old_prot
);
3222 ok(!ret
, "VirtualProtectEx should fail\n");
3223 ok(GetLastError() == ERROR_ACCESS_DENIED
, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
3224 SetLastError(0xdeadbeef);
3226 ret
= ReadProcessMemory(pi
.hProcess
, addr
, buf
, 4, &size
);
3227 ok(!ret
, "ReadProcessMemory should fail\n");
3228 ok(GetLastError() == ERROR_PARTIAL_COPY
|| GetLastError() == ERROR_ACCESS_DENIED
,
3229 "expected ERROR_PARTIAL_COPY, got %d\n", GetLastError());
3230 ok(!size
, "expected 0, got %lu\n", size
);
3231 SetLastError(0xdeadbeef);
3232 ret
= VirtualFreeEx(pi
.hProcess
, addr
, 0, MEM_RELEASE
);
3233 ok(!ret
, "VirtualFreeEx should fail\n");
3234 ok(GetLastError() == ERROR_ACCESS_DENIED
, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
3235 SetLastError(0xdeadbeef);
3236 addr
= VirtualAllocEx(pi
.hProcess
, NULL
, 4096, MEM_COMMIT
, PAGE_READWRITE
);
3237 ok(!addr
, "VirtualAllocEx should fail\n");
3238 ok(GetLastError() == ERROR_ACCESS_DENIED
, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
3239 SetLastError(0xdeadbeef);
3240 size
= VirtualQueryEx(pi
.hProcess
, NULL
, &mbi
, sizeof(mbi
));
3241 ok(!size
, "VirtualQueryEx should fail\n");
3242 ok(GetLastError() == ERROR_ACCESS_DENIED
, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
3244 /* CloseHandle() call below leads to premature process termination
3245 * under some Windows versions.
3249 SetLastError(0xdeadbeef);
3250 ret
= CloseHandle(hmap_dup
);
3251 ok(ret
, "CloseHandle should not fail\n");
3254 SetLastError(0xdeadbeef);
3255 ret
= DuplicateHandle(GetCurrentProcess(), hmap
, pi
.hProcess
, &hmap_dup
,
3256 0, FALSE
, DUPLICATE_SAME_ACCESS
);
3257 ok(!ret
, "DuplicateHandle should fail\n");
3258 ok(GetLastError() == ERROR_ACCESS_DENIED
, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
3260 offset
.u
.LowPart
= 0;
3261 offset
.u
.HighPart
= 0;
3264 ret
= pNtMapViewOfSection(hmap
, pi
.hProcess
, &addr
, 0, 0, &offset
,
3265 &size
, 1 /* ViewShare */, 0, PAGE_READONLY
);
3266 ok(ret
== STATUS_PROCESS_IS_TERMINATING
, "expected STATUS_PROCESS_IS_TERMINATING, got %#x\n", ret
);
3268 SetLastError(0xdeadbeef);
3269 thread
= CreateRemoteThread(pi
.hProcess
, NULL
, 0, (void *)0xdeadbeef, NULL
, CREATE_SUSPENDED
, &ret
);
3270 ok(!thread
, "CreateRemoteThread should fail\n");
3271 ok(GetLastError() == ERROR_ACCESS_DENIED
, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
3273 SetLastError(0xdeadbeef);
3274 ret
= DebugActiveProcess(pi
.dwProcessId
);
3275 ok(!ret
, "DebugActiveProcess should fail\n");
3276 ok(GetLastError() == ERROR_ACCESS_DENIED
/* 64-bit */ || GetLastError() == ERROR_NOT_SUPPORTED
/* 32-bit */,
3277 "ERROR_ACCESS_DENIED, got %d\n", GetLastError());
3279 GetExitCodeProcess(pi
.hProcess
, &ret
);
3280 ok(ret
== 198 || broken(ret
!= 198) /* some 32-bit XP version in a VM returns random exit code */,
3281 "expected exit code 198, got %u\n", ret
);
3282 CloseHandle(pi
.hThread
);
3283 CloseHandle(pi
.hProcess
);
3285 ret
= DeleteFileA(dll_name
);
3286 ok(ret
, "DeleteFile error %d\n", GetLastError());
3289 static PVOID WINAPI
failuredllhook(ULONG ul
, DELAYLOAD_INFO
* pd
)
3291 ok(ul
== 4, "expected 4, got %u\n", ul
);
3292 ok(!!pd
, "no delayload info supplied\n");
3295 ok(pd
->Size
== sizeof(*pd
), "got %u\n", pd
->Size
);
3296 ok(!!pd
->DelayloadDescriptor
, "no DelayloadDescriptor supplied\n");
3297 if (pd
->DelayloadDescriptor
)
3299 ok(pd
->DelayloadDescriptor
->Attributes
.AllAttributes
== 1,
3300 "expected 1, got %u\n", pd
->DelayloadDescriptor
->Attributes
.AllAttributes
);
3301 ok(pd
->DelayloadDescriptor
->DllNameRVA
== 0x2000,
3302 "expected 0x2000, got %x\n", pd
->DelayloadDescriptor
->DllNameRVA
);
3303 ok(pd
->DelayloadDescriptor
->ModuleHandleRVA
== 0x201a,
3304 "expected 0x201a, got %x\n", pd
->DelayloadDescriptor
->ModuleHandleRVA
);
3305 ok(pd
->DelayloadDescriptor
->ImportAddressTableRVA
> pd
->DelayloadDescriptor
->ModuleHandleRVA
,
3306 "expected %x > %x\n", pd
->DelayloadDescriptor
->ImportAddressTableRVA
,
3307 pd
->DelayloadDescriptor
->ModuleHandleRVA
);
3308 ok(pd
->DelayloadDescriptor
->ImportNameTableRVA
> pd
->DelayloadDescriptor
->ImportAddressTableRVA
,
3309 "expected %x > %x\n", pd
->DelayloadDescriptor
->ImportNameTableRVA
,
3310 pd
->DelayloadDescriptor
->ImportAddressTableRVA
);
3311 ok(pd
->DelayloadDescriptor
->BoundImportAddressTableRVA
== 0,
3312 "expected 0, got %x\n", pd
->DelayloadDescriptor
->BoundImportAddressTableRVA
);
3313 ok(pd
->DelayloadDescriptor
->UnloadInformationTableRVA
== 0,
3314 "expected 0, got %x\n", pd
->DelayloadDescriptor
->UnloadInformationTableRVA
);
3315 ok(pd
->DelayloadDescriptor
->TimeDateStamp
== 0,
3316 "expected 0, got %x\n", pd
->DelayloadDescriptor
->TimeDateStamp
);
3319 ok(!!pd
->ThunkAddress
, "no ThunkAddress supplied\n");
3320 if (pd
->ThunkAddress
)
3321 ok(pd
->ThunkAddress
->u1
.Ordinal
, "no ThunkAddress value supplied\n");
3323 ok(!!pd
->TargetDllName
, "no TargetDllName supplied\n");
3324 if (pd
->TargetDllName
)
3325 ok(!strcmp(pd
->TargetDllName
, "secur32.dll"),
3326 "expected \"secur32.dll\", got \"%s\"\n", pd
->TargetDllName
);
3328 ok(pd
->TargetApiDescriptor
.ImportDescribedByName
== 0,
3329 "expected 0, got %x\n", pd
->TargetApiDescriptor
.ImportDescribedByName
);
3330 ok(pd
->TargetApiDescriptor
.Description
.Ordinal
== 0 ||
3331 pd
->TargetApiDescriptor
.Description
.Ordinal
== 999,
3332 "expected 0, got %x\n", pd
->TargetApiDescriptor
.Description
.Ordinal
);
3334 ok(!!pd
->TargetModuleBase
, "no TargetModuleBase supplied\n");
3335 ok(pd
->Unused
== NULL
, "expected NULL, got %p\n", pd
->Unused
);
3336 ok(pd
->LastError
, "no LastError supplied\n");
3339 return (void*)0xdeadbeef;
3342 static void test_ResolveDelayLoadedAPI(void)
3344 static const char test_dll
[] = "secur32.dll";
3345 static const char test_func
[] = "SealMessage";
3346 char temp_path
[MAX_PATH
];
3347 char dll_name
[MAX_PATH
];
3348 IMAGE_DELAYLOAD_DESCRIPTOR idd
, *delaydir
;
3349 IMAGE_THUNK_DATA itd32
;
3352 DWORD dummy
, file_size
, i
;
3355 IMAGE_NT_HEADERS nt_header
;
3357 static const struct test_data
3368 FALSE
, IMAGE_ORDINAL_FLAG
| 2, TRUE
3371 FALSE
, IMAGE_ORDINAL_FLAG
| 5, TRUE
3374 FALSE
, IMAGE_ORDINAL_FLAG
| 0, FALSE
3377 FALSE
, IMAGE_ORDINAL_FLAG
| 999, FALSE
3381 if (!pResolveDelayLoadedAPI
)
3383 win_skip("ResolveDelayLoadedAPI is not available\n");
3387 if (0) /* crashes on native */
3389 SetLastError(0xdeadbeef);
3390 ok(!pResolveDelayLoadedAPI(NULL
, NULL
, NULL
, NULL
, NULL
, 0),
3391 "ResolveDelayLoadedAPI succeeded\n");
3392 ok(GetLastError() == 0xdeadbeef, "GetLastError changed to %x\n", GetLastError());
3395 SetLastError(0xdeadbeef);
3396 ok(!pResolveDelayLoadedAPI(NULL
, NULL
, failuredllhook
, NULL
, NULL
, 0),
3397 "ResolveDelayLoadedAPI succeeded\n");
3398 ok(GetLastError() == 0xdeadbeef, "GetLastError changed to %x\n", GetLastError());
3399 ok(cb_count
== 1, "Wrong callback count: %d\n", cb_count
);
3402 GetTempPathA(MAX_PATH
, temp_path
);
3403 GetTempFileNameA(temp_path
, "ldr", 0, dll_name
);
3404 trace("creating %s\n", dll_name
);
3405 hfile
= CreateFileA(dll_name
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
3406 if (hfile
== INVALID_HANDLE_VALUE
)
3408 ok(0, "could not create %s\n", dll_name
);
3412 SetLastError(0xdeadbeef);
3413 ret
= WriteFile(hfile
, &dos_header
, sizeof(dos_header
), &dummy
, NULL
);
3414 ok(ret
, "WriteFile error %d\n", GetLastError());
3416 nt_header
= nt_header_template
;
3417 nt_header
.FileHeader
.NumberOfSections
= 2;
3418 nt_header
.FileHeader
.SizeOfOptionalHeader
= sizeof(IMAGE_OPTIONAL_HEADER
);
3420 nt_header
.OptionalHeader
.SectionAlignment
= 0x1000;
3421 nt_header
.OptionalHeader
.FileAlignment
= 0x1000;
3422 nt_header
.OptionalHeader
.SizeOfImage
= sizeof(dos_header
) + sizeof(nt_header
) + sizeof(IMAGE_SECTION_HEADER
) + 0x2200;
3423 nt_header
.OptionalHeader
.SizeOfHeaders
= sizeof(dos_header
) + sizeof(nt_header
) + 2 * sizeof(IMAGE_SECTION_HEADER
);
3424 nt_header
.OptionalHeader
.NumberOfRvaAndSizes
= IMAGE_NUMBEROF_DIRECTORY_ENTRIES
;
3425 nt_header
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
].VirtualAddress
= 0x1000;
3426 nt_header
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
].Size
= 0x100;
3428 SetLastError(0xdeadbeef);
3429 ret
= WriteFile(hfile
, &nt_header
, sizeof(DWORD
) + sizeof(IMAGE_FILE_HEADER
), &dummy
, NULL
);
3430 ok(ret
, "WriteFile error %d\n", GetLastError());
3432 SetLastError(0xdeadbeef);
3433 ret
= WriteFile(hfile
, &nt_header
.OptionalHeader
, sizeof(IMAGE_OPTIONAL_HEADER
), &dummy
, NULL
);
3434 ok(ret
, "WriteFile error %d\n", GetLastError());
3437 section
.PointerToRawData
= nt_header
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
].VirtualAddress
;
3438 section
.VirtualAddress
= nt_header
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
].VirtualAddress
;
3439 section
.Misc
.VirtualSize
= 2 * sizeof(idd
);
3440 section
.SizeOfRawData
= section
.Misc
.VirtualSize
;
3441 section
.Characteristics
= IMAGE_SCN_CNT_INITIALIZED_DATA
| IMAGE_SCN_MEM_READ
;
3442 SetLastError(0xdeadbeef);
3443 ret
= WriteFile(hfile
, §ion
, sizeof(section
), &dummy
, NULL
);
3444 ok(ret
, "WriteFile error %d\n", GetLastError());
3446 section
.PointerToRawData
= 0x2000;
3447 section
.VirtualAddress
= 0x2000;
3449 section
.Misc
.VirtualSize
= sizeof(test_dll
) + sizeof(hint
) + sizeof(test_func
) + sizeof(HMODULE
) +
3450 2 * (i
+ 1) * sizeof(IMAGE_THUNK_DATA
);
3451 ok(section
.Misc
.VirtualSize
<= 0x1000, "Too much tests, add a new section!\n");
3452 section
.SizeOfRawData
= section
.Misc
.VirtualSize
;
3453 section
.Characteristics
= IMAGE_SCN_CNT_INITIALIZED_DATA
| IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_WRITE
;
3454 SetLastError(0xdeadbeef);
3455 ret
= WriteFile(hfile
, §ion
, sizeof(section
), &dummy
, NULL
);
3456 ok(ret
, "WriteFile error %d\n", GetLastError());
3458 /* fill up to delay data */
3459 SetFilePointer( hfile
, nt_header
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
].VirtualAddress
, NULL
, SEEK_SET
);
3462 idd
.Attributes
.AllAttributes
= 1;
3463 idd
.DllNameRVA
= 0x2000;
3464 idd
.ModuleHandleRVA
= idd
.DllNameRVA
+ sizeof(test_dll
) + sizeof(hint
) + sizeof(test_func
);
3465 idd
.ImportAddressTableRVA
= idd
.ModuleHandleRVA
+ sizeof(HMODULE
);
3466 idd
.ImportNameTableRVA
= idd
.ImportAddressTableRVA
+ (i
+ 1) * sizeof(IMAGE_THUNK_DATA
);
3467 idd
.BoundImportAddressTableRVA
= 0;
3468 idd
.UnloadInformationTableRVA
= 0;
3469 idd
.TimeDateStamp
= 0;
3471 SetLastError(0xdeadbeef);
3472 ret
= WriteFile(hfile
, &idd
, sizeof(idd
), &dummy
, NULL
);
3473 ok(ret
, "WriteFile error %d\n", GetLastError());
3475 SetLastError(0xdeadbeef);
3476 ret
= WriteFile(hfile
, filler
, sizeof(idd
), &dummy
, NULL
);
3477 ok(ret
, "WriteFile error %d\n", GetLastError());
3479 /* fill up to extended delay data */
3480 SetFilePointer( hfile
, idd
.DllNameRVA
, NULL
, SEEK_SET
);
3482 /* extended delay data */
3483 SetLastError(0xdeadbeef);
3484 ret
= WriteFile(hfile
, test_dll
, sizeof(test_dll
), &dummy
, NULL
);
3485 ok(ret
, "WriteFile error %d\n", GetLastError());
3487 SetLastError(0xdeadbeef);
3488 ret
= WriteFile(hfile
, &hint
, sizeof(hint
), &dummy
, NULL
);
3489 ok(ret
, "WriteFile error %d\n", GetLastError());
3491 SetLastError(0xdeadbeef);
3492 ret
= WriteFile(hfile
, test_func
, sizeof(test_func
), &dummy
, NULL
);
3493 ok(ret
, "WriteFile error %d\n", GetLastError());
3495 SetFilePointer( hfile
, idd
.ImportAddressTableRVA
, NULL
, SEEK_SET
);
3497 for (i
= 0; i
< ARRAY_SIZE(td
); i
++)
3499 /* 0x1a00 is an empty space between delay data and extended delay data, real thunks are not necessary */
3500 itd32
.u1
.Function
= nt_header
.OptionalHeader
.ImageBase
+ 0x1a00 + i
* 0x20;
3501 SetLastError(0xdeadbeef);
3502 ret
= WriteFile(hfile
, &itd32
, sizeof(itd32
), &dummy
, NULL
);
3503 ok(ret
, "WriteFile error %d\n", GetLastError());
3506 itd32
.u1
.Function
= 0;
3507 SetLastError(0xdeadbeef);
3508 ret
= WriteFile(hfile
, &itd32
, sizeof(itd32
), &dummy
, NULL
);
3509 ok(ret
, "WriteFile error %d\n", GetLastError());
3511 for (i
= 0; i
< ARRAY_SIZE(td
); i
++)
3514 itd32
.u1
.AddressOfData
= idd
.DllNameRVA
+ sizeof(test_dll
);
3516 itd32
.u1
.Ordinal
= td
[i
].ordinal
;
3517 SetLastError(0xdeadbeef);
3518 ret
= WriteFile(hfile
, &itd32
, sizeof(itd32
), &dummy
, NULL
);
3519 ok(ret
, "WriteFile error %d\n", GetLastError());
3522 itd32
.u1
.Ordinal
= 0;
3523 SetLastError(0xdeadbeef);
3524 ret
= WriteFile(hfile
, &itd32
, sizeof(itd32
), &dummy
, NULL
);
3525 ok(ret
, "WriteFile error %d\n", GetLastError());
3527 /* fill up to eof */
3528 SetFilePointer( hfile
, section
.VirtualAddress
+ section
.Misc
.VirtualSize
, NULL
, SEEK_SET
);
3529 SetEndOfFile( hfile
);
3532 SetLastError(0xdeadbeef);
3533 hlib
= LoadLibraryA(dll_name
);
3534 ok(hlib
!= NULL
, "LoadLibrary error %u\n", GetLastError());
3537 skip("couldn't load %s.\n", dll_name
);
3538 DeleteFileA(dll_name
);
3542 delaydir
= pRtlImageDirectoryEntryToData(hlib
, TRUE
, IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
, &file_size
);
3545 skip("haven't found section for delay import directory.\n");
3547 DeleteFileA(dll_name
);
3553 IMAGE_THUNK_DATA
*itdn
, *itda
;
3556 if (!delaydir
->DllNameRVA
||
3557 !delaydir
->ImportAddressTableRVA
||
3558 !delaydir
->ImportNameTableRVA
) break;
3560 itdn
= RVAToAddr(delaydir
->ImportNameTableRVA
, hlib
);
3561 itda
= RVAToAddr(delaydir
->ImportAddressTableRVA
, hlib
);
3562 htarget
= LoadLibraryA(RVAToAddr(delaydir
->DllNameRVA
, hlib
));
3564 for (i
= 0; i
< ARRAY_SIZE(td
); i
++)
3568 if (IMAGE_SNAP_BY_ORDINAL(itdn
[i
].u1
.Ordinal
))
3569 load
= (void *)GetProcAddress(htarget
, (LPSTR
)IMAGE_ORDINAL(itdn
[i
].u1
.Ordinal
));
3572 const IMAGE_IMPORT_BY_NAME
* iibn
= RVAToAddr(itdn
[i
].u1
.AddressOfData
, hlib
);
3573 load
= (void *)GetProcAddress(htarget
, (char*)iibn
->Name
);
3577 ret
= pResolveDelayLoadedAPI(hlib
, delaydir
, failuredllhook
, NULL
, &itda
[i
], 0);
3580 ok(ret
!= NULL
, "Test %u: ResolveDelayLoadedAPI failed\n", i
);
3581 ok(ret
== load
, "Test %u: expected %p, got %p\n", i
, load
, ret
);
3582 ok(ret
== (void*)itda
[i
].u1
.AddressOfData
, "Test %u: expected %p, got %p\n",
3583 i
, ret
, (void*)itda
[i
].u1
.AddressOfData
);
3584 ok(!cb_count
, "Test %u: Wrong callback count: %d\n", i
, cb_count
);
3588 ok(ret
== (void*)0xdeadbeef, "Test %u: ResolveDelayLoadedAPI succeeded with %p\n", i
, ret
);
3589 ok(cb_count
, "Test %u: Wrong callback count: %d\n", i
, cb_count
);
3596 trace("deleting %s\n", dll_name
);
3597 DeleteFileA(dll_name
);
3600 static void test_InMemoryOrderModuleList(void)
3602 PEB_LDR_DATA
*ldr
= NtCurrentTeb()->Peb
->LdrData
;
3603 LIST_ENTRY
*entry1
, *mark1
= &ldr
->InLoadOrderModuleList
;
3604 LIST_ENTRY
*entry2
, *mark2
= &ldr
->InMemoryOrderModuleList
;
3605 LDR_MODULE
*module1
, *module2
;
3607 ok(ldr
->Initialized
== TRUE
, "expected TRUE, got %u\n", ldr
->Initialized
);
3609 for (entry1
= mark1
->Flink
, entry2
= mark2
->Flink
;
3610 entry1
!= mark1
&& entry2
!= mark2
;
3611 entry1
= entry1
->Flink
, entry2
= entry2
->Flink
)
3613 module1
= CONTAINING_RECORD(entry1
, LDR_MODULE
, InLoadOrderModuleList
);
3614 module2
= CONTAINING_RECORD(entry2
, LDR_MODULE
, InMemoryOrderModuleList
);
3615 ok(module1
== module2
, "expected module1 == module2, got %p and %p\n", module1
, module2
);
3617 ok(entry1
== mark1
, "expected entry1 == mark1, got %p and %p\n", entry1
, mark1
);
3618 ok(entry2
== mark2
, "expected entry2 == mark2, got %p and %p\n", entry2
, mark2
);
3625 HANDLE ntdll
, mapping
, kernel32
;
3628 ntdll
= GetModuleHandleA("ntdll.dll");
3629 kernel32
= GetModuleHandleA("kernel32.dll");
3630 pNtCreateSection
= (void *)GetProcAddress(ntdll
, "NtCreateSection");
3631 pNtQuerySection
= (void *)GetProcAddress(ntdll
, "NtQuerySection");
3632 pNtMapViewOfSection
= (void *)GetProcAddress(ntdll
, "NtMapViewOfSection");
3633 pNtUnmapViewOfSection
= (void *)GetProcAddress(ntdll
, "NtUnmapViewOfSection");
3634 pNtTerminateProcess
= (void *)GetProcAddress(ntdll
, "NtTerminateProcess");
3635 pNtQueryInformationProcess
= (void *)GetProcAddress(ntdll
, "NtQueryInformationProcess");
3636 pNtSetInformationProcess
= (void *)GetProcAddress(ntdll
, "NtSetInformationProcess");
3637 pLdrShutdownProcess
= (void *)GetProcAddress(ntdll
, "LdrShutdownProcess");
3638 pRtlDllShutdownInProgress
= (void *)GetProcAddress(ntdll
, "RtlDllShutdownInProgress");
3639 pNtAllocateVirtualMemory
= (void *)GetProcAddress(ntdll
, "NtAllocateVirtualMemory");
3640 pNtFreeVirtualMemory
= (void *)GetProcAddress(ntdll
, "NtFreeVirtualMemory");
3641 pLdrLockLoaderLock
= (void *)GetProcAddress(ntdll
, "LdrLockLoaderLock");
3642 pLdrUnlockLoaderLock
= (void *)GetProcAddress(ntdll
, "LdrUnlockLoaderLock");
3643 pRtlAcquirePebLock
= (void *)GetProcAddress(ntdll
, "RtlAcquirePebLock");
3644 pRtlReleasePebLock
= (void *)GetProcAddress(ntdll
, "RtlReleasePebLock");
3645 pRtlImageDirectoryEntryToData
= (void *)GetProcAddress(ntdll
, "RtlImageDirectoryEntryToData");
3646 pFlsAlloc
= (void *)GetProcAddress(kernel32
, "FlsAlloc");
3647 pFlsSetValue
= (void *)GetProcAddress(kernel32
, "FlsSetValue");
3648 pFlsGetValue
= (void *)GetProcAddress(kernel32
, "FlsGetValue");
3649 pFlsFree
= (void *)GetProcAddress(kernel32
, "FlsFree");
3650 pIsWow64Process
= (void *)GetProcAddress(kernel32
, "IsWow64Process");
3651 pResolveDelayLoadedAPI
= (void *)GetProcAddress(kernel32
, "ResolveDelayLoadedAPI");
3653 if (pIsWow64Process
) pIsWow64Process( GetCurrentProcess(), &is_wow64
);
3654 GetSystemInfo( &si
);
3655 page_size
= si
.dwPageSize
;
3656 dos_header
.e_magic
= IMAGE_DOS_SIGNATURE
;
3657 dos_header
.e_lfanew
= sizeof(dos_header
);
3659 mapping
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
, 0, 4096, "winetest_loader");
3660 ok(mapping
!= 0, "CreateFileMapping failed\n");
3661 child_failures
= MapViewOfFile(mapping
, FILE_MAP_READ
|FILE_MAP_WRITE
, 0, 0, 4096);
3662 if (*child_failures
== -1)
3664 *child_failures
= 0;
3667 *child_failures
= -1;
3669 argc
= winetest_get_mainargs(&argv
);
3672 test_dll_phase
= atoi(argv
[4]);
3673 child_process(argv
[2], atol(argv
[3]));
3679 test_ResolveDelayLoadedAPI();
3680 test_ImportDescriptors();
3681 test_section_access();
3682 test_import_resolution();
3684 test_InMemoryOrderModuleList();