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