d551ee200bac7c7c6fae2df6bbcb54de46053337
[reactos.git] / rostests / kmtests / ntos_mm / ZwAllocateVirtualMemory.c
1 /*
2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Kernel-Mode Test Suite ZwAllocateVirtualMemory/ZwFreeVirtualMemory
5 * PROGRAMMER: Nikolay Borisov <nib9@aber.ac.uk>
6 */
7
8 #include <kmt_test.h>
9
10 #define ROUND_DOWN(n,align) (((ULONG_PTR)n) & ~((align) - 1l))
11 #define DEFAULT_ALLOC_SIZE 200
12 #define IGNORE -1
13 #define PAGE_NOPROT 0x0 //MEM_RESERVE has this type of "protection"
14
15 /* These are being used in ZwMapViewOfSection as well */
16 const char TestString[] = "TheLongBrownFoxJumpedTheWhiteRabbitTheLongBrownFoxJumpedTheWhiteRabbitTheLongBrownFoxJumpedTheWhiteRabbitTheLongBrownFoxJumpedTheWhiteRabbitTheLongBrownFoxJumpedTheWhiteRabbitTheLongBrownFoxJumpedThe";
17 const ULONG TestStringSize = sizeof(TestString);
18
19 VOID Test_ZwAllocateVirtualMemory(VOID);
20
21 typedef struct _TEST_CONTEXT
22 {
23 HANDLE ProcessHandle;
24 SIZE_T RegionSize;
25 ULONG AllocationType;
26 ULONG Protect;
27 PVOID Bases[1024];
28 SHORT ThreadId;
29 } TEST_CONTEXT, *PTEST_CONTEXT;
30
31
32 #define ALLOC_MEMORY_WITH_FREE(ProcessHandle, BaseAddress, ZeroBits, RegionSize, AllocationType, Protect, RetStatus, FreeStatus) \
33 do { \
34 Status = ZwAllocateVirtualMemory(ProcessHandle, &BaseAddress, ZeroBits, &RegionSize, AllocationType, Protect); \
35 ok_eq_hex(Status, RetStatus); \
36 RegionSize = 0; \
37 Status = ZwFreeVirtualMemory(ProcessHandle, &BaseAddress, &RegionSize, MEM_RELEASE); \
38 if (FreeStatus != IGNORE) ok_eq_hex(Status, FreeStatus); \
39 BaseAddress = NULL; \
40 RegionSize = DEFAULT_ALLOC_SIZE; \
41 } while (0) \
42
43
44
45 static
46 BOOLEAN
47 CheckBuffer(PVOID Buffer, SIZE_T Size, UCHAR Value)
48 {
49 PUCHAR Array = Buffer;
50 SIZE_T i;
51
52 for (i = 0; i < Size; i++)
53 {
54 if (Array[i] != Value)
55 {
56 trace("Expected %x, found %x at offset %lu\n", Value, Array[i], (ULONG)i);
57 return FALSE;
58 }
59 }
60 return TRUE;
61 }
62
63 static
64 SIZE_T
65 CheckBufferRead(CONST VOID *Source, CONST VOID *Destination, SIZE_T Length, NTSTATUS ExpectedStatus)
66 {
67 NTSTATUS ExceptionStatus;
68 SIZE_T Match = 0;
69
70 KmtStartSeh()
71 Match = RtlCompareMemory(Source, Destination, Length);
72 KmtEndSeh(ExpectedStatus);
73
74 return Match;
75 }
76
77 static
78 VOID
79 CheckBufferReadWrite(PVOID Destination, CONST VOID *Source, SIZE_T Length, NTSTATUS ExpectedStatus)
80 {
81 //do a little bit of writing/reading to memory
82 NTSTATUS ExceptionStatus;
83 SIZE_T Match = 0;
84
85 KmtStartSeh()
86 RtlCopyMemory(Destination, Source, Length);
87 KmtEndSeh(ExpectedStatus);
88
89 Match = CheckBufferRead(Source, Destination, Length, ExpectedStatus);
90 if (ExpectedStatus == STATUS_SUCCESS) ok_eq_int(Match, Length);
91 }
92
93
94 static
95 VOID
96 SimpleErrorChecks(VOID)
97 {
98 NTSTATUS Status;
99 PVOID Base = NULL;
100 SIZE_T RegionSize = DEFAULT_ALLOC_SIZE;
101
102 //HANDLE TESTS
103 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS);
104 ALLOC_MEMORY_WITH_FREE(NULL, Base, 0, RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE, STATUS_INVALID_HANDLE, STATUS_INVALID_HANDLE);
105 ALLOC_MEMORY_WITH_FREE((HANDLE)0xdeadbeef, Base, 0, RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE, STATUS_INVALID_HANDLE, STATUS_INVALID_HANDLE);
106
107 //BASE ADDRESS TESTS
108 Base = (PVOID)0x00567A20;
109 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE, STATUS_CONFLICTING_ADDRESSES, STATUS_FREE_VM_NOT_AT_BASE);
110
111 Base = (PVOID) 0x60000000;
112 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS);
113
114 Base = (PVOID)((char *)MmSystemRangeStart + 200);
115 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE, STATUS_INVALID_PARAMETER_2, STATUS_INVALID_PARAMETER_2);
116
117 /* http://jira.reactos.org/browse/CORE-6814 */
118 RegionSize = 0x1000;
119 Base = Test_ZwAllocateVirtualMemory;
120 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, MEM_COMMIT, PAGE_READWRITE, STATUS_INVALID_PARAMETER_2, STATUS_INVALID_PARAMETER_2);
121
122 //ZERO BITS TESTS
123 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 21, RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE, STATUS_NO_MEMORY, STATUS_MEMORY_NOT_ALLOCATED);
124 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 22, RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE, STATUS_INVALID_PARAMETER_3, STATUS_MEMORY_NOT_ALLOCATED);
125 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, -1, RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE, STATUS_INVALID_PARAMETER_3, STATUS_MEMORY_NOT_ALLOCATED);
126 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 3, RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS);
127
128 //REGION SIZE TESTS
129 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS);
130 RegionSize = -1;
131 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE, STATUS_INVALID_PARAMETER_4, STATUS_MEMORY_NOT_ALLOCATED);
132 RegionSize = 0;
133 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE, STATUS_INVALID_PARAMETER_4, STATUS_MEMORY_NOT_ALLOCATED);
134 RegionSize = 0xFFFFFFFF; // 4 gb is invalid
135 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE, STATUS_INVALID_PARAMETER_4, STATUS_MEMORY_NOT_ALLOCATED);
136
137 //Allocation type tests
138 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, MEM_PHYSICAL, PAGE_READWRITE, STATUS_INVALID_PARAMETER_5, STATUS_MEMORY_NOT_ALLOCATED);
139 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_COMMIT | MEM_RESET), PAGE_READWRITE, STATUS_INVALID_PARAMETER_5, STATUS_MEMORY_NOT_ALLOCATED);
140 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, 0, PAGE_READWRITE, STATUS_INVALID_PARAMETER_5, STATUS_MEMORY_NOT_ALLOCATED);
141 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, MEM_TOP_DOWN, PAGE_READWRITE, STATUS_INVALID_PARAMETER_5, STATUS_MEMORY_NOT_ALLOCATED);
142 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_TOP_DOWN | MEM_RESET), PAGE_READWRITE, STATUS_INVALID_PARAMETER_5, STATUS_MEMORY_NOT_ALLOCATED);
143 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_TOP_DOWN | MEM_COMMIT), PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS);
144 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_PHYSICAL | MEM_RESERVE), PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS);
145 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_PHYSICAL | MEM_COMMIT), PAGE_READWRITE, STATUS_INVALID_PARAMETER_5, STATUS_MEMORY_NOT_ALLOCATED);
146 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_RESET | MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE, STATUS_INVALID_PARAMETER_5, STATUS_MEMORY_NOT_ALLOCATED);
147 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, -1, PAGE_READWRITE, STATUS_INVALID_PARAMETER_5, STATUS_MEMORY_NOT_ALLOCATED);
148 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, MEM_COMMIT, PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS);
149 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, MEM_RESERVE, PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS);
150 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, MEM_RESERVE, PAGE_WRITECOPY, STATUS_INVALID_PAGE_PROTECTION, STATUS_MEMORY_NOT_ALLOCATED);
151 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, MEM_RESERVE, PAGE_EXECUTE_WRITECOPY, STATUS_INVALID_PAGE_PROTECTION, STATUS_MEMORY_NOT_ALLOCATED);
152
153 //Memory protection tests
154 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_COMMIT | MEM_RESERVE), 0, STATUS_INVALID_PAGE_PROTECTION, STATUS_MEMORY_NOT_ALLOCATED);
155 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_COMMIT | MEM_RESERVE), -1, STATUS_INVALID_PAGE_PROTECTION, STATUS_MEMORY_NOT_ALLOCATED);
156 if (!KmtIsCheckedBuild)
157 {
158 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_COMMIT | MEM_RESERVE), (PAGE_NOACCESS | PAGE_GUARD), STATUS_INVALID_PAGE_PROTECTION, STATUS_MEMORY_NOT_ALLOCATED);
159 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_COMMIT | MEM_RESERVE), (PAGE_NOACCESS | PAGE_WRITECOMBINE), STATUS_INVALID_PAGE_PROTECTION, STATUS_MEMORY_NOT_ALLOCATED);
160 }
161 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_COMMIT | MEM_RESERVE), (PAGE_READONLY | PAGE_WRITECOMBINE), STATUS_SUCCESS, STATUS_SUCCESS);
162 }
163
164
165 static
166 NTSTATUS
167 SimpleAllocation(VOID)
168 {
169 NTSTATUS Status;
170 NTSTATUS ExceptionStatus;
171 PVOID Base = NULL;
172 SIZE_T RegionSize = DEFAULT_ALLOC_SIZE;
173
174 //////////////////////////////////////////////////////////////////////////
175 //Normal operation
176 //////////////////////////////////////////////////////////////////////////
177 Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &Base, 0, &RegionSize, MEM_COMMIT, PAGE_READWRITE);
178 ok_eq_size(RegionSize, 4096);
179
180 //check for the zero-filled pages
181 ok_bool_true(CheckBuffer(Base, RegionSize, 0), "The buffer is not zero-filled");
182
183 CheckBufferReadWrite(Base, TestString, TestStringSize, STATUS_SUCCESS);
184
185 // try freeing
186 RegionSize = 0;
187 Status = ZwFreeVirtualMemory(NtCurrentProcess(), &Base, &RegionSize, MEM_RELEASE);
188 ok_eq_hex(Status, STATUS_SUCCESS);
189 ok_eq_size(RegionSize, PAGE_SIZE);
190
191 //////////////////////////////////////////////////////////////////////////
192 // COMMIT AND RESERVE SCENARIO AND STATE CHANGE
193 //////////////////////////////////////////////////////////////////////////
194 //reserve and then commit
195 Base = NULL;
196 RegionSize = DEFAULT_ALLOC_SIZE;
197 Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &Base, 0, &RegionSize, MEM_RESERVE, PAGE_READWRITE);
198 Test_NtQueryVirtualMemory(Base, RegionSize, MEM_RESERVE, PAGE_NOPROT);
199 CheckBufferReadWrite(Base, TestString, TestStringSize, STATUS_ACCESS_VIOLATION);
200
201
202 Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &Base, 0, &RegionSize, MEM_COMMIT, PAGE_READWRITE);
203 CheckBufferReadWrite(Base, TestString, TestStringSize, STATUS_SUCCESS);
204 Test_NtQueryVirtualMemory(Base, RegionSize, MEM_COMMIT, PAGE_READWRITE);
205
206 RegionSize = 0;
207 ZwFreeVirtualMemory(NtCurrentProcess(), &Base, &RegionSize, MEM_RELEASE);
208
209 //////////////////////////////////////////////////////////////////////////
210 // TRY READING/WRITING TO INVALID PROTECTION PAGES
211 //////////////////////////////////////////////////////////////////////////
212 RegionSize = DEFAULT_ALLOC_SIZE;
213 Base = NULL;
214 ZwAllocateVirtualMemory(NtCurrentProcess(), &Base, 0, &RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_NOACCESS);
215
216 KmtStartSeh()
217 RtlCopyMemory(Base, TestString, TestStringSize);
218 KmtEndSeh(STATUS_ACCESS_VIOLATION);
219
220 Test_NtQueryVirtualMemory(Base, RegionSize, MEM_COMMIT, PAGE_NOACCESS);
221 CheckBufferRead(Base, TestString, TestStringSize, STATUS_ACCESS_VIOLATION);
222
223 RegionSize = 0;
224 ZwFreeVirtualMemory(NtCurrentProcess(), &Base, &RegionSize, MEM_RELEASE);
225
226 ZwAllocateVirtualMemory(NtCurrentProcess(), &Base, 0, &RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READONLY);
227 KmtStartSeh()
228 RtlCopyMemory(Base, TestString, TestStringSize);
229 KmtEndSeh(STATUS_ACCESS_VIOLATION);
230
231 Test_NtQueryVirtualMemory(Base, RegionSize, MEM_COMMIT, PAGE_READONLY);
232
233 ok_bool_true(CheckBuffer(Base, TestStringSize, 0), "Couldn't read a read-only buffer");
234
235 RegionSize = 0;
236 ZwFreeVirtualMemory(NtCurrentProcess(), &Base, &RegionSize, MEM_RELEASE);
237
238 //////////////////////////////////////////////////////////////////////////
239 // GUARD PAGES
240 //////////////////////////////////////////////////////////////////////////
241 /* FIXME: We don't support guard pages. See CORE-6639, ROSTESTS-107 */
242 #ifdef ROSTESTS_107_FIXED
243 RegionSize = 1000;
244 Base = NULL;
245 ZwAllocateVirtualMemory(NtCurrentProcess(), &Base, 0, &RegionSize, (MEM_COMMIT | MEM_RESERVE), (PAGE_GUARD | PAGE_READWRITE));
246
247 Test_NtQueryVirtualMemory(Base, RegionSize, MEM_COMMIT, (PAGE_GUARD | PAGE_READWRITE));
248 KmtStartSeh()
249 RtlCopyMemory(Base, TestString, TestStringSize);
250 KmtEndSeh(STATUS_GUARD_PAGE_VIOLATION);
251
252 Test_NtQueryVirtualMemory(Base, RegionSize, MEM_COMMIT, PAGE_READWRITE);
253
254 KmtStartSeh()
255 RtlCopyMemory(Base, TestString, TestStringSize);
256 KmtEndSeh(STATUS_SUCCESS);
257
258 RegionSize = 0;
259 ZwFreeVirtualMemory(NtCurrentProcess(), &Base, &RegionSize, MEM_RELEASE);
260 #endif /* ROSTESTS_107_FIXED */
261
262 return Status;
263 }
264
265
266 static
267 VOID
268 CustomBaseAllocation(VOID)
269 {
270 NTSTATUS Status;
271 SIZE_T RegionSize = 200;
272 PVOID Base = (PVOID) 0x60025000;
273 PVOID ActualStartingAddress = (PVOID)ROUND_DOWN(Base, MM_ALLOCATION_GRANULARITY); //it is rounded down to the nearest allocation granularity (64k) address
274 PVOID EndingAddress = (PVOID)(((ULONG_PTR)Base + RegionSize - 1) | (PAGE_SIZE - 1));
275 SIZE_T ActualSize = BYTES_TO_PAGES((ULONG_PTR)EndingAddress - (ULONG_PTR)ActualStartingAddress) * PAGE_SIZE; //calculates the actual size based on the required pages
276
277 // allocate the memory
278 Status = ZwAllocateVirtualMemory(NtCurrentProcess(), (PVOID *)&Base, 0, &RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE);
279 ok_eq_hex(Status, STATUS_SUCCESS);
280 ok_eq_size(RegionSize, ActualSize);
281 ok_eq_ulong(Base, ActualStartingAddress);
282 Test_NtQueryVirtualMemory(ActualStartingAddress, ActualSize, MEM_COMMIT, PAGE_READWRITE);
283
284 // try freeing
285 RegionSize = 0;
286 Status = ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID *)&Base, &RegionSize, MEM_RELEASE);
287 ok_eq_hex(Status, STATUS_SUCCESS);
288 ok_eq_ulong(RegionSize, ActualSize);
289 }
290
291
292 static
293 NTSTATUS
294 StressTesting(ULONG AllocationType)
295 {
296 NTSTATUS Status = STATUS_SUCCESS;
297 NTSTATUS ReturnStatus = STATUS_SUCCESS;
298 static PVOID bases[1024]; //assume we are going to allocate only 5 gigs. static here means the arrays is not allocated on the stack but in the BSS segment of the driver
299 ULONG Index = 0;
300 PVOID Base = NULL;
301 SIZE_T RegionSize = 5 * 1024 * 1024; // 5 megabytes;
302
303 RtlZeroMemory(bases, sizeof(bases));
304
305 for (Index = 0; Index < RTL_NUMBER_OF(bases) && NT_SUCCESS(Status); Index++)
306 {
307 Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &Base, 0, &RegionSize, AllocationType, PAGE_READWRITE);
308
309 bases[Index] = Base;
310 if ((Index % 10) == 0)
311 {
312 if (AllocationType == MEM_COMMIT && NT_SUCCESS(Status))
313 {
314 CheckBufferReadWrite(Base, TestString, TestStringSize, STATUS_SUCCESS);
315 }
316 else
317 {
318 CheckBufferReadWrite(Base, TestString, TestStringSize, STATUS_ACCESS_VIOLATION);
319 }
320 }
321
322 Base = NULL;
323 }
324
325 trace("Finished reserving. Error code %x. Chunks allocated: %d\n", Status, Index );
326
327 ReturnStatus = Status;
328
329 //free the allocated memory so that we can continue with the tests
330 Status = STATUS_SUCCESS;
331 Index = 0;
332 while (NT_SUCCESS(Status) && Index < RTL_NUMBER_OF(bases))
333 {
334 RegionSize = 0;
335 Status = ZwFreeVirtualMemory(NtCurrentProcess(), &bases[Index], &RegionSize, MEM_RELEASE);
336 bases[Index++] = NULL;
337 }
338
339 return ReturnStatus;
340 }
341
342
343 static
344 VOID
345 NTAPI
346 SystemProcessTestWorker(PVOID StartContext)
347 {
348 NTSTATUS Status = STATUS_SUCCESS;
349 PTEST_CONTEXT Context = (PTEST_CONTEXT)StartContext;
350 ULONG Index = 0;
351 PVOID Base = NULL;
352
353 PAGED_CODE();
354
355 RtlZeroMemory(Context->Bases, sizeof(Context->Bases));
356
357 Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &Base, 0, &Context->RegionSize, Context->AllocationType, Context->Protect);
358 ZwFreeVirtualMemory(NtCurrentProcess(), &Base, &Context->RegionSize, MEM_RELEASE);
359 Base = NULL;
360
361 //if the previous allocation has failed there is no need to do the loop
362 while (NT_SUCCESS(Status) && Index < RTL_NUMBER_OF(Context->Bases))
363 {
364 Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &Base, 0, &Context->RegionSize, Context->AllocationType, Context->Protect);
365
366 Context->Bases[Index] = Base;
367 if ((Index % 10) == 0)
368 {
369 if (Context->AllocationType == MEM_COMMIT)
370 {
371 CheckBufferReadWrite(Base, TestString, TestStringSize, STATUS_SUCCESS);
372 }
373 else
374 {
375 CheckBufferReadWrite(Base, TestString, TestStringSize, STATUS_ACCESS_VIOLATION);
376 }
377 }
378
379 Base = NULL;
380 Index++;
381 }
382
383 trace("[SYSTEM THREAD %d]. Error code %x. Chunks allocated: %d\n", Context->ThreadId, Status, Index);
384
385 //free the allocated memory so that we can continue with the tests
386 Status = STATUS_SUCCESS;
387 Index = 0;
388 while (NT_SUCCESS(Status) && Index < RTL_NUMBER_OF(Context->Bases))
389 {
390 Context->RegionSize = 0;
391 Status = ZwFreeVirtualMemory(NtCurrentProcess(), &Context->Bases[Index], &Context->RegionSize, MEM_RELEASE);
392 Context->Bases[Index++] = NULL;
393 }
394
395 PsTerminateSystemThread(Status);
396 }
397
398
399 static
400 VOID
401 KmtInitTestContext(PTEST_CONTEXT Ctx, SHORT ThreadId, ULONG RegionSize, ULONG AllocationType, ULONG Protect)
402 {
403 PAGED_CODE();
404
405 Ctx->AllocationType = AllocationType;
406 Ctx->Protect = Protect;
407 Ctx->RegionSize = RegionSize;
408 Ctx->ThreadId = ThreadId;
409 }
410
411
412 static
413 VOID
414 SystemProcessTest(VOID)
415 {
416 NTSTATUS Status;
417 HANDLE Thread1 = INVALID_HANDLE_VALUE;
418 HANDLE Thread2 = INVALID_HANDLE_VALUE;
419 PVOID ThreadObjects[2] = { NULL };
420 OBJECT_ATTRIBUTES ObjectAttributes;
421 PTEST_CONTEXT StartContext1;
422 PTEST_CONTEXT StartContext2;
423
424 PAGED_CODE();
425
426 StartContext1 = ExAllocatePoolWithTag(PagedPool, sizeof(TEST_CONTEXT), 'tXTC');
427 StartContext2 = ExAllocatePoolWithTag(PagedPool, sizeof(TEST_CONTEXT), 'tXTC');
428 if (StartContext1 == NULL || StartContext2 == NULL)
429 {
430 trace("Error allocating space for context structs\n");
431 goto cleanup;
432 }
433
434 KmtInitTestContext(StartContext1, 1, 1 * 1024 * 1024, MEM_COMMIT, PAGE_READWRITE);
435 KmtInitTestContext(StartContext2, 2, 3 * 1024 * 1024, MEM_COMMIT, PAGE_READWRITE);
436 InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
437
438 Status = PsCreateSystemThread(&Thread1, THREAD_ALL_ACCESS, &ObjectAttributes, NULL, NULL, SystemProcessTestWorker, StartContext1);
439 if (!NT_SUCCESS(Status))
440 {
441 trace("Error creating thread1\n");
442 goto cleanup;
443 }
444
445 Status = ObReferenceObjectByHandle(Thread1, THREAD_ALL_ACCESS, PsThreadType, KernelMode, &ThreadObjects[0], NULL);
446 if (!NT_SUCCESS(Status))
447 {
448 trace("error referencing thread1\n");
449 goto cleanup;
450 }
451
452 Status = PsCreateSystemThread(&Thread2, THREAD_ALL_ACCESS, &ObjectAttributes, NULL, NULL, SystemProcessTestWorker, StartContext2);
453 if (!NT_SUCCESS(Status))
454 {
455 trace("Error creating thread2\n");
456 goto cleanup;
457 }
458
459 Status = ObReferenceObjectByHandle(Thread2, THREAD_ALL_ACCESS, PsThreadType, KernelMode, &ThreadObjects[1], NULL);
460 if (!NT_SUCCESS(Status))
461 {
462 trace("error referencing thread2\n");
463 goto cleanup;
464 }
465
466 cleanup:
467
468 if (ThreadObjects[0])
469 Status = KeWaitForSingleObject(ThreadObjects[0], Executive, KernelMode, FALSE, NULL);
470
471 if (StartContext1 != NULL)
472 ExFreePoolWithTag(StartContext1, 'tXTC');
473
474 if (ThreadObjects[1])
475 Status = KeWaitForSingleObject(ThreadObjects[1], Executive, KernelMode, FALSE, NULL);
476
477 if (StartContext2 != NULL)
478 ExFreePoolWithTag(StartContext2, 'tXTC');
479
480 if (ThreadObjects[0] != NULL)
481 ObDereferenceObject(ThreadObjects[0]);
482
483 if (ThreadObjects[1] != NULL)
484 ObDereferenceObject(ThreadObjects[1]);
485
486 if (Thread1 != INVALID_HANDLE_VALUE)
487 ZwClose(Thread1);
488
489 if (Thread2 != INVALID_HANDLE_VALUE)
490 ZwClose(Thread2);
491 }
492
493
494 START_TEST(ZwAllocateVirtualMemory)
495 {
496 NTSTATUS Status;
497
498 SimpleErrorChecks();
499
500 SimpleAllocation();
501
502 CustomBaseAllocation();
503
504 Status = StressTesting(MEM_RESERVE);
505 ok_eq_hex(Status, STATUS_NO_MEMORY);
506
507 Status = STATUS_SUCCESS;
508 Status = StressTesting(MEM_COMMIT);
509 ok_eq_hex(Status, STATUS_COMMITMENT_LIMIT);
510
511 SystemProcessTest();
512 }