[KMTESTS]
[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
242 RegionSize = 1000;
243 Base = NULL;
244 ZwAllocateVirtualMemory(NtCurrentProcess(), &Base, 0, &RegionSize, (MEM_COMMIT | MEM_RESERVE), (PAGE_GUARD | PAGE_READWRITE));
245
246 Test_NtQueryVirtualMemory(Base, RegionSize, MEM_COMMIT, (PAGE_GUARD | PAGE_READWRITE));
247 KmtStartSeh()
248 RtlCopyMemory(Base, TestString, TestStringSize);
249 KmtEndSeh(STATUS_GUARD_PAGE_VIOLATION);
250
251 Test_NtQueryVirtualMemory(Base, RegionSize, MEM_COMMIT, PAGE_READWRITE);
252
253 KmtStartSeh()
254 RtlCopyMemory(Base, TestString, TestStringSize);
255 KmtEndSeh(STATUS_SUCCESS);
256
257 RegionSize = 0;
258 ZwFreeVirtualMemory(NtCurrentProcess(), &Base, &RegionSize, MEM_RELEASE);
259
260 return Status;
261 }
262
263
264 static
265 VOID
266 CustomBaseAllocation(VOID)
267 {
268 NTSTATUS Status;
269 SIZE_T RegionSize = 200;
270 PVOID Base = (PVOID) 0x60025000;
271 PVOID ActualStartingAddress = (PVOID)ROUND_DOWN(Base, MM_ALLOCATION_GRANULARITY); //it is rounded down to the nearest allocation granularity (64k) address
272 PVOID EndingAddress = (PVOID)(((ULONG_PTR)Base + RegionSize - 1) | (PAGE_SIZE - 1));
273 SIZE_T ActualSize = BYTES_TO_PAGES((ULONG_PTR)EndingAddress - (ULONG_PTR)ActualStartingAddress) * PAGE_SIZE; //calculates the actual size based on the required pages
274
275 // allocate the memory
276 Status = ZwAllocateVirtualMemory(NtCurrentProcess(), (PVOID *)&Base, 0, &RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE);
277 ok_eq_hex(Status, STATUS_SUCCESS);
278 ok_eq_size(RegionSize, ActualSize);
279 ok_eq_ulong(Base, ActualStartingAddress);
280 Test_NtQueryVirtualMemory(ActualStartingAddress, ActualSize, MEM_COMMIT, PAGE_READWRITE);
281
282 // try freeing
283 RegionSize = 0;
284 Status = ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID *)&Base, &RegionSize, MEM_RELEASE);
285 ok_eq_hex(Status, STATUS_SUCCESS);
286 ok_eq_ulong(RegionSize, ActualSize);
287 }
288
289
290 static
291 NTSTATUS
292 StressTesting(ULONG AllocationType)
293 {
294 NTSTATUS Status = STATUS_SUCCESS;
295 NTSTATUS ReturnStatus = STATUS_SUCCESS;
296 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
297 ULONG Index = 0;
298 PVOID Base = NULL;
299 SIZE_T RegionSize = 5 * 1024 * 1024; // 5 megabytes;
300
301 RtlZeroMemory(bases, sizeof(bases));
302
303 for (Index = 0; Index < RTL_NUMBER_OF(bases) && NT_SUCCESS(Status); Index++)
304 {
305 Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &Base, 0, &RegionSize, AllocationType, PAGE_READWRITE);
306
307 bases[Index] = Base;
308 if ((Index % 10) == 0)
309 {
310 if (AllocationType == MEM_COMMIT && NT_SUCCESS(Status))
311 {
312 CheckBufferReadWrite(Base, TestString, TestStringSize, STATUS_SUCCESS);
313 }
314 else
315 {
316 CheckBufferReadWrite(Base, TestString, TestStringSize, STATUS_ACCESS_VIOLATION);
317 }
318 }
319
320 Base = NULL;
321 }
322
323 trace("Finished reserving. Error code %x. Chunks allocated: %d\n", Status, Index );
324
325 ReturnStatus = Status;
326
327 //free the allocated memory so that we can continue with the tests
328 Status = STATUS_SUCCESS;
329 Index = 0;
330 while (NT_SUCCESS(Status) && Index < RTL_NUMBER_OF(bases))
331 {
332 RegionSize = 0;
333 Status = ZwFreeVirtualMemory(NtCurrentProcess(), &bases[Index], &RegionSize, MEM_RELEASE);
334 bases[Index++] = NULL;
335 }
336
337 return ReturnStatus;
338 }
339
340
341 static
342 VOID
343 NTAPI
344 SystemProcessTestWorker(PVOID StartContext)
345 {
346 NTSTATUS Status = STATUS_SUCCESS;
347 PTEST_CONTEXT Context = (PTEST_CONTEXT)StartContext;
348 ULONG Index = 0;
349 PVOID Base = NULL;
350
351 PAGED_CODE();
352
353 RtlZeroMemory(Context->Bases, sizeof(Context->Bases));
354
355 Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &Base, 0, &Context->RegionSize, Context->AllocationType, Context->Protect);
356 ZwFreeVirtualMemory(NtCurrentProcess(), &Base, &Context->RegionSize, MEM_RELEASE);
357 Base = NULL;
358
359 //if the previous allocation has failed there is no need to do the loop
360 while (NT_SUCCESS(Status) && Index < RTL_NUMBER_OF(Context->Bases))
361 {
362 Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &Base, 0, &Context->RegionSize, Context->AllocationType, Context->Protect);
363
364 Context->Bases[Index] = Base;
365 if ((Index % 10) == 0)
366 {
367 if (Context->AllocationType == MEM_COMMIT)
368 {
369 CheckBufferReadWrite(Base, TestString, TestStringSize, STATUS_SUCCESS);
370 }
371 else
372 {
373 CheckBufferReadWrite(Base, TestString, TestStringSize, STATUS_ACCESS_VIOLATION);
374 }
375 }
376
377 Base = NULL;
378 Index++;
379 }
380
381 trace("[SYSTEM THREAD %d]. Error code %x. Chunks allocated: %d\n", Context->ThreadId, Status, Index);
382
383 //free the allocated memory so that we can continue with the tests
384 Status = STATUS_SUCCESS;
385 Index = 0;
386 while (NT_SUCCESS(Status) && Index < RTL_NUMBER_OF(Context->Bases))
387 {
388 Context->RegionSize = 0;
389 Status = ZwFreeVirtualMemory(NtCurrentProcess(), &Context->Bases[Index], &Context->RegionSize, MEM_RELEASE);
390 Context->Bases[Index++] = NULL;
391 }
392
393 PsTerminateSystemThread(Status);
394 }
395
396
397 static
398 VOID
399 KmtInitTestContext(PTEST_CONTEXT Ctx, SHORT ThreadId, ULONG RegionSize, ULONG AllocationType, ULONG Protect)
400 {
401 PAGED_CODE();
402
403 Ctx->AllocationType = AllocationType;
404 Ctx->Protect = Protect;
405 Ctx->RegionSize = RegionSize;
406 Ctx->ThreadId = ThreadId;
407 }
408
409
410 static
411 VOID
412 SystemProcessTest(VOID)
413 {
414 NTSTATUS Status;
415 HANDLE Thread1 = INVALID_HANDLE_VALUE;
416 HANDLE Thread2 = INVALID_HANDLE_VALUE;
417 PVOID ThreadObjects[2] = { NULL };
418 OBJECT_ATTRIBUTES ObjectAttributes;
419 PTEST_CONTEXT StartContext1;
420 PTEST_CONTEXT StartContext2;
421
422 PAGED_CODE();
423
424 StartContext1 = ExAllocatePoolWithTag(PagedPool, sizeof(TEST_CONTEXT), 'tXTC');
425 StartContext2 = ExAllocatePoolWithTag(PagedPool, sizeof(TEST_CONTEXT), 'tXTC');
426 if (StartContext1 == NULL || StartContext2 == NULL)
427 {
428 trace("Error allocating space for context structs\n");
429 goto cleanup;
430 }
431
432 KmtInitTestContext(StartContext1, 1, 1 * 1024 * 1024, MEM_COMMIT, PAGE_READWRITE);
433 KmtInitTestContext(StartContext2, 2, 3 * 1024 * 1024, MEM_COMMIT, PAGE_READWRITE);
434 InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
435
436 Status = PsCreateSystemThread(&Thread1, THREAD_ALL_ACCESS, &ObjectAttributes, NULL, NULL, SystemProcessTestWorker, StartContext1);
437 if (!NT_SUCCESS(Status))
438 {
439 trace("Error creating thread1\n");
440 goto cleanup;
441 }
442
443 Status = ObReferenceObjectByHandle(Thread1, THREAD_ALL_ACCESS, PsThreadType, KernelMode, &ThreadObjects[0], NULL);
444 if (!NT_SUCCESS(Status))
445 {
446 trace("error referencing thread1\n");
447 goto cleanup;
448 }
449
450 Status = PsCreateSystemThread(&Thread2, THREAD_ALL_ACCESS, &ObjectAttributes, NULL, NULL, SystemProcessTestWorker, StartContext2);
451 if (!NT_SUCCESS(Status))
452 {
453 trace("Error creating thread2\n");
454 goto cleanup;
455 }
456
457 Status = ObReferenceObjectByHandle(Thread2, THREAD_ALL_ACCESS, PsThreadType, KernelMode, &ThreadObjects[1], NULL);
458 if (!NT_SUCCESS(Status))
459 {
460 trace("error referencing thread2\n");
461 goto cleanup;
462 }
463
464 cleanup:
465
466 if (ThreadObjects[0])
467 Status = KeWaitForSingleObject(ThreadObjects[0], Executive, KernelMode, FALSE, NULL);
468
469 if (StartContext1 != NULL)
470 ExFreePoolWithTag(StartContext1, 'tXTC');
471
472 if (ThreadObjects[1])
473 Status = KeWaitForSingleObject(ThreadObjects[1], Executive, KernelMode, FALSE, NULL);
474
475 if (StartContext2 != NULL)
476 ExFreePoolWithTag(StartContext2, 'tXTC');
477
478 if (ThreadObjects[0] != NULL)
479 ObDereferenceObject(ThreadObjects[0]);
480
481 if (ThreadObjects[1] != NULL)
482 ObDereferenceObject(ThreadObjects[1]);
483
484 if (Thread1 != INVALID_HANDLE_VALUE)
485 ZwClose(Thread1);
486
487 if (Thread2 != INVALID_HANDLE_VALUE)
488 ZwClose(Thread2);
489 }
490
491
492 START_TEST(ZwAllocateVirtualMemory)
493 {
494 NTSTATUS Status;
495
496 SimpleErrorChecks();
497
498 SimpleAllocation();
499
500 CustomBaseAllocation();
501
502 Status = StressTesting(MEM_RESERVE);
503 ok_eq_hex(Status, STATUS_NO_MEMORY);
504
505 Status = STATUS_SUCCESS;
506 Status = StressTesting(MEM_COMMIT);
507 ok_eq_hex(Status, STATUS_COMMITMENT_LIMIT);
508
509 SystemProcessTest();
510 }