ReactOS 0.4.15-dev-7842-g558ab78
quota.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
Include dependency graph for quota.c:

Go to the source code of this file.

Macros

#define NDEBUG
 
#define VALID_QUOTA_FLAGS
 

Functions

 _Requires_lock_held_ (PspQuotaLock)
 Returns pool quotas back to the Memory Manager when the pool quota block is no longer being used by anybody.
 
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 exported kernel routines needed for quota management.
 
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 away) quotas back from a process and/or quota block, which is the opposite of charging quotas.
 
VOID NTAPI PsInitializeQuotaSystem (VOID)
 Initializes the quota system during boot phase of the system, which sets up the default quota block that is used across several processes.
 
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, the default quota block is assigned.
 
VOID NTAPI PspInsertQuotaBlock (_In_ PEPROCESS_QUOTA_BLOCK QuotaBlock)
 Inserts the new quota block into the quota list.
 
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 when a process gets destroyed. If the last instance that held up the block gets de-referenced the function will perform a cleanup against that block and it'll free the quota block from memory.
 
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 Manager to manage quota returns handling of objects.
 
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 Manager to manage quota charges handling of objects.
 
NTSTATUS NTAPI PsChargeProcessPageFileQuota (_In_ PEPROCESS Process, _In_ SIZE_T Amount)
 Charges the process page file quota. The function is used internally by the kernel.
 
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 PoolType parameter.
 
NTSTATUS NTAPI PsChargeProcessNonPagedPoolQuota (_In_ PEPROCESS Process, _In_ SIZE_T Amount)
 Charges the non paged pool quota of a given process.
 
NTSTATUS NTAPI PsChargeProcessPagedPoolQuota (_In_ PEPROCESS Process, _In_ SIZE_T Amount)
 Charges the paged pool quota of a given process.
 
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.
 
VOID NTAPI PsReturnPoolQuota (_In_ PEPROCESS Process, _In_ POOL_TYPE PoolType, _In_ SIZE_T Amount)
 Returns the pool quota that the process was taking up.
 
VOID NTAPI PsReturnProcessNonPagedPoolQuota (_In_ PEPROCESS Process, _In_ SIZE_T Amount)
 Returns the non paged quota pool that the process was taking up.
 
VOID NTAPI PsReturnProcessPagedPoolQuota (_In_ PEPROCESS Process, _In_ SIZE_T Amount)
 Returns the paged pool quota that the process was taking up.
 
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 kernel.
 
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. The function is used when the caller requests to set up new working set sizes.
 

Variables

EPROCESS_QUOTA_BLOCK PspDefaultQuotaBlock
 
static LIST_ENTRY PspQuotaBlockList = {&PspQuotaBlockList, &PspQuotaBlockList}
 
static KSPIN_LOCK PspQuotaLock
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 13 of file quota.c.

◆ VALID_QUOTA_FLAGS

#define VALID_QUOTA_FLAGS
Value:
#define QUOTA_LIMITS_HARDWS_MIN_DISABLE
#define QUOTA_LIMITS_HARDWS_MAX_DISABLE
#define QUOTA_LIMITS_HARDWS_MAX_ENABLE
#define QUOTA_LIMITS_HARDWS_MIN_ENABLE

Definition at line 20 of file quota.c.

Function Documentation

◆ _Requires_lock_held_()

_Requires_lock_held_ ( PspQuotaLock  )

Returns pool quotas back to the Memory Manager when the pool quota block is no longer being used by anybody.

Releases some of excess quotas in order to attempt free up some resources. This is done primarily in in case the Memory Manager fails to raise the quota limit.

Parameters
[in]QuotaBlockThe pool quota block of which quota resources are to be sent back.
Returns
Nothing.
Remarks
The function only returns quotas back to Memory Manager that is paged or non paged. It does not return page file quotas as page file quota management is done in a different way. Furthermore, quota spin lock has to be held when returning quotas.
Parameters
[in]QuotaTypeProcess pool quota type.
[out]ReturnedQuotasA pointer to the returned amount of quotas back to Memory Manager.
Returns
Nothing.
Remarks
The function releases excess paged or non paged pool quotas. Page file quota type is not permitted. Furthermore, quota spin lock has to be held when returning quotas.

