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 "precomp.h" 22 23 #include <delayloadhandler.h> 24 25 /* PROCESS_ALL_ACCESS in Vista+ PSDKs is incompatible with older Windows versions */ 26 #define PROCESS_ALL_ACCESS_NT4 (PROCESS_ALL_ACCESS & ~0xf000) 27 28 #define ALIGN_SIZE(size, alignment) (((size) + (alignment - 1)) & ~((alignment - 1))) 29 30 struct PROCESS_BASIC_INFORMATION_PRIVATE 31 { 32 DWORD_PTR ExitStatus; 33 PPEB PebBaseAddress; 34 DWORD_PTR AffinityMask; 35 DWORD_PTR BasePriority; 36 ULONG_PTR UniqueProcessId; 37 ULONG_PTR InheritedFromUniqueProcessId; 38 }; 39 40 static LONG *child_failures; 41 static WORD cb_count; 42 static DWORD page_size; 43 44 static NTSTATUS (WINAPI *pNtCreateSection)(HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, 45 const LARGE_INTEGER *, ULONG, ULONG, HANDLE ); 46 static NTSTATUS (WINAPI *pNtQuerySection)(HANDLE, SECTION_INFORMATION_CLASS, void *, ULONG, ULONG *); 47 static NTSTATUS (WINAPI *pNtMapViewOfSection)(HANDLE, HANDLE, PVOID *, ULONG, SIZE_T, const LARGE_INTEGER *, SIZE_T *, ULONG, ULONG, ULONG); 48 static NTSTATUS (WINAPI *pNtUnmapViewOfSection)(HANDLE, PVOID); 49 static NTSTATUS (WINAPI *pNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG); 50 static NTSTATUS (WINAPI *pNtSetInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG); 51 static NTSTATUS (WINAPI *pNtTerminateProcess)(HANDLE, DWORD); 52 static void (WINAPI *pLdrShutdownProcess)(void); 53 static BOOLEAN (WINAPI *pRtlDllShutdownInProgress)(void); 54 static NTSTATUS (WINAPI *pNtAllocateVirtualMemory)(HANDLE, PVOID *, ULONG, SIZE_T *, ULONG, ULONG); 55 static NTSTATUS (WINAPI *pNtFreeVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG); 56 static NTSTATUS (WINAPI *pLdrLockLoaderLock)(ULONG, ULONG *, ULONG_PTR *); 57 static NTSTATUS (WINAPI *pLdrUnlockLoaderLock)(ULONG, ULONG_PTR); 58 static void (WINAPI *pRtlAcquirePebLock)(void); 59 static void (WINAPI *pRtlReleasePebLock)(void); 60 static PVOID (WINAPI *pResolveDelayLoadedAPI)(PVOID, PCIMAGE_DELAYLOAD_DESCRIPTOR, 61 PDELAYLOAD_FAILURE_DLL_CALLBACK, PVOID, 62 PIMAGE_THUNK_DATA ThunkAddress,ULONG); 63 static PVOID (WINAPI *pRtlImageDirectoryEntryToData)(HMODULE,BOOL,WORD,ULONG *); 64 static DWORD (WINAPI *pFlsAlloc)(PFLS_CALLBACK_FUNCTION); 65 static BOOL (WINAPI *pFlsSetValue)(DWORD, PVOID); 66 static PVOID (WINAPI *pFlsGetValue)(DWORD); 67 static BOOL (WINAPI *pFlsFree)(DWORD); 68 69 static PVOID RVAToAddr(DWORD_PTR rva, HMODULE module) 70 { 71 if (rva == 0) 72 return NULL; 73 return ((char*) module) + rva; 74 } 75 76 static IMAGE_DOS_HEADER dos_header; 77 78 static const IMAGE_NT_HEADERS nt_header_template = 79 { 80 IMAGE_NT_SIGNATURE, /* Signature */ 81 { 82 #if defined __i386__ 83 IMAGE_FILE_MACHINE_I386, /* Machine */ 84 #elif defined __x86_64__ 85 IMAGE_FILE_MACHINE_AMD64, /* Machine */ 86 #elif defined __powerpc__ 87 IMAGE_FILE_MACHINE_POWERPC, /* Machine */ 88 #elif defined __arm__ 89 IMAGE_FILE_MACHINE_ARMNT, /* Machine */ 90 #elif defined __aarch64__ 91 IMAGE_FILE_MACHINE_ARM64, /* Machine */ 92 #else 93 # error You must specify the machine type 94 #endif 95 1, /* NumberOfSections */ 96 0, /* TimeDateStamp */ 97 0, /* PointerToSymbolTable */ 98 0, /* NumberOfSymbols */ 99 sizeof(IMAGE_OPTIONAL_HEADER), /* SizeOfOptionalHeader */ 100 IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL /* Characteristics */ 101 }, 102 { IMAGE_NT_OPTIONAL_HDR_MAGIC, /* Magic */ 103 1, /* MajorLinkerVersion */ 104 0, /* MinorLinkerVersion */ 105 0, /* SizeOfCode */ 106 0, /* SizeOfInitializedData */ 107 0, /* SizeOfUninitializedData */ 108 0, /* AddressOfEntryPoint */ 109 0x10, /* BaseOfCode, also serves as e_lfanew in the truncated MZ header */ 110 #ifndef _WIN64 111 0, /* BaseOfData */ 112 #endif 113 0x10000000, /* ImageBase */ 114 0, /* SectionAlignment */ 115 0, /* FileAlignment */ 116 4, /* MajorOperatingSystemVersion */ 117 0, /* MinorOperatingSystemVersion */ 118 1, /* MajorImageVersion */ 119 0, /* MinorImageVersion */ 120 4, /* MajorSubsystemVersion */ 121 0, /* MinorSubsystemVersion */ 122 0, /* Win32VersionValue */ 123 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0x1000, /* SizeOfImage */ 124 sizeof(dos_header) + sizeof(nt_header_template), /* SizeOfHeaders */ 125 0, /* CheckSum */ 126 IMAGE_SUBSYSTEM_WINDOWS_CUI, /* Subsystem */ 127 0, /* DllCharacteristics */ 128 0, /* SizeOfStackReserve */ 129 0, /* SizeOfStackCommit */ 130 0, /* SizeOfHeapReserve */ 131 0, /* SizeOfHeapCommit */ 132 0, /* LoaderFlags */ 133 0, /* NumberOfRvaAndSizes */ 134 { { 0 } } /* DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES] */ 135 } 136 }; 137 138 static IMAGE_SECTION_HEADER section = 139 { 140 ".rodata", /* Name */ 141 { 0 }, /* Misc */ 142 0, /* VirtualAddress */ 143 0, /* SizeOfRawData */ 144 0, /* PointerToRawData */ 145 0, /* PointerToRelocations */ 146 0, /* PointerToLinenumbers */ 147 0, /* NumberOfRelocations */ 148 0, /* NumberOfLinenumbers */ 149 IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ, /* Characteristics */ 150 }; 151 152 153 static const char filler[0x1000]; 154 static const char section_data[0x10] = "section data"; 155 156 static DWORD create_test_dll( const IMAGE_DOS_HEADER *dos_header, UINT dos_size, 157 const IMAGE_NT_HEADERS *nt_header, const char *dll_name ) 158 { 159 DWORD dummy, size, file_align; 160 HANDLE hfile; 161 BOOL ret; 162 163 hfile = CreateFileA(dll_name, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, 0); 164 if (hfile == INVALID_HANDLE_VALUE) return 0; 165 166 SetLastError(0xdeadbeef); 167 ret = WriteFile(hfile, dos_header, dos_size, &dummy, NULL); 168 ok(ret, "WriteFile error %d\n", GetLastError()); 169 170 SetLastError(0xdeadbeef); 171 ret = WriteFile(hfile, nt_header, sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER), &dummy, NULL); 172 ok(ret, "WriteFile error %d\n", GetLastError()); 173 174 if (nt_header->FileHeader.SizeOfOptionalHeader) 175 { 176 SetLastError(0xdeadbeef); 177 ret = WriteFile(hfile, &nt_header->OptionalHeader, 178 sizeof(IMAGE_OPTIONAL_HEADER), 179 &dummy, NULL); 180 ok(ret, "WriteFile error %d\n", GetLastError()); 181 if (nt_header->FileHeader.SizeOfOptionalHeader > sizeof(IMAGE_OPTIONAL_HEADER)) 182 { 183 file_align = nt_header->FileHeader.SizeOfOptionalHeader - sizeof(IMAGE_OPTIONAL_HEADER); 184 assert(file_align < sizeof(filler)); 185 SetLastError(0xdeadbeef); 186 ret = WriteFile(hfile, filler, file_align, &dummy, NULL); 187 ok(ret, "WriteFile error %d\n", GetLastError()); 188 } 189 } 190 191 assert(nt_header->FileHeader.NumberOfSections <= 1); 192 if (nt_header->FileHeader.NumberOfSections) 193 { 194 SetFilePointer(hfile, dos_size + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + nt_header->FileHeader.SizeOfOptionalHeader, NULL, FILE_BEGIN); 195 196 section.SizeOfRawData = 10; 197 198 if (nt_header->OptionalHeader.SectionAlignment >= page_size) 199 { 200 section.PointerToRawData = dos_size; 201 section.VirtualAddress = nt_header->OptionalHeader.SectionAlignment; 202 section.Misc.VirtualSize = section.SizeOfRawData * 10; 203 } 204 else 205 { 206 section.PointerToRawData = nt_header->OptionalHeader.SizeOfHeaders; 207 section.VirtualAddress = nt_header->OptionalHeader.SizeOfHeaders; 208 section.Misc.VirtualSize = 5; 209 } 210 211 SetLastError(0xdeadbeef); 212 ret = WriteFile(hfile, §ion, sizeof(section), &dummy, NULL); 213 ok(ret, "WriteFile error %d\n", GetLastError()); 214 215 /* section data */ 216 SetLastError(0xdeadbeef); 217 ret = WriteFile(hfile, section_data, sizeof(section_data), &dummy, NULL); 218 ok(ret, "WriteFile error %d\n", GetLastError()); 219 } 220 221 /* Minimal PE image that Windows7+ is able to load: 268 bytes */ 222 size = GetFileSize(hfile, NULL); 223 if (size < 268) 224 { 225 file_align = 268 - size; 226 SetLastError(0xdeadbeef); 227 ret = WriteFile(hfile, filler, file_align, &dummy, NULL); 228 ok(ret, "WriteFile error %d\n", GetLastError()); 229 } 230 231 size = GetFileSize(hfile, NULL); 232 CloseHandle(hfile); 233 return size; 234 } 235 236 static void query_image_section( int id, const char *dll_name, const IMAGE_NT_HEADERS *nt_header ) 237 { 238 SECTION_BASIC_INFORMATION info; 239 SECTION_IMAGE_INFORMATION image; 240 ULONG info_size = 0xdeadbeef; 241 NTSTATUS status; 242 HANDLE file, mapping; 243 ULONG file_size; 244 LARGE_INTEGER map_size; 245 /* truncated header is not handled correctly in windows <= w2k3 */ 246 BOOL truncated = nt_header->FileHeader.SizeOfOptionalHeader < sizeof(nt_header->OptionalHeader); 247 248 file = CreateFileA( dll_name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE, 249 NULL, OPEN_EXISTING, 0, 0 ); 250 ok( file != INVALID_HANDLE_VALUE, "%u: CreateFile error %d\n", id, GetLastError() ); 251 file_size = GetFileSize( file, NULL ); 252 253 status = pNtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_MAP_READ | SECTION_QUERY, 254 NULL, NULL, PAGE_READONLY, SEC_IMAGE, file ); 255 ok( !status, "%u: NtCreateSection failed err %x\n", id, status ); 256 if (status) 257 { 258 CloseHandle( file ); 259 return; 260 } 261 status = pNtQuerySection( mapping, SectionImageInformation, &image, sizeof(image), &info_size ); 262 ok( !status, "%u: NtQuerySection failed err %x\n", id, status ); 263 ok( info_size == sizeof(image), "%u: NtQuerySection wrong size %u\n", id, info_size ); 264 ok( (char *)image.TransferAddress == (char *)nt_header->OptionalHeader.ImageBase + nt_header->OptionalHeader.AddressOfEntryPoint, 265 "%u: TransferAddress wrong %p / %p+%08x\n", id, 266 image.TransferAddress, (char *)nt_header->OptionalHeader.ImageBase, 267 nt_header->OptionalHeader.AddressOfEntryPoint ); 268 ok( image.ZeroBits == 0, "%u: ZeroBits wrong %08x\n", id, image.ZeroBits ); 269 ok( image.MaximumStackSize == nt_header->OptionalHeader.SizeOfStackReserve || broken(truncated), 270 "%u: MaximumStackSize wrong %lx / %lx\n", id, 271 image.MaximumStackSize, (SIZE_T)nt_header->OptionalHeader.SizeOfStackReserve ); 272 ok( image.CommittedStackSize == nt_header->OptionalHeader.SizeOfStackCommit || broken(truncated), 273 "%u: CommittedStackSize wrong %lx / %lx\n", id, 274 image.CommittedStackSize, (SIZE_T)nt_header->OptionalHeader.SizeOfStackCommit ); 275 if (truncated) 276 ok( !image.SubSystemType || broken(truncated), 277 "%u: SubSystemType wrong %08x / 00000000\n", id, image.SubSystemType ); 278 else 279 ok( image.SubSystemType == nt_header->OptionalHeader.Subsystem, 280 "%u: SubSystemType wrong %08x / %08x\n", id, 281 image.SubSystemType, nt_header->OptionalHeader.Subsystem ); 282 ok( image.SubsystemVersionLow == nt_header->OptionalHeader.MinorSubsystemVersion, 283 "%u: SubsystemVersionLow wrong %04x / %04x\n", id, 284 image.SubsystemVersionLow, nt_header->OptionalHeader.MinorSubsystemVersion ); 285 ok( image.SubsystemVersionHigh == nt_header->OptionalHeader.MajorSubsystemVersion, 286 "%u: SubsystemVersionHigh wrong %04x / %04x\n", id, 287 image.SubsystemVersionHigh, nt_header->OptionalHeader.MajorSubsystemVersion ); 288 ok( image.ImageCharacteristics == nt_header->FileHeader.Characteristics, 289 "%u: ImageCharacteristics wrong %04x / %04x\n", id, 290 image.ImageCharacteristics, nt_header->FileHeader.Characteristics ); 291 ok( image.DllCharacteristics == nt_header->OptionalHeader.DllCharacteristics || broken(truncated), 292 "%u: DllCharacteristics wrong %04x / %04x\n", id, 293 image.DllCharacteristics, nt_header->OptionalHeader.DllCharacteristics ); 294 ok( image.Machine == nt_header->FileHeader.Machine, "%u: Machine wrong %04x / %04x\n", id, 295 image.Machine, nt_header->FileHeader.Machine ); 296 ok( image.LoaderFlags == nt_header->OptionalHeader.LoaderFlags, 297 "%u: LoaderFlags wrong %08x / %08x\n", id, 298 image.LoaderFlags, nt_header->OptionalHeader.LoaderFlags ); 299 ok( image.ImageFileSize == file_size || broken(!image.ImageFileSize), /* winxpsp1 */ 300 "%u: ImageFileSize wrong %08x / %08x\n", id, image.ImageFileSize, file_size ); 301 ok( image.CheckSum == nt_header->OptionalHeader.CheckSum || broken(truncated), 302 "%u: CheckSum wrong %08x / %08x\n", id, 303 image.CheckSum, nt_header->OptionalHeader.CheckSum ); 304 /* FIXME: needs more work: */ 305 /* image.GpValue */ 306 /* image.ImageFlags */ 307 /* image.ImageContainsCode */ 308 309 map_size.QuadPart = (nt_header->OptionalHeader.SizeOfImage + page_size - 1) & ~(page_size - 1); 310 status = pNtQuerySection( mapping, SectionBasicInformation, &info, sizeof(info), NULL ); 311 ok( !status, "NtQuerySection failed err %x\n", status ); 312 ok( info.Size.QuadPart == map_size.QuadPart, "NtQuerySection wrong size %x%08x / %x%08x\n", 313 info.Size.u.HighPart, info.Size.u.LowPart, map_size.u.HighPart, map_size.u.LowPart ); 314 CloseHandle( mapping ); 315 316 map_size.QuadPart = (nt_header->OptionalHeader.SizeOfImage + page_size - 1) & ~(page_size - 1); 317 status = pNtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_MAP_READ | SECTION_QUERY, 318 NULL, &map_size, PAGE_READONLY, SEC_IMAGE, file ); 319 ok( !status, "%u: NtCreateSection failed err %x\n", id, status ); 320 status = pNtQuerySection( mapping, SectionBasicInformation, &info, sizeof(info), NULL ); 321 ok( !status, "NtQuerySection failed err %x\n", status ); 322 ok( info.Size.QuadPart == map_size.QuadPart, "NtQuerySection wrong size %x%08x / %x%08x\n", 323 info.Size.u.HighPart, info.Size.u.LowPart, map_size.u.HighPart, map_size.u.LowPart ); 324 CloseHandle( mapping ); 325 326 map_size.QuadPart++; 327 status = pNtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_MAP_READ | SECTION_QUERY, 328 NULL, &map_size, PAGE_READONLY, SEC_IMAGE, file ); 329 ok( status == STATUS_SECTION_TOO_BIG, "%u: NtCreateSection failed err %x\n", id, status ); 330 331 SetFilePointerEx( file, map_size, NULL, FILE_BEGIN ); 332 SetEndOfFile( file ); 333 status = pNtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_MAP_READ | SECTION_QUERY, 334 NULL, &map_size, PAGE_READONLY, SEC_IMAGE, file ); 335 ok( status == STATUS_SECTION_TOO_BIG, "%u: NtCreateSection failed err %x\n", id, status ); 336 337 map_size.QuadPart = 1; 338 status = pNtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_MAP_READ | SECTION_QUERY, 339 NULL, &map_size, PAGE_READONLY, SEC_IMAGE, file ); 340 ok( !status, "%u: NtCreateSection failed err %x\n", id, status ); 341 status = pNtQuerySection( mapping, SectionBasicInformation, &info, sizeof(info), NULL ); 342 ok( !status, "NtQuerySection failed err %x\n", status ); 343 ok( info.Size.QuadPart == map_size.QuadPart, "NtQuerySection wrong size %x%08x / %x%08x\n", 344 info.Size.u.HighPart, info.Size.u.LowPart, map_size.u.HighPart, map_size.u.LowPart ); 345 CloseHandle( mapping ); 346 347 CloseHandle( file ); 348 } 349 350 /* helper to test image section mapping */ 351 static NTSTATUS map_image_section( const IMAGE_NT_HEADERS *nt_header ) 352 { 353 char temp_path[MAX_PATH]; 354 char dll_name[MAX_PATH]; 355 LARGE_INTEGER size; 356 HANDLE file, map; 357 NTSTATUS status; 358 ULONG file_size; 359 360 GetTempPathA(MAX_PATH, temp_path); 361 GetTempFileNameA(temp_path, "ldr", 0, dll_name); 362 363 file_size = create_test_dll( &dos_header, sizeof(dos_header), nt_header, dll_name ); 364 ok( file_size, "could not create %s\n", dll_name); 365 366 file = CreateFileA(dll_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); 367 ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError()); 368 369 size.QuadPart = file_size; 370 status = pNtCreateSection(&map, STANDARD_RIGHTS_REQUIRED | SECTION_MAP_READ | SECTION_QUERY, 371 NULL, &size, PAGE_READONLY, SEC_IMAGE, file ); 372 if (!status) 373 { 374 SECTION_BASIC_INFORMATION info; 375 ULONG info_size = 0xdeadbeef; 376 NTSTATUS ret = pNtQuerySection( map, SectionBasicInformation, &info, sizeof(info), &info_size ); 377 ok( !ret, "NtQuerySection failed err %x\n", ret ); 378 ok( info_size == sizeof(info), "NtQuerySection wrong size %u\n", info_size ); 379 ok( info.Attributes == (SEC_IMAGE | SEC_FILE), "NtQuerySection wrong attr %x\n", info.Attributes ); 380 ok( info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", info.BaseAddress ); 381 ok( info.Size.QuadPart == file_size, "NtQuerySection wrong size %x%08x / %08x\n", 382 info.Size.u.HighPart, info.Size.u.LowPart, file_size ); 383 query_image_section( 1000, dll_name, nt_header ); 384 } 385 if (map) CloseHandle( map ); 386 CloseHandle( file ); 387 DeleteFileA( dll_name ); 388 return status; 389 } 390 391 392 static void test_Loader(void) 393 { 394 static const struct test_data 395 { 396 DWORD size_of_dos_header; 397 WORD number_of_sections, size_of_optional_header; 398 DWORD section_alignment, file_alignment; 399 DWORD size_of_image, size_of_headers; 400 DWORD errors[4]; /* 0 means LoadLibrary should succeed */ 401 } td[] = 402 { 403 { sizeof(dos_header), 404 1, 0, 0, 0, 0, 0, 405 { ERROR_BAD_EXE_FORMAT } 406 }, 407 { sizeof(dos_header), 408 1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x1000, 409 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0xe00, 410 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER), 411 { ERROR_BAD_EXE_FORMAT } /* XP doesn't like too small image size */ 412 }, 413 { sizeof(dos_header), 414 1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x1000, 415 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0x1000, 416 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER), 417 { ERROR_SUCCESS } 418 }, 419 { sizeof(dos_header), 420 1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x1000, 421 0x1f00, 422 0x1000, 423 { ERROR_SUCCESS } 424 }, 425 { sizeof(dos_header), 426 1, sizeof(IMAGE_OPTIONAL_HEADER), 0x200, 0x200, 427 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0x200, 428 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER), 429 { ERROR_SUCCESS, ERROR_INVALID_ADDRESS } /* vista is more strict */ 430 }, 431 { sizeof(dos_header), 432 1, sizeof(IMAGE_OPTIONAL_HEADER), 0x200, 0x1000, 433 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0x1000, 434 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER), 435 { ERROR_BAD_EXE_FORMAT } /* XP doesn't like alignments */ 436 }, 437 { sizeof(dos_header), 438 1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x200, 439 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0x1000, 440 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER), 441 { ERROR_SUCCESS } 442 }, 443 { sizeof(dos_header), 444 1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x200, 445 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0x1000, 446 0x200, 447 { ERROR_SUCCESS } 448 }, 449 /* Mandatory are all fields up to SizeOfHeaders, everything else 450 * is really optional (at least that's true for XP). 451 */ 452 #if 0 /* 32-bit Windows 8 crashes inside of LoadLibrary */ 453 { sizeof(dos_header), 454 1, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200, 455 sizeof(dos_header) + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum) + sizeof(IMAGE_SECTION_HEADER) + 0x10, 456 sizeof(dos_header) + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum) + sizeof(IMAGE_SECTION_HEADER), 457 { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT, ERROR_INVALID_ADDRESS, 458 ERROR_NOACCESS } 459 }, 460 #endif 461 { sizeof(dos_header), 462 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200, 463 0xd0, /* beyond of the end of file */ 464 0xc0, /* beyond of the end of file */ 465 { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */ 466 }, 467 { sizeof(dos_header), 468 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200, 469 0x1000, 470 0, 471 { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */ 472 }, 473 { sizeof(dos_header), 474 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200, 475 1, 476 0, 477 { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */ 478 }, 479 #if 0 /* not power of 2 alignments need more test cases */ 480 { sizeof(dos_header), 481 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x300, 0x300, 482 1, 483 0, 484 { ERROR_BAD_EXE_FORMAT } /* alignment is not power of 2 */ 485 }, 486 #endif 487 { sizeof(dos_header), 488 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 4, 4, 489 1, 490 0, 491 { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */ 492 }, 493 { sizeof(dos_header), 494 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 1, 1, 495 1, 496 0, 497 { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */ 498 }, 499 { sizeof(dos_header), 500 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200, 501 0, 502 0, 503 { ERROR_BAD_EXE_FORMAT } /* image size == 0 -> failure */ 504 }, 505 /* the following data mimics the PE image which upack creates */ 506 { 0x10, 507 1, 0x148, 0x1000, 0x200, 508 sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0x1000, 509 0x200, 510 { ERROR_SUCCESS } 511 }, 512 /* Minimal PE image that XP is able to load: 92 bytes */ 513 { 0x04, 514 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 515 0x04 /* also serves as e_lfanew in the truncated MZ header */, 0x04, 516 1, 517 0, 518 { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */ 519 }, 520 /* Minimal PE image that Windows7 is able to load: 268 bytes */ 521 { 0x04, 522 0, 0xf0, /* optional header size just forces 0xf0 bytes to be written, 523 0 or another number don't change the behaviour, what really 524 matters is file size regardless of values in the headers */ 525 0x04 /* also serves as e_lfanew in the truncated MZ header */, 0x04, 526 0x40, /* minimal image size that Windows7 accepts */ 527 0, 528 { ERROR_SUCCESS } 529 }, 530 /* the following data mimics the PE image which 8k demos have */ 531 { 0x04, 532 0, 0x08, 533 0x04 /* also serves as e_lfanew in the truncated MZ header */, 0x04, 534 0x200000, 535 0x40, 536 { ERROR_SUCCESS } 537 } 538 }; 539 int i; 540 DWORD file_size; 541 HANDLE h; 542 HMODULE hlib, hlib_as_data_file; 543 char temp_path[MAX_PATH]; 544 char dll_name[MAX_PATH]; 545 SIZE_T size; 546 BOOL ret; 547 NTSTATUS status; 548 WORD orig_machine = nt_header_template.FileHeader.Machine; 549 IMAGE_NT_HEADERS nt_header; 550 551 /* prevent displaying of the "Unable to load this DLL" message box */ 552 SetErrorMode(SEM_FAILCRITICALERRORS); 553 554 GetTempPathA(MAX_PATH, temp_path); 555 556 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++) 557 { 558 GetTempFileNameA(temp_path, "ldr", 0, dll_name); 559 560 nt_header = nt_header_template; 561 nt_header.FileHeader.NumberOfSections = td[i].number_of_sections; 562 nt_header.FileHeader.SizeOfOptionalHeader = td[i].size_of_optional_header; 563 564 nt_header.OptionalHeader.SectionAlignment = td[i].section_alignment; 565 nt_header.OptionalHeader.FileAlignment = td[i].file_alignment; 566 nt_header.OptionalHeader.SizeOfImage = td[i].size_of_image; 567 nt_header.OptionalHeader.SizeOfHeaders = td[i].size_of_headers; 568 569 file_size = create_test_dll( &dos_header, td[i].size_of_dos_header, &nt_header, dll_name ); 570 if (!file_size) 571 { 572 ok(0, "could not create %s\n", dll_name); 573 break; 574 } 575 576 SetLastError(0xdeadbeef); 577 hlib = LoadLibraryA(dll_name); 578 if (hlib) 579 { 580 MEMORY_BASIC_INFORMATION info; 581 void *ptr; 582 583 ok( td[i].errors[0] == ERROR_SUCCESS, "%d: should have failed\n", i ); 584 585 SetLastError(0xdeadbeef); 586 size = VirtualQuery(hlib, &info, sizeof(info)); 587 ok(size == sizeof(info), 588 "%d: VirtualQuery error %d\n", i, GetLastError()); 589 ok(info.BaseAddress == hlib, "%d: %p != %p\n", i, info.BaseAddress, hlib); 590 ok(info.AllocationBase == hlib, "%d: %p != %p\n", i, info.AllocationBase, hlib); 591 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect); 592 ok(info.RegionSize == ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, page_size), "%d: got %lx != expected %x\n", 593 i, info.RegionSize, ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, page_size)); 594 ok(info.State == MEM_COMMIT, "%d: %x != MEM_COMMIT\n", i, info.State); 595 if (nt_header.OptionalHeader.SectionAlignment < page_size) 596 ok(info.Protect == PAGE_EXECUTE_WRITECOPY, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i, info.Protect); 597 else 598 ok(info.Protect == PAGE_READONLY, "%d: %x != PAGE_READONLY\n", i, info.Protect); 599 ok(info.Type == SEC_IMAGE, "%d: %x != SEC_IMAGE\n", i, info.Type); 600 601 SetLastError(0xdeadbeef); 602 ptr = VirtualAlloc(hlib, page_size, MEM_COMMIT, info.Protect); 603 ok(!ptr, "%d: VirtualAlloc should fail\n", i); 604 /* FIXME: Remove once Wine is fixed */ 605 todo_wine_if (info.Protect == PAGE_WRITECOPY || info.Protect == PAGE_EXECUTE_WRITECOPY) 606 ok(GetLastError() == ERROR_ACCESS_DENIED, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i, GetLastError()); 607 608 SetLastError(0xdeadbeef); 609 size = VirtualQuery((char *)hlib + info.RegionSize, &info, sizeof(info)); 610 ok(size == sizeof(info), 611 "%d: VirtualQuery error %d\n", i, GetLastError()); 612 if (nt_header.OptionalHeader.SectionAlignment == page_size || 613 nt_header.OptionalHeader.SectionAlignment == nt_header.OptionalHeader.FileAlignment) 614 { 615 ok(info.BaseAddress == (char *)hlib + ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, page_size), "%d: got %p != expected %p\n", 616 i, info.BaseAddress, (char *)hlib + ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, page_size)); 617 ok(info.AllocationBase == 0, "%d: %p != 0\n", i, info.AllocationBase); 618 ok(info.AllocationProtect == 0, "%d: %x != 0\n", i, info.AllocationProtect); 619 /*ok(info.RegionSize == not_practical_value, "%d: %lx != not_practical_value\n", i, info.RegionSize);*/ 620 ok(info.State == MEM_FREE, "%d: %x != MEM_FREE\n", i, info.State); 621 ok(info.Type == 0, "%d: %x != 0\n", i, info.Type); 622 ok(info.Protect == PAGE_NOACCESS, "%d: %x != PAGE_NOACCESS\n", i, info.Protect); 623 } 624 else 625 { 626 ok(info.Protect == PAGE_EXECUTE_WRITECOPY, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i, info.Protect); 627 ok(info.BaseAddress == hlib, "%d: got %p != expected %p\n", i, info.BaseAddress, hlib); 628 ok(info.AllocationBase == hlib, "%d: %p != %p\n", i, info.AllocationBase, hlib); 629 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect); 630 ok(info.RegionSize == ALIGN_SIZE(file_size, page_size), "%d: got %lx != expected %x\n", 631 i, info.RegionSize, ALIGN_SIZE(file_size, page_size)); 632 ok(info.State == MEM_COMMIT, "%d: %x != MEM_COMMIT\n", i, info.State); 633 ok(info.Protect == PAGE_READONLY, "%d: %x != PAGE_READONLY\n", i, info.Protect); 634 ok(info.Type == SEC_IMAGE, "%d: %x != SEC_IMAGE\n", i, info.Type); 635 } 636 637 /* header: check the zeroing of alignment */ 638 if (nt_header.OptionalHeader.SectionAlignment >= page_size) 639 { 640 const char *start; 641 642 start = (const char *)hlib + nt_header.OptionalHeader.SizeOfHeaders; 643 size = ALIGN_SIZE((ULONG_PTR)start, page_size) - (ULONG_PTR)start; 644 ok(!memcmp(start, filler, size), "%d: header alignment is not cleared\n", i); 645 } 646 647 if (nt_header.FileHeader.NumberOfSections) 648 { 649 SetLastError(0xdeadbeef); 650 size = VirtualQuery((char *)hlib + section.VirtualAddress, &info, sizeof(info)); 651 ok(size == sizeof(info), 652 "%d: VirtualQuery error %d\n", i, GetLastError()); 653 if (nt_header.OptionalHeader.SectionAlignment < page_size) 654 { 655 ok(info.BaseAddress == hlib, "%d: got %p != expected %p\n", i, info.BaseAddress, hlib); 656 ok(info.RegionSize == ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, page_size), "%d: got %lx != expected %x\n", 657 i, info.RegionSize, ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, page_size)); 658 ok(info.Protect == PAGE_EXECUTE_WRITECOPY, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i, info.Protect); 659 } 660 else 661 { 662 ok(info.BaseAddress == (char *)hlib + section.VirtualAddress, "%d: got %p != expected %p\n", i, info.BaseAddress, (char *)hlib + section.VirtualAddress); 663 ok(info.RegionSize == ALIGN_SIZE(section.Misc.VirtualSize, page_size), "%d: got %lx != expected %x\n", 664 i, info.RegionSize, ALIGN_SIZE(section.Misc.VirtualSize, page_size)); 665 ok(info.Protect == PAGE_READONLY, "%d: %x != PAGE_READONLY\n", i, info.Protect); 666 } 667 ok(info.AllocationBase == hlib, "%d: %p != %p\n", i, info.AllocationBase, hlib); 668 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect); 669 ok(info.State == MEM_COMMIT, "%d: %x != MEM_COMMIT\n", i, info.State); 670 ok(info.Type == SEC_IMAGE, "%d: %x != SEC_IMAGE\n", i, info.Type); 671 672 if (nt_header.OptionalHeader.SectionAlignment >= page_size) 673 ok(!memcmp((const char *)hlib + section.VirtualAddress + section.PointerToRawData, &nt_header, section.SizeOfRawData), "wrong section data\n"); 674 else 675 ok(!memcmp((const char *)hlib + section.PointerToRawData, section_data, section.SizeOfRawData), "wrong section data\n"); 676 677 /* check the zeroing of alignment */ 678 if (nt_header.OptionalHeader.SectionAlignment >= page_size) 679 { 680 const char *start; 681 682 start = (const char *)hlib + section.VirtualAddress + section.PointerToRawData + section.SizeOfRawData; 683 size = ALIGN_SIZE((ULONG_PTR)start, page_size) - (ULONG_PTR)start; 684 ok(memcmp(start, filler, size), "%d: alignment should not be cleared\n", i); 685 } 686 687 SetLastError(0xdeadbeef); 688 ptr = VirtualAlloc((char *)hlib + section.VirtualAddress, page_size, MEM_COMMIT, info.Protect); 689 ok(!ptr, "%d: VirtualAlloc should fail\n", i); 690 /* FIXME: Remove once Wine is fixed */ 691 todo_wine_if (info.Protect == PAGE_WRITECOPY || info.Protect == PAGE_EXECUTE_WRITECOPY) 692 ok(GetLastError() == ERROR_ACCESS_DENIED || GetLastError() == ERROR_INVALID_ADDRESS, 693 "%d: expected ERROR_ACCESS_DENIED, got %d\n", i, GetLastError()); 694 } 695 696 SetLastError(0xdeadbeef); 697 hlib_as_data_file = LoadLibraryExA(dll_name, 0, LOAD_LIBRARY_AS_DATAFILE); 698 ok(hlib_as_data_file != 0, "LoadLibraryEx error %u\n", GetLastError()); 699 ok(hlib_as_data_file == hlib, "hlib_as_file and hlib are different\n"); 700 701 SetLastError(0xdeadbeef); 702 ret = FreeLibrary(hlib); 703 ok(ret, "FreeLibrary error %d\n", GetLastError()); 704 705 SetLastError(0xdeadbeef); 706 hlib = GetModuleHandleA(dll_name); 707 ok(hlib != 0, "GetModuleHandle error %u\n", GetLastError()); 708 709 SetLastError(0xdeadbeef); 710 ret = FreeLibrary(hlib_as_data_file); 711 ok(ret, "FreeLibrary error %d\n", GetLastError()); 712 713 hlib = GetModuleHandleA(dll_name); 714 ok(!hlib, "GetModuleHandle should fail\n"); 715 716 SetLastError(0xdeadbeef); 717 hlib_as_data_file = LoadLibraryExA(dll_name, 0, LOAD_LIBRARY_AS_DATAFILE); 718 ok(hlib_as_data_file != 0, "LoadLibraryEx error %u\n", GetLastError()); 719 ok((ULONG_PTR)hlib_as_data_file & 1, "hlib_as_data_file is even\n"); 720 721 hlib = GetModuleHandleA(dll_name); 722 ok(!hlib, "GetModuleHandle should fail\n"); 723 724 SetLastError(0xdeadbeef); 725 h = CreateFileA( dll_name, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 ); 726 ok( h != INVALID_HANDLE_VALUE, "open failed err %u\n", GetLastError() ); 727 CloseHandle( h ); 728 729 SetLastError(0xdeadbeef); 730 ret = FreeLibrary(hlib_as_data_file); 731 ok(ret, "FreeLibrary error %d\n", GetLastError()); 732 733 SetLastError(0xdeadbeef); 734 hlib_as_data_file = LoadLibraryExA(dll_name, 0, LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE); 735 if (!((ULONG_PTR)hlib_as_data_file & 1) || /* winxp */ 736 (!hlib_as_data_file && GetLastError() == ERROR_INVALID_PARAMETER)) /* w2k3 */ 737 { 738 win_skip( "LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE not supported\n" ); 739 FreeLibrary(hlib_as_data_file); 740 } 741 else 742 { 743 ok(hlib_as_data_file != 0, "LoadLibraryEx error %u\n", GetLastError()); 744 745 SetLastError(0xdeadbeef); 746 h = CreateFileA( dll_name, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 ); 747 todo_wine ok( h == INVALID_HANDLE_VALUE, "open succeeded\n" ); 748 todo_wine ok( GetLastError() == ERROR_SHARING_VIOLATION, "wrong error %u\n", GetLastError() ); 749 CloseHandle( h ); 750 751 SetLastError(0xdeadbeef); 752 ret = FreeLibrary(hlib_as_data_file); 753 ok(ret, "FreeLibrary error %d\n", GetLastError()); 754 } 755 756 SetLastError(0xdeadbeef); 757 ret = DeleteFileA(dll_name); 758 ok(ret, "DeleteFile error %d\n", GetLastError()); 759 760 nt_header.OptionalHeader.AddressOfEntryPoint = 0x12345678; 761 file_size = create_test_dll( &dos_header, td[i].size_of_dos_header, &nt_header, dll_name ); 762 if (!file_size) 763 { 764 ok(0, "could not create %s\n", dll_name); 765 break; 766 } 767 query_image_section( i, dll_name, &nt_header ); 768 } 769 else 770 { 771 BOOL error_match; 772 int error_index; 773 774 error_match = FALSE; 775 for (error_index = 0; 776 ! error_match && error_index < sizeof(td[i].errors) / sizeof(DWORD); 777 error_index++) 778 { 779 error_match = td[i].errors[error_index] == GetLastError(); 780 } 781 ok(error_match, "%d: unexpected error %d\n", i, GetLastError()); 782 } 783 784 SetLastError(0xdeadbeef); 785 ret = DeleteFileA(dll_name); 786 ok(ret, "DeleteFile error %d\n", GetLastError()); 787 } 788 789 nt_header = nt_header_template; 790 nt_header.FileHeader.NumberOfSections = 1; 791 nt_header.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER); 792 793 nt_header.OptionalHeader.SectionAlignment = page_size; 794 nt_header.OptionalHeader.AddressOfEntryPoint = 0x1234; 795 nt_header.OptionalHeader.DllCharacteristics = IMAGE_DLLCHARACTERISTICS_NX_COMPAT; 796 nt_header.OptionalHeader.FileAlignment = page_size; 797 nt_header.OptionalHeader.SizeOfHeaders = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER); 798 nt_header.OptionalHeader.SizeOfImage = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + page_size; 799 800 status = map_image_section( &nt_header ); 801 ok( status == STATUS_SUCCESS, "NtCreateSection error %08x\n", status ); 802 803 dos_header.e_magic = 0; 804 status = map_image_section( &nt_header ); 805 ok( status == STATUS_INVALID_IMAGE_NOT_MZ, "NtCreateSection error %08x\n", status ); 806 807 dos_header.e_magic = IMAGE_DOS_SIGNATURE; 808 nt_header.Signature = IMAGE_OS2_SIGNATURE; 809 status = map_image_section( &nt_header ); 810 ok( status == STATUS_INVALID_IMAGE_NE_FORMAT, "NtCreateSection error %08x\n", status ); 811 812 nt_header.Signature = 0xdeadbeef; 813 status = map_image_section( &nt_header ); 814 ok( status == STATUS_INVALID_IMAGE_PROTECT, "NtCreateSection error %08x\n", status ); 815 816 nt_header.Signature = IMAGE_NT_SIGNATURE; 817 nt_header.OptionalHeader.Magic = 0xdead; 818 status = map_image_section( &nt_header ); 819 ok( status == STATUS_INVALID_IMAGE_FORMAT, "NtCreateSection error %08x\n", status ); 820 821 nt_header.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR_MAGIC; 822 nt_header.FileHeader.Machine = 0xdead; 823 status = map_image_section( &nt_header ); 824 ok( status == STATUS_INVALID_IMAGE_FORMAT || broken(status == STATUS_SUCCESS), /* win2k */ 825 "NtCreateSection error %08x\n", status ); 826 827 nt_header.FileHeader.Machine = IMAGE_FILE_MACHINE_UNKNOWN; 828 status = map_image_section( &nt_header ); 829 ok( status == STATUS_INVALID_IMAGE_FORMAT || broken(status == STATUS_SUCCESS), /* win2k */ 830 "NtCreateSection error %08x\n", status ); 831 832 switch (orig_machine) 833 { 834 case IMAGE_FILE_MACHINE_I386: nt_header.FileHeader.Machine = IMAGE_FILE_MACHINE_AMD64; break; 835 case IMAGE_FILE_MACHINE_AMD64: nt_header.FileHeader.Machine = IMAGE_FILE_MACHINE_I386; break; 836 case IMAGE_FILE_MACHINE_ARMNT: nt_header.FileHeader.Machine = IMAGE_FILE_MACHINE_ARM64; break; 837 case IMAGE_FILE_MACHINE_ARM64: nt_header.FileHeader.Machine = IMAGE_FILE_MACHINE_ARMNT; break; 838 } 839 status = map_image_section( &nt_header ); 840 ok( status == STATUS_INVALID_IMAGE_FORMAT || broken(status == STATUS_SUCCESS), /* win2k */ 841 "NtCreateSection error %08x\n", status ); 842 843 if (nt_header.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) 844 { 845 IMAGE_NT_HEADERS64 nt64; 846 847 memset( &nt64, 0, sizeof(nt64) ); 848 nt64.Signature = IMAGE_NT_SIGNATURE; 849 nt64.FileHeader.Machine = orig_machine; 850 nt64.FileHeader.NumberOfSections = 1; 851 nt64.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER64); 852 nt64.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR64_MAGIC; 853 nt64.OptionalHeader.MajorLinkerVersion = 1; 854 nt64.OptionalHeader.ImageBase = 0x10000000; 855 nt64.OptionalHeader.MajorOperatingSystemVersion = 4; 856 nt64.OptionalHeader.MajorImageVersion = 1; 857 nt64.OptionalHeader.MajorSubsystemVersion = 4; 858 nt64.OptionalHeader.SizeOfHeaders = sizeof(dos_header) + sizeof(nt64) + sizeof(IMAGE_SECTION_HEADER); 859 nt64.OptionalHeader.SizeOfImage = nt64.OptionalHeader.SizeOfHeaders + 0x1000; 860 nt64.OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI; 861 status = map_image_section( (IMAGE_NT_HEADERS *)&nt64 ); 862 ok( status == STATUS_INVALID_IMAGE_FORMAT, "NtCreateSection error %08x\n", status ); 863 } 864 else 865 { 866 IMAGE_NT_HEADERS32 nt32; 867 868 memset( &nt32, 0, sizeof(nt32) ); 869 nt32.Signature = IMAGE_NT_SIGNATURE; 870 nt32.FileHeader.Machine = orig_machine; 871 nt32.FileHeader.NumberOfSections = 1; 872 nt32.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER32); 873 nt32.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR32_MAGIC; 874 nt32.OptionalHeader.MajorLinkerVersion = 1; 875 nt32.OptionalHeader.ImageBase = 0x10000000; 876 nt32.OptionalHeader.MajorOperatingSystemVersion = 4; 877 nt32.OptionalHeader.MajorImageVersion = 1; 878 nt32.OptionalHeader.MajorSubsystemVersion = 4; 879 nt32.OptionalHeader.SizeOfHeaders = sizeof(dos_header) + sizeof(nt32) + sizeof(IMAGE_SECTION_HEADER); 880 nt32.OptionalHeader.SizeOfImage = nt32.OptionalHeader.SizeOfHeaders + 0x1000; 881 nt32.OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI; 882 status = map_image_section( (IMAGE_NT_HEADERS *)&nt32 ); 883 ok( status == STATUS_INVALID_IMAGE_FORMAT, "NtCreateSection error %08x\n", status ); 884 } 885 886 nt_header.FileHeader.Machine = orig_machine; /* restore it for the next tests */ 887 } 888 889 static void test_FakeDLL(void) 890 { 891 #if defined(__i386__) || defined(__x86_64__) 892 NTSTATUS (WINAPI *pNtSetEvent)(HANDLE, ULONG *) = NULL; 893 IMAGE_EXPORT_DIRECTORY *dir; 894 HMODULE module = GetModuleHandleA("ntdll.dll"); 895 HANDLE file, map, event; 896 WCHAR path[MAX_PATH]; 897 DWORD *names, *funcs; 898 WORD *ordinals; 899 ULONG size; 900 void *ptr; 901 int i; 902 903 GetModuleFileNameW(module, path, MAX_PATH); 904 905 file = CreateFileW(path, GENERIC_READ | GENERIC_EXECUTE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); 906 ok(file != INVALID_HANDLE_VALUE, "Failed to open %s (error %u)\n", wine_dbgstr_w(path), GetLastError()); 907 908 map = CreateFileMappingW(file, NULL, PAGE_EXECUTE_READ | SEC_IMAGE, 0, 0, NULL); 909 ok(map != NULL, "CreateFileMapping failed with error %u\n", GetLastError()); 910 ptr = MapViewOfFile(map, FILE_MAP_READ | FILE_MAP_EXECUTE, 0, 0, 0); 911 ok(ptr != NULL, "MapViewOfFile failed with error %u\n", GetLastError()); 912 913 dir = RtlImageDirectoryEntryToData(ptr, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &size); 914 ok(dir != NULL, "RtlImageDirectoryEntryToData failed\n"); 915 916 names = RVAToAddr(dir->AddressOfNames, ptr); 917 ordinals = RVAToAddr(dir->AddressOfNameOrdinals, ptr); 918 funcs = RVAToAddr(dir->AddressOfFunctions, ptr); 919 ok(dir->NumberOfNames > 0, "Could not find any exported functions\n"); 920 921 for (i = 0; i < dir->NumberOfNames; i++) 922 { 923 DWORD map_rva, dll_rva, map_offset, dll_offset; 924 char *func_name = RVAToAddr(names[i], ptr); 925 BYTE *dll_func, *map_func; 926 927 /* check only Nt functions for now */ 928 if (strncmp(func_name, "Zw", 2) && strncmp(func_name, "Nt", 2)) 929 continue; 930 931 dll_func = (BYTE *)GetProcAddress(module, func_name); 932 ok(dll_func != NULL, "%s: GetProcAddress returned NULL\n", func_name); 933 #if defined(__i386__) 934 if (dll_func[0] == 0x90 && dll_func[1] == 0x90 && 935 dll_func[2] == 0x90 && dll_func[3] == 0x90) 936 #elif defined(__x86_64__) 937 if (dll_func[0] == 0x48 && dll_func[1] == 0x83 && 938 dll_func[2] == 0xec && dll_func[3] == 0x08) 939 #endif 940 { 941 todo_wine ok(0, "%s: Export is a stub-function, skipping\n", func_name); 942 continue; 943 } 944 945 /* check position in memory */ 946 dll_rva = (DWORD_PTR)dll_func - (DWORD_PTR)module; 947 map_rva = funcs[ordinals[i]]; 948 ok(map_rva == dll_rva, "%s: Rva of mapped function (0x%x) does not match dll (0x%x)\n", 949 func_name, dll_rva, map_rva); 950 951 /* check position in file */ 952 map_offset = (DWORD_PTR)RtlImageRvaToVa(RtlImageNtHeader(ptr), ptr, map_rva, NULL) - (DWORD_PTR)ptr; 953 dll_offset = (DWORD_PTR)RtlImageRvaToVa(RtlImageNtHeader(module), module, dll_rva, NULL) - (DWORD_PTR)module; 954 ok(map_offset == dll_offset, "%s: File offset of mapped function (0x%x) does not match dll (0x%x)\n", 955 func_name, map_offset, dll_offset); 956 957 /* check function content */ 958 map_func = RVAToAddr(map_rva, ptr); 959 ok(!memcmp(map_func, dll_func, 0x20), "%s: Function content does not match!\n", func_name); 960 961 if (!strcmp(func_name, "NtSetEvent")) 962 pNtSetEvent = (void *)map_func; 963 } 964 965 ok(pNtSetEvent != NULL, "Could not find NtSetEvent export\n"); 966 if (pNtSetEvent) 967 { 968 event = CreateEventA(NULL, TRUE, FALSE, NULL); 969 ok(event != NULL, "CreateEvent failed with error %u\n", GetLastError()); 970 pNtSetEvent(event, 0); 971 ok(WaitForSingleObject(event, 0) == WAIT_OBJECT_0, "Event was not signaled\n"); 972 pNtSetEvent(event, 0); 973 ok(WaitForSingleObject(event, 0) == WAIT_OBJECT_0, "Event was not signaled\n"); 974 CloseHandle(event); 975 } 976 977 UnmapViewOfFile(ptr); 978 CloseHandle(map); 979 CloseHandle(file); 980 #endif 981 } 982 983 /* Verify linking style of import descriptors */ 984 static void test_ImportDescriptors(void) 985 { 986 HMODULE kernel32_module = NULL; 987 PIMAGE_DOS_HEADER d_header; 988 PIMAGE_NT_HEADERS nt_headers; 989 DWORD import_dir_size; 990 DWORD_PTR dir_offset; 991 PIMAGE_IMPORT_DESCRIPTOR import_chunk; 992 993 /* Load kernel32 module */ 994 kernel32_module = GetModuleHandleA("kernel32.dll"); 995 assert( kernel32_module != NULL ); 996 997 /* Get PE header info from module image */ 998 d_header = (PIMAGE_DOS_HEADER) kernel32_module; 999 nt_headers = (PIMAGE_NT_HEADERS) (((char*) d_header) + 1000 d_header->e_lfanew); 1001 1002 /* Get size of import entry directory */ 1003 import_dir_size = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size; 1004 if (!import_dir_size) 1005 { 1006 skip("Unable to continue testing due to missing import directory.\n"); 1007 return; 1008 } 1009 1010 /* Get address of first import chunk */ 1011 dir_offset = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; 1012 import_chunk = RVAToAddr(dir_offset, kernel32_module); 1013 ok(import_chunk != 0, "Invalid import_chunk: %p\n", import_chunk); 1014 if (!import_chunk) return; 1015 1016 /* Iterate through import descriptors and verify set name, 1017 * OriginalFirstThunk, and FirstThunk. Core Windows DLLs, such as 1018 * kernel32.dll, don't use Borland-style linking, where the table of 1019 * imported names is stored directly in FirstThunk and overwritten 1020 * by the relocation, instead of being stored in OriginalFirstThunk. 1021 * */ 1022 for (; import_chunk->FirstThunk; import_chunk++) 1023 { 1024 LPCSTR module_name = RVAToAddr(import_chunk->Name, kernel32_module); 1025 PIMAGE_THUNK_DATA name_table = RVAToAddr( 1026 U(*import_chunk).OriginalFirstThunk, kernel32_module); 1027 PIMAGE_THUNK_DATA iat = RVAToAddr( 1028 import_chunk->FirstThunk, kernel32_module); 1029 ok(module_name != NULL, "Imported module name should not be NULL\n"); 1030 ok(name_table != NULL, 1031 "Name table for imported module %s should not be NULL\n", 1032 module_name); 1033 ok(iat != NULL, "IAT for imported module %s should not be NULL\n", 1034 module_name); 1035 } 1036 } 1037 1038 static void test_image_mapping(const char *dll_name, DWORD scn_page_access, BOOL is_dll) 1039 { 1040 HANDLE hfile, hmap; 1041 NTSTATUS status; 1042 LARGE_INTEGER offset; 1043 SIZE_T size; 1044 void *addr1, *addr2; 1045 MEMORY_BASIC_INFORMATION info; 1046 1047 if (!pNtMapViewOfSection) return; 1048 1049 SetLastError(0xdeadbeef); 1050 hfile = CreateFileA(dll_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); 1051 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError()); 1052 1053 SetLastError(0xdeadbeef); 1054 hmap = CreateFileMappingW(hfile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, 0); 1055 ok(hmap != 0, "CreateFileMapping error %d\n", GetLastError()); 1056 1057 offset.u.LowPart = 0; 1058 offset.u.HighPart = 0; 1059 1060 addr1 = NULL; 1061 size = 0; 1062 status = pNtMapViewOfSection(hmap, GetCurrentProcess(), &addr1, 0, 0, &offset, 1063 &size, 1 /* ViewShare */, 0, PAGE_READONLY); 1064 ok(status == STATUS_SUCCESS, "NtMapViewOfSection error %x\n", status); 1065 ok(addr1 != 0, "mapped address should be valid\n"); 1066 1067 SetLastError(0xdeadbeef); 1068 size = VirtualQuery((char *)addr1 + section.VirtualAddress, &info, sizeof(info)); 1069 ok(size == sizeof(info), "VirtualQuery error %d\n", GetLastError()); 1070 ok(info.BaseAddress == (char *)addr1 + section.VirtualAddress, "got %p != expected %p\n", info.BaseAddress, (char *)addr1 + section.VirtualAddress); 1071 ok(info.RegionSize == page_size, "got %#lx != expected %#x\n", info.RegionSize, page_size); 1072 ok(info.Protect == scn_page_access, "got %#x != expected %#x\n", info.Protect, scn_page_access); 1073 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1); 1074 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%#x != PAGE_EXECUTE_WRITECOPY\n", info.AllocationProtect); 1075 ok(info.State == MEM_COMMIT, "%#x != MEM_COMMIT\n", info.State); 1076 ok(info.Type == SEC_IMAGE, "%#x != SEC_IMAGE\n", info.Type); 1077 1078 addr2 = NULL; 1079 size = 0; 1080 status = pNtMapViewOfSection(hmap, GetCurrentProcess(), &addr2, 0, 0, &offset, 1081 &size, 1 /* ViewShare */, 0, PAGE_READONLY); 1082 ok(status == STATUS_IMAGE_NOT_AT_BASE, "expected STATUS_IMAGE_NOT_AT_BASE, got %x\n", status); 1083 ok(addr2 != 0, "mapped address should be valid\n"); 1084 ok(addr2 != addr1, "mapped addresses should be different\n"); 1085 1086 SetLastError(0xdeadbeef); 1087 size = VirtualQuery((char *)addr2 + section.VirtualAddress, &info, sizeof(info)); 1088 ok(size == sizeof(info), "VirtualQuery error %d\n", GetLastError()); 1089 ok(info.BaseAddress == (char *)addr2 + section.VirtualAddress, "got %p != expected %p\n", info.BaseAddress, (char *)addr2 + section.VirtualAddress); 1090 ok(info.RegionSize == page_size, "got %#lx != expected %#x\n", info.RegionSize, page_size); 1091 ok(info.Protect == scn_page_access, "got %#x != expected %#x\n", info.Protect, scn_page_access); 1092 ok(info.AllocationBase == addr2, "%p != %p\n", info.AllocationBase, addr2); 1093 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%#x != PAGE_EXECUTE_WRITECOPY\n", info.AllocationProtect); 1094 ok(info.State == MEM_COMMIT, "%#x != MEM_COMMIT\n", info.State); 1095 ok(info.Type == SEC_IMAGE, "%#x != SEC_IMAGE\n", info.Type); 1096 1097 status = pNtUnmapViewOfSection(GetCurrentProcess(), addr2); 1098 ok(status == STATUS_SUCCESS, "NtUnmapViewOfSection error %x\n", status); 1099 1100 addr2 = MapViewOfFile(hmap, 0, 0, 0, 0); 1101 ok(addr2 != 0, "mapped address should be valid\n"); 1102 ok(addr2 != addr1, "mapped addresses should be different\n"); 1103 1104 SetLastError(0xdeadbeef); 1105 size = VirtualQuery((char *)addr2 + section.VirtualAddress, &info, sizeof(info)); 1106 ok(size == sizeof(info), "VirtualQuery error %d\n", GetLastError()); 1107 ok(info.BaseAddress == (char *)addr2 + section.VirtualAddress, "got %p != expected %p\n", info.BaseAddress, (char *)addr2 + section.VirtualAddress); 1108 ok(info.RegionSize == page_size, "got %#lx != expected %#x\n", info.RegionSize, page_size); 1109 ok(info.Protect == scn_page_access, "got %#x != expected %#x\n", info.Protect, scn_page_access); 1110 ok(info.AllocationBase == addr2, "%p != %p\n", info.AllocationBase, addr2); 1111 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%#x != PAGE_EXECUTE_WRITECOPY\n", info.AllocationProtect); 1112 ok(info.State == MEM_COMMIT, "%#x != MEM_COMMIT\n", info.State); 1113 ok(info.Type == SEC_IMAGE, "%#x != SEC_IMAGE\n", info.Type); 1114 1115 UnmapViewOfFile(addr2); 1116 1117 SetLastError(0xdeadbeef); 1118 addr2 = LoadLibraryA(dll_name); 1119 if (is_dll) 1120 { 1121 ok(!addr2, "LoadLibrary should fail, is_dll %d\n", is_dll); 1122 ok(GetLastError() == ERROR_INVALID_ADDRESS, "expected ERROR_INVALID_ADDRESS, got %d\n", GetLastError()); 1123 } 1124 else 1125 { 1126 BOOL ret; 1127 ok(addr2 != 0, "LoadLibrary error %d, is_dll %d\n", GetLastError(), is_dll); 1128 ok(addr2 != addr1, "mapped addresses should be different\n"); 1129 1130 SetLastError(0xdeadbeef); 1131 ret = FreeLibrary(addr2); 1132 ok(ret, "FreeLibrary error %d\n", GetLastError()); 1133 } 1134 1135 status = pNtUnmapViewOfSection(GetCurrentProcess(), addr1); 1136 ok(status == STATUS_SUCCESS, "NtUnmapViewOfSection error %x\n", status); 1137 1138 CloseHandle(hmap); 1139 CloseHandle(hfile); 1140 } 1141 1142 static BOOL is_mem_writable(DWORD prot) 1143 { 1144 switch (prot & 0xff) 1145 { 1146 case PAGE_READWRITE: 1147 case PAGE_WRITECOPY: 1148 case PAGE_EXECUTE_READWRITE: 1149 case PAGE_EXECUTE_WRITECOPY: 1150 return TRUE; 1151 1152 default: 1153 return FALSE; 1154 } 1155 } 1156 1157 static void test_VirtualProtect(void *base, void *section) 1158 { 1159 static const struct test_data 1160 { 1161 DWORD prot_set, prot_get; 1162 } td[] = 1163 { 1164 { 0, 0 }, /* 0x00 */ 1165 { PAGE_NOACCESS, PAGE_NOACCESS }, /* 0x01 */ 1166 { PAGE_READONLY, PAGE_READONLY }, /* 0x02 */ 1167 { PAGE_READONLY | PAGE_NOACCESS, 0 }, /* 0x03 */ 1168 { PAGE_READWRITE, PAGE_WRITECOPY }, /* 0x04 */ 1169 { PAGE_READWRITE | PAGE_NOACCESS, 0 }, /* 0x05 */ 1170 { PAGE_READWRITE | PAGE_READONLY, 0 }, /* 0x06 */ 1171 { PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, 0 }, /* 0x07 */ 1172 { PAGE_WRITECOPY, PAGE_WRITECOPY }, /* 0x08 */ 1173 { PAGE_WRITECOPY | PAGE_NOACCESS, 0 }, /* 0x09 */ 1174 { PAGE_WRITECOPY | PAGE_READONLY, 0 }, /* 0x0a */ 1175 { PAGE_WRITECOPY | PAGE_NOACCESS | PAGE_READONLY, 0 }, /* 0x0b */ 1176 { PAGE_WRITECOPY | PAGE_READWRITE, 0 }, /* 0x0c */ 1177 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_NOACCESS, 0 }, /* 0x0d */ 1178 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY, 0 }, /* 0x0e */ 1179 { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, 0 }, /* 0x0f */ 1180 1181 { PAGE_EXECUTE, PAGE_EXECUTE }, /* 0x10 */ 1182 { PAGE_EXECUTE_READ, PAGE_EXECUTE_READ }, /* 0x20 */ 1183 { PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 }, /* 0x30 */ 1184 { PAGE_EXECUTE_READWRITE, PAGE_EXECUTE_WRITECOPY }, /* 0x40 */ 1185 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, 0 }, /* 0x50 */ 1186 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, 0 }, /* 0x60 */ 1187 { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 }, /* 0x70 */ 1188 { PAGE_EXECUTE_WRITECOPY, PAGE_EXECUTE_WRITECOPY }, /* 0x80 */ 1189 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE, 0 }, /* 0x90 */ 1190 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ, 0 }, /* 0xa0 */ 1191 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 }, /* 0xb0 */ 1192 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE, 0 }, /* 0xc0 */ 1193 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, 0 }, /* 0xd0 */ 1194 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, 0 }, /* 0xe0 */ 1195 { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 } /* 0xf0 */ 1196 }; 1197 DWORD ret, orig_prot, old_prot, rw_prot, exec_prot, i, j; 1198 MEMORY_BASIC_INFORMATION info; 1199 1200 SetLastError(0xdeadbeef); 1201 ret = VirtualProtect(section, page_size, PAGE_NOACCESS, &old_prot); 1202 ok(ret, "VirtualProtect error %d\n", GetLastError()); 1203 1204 orig_prot = old_prot; 1205 1206 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++) 1207 { 1208 SetLastError(0xdeadbeef); 1209 ret = VirtualQuery(section, &info, sizeof(info)); 1210 ok(ret, "VirtualQuery failed %d\n", GetLastError()); 1211 ok(info.BaseAddress == section, "%d: got %p != expected %p\n", i, info.BaseAddress, section); 1212 ok(info.RegionSize == page_size, "%d: got %#lx != expected %#x\n", i, info.RegionSize, page_size); 1213 ok(info.Protect == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, info.Protect); 1214 ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base); 1215 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%d: %#x != PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect); 1216 ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State); 1217 ok(info.Type == SEC_IMAGE, "%d: %#x != SEC_IMAGE\n", i, info.Type); 1218 1219 old_prot = 0xdeadbeef; 1220 SetLastError(0xdeadbeef); 1221 ret = VirtualProtect(section, page_size, td[i].prot_set, &old_prot); 1222 if (td[i].prot_get) 1223 { 1224 ok(ret, "%d: VirtualProtect error %d, requested prot %#x\n", i, GetLastError(), td[i].prot_set); 1225 ok(old_prot == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, old_prot); 1226 1227 SetLastError(0xdeadbeef); 1228 ret = VirtualQuery(section, &info, sizeof(info)); 1229 ok(ret, "VirtualQuery failed %d\n", GetLastError()); 1230 ok(info.BaseAddress == section, "%d: got %p != expected %p\n", i, info.BaseAddress, section); 1231 ok(info.RegionSize == page_size, "%d: got %#lx != expected %#x\n", i, info.RegionSize, page_size); 1232 ok(info.Protect == td[i].prot_get, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot_get); 1233 ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base); 1234 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%d: %#x != PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect); 1235 ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State); 1236 ok(info.Type == SEC_IMAGE, "%d: %#x != SEC_IMAGE\n", i, info.Type); 1237 } 1238 else 1239 { 1240 ok(!ret, "%d: VirtualProtect should fail\n", i); 1241 ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError()); 1242 } 1243 1244 old_prot = 0xdeadbeef; 1245 SetLastError(0xdeadbeef); 1246 ret = VirtualProtect(section, page_size, PAGE_NOACCESS, &old_prot); 1247 ok(ret, "%d: VirtualProtect error %d\n", i, GetLastError()); 1248 if (td[i].prot_get) 1249 ok(old_prot == td[i].prot_get, "%d: got %#x != expected %#x\n", i, old_prot, td[i].prot_get); 1250 else 1251 ok(old_prot == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, old_prot); 1252 } 1253 1254 exec_prot = 0; 1255 1256 for (i = 0; i <= 4; i++) 1257 { 1258 rw_prot = 0; 1259 1260 for (j = 0; j <= 4; j++) 1261 { 1262 DWORD prot = exec_prot | rw_prot; 1263 1264 SetLastError(0xdeadbeef); 1265 ret = VirtualProtect(section, page_size, prot, &old_prot); 1266 if ((rw_prot && exec_prot) || (!rw_prot && !exec_prot)) 1267 { 1268 ok(!ret, "VirtualProtect(%02x) should fail\n", prot); 1269 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 1270 } 1271 else 1272 ok(ret, "VirtualProtect(%02x) error %d\n", prot, GetLastError()); 1273 1274 rw_prot = 1 << j; 1275 } 1276 1277 exec_prot = 1 << (i + 4); 1278 } 1279 1280 SetLastError(0xdeadbeef); 1281 ret = VirtualProtect(section, page_size, orig_prot, &old_prot); 1282 ok(ret, "VirtualProtect error %d\n", GetLastError()); 1283 } 1284 1285 static void test_section_access(void) 1286 { 1287 static const struct test_data 1288 { 1289 DWORD scn_file_access, scn_page_access, scn_page_access_after_write; 1290 } td[] = 1291 { 1292 { 0, PAGE_NOACCESS, 0 }, 1293 { IMAGE_SCN_MEM_READ, PAGE_READONLY, 0 }, 1294 { IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY, PAGE_READWRITE }, 1295 { IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE, 0 }, 1296 { IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY, PAGE_READWRITE }, 1297 { IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_READ }, 1298 { IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY, PAGE_EXECUTE_READWRITE }, 1299 { IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY, PAGE_EXECUTE_READWRITE }, 1300 1301 { IMAGE_SCN_CNT_INITIALIZED_DATA, PAGE_NOACCESS, 0 }, 1302 { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ, PAGE_READONLY, 0 }, 1303 { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY, PAGE_READWRITE }, 1304 { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE, 0 }, 1305 { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY, PAGE_READWRITE }, 1306 { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_READ, 0 }, 1307 { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY, PAGE_EXECUTE_READWRITE }, 1308 { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY, PAGE_EXECUTE_READWRITE }, 1309 1310 { IMAGE_SCN_CNT_UNINITIALIZED_DATA, PAGE_NOACCESS, 0 }, 1311 { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ, PAGE_READONLY, 0 }, 1312 { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY, PAGE_READWRITE }, 1313 { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE, 0 }, 1314 { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY, PAGE_READWRITE }, 1315 { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_READ, 0 }, 1316 { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY, PAGE_EXECUTE_READWRITE }, 1317 { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY, PAGE_EXECUTE_READWRITE } 1318 }; 1319 char buf[256]; 1320 int i; 1321 DWORD dummy, file_align; 1322 HANDLE hfile; 1323 HMODULE hlib; 1324 char temp_path[MAX_PATH]; 1325 char dll_name[MAX_PATH]; 1326 SIZE_T size; 1327 MEMORY_BASIC_INFORMATION info; 1328 STARTUPINFOA sti; 1329 PROCESS_INFORMATION pi; 1330 DWORD ret; 1331 1332 /* prevent displaying of the "Unable to load this DLL" message box */ 1333 SetErrorMode(SEM_FAILCRITICALERRORS); 1334 1335 GetTempPathA(MAX_PATH, temp_path); 1336 1337 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++) 1338 { 1339 IMAGE_NT_HEADERS nt_header; 1340 1341 GetTempFileNameA(temp_path, "ldr", 0, dll_name); 1342 1343 /*trace("creating %s\n", dll_name);*/ 1344 hfile = CreateFileA(dll_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); 1345 if (hfile == INVALID_HANDLE_VALUE) 1346 { 1347 ok(0, "could not create %s\n", dll_name); 1348 return; 1349 } 1350 1351 SetLastError(0xdeadbeef); 1352 ret = WriteFile(hfile, &dos_header, sizeof(dos_header), &dummy, NULL); 1353 ok(ret, "WriteFile error %d\n", GetLastError()); 1354 1355 nt_header = nt_header_template; 1356 nt_header.FileHeader.NumberOfSections = 1; 1357 nt_header.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER); 1358 nt_header.FileHeader.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL | IMAGE_FILE_RELOCS_STRIPPED; 1359 1360 nt_header.OptionalHeader.SectionAlignment = page_size; 1361 nt_header.OptionalHeader.FileAlignment = 0x200; 1362 nt_header.OptionalHeader.SizeOfImage = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + page_size; 1363 nt_header.OptionalHeader.SizeOfHeaders = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER); 1364 SetLastError(0xdeadbeef); 1365 ret = WriteFile(hfile, &nt_header, sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER), &dummy, NULL); 1366 ok(ret, "WriteFile error %d\n", GetLastError()); 1367 SetLastError(0xdeadbeef); 1368 ret = WriteFile(hfile, &nt_header.OptionalHeader, sizeof(IMAGE_OPTIONAL_HEADER), &dummy, NULL); 1369 ok(ret, "WriteFile error %d\n", GetLastError()); 1370 1371 section.SizeOfRawData = sizeof(section_data); 1372 section.PointerToRawData = nt_header.OptionalHeader.FileAlignment; 1373 section.VirtualAddress = nt_header.OptionalHeader.SectionAlignment; 1374 section.Misc.VirtualSize = section.SizeOfRawData; 1375 section.Characteristics = td[i].scn_file_access; 1376 SetLastError(0xdeadbeef); 1377 ret = WriteFile(hfile, §ion, sizeof(section), &dummy, NULL); 1378 ok(ret, "WriteFile error %d\n", GetLastError()); 1379 1380 file_align = nt_header.OptionalHeader.FileAlignment - nt_header.OptionalHeader.SizeOfHeaders; 1381 assert(file_align < sizeof(filler)); 1382 SetLastError(0xdeadbeef); 1383 ret = WriteFile(hfile, filler, file_align, &dummy, NULL); 1384 ok(ret, "WriteFile error %d\n", GetLastError()); 1385 1386 /* section data */ 1387 SetLastError(0xdeadbeef); 1388 ret = WriteFile(hfile, section_data, sizeof(section_data), &dummy, NULL); 1389 ok(ret, "WriteFile error %d\n", GetLastError()); 1390 1391 CloseHandle(hfile); 1392 1393 SetLastError(0xdeadbeef); 1394 hlib = LoadLibraryA(dll_name); 1395 ok(hlib != 0, "LoadLibrary error %d\n", GetLastError()); 1396 1397 SetLastError(0xdeadbeef); 1398 size = VirtualQuery((char *)hlib + section.VirtualAddress, &info, sizeof(info)); 1399 ok(size == sizeof(info), 1400 "%d: VirtualQuery error %d\n", i, GetLastError()); 1401 ok(info.BaseAddress == (char *)hlib + section.VirtualAddress, "%d: got %p != expected %p\n", i, info.BaseAddress, (char *)hlib + section.VirtualAddress); 1402 ok(info.RegionSize == page_size, "%d: got %#lx != expected %#x\n", i, info.RegionSize, page_size); 1403 ok(info.Protect == td[i].scn_page_access, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].scn_page_access); 1404 ok(info.AllocationBase == hlib, "%d: %p != %p\n", i, info.AllocationBase, hlib); 1405 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%d: %#x != PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect); 1406 ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State); 1407 ok(info.Type == SEC_IMAGE, "%d: %#x != SEC_IMAGE\n", i, info.Type); 1408 if (info.Protect != PAGE_NOACCESS) 1409 ok(!memcmp((const char *)info.BaseAddress, section_data, section.SizeOfRawData), "wrong section data\n"); 1410 1411 test_VirtualProtect(hlib, (char *)hlib + section.VirtualAddress); 1412 1413 /* Windows changes the WRITECOPY to WRITE protection on an image section write (for a changed page only) */ 1414 if (is_mem_writable(info.Protect)) 1415 { 1416 char *p = info.BaseAddress; 1417 *p = 0xfe; 1418 SetLastError(0xdeadbeef); 1419 size = VirtualQuery((char *)hlib + section.VirtualAddress, &info, sizeof(info)); 1420 ok(size == sizeof(info), "%d: VirtualQuery error %d\n", i, GetLastError()); 1421 /* FIXME: remove the condition below once Wine is fixed */ 1422 todo_wine_if (info.Protect == PAGE_WRITECOPY || info.Protect == PAGE_EXECUTE_WRITECOPY) 1423 ok(info.Protect == td[i].scn_page_access_after_write, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].scn_page_access_after_write); 1424 } 1425 1426 SetLastError(0xdeadbeef); 1427 ret = FreeLibrary(hlib); 1428 ok(ret, "FreeLibrary error %d\n", GetLastError()); 1429 1430 test_image_mapping(dll_name, td[i].scn_page_access, TRUE); 1431 1432 /* reset IMAGE_FILE_DLL otherwise CreateProcess fails */ 1433 nt_header.FileHeader.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_RELOCS_STRIPPED; 1434 SetLastError(0xdeadbeef); 1435 hfile = CreateFileA(dll_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0); 1436 /* LoadLibrary called on an already memory-mapped file in 1437 * test_image_mapping() above leads to a file handle leak 1438 * under nt4, and inability to overwrite and delete the file 1439 * due to sharing violation error. Ignore it and skip the test, 1440 * but leave a not deletable temporary file. 1441 */ 1442 ok(hfile != INVALID_HANDLE_VALUE || broken(hfile == INVALID_HANDLE_VALUE) /* nt4 */, 1443 "CreateFile error %d\n", GetLastError()); 1444 if (hfile == INVALID_HANDLE_VALUE) goto nt4_is_broken; 1445 SetFilePointer(hfile, sizeof(dos_header), NULL, FILE_BEGIN); 1446 SetLastError(0xdeadbeef); 1447 ret = WriteFile(hfile, &nt_header, sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER), &dummy, NULL); 1448 ok(ret, "WriteFile error %d\n", GetLastError()); 1449 CloseHandle(hfile); 1450 1451 memset(&sti, 0, sizeof(sti)); 1452 sti.cb = sizeof(sti); 1453 SetLastError(0xdeadbeef); 1454 ret = CreateProcessA(dll_name, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &sti, &pi); 1455 ok(ret, "CreateProcess() error %d\n", GetLastError()); 1456 1457 SetLastError(0xdeadbeef); 1458 size = VirtualQueryEx(pi.hProcess, (char *)hlib + section.VirtualAddress, &info, sizeof(info)); 1459 ok(size == sizeof(info), 1460 "%d: VirtualQuery error %d\n", i, GetLastError()); 1461 ok(info.BaseAddress == (char *)hlib + section.VirtualAddress, "%d: got %p != expected %p\n", i, info.BaseAddress, (char *)hlib + section.VirtualAddress); 1462 ok(info.RegionSize == page_size, "%d: got %#lx != expected %#x\n", i, info.RegionSize, page_size); 1463 ok(info.Protect == td[i].scn_page_access, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].scn_page_access); 1464 ok(info.AllocationBase == hlib, "%d: %p != %p\n", i, info.AllocationBase, hlib); 1465 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%d: %#x != PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect); 1466 ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State); 1467 ok(info.Type == SEC_IMAGE, "%d: %#x != SEC_IMAGE\n", i, info.Type); 1468 if (info.Protect != PAGE_NOACCESS) 1469 { 1470 SetLastError(0xdeadbeef); 1471 ret = ReadProcessMemory(pi.hProcess, info.BaseAddress, buf, section.SizeOfRawData, NULL); 1472 ok(ret, "ReadProcessMemory() error %d\n", GetLastError()); 1473 ok(!memcmp(buf, section_data, section.SizeOfRawData), "wrong section data\n"); 1474 } 1475 1476 SetLastError(0xdeadbeef); 1477 ret = TerminateProcess(pi.hProcess, 0); 1478 ok(ret, "TerminateProcess() error %d\n", GetLastError()); 1479 ret = WaitForSingleObject(pi.hProcess, 3000); 1480 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed: %x\n", ret); 1481 1482 CloseHandle(pi.hThread); 1483 CloseHandle(pi.hProcess); 1484 1485 test_image_mapping(dll_name, td[i].scn_page_access, FALSE); 1486 1487 nt4_is_broken: 1488 SetLastError(0xdeadbeef); 1489 ret = DeleteFileA(dll_name); 1490 ok(ret || broken(!ret) /* nt4 */, "DeleteFile error %d\n", GetLastError()); 1491 } 1492 } 1493 1494 static void test_import_resolution(void) 1495 { 1496 char temp_path[MAX_PATH]; 1497 char dll_name[MAX_PATH]; 1498 DWORD dummy; 1499 void *expect; 1500 char *str; 1501 HANDLE hfile; 1502 HMODULE mod, mod2; 1503 struct imports 1504 { 1505 IMAGE_IMPORT_DESCRIPTOR descr[2]; 1506 IMAGE_THUNK_DATA original_thunks[2]; 1507 IMAGE_THUNK_DATA thunks[2]; 1508 char module[16]; 1509 struct { WORD hint; char name[32]; } function; 1510 IMAGE_TLS_DIRECTORY tls; 1511 char tls_data[16]; 1512 SHORT tls_index; 1513 } data, *ptr; 1514 IMAGE_NT_HEADERS nt; 1515 IMAGE_SECTION_HEADER section; 1516 int test; 1517 1518 for (test = 0; test < 3; test++) 1519 { 1520 #define DATA_RVA(ptr) (page_size + ((char *)(ptr) - (char *)&data)) 1521 nt = nt_header_template; 1522 nt.FileHeader.NumberOfSections = 1; 1523 nt.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER); 1524 nt.FileHeader.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_RELOCS_STRIPPED; 1525 if (test != 2) nt.FileHeader.Characteristics |= IMAGE_FILE_DLL; 1526 nt.OptionalHeader.SectionAlignment = page_size; 1527 nt.OptionalHeader.FileAlignment = 0x200; 1528 nt.OptionalHeader.ImageBase = 0x12340000; 1529 nt.OptionalHeader.SizeOfImage = 2 * page_size; 1530 nt.OptionalHeader.SizeOfHeaders = nt.OptionalHeader.FileAlignment; 1531 nt.OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES; 1532 memset( nt.OptionalHeader.DataDirectory, 0, sizeof(nt.OptionalHeader.DataDirectory) ); 1533 nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = sizeof(data.descr); 1534 nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = DATA_RVA(data.descr); 1535 nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size = sizeof(data.tls); 1536 nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress = DATA_RVA(&data.tls); 1537 1538 memset( &data, 0, sizeof(data) ); 1539 data.descr[0].OriginalFirstThunk = DATA_RVA( data.original_thunks ); 1540 data.descr[0].FirstThunk = DATA_RVA( data.thunks ); 1541 data.descr[0].Name = DATA_RVA( data.module ); 1542 strcpy( data.module, "kernel32.dll" ); 1543 strcpy( data.function.name, "CreateEventA" ); 1544 data.original_thunks[0].u1.AddressOfData = DATA_RVA( &data.function ); 1545 data.thunks[0].u1.AddressOfData = 0xdeadbeef; 1546 1547 data.tls.StartAddressOfRawData = nt.OptionalHeader.ImageBase + DATA_RVA( data.tls_data ); 1548 data.tls.EndAddressOfRawData = data.tls.StartAddressOfRawData + sizeof(data.tls_data); 1549 data.tls.AddressOfIndex = nt.OptionalHeader.ImageBase + DATA_RVA( &data.tls_index ); 1550 strcpy( data.tls_data, "hello world" ); 1551 data.tls_index = 9999; 1552 1553 GetTempPathA(MAX_PATH, temp_path); 1554 GetTempFileNameA(temp_path, "ldr", 0, dll_name); 1555 1556 hfile = CreateFileA(dll_name, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, 0); 1557 ok( hfile != INVALID_HANDLE_VALUE, "creation failed\n" ); 1558 1559 memset( §ion, 0, sizeof(section) ); 1560 memcpy( section.Name, ".text", sizeof(".text") ); 1561 section.PointerToRawData = nt.OptionalHeader.FileAlignment; 1562 section.VirtualAddress = nt.OptionalHeader.SectionAlignment; 1563 section.Misc.VirtualSize = sizeof(data); 1564 section.SizeOfRawData = sizeof(data); 1565 section.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE; 1566 1567 WriteFile(hfile, &dos_header, sizeof(dos_header), &dummy, NULL); 1568 WriteFile(hfile, &nt, sizeof(nt), &dummy, NULL); 1569 WriteFile(hfile, §ion, sizeof(section), &dummy, NULL); 1570 1571 SetFilePointer( hfile, section.PointerToRawData, NULL, SEEK_SET ); 1572 WriteFile(hfile, &data, sizeof(data), &dummy, NULL); 1573 1574 CloseHandle( hfile ); 1575 1576 switch (test) 1577 { 1578 case 0: /* normal load */ 1579 mod = LoadLibraryA( dll_name ); 1580 ok( mod != NULL, "failed to load err %u\n", GetLastError() ); 1581 if (!mod) break; 1582 ptr = (struct imports *)((char *)mod + page_size); 1583 expect = GetProcAddress( GetModuleHandleA( data.module ), data.function.name ); 1584 ok( (void *)ptr->thunks[0].u1.Function == expect, "thunk %p instead of %p for %s.%s\n", 1585 (void *)ptr->thunks[0].u1.Function, expect, data.module, data.function.name ); 1586 ok( ptr->tls_index < 32 || broken(ptr->tls_index == 9999), /* before vista */ 1587 "wrong tls index %d\n", ptr->tls_index ); 1588 if (ptr->tls_index != 9999) 1589 { 1590 str = ((char **)NtCurrentTeb()->ThreadLocalStoragePointer)[ptr->tls_index]; 1591 ok( !strcmp( str, "hello world" ), "wrong tls data '%s' at %p\n", str, str ); 1592 } 1593 FreeLibrary( mod ); 1594 break; 1595 case 1: /* load with DONT_RESOLVE_DLL_REFERENCES doesn't resolve imports */ 1596 mod = LoadLibraryExA( dll_name, 0, DONT_RESOLVE_DLL_REFERENCES ); 1597 ok( mod != NULL, "failed to load err %u\n", GetLastError() ); 1598 if (!mod) break; 1599 ptr = (struct imports *)((char *)mod + page_size); 1600 ok( ptr->thunks[0].u1.Function == 0xdeadbeef, "thunk resolved to %p for %s.%s\n", 1601 (void *)ptr->thunks[0].u1.Function, data.module, data.function.name ); 1602 ok( ptr->tls_index == 9999, "wrong tls index %d\n", ptr->tls_index ); 1603 1604 mod2 = LoadLibraryA( dll_name ); 1605 ok( mod2 == mod, "loaded twice %p / %p\n", mod, mod2 ); 1606 ok( ptr->thunks[0].u1.Function == 0xdeadbeef, "thunk resolved to %p for %s.%s\n", 1607 (void *)ptr->thunks[0].u1.Function, data.module, data.function.name ); 1608 ok( ptr->tls_index == 9999, "wrong tls index %d\n", ptr->tls_index ); 1609 FreeLibrary( mod2 ); 1610 FreeLibrary( mod ); 1611 break; 1612 case 2: /* load without IMAGE_FILE_DLL doesn't resolve imports */ 1613 mod = LoadLibraryA( dll_name ); 1614 ok( mod != NULL, "failed to load err %u\n", GetLastError() ); 1615 if (!mod) break; 1616 ptr = (struct imports *)((char *)mod + page_size); 1617 ok( ptr->thunks[0].u1.Function == 0xdeadbeef, "thunk resolved to %p for %s.%s\n", 1618 (void *)ptr->thunks[0].u1.Function, data.module, data.function.name ); 1619 ok( ptr->tls_index == 9999, "wrong tls index %d\n", ptr->tls_index ); 1620 FreeLibrary( mod ); 1621 break; 1622 } 1623 DeleteFileA( dll_name ); 1624 #undef DATA_RVA 1625 } 1626 } 1627 1628 #define MAX_COUNT 10 1629 static HANDLE attached_thread[MAX_COUNT]; 1630 static DWORD attached_thread_count; 1631 HANDLE stop_event, event, mutex, semaphore, loader_lock_event, peb_lock_event, heap_lock_event, ack_event; 1632 static int test_dll_phase, inside_loader_lock, inside_peb_lock, inside_heap_lock; 1633 static LONG fls_callback_count; 1634 1635 static DWORD WINAPI mutex_thread_proc(void *param) 1636 { 1637 HANDLE wait_list[4]; 1638 DWORD ret; 1639 1640 ret = WaitForSingleObject(mutex, 0); 1641 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %#x\n", ret); 1642 1643 SetEvent(param); 1644 1645 wait_list[0] = stop_event; 1646 wait_list[1] = loader_lock_event; 1647 wait_list[2] = peb_lock_event; 1648 wait_list[3] = heap_lock_event; 1649 1650 trace("%04u: mutex_thread_proc: starting\n", GetCurrentThreadId()); 1651 while (1) 1652 { 1653 ret = WaitForMultipleObjects(sizeof(wait_list)/sizeof(wait_list[0]), wait_list, FALSE, 50); 1654 if (ret == WAIT_OBJECT_0) break; 1655 else if (ret == WAIT_OBJECT_0 + 1) 1656 { 1657 ULONG_PTR loader_lock_magic; 1658 trace("%04u: mutex_thread_proc: Entering loader lock\n", GetCurrentThreadId()); 1659 ret = pLdrLockLoaderLock(0, NULL, &loader_lock_magic); 1660 ok(!ret, "LdrLockLoaderLock error %#x\n", ret); 1661 inside_loader_lock++; 1662 SetEvent(ack_event); 1663 } 1664 else if (ret == WAIT_OBJECT_0 + 2) 1665 { 1666 trace("%04u: mutex_thread_proc: Entering PEB lock\n", GetCurrentThreadId()); 1667 pRtlAcquirePebLock(); 1668 inside_peb_lock++; 1669 SetEvent(ack_event); 1670 } 1671 else if (ret == WAIT_OBJECT_0 + 3) 1672 { 1673 trace("%04u: mutex_thread_proc: Entering heap lock\n", GetCurrentThreadId()); 1674 HeapLock(GetProcessHeap()); 1675 inside_heap_lock++; 1676 SetEvent(ack_event); 1677 } 1678 } 1679 1680 trace("%04u: mutex_thread_proc: exiting\n", GetCurrentThreadId()); 1681 return 196; 1682 } 1683 1684 static DWORD WINAPI semaphore_thread_proc(void *param) 1685 { 1686 DWORD ret; 1687 1688 ret = WaitForSingleObject(semaphore, 0); 1689 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %#x\n", ret); 1690 1691 SetEvent(param); 1692 1693 while (1) 1694 { 1695 if (winetest_debug > 1) 1696 trace("%04u: semaphore_thread_proc: still alive\n", GetCurrentThreadId()); 1697 if (WaitForSingleObject(stop_event, 50) != WAIT_TIMEOUT) break; 1698 } 1699 1700 trace("%04u: semaphore_thread_proc: exiting\n", GetCurrentThreadId()); 1701 return 196; 1702 } 1703 1704 static DWORD WINAPI noop_thread_proc(void *param) 1705 { 1706 if (param) 1707 { 1708 LONG *noop_thread_started = param; 1709 InterlockedIncrement(noop_thread_started); 1710 } 1711 1712 trace("%04u: noop_thread_proc: exiting\n", GetCurrentThreadId()); 1713 return 195; 1714 } 1715 1716 static VOID WINAPI fls_callback(PVOID lpFlsData) 1717 { 1718 ok(lpFlsData == (void*) 0x31415, "lpFlsData is %p, expected %p\n", lpFlsData, (void*) 0x31415); 1719 InterlockedIncrement(&fls_callback_count); 1720 } 1721 1722 static BOOL WINAPI dll_entry_point(HINSTANCE hinst, DWORD reason, LPVOID param) 1723 { 1724 static LONG noop_thread_started; 1725 static DWORD fls_index = FLS_OUT_OF_INDEXES; 1726 static int fls_count = 0; 1727 static int thread_detach_count = 0; 1728 DWORD ret; 1729 1730 ok(!inside_loader_lock, "inside_loader_lock should not be set\n"); 1731 ok(!inside_peb_lock, "inside_peb_lock should not be set\n"); 1732 1733 switch (reason) 1734 { 1735 case DLL_PROCESS_ATTACH: 1736 trace("dll: %p, DLL_PROCESS_ATTACH, %p\n", hinst, param); 1737 1738 ret = pRtlDllShutdownInProgress(); 1739 ok(!ret, "RtlDllShutdownInProgress returned %d\n", ret); 1740 1741 /* Set up the FLS slot, if FLS is available */ 1742 if (pFlsGetValue) 1743 { 1744 void* value; 1745 BOOL bret; 1746 ret = pFlsAlloc(&fls_callback); 1747 ok(ret != FLS_OUT_OF_INDEXES, "FlsAlloc returned %d\n", ret); 1748 fls_index = ret; 1749 SetLastError(0xdeadbeef); 1750 value = pFlsGetValue(fls_index); 1751 ok(!value, "FlsGetValue returned %p, expected NULL\n", value); 1752 ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %u\n", GetLastError()); 1753 bret = pFlsSetValue(fls_index, (void*) 0x31415); 1754 ok(bret, "FlsSetValue failed\n"); 1755 fls_count++; 1756 } 1757 1758 break; 1759 case DLL_PROCESS_DETACH: 1760 { 1761 DWORD code, expected_code, i; 1762 HANDLE handle, process; 1763 void *addr; 1764 SIZE_T size; 1765 LARGE_INTEGER offset; 1766 DEBUG_EVENT de; 1767 1768 trace("dll: %p, DLL_PROCESS_DETACH, %p\n", hinst, param); 1769 1770 if (test_dll_phase == 4 || test_dll_phase == 5) 1771 { 1772 ok(0, "dll_entry_point(DLL_PROCESS_DETACH) should not be called\n"); 1773 break; 1774 } 1775 1776 /* The process should already deadlock at this point */ 1777 if (test_dll_phase == 6) 1778 { 1779 /* In reality, code below never gets executed, probably some other 1780 * code tries to access process heap and deadlocks earlier, even XP 1781 * doesn't call the DLL entry point on process detach either. 1782 */ 1783 HeapLock(GetProcessHeap()); 1784 ok(0, "dll_entry_point: process should already deadlock\n"); 1785 break; 1786 } 1787 1788 if (test_dll_phase == 0 || test_dll_phase == 1 || test_dll_phase == 3) 1789 ok(param != NULL, "dll: param %p\n", param); 1790 else 1791 ok(!param, "dll: param %p\n", param); 1792 1793 if (test_dll_phase == 0 || test_dll_phase == 1) expected_code = 195; 1794 else if (test_dll_phase == 3) expected_code = 196; 1795 else expected_code = STILL_ACTIVE; 1796 1797 if (test_dll_phase == 3) 1798 { 1799 ret = pRtlDllShutdownInProgress(); 1800 ok(ret, "RtlDllShutdownInProgress returned %d\n", ret); 1801 } 1802 else 1803 { 1804 ret = pRtlDllShutdownInProgress(); 1805 1806 /* FIXME: remove once Wine is fixed */ 1807 todo_wine_if (!(expected_code == STILL_ACTIVE || expected_code == 196)) 1808 ok(!ret || broken(ret) /* before Vista */, "RtlDllShutdownInProgress returned %d\n", ret); 1809 } 1810 1811 /* In the case that the process is terminating, FLS slots should still be accessible, but 1812 * the callback should be already run for this thread and the contents already NULL. 1813 * Note that this is broken for Win2k3, which runs the callbacks *after* the DLL entry 1814 * point has already run. 1815 */ 1816 if (param && pFlsGetValue) 1817 { 1818 void* value; 1819 SetLastError(0xdeadbeef); 1820 value = pFlsGetValue(fls_index); 1821 todo_wine 1822 { 1823 ok(broken(value == (void*) 0x31415) || /* Win2k3 */ 1824 value == NULL, "FlsGetValue returned %p, expected NULL\n", value); 1825 } 1826 ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %u\n", GetLastError()); 1827 todo_wine 1828 { 1829 ok(broken(fls_callback_count == thread_detach_count) || /* Win2k3 */ 1830 fls_callback_count == thread_detach_count + 1, 1831 "wrong FLS callback count %d, expected %d\n", fls_callback_count, thread_detach_count + 1); 1832 } 1833 } 1834 if (pFlsFree) 1835 { 1836 BOOL ret; 1837 /* Call FlsFree now and run the remaining callbacks from uncleanly terminated threads */ 1838 ret = pFlsFree(fls_index); 1839 ok(ret, "FlsFree failed with error %u\n", GetLastError()); 1840 fls_index = FLS_OUT_OF_INDEXES; 1841 todo_wine 1842 { 1843 ok(fls_callback_count == fls_count, 1844 "wrong FLS callback count %d, expected %d\n", fls_callback_count, fls_count); 1845 } 1846 } 1847 1848 ok(attached_thread_count >= 2, "attached thread count should be >= 2\n"); 1849 1850 for (i = 0; i < attached_thread_count; i++) 1851 { 1852 /* Calling GetExitCodeThread() without waiting for thread termination 1853 * leads to different results due to a race condition. 1854 */ 1855 if (expected_code != STILL_ACTIVE) 1856 { 1857 ret = WaitForSingleObject(attached_thread[i], 1000); 1858 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %#x\n", ret); 1859 } 1860 ret = GetExitCodeThread(attached_thread[i], &code); 1861 trace("dll: GetExitCodeThread(%u) => %d,%u\n", i, ret, code); 1862 ok(ret == 1, "GetExitCodeThread returned %d, expected 1\n", ret); 1863 ok(code == expected_code, "expected thread exit code %u, got %u\n", expected_code, code); 1864 } 1865 1866 ret = WaitForSingleObject(event, 0); 1867 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret); 1868 1869 ret = WaitForSingleObject(mutex, 0); 1870 if (expected_code == STILL_ACTIVE) 1871 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret); 1872 else 1873 ok(ret == WAIT_ABANDONED, "expected WAIT_ABANDONED, got %#x\n", ret); 1874 1875 /* semaphore is not abandoned on thread termination */ 1876 ret = WaitForSingleObject(semaphore, 0); 1877 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret); 1878 1879 if (expected_code == STILL_ACTIVE) 1880 { 1881 ret = WaitForSingleObject(attached_thread[0], 0); 1882 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret); 1883 ret = WaitForSingleObject(attached_thread[1], 0); 1884 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret); 1885 } 1886 else 1887 { 1888 ret = WaitForSingleObject(attached_thread[0], 0); 1889 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %#x\n", ret); 1890 ret = WaitForSingleObject(attached_thread[1], 0); 1891 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %#x\n", ret); 1892 } 1893 1894 /* win7 doesn't allow creating a thread during process shutdown but 1895 * earlier Windows versions allow it. 1896 */ 1897 noop_thread_started = 0; 1898 SetLastError(0xdeadbeef); 1899 handle = CreateThread(NULL, 0, noop_thread_proc, &noop_thread_started, 0, &ret); 1900 if (param) 1901 { 1902 ok(!handle || broken(handle != 0) /* before win7 */, "CreateThread should fail\n"); 1903 if (!handle) 1904 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); 1905 else 1906 { 1907 ret = WaitForSingleObject(handle, 1000); 1908 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret); 1909 CloseHandle(handle); 1910 } 1911 } 1912 else 1913 { 1914 ok(handle != 0, "CreateThread error %d\n", GetLastError()); 1915 ret = WaitForSingleObject(handle, 1000); 1916 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret); 1917 ok(!noop_thread_started || broken(noop_thread_started) /* XP64 */, "thread shouldn't start yet\n"); 1918 CloseHandle(handle); 1919 } 1920 1921 SetLastError(0xdeadbeef); 1922 process = OpenProcess(PROCESS_ALL_ACCESS_NT4, FALSE, GetCurrentProcessId()); 1923 ok(process != NULL, "OpenProcess error %d\n", GetLastError()); 1924 1925 noop_thread_started = 0; 1926 SetLastError(0xdeadbeef); 1927 handle = CreateRemoteThread(process, NULL, 0, noop_thread_proc, &noop_thread_started, 0, &ret); 1928 if (param) 1929 { 1930 ok(!handle || broken(handle != 0) /* before win7 */, "CreateRemoteThread should fail\n"); 1931 if (!handle) 1932 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); 1933 else 1934 { 1935 ret = WaitForSingleObject(handle, 1000); 1936 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret); 1937 CloseHandle(handle); 1938 } 1939 } 1940 else 1941 { 1942 ok(handle != 0, "CreateRemoteThread error %d\n", GetLastError()); 1943 ret = WaitForSingleObject(handle, 1000); 1944 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret); 1945 ok(!noop_thread_started || broken(noop_thread_started) /* XP64 */, "thread shouldn't start yet\n"); 1946 CloseHandle(handle); 1947 } 1948 1949 SetLastError(0xdeadbeef); 1950 handle = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, NULL); 1951 ok(handle != 0, "CreateFileMapping error %d\n", GetLastError()); 1952 1953 offset.u.LowPart = 0; 1954 offset.u.HighPart = 0; 1955 addr = NULL; 1956 size = 0; 1957 ret = pNtMapViewOfSection(handle, process, &addr, 0, 0, &offset, 1958 &size, 1 /* ViewShare */, 0, PAGE_READONLY); 1959 ok(ret == STATUS_SUCCESS, "NtMapViewOfSection error %#x\n", ret); 1960 ret = pNtUnmapViewOfSection(process, addr); 1961 ok(ret == STATUS_SUCCESS, "NtUnmapViewOfSection error %#x\n", ret); 1962 1963 CloseHandle(handle); 1964 CloseHandle(process); 1965 1966 handle = GetModuleHandleA("winver.exe"); 1967 ok(!handle, "winver.exe shouldn't be loaded yet\n"); 1968 SetLastError(0xdeadbeef); 1969 handle = LoadLibraryA("winver.exe"); 1970 ok(handle != 0, "LoadLibrary error %d\n", GetLastError()); 1971 SetLastError(0xdeadbeef); 1972 ret = FreeLibrary(handle); 1973 ok(ret, "FreeLibrary error %d\n", GetLastError()); 1974 handle = GetModuleHandleA("winver.exe"); 1975 if (param) 1976 ok(handle != 0, "winver.exe should not be unloaded\n"); 1977 else 1978 todo_wine 1979 ok(!handle || broken(handle != 0) /* before win7 */, "winver.exe should be unloaded\n"); 1980 1981 SetLastError(0xdeadbeef); 1982 ret = WaitForDebugEvent(&de, 0); 1983 ok(!ret, "WaitForDebugEvent should fail\n"); 1984 todo_wine 1985 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); 1986 1987 SetLastError(0xdeadbeef); 1988 ret = DebugActiveProcess(GetCurrentProcessId()); 1989 ok(!ret, "DebugActiveProcess should fail\n"); 1990 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); 1991 1992 SetLastError(0xdeadbeef); 1993 ret = WaitForDebugEvent(&de, 0); 1994 ok(!ret, "WaitForDebugEvent should fail\n"); 1995 ok(GetLastError() == ERROR_SEM_TIMEOUT, "expected ERROR_SEM_TIMEOUT, got %d\n", GetLastError()); 1996 1997 if (test_dll_phase == 2) 1998 { 1999 trace("dll: call ExitProcess()\n"); 2000 *child_failures = winetest_get_failures(); 2001 ExitProcess(197); 2002 } 2003 trace("dll: %p, DLL_PROCESS_DETACH, %p => DONE\n", hinst, param); 2004 break; 2005 } 2006 case DLL_THREAD_ATTACH: 2007 trace("dll: %p, DLL_THREAD_ATTACH, %p\n", hinst, param); 2008 2009 ret = pRtlDllShutdownInProgress(); 2010 ok(!ret, "RtlDllShutdownInProgress returned %d\n", ret); 2011 2012 if (attached_thread_count < MAX_COUNT) 2013 { 2014 DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &attached_thread[attached_thread_count], 2015 0, TRUE, DUPLICATE_SAME_ACCESS); 2016 attached_thread_count++; 2017 } 2018 2019 /* Make sure the FLS slot is empty, if FLS is available */ 2020 if (pFlsGetValue) 2021 { 2022 void* value; 2023 BOOL ret; 2024 SetLastError(0xdeadbeef); 2025 value = pFlsGetValue(fls_index); 2026 ok(!value, "FlsGetValue returned %p, expected NULL\n", value); 2027 todo_wine 2028 ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %u\n", GetLastError()); 2029 ret = pFlsSetValue(fls_index, (void*) 0x31415); 2030 ok(ret, "FlsSetValue failed\n"); 2031 fls_count++; 2032 } 2033 2034 break; 2035 case DLL_THREAD_DETACH: 2036 trace("dll: %p, DLL_THREAD_DETACH, %p\n", hinst, param); 2037 thread_detach_count++; 2038 2039 ret = pRtlDllShutdownInProgress(); 2040 /* win7 doesn't allow creating a thread during process shutdown but 2041 * earlier Windows versions allow it. In that case DLL_THREAD_DETACH is 2042 * sent on thread exit, but DLL_THREAD_ATTACH is never received. 2043 */ 2044 if (noop_thread_started) 2045 ok(ret, "RtlDllShutdownInProgress returned %d\n", ret); 2046 else 2047 ok(!ret, "RtlDllShutdownInProgress returned %d\n", ret); 2048 2049 /* FLS data should already be destroyed, if FLS is available. 2050 * Note that this is broken for Win2k3, which runs the callbacks *after* the DLL entry 2051 * point has already run. 2052 */ 2053 if (pFlsGetValue && fls_index != FLS_OUT_OF_INDEXES) 2054 { 2055 void* value; 2056 SetLastError(0xdeadbeef); 2057 value = pFlsGetValue(fls_index); 2058 todo_wine 2059 { 2060 ok(broken(value == (void*) 0x31415) || /* Win2k3 */ 2061 !value, "FlsGetValue returned %p, expected NULL\n", value); 2062 } 2063 ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %u\n", GetLastError()); 2064 } 2065 2066 break; 2067 default: 2068 trace("dll: %p, %d, %p\n", hinst, reason, param); 2069 break; 2070 } 2071 2072 *child_failures = winetest_get_failures(); 2073 2074 return TRUE; 2075 } 2076 2077 static void child_process(const char *dll_name, DWORD target_offset) 2078 { 2079 void *target; 2080 DWORD ret, dummy, i, code, expected_code; 2081 HANDLE file, thread, process; 2082 HMODULE hmod; 2083 struct PROCESS_BASIC_INFORMATION_PRIVATE pbi; 2084 DWORD_PTR affinity; 2085 2086 trace("phase %d: writing %p at %#x\n", test_dll_phase, dll_entry_point, target_offset); 2087 2088 SetLastError(0xdeadbeef); 2089 mutex = CreateMutexW(NULL, FALSE, NULL); 2090 ok(mutex != 0, "CreateMutex error %d\n", GetLastError()); 2091 2092 SetLastError(0xdeadbeef); 2093 semaphore = CreateSemaphoreW(NULL, 1, 1, NULL); 2094 ok(semaphore != 0, "CreateSemaphore error %d\n", GetLastError()); 2095 2096 SetLastError(0xdeadbeef); 2097 event = CreateEventW(NULL, TRUE, FALSE, NULL); 2098 ok(event != 0, "CreateEvent error %d\n", GetLastError()); 2099 2100 SetLastError(0xdeadbeef); 2101 loader_lock_event = CreateEventW(NULL, FALSE, FALSE, NULL); 2102 ok(loader_lock_event != 0, "CreateEvent error %d\n", GetLastError()); 2103 2104 SetLastError(0xdeadbeef); 2105 peb_lock_event = CreateEventW(NULL, FALSE, FALSE, NULL); 2106 ok(peb_lock_event != 0, "CreateEvent error %d\n", GetLastError()); 2107 2108 SetLastError(0xdeadbeef); 2109 heap_lock_event = CreateEventW(NULL, FALSE, FALSE, NULL); 2110 ok(heap_lock_event != 0, "CreateEvent error %d\n", GetLastError()); 2111 2112 SetLastError(0xdeadbeef); 2113 ack_event = CreateEventW(NULL, FALSE, FALSE, NULL); 2114 ok(ack_event != 0, "CreateEvent error %d\n", GetLastError()); 2115 2116 file = CreateFileA(dll_name, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0); 2117 if (file == INVALID_HANDLE_VALUE) 2118 { 2119 ok(0, "could not open %s\n", dll_name); 2120 return; 2121 } 2122 SetFilePointer(file, target_offset, NULL, FILE_BEGIN); 2123 SetLastError(0xdeadbeef); 2124 target = dll_entry_point; 2125 ret = WriteFile(file, &target, sizeof(target), &dummy, NULL); 2126 ok(ret, "WriteFile error %d\n", GetLastError()); 2127 CloseHandle(file); 2128 2129 SetLastError(0xdeadbeef); 2130 hmod = LoadLibraryA(dll_name); 2131 ok(hmod != 0, "LoadLibrary error %d\n", GetLastError()); 2132 2133 SetLastError(0xdeadbeef); 2134 stop_event = CreateEventW(NULL, TRUE, FALSE, NULL); 2135 ok(stop_event != 0, "CreateEvent error %d\n", GetLastError()); 2136 2137 SetLastError(0xdeadbeef); 2138 thread = CreateThread(NULL, 0, mutex_thread_proc, event, 0, &dummy); 2139 ok(thread != 0, "CreateThread error %d\n", GetLastError()); 2140 WaitForSingleObject(event, 3000); 2141 CloseHandle(thread); 2142 2143 ResetEvent(event); 2144 2145 SetLastError(0xdeadbeef); 2146 thread = CreateThread(NULL, 0, semaphore_thread_proc, event, 0, &dummy); 2147 ok(thread != 0, "CreateThread error %d\n", GetLastError()); 2148 WaitForSingleObject(event, 3000); 2149 CloseHandle(thread); 2150 2151 ResetEvent(event); 2152 Sleep(100); 2153 2154 ok(attached_thread_count == 2, "attached thread count should be 2\n"); 2155 for (i = 0; i < attached_thread_count; i++) 2156 { 2157 ret = GetExitCodeThread(attached_thread[i], &code); 2158 trace("child: GetExitCodeThread(%u) => %d,%u\n", i, ret, code); 2159 ok(ret == 1, "GetExitCodeThread returned %d, expected 1\n", ret); 2160 ok(code == STILL_ACTIVE, "expected thread exit code STILL_ACTIVE, got %u\n", code); 2161 } 2162 2163 ret = WaitForSingleObject(attached_thread[0], 0); 2164 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret); 2165 ret = WaitForSingleObject(attached_thread[1], 0); 2166 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret); 2167 2168 ret = WaitForSingleObject(event, 0); 2169 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret); 2170 ret = WaitForSingleObject(mutex, 0); 2171 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret); 2172 ret = WaitForSingleObject(semaphore, 0); 2173 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret); 2174 2175 ret = pRtlDllShutdownInProgress(); 2176 ok(!ret, "RtlDllShutdownInProgress returned %d\n", ret); 2177 2178 SetLastError(0xdeadbeef); 2179 process = OpenProcess(PROCESS_ALL_ACCESS_NT4, FALSE, GetCurrentProcessId()); 2180 ok(process != NULL, "OpenProcess error %d\n", GetLastError()); 2181 2182 SetLastError(0xdeadbeef); 2183 ret = TerminateProcess(0, 195); 2184 ok(!ret, "TerminateProcess(0) should fail\n"); 2185 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); 2186 2187 Sleep(100); 2188 2189 affinity = 1; 2190 ret = pNtSetInformationProcess(process, ProcessAffinityMask, &affinity, sizeof(affinity)); 2191 ok(!ret, "NtSetInformationProcess error %#x\n", ret); 2192 2193 switch (test_dll_phase) 2194 { 2195 case 0: 2196 ret = pRtlDllShutdownInProgress(); 2197 ok(!ret, "RtlDllShutdownInProgress returned %d\n", ret); 2198 2199 trace("call NtTerminateProcess(0, 195)\n"); 2200 ret = pNtTerminateProcess(0, 195); 2201 ok(!ret, "NtTerminateProcess error %#x\n", ret); 2202 2203 memset(&pbi, 0, sizeof(pbi)); 2204 ret = pNtQueryInformationProcess(process, ProcessBasicInformation, &pbi, sizeof(pbi), NULL); 2205 ok(!ret, "NtQueryInformationProcess error %#x\n", ret); 2206 ok(pbi.ExitStatus == STILL_ACTIVE || pbi.ExitStatus == 195, 2207 "expected STILL_ACTIVE, got %lu\n", pbi.ExitStatus); 2208 affinity = 1; 2209 ret = pNtSetInformationProcess(process, ProcessAffinityMask, &affinity, sizeof(affinity)); 2210 ok(!ret, "NtSetInformationProcess error %#x\n", ret); 2211 2212 ret = pRtlDllShutdownInProgress(); 2213 ok(!ret, "RtlDllShutdownInProgress returned %d\n", ret); 2214 2215 hmod = GetModuleHandleA(dll_name); 2216 ok(hmod != 0, "DLL should not be unloaded\n"); 2217 2218 SetLastError(0xdeadbeef); 2219 thread = CreateThread(NULL, 0, noop_thread_proc, &dummy, 0, &ret); 2220 ok(!thread || broken(thread != 0) /* before win7 */, "CreateThread should fail\n"); 2221 if (!thread) 2222 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); 2223 else 2224 { 2225 ret = WaitForSingleObject(thread, 1000); 2226 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %#x\n", ret); 2227 CloseHandle(thread); 2228 } 2229 2230 trace("call LdrShutdownProcess()\n"); 2231 pLdrShutdownProcess(); 2232 2233 ret = pRtlDllShutdownInProgress(); 2234 ok(ret, "RtlDllShutdownInProgress returned %d\n", ret); 2235 2236 hmod = GetModuleHandleA(dll_name); 2237 ok(hmod != 0, "DLL should not be unloaded\n"); 2238 2239 memset(&pbi, 0, sizeof(pbi)); 2240 ret = pNtQueryInformationProcess(process, ProcessBasicInformation, &pbi, sizeof(pbi), NULL); 2241 ok(!ret, "NtQueryInformationProcess error %#x\n", ret); 2242 ok(pbi.ExitStatus == STILL_ACTIVE || pbi.ExitStatus == 195, 2243 "expected STILL_ACTIVE, got %lu\n", pbi.ExitStatus); 2244 affinity = 1; 2245 ret = pNtSetInformationProcess(process, ProcessAffinityMask, &affinity, sizeof(affinity)); 2246 ok(!ret, "NtSetInformationProcess error %#x\n", ret); 2247 break; 2248 2249 case 1: /* normal ExitProcess */ 2250 ret = pRtlDllShutdownInProgress(); 2251 ok(!ret, "RtlDllShutdownInProgress returned %d\n", ret); 2252 break; 2253 2254 case 2: /* ExitProcess will be called by the PROCESS_DETACH handler */ 2255 ret = pRtlDllShutdownInProgress(); 2256 ok(!ret, "RtlDllShutdownInProgress returned %d\n", ret); 2257 2258 trace("call FreeLibrary(%p)\n", hmod); 2259 SetLastError(0xdeadbeef); 2260 ret = FreeLibrary(hmod); 2261 ok(ret, "FreeLibrary error %d\n", GetLastError()); 2262 hmod = GetModuleHandleA(dll_name); 2263 ok(!hmod, "DLL should be unloaded\n"); 2264 2265 if (test_dll_phase == 2) 2266 ok(0, "FreeLibrary+ExitProcess should never return\n"); 2267 2268 ret = pRtlDllShutdownInProgress(); 2269 ok(!ret, "RtlDllShutdownInProgress returned %d\n", ret); 2270 2271 break; 2272 2273 case 3: 2274 trace("signalling thread exit\n"); 2275 SetEvent(stop_event); 2276 CloseHandle(stop_event); 2277 break; 2278 2279 case 4: 2280 trace("setting loader_lock_event\n"); 2281 SetEvent(loader_lock_event); 2282 WaitForSingleObject(ack_event, 1000); 2283 ok(inside_loader_lock != 0, "inside_loader_lock is not set\n"); 2284 2285 /* calling NtTerminateProcess should not cause a deadlock */ 2286 trace("call NtTerminateProcess(0, 198)\n"); 2287 ret = pNtTerminateProcess(0, 198); 2288 ok(!ret, "NtTerminateProcess error %#x\n", ret); 2289 2290 *child_failures = winetest_get_failures(); 2291 2292 /* Windows fails to release loader lock acquired from another thread, 2293 * so the LdrUnlockLoaderLock call fails here and ExitProcess deadlocks 2294 * later on, so NtTerminateProcess is used instead. 2295 */ 2296 trace("call NtTerminateProcess(GetCurrentProcess(), 198)\n"); 2297 pNtTerminateProcess(GetCurrentProcess(), 198); 2298 ok(0, "NtTerminateProcess should not return\n"); 2299 break; 2300 2301 case 5: 2302 trace("setting peb_lock_event\n"); 2303 SetEvent(peb_lock_event); 2304 WaitForSingleObject(ack_event, 1000); 2305 ok(inside_peb_lock != 0, "inside_peb_lock is not set\n"); 2306 2307 *child_failures = winetest_get_failures(); 2308 2309 /* calling ExitProcess should cause a deadlock */ 2310 trace("call ExitProcess(198)\n"); 2311 ExitProcess(198); 2312 ok(0, "ExitProcess should not return\n"); 2313 break; 2314 2315 case 6: 2316 trace("setting heap_lock_event\n"); 2317 SetEvent(heap_lock_event); 2318 WaitForSingleObject(ack_event, 1000); 2319 ok(inside_heap_lock != 0, "inside_heap_lock is not set\n"); 2320 2321 *child_failures = winetest_get_failures(); 2322 2323 /* calling ExitProcess should cause a deadlock */ 2324 trace("call ExitProcess(1)\n"); 2325 ExitProcess(1); 2326 ok(0, "ExitProcess should not return\n"); 2327 break; 2328 2329 default: 2330 assert(0); 2331 break; 2332 } 2333 2334 if (test_dll_phase == 0) expected_code = 195; 2335 else if (test_dll_phase == 3) expected_code = 196; 2336 else if (test_dll_phase == 4) expected_code = 198; 2337 else expected_code = STILL_ACTIVE; 2338 2339 if (expected_code == STILL_ACTIVE) 2340 { 2341 ret = WaitForSingleObject(attached_thread[0], 100); 2342 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret); 2343 ret = WaitForSingleObject(attached_thread[1], 100); 2344 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret); 2345 } 2346 else 2347 { 2348 ret = WaitForSingleObject(attached_thread[0], 2000); 2349 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %#x\n", ret); 2350 ret = WaitForSingleObject(attached_thread[1], 2000); 2351 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %#x\n", ret); 2352 } 2353 2354 for (i = 0; i < attached_thread_count; i++) 2355 { 2356 ret = GetExitCodeThread(attached_thread[i], &code); 2357 trace("child: GetExitCodeThread(%u) => %d,%u\n", i, ret, code); 2358 ok(ret == 1, "GetExitCodeThread returned %d, expected 1\n", ret); 2359 ok(code == expected_code, "expected thread exit code %u, got %u\n", expected_code, code); 2360 } 2361 2362 *child_failures = winetest_get_failures(); 2363 2364 trace("call ExitProcess(195)\n"); 2365 ExitProcess(195); 2366 } 2367 2368 static void test_ExitProcess(void) 2369 { 2370 #include "pshpack1.h" 2371 #ifdef __x86_64__ 2372 static struct section_data 2373 { 2374 BYTE mov_rax[2]; 2375 void *target; 2376 BYTE jmp_rax[2]; 2377 } section_data = { { 0x48,0xb8 }, dll_entry_point, { 0xff,0xe0 } }; 2378 #else 2379 static struct section_data 2380 { 2381 BYTE mov_eax; 2382 void *target; 2383 BYTE jmp_eax[2]; 2384 } section_data = { 0xb8, dll_entry_point, { 0xff,0xe0 } }; 2385 #endif 2386 #include "poppack.h" 2387 DWORD dummy, file_align; 2388 HANDLE file, thread, process, hmap, hmap_dup; 2389 char temp_path[MAX_PATH], dll_name[MAX_PATH], cmdline[MAX_PATH * 2]; 2390 DWORD ret, target_offset, old_prot; 2391 char **argv, buf[256]; 2392 PROCESS_INFORMATION pi; 2393 STARTUPINFOA si = { sizeof(si) }; 2394 CONTEXT ctx; 2395 struct PROCESS_BASIC_INFORMATION_PRIVATE pbi; 2396 MEMORY_BASIC_INFORMATION mbi; 2397 DWORD_PTR affinity; 2398 void *addr; 2399 LARGE_INTEGER offset; 2400 SIZE_T size; 2401 IMAGE_NT_HEADERS nt_header; 2402 2403 #if !defined(__i386__) && !defined(__x86_64__) 2404 skip("x86 specific ExitProcess test\n"); 2405 return; 2406 #endif 2407 2408 if (!pRtlDllShutdownInProgress) 2409 { 2410 win_skip("RtlDllShutdownInProgress is not available on this platform (XP+)\n"); 2411 return; 2412 } 2413 if (!pNtQueryInformationProcess || !pNtSetInformationProcess) 2414 { 2415 win_skip("NtQueryInformationProcess/NtSetInformationProcess are not available on this platform\n"); 2416 return; 2417 } 2418 if (!pNtAllocateVirtualMemory || !pNtFreeVirtualMemory) 2419 { 2420 win_skip("NtAllocateVirtualMemory/NtFreeVirtualMemory are not available on this platform\n"); 2421 return; 2422 } 2423 2424 /* prevent displaying of the "Unable to load this DLL" message box */ 2425 SetErrorMode(SEM_FAILCRITICALERRORS); 2426 2427 GetTempPathA(MAX_PATH, temp_path); 2428 GetTempFileNameA(temp_path, "ldr", 0, dll_name); 2429 2430 /*trace("creating %s\n", dll_name);*/ 2431 file = CreateFileA(dll_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); 2432 if (file == INVALID_HANDLE_VALUE) 2433 { 2434 ok(0, "could not create %s\n", dll_name); 2435 return; 2436 } 2437 2438 SetLastError(0xdeadbeef); 2439 ret = WriteFile(file, &dos_header, sizeof(dos_header), &dummy, NULL); 2440 ok(ret, "WriteFile error %d\n", GetLastError()); 2441 2442 nt_header = nt_header_template; 2443 nt_header.FileHeader.NumberOfSections = 1; 2444 nt_header.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER); 2445 nt_header.FileHeader.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL | IMAGE_FILE_RELOCS_STRIPPED; 2446 2447 nt_header.OptionalHeader.AddressOfEntryPoint = 0x1000; 2448 nt_header.OptionalHeader.SectionAlignment = 0x1000; 2449 nt_header.OptionalHeader.FileAlignment = 0x200; 2450 nt_header.OptionalHeader.SizeOfImage = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x1000; 2451 nt_header.OptionalHeader.SizeOfHeaders = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER); 2452 SetLastError(0xdeadbeef); 2453 ret = WriteFile(file, &nt_header, sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER), &dummy, NULL); 2454 ok(ret, "WriteFile error %d\n", GetLastError()); 2455 SetLastError(0xdeadbeef); 2456 ret = WriteFile(file, &nt_header.OptionalHeader, sizeof(IMAGE_OPTIONAL_HEADER), &dummy, NULL); 2457 ok(ret, "WriteFile error %d\n", GetLastError()); 2458 2459 section.SizeOfRawData = sizeof(section_data); 2460 section.PointerToRawData = nt_header.OptionalHeader.FileAlignment; 2461 section.VirtualAddress = nt_header.OptionalHeader.SectionAlignment; 2462 section.Misc.VirtualSize = sizeof(section_data); 2463 section.Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE; 2464 SetLastError(0xdeadbeef); 2465 ret = WriteFile(file, §ion, sizeof(section), &dummy, NULL); 2466 ok(ret, "WriteFile error %d\n", GetLastError()); 2467 2468 file_align = nt_header.OptionalHeader.FileAlignment - nt_header.OptionalHeader.SizeOfHeaders; 2469 assert(file_align < sizeof(filler)); 2470 SetLastError(0xdeadbeef); 2471 ret = WriteFile(file, filler, file_align, &dummy, NULL); 2472 ok(ret, "WriteFile error %d\n", GetLastError()); 2473 2474 target_offset = SetFilePointer(file, 0, NULL, FILE_CURRENT) + FIELD_OFFSET(struct section_data, target); 2475 2476 /* section data */ 2477 SetLastError(0xdeadbeef); 2478 ret = WriteFile(file, §ion_data, sizeof(section_data), &dummy, NULL); 2479 ok(ret, "WriteFile error %d\n", GetLastError()); 2480 2481 CloseHandle(file); 2482 2483 winetest_get_mainargs(&argv); 2484 2485 /* phase 0 */ 2486 *child_failures = -1; 2487 sprintf(cmdline, "\"%s\" loader %s %u 0", argv[0], dll_name, target_offset); 2488 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 2489 ok(ret, "CreateProcess(%s) error %d\n", cmdline, GetLastError()); 2490 ret = WaitForSingleObject(pi.hProcess, 10000); 2491 ok(ret == WAIT_OBJECT_0, "child process failed to terminate\n"); 2492 if (ret != WAIT_OBJECT_0) TerminateProcess(pi.hProcess, 0); 2493 GetExitCodeProcess(pi.hProcess, &ret); 2494 ok(ret == 195, "expected exit code 195, got %u\n", ret); 2495 if (*child_failures) 2496 { 2497 trace("%d failures in child process\n", *child_failures); 2498 winetest_add_failures(*child_failures); 2499 } 2500 CloseHandle(pi.hThread); 2501 CloseHandle(pi.hProcess); 2502 2503 /* phase 1 */ 2504 *child_failures = -1; 2505 sprintf(cmdline, "\"%s\" loader %s %u 1", argv[0], dll_name, target_offset); 2506 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 2507 ok(ret, "CreateProcess(%s) error %d\n", cmdline, GetLastError()); 2508 ret = WaitForSingleObject(pi.hProcess, 10000); 2509 ok(ret == WAIT_OBJECT_0, "child process failed to terminate\n"); 2510 if (ret != WAIT_OBJECT_0) TerminateProcess(pi.hProcess, 0); 2511 GetExitCodeProcess(pi.hProcess, &ret); 2512 ok(ret == 195, "expected exit code 195, got %u\n", ret); 2513 if (*child_failures) 2514 { 2515 trace("%d failures in child process\n", *child_failures); 2516 winetest_add_failures(*child_failures); 2517 } 2518 CloseHandle(pi.hThread); 2519 CloseHandle(pi.hProcess); 2520 2521 /* phase 2 */ 2522 *child_failures = -1; 2523 sprintf(cmdline, "\"%s\" loader %s %u 2", argv[0], dll_name, target_offset); 2524 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 2525 ok(ret, "CreateProcess(%s) error %d\n", cmdline, GetLastError()); 2526 ret = WaitForSingleObject(pi.hProcess, 10000); 2527 ok(ret == WAIT_OBJECT_0, "child process failed to terminate\n"); 2528 if (ret != WAIT_OBJECT_0) TerminateProcess(pi.hProcess, 0); 2529 GetExitCodeProcess(pi.hProcess, &ret); 2530 ok(ret == 197, "expected exit code 197, got %u\n", ret); 2531 if (*child_failures) 2532 { 2533 trace("%d failures in child process\n", *child_failures); 2534 winetest_add_failures(*child_failures); 2535 } 2536 CloseHandle(pi.hThread); 2537 CloseHandle(pi.hProcess); 2538 2539 /* phase 3 */ 2540 *child_failures = -1; 2541 sprintf(cmdline, "\"%s\" loader %s %u 3", argv[0], dll_name, target_offset); 2542 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 2543 ok(ret, "CreateProcess(%s) error %d\n", cmdline, GetLastError()); 2544 ret = WaitForSingleObject(pi.hProcess, 10000); 2545 ok(ret == WAIT_OBJECT_0, "child process failed to terminate\n"); 2546 if (ret != WAIT_OBJECT_0) TerminateProcess(pi.hProcess, 0); 2547 GetExitCodeProcess(pi.hProcess, &ret); 2548 ok(ret == 195, "expected exit code 195, got %u\n", ret); 2549 if (*child_failures) 2550 { 2551 trace("%d failures in child process\n", *child_failures); 2552 winetest_add_failures(*child_failures); 2553 } 2554 CloseHandle(pi.hThread); 2555 CloseHandle(pi.hProcess); 2556 2557 /* phase 4 */ 2558 if (pLdrLockLoaderLock && pLdrUnlockLoaderLock) 2559 { 2560 *child_failures = -1; 2561 sprintf(cmdline, "\"%s\" loader %s %u 4", argv[0], dll_name, target_offset); 2562 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 2563 ok(ret, "CreateProcess(%s) error %d\n", cmdline, GetLastError()); 2564 ret = WaitForSingleObject(pi.hProcess, 10000); 2565 ok(ret == WAIT_OBJECT_0, "child process failed to terminate\n"); 2566 if (ret != WAIT_OBJECT_0) TerminateProcess(pi.hProcess, 0); 2567 GetExitCodeProcess(pi.hProcess, &ret); 2568 ok(ret == 198, "expected exit code 198, got %u\n", ret); 2569 if (*child_failures) 2570 { 2571 trace("%d failures in child process\n", *child_failures); 2572 winetest_add_failures(*child_failures); 2573 } 2574 CloseHandle(pi.hThread); 2575 CloseHandle(pi.hProcess); 2576 } 2577 else 2578 win_skip("LdrLockLoaderLock/LdrUnlockLoaderLock are not available on this platform\n"); 2579 2580 /* phase 5 */ 2581 if (pRtlAcquirePebLock && pRtlReleasePebLock) 2582 { 2583 *child_failures = -1; 2584 sprintf(cmdline, "\"%s\" loader %s %u 5", argv[0], dll_name, target_offset); 2585 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 2586 ok(ret, "CreateProcess(%s) error %d\n", cmdline, GetLastError()); 2587 ret = WaitForSingleObject(pi.hProcess, 5000); 2588 ok(ret == WAIT_TIMEOUT, "child process should fail to terminate\n"); 2589 if (ret != WAIT_OBJECT_0) 2590 { 2591 trace("terminating child process\n"); 2592 TerminateProcess(pi.hProcess, 199); 2593 } 2594 ret = WaitForSingleObject(pi.hProcess, 1000); 2595 ok(ret == WAIT_OBJECT_0, "child process failed to terminate\n"); 2596 GetExitCodeProcess(pi.hProcess, &ret); 2597 ok(ret == 199, "expected exit code 199, got %u\n", ret); 2598 if (*child_failures) 2599 { 2600 trace("%d failures in child process\n", *child_failures); 2601 winetest_add_failures(*child_failures); 2602 } 2603 CloseHandle(pi.hThread); 2604 CloseHandle(pi.hProcess); 2605 } 2606 else 2607 win_skip("RtlAcquirePebLock/RtlReleasePebLock are not available on this platform\n"); 2608 2609 /* phase 6 */ 2610 *child_failures = -1; 2611 sprintf(cmdline, "\"%s\" loader %s %u 6", argv[0], dll_name, target_offset); 2612 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 2613 ok(ret, "CreateProcess(%s) error %d\n", cmdline, GetLastError()); 2614 ret = WaitForSingleObject(pi.hProcess, 5000); 2615 ok(ret == WAIT_TIMEOUT || broken(ret == WAIT_OBJECT_0) /* XP */, "child process should fail to terminate\n"); 2616 if (ret != WAIT_OBJECT_0) 2617 { 2618 trace("terminating child process\n"); 2619 TerminateProcess(pi.hProcess, 201); 2620 } 2621 ret = WaitForSingleObject(pi.hProcess, 1000); 2622 ok(ret == WAIT_OBJECT_0, "child process failed to terminate\n"); 2623 GetExitCodeProcess(pi.hProcess, &ret); 2624 ok(ret == 201 || broken(ret == 1) /* XP */, "expected exit code 201, got %u\n", ret); 2625 if (*child_failures) 2626 { 2627 trace("%d failures in child process\n", *child_failures); 2628 winetest_add_failures(*child_failures); 2629 } 2630 CloseHandle(pi.hThread); 2631 CloseHandle(pi.hProcess); 2632 2633 /* test remote process termination */ 2634 SetLastError(0xdeadbeef); 2635 ret = CreateProcessA(argv[0], NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi); 2636 ok(ret, "CreateProcess(%s) error %d\n", argv[0], GetLastError()); 2637 2638 SetLastError(0xdeadbeef); 2639 addr = VirtualAllocEx(pi.hProcess, NULL, 4096, MEM_COMMIT, PAGE_READWRITE); 2640 ok(addr != NULL, "VirtualAllocEx error %d\n", GetLastError()); 2641 SetLastError(0xdeadbeef); 2642 ret = VirtualProtectEx(pi.hProcess, addr, 4096, PAGE_READONLY, &old_prot); 2643 ok(ret, "VirtualProtectEx error %d\n", GetLastError()); 2644 ok(old_prot == PAGE_READWRITE, "expected PAGE_READWRITE, got %#x\n", old_prot); 2645 SetLastError(0xdeadbeef); 2646 size = VirtualQueryEx(pi.hProcess, NULL, &mbi, sizeof(mbi)); 2647 ok(size == sizeof(mbi), "VirtualQueryEx error %d\n", GetLastError()); 2648 2649 SetLastError(0xdeadbeef); 2650 ret = ReadProcessMemory(pi.hProcess, addr, buf, 4, &size); 2651 ok(ret, "ReadProcessMemory error %d\n", GetLastError()); 2652 ok(size == 4, "expected 4, got %lu\n", size); 2653 2654 SetLastError(0xdeadbeef); 2655 hmap = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, NULL); 2656 ok(hmap != 0, "CreateFileMapping error %d\n", GetLastError()); 2657 2658 SetLastError(0xdeadbeef); 2659 ret = DuplicateHandle(GetCurrentProcess(), hmap, pi.hProcess, &hmap_dup, 2660 0, FALSE, DUPLICATE_SAME_ACCESS); 2661 ok(ret, "DuplicateHandle error %d\n", GetLastError()); 2662 2663 offset.u.LowPart = 0; 2664 offset.u.HighPart = 0; 2665 addr = NULL; 2666 size = 0; 2667 ret = pNtMapViewOfSection(hmap, pi.hProcess, &addr, 0, 0, &offset, 2668 &size, 1 /* ViewShare */, 0, PAGE_READONLY); 2669 ok(!ret, "NtMapViewOfSection error %#x\n", ret); 2670 ret = pNtUnmapViewOfSection(pi.hProcess, addr); 2671 ok(!ret, "NtUnmapViewOfSection error %#x\n", ret); 2672 2673 SetLastError(0xdeadbeef); 2674 thread = CreateRemoteThread(pi.hProcess, NULL, 0, (void *)0xdeadbeef, NULL, CREATE_SUSPENDED, &ret); 2675 ok(thread != 0, "CreateRemoteThread error %d\n", GetLastError()); 2676 SetLastError(0xdeadbeef); 2677 ctx.ContextFlags = CONTEXT_INTEGER; 2678 ret = GetThreadContext(thread, &ctx); 2679 ok(ret, "GetThreadContext error %d\n", GetLastError()); 2680 SetLastError(0xdeadbeef); 2681 ctx.ContextFlags = CONTEXT_INTEGER; 2682 ret = SetThreadContext(thread, &ctx); 2683 ok(ret, "SetThreadContext error %d\n", GetLastError()); 2684 SetLastError(0xdeadbeef); 2685 ret = SetThreadPriority(thread, 0); 2686 ok(ret, "SetThreadPriority error %d\n", GetLastError()); 2687 2688 SetLastError(0xdeadbeef); 2689 ret = TerminateThread(thread, 199); 2690 ok(ret, "TerminateThread error %d\n", GetLastError()); 2691 /* Calling GetExitCodeThread() without waiting for thread termination 2692 * leads to different results due to a race condition. 2693 */ 2694 ret = WaitForSingleObject(thread, 1000); 2695 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed: %x\n", ret); 2696 GetExitCodeThread(thread, &ret); 2697 ok(ret == 199, "expected exit code 199, got %u\n", ret); 2698 2699 SetLastError(0xdeadbeef); 2700 ret = TerminateProcess(pi.hProcess, 198); 2701 ok(ret, "TerminateProcess error %d\n", GetLastError()); 2702 /* Checking process state without waiting for process termination 2703 * leads to different results due to a race condition. 2704 */ 2705 ret = WaitForSingleObject(pi.hProcess, 1000); 2706 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed: %x\n", ret); 2707 2708 SetLastError(0xdeadbeef); 2709 process = OpenProcess(PROCESS_ALL_ACCESS_NT4, FALSE, pi.dwProcessId); 2710 ok(process != NULL, "OpenProcess error %d\n", GetLastError()); 2711 CloseHandle(process); 2712 2713 memset(&pbi, 0, sizeof(pbi)); 2714 ret = pNtQueryInformationProcess(pi.hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), NULL); 2715 ok(!ret, "NtQueryInformationProcess error %#x\n", ret); 2716 ok(pbi.ExitStatus == 198, "expected 198, got %lu\n", pbi.ExitStatus); 2717 affinity = 1; 2718 ret = pNtSetInformationProcess(pi.hProcess, ProcessAffinityMask, &affinity, sizeof(affinity)); 2719 ok(ret == STATUS_PROCESS_IS_TERMINATING, "expected STATUS_PROCESS_IS_TERMINATING, got %#x\n", ret); 2720 2721 SetLastError(0xdeadbeef); 2722 ctx.ContextFlags = CONTEXT_INTEGER; 2723 ret = GetThreadContext(thread, &ctx); 2724 ok(!ret || broken(ret) /* XP 64-bit */, "GetThreadContext should fail\n"); 2725 if (!ret) 2726 ok(GetLastError() == ERROR_INVALID_PARAMETER || 2727 GetLastError() == ERROR_GEN_FAILURE /* win7 64-bit */ || 2728 GetLastError() == ERROR_INVALID_FUNCTION /* vista 64-bit */, 2729 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 2730 SetLastError(0xdeadbeef); 2731 ctx.ContextFlags = CONTEXT_INTEGER; 2732 ret = SetThreadContext(thread, &ctx); 2733 ok(!ret || broken(ret) /* XP 64-bit */, "SetThreadContext should fail\n"); 2734 if (!ret) 2735 ok(GetLastError() == ERROR_ACCESS_DENIED || 2736 GetLastError() == ERROR_GEN_FAILURE /* win7 64-bit */ || 2737 GetLastError() == ERROR_INVALID_FUNCTION /* vista 64-bit */, 2738 "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); 2739 SetLastError(0xdeadbeef); 2740 ret = SetThreadPriority(thread, 0); 2741 ok(ret, "SetThreadPriority error %d\n", GetLastError()); 2742 CloseHandle(thread); 2743 2744 SetLastError(0xdeadbeef); 2745 ctx.ContextFlags = CONTEXT_INTEGER; 2746 ret = GetThreadContext(pi.hThread, &ctx); 2747 ok(!ret || broken(ret) /* XP 64-bit */, "GetThreadContext should fail\n"); 2748 if (!ret) 2749 ok(GetLastError() == ERROR_INVALID_PARAMETER || 2750 GetLastError() == ERROR_GEN_FAILURE /* win7 64-bit */ || 2751 GetLastError() == ERROR_INVALID_FUNCTION /* vista 64-bit */, 2752 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 2753 SetLastError(0xdeadbeef); 2754 ctx.ContextFlags = CONTEXT_INTEGER; 2755 ret = SetThreadContext(pi.hThread, &ctx); 2756 ok(!ret || broken(ret) /* XP 64-bit */, "SetThreadContext should fail\n"); 2757 if (!ret) 2758 ok(GetLastError() == ERROR_ACCESS_DENIED || 2759 GetLastError() == ERROR_GEN_FAILURE /* win7 64-bit */ || 2760 GetLastError() == ERROR_INVALID_FUNCTION /* vista 64-bit */, 2761 "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); 2762 SetLastError(0xdeadbeef); 2763 ret = VirtualProtectEx(pi.hProcess, addr, 4096, PAGE_READWRITE, &old_prot); 2764 ok(!ret, "VirtualProtectEx should fail\n"); 2765 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); 2766 SetLastError(0xdeadbeef); 2767 size = 0; 2768 ret = ReadProcessMemory(pi.hProcess, addr, buf, 4, &size); 2769 ok(!ret, "ReadProcessMemory should fail\n"); 2770 ok(GetLastError() == ERROR_PARTIAL_COPY || GetLastError() == ERROR_ACCESS_DENIED, 2771 "expected ERROR_PARTIAL_COPY, got %d\n", GetLastError()); 2772 ok(!size, "expected 0, got %lu\n", size); 2773 SetLastError(0xdeadbeef); 2774 ret = VirtualFreeEx(pi.hProcess, addr, 0, MEM_RELEASE); 2775 ok(!ret, "VirtualFreeEx should fail\n"); 2776 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); 2777 SetLastError(0xdeadbeef); 2778 addr = VirtualAllocEx(pi.hProcess, NULL, 4096, MEM_COMMIT, PAGE_READWRITE); 2779 ok(!addr, "VirtualAllocEx should fail\n"); 2780 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); 2781 SetLastError(0xdeadbeef); 2782 size = VirtualQueryEx(pi.hProcess, NULL, &mbi, sizeof(mbi)); 2783 ok(!size, "VirtualQueryEx should fail\n"); 2784 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); 2785 2786 /* CloseHandle() call below leads to premature process termination 2787 * under some Windows versions. 2788 */ 2789 if (0) 2790 { 2791 SetLastError(0xdeadbeef); 2792 ret = CloseHandle(hmap_dup); 2793 ok(ret, "CloseHandle should not fail\n"); 2794 } 2795 2796 SetLastError(0xdeadbeef); 2797 ret = DuplicateHandle(GetCurrentProcess(), hmap, pi.hProcess, &hmap_dup, 2798 0, FALSE, DUPLICATE_SAME_ACCESS); 2799 ok(!ret, "DuplicateHandle should fail\n"); 2800 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); 2801 2802 offset.u.LowPart = 0; 2803 offset.u.HighPart = 0; 2804 addr = NULL; 2805 size = 0; 2806 ret = pNtMapViewOfSection(hmap, pi.hProcess, &addr, 0, 0, &offset, 2807 &size, 1 /* ViewShare */, 0, PAGE_READONLY); 2808 ok(ret == STATUS_PROCESS_IS_TERMINATING, "expected STATUS_PROCESS_IS_TERMINATING, got %#x\n", ret); 2809 2810 SetLastError(0xdeadbeef); 2811 thread = CreateRemoteThread(pi.hProcess, NULL, 0, (void *)0xdeadbeef, NULL, CREATE_SUSPENDED, &ret); 2812 ok(!thread, "CreateRemoteThread should fail\n"); 2813 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); 2814 2815 SetLastError(0xdeadbeef); 2816 ret = DebugActiveProcess(pi.dwProcessId); 2817 ok(!ret, "DebugActiveProcess should fail\n"); 2818 ok(GetLastError() == ERROR_ACCESS_DENIED /* 64-bit */ || GetLastError() == ERROR_NOT_SUPPORTED /* 32-bit */, 2819 "ERROR_ACCESS_DENIED, got %d\n", GetLastError()); 2820 2821 GetExitCodeProcess(pi.hProcess, &ret); 2822 ok(ret == 198 || broken(ret != 198) /* some 32-bit XP version in a VM returns random exit code */, 2823 "expected exit code 198, got %u\n", ret); 2824 CloseHandle(pi.hThread); 2825 CloseHandle(pi.hProcess); 2826 2827 ret = DeleteFileA(dll_name); 2828 ok(ret, "DeleteFile error %d\n", GetLastError()); 2829 } 2830 2831 static PVOID WINAPI failuredllhook(ULONG ul, DELAYLOAD_INFO* pd) 2832 { 2833 ok(ul == 4, "expected 4, got %u\n", ul); 2834 ok(!!pd, "no delayload info supplied\n"); 2835 if (pd) 2836 { 2837 ok(pd->Size == sizeof(*pd), "got %u\n", pd->Size); 2838 ok(!!pd->DelayloadDescriptor, "no DelayloadDescriptor supplied\n"); 2839 if (pd->DelayloadDescriptor) 2840 { 2841 ok(pd->DelayloadDescriptor->Attributes.AllAttributes == 1, 2842 "expected 1, got %u\n", pd->DelayloadDescriptor->Attributes.AllAttributes); 2843 ok(pd->DelayloadDescriptor->DllNameRVA == 0x2000, 2844 "expected 0x2000, got %x\n", pd->DelayloadDescriptor->DllNameRVA); 2845 ok(pd->DelayloadDescriptor->ModuleHandleRVA == 0x201a, 2846 "expected 0x201a, got %x\n", pd->DelayloadDescriptor->ModuleHandleRVA); 2847 ok(pd->DelayloadDescriptor->ImportAddressTableRVA > pd->DelayloadDescriptor->ModuleHandleRVA, 2848 "expected %x > %x\n", pd->DelayloadDescriptor->ImportAddressTableRVA, 2849 pd->DelayloadDescriptor->ModuleHandleRVA); 2850 ok(pd->DelayloadDescriptor->ImportNameTableRVA > pd->DelayloadDescriptor->ImportAddressTableRVA, 2851 "expected %x > %x\n", pd->DelayloadDescriptor->ImportNameTableRVA, 2852 pd->DelayloadDescriptor->ImportAddressTableRVA); 2853 ok(pd->DelayloadDescriptor->BoundImportAddressTableRVA == 0, 2854 "expected 0, got %x\n", pd->DelayloadDescriptor->BoundImportAddressTableRVA); 2855 ok(pd->DelayloadDescriptor->UnloadInformationTableRVA == 0, 2856 "expected 0, got %x\n", pd->DelayloadDescriptor->UnloadInformationTableRVA); 2857 ok(pd->DelayloadDescriptor->TimeDateStamp == 0, 2858 "expected 0, got %x\n", pd->DelayloadDescriptor->TimeDateStamp); 2859 } 2860 2861 ok(!!pd->ThunkAddress, "no ThunkAddress supplied\n"); 2862 if (pd->ThunkAddress) 2863 ok(pd->ThunkAddress->u1.Ordinal, "no ThunkAddress value supplied\n"); 2864 2865 ok(!!pd->TargetDllName, "no TargetDllName supplied\n"); 2866 if (pd->TargetDllName) 2867 ok(!strcmp(pd->TargetDllName, "secur32.dll"), 2868 "expected \"secur32.dll\", got \"%s\"\n", pd->TargetDllName); 2869 2870 ok(pd->TargetApiDescriptor.ImportDescribedByName == 0, 2871 "expected 0, got %x\n", pd->TargetApiDescriptor.ImportDescribedByName); 2872 ok(pd->TargetApiDescriptor.Description.Ordinal == 0 || 2873 pd->TargetApiDescriptor.Description.Ordinal == 999, 2874 "expected 0, got %x\n", pd->TargetApiDescriptor.Description.Ordinal); 2875 2876 ok(!!pd->TargetModuleBase, "no TargetModuleBase supplied\n"); 2877 ok(pd->Unused == NULL, "expected NULL, got %p\n", pd->Unused); 2878 ok(pd->LastError, "no LastError supplied\n"); 2879 } 2880 cb_count++; 2881 return (void*)0xdeadbeef; 2882 } 2883 2884 static void test_ResolveDelayLoadedAPI(void) 2885 { 2886 static const char test_dll[] = "secur32.dll"; 2887 static const char test_func[] = "SealMessage"; 2888 char temp_path[MAX_PATH]; 2889 char dll_name[MAX_PATH]; 2890 IMAGE_DELAYLOAD_DESCRIPTOR idd, *delaydir; 2891 IMAGE_THUNK_DATA itd32; 2892 HANDLE hfile; 2893 HMODULE hlib; 2894 DWORD dummy, file_size, i; 2895 WORD hint = 0; 2896 BOOL ret; 2897 IMAGE_NT_HEADERS nt_header; 2898 2899 static const struct test_data 2900 { 2901 BOOL func; 2902 UINT_PTR ordinal; 2903 BOOL succeeds; 2904 } td[] = 2905 { 2906 { 2907 TRUE, 0, TRUE 2908 }, 2909 { 2910 FALSE, IMAGE_ORDINAL_FLAG | 2, TRUE 2911 }, 2912 { 2913 FALSE, IMAGE_ORDINAL_FLAG | 5, TRUE 2914 }, 2915 { 2916 FALSE, IMAGE_ORDINAL_FLAG | 0, FALSE 2917 }, 2918 { 2919 FALSE, IMAGE_ORDINAL_FLAG | 999, FALSE 2920 }, 2921 }; 2922 2923 if (!pResolveDelayLoadedAPI) 2924 { 2925 win_skip("ResolveDelayLoadedAPI is not available\n"); 2926 return; 2927 } 2928 2929 if (0) /* crashes on native */ 2930 { 2931 SetLastError(0xdeadbeef); 2932 ok(!pResolveDelayLoadedAPI(NULL, NULL, NULL, NULL, NULL, 0), 2933 "ResolveDelayLoadedAPI succeeded\n"); 2934 ok(GetLastError() == 0xdeadbeef, "GetLastError changed to %x\n", GetLastError()); 2935 2936 cb_count = 0; 2937 SetLastError(0xdeadbeef); 2938 ok(!pResolveDelayLoadedAPI(NULL, NULL, failuredllhook, NULL, NULL, 0), 2939 "ResolveDelayLoadedAPI succeeded\n"); 2940 ok(GetLastError() == 0xdeadbeef, "GetLastError changed to %x\n", GetLastError()); 2941 ok(cb_count == 1, "Wrong callback count: %d\n", cb_count); 2942 } 2943 2944 GetTempPathA(MAX_PATH, temp_path); 2945 GetTempFileNameA(temp_path, "ldr", 0, dll_name); 2946 trace("creating %s\n", dll_name); 2947 hfile = CreateFileA(dll_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); 2948 if (hfile == INVALID_HANDLE_VALUE) 2949 { 2950 ok(0, "could not create %s\n", dll_name); 2951 return; 2952 } 2953 2954 SetLastError(0xdeadbeef); 2955 ret = WriteFile(hfile, &dos_header, sizeof(dos_header), &dummy, NULL); 2956 ok(ret, "WriteFile error %d\n", GetLastError()); 2957 2958 nt_header = nt_header_template; 2959 nt_header.FileHeader.NumberOfSections = 2; 2960 nt_header.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER); 2961 2962 nt_header.OptionalHeader.SectionAlignment = 0x1000; 2963 nt_header.OptionalHeader.FileAlignment = 0x1000; 2964 nt_header.OptionalHeader.SizeOfImage = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x2200; 2965 nt_header.OptionalHeader.SizeOfHeaders = sizeof(dos_header) + sizeof(nt_header) + 2 * sizeof(IMAGE_SECTION_HEADER); 2966 nt_header.OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES; 2967 nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress = 0x1000; 2968 nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].Size = 0x100; 2969 2970 SetLastError(0xdeadbeef); 2971 ret = WriteFile(hfile, &nt_header, sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER), &dummy, NULL); 2972 ok(ret, "WriteFile error %d\n", GetLastError()); 2973 2974 SetLastError(0xdeadbeef); 2975 ret = WriteFile(hfile, &nt_header.OptionalHeader, sizeof(IMAGE_OPTIONAL_HEADER), &dummy, NULL); 2976 ok(ret, "WriteFile error %d\n", GetLastError()); 2977 2978 /* sections */ 2979 section.PointerToRawData = nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress; 2980 section.VirtualAddress = nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress; 2981 section.Misc.VirtualSize = 2 * sizeof(idd); 2982 section.SizeOfRawData = section.Misc.VirtualSize; 2983 section.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ; 2984 SetLastError(0xdeadbeef); 2985 ret = WriteFile(hfile, §ion, sizeof(section), &dummy, NULL); 2986 ok(ret, "WriteFile error %d\n", GetLastError()); 2987 2988 section.PointerToRawData = 0x2000; 2989 section.VirtualAddress = 0x2000; 2990 i = sizeof(td)/sizeof(td[0]); 2991 section.Misc.VirtualSize = sizeof(test_dll) + sizeof(hint) + sizeof(test_func) + sizeof(HMODULE) + 2992 2 * (i + 1) * sizeof(IMAGE_THUNK_DATA); 2993 ok(section.Misc.VirtualSize <= 0x1000, "Too much tests, add a new section!\n"); 2994 section.SizeOfRawData = section.Misc.VirtualSize; 2995 section.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE; 2996 SetLastError(0xdeadbeef); 2997 ret = WriteFile(hfile, §ion, sizeof(section), &dummy, NULL); 2998 ok(ret, "WriteFile error %d\n", GetLastError()); 2999 3000 /* fill up to delay data */ 3001 SetFilePointer( hfile, nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress, NULL, SEEK_SET ); 3002 3003 /* delay data */ 3004 idd.Attributes.AllAttributes = 1; 3005 idd.DllNameRVA = 0x2000; 3006 idd.ModuleHandleRVA = idd.DllNameRVA + sizeof(test_dll) + sizeof(hint) + sizeof(test_func); 3007 idd.ImportAddressTableRVA = idd.ModuleHandleRVA + sizeof(HMODULE); 3008 idd.ImportNameTableRVA = idd.ImportAddressTableRVA + (i + 1) * sizeof(IMAGE_THUNK_DATA); 3009 idd.BoundImportAddressTableRVA = 0; 3010 idd.UnloadInformationTableRVA = 0; 3011 idd.TimeDateStamp = 0; 3012 3013 SetLastError(0xdeadbeef); 3014 ret = WriteFile(hfile, &idd, sizeof(idd), &dummy, NULL); 3015 ok(ret, "WriteFile error %d\n", GetLastError()); 3016 3017 SetLastError(0xdeadbeef); 3018 ret = WriteFile(hfile, filler, sizeof(idd), &dummy, NULL); 3019 ok(ret, "WriteFile error %d\n", GetLastError()); 3020 3021 /* fill up to extended delay data */ 3022 SetFilePointer( hfile, idd.DllNameRVA, NULL, SEEK_SET ); 3023 3024 /* extended delay data */ 3025 SetLastError(0xdeadbeef); 3026 ret = WriteFile(hfile, test_dll, sizeof(test_dll), &dummy, NULL); 3027 ok(ret, "WriteFile error %d\n", GetLastError()); 3028 3029 SetLastError(0xdeadbeef); 3030 ret = WriteFile(hfile, &hint, sizeof(hint), &dummy, NULL); 3031 ok(ret, "WriteFile error %d\n", GetLastError()); 3032 3033 SetLastError(0xdeadbeef); 3034 ret = WriteFile(hfile, test_func, sizeof(test_func), &dummy, NULL); 3035 ok(ret, "WriteFile error %d\n", GetLastError()); 3036 3037 SetFilePointer( hfile, idd.ImportAddressTableRVA, NULL, SEEK_SET ); 3038 3039 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++) 3040 { 3041 /* 0x1a00 is an empty space between delay data and extended delay data, real thunks are not necessary */ 3042 itd32.u1.Function = nt_header.OptionalHeader.ImageBase + 0x1a00 + i * 0x20; 3043 SetLastError(0xdeadbeef); 3044 ret = WriteFile(hfile, &itd32, sizeof(itd32), &dummy, NULL); 3045 ok(ret, "WriteFile error %d\n", GetLastError()); 3046 } 3047 3048 itd32.u1.Function = 0; 3049 SetLastError(0xdeadbeef); 3050 ret = WriteFile(hfile, &itd32, sizeof(itd32), &dummy, NULL); 3051 ok(ret, "WriteFile error %d\n", GetLastError()); 3052 3053 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++) 3054 { 3055 if (td[i].func) 3056 itd32.u1.AddressOfData = idd.DllNameRVA + sizeof(test_dll); 3057 else 3058 itd32.u1.Ordinal = td[i].ordinal; 3059 SetLastError(0xdeadbeef); 3060 ret = WriteFile(hfile, &itd32, sizeof(itd32), &dummy, NULL); 3061 ok(ret, "WriteFile error %d\n", GetLastError()); 3062 } 3063 3064 itd32.u1.Ordinal = 0; 3065 SetLastError(0xdeadbeef); 3066 ret = WriteFile(hfile, &itd32, sizeof(itd32), &dummy, NULL); 3067 ok(ret, "WriteFile error %d\n", GetLastError()); 3068 3069 /* fill up to eof */ 3070 SetFilePointer( hfile, section.VirtualAddress + section.Misc.VirtualSize, NULL, SEEK_SET ); 3071 SetEndOfFile( hfile ); 3072 CloseHandle(hfile); 3073 3074 SetLastError(0xdeadbeef); 3075 hlib = LoadLibraryA(dll_name); 3076 ok(hlib != NULL, "LoadLibrary error %u\n", GetLastError()); 3077 if (!hlib) 3078 { 3079 skip("couldn't load %s.\n", dll_name); 3080 DeleteFileA(dll_name); 3081 return; 3082 } 3083 3084 delaydir = pRtlImageDirectoryEntryToData(hlib, TRUE, IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT, &file_size); 3085 if (!delaydir) 3086 { 3087 skip("haven't found section for delay import directory.\n"); 3088 FreeLibrary(hlib); 3089 DeleteFileA(dll_name); 3090 return; 3091 } 3092 3093 for (;;) 3094 { 3095 IMAGE_THUNK_DATA *itdn, *itda; 3096 HMODULE htarget; 3097 3098 if (!delaydir->DllNameRVA || 3099 !delaydir->ImportAddressTableRVA || 3100 !delaydir->ImportNameTableRVA) break; 3101 3102 itdn = RVAToAddr(delaydir->ImportNameTableRVA, hlib); 3103 itda = RVAToAddr(delaydir->ImportAddressTableRVA, hlib); 3104 htarget = LoadLibraryA(RVAToAddr(delaydir->DllNameRVA, hlib)); 3105 3106 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++) 3107 { 3108 void *ret, *load; 3109 3110 if (IMAGE_SNAP_BY_ORDINAL(itdn[i].u1.Ordinal)) 3111 load = (void *)GetProcAddress(htarget, (LPSTR)IMAGE_ORDINAL(itdn[i].u1.Ordinal)); 3112 else 3113 { 3114 const IMAGE_IMPORT_BY_NAME* iibn = RVAToAddr(itdn[i].u1.AddressOfData, hlib); 3115 load = (void *)GetProcAddress(htarget, (char*)iibn->Name); 3116 } 3117 3118 cb_count = 0; 3119 ret = pResolveDelayLoadedAPI(hlib, delaydir, failuredllhook, NULL, &itda[i], 0); 3120 if (td[i].succeeds) 3121 { 3122 ok(ret != NULL, "Test %u: ResolveDelayLoadedAPI failed\n", i); 3123 ok(ret == load, "Test %u: expected %p, got %p\n", i, load, ret); 3124 ok(ret == (void*)itda[i].u1.AddressOfData, "Test %u: expected %p, got %p\n", 3125 i, ret, (void*)itda[i].u1.AddressOfData); 3126 ok(!cb_count, "Test %u: Wrong callback count: %d\n", i, cb_count); 3127 } 3128 else 3129 { 3130 ok(ret == (void*)0xdeadbeef, "Test %u: ResolveDelayLoadedAPI succeeded with %p\n", i, ret); 3131 ok(cb_count, "Test %u: Wrong callback count: %d\n", i, cb_count); 3132 } 3133 } 3134 delaydir++; 3135 } 3136 3137 FreeLibrary(hlib); 3138 trace("deleting %s\n", dll_name); 3139 DeleteFileA(dll_name); 3140 } 3141 3142 static void test_InMemoryOrderModuleList(void) 3143 { 3144 PEB_LDR_DATA *ldr = NtCurrentTeb()->Peb->LdrData; 3145 LIST_ENTRY *entry1, *mark1 = &ldr->InLoadOrderModuleList; 3146 LIST_ENTRY *entry2, *mark2 = &ldr->InMemoryOrderModuleList; 3147 LDR_MODULE *module1, *module2; 3148 3149 ok(ldr->Initialized == TRUE, "expected TRUE, got %u\n", ldr->Initialized); 3150 3151 for (entry1 = mark1->Flink, entry2 = mark2->Flink; 3152 entry1 != mark1 && entry2 != mark2; 3153 entry1 = entry1->Flink, entry2 = entry2->Flink) 3154 { 3155 module1 = CONTAINING_RECORD(entry1, LDR_MODULE, InLoadOrderModuleList); 3156 module2 = CONTAINING_RECORD(entry2, LDR_MODULE, InMemoryOrderModuleList); 3157 ok(module1 == module2, "expected module1 == module2, got %p and %p\n", module1, module2); 3158 } 3159 ok(entry1 == mark1, "expected entry1 == mark1, got %p and %p\n", entry1, mark1); 3160 ok(entry2 == mark2, "expected entry2 == mark2, got %p and %p\n", entry2, mark2); 3161 } 3162 3163 static inline WCHAR toupperW(WCHAR c) 3164 { 3165 WCHAR tmp = c; 3166 CharUpperBuffW(&tmp, 1); 3167 return tmp; 3168 } 3169 3170 static ULONG hash_basename(const WCHAR *basename) 3171 { 3172 WORD version = MAKEWORD(NtCurrentTeb()->Peb->OSMinorVersion, 3173 NtCurrentTeb()->Peb->OSMajorVersion); 3174 ULONG hash = 0; 3175 3176 if (version >= 0x0602) 3177 { 3178 for (; *basename; basename++) 3179 hash = hash * 65599 + toupperW(*basename); 3180 } 3181 else if (version == 0x0601) 3182 { 3183 for (; *basename; basename++) 3184 hash = hash + 65599 * toupperW(*basename); 3185 } 3186 else 3187 hash = toupperW(basename[0]) - 'A'; 3188 3189 return hash & 31; 3190 } 3191 3192 static void test_HashLinks(void) 3193 { 3194 static WCHAR ntdllW[] = {'n','t','d','l','l','.','d','l','l',0}; 3195 static WCHAR kernel32W[] = {'k','e','r','n','e','l','3','2','.','d','l','l',0}; 3196 3197 LIST_ENTRY *hash_map, *entry, *mark; 3198 LDR_MODULE *module; 3199 BOOL found; 3200 3201 entry = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList; 3202 entry = entry->Flink; 3203 3204 module = CONTAINING_RECORD(entry, LDR_MODULE, InLoadOrderModuleList); 3205 entry = module->HashLinks.Blink; 3206 3207 hash_map = entry - hash_basename(module->BaseDllName.Buffer); 3208 3209 mark = &hash_map[hash_basename(ntdllW)]; 3210 found = FALSE; 3211 for (entry = mark->Flink; entry != mark; entry = entry->Flink) 3212 { 3213 module = CONTAINING_RECORD(entry, LDR_MODULE, HashLinks); 3214 if (!lstrcmpiW(module->BaseDllName.Buffer, ntdllW)) 3215 { 3216 found = TRUE; 3217 break; 3218 } 3219 } 3220 ok(found, "Could not find ntdll\n"); 3221 3222 mark = &hash_map[hash_basename(kernel32W)]; 3223 found = FALSE; 3224 for (entry = mark->Flink; entry != mark; entry = entry->Flink) 3225 { 3226 module = CONTAINING_RECORD(entry, LDR_MODULE, HashLinks); 3227 if (!lstrcmpiW(module->BaseDllName.Buffer, kernel32W)) 3228 { 3229 found = TRUE; 3230 break; 3231 } 3232 } 3233 ok(found, "Could not find kernel32\n"); 3234 } 3235 3236 START_TEST(loader) 3237 { 3238 int argc; 3239 char **argv; 3240 HANDLE ntdll, mapping, kernel32; 3241 SYSTEM_INFO si; 3242 3243 ntdll = GetModuleHandleA("ntdll.dll"); 3244 kernel32 = GetModuleHandleA("kernel32.dll"); 3245 pNtCreateSection = (void *)GetProcAddress(ntdll, "NtCreateSection"); 3246 pNtQuerySection = (void *)GetProcAddress(ntdll, "NtQuerySection"); 3247 pNtMapViewOfSection = (void *)GetProcAddress(ntdll, "NtMapViewOfSection"); 3248 pNtUnmapViewOfSection = (void *)GetProcAddress(ntdll, "NtUnmapViewOfSection"); 3249 pNtTerminateProcess = (void *)GetProcAddress(ntdll, "NtTerminateProcess"); 3250 pNtQueryInformationProcess = (void *)GetProcAddress(ntdll, "NtQueryInformationProcess"); 3251 pNtSetInformationProcess = (void *)GetProcAddress(ntdll, "NtSetInformationProcess"); 3252 pLdrShutdownProcess = (void *)GetProcAddress(ntdll, "LdrShutdownProcess"); 3253 pRtlDllShutdownInProgress = (void *)GetProcAddress(ntdll, "RtlDllShutdownInProgress"); 3254 pNtAllocateVirtualMemory = (void *)GetProcAddress(ntdll, "NtAllocateVirtualMemory"); 3255 pNtFreeVirtualMemory = (void *)GetProcAddress(ntdll, "NtFreeVirtualMemory"); 3256 pLdrLockLoaderLock = (void *)GetProcAddress(ntdll, "LdrLockLoaderLock"); 3257 pLdrUnlockLoaderLock = (void *)GetProcAddress(ntdll, "LdrUnlockLoaderLock"); 3258 pRtlAcquirePebLock = (void *)GetProcAddress(ntdll, "RtlAcquirePebLock"); 3259 pRtlReleasePebLock = (void *)GetProcAddress(ntdll, "RtlReleasePebLock"); 3260 pRtlImageDirectoryEntryToData = (void *)GetProcAddress(ntdll, "RtlImageDirectoryEntryToData"); 3261 pFlsAlloc = (void *)GetProcAddress(kernel32, "FlsAlloc"); 3262 pFlsSetValue = (void *)GetProcAddress(kernel32, "FlsSetValue"); 3263 pFlsGetValue = (void *)GetProcAddress(kernel32, "FlsGetValue"); 3264 pFlsFree = (void *)GetProcAddress(kernel32, "FlsFree"); 3265 pResolveDelayLoadedAPI = (void *)GetProcAddress(kernel32, "ResolveDelayLoadedAPI"); 3266 3267 GetSystemInfo( &si ); 3268 page_size = si.dwPageSize; 3269 dos_header.e_magic = IMAGE_DOS_SIGNATURE; 3270 dos_header.e_lfanew = sizeof(dos_header); 3271 3272 mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, "winetest_loader"); 3273 ok(mapping != 0, "CreateFileMapping failed\n"); 3274 child_failures = MapViewOfFile(mapping, FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, 4096); 3275 if (*child_failures == -1) 3276 { 3277 *child_failures = 0; 3278 } 3279 else 3280 *child_failures = -1; 3281 3282 argc = winetest_get_mainargs(&argv); 3283 if (argc > 4) 3284 { 3285 test_dll_phase = atoi(argv[4]); 3286 child_process(argv[2], atol(argv[3])); 3287 return; 3288 } 3289 3290 test_Loader(); 3291 test_FakeDLL(); 3292 test_ResolveDelayLoadedAPI(); 3293 test_ImportDescriptors(); 3294 test_section_access(); 3295 test_import_resolution(); 3296 test_ExitProcess(); 3297 test_InMemoryOrderModuleList(); 3298 test_HashLinks(); 3299 } 3300