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 PVOID __BaseSave = BaseAddress; \
35 Status = ZwAllocateVirtualMemory(ProcessHandle, &BaseAddress, ZeroBits, &RegionSize, AllocationType, Protect); \
36 ok_eq_hex(Status, RetStatus); \
37 if (__BaseSave != NULL) \
38 ok_eq_pointer(BaseAddress, __BaseSave); \
39 else if (!NT_SUCCESS(Status)) \
40 ok_eq_pointer(BaseAddress, NULL); \
41 RegionSize = 0; \
42 Status = ZwFreeVirtualMemory(ProcessHandle, &BaseAddress, &RegionSize, MEM_RELEASE); \
43 if (FreeStatus != IGNORE) ok_eq_hex(Status, FreeStatus); \
44 BaseAddress = NULL; \
45 RegionSize = DEFAULT_ALLOC_SIZE; \
46 } while (0) \
47
48
49
50 static
51 BOOLEAN
CheckBuffer(PVOID Buffer,SIZE_T Size,UCHAR Value)52 CheckBuffer(PVOID Buffer, SIZE_T Size, UCHAR Value)
53 {
54 PUCHAR Array = Buffer;
55 SIZE_T i;
56
57 for (i = 0; i < Size; i++)
58 {
59 if (Array[i] != Value)
60 {
61 trace("Expected %x, found %x at offset %lu\n", Value, Array[i], (ULONG)i);
62 return FALSE;
63 }
64 }
65 return TRUE;
66 }
67
68 static
69 SIZE_T
CheckBufferRead(CONST VOID * Source,CONST VOID * Destination,SIZE_T Length,NTSTATUS ExpectedStatus)70 CheckBufferRead(CONST VOID *Source, CONST VOID *Destination, SIZE_T Length, NTSTATUS ExpectedStatus)
71 {
72 SIZE_T Match = 0;
73
74 KmtStartSeh()
75 Match = RtlCompareMemory(Source, Destination, Length);
76 KmtEndSeh(ExpectedStatus);
77
78 return Match;
79 }
80
81 static
82 VOID
CheckBufferReadWrite(PVOID Destination,CONST VOID * Source,SIZE_T Length,NTSTATUS ExpectedStatus)83 CheckBufferReadWrite(PVOID Destination, CONST VOID *Source, SIZE_T Length, NTSTATUS ExpectedStatus)
84 {
85 //do a little bit of writing/reading to memory
86 SIZE_T Match = 0;
87
88 KmtStartSeh()
89 RtlCopyMemory(Destination, Source, Length);
90 KmtEndSeh(ExpectedStatus);
91
92 Match = CheckBufferRead(Source, Destination, Length, ExpectedStatus);
93 if (ExpectedStatus == STATUS_SUCCESS) ok_eq_int(Match, Length);
94 }
95
96
97 static
98 VOID
SimpleErrorChecks(VOID)99 SimpleErrorChecks(VOID)
100 {
101 NTSTATUS Status;
102 PVOID Base = NULL;
103 SIZE_T RegionSize = DEFAULT_ALLOC_SIZE;
104
105 //HANDLE TESTS
106 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS);
107 ALLOC_MEMORY_WITH_FREE(NULL, Base, 0, RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE, STATUS_INVALID_HANDLE, STATUS_INVALID_HANDLE);
108 ALLOC_MEMORY_WITH_FREE((HANDLE)(ULONG_PTR)0xDEADBEEFDEADBEEFull, Base, 0, RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE, STATUS_INVALID_HANDLE, STATUS_INVALID_HANDLE);
109
110 //BASE ADDRESS TESTS
111 Base = (PVOID)0x00567A20;
112 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE, STATUS_CONFLICTING_ADDRESSES, STATUS_UNABLE_TO_DELETE_SECTION);
113
114 Base = (PVOID) 0x60000000;
115 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS);
116
117 Base = (PVOID)((char *)MmSystemRangeStart + 200);
118 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE, STATUS_INVALID_PARAMETER_2, STATUS_INVALID_PARAMETER_2);
119
120 /* http://jira.reactos.org/browse/CORE-6814 */
121 RegionSize = 0x1000;
122 Base = Test_ZwAllocateVirtualMemory;
123 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, MEM_COMMIT, PAGE_READWRITE, STATUS_INVALID_PARAMETER_2, STATUS_INVALID_PARAMETER_2);
124
125 //ZERO BITS TESTS
126 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 21, RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE, STATUS_NO_MEMORY, STATUS_MEMORY_NOT_ALLOCATED);
127 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 22, RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE, STATUS_INVALID_PARAMETER_3, STATUS_MEMORY_NOT_ALLOCATED);
128 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, -1, RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE, STATUS_INVALID_PARAMETER_3, STATUS_MEMORY_NOT_ALLOCATED);
129 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 3, RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS);
130
131 //REGION SIZE TESTS
132 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS);
133 RegionSize = -1;
134 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE, STATUS_INVALID_PARAMETER_4, STATUS_MEMORY_NOT_ALLOCATED);
135 RegionSize = 0;
136 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE, STATUS_INVALID_PARAMETER_4, STATUS_MEMORY_NOT_ALLOCATED);
137 RegionSize = 0xFFFFFFFF; // 4 gb is invalid
138 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE, STATUS_INVALID_PARAMETER_4, STATUS_MEMORY_NOT_ALLOCATED);
139
140 //Allocation type tests
141 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, MEM_PHYSICAL, PAGE_READWRITE, STATUS_INVALID_PARAMETER_5, STATUS_MEMORY_NOT_ALLOCATED);
142 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_COMMIT | MEM_RESET), PAGE_READWRITE, STATUS_INVALID_PARAMETER_5, STATUS_MEMORY_NOT_ALLOCATED);
143 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, 0, PAGE_READWRITE, STATUS_INVALID_PARAMETER_5, STATUS_MEMORY_NOT_ALLOCATED);
144 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, MEM_TOP_DOWN, PAGE_READWRITE, STATUS_INVALID_PARAMETER_5, STATUS_MEMORY_NOT_ALLOCATED);
145 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_TOP_DOWN | MEM_RESET), PAGE_READWRITE, STATUS_INVALID_PARAMETER_5, STATUS_MEMORY_NOT_ALLOCATED);
146 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_TOP_DOWN | MEM_COMMIT), PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS);
147 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_PHYSICAL | MEM_RESERVE), PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS);
148 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_PHYSICAL | MEM_COMMIT), PAGE_READWRITE, STATUS_INVALID_PARAMETER_5, STATUS_MEMORY_NOT_ALLOCATED);
149 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_RESET | MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE, STATUS_INVALID_PARAMETER_5, STATUS_MEMORY_NOT_ALLOCATED);
150 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, -1, PAGE_READWRITE, STATUS_INVALID_PARAMETER_5, STATUS_MEMORY_NOT_ALLOCATED);
151 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, MEM_COMMIT, PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS);
152 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, MEM_RESERVE, PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS);
153 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, MEM_RESERVE, PAGE_WRITECOPY, STATUS_INVALID_PAGE_PROTECTION, STATUS_MEMORY_NOT_ALLOCATED);
154 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, MEM_RESERVE, PAGE_EXECUTE_WRITECOPY, STATUS_INVALID_PAGE_PROTECTION, STATUS_MEMORY_NOT_ALLOCATED);
155
156 //Memory protection tests
157 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_COMMIT | MEM_RESERVE), 0, STATUS_INVALID_PAGE_PROTECTION, STATUS_MEMORY_NOT_ALLOCATED);
158 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_COMMIT | MEM_RESERVE), -1, STATUS_INVALID_PAGE_PROTECTION, STATUS_MEMORY_NOT_ALLOCATED);
159 if (!KmtIsCheckedBuild)
160 {
161 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_COMMIT | MEM_RESERVE), (PAGE_NOACCESS | PAGE_GUARD), STATUS_INVALID_PAGE_PROTECTION, STATUS_MEMORY_NOT_ALLOCATED);
162 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_COMMIT | MEM_RESERVE), (PAGE_NOACCESS | PAGE_WRITECOMBINE), STATUS_INVALID_PAGE_PROTECTION, STATUS_MEMORY_NOT_ALLOCATED);
163 }
164 ALLOC_MEMORY_WITH_FREE(NtCurrentProcess(), Base, 0, RegionSize, (MEM_COMMIT | MEM_RESERVE), (PAGE_READONLY | PAGE_WRITECOMBINE), STATUS_SUCCESS, STATUS_SUCCESS);
165 }
166
167
168 static
169 NTSTATUS
SimpleAllocation(VOID)170 SimpleAllocation(VOID)
171 {
172 NTSTATUS Status;
173 PVOID Base = NULL;
174 SIZE_T RegionSize = DEFAULT_ALLOC_SIZE;
175
176 //////////////////////////////////////////////////////////////////////////
177 //Normal operation
178 //////////////////////////////////////////////////////////////////////////
179 Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &Base, 0, &RegionSize, MEM_COMMIT, PAGE_READWRITE);
180 ok_eq_size(RegionSize, 4096);
181
182 //check for the zero-filled pages
183 ok_bool_true(CheckBuffer(Base, RegionSize, 0), "The buffer is not zero-filled");
184
185 CheckBufferReadWrite(Base, TestString, TestStringSize, STATUS_SUCCESS);
186
187 // try freeing
188 RegionSize = 0;
189 Status = ZwFreeVirtualMemory(NtCurrentProcess(), &Base, &RegionSize, MEM_RELEASE);
190 ok_eq_hex(Status, STATUS_SUCCESS);
191 ok_eq_size(RegionSize, PAGE_SIZE);
192
193 //////////////////////////////////////////////////////////////////////////
194 // COMMIT AND RESERVE SCENARIO AND STATE CHANGE
195 //////////////////////////////////////////////////////////////////////////
196 //reserve and then commit
197 Base = NULL;
198 RegionSize = DEFAULT_ALLOC_SIZE;
199 Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &Base, 0, &RegionSize, MEM_RESERVE, PAGE_READWRITE);
200 Test_NtQueryVirtualMemory(Base, RegionSize, MEM_RESERVE, PAGE_NOPROT);
201 CheckBufferReadWrite(Base, TestString, TestStringSize, STATUS_ACCESS_VIOLATION);
202
203
204 Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &Base, 0, &RegionSize, MEM_COMMIT, PAGE_READWRITE);
205 CheckBufferReadWrite(Base, TestString, TestStringSize, STATUS_SUCCESS);
206 Test_NtQueryVirtualMemory(Base, RegionSize, MEM_COMMIT, PAGE_READWRITE);
207
208 RegionSize = 0;
209 ZwFreeVirtualMemory(NtCurrentProcess(), &Base, &RegionSize, MEM_RELEASE);
210
211 //////////////////////////////////////////////////////////////////////////
212 // TRY READING/WRITING TO INVALID PROTECTION PAGES
213 //////////////////////////////////////////////////////////////////////////
214 RegionSize = DEFAULT_ALLOC_SIZE;
215 Base = NULL;
216 ZwAllocateVirtualMemory(NtCurrentProcess(), &Base, 0, &RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_NOACCESS);
217
218 KmtStartSeh()
219 RtlCopyMemory(Base, TestString, TestStringSize);
220 KmtEndSeh(STATUS_ACCESS_VIOLATION);
221
222 Test_NtQueryVirtualMemory(Base, RegionSize, MEM_COMMIT, PAGE_NOACCESS);
223 CheckBufferRead(Base, TestString, TestStringSize, STATUS_ACCESS_VIOLATION);
224
225 RegionSize = 0;
226 ZwFreeVirtualMemory(NtCurrentProcess(), &Base, &RegionSize, MEM_RELEASE);
227
228 ZwAllocateVirtualMemory(NtCurrentProcess(), &Base, 0, &RegionSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READONLY);
229 KmtStartSeh()
230 RtlCopyMemory(Base, TestString, TestStringSize);
231 KmtEndSeh(STATUS_ACCESS_VIOLATION);
232
233 Test_NtQueryVirtualMemory(Base, RegionSize, MEM_COMMIT, PAGE_READONLY);
234
235 ok_bool_true(CheckBuffer(Base, TestStringSize, 0), "Couldn't read a read-only buffer");
236
237 RegionSize = 0;
238 ZwFreeVirtualMemory(NtCurrentProcess(), &Base, &RegionSize, MEM_RELEASE);
239
240 //////////////////////////////////////////////////////////////////////////
241 // GUARD PAGES
242 //////////////////////////////////////////////////////////////////////////
243
244 RegionSize = 1000;
245 Base = NULL;
246 ZwAllocateVirtualMemory(NtCurrentProcess(), &Base, 0, &RegionSize, (MEM_COMMIT | MEM_RESERVE), (PAGE_GUARD | PAGE_READWRITE));
247
248 Test_NtQueryVirtualMemory(Base, RegionSize, MEM_COMMIT, (PAGE_GUARD | PAGE_READWRITE));
249 KmtStartSeh()
250 RtlCopyMemory(Base, TestString, TestStringSize);
251 KmtEndSeh(STATUS_GUARD_PAGE_VIOLATION);
252
253 Test_NtQueryVirtualMemory(Base, RegionSize, MEM_COMMIT, PAGE_READWRITE);
254
255 KmtStartSeh()
256 RtlCopyMemory(Base, TestString, TestStringSize);
257 KmtEndSeh(STATUS_SUCCESS);
258
259 RegionSize = 0;
260 ZwFreeVirtualMemory(NtCurrentProcess(), &Base, &RegionSize, MEM_RELEASE);
261
262 return Status;
263 }
264
265
266 static
267 VOID
CustomBaseAllocation(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
StressTesting(ULONG AllocationType)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
SystemProcessTestWorker(PVOID StartContext)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
KmtInitTestContext(PTEST_CONTEXT Ctx,SHORT ThreadId,ULONG RegionSize,ULONG AllocationType,ULONG Protect)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
SystemProcessTest(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
START_TEST(ZwAllocateVirtualMemory)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_NO_MEMORY);
510
511 SystemProcessTest();
512 }
513