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