Reactos
at master 4909 lines 220 kB view raw
1/* 2 * Unit test suite for the PE loader. 3 * 4 * Copyright 2006,2011 Dmitry Timoshkov 5 * 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. 10 * 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. 15 * 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 19 */ 20 21#include <stdarg.h> 22#include <stdio.h> 23#include <assert.h> 24 25#include "ntstatus.h" 26#define WIN32_NO_STATUS 27#include "windef.h" 28#include "winbase.h" 29#include "winternl.h" 30#include "winnls.h" 31#include "wine/test.h" 32#include "delayloadhandler.h" 33#ifdef __REACTOS__ 34#include "winehacks.h" 35#endif 36 37/* PROCESS_ALL_ACCESS in Vista+ PSDKs is incompatible with older Windows versions */ 38#define PROCESS_ALL_ACCESS_NT4 (PROCESS_ALL_ACCESS & ~0xf000) 39 40#define ALIGN_SIZE(size, alignment) (((size) + ((ULONG_PTR)(alignment) - 1)) & ~(((ULONG_PTR)(alignment) - 1))) 41 42struct PROCESS_BASIC_INFORMATION_PRIVATE 43{ 44 NTSTATUS ExitStatus; 45 PPEB PebBaseAddress; 46 DWORD_PTR AffinityMask; 47 DWORD_PTR BasePriority; 48 ULONG_PTR UniqueProcessId; 49 ULONG_PTR InheritedFromUniqueProcessId; 50}; 51 52static LONG *child_failures; 53static WORD cb_count, cb_count_sys; 54static DWORD page_size; 55static BOOL is_win64 = sizeof(void *) > sizeof(int); 56static BOOL is_wow64; 57static char system_dir[MAX_PATH]; 58static char syswow_dir[MAX_PATH]; /* only available if is_wow64 */ 59 60static NTSTATUS (WINAPI *pNtCreateSection)(HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, 61 const LARGE_INTEGER *, ULONG, ULONG, HANDLE ); 62static NTSTATUS (WINAPI *pNtQuerySection)(HANDLE, SECTION_INFORMATION_CLASS, void *, SIZE_T, SIZE_T *); 63static NTSTATUS (WINAPI *pNtMapViewOfSection)(HANDLE, HANDLE, PVOID *, ULONG_PTR, SIZE_T, const LARGE_INTEGER *, SIZE_T *, ULONG, ULONG, ULONG); 64static NTSTATUS (WINAPI *pNtUnmapViewOfSection)(HANDLE, PVOID); 65static NTSTATUS (WINAPI *pNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG); 66static NTSTATUS (WINAPI *pNtSetInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG); 67static NTSTATUS (WINAPI *pNtTerminateProcess)(HANDLE, DWORD); 68static void (WINAPI *pLdrShutdownProcess)(void); 69static BOOLEAN (WINAPI *pRtlDllShutdownInProgress)(void); 70static NTSTATUS (WINAPI *pNtAllocateVirtualMemory)(HANDLE, PVOID *, ULONG_PTR, SIZE_T *, ULONG, ULONG); 71static NTSTATUS (WINAPI *pNtFreeVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG); 72static NTSTATUS (WINAPI *pLdrLockLoaderLock)(ULONG, ULONG *, ULONG_PTR *); 73static NTSTATUS (WINAPI *pLdrUnlockLoaderLock)(ULONG, ULONG_PTR); 74static NTSTATUS (WINAPI *pLdrLoadDll)(LPCWSTR,DWORD,const UNICODE_STRING *,HMODULE*); 75static NTSTATUS (WINAPI *pLdrUnloadDll)(HMODULE); 76static void (WINAPI *pRtlInitUnicodeString)(PUNICODE_STRING,LPCWSTR); 77static void (WINAPI *pRtlAcquirePebLock)(void); 78static void (WINAPI *pRtlReleasePebLock)(void); 79static PVOID (WINAPI *pResolveDelayLoadedAPI)(PVOID, PCIMAGE_DELAYLOAD_DESCRIPTOR, 80 PDELAYLOAD_FAILURE_DLL_CALLBACK, 81 PDELAYLOAD_FAILURE_SYSTEM_ROUTINE, 82 PIMAGE_THUNK_DATA ThunkAddress,ULONG); 83static PVOID (WINAPI *pRtlImageDirectoryEntryToData)(HMODULE,BOOL,WORD,ULONG *); 84static PIMAGE_NT_HEADERS (WINAPI *pRtlImageNtHeader)(HMODULE); 85static DWORD (WINAPI *pFlsAlloc)(PFLS_CALLBACK_FUNCTION); 86static BOOL (WINAPI *pFlsSetValue)(DWORD, PVOID); 87static PVOID (WINAPI *pFlsGetValue)(DWORD); 88static BOOL (WINAPI *pFlsFree)(DWORD); 89static BOOL (WINAPI *pIsWow64Process)(HANDLE,PBOOL); 90static BOOL (WINAPI *pWow64DisableWow64FsRedirection)(void **); 91static BOOL (WINAPI *pWow64RevertWow64FsRedirection)(void *); 92static HMODULE (WINAPI *pLoadPackagedLibrary)(LPCWSTR lpwLibFileName, DWORD Reserved); 93static NTSTATUS (WINAPI *pLdrRegisterDllNotification)(ULONG, PLDR_DLL_NOTIFICATION_FUNCTION, void *, void **); 94 95static PVOID RVAToAddr(DWORD_PTR rva, HMODULE module) 96{ 97 if (rva == 0) 98 return NULL; 99 return ((char*) module) + rva; 100} 101 102static IMAGE_DOS_HEADER dos_header; 103 104static const IMAGE_NT_HEADERS nt_header_template = 105{ 106 IMAGE_NT_SIGNATURE, /* Signature */ 107 { 108#if defined __i386__ 109 IMAGE_FILE_MACHINE_I386, /* Machine */ 110#elif defined __x86_64__ 111 IMAGE_FILE_MACHINE_AMD64, /* Machine */ 112#elif defined __arm__ 113 IMAGE_FILE_MACHINE_ARMNT, /* Machine */ 114#elif defined __aarch64__ 115 IMAGE_FILE_MACHINE_ARM64, /* Machine */ 116#else 117# error You must specify the machine type 118#endif 119 1, /* NumberOfSections */ 120 0, /* TimeDateStamp */ 121 0, /* PointerToSymbolTable */ 122 0, /* NumberOfSymbols */ 123 sizeof(IMAGE_OPTIONAL_HEADER), /* SizeOfOptionalHeader */ 124 IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL /* Characteristics */ 125 }, 126 { IMAGE_NT_OPTIONAL_HDR_MAGIC, /* Magic */ 127 1, /* MajorLinkerVersion */ 128 0, /* MinorLinkerVersion */ 129 0, /* SizeOfCode */ 130 0, /* SizeOfInitializedData */ 131 0, /* SizeOfUninitializedData */ 132 0, /* AddressOfEntryPoint */ 133 0x10, /* BaseOfCode, also serves as e_lfanew in the truncated MZ header */ 134#ifndef _WIN64 135 0, /* BaseOfData */ 136 0x10000000, /* ImageBase */ 137#else 138 0x123450000, /* ImageBase */ 139#endif 140 0, /* SectionAlignment */ 141 0, /* FileAlignment */ 142 4, /* MajorOperatingSystemVersion */ 143 0, /* MinorOperatingSystemVersion */ 144 1, /* MajorImageVersion */ 145 0, /* MinorImageVersion */ 146 4, /* MajorSubsystemVersion */ 147 0, /* MinorSubsystemVersion */ 148 0, /* Win32VersionValue */ 149 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0x1000, /* SizeOfImage */ 150 sizeof(dos_header) + sizeof(nt_header_template), /* SizeOfHeaders */ 151 0, /* CheckSum */ 152 IMAGE_SUBSYSTEM_WINDOWS_CUI, /* Subsystem */ 153 IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE | IMAGE_DLLCHARACTERISTICS_NX_COMPAT, /* DllCharacteristics */ 154 0x100000, /* SizeOfStackReserve */ 155 0x1000, /* SizeOfStackCommit */ 156 0x100000, /* SizeOfHeapReserve */ 157 0x1000, /* SizeOfHeapCommit */ 158 0, /* LoaderFlags */ 159 IMAGE_NUMBEROF_DIRECTORY_ENTRIES, /* NumberOfRvaAndSizes */ 160 { { 0 } } /* DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES] */ 161 } 162}; 163 164static IMAGE_SECTION_HEADER section = 165{ 166 ".rodata", /* Name */ 167 { 0 }, /* Misc */ 168 0, /* VirtualAddress */ 169 0, /* SizeOfRawData */ 170 0, /* PointerToRawData */ 171 0, /* PointerToRelocations */ 172 0, /* PointerToLinenumbers */ 173 0, /* NumberOfRelocations */ 174 0, /* NumberOfLinenumbers */ 175 IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ, /* Characteristics */ 176}; 177 178 179static const char filler[0x1000]; 180static const char section_data[0x10] = "section data"; 181 182/* return an alternate machine of the same 32/64 bitness */ 183static WORD get_alt_machine( WORD orig_machine ) 184{ 185 switch (orig_machine) 186 { 187 case IMAGE_FILE_MACHINE_I386: return IMAGE_FILE_MACHINE_ARMNT; 188 case IMAGE_FILE_MACHINE_AMD64: return IMAGE_FILE_MACHINE_ARM64; 189 case IMAGE_FILE_MACHINE_ARMNT: return IMAGE_FILE_MACHINE_I386; 190 case IMAGE_FILE_MACHINE_ARM64: return IMAGE_FILE_MACHINE_AMD64; 191 } 192 return 0; 193} 194 195/* return the machine of the alternate 32/64 bitness */ 196static WORD get_alt_bitness_machine( WORD orig_machine ) 197{ 198 switch (orig_machine) 199 { 200 case IMAGE_FILE_MACHINE_I386: return IMAGE_FILE_MACHINE_AMD64; 201 case IMAGE_FILE_MACHINE_AMD64: return IMAGE_FILE_MACHINE_I386; 202 case IMAGE_FILE_MACHINE_ARMNT: return IMAGE_FILE_MACHINE_ARM64; 203 case IMAGE_FILE_MACHINE_ARM64: return IMAGE_FILE_MACHINE_ARMNT; 204 } 205 return 0; 206} 207 208static DWORD create_test_dll( const IMAGE_DOS_HEADER *dos_header, UINT dos_size, 209 const IMAGE_NT_HEADERS *nt_header, char dll_name[MAX_PATH] ) 210{ 211 char temp_path[MAX_PATH]; 212 DWORD dummy, size, file_align; 213 HANDLE hfile; 214 BOOL ret; 215 216 GetTempPathA(MAX_PATH, temp_path); 217 GetTempFileNameA(temp_path, "ldr", 0, dll_name); 218 219 hfile = CreateFileA(dll_name, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, 0); 220 ok( hfile != INVALID_HANDLE_VALUE, "failed to create %s err %lu\n", dll_name, GetLastError() ); 221 if (hfile == INVALID_HANDLE_VALUE) return 0; 222 223 SetLastError(0xdeadbeef); 224 ret = WriteFile(hfile, dos_header, dos_size, &dummy, NULL); 225 ok(ret, "WriteFile error %ld\n", GetLastError()); 226 227 SetLastError(0xdeadbeef); 228 ret = WriteFile(hfile, nt_header, sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER), &dummy, NULL); 229 ok(ret, "WriteFile error %ld\n", GetLastError()); 230 231 if (nt_header->FileHeader.SizeOfOptionalHeader) 232 { 233 SetLastError(0xdeadbeef); 234 ret = WriteFile(hfile, &nt_header->OptionalHeader, 235 sizeof(IMAGE_OPTIONAL_HEADER), 236 &dummy, NULL); 237 ok(ret, "WriteFile error %ld\n", GetLastError()); 238 if (nt_header->FileHeader.SizeOfOptionalHeader > sizeof(IMAGE_OPTIONAL_HEADER)) 239 { 240 file_align = nt_header->FileHeader.SizeOfOptionalHeader - sizeof(IMAGE_OPTIONAL_HEADER); 241 assert(file_align < sizeof(filler)); 242 SetLastError(0xdeadbeef); 243 ret = WriteFile(hfile, filler, file_align, &dummy, NULL); 244 ok(ret, "WriteFile error %ld\n", GetLastError()); 245 } 246 } 247 248 assert(nt_header->FileHeader.NumberOfSections <= 1); 249 if (nt_header->FileHeader.NumberOfSections) 250 { 251 SetFilePointer(hfile, dos_size + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + nt_header->FileHeader.SizeOfOptionalHeader, NULL, FILE_BEGIN); 252 253 section.SizeOfRawData = 10; 254 255 if (nt_header->OptionalHeader.SectionAlignment >= page_size) 256 { 257 section.PointerToRawData = dos_size; 258 section.VirtualAddress = nt_header->OptionalHeader.SectionAlignment; 259 section.Misc.VirtualSize = section.SizeOfRawData * 10; 260 } 261 else 262 { 263 section.PointerToRawData = nt_header->OptionalHeader.SizeOfHeaders; 264 section.VirtualAddress = nt_header->OptionalHeader.SizeOfHeaders; 265 section.Misc.VirtualSize = 5; 266 } 267 268 SetLastError(0xdeadbeef); 269 ret = WriteFile(hfile, &section, sizeof(section), &dummy, NULL); 270 ok(ret, "WriteFile error %ld\n", GetLastError()); 271 272 /* section data */ 273 SetLastError(0xdeadbeef); 274 ret = WriteFile(hfile, section_data, sizeof(section_data), &dummy, NULL); 275 ok(ret, "WriteFile error %ld\n", GetLastError()); 276 } 277 278 /* Minimal PE image that Windows7+ is able to load: 268 bytes */ 279 size = GetFileSize(hfile, NULL); 280 if (size < 268) 281 { 282 file_align = 268 - size; 283 SetLastError(0xdeadbeef); 284 ret = WriteFile(hfile, filler, file_align, &dummy, NULL); 285 ok(ret, "WriteFile error %ld\n", GetLastError()); 286 } 287 288 size = GetFileSize(hfile, NULL); 289 CloseHandle(hfile); 290 return size; 291} 292 293static DWORD create_test_dll_sections( const IMAGE_DOS_HEADER *dos_header, const IMAGE_NT_HEADERS *nt_header, 294 const IMAGE_SECTION_HEADER *sections, const void *section_data, 295 char dll_name[MAX_PATH] ) 296{ 297 char temp_path[MAX_PATH]; 298 DWORD dummy, i, size; 299 HANDLE hfile; 300 BOOL ret; 301 302 GetTempPathA(MAX_PATH, temp_path); 303 GetTempFileNameA(temp_path, "ldr", 0, dll_name); 304 305 hfile = CreateFileA(dll_name, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, 0); 306 ok( hfile != INVALID_HANDLE_VALUE, "failed to create %s err %lu\n", dll_name, GetLastError() ); 307 if (hfile == INVALID_HANDLE_VALUE) return 0; 308 309 SetLastError(0xdeadbeef); 310 ret = WriteFile(hfile, dos_header, sizeof(*dos_header), &dummy, NULL); 311 ok(ret, "WriteFile error %ld\n", GetLastError()); 312 313 SetLastError(0xdeadbeef); 314 ret = WriteFile(hfile, nt_header, offsetof(IMAGE_NT_HEADERS, OptionalHeader) + nt_header->FileHeader.SizeOfOptionalHeader, &dummy, NULL); 315 ok(ret, "WriteFile error %ld\n", GetLastError()); 316 317 SetLastError(0xdeadbeef); 318 ret = WriteFile(hfile, sections, sizeof(*sections) * nt_header->FileHeader.NumberOfSections, 319 &dummy, NULL); 320 ok(ret, "WriteFile error %ld\n", GetLastError()); 321 322 for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++) 323 { 324 SetFilePointer(hfile, sections[i].PointerToRawData, NULL, FILE_BEGIN); 325 SetLastError(0xdeadbeef); 326 ret = WriteFile(hfile, section_data, sections[i].SizeOfRawData, &dummy, NULL); 327 ok(ret, "WriteFile error %ld\n", GetLastError()); 328 } 329 size = GetFileSize(hfile, NULL); 330 CloseHandle(hfile); 331 return size; 332} 333 334static BOOL query_image_section( int id, const char *dll_name, const IMAGE_NT_HEADERS *nt_header, 335 const void *section_data ) 336{ 337 SECTION_BASIC_INFORMATION info; 338 SECTION_IMAGE_INFORMATION image; 339 const IMAGE_COR20_HEADER *cor_header = NULL; 340 SIZE_T info_size = (SIZE_T)0xdeadbeef << 16; 341 NTSTATUS status; 342 HANDLE file, mapping; 343 ULONG file_size; 344 LARGE_INTEGER map_size; 345 SIZE_T max_stack, commit_stack; 346 void *entry_point; 347 BOOL truncated; 348 349 file = CreateFileA( dll_name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE, 350 NULL, OPEN_EXISTING, 0, 0 ); 351 ok( file != INVALID_HANDLE_VALUE, "%u: CreateFile error %ld\n", id, GetLastError() ); 352 file_size = GetFileSize( file, NULL ); 353 354 status = pNtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_MAP_READ | SECTION_QUERY, 355 NULL, NULL, PAGE_READONLY, SEC_IMAGE, file ); 356 ok( !status, "%u: NtCreateSection failed err %lx\n", id, status ); 357 if (status) 358 { 359 CloseHandle( file ); 360 return FALSE; 361 } 362 status = pNtQuerySection( mapping, SectionImageInformation, &image, sizeof(image), &info_size ); 363 ok( !status, "%u: NtQuerySection failed err %lx\n", id, status ); 364 ok( info_size == sizeof(image), "%u: NtQuerySection wrong size %Iu\n", id, info_size ); 365 if (nt_header->OptionalHeader.Magic == (is_win64 ? IMAGE_NT_OPTIONAL_HDR64_MAGIC 366 : IMAGE_NT_OPTIONAL_HDR32_MAGIC)) 367 { 368 max_stack = nt_header->OptionalHeader.SizeOfStackReserve; 369 commit_stack = nt_header->OptionalHeader.SizeOfStackCommit; 370 entry_point = (char *)nt_header->OptionalHeader.ImageBase + nt_header->OptionalHeader.AddressOfEntryPoint; 371 truncated = nt_header->FileHeader.SizeOfOptionalHeader < sizeof(IMAGE_OPTIONAL_HEADER); 372 if (!truncated && 373 nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress && 374 nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size) 375 cor_header = section_data; 376 } 377 else if (nt_header->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) 378 { 379 const IMAGE_NT_HEADERS64 *nt64 = (const IMAGE_NT_HEADERS64 *)nt_header; 380 max_stack = 0x100000; 381 commit_stack = 0x10000; 382 entry_point = (void *)0x81231234; 383 truncated = nt_header->FileHeader.SizeOfOptionalHeader < sizeof(IMAGE_OPTIONAL_HEADER64); 384 if (!truncated && 385 nt64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress && 386 nt64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size) 387 cor_header = section_data; 388 } 389 else 390 { 391 const IMAGE_NT_HEADERS32 *nt32 = (const IMAGE_NT_HEADERS32 *)nt_header; 392 max_stack = nt32->OptionalHeader.SizeOfStackReserve; 393 commit_stack = nt32->OptionalHeader.SizeOfStackCommit; 394 entry_point = (char *)(ULONG_PTR)nt32->OptionalHeader.ImageBase + nt32->OptionalHeader.AddressOfEntryPoint; 395 truncated = nt_header->FileHeader.SizeOfOptionalHeader < sizeof(IMAGE_OPTIONAL_HEADER32); 396 if (!truncated && 397 nt32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress && 398 nt32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size) 399 cor_header = section_data; 400 } 401 ok( (char *)image.TransferAddress == (char *)entry_point || 402 (image.ImageDynamicallyRelocated && LOWORD(image.TransferAddress) == LOWORD(entry_point)), 403 "%u: TransferAddress wrong %p / %p (%08lx)\n", id, 404 image.TransferAddress, entry_point, nt_header->OptionalHeader.AddressOfEntryPoint ); 405 ok( image.ZeroBits == 0, "%u: ZeroBits wrong %08lx\n", id, image.ZeroBits ); 406 ok( image.MaximumStackSize == max_stack, 407 "%u: MaximumStackSize wrong %Ix / %Ix\n", id, image.MaximumStackSize, max_stack ); 408 ok( image.CommittedStackSize == commit_stack, 409 "%u: CommittedStackSize wrong %Ix / %Ix\n", id, image.CommittedStackSize, commit_stack ); 410 ok( image.SubSystemType == nt_header->OptionalHeader.Subsystem, 411 "%u: SubSystemType wrong %08lx / %08x\n", id, 412 image.SubSystemType, nt_header->OptionalHeader.Subsystem ); 413 ok( image.MinorSubsystemVersion == nt_header->OptionalHeader.MinorSubsystemVersion, 414 "%u: MinorSubsystemVersion wrong %04x / %04x\n", id, 415 image.MinorSubsystemVersion, nt_header->OptionalHeader.MinorSubsystemVersion ); 416 ok( image.MajorSubsystemVersion == nt_header->OptionalHeader.MajorSubsystemVersion, 417 "%u: MajorSubsystemVersion wrong %04x / %04x\n", id, 418 image.MajorSubsystemVersion, nt_header->OptionalHeader.MajorSubsystemVersion ); 419 ok( image.MajorOperatingSystemVersion == nt_header->OptionalHeader.MajorOperatingSystemVersion || 420 broken( !image.MajorOperatingSystemVersion), /* before win10 */ 421 "%u: MajorOperatingSystemVersion wrong %04x / %04x\n", id, 422 image.MajorOperatingSystemVersion, nt_header->OptionalHeader.MajorOperatingSystemVersion ); 423 ok( image.MinorOperatingSystemVersion == nt_header->OptionalHeader.MinorOperatingSystemVersion, 424 "%u: MinorOperatingSystemVersion wrong %04x / %04x\n", id, 425 image.MinorOperatingSystemVersion, nt_header->OptionalHeader.MinorOperatingSystemVersion ); 426 ok( image.ImageCharacteristics == nt_header->FileHeader.Characteristics, 427 "%u: ImageCharacteristics wrong %04x / %04x\n", id, 428 image.ImageCharacteristics, nt_header->FileHeader.Characteristics ); 429 ok( image.DllCharacteristics == nt_header->OptionalHeader.DllCharacteristics, 430 "%u: DllCharacteristics wrong %04x / %04x\n", id, 431 image.DllCharacteristics, nt_header->OptionalHeader.DllCharacteristics ); 432 ok( image.Machine == nt_header->FileHeader.Machine, "%u: Machine wrong %04x / %04x\n", id, 433 image.Machine, nt_header->FileHeader.Machine ); 434 ok( image.LoaderFlags == (cor_header != NULL), "%u: LoaderFlags wrong %08lx\n", id, image.LoaderFlags ); 435 ok( image.ImageFileSize == file_size, 436 "%u: ImageFileSize wrong %08lx / %08lx\n", id, image.ImageFileSize, file_size ); 437 ok( image.CheckSum == nt_header->OptionalHeader.CheckSum, 438 "%u: CheckSum wrong %08lx / %08lx\n", id, 439 image.CheckSum, nt_header->OptionalHeader.CheckSum ); 440 441 if (nt_header->OptionalHeader.SizeOfCode || nt_header->OptionalHeader.AddressOfEntryPoint) 442 ok( image.ImageContainsCode == TRUE, "%u: ImageContainsCode wrong %u\n", id, 443 image.ImageContainsCode ); 444 else if ((nt_header->OptionalHeader.SectionAlignment % page_size) || 445 (nt_header->FileHeader.NumberOfSections == 1 && 446 (section.Characteristics & IMAGE_SCN_MEM_EXECUTE))) 447 ok( image.ImageContainsCode == TRUE || broken(!image.ImageContainsCode), /* <= win8 */ 448 "%u: ImageContainsCode wrong %u\n", id, image.ImageContainsCode ); 449 else 450 ok( !image.ImageContainsCode, "%u: ImageContainsCode wrong %u\n", id, image.ImageContainsCode ); 451 452 if (cor_header && 453 (cor_header->Flags & COMIMAGE_FLAGS_ILONLY) && 454 (cor_header->MajorRuntimeVersion > 2 || 455 (cor_header->MajorRuntimeVersion == 2 && cor_header->MinorRuntimeVersion >= 5))) 456 { 457#ifdef __REACTOS__ 458 ok( image.ComPlusILOnly || broken(GetNTVersion() < _WIN32_WINNT_VISTA), 459#else 460 ok( image.ComPlusILOnly, 461#endif 462 "%u: wrong ComPlusILOnly flags %02x\n", id, image.ImageFlags ); 463 if (nt_header->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC && 464 !(cor_header->Flags & COMIMAGE_FLAGS_32BITREQUIRED)) 465#ifdef __REACTOS__ 466 ok( image.ComPlusNativeReady || broken(GetNTVersion() < _WIN32_WINNT_VISTA), 467#else 468 ok( image.ComPlusNativeReady, 469#endif 470 "%u: wrong ComPlusNativeReady flags %02x\n", id, image.ImageFlags ); 471 else 472 ok( !image.ComPlusNativeReady, 473 "%u: wrong ComPlusNativeReady flags %02x\n", id, image.ImageFlags ); 474 if (nt_header->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC && 475 (cor_header->Flags & COMIMAGE_FLAGS_32BITPREFERRED)) 476 ok( image.ComPlusPrefer32bit || 477 broken( !image.MajorOperatingSystemVersion ), /* before win10 */ 478 "%u: wrong ComPlusPrefer32bit flags %02x\n", id, image.ImageFlags ); 479 else 480 ok( !image.ComPlusPrefer32bit, "%u: wrong ComPlusPrefer32bit flags %02x\n", id, image.ImageFlags ); 481 } 482 else 483 { 484 ok( !image.ComPlusILOnly, "%u: wrong ComPlusILOnly flags %02x\n", id, image.ImageFlags ); 485 ok( !image.ComPlusNativeReady, "%u: wrong ComPlusNativeReady flags %02x\n", id, image.ImageFlags ); 486 ok( !image.ComPlusPrefer32bit, "%u: wrong ComPlusPrefer32bit flags %02x\n", id, image.ImageFlags ); 487 } 488 if (!(nt_header->OptionalHeader.SectionAlignment % page_size)) 489 ok( !image.ImageMappedFlat, "%u: wrong ImageMappedFlat flags %02x\n", id, image.ImageFlags ); 490 else 491#ifdef __REACTOS__ 492 ok( image.ImageMappedFlat || broken(GetNTVersion() < _WIN32_WINNT_VISTA), 493#else 494 ok( image.ImageMappedFlat, 495#endif 496 "%u: wrong ImageMappedFlat flags %02x\n", id, image.ImageFlags ); 497 498 if (!(nt_header->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE)) 499 ok( !image.ImageDynamicallyRelocated || broken( image.ComPlusILOnly ), /* <= win7 */ 500 "%u: wrong ImageDynamicallyRelocated flags %02x\n", id, image.ImageFlags ); 501 else if (image.ImageContainsCode && !image.ImageMappedFlat && !cor_header) 502#ifdef __REACTOS__ 503 ok( image.ImageDynamicallyRelocated || broken(GetNTVersion() < _WIN32_WINNT_VISTA), 504#else 505 ok( image.ImageDynamicallyRelocated, 506#endif 507 "%u: wrong ImageDynamicallyRelocated flags %02x\n", id, image.ImageFlags ); 508 else 509 ok( !image.ImageDynamicallyRelocated || broken(TRUE), /* <= win8 */ 510 "%u: wrong ImageDynamicallyRelocated flags %02x\n", id, image.ImageFlags ); 511 ok( !image.BaseBelow4gb, "%u: wrong BaseBelow4gb flags %02x\n", id, image.ImageFlags ); 512 513 map_size.QuadPart = (nt_header->OptionalHeader.SizeOfImage + page_size - 1) & ~(page_size - 1); 514 status = pNtQuerySection( mapping, SectionBasicInformation, &info, sizeof(info), NULL ); 515 ok( !status, "NtQuerySection failed err %lx\n", status ); 516 ok( info.Size.QuadPart == map_size.QuadPart, "NtQuerySection wrong size %lx%08lx / %lx%08lx\n", 517 info.Size.u.HighPart, info.Size.u.LowPart, map_size.u.HighPart, map_size.u.LowPart ); 518 CloseHandle( mapping ); 519 520 map_size.QuadPart = (nt_header->OptionalHeader.SizeOfImage + page_size - 1) & ~(page_size - 1); 521 status = pNtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_MAP_READ | SECTION_QUERY, 522 NULL, &map_size, PAGE_READONLY, SEC_IMAGE, file ); 523 ok( !status, "%u: NtCreateSection failed err %lx\n", id, status ); 524 status = pNtQuerySection( mapping, SectionBasicInformation, &info, sizeof(info), NULL ); 525 ok( !status, "NtQuerySection failed err %lx\n", status ); 526 ok( info.Size.QuadPart == map_size.QuadPart, "NtQuerySection wrong size %lx%08lx / %lx%08lx\n", 527 info.Size.u.HighPart, info.Size.u.LowPart, map_size.u.HighPart, map_size.u.LowPart ); 528 CloseHandle( mapping ); 529 530 map_size.QuadPart++; 531 status = pNtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_MAP_READ | SECTION_QUERY, 532 NULL, &map_size, PAGE_READONLY, SEC_IMAGE, file ); 533 ok( status == STATUS_SECTION_TOO_BIG, "%u: NtCreateSection failed err %lx\n", id, status ); 534 535 SetFilePointerEx( file, map_size, NULL, FILE_BEGIN ); 536 SetEndOfFile( file ); 537 status = pNtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_MAP_READ | SECTION_QUERY, 538 NULL, &map_size, PAGE_READONLY, SEC_IMAGE, file ); 539 ok( status == STATUS_SECTION_TOO_BIG, "%u: NtCreateSection failed err %lx\n", id, status ); 540 541 map_size.QuadPart = 1; 542 status = pNtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_MAP_READ | SECTION_QUERY, 543 NULL, &map_size, PAGE_READONLY, SEC_IMAGE, file ); 544 ok( !status, "%u: NtCreateSection failed err %lx\n", id, status ); 545 status = pNtQuerySection( mapping, SectionBasicInformation, &info, sizeof(info), NULL ); 546 ok( !status, "NtQuerySection failed err %lx\n", status ); 547 ok( info.Size.QuadPart == map_size.QuadPart, "NtQuerySection wrong size %lx%08lx / %lx%08lx\n", 548 info.Size.u.HighPart, info.Size.u.LowPart, map_size.u.HighPart, map_size.u.LowPart ); 549 CloseHandle( mapping ); 550 551 CloseHandle( file ); 552 return image.ImageContainsCode && (!cor_header || !(cor_header->Flags & COMIMAGE_FLAGS_ILONLY)); 553} 554 555static const WCHAR wldr_nameW[] = {'w','l','d','r','t','e','s','t','.','d','l','l',0}; 556static WCHAR load_test_name[MAX_PATH], load_fallback_name[MAX_PATH]; 557static WCHAR load_path[MAX_PATH]; 558 559static void init_load_path( const char *fallback_dll ) 560{ 561 static const WCHAR pathW[] = {'P','A','T','H',0}; 562 static const WCHAR ldrW[] = {'l','d','r',0}; 563 static const WCHAR sepW[] = {';',0}; 564 static const WCHAR bsW[] = {'\\',0}; 565 WCHAR path[MAX_PATH]; 566 567 GetTempPathW( MAX_PATH, path ); 568 GetTempFileNameW( path, ldrW, 0, load_test_name ); 569 GetTempFileNameW( path, ldrW, 0, load_fallback_name ); 570 DeleteFileW( load_test_name ); 571 ok( CreateDirectoryW( load_test_name, NULL ), "failed to create dir\n" ); 572 DeleteFileW( load_fallback_name ); 573 ok( CreateDirectoryW( load_fallback_name, NULL ), "failed to create dir\n" ); 574 lstrcpyW( load_path, load_test_name ); 575 lstrcatW( load_path, sepW ); 576 lstrcatW( load_path, load_fallback_name ); 577 lstrcatW( load_path, sepW ); 578 GetEnvironmentVariableW( pathW, load_path + lstrlenW(load_path), 579 ARRAY_SIZE(load_path) - lstrlenW(load_path) ); 580 lstrcatW( load_test_name, bsW ); 581 lstrcatW( load_test_name, wldr_nameW ); 582 lstrcatW( load_fallback_name, bsW ); 583 lstrcatW( load_fallback_name, wldr_nameW ); 584 MultiByteToWideChar( CP_ACP, 0, fallback_dll, -1, path, MAX_PATH ); 585 MoveFileW( path, load_fallback_name ); 586} 587 588static void delete_load_path(void) 589{ 590 WCHAR *p; 591 592 DeleteFileW( load_test_name ); 593 for (p = load_test_name + lstrlenW(load_test_name) - 1; *p != '\\'; p--) ; 594 *p = 0; 595 RemoveDirectoryW( load_test_name ); 596 DeleteFileW( load_fallback_name ); 597 for (p = load_fallback_name + lstrlenW(load_fallback_name) - 1; *p != '\\'; p--) ; 598 *p = 0; 599 RemoveDirectoryW( load_fallback_name ); 600} 601 602static UINT get_com_dir_size( const IMAGE_NT_HEADERS *nt ) 603{ 604 if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) 605 return ((const IMAGE_NT_HEADERS32 *)nt)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size; 606 else if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) 607 return ((const IMAGE_NT_HEADERS64 *)nt)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size; 608 else 609 return 0; 610} 611 612/* helper to test image section mapping */ 613static NTSTATUS map_image_section( const IMAGE_NT_HEADERS *nt_header, const IMAGE_SECTION_HEADER *sections, 614 const void *section_data, int line ) 615{ 616 char dll_name[MAX_PATH]; 617 WCHAR path[MAX_PATH]; 618 UNICODE_STRING name; 619 LARGE_INTEGER size; 620 HANDLE file, map; 621 NTSTATUS status, expect_status, ldr_status; 622 ULONG file_size; 623 BOOL has_code = FALSE, il_only = FALSE, want_32bit = FALSE, expect_fallback = FALSE, wrong_machine = FALSE; 624 HMODULE mod = 0, ldr_mod; 625 626 file_size = create_test_dll_sections( &dos_header, nt_header, sections, section_data, dll_name ); 627 628 file = CreateFileA(dll_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); 629 ok(file != INVALID_HANDLE_VALUE, "CreateFile error %ld\n", GetLastError()); 630 631 size.QuadPart = file_size; 632 status = pNtCreateSection(&map, STANDARD_RIGHTS_REQUIRED | SECTION_MAP_READ | SECTION_QUERY, 633 NULL, &size, PAGE_READONLY, SEC_IMAGE, file ); 634 expect_status = status; 635 636 if (get_com_dir_size( nt_header )) 637 { 638 /* invalid COR20 header seems to corrupt internal loader state on Windows */ 639 if (get_com_dir_size( nt_header ) < sizeof(IMAGE_COR20_HEADER)) goto done; 640 if (!((const IMAGE_COR20_HEADER *)section_data)->Flags) goto done; 641 } 642 643 if (!status) 644 { 645 SECTION_BASIC_INFORMATION info; 646 SIZE_T info_size = 0xdeadbeef; 647 NTSTATUS ret = pNtQuerySection( map, SectionBasicInformation, &info, sizeof(info), &info_size ); 648 ok( !ret, "NtQuerySection failed err %lx\n", ret ); 649 ok( info_size == sizeof(info), "NtQuerySection wrong size %Iu\n", info_size ); 650 ok( info.Attributes == (SEC_IMAGE | SEC_FILE), "NtQuerySection wrong attr %lx\n", info.Attributes ); 651 ok( info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", info.BaseAddress ); 652 ok( info.Size.QuadPart == file_size, "NtQuerySection wrong size %lx%08lx / %08lx\n", 653 info.Size.u.HighPart, info.Size.u.LowPart, file_size ); 654 has_code = query_image_section( line, dll_name, nt_header, section_data ); 655 656 if (get_com_dir_size( nt_header )) 657 { 658 const IMAGE_COR20_HEADER *cor_header = section_data; 659 il_only = (cor_header->Flags & COMIMAGE_FLAGS_ILONLY) != 0; 660 if (il_only) want_32bit = (cor_header->Flags & COMIMAGE_FLAGS_32BITREQUIRED) != 0; 661 } 662 663 SetLastError( 0xdeadbeef ); 664 mod = LoadLibraryExA( dll_name, 0, DONT_RESOLVE_DLL_REFERENCES ); 665 /* test loading dll of wrong 32/64 bitness */ 666 if (nt_header->OptionalHeader.Magic == (is_win64 ? IMAGE_NT_OPTIONAL_HDR32_MAGIC 667 : IMAGE_NT_OPTIONAL_HDR64_MAGIC)) 668 { 669 if (!has_code && is_win64) 670 { 671 ok_(__FILE__,line)( mod != NULL || want_32bit || broken(il_only), /* <= win7 */ 672 "loading failed err %lu\n", GetLastError() ); 673 } 674 else 675 { 676 ok_(__FILE__, line)( !mod, "loading succeeded\n" ); 677 ok_(__FILE__, line)( GetLastError() == ERROR_BAD_EXE_FORMAT, "wrong error %lu\n", GetLastError() ); 678 if (nt_header_template.FileHeader.Machine == IMAGE_FILE_MACHINE_ARM64) 679 { 680 wrong_machine = TRUE; 681 expect_status = STATUS_INVALID_IMAGE_FORMAT; 682 } 683 } 684 } 685 else 686 { 687 wrong_machine = (nt_header->FileHeader.Machine == get_alt_machine( nt_header_template.FileHeader.Machine )); 688 689 ok( mod != NULL || broken(il_only) || /* <= win7 */ 690 broken( wrong_machine ), /* win8 */ 691 "%u: loading failed err %lu\n", line, GetLastError() ); 692 } 693 if (mod) FreeLibrary( mod ); 694 expect_fallback = !mod; 695 } 696 697 /* test fallback to another dll further in the load path */ 698 699 MultiByteToWideChar( CP_ACP, 0, dll_name, -1, path, MAX_PATH ); 700 CopyFileW( path, load_test_name, FALSE ); 701 pRtlInitUnicodeString( &name, wldr_nameW ); 702 ldr_status = pLdrLoadDll( load_path, 0, &name, &ldr_mod ); 703 if (!ldr_status) 704 { 705 GetModuleFileNameW( ldr_mod, path, MAX_PATH ); 706 if (!lstrcmpiW( path, load_test_name )) 707 { 708 if (!expect_status) 709 ok( !expect_fallback, "%u: got test dll but expected fallback\n", line ); 710 else 711 ok( !expect_fallback, "%u: got test dll but expected failure %lx\n", line, expect_status ); 712 } 713 else if (!lstrcmpiW( path, load_fallback_name )) 714 { 715 trace( "%u: loaded fallback\n", line ); 716#ifdef __REACTOS__ 717 ok( !expect_status || broken(is_win64) /* Broken on Vista, 8.1 x64 */, "%u: got fallback but expected failure %lx\n", line, expect_status ); 718 ok( expect_fallback || broken(is_win64) /* Broken on Vista, 8.1 x64 */ || 719#else 720 ok( !expect_status, "%u: got fallback but expected failure %lx\n", line, expect_status ); 721 ok( expect_fallback || 722#endif 723 /* win10 also falls back for 32-bit dll without code, even though it could be loaded */ 724 (is_win64 && !has_code && 725 nt_header->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC), 726 "%u: got fallback but expected test dll\n", line ); 727 } 728 else ok( 0, "%u: got unexpected path %s instead of %s\n", line, wine_dbgstr_w(path), wine_dbgstr_w(load_test_name)); 729 pLdrUnloadDll( ldr_mod ); 730 } 731 else if (ldr_status == STATUS_DLL_INIT_FAILED || 732 ldr_status == STATUS_ACCESS_VIOLATION || 733 ldr_status == STATUS_ILLEGAL_INSTRUCTION) 734 { 735 /* some dlls with invalid entry point will crash, but this means we loaded the test dll */ 736#ifdef __REACTOS__ 737 ok( !expect_fallback || broken(is_win64 && GetNTVersion() == _WIN32_WINNT_WIN8) /* Broken on 8.1 x64 */, "%u: got test dll but expected fallback\n", line ); 738#else 739 ok( !expect_fallback, "%u: got test dll but expected fallback\n", line ); 740#endif 741 } 742 else 743 { 744 ok( ldr_status == expect_status || 745 (wrong_machine && !expect_status && ldr_status == STATUS_INVALID_IMAGE_FORMAT) || 746 broken(il_only && !expect_status && ldr_status == STATUS_INVALID_IMAGE_FORMAT) || 747 broken(nt_header->Signature == IMAGE_OS2_SIGNATURE && ldr_status == STATUS_INVALID_IMAGE_NE_FORMAT), 748 "%u: wrong status %lx/%lx\n", line, ldr_status, expect_status ); 749 ok( !expect_fallback || wrong_machine || broken(il_only), 750 "%u: failed with %lx expected fallback\n", line, ldr_status ); 751 } 752 753done: 754 if (map) CloseHandle( map ); 755 CloseHandle( file ); 756 DeleteFileA( dll_name ); 757 return status; 758} 759 760 761static void test_Loader(void) 762{ 763 static const struct test_data 764 { 765 DWORD size_of_dos_header; 766 WORD number_of_sections, size_of_optional_header; 767 DWORD section_alignment, file_alignment; 768 DWORD size_of_image, size_of_headers; 769 DWORD errors[4]; /* 0 means LoadLibrary should succeed */ 770 } td[] = 771 { 772 { sizeof(dos_header), 773 1, 0, 0, 0, 0, 0, 774 { ERROR_BAD_EXE_FORMAT } 775 }, 776 { sizeof(dos_header), 777 1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x1000, 778 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0xe00, 779 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER), 780 { ERROR_BAD_EXE_FORMAT } /* XP doesn't like too small image size */ 781 }, 782 { sizeof(dos_header), 783 1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x1000, 784 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0x1000, 785 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER), 786 { ERROR_SUCCESS } 787 }, 788 { sizeof(dos_header), 789 1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x1000, 790 0x1f00, 791 0x1000, 792 { ERROR_SUCCESS } 793 }, 794 { sizeof(dos_header), 795 1, sizeof(IMAGE_OPTIONAL_HEADER), 0x200, 0x200, 796 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0x200, 797 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER), 798 { ERROR_SUCCESS, ERROR_INVALID_ADDRESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */ 799 }, 800 { sizeof(dos_header), 801 1, sizeof(IMAGE_OPTIONAL_HEADER), 0x200, 0x1000, 802 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0x1000, 803 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER), 804 { ERROR_BAD_EXE_FORMAT } /* XP doesn't like alignments */ 805 }, 806 { sizeof(dos_header), 807 1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x200, 808 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0x1000, 809 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER), 810 { ERROR_SUCCESS } 811 }, 812 { sizeof(dos_header), 813 1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x200, 814 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0x1000, 815 0x200, 816 { ERROR_SUCCESS } 817 }, 818 /* Mandatory are all fields up to SizeOfHeaders, everything else 819 * is really optional (at least that's true for XP). 820 */ 821#if 0 /* 32-bit Windows 8 crashes inside of LoadLibrary */ 822 { sizeof(dos_header), 823 1, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200, 824 sizeof(dos_header) + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum) + sizeof(IMAGE_SECTION_HEADER) + 0x10, 825 sizeof(dos_header) + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum) + sizeof(IMAGE_SECTION_HEADER), 826 { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT, ERROR_INVALID_ADDRESS, 827 ERROR_NOACCESS } 828 }, 829#endif 830 { sizeof(dos_header), 831 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200, 832 0xd0, /* beyond of the end of file */ 833 0xc0, /* beyond of the end of file */ 834 { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */ 835 }, 836 { sizeof(dos_header), 837 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200, 838 0x1000, 839 0, 840 { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */ 841 }, 842 { sizeof(dos_header), 843 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200, 844 1, 845 0, 846 { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */ 847 }, 848#if 0 /* not power of 2 alignments need more test cases */ 849 { sizeof(dos_header), 850 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x300, 0x300, 851 1, 852 0, 853 { ERROR_BAD_EXE_FORMAT } /* alignment is not power of 2 */ 854 }, 855#endif 856 { sizeof(dos_header), 857 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 4, 4, 858 1, 859 0, 860 { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */ 861 }, 862 { sizeof(dos_header), 863 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 1, 1, 864 1, 865 0, 866 { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */ 867 }, 868 { sizeof(dos_header), 869 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200, 870 0, 871 0, 872 { ERROR_BAD_EXE_FORMAT } /* image size == 0 -> failure */ 873 }, 874 /* the following data mimics the PE image which upack creates */ 875 { 0x10, 876 1, 0x148, 0x1000, 0x200, 877 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0x1000, 878 0x200, 879 { ERROR_SUCCESS } 880 }, 881 /* Minimal PE image that XP is able to load: 92 bytes */ 882 { 0x04, 883 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 884 0x04 /* also serves as e_lfanew in the truncated MZ header */, 0x04, 885 1, 886 0, 887 { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */ 888 }, 889 /* Minimal PE image initially created for Windows 7 and accepted from 890 * Vista up to Windows 10 1709 with some unexplained exceptions: 891 * 268 bytes 892 */ 893 { 0x04, 894 0, 0xf0, /* optional header size just forces 0xf0 bytes to be written, 895 0 or another number don't change the behaviour, what really 896 matters is file size regardless of values in the headers */ 897 0x04 /* also serves as e_lfanew in the truncated MZ header */, 0x04, 898 0x40, /* minimal image size that Windows7 accepts */ 899 0, 900 { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* rejected by win10 1809+ */ 901 }, 902 /* the following data mimics the PE image which 8k demos have */ 903 { 0x04, 904 0, 0x08, 905 0x04 /* also serves as e_lfanew in the truncated MZ header */, 0x04, 906 0x2000, 907 0x40, 908 { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } 909 } 910 }; 911 int i; 912 DWORD file_size; 913 HANDLE h; 914 HMODULE hlib, hlib_as_data_file; 915 char dll_name[MAX_PATH]; 916 SIZE_T size; 917 BOOL ret; 918 NTSTATUS status; 919 WORD orig_machine = nt_header_template.FileHeader.Machine; 920 IMAGE_NT_HEADERS nt_header; 921 IMAGE_COR20_HEADER cor_header; 922 923 /* prevent displaying of the "Unable to load this DLL" message box */ 924 SetErrorMode(SEM_FAILCRITICALERRORS); 925 926 for (i = 0; i < ARRAY_SIZE(td); i++) 927 { 928 winetest_push_context("%d", i); 929 nt_header = nt_header_template; 930 nt_header.FileHeader.NumberOfSections = td[i].number_of_sections; 931 nt_header.FileHeader.SizeOfOptionalHeader = td[i].size_of_optional_header; 932 933 nt_header.OptionalHeader.SectionAlignment = td[i].section_alignment; 934 nt_header.OptionalHeader.FileAlignment = td[i].file_alignment; 935 nt_header.OptionalHeader.SizeOfImage = td[i].size_of_image; 936 nt_header.OptionalHeader.SizeOfHeaders = td[i].size_of_headers; 937 938 section.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ; 939 file_size = create_test_dll( &dos_header, td[i].size_of_dos_header, &nt_header, dll_name ); 940 941 SetLastError(0xdeadbeef); 942 hlib = LoadLibraryA(dll_name); 943 if (hlib) 944 { 945 MEMORY_BASIC_INFORMATION info; 946 void *ptr; 947 948 ok( td[i].errors[0] == ERROR_SUCCESS, "should have failed\n" ); 949 950 SetLastError(0xdeadbeef); 951 size = VirtualQuery(hlib, &info, sizeof(info)); 952 ok(size == sizeof(info), 953 "%d: VirtualQuery error %ld\n", i, GetLastError()); 954 ok(info.BaseAddress == hlib, "%p != %p\n", info.BaseAddress, hlib); 955 ok(info.AllocationBase == hlib, "%p != %p\n", info.AllocationBase, hlib); 956 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%lx != PAGE_EXECUTE_WRITECOPY\n", info.AllocationProtect); 957 ok(info.RegionSize == ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, page_size), "got %Ix != expected %x\n", 958 info.RegionSize, (UINT)ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, page_size)); 959 ok(info.State == MEM_COMMIT, "%lx != MEM_COMMIT\n", info.State); 960 if (nt_header.OptionalHeader.SectionAlignment < page_size) 961 ok(info.Protect == PAGE_EXECUTE_WRITECOPY, "%lx != PAGE_EXECUTE_WRITECOPY\n", info.Protect); 962 else 963 ok(info.Protect == PAGE_READONLY, "%lx != PAGE_READONLY\n", info.Protect); 964 ok(info.Type == SEC_IMAGE, "%lx != SEC_IMAGE\n", info.Type); 965 966 SetLastError(0xdeadbeef); 967 ptr = VirtualAlloc(hlib, page_size, MEM_COMMIT, info.Protect); 968 ok(!ptr, "VirtualAlloc should fail\n"); 969 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError()); 970 971 SetLastError(0xdeadbeef); 972 size = VirtualQuery((char *)hlib + info.RegionSize, &info, sizeof(info)); 973 ok(size == sizeof(info), "VirtualQuery error %ld\n", GetLastError()); 974 if (nt_header.OptionalHeader.SectionAlignment == page_size || 975 nt_header.OptionalHeader.SectionAlignment == nt_header.OptionalHeader.FileAlignment) 976 { 977 ok(info.BaseAddress == (char *)hlib + ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, page_size), "got %p != expected %p\n", 978 info.BaseAddress, (char *)hlib + ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, page_size)); 979 ok(info.AllocationBase == 0, "%p != 0\n", info.AllocationBase); 980 ok(info.AllocationProtect == 0, "%lx != 0\n", info.AllocationProtect); 981 /*ok(info.RegionSize == not_practical_value, "%d: %lx != not_practical_value\n", i, info.RegionSize);*/ 982 ok(info.State == MEM_FREE, "%lx != MEM_FREE\n", info.State); 983 ok(info.Type == 0, "%lx != 0\n", info.Type); 984 ok(info.Protect == PAGE_NOACCESS, "%lx != PAGE_NOACCESS\n", info.Protect); 985 } 986 else 987 { 988 ok(info.Protect == PAGE_EXECUTE_WRITECOPY, "%lx != PAGE_EXECUTE_WRITECOPY\n", info.Protect); 989 ok(info.BaseAddress == hlib, "got %p != expected %p\n", info.BaseAddress, hlib); 990 ok(info.AllocationBase == hlib, "%p != %p\n", info.AllocationBase, hlib); 991 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%lx != PAGE_EXECUTE_WRITECOPY\n", info.AllocationProtect); 992 ok(info.RegionSize == ALIGN_SIZE(file_size, page_size), "got %Ix != expected %x\n", 993 info.RegionSize, (UINT)ALIGN_SIZE(file_size, page_size)); 994 ok(info.State == MEM_COMMIT, "%lx != MEM_COMMIT\n", info.State); 995 ok(info.Protect == PAGE_READONLY, "%lx != PAGE_READONLY\n", info.Protect); 996 ok(info.Type == SEC_IMAGE, "%lx != SEC_IMAGE\n", info.Type); 997 } 998 999 /* header: check the zeroing of alignment */ 1000 if (nt_header.OptionalHeader.SectionAlignment >= page_size) 1001 { 1002 const char *start; 1003 1004 start = (const char *)hlib + nt_header.OptionalHeader.SizeOfHeaders; 1005 size = ALIGN_SIZE((ULONG_PTR)start, page_size) - (ULONG_PTR)start; 1006 ok(!memcmp(start, filler, size), "header alignment is not cleared\n"); 1007 } 1008 1009 if (nt_header.FileHeader.NumberOfSections) 1010 { 1011 SetLastError(0xdeadbeef); 1012 size = VirtualQuery((char *)hlib + section.VirtualAddress, &info, sizeof(info)); 1013 ok(size == sizeof(info), 1014 "VirtualQuery error %ld\n", GetLastError()); 1015 if (nt_header.OptionalHeader.SectionAlignment < page_size) 1016 { 1017 ok(info.BaseAddress == hlib, "got %p != expected %p\n", info.BaseAddress, hlib); 1018 ok(info.RegionSize == ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, page_size), "got %Ix != expected %x\n", 1019 info.RegionSize, (UINT)ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, page_size)); 1020 ok(info.Protect == PAGE_EXECUTE_WRITECOPY, "%lx != PAGE_EXECUTE_WRITECOPY\n", info.Protect); 1021 } 1022 else 1023 { 1024 ok(info.BaseAddress == (char *)hlib + section.VirtualAddress, "got %p != expected %p\n", info.BaseAddress, (char *)hlib + section.VirtualAddress); 1025 ok(info.RegionSize == ALIGN_SIZE(section.Misc.VirtualSize, page_size), "got %Ix != expected %x\n", 1026 info.RegionSize, (UINT)ALIGN_SIZE(section.Misc.VirtualSize, page_size)); 1027 ok(info.Protect == PAGE_READONLY, "%lx != PAGE_READONLY\n", info.Protect); 1028 } 1029 ok(info.AllocationBase == hlib, "%p != %p\n", info.AllocationBase, hlib); 1030 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%lx != PAGE_EXECUTE_WRITECOPY\n", info.AllocationProtect); 1031 ok(info.State == MEM_COMMIT, "%lx != MEM_COMMIT\n", info.State); 1032 ok(info.Type == SEC_IMAGE, "%lx != SEC_IMAGE\n", info.Type); 1033 1034 if (nt_header.OptionalHeader.SectionAlignment >= page_size) 1035 ok(!memcmp((const char *)hlib + section.VirtualAddress + section.PointerToRawData, &nt_header, section.SizeOfRawData), "wrong section data\n"); 1036 else 1037 ok(!memcmp((const char *)hlib + section.PointerToRawData, section_data, section.SizeOfRawData), "wrong section data\n"); 1038 1039 /* check the zeroing of alignment */ 1040 if (nt_header.OptionalHeader.SectionAlignment >= page_size) 1041 { 1042 const char *start; 1043 1044 start = (const char *)hlib + section.VirtualAddress + section.PointerToRawData + section.SizeOfRawData; 1045 size = ALIGN_SIZE((ULONG_PTR)start, page_size) - (ULONG_PTR)start; 1046 ok(memcmp(start, filler, size), "alignment should not be cleared\n"); 1047 } 1048 1049 SetLastError(0xdeadbeef); 1050 ptr = VirtualAlloc((char *)hlib + section.VirtualAddress, page_size, MEM_COMMIT, info.Protect); 1051 ok(!ptr, "VirtualAlloc should fail\n"); 1052 ok(GetLastError() == ERROR_ACCESS_DENIED || GetLastError() == ERROR_INVALID_ADDRESS, 1053 "expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError()); 1054 } 1055 1056 SetLastError(0xdeadbeef); 1057 hlib_as_data_file = LoadLibraryExA(dll_name, 0, LOAD_LIBRARY_AS_DATAFILE); 1058 ok(hlib_as_data_file != 0, "LoadLibraryEx error %lu\n", GetLastError()); 1059 ok(hlib_as_data_file == hlib, "hlib_as_file and hlib are different\n"); 1060 1061 SetLastError(0xdeadbeef); 1062 ret = FreeLibrary(hlib); 1063 ok(ret, "FreeLibrary error %ld\n", GetLastError()); 1064 1065 SetLastError(0xdeadbeef); 1066 hlib = GetModuleHandleA(dll_name); 1067 ok(hlib != 0, "GetModuleHandle error %lu\n", GetLastError()); 1068 1069 SetLastError(0xdeadbeef); 1070 ret = FreeLibrary(hlib_as_data_file); 1071 ok(ret, "FreeLibrary error %ld\n", GetLastError()); 1072 1073 hlib = GetModuleHandleA(dll_name); 1074 ok(!hlib, "GetModuleHandle should fail\n"); 1075 1076 SetLastError(0xdeadbeef); 1077 hlib_as_data_file = LoadLibraryExA(dll_name, 0, LOAD_LIBRARY_AS_DATAFILE); 1078 ok(hlib_as_data_file != 0, "LoadLibraryEx error %lu\n", GetLastError()); 1079 ok(((ULONG_PTR)hlib_as_data_file & 3) == 1, "hlib_as_data_file got %p\n", hlib_as_data_file); 1080 1081 hlib = GetModuleHandleA(dll_name); 1082 ok(!hlib, "GetModuleHandle should fail\n"); 1083 1084 SetLastError(0xdeadbeef); 1085 h = CreateFileA( dll_name, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 ); 1086 ok( h != INVALID_HANDLE_VALUE, "open failed err %lu\n", GetLastError() ); 1087 CloseHandle( h ); 1088 1089 SetLastError(0xdeadbeef); 1090 ret = FreeLibrary(hlib_as_data_file); 1091 ok(ret, "FreeLibrary error %ld\n", GetLastError()); 1092 1093 SetLastError(0xdeadbeef); 1094 hlib_as_data_file = LoadLibraryExA(dll_name, 0, LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE); 1095#ifdef __REACTOS__ 1096 if (!hlib_as_data_file && GetLastError() == ERROR_INVALID_PARAMETER) { 1097 skip("LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE not supported\n"); 1098 FreeLibrary(hlib_as_data_file); 1099 } else { 1100#endif 1101 ok(hlib_as_data_file != 0, "LoadLibraryEx error %lu\n", GetLastError()); 1102 1103 SetLastError(0xdeadbeef); 1104 h = CreateFileA( dll_name, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 ); 1105 ok( h == INVALID_HANDLE_VALUE, "open succeeded\n" ); 1106 ok( GetLastError() == ERROR_SHARING_VIOLATION, "wrong error %lu\n", GetLastError() ); 1107 CloseHandle( h ); 1108 1109 SetLastError(0xdeadbeef); 1110 h = CreateFileA( dll_name, GENERIC_READ | DELETE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 ); 1111 ok( h != INVALID_HANDLE_VALUE, "open failed err %lu\n", GetLastError() ); 1112 CloseHandle( h ); 1113 1114 SetLastError(0xdeadbeef); 1115 ret = FreeLibrary(hlib_as_data_file); 1116 ok(ret, "FreeLibrary error %ld\n", GetLastError()); 1117#ifdef __REACTOS__ 1118 } 1119#endif 1120 1121 SetLastError(0xdeadbeef); 1122 hlib_as_data_file = LoadLibraryExA(dll_name, 0, LOAD_LIBRARY_AS_IMAGE_RESOURCE); 1123#ifdef __REACTOS__ 1124 if (!hlib_as_data_file && GetLastError() == ERROR_INVALID_PARAMETER) { 1125 skip("LOAD_LIBRARY_AS_IMAGE_RESOURCE not supported\n"); 1126 FreeLibrary(hlib_as_data_file); 1127 } else { 1128#endif 1129 ok(hlib_as_data_file != 0, "LoadLibraryEx error %lu\n", GetLastError()); 1130 ok(((ULONG_PTR)hlib_as_data_file & 3) == 2, "hlib_as_data_file got %p\n", 1131 hlib_as_data_file); 1132 1133 hlib = GetModuleHandleA(dll_name); 1134 ok(!hlib, "GetModuleHandle should fail\n"); 1135 1136 SetLastError(0xdeadbeef); 1137 ret = FreeLibrary(hlib_as_data_file); 1138 ok(ret, "FreeLibrary error %ld\n", GetLastError()); 1139#ifdef __REACTOS__ 1140 } 1141#endif 1142 1143 SetLastError(0xdeadbeef); 1144 ret = DeleteFileA(dll_name); 1145 ok(ret, "DeleteFile error %ld\n", GetLastError()); 1146 1147 nt_header.OptionalHeader.AddressOfEntryPoint = 0x12345678; 1148 file_size = create_test_dll( &dos_header, td[i].size_of_dos_header, &nt_header, dll_name ); 1149 if (!file_size) 1150 { 1151 ok(0, "could not create %s\n", dll_name); 1152 winetest_pop_context(); 1153 break; 1154 } 1155 1156 query_image_section( i, dll_name, &nt_header, NULL ); 1157 } 1158 else 1159 { 1160 BOOL error_match; 1161 int error_index; 1162 1163 error_match = FALSE; 1164 for (error_index = 0; 1165 ! error_match && error_index < ARRAY_SIZE(td[i].errors); 1166 error_index++) 1167 { 1168 error_match = td[i].errors[error_index] == GetLastError(); 1169 } 1170 ok(error_match, "unexpected error %ld\n", GetLastError()); 1171 } 1172 1173 SetLastError(0xdeadbeef); 1174 ret = DeleteFileA(dll_name); 1175 ok(ret, "DeleteFile error %ld\n", GetLastError()); 1176 winetest_pop_context(); 1177 } 1178 1179 nt_header = nt_header_template; 1180 nt_header.FileHeader.NumberOfSections = 1; 1181 nt_header.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER); 1182 1183 nt_header.OptionalHeader.SectionAlignment = page_size; 1184 nt_header.OptionalHeader.DllCharacteristics = IMAGE_DLLCHARACTERISTICS_NX_COMPAT; 1185 nt_header.OptionalHeader.FileAlignment = page_size; 1186 nt_header.OptionalHeader.SizeOfHeaders = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER); 1187 nt_header.OptionalHeader.SizeOfImage = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + page_size; 1188 1189 section.SizeOfRawData = sizeof(section_data); 1190 section.PointerToRawData = page_size; 1191 section.VirtualAddress = page_size; 1192 section.Misc.VirtualSize = page_size; 1193 1194 create_test_dll_sections( &dos_header, &nt_header, &section, section_data, dll_name ); 1195 init_load_path( dll_name ); 1196 1197 nt_header.OptionalHeader.AddressOfEntryPoint = 0x1234; 1198 status = map_image_section( &nt_header, &section, section_data, __LINE__ ); 1199 ok( status == (nt_header.FileHeader.Machine == IMAGE_FILE_MACHINE_ARM64 ? STATUS_INVALID_IMAGE_FORMAT : STATUS_SUCCESS), 1200 "NtCreateSection error %08lx\n", status ); 1201 1202 nt_header.OptionalHeader.DllCharacteristics = IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE; 1203 status = map_image_section( &nt_header, &section, section_data, __LINE__ ); 1204 ok( status == (nt_header.FileHeader.Machine == IMAGE_FILE_MACHINE_ARM64 ? STATUS_INVALID_IMAGE_FORMAT : STATUS_SUCCESS), 1205 "NtCreateSection error %08lx\n", status ); 1206 1207 nt_header.OptionalHeader.SizeOfCode = 0x1000; 1208 status = map_image_section( &nt_header, &section, section_data, __LINE__ ); 1209 ok( status == (nt_header.FileHeader.Machine == IMAGE_FILE_MACHINE_ARM64 ? STATUS_INVALID_IMAGE_FORMAT : STATUS_SUCCESS), 1210 "NtCreateSection error %08lx\n", status ); 1211 1212 nt_header.OptionalHeader.SizeOfCode = 0; 1213 nt_header.OptionalHeader.DllCharacteristics = IMAGE_DLLCHARACTERISTICS_NX_COMPAT | IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE; 1214 1215 dos_header.e_magic = 0; 1216 status = map_image_section( &nt_header, &section, section_data, __LINE__ ); 1217 ok( status == STATUS_INVALID_IMAGE_NOT_MZ, "NtCreateSection error %08lx\n", status ); 1218 1219 dos_header.e_magic = IMAGE_DOS_SIGNATURE; 1220 nt_header.Signature = IMAGE_OS2_SIGNATURE; 1221 status = map_image_section( &nt_header, &section, section_data, __LINE__ ); 1222 ok( status == STATUS_INVALID_IMAGE_NE_FORMAT, "NtCreateSection error %08lx\n", status ); 1223 for (i = 0; i < 16; i++) 1224 { 1225 ((IMAGE_OS2_HEADER *)&nt_header)->ne_exetyp = i; 1226 status = map_image_section( &nt_header, &section, section_data, __LINE__ ); 1227 switch (i) 1228 { 1229 case 2: 1230 ok( status == STATUS_INVALID_IMAGE_WIN_16, "NtCreateSection %u error %08lx\n", i, status ); 1231 break; 1232 case 5: 1233 ok( status == STATUS_INVALID_IMAGE_PROTECT, "NtCreateSection %u error %08lx\n", i, status ); 1234 break; 1235 default: 1236 ok( status == STATUS_INVALID_IMAGE_NE_FORMAT, "NtCreateSection %u error %08lx\n", i, status ); 1237 break; 1238 } 1239 } 1240 ((IMAGE_OS2_HEADER *)&nt_header)->ne_exetyp = ((IMAGE_OS2_HEADER *)&nt_header_template)->ne_exetyp; 1241 1242 dos_header.e_lfanew = 0x98760000; 1243 status = map_image_section( &nt_header, &section, section_data, __LINE__ ); 1244 ok( status == STATUS_INVALID_IMAGE_PROTECT, "NtCreateSection error %08lx\n", status ); 1245 1246 dos_header.e_lfanew = sizeof(dos_header); 1247 nt_header.Signature = 0xdeadbeef; 1248 status = map_image_section( &nt_header, &section, section_data, __LINE__ ); 1249 ok( status == STATUS_INVALID_IMAGE_PROTECT, "NtCreateSection error %08lx\n", status ); 1250 1251 nt_header.Signature = IMAGE_NT_SIGNATURE; 1252 nt_header.OptionalHeader.Magic = 0xdead; 1253 status = map_image_section( &nt_header, &section, section_data, __LINE__ ); 1254 ok( status == STATUS_INVALID_IMAGE_FORMAT, "NtCreateSection error %08lx\n", status ); 1255 1256 nt_header.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR_MAGIC; 1257 nt_header.FileHeader.Machine = 0xdead; 1258 status = map_image_section( &nt_header, &section, section_data, __LINE__ ); 1259 ok( status == STATUS_INVALID_IMAGE_FORMAT, "NtCreateSection error %08lx\n", status ); 1260 1261 nt_header.FileHeader.Machine = IMAGE_FILE_MACHINE_UNKNOWN; 1262 status = map_image_section( &nt_header, &section, section_data, __LINE__ ); 1263 ok( status == STATUS_INVALID_IMAGE_FORMAT, "NtCreateSection error %08lx\n", status ); 1264 1265 nt_header.FileHeader.Machine = get_alt_bitness_machine( orig_machine ); 1266 status = map_image_section( &nt_header, &section, section_data, __LINE__ ); 1267 ok( status == STATUS_INVALID_IMAGE_FORMAT, "NtCreateSection error %08lx\n", status ); 1268 1269 nt_header.FileHeader.Machine = orig_machine; 1270 nt_header.OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES; 1271 nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress = page_size; 1272 nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size = sizeof(cor_header); 1273 section.SizeOfRawData = sizeof(cor_header); 1274 1275 memset( &cor_header, 0, sizeof(cor_header) ); 1276 cor_header.cb = sizeof(cor_header); 1277 cor_header.MajorRuntimeVersion = 2; 1278 cor_header.MinorRuntimeVersion = 4; 1279 cor_header.Flags = COMIMAGE_FLAGS_ILONLY; 1280 cor_header.EntryPointToken = 0xbeef; 1281 status = map_image_section( &nt_header, &section, &cor_header, __LINE__ ); 1282 ok( status == STATUS_SUCCESS, "NtCreateSection error %08lx\n", status ); 1283 1284 cor_header.MinorRuntimeVersion = 5; 1285 status = map_image_section( &nt_header, &section, &cor_header, __LINE__ ); 1286 ok( status == STATUS_SUCCESS, "NtCreateSection error %08lx\n", status ); 1287 1288 cor_header.MajorRuntimeVersion = 3; 1289 cor_header.MinorRuntimeVersion = 0; 1290 status = map_image_section( &nt_header, &section, &cor_header, __LINE__ ); 1291 ok( status == STATUS_SUCCESS, "NtCreateSection error %08lx\n", status ); 1292 1293 cor_header.Flags = COMIMAGE_FLAGS_ILONLY | COMIMAGE_FLAGS_32BITREQUIRED; 1294 status = map_image_section( &nt_header, &section, &cor_header, __LINE__ ); 1295 ok( status == STATUS_SUCCESS, "NtCreateSection error %08lx\n", status ); 1296 1297 cor_header.Flags = COMIMAGE_FLAGS_ILONLY | COMIMAGE_FLAGS_32BITPREFERRED; 1298 status = map_image_section( &nt_header, &section, &cor_header, __LINE__ ); 1299 ok( status == STATUS_SUCCESS, "NtCreateSection error %08lx\n", status ); 1300 1301 cor_header.Flags = 0; 1302 status = map_image_section( &nt_header, &section, &cor_header, __LINE__ ); 1303 ok( status == STATUS_SUCCESS, "NtCreateSection error %08lx\n", status ); 1304 1305 nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress = 1; 1306 nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size = 1; 1307 status = map_image_section( &nt_header, &section, &cor_header, __LINE__ ); 1308 ok( status == STATUS_SUCCESS, "NtCreateSection error %08lx\n", status ); 1309 1310 if (nt_header.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) 1311 { 1312 IMAGE_NT_HEADERS64 nt64; 1313 1314 memset( &nt64, 0, sizeof(nt64) ); 1315 nt64.Signature = IMAGE_NT_SIGNATURE; 1316 nt64.FileHeader.Machine = orig_machine; 1317 nt64.FileHeader.NumberOfSections = 1; 1318 nt64.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER64); 1319 nt64.FileHeader.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL; 1320 nt64.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR64_MAGIC; 1321 nt64.OptionalHeader.MajorLinkerVersion = 1; 1322 nt64.OptionalHeader.SizeOfCode = 0x1000; 1323 nt64.OptionalHeader.AddressOfEntryPoint = 0x1000; 1324 nt64.OptionalHeader.ImageBase = 0x10000000; 1325 nt64.OptionalHeader.SectionAlignment = 0x1000; 1326 nt64.OptionalHeader.FileAlignment = 0x1000; 1327 nt64.OptionalHeader.MajorOperatingSystemVersion = 4; 1328 nt64.OptionalHeader.MajorImageVersion = 1; 1329 nt64.OptionalHeader.MajorSubsystemVersion = 4; 1330 nt64.OptionalHeader.SizeOfHeaders = sizeof(dos_header) + sizeof(nt64) + sizeof(IMAGE_SECTION_HEADER); 1331 nt64.OptionalHeader.SizeOfImage = nt64.OptionalHeader.SizeOfHeaders + 0x1000; 1332 nt64.OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI; 1333 nt64.OptionalHeader.SizeOfStackReserve = 0x321000; 1334 nt64.OptionalHeader.SizeOfStackCommit = 0x123000; 1335 section.Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE; 1336 1337 status = map_image_section( (IMAGE_NT_HEADERS *)&nt64, &section, section_data, __LINE__ ); 1338 ok( status == (is_wow64 ? STATUS_INVALID_IMAGE_FORMAT : STATUS_INVALID_IMAGE_WIN_64), 1339 "NtCreateSection error %08lx\n", status ); 1340 1341 switch (orig_machine) 1342 { 1343 case IMAGE_FILE_MACHINE_I386: nt64.FileHeader.Machine = IMAGE_FILE_MACHINE_ARM64; break; 1344 case IMAGE_FILE_MACHINE_ARMNT: nt64.FileHeader.Machine = IMAGE_FILE_MACHINE_AMD64; break; 1345 } 1346 status = map_image_section( (IMAGE_NT_HEADERS *)&nt64, &section, section_data, __LINE__ ); 1347 ok( status == (is_wow64 ? STATUS_INVALID_IMAGE_FORMAT : STATUS_INVALID_IMAGE_WIN_64), 1348 "NtCreateSection error %08lx\n", status ); 1349 1350 nt64.FileHeader.Machine = get_alt_bitness_machine( orig_machine ); 1351 status = map_image_section( (IMAGE_NT_HEADERS *)&nt64, &section, section_data, __LINE__ ); 1352 ok( status == (is_wow64 ? STATUS_SUCCESS : STATUS_INVALID_IMAGE_WIN_64), 1353 "NtCreateSection error %08lx\n", status ); 1354 1355 nt64.OptionalHeader.SizeOfCode = 0; 1356 nt64.OptionalHeader.AddressOfEntryPoint = 0x1000; 1357 section.Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE; 1358 status = map_image_section( (IMAGE_NT_HEADERS *)&nt64, &section, section_data, __LINE__ ); 1359 ok( status == (is_wow64 ? STATUS_SUCCESS : STATUS_INVALID_IMAGE_WIN_64), 1360 "NtCreateSection error %08lx\n", status ); 1361 1362 nt64.OptionalHeader.SizeOfCode = 0; 1363 nt64.OptionalHeader.AddressOfEntryPoint = 0; 1364 section.Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE; 1365 status = map_image_section( (IMAGE_NT_HEADERS *)&nt64, &section, section_data, __LINE__ ); 1366 ok( status == (is_wow64 ? STATUS_SUCCESS : STATUS_INVALID_IMAGE_WIN_64), 1367 "NtCreateSection error %08lx\n", status ); 1368 1369 nt64.OptionalHeader.SizeOfCode = 0x1000; 1370 nt64.OptionalHeader.AddressOfEntryPoint = 0; 1371 nt64.OptionalHeader.DllCharacteristics = IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE; 1372 section.Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE; 1373 status = map_image_section( (IMAGE_NT_HEADERS *)&nt64, &section, section_data, __LINE__ ); 1374 ok( status == (is_wow64 ? STATUS_SUCCESS : STATUS_INVALID_IMAGE_WIN_64), 1375 "NtCreateSection error %08lx\n", status ); 1376 1377 nt64.OptionalHeader.SizeOfCode = 0; 1378 nt64.OptionalHeader.AddressOfEntryPoint = 0; 1379 section.Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE; 1380 status = map_image_section( (IMAGE_NT_HEADERS *)&nt64, &section, section_data, __LINE__ ); 1381 ok( status == (is_wow64 ? STATUS_SUCCESS : STATUS_INVALID_IMAGE_WIN_64), 1382 "NtCreateSection error %08lx\n", status ); 1383 1384 nt64.OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES; 1385 nt64.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress = page_size; 1386 nt64.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size = sizeof(cor_header); 1387 cor_header.MajorRuntimeVersion = 2; 1388 cor_header.MinorRuntimeVersion = 4; 1389 cor_header.Flags = COMIMAGE_FLAGS_ILONLY; 1390 status = map_image_section( (IMAGE_NT_HEADERS *)&nt64, &section, &cor_header, __LINE__ ); 1391 ok( status == (is_wow64 ? STATUS_SUCCESS : STATUS_INVALID_IMAGE_WIN_64), 1392 "NtCreateSection error %08lx\n", status ); 1393 1394 nt64.OptionalHeader.SizeOfCode = 0x1000; 1395 status = map_image_section( (IMAGE_NT_HEADERS *)&nt64, &section, &cor_header, __LINE__ ); 1396 ok( status == (is_wow64 ? STATUS_SUCCESS : STATUS_INVALID_IMAGE_WIN_64), 1397 "NtCreateSection error %08lx\n", status ); 1398 1399 cor_header.MinorRuntimeVersion = 5; 1400 status = map_image_section( (IMAGE_NT_HEADERS *)&nt64, &section, &cor_header, __LINE__ ); 1401 ok( status == (is_wow64 ? STATUS_SUCCESS : STATUS_INVALID_IMAGE_WIN_64), 1402 "NtCreateSection error %08lx\n", status ); 1403 1404 cor_header.Flags = COMIMAGE_FLAGS_ILONLY | COMIMAGE_FLAGS_32BITREQUIRED; 1405 status = map_image_section( (IMAGE_NT_HEADERS *)&nt64, &section, &cor_header, __LINE__ ); 1406 ok( status == (is_wow64 ? STATUS_SUCCESS : STATUS_INVALID_IMAGE_WIN_64), 1407 "NtCreateSection error %08lx\n", status ); 1408 1409 cor_header.Flags = COMIMAGE_FLAGS_ILONLY | COMIMAGE_FLAGS_32BITPREFERRED; 1410 status = map_image_section( (IMAGE_NT_HEADERS *)&nt64, &section, &cor_header, __LINE__ ); 1411 ok( status == (is_wow64 ? STATUS_SUCCESS : STATUS_INVALID_IMAGE_WIN_64), 1412 "NtCreateSection error %08lx\n", status ); 1413 1414 cor_header.Flags = 0; 1415 status = map_image_section( (IMAGE_NT_HEADERS *)&nt64, &section, &cor_header, __LINE__ ); 1416 ok( status == (is_wow64 ? STATUS_SUCCESS : STATUS_INVALID_IMAGE_WIN_64), 1417 "NtCreateSection error %08lx\n", status ); 1418 1419 nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress = 1; 1420 nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size = 1; 1421 status = map_image_section( (IMAGE_NT_HEADERS *)&nt64, &section, &cor_header, __LINE__ ); 1422 ok( status == (is_wow64 ? STATUS_SUCCESS : STATUS_INVALID_IMAGE_WIN_64), 1423 "NtCreateSection error %08lx\n", status ); 1424 } 1425#ifdef __REACTOS__ 1426 else if (is_reactos() && orig_machine == IMAGE_FILE_MACHINE_AMD64) 1427 { 1428 ok(FALSE, "FIXME: These tests crash on ReactOS x64!\n"); 1429 } 1430 else 1431#else 1432 else 1433#endif 1434 { 1435 IMAGE_NT_HEADERS32 nt32; 1436 1437 memset( &nt32, 0, sizeof(nt32) ); 1438 nt32.Signature = IMAGE_NT_SIGNATURE; 1439 nt32.FileHeader.Machine = orig_machine; 1440 nt32.FileHeader.NumberOfSections = 1; 1441 nt32.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER32); 1442 nt32.FileHeader.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL; 1443 nt32.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR32_MAGIC; 1444 nt32.OptionalHeader.MajorLinkerVersion = 1; 1445 nt32.OptionalHeader.SizeOfCode = 0x1000; 1446 nt32.OptionalHeader.AddressOfEntryPoint = 0x1000; 1447 nt32.OptionalHeader.ImageBase = 0x10000000; 1448 nt32.OptionalHeader.SectionAlignment = 0x1000; 1449 nt32.OptionalHeader.FileAlignment = 0x1000; 1450 nt32.OptionalHeader.MajorOperatingSystemVersion = 4; 1451 nt32.OptionalHeader.MajorImageVersion = 1; 1452 nt32.OptionalHeader.MajorSubsystemVersion = 4; 1453 nt32.OptionalHeader.SizeOfHeaders = sizeof(dos_header) + sizeof(nt32) + sizeof(IMAGE_SECTION_HEADER); 1454 nt32.OptionalHeader.SizeOfImage = nt32.OptionalHeader.SizeOfHeaders + 0x1000; 1455 nt32.OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI; 1456 nt32.OptionalHeader.SizeOfStackReserve = 0x321000; 1457 nt32.OptionalHeader.SizeOfStackCommit = 0x123000; 1458 section.Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE; 1459 1460 status = map_image_section( (IMAGE_NT_HEADERS *)&nt32, &section, section_data, __LINE__ ); 1461 ok( status == STATUS_INVALID_IMAGE_FORMAT, "NtCreateSection error %08lx\n", status ); 1462 1463 if (orig_machine == IMAGE_FILE_MACHINE_AMD64) 1464 { 1465 nt32.FileHeader.Machine = IMAGE_FILE_MACHINE_ARMNT; 1466 status = map_image_section( (IMAGE_NT_HEADERS *)&nt32, &section, section_data, __LINE__ ); 1467 ok( status == STATUS_INVALID_IMAGE_FORMAT || broken(!status) /* win8 */, 1468 "NtCreateSection error %08lx\n", status ); 1469 } 1470 1471 nt32.FileHeader.Machine = IMAGE_FILE_MACHINE_I386; 1472 status = map_image_section( (IMAGE_NT_HEADERS *)&nt32, &section, section_data, __LINE__ ); 1473 ok( status == STATUS_SUCCESS, "NtCreateSection error %08lx\n", status ); 1474 1475 nt32.OptionalHeader.SizeOfCode = 0; 1476 nt32.OptionalHeader.AddressOfEntryPoint = 0x1000; 1477 section.Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE; 1478 status = map_image_section( (IMAGE_NT_HEADERS *)&nt32, &section, section_data, __LINE__ ); 1479 ok( status == STATUS_SUCCESS, "NtCreateSection error %08lx\n", status ); 1480 1481 nt32.OptionalHeader.SizeOfCode = 0; 1482 nt32.OptionalHeader.AddressOfEntryPoint = 0; 1483 section.Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE; 1484 status = map_image_section( (IMAGE_NT_HEADERS *)&nt32, &section, section_data, __LINE__ ); 1485 ok( status == STATUS_SUCCESS, "NtCreateSection error %08lx\n", status ); 1486 1487 nt32.OptionalHeader.SizeOfCode = 0x1000; 1488 nt32.OptionalHeader.AddressOfEntryPoint = 0; 1489 nt32.OptionalHeader.DllCharacteristics = IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE; 1490 section.Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE; 1491 status = map_image_section( (IMAGE_NT_HEADERS *)&nt32, &section, section_data, __LINE__ ); 1492 ok( status == STATUS_SUCCESS, "NtCreateSection error %08lx\n", status ); 1493 1494 nt32.OptionalHeader.SizeOfCode = 0; 1495 nt32.OptionalHeader.AddressOfEntryPoint = 0; 1496 section.Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE; 1497 status = map_image_section( (IMAGE_NT_HEADERS *)&nt32, &section, section_data, __LINE__ ); 1498 ok( status == STATUS_SUCCESS, "NtCreateSection error %08lx\n", status ); 1499 1500 nt32.OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES; 1501 nt32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress = page_size; 1502 nt32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size = sizeof(cor_header); 1503 cor_header.MajorRuntimeVersion = 2; 1504 cor_header.MinorRuntimeVersion = 4; 1505 cor_header.Flags = COMIMAGE_FLAGS_ILONLY; 1506 status = map_image_section( (IMAGE_NT_HEADERS *)&nt32, &section, &cor_header, __LINE__ ); 1507 ok( status == STATUS_SUCCESS, "NtCreateSection error %08lx\n", status ); 1508 1509 nt32.OptionalHeader.SizeOfCode = 0x1000; 1510 status = map_image_section( (IMAGE_NT_HEADERS *)&nt32, &section, &cor_header, __LINE__ ); 1511 ok( status == STATUS_SUCCESS, "NtCreateSection error %08lx\n", status ); 1512 1513 cor_header.MinorRuntimeVersion = 5; 1514 status = map_image_section( (IMAGE_NT_HEADERS *)&nt32, &section, &cor_header, __LINE__ ); 1515 ok( status == STATUS_SUCCESS, "NtCreateSection error %08lx\n", status ); 1516 1517 cor_header.Flags = COMIMAGE_FLAGS_ILONLY | COMIMAGE_FLAGS_32BITREQUIRED; 1518 status = map_image_section( (IMAGE_NT_HEADERS *)&nt32, &section, &cor_header, __LINE__ ); 1519 ok( status == STATUS_SUCCESS, "NtCreateSection error %08lx\n", status ); 1520 1521 cor_header.Flags = COMIMAGE_FLAGS_ILONLY | COMIMAGE_FLAGS_32BITPREFERRED; 1522 status = map_image_section( (IMAGE_NT_HEADERS *)&nt32, &section, &cor_header, __LINE__ ); 1523 ok( status == STATUS_SUCCESS, "NtCreateSection error %08lx\n", status ); 1524 1525 cor_header.Flags = 0; 1526 status = map_image_section( (IMAGE_NT_HEADERS *)&nt32, &section, &cor_header, __LINE__ ); 1527 ok( status == STATUS_SUCCESS, "NtCreateSection error %08lx\n", status ); 1528 1529 nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress = 1; 1530 nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size = 1; 1531 status = map_image_section( (IMAGE_NT_HEADERS *)&nt32, &section, &cor_header, __LINE__ ); 1532 ok( status == STATUS_SUCCESS, "NtCreateSection error %08lx\n", status ); 1533 } 1534 1535 section.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ; 1536 delete_load_path(); 1537} 1538 1539static void test_filenames(void) 1540{ 1541 IMAGE_NT_HEADERS nt_header = nt_header_template; 1542 char dll_name[MAX_PATH], long_path[MAX_PATH], short_path[MAX_PATH], buffer[MAX_PATH]; 1543 HMODULE mod, mod2; 1544 BOOL ret; 1545 1546 nt_header.FileHeader.NumberOfSections = 1; 1547 nt_header.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER); 1548 1549 nt_header.OptionalHeader.SectionAlignment = page_size; 1550 nt_header.OptionalHeader.DllCharacteristics = IMAGE_DLLCHARACTERISTICS_NX_COMPAT | IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE; 1551 nt_header.OptionalHeader.FileAlignment = page_size; 1552 nt_header.OptionalHeader.SizeOfHeaders = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER); 1553 nt_header.OptionalHeader.SizeOfImage = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + page_size; 1554 1555 create_test_dll( &dos_header, sizeof(dos_header), &nt_header, dll_name ); 1556 strcpy( long_path, dll_name ); 1557 strcpy( strrchr( long_path, '\\' ), "\\this-is-a-long-name.dll" ); 1558 ret = MoveFileA( dll_name, long_path ); 1559 ok( ret, "MoveFileA failed err %lu\n", GetLastError() ); 1560 GetShortPathNameA( long_path, short_path, MAX_PATH ); 1561 1562 mod = LoadLibraryA( short_path ); 1563 ok( mod != NULL, "loading failed err %lu\n", GetLastError() ); 1564 GetModuleFileNameA( mod, buffer, MAX_PATH ); 1565 ok( !lstrcmpiA( buffer, short_path ), "got wrong path %s / %s\n", buffer, short_path ); 1566 mod2 = GetModuleHandleA( short_path ); 1567 ok( mod == mod2, "wrong module %p for %s\n", mod2, short_path ); 1568 mod2 = GetModuleHandleA( long_path ); 1569 ok( mod == mod2, "wrong module %p for %s\n", mod2, long_path ); 1570 mod2 = LoadLibraryA( long_path ); 1571 ok( mod2 != NULL, "loading failed err %lu\n", GetLastError() ); 1572 ok( mod == mod2, "library loaded twice\n" ); 1573 GetModuleFileNameA( mod2, buffer, MAX_PATH ); 1574 ok( !lstrcmpiA( buffer, short_path ), "got wrong path %s / %s\n", buffer, short_path ); 1575 FreeLibrary( mod2 ); 1576 FreeLibrary( mod ); 1577 1578 mod = LoadLibraryA( long_path ); 1579 ok( mod != NULL, "loading failed err %lu\n", GetLastError() ); 1580 GetModuleFileNameA( mod, buffer, MAX_PATH ); 1581 ok( !lstrcmpiA( buffer, long_path ), "got wrong path %s / %s\n", buffer, long_path ); 1582 mod2 = GetModuleHandleA( short_path ); 1583 ok( mod == mod2, "wrong module %p for %s\n", mod2, short_path ); 1584 mod2 = GetModuleHandleA( long_path ); 1585 ok( mod == mod2, "wrong module %p for %s\n", mod2, long_path ); 1586 mod2 = LoadLibraryA( short_path ); 1587 ok( mod2 != NULL, "loading failed err %lu\n", GetLastError() ); 1588 ok( mod == mod2, "library loaded twice\n" ); 1589 GetModuleFileNameA( mod2, buffer, MAX_PATH ); 1590 ok( !lstrcmpiA( buffer, long_path ), "got wrong path %s / %s\n", buffer, long_path ); 1591 FreeLibrary( mod2 ); 1592 FreeLibrary( mod ); 1593 1594 strcpy( dll_name, long_path ); 1595 strcpy( strrchr( dll_name, '\\' ), "\\this-is-another-name.dll" ); 1596 ret = CreateHardLinkA( dll_name, long_path, NULL ); 1597 ok( ret, "CreateHardLinkA failed err %lu\n", GetLastError() ); 1598 if (ret) 1599 { 1600 mod = LoadLibraryA( dll_name ); 1601 ok( mod != NULL, "loading failed err %lu\n", GetLastError() ); 1602 GetModuleFileNameA( mod, buffer, MAX_PATH ); 1603 ok( !lstrcmpiA( buffer, dll_name ), "got wrong path %s / %s\n", buffer, dll_name ); 1604 mod2 = GetModuleHandleA( long_path ); 1605 ok( mod == mod2, "wrong module %p for %s\n", mod2, long_path ); 1606 mod2 = LoadLibraryA( long_path ); 1607 ok( mod2 != NULL, "loading failed err %lu\n", GetLastError() ); 1608 ok( mod == mod2, "library loaded twice\n" ); 1609 GetModuleFileNameA( mod2, buffer, MAX_PATH ); 1610 ok( !lstrcmpiA( buffer, dll_name ), "got wrong path %s / %s\n", buffer, short_path ); 1611 FreeLibrary( mod2 ); 1612 FreeLibrary( mod ); 1613 DeleteFileA( dll_name ); 1614 } 1615 DeleteFileA( long_path ); 1616} 1617 1618/* Verify linking style of import descriptors */ 1619static void test_ImportDescriptors(void) 1620{ 1621 HMODULE kernel32_module = NULL; 1622 PIMAGE_DOS_HEADER d_header; 1623 PIMAGE_NT_HEADERS nt_headers; 1624 DWORD import_dir_size; 1625 DWORD_PTR dir_offset; 1626 PIMAGE_IMPORT_DESCRIPTOR import_chunk; 1627 1628 /* Load kernel32 module */ 1629 kernel32_module = GetModuleHandleA("kernel32.dll"); 1630 assert( kernel32_module != NULL ); 1631 1632 /* Get PE header info from module image */ 1633 d_header = (PIMAGE_DOS_HEADER) kernel32_module; 1634 nt_headers = (PIMAGE_NT_HEADERS) (((char*) d_header) + 1635 d_header->e_lfanew); 1636 1637 /* Get size of import entry directory */ 1638 import_dir_size = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size; 1639 if (!import_dir_size) 1640 { 1641 skip("Unable to continue testing due to missing import directory.\n"); 1642 return; 1643 } 1644 1645 /* Get address of first import chunk */ 1646 dir_offset = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; 1647 import_chunk = RVAToAddr(dir_offset, kernel32_module); 1648 ok(import_chunk != 0, "Invalid import_chunk: %p\n", import_chunk); 1649 if (!import_chunk) return; 1650 1651 /* Iterate through import descriptors and verify set name, 1652 * OriginalFirstThunk, and FirstThunk. Core Windows DLLs, such as 1653 * kernel32.dll, don't use Borland-style linking, where the table of 1654 * imported names is stored directly in FirstThunk and overwritten 1655 * by the relocation, instead of being stored in OriginalFirstThunk. 1656 * */ 1657 for (; import_chunk->FirstThunk; import_chunk++) 1658 { 1659 LPCSTR module_name = RVAToAddr(import_chunk->Name, kernel32_module); 1660 PIMAGE_THUNK_DATA name_table = RVAToAddr( 1661 import_chunk->OriginalFirstThunk, kernel32_module); 1662 PIMAGE_THUNK_DATA iat = RVAToAddr( 1663 import_chunk->FirstThunk, kernel32_module); 1664 ok(module_name != NULL, "Imported module name should not be NULL\n"); 1665 ok(name_table != NULL, 1666 "Name table for imported module %s should not be NULL\n", 1667 module_name); 1668 ok(iat != NULL, "IAT for imported module %s should not be NULL\n", 1669 module_name); 1670 } 1671} 1672 1673static void test_image_mapping(const char *dll_name, DWORD scn_page_access, BOOL is_dll) 1674{ 1675 HANDLE hfile, hmap; 1676 NTSTATUS status; 1677 LARGE_INTEGER offset; 1678 SIZE_T size; 1679 void *addr1, *addr2; 1680 MEMORY_BASIC_INFORMATION info; 1681 1682 if (!pNtMapViewOfSection) return; 1683 1684 SetLastError(0xdeadbeef); 1685 hfile = CreateFileA(dll_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); 1686 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile error %ld\n", GetLastError()); 1687 1688 SetLastError(0xdeadbeef); 1689 hmap = CreateFileMappingW(hfile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, 0); 1690 ok(hmap != 0, "CreateFileMapping error %ld\n", GetLastError()); 1691 1692 offset.u.LowPart = 0; 1693 offset.u.HighPart = 0; 1694 1695 addr1 = NULL; 1696 size = 0; 1697 status = pNtMapViewOfSection(hmap, GetCurrentProcess(), &addr1, 0, 0, &offset, 1698 &size, 1 /* ViewShare */, 0, PAGE_READONLY); 1699 ok(NT_SUCCESS(status), "NtMapViewOfSection error %lx\n", status); 1700 ok(addr1 != 0, "mapped address should be valid\n"); 1701 1702 SetLastError(0xdeadbeef); 1703 size = VirtualQuery((char *)addr1 + section.VirtualAddress, &info, sizeof(info)); 1704 ok(size == sizeof(info), "VirtualQuery error %ld\n", GetLastError()); 1705 ok(info.BaseAddress == (char *)addr1 + section.VirtualAddress, "got %p != expected %p\n", info.BaseAddress, (char *)addr1 + section.VirtualAddress); 1706 ok(info.RegionSize == page_size, "got %#Ix != expected %#lx\n", info.RegionSize, page_size); 1707 ok(info.Protect == scn_page_access, "got %#lx != expected %#lx\n", info.Protect, scn_page_access); 1708 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1); 1709 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%#lx != PAGE_EXECUTE_WRITECOPY\n", info.AllocationProtect); 1710 ok(info.State == MEM_COMMIT, "%#lx != MEM_COMMIT\n", info.State); 1711 ok(info.Type == SEC_IMAGE, "%#lx != SEC_IMAGE\n", info.Type); 1712 1713 addr2 = NULL; 1714 size = 0; 1715 status = pNtMapViewOfSection(hmap, GetCurrentProcess(), &addr2, 0, 0, &offset, 1716 &size, 1 /* ViewShare */, 0, PAGE_READONLY); 1717 ok(status == STATUS_IMAGE_NOT_AT_BASE, "expected STATUS_IMAGE_NOT_AT_BASE, got %lx\n", status); 1718 ok(addr2 != 0, "mapped address should be valid\n"); 1719 ok(addr2 != addr1, "mapped addresses should be different\n"); 1720 1721 SetLastError(0xdeadbeef); 1722 size = VirtualQuery((char *)addr2 + section.VirtualAddress, &info, sizeof(info)); 1723 ok(size == sizeof(info), "VirtualQuery error %ld\n", GetLastError()); 1724 ok(info.BaseAddress == (char *)addr2 + section.VirtualAddress, "got %p != expected %p\n", info.BaseAddress, (char *)addr2 + section.VirtualAddress); 1725 ok(info.RegionSize == page_size, "got %#Ix != expected %#lx\n", info.RegionSize, page_size); 1726 ok(info.Protect == scn_page_access, "got %#lx != expected %#lx\n", info.Protect, scn_page_access); 1727 ok(info.AllocationBase == addr2, "%p != %p\n", info.AllocationBase, addr2); 1728 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%#lx != PAGE_EXECUTE_WRITECOPY\n", info.AllocationProtect); 1729 ok(info.State == MEM_COMMIT, "%#lx != MEM_COMMIT\n", info.State); 1730 ok(info.Type == SEC_IMAGE, "%#lx != SEC_IMAGE\n", info.Type); 1731 1732 status = pNtUnmapViewOfSection(GetCurrentProcess(), addr2); 1733 ok(status == STATUS_SUCCESS, "NtUnmapViewOfSection error %lx\n", status); 1734 1735 addr2 = MapViewOfFile(hmap, 0, 0, 0, 0); 1736 ok(addr2 != 0, "mapped address should be valid\n"); 1737 ok(addr2 != addr1, "mapped addresses should be different\n"); 1738 1739 SetLastError(0xdeadbeef); 1740 size = VirtualQuery((char *)addr2 + section.VirtualAddress, &info, sizeof(info)); 1741 ok(size == sizeof(info), "VirtualQuery error %ld\n", GetLastError()); 1742 ok(info.BaseAddress == (char *)addr2 + section.VirtualAddress, "got %p != expected %p\n", info.BaseAddress, (char *)addr2 + section.VirtualAddress); 1743 ok(info.RegionSize == page_size, "got %#Ix != expected %#lx\n", info.RegionSize, page_size); 1744 ok(info.Protect == scn_page_access, "got %#lx != expected %#lx\n", info.Protect, scn_page_access); 1745 ok(info.AllocationBase == addr2, "%p != %p\n", info.AllocationBase, addr2); 1746 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%#lx != PAGE_EXECUTE_WRITECOPY\n", info.AllocationProtect); 1747 ok(info.State == MEM_COMMIT, "%#lx != MEM_COMMIT\n", info.State); 1748 ok(info.Type == SEC_IMAGE, "%#lx != SEC_IMAGE\n", info.Type); 1749 1750 UnmapViewOfFile(addr2); 1751 1752 SetLastError(0xdeadbeef); 1753 addr2 = LoadLibraryA(dll_name); 1754 if (!addr2) 1755 { 1756 ok(is_dll, "LoadLibrary should fail, is_dll %d\n", is_dll); 1757 ok(GetLastError() == ERROR_INVALID_ADDRESS, "expected ERROR_INVALID_ADDRESS, got %ld\n", GetLastError()); 1758 } 1759 else 1760 { 1761 BOOL ret; 1762 ok(addr2 != 0, "LoadLibrary error %ld, is_dll %d\n", GetLastError(), is_dll); 1763 ok(addr2 != addr1, "mapped addresses should be different\n"); 1764 1765 SetLastError(0xdeadbeef); 1766 ret = FreeLibrary(addr2); 1767 ok(ret, "FreeLibrary error %ld\n", GetLastError()); 1768 } 1769 1770 status = pNtUnmapViewOfSection(GetCurrentProcess(), addr1); 1771 ok(status == STATUS_SUCCESS, "NtUnmapViewOfSection error %lx\n", status); 1772 1773 CloseHandle(hmap); 1774 CloseHandle(hfile); 1775} 1776 1777static BOOL is_mem_writable(DWORD prot) 1778{ 1779 switch (prot & 0xff) 1780 { 1781 case PAGE_READWRITE: 1782 case PAGE_WRITECOPY: 1783 case PAGE_EXECUTE_READWRITE: 1784 case PAGE_EXECUTE_WRITECOPY: 1785 return TRUE; 1786 1787 default: 1788 return FALSE; 1789 } 1790} 1791 1792static void test_VirtualProtect(void *base, void *section) 1793{ 1794 static const struct test_data 1795 { 1796 DWORD prot_set, prot_get; 1797 } td[] = 1798 { 1799 { 0, 0 }, /* 0x00 */ 1800 { PAGE_NOACCESS, PAGE_NOACCESS }, /* 0x01 */ 1801 { PAGE_READONLY, PAGE_READONLY }, /* 0x02 */ 1802 { PAGE_READONLY | PAGE_NOACCESS, 0 }, /* 0x03 */ 1803 { PAGE_READWRITE, PAGE_WRITECOPY }, /* 0x04 */ 1804 { PAGE_READWRITE | PAGE_NOACCESS, 0 }, /* 0x05 */ 1805 { PAGE_READWRITE | PAGE_READONLY, 0 }, /* 0x06 */ 1806 { PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, 0 }, /* 0x07 */ 1807 { PAGE_WRITECOPY, PAGE_WRITECOPY }, /* 0x08 */ 1808 { PAGE_WRITECOPY | PAGE_NOACCESS, 0 }, /* 0x09 */ 1809 { PAGE_WRITECOPY | PAGE_READONLY, 0 }, /* 0x0a */ 1810 { PAGE_WRITECOPY | PAGE_NOACCESS | PAGE_READONLY, 0 }, /* 0x0b */ 1811 { PAGE_WRITECOPY | PAGE_READWRITE, 0 }, /* 0x0c */ 1812 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_NOACCESS, 0 }, /* 0x0d */ 1813 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY, 0 }, /* 0x0e */ 1814 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, 0 }, /* 0x0f */ 1815 1816 { PAGE_EXECUTE, PAGE_EXECUTE }, /* 0x10 */ 1817 { PAGE_EXECUTE_READ, PAGE_EXECUTE_READ }, /* 0x20 */ 1818 { PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 }, /* 0x30 */ 1819 { PAGE_EXECUTE_READWRITE, PAGE_EXECUTE_WRITECOPY }, /* 0x40 */ 1820 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, 0 }, /* 0x50 */ 1821 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, 0 }, /* 0x60 */ 1822 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 }, /* 0x70 */ 1823 { PAGE_EXECUTE_WRITECOPY, PAGE_EXECUTE_WRITECOPY }, /* 0x80 */ 1824 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE, 0 }, /* 0x90 */ 1825 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ, 0 }, /* 0xa0 */ 1826 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 }, /* 0xb0 */ 1827 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE, 0 }, /* 0xc0 */ 1828 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, 0 }, /* 0xd0 */ 1829 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, 0 }, /* 0xe0 */ 1830 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 } /* 0xf0 */ 1831 }; 1832 DWORD ret, orig_prot, old_prot, rw_prot, exec_prot, i, j; 1833 MEMORY_BASIC_INFORMATION info; 1834 1835 SetLastError(0xdeadbeef); 1836 ret = VirtualProtect(section, page_size, PAGE_NOACCESS, &old_prot); 1837 ok(ret, "VirtualProtect error %ld\n", GetLastError()); 1838 1839 orig_prot = old_prot; 1840 1841 for (i = 0; i < ARRAY_SIZE(td); i++) 1842 { 1843 SetLastError(0xdeadbeef); 1844 ret = VirtualQuery(section, &info, sizeof(info)); 1845 ok(ret, "VirtualQuery failed %ld\n", GetLastError()); 1846 ok(info.BaseAddress == section, "%ld: got %p != expected %p\n", i, info.BaseAddress, section); 1847 ok(info.RegionSize == page_size, "%ld: got %#Ix != expected %#lx\n", i, info.RegionSize, page_size); 1848 ok(info.Protect == PAGE_NOACCESS, "%ld: got %#lx != expected PAGE_NOACCESS\n", i, info.Protect); 1849 ok(info.AllocationBase == base, "%ld: %p != %p\n", i, info.AllocationBase, base); 1850 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%ld: %#lx != PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect); 1851 ok(info.State == MEM_COMMIT, "%ld: %#lx != MEM_COMMIT\n", i, info.State); 1852 ok(info.Type == SEC_IMAGE, "%ld: %#lx != SEC_IMAGE\n", i, info.Type); 1853 1854 old_prot = 0xdeadbeef; 1855 SetLastError(0xdeadbeef); 1856 ret = VirtualProtect(section, page_size, td[i].prot_set, &old_prot); 1857 if (td[i].prot_get) 1858 { 1859 ok(ret, "%ld: VirtualProtect error %ld, requested prot %#lx\n", i, GetLastError(), td[i].prot_set); 1860 ok(old_prot == PAGE_NOACCESS, "%ld: got %#lx != expected PAGE_NOACCESS\n", i, old_prot); 1861 1862 SetLastError(0xdeadbeef); 1863 ret = VirtualQuery(section, &info, sizeof(info)); 1864 ok(ret, "VirtualQuery failed %ld\n", GetLastError()); 1865 ok(info.BaseAddress == section, "%ld: got %p != expected %p\n", i, info.BaseAddress, section); 1866 ok(info.RegionSize == page_size, "%ld: got %#Ix != expected %#lx\n", i, info.RegionSize, page_size); 1867 ok(info.Protect == td[i].prot_get, "%ld: got %#lx != expected %#lx\n", i, info.Protect, td[i].prot_get); 1868 ok(info.AllocationBase == base, "%ld: %p != %p\n", i, info.AllocationBase, base); 1869 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%ld: %#lx != PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect); 1870 ok(info.State == MEM_COMMIT, "%ld: %#lx != MEM_COMMIT\n", i, info.State); 1871 ok(info.Type == SEC_IMAGE, "%ld: %#lx != SEC_IMAGE\n", i, info.Type); 1872 } 1873 else 1874 { 1875 ok(!ret, "%ld: VirtualProtect should fail\n", i); 1876 ok(GetLastError() == ERROR_INVALID_PARAMETER, "%ld: expected ERROR_INVALID_PARAMETER, got %ld\n", i, GetLastError()); 1877 } 1878 1879 old_prot = 0xdeadbeef; 1880 SetLastError(0xdeadbeef); 1881 ret = VirtualProtect(section, page_size, PAGE_NOACCESS, &old_prot); 1882 ok(ret, "%ld: VirtualProtect error %ld\n", i, GetLastError()); 1883 if (td[i].prot_get) 1884 ok(old_prot == td[i].prot_get, "%ld: got %#lx != expected %#lx\n", i, old_prot, td[i].prot_get); 1885 else 1886 ok(old_prot == PAGE_NOACCESS, "%ld: got %#lx != expected PAGE_NOACCESS\n", i, old_prot); 1887 } 1888 1889 exec_prot = 0; 1890 1891 for (i = 0; i <= 4; i++) 1892 { 1893 rw_prot = 0; 1894 1895 for (j = 0; j <= 4; j++) 1896 { 1897 DWORD prot = exec_prot | rw_prot; 1898 1899 SetLastError(0xdeadbeef); 1900 ret = VirtualProtect(section, page_size, prot, &old_prot); 1901 if ((rw_prot && exec_prot) || (!rw_prot && !exec_prot)) 1902 { 1903 ok(!ret, "VirtualProtect(%02lx) should fail\n", prot); 1904 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError()); 1905 } 1906 else 1907 ok(ret, "VirtualProtect(%02lx) error %ld\n", prot, GetLastError()); 1908 1909 rw_prot = 1 << j; 1910 } 1911 1912 exec_prot = 1 << (i + 4); 1913 } 1914 1915 SetLastError(0xdeadbeef); 1916 ret = VirtualProtect(section, page_size, orig_prot, &old_prot); 1917 ok(ret, "VirtualProtect error %ld\n", GetLastError()); 1918} 1919 1920static void test_section_access(void) 1921{ 1922 static const struct test_data 1923 { 1924 DWORD scn_file_access, scn_page_access, scn_page_access_after_write; 1925 } td[] = 1926 { 1927 { 0, PAGE_NOACCESS, 0 }, 1928 { IMAGE_SCN_MEM_READ, PAGE_READONLY, 0 }, 1929 { IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY, PAGE_READWRITE }, 1930 { IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE, 0 }, 1931 { IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY, PAGE_READWRITE }, 1932 { IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_READ }, 1933 { IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY, PAGE_EXECUTE_READWRITE }, 1934 { IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY, PAGE_EXECUTE_READWRITE }, 1935 1936 { IMAGE_SCN_CNT_INITIALIZED_DATA, PAGE_NOACCESS, 0 }, 1937 { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ, PAGE_READONLY, 0 }, 1938 { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY, PAGE_READWRITE }, 1939 { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE, 0 }, 1940 { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY, PAGE_READWRITE }, 1941 { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_READ, 0 }, 1942 { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY, PAGE_EXECUTE_READWRITE }, 1943 { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY, PAGE_EXECUTE_READWRITE }, 1944 1945 { IMAGE_SCN_CNT_UNINITIALIZED_DATA, PAGE_NOACCESS, 0 }, 1946 { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ, PAGE_READONLY, 0 }, 1947 { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY, PAGE_READWRITE }, 1948 { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE, 0 }, 1949 { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY, PAGE_READWRITE }, 1950 { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_READ, 0 }, 1951 { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY, PAGE_EXECUTE_READWRITE }, 1952 { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY, PAGE_EXECUTE_READWRITE } 1953 }; 1954 char buf[256]; 1955 int i; 1956 DWORD dummy; 1957 HANDLE hfile; 1958 HMODULE hlib; 1959 char temp_path[MAX_PATH]; 1960 char dll_name[MAX_PATH]; 1961 SIZE_T size; 1962 PEB child_peb; 1963 PROCESS_BASIC_INFORMATION pbi; 1964 SECTION_IMAGE_INFORMATION image_info; 1965 MEMORY_BASIC_INFORMATION info; 1966 STARTUPINFOA sti; 1967 PROCESS_INFORMATION pi; 1968 NTSTATUS status; 1969 DWORD ret; 1970 1971 /* prevent displaying of the "Unable to load this DLL" message box */ 1972 SetErrorMode(SEM_FAILCRITICALERRORS); 1973 1974 GetTempPathA(MAX_PATH, temp_path); 1975 1976 for (i = 0; i < ARRAY_SIZE(td); i++) 1977 { 1978 IMAGE_NT_HEADERS nt_header; 1979 1980 GetTempFileNameA(temp_path, "ldr", 0, dll_name); 1981 1982 /*trace("creating %s\n", dll_name);*/ 1983 hfile = CreateFileA(dll_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); 1984 if (hfile == INVALID_HANDLE_VALUE) 1985 { 1986 ok(0, "could not create %s\n", dll_name); 1987 return; 1988 } 1989 1990 SetLastError(0xdeadbeef); 1991 ret = WriteFile(hfile, &dos_header, sizeof(dos_header), &dummy, NULL); 1992 ok(ret, "WriteFile error %ld\n", GetLastError()); 1993 1994 nt_header = nt_header_template; 1995 nt_header.OptionalHeader.SectionAlignment = page_size; 1996 nt_header.OptionalHeader.FileAlignment = 0x200; 1997 nt_header.OptionalHeader.SizeOfImage = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + page_size; 1998 nt_header.OptionalHeader.SizeOfHeaders = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER); 1999 2000 section.SizeOfRawData = sizeof(section_data); 2001 section.PointerToRawData = nt_header.OptionalHeader.FileAlignment; 2002 section.VirtualAddress = nt_header.OptionalHeader.SectionAlignment; 2003 section.Misc.VirtualSize = section.SizeOfRawData; 2004 section.Characteristics = td[i].scn_file_access; 2005 SetLastError(0xdeadbeef); 2006 2007 SetLastError(0xdeadbeef); 2008 ret = WriteFile(hfile, &nt_header, sizeof(nt_header), &dummy, NULL); 2009 ok(ret, "WriteFile error %ld\n", GetLastError()); 2010 2011 ret = WriteFile(hfile, &section, sizeof(section), &dummy, NULL); 2012 ok(ret, "WriteFile error %ld\n", GetLastError()); 2013 2014 /* section data */ 2015 SetFilePointer( hfile, nt_header.OptionalHeader.FileAlignment, NULL, FILE_BEGIN ); 2016 SetLastError(0xdeadbeef); 2017 ret = WriteFile(hfile, section_data, sizeof(section_data), &dummy, NULL); 2018 ok(ret, "WriteFile error %ld\n", GetLastError()); 2019 2020 CloseHandle(hfile); 2021 SetLastError(0xdeadbeef); 2022 hlib = LoadLibraryExA(dll_name, NULL, DONT_RESOLVE_DLL_REFERENCES); 2023 ok(hlib != 0, "LoadLibrary error %ld\n", GetLastError()); 2024 2025 SetLastError(0xdeadbeef); 2026 size = VirtualQuery((char *)hlib + section.VirtualAddress, &info, sizeof(info)); 2027 ok(size == sizeof(info), 2028 "%d: VirtualQuery error %ld\n", i, GetLastError()); 2029 ok(info.BaseAddress == (char *)hlib + section.VirtualAddress, "%d: got %p != expected %p\n", i, info.BaseAddress, (char *)hlib + section.VirtualAddress); 2030 ok(info.RegionSize == page_size, "%d: got %#Ix != expected %#lx\n", i, info.RegionSize, page_size); 2031 ok(info.Protect == td[i].scn_page_access, "%d: got %#lx != expected %#lx\n", i, info.Protect, td[i].scn_page_access); 2032 ok(info.AllocationBase == hlib, "%d: %p != %p\n", i, info.AllocationBase, hlib); 2033 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%d: %#lx != PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect); 2034 ok(info.State == MEM_COMMIT, "%d: %#lx != MEM_COMMIT\n", i, info.State); 2035 ok(info.Type == SEC_IMAGE, "%d: %#lx != SEC_IMAGE\n", i, info.Type); 2036 if (info.Protect != PAGE_NOACCESS) 2037 ok(!memcmp((const char *)info.BaseAddress, section_data, section.SizeOfRawData), "wrong section data\n"); 2038 2039 test_VirtualProtect(hlib, (char *)hlib + section.VirtualAddress); 2040 2041 /* Windows changes the WRITECOPY to WRITE protection on an image section write (for a changed page only) */ 2042 if (is_mem_writable(info.Protect)) 2043 { 2044 char *p = info.BaseAddress; 2045 *p = 0xfe; 2046 SetLastError(0xdeadbeef); 2047 size = VirtualQuery((char *)hlib + section.VirtualAddress, &info, sizeof(info)); 2048 ok(size == sizeof(info), "%d: VirtualQuery error %ld\n", i, GetLastError()); 2049 /* FIXME: remove the condition below once Wine is fixed */ 2050 todo_wine_if (info.Protect == PAGE_WRITECOPY || info.Protect == PAGE_EXECUTE_WRITECOPY) 2051 ok(info.Protect == td[i].scn_page_access_after_write, "%d: got %#lx != expected %#lx\n", i, info.Protect, td[i].scn_page_access_after_write); 2052 } 2053 2054 SetLastError(0xdeadbeef); 2055 ret = FreeLibrary(hlib); 2056 ok(ret, "FreeLibrary error %ld\n", GetLastError()); 2057 2058 test_image_mapping(dll_name, td[i].scn_page_access, TRUE); 2059 2060 /* reset IMAGE_FILE_DLL otherwise CreateProcess fails */ 2061 nt_header.FileHeader.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE; 2062 SetLastError(0xdeadbeef); 2063 hfile = CreateFileA(dll_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0); 2064 /* LoadLibrary called on an already memory-mapped file in 2065 * test_image_mapping() above leads to a file handle leak 2066 * under nt4, and inability to overwrite and delete the file 2067 * due to sharing violation error. Ignore it and skip the test, 2068 * but leave a not deletable temporary file. 2069 */ 2070 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile error %ld\n", GetLastError()); 2071 SetFilePointer(hfile, sizeof(dos_header), NULL, FILE_BEGIN); 2072 SetLastError(0xdeadbeef); 2073 ret = WriteFile(hfile, &nt_header, sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER), &dummy, NULL); 2074 ok(ret, "WriteFile error %ld\n", GetLastError()); 2075 CloseHandle(hfile); 2076 2077 memset(&sti, 0, sizeof(sti)); 2078 sti.cb = sizeof(sti); 2079 SetLastError(0xdeadbeef); 2080 ret = CreateProcessA(dll_name, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &sti, &pi); 2081 ok(ret, "CreateProcess() error %ld\n", GetLastError()); 2082 2083 status = pNtQueryInformationProcess( pi.hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), NULL ); 2084 ok( !status, "ProcessBasicInformation got %lx\n", status ); 2085 ret = ReadProcessMemory( pi.hProcess, pbi.PebBaseAddress, &child_peb, sizeof(child_peb), NULL ); 2086 ok( ret, "ReadProcessMemory failed err %lu\n", GetLastError() ); 2087 hlib = child_peb.ImageBaseAddress; 2088 2089 SetLastError(0xdeadbeef); 2090 size = VirtualQueryEx(pi.hProcess, (char *)hlib + section.VirtualAddress, &info, sizeof(info)); 2091 ok(size == sizeof(info), 2092 "%d: VirtualQuery error %ld\n", i, GetLastError()); 2093 ok(info.BaseAddress == (char *)hlib + section.VirtualAddress, "%d: got %p != expected %p\n", i, info.BaseAddress, (char *)hlib + section.VirtualAddress); 2094 ok(info.RegionSize == page_size, "%d: got %#Ix != expected %#lx\n", i, info.RegionSize, page_size); 2095 ok(info.Protect == td[i].scn_page_access, "%d: got %#lx != expected %#lx\n", i, info.Protect, td[i].scn_page_access); 2096 ok(info.AllocationBase == hlib, "%d: %p != %p\n", i, info.AllocationBase, hlib); 2097 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%d: %#lx != PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect); 2098 ok(info.State == MEM_COMMIT, "%d: %#lx != MEM_COMMIT\n", i, info.State); 2099 ok(info.Type == SEC_IMAGE, "%d: %#lx != SEC_IMAGE\n", i, info.Type); 2100 if (info.Protect != PAGE_NOACCESS) 2101 { 2102 SetLastError(0xdeadbeef); 2103 ret = ReadProcessMemory(pi.hProcess, info.BaseAddress, buf, section.SizeOfRawData, NULL); 2104 ok(ret, "ReadProcessMemory() error %ld\n", GetLastError()); 2105 ok(!memcmp(buf, section_data, section.SizeOfRawData), "wrong section data\n"); 2106 } 2107 2108#ifdef __REACTOS__ 2109 if (GetNTVersion() >= _WIN32_WINNT_VISTA) { // Crashes on WS03 2110#endif 2111 status = NtQueryInformationProcess(pi.hProcess, ProcessImageInformation, 2112 &image_info, sizeof(image_info), NULL ); 2113 ok(!status, "Got unexpected status %#lx.\n", status); 2114 ok(!(image_info.ImageCharacteristics & IMAGE_FILE_DLL), 2115 "Got unexpected characteristics %#x.\n", nt_header.FileHeader.Characteristics); 2116 status = NtUnmapViewOfSection(pi.hProcess, info.BaseAddress); 2117 ok(!status, "Got unexpected status %#lx.\n", status); 2118 status = NtQueryInformationProcess(pi.hProcess, ProcessImageInformation, 2119 &image_info, sizeof(image_info), NULL ); 2120 ok(!status, "Got unexpected status %#lx.\n", status); 2121 ok(!(image_info.ImageCharacteristics & IMAGE_FILE_DLL), 2122 "Got unexpected characteristics %#x.\n", nt_header.FileHeader.Characteristics); 2123#ifdef __REACTOS__ 2124 } 2125#endif 2126 2127 SetLastError(0xdeadbeef); 2128 ret = TerminateProcess(pi.hProcess, 0); 2129 ok(ret, "TerminateProcess() error %ld\n", GetLastError()); 2130 ret = WaitForSingleObject(pi.hProcess, 3000); 2131 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed: %lx\n", ret); 2132 2133 CloseHandle(pi.hThread); 2134 CloseHandle(pi.hProcess); 2135 2136 test_image_mapping(dll_name, td[i].scn_page_access, FALSE); 2137 2138 DeleteFileA(dll_name); 2139 } 2140} 2141 2142static void check_tls_index(HANDLE dll, BOOL tls_initialized) 2143{ 2144 BOOL found_dll = FALSE; 2145 LIST_ENTRY *root = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList; 2146 for (LIST_ENTRY *entry = root->Flink; entry != root; entry = entry->Flink) 2147 { 2148 LDR_DATA_TABLE_ENTRY *mod = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); 2149 if (wcsicmp(L"ntdll.dll", mod->BaseDllName.Buffer) == 0) 2150 { 2151 /* Pick ntdll as a dll that definitely won't have TLS */ 2152 ok(mod->TlsIndex == 0, "ntdll.dll TlsIndex: %d instead of 0\n", mod->TlsIndex); 2153 } 2154 else if (mod->DllBase == dll) 2155 { 2156 SHORT expected = tls_initialized ? -1 : 0; 2157 ok(mod->TlsIndex == expected, "Test exe TlsIndex: %d instead of %d\n", mod->TlsIndex, expected); 2158 found_dll = TRUE; 2159 } 2160 else 2161 { 2162 ok(mod->TlsIndex == 0 || mod->TlsIndex == -1, "%s TlsIndex: %d\n", 2163 debugstr_w(mod->BaseDllName.Buffer), mod->TlsIndex); 2164 } 2165 } 2166 ok(found_dll, "Couldn't find dll %p in module list\n", dll); 2167} 2168 2169static int tls_init_fn_output; 2170 2171static DWORD WINAPI tls_thread_fn(void* tlsidx_v) 2172{ 2173 int tls_index = (int)(DWORD_PTR)(tlsidx_v); 2174 const char* str = ((char **)NtCurrentTeb()->ThreadLocalStoragePointer)[tls_index]; 2175 ok( !strcmp( str, "hello world" ), "wrong tls data '%s' at %p\n", str, str ); 2176 ok( tls_init_fn_output == DLL_THREAD_ATTACH, 2177 "tls init function didn't run or got wrong reason: %d instead of %d\n", tls_init_fn_output, DLL_THREAD_ATTACH ); 2178 tls_init_fn_output = 9999; 2179 return 0; 2180} 2181 2182static void test_import_resolution(void) 2183{ 2184 char temp_path[MAX_PATH]; 2185 char dll_name[MAX_PATH]; 2186 DWORD dummy; 2187 void *expect, *tmp; 2188 char *str; 2189 SIZE_T size; 2190 HANDLE hfile, mapping; 2191 HMODULE mod, mod2; 2192 NTSTATUS status; 2193 LARGE_INTEGER offset; 2194 struct imports 2195 { 2196 IMAGE_IMPORT_DESCRIPTOR descr[2]; 2197 IMAGE_THUNK_DATA original_thunks[2]; 2198 IMAGE_THUNK_DATA thunks[2]; 2199 char module[16]; 2200 struct { WORD hint; char name[32]; } function; 2201 IMAGE_TLS_DIRECTORY tls; 2202 UINT_PTR tls_init_fn_list[2]; 2203 char tls_data[16]; 2204 SHORT tls_index; 2205 SHORT tls_index_hi; 2206 int* tls_init_fn_output; 2207 UCHAR tls_init_fn[64]; /* Note: Uses rip-relative address of tls_init_fn_output, don't separate */ 2208 UCHAR entry_point_fn[16]; 2209 struct 2210 { 2211 IMAGE_BASE_RELOCATION reloc; 2212 USHORT type_off[32]; 2213 } rel; 2214 } data, *ptr; 2215 IMAGE_NT_HEADERS nt, *pnt; 2216 IMAGE_SECTION_HEADER section; 2217 SECTION_IMAGE_INFORMATION image; 2218 int test, tls_index_save, nb_rel; 2219#if defined(__i386__) 2220 static const UCHAR tls_init_code[] = { 2221 0xE8, 0x00, 0x00, 0x00, 0x00, /* call 1f */ 2222 0x59, /* 1: pop ecx */ 2223 0x8B, 0x49, 0xF7, /* mov ecx, [ecx - 9] ; mov ecx, [tls_init_fn_output] */ 2224 0x8B, 0x54, 0x24, 0x08, /* mov edx, [esp + 8] */ 2225 0x89, 0x11, /* mov [ecx], edx */ 2226 0xB8, 0x01, 0x00, 0x00, 0x00, /* mov eax, 1 */ 2227 0xC2, 0x0C, 0x00, /* ret 12 */ 2228 }; 2229 static const UCHAR entry_point_code[] = { 2230 0xB8, 0x01, 0x00, 0x00, 0x00, /* mov eax, 1 */ 2231 0xC2, 0x0C, 0x00, /* ret 12 */ 2232 }; 2233#elif defined(__x86_64__) 2234 static const UCHAR tls_init_code[] = { 2235 0x48, 0x8B, 0x0D, 0xF1, 0xFF, 0xFF, 0xFF, /* mov rcx, [rip + tls_init_fn_output] */ 2236 0x89, 0x11, /* mov [rcx], edx */ 2237 0xB8, 0x01, 0x00, 0x00, 0x00, /* mov eax, 1 */ 2238 0xC3, /* ret */ 2239 }; 2240 static const UCHAR entry_point_code[] = { 2241 0xB8, 0x01, 0x00, 0x00, 0x00, /* mov eax, 1 */ 2242 0xC3, /* ret */ 2243 }; 2244#else 2245 static const UCHAR tls_init_code[] = { 0x00 }; 2246 static const UCHAR entry_point_code[] = { 0x00 }; 2247#endif 2248 2249 for (test = 0; test < 7; test++) 2250 { 2251#define DATA_RVA(ptr) (page_size + ((char *)(ptr) - (char *)&data)) 2252#ifdef _WIN64 2253#define ADD_RELOC(field) data.rel.type_off[nb_rel++] = (IMAGE_REL_BASED_DIR64 << 12) + offsetof( struct imports, field ) 2254#else 2255#define ADD_RELOC(field) data.rel.type_off[nb_rel++] = (IMAGE_REL_BASED_HIGHLOW << 12) + offsetof( struct imports, field ) 2256#endif 2257 winetest_push_context( "%u", test ); 2258 nt = nt_header_template; 2259 nt.FileHeader.NumberOfSections = 1; 2260 nt.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER); 2261 nt.FileHeader.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE; 2262 if (test != 2 && test != 5) nt.FileHeader.Characteristics |= IMAGE_FILE_DLL; 2263 nt.OptionalHeader.SectionAlignment = page_size; 2264 nt.OptionalHeader.FileAlignment = 0x200; 2265 nt.OptionalHeader.SizeOfImage = 2 * page_size; 2266 nt.OptionalHeader.SizeOfHeaders = nt.OptionalHeader.FileAlignment; 2267 nt.OptionalHeader.DllCharacteristics = IMAGE_DLLCHARACTERISTICS_NX_COMPAT; 2268 if (test < 6) nt.OptionalHeader.DllCharacteristics |= IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE; 2269 nt.OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES; 2270 memset( nt.OptionalHeader.DataDirectory, 0, sizeof(nt.OptionalHeader.DataDirectory) ); 2271 nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = sizeof(data.descr); 2272 nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = DATA_RVA(data.descr); 2273 nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size = sizeof(data.tls); 2274 nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress = DATA_RVA(&data.tls); 2275 2276 memset( &data, 0, sizeof(data) ); 2277 data.descr[0].OriginalFirstThunk = DATA_RVA( data.original_thunks ); 2278 data.descr[0].FirstThunk = DATA_RVA( data.thunks ); 2279 data.descr[0].Name = DATA_RVA( data.module ); 2280 strcpy( data.module, "kernel32.dll" ); 2281 strcpy( data.function.name, "CreateEventA" ); 2282 data.original_thunks[0].u1.AddressOfData = DATA_RVA( &data.function ); 2283 data.thunks[0].u1.AddressOfData = 0xdeadbeef; 2284 nb_rel = 0; 2285 2286 data.tls.StartAddressOfRawData = nt.OptionalHeader.ImageBase + DATA_RVA( data.tls_data ); 2287 ADD_RELOC( tls.StartAddressOfRawData ); 2288 data.tls.EndAddressOfRawData = data.tls.StartAddressOfRawData + sizeof(data.tls_data); 2289 ADD_RELOC( tls.EndAddressOfRawData ); 2290 data.tls.AddressOfIndex = nt.OptionalHeader.ImageBase + DATA_RVA( &data.tls_index ); 2291 ADD_RELOC( tls.AddressOfIndex ); 2292 strcpy( data.tls_data, "hello world" ); 2293 data.tls_index = 9999; 2294 data.tls_index_hi = 9999; 2295 2296 if (test == 3 && sizeof(tls_init_code) > 1) 2297 { 2298 /* Windows doesn't consistently call tls init functions on dlls without entry points */ 2299 assert(sizeof(tls_init_code) <= sizeof(data.tls_init_fn)); 2300 assert(sizeof(entry_point_code) <= sizeof(data.entry_point_fn)); 2301 memcpy(data.tls_init_fn, tls_init_code, sizeof(tls_init_code)); 2302 memcpy(data.entry_point_fn, entry_point_code, sizeof(entry_point_code)); 2303 tls_init_fn_output = 9999; 2304 data.tls_init_fn_output = &tls_init_fn_output; 2305 data.tls_init_fn_list[0] = nt.OptionalHeader.ImageBase + DATA_RVA(&data.tls_init_fn); 2306 ADD_RELOC( tls_init_fn_list[0] ); 2307 data.tls.AddressOfCallBacks = nt.OptionalHeader.ImageBase + DATA_RVA(&data.tls_init_fn_list); 2308 ADD_RELOC( tls.AddressOfCallBacks ); 2309 nt.OptionalHeader.AddressOfEntryPoint = DATA_RVA(&data.entry_point_fn); 2310 } 2311 2312 if (nb_rel % 2) nb_rel++; 2313 data.rel.reloc.VirtualAddress = nt.OptionalHeader.SectionAlignment; 2314 data.rel.reloc.SizeOfBlock = (char *)&data.rel.type_off[nb_rel] - (char *)&data.rel.reloc; 2315 nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = data.rel.reloc.SizeOfBlock; 2316 nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = DATA_RVA(&data.rel); 2317 2318 GetTempPathA(MAX_PATH, temp_path); 2319 GetTempFileNameA(temp_path, "ldr", 0, dll_name); 2320 2321 hfile = CreateFileA(dll_name, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, 0); 2322 ok( hfile != INVALID_HANDLE_VALUE, "creation failed\n" ); 2323 2324 memset( &section, 0, sizeof(section) ); 2325 memcpy( section.Name, ".text", sizeof(".text") ); 2326 section.PointerToRawData = nt.OptionalHeader.FileAlignment; 2327 section.VirtualAddress = nt.OptionalHeader.SectionAlignment; 2328 section.Misc.VirtualSize = sizeof(data); 2329 section.SizeOfRawData = sizeof(data); 2330 section.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE; 2331 if (test == 3) section.Characteristics |= IMAGE_SCN_MEM_EXECUTE; 2332 2333 WriteFile(hfile, &dos_header, sizeof(dos_header), &dummy, NULL); 2334 WriteFile(hfile, &nt, sizeof(nt), &dummy, NULL); 2335 WriteFile(hfile, &section, sizeof(section), &dummy, NULL); 2336 2337 SetFilePointer( hfile, section.PointerToRawData, NULL, SEEK_SET ); 2338 WriteFile(hfile, &data, sizeof(data), &dummy, NULL); 2339 2340 CloseHandle( hfile ); 2341 2342 switch (test) 2343 { 2344 case 0: /* normal load */ 2345 mod = LoadLibraryA( dll_name ); 2346 ok( mod != NULL, "failed to load err %lu\n", GetLastError() ); 2347 if (!mod) break; 2348 ptr = (struct imports *)((char *)mod + page_size); 2349 expect = GetProcAddress( GetModuleHandleA( data.module ), data.function.name ); 2350 ok( (void *)ptr->thunks[0].u1.Function == expect, "thunk %p instead of %p for %s.%s\n", 2351 (void *)ptr->thunks[0].u1.Function, expect, data.module, data.function.name ); 2352#ifdef __REACTOS__ 2353 ok( ptr->tls_index < 32 || broken(ptr->tls_index == 9999) /* WS03 */, "wrong tls index %d\n", ptr->tls_index ); 2354 if (ptr->tls_index != 9999) { 2355#else 2356 ok( ptr->tls_index < 32, "wrong tls index %d\n", ptr->tls_index ); 2357#endif 2358 str = ((char **)NtCurrentTeb()->ThreadLocalStoragePointer)[ptr->tls_index]; 2359 ok( !strcmp( str, "hello world" ), "wrong tls data '%s' at %p\n", str, str ); 2360 ok(ptr->tls_index_hi == 0, "TLS Index written as a short, high half: %d\n", ptr->tls_index_hi); 2361#ifdef __REACTOS__ 2362 } 2363#endif 2364 check_tls_index(mod, ptr->tls_index != 9999); 2365 FreeLibrary( mod ); 2366 break; 2367 case 1: /* load with DONT_RESOLVE_DLL_REFERENCES doesn't resolve imports */ 2368 mod = LoadLibraryExA( dll_name, 0, DONT_RESOLVE_DLL_REFERENCES ); 2369 ok( mod != NULL, "failed to load err %lu\n", GetLastError() ); 2370 if (!mod) break; 2371 ptr = (struct imports *)((char *)mod + page_size); 2372 ok( ptr->thunks[0].u1.Function == 0xdeadbeef, "thunk resolved to %p for %s.%s\n", 2373 (void *)ptr->thunks[0].u1.Function, data.module, data.function.name ); 2374 ok( ptr->tls_index == 9999, "wrong tls index %d\n", ptr->tls_index ); 2375 2376 mod2 = LoadLibraryA( dll_name ); 2377 ok( mod2 == mod, "loaded twice %p / %p\n", mod, mod2 ); 2378 ok( ptr->thunks[0].u1.Function == 0xdeadbeef, "thunk resolved to %p for %s.%s\n", 2379 (void *)ptr->thunks[0].u1.Function, data.module, data.function.name ); 2380 ok( ptr->tls_index == 9999, "wrong tls index %d\n", ptr->tls_index ); 2381 check_tls_index(mod, ptr->tls_index != 9999); 2382 FreeLibrary( mod2 ); 2383 FreeLibrary( mod ); 2384 break; 2385 case 2: /* load without IMAGE_FILE_DLL doesn't resolve imports */ 2386 mod = LoadLibraryA( dll_name ); 2387 ok( mod != NULL, "failed to load err %lu\n", GetLastError() ); 2388 if (!mod) break; 2389 ptr = (struct imports *)((char *)mod + page_size); 2390 ok( ptr->thunks[0].u1.Function == 0xdeadbeef, "thunk resolved to %p for %s.%s\n", 2391 (void *)ptr->thunks[0].u1.Function, data.module, data.function.name ); 2392 ok( ptr->tls_index == 9999, "wrong tls index %d\n", ptr->tls_index ); 2393 check_tls_index(mod, ptr->tls_index != 9999); 2394 FreeLibrary( mod ); 2395 break; 2396 case 3: /* load with tls init function */ 2397 mod = LoadLibraryA( dll_name ); 2398 ok( mod != NULL, "failed to load err %lu\n", GetLastError() ); 2399 if (!mod) break; 2400 ptr = (struct imports *)((char *)mod + page_size); 2401 tls_index_save = ptr->tls_index; 2402#ifdef __REACTOS__ 2403 ok( ptr->tls_index < 32 || broken(ptr->tls_index == 9999) /* WS03 */, "wrong tls index %d\n", ptr->tls_index ); 2404 if (sizeof(tls_init_code) > 1 && ptr->tls_index != 9999) 2405#else 2406 ok( ptr->tls_index < 32, "wrong tls index %d\n", ptr->tls_index ); 2407 if (sizeof(tls_init_code) > 1) 2408#endif 2409 { 2410 str = ((char **)NtCurrentTeb()->ThreadLocalStoragePointer)[ptr->tls_index]; 2411 ok( !strcmp( str, "hello world" ), "wrong tls data '%s' at %p\n", str, str ); 2412 /* tls init function will write the reason to *tls_init_fn_output */ 2413 ok( tls_init_fn_output == DLL_PROCESS_ATTACH, 2414 "tls init function didn't run or got wrong reason: %d instead of %d\n", tls_init_fn_output, DLL_PROCESS_ATTACH ); 2415 tls_init_fn_output = 9999; 2416 WaitForSingleObject(CreateThread(NULL, 0, tls_thread_fn, (void*)(DWORD_PTR)ptr->tls_index, 0, NULL), INFINITE); 2417 ok( tls_init_fn_output == DLL_THREAD_DETACH, 2418 "tls init function didn't run or got wrong reason: %d instead of %d\n", tls_init_fn_output, DLL_THREAD_DETACH ); 2419 } 2420 check_tls_index(mod, ptr->tls_index != 9999); 2421 tls_init_fn_output = 9999; 2422 FreeLibrary( mod ); 2423 if (tls_index_save != 9999 && sizeof(tls_init_code) > 1) 2424 ok( tls_init_fn_output == DLL_PROCESS_DETACH, 2425 "tls init function didn't run or got wrong reason: %d instead of %d\n", tls_init_fn_output, DLL_PROCESS_DETACH ); 2426 break; 2427 case 4: /* map with ntdll */ 2428 case 5: /* map with ntdll, without IMAGE_FILE_DLL */ 2429 case 6: /* map with ntdll, without IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE */ 2430 hfile = CreateFileA(dll_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); 2431 ok( hfile != INVALID_HANDLE_VALUE, "CreateFile failed err %lu\n", GetLastError() ); 2432 mapping = CreateFileMappingA( hfile, NULL, SEC_IMAGE | PAGE_READONLY, 0, 0, NULL ); 2433 CloseHandle( hfile ); 2434 if (test == 6 && 2435 (nt_header_template.FileHeader.Machine == IMAGE_FILE_MACHINE_ARMNT || 2436 nt_header_template.FileHeader.Machine == IMAGE_FILE_MACHINE_ARM64)) 2437 { 2438 ok( !mapping, "CreateFileMappingA succeeded\n" ); 2439 ok( GetLastError() == ERROR_BAD_EXE_FORMAT, "wrong error %lu\n", GetLastError() ); 2440 break; 2441 } 2442 status = pNtQuerySection( mapping, SectionImageInformation, &image, sizeof(image), &size ); 2443 ok( !status, "NtQuerySection failed %lx\n", status ); 2444#ifdef __REACTOS__ 2445 ok( test == 6 ? !image.ImageDynamicallyRelocated : image.ImageDynamicallyRelocated || broken(GetNTVersion() < _WIN32_WINNT_VISTA), 2446#else 2447 ok( test == 6 ? !image.ImageDynamicallyRelocated : image.ImageDynamicallyRelocated, 2448#endif 2449 "image flags %x\n", image.ImageFlags); 2450 ok( !image.ImageContainsCode, "contains code %x\n", image.ImageContainsCode); 2451 ok( mapping != 0, "CreateFileMappingA failed err %lu\n", GetLastError() ); 2452 /* make sure that the address is not available */ 2453 tmp = VirtualAlloc( (void *)nt.OptionalHeader.ImageBase, 0x10000, 2454 MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE ); 2455 mod = NULL; 2456 size = 0; 2457 offset.QuadPart = 0; 2458 status = pNtMapViewOfSection( mapping, GetCurrentProcess(), (void **)&mod, 0, 0, &offset, 2459 &size, 1 /* ViewShare */, 0, PAGE_READONLY ); 2460 todo_wine_if (test == 5) 2461#ifdef __REACTOS__ 2462 ok( status == (test == 6 ? STATUS_IMAGE_NOT_AT_BASE : STATUS_SUCCESS) || broken(GetNTVersion() < _WIN32_WINNT_VISTA), 2463#else 2464 ok( status == (test == 6 ? STATUS_IMAGE_NOT_AT_BASE : STATUS_SUCCESS), 2465#endif 2466 "NtMapViewOfSection failed %lx\n", status ); 2467 ok( mod != (void *)nt.OptionalHeader.ImageBase, "loaded at image base %p\n", mod ); 2468 pnt = pRtlImageNtHeader( mod ); 2469 ptr = (void *)((char *)mod + page_size); 2470 if (test == 6) 2471 { 2472 ok( (void *)pnt->OptionalHeader.ImageBase != mod, "not relocated from %p\n", mod ); 2473 ok( (char *)ptr->tls.StartAddressOfRawData == (char *)nt.OptionalHeader.ImageBase + DATA_RVA( data.tls_data ), 2474 "tls relocated %p / %p\n", (void *)ptr->tls.StartAddressOfRawData, 2475 (char *)nt.OptionalHeader.ImageBase + DATA_RVA( data.tls_data )); 2476 } 2477 else todo_wine_if (test == 5) 2478 { 2479#ifdef __REACTOS__ 2480 if (GetNTVersion() >= _WIN32_WINNT_VISTA) { 2481#endif 2482 ok( (void *)pnt->OptionalHeader.ImageBase == mod, "not at base %p / %p\n", 2483 (void *)pnt->OptionalHeader.ImageBase, mod ); 2484 ok( (char *)ptr->tls.StartAddressOfRawData == (char *)mod + DATA_RVA( data.tls_data ), 2485 "tls not relocated %p / %p\n", (void *)ptr->tls.StartAddressOfRawData, 2486 (char *)mod + DATA_RVA( data.tls_data )); 2487#ifdef __REACTOS__ 2488 } 2489#endif 2490 } 2491 UnmapViewOfFile( mod ); 2492 CloseHandle( mapping ); 2493 if (tmp) VirtualFree( tmp, 0, MEM_RELEASE ); 2494 break; 2495 } 2496 DeleteFileA( dll_name ); 2497 winetest_pop_context(); 2498#undef DATA_RVA 2499 } 2500} 2501 2502static HANDLE gen_forward_chain_testdll( char testdll_path[MAX_PATH], 2503 const char source_dll[MAX_PATH], 2504 BOOL is_export, BOOL is_import, 2505 DWORD *exp_func_base_rva, 2506 DWORD *imp_thunk_base_rva ) 2507{ 2508 DWORD text_rva = page_size; /* assumes that the PE/COFF headers fit in a page */ 2509 DWORD text_size = page_size; 2510 DWORD edata_rva = text_rva + text_size; 2511 DWORD edata_size = page_size; 2512 DWORD idata_rva = edata_rva + text_size; 2513 DWORD idata_size = page_size; 2514 DWORD eof_rva = idata_rva + edata_size; 2515 const IMAGE_SECTION_HEADER sections[3] = { 2516 { 2517 .Name = ".text", 2518 .Misc = { .VirtualSize = text_size }, 2519 .VirtualAddress = text_rva, 2520 .SizeOfRawData = text_size, 2521 .PointerToRawData = text_rva, 2522 .Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE, 2523 }, 2524 { 2525 .Name = ".edata", 2526 .Misc = { .VirtualSize = edata_size }, 2527 .VirtualAddress = edata_rva, 2528 .SizeOfRawData = edata_size, 2529 .PointerToRawData = edata_rva, 2530 .Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ, 2531 }, 2532 { 2533 .Name = ".idata", 2534 .Misc = { .VirtualSize = edata_size }, 2535 .VirtualAddress = idata_rva, 2536 .SizeOfRawData = idata_size, 2537 .PointerToRawData = idata_rva, 2538 .Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE, 2539 }, 2540 }; 2541 struct expdesc 2542 { 2543 const IMAGE_EXPORT_DIRECTORY dir; 2544 2545 DWORD functions[2]; 2546 2547 const DWORD names[2]; 2548 const WORD name_ords[2]; 2549 const char str_forward_test_func[32]; 2550 const char str_forward_test_func2[32]; 2551 2552 char dll_name[MAX_PATH]; /* dynamically populated */ 2553 char strpool[2][MAX_PATH + 16]; /* for names of export forwarders */ 2554 } expdesc = { 2555 .dir = { 2556 .Characteristics = 0, 2557 .TimeDateStamp = 0x12345678, 2558 .Name = edata_rva + offsetof(struct expdesc, dll_name), 2559 .Base = 1, 2560 .NumberOfFunctions = ARRAY_SIZE(expdesc.functions), 2561 .NumberOfNames = ARRAY_SIZE(expdesc.names), 2562 .AddressOfFunctions = edata_rva + offsetof(struct expdesc, functions), 2563 .AddressOfNames = edata_rva + offsetof(struct expdesc, names), 2564 .AddressOfNameOrdinals = edata_rva + offsetof(struct expdesc, name_ords), 2565 }, 2566 .functions = { 2567 text_rva + 0x4, /* may be overwritten */ 2568 text_rva + 0x8, /* may be overwritten */ 2569 }, 2570 .names = { 2571 edata_rva + offsetof(struct expdesc, str_forward_test_func), 2572 edata_rva + offsetof(struct expdesc, str_forward_test_func2), 2573 }, 2574 .name_ords = { 2575 0, 2576 1, 2577 }, 2578 .str_forward_test_func = "forward_test_func", 2579 .str_forward_test_func2 = "forward_test_func2", 2580 }; 2581 struct impdesc 2582 { 2583 const IMAGE_IMPORT_DESCRIPTOR descr[2]; 2584 const IMAGE_THUNK_DATA original_thunks[3]; 2585 const IMAGE_THUNK_DATA thunks[3]; 2586 const struct { WORD hint; char name[32]; } impname_forward_test_func; 2587 2588 char module[MAX_PATH]; /* dynamically populated */ 2589 } impdesc = { 2590 .descr = { 2591 { 2592 .OriginalFirstThunk = idata_rva + offsetof(struct impdesc, original_thunks), 2593 .TimeDateStamp = 0, 2594 .ForwarderChain = -1, 2595 .Name = idata_rva + offsetof(struct impdesc, module), 2596 .FirstThunk = idata_rva + offsetof(struct impdesc, thunks), 2597 }, 2598 {{ 0 }}, 2599 }, 2600 .original_thunks = { 2601 {{ idata_rva + offsetof(struct impdesc, impname_forward_test_func) }}, 2602 {{ IMAGE_ORDINAL_FLAG | 2 }}, 2603 {{ 0 }}, 2604 }, 2605 .thunks = { 2606 {{ idata_rva + offsetof(struct impdesc, impname_forward_test_func) }}, 2607 {{ IMAGE_ORDINAL_FLAG | 2 }}, 2608 {{ 0 }}, 2609 }, 2610 .impname_forward_test_func = { 0, "forward_test_func" }, 2611 }; 2612 IMAGE_NT_HEADERS nt_header; 2613 char temp_path[MAX_PATH]; 2614 HANDLE file, file_w; 2615 LARGE_INTEGER qpc; 2616 DWORD outlen; 2617 BOOL ret; 2618 int res; 2619 2620 QueryPerformanceCounter( &qpc ); 2621 res = snprintf( expdesc.dll_name, ARRAY_SIZE(expdesc.dll_name), 2622 "ldr%05lx.dll", qpc.LowPart & 0xfffffUL ); 2623 ok( res > 0 && res < ARRAY_SIZE(expdesc.dll_name), "snprintf failed\n" ); 2624 2625 if (source_dll) 2626 { 2627 const char *export_names[2] = { 2628 "forward_test_func", 2629 "#2", 2630 }; 2631 const char *backslash = strrchr( source_dll, '\\' ); 2632 const char *dllname = backslash ? backslash + 1 : source_dll; 2633 const char *dot = strrchr( dllname, '.' ); 2634 size_t ext_start = dot ? dot - dllname : strlen(dllname); 2635 size_t i; 2636 2637 res = snprintf( impdesc.module, ARRAY_SIZE(impdesc.module), "%s", dllname ); 2638 ok( res > 0 && res < ARRAY_SIZE(impdesc.module), "snprintf() failed\n" ); 2639 2640 for (i = 0; i < ARRAY_SIZE(export_names); i++) 2641 { 2642 char *buf; 2643 size_t buf_size; 2644 2645 assert( i < ARRAY_SIZE(expdesc.strpool) ); 2646 buf = expdesc.strpool[i]; 2647 buf_size = ARRAY_SIZE(expdesc.strpool[i]); 2648 2649 assert( ext_start < buf_size ); 2650 memcpy( buf, dllname, ext_start ); 2651 buf += ext_start; 2652 buf_size -= ext_start; 2653 2654 res = snprintf( buf, buf_size, ".%s", export_names[i] ); 2655 ok( res > 0 && res < buf_size, "snprintf() failed\n" ); 2656 2657 assert( i < ARRAY_SIZE(expdesc.functions) ); 2658 expdesc.functions[i] = edata_rva + (expdesc.strpool[i] - (char *)&expdesc); 2659 } 2660 } 2661 2662 nt_header = nt_header_template; 2663 nt_header.FileHeader.TimeDateStamp = 0x12345678; 2664 nt_header.FileHeader.NumberOfSections = ARRAY_SIZE(sections); 2665 nt_header.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER); 2666 2667 nt_header.OptionalHeader.SizeOfCode = text_size; 2668 nt_header.OptionalHeader.SectionAlignment = page_size; 2669 nt_header.OptionalHeader.FileAlignment = page_size; 2670 nt_header.OptionalHeader.SizeOfHeaders = sizeof(dos_header) + sizeof(nt_header) + sizeof(sections); 2671 nt_header.OptionalHeader.SizeOfImage = eof_rva; 2672 if (is_export) 2673 { 2674 nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = edata_rva; 2675 nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size = sizeof(expdesc); 2676 } 2677 /* Always have an import descriptor (even if empty) just like a real DLL */ 2678 nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = idata_rva; 2679 nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = is_import ? sizeof(impdesc) : sizeof(IMAGE_IMPORT_DESCRIPTOR); 2680 2681 ok( nt_header.OptionalHeader.SizeOfHeaders <= text_rva, 2682 "headers (size %#lx) should not overlap with text area (RVA %#lx)\n", 2683 nt_header.OptionalHeader.SizeOfHeaders, text_rva ); 2684 2685 outlen = GetTempPathA( ARRAY_SIZE(temp_path), temp_path ); 2686 ok( outlen > 0 && outlen < ARRAY_SIZE(temp_path), "GetTempPathA() err=%lu\n", GetLastError() ); 2687 2688 res = snprintf( testdll_path, MAX_PATH, "%s\\%s", temp_path, expdesc.dll_name ); 2689 ok( res > 0 && res < MAX_PATH, "snprintf failed\n" ); 2690 2691 /* Open file handle that will be deleted on close or process termination */ 2692 file = CreateFileA( testdll_path, 2693 DELETE, 2694 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 2695 NULL, 2696 CREATE_NEW, 2697 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, 2698 NULL ); 2699 ok( file != INVALID_HANDLE_VALUE, "CreateFile(%s) for delete returned error %lu\n", 2700 wine_dbgstr_a( testdll_path ), GetLastError() ); 2701 2702 /* Open file again with write access */ 2703 file_w = CreateFileA( testdll_path, 2704 GENERIC_WRITE, 2705 FILE_SHARE_READ | FILE_SHARE_DELETE, 2706 NULL, 2707 OPEN_EXISTING, 2708 FILE_ATTRIBUTE_NORMAL, 2709 NULL ); 2710 ok( file_w != INVALID_HANDLE_VALUE, "CreateFile(%s) for write returned error %lu\n", 2711 wine_dbgstr_a( testdll_path ), GetLastError() ); 2712 2713 ret = WriteFile( file_w, &dos_header, sizeof(dos_header), &outlen, NULL ); 2714 ok( ret && outlen == sizeof(dos_header), "write dos_header: err=%lu outlen=%lu\n", GetLastError(), outlen ); 2715 2716 ret = WriteFile( file_w, &nt_header, sizeof(nt_header), &outlen, NULL ); 2717 ok( ret && outlen == sizeof(nt_header), "write nt_header: err=%lu outlen=%lu\n", GetLastError(), outlen ); 2718 2719 ret = WriteFile( file_w, sections, sizeof(sections), &outlen, NULL ); 2720 ok( ret && outlen == sizeof(sections), "write sections: err=%lu outlen=%lu\n", GetLastError(), outlen ); 2721 2722 if (is_export) 2723 { 2724 SetFilePointer( file_w, edata_rva, NULL, FILE_BEGIN ); 2725 ret = WriteFile( file_w, &expdesc, sizeof(expdesc), &outlen, NULL ); 2726 ok( ret && outlen == sizeof(expdesc), "write expdesc: err=%lu outlen=%lu\n", GetLastError(), outlen ); 2727 } 2728 2729 if (is_import) 2730 { 2731 SetFilePointer( file_w, idata_rva, NULL, FILE_BEGIN ); 2732 ret = WriteFile( file_w, &impdesc, sizeof(impdesc), &outlen, NULL ); 2733 ok( ret && outlen == sizeof(impdesc), "write impdesc: err=%lu outlen=%lu\n", GetLastError(), outlen ); 2734 } 2735 2736 ret = SetFilePointer( file_w, eof_rva, NULL, FILE_BEGIN ); 2737 ok( ret, "%lu\n", GetLastError() ); 2738 ret = SetEndOfFile( file_w ); 2739 ok( ret, "%lu\n", GetLastError() ); 2740 2741 ret = CloseHandle( file_w ); 2742 ok( ret, "%lu\n", GetLastError() ); 2743 2744 if (exp_func_base_rva) 2745 { 2746 *exp_func_base_rva = is_export ? edata_rva + ((char *)&expdesc.functions - (char *)&expdesc) : 0; 2747 } 2748 2749 if (imp_thunk_base_rva) 2750 { 2751 *imp_thunk_base_rva = is_import ? idata_rva + ((char *)&impdesc.thunks - (char *)&impdesc) : 0; 2752 } 2753 2754 return file; 2755} 2756 2757static void subtest_export_forwarder_dep_chain( size_t num_chained_export_modules, 2758 size_t exporter_index, 2759 BOOL test_static_import ) 2760{ 2761 size_t num_modules = num_chained_export_modules + !!test_static_import; 2762 size_t importer_index = test_static_import ? num_modules - 1 : 0; 2763 DWORD imp_thunk_base_rva, exp_func_base_rva; 2764 size_t ultimate_depender_index = 0; /* latest module depending on modules earlier in chain */ 2765 char temp_paths[4][MAX_PATH]; 2766 HANDLE temp_files[4]; 2767 UINT_PTR exports[2]; 2768 HMODULE modules[4]; 2769 BOOL res; 2770 size_t i; 2771 2772 assert(exporter_index < num_chained_export_modules); 2773 assert(num_modules > 1); 2774 assert(num_modules <= ARRAY_SIZE(temp_paths)); 2775 assert(num_modules <= ARRAY_SIZE(temp_files)); 2776 assert(num_modules <= ARRAY_SIZE(modules)); 2777 2778 if (winetest_debug > 1) 2779 trace( "Generate a chain of test DLL fixtures\n" ); 2780 2781 for (i = 0; i < num_modules; i++) 2782 { 2783 temp_files[i] = gen_forward_chain_testdll( temp_paths[i], 2784 i >= 1 ? temp_paths[i - 1] : NULL, 2785 i < num_chained_export_modules, 2786 importer_index && i == importer_index, 2787 i == 0 ? &exp_func_base_rva : NULL, 2788 i == importer_index ? &imp_thunk_base_rva : NULL ); 2789 } 2790 2791 if (winetest_debug > 1) 2792 trace( "Load the entire test DLL chain\n" ); 2793 2794 for (i = 0; i < num_modules; i++) 2795 { 2796 HMODULE module; 2797 2798 ok( !GetModuleHandleA( temp_paths[i] ), "%s already loaded\n", 2799 wine_dbgstr_a( temp_paths[i] ) ); 2800 2801 modules[i] = LoadLibraryA( temp_paths[i] ); 2802 ok( !!modules[i], "LoadLibraryA(temp_paths[%Iu] = %s) err=%lu\n", 2803 i, wine_dbgstr_a( temp_paths[i] ), GetLastError() ); 2804 2805 if (i == importer_index) 2806 { 2807 /* Statically importing export forwarder introduces a load-time dependency */ 2808 ultimate_depender_index = max( ultimate_depender_index, importer_index ); 2809 } 2810 2811 module = GetModuleHandleA( temp_paths[i] ); 2812 ok( module == modules[i], "modules[%Iu] expected %p, got %p err=%lu\n", 2813 i, modules[i], module, GetLastError() ); 2814 } 2815 2816 if (winetest_debug > 1) 2817 trace( "Get address of exported functions from the source module\n" ); 2818 2819 for (i = 0; i < ARRAY_SIZE(exports); i++) 2820 { 2821 char *mod_base = (char *)modules[0]; /* source (non-forward) DLL */ 2822 exports[i] = (UINT_PTR)(mod_base + ((DWORD *)(mod_base + exp_func_base_rva))[i]); 2823 } 2824 2825 if (winetest_debug > 1) 2826 trace( "Check import address table of the importer DLL, if any\n" ); 2827 2828 if (importer_index) 2829 { 2830 UINT_PTR *imp_thunk_base = (UINT_PTR *)((char *)modules[importer_index] + imp_thunk_base_rva); 2831 for (i = 0; i < ARRAY_SIZE(exports); i++) 2832 { 2833 ok( imp_thunk_base[i] == exports[i], "import thunk mismatch [%Iu]: (%#Ix, %#Ix)\n", 2834 i, imp_thunk_base[i], exports[i] ); 2835 } 2836 } 2837 2838 if (winetest_debug > 1) 2839 trace( "Call GetProcAddress() on the exporter DLL, if any\n" ); 2840 2841 if (exporter_index) 2842 { 2843 UINT_PTR proc; 2844 2845 proc = (UINT_PTR)GetProcAddress( modules[exporter_index], "forward_test_func" ); 2846 ok( proc == exports[0], "GetProcAddress mismatch [0]: (%#Ix, %#Ix)\n", proc, exports[0] ); 2847 2848 proc = (UINT_PTR)GetProcAddress( modules[exporter_index], (LPSTR)2 ); 2849 ok( proc == exports[1], "GetProcAddress mismatch [1]: (%#Ix, %#Ix)\n", proc, exports[1] ); 2850 2851 /* Dynamically importing export forwarder introduces a runtime dependency */ 2852 ultimate_depender_index = max( ultimate_depender_index, exporter_index ); 2853 } 2854 2855 if (winetest_debug > 1) 2856 trace( "Unreference modules except the ultimate dependant DLL\n" ); 2857 2858 for (i = 0; i < ultimate_depender_index; i++) 2859 { 2860 HMODULE module; 2861 2862 res = FreeLibrary( modules[i] ); 2863 ok( res, "FreeLibrary(modules[%Iu]) err=%lu\n", i, GetLastError() ); 2864 2865 /* FreeLibrary() should *not* unload the DLL immediately */ 2866 module = GetModuleHandleA( temp_paths[i] ); 2867 todo_wine_if(i < ultimate_depender_index && i + 1 != importer_index) 2868 ok( module == modules[i], "modules[%Iu] expected %p, got %p (unloaded?) err=%lu\n", 2869 i, modules[i], module, GetLastError() ); 2870 } 2871 2872 if (winetest_debug > 1) 2873 trace( "The ultimate dependant DLL should keep other DLLs from being unloaded\n" ); 2874 2875 for (i = 0; i < num_modules; i++) 2876 { 2877 HMODULE module = GetModuleHandleA( temp_paths[i] ); 2878 2879 todo_wine_if(i < ultimate_depender_index && i + 1 != importer_index) 2880 ok( module == modules[i], "modules[%Iu] expected %p, got %p (unloaded?) err=%lu\n", 2881 i, modules[i], module, GetLastError() ); 2882 } 2883 2884 if (winetest_debug > 1) 2885 trace( "Unreference the remaining modules (including the dependant DLL)\n" ); 2886 2887 for (i = ultimate_depender_index; i < num_modules; i++) 2888 { 2889 res = FreeLibrary( modules[i] ); 2890 ok( res, "FreeLibrary(modules[%Iu]) err=%lu\n", i, GetLastError() ); 2891 2892 /* FreeLibrary() should unload the DLL immediately */ 2893 ok( !GetModuleHandleA( temp_paths[i] ), "modules[%Iu] should not be kept loaded (2)\n", i ); 2894 } 2895 2896 if (winetest_debug > 1) 2897 trace( "All modules should be unloaded; the unloading process should not reload any DLL\n" ); 2898 2899#ifdef __REACTOS__ 2900 if (GetNTVersion() >= _WIN32_WINNT_VISTA) { 2901#endif 2902 for (i = 0; i < num_modules; i++) 2903 { 2904 ok( !GetModuleHandleA( temp_paths[i] ), "modules[%Iu] should not be kept loaded (3)\n", i ); 2905 } 2906#ifdef __REACTOS__ 2907 } 2908#endif 2909 2910 if (winetest_debug > 1) 2911 trace( "Close and delete temp files\n" ); 2912 2913 for (i = 0; i < num_modules; i++) 2914 { 2915 /* handles should be delete-on-close */ 2916 CloseHandle( temp_files[i] ); 2917 } 2918} 2919 2920static void test_export_forwarder_dep_chain(void) 2921{ 2922 winetest_push_context( "no import" ); 2923 /* export forwarder does not introduce a dependency on its own */ 2924 subtest_export_forwarder_dep_chain( 2, 0, FALSE ); 2925 winetest_pop_context(); 2926 2927 winetest_push_context( "static import of export forwarder" ); 2928 subtest_export_forwarder_dep_chain( 2, 0, TRUE ); 2929 winetest_pop_context(); 2930 2931 winetest_push_context( "static import of chained export forwarder" ); 2932 subtest_export_forwarder_dep_chain( 3, 0, TRUE ); 2933 winetest_pop_context(); 2934 2935 winetest_push_context( "dynamic import of export forwarder" ); 2936 subtest_export_forwarder_dep_chain( 2, 1, FALSE ); 2937 winetest_pop_context(); 2938 2939 winetest_push_context( "dynamic import of chained export forwarder" ); 2940 subtest_export_forwarder_dep_chain( 3, 2, FALSE ); 2941 winetest_pop_context(); 2942} 2943 2944#define MAX_COUNT 10 2945static HANDLE attached_thread[MAX_COUNT]; 2946static DWORD attached_thread_count; 2947static HANDLE event, mutex, semaphore; 2948static HANDLE stop_event, loader_lock_event, peb_lock_event, heap_lock_event, cs_lock_event, ack_event; 2949static CRITICAL_SECTION cs_lock; 2950static int test_dll_phase, inside_loader_lock, inside_peb_lock, inside_heap_lock, inside_cs_lock; 2951static LONG fls_callback_count; 2952 2953static DWORD WINAPI mutex_thread_proc(void *param) 2954{ 2955 HANDLE wait_list[5]; 2956 DWORD ret; 2957 2958 ret = WaitForSingleObject(mutex, 0); 2959 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %#lx\n", ret); 2960 2961 SetEvent(param); 2962 2963 wait_list[0] = stop_event; 2964 wait_list[1] = loader_lock_event; 2965 wait_list[2] = peb_lock_event; 2966 wait_list[3] = heap_lock_event; 2967 wait_list[4] = cs_lock_event; 2968 2969 trace("%04lx: mutex_thread_proc: starting\n", GetCurrentThreadId()); 2970 while (1) 2971 { 2972 ret = WaitForMultipleObjects(ARRAY_SIZE(wait_list), wait_list, FALSE, 50); 2973 if (ret == WAIT_OBJECT_0) break; 2974 else if (ret == WAIT_OBJECT_0 + 1) 2975 { 2976 ULONG_PTR loader_lock_magic; 2977 trace("%04lx: mutex_thread_proc: Entering loader lock\n", GetCurrentThreadId()); 2978 ret = pLdrLockLoaderLock(0, NULL, &loader_lock_magic); 2979 ok(!ret, "LdrLockLoaderLock error %#lx\n", ret); 2980 inside_loader_lock++; 2981 SetEvent(ack_event); 2982 } 2983 else if (ret == WAIT_OBJECT_0 + 2) 2984 { 2985 trace("%04lx: mutex_thread_proc: Entering PEB lock\n", GetCurrentThreadId()); 2986 pRtlAcquirePebLock(); 2987 inside_peb_lock++; 2988 SetEvent(ack_event); 2989 } 2990 else if (ret == WAIT_OBJECT_0 + 3) 2991 { 2992 trace("%04lx: mutex_thread_proc: Entering heap lock\n", GetCurrentThreadId()); 2993 HeapLock(GetProcessHeap()); 2994 inside_heap_lock++; 2995 SetEvent(ack_event); 2996 } 2997 else if (ret == WAIT_OBJECT_0 + 4) 2998 { 2999 trace("%04lx: mutex_thread_proc: Entering CS lock\n", GetCurrentThreadId()); 3000 EnterCriticalSection(&cs_lock); 3001 inside_cs_lock++; 3002 SetEvent(ack_event); 3003 } 3004 } 3005 3006 trace("%04lx: mutex_thread_proc: exiting\n", GetCurrentThreadId()); 3007 return 196; 3008} 3009 3010static DWORD WINAPI semaphore_thread_proc(void *param) 3011{ 3012 DWORD ret; 3013 3014 ret = WaitForSingleObject(semaphore, 0); 3015 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %#lx\n", ret); 3016 3017 SetEvent(param); 3018 3019 while (1) 3020 { 3021 if (winetest_debug > 1) 3022 trace("%04lx: semaphore_thread_proc: still alive\n", GetCurrentThreadId()); 3023 if (WaitForSingleObject(stop_event, 50) != WAIT_TIMEOUT) break; 3024 } 3025 3026 trace("%04lx: semaphore_thread_proc: exiting\n", GetCurrentThreadId()); 3027 return 196; 3028} 3029 3030static DWORD WINAPI noop_thread_proc(void *param) 3031{ 3032 if (param) 3033 { 3034 LONG *noop_thread_started = param; 3035 InterlockedIncrement(noop_thread_started); 3036 } 3037 3038 trace("%04lx: noop_thread_proc: exiting\n", GetCurrentThreadId()); 3039 return 195; 3040} 3041 3042static VOID WINAPI fls_callback(PVOID lpFlsData) 3043{ 3044 ok(lpFlsData == (void*) 0x31415, "lpFlsData is %p, expected %p\n", lpFlsData, (void*) 0x31415); 3045 InterlockedIncrement(&fls_callback_count); 3046} 3047 3048static LIST_ENTRY *fls_list_head; 3049 3050static unsigned int check_linked_list(const LIST_ENTRY *le, const LIST_ENTRY *search_entry, unsigned int *index_found) 3051{ 3052 unsigned int count = 0; 3053 LIST_ENTRY *entry; 3054 3055 *index_found = ~0; 3056 3057 for (entry = le->Flink; entry != le; entry = entry->Flink) 3058 { 3059 if (entry == search_entry) 3060 { 3061 ok(*index_found == ~0, "Duplicate list entry.\n"); 3062 *index_found = count; 3063 } 3064 ++count; 3065 } 3066 return count; 3067} 3068 3069static BOOL WINAPI dll_entry_point(HINSTANCE hinst, DWORD reason, LPVOID param) 3070{ 3071 static LONG noop_thread_started; 3072 static DWORD fls_index = FLS_OUT_OF_INDEXES, fls_index2 = FLS_OUT_OF_INDEXES; 3073 static int fls_count = 0; 3074 static int thread_detach_count = 0; 3075 static int thread_count; 3076 DWORD ret; 3077 3078 ok(!inside_loader_lock, "inside_loader_lock should not be set\n"); 3079 ok(!inside_peb_lock, "inside_peb_lock should not be set\n"); 3080 3081 switch (reason) 3082 { 3083 case DLL_PROCESS_ATTACH: 3084 trace("dll: %p, DLL_PROCESS_ATTACH, %p\n", hinst, param); 3085 3086 ret = pRtlDllShutdownInProgress(); 3087 ok(!ret, "RtlDllShutdownInProgress returned %ld\n", ret); 3088 3089 /* Set up the FLS slot, if FLS is available */ 3090 if (pFlsGetValue) 3091 { 3092 void* value; 3093 BOOL bret; 3094 ret = pFlsAlloc(&fls_callback); 3095 ok(ret != FLS_OUT_OF_INDEXES, "FlsAlloc returned %ld\n", ret); 3096 fls_index = ret; 3097 SetLastError(0xdeadbeef); 3098 value = pFlsGetValue(fls_index); 3099 ok(!value, "FlsGetValue returned %p, expected NULL\n", value); 3100 ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %lu\n", GetLastError()); 3101 bret = pFlsSetValue(fls_index, (void*) 0x31415); 3102 ok(bret, "FlsSetValue failed\n"); 3103 fls_count++; 3104 3105 fls_index2 = pFlsAlloc(&fls_callback); 3106 ok(fls_index2 != FLS_OUT_OF_INDEXES, "FlsAlloc returned %ld\n", ret); 3107 } 3108 ++thread_count; 3109 break; 3110 case DLL_PROCESS_DETACH: 3111 { 3112 DWORD code, expected_code, i; 3113 HANDLE handle, process; 3114 void *addr; 3115 SIZE_T size; 3116 LARGE_INTEGER offset; 3117 DEBUG_EVENT de; 3118 3119 trace("dll: %p, DLL_PROCESS_DETACH, %p\n", hinst, param); 3120 3121 if (test_dll_phase == 4 || test_dll_phase == 5) 3122 { 3123 ok(0, "dll_entry_point(DLL_PROCESS_DETACH) should not be called\n"); 3124 break; 3125 } 3126 3127 /* The process should already deadlock at this point */ 3128 if (test_dll_phase == 6) 3129 { 3130 /* In reality, code below never gets executed, probably some other 3131 * code tries to access process heap and deadlocks earlier, even XP 3132 * doesn't call the DLL entry point on process detach either. 3133 */ 3134 HeapLock(GetProcessHeap()); 3135 todo_wine 3136 ok(0, "dll_entry_point: process should already deadlock\n"); 3137 break; 3138 } 3139 else if (test_dll_phase == 7) 3140 { 3141 EnterCriticalSection(&cs_lock); 3142 } 3143 3144 if (test_dll_phase == 0 || test_dll_phase == 1 || test_dll_phase == 3 || test_dll_phase == 7) 3145 ok(param != NULL, "dll: param %p\n", param); 3146 else 3147 ok(!param, "dll: param %p\n", param); 3148 3149 if (test_dll_phase == 0 || test_dll_phase == 1) expected_code = 195; 3150 else if (test_dll_phase == 3) expected_code = 196; 3151 else if (test_dll_phase == 7) expected_code = 199; 3152 else expected_code = STILL_ACTIVE; 3153 3154 ret = pRtlDllShutdownInProgress(); 3155 if (test_dll_phase == 0 || test_dll_phase == 1 || test_dll_phase == 3) 3156 { 3157 ok(ret, "RtlDllShutdownInProgress returned %ld\n", ret); 3158 } 3159 else 3160 { 3161 /* FIXME: remove once Wine is fixed */ 3162 todo_wine_if (!(expected_code == STILL_ACTIVE || expected_code == 196)) 3163#ifdef __REACTOS__ 3164 ok(!ret || broken(GetNTVersion() < _WIN32_WINNT_VISTA), "RtlDllShutdownInProgress returned %ld\n", ret); 3165#else 3166 ok(!ret, "RtlDllShutdownInProgress returned %ld\n", ret); 3167#endif 3168 } 3169 3170 /* In the case that the process is terminating, FLS slots should still be accessible, but 3171 * the callback should be already run for this thread and the contents already NULL. 3172 */ 3173 if (param && pFlsGetValue) 3174 { 3175 void* value; 3176 SetLastError(0xdeadbeef); 3177 value = pFlsGetValue(fls_index); 3178#ifdef __REACTOS__ 3179 ok(value == NULL || broken(value == (void*)0x31415) /* WS03 */, "FlsGetValue returned %p, expected NULL\n", value); 3180#else 3181 ok(value == NULL, "FlsGetValue returned %p, expected NULL\n", value); 3182#endif 3183 ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %lu\n", GetLastError()); 3184#ifdef __REACTOS__ 3185 ok(fls_callback_count == thread_detach_count + 1 || broken(GetNTVersion() < _WIN32_WINNT_VISTA), 3186 "wrong FLS callback count %ld, expected %d\n", fls_callback_count, thread_detach_count + 1); 3187#else 3188 ok(fls_callback_count == thread_detach_count + 1, 3189 "wrong FLS callback count %ld, expected %d\n", fls_callback_count, thread_detach_count + 1); 3190#endif 3191 } 3192 if (pFlsFree) 3193 { 3194 BOOL ret; 3195 /* Call FlsFree now and run the remaining callbacks from uncleanly terminated threads */ 3196 ret = pFlsFree(fls_index); 3197 ok(ret, "FlsFree failed with error %lu\n", GetLastError()); 3198 fls_index = FLS_OUT_OF_INDEXES; 3199#ifdef __REACTOS__ 3200 if (GetNTVersion() >= _WIN32_WINNT_VISTA) 3201#endif 3202 ok(fls_callback_count == fls_count, 3203 "wrong FLS callback count %ld, expected %d\n", fls_callback_count, fls_count); 3204 } 3205 3206 ok(attached_thread_count >= 2, "attached thread count should be >= 2\n"); 3207 3208 for (i = 0; i < attached_thread_count; i++) 3209 { 3210 /* Calling GetExitCodeThread() without waiting for thread termination 3211 * leads to different results due to a race condition. 3212 */ 3213 if (expected_code != STILL_ACTIVE) 3214 { 3215 ret = WaitForSingleObject(attached_thread[i], 1000); 3216 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %#lx\n", ret); 3217 } 3218 ret = GetExitCodeThread(attached_thread[i], &code); 3219 trace("dll: GetExitCodeThread(%lu) => %ld,%lu\n", i, ret, code); 3220 ok(ret == 1, "GetExitCodeThread returned %ld, expected 1\n", ret); 3221 ok(code == expected_code, "expected thread exit code %lu, got %lu\n", expected_code, code); 3222 } 3223 3224 ret = WaitForSingleObject(event, 0); 3225 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#lx\n", ret); 3226 3227 ret = WaitForSingleObject(mutex, 0); 3228 if (expected_code == STILL_ACTIVE) 3229 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#lx\n", ret); 3230 else 3231 ok(ret == WAIT_ABANDONED, "expected WAIT_ABANDONED, got %#lx\n", ret); 3232 3233 /* semaphore is not abandoned on thread termination */ 3234 ret = WaitForSingleObject(semaphore, 0); 3235 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#lx\n", ret); 3236 3237 if (expected_code == STILL_ACTIVE) 3238 { 3239 ret = WaitForSingleObject(attached_thread[0], 0); 3240 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#lx\n", ret); 3241 ret = WaitForSingleObject(attached_thread[1], 0); 3242 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#lx\n", ret); 3243 } 3244 else 3245 { 3246 ret = WaitForSingleObject(attached_thread[0], 0); 3247 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %#lx\n", ret); 3248 ret = WaitForSingleObject(attached_thread[1], 0); 3249 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %#lx\n", ret); 3250 } 3251 3252 /* win7 doesn't allow creating a thread during process shutdown but 3253 * earlier Windows versions allow it. 3254 */ 3255 noop_thread_started = 0; 3256 SetLastError(0xdeadbeef); 3257 handle = CreateThread(NULL, 0, noop_thread_proc, &noop_thread_started, 0, &ret); 3258 if (param) 3259 { 3260#ifdef __REACTOS__ 3261 ok(!handle || broken(handle != 0) /* Pre-Win7 */, "CreateThread should fail\n"); 3262 3263 if (!handle) 3264 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError()); 3265 else 3266 { 3267 ret = WaitForSingleObject(handle, 1000); 3268 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret); 3269 CloseHandle(handle); 3270 } 3271#else 3272 ok(!handle, "CreateThread should fail\n"); 3273 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError()); 3274#endif 3275 } 3276 else 3277 { 3278 ok(handle != 0, "CreateThread error %ld\n", GetLastError()); 3279 ret = WaitForSingleObject(handle, 1000); 3280 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#lx\n", ret); 3281 ok(!noop_thread_started, "thread shouldn't start yet\n"); 3282 CloseHandle(handle); 3283 } 3284 3285 SetLastError(0xdeadbeef); 3286 process = OpenProcess(PROCESS_ALL_ACCESS_NT4, FALSE, GetCurrentProcessId()); 3287 ok(process != NULL, "OpenProcess error %ld\n", GetLastError()); 3288 3289 noop_thread_started = 0; 3290 SetLastError(0xdeadbeef); 3291 handle = CreateRemoteThread(process, NULL, 0, noop_thread_proc, &noop_thread_started, 0, &ret); 3292 if (param) 3293 { 3294#ifdef __REACTOS__ 3295 ok(!handle || broken(handle != 0) /* Pre-Win7 */, "CreateRemoteThread should fail\n"); 3296 3297 if (!handle) 3298 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError()); 3299 else 3300 { 3301 ret = WaitForSingleObject(handle, 1000); 3302 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret); 3303 CloseHandle(handle); 3304 } 3305#else 3306 ok(!handle, "CreateRemoteThread should fail\n"); 3307 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError()); 3308#endif 3309 } 3310 else 3311 { 3312 ok(handle != 0, "CreateRemoteThread error %ld\n", GetLastError()); 3313 ret = WaitForSingleObject(handle, 1000); 3314 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#lx\n", ret); 3315 ok(!noop_thread_started, "thread shouldn't start yet\n"); 3316 CloseHandle(handle); 3317 } 3318 3319 SetLastError(0xdeadbeef); 3320 handle = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, NULL); 3321 ok(handle != 0, "CreateFileMapping error %ld\n", GetLastError()); 3322 3323 offset.u.LowPart = 0; 3324 offset.u.HighPart = 0; 3325 addr = NULL; 3326 size = 0; 3327 ret = pNtMapViewOfSection(handle, process, &addr, 0, 0, &offset, 3328 &size, 1 /* ViewShare */, 0, PAGE_READONLY); 3329 ok(ret == STATUS_SUCCESS, "NtMapViewOfSection error %#lx\n", ret); 3330 ret = pNtUnmapViewOfSection(process, addr); 3331 ok(ret == STATUS_SUCCESS, "NtUnmapViewOfSection error %#lx\n", ret); 3332 3333 CloseHandle(handle); 3334 CloseHandle(process); 3335 3336 handle = GetModuleHandleA("winver.exe"); 3337 ok(!handle, "winver.exe shouldn't be loaded yet\n"); 3338 SetLastError(0xdeadbeef); 3339 handle = LoadLibraryA("winver.exe"); 3340 ok(handle != 0, "LoadLibrary error %ld\n", GetLastError()); 3341 SetLastError(0xdeadbeef); 3342 ret = FreeLibrary(handle); 3343 ok(ret, "FreeLibrary error %ld\n", GetLastError()); 3344 handle = GetModuleHandleA("winver.exe"); 3345 if (param) 3346 ok(handle != 0, "winver.exe should not be unloaded\n"); 3347 else 3348 todo_wine 3349 ok(!handle, "winver.exe should be unloaded\n"); 3350 3351 SetLastError(0xdeadbeef); 3352 ret = WaitForDebugEvent(&de, 0); 3353 ok(!ret, "WaitForDebugEvent should fail\n"); 3354 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError()); 3355 3356 SetLastError(0xdeadbeef); 3357 ret = DebugActiveProcess(GetCurrentProcessId()); 3358 ok(!ret, "DebugActiveProcess should fail\n"); 3359 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError()); 3360 3361 SetLastError(0xdeadbeef); 3362 ret = WaitForDebugEvent(&de, 0); 3363 ok(!ret, "WaitForDebugEvent should fail\n"); 3364 ok(GetLastError() == ERROR_SEM_TIMEOUT, "expected ERROR_SEM_TIMEOUT, got %ld\n", GetLastError()); 3365 3366 if (test_dll_phase == 2) 3367 { 3368 trace("dll: call ExitProcess()\n"); 3369 *child_failures = winetest_get_failures(); 3370 ExitProcess(197); 3371 } 3372 trace("dll: %p, DLL_PROCESS_DETACH, %p => DONE\n", hinst, param); 3373 break; 3374 } 3375 case DLL_THREAD_ATTACH: 3376 trace("dll: %p, DLL_THREAD_ATTACH, %p\n", hinst, param); 3377 3378 ++thread_count; 3379 3380 ret = pRtlDllShutdownInProgress(); 3381 ok(!ret, "RtlDllShutdownInProgress returned %ld\n", ret); 3382 3383 if (attached_thread_count < MAX_COUNT) 3384 { 3385 DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &attached_thread[attached_thread_count], 3386 0, TRUE, DUPLICATE_SAME_ACCESS); 3387 attached_thread_count++; 3388 } 3389 3390 /* Make sure the FLS slot is empty, if FLS is available */ 3391 if (pFlsGetValue) 3392 { 3393 void* value; 3394 BOOL ret; 3395 SetLastError(0xdeadbeef); 3396 value = pFlsGetValue(fls_index); 3397 ok(!value, "FlsGetValue returned %p, expected NULL\n", value); 3398 ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %lu\n", GetLastError()); 3399 ret = pFlsSetValue(fls_index, (void*) 0x31415); 3400 ok(ret, "FlsSetValue failed\n"); 3401 fls_count++; 3402 } 3403 3404 break; 3405 case DLL_THREAD_DETACH: 3406 trace("dll: %p, DLL_THREAD_DETACH, %p\n", hinst, param); 3407 --thread_count; 3408 thread_detach_count++; 3409 3410 ret = pRtlDllShutdownInProgress(); 3411 /* win7 doesn't allow creating a thread during process shutdown but 3412 * earlier Windows versions allow it. In that case DLL_THREAD_DETACH is 3413 * sent on thread exit, but DLL_THREAD_ATTACH is never received. 3414 */ 3415 if (noop_thread_started) 3416 ok(ret, "RtlDllShutdownInProgress returned %ld\n", ret); 3417 else 3418 ok(!ret, "RtlDllShutdownInProgress returned %ld\n", ret); 3419 3420 /* FLS data should already be destroyed, if FLS is available. 3421 */ 3422 if (pFlsGetValue && fls_index != FLS_OUT_OF_INDEXES) 3423 { 3424 unsigned int index, count; 3425 void* value; 3426 BOOL bret; 3427 3428 SetLastError(0xdeadbeef); 3429 value = pFlsGetValue(fls_index); 3430#ifdef __REACTOS__ 3431 ok(!value || broken(value == (void*)0x31415) /* WS03 */, "FlsGetValue returned %p, expected NULL\n", value); 3432#else 3433 ok(!value, "FlsGetValue returned %p, expected NULL\n", value); 3434#endif 3435 ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %lu\n", GetLastError()); 3436 3437 bret = pFlsSetValue(fls_index2, (void*) 0x31415); 3438 ok(bret, "FlsSetValue failed\n"); 3439 3440 if (fls_list_head) 3441 { 3442 count = check_linked_list(fls_list_head, &NtCurrentTeb()->FlsSlots->fls_list_entry, &index); 3443#ifdef __REACTOS__ 3444 if (GetNTVersion() >= _WIN32_WINNT_VISTA) { 3445#endif 3446 ok(count <= thread_count, "Got unexpected count %u, thread_count %u.\n", count, thread_count); 3447 ok(index == ~0, "Got unexpected index %u.\n", index); 3448#ifdef __REACTOS__ 3449 } 3450#endif 3451 } 3452 } 3453 3454 break; 3455 default: 3456 trace("dll: %p, %ld, %p\n", hinst, reason, param); 3457 break; 3458 } 3459 3460 *child_failures = winetest_get_failures(); 3461 3462 return TRUE; 3463} 3464 3465static void CALLBACK ldr_notify_callback(ULONG reason, LDR_DLL_NOTIFICATION_DATA *data, void *context) 3466{ 3467 /* If some DLL happens to be loaded during process shutdown load notification is called but never unload 3468 * notification. */ 3469 ok(reason == LDR_DLL_NOTIFICATION_REASON_LOADED, "got reason %lu.\n", reason); 3470} 3471 3472static void child_process(const char *dll_name, DWORD target_offset) 3473{ 3474 void *target; 3475 DWORD ret, dummy, i, code, expected_code; 3476 HANDLE file, thread, process; 3477 HMODULE hmod; 3478 struct PROCESS_BASIC_INFORMATION_PRIVATE pbi; 3479 DWORD_PTR affinity; 3480 void *cookie; 3481 3482 trace("phase %d: writing %p at %#lx\n", test_dll_phase, dll_entry_point, target_offset); 3483 3484 if (pFlsAlloc) 3485 { 3486 fls_list_head = NtCurrentTeb()->Peb->FlsListHead.Flink ? &NtCurrentTeb()->Peb->FlsListHead 3487 : NtCurrentTeb()->FlsSlots->fls_list_entry.Flink; 3488 } 3489 3490 SetLastError(0xdeadbeef); 3491 mutex = CreateMutexW(NULL, FALSE, NULL); 3492 ok(mutex != 0, "CreateMutex error %ld\n", GetLastError()); 3493 3494 SetLastError(0xdeadbeef); 3495 semaphore = CreateSemaphoreW(NULL, 1, 1, NULL); 3496 ok(semaphore != 0, "CreateSemaphore error %ld\n", GetLastError()); 3497 3498 SetLastError(0xdeadbeef); 3499 event = CreateEventW(NULL, TRUE, FALSE, NULL); 3500 ok(event != 0, "CreateEvent error %ld\n", GetLastError()); 3501 3502 SetLastError(0xdeadbeef); 3503 loader_lock_event = CreateEventW(NULL, FALSE, FALSE, NULL); 3504 ok(loader_lock_event != 0, "CreateEvent error %ld\n", GetLastError()); 3505 3506 SetLastError(0xdeadbeef); 3507 peb_lock_event = CreateEventW(NULL, FALSE, FALSE, NULL); 3508 ok(peb_lock_event != 0, "CreateEvent error %ld\n", GetLastError()); 3509 3510 SetLastError(0xdeadbeef); 3511 heap_lock_event = CreateEventW(NULL, FALSE, FALSE, NULL); 3512 ok(heap_lock_event != 0, "CreateEvent error %ld\n", GetLastError()); 3513 3514 InitializeCriticalSection(&cs_lock); 3515 SetLastError(0xdeadbeef); 3516 cs_lock_event = CreateEventW(NULL, FALSE, FALSE, NULL); 3517 ok(cs_lock_event != 0, "CreateEvent error %ld\n", GetLastError()); 3518 3519 SetLastError(0xdeadbeef); 3520 ack_event = CreateEventW(NULL, FALSE, FALSE, NULL); 3521 ok(ack_event != 0, "CreateEvent error %ld\n", GetLastError()); 3522 3523 file = CreateFileA(dll_name, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0); 3524 if (file == INVALID_HANDLE_VALUE) 3525 { 3526 ok(0, "could not open %s\n", dll_name); 3527 return; 3528 } 3529 SetFilePointer(file, target_offset, NULL, FILE_BEGIN); 3530 SetLastError(0xdeadbeef); 3531 target = dll_entry_point; 3532 ret = WriteFile(file, &target, sizeof(target), &dummy, NULL); 3533 ok(ret, "WriteFile error %ld\n", GetLastError()); 3534 CloseHandle(file); 3535 3536 SetLastError(0xdeadbeef); 3537 hmod = LoadLibraryA(dll_name); 3538 ok(hmod != 0, "LoadLibrary error %ld\n", GetLastError()); 3539 3540 SetLastError(0xdeadbeef); 3541 stop_event = CreateEventW(NULL, TRUE, FALSE, NULL); 3542 ok(stop_event != 0, "CreateEvent error %ld\n", GetLastError()); 3543 3544 SetLastError(0xdeadbeef); 3545 thread = CreateThread(NULL, 0, mutex_thread_proc, event, 0, &dummy); 3546 ok(thread != 0, "CreateThread error %ld\n", GetLastError()); 3547 WaitForSingleObject(event, 3000); 3548 CloseHandle(thread); 3549 3550 ResetEvent(event); 3551 3552 SetLastError(0xdeadbeef); 3553 thread = CreateThread(NULL, 0, semaphore_thread_proc, event, 0, &dummy); 3554 ok(thread != 0, "CreateThread error %ld\n", GetLastError()); 3555 WaitForSingleObject(event, 3000); 3556 CloseHandle(thread); 3557 3558 ResetEvent(event); 3559 Sleep(100); 3560 3561 ok(attached_thread_count == 2, "attached thread count should be 2\n"); 3562 for (i = 0; i < attached_thread_count; i++) 3563 { 3564 ret = GetExitCodeThread(attached_thread[i], &code); 3565 trace("child: GetExitCodeThread(%lu) => %ld,%lu\n", i, ret, code); 3566 ok(ret == 1, "GetExitCodeThread returned %ld, expected 1\n", ret); 3567 ok(code == STILL_ACTIVE, "expected thread exit code STILL_ACTIVE, got %lu\n", code); 3568 } 3569 3570 ret = WaitForSingleObject(attached_thread[0], 0); 3571 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#lx\n", ret); 3572 ret = WaitForSingleObject(attached_thread[1], 0); 3573 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#lx\n", ret); 3574 3575 ret = WaitForSingleObject(event, 0); 3576 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#lx\n", ret); 3577 ret = WaitForSingleObject(mutex, 0); 3578 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#lx\n", ret); 3579 ret = WaitForSingleObject(semaphore, 0); 3580 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#lx\n", ret); 3581 3582 ret = pRtlDllShutdownInProgress(); 3583 ok(!ret, "RtlDllShutdownInProgress returned %ld\n", ret); 3584 3585 SetLastError(0xdeadbeef); 3586 process = OpenProcess(PROCESS_ALL_ACCESS_NT4, FALSE, GetCurrentProcessId()); 3587 ok(process != NULL, "OpenProcess error %ld\n", GetLastError()); 3588 3589 SetLastError(0xdeadbeef); 3590 ret = TerminateProcess(0, 195); 3591 ok(!ret, "TerminateProcess(0) should fail\n"); 3592 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError()); 3593 3594 Sleep(100); 3595 3596 affinity = 1; 3597 ret = pNtSetInformationProcess(process, ProcessAffinityMask, &affinity, sizeof(affinity)); 3598 ok(!ret, "NtSetInformationProcess error %#lx\n", ret); 3599 3600 switch (test_dll_phase) 3601 { 3602 case 0: 3603 ret = pRtlDllShutdownInProgress(); 3604 ok(!ret, "RtlDllShutdownInProgress returned %ld\n", ret); 3605 3606 trace("call NtTerminateProcess(0, 195)\n"); 3607 ret = pNtTerminateProcess(0, 195); 3608 ok(!ret, "NtTerminateProcess error %#lx\n", ret); 3609 3610 memset(&pbi, 0, sizeof(pbi)); 3611 ret = pNtQueryInformationProcess(process, ProcessBasicInformation, &pbi, sizeof(pbi), NULL); 3612 ok(!ret, "NtQueryInformationProcess error %#lx\n", ret); 3613 ok(pbi.ExitStatus == STILL_ACTIVE || pbi.ExitStatus == 195, 3614 "expected STILL_ACTIVE, got %lu\n", pbi.ExitStatus); 3615 affinity = 1; 3616 ret = pNtSetInformationProcess(process, ProcessAffinityMask, &affinity, sizeof(affinity)); 3617 ok(!ret, "NtSetInformationProcess error %#lx\n", ret); 3618 3619 ret = pRtlDllShutdownInProgress(); 3620 ok(!ret, "RtlDllShutdownInProgress returned %ld\n", ret); 3621 3622 hmod = GetModuleHandleA(dll_name); 3623 ok(hmod != 0, "DLL should not be unloaded\n"); 3624 3625#ifdef __REACTOS__ 3626 if (GetNTVersion() >= _WIN32_WINNT_VISTA) { 3627#endif 3628 SetLastError(0xdeadbeef); 3629 thread = CreateThread(NULL, 0, noop_thread_proc, &dummy, 0, &ret); 3630 ok(!thread, "CreateThread should fail\n"); 3631 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError()); 3632#ifdef __REACTOS__ 3633 } 3634#endif 3635 3636 trace("call LdrShutdownProcess()\n"); 3637 pLdrRegisterDllNotification(0, ldr_notify_callback, NULL, &cookie); 3638 pLdrShutdownProcess(); 3639 3640 ret = pRtlDllShutdownInProgress(); 3641 ok(ret, "RtlDllShutdownInProgress returned %ld\n", ret); 3642 3643 hmod = GetModuleHandleA(dll_name); 3644 ok(hmod != 0, "DLL should not be unloaded\n"); 3645 3646 memset(&pbi, 0, sizeof(pbi)); 3647 ret = pNtQueryInformationProcess(process, ProcessBasicInformation, &pbi, sizeof(pbi), NULL); 3648 ok(!ret, "NtQueryInformationProcess error %#lx\n", ret); 3649 ok(pbi.ExitStatus == STILL_ACTIVE || pbi.ExitStatus == 195, 3650 "expected STILL_ACTIVE, got %lu\n", pbi.ExitStatus); 3651 affinity = 1; 3652 ret = pNtSetInformationProcess(process, ProcessAffinityMask, &affinity, sizeof(affinity)); 3653 ok(!ret, "NtSetInformationProcess error %#lx\n", ret); 3654 break; 3655 3656 case 1: /* normal ExitProcess */ 3657 ret = pRtlDllShutdownInProgress(); 3658 ok(!ret, "RtlDllShutdownInProgress returned %ld\n", ret); 3659 break; 3660 3661 case 2: /* ExitProcess will be called by the PROCESS_DETACH handler */ 3662 ret = pRtlDllShutdownInProgress(); 3663 ok(!ret, "RtlDllShutdownInProgress returned %ld\n", ret); 3664 3665 trace("call FreeLibrary(%p)\n", hmod); 3666 SetLastError(0xdeadbeef); 3667 ret = FreeLibrary(hmod); 3668 ok(ret, "FreeLibrary error %ld\n", GetLastError()); 3669 hmod = GetModuleHandleA(dll_name); 3670 ok(!hmod, "DLL should be unloaded\n"); 3671 3672 if (test_dll_phase == 2) 3673 ok(0, "FreeLibrary+ExitProcess should never return\n"); 3674 3675 ret = pRtlDllShutdownInProgress(); 3676 ok(!ret, "RtlDllShutdownInProgress returned %ld\n", ret); 3677 3678 break; 3679 3680 case 3: 3681 trace("signalling thread exit\n"); 3682 SetEvent(stop_event); 3683 break; 3684 3685 case 4: 3686 trace("setting loader_lock_event\n"); 3687 SetEvent(loader_lock_event); 3688 WaitForSingleObject(ack_event, 1000); 3689 ok(inside_loader_lock != 0, "inside_loader_lock is not set\n"); 3690 3691 /* calling NtTerminateProcess should not cause a deadlock */ 3692 trace("call NtTerminateProcess(0, 198)\n"); 3693 ret = pNtTerminateProcess(0, 198); 3694 ok(!ret, "NtTerminateProcess error %#lx\n", ret); 3695 3696 *child_failures = winetest_get_failures(); 3697 3698 /* Windows fails to release loader lock acquired from another thread, 3699 * so the LdrUnlockLoaderLock call fails here and ExitProcess deadlocks 3700 * later on, so NtTerminateProcess is used instead. 3701 */ 3702 trace("call NtTerminateProcess(GetCurrentProcess(), 198)\n"); 3703 pNtTerminateProcess(GetCurrentProcess(), 198); 3704 ok(0, "NtTerminateProcess should not return\n"); 3705 break; 3706 3707 case 5: 3708 trace("setting peb_lock_event\n"); 3709 SetEvent(peb_lock_event); 3710 WaitForSingleObject(ack_event, 1000); 3711 ok(inside_peb_lock != 0, "inside_peb_lock is not set\n"); 3712 3713 *child_failures = winetest_get_failures(); 3714 3715 /* calling ExitProcess should cause a deadlock */ 3716 trace("call ExitProcess(198)\n"); 3717 ExitProcess(198); 3718 ok(0, "ExitProcess should not return\n"); 3719 break; 3720 3721 case 6: 3722 trace("setting heap_lock_event\n"); 3723 SetEvent(heap_lock_event); 3724 WaitForSingleObject(ack_event, 1000); 3725 ok(inside_heap_lock != 0, "inside_heap_lock is not set\n"); 3726 3727 *child_failures = winetest_get_failures(); 3728 3729 /* calling ExitProcess should cause a deadlock */ 3730 trace("call ExitProcess(1)\n"); 3731 ExitProcess(1); 3732 ok(0, "ExitProcess should not return\n"); 3733 break; 3734 3735 case 7: 3736 trace("setting cs_lock_event\n"); 3737 SetEvent(cs_lock_event); 3738 WaitForSingleObject(ack_event, 1000); 3739 ok(inside_cs_lock != 0, "inside_cs_lock is not set\n"); 3740 3741 *child_failures = winetest_get_failures(); 3742 3743 /* calling ExitProcess should not cause a deadlock */ 3744 trace("call ExitProcess(199)\n"); 3745 ExitProcess(199); 3746 ok(0, "ExitProcess should not return\n"); 3747 break; 3748 3749 default: 3750 assert(0); 3751 break; 3752 } 3753 3754 if (test_dll_phase == 0) expected_code = 195; 3755 else if (test_dll_phase == 3) expected_code = 196; 3756 else if (test_dll_phase == 4) expected_code = 198; 3757 else expected_code = STILL_ACTIVE; 3758 3759 if (expected_code == STILL_ACTIVE) 3760 { 3761 ret = WaitForSingleObject(attached_thread[0], 100); 3762 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#lx\n", ret); 3763 ret = WaitForSingleObject(attached_thread[1], 100); 3764 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#lx\n", ret); 3765 } 3766 else 3767 { 3768 ret = WaitForSingleObject(attached_thread[0], 2000); 3769 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %#lx\n", ret); 3770 ret = WaitForSingleObject(attached_thread[1], 2000); 3771 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %#lx\n", ret); 3772 } 3773 3774 for (i = 0; i < attached_thread_count; i++) 3775 { 3776 ret = GetExitCodeThread(attached_thread[i], &code); 3777 trace("child: GetExitCodeThread(%lu) => %ld,%lu\n", i, ret, code); 3778 ok(ret == 1, "GetExitCodeThread returned %ld, expected 1\n", ret); 3779 ok(code == expected_code, "expected thread exit code %lu, got %lu\n", expected_code, code); 3780 } 3781 3782 *child_failures = winetest_get_failures(); 3783 3784 trace("call ExitProcess(195)\n"); 3785 ExitProcess(195); 3786} 3787 3788static void test_ExitProcess(void) 3789{ 3790#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) 3791#include "pshpack1.h" 3792#ifdef __x86_64__ 3793 static struct section_data 3794 { 3795 BYTE mov_rax[2]; 3796 void *target; 3797 BYTE jmp_rax[2]; 3798 } section_data = { { 0x48,0xb8 }, dll_entry_point, { 0xff,0xe0 } }; 3799#elif defined(__i386__) 3800 static struct section_data 3801 { 3802 BYTE mov_eax; 3803 void *target; 3804 BYTE jmp_eax[2]; 3805 } section_data = { 0xb8, dll_entry_point, { 0xff,0xe0 } }; 3806#elif defined(__aarch64__) 3807 static struct section_data 3808 { 3809 DWORD ldr; /* ldr x0,target */ 3810 DWORD br; /* br x0 */ 3811 void *target; 3812 } section_data = { 0x58000040, 0xd61f0000, dll_entry_point }; 3813#endif 3814#include "poppack.h" 3815 DWORD dummy, file_align; 3816 HANDLE file, thread, process, hmap, hmap_dup; 3817 char temp_path[MAX_PATH], dll_name[MAX_PATH], cmdline[MAX_PATH * 2]; 3818 DWORD ret, target_offset, old_prot; 3819 char **argv, buf[256]; 3820 PROCESS_INFORMATION pi; 3821 STARTUPINFOA si = { sizeof(si) }; 3822 CONTEXT ctx; 3823 struct PROCESS_BASIC_INFORMATION_PRIVATE pbi; 3824 MEMORY_BASIC_INFORMATION mbi; 3825 DWORD_PTR affinity; 3826 void *addr; 3827 LARGE_INTEGER offset; 3828 SIZE_T size; 3829 IMAGE_NT_HEADERS nt_header; 3830 3831 if (!pRtlDllShutdownInProgress) 3832 { 3833 win_skip("RtlDllShutdownInProgress is not available on this platform (XP+)\n"); 3834 return; 3835 } 3836 if (!pNtQueryInformationProcess || !pNtSetInformationProcess) 3837 { 3838 win_skip("NtQueryInformationProcess/NtSetInformationProcess are not available on this platform\n"); 3839 return; 3840 } 3841 if (!pNtAllocateVirtualMemory || !pNtFreeVirtualMemory) 3842 { 3843 win_skip("NtAllocateVirtualMemory/NtFreeVirtualMemory are not available on this platform\n"); 3844 return; 3845 } 3846 3847 /* prevent displaying of the "Unable to load this DLL" message box */ 3848 SetErrorMode(SEM_FAILCRITICALERRORS); 3849 3850 GetTempPathA(MAX_PATH, temp_path); 3851 GetTempFileNameA(temp_path, "ldr", 0, dll_name); 3852 3853 /*trace("creating %s\n", dll_name);*/ 3854 file = CreateFileA(dll_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); 3855 if (file == INVALID_HANDLE_VALUE) 3856 { 3857 ok(0, "could not create %s\n", dll_name); 3858 return; 3859 } 3860 3861 SetLastError(0xdeadbeef); 3862 ret = WriteFile(file, &dos_header, sizeof(dos_header), &dummy, NULL); 3863 ok(ret, "WriteFile error %ld\n", GetLastError()); 3864 3865 nt_header = nt_header_template; 3866 nt_header.OptionalHeader.AddressOfEntryPoint = 0x1000; 3867 nt_header.OptionalHeader.SectionAlignment = 0x1000; 3868 nt_header.OptionalHeader.FileAlignment = 0x200; 3869 nt_header.OptionalHeader.SizeOfImage = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x1000; 3870 nt_header.OptionalHeader.SizeOfHeaders = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER); 3871 SetLastError(0xdeadbeef); 3872 ret = WriteFile(file, &nt_header, sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER), &dummy, NULL); 3873 ok(ret, "WriteFile error %ld\n", GetLastError()); 3874 SetLastError(0xdeadbeef); 3875 ret = WriteFile(file, &nt_header.OptionalHeader, sizeof(IMAGE_OPTIONAL_HEADER), &dummy, NULL); 3876 ok(ret, "WriteFile error %ld\n", GetLastError()); 3877 3878 section.SizeOfRawData = sizeof(section_data); 3879 section.PointerToRawData = nt_header.OptionalHeader.FileAlignment; 3880 section.VirtualAddress = nt_header.OptionalHeader.SectionAlignment; 3881 section.Misc.VirtualSize = sizeof(section_data); 3882 section.Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE; 3883 SetLastError(0xdeadbeef); 3884 ret = WriteFile(file, &section, sizeof(section), &dummy, NULL); 3885 ok(ret, "WriteFile error %ld\n", GetLastError()); 3886 3887 file_align = nt_header.OptionalHeader.FileAlignment - nt_header.OptionalHeader.SizeOfHeaders; 3888 assert(file_align < sizeof(filler)); 3889 SetLastError(0xdeadbeef); 3890 ret = WriteFile(file, filler, file_align, &dummy, NULL); 3891 ok(ret, "WriteFile error %ld\n", GetLastError()); 3892 3893 target_offset = SetFilePointer(file, 0, NULL, FILE_CURRENT) + FIELD_OFFSET(struct section_data, target); 3894 3895 /* section data */ 3896 SetLastError(0xdeadbeef); 3897 ret = WriteFile(file, &section_data, sizeof(section_data), &dummy, NULL); 3898 ok(ret, "WriteFile error %ld\n", GetLastError()); 3899 3900 CloseHandle(file); 3901 3902 winetest_get_mainargs(&argv); 3903 3904 /* phase 0 */ 3905 *child_failures = -1; 3906 sprintf(cmdline, "\"%s\" loader %s %lu 0", argv[0], dll_name, target_offset); 3907 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 3908 ok(ret, "CreateProcess(%s) error %ld\n", cmdline, GetLastError()); 3909 ret = WaitForSingleObject(pi.hProcess, 10000); 3910 ok(ret == WAIT_OBJECT_0, "child process failed to terminate\n"); 3911 if (ret != WAIT_OBJECT_0) TerminateProcess(pi.hProcess, 0); 3912 GetExitCodeProcess(pi.hProcess, &ret); 3913#ifdef __REACTOS__ 3914 ok(ret == 195 || broken(ret == 0xc0000005) /* WS03 */, "expected exit code 195, got %lu\n", ret); 3915#else 3916 ok(ret == 195, "expected exit code 195, got %lu\n", ret); 3917#endif 3918 if (*child_failures) 3919 { 3920 trace("%ld failures in child process\n", *child_failures); 3921 winetest_add_failures(*child_failures); 3922 } 3923 CloseHandle(pi.hThread); 3924 CloseHandle(pi.hProcess); 3925 3926 /* phase 1 */ 3927 *child_failures = -1; 3928 sprintf(cmdline, "\"%s\" loader %s %lu 1", argv[0], dll_name, target_offset); 3929 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 3930 ok(ret, "CreateProcess(%s) error %ld\n", cmdline, GetLastError()); 3931 ret = WaitForSingleObject(pi.hProcess, 10000); 3932 ok(ret == WAIT_OBJECT_0, "child process failed to terminate\n"); 3933 if (ret != WAIT_OBJECT_0) TerminateProcess(pi.hProcess, 0); 3934 GetExitCodeProcess(pi.hProcess, &ret); 3935 ok(ret == 195, "expected exit code 195, got %lu\n", ret); 3936 if (*child_failures) 3937 { 3938 trace("%ld failures in child process\n", *child_failures); 3939 winetest_add_failures(*child_failures); 3940 } 3941 CloseHandle(pi.hThread); 3942 CloseHandle(pi.hProcess); 3943 3944 /* phase 2 */ 3945 *child_failures = -1; 3946 sprintf(cmdline, "\"%s\" loader %s %lu 2", argv[0], dll_name, target_offset); 3947 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 3948 ok(ret, "CreateProcess(%s) error %ld\n", cmdline, GetLastError()); 3949 ret = WaitForSingleObject(pi.hProcess, 10000); 3950 ok(ret == WAIT_OBJECT_0, "child process failed to terminate\n"); 3951 if (ret != WAIT_OBJECT_0) TerminateProcess(pi.hProcess, 0); 3952 GetExitCodeProcess(pi.hProcess, &ret); 3953 ok(ret == 197, "expected exit code 197, got %lu\n", ret); 3954 if (*child_failures) 3955 { 3956 trace("%ld failures in child process\n", *child_failures); 3957 winetest_add_failures(*child_failures); 3958 } 3959 CloseHandle(pi.hThread); 3960 CloseHandle(pi.hProcess); 3961 3962 /* phase 3 */ 3963 *child_failures = -1; 3964 sprintf(cmdline, "\"%s\" loader %s %lu 3", argv[0], dll_name, target_offset); 3965 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 3966 ok(ret, "CreateProcess(%s) error %ld\n", cmdline, GetLastError()); 3967 ret = WaitForSingleObject(pi.hProcess, 10000); 3968 ok(ret == WAIT_OBJECT_0, "child process failed to terminate\n"); 3969 if (ret != WAIT_OBJECT_0) TerminateProcess(pi.hProcess, 0); 3970 GetExitCodeProcess(pi.hProcess, &ret); 3971 ok(ret == 195, "expected exit code 195, got %lu\n", ret); 3972 if (*child_failures) 3973 { 3974 trace("%ld failures in child process\n", *child_failures); 3975 winetest_add_failures(*child_failures); 3976 } 3977 CloseHandle(pi.hThread); 3978 CloseHandle(pi.hProcess); 3979 3980 /* phase 4 */ 3981 if (pLdrLockLoaderLock && pLdrUnlockLoaderLock) 3982 { 3983 *child_failures = -1; 3984 sprintf(cmdline, "\"%s\" loader %s %lu 4", argv[0], dll_name, target_offset); 3985 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 3986 ok(ret, "CreateProcess(%s) error %ld\n", cmdline, GetLastError()); 3987 ret = WaitForSingleObject(pi.hProcess, 10000); 3988 ok(ret == WAIT_OBJECT_0, "child process failed to terminate\n"); 3989 if (ret != WAIT_OBJECT_0) TerminateProcess(pi.hProcess, 0); 3990 GetExitCodeProcess(pi.hProcess, &ret); 3991 ok(ret == 198, "expected exit code 198, got %lu\n", ret); 3992 if (*child_failures) 3993 { 3994 trace("%ld failures in child process\n", *child_failures); 3995 winetest_add_failures(*child_failures); 3996 } 3997 CloseHandle(pi.hThread); 3998 CloseHandle(pi.hProcess); 3999 } 4000 else 4001 win_skip("LdrLockLoaderLock/LdrUnlockLoaderLock are not available on this platform\n"); 4002 4003 /* phase 5 */ 4004 if (pRtlAcquirePebLock && pRtlReleasePebLock) 4005 { 4006 *child_failures = -1; 4007 sprintf(cmdline, "\"%s\" loader %s %lu 5", argv[0], dll_name, target_offset); 4008 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 4009 ok(ret, "CreateProcess(%s) error %ld\n", cmdline, GetLastError()); 4010 ret = WaitForSingleObject(pi.hProcess, 5000); 4011 ok(ret == WAIT_TIMEOUT, "child process should fail to terminate\n"); 4012 if (ret != WAIT_OBJECT_0) 4013 { 4014 trace("terminating child process\n"); 4015 TerminateProcess(pi.hProcess, 199); 4016 } 4017 ret = WaitForSingleObject(pi.hProcess, 1000); 4018 ok(ret == WAIT_OBJECT_0, "child process failed to terminate\n"); 4019 GetExitCodeProcess(pi.hProcess, &ret); 4020 ok(ret == 199, "expected exit code 199, got %lu\n", ret); 4021 if (*child_failures) 4022 { 4023 trace("%ld failures in child process\n", *child_failures); 4024 winetest_add_failures(*child_failures); 4025 } 4026 CloseHandle(pi.hThread); 4027 CloseHandle(pi.hProcess); 4028 } 4029 else 4030 win_skip("RtlAcquirePebLock/RtlReleasePebLock are not available on this platform\n"); 4031 4032 /* phase 6 */ 4033 *child_failures = -1; 4034 sprintf(cmdline, "\"%s\" loader %s %lu 6", argv[0], dll_name, target_offset); 4035 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 4036 ok(ret, "CreateProcess(%s) error %ld\n", cmdline, GetLastError()); 4037 ret = WaitForSingleObject(pi.hProcess, 5000); 4038 todo_wine 4039#ifdef __REACTOS__ 4040 ok(ret == WAIT_TIMEOUT || broken(ret == WAIT_OBJECT_0) /* WS03 */, "child process should fail to terminate\n"); 4041#else 4042 ok(ret == WAIT_TIMEOUT, "child process should fail to terminate\n"); 4043#endif 4044 if (ret != WAIT_OBJECT_0) 4045 { 4046 trace("terminating child process\n"); 4047 TerminateProcess(pi.hProcess, 201); 4048 } 4049 ret = WaitForSingleObject(pi.hProcess, 1000); 4050 ok(ret == WAIT_OBJECT_0, "child process failed to terminate\n"); 4051 GetExitCodeProcess(pi.hProcess, &ret); 4052 todo_wine 4053#ifdef __REACTOS__ 4054 ok(ret == 201 || broken(ret == 1) /* WS03 */, "expected exit code 201, got %lu\n", ret); 4055#else 4056 ok(ret == 201, "expected exit code 201, got %lu\n", ret); 4057#endif 4058 if (*child_failures) 4059 { 4060 trace("%ld failures in child process\n", *child_failures); 4061 winetest_add_failures(*child_failures); 4062 } 4063 CloseHandle(pi.hThread); 4064 CloseHandle(pi.hProcess); 4065 4066 /* phase 7 */ 4067 *child_failures = -1; 4068 sprintf(cmdline, "\"%s\" loader %s %lu 7", argv[0], dll_name, target_offset); 4069 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 4070 ok(ret, "CreateProcess(%s) error %ld\n", cmdline, GetLastError()); 4071 ret = WaitForSingleObject(pi.hProcess, 5000); 4072 ok(ret == WAIT_OBJECT_0, "child process failed to terminate\n"); 4073 if (ret != WAIT_OBJECT_0) 4074 { 4075 trace("terminating child process\n"); 4076 TerminateProcess(pi.hProcess, 199); 4077 } 4078 ret = WaitForSingleObject(pi.hProcess, 1000); 4079 ok(ret == WAIT_OBJECT_0, "child process failed to terminate\n"); 4080 GetExitCodeProcess(pi.hProcess, &ret); 4081 ok(ret == 199, "expected exit code 199, got %lu\n", ret); 4082 if (*child_failures) 4083 { 4084 trace("%ld failures in child process\n", *child_failures); 4085 winetest_add_failures(*child_failures); 4086 } 4087 CloseHandle(pi.hThread); 4088 CloseHandle(pi.hProcess); 4089 4090 /* test remote process termination */ 4091 SetLastError(0xdeadbeef); 4092 ret = CreateProcessA(argv[0], NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi); 4093 ok(ret, "CreateProcess(%s) error %ld\n", argv[0], GetLastError()); 4094 4095 SetLastError(0xdeadbeef); 4096 addr = VirtualAllocEx(pi.hProcess, NULL, 4096, MEM_COMMIT, PAGE_READWRITE); 4097 ok(addr != NULL, "VirtualAllocEx error %ld\n", GetLastError()); 4098 SetLastError(0xdeadbeef); 4099 ret = VirtualProtectEx(pi.hProcess, addr, 4096, PAGE_READONLY, &old_prot); 4100 ok(ret, "VirtualProtectEx error %ld\n", GetLastError()); 4101 ok(old_prot == PAGE_READWRITE, "expected PAGE_READWRITE, got %#lx\n", old_prot); 4102 SetLastError(0xdeadbeef); 4103 size = VirtualQueryEx(pi.hProcess, NULL, &mbi, sizeof(mbi)); 4104 ok(size == sizeof(mbi), "VirtualQueryEx error %ld\n", GetLastError()); 4105 4106 SetLastError(0xdeadbeef); 4107 ret = ReadProcessMemory(pi.hProcess, addr, buf, 4, &size); 4108 ok(ret, "ReadProcessMemory error %ld\n", GetLastError()); 4109 ok(size == 4, "expected 4, got %Iu\n", size); 4110 4111 SetLastError(0xdeadbeef); 4112 hmap = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, NULL); 4113 ok(hmap != 0, "CreateFileMapping error %ld\n", GetLastError()); 4114 4115 SetLastError(0xdeadbeef); 4116 ret = DuplicateHandle(GetCurrentProcess(), hmap, pi.hProcess, &hmap_dup, 4117 0, FALSE, DUPLICATE_SAME_ACCESS); 4118 ok(ret, "DuplicateHandle error %ld\n", GetLastError()); 4119 4120 offset.u.LowPart = 0; 4121 offset.u.HighPart = 0; 4122 addr = NULL; 4123 size = 0; 4124 ret = pNtMapViewOfSection(hmap, pi.hProcess, &addr, 0, 0, &offset, 4125 &size, 1 /* ViewShare */, 0, PAGE_READONLY); 4126 ok(!ret, "NtMapViewOfSection error %#lx\n", ret); 4127 ret = pNtUnmapViewOfSection(pi.hProcess, addr); 4128 ok(!ret, "NtUnmapViewOfSection error %#lx\n", ret); 4129 4130 SetLastError(0xdeadbeef); 4131 thread = CreateRemoteThread(pi.hProcess, NULL, 0, (void *)0xdeadbeef, NULL, CREATE_SUSPENDED, &ret); 4132 ok(thread != 0, "CreateRemoteThread error %ld\n", GetLastError()); 4133 SetLastError(0xdeadbeef); 4134 ctx.ContextFlags = CONTEXT_INTEGER; 4135 ret = GetThreadContext(thread, &ctx); 4136 ok(ret, "GetThreadContext error %ld\n", GetLastError()); 4137 SetLastError(0xdeadbeef); 4138 ctx.ContextFlags = CONTEXT_INTEGER; 4139 ret = SetThreadContext(thread, &ctx); 4140 ok(ret, "SetThreadContext error %ld\n", GetLastError()); 4141 SetLastError(0xdeadbeef); 4142 ret = SetThreadPriority(thread, 0); 4143 ok(ret, "SetThreadPriority error %ld\n", GetLastError()); 4144 4145 SetLastError(0xdeadbeef); 4146 ret = TerminateThread(thread, 199); 4147 ok(ret, "TerminateThread error %ld\n", GetLastError()); 4148 /* Calling GetExitCodeThread() without waiting for thread termination 4149 * leads to different results due to a race condition. 4150 */ 4151 ret = WaitForSingleObject(thread, 1000); 4152 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed: %lx\n", ret); 4153 GetExitCodeThread(thread, &ret); 4154 ok(ret == 199, "expected exit code 199, got %lu\n", ret); 4155 4156 SetLastError(0xdeadbeef); 4157 ret = TerminateProcess(pi.hProcess, 198); 4158 ok(ret, "TerminateProcess error %ld\n", GetLastError()); 4159 /* Checking process state without waiting for process termination 4160 * leads to different results due to a race condition. 4161 */ 4162 ret = WaitForSingleObject(pi.hProcess, 1000); 4163 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed: %lx\n", ret); 4164 4165 SetLastError(0xdeadbeef); 4166 process = OpenProcess(PROCESS_ALL_ACCESS_NT4, FALSE, pi.dwProcessId); 4167 ok(process != NULL, "OpenProcess error %ld\n", GetLastError()); 4168 CloseHandle(process); 4169 4170 memset(&pbi, 0, sizeof(pbi)); 4171 ret = pNtQueryInformationProcess(pi.hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), NULL); 4172 ok(!ret, "NtQueryInformationProcess error %#lx\n", ret); 4173 ok(pbi.ExitStatus == 198, "expected 198, got %lu\n", pbi.ExitStatus); 4174 affinity = 1; 4175 ret = pNtSetInformationProcess(pi.hProcess, ProcessAffinityMask, &affinity, sizeof(affinity)); 4176 ok(ret == STATUS_PROCESS_IS_TERMINATING, "expected STATUS_PROCESS_IS_TERMINATING, got %#lx\n", ret); 4177 4178 SetLastError(0xdeadbeef); 4179 ctx.ContextFlags = CONTEXT_INTEGER; 4180 ret = GetThreadContext(thread, &ctx); 4181 ok(!ret, "GetThreadContext should fail\n"); 4182 ok(GetLastError() == ERROR_INVALID_PARAMETER || 4183 GetLastError() == ERROR_GEN_FAILURE /* win7 64-bit */ || 4184 GetLastError() == ERROR_INVALID_FUNCTION /* vista 64-bit */ || 4185 GetLastError() == ERROR_ACCESS_DENIED /* Win10 32-bit */, 4186 "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError()); 4187 SetLastError(0xdeadbeef); 4188 ctx.ContextFlags = CONTEXT_INTEGER; 4189 ret = SetThreadContext(thread, &ctx); 4190 ok(!ret, "SetThreadContext should fail\n"); 4191 ok(GetLastError() == ERROR_ACCESS_DENIED || 4192 GetLastError() == ERROR_GEN_FAILURE /* win7 64-bit */ || 4193 GetLastError() == ERROR_INVALID_FUNCTION /* vista 64-bit */, 4194 "expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError()); 4195 SetLastError(0xdeadbeef); 4196 ret = SetThreadPriority(thread, 0); 4197 ok(ret, "SetThreadPriority error %ld\n", GetLastError()); 4198 CloseHandle(thread); 4199 4200 ret = WaitForSingleObject(pi.hThread, 1000); 4201 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed: %lx\n", ret); 4202 SetLastError(0xdeadbeef); 4203 ctx.ContextFlags = CONTEXT_INTEGER; 4204 ret = GetThreadContext(pi.hThread, &ctx); 4205 ok(!ret, "GetThreadContext should fail\n"); 4206 ok(GetLastError() == ERROR_INVALID_PARAMETER || 4207 GetLastError() == ERROR_GEN_FAILURE /* win7 64-bit */ || 4208 GetLastError() == ERROR_INVALID_FUNCTION /* vista 64-bit */ || 4209 GetLastError() == ERROR_ACCESS_DENIED /* Win10 32-bit */, 4210 "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError()); 4211 SetLastError(0xdeadbeef); 4212 ctx.ContextFlags = CONTEXT_INTEGER; 4213 ret = SetThreadContext(pi.hThread, &ctx); 4214 ok(!ret, "SetThreadContext should fail\n"); 4215 ok(GetLastError() == ERROR_ACCESS_DENIED || 4216 GetLastError() == ERROR_GEN_FAILURE /* win7 64-bit */ || 4217 GetLastError() == ERROR_INVALID_FUNCTION /* vista 64-bit */, 4218 "expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError()); 4219 SetLastError(0xdeadbeef); 4220 ret = VirtualProtectEx(pi.hProcess, addr, 4096, PAGE_READWRITE, &old_prot); 4221 ok(!ret, "VirtualProtectEx should fail\n"); 4222 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError()); 4223 SetLastError(0xdeadbeef); 4224 size = 0; 4225 ret = ReadProcessMemory(pi.hProcess, addr, buf, 4, &size); 4226 ok(!ret, "ReadProcessMemory should fail\n"); 4227 ok(GetLastError() == ERROR_PARTIAL_COPY || GetLastError() == ERROR_ACCESS_DENIED, 4228 "expected ERROR_PARTIAL_COPY, got %ld\n", GetLastError()); 4229 ok(!size, "expected 0, got %Iu\n", size); 4230 SetLastError(0xdeadbeef); 4231 ret = VirtualFreeEx(pi.hProcess, addr, 0, MEM_RELEASE); 4232 ok(!ret, "VirtualFreeEx should fail\n"); 4233 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError()); 4234 SetLastError(0xdeadbeef); 4235 addr = VirtualAllocEx(pi.hProcess, NULL, 4096, MEM_COMMIT, PAGE_READWRITE); 4236 ok(!addr, "VirtualAllocEx should fail\n"); 4237 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError()); 4238 SetLastError(0xdeadbeef); 4239 size = VirtualQueryEx(pi.hProcess, NULL, &mbi, sizeof(mbi)); 4240 ok(!size, "VirtualQueryEx should fail\n"); 4241 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError()); 4242 4243 /* CloseHandle() call below leads to premature process termination 4244 * under some Windows versions. 4245 */ 4246if (0) 4247{ 4248 SetLastError(0xdeadbeef); 4249 ret = CloseHandle(hmap_dup); 4250 ok(ret, "CloseHandle should not fail\n"); 4251} 4252 4253 SetLastError(0xdeadbeef); 4254 ret = DuplicateHandle(GetCurrentProcess(), hmap, pi.hProcess, &hmap_dup, 4255 0, FALSE, DUPLICATE_SAME_ACCESS); 4256 ok(!ret, "DuplicateHandle should fail\n"); 4257 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError()); 4258 4259 offset.u.LowPart = 0; 4260 offset.u.HighPart = 0; 4261 addr = NULL; 4262 size = 0; 4263 ret = pNtMapViewOfSection(hmap, pi.hProcess, &addr, 0, 0, &offset, 4264 &size, 1 /* ViewShare */, 0, PAGE_READONLY); 4265 ok(ret == STATUS_PROCESS_IS_TERMINATING, "expected STATUS_PROCESS_IS_TERMINATING, got %#lx\n", ret); 4266 4267 SetLastError(0xdeadbeef); 4268 thread = CreateRemoteThread(pi.hProcess, NULL, 0, (void *)0xdeadbeef, NULL, CREATE_SUSPENDED, &ret); 4269 ok(!thread, "CreateRemoteThread should fail\n"); 4270 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError()); 4271 4272 SetLastError(0xdeadbeef); 4273 ret = DebugActiveProcess(pi.dwProcessId); 4274 ok(!ret, "DebugActiveProcess should fail\n"); 4275 ok(GetLastError() == ERROR_ACCESS_DENIED /* 64-bit */ || GetLastError() == ERROR_NOT_SUPPORTED /* 32-bit */, 4276 "ERROR_ACCESS_DENIED, got %ld\n", GetLastError()); 4277 4278 GetExitCodeProcess(pi.hProcess, &ret); 4279 ok(ret == 198, "expected exit code 198, got %lu\n", ret); 4280 CloseHandle(pi.hThread); 4281 CloseHandle(pi.hProcess); 4282 4283 ret = DeleteFileA(dll_name); 4284 ok(ret, "DeleteFile error %ld\n", GetLastError()); 4285#else 4286 skip("x86 specific ExitProcess test\n"); 4287#endif 4288} 4289 4290static PVOID WINAPI failuredllhook(ULONG ul, DELAYLOAD_INFO* pd) 4291{ 4292 ok(ul == 4, "expected 4, got %lu\n", ul); 4293 ok(!!pd, "no delayload info supplied\n"); 4294 if (pd) 4295 { 4296 ok(pd->Size == sizeof(*pd), "got %lu\n", pd->Size); 4297 ok(!!pd->DelayloadDescriptor, "no DelayloadDescriptor supplied\n"); 4298 if (pd->DelayloadDescriptor) 4299 { 4300 ok(pd->DelayloadDescriptor->Attributes.AllAttributes == 1, 4301 "expected 1, got %lu\n", pd->DelayloadDescriptor->Attributes.AllAttributes); 4302 ok(pd->DelayloadDescriptor->DllNameRVA == 0x2000, 4303 "expected 0x2000, got %lx\n", pd->DelayloadDescriptor->DllNameRVA); 4304 ok(pd->DelayloadDescriptor->ModuleHandleRVA == 0x201a, 4305 "expected 0x201a, got %lx\n", pd->DelayloadDescriptor->ModuleHandleRVA); 4306 ok(pd->DelayloadDescriptor->ImportAddressTableRVA > pd->DelayloadDescriptor->ModuleHandleRVA, 4307 "expected %lx > %lx\n", pd->DelayloadDescriptor->ImportAddressTableRVA, 4308 pd->DelayloadDescriptor->ModuleHandleRVA); 4309 ok(pd->DelayloadDescriptor->ImportNameTableRVA > pd->DelayloadDescriptor->ImportAddressTableRVA, 4310 "expected %lx > %lx\n", pd->DelayloadDescriptor->ImportNameTableRVA, 4311 pd->DelayloadDescriptor->ImportAddressTableRVA); 4312 ok(pd->DelayloadDescriptor->BoundImportAddressTableRVA == 0, 4313 "expected 0, got %lx\n", pd->DelayloadDescriptor->BoundImportAddressTableRVA); 4314 ok(pd->DelayloadDescriptor->UnloadInformationTableRVA == 0, 4315 "expected 0, got %lx\n", pd->DelayloadDescriptor->UnloadInformationTableRVA); 4316 ok(pd->DelayloadDescriptor->TimeDateStamp == 0, 4317 "expected 0, got %lx\n", pd->DelayloadDescriptor->TimeDateStamp); 4318 } 4319 4320 ok(!!pd->ThunkAddress, "no ThunkAddress supplied\n"); 4321 if (pd->ThunkAddress) 4322 ok(pd->ThunkAddress->u1.Ordinal, "no ThunkAddress value supplied\n"); 4323 4324 ok(!!pd->TargetDllName, "no TargetDllName supplied\n"); 4325 if (pd->TargetDllName) 4326 ok(!strcmp(pd->TargetDllName, "secur32.dll"), 4327 "expected \"secur32.dll\", got \"%s\"\n", pd->TargetDllName); 4328 4329 ok(pd->TargetApiDescriptor.ImportDescribedByName == 0, 4330 "expected 0, got %lx\n", pd->TargetApiDescriptor.ImportDescribedByName); 4331 ok(pd->TargetApiDescriptor.Description.Ordinal == 0 || 4332 pd->TargetApiDescriptor.Description.Ordinal == 999, 4333 "expected 0, got %lx\n", pd->TargetApiDescriptor.Description.Ordinal); 4334 4335 ok(!!pd->TargetModuleBase, "no TargetModuleBase supplied\n"); 4336 ok(pd->Unused == NULL, "expected NULL, got %p\n", pd->Unused); 4337 ok(pd->LastError, "no LastError supplied\n"); 4338 } 4339 cb_count++; 4340 return (void*)0xdeadbeef; 4341} 4342 4343static PVOID WINAPI failuresyshook(const char *dll, const char *function) 4344{ 4345 ok(!strcmp(dll, "secur32.dll"), "wrong dll: %s\n", dll); 4346 ok(!((ULONG_PTR)function >> 16), "expected ordinal, got %p\n", function); 4347 cb_count_sys++; 4348 return (void*)0x12345678; 4349} 4350 4351static void test_ResolveDelayLoadedAPI(void) 4352{ 4353 static const char test_dll[] = "secur32.dll"; 4354 static const char test_func[] = "SealMessage"; 4355 char temp_path[MAX_PATH]; 4356 char dll_name[MAX_PATH]; 4357 IMAGE_DELAYLOAD_DESCRIPTOR idd, *delaydir; 4358 IMAGE_THUNK_DATA itd32; 4359 HANDLE hfile; 4360 HMODULE hlib; 4361 DWORD dummy, file_size, i; 4362 WORD hint = 0; 4363 BOOL ret; 4364 IMAGE_NT_HEADERS nt_header; 4365 4366 static const struct test_data 4367 { 4368 BOOL func; 4369 UINT_PTR ordinal; 4370 BOOL succeeds; 4371 } td[] = 4372 { 4373 { 4374 TRUE, 0, TRUE 4375 }, 4376 { 4377 FALSE, IMAGE_ORDINAL_FLAG | 2, TRUE 4378 }, 4379 { 4380 FALSE, IMAGE_ORDINAL_FLAG | 5, TRUE 4381 }, 4382 { 4383 FALSE, IMAGE_ORDINAL_FLAG | 0, FALSE 4384 }, 4385 { 4386 FALSE, IMAGE_ORDINAL_FLAG | 999, FALSE 4387 }, 4388 }; 4389 4390 if (!pResolveDelayLoadedAPI) 4391 { 4392 win_skip("ResolveDelayLoadedAPI is not available\n"); 4393 return; 4394 } 4395 4396 if (0) /* crashes on native */ 4397 { 4398 SetLastError(0xdeadbeef); 4399 ok(!pResolveDelayLoadedAPI(NULL, NULL, NULL, NULL, NULL, 0), 4400 "ResolveDelayLoadedAPI succeeded\n"); 4401 ok(GetLastError() == 0xdeadbeef, "GetLastError changed to %lx\n", GetLastError()); 4402 4403 cb_count = 0; 4404 SetLastError(0xdeadbeef); 4405 ok(!pResolveDelayLoadedAPI(NULL, NULL, failuredllhook, NULL, NULL, 0), 4406 "ResolveDelayLoadedAPI succeeded\n"); 4407 ok(GetLastError() == 0xdeadbeef, "GetLastError changed to %lx\n", GetLastError()); 4408 ok(cb_count == 1, "Wrong callback count: %d\n", cb_count); 4409 } 4410 4411 GetTempPathA(MAX_PATH, temp_path); 4412 GetTempFileNameA(temp_path, "ldr", 0, dll_name); 4413 trace("creating %s\n", dll_name); 4414 hfile = CreateFileA(dll_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); 4415 if (hfile == INVALID_HANDLE_VALUE) 4416 { 4417 ok(0, "could not create %s\n", dll_name); 4418 return; 4419 } 4420 4421 SetLastError(0xdeadbeef); 4422 ret = WriteFile(hfile, &dos_header, sizeof(dos_header), &dummy, NULL); 4423 ok(ret, "WriteFile error %ld\n", GetLastError()); 4424 4425 nt_header = nt_header_template; 4426 nt_header.FileHeader.NumberOfSections = 2; 4427 nt_header.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER); 4428 4429 nt_header.OptionalHeader.SectionAlignment = 0x1000; 4430 nt_header.OptionalHeader.FileAlignment = 0x1000; 4431 nt_header.OptionalHeader.SizeOfImage = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x2200; 4432 nt_header.OptionalHeader.SizeOfHeaders = sizeof(dos_header) + sizeof(nt_header) + 2 * sizeof(IMAGE_SECTION_HEADER); 4433 nt_header.OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES; 4434 nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress = 0x1000; 4435 nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].Size = 2 * sizeof(idd); 4436 4437 SetLastError(0xdeadbeef); 4438 ret = WriteFile(hfile, &nt_header, sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER), &dummy, NULL); 4439 ok(ret, "WriteFile error %ld\n", GetLastError()); 4440 4441 SetLastError(0xdeadbeef); 4442 ret = WriteFile(hfile, &nt_header.OptionalHeader, sizeof(IMAGE_OPTIONAL_HEADER), &dummy, NULL); 4443 ok(ret, "WriteFile error %ld\n", GetLastError()); 4444 4445 /* sections */ 4446 section.PointerToRawData = nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress; 4447 section.VirtualAddress = nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress; 4448 section.Misc.VirtualSize = 0x1000; 4449 section.SizeOfRawData = 2 * sizeof(idd); 4450 section.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ; 4451 SetLastError(0xdeadbeef); 4452 ret = WriteFile(hfile, &section, sizeof(section), &dummy, NULL); 4453 ok(ret, "WriteFile error %ld\n", GetLastError()); 4454 4455 section.PointerToRawData = 0x2000; 4456 section.VirtualAddress = 0x2000; 4457 i = ARRAY_SIZE(td); 4458 section.SizeOfRawData = sizeof(test_dll) + sizeof(hint) + sizeof(test_func) + sizeof(HMODULE) + 4459 2 * (i + 1) * sizeof(IMAGE_THUNK_DATA); 4460 ok(section.SizeOfRawData <= 0x1000, "Too much tests, add a new section!\n"); 4461 section.Misc.VirtualSize = 0x1000; 4462 section.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE; 4463 SetLastError(0xdeadbeef); 4464 ret = WriteFile(hfile, &section, sizeof(section), &dummy, NULL); 4465 ok(ret, "WriteFile error %ld\n", GetLastError()); 4466 4467 /* fill up to delay data */ 4468 SetFilePointer( hfile, nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress, NULL, SEEK_SET ); 4469 4470 /* delay data */ 4471 idd.Attributes.AllAttributes = 1; 4472 idd.DllNameRVA = 0x2000; 4473 idd.ModuleHandleRVA = idd.DllNameRVA + sizeof(test_dll) + sizeof(hint) + sizeof(test_func); 4474 idd.ImportAddressTableRVA = idd.ModuleHandleRVA + sizeof(HMODULE); 4475 idd.ImportNameTableRVA = idd.ImportAddressTableRVA + (i + 1) * sizeof(IMAGE_THUNK_DATA); 4476 idd.BoundImportAddressTableRVA = 0; 4477 idd.UnloadInformationTableRVA = 0; 4478 idd.TimeDateStamp = 0; 4479 4480 SetLastError(0xdeadbeef); 4481 ret = WriteFile(hfile, &idd, sizeof(idd), &dummy, NULL); 4482 ok(ret, "WriteFile error %ld\n", GetLastError()); 4483 4484 SetLastError(0xdeadbeef); 4485 ret = WriteFile(hfile, filler, sizeof(idd), &dummy, NULL); 4486 ok(ret, "WriteFile error %ld\n", GetLastError()); 4487 4488 /* fill up to extended delay data */ 4489 SetFilePointer( hfile, idd.DllNameRVA, NULL, SEEK_SET ); 4490 4491 /* extended delay data */ 4492 SetLastError(0xdeadbeef); 4493 ret = WriteFile(hfile, test_dll, sizeof(test_dll), &dummy, NULL); 4494 ok(ret, "WriteFile error %ld\n", GetLastError()); 4495 4496 SetLastError(0xdeadbeef); 4497 ret = WriteFile(hfile, &hint, sizeof(hint), &dummy, NULL); 4498 ok(ret, "WriteFile error %ld\n", GetLastError()); 4499 4500 SetLastError(0xdeadbeef); 4501 ret = WriteFile(hfile, test_func, sizeof(test_func), &dummy, NULL); 4502 ok(ret, "WriteFile error %ld\n", GetLastError()); 4503 4504 SetFilePointer( hfile, idd.ImportAddressTableRVA, NULL, SEEK_SET ); 4505 4506 for (i = 0; i < ARRAY_SIZE(td); i++) 4507 { 4508 /* 0x1a00 is an empty space between delay data and extended delay data, real thunks are not necessary */ 4509 itd32.u1.Function = nt_header.OptionalHeader.ImageBase + 0x1a00 + i * 0x20; 4510 SetLastError(0xdeadbeef); 4511 ret = WriteFile(hfile, &itd32, sizeof(itd32), &dummy, NULL); 4512 ok(ret, "WriteFile error %ld\n", GetLastError()); 4513 } 4514 4515 itd32.u1.Function = 0; 4516 SetLastError(0xdeadbeef); 4517 ret = WriteFile(hfile, &itd32, sizeof(itd32), &dummy, NULL); 4518 ok(ret, "WriteFile error %ld\n", GetLastError()); 4519 4520 for (i = 0; i < ARRAY_SIZE(td); i++) 4521 { 4522 if (td[i].func) 4523 itd32.u1.AddressOfData = idd.DllNameRVA + sizeof(test_dll); 4524 else 4525 itd32.u1.Ordinal = td[i].ordinal; 4526 SetLastError(0xdeadbeef); 4527 ret = WriteFile(hfile, &itd32, sizeof(itd32), &dummy, NULL); 4528 ok(ret, "WriteFile error %ld\n", GetLastError()); 4529 } 4530 4531 itd32.u1.Ordinal = 0; 4532 SetLastError(0xdeadbeef); 4533 ret = WriteFile(hfile, &itd32, sizeof(itd32), &dummy, NULL); 4534 ok(ret, "WriteFile error %ld\n", GetLastError()); 4535 4536 /* fill up to eof */ 4537 SetFilePointer( hfile, section.VirtualAddress + section.Misc.VirtualSize, NULL, SEEK_SET ); 4538 SetEndOfFile( hfile ); 4539 CloseHandle(hfile); 4540 4541 SetLastError(0xdeadbeef); 4542 hlib = LoadLibraryA(dll_name); 4543 ok(hlib != NULL, "LoadLibrary error %lu\n", GetLastError()); 4544 if (!hlib) 4545 { 4546 skip("couldn't load %s.\n", dll_name); 4547 DeleteFileA(dll_name); 4548 return; 4549 } 4550 4551 delaydir = pRtlImageDirectoryEntryToData(hlib, TRUE, IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT, &file_size); 4552 if (!delaydir) 4553 { 4554 skip("haven't found section for delay import directory.\n"); 4555 FreeLibrary(hlib); 4556 DeleteFileA(dll_name); 4557 return; 4558 } 4559 4560 for (;;) 4561 { 4562 IMAGE_THUNK_DATA *itdn, *itda; 4563 HMODULE htarget; 4564 4565 if (!delaydir->DllNameRVA || 4566 !delaydir->ImportAddressTableRVA || 4567 !delaydir->ImportNameTableRVA) break; 4568 4569 itdn = RVAToAddr(delaydir->ImportNameTableRVA, hlib); 4570 itda = RVAToAddr(delaydir->ImportAddressTableRVA, hlib); 4571 htarget = LoadLibraryA(RVAToAddr(delaydir->DllNameRVA, hlib)); 4572 4573 for (i = 0; i < ARRAY_SIZE(td); i++) 4574 { 4575 void *ret, *load; 4576 4577 /* relocate thunk address by hand since we don't generate reloc records */ 4578 itda[i].u1.AddressOfData += (char *)hlib - (char *)nt_header.OptionalHeader.ImageBase; 4579 4580 if (IMAGE_SNAP_BY_ORDINAL(itdn[i].u1.Ordinal)) 4581 load = (void *)GetProcAddress(htarget, (LPSTR)IMAGE_ORDINAL(itdn[i].u1.Ordinal)); 4582 else 4583 { 4584 const IMAGE_IMPORT_BY_NAME* iibn = RVAToAddr(itdn[i].u1.AddressOfData, hlib); 4585 load = (void *)GetProcAddress(htarget, (char*)iibn->Name); 4586 } 4587 4588 /* test without failure dll callback */ 4589 cb_count = cb_count_sys = 0; 4590 ret = pResolveDelayLoadedAPI(hlib, delaydir, NULL, failuresyshook, &itda[i], 0); 4591 if (td[i].succeeds) 4592 { 4593 ok(ret != NULL, "Test %lu: ResolveDelayLoadedAPI failed\n", i); 4594 ok(ret == load, "Test %lu: expected %p, got %p\n", i, load, ret); 4595 ok(ret == (void*)itda[i].u1.AddressOfData, "Test %lu: expected %p, got %p\n", 4596 i, ret, (void*)itda[i].u1.AddressOfData); 4597 ok(!cb_count, "Test %lu: Wrong callback count: %d\n", i, cb_count); 4598 ok(!cb_count_sys, "Test %lu: Wrong sys callback count: %d\n", i, cb_count_sys); 4599 } 4600 else 4601 { 4602 ok(ret == (void*)0x12345678, "Test %lu: ResolveDelayLoadedAPI succeeded with %p\n", i, ret); 4603 ok(!cb_count, "Test %lu: Wrong callback count: %d\n", i, cb_count); 4604 ok(cb_count_sys == 1, "Test %lu: Wrong sys callback count: %d\n", i, cb_count_sys); 4605 } 4606 4607 /* test with failure dll callback */ 4608 cb_count = cb_count_sys = 0; 4609 ret = pResolveDelayLoadedAPI(hlib, delaydir, failuredllhook, failuresyshook, &itda[i], 0); 4610 if (td[i].succeeds) 4611 { 4612 ok(ret != NULL, "Test %lu: ResolveDelayLoadedAPI failed\n", i); 4613 ok(ret == load, "Test %lu: expected %p, got %p\n", i, load, ret); 4614 ok(ret == (void*)itda[i].u1.AddressOfData, "Test %lu: expected %p, got %p\n", 4615 i, ret, (void*)itda[i].u1.AddressOfData); 4616 ok(!cb_count, "Test %lu: Wrong callback count: %d\n", i, cb_count); 4617 ok(!cb_count_sys, "Test %lu: Wrong sys callback count: %d\n", i, cb_count_sys); 4618 } 4619 else 4620 { 4621 if (ret == (void*)0x12345678) 4622 { 4623 /* Win10+ sometimes buffers the address of the stub function */ 4624 ok(!cb_count, "Test %lu: Wrong callback count: %d\n", i, cb_count); 4625 ok(!cb_count_sys, "Test %lu: Wrong sys callback count: %d\n", i, cb_count_sys); 4626 } 4627 else if (ret == (void*)0xdeadbeef) 4628 { 4629 ok(cb_count == 1, "Test %lu: Wrong callback count: %d\n", i, cb_count); 4630 ok(!cb_count_sys, "Test %lu: Wrong sys callback count: %d\n", i, cb_count_sys); 4631 } 4632 else 4633 ok(0, "Test %lu: ResolveDelayLoadedAPI succeeded with %p\n", i, ret); 4634 } 4635 } 4636 delaydir++; 4637 } 4638 4639 FreeLibrary(hlib); 4640 trace("deleting %s\n", dll_name); 4641 DeleteFileA(dll_name); 4642} 4643 4644static void test_InMemoryOrderModuleList(void) 4645{ 4646 PEB_LDR_DATA *ldr = NtCurrentTeb()->Peb->LdrData; 4647 LIST_ENTRY *entry1, *mark1 = &ldr->InLoadOrderModuleList; 4648 LIST_ENTRY *entry2, *mark2 = &ldr->InMemoryOrderModuleList; 4649 LDR_DATA_TABLE_ENTRY *module1, *module2; 4650 4651 ok(ldr->Initialized == TRUE, "expected TRUE, got %u\n", ldr->Initialized); 4652 4653 for (entry1 = mark1->Flink, entry2 = mark2->Flink; 4654 entry1 != mark1 && entry2 != mark2; 4655 entry1 = entry1->Flink, entry2 = entry2->Flink) 4656 { 4657 module1 = CONTAINING_RECORD(entry1, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); 4658 module2 = CONTAINING_RECORD(entry2, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks); 4659 ok(module1 == module2, "expected module1 == module2, got %p and %p\n", module1, module2); 4660 } 4661 ok(entry1 == mark1, "expected entry1 == mark1, got %p and %p\n", entry1, mark1); 4662 ok(entry2 == mark2, "expected entry2 == mark2, got %p and %p\n", entry2, mark2); 4663} 4664 4665static BOOL is_path_made_of(const char *filename, const char *pfx, const char *sfx) 4666{ 4667 const size_t len = strlen(pfx); 4668 return !strncasecmp(filename, pfx, len) && filename[len] == '\\' && 4669 !strcasecmp(filename + len + 1, sfx); 4670} 4671 4672static void test_wow64_redirection_for_dll(const char *libname, BOOL will_fail) 4673{ 4674 HMODULE lib; 4675 char buf[256]; 4676 const char *modname; 4677 4678 if (!GetModuleHandleA(libname)) 4679 { 4680 lib = LoadLibraryExA(libname, NULL, 0); 4681 ok(lib != NULL, "Loading %s should succeed with WOW64 redirection disabled\n", libname); 4682 /* Win 7/2008R2 return the un-redirected path (i.e. c:\windows\system32\dwrite.dll), test loading it. */ 4683 GetModuleFileNameA(lib, buf, sizeof(buf)); 4684 FreeLibrary(lib); 4685 lib = LoadLibraryExA(buf, NULL, 0); 4686 ok(lib != NULL, "Loading %s from full path should succeed with WOW64 redirection disabled\n", libname); 4687 if (lib) 4688 FreeLibrary(lib); 4689 modname = strrchr(libname, '\\'); 4690 modname = modname ? modname + 1 : libname; 4691 todo_wine_if(will_fail) 4692 ok(is_path_made_of(buf, system_dir, modname) || 4693 /* Win7 report from syswow64 */ broken(is_path_made_of(buf, syswow_dir, modname)), 4694 "Unexpected loaded DLL name %s for %s\n", buf, libname); 4695 } 4696 else 4697 { 4698 skip("%s was already loaded in the process\n", libname); 4699 } 4700} 4701 4702static void test_wow64_redirection(void) 4703{ 4704 void *OldValue; 4705 char buffer[MAX_PATH]; 4706 static const char *dlls[] = {"wlanapi.dll", "dxgi.dll", "dwrite.dll"}; 4707 unsigned i; 4708 4709 if (!is_wow64) 4710 return; 4711 4712 /* Disable FS redirection, then test loading system libraries (pick ones that shouldn't 4713 * already be loaded in this process). 4714 */ 4715 ok(pWow64DisableWow64FsRedirection(&OldValue), "Disabling FS redirection failed\n"); 4716 for (i = 0; i < ARRAY_SIZE(dlls); i++) 4717 { 4718 test_wow64_redirection_for_dll(dlls[i], FALSE); 4719 /* even absolute paths to syswow64 are loaded with path to system32 */ 4720 snprintf(buffer, ARRAY_SIZE(buffer), "%s\\%s", syswow_dir, dlls[i]); 4721 test_wow64_redirection_for_dll(buffer, TRUE); 4722 } 4723 4724 ok(pWow64RevertWow64FsRedirection(OldValue), "Re-enabling FS redirection failed\n"); 4725 /* and results don't depend whether redirection is enabled or not */ 4726 for (i = 0; i < ARRAY_SIZE(dlls); i++) 4727 { 4728 test_wow64_redirection_for_dll(dlls[i], FALSE); 4729 snprintf(buffer, ARRAY_SIZE(buffer), "%s\\%s", syswow_dir, dlls[i]); 4730 test_wow64_redirection_for_dll(buffer, TRUE); 4731 } 4732} 4733 4734static void test_dll_file( const char *name ) 4735{ 4736 HMODULE module = GetModuleHandleA( name ); 4737 IMAGE_NT_HEADERS *nt, *nt_file; 4738 IMAGE_SECTION_HEADER *sec, *sec_file; 4739 char path[MAX_PATH]; 4740 HANDLE file, mapping; 4741 int i = 0; 4742 void *ptr; 4743 4744 GetModuleFileNameA( module, path, MAX_PATH ); 4745 file = CreateFileA( path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 ); 4746 ok( file != INVALID_HANDLE_VALUE, "can't open '%s': %lu\n", path, GetLastError() ); 4747 4748 mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 0, NULL ); 4749 ok( mapping != NULL, "%s: CreateFileMappingW failed err %lu\n", name, GetLastError() ); 4750 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 ); 4751 ok( ptr != NULL, "%s: MapViewOfFile failed err %lu\n", name, GetLastError() ); 4752 CloseHandle( mapping ); 4753 CloseHandle( file ); 4754 4755 nt = pRtlImageNtHeader( module ); 4756 nt_file = pRtlImageNtHeader( ptr ); 4757 ok( nt_file != NULL, "%s: invalid header\n", path ); 4758#define OK_FIELD(x, f) ok( nt->x == nt_file->x, "%s:%u: wrong " #x " " f " / " f "\n", name, i, nt->x, nt_file->x ) 4759 OK_FIELD( FileHeader.NumberOfSections, "%x" ); 4760 OK_FIELD( OptionalHeader.AddressOfEntryPoint, "%lx" ); 4761 OK_FIELD( OptionalHeader.NumberOfRvaAndSizes, "%lx" ); 4762 for (i = 0; i < nt->OptionalHeader.NumberOfRvaAndSizes; i++) 4763 { 4764 OK_FIELD( OptionalHeader.DataDirectory[i].VirtualAddress, "%lx" ); 4765 OK_FIELD( OptionalHeader.DataDirectory[i].Size, "%lx" ); 4766 } 4767 sec = IMAGE_FIRST_SECTION( nt ); 4768 sec_file = IMAGE_FIRST_SECTION( nt_file ); 4769 for (i = 0; i < nt->FileHeader.NumberOfSections; i++) 4770 ok( !memcmp( sec + i, sec_file + i, sizeof(*sec) ), "%s: wrong section %d\n", name, i ); 4771 UnmapViewOfFile( ptr ); 4772#undef OK_FIELD 4773} 4774 4775static void test_LoadPackagedLibrary(void) 4776{ 4777 HMODULE h; 4778 4779 if (!pLoadPackagedLibrary) 4780 { 4781 win_skip("LoadPackagedLibrary is not available.\n"); 4782 return; 4783 } 4784 4785 SetLastError( 0xdeadbeef ); 4786 h = pLoadPackagedLibrary(L"kernel32.dll", 0); 4787 ok(!h && GetLastError() == APPMODEL_ERROR_NO_PACKAGE, "Got unexpected handle %p, GetLastError() %lu.\n", 4788 h, GetLastError()); 4789} 4790 4791static void test_Wow64Transition(void) 4792{ 4793 char buffer[400]; 4794 MEMORY_SECTION_NAME *name = (MEMORY_SECTION_NAME *)buffer; 4795 const WCHAR *filepart; 4796 void **pWow64Transition; 4797 NTSTATUS status; 4798 4799 if (!(pWow64Transition = (void *)GetProcAddress(GetModuleHandleA("ntdll"), "Wow64Transition"))) 4800 { 4801 skip("Wow64Transition is not present\n"); 4802 return; 4803 } 4804 if (!is_wow64) 4805 { 4806 skip("Wow64Transition is not patched\n"); 4807 return; 4808 } 4809 4810 status = NtQueryVirtualMemory(GetCurrentProcess(), *pWow64Transition, 4811 MemoryMappedFilenameInformation, name, sizeof(buffer), NULL); 4812 ok(!status, "got %#lx\n", status); 4813 filepart = name->SectionFileName.Buffer + name->SectionFileName.Length / sizeof(WCHAR); 4814 while (*filepart != '\\') --filepart; 4815 ok(!wcsnicmp(filepart, L"\\wow64cpu.dll", wcslen(L"\\wow64cpu.dll")), "got file name %s\n", 4816 debugstr_wn(name->SectionFileName.Buffer, name->SectionFileName.Length / sizeof(WCHAR))); 4817} 4818 4819START_TEST(loader) 4820{ 4821 int argc; 4822 char **argv; 4823 HANDLE ntdll, mapping, kernel32; 4824 SYSTEM_INFO si; 4825 DWORD len; 4826 4827 ntdll = GetModuleHandleA("ntdll.dll"); 4828 kernel32 = GetModuleHandleA("kernel32.dll"); 4829 pNtCreateSection = (void *)GetProcAddress(ntdll, "NtCreateSection"); 4830 pNtQuerySection = (void *)GetProcAddress(ntdll, "NtQuerySection"); 4831 pNtMapViewOfSection = (void *)GetProcAddress(ntdll, "NtMapViewOfSection"); 4832 pNtUnmapViewOfSection = (void *)GetProcAddress(ntdll, "NtUnmapViewOfSection"); 4833 pNtTerminateProcess = (void *)GetProcAddress(ntdll, "NtTerminateProcess"); 4834 pNtQueryInformationProcess = (void *)GetProcAddress(ntdll, "NtQueryInformationProcess"); 4835 pNtSetInformationProcess = (void *)GetProcAddress(ntdll, "NtSetInformationProcess"); 4836 pLdrShutdownProcess = (void *)GetProcAddress(ntdll, "LdrShutdownProcess"); 4837 pRtlDllShutdownInProgress = (void *)GetProcAddress(ntdll, "RtlDllShutdownInProgress"); 4838 pNtAllocateVirtualMemory = (void *)GetProcAddress(ntdll, "NtAllocateVirtualMemory"); 4839 pNtFreeVirtualMemory = (void *)GetProcAddress(ntdll, "NtFreeVirtualMemory"); 4840 pLdrLockLoaderLock = (void *)GetProcAddress(ntdll, "LdrLockLoaderLock"); 4841 pLdrUnlockLoaderLock = (void *)GetProcAddress(ntdll, "LdrUnlockLoaderLock"); 4842 pLdrLoadDll = (void *)GetProcAddress(ntdll, "LdrLoadDll"); 4843 pLdrUnloadDll = (void *)GetProcAddress(ntdll, "LdrUnloadDll"); 4844 pRtlInitUnicodeString = (void *)GetProcAddress(ntdll, "RtlInitUnicodeString"); 4845 pRtlAcquirePebLock = (void *)GetProcAddress(ntdll, "RtlAcquirePebLock"); 4846 pRtlReleasePebLock = (void *)GetProcAddress(ntdll, "RtlReleasePebLock"); 4847 pRtlImageDirectoryEntryToData = (void *)GetProcAddress(ntdll, "RtlImageDirectoryEntryToData"); 4848 pRtlImageNtHeader = (void *)GetProcAddress(ntdll, "RtlImageNtHeader"); 4849 pLdrRegisterDllNotification = (void *)GetProcAddress(ntdll, "LdrRegisterDllNotification"); 4850 pFlsAlloc = (void *)GetProcAddress(kernel32, "FlsAlloc"); 4851 pFlsSetValue = (void *)GetProcAddress(kernel32, "FlsSetValue"); 4852 pFlsGetValue = (void *)GetProcAddress(kernel32, "FlsGetValue"); 4853 pFlsFree = (void *)GetProcAddress(kernel32, "FlsFree"); 4854 pIsWow64Process = (void *)GetProcAddress(kernel32, "IsWow64Process"); 4855 pWow64DisableWow64FsRedirection = (void *)GetProcAddress(kernel32, "Wow64DisableWow64FsRedirection"); 4856 pWow64RevertWow64FsRedirection = (void *)GetProcAddress(kernel32, "Wow64RevertWow64FsRedirection"); 4857 pResolveDelayLoadedAPI = (void *)GetProcAddress(kernel32, "ResolveDelayLoadedAPI"); 4858 pLoadPackagedLibrary = (void *)GetProcAddress(kernel32, "LoadPackagedLibrary"); 4859 4860 if (pIsWow64Process) pIsWow64Process( GetCurrentProcess(), &is_wow64 ); 4861 GetSystemInfo( &si ); 4862 page_size = si.dwPageSize; 4863 dos_header.e_magic = IMAGE_DOS_SIGNATURE; 4864 dos_header.e_lfanew = sizeof(dos_header); 4865 4866 mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, "winetest_loader"); 4867 ok(mapping != 0, "CreateFileMapping failed\n"); 4868 child_failures = MapViewOfFile(mapping, FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, 4096); 4869 if (*child_failures == -1) 4870 { 4871 *child_failures = 0; 4872 } 4873 else 4874 *child_failures = -1; 4875 4876 argc = winetest_get_mainargs(&argv); 4877 if (argc > 4) 4878 { 4879 test_dll_phase = atoi(argv[4]); 4880 child_process(argv[2], atol(argv[3])); 4881 return; 4882 } 4883 4884 len = GetSystemDirectoryA(system_dir, ARRAY_SIZE(system_dir)); 4885 ok(len && len < ARRAY_SIZE(system_dir), "Couldn't get system directory: %lu\n", GetLastError()); 4886 if (is_wow64) 4887 { 4888 len = GetSystemWow64DirectoryA(syswow_dir, ARRAY_SIZE(syswow_dir)); 4889 ok(len && len < ARRAY_SIZE(syswow_dir), "Couldn't get wow directory: %lu\n", GetLastError()); 4890 } 4891 4892 test_filenames(); 4893 test_ResolveDelayLoadedAPI(); 4894 test_ImportDescriptors(); 4895 test_section_access(); 4896 test_import_resolution(); 4897 test_export_forwarder_dep_chain(); 4898 test_ExitProcess(); 4899 test_InMemoryOrderModuleList(); 4900 test_LoadPackagedLibrary(); 4901 test_wow64_redirection(); 4902 test_dll_file( "ntdll.dll" ); 4903 test_dll_file( "kernel32.dll" ); 4904 test_dll_file( "advapi32.dll" ); 4905 test_dll_file( "user32.dll" ); 4906 test_Wow64Transition(); 4907 /* loader test must be last, it can corrupt the internal loader state on Windows */ 4908 test_Loader(); 4909}