Definition at line 47 of file quota.c.

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}
#define ASSERT_IRQL_EQUAL(x)
Definition: debug.h:43
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
@ PsNonPagedPool
Definition: pstypes.h:1021
@ PsPageFile
Definition: pstypes.h:1023
#define ASSERT(a)
Definition: mode.c:44
_In_ SIZE_T QuotaToReturn
Definition: mm.h:675
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint32_t ULONG
Definition: typedefs.h:59

◆ PsChargePoolQuota()

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 PoolType parameter.

Parameters
[in]ProcessThe process which quota is to be charged.
[in]PoolTypeThe pool type to choose to charge quotas (e.g. PagedPool or NonPagedPool).
[in]AmountThe amount of quotas to charge into a process.
Returns
Nothing.
Remarks
The function raises an exception if STATUS_QUOTA_EXCEEDED status code is returned. Callers are responsible on their own to handle the raised exception.

Definition at line 775 of file quota.c.

779{
782
783 /* Don't do anything for the system process */
784 if (Process == PsInitialSystemProcess) return;
785
786 /* Charge the usage */
789}
LONG NTSTATUS
Definition: precomp.h:26
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
_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 ExRaiseStatus
Definition: ntoskrnl.h:114
PEPROCESS PsInitialSystemProcess
Definition: psmgr.c:50
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
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ _Strict_type_match_ POOL_TYPE PoolType
Definition: wdfdevice.h:3815

Referenced by FsRtlCancelNotify(), and FsRtlNotifyFilterReportChange().

◆ PsChargeProcessNonPagedPoolQuota()

NTSTATUS NTAPI PsChargeProcessNonPagedPoolQuota ( _In_ PEPROCESS  Process,
_In_ SIZE_T  Amount 
)

Charges the non paged pool quota of a given process.

Parameters
[in]ProcessThe process which non paged quota is to be charged.
[in]AmountThe amount of quotas to charge into a process.
Returns
Returns STATUS_SUCCESS if quota charing has suceeded, STATUS_QUOTA_EXCEEDED is returned otherwise to indicate the caller attempted to charge quotas over the limits.

Definition at line 811 of file quota.c.

814{
815 /* Call the general function */
817}
#define NonPagedPool
Definition: env_spec_w32.h:307

Referenced by MiCreatePebOrTeb(), MiMapLockedPagesInUserSpace(), MiMapViewOfDataSection(), NtAllocateVirtualMemory(), NtFreeVirtualMemory(), and START_TEST().

◆ PsChargeProcessPagedPoolQuota()

NTSTATUS NTAPI PsChargeProcessPagedPoolQuota ( _In_ PEPROCESS  Process,
_In_ SIZE_T  Amount 
)

Charges the paged pool quota of a given process.

Parameters
[in]ProcessThe process which paged quota is to be charged.
[in]AmountThe amount of quotas to charge into a process.
Returns
Returns STATUS_SUCCESS if quota charing has suceeded, STATUS_QUOTA_EXCEEDED is returned otherwise to indicate the caller attempted to charge quotas over the limits.

Definition at line 839 of file quota.c.

842{
843 /* Call the general function */
845}
#define PagedPool
Definition: env_spec_w32.h:308

Referenced by ExpAllocateHandleTable(), ExpAllocateTablePagedPool(), ExpAllocateTablePagedPoolNoZero(), and START_TEST().

◆ PsChargeProcessPageFileQuota()

NTSTATUS NTAPI PsChargeProcessPageFileQuota ( _In_ PEPROCESS  Process,
_In_ SIZE_T  Amount 
)

Charges the process page file quota. The function is used internally by the kernel.

Parameters
[in]ProcessThe process which page file quota is to be charged.
[in]AmountThe amount of page file quota to charge.
Returns
Returns STATUS_SUCCESS if quota charging has been done with success, otherwise a NTSTATUS code of STATUS_PAGEFILE_QUOTA_EXCEEDED is returned.

Definition at line 738 of file quota.c.

741{
742 /* Don't do anything for the system process */
744
746}
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
#define STATUS_SUCCESS
Definition: shellext.h:65

◆ PsChargeProcessPoolQuota()

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.

