1 /* 2 * PROJECT: ReactOS API Tests 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: Test for NtAllocateVirtualMemory 5 * COPYRIGHT: Copyright 2011 Thomas Faber <thomas.faber@reactos.org> 6 * Copyright 2013 Timo Kreuzer <timo.kreuzer@reactos.org> 7 * Copyright 2015 J�r�me Gardou <jerome.gardou@reactos.org> 8 * Copyright 2018 Serge Gautherie <reactos-git_serge_171003@gautherie.fr> 9 */ 10 11 #include "precomp.h" 12 13 #include <pseh/pseh2.h> 14 15 static PVOID Allocations[4096] = { NULL }; 16 static ULONG CurrentAllocation = 0; 17 18 static 19 VOID 20 ValidateAllocations(VOID) 21 { 22 ULONG i; 23 24 ASSERT(CurrentAllocation < sizeof(Allocations) / sizeof(Allocations[0])); 25 for (i = 0; i < CurrentAllocation; ++i) 26 { 27 PUCHAR UserBuffer = Allocations[i]; 28 SIZE_T AllocationSize; 29 SIZE_T DataSize; 30 31 if (UserBuffer == NULL) 32 continue; 33 34 AllocationSize = ((PSIZE_T)UserBuffer)[-2]; 35 DataSize = ((PSIZE_T)UserBuffer)[-1]; 36 ASSERT(AllocationSize != 0); 37 ASSERT(AllocationSize % PAGE_SIZE == 0); 38 ASSERT(DataSize != 0); 39 ASSERT(((SIZE_T)UserBuffer + DataSize) % PAGE_SIZE == 0); 40 } 41 } 42 43 static 44 PVOID 45 Allocate( 46 SIZE_T DataSize) 47 { 48 NTSTATUS Status; 49 PVOID AllocationStart = NULL; 50 SIZE_T AllocationSize = PAGE_ROUND_UP(DataSize + PAGE_SIZE + 2 * sizeof(SIZE_T)); 51 PVOID FirstPageStart; 52 SIZE_T NumberOfPages = AllocationSize / PAGE_SIZE; 53 SIZE_T Size; 54 PUCHAR UserBuffer; 55 56 Status = NtAllocateVirtualMemory(NtCurrentProcess(), &AllocationStart, 0, &AllocationSize, MEM_RESERVE, PAGE_NOACCESS); 57 58 if (!NT_SUCCESS(Status)) 59 return NULL; 60 61 FirstPageStart = (PUCHAR)AllocationStart + AllocationSize - PAGE_SIZE * NumberOfPages; 62 Size = (NumberOfPages - 1) * PAGE_SIZE; 63 Status = NtAllocateVirtualMemory(NtCurrentProcess(), &FirstPageStart, 0, &Size, MEM_COMMIT, PAGE_READWRITE); 64 if (!NT_SUCCESS(Status)) 65 { 66 AllocationSize = 0; 67 Status = NtFreeVirtualMemory(NtCurrentProcess(), &AllocationStart, &AllocationSize, MEM_RELEASE); 68 ASSERT(Status == STATUS_SUCCESS); 69 return NULL; 70 } 71 ASSERT(Size % sizeof(ULONG) == 0); 72 ASSERT(RtlCompareMemoryUlong(FirstPageStart, Size, 0) == Size); 73 74 UserBuffer = AllocationStart; 75 UserBuffer += AllocationSize - PAGE_SIZE - DataSize; 76 RtlFillMemory(FirstPageStart, UserBuffer - (PUCHAR)FirstPageStart, 0xae); 77 RtlZeroMemory(UserBuffer, DataSize); 78 ((PSIZE_T)UserBuffer)[-2] = AllocationSize; 79 ((PSIZE_T)UserBuffer)[-1] = DataSize; 80 81 Allocations[CurrentAllocation++] = UserBuffer; 82 ValidateAllocations(); 83 return UserBuffer; 84 } 85 86 static 87 VOID 88 Free( 89 PVOID UserBuffer) 90 { 91 NTSTATUS Status; 92 PVOID AllocationStart; 93 SIZE_T Zero = 0; 94 SIZE_T AllocationSize; 95 SIZE_T DataSize; 96 ULONG i; 97 98 AllocationSize = ((PSIZE_T)UserBuffer)[-2]; 99 DataSize = ((PSIZE_T)UserBuffer)[-1]; 100 ASSERT(DataSize != 0); 101 102 AllocationStart = (PUCHAR)UserBuffer + DataSize + PAGE_SIZE - AllocationSize; 103 ASSERT((SIZE_T)AllocationStart % PAGE_SIZE == 0); 104 105 RtlFillMemory(UserBuffer, DataSize, 0xbe); 106 ((PSIZE_T)UserBuffer)[-1] = 0; 107 ((PSIZE_T)UserBuffer)[-2] = 0xFAFBFCFD; 108 109 for (i = 0; i < CurrentAllocation; ++i) 110 if (Allocations[i] == UserBuffer) 111 { 112 Allocations[i] = NULL; 113 break; 114 } 115 ValidateAllocations(); 116 117 Status = NtFreeVirtualMemory(NtCurrentProcess(), &AllocationStart, &Zero, MEM_RELEASE); 118 ASSERT(Status == STATUS_SUCCESS); 119 } 120 121 static 122 PVOID 123 ReAllocate( 124 PVOID OldUserBuffer, 125 SIZE_T NewDataSize) 126 { 127 PVOID NewUserBuffer; 128 SIZE_T OldDataSize; 129 130 OldDataSize = ((PSIZE_T)OldUserBuffer)[-1]; 131 ASSERT(OldDataSize != 0); 132 133 NewUserBuffer = Allocate(NewDataSize); 134 ASSERT(((PSIZE_T)OldUserBuffer)[-1] == OldDataSize); 135 RtlCopyMemory(NewUserBuffer, OldUserBuffer, min(OldDataSize, NewDataSize)); 136 ASSERT(((PSIZE_T)OldUserBuffer)[-1] == OldDataSize); 137 Free(OldUserBuffer); 138 return NewUserBuffer; 139 } 140 141 static 142 VOID 143 AccessMemory1( 144 PVOID UserBuffer, 145 SIZE_T DataSize) 146 { 147 PBYTE Buffer = UserBuffer; 148 SIZE_T i; 149 150 for (i = 0; i < DataSize; ++i) 151 Buffer[i] = LOBYTE(i); 152 } 153 154 static 155 BOOLEAN 156 CheckMemory1( 157 PVOID UserBuffer, 158 SIZE_T DataSize) 159 { 160 PBYTE Buffer = UserBuffer; 161 SIZE_T i; 162 163 for (i = 0; i < DataSize; ++i) 164 if (Buffer[i] != LOBYTE(i)) 165 { 166 trace("Mismatch in region %p at index %lu. Value=%02x\n", UserBuffer, (ULONG)i, Buffer[i]); 167 ASSERT(FALSE); 168 return FALSE; 169 } 170 return TRUE; 171 } 172 173 static 174 VOID 175 AccessMemory2( 176 PVOID UserBuffer, 177 SIZE_T DataSize) 178 { 179 PBYTE Buffer = UserBuffer; 180 SIZE_T i; 181 182 for (i = 0; i < DataSize; ++i) 183 Buffer[i] = UCHAR_MAX - LOBYTE(i); 184 } 185 186 static 187 BOOLEAN 188 CheckMemory2( 189 PVOID UserBuffer, 190 SIZE_T DataSize) 191 { 192 PBYTE Buffer = UserBuffer; 193 SIZE_T i; 194 195 for (i = 0; i < DataSize; ++i) 196 if (Buffer[i] != UCHAR_MAX - LOBYTE(i)) 197 { 198 trace("Mismatch in region %p at index %lu. Value=%02x\n", UserBuffer, (ULONG)i, Buffer[i]); 199 ASSERT(FALSE); 200 return FALSE; 201 } 202 return TRUE; 203 } 204 205 VOID 206 CheckSize(ULONG_PTR Base, SIZE_T InSize, SIZE_T ExpectedSize) 207 { 208 NTSTATUS Status; 209 PVOID BaseAddress; 210 SIZE_T Size; 211 212 /* Reserve memory */ 213 BaseAddress = (PVOID)Base; 214 Size = InSize; 215 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 216 &BaseAddress, 217 0, 218 &Size, 219 MEM_RESERVE, 220 PAGE_NOACCESS); 221 ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed!\n"); 222 ok(BaseAddress == (PVOID)(Base & ~((ULONG_PTR)0xFFFF)), "Got back wrong base address: %p\n", BaseAddress); 223 ok(Size == ExpectedSize, "Alloc of 0x%Ix: got back wrong size: 0x%Ix, expected 0x%Ix\n", InSize, Size, ExpectedSize); 224 Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); 225 ok(NT_SUCCESS(Status), "NtFreeVirtualMemory failed!\n"); 226 } 227 228 VOID 229 CheckAlignment() 230 { 231 NTSTATUS Status; 232 PVOID BaseAddress; 233 SIZE_T Size; 234 235 CheckSize(0x50000000, 0x0001, 0x1000); 236 CheckSize(0x50008000, 0x0001, 0x9000); 237 CheckSize(0x50000010, 0x1000, 0x2000); 238 CheckSize(0x50010000, 0x2000, 0x2000); 239 CheckSize(0x5000FFFF, 0x3000, 0x13000); 240 CheckSize(0x50001010, 0x7000, 0x9000); 241 CheckSize(0x50001010, 0xC000, 0xe000); 242 243 /* Reserve memory not aligned to allocation granularity */ 244 BaseAddress = UlongToPtr(0x50001010); 245 Size = 0x1000; 246 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 247 &BaseAddress, 248 0, 249 &Size, 250 MEM_RESERVE, 251 PAGE_NOACCESS); 252 ok_ntstatus(Status, STATUS_SUCCESS); 253 ok(BaseAddress == UlongToPtr(0x50000000), "Got back wrong base address: %p", BaseAddress); 254 ok(Size == 0x3000, "Got back wrong size: 0x%Ix", Size); 255 256 /* Try to reserve again in the same 64k region */ 257 BaseAddress = UlongToPtr(0x50008000); 258 Size = 0x1000; 259 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 260 &BaseAddress, 261 0, 262 &Size, 263 MEM_RESERVE, 264 PAGE_NOACCESS); 265 ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES); 266 267 /* Commit memory */ 268 BaseAddress = UlongToPtr(0x50002000); 269 Size = 0x1000; 270 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 271 &BaseAddress, 272 0, 273 &Size, 274 MEM_COMMIT, 275 PAGE_NOACCESS); 276 ok_ntstatus(Status, STATUS_SUCCESS); 277 ok(BaseAddress == UlongToPtr(0x50002000), "Got back wrong base address: %p", BaseAddress); 278 ok(Size == 0x1000, "Got back wrong size: 0x%Ix", Size); 279 280 /* Commit the same address again with a different protection */ 281 BaseAddress = UlongToPtr(0x50002000); 282 Size = 0x1000; 283 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 284 &BaseAddress, 285 0, 286 &Size, 287 MEM_COMMIT, 288 PAGE_READWRITE); 289 ok_ntstatus(Status, STATUS_SUCCESS); 290 ok(BaseAddress == UlongToPtr(0x50002000), "Got back wrong base address: %p", BaseAddress); 291 ok(Size == 0x1000, "Got back wrong size: 0x%Ix", Size); 292 293 /* Commit memory at a too high address */ 294 BaseAddress = UlongToPtr(0x50003000); 295 Size = 0x1000; 296 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 297 &BaseAddress, 298 0, 299 &Size, 300 MEM_COMMIT, 301 PAGE_NOACCESS); 302 ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES); 303 304 /* Decommit the memory, even those pages that were not committed */ 305 BaseAddress = UlongToPtr(0x50000000); 306 Size = 0x3000; 307 Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_DECOMMIT); 308 ok_ntstatus(Status, STATUS_SUCCESS); 309 310 /* Try to release memory in a different 64k region */ 311 BaseAddress = UlongToPtr(0x50010000); 312 Size = 0x1000; 313 Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); 314 ok_ntstatus(Status, STATUS_MEMORY_NOT_ALLOCATED); 315 316 /* Release the memory in the same 64k region at a different address */ 317 BaseAddress = UlongToPtr(0x50008000); 318 Size = 0x1000; 319 Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); 320 ok_ntstatus(Status, STATUS_MEMORY_NOT_ALLOCATED); 321 322 /* Release the memory at the correct address but with wrong size */ 323 BaseAddress = UlongToPtr(0x50000000); 324 Size = 0x4000; 325 Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); 326 ok_ntstatus(Status, STATUS_UNABLE_TO_FREE_VM); 327 328 /* Release the memory */ 329 BaseAddress = UlongToPtr(0x50000000); 330 Size = 0x3000; 331 Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); 332 ok_ntstatus(Status, STATUS_SUCCESS); 333 334 /* Reserve and commit at once */ 335 BaseAddress = UlongToPtr(0x50004080); 336 Size = 0x1000; 337 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 338 &BaseAddress, 339 0, 340 &Size, 341 MEM_RESERVE | MEM_COMMIT, 342 PAGE_READWRITE); 343 ok_ntstatus(Status, STATUS_SUCCESS); 344 ok(BaseAddress == UlongToPtr(0x50000000), "Got back wrong base address: %p", BaseAddress); 345 ok(Size == 0x6000, "Got back wrong size: 0x%Ix", Size); 346 347 _SEH2_TRY 348 { 349 *(int*)BaseAddress = 1; 350 *(int*)UlongToPtr(0x50004080) = 1; 351 } 352 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 353 { 354 ok(0, "Got exception\n"); 355 } 356 _SEH2_END; 357 358 /* Release the memory */ 359 Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); 360 ok_ntstatus(Status, STATUS_SUCCESS); 361 362 } 363 364 static 365 VOID 366 CheckAdjacentVADs() 367 { 368 NTSTATUS Status; 369 PVOID BaseAddress; 370 SIZE_T Size; 371 MEMORY_BASIC_INFORMATION MemoryBasicInfo; 372 373 /* Reserve a full 64k region */ 374 BaseAddress = UlongToPtr(0x50000000); 375 Size = 0x10000; 376 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 377 &BaseAddress, 378 0, 379 &Size, 380 MEM_RESERVE, 381 PAGE_NOACCESS); 382 ok_ntstatus(Status, STATUS_SUCCESS); 383 if (!NT_SUCCESS(Status)) 384 return; 385 386 /* Reserve another 64k region, but with 64k between */ 387 BaseAddress = UlongToPtr(0x50020000); 388 Size = 0x10000; 389 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 390 &BaseAddress, 391 0, 392 &Size, 393 MEM_RESERVE, 394 PAGE_NOACCESS); 395 ok_ntstatus(Status, STATUS_SUCCESS); 396 if (!NT_SUCCESS(Status)) 397 return; 398 399 /* Try to free the whole at once */ 400 BaseAddress = UlongToPtr(0x50000000); 401 Size = 0x30000; 402 Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); 403 ok_ntstatus(Status, STATUS_UNABLE_TO_FREE_VM); 404 405 /* Reserve the part in the middle */ 406 BaseAddress = UlongToPtr(0x50010000); 407 Size = 0x10000; 408 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 409 &BaseAddress, 410 0, 411 &Size, 412 MEM_RESERVE, 413 PAGE_NOACCESS); 414 ok_ntstatus(Status, STATUS_SUCCESS); 415 416 /* Try to commit memory covering 2 allocations */ 417 BaseAddress = UlongToPtr(0x50004000); 418 Size = 0x10000; 419 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 420 &BaseAddress, 421 0, 422 &Size, 423 MEM_COMMIT, 424 PAGE_NOACCESS); 425 ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES); 426 427 /* Commit a page */ 428 BaseAddress = UlongToPtr(0x50000000); 429 Size = 0x1000; 430 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 431 &BaseAddress, 432 0, 433 &Size, 434 MEM_COMMIT, 435 PAGE_READWRITE); 436 ok_ntstatus(Status, STATUS_SUCCESS); 437 438 /* Commit another page */ 439 BaseAddress = UlongToPtr(0x50002000); 440 Size = 0x1000; 441 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 442 &BaseAddress, 443 0, 444 &Size, 445 MEM_COMMIT, 446 PAGE_NOACCESS); 447 ok_ntstatus(Status, STATUS_SUCCESS); 448 449 _SEH2_TRY 450 { 451 *(int*)UlongToPtr(0x50000000) = 1; 452 } 453 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 454 { 455 ok(0, "Got exception\n"); 456 } 457 _SEH2_END; 458 459 _SEH2_TRY 460 { 461 (void)*(volatile int*)UlongToPtr(0x50002000); 462 } 463 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 464 { 465 Status = _SEH2_GetExceptionCode(); 466 } 467 _SEH2_END; 468 ok_ntstatus(Status, STATUS_ACCESS_VIOLATION); 469 470 /* Allocate 3 pages, on top of the previous 2 */ 471 BaseAddress = UlongToPtr(0x50000000); 472 Size = 0x3000; 473 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 474 &BaseAddress, 475 0, 476 &Size, 477 MEM_COMMIT, 478 PAGE_READONLY); 479 ok_ntstatus(Status, STATUS_SUCCESS); 480 481 _SEH2_TRY 482 { 483 *(int*)UlongToPtr(0x50000000) = 1; 484 } 485 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 486 { 487 Status = _SEH2_GetExceptionCode(); 488 } 489 _SEH2_END; 490 ok_ntstatus(Status, STATUS_ACCESS_VIOLATION); 491 492 /* Commit a page at the end of the first region */ 493 BaseAddress = UlongToPtr(0x5000F000); 494 Size = 0x1000; 495 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 496 &BaseAddress, 497 0, 498 &Size, 499 MEM_COMMIT, 500 PAGE_READWRITE); 501 ok_ntstatus(Status, STATUS_SUCCESS); 502 ok_ptr(BaseAddress, UlongToPtr(0x5000F000)); 503 504 /* See where is the base of this newly committed area 505 * (choose a base address in the middle of it) */ 506 Status = NtQueryVirtualMemory(NtCurrentProcess(), 507 UlongToPtr(0x5000F700), 508 MemoryBasicInformation, 509 &MemoryBasicInfo, 510 sizeof(MemoryBasicInfo), 511 NULL); 512 ok_ntstatus(Status, STATUS_SUCCESS); 513 /* The base address is the beginning of the committed area */ 514 ok_ptr(MemoryBasicInfo.BaseAddress, UlongToPtr(0x5000F000)); 515 /* The allocation base address is the beginning of the whole region */ 516 ok_ptr(MemoryBasicInfo.AllocationBase, UlongToPtr(0x50000000)); 517 /* This is the protection of the memory when it was reserved. */ 518 ok_long(MemoryBasicInfo.AllocationProtect, PAGE_NOACCESS); 519 /* This is the size of the committed region. (ie, smallest chunk size) */ 520 ok_long(MemoryBasicInfo.RegionSize, 0x1000); 521 /* This is the state of the queried address */ 522 ok_long(MemoryBasicInfo.State, MEM_COMMIT); 523 /* This is the protection of the queried address */ 524 ok_long(MemoryBasicInfo.Protect, PAGE_READWRITE); 525 /* NtAllocateVirtualMemory makes it MEM_PRIVATE */ 526 ok_long(MemoryBasicInfo.Type, MEM_PRIVATE); 527 528 /* Try to free the whole region at once */ 529 BaseAddress = UlongToPtr(0x50000000); 530 Size = 0x30000; 531 Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); 532 ok_ntstatus(Status, STATUS_UNABLE_TO_FREE_VM); 533 534 BaseAddress = UlongToPtr(0x50000000); 535 Size = 0x10000; 536 Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); 537 ok_ntstatus(Status, STATUS_SUCCESS); 538 539 BaseAddress = UlongToPtr(0x50010000); 540 Size = 0x10000; 541 Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); 542 ok_ntstatus(Status, STATUS_SUCCESS); 543 544 BaseAddress = UlongToPtr(0x50020000); 545 Size = 0x10000; 546 Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); 547 ok_ntstatus(Status, STATUS_SUCCESS); 548 549 /* Reserve 3 full 64k region */ 550 BaseAddress = UlongToPtr(0x50000000); 551 Size = 0x30000; 552 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 553 &BaseAddress, 554 0, 555 &Size, 556 MEM_RESERVE, 557 PAGE_NOACCESS); 558 ok_ntstatus(Status, STATUS_SUCCESS); 559 if (!NT_SUCCESS(Status)) 560 return; 561 562 /* Release the 64k region in the middle */ 563 BaseAddress = UlongToPtr(0x50010000); 564 Size = 0x10000; 565 Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); 566 ok_ntstatus(Status, STATUS_SUCCESS); 567 568 } 569 570 static 571 VOID 572 CheckSomeDefaultAddresses(VOID) 573 { 574 NTSTATUS Status; 575 PVOID BaseAddress; 576 SIZE_T Size; 577 578 // NULL. 579 580 /* Reserve memory dynamically, not at 0x00000000 */ 581 BaseAddress = NULL; 582 Size = 0x1000; 583 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 584 &BaseAddress, 585 0, 586 &Size, 587 MEM_RESERVE, 588 PAGE_READWRITE); 589 ok_ntstatus(Status, STATUS_SUCCESS); 590 ok(BaseAddress != 0x00000000, "Unexpected BaseAddress = 0x00000000\n"); 591 Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); 592 ok_ntstatus(Status, STATUS_SUCCESS); 593 594 // 0x00000000, 64k: Free. 595 596 /* Reserve and commit memory at 0x00000000, after round down */ 597 BaseAddress = UlongToPtr(0x00000000 + 0x0FFF); 598 Size = 0x1000; 599 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 600 &BaseAddress, 601 0, 602 &Size, 603 MEM_RESERVE | MEM_COMMIT, 604 PAGE_READWRITE); 605 ok_ntstatus(Status, STATUS_SUCCESS); 606 ok_ptr(BaseAddress, 0x00000000); 607 608 // Double-check that it is not forbidden "in order to catch null pointer accesses". 609 StartSeh() 610 *(int*)UlongToPtr(0x00000000) = 1; 611 EndSeh(STATUS_SUCCESS) 612 613 Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); 614 ok_ntstatus(Status, STATUS_SUCCESS); 615 616 /* Reserve memory above 0x00000000 */ 617 BaseAddress = UlongToPtr(0x00000000 + 0x1000); 618 Size = 0x1000; 619 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 620 &BaseAddress, 621 0, 622 &Size, 623 MEM_RESERVE, 624 PAGE_READWRITE); 625 ok_ntstatus(Status, STATUS_SUCCESS); 626 Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); 627 ok_ntstatus(Status, STATUS_SUCCESS); 628 629 /* The following checks assume very default addresses, 630 * no address space layout randomization (ASLR). */ 631 #ifdef _WIN64 632 ok(FALSE, "ToDo, 64-bit: Check/Adapt 32-bit results\n"); 633 #endif 634 635 // 0x00010000, 4k: Private Data. 636 // 0x00011000, 60k: Unusable. 637 638 /* Reserve memory below 0x00010000 */ 639 BaseAddress = UlongToPtr(0x00010000 - 0x1000); 640 Size = 0x1000; 641 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 642 &BaseAddress, 643 0, 644 &Size, 645 MEM_RESERVE, 646 PAGE_READWRITE); 647 ok_ntstatus(Status, STATUS_SUCCESS); 648 Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); 649 ok_ntstatus(Status, STATUS_SUCCESS); 650 651 /* Reserve memory at 0x00010000: 652 * Windows NT legacy default executable image base */ 653 BaseAddress = UlongToPtr(0x00010000); 654 Size = 0x1000; 655 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 656 &BaseAddress, 657 0, 658 &Size, 659 MEM_RESERVE, 660 PAGE_READWRITE); 661 ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES); 662 if (NT_SUCCESS(Status)) 663 { // Unexpected, cleanup. 664 Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); 665 ok_ntstatus(Status, STATUS_SUCCESS); 666 } 667 668 // 0x00400000: Image base. 669 670 /* Reserve memory below 0x00400000 */ 671 BaseAddress = UlongToPtr(0x00400000 - 0x1000); 672 Size = 0x1000; 673 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 674 &BaseAddress, 675 0, 676 &Size, 677 MEM_RESERVE, 678 PAGE_READWRITE); 679 if (NT_SUCCESS(Status)) 680 { 681 trace("Below 0x00400000 is available, as on ReactOS and Windows S03\n"); 682 // 0x003F0000, 64k: Free. 683 ok_ntstatus(Status, STATUS_SUCCESS); 684 Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); 685 ok_ntstatus(Status, STATUS_SUCCESS); 686 } 687 else 688 { 689 trace("Below 0x00400000 is not available, as on Windows XP\n"); 690 // 0x003F0000, 4k: Shareable. 691 // 0x003F1000, 60k: Unusable. 692 ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES); 693 } 694 695 /* Reserve memory at 0x00400000: 696 * Windows NT legacy default DLL image base, 697 * (ReactOS and) Windows 95 new default executable image base */ 698 BaseAddress = UlongToPtr(0x00400000); 699 Size = 0x1000; 700 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 701 &BaseAddress, 702 0, 703 &Size, 704 MEM_RESERVE, 705 PAGE_READWRITE); 706 ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES); 707 if (NT_SUCCESS(Status)) 708 { // Unexpected, cleanup. 709 Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); 710 ok_ntstatus(Status, STATUS_SUCCESS); 711 } 712 713 // 0x10000000: Free. 714 715 /* Reserve memory below 0x10000000 */ 716 BaseAddress = UlongToPtr(0x10000000 - 0x1000); 717 Size = 0x1000; 718 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 719 &BaseAddress, 720 0, 721 &Size, 722 MEM_RESERVE, 723 PAGE_READWRITE); 724 ok_ntstatus(Status, STATUS_SUCCESS); 725 Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); 726 ok_ntstatus(Status, STATUS_SUCCESS); 727 728 /* Reserve memory at 0x10000000: 729 * Windows new default non-OS DLL image base */ 730 BaseAddress = UlongToPtr(0x10000000); 731 Size = 0x1000; 732 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 733 &BaseAddress, 734 0, 735 &Size, 736 MEM_RESERVE, 737 PAGE_READWRITE); 738 ok_ntstatus(Status, STATUS_SUCCESS); 739 Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); 740 ok_ntstatus(Status, STATUS_SUCCESS); 741 742 #ifdef _WIN64 743 skip("ToDo, 64-bit: Add 0x140000000/Exe and 0x180000000/DLL checks\n"); 744 #endif 745 } 746 747 #define RUNS 32 748 749 START_TEST(NtAllocateVirtualMemory) 750 { 751 PVOID Mem1, Mem2; 752 SIZE_T Size1, Size2; 753 ULONG i; 754 755 CheckAlignment(); 756 CheckAdjacentVADs(); 757 CheckSomeDefaultAddresses(); 758 759 Size1 = 32; 760 Mem1 = Allocate(Size1); 761 AccessMemory1(Mem1, Size1); 762 Size2 = 128; 763 Mem2 = Allocate(Size2); 764 AccessMemory2(Mem2, Size2); 765 for (i = 0; i < RUNS; ++i) 766 { 767 PVOID New; 768 ok(CheckMemory1(Mem1, Size1) == TRUE, "CheckMemory1 failure\n"); 769 New = ReAllocate(Mem1, Size1 * 3 / 2); 770 if (New == NULL) 771 { 772 skip("Realloc failure\n"); 773 break; 774 } 775 Mem1 = New; 776 ok(CheckMemory1(Mem1, Size1) == TRUE, "CheckMemory1 failure\n"); 777 Size1 = Size1 * 3 / 2; 778 AccessMemory1(Mem1, Size1); 779 780 ok(CheckMemory2(Mem2, Size2) == TRUE, "CheckMemory2 failure\n"); 781 New = ReAllocate(Mem2, Size2 + 128); 782 if (New == NULL) 783 { 784 skip("Realloc failure\n"); 785 break; 786 } 787 Mem2 = New; 788 ok(CheckMemory2(Mem2, Size2) == TRUE, "CheckMemory2 failure\n"); 789 Size2 += 128; 790 AccessMemory2(Mem2, Size2); 791 } 792 ok(CheckMemory2(Mem2, Size2) == TRUE, "CheckMemory2 failure\n"); 793 Free(Mem2); 794 ok(CheckMemory1(Mem1, Size1) == TRUE, "CheckMemory1 failure\n"); 795 Free(Mem1); 796 } 797