1 /* 2 * PROJECT: ReactOS API Tests 3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory 4 * PURPOSE: Test for NtMapViewOfSection 5 * PROGRAMMERS: Timo Kreuzer 6 * Thomas Faber 7 */ 8 9 #include "precomp.h" 10 11 void 12 Test_PageFileSection(void) 13 { 14 NTSTATUS Status; 15 HANDLE SectionHandle; 16 LARGE_INTEGER MaximumSize, SectionOffset; 17 PVOID BaseAddress, BaseAddress2; 18 SIZE_T ViewSize; 19 ULONG OldProtect; 20 21 /* Create a page file backed section with SEC_COMMIT */ 22 MaximumSize.QuadPart = 0x20000; 23 Status = NtCreateSection(&SectionHandle, 24 SECTION_ALL_ACCESS, 25 NULL, 26 &MaximumSize, 27 PAGE_READWRITE, 28 SEC_COMMIT, 29 NULL); 30 ok_ntstatus(Status, STATUS_SUCCESS); 31 if (!NT_SUCCESS(Status)) 32 return; 33 34 /* Try to map a page at an address that is not 64k aligned */ 35 BaseAddress = (PVOID)0x30001000; 36 SectionOffset.QuadPart = 0; 37 ViewSize = 0x1000; 38 Status = NtMapViewOfSection(SectionHandle, 39 NtCurrentProcess(), 40 &BaseAddress, 41 0, 42 0, 43 &SectionOffset, 44 &ViewSize, 45 ViewShare, 46 0, 47 PAGE_READWRITE); 48 ok_ntstatus(Status, STATUS_MAPPED_ALIGNMENT); 49 50 /* Try to map a page with execute rights */ 51 BaseAddress = (PVOID)0x30000000; 52 SectionOffset.QuadPart = 0; 53 ViewSize = 0x1000; 54 Status = NtMapViewOfSection(SectionHandle, 55 NtCurrentProcess(), 56 &BaseAddress, 57 0, 58 0, 59 &SectionOffset, 60 &ViewSize, 61 ViewShare, 62 0, 63 PAGE_EXECUTE_READWRITE); 64 ok_ntstatus(Status, STATUS_SECTION_PROTECTION); 65 66 /* Try to map 2 pages with MEM_COMMIT */ 67 BaseAddress = (PVOID)0x30000000; 68 SectionOffset.QuadPart = 0; 69 ViewSize = 0x2000; 70 Status = NtMapViewOfSection(SectionHandle, 71 NtCurrentProcess(), 72 &BaseAddress, 73 0, 74 PAGE_SIZE, 75 &SectionOffset, 76 &ViewSize, 77 ViewShare, 78 MEM_COMMIT, 79 PAGE_READWRITE); 80 ok_ntstatus(Status, STATUS_INVALID_PARAMETER_9); 81 82 /* Try to map 1 page, with free base address and zero bits compatible with 64k granularity */ 83 BaseAddress = NULL; 84 SectionOffset.QuadPart = 0; 85 ViewSize = 0x1000; 86 Status = NtMapViewOfSection(SectionHandle, 87 NtCurrentProcess(), 88 &BaseAddress, 89 10, 90 0, 91 &SectionOffset, 92 &ViewSize, 93 ViewShare, 94 0, 95 PAGE_READWRITE); 96 ok_ntstatus(Status, STATUS_SUCCESS); 97 Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress); 98 ok_ntstatus(Status, STATUS_SUCCESS); 99 100 { 101 ULONG_PTR gran = 64 * 1024; 102 ULONG_PTR ZeroBits = 11; 103 104 ok_hex(gran, 0x10000); 105 gran <<= ZeroBits; 106 ok_hex(gran, 0x8000000); 107 gran >>= ZeroBits; 108 ok_hex(gran, 0x10000); 109 110 ok_hex((gran << ZeroBits) >> ZeroBits, gran); 111 112 } 113 114 /* Try to map 1 page, with free base address and zero bits incompatible with 64k granularity */ 115 BaseAddress = NULL; 116 SectionOffset.QuadPart = 0; 117 ViewSize = 0x1000; 118 Status = NtMapViewOfSection(SectionHandle, 119 NtCurrentProcess(), 120 &BaseAddress, 121 11, 122 0, 123 &SectionOffset, 124 &ViewSize, 125 ViewShare, 126 0, 127 PAGE_READWRITE); 128 ok_ntstatus(Status, STATUS_NO_MEMORY); 129 130 /* Try to map 1 page, with base address and zero bits being compatible */ 131 BaseAddress = (PVOID)0x30000000; 132 SectionOffset.QuadPart = 0; 133 ViewSize = 0x1000; 134 Status = NtMapViewOfSection(SectionHandle, 135 NtCurrentProcess(), 136 &BaseAddress, 137 2, 138 0, 139 &SectionOffset, 140 &ViewSize, 141 ViewShare, 142 0, 143 PAGE_READWRITE); 144 ok_ntstatus(Status, STATUS_SUCCESS); 145 Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress); 146 ok_ntstatus(Status, STATUS_SUCCESS); 147 148 /* Try to map 1 page, with base address and zero bits being incompatible */ 149 BaseAddress = (PVOID)0x30000000; 150 SectionOffset.QuadPart = 0; 151 ViewSize = 0x1000; 152 Status = NtMapViewOfSection(SectionHandle, 153 NtCurrentProcess(), 154 &BaseAddress, 155 3, 156 0, 157 &SectionOffset, 158 &ViewSize, 159 ViewShare, 160 0, 161 PAGE_READWRITE); 162 ok_ntstatus(Status, STATUS_INVALID_PARAMETER_4); 163 164 /* Map 2 pages, without MEM_COMMIT */ 165 BaseAddress = (PVOID)0x30000000; 166 SectionOffset.QuadPart = 0; 167 ViewSize = 0x2000; 168 Status = NtMapViewOfSection(SectionHandle, 169 NtCurrentProcess(), 170 &BaseAddress, 171 0, 172 0, 173 &SectionOffset, 174 &ViewSize, 175 ViewShare, 176 0, 177 PAGE_READWRITE); 178 ok_ntstatus(Status, STATUS_SUCCESS); 179 180 /* We must be able to access the memory */ 181 _SEH2_TRY 182 { 183 *(PULONG)BaseAddress = 1; 184 } 185 _SEH2_EXCEPT(1) 186 { 187 ok(FALSE, "Got an exception\n"); 188 } 189 _SEH2_END; 190 191 /* Commit a page in the section */ 192 BaseAddress = (PVOID)0x30000000; 193 ViewSize = 0x1000; 194 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 195 &BaseAddress, 196 0, 197 &ViewSize, 198 MEM_COMMIT, 199 PAGE_READWRITE); 200 ok_ntstatus(Status, STATUS_SUCCESS); 201 202 /* Try to decommit a page in the section */ 203 Status = NtFreeVirtualMemory(NtCurrentProcess(), 204 &BaseAddress, 205 &ViewSize, 206 MEM_DECOMMIT); 207 ok_ntstatus(Status, STATUS_UNABLE_TO_DELETE_SECTION); 208 209 /* Try to commit a range larger than the section */ 210 BaseAddress = (PVOID)0x30000000; 211 ViewSize = 0x3000; 212 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 213 &BaseAddress, 214 0, 215 &ViewSize, 216 MEM_COMMIT, 217 PAGE_READWRITE); 218 ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES); 219 220 /* Try to commit a page after the section */ 221 BaseAddress = (PVOID)0x30002000; 222 ViewSize = 0x1000; 223 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 224 &BaseAddress, 225 0, 226 &ViewSize, 227 MEM_COMMIT, 228 PAGE_READWRITE); 229 ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES); 230 231 /* Try to allocate a page after the section */ 232 BaseAddress = (PVOID)0x30002000; 233 ViewSize = 0x1000; 234 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 235 &BaseAddress, 236 0, 237 &ViewSize, 238 MEM_RESERVE | MEM_COMMIT, 239 PAGE_READWRITE); 240 ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES); 241 242 /* Need to go to next 64k boundary */ 243 BaseAddress = (PVOID)0x30010000; 244 ViewSize = 0x1000; 245 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 246 &BaseAddress, 247 0, 248 &ViewSize, 249 MEM_RESERVE | MEM_COMMIT, 250 PAGE_READWRITE); 251 ok_ntstatus(Status, STATUS_SUCCESS); 252 if (!NT_SUCCESS(Status)) 253 return; 254 255 /* Free the allocation */ 256 BaseAddress = (PVOID)0x30010000; 257 ViewSize = 0x1000; 258 Status = NtFreeVirtualMemory(NtCurrentProcess(), 259 &BaseAddress, 260 &ViewSize, 261 MEM_RELEASE); 262 ok(NT_SUCCESS(Status), "NtFreeVirtualMemory failed with Status %lx\n", Status); 263 264 /* Try to release the section mapping with NtFreeVirtualMemory */ 265 BaseAddress = (PVOID)0x30000000; 266 ViewSize = 0x1000; 267 Status = NtFreeVirtualMemory(NtCurrentProcess(), 268 &BaseAddress, 269 &ViewSize, 270 MEM_RELEASE); 271 ok_ntstatus(Status, STATUS_UNABLE_TO_DELETE_SECTION); 272 273 /* Commit a page in the section */ 274 BaseAddress = (PVOID)0x30001000; 275 ViewSize = 0x1000; 276 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 277 &BaseAddress, 278 0, 279 &ViewSize, 280 MEM_COMMIT, 281 PAGE_READWRITE); 282 ok_ntstatus(Status, STATUS_SUCCESS); 283 284 /* Try to decommit the page */ 285 BaseAddress = (PVOID)0x30001000; 286 ViewSize = 0x1000; 287 Status = NtFreeVirtualMemory(NtCurrentProcess(), 288 &BaseAddress, 289 &ViewSize, 290 MEM_DECOMMIT); 291 ok_ntstatus(Status, STATUS_UNABLE_TO_DELETE_SECTION); 292 293 BaseAddress = UlongToPtr(0x40000000); 294 SectionOffset.QuadPart = 0; 295 ViewSize = 0x1000; 296 Status = NtMapViewOfSection(SectionHandle, 297 NtCurrentProcess(), 298 &BaseAddress, 299 0, 300 0, 301 &SectionOffset, 302 &ViewSize, 303 ViewShare, 304 0, 305 PAGE_READWRITE); 306 ok_ntstatus(Status, STATUS_SUCCESS); 307 if (!NT_SUCCESS(Status)) 308 return; 309 310 ok(BaseAddress == UlongToPtr(0x40000000), "Invalid BaseAddress: %p\n", BaseAddress); 311 312 BaseAddress = (PVOID)0x40080000; 313 SectionOffset.QuadPart = 0x10000; 314 ViewSize = 0x1000; 315 Status = NtMapViewOfSection(SectionHandle, 316 NtCurrentProcess(), 317 &BaseAddress, 318 0, 319 0, 320 &SectionOffset, 321 &ViewSize, 322 ViewShare, 323 0, 324 PAGE_READWRITE); 325 ok_ntstatus(Status, STATUS_SUCCESS); 326 327 ok(BaseAddress == (PVOID)0x40080000, "Invalid BaseAddress: %p\n", BaseAddress); 328 329 /* Commit a page in the section */ 330 BaseAddress = (PVOID)0x40000000; 331 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 332 &BaseAddress, 333 0, 334 &ViewSize, 335 MEM_COMMIT, 336 PAGE_READWRITE); 337 ok_ntstatus(Status, STATUS_SUCCESS); 338 339 /* Close the mapping */ 340 Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress); 341 ok_ntstatus(Status, STATUS_SUCCESS); 342 BaseAddress = (PVOID)0x30000000; 343 Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress); 344 ok_ntstatus(Status, STATUS_SUCCESS); 345 Status = NtClose(SectionHandle); 346 ok_ntstatus(Status, STATUS_SUCCESS); 347 348 /* Create a page file backed section, but only reserved */ 349 MaximumSize.QuadPart = 0x20000; 350 Status = NtCreateSection(&SectionHandle, 351 SECTION_ALL_ACCESS, 352 NULL, 353 &MaximumSize, 354 PAGE_READWRITE, 355 SEC_RESERVE, 356 NULL); 357 ok_ntstatus(Status, STATUS_SUCCESS); 358 359 /* Try to map 1 page, passing MEM_RESERVE */ 360 BaseAddress = NULL; 361 SectionOffset.QuadPart = 0; 362 ViewSize = PAGE_SIZE; 363 Status = NtMapViewOfSection(SectionHandle, 364 NtCurrentProcess(), 365 &BaseAddress, 366 0, 367 PAGE_SIZE, 368 &SectionOffset, 369 &ViewSize, 370 ViewShare, 371 MEM_RESERVE, 372 PAGE_READWRITE); 373 ok_ntstatus(Status, STATUS_INVALID_PARAMETER_9); 374 375 /* Try to map 1 page using MEM_COMMIT */ 376 BaseAddress = NULL; 377 SectionOffset.QuadPart = 0; 378 ViewSize = PAGE_SIZE; 379 Status = NtMapViewOfSection(SectionHandle, 380 NtCurrentProcess(), 381 &BaseAddress, 382 0, 383 PAGE_SIZE, 384 &SectionOffset, 385 &ViewSize, 386 ViewShare, 387 MEM_COMMIT, 388 PAGE_READWRITE); 389 ok_ntstatus(Status, STATUS_INVALID_PARAMETER_9); 390 391 /* Map 2 pages, but commit 1 */ 392 BaseAddress = NULL; 393 SectionOffset.QuadPart = 0; 394 ViewSize = 2 * PAGE_SIZE; 395 Status = NtMapViewOfSection(SectionHandle, 396 NtCurrentProcess(), 397 &BaseAddress, 398 0, 399 PAGE_SIZE, 400 &SectionOffset, 401 &ViewSize, 402 ViewShare, 403 0, 404 PAGE_READWRITE); 405 ok_ntstatus(Status, STATUS_SUCCESS); 406 407 /* We must be able to access the 1st page */ 408 Status = STATUS_SUCCESS; 409 _SEH2_TRY 410 { 411 *(PUCHAR)BaseAddress = 1; 412 } 413 _SEH2_EXCEPT(1) 414 { 415 Status = _SEH2_GetExceptionCode(); 416 } 417 _SEH2_END; 418 ok_ntstatus(Status, STATUS_SUCCESS); 419 420 /* We must not be able to access the 2nd page */ 421 Status = STATUS_SUCCESS; 422 _SEH2_TRY 423 { 424 *((PUCHAR)BaseAddress + PAGE_SIZE) = 1; 425 } 426 _SEH2_EXCEPT(1) 427 { 428 Status = _SEH2_GetExceptionCode(); 429 } 430 _SEH2_END; 431 ok_ntstatus(Status, STATUS_ACCESS_VIOLATION); 432 433 /* Map the 2 pages again into a different memory location */ 434 BaseAddress2 = NULL; 435 Status = NtMapViewOfSection(SectionHandle, 436 NtCurrentProcess(), 437 &BaseAddress2, 438 0, 439 0, 440 &SectionOffset, 441 &ViewSize, 442 ViewShare, 443 0, 444 PAGE_READWRITE); 445 ok_ntstatus(Status, STATUS_SUCCESS); 446 447 /* Commit a the 2nd page in the 2nd memory location */ 448 BaseAddress2 = (PUCHAR)BaseAddress2 + PAGE_SIZE; 449 ViewSize = PAGE_SIZE; 450 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 451 &BaseAddress2, 452 0, 453 &ViewSize, 454 MEM_COMMIT, 455 PAGE_READONLY); 456 ok_ntstatus(Status, STATUS_SUCCESS); 457 458 /* Try to commit again (the already committed page) */ 459 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 460 &BaseAddress2, 461 0, 462 &ViewSize, 463 MEM_COMMIT, 464 PAGE_READONLY); 465 ok_ntstatus(Status, STATUS_SUCCESS); 466 467 /* We must be able to access the memory in the 2nd page of the 1st memory location */ 468 Status = STATUS_SUCCESS; 469 _SEH2_TRY 470 { 471 *((PUCHAR)BaseAddress + PAGE_SIZE) = 2; 472 } 473 _SEH2_EXCEPT(1) 474 { 475 Status = _SEH2_GetExceptionCode(); 476 } 477 _SEH2_END; 478 ok_ntstatus(Status, STATUS_SUCCESS); 479 480 ok(*(PULONG)BaseAddress2 == 2, "Value in memory was wrong\n"); 481 482 /* Close the mapping */ 483 Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress); 484 ok_ntstatus(Status, STATUS_SUCCESS); 485 Status = NtUnmapViewOfSection(NtCurrentProcess(), (PUCHAR)BaseAddress2 - PAGE_SIZE); 486 ok_ntstatus(Status, STATUS_SUCCESS); 487 Status = NtClose(SectionHandle); 488 ok_ntstatus(Status, STATUS_SUCCESS); 489 490 /* Try to create a 512 GB page file backed section with committed pages */ 491 MaximumSize.QuadPart = 0x8000000000; 492 Status = NtCreateSection(&SectionHandle, 493 SECTION_ALL_ACCESS, 494 NULL, 495 &MaximumSize, 496 PAGE_READWRITE, 497 SEC_COMMIT, 498 NULL); 499 ok_ntstatus(Status, STATUS_COMMITMENT_LIMIT); 500 501 /* Try to create a huge page file backed section with PAGE_NOACCESS protection */ 502 MaximumSize.QuadPart = 0x8000000000; 503 Status = NtCreateSection(&SectionHandle, 504 SECTION_ALL_ACCESS, 505 NULL, 506 &MaximumSize, 507 PAGE_NOACCESS, 508 SEC_COMMIT, 509 NULL); 510 ok_ntstatus(Status, STATUS_INVALID_PAGE_PROTECTION); 511 512 /* Try to create a very huge page file backed section, but only reserved */ 513 MaximumSize.QuadPart = 0x80000000000; 514 Status = NtCreateSection(&SectionHandle, 515 SECTION_ALL_ACCESS, 516 NULL, 517 &MaximumSize, 518 PAGE_READWRITE, 519 SEC_RESERVE, 520 NULL); 521 #ifdef _WIN64 522 ok_ntstatus(Status, STATUS_INSUFFICIENT_RESOURCES); 523 #else 524 /* WoW64 returns STATUS_INSUFFICIENT_RESOURCES */ 525 ok((Status == STATUS_INSUFFICIENT_RESOURCES) || (Status == STATUS_SECTION_TOO_BIG), 526 "got wrong Status: 0x%lx\n", Status); 527 #endif 528 529 /* Try to create a even huger page file backed section, but only reserved */ 530 MaximumSize.QuadPart = 0x800000000000; 531 Status = NtCreateSection(&SectionHandle, 532 SECTION_ALL_ACCESS, 533 NULL, 534 &MaximumSize, 535 PAGE_READWRITE, 536 SEC_RESERVE, 537 NULL); 538 ok_ntstatus(Status, STATUS_SECTION_TOO_BIG); 539 540 /* Create a 8 GB page file backed section, but only reserved */ 541 MaximumSize.QuadPart = 0x200000000; 542 Status = NtCreateSection(&SectionHandle, 543 SECTION_ALL_ACCESS, 544 NULL, 545 &MaximumSize, 546 PAGE_READWRITE, 547 SEC_RESERVE, 548 NULL); 549 ok_ntstatus(Status, STATUS_SUCCESS); 550 551 /* Pass a too large region size */ 552 BaseAddress = NULL; 553 SectionOffset.QuadPart = 0; 554 ViewSize = MAXULONG_PTR; 555 Status = NtMapViewOfSection(SectionHandle, 556 NtCurrentProcess(), 557 &BaseAddress, 558 0, 559 0, 560 &SectionOffset, 561 &ViewSize, 562 ViewShare, 563 0, 564 PAGE_READWRITE); 565 #ifdef _WIN64 566 ok_ntstatus(Status, STATUS_INVALID_PARAMETER_3); 567 #else 568 /* WoW64 returns STATUS_INVALID_PARAMETER_4 */ 569 ok((Status == STATUS_INVALID_PARAMETER_4) || (Status == STATUS_INVALID_PARAMETER_3), 570 "got wrong Status: 0x%lx\n", Status); 571 #endif 572 573 /* Pass 0 region size */ 574 BaseAddress = NULL; 575 SectionOffset.QuadPart = 0; 576 ViewSize = 0; 577 Status = NtMapViewOfSection(SectionHandle, 578 NtCurrentProcess(), 579 &BaseAddress, 580 0, 581 0, 582 &SectionOffset, 583 &ViewSize, 584 ViewShare, 585 0, 586 PAGE_READWRITE); 587 #ifdef _WIN64 588 ok_ntstatus(Status, STATUS_SUCCESS); 589 ok(ViewSize == 0x200000000, "wrong ViewSize: 0x%Ix\n", ViewSize); 590 #else 591 /* WoW64 returns STATUS_NO_MEMORY */ 592 ok((Status == STATUS_NO_MEMORY) || (Status == STATUS_INVALID_VIEW_SIZE), 593 "got wrong Status: 0x%lx\n", Status); 594 ok(ViewSize == 0, "wrong ViewSize: 0x%Ix\n", ViewSize); 595 #endif 596 597 /* Map with PAGE_NOACCESS */ 598 BaseAddress = NULL; 599 SectionOffset.QuadPart = 0; 600 ViewSize = 0x20000000; 601 Status = NtMapViewOfSection(SectionHandle, 602 NtCurrentProcess(), 603 &BaseAddress, 604 0, 605 0, 606 &SectionOffset, 607 &ViewSize, 608 ViewShare, 609 0, 610 PAGE_NOACCESS); 611 ok_ntstatus(Status, STATUS_SUCCESS); 612 613 /* Try to change protection to read/write */ 614 ViewSize = 0x1000; 615 OldProtect = -1; 616 BaseAddress2 = BaseAddress; 617 Status = NtProtectVirtualMemory(NtCurrentProcess(), &BaseAddress2, &ViewSize, PAGE_READWRITE, &OldProtect); 618 ok_ntstatus(Status, STATUS_SECTION_PROTECTION); 619 // Windows 2003 returns bogus 620 //ok(OldProtect == PAGE_READWRITE, "Wrong protection returned: %u\n", OldProtect); 621 622 /* Test read access */ 623 Status = STATUS_SUCCESS; 624 _SEH2_TRY 625 { 626 (void)(*(volatile char*)BaseAddress2); 627 } 628 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 629 { 630 Status = _SEH2_GetExceptionCode(); 631 } 632 _SEH2_END; 633 ok_ntstatus(Status, STATUS_ACCESS_VIOLATION); 634 635 /* Try to change protection to read/write */ 636 ViewSize = 0x1000; 637 OldProtect = -1; 638 BaseAddress2 = BaseAddress; 639 Status = NtProtectVirtualMemory(NtCurrentProcess(), &BaseAddress2, &ViewSize, PAGE_READWRITE, &OldProtect); 640 ok_ntstatus(Status, STATUS_SECTION_PROTECTION); 641 #ifdef _WIN64 642 ok(OldProtect == 0, "Wrong protection returned: 0x%lx\n", OldProtect); 643 #else 644 // Windows 2003 returns bogus 645 #endif 646 647 /* Try to change protection to readonly */ 648 ViewSize = 0x1000; 649 OldProtect = -1; 650 BaseAddress2 = BaseAddress; 651 Status = NtProtectVirtualMemory(NtCurrentProcess(), &BaseAddress2, &ViewSize, PAGE_READONLY, &OldProtect); 652 ok_ntstatus(Status, STATUS_SECTION_PROTECTION); 653 #ifdef _WIN64 654 //ok(OldProtect == 0, "Wrong protection returned: 0x%lx\n", OldProtect); 655 #else 656 // Windows 2003 returns bogus 657 #endif 658 659 /* Commit a page */ 660 ViewSize = 0x1000; 661 BaseAddress2 = BaseAddress; 662 Status = NtAllocateVirtualMemory(NtCurrentProcess(), &BaseAddress2, 0, &ViewSize, MEM_COMMIT, PAGE_READONLY); 663 ok_ntstatus(Status, STATUS_SUCCESS); 664 ok(BaseAddress2 == BaseAddress, "Invalid base address: %p\n", BaseAddress2); 665 666 /* Commit the page again */ 667 ViewSize = 0x1000; 668 BaseAddress2 = BaseAddress; 669 Status = NtAllocateVirtualMemory(NtCurrentProcess(), &BaseAddress2, 0, &ViewSize, MEM_COMMIT, PAGE_READONLY); 670 ok_ntstatus(Status, STATUS_SUCCESS); 671 ok(BaseAddress2 == BaseAddress, "Invalid base address: %p\n", BaseAddress2); 672 673 /* Test read access */ 674 Status = STATUS_SUCCESS; 675 _SEH2_TRY 676 { 677 (void)(*(volatile char*)BaseAddress2); 678 } 679 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 680 { 681 Status = _SEH2_GetExceptionCode(); 682 } 683 _SEH2_END; 684 ok_ntstatus(Status, STATUS_SUCCESS); 685 686 /* Test write access */ 687 Status = STATUS_SUCCESS; 688 _SEH2_TRY 689 { 690 *(char*)BaseAddress2 = 1; 691 } 692 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 693 { 694 Status = _SEH2_GetExceptionCode(); 695 } 696 _SEH2_END; 697 ok_ntstatus(Status, STATUS_ACCESS_VIOLATION); 698 699 /* Update protection to PAGE_READWRITE */ 700 ViewSize = 0x1000; 701 BaseAddress2 = BaseAddress; 702 Status = NtAllocateVirtualMemory(NtCurrentProcess(), &BaseAddress2, 0, &ViewSize, MEM_COMMIT, PAGE_READWRITE); 703 ok_ntstatus(Status, STATUS_SUCCESS); 704 705 /* Test write access */ 706 Status = STATUS_SUCCESS; 707 _SEH2_TRY 708 { 709 *(char*)BaseAddress2 = 1; 710 } 711 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 712 { 713 Status = _SEH2_GetExceptionCode(); 714 } 715 _SEH2_END; 716 ok_ntstatus(Status, STATUS_SUCCESS); 717 718 /* Update protection to PAGE_EXECUTE_READWRITE (1 page) */ 719 ViewSize = 0x1000; 720 BaseAddress2 = BaseAddress; 721 Status = NtAllocateVirtualMemory(NtCurrentProcess(), &BaseAddress2, 0, &ViewSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 722 ok_ntstatus(Status, STATUS_SUCCESS); 723 724 Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress); 725 ok_ntstatus(Status, STATUS_SUCCESS); 726 Status = NtClose(SectionHandle); 727 ok_ntstatus(Status, STATUS_SUCCESS); 728 } 729 730 void 731 Test_ImageSection(void) 732 { 733 UNICODE_STRING FileName; 734 NTSTATUS Status; 735 OBJECT_ATTRIBUTES FileObjectAttributes; 736 IO_STATUS_BLOCK IoStatusBlock; 737 WCHAR TestDllPath[MAX_PATH]; 738 HANDLE FileHandle, DataSectionHandle, ImageSectionHandle; 739 PVOID DataBase, ImageBase; 740 SIZE_T ViewSize; 741 742 GetModuleFileNameW(NULL, TestDllPath, RTL_NUMBER_OF(TestDllPath)); 743 wcsrchr(TestDllPath, L'\\')[1] = UNICODE_NULL; 744 StringCbCatW(TestDllPath, sizeof(TestDllPath), L"testdata\\test.dll"); 745 if (!RtlDosPathNameToNtPathName_U(TestDllPath, 746 &FileName, 747 NULL, 748 NULL)) 749 { 750 ok(0, "RtlDosPathNameToNtPathName_U failed\n"); 751 return; 752 } 753 754 InitializeObjectAttributes(&FileObjectAttributes, 755 &FileName, 756 0, 757 NULL, 758 NULL); 759 760 Status = NtOpenFile(&FileHandle, 761 GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE, 762 &FileObjectAttributes, 763 &IoStatusBlock, 764 FILE_SHARE_READ, 765 FILE_SYNCHRONOUS_IO_NONALERT); 766 ok_ntstatus(Status, STATUS_SUCCESS); 767 if (!NT_SUCCESS(Status)) 768 { 769 skip("Failed to open file\n"); 770 return; 771 } 772 773 /* Create a data section with write access */ 774 Status = NtCreateSection(&DataSectionHandle, 775 SECTION_ALL_ACCESS, // DesiredAccess 776 NULL, // ObjectAttributes 777 NULL, // MaximumSize 778 PAGE_READWRITE, // SectionPageProtection 779 SEC_COMMIT, // AllocationAttributes 780 FileHandle); 781 ok_ntstatus(Status, STATUS_SUCCESS); 782 if (!NT_SUCCESS(Status)) 783 { 784 skip("Failed to create data section\n"); 785 NtClose(FileHandle); 786 return; 787 } 788 789 /* Map the data section as flat mapping */ 790 DataBase = NULL; 791 ViewSize = 0; 792 Status = NtMapViewOfSection(DataSectionHandle, 793 NtCurrentProcess(), 794 &DataBase, 795 0, 796 0, 797 NULL, 798 &ViewSize, 799 ViewShare, 800 0, 801 PAGE_READWRITE); 802 ok_ntstatus(Status, STATUS_SUCCESS); 803 //ok(ViewSize == 0x3f95cc48, "ViewSize wrong: 0x%lx\n"); 804 if (!NT_SUCCESS(Status)) 805 { 806 skip("Failed to map view of data section\n"); 807 NtClose(DataSectionHandle); 808 NtClose(FileHandle); 809 return; 810 } 811 812 /* Check the original data */ 813 ok(*(ULONG*)DataBase == 0x00905a4d, "Header not ok\n"); 814 815 /* Modify the PE header (but do not flush!) */ 816 *(ULONG*)DataBase = 0xdeadbabe; 817 ok(*(ULONG*)DataBase == 0xdeadbabe, "Header not ok\n"); 818 819 /* Modify data in the .data section (but do not flush!) */ 820 ok(*(ULONG*)((PUCHAR)DataBase + 0x800) == 0x12345678, 821 "Data in .data section invalid: 0x%lx!\n", *(ULONG*)((PUCHAR)DataBase + 0x800)); 822 *(ULONG*)((PUCHAR)DataBase + 0x800) = 0x87654321; 823 824 /* Now try to create an image section (should fail) */ 825 Status = NtCreateSection(&ImageSectionHandle, 826 SECTION_ALL_ACCESS, // DesiredAccess 827 NULL, // ObjectAttributes 828 NULL, // MaximumSize 829 PAGE_READWRITE, // SectionPageProtection 830 SEC_IMAGE, // AllocationAttributes 831 FileHandle); 832 ok_ntstatus(Status, STATUS_INVALID_IMAGE_NOT_MZ); 833 if (NT_SUCCESS(Status)) NtClose(ImageSectionHandle); 834 835 /* Restore the original header */ 836 *(ULONG*)DataBase = 0x00905a4d; 837 838 /* Modify data in the .data section (but do not flush!) */ 839 ok_hex(*(ULONG*)((PUCHAR)DataBase + 0x800), 0x87654321); 840 *(ULONG*)((PUCHAR)DataBase + 0x800) = 0xdeadbabe; 841 842 /* Try to create an image section again */ 843 Status = NtCreateSection(&ImageSectionHandle, 844 SECTION_ALL_ACCESS, // DesiredAccess 845 NULL, // ObjectAttributes 846 NULL, // MaximumSize 847 PAGE_READWRITE, // SectionPageProtection 848 SEC_IMAGE, // AllocationAttributes 849 FileHandle); 850 ok_ntstatus(Status, STATUS_SUCCESS); 851 if (!NT_SUCCESS(Status)) 852 { 853 skip("Failed to create image section\n"); 854 NtClose(DataSectionHandle); 855 NtClose(FileHandle); 856 return; 857 } 858 859 /* Map the image section */ 860 ImageBase = NULL; 861 ViewSize = 0; 862 Status = NtMapViewOfSection(ImageSectionHandle, 863 NtCurrentProcess(), 864 &ImageBase, 865 0, // ZeroBits 866 0, // CommitSize 867 NULL, // SectionOffset 868 &ViewSize, 869 ViewShare, 870 0, // AllocationType 871 PAGE_READONLY); 872 #ifdef _M_IX86 873 ok_ntstatus(Status, STATUS_SUCCESS); 874 #else 875 ok_ntstatus(Status, STATUS_IMAGE_MACHINE_TYPE_MISMATCH); 876 #endif 877 if (!NT_SUCCESS(Status)) 878 { 879 skip("Failed to map view of image section\n"); 880 NtClose(ImageSectionHandle); 881 NtClose(DataSectionHandle); 882 NtClose(FileHandle); 883 return; 884 } 885 886 /* Check the header */ 887 ok(*(ULONG*)DataBase == 0x00905a4d, "Header not ok\n"); 888 ok(*(ULONG*)ImageBase == 0x00905a4d, "Header not ok\n"); 889 890 /* Check the data section. Either of these can be present! */ 891 ok((*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x87654321) || 892 (*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x12345678), 893 "Wrong value in data section: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000)); 894 895 /* Now modify the data again */ 896 *(ULONG*)DataBase = 0xdeadbabe; 897 *(ULONG*)((PUCHAR)DataBase + 0x800) = 0xf00dada; 898 899 /* Check the data */ 900 ok(*(ULONG*)DataBase == 0xdeadbabe, "Header not ok\n"); 901 ok(*(ULONG*)ImageBase == 0x00905a4d, "Data should not be synced!\n"); 902 ok((*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x87654321) || 903 (*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x12345678), 904 "Wrong value in data section: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000)); 905 906 /* Flush the view */ 907 ViewSize = 0x1000; 908 Status = NtFlushVirtualMemory(NtCurrentProcess(), 909 &DataBase, 910 &ViewSize, 911 &IoStatusBlock); 912 ok_ntstatus(Status, STATUS_SUCCESS); 913 914 /* Check the data again */ 915 ok(*(ULONG*)ImageBase == 0x00905a4d, "Data should not be synced!\n"); 916 ok((*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x87654321) || 917 (*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x12345678), 918 "Wrong value in data section: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000)); 919 920 /* Restore the original header */ 921 *(ULONG*)DataBase = 0x00905a4d; 922 ok(*(ULONG*)DataBase == 0x00905a4d, "Header not ok\n"); 923 924 /* Close the image mapping */ 925 NtUnmapViewOfSection(NtCurrentProcess(), ImageBase); 926 NtClose(ImageSectionHandle); 927 928 /* Create an image section again */ 929 Status = NtCreateSection(&ImageSectionHandle, 930 SECTION_ALL_ACCESS, // DesiredAccess 931 NULL, // ObjectAttributes 932 NULL, // MaximumSize 933 PAGE_READWRITE, // SectionPageProtection 934 SEC_IMAGE, // AllocationAttributes 935 FileHandle); 936 ok_ntstatus(Status, STATUS_SUCCESS); 937 if (!NT_SUCCESS(Status)) 938 { 939 skip("Failed to create image section\n"); 940 NtClose(DataSectionHandle); 941 NtClose(FileHandle); 942 return; 943 } 944 945 /* Map the image section again */ 946 ImageBase = NULL; 947 ViewSize = 0; 948 Status = NtMapViewOfSection(ImageSectionHandle, 949 NtCurrentProcess(), 950 &ImageBase, 951 0, 952 0, 953 NULL, 954 &ViewSize, 955 ViewShare, 956 0, 957 PAGE_READONLY); 958 #ifdef _M_IX86 959 ok_ntstatus(Status, STATUS_SUCCESS); 960 #else 961 ok_ntstatus(Status, STATUS_IMAGE_MACHINE_TYPE_MISMATCH); 962 #endif 963 if (!NT_SUCCESS(Status)) 964 { 965 skip("Failed to map view of image section\n"); 966 NtClose(ImageSectionHandle); 967 NtClose(DataSectionHandle); 968 NtClose(FileHandle); 969 return; 970 } 971 972 // This one doesn't always work, needs investigation 973 /* Check the .data section again */ 974 //ok(*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0xf00dada, 975 // "Data should be synced: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000)); 976 977 /* Restore the original data */ 978 *(ULONG*)((PUCHAR)DataBase + 0x800) = 0x12345678; 979 980 /* Close the data mapping */ 981 NtUnmapViewOfSection(NtCurrentProcess(), DataBase); 982 983 NtClose(DataSectionHandle); 984 985 /* Try to allocate memory inside the image mapping */ 986 DataBase = (PUCHAR)ImageBase + 0x20000; 987 ViewSize = 0x1000; 988 Status = NtAllocateVirtualMemory(NtCurrentProcess(), &DataBase, 0, &ViewSize, MEM_RESERVE, PAGE_NOACCESS); 989 ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES); 990 991 /* Cleanup */ 992 NtClose(FileHandle); 993 NtClose(ImageSectionHandle); 994 NtUnmapViewOfSection(NtCurrentProcess(), ImageBase); 995 } 996 997 void 998 Test_ImageSection2(void) 999 { 1000 UNICODE_STRING FileName; 1001 NTSTATUS Status; 1002 OBJECT_ATTRIBUTES FileObjectAttributes; 1003 IO_STATUS_BLOCK IoStatusBlock; 1004 HANDLE FileHandle, ImageSectionHandle; 1005 PVOID ImageBase, BaseAddress; 1006 SIZE_T ViewSize; 1007 LARGE_INTEGER MaximumSize, SectionOffset; 1008 1009 if (!RtlDosPathNameToNtPathName_U(L"testdata\\nvoglv32.dll", 1010 &FileName, 1011 NULL, 1012 NULL)) 1013 { 1014 ok(0, "RtlDosPathNameToNtPathName_U failed\n"); 1015 return; 1016 } 1017 1018 InitializeObjectAttributes(&FileObjectAttributes, 1019 &FileName, 1020 0, 1021 NULL, 1022 NULL); 1023 1024 Status = NtOpenFile(&FileHandle, 1025 GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE, 1026 &FileObjectAttributes, 1027 &IoStatusBlock, 1028 FILE_SHARE_READ, 1029 FILE_SYNCHRONOUS_IO_NONALERT); 1030 ok_ntstatus(Status, STATUS_SUCCESS); 1031 printf("Opened file with handle %p\n", FileHandle); 1032 1033 /* Create a data section with write access */ 1034 MaximumSize.QuadPart = 0x20000; 1035 Status = NtCreateSection(&ImageSectionHandle, 1036 SECTION_ALL_ACCESS, // DesiredAccess 1037 NULL, // ObjectAttributes 1038 &MaximumSize, // MaximumSize 1039 PAGE_READWRITE, // SectionPageProtection 1040 SEC_IMAGE, // AllocationAttributes 1041 FileHandle); 1042 ok_ntstatus(Status, STATUS_SUCCESS); 1043 1044 printf("Created image section with handle %p\n", ImageSectionHandle); 1045 //system("PAUSE"); 1046 1047 /* Map the image section */ 1048 ImageBase = NULL; 1049 ViewSize = 0x0000; 1050 SectionOffset.QuadPart = 0x00000; 1051 Status = NtMapViewOfSection(ImageSectionHandle, 1052 NtCurrentProcess(), 1053 &ImageBase, 1054 0, 1055 0, 1056 &SectionOffset, 1057 &ViewSize, 1058 ViewShare, 1059 0, 1060 PAGE_READWRITE); 1061 ok_ntstatus(Status, STATUS_SUCCESS); 1062 1063 printf("Mapped image section at %p, value in text section: %lx\n", 1064 ImageBase, *((ULONG*)((PCHAR)ImageBase + 0x1196))); 1065 system("PAUSE"); 1066 1067 /* Try to allocate a page after the section */ 1068 BaseAddress = (PUCHAR)ImageBase + 0x10000; 1069 ViewSize = 0x1000; 1070 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 1071 &BaseAddress, 1072 0, 1073 &ViewSize, 1074 MEM_RESERVE | MEM_COMMIT, 1075 PAGE_READWRITE); 1076 printf("allocation status: %lx\n", Status); 1077 system("PAUSE"); 1078 1079 } 1080 1081 // doesn't work with WoW64! 1082 void 1083 Test_BasedSection(void) 1084 { 1085 NTSTATUS Status; 1086 HANDLE SectionHandle1, SectionHandle2; 1087 LARGE_INTEGER MaximumSize, SectionOffset; 1088 PVOID BaseAddress1, BaseAddress2; 1089 SIZE_T ViewSize; 1090 1091 /* Create a based section with SEC_COMMIT */ 1092 MaximumSize.QuadPart = 0x1000; 1093 Status = NtCreateSection(&SectionHandle1, 1094 SECTION_ALL_ACCESS, 1095 NULL, 1096 &MaximumSize, 1097 PAGE_READWRITE, 1098 SEC_COMMIT | SEC_BASED, 1099 NULL); 1100 ok_ntstatus(Status, STATUS_SUCCESS); 1101 1102 /* Map the 1st section */ 1103 BaseAddress1 = NULL; 1104 SectionOffset.QuadPart = 0; 1105 ViewSize = 0; 1106 Status = NtMapViewOfSection(SectionHandle1, 1107 NtCurrentProcess(), 1108 &BaseAddress1, 1109 0, 1110 0, 1111 &SectionOffset, 1112 &ViewSize, 1113 ViewShare, 1114 0, 1115 PAGE_READWRITE); 1116 #if 0 // WOW64? 1117 ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES); 1118 #else 1119 ok_ntstatus(Status, STATUS_SUCCESS); 1120 #endif 1121 1122 /* Create a 2nd based section with SEC_COMMIT */ 1123 MaximumSize.QuadPart = 0x1000; 1124 Status = NtCreateSection(&SectionHandle2, 1125 SECTION_ALL_ACCESS, 1126 NULL, 1127 &MaximumSize, 1128 PAGE_READWRITE, 1129 SEC_COMMIT | SEC_BASED, 1130 NULL); 1131 ok_ntstatus(Status, STATUS_SUCCESS);// 1132 1133 /* Map the 2nd section */ 1134 BaseAddress2 = NULL; 1135 SectionOffset.QuadPart = 0; 1136 ViewSize = 0; 1137 Status = NtMapViewOfSection(SectionHandle2, 1138 NtCurrentProcess(), 1139 &BaseAddress2, 1140 0, 1141 0, 1142 &SectionOffset, 1143 &ViewSize, 1144 ViewShare, 1145 0, 1146 PAGE_READWRITE); 1147 #if 0 // WOW64? 1148 ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES); 1149 #else 1150 ok_ntstatus(Status, STATUS_SUCCESS); 1151 ok((ULONG_PTR)BaseAddress2 < (ULONG_PTR)BaseAddress1, 1152 "Invalid addresses: BaseAddress1=%p, BaseAddress2=%p\n", BaseAddress1, BaseAddress2); 1153 ok(((ULONG_PTR)BaseAddress1 - (ULONG_PTR)BaseAddress2) == 0x10000, 1154 "Invalid addresses: BaseAddress1=%p, BaseAddress2=%p\n", BaseAddress1, BaseAddress2); 1155 #endif 1156 } 1157 1158 #define BYTES4(x) x, x, x, x 1159 #define BYTES8(x) BYTES4(x), BYTES4(x) 1160 #define BYTES16(x) BYTES8(x), BYTES8(x) 1161 #define BYTES32(x) BYTES16(x), BYTES16(x) 1162 #define BYTES64(x) BYTES32(x), BYTES32(x) 1163 #define BYTES128(x) BYTES64(x), BYTES64(x) 1164 #define BYTES256(x) BYTES128(x), BYTES128(x) 1165 #define BYTES512(x) BYTES256(x), BYTES256(x) 1166 #define BYTES1024(x) BYTES512(x), BYTES512(x) 1167 1168 static struct _MY_IMAGE_FILE 1169 { 1170 IMAGE_DOS_HEADER doshdr; 1171 WORD stub[32]; 1172 IMAGE_NT_HEADERS32 nthdrs; 1173 IMAGE_SECTION_HEADER text_header; 1174 IMAGE_SECTION_HEADER rossym_header; 1175 IMAGE_SECTION_HEADER rsrc_header; 1176 BYTE pad[16]; 1177 BYTE text_data[0x400]; 1178 BYTE rossym_data[0x400]; 1179 BYTE rsrc_data[0x400]; 1180 } ImageFile = 1181 { 1182 /* IMAGE_DOS_HEADER */ 1183 { 1184 IMAGE_DOS_SIGNATURE, 144, 3, 0, 4, 0, 0xFFFF, 0, 0xB8, 0, 0, 0, 0x40, 1185 0, { 0 }, 0, 0, { 0 }, 0x80 1186 }, 1187 /* binary to print "This program cannot be run in DOS mode." */ 1188 { 1189 0x1F0E, 0x0EBA, 0xB400, 0xCD09, 0xB821, 0x4C01, 0x21CD, 0x6854, 0x7369, 1190 0x7020, 0x6F72, 0x7267, 0x6D61, 0x6320, 0x6E61, 0x6F6E, 0x2074, 0x6562, 1191 0x7220, 0x6E75, 0x6920, 0x206E, 0x4F44, 0x2053, 0x6F6D, 0x6564, 0x0D2E, 1192 0x0A0D, 0x0024, 0x0000, 0x0000, 0x0000 1193 }, 1194 /* IMAGE_NT_HEADERS32 */ 1195 { 1196 IMAGE_NT_SIGNATURE, /* Signature */ 1197 /* IMAGE_FILE_HEADER */ 1198 { 1199 IMAGE_FILE_MACHINE_I386, /* Machine */ 1200 3, /* NumberOfSections */ 1201 0x47EFDF09, /* TimeDateStamp */ 1202 0, /* PointerToSymbolTable */ 1203 0, /* NumberOfSymbols */ 1204 0xE0, /* SizeOfOptionalHeader */ 1205 IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_LOCAL_SYMS_STRIPPED | 1206 IMAGE_FILE_LINE_NUMS_STRIPPED | IMAGE_FILE_EXECUTABLE_IMAGE | 1207 IMAGE_FILE_DLL, /* Characteristics */ 1208 }, 1209 /* IMAGE_OPTIONAL_HEADER32 */ 1210 { 1211 IMAGE_NT_OPTIONAL_HDR32_MAGIC, /* Magic */ 1212 8, /* MajorLinkerVersion */ 1213 0, /* MinorLinkerVersion */ 1214 0x400, /* SizeOfCode */ 1215 0x000, /* SizeOfInitializedData */ 1216 0, /* SizeOfUninitializedData */ 1217 0x2000, /* AddressOfEntryPoint */ 1218 0x2000, /* BaseOfCode */ 1219 0x0000, /* BaseOfData */ 1220 0x400000, /* ImageBase */ 1221 0x2000, /* SectionAlignment */ 1222 0x200, /* FileAlignment */ 1223 4, /* MajorOperatingSystemVersion */ 1224 0, /* MinorOperatingSystemVersion */ 1225 0, /* MajorImageVersion */ 1226 0, /* MinorImageVersion */ 1227 4, /* MajorSubsystemVersion */ 1228 0, /* MinorSubsystemVersion */ 1229 0, /* Win32VersionValue */ 1230 0x8000, /* SizeOfImage */ 1231 0x200, /* SizeOfHeaders */ 1232 0x0, /* CheckSum */ 1233 IMAGE_SUBSYSTEM_WINDOWS_CUI, /* Subsystem */ 1234 IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE | 1235 IMAGE_DLLCHARACTERISTICS_NO_SEH | 1236 IMAGE_DLLCHARACTERISTICS_NX_COMPAT, /* DllCharacteristics */ 1237 0x100000, /* SizeOfStackReserve */ 1238 0x1000, /* SizeOfStackCommit */ 1239 0x100000, /* SizeOfHeapReserve */ 1240 0x1000, /* SizeOfHeapCommit */ 1241 0, /* LoaderFlags */ 1242 0x10, /* NumberOfRvaAndSizes */ 1243 /* IMAGE_DATA_DIRECTORY */ 1244 { 1245 { 0 }, /* Export Table */ 1246 { 0 }, /* Import Table */ 1247 { 0 }, /* Resource Table */ 1248 { 0 }, /* Exception Table */ 1249 { 0 }, /* Certificate Table */ 1250 { 0 }, /* Base Relocation Table */ 1251 { 0 }, /* Debug */ 1252 { 0 }, /* Copyright */ 1253 { 0 }, /* Global Ptr */ 1254 { 0 }, /* TLS Table */ 1255 { 0 }, /* Load Config Table */ 1256 { 0 }, /* Bound Import */ 1257 { 0 }, /* IAT */ 1258 { 0 }, /* Delay Import Descriptor */ 1259 { 0 }, /* CLI Header */ 1260 { 0 } /* Reserved */ 1261 } 1262 } 1263 }, 1264 /* IMAGE_SECTION_HEADER */ 1265 { 1266 ".text", /* Name */ 1267 { 0x394 }, /* Misc.VirtualSize */ 1268 0x2000, /* VirtualAddress */ 1269 0x400, /* SizeOfRawData */ 1270 0x200, /* PointerToRawData */ 1271 0, /* PointerToRelocations */ 1272 0, /* PointerToLinenumbers */ 1273 0, /* NumberOfRelocations */ 1274 0, /* NumberOfLinenumbers */ 1275 IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE | 1276 IMAGE_SCN_CNT_CODE, /* Characteristics */ 1277 }, 1278 /* IMAGE_SECTION_HEADER */ 1279 { 1280 ".rossym", /* Name */ 1281 { 0x100 }, /* Misc.VirtualSize */ 1282 0x4000, /* VirtualAddress */ 1283 0x400, /* SizeOfRawData */ 1284 0x600, /* PointerToRawData */ 1285 0, /* PointerToRelocations */ 1286 0, /* PointerToLinenumbers */ 1287 0, /* NumberOfRelocations */ 1288 0, /* NumberOfLinenumbers */ 1289 IMAGE_SCN_MEM_READ | IMAGE_SCN_TYPE_NOLOAD, /* Characteristics */ 1290 }, 1291 /* IMAGE_SECTION_HEADER */ 1292 { 1293 ".rsrc", /* Name */ 1294 { 0x100 }, /* Misc.VirtualSize */ 1295 0x6000, /* VirtualAddress */ 1296 0x400, /* SizeOfRawData */ 1297 0xA00, /* PointerToRawData */ 1298 0, /* PointerToRelocations */ 1299 0, /* PointerToLinenumbers */ 1300 0, /* NumberOfRelocations */ 1301 0, /* NumberOfLinenumbers */ 1302 IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ, /* Characteristics */ 1303 }, 1304 /* fill */ 1305 { 0 }, 1306 /* text */ 1307 { 0xc3, 0 }, 1308 /* rossym */ 1309 { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 1310 BYTES8(0xaa), 1311 BYTES16(0xbb), 1312 BYTES32(0xcc), 1313 BYTES64(0xdd), 1314 BYTES64(0xee), 1315 BYTES64(0xff), 1316 }, 1317 /* rsrc */ 1318 { 0 }, 1319 }; 1320 1321 C_ASSERT(FIELD_OFFSET(struct _MY_IMAGE_FILE, text_data) == 0x200); 1322 C_ASSERT(FIELD_OFFSET(struct _MY_IMAGE_FILE, rossym_data) == 0x600); 1323 C_ASSERT(FIELD_OFFSET(struct _MY_IMAGE_FILE, rsrc_data) == 0xa00); 1324 1325 static 1326 void 1327 Test_NoLoadSection(BOOL Relocate) 1328 { 1329 NTSTATUS Status; 1330 WCHAR TempPath[MAX_PATH]; 1331 WCHAR FileName[MAX_PATH]; 1332 HANDLE Handle; 1333 HANDLE SectionHandle; 1334 LARGE_INTEGER SectionOffset; 1335 PVOID BaseAddress; 1336 SIZE_T ViewSize; 1337 ULONG Written; 1338 ULONG Length; 1339 BOOL Success; 1340 1341 Length = GetTempPathW(MAX_PATH, TempPath); 1342 ok(Length != 0, "GetTempPathW failed with %lu\n", GetLastError()); 1343 Length = GetTempFileNameW(TempPath, L"nta", 0, FileName); 1344 ok(Length != 0, "GetTempFileNameW failed with %lu\n", GetLastError()); 1345 Handle = CreateFileW(FileName, 1346 FILE_ALL_ACCESS, 1347 0, 1348 NULL, 1349 CREATE_ALWAYS, 1350 0, 1351 NULL); 1352 if (Handle == INVALID_HANDLE_VALUE) 1353 { 1354 skip("Failed to create temp file %ls, error %lu\n", FileName, GetLastError()); 1355 return; 1356 } 1357 if (Relocate) 1358 { 1359 ok((ULONG_PTR)GetModuleHandle(NULL) <= 0x80000000, "Module at %p\n", GetModuleHandle(NULL)); 1360 ImageFile.nthdrs.OptionalHeader.ImageBase = (ULONG)(ULONG_PTR)GetModuleHandle(NULL); 1361 } 1362 else 1363 { 1364 ImageFile.nthdrs.OptionalHeader.ImageBase = 0xe400000; 1365 } 1366 1367 Success = WriteFile(Handle, 1368 &ImageFile, 1369 sizeof(ImageFile), 1370 &Written, 1371 NULL); 1372 ok(Success == TRUE, "WriteFile failed with %lu\n", GetLastError()); 1373 ok(Written == sizeof(ImageFile), "WriteFile wrote %lu bytes\n", Written); 1374 1375 Status = NtCreateSection(&SectionHandle, 1376 SECTION_ALL_ACCESS, 1377 NULL, 1378 NULL, 1379 PAGE_EXECUTE_READWRITE, 1380 SEC_IMAGE, 1381 Handle); 1382 ok_ntstatus(Status, STATUS_SUCCESS); 1383 1384 if (NT_SUCCESS(Status)) 1385 { 1386 /* Map the section with */ 1387 BaseAddress = NULL; 1388 SectionOffset.QuadPart = 0; 1389 ViewSize = 0; 1390 Status = NtMapViewOfSection(SectionHandle, 1391 NtCurrentProcess(), 1392 &BaseAddress, 1393 0, 1394 0, 1395 &SectionOffset, 1396 &ViewSize, 1397 ViewShare, 1398 0, 1399 PAGE_READWRITE); 1400 if (Relocate) 1401 ok_ntstatus(Status, STATUS_IMAGE_NOT_AT_BASE); 1402 else 1403 ok_ntstatus(Status, STATUS_SUCCESS); 1404 if (NT_SUCCESS(Status)) 1405 { 1406 PUCHAR Bytes = BaseAddress; 1407 #define TEST_BYTE(n, v) StartSeh() ok_hex(Bytes[n], v); EndSeh(STATUS_SUCCESS); 1408 TEST_BYTE(0x2000, 0xc3); 1409 TEST_BYTE(0x2001, 0x00); 1410 TEST_BYTE(0x4000, 0x01); 1411 TEST_BYTE(0x4001, 0x23); 1412 TEST_BYTE(0x4007, 0xef); 1413 TEST_BYTE(0x4008, 0xaa); 1414 TEST_BYTE(0x4010, 0xbb); 1415 TEST_BYTE(0x4020, 0xcc); 1416 TEST_BYTE(0x4040, 0xdd); 1417 TEST_BYTE(0x4080, 0xee); 1418 TEST_BYTE(0x40c0, 0xff); 1419 TEST_BYTE(0x40ff, 0xff); 1420 TEST_BYTE(0x4100, 0x00); 1421 TEST_BYTE(0x41ff, 0x00); 1422 Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress); 1423 ok_ntstatus(Status, STATUS_SUCCESS); 1424 } 1425 Status = NtClose(SectionHandle); 1426 ok_ntstatus(Status, STATUS_SUCCESS); 1427 } 1428 1429 CloseHandle(Handle); 1430 DeleteFileW(FileName); 1431 } 1432 1433 static void 1434 Test_EmptyFile(VOID) 1435 { 1436 NTSTATUS Status; 1437 WCHAR TempPath[MAX_PATH]; 1438 WCHAR FileName[MAX_PATH]; 1439 HANDLE Handle; 1440 HANDLE SectionHandle; 1441 ULONG Length; 1442 1443 Length = GetTempPathW(MAX_PATH, TempPath); 1444 ok(Length != 0, "GetTempPathW failed with %lu\n", GetLastError()); 1445 Length = GetTempFileNameW(TempPath, L"nta", 0, FileName); 1446 ok(Length != 0, "GetTempFileNameW failed with %lu\n", GetLastError()); 1447 Handle = CreateFileW(FileName, 1448 FILE_ALL_ACCESS, 1449 0, 1450 NULL, 1451 CREATE_ALWAYS, 1452 0, 1453 NULL); 1454 if (Handle == INVALID_HANDLE_VALUE) 1455 { 1456 skip("Failed to create temp file %ls, error %lu\n", FileName, GetLastError()); 1457 return; 1458 } 1459 1460 Status = NtCreateSection(&SectionHandle, 1461 STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ, 1462 0, 0, PAGE_READONLY, SEC_COMMIT, Handle); 1463 ok_ntstatus(Status, STATUS_MAPPED_FILE_SIZE_ZERO); 1464 1465 if (NT_SUCCESS(Status)) 1466 NtClose(SectionHandle); 1467 1468 Status = NtCreateSection(&SectionHandle, 1469 STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ, 1470 0, 0, PAGE_READONLY, SEC_IMAGE, Handle); 1471 ok_ntstatus(Status, STATUS_INVALID_FILE_FOR_SECTION); 1472 1473 if (NT_SUCCESS(Status)) 1474 NtClose(SectionHandle); 1475 1476 CloseHandle(Handle); 1477 DeleteFileW(FileName); 1478 } 1479 1480 // CORE-11206 1481 static void 1482 Test_Truncate(VOID) 1483 { 1484 WCHAR TempPath[MAX_PATH]; 1485 WCHAR FileName[MAX_PATH]; 1486 NTSTATUS Status; 1487 SIZE_T ViewSize = 0; 1488 HANDLE Handle; 1489 HANDLE SectionHandle; 1490 1491 ULONG Length; 1492 BOOL Success; 1493 DWORD Written, Error; 1494 VOID* BaseAddress; 1495 1496 Length = GetTempPathW(MAX_PATH, TempPath); 1497 ok(Length != 0, "GetTempPathW failed with %lu\n", GetLastError()); 1498 Length = GetTempFileNameW(TempPath, L"nta", 0, FileName); 1499 ok(Length != 0, "GetTempFileNameW failed with %lu\n", GetLastError()); 1500 Handle = CreateFileW(FileName, FILE_ALL_ACCESS, 0, NULL, CREATE_ALWAYS, 0, NULL); 1501 1502 Success = WriteFile(Handle, "TESTDATA", 8, &Written, NULL); 1503 ok(Success == TRUE, "WriteFile failed with %lu\n", GetLastError()); 1504 ok(Written == 8, "WriteFile wrote %lu bytes\n", Written); 1505 1506 Written = SetFilePointer(Handle, 6, NULL, FILE_BEGIN); 1507 ok(Written == 6, "SetFilePointer returned %lu bytes\n", Written); 1508 Success = SetEndOfFile(Handle); 1509 ok(Success == TRUE, "SetEndOfFile failed with %lu\n", GetLastError()); 1510 1511 Status = NtCreateSection(&SectionHandle, 1512 STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ, 1513 0, 0, PAGE_READONLY, SEC_COMMIT, Handle); 1514 ok_ntstatus(Status, STATUS_SUCCESS); 1515 BaseAddress = NULL; 1516 ViewSize = 0; 1517 Status = NtMapViewOfSection(SectionHandle, NtCurrentProcess(), &BaseAddress, 0, 1518 0, 0, &ViewSize, ViewShare, 0, PAGE_READONLY); 1519 ok_ntstatus(Status, STATUS_SUCCESS); 1520 1521 if (BaseAddress) 1522 { 1523 // First we test data that was truncated even before the file mapping was opened 1524 Length = strlen((char*)BaseAddress); 1525 ok(Length == 6, "Old data was not properly erased! (Length=%lu)\n", Length); 1526 } 1527 1528 // Now we truncate the file on disk some more 1529 Written = SetFilePointer(Handle, 4, NULL, FILE_BEGIN); 1530 ok(Written == 4, "SetFilePointer returned %lu bytes\n", Written); 1531 Success = SetEndOfFile(Handle); 1532 Error = GetLastError(); 1533 ok(Success == FALSE, "SetEndOfFile succeeded\n"); 1534 ok(Error == ERROR_USER_MAPPED_FILE, "SetEndOfFile did not set error to ERROR_USER_MAPPED_FILE (%lu)\n", Error); 1535 1536 if (BaseAddress) 1537 { 1538 Length = strlen((char*)BaseAddress); 1539 ok(Length == 6, "Length should not have changed! (Length=%lu)\n", Length); 1540 } 1541 1542 // Unmap and set the end shorter. 1543 Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress); 1544 ok_ntstatus(Status, STATUS_SUCCESS); 1545 Success = CloseHandle(SectionHandle); 1546 ok(Success == TRUE, "CloseHandle failed with %lu\n", GetLastError()); 1547 1548 Written = SetFilePointer(Handle, 4, NULL, FILE_BEGIN); 1549 ok(Written == 4, "SetFilePointer returned %lu bytes\n", Written); 1550 Success = SetEndOfFile(Handle); 1551 ok(Success == TRUE, "SetEndOfFile failed with %lu\n", GetLastError()); 1552 1553 Status = NtCreateSection(&SectionHandle, 1554 STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ, 1555 0, 0, PAGE_READONLY, SEC_COMMIT, Handle); 1556 ok_ntstatus(Status, STATUS_SUCCESS); 1557 BaseAddress = NULL; 1558 ViewSize = 0; 1559 Status = NtMapViewOfSection(SectionHandle, NtCurrentProcess(), &BaseAddress, 0, 1560 0, 0, &ViewSize, ViewShare, 0, PAGE_READONLY); 1561 ok_ntstatus(Status, STATUS_SUCCESS); 1562 1563 // CLEANUP 1564 Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress); 1565 ok_ntstatus(Status, STATUS_SUCCESS); 1566 Success = CloseHandle(SectionHandle); 1567 ok(Success == TRUE, "CloseHandle failed with %lu\n", GetLastError()); 1568 Success = CloseHandle(Handle); 1569 ok(Success == TRUE, "CloseHandle failed with %lu\n", GetLastError()); 1570 1571 Success = DeleteFileW(FileName); 1572 ok(Success == TRUE, "DeleteFileW failed with %lu\n", GetLastError()); 1573 } 1574 1575 START_TEST(NtMapViewOfSection) 1576 { 1577 Test_PageFileSection(); 1578 Test_ImageSection(); 1579 Test_BasedSection(); 1580 Test_NoLoadSection(FALSE); 1581 Test_NoLoadSection(TRUE); 1582 Test_EmptyFile(); 1583 Test_Truncate(); 1584 } 1585