Parameters
[in]ProcessThe process which quota is to be charged.
[in]PoolTypeThe type of quota pool to charge (e.g. PagedPool or NonPagedPool).
[in]AmountThe amount of quotas to charge into a process.
Returns
Returns STATUS_SUCCESS if quota charing has suceeded, STATUS_QUOTA_EXCEEDED is returned otherwise to indicate the caller attempted to charge quotas over the limits.

Definition at line 872 of file quota.c.

876{
877 /* Don't do anything for the system process */
879
881 Process->QuotaBlock,
883 Amount);
884}
#define PAGED_POOL_MASK
Definition: mm.h:118

Referenced by ExAllocatePoolWithQuotaTag(), PsChargePoolQuota(), PsChargeProcessNonPagedPoolQuota(), and PsChargeProcessPagedPoolQuota().

◆ PsChargeSharedPoolQuota()

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 Manager to manage quota charges handling of objects.

Parameters
[in]ProcessThe process which quotas are to be charged within its quota block.
[in]AmountToChargePagedThe amount of paged quotas quotas to be charged.
[in]AmountToChargeNonPagedThe amount of non paged quotas to be charged.
Returns
Returns the charged quota block, which it'll be used by the Object Manager to attach the charged quotas information to the object. If the function fails to charge quotas, NULL is returned to the caller.

Definition at line 674 of file quota.c.

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}
#define DPRINT1
Definition: precomp.h:8
#define NULL
Definition: types.h:112
@ PsPagedPool
Definition: pstypes.h:1022
#define InterlockedIncrementSizeT(a)
Definition: interlocked.h:220
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 DPRINT
Definition: sndvol32.h:71

Referenced by ObpChargeQuotaForObject().

◆ PsInitializeQuotaSystem()

VOID NTAPI PsInitializeQuotaSystem ( VOID  )

Initializes the quota system during boot phase of the system, which sets up the default quota block that is used across several processes.

Returns
Nothing.

Definition at line 443 of file quota.c.

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}
EPROCESS_QUOTA_BLOCK PspDefaultQuotaBlock
Definition: quota.c:16
EPROCESS_QUOTA_ENTRY QuotaEntry[PsQuotaTypes]
Definition: pstypes.h:1046
SIZE_T Limit
Definition: pstypes.h:1039
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define PsGetCurrentProcess
Definition: psfuncs.h:17

Referenced by ObInitSystem().

◆ PspChargeProcessQuotaSpecifiedPool()

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 exported kernel routines needed for quota management.

Parameters
[in]ProcessA process, represented as a EPROCESS object. This parameter is used to charge the own process' quota usage.
[in]QuotaBlockThe quota block which quotas are to be charged. This block can either come from the process itself or from an object with specified quota charges.
[in]QuotaTypeThe quota type which quota in question is to be charged. The permitted types are PsPagedPool, PsNonPagedPool and PsPageFile.
[in]AmountThe amount of quota to be charged.
Returns
Returns STATUS_SUCCESS if quota charging has been done successfully without problemns. STATUS_QUOTA_EXCEEDED is returned if the caller wants to charge quotas with amount way over the limits. STATUS_PAGEFILE_QUOTA_EXCEEDED is returned for the same situation but specific to page files instead.

Definition at line 195 of file quota.c.

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}
LONG_PTR SSIZE_T
Definition: basetsd.h:181
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define InterlockedExchangeSizeT(Target, Value)
Definition: ex.h:1546
@ PsQuotaTypes
Definition: pstypes.h:1030
#define InterlockedExchangeAddSizeT(a, b)
Definition: interlocked.h:196
#define STATUS_QUOTA_EXCEEDED
Definition: ntstatus.h:304
#define STATUS_PAGEFILE_QUOTA_EXCEEDED
Definition: ntstatus.h:536
static KSPIN_LOCK PspQuotaLock
Definition: quota.c:18
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778

Referenced by PsChargeProcessPageFileQuota(), PsChargeProcessPoolQuota(), and PsChargeSharedPoolQuota().

◆ PspDereferenceQuotaBlock()

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 when a process gets destroyed. If the last instance that held up the block gets de-referenced the function will perform a cleanup against that block and it'll free the quota block from memory.

Parameters
[in]ProcessA pointer to a process that de-references the quota block.
[in]QuotaBlockA pointer to a quota block that is to be de-referenced. This block can come from a process that references it or an object.
Returns
Nothing.

