[NTDLL_APITEST] Show that registry strings can be longer than MAXUSHORT.
[reactos.git] / modules / rostests / apitests / ntdll / NtAllocateVirtualMemory.c
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 }