[NTOSKRNL]: Activate the pseudo-quota system. It doesnt' do much but at least it...
[reactos.git] / reactos / ntoskrnl / ps / quota.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ps/quota.c
5 * PURPOSE: Process Pool Quotas
6 *
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
8 * Mike Nordell
9 */
10
11 /* INCLUDES **************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <debug.h>
16
17 EPROCESS_QUOTA_BLOCK PspDefaultQuotaBlock;
18
19 /* PRIVATE FUNCTIONS *******************************************************/
20
21 /*
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.
28 */
29 NTSTATUS
30 NTAPI
31 PspChargeProcessQuotaSpecifiedPool(IN PEPROCESS Process,
32 IN UCHAR PoolIndex,
33 IN SIZE_T Amount)
34 {
35 ASSERT(Process);
36 ASSERT(Process != PsInitialSystemProcess);
37 ASSERT(PoolIndex <= 2);
38 ASSERT(Process->QuotaBlock);
39
40 /* Note: Race warning. TODO: Needs to add/use lock for this */
41 if (Process->QuotaUsage[PoolIndex] + Amount >
42 Process->QuotaBlock->QuotaEntry[PoolIndex].Limit)
43 {
44 DPRINT1("Quota exceeded, but ROS will let it slide...\n");
45 return STATUS_SUCCESS;
46 //return STATUS_QUOTA_EXCEEDED; /* caller raises the exception */
47 }
48
49 InterlockedExchangeAdd((LONG*)&Process->QuotaUsage[PoolIndex], Amount);
50
51 /* Note: Race warning. TODO: Needs to add/use lock for this */
52 if (Process->QuotaPeak[PoolIndex] < Process->QuotaUsage[PoolIndex])
53 {
54 Process->QuotaPeak[PoolIndex] = Process->QuotaUsage[PoolIndex];
55 }
56
57 return STATUS_SUCCESS;
58 }
59
60 /*
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.
65 */
66 VOID
67 NTAPI
68 PspReturnProcessQuotaSpecifiedPool(IN PEPROCESS Process,
69 IN UCHAR PoolIndex,
70 IN SIZE_T Amount)
71 {
72 ASSERT(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)
77 {
78 DPRINT1("WARNING: Process->QuotaUsage sanity check failed.\n");
79 }
80 else
81 {
82 InterlockedExchangeAdd((LONG*)&Process->QuotaUsage[PoolIndex],
83 -(LONG)Amount);
84 }
85 }
86
87 /* FUNCTIONS ***************************************************************/
88
89 VOID
90 NTAPI
91 INIT_FUNCTION
92 PsInitializeQuotaSystem(VOID)
93 {
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;
99 }
100
101 VOID
102 NTAPI
103 PspInheritQuota(PEPROCESS Process, PEPROCESS ParentProcess)
104 {
105 if (ParentProcess != NULL)
106 {
107 PEPROCESS_QUOTA_BLOCK QuotaBlock = ParentProcess->QuotaBlock;
108
109 ASSERT(QuotaBlock != NULL);
110
111 (void)InterlockedIncrementUL(&QuotaBlock->ReferenceCount);
112
113 Process->QuotaBlock = QuotaBlock;
114 }
115 else
116 Process->QuotaBlock = &PspDefaultQuotaBlock;
117 }
118
119 VOID
120 NTAPI
121 PspDestroyQuotaBlock(PEPROCESS Process)
122 {
123 PEPROCESS_QUOTA_BLOCK QuotaBlock = Process->QuotaBlock;
124
125 if (QuotaBlock != &PspDefaultQuotaBlock &&
126 InterlockedDecrementUL(&QuotaBlock->ReferenceCount) == 0)
127 {
128 ExFreePool(QuotaBlock);
129 }
130 }
131
132 /*
133 * @implemented
134 */
135 NTSTATUS
136 NTAPI
137 PsChargeProcessPageFileQuota(IN PEPROCESS Process,
138 IN SIZE_T Amount)
139 {
140 /* Don't do anything for the system process */
141 if (Process == PsInitialSystemProcess) return STATUS_SUCCESS;
142
143 return PspChargeProcessQuotaSpecifiedPool(Process, 2, Amount);
144 }
145
146 /*
147 * @implemented
148 */
149 VOID
150 NTAPI
151 PsChargePoolQuota(IN PEPROCESS Process,
152 IN POOL_TYPE PoolType,
153 IN SIZE_T Amount)
154 {
155 NTSTATUS Status;
156 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
157
158 /* Don't do anything for the system process */
159 if (Process == PsInitialSystemProcess) return;
160
161 /* Charge the usage */
162 Status = PsChargeProcessPoolQuota(Process, PoolType, Amount);
163 if (!NT_SUCCESS(Status)) ExRaiseStatus(Status);
164 }
165
166 /*
167 * @implemented
168 */
169 NTSTATUS
170 NTAPI
171 PsChargeProcessNonPagedPoolQuota(IN PEPROCESS Process,
172 IN SIZE_T Amount)
173 {
174 /* Call the general function */
175 return PsChargeProcessPoolQuota(Process, NonPagedPool, Amount);
176 }
177
178 /*
179 * @implemented
180 */
181 NTSTATUS
182 NTAPI
183 PsChargeProcessPagedPoolQuota(IN PEPROCESS Process,
184 IN SIZE_T Amount)
185 {
186 /* Call the general function */
187 return PsChargeProcessPoolQuota(Process, PagedPool, Amount);
188 }
189
190 /*
191 * @implemented
192 */
193 NTSTATUS
194 NTAPI
195 PsChargeProcessPoolQuota(IN PEPROCESS Process,
196 IN POOL_TYPE PoolType,
197 IN SIZE_T Amount)
198 {
199 /* Don't do anything for the system process */
200 if (Process == PsInitialSystemProcess) return STATUS_SUCCESS;
201
202 return PspChargeProcessQuotaSpecifiedPool(Process,
203 (PoolType & PAGED_POOL_MASK),
204 Amount);
205 }
206
207 /*
208 * @implemented
209 */
210 VOID
211 NTAPI
212 PsReturnPoolQuota(IN PEPROCESS Process,
213 IN POOL_TYPE PoolType,
214 IN SIZE_T Amount)
215 {
216 /* Don't do anything for the system process */
217 if (Process == PsInitialSystemProcess) return;
218
219 PspReturnProcessQuotaSpecifiedPool(Process,
220 (PoolType & PAGED_POOL_MASK),
221 Amount);
222 }
223
224 /*
225 * @implemented
226 */
227 VOID
228 NTAPI
229 PsReturnProcessNonPagedPoolQuota(IN PEPROCESS Process,
230 IN SIZE_T Amount)
231 {
232 /* Don't do anything for the system process */
233 if (Process == PsInitialSystemProcess) return;
234
235 PsReturnPoolQuota(Process, NonPagedPool, Amount);
236 }
237
238 /*
239 * @implemented
240 */
241 VOID
242 NTAPI
243 PsReturnProcessPagedPoolQuota(IN PEPROCESS Process,
244 IN SIZE_T Amount)
245 {
246 /* Don't do anything for the system process */
247 if (Process == PsInitialSystemProcess) return;
248
249 PsReturnPoolQuota(Process, PagedPool, Amount);
250 }
251
252 /*
253 * @implemented
254 */
255 NTSTATUS
256 NTAPI
257 PsReturnProcessPageFileQuota(IN PEPROCESS Process,
258 IN SIZE_T Amount)
259 {
260 /* Don't do anything for the system process */
261 if (Process == PsInitialSystemProcess) return STATUS_SUCCESS;
262
263 PspReturnProcessQuotaSpecifiedPool(Process, 2, Amount);
264 return STATUS_SUCCESS;
265 }
266
267 /* EOF */