Definition at line 553 of file quota.c.

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}
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InterlockedDecrementUL(Addend)
Definition: ex.h:1524
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define TAG_QUOTA_BLOCK
Definition: tag.h:139

Referenced by PspDeleteProcess(), and PsReturnSharedPoolQuota().

◆ PspInheritQuota()

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, the default quota block is assigned.

Parameters
[in]ProcessThe child process which quota block is to be given.
[in]ParentProcessThe parent process.
Returns
Nothing.

Definition at line 483 of file quota.c.

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}

◆ PspInsertQuotaBlock()

VOID NTAPI PspInsertQuotaBlock ( _In_ PEPROCESS_QUOTA_BLOCK  QuotaBlock)

Inserts the new quota block into the quota list.

Parameters
[in]QuotaBlockThe new quota block.
Returns
Nothing.

Definition at line 518 of file quota.c.

520{
522
524 InsertTailList(&PspQuotaBlockList, &QuotaBlock->QuotaList);
526}
#define InsertTailList(ListHead, Entry)
static LIST_ENTRY PspQuotaBlockList
Definition: quota.c:17

Referenced by PspSetQuotaLimits().

◆ PspReturnProcessQuotaSpecifiedPool()

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 away) quotas back from a process and/or quota block, which is the opposite of charging quotas.

Parameters
[in]ProcessA process, represented as a EPROCESS object. This parameter is used to return the own process' quota usage.
[in]QuotaBlockThe quota block which quotas are to be returned. This block can either come from the process itself or from an object with specified quota charges.
[in]QuotaTypeThe quota type which quota in question is to be returned. The permitted types are PsPagedPool, PsNonPagedPool and PsPageFile.
[in]AmountThe amount of quota to be returned.
Returns
Nothing.

Definition at line 345 of file quota.c.

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}
#define min(a, b)
Definition: monoChain.cc:55
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
#define PSP_NON_PAGED_POOL_QUOTA_THRESHOLD
Definition: ps.h:76
#define PSP_PAGED_POOL_QUOTA_THRESHOLD
Definition: ps.h:77
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
uint32_t ULONG_PTR
Definition: typedefs.h:65

Referenced by PsChargeSharedPoolQuota(), PsReturnPoolQuota(), PsReturnProcessPageFileQuota(), and PsReturnSharedPoolQuota().

◆ PspSetQuotaLimits()

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. The function is used when the caller requests to set up new working set sizes.

Parameters
[in]ProcessThe process which quota limits or working set sizes are to be changed.
[in]UnusedThis parameter is unused.
[in]QuotaLimitsAn arbitrary pointer that points to a quota limits structure, needed to determine on setting up new working set sizes.
[in]QuotaLimitsLengthThe length of QuotaLimits buffer, which size is expressed in bytes.
[in]PreviousModeThe processor level access mode.
Returns
Returns STATUS_SUCCESS if the function has completed successfully. STATUS_INVALID_PARAMETER is returned if the caller has given a quota limits structure with invalid data. STATUS_INFO_LENGTH_MISMATCH is returned if the length of QuotaLimits pointed by QuotaLimitsLength is not right. STATUS_PRIVILEGE_NOT_HELD is returned if the calling thread of the process doesn't hold the necessary right privilege to increase quotas. STATUS_NO_MEMORY is returned if a memory pool allocation has failed. A failure NTSTATUS code is returned otherwise.

Definition at line 1045 of file quota.c.

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}
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
unsigned char BOOLEAN
#define SIZE_T_MAX
Definition: dhcpd.h:91
#define FALSE
Definition: types.h:117
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
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
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129
#define KeLeaveGuardedRegion()
Definition: ke_x.h:68
#define KeEnterGuardedRegion()
Definition: ke_x.h:39
#define Unused(x)
Definition: atlwin.h:28
#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
const LUID SeIncreaseQuotaPrivilege
Definition: priv.c:24
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_NO_MEMORY
Definition: ntstatus.h:260
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 _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:162
#define VALID_QUOTA_FLAGS
Definition: quota.c:20
VOID NTAPI PspInsertQuotaBlock(_In_ PEPROCESS_QUOTA_BLOCK QuotaBlock)
Inserts the new quota block into the quota list.
Definition: quota.c:518
SIZE_T Peak
Definition: pstypes.h:1040
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 RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#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
KAPC_STATE
Definition: ketypes.h:1409
#define ObDereferenceObject
Definition: obfuncs.h:203
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103

