ReactOS  0.4.15-dev-4872-g8a3db97
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
VOID NTAPI PspInsertQuotaBlock (_In_ PEPROCESS_QUOTA_BLOCK QuotaBlock)
 Inserts the new quota block into the quota list. More...
 
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. More...
 
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. More...
 
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. More...
 
NTSTATUS NTAPI PsChargeProcessPageFileQuota (_In_ PEPROCESS Process, _In_ SIZE_T Amount)
 Charges the process page file quota. The function is used internally by the kernel. More...
 
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. More...
 
NTSTATUS NTAPI PsChargeProcessNonPagedPoolQuota (_In_ PEPROCESS Process, _In_ SIZE_T Amount)
 Charges the non paged pool quota of a given process. More...
 
NTSTATUS NTAPI PsChargeProcessPagedPoolQuota (_In_ PEPROCESS Process, _In_ SIZE_T Amount)
 Charges the paged pool quota of a given process. More...
 
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. More...
 
VOID NTAPI PsReturnPoolQuota (_In_ PEPROCESS Process, _In_ POOL_TYPE PoolType, _In_ SIZE_T Amount)
 Returns the pool quota that the process was taking up. More...
 
VOID NTAPI PsReturnProcessNonPagedPoolQuota (_In_ PEPROCESS Process, _In_ SIZE_T Amount)
 Returns the non paged quota pool that the process was taking up. More...
 
VOID NTAPI PsReturnProcessPagedPoolQuota (_In_ PEPROCESS Process, _In_ SIZE_T Amount)
 Returns the paged pool quota that the process was taking up. More...
 
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. More...
 
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. More...
 

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:
QUOTA_LIMITS_HARDWS_MIN_DISABLE | \
QUOTA_LIMITS_HARDWS_MAX_ENABLE | \
QUOTA_LIMITS_HARDWS_MAX_DISABLE)
#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 ASSERT(a)
Definition: mode.c:44
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
ULONG_PTR SIZE_T
Definition: typedefs.h:80
_In_ SIZE_T QuotaToReturn
Definition: mm.h:675
unsigned int ULONG
Definition: retypes.h:1

◆ 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 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
_Must_inspect_result_ _In_ LONGLONG _In_ LONGLONG Amount
Definition: fsrtlfuncs.h:550
LONG NTSTATUS
Definition: precomp.h:26
#define ExRaiseStatus
Definition: ntoskrnl.h:108
PEPROCESS PsInitialSystemProcess
Definition: psmgr.c:50
Status
Definition: gdiplustypes.h:24
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ _Strict_type_match_ POOL_TYPE PoolType
Definition: wdfdevice.h:3810
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

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 }
_Must_inspect_result_ _In_ LONGLONG _In_ LONGLONG Amount
Definition: fsrtlfuncs.h:550
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
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

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 }
_Must_inspect_result_ _In_ LONGLONG _In_ LONGLONG Amount
Definition: fsrtlfuncs.h:550
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
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

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 }
_Must_inspect_result_ _In_ LONGLONG _In_ LONGLONG Amount
Definition: fsrtlfuncs.h:550
PEPROCESS PsInitialSystemProcess
Definition: psmgr.c:50
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
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
#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 }
_Must_inspect_result_ _In_ LONGLONG _In_ LONGLONG Amount
Definition: fsrtlfuncs.h:550
#define PAGED_POOL_MASK
Definition: mm.h:118
PEPROCESS PsInitialSystemProcess
Definition: psmgr.c:50
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
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ _Strict_type_match_ POOL_TYPE PoolType
Definition: wdfdevice.h:3810
#define STATUS_SUCCESS
Definition: shellext.h:65

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 */
682  ASSERT(Process);
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 }
LONG NTSTATUS
Definition: precomp.h:26
#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
Status
Definition: gdiplustypes.h:24
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
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
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
#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 */
461  PsGetCurrentProcess()->QuotaBlock = &PspDefaultQuotaBlock;
462 }
EPROCESS_QUOTA_ENTRY QuotaEntry[PsQuotaTypes]
Definition: pstypes.h:1046
EPROCESS_QUOTA_BLOCK PspDefaultQuotaBlock
Definition: quota.c:16
#define PsGetCurrentProcess
Definition: psfuncs.h:17
ULONG_PTR SIZE_T
Definition: typedefs.h:80
SIZE_T Limit
Definition: pstypes.h:1039
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262

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 {
201  KIRQL OldIrql;
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");
249  return STATUS_QUOTA_EXCEEDED;
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);
273  return STATUS_QUOTA_EXCEEDED;
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 }
#define STATUS_PAGEFILE_QUOTA_EXCEEDED
Definition: ntstatus.h:536
_Must_inspect_result_ _In_ LONGLONG _In_ LONGLONG Amount
Definition: fsrtlfuncs.h:550
#define STATUS_QUOTA_EXCEEDED
Definition: ntstatus.h:304
VOID NTAPI KeAcquireSpinLock(PKSPIN_LOCK SpinLock, PKIRQL OldIrql)
Definition: spinlock.c:50
LONG_PTR SSIZE_T
Definition: basetsd.h:183
EPROCESS_QUOTA_BLOCK PspDefaultQuotaBlock
Definition: quota.c:16
UCHAR KIRQL
Definition: env_spec_w32.h:591
PEPROCESS PsInitialSystemProcess
Definition: psmgr.c:50
#define ASSERT(a)
Definition: mode.c:44
#define InterlockedExchangeAddSizeT(a, b)
Definition: interlocked.h:196
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define InterlockedExchangeSizeT(Target, Value)
Definition: ex.h:1544
#define DPRINT1
Definition: precomp.h:8
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
#define STATUS_SUCCESS
Definition: shellext.h:65
static KSPIN_LOCK PspQuotaLock
Definition: quota.c:18

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;
558  KIRQL OldIrql;
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 */
593  ExFreePoolWithTag(QuotaBlock, TAG_QUOTA_BLOCK);
594  }
595 }
VOID NTAPI KeAcquireSpinLock(PKSPIN_LOCK SpinLock, PKIRQL OldIrql)
Definition: spinlock.c:50
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
EPROCESS_QUOTA_BLOCK PspDefaultQuotaBlock
Definition: quota.c:16
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define ASSERT(a)
Definition: mode.c:44
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
#define InterlockedDecrementUL(Addend)
Definition: ex.h:1522
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
#define TAG_QUOTA_BLOCK
Definition: tag.h:136
unsigned int ULONG
Definition: retypes.h:1
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
static KSPIN_LOCK PspQuotaLock
Definition: quota.c:18

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 }
EPROCESS_QUOTA_BLOCK PspDefaultQuotaBlock
Definition: quota.c:16
#define InterlockedIncrementSizeT(a)
Definition: interlocked.h:220
#define ASSERT(a)
Definition: mode.c:44
#define NULL
Definition: types.h:112
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219

