1 /* 2 * PROJECT: ReactOS kernel-mode tests 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Kernel mode tests for process quotas 5 * COPYRIGHT: Copyright 2021 George Bișoc <george.bisoc@reactos.org> 6 */ 7 8 #include <kmt_test.h> 9 10 START_TEST(PsQuota) 11 { 12 NTSTATUS Status; 13 VM_COUNTERS VmCounters; 14 QUOTA_LIMITS QuotaLimits; 15 SIZE_T NonPagedUsage, PagedUsage; 16 PEPROCESS Process = PsGetCurrentProcess(); 17 18 /* Guard the quota operations in a guarded region */ 19 KeEnterGuardedRegion(); 20 21 /* Report the current process' quota limits */ 22 Status = ZwQueryInformationProcess(NtCurrentProcess(), 23 ProcessQuotaLimits, 24 &QuotaLimits, 25 sizeof(QuotaLimits), 26 NULL); 27 if (skip(NT_SUCCESS(Status), "Failed to query quota limits -- %lx\n", Status)) 28 { 29 return; 30 } 31 32 trace("Process paged pool quota limit -- %lu\n", QuotaLimits.PagedPoolLimit); 33 trace("Process non paged pool quota limit -- %lu\n", QuotaLimits.NonPagedPoolLimit); 34 trace("Process page file quota limit -- %lu\n\n", QuotaLimits.PagefileLimit); 35 36 /* Query the quota usage */ 37 Status = ZwQueryInformationProcess(NtCurrentProcess(), 38 ProcessVmCounters, 39 &VmCounters, 40 sizeof(VmCounters), 41 NULL); 42 if (skip(NT_SUCCESS(Status), "Failed to query quota usage -- %lx\n", Status)) 43 { 44 return; 45 } 46 47 /* Test that quotas usage are within limits */ 48 ok(VmCounters.QuotaNonPagedPoolUsage < QuotaLimits.NonPagedPoolLimit, "Non paged quota over limits (usage -> %lu || limit -> %lu)\n", 49 VmCounters.QuotaNonPagedPoolUsage, QuotaLimits.NonPagedPoolLimit); 50 ok(VmCounters.QuotaPagedPoolUsage < QuotaLimits.PagedPoolLimit, "Paged quota over limits (usage -> %lu || limit -> %lu)\n", 51 VmCounters.QuotaPagedPoolUsage, QuotaLimits.PagedPoolLimit); 52 53 /* Cache the quota usage pools for later checks */ 54 NonPagedUsage = VmCounters.QuotaNonPagedPoolUsage; 55 PagedUsage = VmCounters.QuotaPagedPoolUsage; 56 57 /* Charge some paged and non paged quotas */ 58 Status = PsChargeProcessNonPagedPoolQuota(Process, 0x200); 59 ok_irql(PASSIVE_LEVEL); 60 ok_eq_hex(Status, STATUS_SUCCESS); 61 62 Status = PsChargeProcessPagedPoolQuota(Process, 0x500); 63 ok_irql(PASSIVE_LEVEL); 64 ok_eq_hex(Status, STATUS_SUCCESS); 65 66 /* Query the quota usage again */ 67 Status = ZwQueryInformationProcess(NtCurrentProcess(), 68 ProcessVmCounters, 69 &VmCounters, 70 sizeof(VmCounters), 71 NULL); 72 if (skip(NT_SUCCESS(Status), "Failed to query quota usage -- %lx\n", Status)) 73 { 74 return; 75 } 76 77 78 /* Test again the usage that's within limits */ 79 ok(VmCounters.QuotaNonPagedPoolUsage < QuotaLimits.NonPagedPoolLimit, "Non paged quota over limits (usage -> %lu || limit -> %lu)\n", 80 VmCounters.QuotaNonPagedPoolUsage, QuotaLimits.NonPagedPoolLimit); 81 ok(VmCounters.QuotaPagedPoolUsage < QuotaLimits.PagedPoolLimit, "Paged quota over limits (usage -> %lu || limit -> %lu)\n", 82 VmCounters.QuotaPagedPoolUsage, QuotaLimits.PagedPoolLimit); 83 84 /* 85 * Make sure the results are consistent, that nobody else 86 * is charging quotas other than us. 87 */ 88 ok_eq_size(VmCounters.QuotaNonPagedPoolUsage, NonPagedUsage + 0x200); 89 ok_eq_size(VmCounters.QuotaPagedPoolUsage, PagedUsage + 0x500); 90 91 /* Report the quota usage */ 92 trace("=== QUOTA USAGE AFTER CHARGE ===\n\n"); 93 trace("Process paged pool quota usage -- %lu\n", VmCounters.QuotaPagedPoolUsage); 94 trace("Process paged pool quota peak -- %lu\n", VmCounters.QuotaPeakPagedPoolUsage); 95 trace("Process non paged pool quota usage -- %lu\n", VmCounters.QuotaNonPagedPoolUsage); 96 trace("Process non paged pool quota peak -- %lu\n", VmCounters.QuotaPeakNonPagedPoolUsage); 97 trace("Process page file quota usage -- %lu\n", VmCounters.PagefileUsage); 98 trace("Process page file quota peak -- %lu\n\n", VmCounters.PeakPagefileUsage); 99 100 /* Return the quotas we've charged up */ 101 PsReturnProcessNonPagedPoolQuota(Process, 0x200); 102 PsReturnProcessPagedPoolQuota(Process, 0x500); 103 104 /* Query the quota usage again */ 105 Status = ZwQueryInformationProcess(NtCurrentProcess(), 106 ProcessVmCounters, 107 &VmCounters, 108 sizeof(VmCounters), 109 NULL); 110 if (skip(NT_SUCCESS(Status), "Failed to query quota usage -- %lx\n", Status)) 111 { 112 return; 113 } 114 115 /* 116 * Check that nobody else has returned quotas 117 * but only us. 118 */ 119 ok_eq_size(VmCounters.QuotaNonPagedPoolUsage, NonPagedUsage); 120 ok_eq_size(VmCounters.QuotaPagedPoolUsage, PagedUsage); 121 122 /* Report the usage again */ 123 trace("=== QUOTA USAGE AFTER RETURN ===\n\n"); 124 trace("Process paged pool quota usage -- %lu\n", VmCounters.QuotaPagedPoolUsage); 125 trace("Process paged pool quota peak -- %lu\n", VmCounters.QuotaPeakPagedPoolUsage); 126 trace("Process non paged pool quota usage -- %lu\n", VmCounters.QuotaNonPagedPoolUsage); 127 trace("Process non paged pool quota peak -- %lu\n", VmCounters.QuotaPeakNonPagedPoolUsage); 128 trace("Process page file quota usage -- %lu\n", VmCounters.PagefileUsage); 129 trace("Process page file quota peak -- %lu\n\n", VmCounters.PeakPagefileUsage); 130 131 /* We're done, leave the region */ 132 KeLeaveGuardedRegion(); 133 } 134