Referenced by NtSetInformationProcess().

◆ PsReturnPoolQuota()

VOID NTAPI PsReturnPoolQuota ( _In_ PEPROCESS  Process,
_In_ POOL_TYPE  PoolType,
_In_ SIZE_T  Amount 
)

Returns the pool quota that the process was taking up.

Parameters
[in]ProcessThe process which quota is to be returned.
[in]PoolTypeThe type of quota pool to return (e.g. PagedPool or NonPagedPool).
[in]AmountThe amount of quotas to return from a process.
Returns
Nothing.

Definition at line 907 of file quota.c.

911{
912 /* Don't do anything for the system process */
913 if (Process == PsInitialSystemProcess) return;
914
916 Process->QuotaBlock,
918 Amount);
919}

Referenced by ExFreePoolWithTag(), ExReturnPoolQuota(), PsReturnProcessNonPagedPoolQuota(), and PsReturnProcessPagedPoolQuota().

◆ PsReturnProcessNonPagedPoolQuota()

NTKERNELAPI VOID NTAPI PsReturnProcessNonPagedPoolQuota ( _In_ PEPROCESS  Process,
_In_ SIZE_T  Amount 
)

Returns the non paged quota pool that the process was taking up.

Parameters
[in]ProcessThe process which non paged quota is to be returned.
[in]AmountThe amount of quotas to return from a process.
Returns
Nothing.

Definition at line 938 of file quota.c.

941{
942 /* Don't do anything for the system process */
943 if (Process == PsInitialSystemProcess) return;
944
946}
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

Referenced by MiCreatePebOrTeb(), MiMapLockedPagesInUserSpace(), MiMapViewOfDataSection(), MiUnmapLockedPagesInUserSpace(), MiUnmapViewOfSection(), MmCleanProcessAddressSpace(), MmDeleteTeb(), NtAllocateVirtualMemory(), NtFreeVirtualMemory(), PspDeleteProcess(), and START_TEST().

◆ PsReturnProcessPagedPoolQuota()

VOID NTAPI PsReturnProcessPagedPoolQuota ( _In_ PEPROCESS  Process,
_In_ SIZE_T  Amount 
)

Returns the paged pool quota that the process was taking up.

Parameters
[in]ProcessThe process which paged pool quota is to be returned.
[in]AmountThe amount of quotas to return from a process.
Returns
Nothing.

Definition at line 965 of file quota.c.

968{
969 /* Don't do anything for the system process */
970 if (Process == PsInitialSystemProcess) return;
971
973}

Referenced by ExpAllocateHandleTable(), ExpFreeHandleTable(), ExpFreeTablePagedPool(), FsRtlCancelNotify(), FsRtlNotifyCleanup(), FsRtlNotifyCompleteIrp(), FsRtlNotifyFilterReportChange(), and START_TEST().

◆ PsReturnProcessPageFileQuota()

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 kernel.

Parameters
[in]ProcessThe process which pagefile quota is to be returned.
[in]AmountThe amount of quotas to return from a process.
Returns
Returns STATUS_SUCCESS.

Definition at line 993 of file quota.c.

996{
997 /* Don't do anything for the system process */
999
1001 return STATUS_SUCCESS;
1002}

◆ PsReturnSharedPoolQuota()

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 Manager to manage quota returns handling of objects.

Parameters
[in]QuotaBlockThe quota block which quotas are to be returned.
[in]AmountToReturnPagedThe amount of paged quotas quotas to be returned.
[in]AmountToReturnNonPagedThe amount of non paged quotas to be returned.
Returns
Nothing.

Definition at line 621 of file quota.c.

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}
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

Referenced by ObpDeallocateObject().

Variable Documentation

◆ PspDefaultQuotaBlock

◆ PspQuotaBlockList

LIST_ENTRY PspQuotaBlockList = {&PspQuotaBlockList, &PspQuotaBlockList}
static

Definition at line 17 of file quota.c.

Referenced by PspInsertQuotaBlock().

◆ PspQuotaLock