◆ 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 {
521  KIRQL OldIrql;
522 
524  InsertTailList(&PspQuotaBlockList, &QuotaBlock->QuotaList);
526 }
VOID NTAPI KeAcquireSpinLock(PKSPIN_LOCK SpinLock, PKIRQL OldIrql)
Definition: spinlock.c:50
#define InsertTailList(ListHead, Entry)
UCHAR KIRQL
Definition: env_spec_w32.h:591
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
static LIST_ENTRY PspQuotaBlockList
Definition: quota.c:17
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
static KSPIN_LOCK PspQuotaLock
Definition: quota.c:18

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 {
351  KIRQL OldIrql;
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,
372  (ULONG_PTR)Amount);
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 }
_Must_inspect_result_ _In_ LONGLONG _In_ LONGLONG Amount
Definition: fsrtlfuncs.h:550
VOID NTAPI KeAcquireSpinLock(PKSPIN_LOCK SpinLock, PKIRQL OldIrql)
Definition: spinlock.c:50
LONG_PTR SSIZE_T
Definition: basetsd.h:183
#define PSP_PAGED_POOL_QUOTA_THRESHOLD
Definition: ps.h:77
uint32_t ULONG_PTR
Definition: typedefs.h:65
EPROCESS_QUOTA_BLOCK PspDefaultQuotaBlock
Definition: quota.c:16
UCHAR KIRQL
Definition: env_spec_w32.h:591
PEPROCESS PsInitialSystemProcess
Definition: psmgr.c:50
#define ASSERT(a)
Definition: mode.c:44
#define InterlockedExchangeAddSizeT(a, b)
Definition: interlocked.h:196
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
ULONG_PTR SIZE_T
Definition: typedefs.h:80
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
#define min(a, b)
Definition: monoChain.cc:55
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define InterlockedExchangeSizeT(Target, Value)
Definition: ex.h:1544
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
#define PSP_NON_PAGED_POOL_QUOTA_THRESHOLD
Definition: ps.h:76
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
static KSPIN_LOCK PspQuotaLock
Definition: quota.c:18

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;
1056  NTSTATUS Status;
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 */
1144  Status = MmAdjustWorkingSetSize(CapturedQuotaLimits.MinimumWorkingSetSize,
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 */
1162  QuotaBlock = ExAllocatePoolWithTag(NonPagedPool,
1163  sizeof(EPROCESS_QUOTA_BLOCK),
1164  TAG_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 */
1193  ExFreePoolWithTag(QuotaBlock, TAG_QUOTA_BLOCK);
1194  }
1195 
1197  }
1198  else
1199  {
1201  }
1202 
1203  return Status;
1204 }
VOID NTAPI PspInsertQuotaBlock(_In_ PEPROCESS_QUOTA_BLOCK QuotaBlock)
Inserts the new quota block into the quota list.
Definition: quota.c:518
_Must_inspect_result_ typedef _In_ PVOID Unused
Definition: iotypes.h:1166
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
KAPC_STATE
Definition: ketypes.h:1285
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
const LUID SeIncreaseQuotaPrivilege
Definition: priv.c:24
EPROCESS_QUOTA_ENTRY QuotaEntry[PsQuotaTypes]
Definition: pstypes.h:1046
SIZE_T Reserved2
Definition: pstypes.h:75
#define QUOTA_LIMITS_HARDWS_MAX_ENABLE
#define SIZE_T_MAX
Definition: dhcpd.h:91
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define VALID_QUOTA_FLAGS
Definition: quota.c:20
LONG NTSTATUS
Definition: precomp.h:26
#define QUOTA_LIMITS_HARDWS_MIN_DISABLE
NTSTATUS NTAPI MmAdjustWorkingSetSize(IN SIZE_T WorkingSetMinimumInBytes, IN SIZE_T WorkingSetMaximumInBytes, IN ULONG SystemCache, IN BOOLEAN IncreaseOkay)
Definition: mmsup.c:44
_SEH2_TRY
Definition: create.c:4226
EPROCESS_QUOTA_BLOCK PspDefaultQuotaBlock
Definition: quota.c:16
#define FALSE
Definition: types.h:117
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:704
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129
unsigned char BOOLEAN
#define KeLeaveGuardedRegion()
Definition: ke_x.h:68
Status
Definition: gdiplustypes.h:24
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
ULONG RateData
Definition: pstypes.h:60
#define QUOTA_LIMITS_HARDWS_MIN_ENABLE
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define ObDereferenceObject
Definition: obfuncs.h:203
#define QUOTA_LIMITS_HARDWS_MAX_DISABLE
#define KeEnterGuardedRegion()
Definition: ke_x.h:39
#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
SIZE_T MaximumWorkingSetSize
Definition: pstypes.h:71
_SEH2_END
Definition: create.c:4400
SIZE_T MinimumWorkingSetSize
Definition: pstypes.h:70
SIZE_T WorkingSetLimit
Definition: pstypes.h:74
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:756
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
SIZE_T Limit
Definition: pstypes.h:1039
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
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
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
#define TAG_QUOTA_BLOCK
Definition: tag.h:136
RATE_QUOTA_LIMIT CpuRateLimit
Definition: pstypes.h:79
unsigned int ULONG
Definition: retypes.h:1
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define STATUS_SUCCESS
Definition: shellext.h:65
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
SIZE_T Reserved3
Definition: pstypes.h:76
SIZE_T Peak
Definition: pstypes.h:1040
SIZE_T Reserved4
Definition: pstypes.h:77

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 }
_Must_inspect_result_ _In_ LONGLONG _In_ LONGLONG Amount
Definition: fsrtlfuncs.h:550
#define PAGED_POOL_MASK
Definition: mm.h:118
PEPROCESS PsInitialSystemProcess
Definition: psmgr.c:50
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
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ _Strict_type_match_ POOL_TYPE PoolType
Definition: wdfdevice.h:3810

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 }
_Must_inspect_result_ _In_ LONGLONG _In_ LONGLONG Amount
Definition: fsrtlfuncs.h:550
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
PEPROCESS PsInitialSystemProcess
Definition: psmgr.c:50
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219

Referenced by MiMapViewOfDataSection(), MiUnmapLockedPagesInUserSpace(), MiUnmapViewOfSection(), MmCleanProcessAddressSpace(), MmDeleteTeb(), 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 }
_Must_inspect_result_ _In_ LONGLONG _In_ LONGLONG Amount
Definition: fsrtlfuncs.h:550
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
PEPROCESS PsInitialSystemProcess
Definition: psmgr.c:50
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219

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 }
_Must_inspect_result_ _In_ LONGLONG _In_ LONGLONG Amount
Definition: fsrtlfuncs.h:550
PEPROCESS PsInitialSystemProcess
Definition: psmgr.c:50
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
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
#define STATUS_SUCCESS
Definition: shellext.h:65

◆ 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 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 ASSERT(a)
Definition: mode.c:44
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
#define NULL
Definition: types.h:112
#define DPRINT
Definition: sndvol32.h:71

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