2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ps/quota.c
5 * PURPOSE: Process Pool Quotas
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
11 /* INCLUDES **************************************************************/
17 EPROCESS_QUOTA_BLOCK PspDefaultQuotaBlock
;
19 /* PRIVATE FUNCTIONS *******************************************************/
22 * Private helper to charge the specified process quota.
23 * ReturnsSTATUS_QUOTA_EXCEEDED on quota limit check failure.
24 * Updates QuotaPeak as needed for specified PoolIndex.
25 * TODO: Research and possibly add (the undocumented) enum type PS_QUOTA_TYPE
26 * to replace UCHAR for 'PoolIndex'.
27 * Notes: Conceptually translation unit local/private.
31 PspChargeProcessQuotaSpecifiedPool(IN PEPROCESS Process
,
36 ASSERT(Process
!= PsInitialSystemProcess
);
37 ASSERT(PoolIndex
<= 2);
38 ASSERT(Process
->QuotaBlock
);
40 /* Note: Race warning. TODO: Needs to add/use lock for this */
41 if (Process
->QuotaUsage
[PoolIndex
] + Amount
>
42 Process
->QuotaBlock
->QuotaEntry
[PoolIndex
].Limit
)
44 DPRINT1("Quota exceeded, but ROS will let it slide...\n");
45 return STATUS_SUCCESS
;
46 //return STATUS_QUOTA_EXCEEDED; /* caller raises the exception */
49 InterlockedExchangeAdd((LONG
*)&Process
->QuotaUsage
[PoolIndex
], Amount
);
51 /* Note: Race warning. TODO: Needs to add/use lock for this */
52 if (Process
->QuotaPeak
[PoolIndex
] < Process
->QuotaUsage
[PoolIndex
])
54 Process
->QuotaPeak
[PoolIndex
] = Process
->QuotaUsage
[PoolIndex
];
57 return STATUS_SUCCESS
;
61 * Private helper to remove quota charge from the specified process quota.
62 * TODO: Research and possibly add (the undocumented) enum type PS_QUOTA_TYPE
63 * to replace UCHAR for 'PoolIndex'.
64 * Notes: Conceptually translation unit local/private.
68 PspReturnProcessQuotaSpecifiedPool(IN PEPROCESS Process
,
73 ASSERT(Process
!= PsInitialSystemProcess
);
74 ASSERT(PoolIndex
<= 2);
75 ASSERT(!(Amount
& 0x80000000)); /* we need to be able to negate it */
76 if (Process
->QuotaUsage
[PoolIndex
] < Amount
)
78 DPRINT1("WARNING: Process->QuotaUsage sanity check failed.\n");
82 InterlockedExchangeAdd((LONG
*)&Process
->QuotaUsage
[PoolIndex
],
87 /* FUNCTIONS ***************************************************************/
92 PsInitializeQuotaSystem(VOID
)
94 RtlZeroMemory(&PspDefaultQuotaBlock
, sizeof(PspDefaultQuotaBlock
));
95 PspDefaultQuotaBlock
.QuotaEntry
[PagedPool
].Limit
= (SIZE_T
)-1;
96 PspDefaultQuotaBlock
.QuotaEntry
[NonPagedPool
].Limit
= (SIZE_T
)-1;
97 PspDefaultQuotaBlock
.QuotaEntry
[2].Limit
= (SIZE_T
)-1; /* Page file */
98 PsGetCurrentProcess()->QuotaBlock
= &PspDefaultQuotaBlock
;
103 PspInheritQuota(PEPROCESS Process
, PEPROCESS ParentProcess
)
105 if (ParentProcess
!= NULL
)
107 PEPROCESS_QUOTA_BLOCK QuotaBlock
= ParentProcess
->QuotaBlock
;
109 ASSERT(QuotaBlock
!= NULL
);
111 (void)InterlockedIncrementUL(&QuotaBlock
->ReferenceCount
);
113 Process
->QuotaBlock
= QuotaBlock
;
116 Process
->QuotaBlock
= &PspDefaultQuotaBlock
;
121 PspDestroyQuotaBlock(PEPROCESS Process
)
123 PEPROCESS_QUOTA_BLOCK QuotaBlock
= Process
->QuotaBlock
;
125 if (QuotaBlock
!= &PspDefaultQuotaBlock
&&
126 InterlockedDecrementUL(&QuotaBlock
->ReferenceCount
) == 0)
128 ExFreePool(QuotaBlock
);
137 PsChargeProcessPageFileQuota(IN PEPROCESS Process
,
140 /* Don't do anything for the system process */
141 if (Process
== PsInitialSystemProcess
) return STATUS_SUCCESS
;
143 return PspChargeProcessQuotaSpecifiedPool(Process
, 2, Amount
);
151 PsChargePoolQuota(IN PEPROCESS Process
,
152 IN POOL_TYPE PoolType
,
156 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL
);
158 /* Don't do anything for the system process */
159 if (Process
== PsInitialSystemProcess
) return;
161 /* Charge the usage */
162 Status
= PsChargeProcessPoolQuota(Process
, PoolType
, Amount
);
163 if (!NT_SUCCESS(Status
)) ExRaiseStatus(Status
);
171 PsChargeProcessNonPagedPoolQuota(IN PEPROCESS Process
,
174 /* Call the general function */
175 return PsChargeProcessPoolQuota(Process
, NonPagedPool
, Amount
);
183 PsChargeProcessPagedPoolQuota(IN PEPROCESS Process
,
186 /* Call the general function */
187 return PsChargeProcessPoolQuota(Process
, PagedPool
, Amount
);
195 PsChargeProcessPoolQuota(IN PEPROCESS Process
,
196 IN POOL_TYPE PoolType
,
199 /* Don't do anything for the system process */
200 if (Process
== PsInitialSystemProcess
) return STATUS_SUCCESS
;
202 return PspChargeProcessQuotaSpecifiedPool(Process
,
203 (PoolType
& PAGED_POOL_MASK
),
212 PsReturnPoolQuota(IN PEPROCESS Process
,
213 IN POOL_TYPE PoolType
,
216 /* Don't do anything for the system process */
217 if (Process
== PsInitialSystemProcess
) return;
219 PspReturnProcessQuotaSpecifiedPool(Process
,
220 (PoolType
& PAGED_POOL_MASK
),
229 PsReturnProcessNonPagedPoolQuota(IN PEPROCESS Process
,
232 /* Don't do anything for the system process */
233 if (Process
== PsInitialSystemProcess
) return;
235 PsReturnPoolQuota(Process
, NonPagedPool
, Amount
);
243 PsReturnProcessPagedPoolQuota(IN PEPROCESS Process
,
246 /* Don't do anything for the system process */
247 if (Process
== PsInitialSystemProcess
) return;
249 PsReturnPoolQuota(Process
, PagedPool
, Amount
);
257 PsReturnProcessPageFileQuota(IN PEPROCESS Process
,
260 /* Don't do anything for the system process */
261 if (Process
== PsInitialSystemProcess
) return STATUS_SUCCESS
;
263 PspReturnProcessQuotaSpecifiedPool(Process
, 2, Amount
);
264 return STATUS_SUCCESS
;