ReactOS 0.4.15-dev-7968-g24a56f8
quota.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Process Pool Quotas Support
5 * COPYRIGHT: Copyright 2005 Alex Ionescu <alex@relsoft.net>
6 * Copyright 2007 Mike Nordell
7 * Copyright 2021 George Bișoc <george.bisoc@reactos.org>
8 */
9
10/* INCLUDES **************************************************************/
11
12#include <ntoskrnl.h>
13#define NDEBUG
14#include <debug.h>
15
19
20#define VALID_QUOTA_FLAGS (QUOTA_LIMITS_HARDWS_MIN_ENABLE | \
21 QUOTA_LIMITS_HARDWS_MIN_DISABLE | \
22 QUOTA_LIMITS_HARDWS_MAX_ENABLE | \
23 QUOTA_LIMITS_HARDWS_MAX_DISABLE)
24
25/* PRIVATE FUNCTIONS *******************************************************/
26
48VOID
50PspReturnQuotasOnDestroy(
51 _In_ PEPROCESS_QUOTA_BLOCK QuotaBlock)
52{
53 ULONG PsQuotaTypeIndex;
55
56 /*
57 * We must be in a dispatch level interrupt here
58 * as we should be under a spin lock.
59 */
61
62 /* Make sure that the quota block is not plain garbage */
63 ASSERT(QuotaBlock);
64
65 /* Loop over the Process quota types */
66 for (PsQuotaTypeIndex = PsNonPagedPool; PsQuotaTypeIndex < PsPageFile; PsQuotaTypeIndex++)
67 {
68 /* The amount needed to return to Mm is the limit and return fields */
69 QuotaToReturn = QuotaBlock->QuotaEntry[PsQuotaTypeIndex].Limit + QuotaBlock->QuotaEntry[PsQuotaTypeIndex].Return;
70 MmReturnPoolQuota(PsQuotaTypeIndex, QuotaToReturn);
71 }
72}
73
98VOID
100PspReturnExcessQuotas(
101 _In_ PS_QUOTA_TYPE QuotaType,
102 _Outptr_ PSIZE_T ReturnedQuotas)
103{
104 PLIST_ENTRY PspQuotaList;
105 PEPROCESS_QUOTA_BLOCK QuotaBlockFromList;
106 SIZE_T AmountToReturn = 0;
107
108 /*
109 * We must be in a dispatch level interrupt here
110 * as we should be under a spin lock.
111 */
113
114 /*
115 * Loop over the quota block lists and reap
116 * whatever quotas we haven't returned which
117 * is needed to free up resources.
118 */
119 for (PspQuotaList = PspQuotaBlockList.Flink;
120 PspQuotaList != &PspQuotaBlockList;
121 PspQuotaList = PspQuotaList->Flink)
122 {
123 /* Gather the quota block from the list */
124 QuotaBlockFromList = CONTAINING_RECORD(PspQuotaList, EPROCESS_QUOTA_BLOCK, QuotaList);
125
126 /*
127 * Gather any unreturned quotas and cache
128 * them to a variable.
129 */
130 AmountToReturn += InterlockedExchangeSizeT(&QuotaBlockFromList->QuotaEntry[QuotaType].Return, 0);
131
132 /*
133 * If no other process is taking use of this
134 * block, then it means that this block has
135 * only shared pool quota and the last process
136 * no longer uses this block. If the limit is
137 * grater than the usage then trim the limit
138 * and use that as additional amount of quota
139 * to return.
140 */
141 if (QuotaBlockFromList->ProcessCount == 0)
142 {
143 if (QuotaBlockFromList->QuotaEntry[QuotaType].Usage <
144 QuotaBlockFromList->QuotaEntry[QuotaType].Limit)
145 {
146 InterlockedExchangeSizeT(&QuotaBlockFromList->QuotaEntry[QuotaType].Limit,
147 QuotaBlockFromList->QuotaEntry[QuotaType].Usage);
148 AmountToReturn += QuotaBlockFromList->QuotaEntry[QuotaType].Limit;
149 }
150 }
151 }
152
153 /* Invoke Mm to return quotas */
154 DPRINT("PspReturnExcessQuotas(): Amount of quota released -- %lu\n", AmountToReturn);
155 MmReturnPoolQuota(QuotaType, AmountToReturn);
156 *ReturnedQuotas = AmountToReturn;
157}
158
194NTAPI
197 _In_ PEPROCESS_QUOTA_BLOCK QuotaBlock,
198 _In_ PS_QUOTA_TYPE QuotaType,
200{
202 SIZE_T ReturnedQuotas;
203 SIZE_T UpdatedLimit;
204
205 /* Sanity checks */
206 ASSERT(QuotaType < PsQuotaTypes);
207 ASSERT((SSIZE_T)Amount >= 0);
208
209 /* Guard ourselves in a spin lock */
211
212 /* Are we within the bounds of quota limit? */
213 if (QuotaBlock->QuotaEntry[QuotaType].Usage + Amount >
214 QuotaBlock->QuotaEntry[QuotaType].Limit &&
215 QuotaBlock != &PspDefaultQuotaBlock)
216 {
217 /* We aren't... Is this a page file quota charging? */
218 if (QuotaType == PsPageFile)
219 {
220 /* It is, return the appropriate status code */
221 DPRINT1("PspChargeProcessQuotaSpecifiedPool(): Quota amount exceeds the limit on page file quota (limit -- %lu || amount -- %lu)\n",
222 QuotaBlock->QuotaEntry[QuotaType].Limit, Amount);
224 }
225
226 /*
227 * This is not a page file charge. What we can do at best
228 * in this scenario is to attempt to raise (expand) the
229 * quota limit charges of the block.
230 */
231 if (!MmRaisePoolQuota(QuotaType,
232 QuotaBlock->QuotaEntry[QuotaType].Limit,
233 &UpdatedLimit))
234 {
235 /*
236 * We can't? It could be that we must free
237 * up some resources in order to raise the
238 * limit, which in that case we must return
239 * the excess of quota that hasn't been
240 * returned. If we haven't returned anything
241 * then what we're doing here is futile.
242 * Bail out...
243 */
244 PspReturnExcessQuotas(QuotaType, &ReturnedQuotas);
245 if (ReturnedQuotas == 0)
246 {
247 DPRINT1("PspChargeProcessQuotaSpecifiedPool(): Failed to free some resources in order to raise quota limits...\n");
250 }
251
252 /* Try to raise the quota limits again */
253 MmRaisePoolQuota(QuotaType,
254 QuotaBlock->QuotaEntry[QuotaType].Limit,
255 &UpdatedLimit);
256 }
257
258 /* Enforce a new raised limit */
259 InterlockedExchangeSizeT(&QuotaBlock->QuotaEntry[QuotaType].Limit, UpdatedLimit);
260
261 /*
262 * Now determine if the current usage and the
263 * amounting by the caller still exceeds the
264 * quota limit of the process. If it's still
265 * over the limit then there's nothing we can
266 * do, so fail.
267 */
268 if (QuotaBlock->QuotaEntry[QuotaType].Usage + Amount >
269 QuotaBlock->QuotaEntry[QuotaType].Limit)
270 {
271 DPRINT1("PspChargeProcessQuotaSpecifiedPool(): Quota amount exceeds the limit (limit -- %lu || amount -- %lu)\n",
272 QuotaBlock->QuotaEntry[QuotaType].Limit, Amount);
274 }
275 }
276
277 /* Update the quota usage */
278 InterlockedExchangeAddSizeT(&QuotaBlock->QuotaEntry[QuotaType].Usage, Amount);
279
280 /* Update the entry peak if it's less than the usage */
281 if (QuotaBlock->QuotaEntry[QuotaType].Peak <
282 QuotaBlock->QuotaEntry[QuotaType].Usage)
283 {
284 InterlockedExchangeSizeT(&QuotaBlock->QuotaEntry[QuotaType].Peak,
285 QuotaBlock->QuotaEntry[QuotaType].Usage);
286 }
287
288 /* Are we being given a process as well? */
289 if (Process)
290 {
291 /* We're being given, check that's not a system one */
293
294 InterlockedExchangeAddSizeT(&Process->QuotaUsage[QuotaType], Amount);
295
296 /*
297 * OK, we've now updated the quota usage of the process
298 * based upon the amount that the caller wanted to charge.
299 * Although the peak of process quota can be less than it was
300 * before so update the peaks as well accordingly.
301 */
302 if (Process->QuotaPeak[QuotaType] < Process->QuotaUsage[QuotaType])
303 {
304 InterlockedExchangeSizeT(&Process->QuotaPeak[QuotaType],
305 Process->QuotaUsage[QuotaType]);
306 }
307 }
308
309 /* Release the lock */
311 return STATUS_SUCCESS;
312}
313
343VOID
344NTAPI
347 _In_ PEPROCESS_QUOTA_BLOCK QuotaBlock,
348 _In_ PS_QUOTA_TYPE QuotaType,
350{
352 SIZE_T ReturnThreshold;
353 SIZE_T AmountToReturn = 0;
354
355 /* Sanity checks */
356 ASSERT(QuotaType < PsQuotaTypes);
357 ASSERT((SSIZE_T)Amount >= 0);
358
359 /* Guard ourselves in a spin lock */
361
362 /* Does the caller return more quota than it was previously charged? */
363 if ((Process && Process->QuotaUsage[QuotaType] < Amount) ||
364 QuotaBlock->QuotaEntry[QuotaType].Usage < Amount)
365 {
366 /* It does, crash the system! */
367 KeBugCheckEx(QUOTA_UNDERFLOW,
369 (ULONG_PTR)QuotaType,
370 Process ? (ULONG_PTR)Process->QuotaUsage[QuotaType] :
371 QuotaBlock->QuotaEntry[QuotaType].Usage,
373 }
374
375 /* The return threshold can be non paged or paged */
377
378 /*
379 * We need to trim the quota limits based on the
380 * amount we're going to return quotas back.
381 */
382 if ((QuotaType != PsPageFile && QuotaBlock != &PspDefaultQuotaBlock) &&
383 (QuotaBlock->QuotaEntry[QuotaType].Limit > QuotaBlock->QuotaEntry[QuotaType].Usage + ReturnThreshold))
384 {
385 /*
386 * If the amount to return exceeds the threshold,
387 * the new amount becomes the default, otherwise
388 * the amount is just the one given by the caller.
389 */
390 AmountToReturn = min(Amount, ReturnThreshold);
391
392 /* Add up the lots to the Return field */
393 InterlockedExchangeAddSizeT(&QuotaBlock->QuotaEntry[QuotaType].Return, AmountToReturn);
394
395 /*
396 * If the amount to return exceeds the threshold then
397 * we have lots of quota to return to Mm. So do it so
398 * and zerou out the Return field.
399 */
400 if (QuotaBlock->QuotaEntry[QuotaType].Return > ReturnThreshold)
401 {
402 MmReturnPoolQuota(QuotaType, QuotaBlock->QuotaEntry[QuotaType].Return);
403 InterlockedExchangeSizeT(QuotaBlock->QuotaEntry[QuotaType].Return, 0);
404 }
405
406 /* And try to trim the limit */
407 InterlockedExchangeSizeT(&QuotaBlock->QuotaEntry[QuotaType].Limit,
408 QuotaBlock->QuotaEntry[QuotaType].Limit - AmountToReturn);
409 }
410
411 /* Update the usage member of the block */
412 InterlockedExchangeAddSizeT(&QuotaBlock->QuotaEntry[QuotaType].Usage, -(LONG_PTR)Amount);
413
414 /* Are we being given a process? */
415 if (Process)
416 {
417 /* We're being given, check that's not a system one */
419
420 /* Decrease the process' quota usage */
421 InterlockedExchangeAddSizeT(&Process->QuotaUsage[QuotaType], -(LONG_PTR)Amount);
422 }
423
424 /* We're done, release the lock */
426}
427
428/* FUNCTIONS ***************************************************************/
429
440CODE_SEG("INIT")
441VOID
442NTAPI
444{
445 /* Initialize the default block */
447
448 /* Assign the default quota limits */
452
453 /*
454 * Set up the count references as the
455 * default block will going to be used.
456 */
459
460 /* Assign that block to initial process */
462}
463
481VOID
482NTAPI
485 _In_opt_ PEPROCESS ParentProcess)
486{
487 PEPROCESS_QUOTA_BLOCK QuotaBlock;
488
489 if (ParentProcess != NULL)
490 {
491 ASSERT(ParentProcess->QuotaBlock != NULL);
492 QuotaBlock = ParentProcess->QuotaBlock;
493 }
494 else
495 {
496 QuotaBlock = &PspDefaultQuotaBlock;
497 }
498
501
502 Process->QuotaBlock = QuotaBlock;
503}
504
516VOID
517NTAPI
519 _In_ PEPROCESS_QUOTA_BLOCK QuotaBlock)
520{
522
524 InsertTailList(&PspQuotaBlockList, &QuotaBlock->QuotaList);
526}
527
551VOID
552NTAPI
555 _In_ PEPROCESS_QUOTA_BLOCK QuotaBlock)
556{
557 ULONG PsQuotaTypeIndex;
559
560 /* Make sure the quota block is not trash */
561 ASSERT(QuotaBlock);
562
563 /* Iterate over the process quota types if we have a process */
564 if (Process)
565 {
566 for (PsQuotaTypeIndex = PsNonPagedPool; PsQuotaTypeIndex < PsQuotaTypes; PsQuotaTypeIndex++)
567 {
568 /*
569 * We need to make sure that the quota usage
570 * uniquely associated with the process is 0
571 * on that moment the process gets destroyed.
572 */
573 ASSERT(Process->QuotaUsage[PsQuotaTypeIndex] == 0);
574 }
575
576 /* As the process is now gone, decrement the process count */
577 InterlockedDecrementUL(&QuotaBlock->ProcessCount);
578 }
579
580 /* If no one is using this block, begin to destroy it */
581 if (QuotaBlock != &PspDefaultQuotaBlock &&
582 InterlockedDecrementUL(&QuotaBlock->ReferenceCount) == 0)
583 {
584 /* Acquire the quota lock */
586
587 /* Return all the quotas back to Mm and remove the quota from list */
588 PspReturnQuotasOnDestroy(QuotaBlock);
589 RemoveEntryList(&QuotaBlock->QuotaList);
590
591 /* Release the lock and free the block */
594 }
595}
596
619VOID
620NTAPI
622 _In_ PEPROCESS_QUOTA_BLOCK QuotaBlock,
623 _In_ SIZE_T AmountToReturnPaged,
624 _In_ SIZE_T AmountToReturnNonPaged)
625{
626 /* Sanity check */
627 ASSERT(QuotaBlock);
628
629 /* Return the pool quotas if there're any */
630 if (AmountToReturnPaged != 0)
631 {
632 PspReturnProcessQuotaSpecifiedPool(NULL, QuotaBlock, PsPagedPool, AmountToReturnPaged);
633 }
634
635 if (AmountToReturnNonPaged != 0)
636 {
637 PspReturnProcessQuotaSpecifiedPool(NULL, QuotaBlock, PsNonPagedPool, AmountToReturnNonPaged);
638 }
639
640 DPRINT("PsReturnSharedPoolQuota(): Amount returned back (paged %lu -- non paged %lu)\n", AmountToReturnPaged, AmountToReturnNonPaged);
641
642 /* Dereference the quota block */
643 PspDereferenceQuotaBlock(NULL, QuotaBlock);
644}
645
673NTAPI
676 _In_ SIZE_T AmountToChargePaged,
677 _In_ SIZE_T AmountToChargeNonPaged)
678{
680
681 /* Sanity checks */
683 ASSERT(Process->QuotaBlock);
684
685 /* Do we have some paged pool quota to charge? */
686 if (AmountToChargePaged != 0)
687 {
688 /* We do, charge! */
689 Status = PspChargeProcessQuotaSpecifiedPool(NULL, Process->QuotaBlock, PsPagedPool, AmountToChargePaged);
690 if (!NT_SUCCESS(Status))
691 {
692 DPRINT1("PsChargeSharedPoolQuota(): Failed to charge the shared pool quota (Status 0x%lx)\n", Status);
693 return NULL;
694 }
695 }
696
697 /* Do we have some non paged pool quota to charge? */
698 if (AmountToChargeNonPaged != 0)
699 {
700 /* We do, charge! */
701 Status = PspChargeProcessQuotaSpecifiedPool(NULL, Process->QuotaBlock, PsNonPagedPool, AmountToChargeNonPaged);
702 if (!NT_SUCCESS(Status))
703 {
704 DPRINT1("PsChargeSharedPoolQuota(): Failed to charge the shared pool quota (Status 0x%lx). Attempting to return some paged pool back...\n", Status);
705 PspReturnProcessQuotaSpecifiedPool(NULL, Process->QuotaBlock, PsPagedPool, AmountToChargePaged);
706 return NULL;
707 }
708 }
709
710 /* We have charged the quotas of an object, increment the reference */
711 InterlockedIncrementSizeT(&Process->QuotaBlock->ReferenceCount);
712
713 DPRINT("PsChargeSharedPoolQuota(): Amount charged (paged %lu -- non paged %lu)\n", AmountToChargePaged, AmountToChargeNonPaged);
714 return Process->QuotaBlock;
715}
716
737NTAPI
741{
742 /* Don't do anything for the system process */
744
746}
747
773VOID
774NTAPI
779{
782
783 /* Don't do anything for the system process */
784 if (Process == PsInitialSystemProcess) return;
785
786 /* Charge the usage */
789}
790
810NTAPI
814{
815 /* Call the general function */
817}
818
838NTAPI
842{
843 /* Call the general function */
845}
846
871NTAPI
876{
877 /* Don't do anything for the system process */
879
881 Process->QuotaBlock,
883 Amount);
884}
885
905VOID
906NTAPI
911{
912 /* Don't do anything for the system process */
913 if (Process == PsInitialSystemProcess) return;
914
916 Process->QuotaBlock,
918 Amount);
919}
920
936VOID
937NTAPI
941{
942 /* Don't do anything for the system process */
943 if (Process == PsInitialSystemProcess) return;
944
946}
947
963VOID
964NTAPI
968{
969 /* Don't do anything for the system process */
970 if (Process == PsInitialSystemProcess) return;
971
973}
974
992NTAPI
996{
997 /* Don't do anything for the system process */
999
1001 return STATUS_SUCCESS;
1002}
1003
1044NTAPI
1048 _In_ PVOID QuotaLimits,
1049 _In_ ULONG QuotaLimitsLength,
1051{
1052 QUOTA_LIMITS_EX CapturedQuotaLimits;
1053 PEPROCESS_QUOTA_BLOCK QuotaBlock, OldQuotaBlock;
1054 BOOLEAN IncreaseOkay;
1055 KAPC_STATE SavedApcState;
1057
1059
1060 _SEH2_TRY
1061 {
1062 ProbeForRead(QuotaLimits, QuotaLimitsLength, sizeof(ULONG));
1063
1064 /* Check if we have the basic or extended structure */
1065 if (QuotaLimitsLength == sizeof(QUOTA_LIMITS))
1066 {
1067 /* Copy the basic structure, zero init the remaining fields */
1068 RtlCopyMemory(&CapturedQuotaLimits, QuotaLimits, sizeof(QUOTA_LIMITS));
1069 CapturedQuotaLimits.WorkingSetLimit = 0;
1070 CapturedQuotaLimits.Reserved2 = 0;
1071 CapturedQuotaLimits.Reserved3 = 0;
1072 CapturedQuotaLimits.Reserved4 = 0;
1073 CapturedQuotaLimits.CpuRateLimit.RateData = 0;
1074 CapturedQuotaLimits.Flags = 0;
1075 }
1076 else if (QuotaLimitsLength == sizeof(QUOTA_LIMITS_EX))
1077 {
1078 /* Copy the full structure */
1079 RtlCopyMemory(&CapturedQuotaLimits, QuotaLimits, sizeof(QUOTA_LIMITS_EX));
1080
1081 /* Verify that the caller passed valid flags */
1082 if ((CapturedQuotaLimits.Flags & ~VALID_QUOTA_FLAGS) ||
1083 ((CapturedQuotaLimits.Flags & QUOTA_LIMITS_HARDWS_MIN_ENABLE) &&
1084 (CapturedQuotaLimits.Flags & QUOTA_LIMITS_HARDWS_MIN_DISABLE)) ||
1085 ((CapturedQuotaLimits.Flags & QUOTA_LIMITS_HARDWS_MAX_ENABLE) &&
1086 (CapturedQuotaLimits.Flags & QUOTA_LIMITS_HARDWS_MAX_DISABLE)))
1087 {
1088 DPRINT1("Invalid quota flags: 0x%lx\n", CapturedQuotaLimits.Flags);
1090 }
1091
1092 /* Verify that the caller didn't pass reserved values */
1093 if ((CapturedQuotaLimits.WorkingSetLimit != 0) ||
1094 (CapturedQuotaLimits.Reserved2 != 0) ||
1095 (CapturedQuotaLimits.Reserved3 != 0) ||
1096 (CapturedQuotaLimits.Reserved4 != 0) ||
1097 (CapturedQuotaLimits.CpuRateLimit.RateData != 0))
1098 {
1099 DPRINT1("Invalid value: (%lx,%lx,%lx,%lx,%lx)\n",
1100 CapturedQuotaLimits.WorkingSetLimit,
1101 CapturedQuotaLimits.Reserved2,
1102 CapturedQuotaLimits.Reserved3,
1103 CapturedQuotaLimits.Reserved4,
1104 CapturedQuotaLimits.CpuRateLimit.RateData);
1106 }
1107 }
1108 else
1109 {
1110 DPRINT1("Invalid quota size: 0x%lx\n", QuotaLimitsLength);
1112 }
1113 }
1115 {
1116 DPRINT1("Exception while copying data\n");
1118 }
1119 _SEH2_END;
1120
1121 /* Check the caller changes the working set size limits */
1122 if ((CapturedQuotaLimits.MinimumWorkingSetSize != 0) &&
1123 (CapturedQuotaLimits.MaximumWorkingSetSize != 0))
1124 {
1125 /* Check for special case: trimming the WS */
1126 if ((CapturedQuotaLimits.MinimumWorkingSetSize == SIZE_T_MAX) &&
1127 (CapturedQuotaLimits.MaximumWorkingSetSize == SIZE_T_MAX))
1128 {
1129 /* No increase allowed */
1130 IncreaseOkay = FALSE;
1131 }
1132 else
1133 {
1134 /* Check if the caller has the required privilege */
1136 PreviousMode);
1137 }
1138
1139 /* Attach to the target process and disable APCs */
1140 KeStackAttachProcess(&Process->Pcb, &SavedApcState);
1142
1143 /* Call Mm to adjust the process' working set size */
1145 CapturedQuotaLimits.MaximumWorkingSetSize,
1146 0,
1147 IncreaseOkay);
1148
1149 /* Bring back APCs and detach from the process */
1151 KeUnstackDetachProcess(&SavedApcState);
1152 }
1153 else if (Process->QuotaBlock == &PspDefaultQuotaBlock)
1154 {
1155 /* Check if the caller has the required privilege */
1157 {
1159 }
1160
1161 /* Allocate a new quota block */
1163 sizeof(EPROCESS_QUOTA_BLOCK),
1165 if (QuotaBlock == NULL)
1166 {
1168 return STATUS_NO_MEMORY;
1169 }
1170
1171 /* Initialize the quota block */
1172 QuotaBlock->ReferenceCount = 1;
1173 QuotaBlock->ProcessCount = 1;
1174 QuotaBlock->QuotaEntry[PsNonPagedPool].Peak = Process->QuotaPeak[PsNonPagedPool];
1175 QuotaBlock->QuotaEntry[PsPagedPool].Peak = Process->QuotaPeak[PsPagedPool];
1176 QuotaBlock->QuotaEntry[PsPageFile].Peak = Process->QuotaPeak[PsPageFile];
1180
1181 /* Try to exchange the quota block, if that failed, just drop it */
1182 OldQuotaBlock = InterlockedCompareExchangePointer((PVOID*)&Process->QuotaBlock,
1183 QuotaBlock,
1185 if (OldQuotaBlock == &PspDefaultQuotaBlock)
1186 {
1187 /* Success, insert the new quota block */
1188 PspInsertQuotaBlock(QuotaBlock);
1189 }
1190 else
1191 {
1192 /* Failed, free the quota block and ignore it */
1194 }
1195
1197 }
1198 else
1199 {
1201 }
1202
1203 return Status;
1204}
1205
1206/* EOF */
#define CODE_SEG(...)
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
LONG_PTR SSIZE_T
Definition: basetsd.h:181
#define _Requires_lock_held_(lock)
#define SIZE_T_MAX
Definition: dhcpd.h:91
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define ASSERT_IRQL_EQUAL(x)
Definition: debug.h:43
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONG KSPIN_LOCK
Definition: env_spec_w32.h:72
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define NonPagedPool
Definition: env_spec_w32.h:307
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
#define PagedPool
Definition: env_spec_w32.h:308
#define InterlockedDecrementUL(Addend)
Definition: ex.h:1524
#define InterlockedExchangeSizeT(Target, Value)
Definition: ex.h:1546
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
_Must_inspect_result_ _In_ LONGLONG _In_ LONGLONG Amount
Definition: fsrtlfuncs.h:551
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
Status
Definition: gdiplustypes.h:25
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
enum _PS_QUOTA_TYPE PS_QUOTA_TYPE
@ PsQuotaTypes
Definition: pstypes.h:1030
@ PsNonPagedPool
Definition: pstypes.h:1021
@ PsPageFile
Definition: pstypes.h:1023
@ PsPagedPool
Definition: pstypes.h:1022
#define QUOTA_LIMITS_HARDWS_MIN_DISABLE
#define QUOTA_LIMITS_HARDWS_MAX_DISABLE
#define QUOTA_LIMITS_HARDWS_MAX_ENABLE
#define QUOTA_LIMITS_HARDWS_MIN_ENABLE
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129
#define InterlockedExchangeAddSizeT(a, b)
Definition: interlocked.h:196
#define InterlockedIncrementSizeT(a)
Definition: interlocked.h:220
#define KeLeaveGuardedRegion()
Definition: ke_x.h:68
#define KeEnterGuardedRegion()
Definition: ke_x.h:39
#define Unused(x)
Definition: atlwin.h:28
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define min(a, b)
Definition: monoChain.cc:55
#define _Outptr_
Definition: ms_sal.h:427
#define _In_
Definition: ms_sal.h:308
#define _In_opt_
Definition: ms_sal.h:309
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
NTSTATUS NTAPI MmAdjustWorkingSetSize(IN SIZE_T WorkingSetMinimumInBytes, IN SIZE_T WorkingSetMaximumInBytes, IN ULONG SystemCache, IN BOOLEAN IncreaseOkay)
Definition: mmsup.c:44
#define PAGED_POOL_MASK
Definition: mm.h:118
_In_ SIZE_T QuotaToReturn
Definition: mm.h:675
const LUID SeIncreaseQuotaPrivilege
Definition: priv.c:24
#define ExRaiseStatus
Definition: ntoskrnl.h:114
BOOLEAN NTAPI SeSinglePrivilegeCheck(_In_ LUID PrivilegeValue, _In_ KPROCESSOR_MODE PreviousMode)
Checks if a single privilege is present in the context of the calling thread.
Definition: priv.c:744
#define STATUS_QUOTA_EXCEEDED
Definition: ntstatus.h:304
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define STATUS_PAGEFILE_QUOTA_EXCEEDED
Definition: ntstatus.h:536
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:704
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:756
#define PSP_NON_PAGED_POOL_QUOTA_THRESHOLD
Definition: ps.h:76
#define PSP_PAGED_POOL_QUOTA_THRESHOLD
Definition: ps.h:77
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:162
PEPROCESS PsInitialSystemProcess
Definition: psmgr.c:50
VOID NTAPI PsReturnSharedPoolQuota(_In_ PEPROCESS_QUOTA_BLOCK QuotaBlock, _In_ SIZE_T AmountToReturnPaged, _In_ SIZE_T AmountToReturnNonPaged)
Returns the shared (paged and non paged) pool quotas. The function is used exclusively by the Object ...
Definition: quota.c:621
VOID NTAPI PspReturnProcessQuotaSpecifiedPool(_In_opt_ PEPROCESS Process, _In_ PEPROCESS_QUOTA_BLOCK QuotaBlock, _In_ PS_QUOTA_TYPE QuotaType, _In_ SIZE_T Amount)
Internal kernel function that provides the bulk logic of process quota returning. It returns (takes a...
Definition: quota.c:345
#define VALID_QUOTA_FLAGS
Definition: quota.c:20
NTSTATUS NTAPI PspSetQuotaLimits(_In_ PEPROCESS Process, _In_ ULONG Unused, _In_ PVOID QuotaLimits, _In_ ULONG QuotaLimitsLength, _In_ KPROCESSOR_MODE PreviousMode)
This function adjusts the working set limits of a process and sets up new quota limits when necessary...
Definition: quota.c:1045
VOID NTAPI PsInitializeQuotaSystem(VOID)
Initializes the quota system during boot phase of the system, which sets up the default quota block t...
Definition: quota.c:443
NTSTATUS NTAPI PsChargeProcessPageFileQuota(_In_ PEPROCESS Process, _In_ SIZE_T Amount)
Charges the process page file quota. The function is used internally by the kernel.
Definition: quota.c:738
NTSTATUS NTAPI PsChargeProcessNonPagedPoolQuota(_In_ PEPROCESS Process, _In_ SIZE_T Amount)
Charges the non paged pool quota of a given process.
Definition: quota.c:811
NTSTATUS NTAPI PspChargeProcessQuotaSpecifiedPool(_In_opt_ PEPROCESS Process, _In_ PEPROCESS_QUOTA_BLOCK QuotaBlock, _In_ PS_QUOTA_TYPE QuotaType, _In_ SIZE_T Amount)
Internal kernel function that provides the bulk logic of process quota charging, necessary for export...
Definition: quota.c:195
PEPROCESS_QUOTA_BLOCK NTAPI PsChargeSharedPoolQuota(_In_ PEPROCESS Process, _In_ SIZE_T AmountToChargePaged, _In_ SIZE_T AmountToChargeNonPaged)
Charges the shared (paged and non paged) pool quotas. The function is used exclusively by the Object ...
Definition: quota.c:674
VOID NTAPI PspDereferenceQuotaBlock(_In_opt_ PEPROCESS Process, _In_ PEPROCESS_QUOTA_BLOCK QuotaBlock)
De-references a quota block when quotas have been returned back because of an object de-allocation or...
Definition: quota.c:553
VOID NTAPI PsReturnProcessNonPagedPoolQuota(_In_ PEPROCESS Process, _In_ SIZE_T Amount)
Returns the non paged quota pool that the process was taking up.
Definition: quota.c:938
NTSTATUS NTAPI PsReturnProcessPageFileQuota(_In_ PEPROCESS Process, _In_ SIZE_T Amount)
Returns the page file quota that the process was taking up. The function is used exclusively by the k...
Definition: quota.c:993
EPROCESS_QUOTA_BLOCK PspDefaultQuotaBlock
Definition: quota.c:16
VOID NTAPI PsReturnProcessPagedPoolQuota(_In_ PEPROCESS Process, _In_ SIZE_T Amount)
Returns the paged pool quota that the process was taking up.
Definition: quota.c:965
static LIST_ENTRY PspQuotaBlockList
Definition: quota.c:17
static KSPIN_LOCK PspQuotaLock
Definition: quota.c:18
VOID NTAPI PspInsertQuotaBlock(_In_ PEPROCESS_QUOTA_BLOCK QuotaBlock)
Inserts the new quota block into the quota list.
Definition: quota.c:518
VOID NTAPI PspInheritQuota(_In_ PEPROCESS Process, _In_opt_ PEPROCESS ParentProcess)
Inherits the quota block to another newborn (child) process. If there's no parent process,...
Definition: quota.c:483
NTSTATUS NTAPI PsChargeProcessPoolQuota(_In_ PEPROCESS Process, _In_ POOL_TYPE PoolType, _In_ SIZE_T Amount)
Charges the process' quota pool. The type of quota to be charged depends upon the PoolType parameter.
Definition: quota.c:872
VOID NTAPI PsChargePoolQuota(_In_ PEPROCESS Process, _In_ POOL_TYPE PoolType, _In_ SIZE_T Amount)
Charges the pool quota of a given process. The kind of pool quota to charge is determined by the Pool...
Definition: quota.c:775
NTSTATUS NTAPI PsChargeProcessPagedPoolQuota(_In_ PEPROCESS Process, _In_ SIZE_T Amount)
Charges the paged pool quota of a given process.
Definition: quota.c:839
VOID NTAPI PsReturnPoolQuota(_In_ PEPROCESS Process, _In_ POOL_TYPE PoolType, _In_ SIZE_T Amount)
Returns the pool quota that the process was taking up.
Definition: quota.c:907
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:108
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
EPROCESS_QUOTA_ENTRY QuotaEntry[PsQuotaTypes]
Definition: pstypes.h:1046
SIZE_T Return
Definition: pstypes.h:1041
SIZE_T Usage
Definition: pstypes.h:1038
SIZE_T Limit
Definition: pstypes.h:1039
SIZE_T Peak
Definition: pstypes.h:1040
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
SIZE_T MaximumWorkingSetSize
Definition: pstypes.h:71
SIZE_T WorkingSetLimit
Definition: pstypes.h:74
SIZE_T Reserved3
Definition: pstypes.h:76
SIZE_T Reserved4
Definition: pstypes.h:77
RATE_QUOTA_LIMIT CpuRateLimit
Definition: pstypes.h:79
SIZE_T MinimumWorkingSetSize
Definition: pstypes.h:70
SIZE_T Reserved2
Definition: pstypes.h:75
#define TAG_QUOTA_BLOCK
Definition: tag.h:139
ULONG_PTR * PSIZE_T
Definition: typedefs.h:80
INT POOL_TYPE
Definition: typedefs.h:78
#define NTAPI
Definition: typedefs.h:36
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
ULONG RateData
Definition: pstypes.h:60
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ _Strict_type_match_ POOL_TYPE PoolType
Definition: wdfdevice.h:3815
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
KAPC_STATE
Definition: ketypes.h:1409
#define ObDereferenceObject
Definition: obfuncs.h:203
#define PsGetCurrentProcess
Definition: psfuncs.h:17
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103