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 IMAGE_SECTION_HEADER clc_header; 1177 BYTE pad[488]; 1178 BYTE text_data[0x400]; 1179 BYTE rossym_data[0x400]; 1180 BYTE rsrc_data[0x400]; 1181 BYTE clc_data[0x1000]; 1182 } ImageFile = 1183 { 1184 /* IMAGE_DOS_HEADER */ 1185 { 1186 IMAGE_DOS_SIGNATURE, 144, 3, 0, 4, 0, 0xFFFF, 0, 0xB8, 0, 0, 0, 0x40, 1187 0, { 0 }, 0, 0, { 0 }, 0x80 1188 }, 1189 /* binary to print "This program cannot be run in DOS mode." */ 1190 { 1191 0x1F0E, 0x0EBA, 0xB400, 0xCD09, 0xB821, 0x4C01, 0x21CD, 0x6854, 0x7369, 1192 0x7020, 0x6F72, 0x7267, 0x6D61, 0x6320, 0x6E61, 0x6F6E, 0x2074, 0x6562, 1193 0x7220, 0x6E75, 0x6920, 0x206E, 0x4F44, 0x2053, 0x6F6D, 0x6564, 0x0D2E, 1194 0x0A0D, 0x0024, 0x0000, 0x0000, 0x0000 1195 }, 1196 /* IMAGE_NT_HEADERS32 */ 1197 { 1198 IMAGE_NT_SIGNATURE, /* Signature */ 1199 /* IMAGE_FILE_HEADER */ 1200 { 1201 IMAGE_FILE_MACHINE_I386, /* Machine */ 1202 4, /* NumberOfSections */ 1203 0x47EFDF09, /* TimeDateStamp */ 1204 0, /* PointerToSymbolTable */ 1205 0, /* NumberOfSymbols */ 1206 0xE0, /* SizeOfOptionalHeader */ 1207 IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_LOCAL_SYMS_STRIPPED | 1208 IMAGE_FILE_LINE_NUMS_STRIPPED | IMAGE_FILE_EXECUTABLE_IMAGE | 1209 IMAGE_FILE_DLL, /* Characteristics */ 1210 }, 1211 /* IMAGE_OPTIONAL_HEADER32 */ 1212 { 1213 IMAGE_NT_OPTIONAL_HDR32_MAGIC, /* Magic */ 1214 8, /* MajorLinkerVersion */ 1215 0, /* MinorLinkerVersion */ 1216 0x400, /* SizeOfCode */ 1217 0x000, /* SizeOfInitializedData */ 1218 0, /* SizeOfUninitializedData */ 1219 0x2000, /* AddressOfEntryPoint */ 1220 0x2000, /* BaseOfCode */ 1221 0x0000, /* BaseOfData */ 1222 0x400000, /* ImageBase */ 1223 0x2000, /* SectionAlignment */ 1224 0x200, /* FileAlignment */ 1225 4, /* MajorOperatingSystemVersion */ 1226 0, /* MinorOperatingSystemVersion */ 1227 0, /* MajorImageVersion */ 1228 0, /* MinorImageVersion */ 1229 4, /* MajorSubsystemVersion */ 1230 0, /* MinorSubsystemVersion */ 1231 0, /* Win32VersionValue */ 1232 0xa000, /* SizeOfImage */ 1233 0x400, /* SizeOfHeaders */ 1234 0x0, /* CheckSum */ 1235 IMAGE_SUBSYSTEM_WINDOWS_CUI, /* Subsystem */ 1236 IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE | 1237 IMAGE_DLLCHARACTERISTICS_NO_SEH | 1238 IMAGE_DLLCHARACTERISTICS_NX_COMPAT, /* DllCharacteristics */ 1239 0x100000, /* SizeOfStackReserve */ 1240 0x1000, /* SizeOfStackCommit */ 1241 0x100000, /* SizeOfHeapReserve */ 1242 0x1000, /* SizeOfHeapCommit */ 1243 0, /* LoaderFlags */ 1244 0x10, /* NumberOfRvaAndSizes */ 1245 /* IMAGE_DATA_DIRECTORY */ 1246 { 1247 { 0 }, /* Export Table */ 1248 { 0 }, /* Import Table */ 1249 { 0 }, /* Resource Table */ 1250 { 0 }, /* Exception Table */ 1251 { 0 }, /* Certificate Table */ 1252 { 0 }, /* Base Relocation Table */ 1253 { 0 }, /* Debug */ 1254 { 0 }, /* Copyright */ 1255 { 0 }, /* Global Ptr */ 1256 { 0 }, /* TLS Table */ 1257 { 0 }, /* Load Config Table */ 1258 { 0 }, /* Bound Import */ 1259 { 0 }, /* IAT */ 1260 { 0 }, /* Delay Import Descriptor */ 1261 { 0 }, /* CLI Header */ 1262 { 0 } /* Reserved */ 1263 } 1264 } 1265 }, 1266 /* IMAGE_SECTION_HEADER */ 1267 { 1268 ".text", /* Name */ 1269 { 0x394 }, /* Misc.VirtualSize */ 1270 0x2000, /* VirtualAddress */ 1271 0x400, /* SizeOfRawData */ 1272 0x400, /* PointerToRawData */ 1273 0, /* PointerToRelocations */ 1274 0, /* PointerToLinenumbers */ 1275 0, /* NumberOfRelocations */ 1276 0, /* NumberOfLinenumbers */ 1277 IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE | 1278 IMAGE_SCN_CNT_CODE, /* Characteristics */ 1279 }, 1280 /* IMAGE_SECTION_HEADER */ 1281 { 1282 ".rossym", /* Name */ 1283 { 0x100 }, /* Misc.VirtualSize */ 1284 0x4000, /* VirtualAddress */ 1285 0x400, /* SizeOfRawData */ 1286 0x800, /* PointerToRawData */ 1287 0, /* PointerToRelocations */ 1288 0, /* PointerToLinenumbers */ 1289 0, /* NumberOfRelocations */ 1290 0, /* NumberOfLinenumbers */ 1291 /* CORE-8384 */ 1292 IMAGE_SCN_MEM_READ | IMAGE_SCN_TYPE_NOLOAD, /* Characteristics */ 1293 }, 1294 /* IMAGE_SECTION_HEADER */ 1295 { 1296 ".rsrc", /* Name */ 1297 { 0x100 }, /* Misc.VirtualSize */ 1298 0x6000, /* VirtualAddress */ 1299 0x400, /* SizeOfRawData */ 1300 0xC00, /* PointerToRawData */ 1301 0, /* PointerToRelocations */ 1302 0, /* PointerToLinenumbers */ 1303 0, /* NumberOfRelocations */ 1304 0, /* NumberOfLinenumbers */ 1305 IMAGE_SCN_MEM_READ | 1306 IMAGE_SCN_CNT_INITIALIZED_DATA, /* Characteristics */ 1307 }, 1308 /* IMAGE_SECTION_HEADER */ 1309 { 1310 ".clc", /* Name */ 1311 { 0x2000 }, /* Misc.VirtualSize */ 1312 0x8000, /* VirtualAddress */ 1313 0x1000, /* SizeOfRawData */ 1314 0x1000, /* PointerToRawData */ 1315 0, /* PointerToRelocations */ 1316 0, /* PointerToLinenumbers */ 1317 0, /* NumberOfRelocations */ 1318 0, /* NumberOfLinenumbers */ 1319 /* CORE-12582 */ 1320 IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE | 1321 IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_CNT_CODE, /* Characteristics */ 1322 }, 1323 /* fill */ 1324 { 0 }, 1325 /* text */ 1326 { 0xc3, 0 }, 1327 /* rossym */ 1328 { 1329 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 1330 BYTES8(0xaa), 1331 BYTES16(0xbb), 1332 BYTES32(0xcc), 1333 BYTES64(0xdd), 1334 BYTES64(0xee), 1335 BYTES64(0xff), 1336 }, 1337 /* rsrc */ 1338 { 1339 BYTES128(0xee), 1340 BYTES128(0x55), 1341 BYTES128(0xee), 1342 BYTES128(0x11), 1343 BYTES128(0xff), 1344 BYTES128(0x00), 1345 BYTES128(0x00), 1346 BYTES128(0xdd), 1347 }, 1348 /* clc */ 1349 { 1350 BYTES512(0x11), 1351 BYTES512(0x22), 1352 BYTES512(0x33), 1353 BYTES512(0x44), 1354 BYTES512(0x55), 1355 BYTES512(0x66), 1356 BYTES512(0x77), 1357 BYTES512(0x88), 1358 }, 1359 }; 1360 1361 C_ASSERT(FIELD_OFFSET(struct _MY_IMAGE_FILE, text_data) == 0x400); 1362 C_ASSERT(FIELD_OFFSET(struct _MY_IMAGE_FILE, rossym_data) == 0x800); 1363 C_ASSERT(FIELD_OFFSET(struct _MY_IMAGE_FILE, rsrc_data) == 0xc00); 1364 C_ASSERT(FIELD_OFFSET(struct _MY_IMAGE_FILE, clc_data) == 0x1000); 1365 1366 static 1367 void 1368 Test_SectionContents(BOOL Relocate) 1369 { 1370 NTSTATUS Status; 1371 WCHAR TempPath[MAX_PATH]; 1372 WCHAR FileName[MAX_PATH]; 1373 HANDLE Handle; 1374 HANDLE SectionHandle; 1375 LARGE_INTEGER SectionOffset; 1376 PVOID BaseAddress; 1377 SIZE_T ViewSize; 1378 ULONG Written; 1379 ULONG Length; 1380 BOOL Success; 1381 1382 Length = GetTempPathW(MAX_PATH, TempPath); 1383 ok(Length != 0, "GetTempPathW failed with %lu\n", GetLastError()); 1384 Length = GetTempFileNameW(TempPath, L"nta", 0, FileName); 1385 ok(Length != 0, "GetTempFileNameW failed with %lu\n", GetLastError()); 1386 Handle = CreateFileW(FileName, 1387 FILE_ALL_ACCESS, 1388 0, 1389 NULL, 1390 CREATE_ALWAYS, 1391 0, 1392 NULL); 1393 if (Handle == INVALID_HANDLE_VALUE) 1394 { 1395 skip("Failed to create temp file %ls, error %lu\n", FileName, GetLastError()); 1396 return; 1397 } 1398 if (Relocate) 1399 { 1400 ok((ULONG_PTR)GetModuleHandle(NULL) <= 0x80000000, "Module at %p\n", GetModuleHandle(NULL)); 1401 ImageFile.nthdrs.OptionalHeader.ImageBase = (ULONG)(ULONG_PTR)GetModuleHandle(NULL); 1402 } 1403 else 1404 { 1405 ImageFile.nthdrs.OptionalHeader.ImageBase = 0xe400000; 1406 } 1407 1408 Success = WriteFile(Handle, 1409 &ImageFile, 1410 sizeof(ImageFile), 1411 &Written, 1412 NULL); 1413 ok(Success == TRUE, "WriteFile failed with %lu\n", GetLastError()); 1414 ok(Written == sizeof(ImageFile), "WriteFile wrote %lu bytes\n", Written); 1415 1416 Status = NtCreateSection(&SectionHandle, 1417 SECTION_ALL_ACCESS, 1418 NULL, 1419 NULL, 1420 PAGE_EXECUTE_READWRITE, 1421 SEC_IMAGE, 1422 Handle); 1423 ok_ntstatus(Status, STATUS_SUCCESS); 1424 1425 if (NT_SUCCESS(Status)) 1426 { 1427 /* Map the section with */ 1428 BaseAddress = NULL; 1429 SectionOffset.QuadPart = 0; 1430 ViewSize = 0; 1431 Status = NtMapViewOfSection(SectionHandle, 1432 NtCurrentProcess(), 1433 &BaseAddress, 1434 0, 1435 0, 1436 &SectionOffset, 1437 &ViewSize, 1438 ViewShare, 1439 0, 1440 PAGE_READWRITE); 1441 if (Relocate) 1442 ok_ntstatus(Status, STATUS_IMAGE_NOT_AT_BASE); 1443 else 1444 ok_ntstatus(Status, STATUS_SUCCESS); 1445 if (NT_SUCCESS(Status)) 1446 { 1447 PUCHAR Bytes = BaseAddress; 1448 #define TEST_BYTE(n, v) StartSeh() ok_hex(Bytes[n], v); EndSeh(STATUS_SUCCESS); 1449 #define TEST_WRITE(n) StartSeh() *(volatile UCHAR *)&Bytes[n] = Bytes[n]; EndSeh(STATUS_SUCCESS); 1450 #define TEST_NOWRITE(n) StartSeh() *(volatile UCHAR *)&Bytes[n] = Bytes[n]; EndSeh(STATUS_ACCESS_VIOLATION); 1451 TEST_NOWRITE(0x2000); 1452 TEST_BYTE(0x2000, 0xc3); 1453 TEST_BYTE(0x2001, 0x00); 1454 TEST_NOWRITE(0x4000); 1455 TEST_BYTE(0x4000, 0x01); 1456 TEST_BYTE(0x4001, 0x23); 1457 TEST_BYTE(0x4007, 0xef); 1458 TEST_BYTE(0x4008, 0xaa); 1459 TEST_BYTE(0x4010, 0xbb); 1460 TEST_BYTE(0x4020, 0xcc); 1461 TEST_BYTE(0x4040, 0xdd); 1462 TEST_BYTE(0x4080, 0xee); 1463 TEST_BYTE(0x40c0, 0xff); 1464 TEST_BYTE(0x40ff, 0xff); 1465 TEST_BYTE(0x4100, 0x00); 1466 TEST_BYTE(0x41ff, 0x00); 1467 TEST_NOWRITE(0x6000); 1468 TEST_BYTE(0x6000, 0xee); 1469 TEST_BYTE(0x60ff, 0x55); 1470 TEST_BYTE(0x6100, 0xee); 1471 TEST_BYTE(0x63ff, 0xdd); 1472 TEST_BYTE(0x6400, 0x00); 1473 TEST_WRITE(0x8000); 1474 TEST_BYTE(0x8000, 0x11); 1475 TEST_BYTE(0x8400, 0x33); 1476 Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress); 1477 ok_ntstatus(Status, STATUS_SUCCESS); 1478 } 1479 Status = NtClose(SectionHandle); 1480 ok_ntstatus(Status, STATUS_SUCCESS); 1481 } 1482 1483 CloseHandle(Handle); 1484 DeleteFileW(FileName); 1485 } 1486 1487 static void 1488 Test_EmptyFile(VOID) 1489 { 1490 NTSTATUS Status; 1491 WCHAR TempPath[MAX_PATH]; 1492 WCHAR FileName[MAX_PATH]; 1493 HANDLE Handle; 1494 HANDLE SectionHandle; 1495 ULONG Length; 1496 1497 Length = GetTempPathW(MAX_PATH, TempPath); 1498 ok(Length != 0, "GetTempPathW failed with %lu\n", GetLastError()); 1499 Length = GetTempFileNameW(TempPath, L"nta", 0, FileName); 1500 ok(Length != 0, "GetTempFileNameW failed with %lu\n", GetLastError()); 1501 Handle = CreateFileW(FileName, 1502 FILE_ALL_ACCESS, 1503 0, 1504 NULL, 1505 CREATE_ALWAYS, 1506 0, 1507 NULL); 1508 if (Handle == INVALID_HANDLE_VALUE) 1509 { 1510 skip("Failed to create temp file %ls, error %lu\n", FileName, GetLastError()); 1511 return; 1512 } 1513 1514 Status = NtCreateSection(&SectionHandle, 1515 STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ, 1516 0, 0, PAGE_READONLY, SEC_COMMIT, Handle); 1517 ok_ntstatus(Status, STATUS_MAPPED_FILE_SIZE_ZERO); 1518 1519 if (NT_SUCCESS(Status)) 1520 NtClose(SectionHandle); 1521 1522 Status = NtCreateSection(&SectionHandle, 1523 STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ, 1524 0, 0, PAGE_READONLY, SEC_IMAGE, Handle); 1525 ok_ntstatus(Status, STATUS_INVALID_FILE_FOR_SECTION); 1526 1527 if (NT_SUCCESS(Status)) 1528 NtClose(SectionHandle); 1529 1530 CloseHandle(Handle); 1531 DeleteFileW(FileName); 1532 } 1533 1534 // CORE-11206 1535 static void 1536 Test_Truncate(VOID) 1537 { 1538 WCHAR TempPath[MAX_PATH]; 1539 WCHAR FileName[MAX_PATH]; 1540 NTSTATUS Status; 1541 SIZE_T ViewSize = 0; 1542 HANDLE Handle; 1543 HANDLE SectionHandle; 1544 1545 ULONG Length; 1546 BOOL Success; 1547 DWORD Written, Error; 1548 VOID* BaseAddress; 1549 1550 Length = GetTempPathW(MAX_PATH, TempPath); 1551 ok(Length != 0, "GetTempPathW failed with %lu\n", GetLastError()); 1552 Length = GetTempFileNameW(TempPath, L"nta", 0, FileName); 1553 ok(Length != 0, "GetTempFileNameW failed with %lu\n", GetLastError()); 1554 Handle = CreateFileW(FileName, FILE_ALL_ACCESS, 0, NULL, CREATE_ALWAYS, 0, NULL); 1555 1556 Success = WriteFile(Handle, "TESTDATA", 8, &Written, NULL); 1557 ok(Success == TRUE, "WriteFile failed with %lu\n", GetLastError()); 1558 ok(Written == 8, "WriteFile wrote %lu bytes\n", Written); 1559 1560 Written = SetFilePointer(Handle, 6, NULL, FILE_BEGIN); 1561 ok(Written == 6, "SetFilePointer returned %lu bytes\n", Written); 1562 Success = SetEndOfFile(Handle); 1563 ok(Success == TRUE, "SetEndOfFile failed with %lu\n", GetLastError()); 1564 1565 Status = NtCreateSection(&SectionHandle, 1566 STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ, 1567 0, 0, PAGE_READONLY, SEC_COMMIT, Handle); 1568 ok_ntstatus(Status, STATUS_SUCCESS); 1569 BaseAddress = NULL; 1570 ViewSize = 0; 1571 Status = NtMapViewOfSection(SectionHandle, NtCurrentProcess(), &BaseAddress, 0, 1572 0, 0, &ViewSize, ViewShare, 0, PAGE_READONLY); 1573 ok_ntstatus(Status, STATUS_SUCCESS); 1574 1575 if (BaseAddress) 1576 { 1577 // First we test data that was truncated even before the file mapping was opened 1578 Length = strlen((char*)BaseAddress); 1579 ok(Length == 6, "Old data was not properly erased! (Length=%lu)\n", Length); 1580 } 1581 1582 // Now we truncate the file on disk some more 1583 Written = SetFilePointer(Handle, 4, NULL, FILE_BEGIN); 1584 ok(Written == 4, "SetFilePointer returned %lu bytes\n", Written); 1585 Success = SetEndOfFile(Handle); 1586 Error = GetLastError(); 1587 ok(Success == FALSE, "SetEndOfFile succeeded\n"); 1588 ok(Error == ERROR_USER_MAPPED_FILE, "SetEndOfFile did not set error to ERROR_USER_MAPPED_FILE (%lu)\n", Error); 1589 1590 if (BaseAddress) 1591 { 1592 Length = strlen((char*)BaseAddress); 1593 ok(Length == 6, "Length should not have changed! (Length=%lu)\n", Length); 1594 } 1595 1596 // Unmap and set the end shorter. 1597 Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress); 1598 ok_ntstatus(Status, STATUS_SUCCESS); 1599 Success = CloseHandle(SectionHandle); 1600 ok(Success == TRUE, "CloseHandle failed with %lu\n", GetLastError()); 1601 1602 Written = SetFilePointer(Handle, 4, NULL, FILE_BEGIN); 1603 ok(Written == 4, "SetFilePointer returned %lu bytes\n", Written); 1604 Success = SetEndOfFile(Handle); 1605 ok(Success == TRUE, "SetEndOfFile failed with %lu\n", GetLastError()); 1606 1607 Status = NtCreateSection(&SectionHandle, 1608 STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ, 1609 0, 0, PAGE_READONLY, SEC_COMMIT, Handle); 1610 ok_ntstatus(Status, STATUS_SUCCESS); 1611 BaseAddress = NULL; 1612 ViewSize = 0; 1613 Status = NtMapViewOfSection(SectionHandle, NtCurrentProcess(), &BaseAddress, 0, 1614 0, 0, &ViewSize, ViewShare, 0, PAGE_READONLY); 1615 ok_ntstatus(Status, STATUS_SUCCESS); 1616 1617 // CLEANUP 1618 Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress); 1619 ok_ntstatus(Status, STATUS_SUCCESS); 1620 Success = CloseHandle(SectionHandle); 1621 ok(Success == TRUE, "CloseHandle failed with %lu\n", GetLastError()); 1622 Success = CloseHandle(Handle); 1623 ok(Success == TRUE, "CloseHandle failed with %lu\n", GetLastError()); 1624 1625 Success = DeleteFileW(FileName); 1626 ok(Success == TRUE, "DeleteFileW failed with %lu\n", GetLastError()); 1627 } 1628 1629 START_TEST(NtMapViewOfSection) 1630 { 1631 Test_PageFileSection(); 1632 Test_ImageSection(); 1633 Test_BasedSection(); 1634 Test_SectionContents(FALSE); 1635 Test_SectionContents(TRUE); 1636 Test_EmptyFile(); 1637 Test_Truncate(); 1638 } 1639