00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
#include "mi.h"
00028
00029
VOID
00030 MiInsertVad (
00031 IN
PMMVAD Vad
00032 )
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 {
00053
PMMADDRESS_NODE *Root;
00054
PEPROCESS CurrentProcess;
00055 SIZE_T RealCharge;
00056 SIZE_T PageCharge;
00057 SIZE_T PagedQuotaCharged;
00058 ULONG FirstPage;
00059 ULONG LastPage;
00060 SIZE_T PagedPoolCharge;
00061 LOGICAL ChargedPageFileQuota;
00062 LOGICAL ChargedJobCommit;
00063
00064
ASSERT (Vad->EndingVpn >= Vad->StartingVpn);
00065
00066 CurrentProcess =
PsGetCurrentProcess();
00067
00068
00069
00070
00071
00072
if (Vad->u.VadFlags.CommitCharge !=
MM_MAX_COMMIT) {
00073
00074 PageCharge = 0;
00075 PagedQuotaCharged = 0;
00076 ChargedPageFileQuota =
FALSE;
00077 ChargedJobCommit =
FALSE;
00078
00079
00080
00081
00082
00083
00084
00085
PsChargePoolQuota (CurrentProcess,
NonPagedPool,
sizeof(
MMVAD));
00086
00087
try {
00088
00089
00090
00091
00092
00093
if ((Vad->u.VadFlags.PrivateMemory == 0) &&
00094 (Vad->ControlArea !=
NULL)) {
00095 PagedPoolCharge =
00096 (Vad->EndingVpn - Vad->StartingVpn) <<
PTE_SHIFT;
00097
PsChargePoolQuota (CurrentProcess,
PagedPool, PagedPoolCharge);
00098 PagedQuotaCharged = PagedPoolCharge;
00099 }
00100
00101
#if !defined (_WIN64)
00102
00103
00104
00105
00106 FirstPage =
MiGetPpePdeOffset (
MI_VPN_TO_VA (Vad->StartingVpn));
00107 LastPage =
MiGetPpePdeOffset (
MI_VPN_TO_VA (Vad->EndingVpn));
00108
00109
while (FirstPage <= LastPage) {
00110
00111
if (!
MI_CHECK_BIT (
MmWorkingSetList->
CommittedPageTables,
00112 FirstPage)) {
00113 PageCharge += 1;
00114 }
00115 FirstPage += 1;
00116 }
00117
#endif
00118
00119 RealCharge = Vad->u.VadFlags.CommitCharge + PageCharge;
00120
00121
if (RealCharge != 0) {
00122
00123
MiChargePageFileQuota (RealCharge, CurrentProcess);
00124 ChargedPageFileQuota =
TRUE;
00125
00126
#if 0 //commented out so page file quota is meaningful.
00127
if (Vad->u.VadFlags.PrivateMemory == 0) {
00128
00129
if ((Vad->ControlArea->FilePointer ==
NULL) &&
00130 (Vad->u.VadFlags.PhysicalMapping == 0)) {
00131
00132
00133
00134
00135
00136
00137
00138 RealCharge -= 1 + (Vad->EndingVpn -
00139 Vad->StartingVpn);
00140 }
00141 }
00142
#endif //0
00143
if (CurrentProcess->
CommitChargeLimit) {
00144
if (CurrentProcess->
CommitCharge + RealCharge > CurrentProcess->
CommitChargeLimit) {
00145
if (CurrentProcess->
Job) {
00146
PsReportProcessMemoryLimitViolation ();
00147 }
00148
ExRaiseStatus (STATUS_COMMITMENT_LIMIT);
00149 }
00150 }
00151
if (CurrentProcess->
JobStatus &
PS_JOB_STATUS_REPORT_COMMIT_CHANGES) {
00152
if (
PsChangeJobMemoryUsage(RealCharge) ==
FALSE) {
00153
ExRaiseStatus (STATUS_COMMITMENT_LIMIT);
00154 }
00155 ChargedJobCommit =
TRUE;
00156 }
00157
00158
if (
MiChargeCommitment (RealCharge, CurrentProcess) ==
FALSE) {
00159
ExRaiseStatus (STATUS_COMMITMENT_LIMIT);
00160 }
00161
00162 CurrentProcess->
CommitCharge += RealCharge;
00163
if (CurrentProcess->
CommitCharge > CurrentProcess->
CommitChargePeak) {
00164 CurrentProcess->
CommitChargePeak = CurrentProcess->
CommitCharge;
00165 }
00166 }
00167 } except (
EXCEPTION_EXECUTE_HANDLER) {
00168
00169
00170
00171
00172
00173
PsReturnPoolQuota (CurrentProcess,
NonPagedPool,
sizeof(
MMVAD));
00174
00175
if (PagedQuotaCharged != 0) {
00176
PsReturnPoolQuota (CurrentProcess,
PagedPool, PagedPoolCharge);
00177 }
00178
00179
if (ChargedPageFileQuota ==
TRUE) {
00180
00181
MiReturnPageFileQuota (RealCharge,
00182 CurrentProcess);
00183 }
00184
00185
if (ChargedJobCommit ==
TRUE) {
00186
00187
00188
00189
00190
00191
00192
00193 CurrentProcess->
CommitCharge += RealCharge;
00194
PsChangeJobMemoryUsage(-(SSIZE_T)RealCharge);
00195 CurrentProcess->
CommitCharge -= RealCharge;
00196 }
00197
00198
ExRaiseStatus (GetExceptionCode());
00199 }
00200
00201
MM_TRACK_COMMIT (
MM_DBG_COMMIT_INSERT_VAD, RealCharge);
00202
00203
#if !defined (_WIN64)
00204
if (PageCharge != 0) {
00205
00206
00207
00208
00209
00210
00211 FirstPage =
MiGetPpePdeOffset (
MI_VPN_TO_VA (Vad->StartingVpn));
00212
00213
while (FirstPage <= LastPage) {
00214
00215
if (!
MI_CHECK_BIT (
MmWorkingSetList->
CommittedPageTables,
00216 FirstPage)) {
00217
MI_SET_BIT (
MmWorkingSetList->
CommittedPageTables,
00218 FirstPage);
00219
MmWorkingSetList->
NumberOfCommittedPageTables += 1;
00220
#if defined (_X86PAE_)
00221
ASSERT (
MmWorkingSetList->
NumberOfCommittedPageTables <
00222 PD_PER_SYSTEM *
PDE_PER_PAGE);
00223
#else
00224
ASSERT (
MmWorkingSetList->
NumberOfCommittedPageTables <
00225
PDE_PER_PAGE);
00226
#endif
00227
}
00228 FirstPage += 1;
00229 }
00230 }
00231
#endif
00232
}
00233
00234 Root = (
PMMADDRESS_NODE *)&CurrentProcess->
VadRoot;
00235
00236
00237
00238
00239
00240 CurrentProcess->
VadHint = Vad;
00241
00242
if (CurrentProcess->
VadFreeHint !=
NULL) {
00243
if (((ULONG)((
PMMVAD)CurrentProcess->
VadFreeHint)->EndingVpn +
00244
MI_VA_TO_VPN (
X64K)) >=
00245 Vad->StartingVpn) {
00246 CurrentProcess->
VadFreeHint = Vad;
00247 }
00248 }
00249
00250
MiInsertNode ( (
PMMADDRESS_NODE)Vad, Root);
00251
return;
00252 }
00253
00254
00255
VOID
00256 MiRemoveVad (
00257 IN
PMMVAD Vad
00258 )
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 {
00280
PMMADDRESS_NODE *Root;
00281
PEPROCESS CurrentProcess;
00282 SIZE_T RealCharge;
00283 PLIST_ENTRY Next;
00284
PMMSECURE_ENTRY Entry;
00285
00286 CurrentProcess =
PsGetCurrentProcess();
00287
00288
00289
00290
00291
00292
00293
if (Vad->u.VadFlags.CommitCharge !=
MM_MAX_COMMIT) {
00294
00295
00296
00297
00298
00299
PsReturnPoolQuota (CurrentProcess,
NonPagedPool,
sizeof(
MMVAD));
00300
00301
if ((Vad->u.VadFlags.PrivateMemory == 0) &&
00302 (Vad->ControlArea !=
NULL)) {
00303
PsReturnPoolQuota (CurrentProcess,
00304
PagedPool,
00305 (Vad->EndingVpn - Vad->StartingVpn) <<
PTE_SHIFT);
00306 }
00307
00308 RealCharge = Vad->u.VadFlags.CommitCharge;
00309
00310
if (RealCharge != 0) {
00311
00312
MiReturnPageFileQuota (RealCharge, CurrentProcess);
00313
00314
if ((Vad->u.VadFlags.PrivateMemory == 0) &&
00315 (Vad->ControlArea !=
NULL)) {
00316
00317
#if 0 //commented out so page file quota is meaningful.
00318
if (Vad->ControlArea->FilePointer ==
NULL) {
00319
00320
00321
00322
00323
00324
00325
00326 RealCharge -=
BYTES_TO_PAGES ((ULONG)Vad->EndingVa -
00327 (ULONG)Vad->StartingVa);
00328 }
00329
#endif
00330
}
00331
00332
MiReturnCommitment (RealCharge);
00333
MM_TRACK_COMMIT (
MM_DBG_COMMIT_RETURN_VAD, RealCharge);
00334
if (CurrentProcess->
JobStatus &
PS_JOB_STATUS_REPORT_COMMIT_CHANGES) {
00335
PsChangeJobMemoryUsage(-(SSIZE_T)RealCharge);
00336 }
00337 CurrentProcess->
CommitCharge -= RealCharge;
00338 }
00339 }
00340
00341
if (Vad == CurrentProcess->
VadFreeHint) {
00342 CurrentProcess->
VadFreeHint =
MiGetPreviousVad (Vad);
00343 }
00344
00345 Root = (
PMMADDRESS_NODE *)&CurrentProcess->
VadRoot;
00346
00347
MiRemoveNode ( (
PMMADDRESS_NODE)Vad, Root);
00348
00349
if (Vad->u.VadFlags.NoChange) {
00350
if (Vad->u2.VadFlags2.MultipleSecured) {
00351
00352
00353
00354
00355
00356 Next = Vad->u3.List.Flink;
00357
do {
00358 Entry = CONTAINING_RECORD( Next,
00359
MMSECURE_ENTRY,
00360
List);
00361
00362 Next = Entry->
List.Flink;
00363
ExFreePool (Entry);
00364 }
while (Next != &Vad->u3.List);
00365 }
00366 }
00367
00368
00369
00370
00371
if (CurrentProcess->
VadHint == Vad) {
00372 CurrentProcess->
VadHint = CurrentProcess->
VadRoot;
00373 }
00374
00375
return;
00376 }
00377
00378
PMMVAD
00379
FASTCALL
00380 MiLocateAddress (
00381 IN PVOID VirtualAddress
00382 )
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403 {
00404
PMMVAD FoundVad;
00405
PEPROCESS CurrentProcess;
00406 ULONG_PTR Vpn;
00407
00408 CurrentProcess =
PsGetCurrentProcess();
00409
00410
if (CurrentProcess->
VadHint ==
NULL) {
00411
return NULL;
00412 }
00413
00414 Vpn =
MI_VA_TO_VPN (VirtualAddress);
00415
if ((Vpn >= ((
PMMADDRESS_NODE)CurrentProcess->
VadHint)->StartingVpn) &&
00416 (Vpn <= ((
PMMADDRESS_NODE)CurrentProcess->
VadHint)->EndingVpn)) {
00417
00418
return (
PMMVAD)CurrentProcess->
VadHint;
00419 }
00420
00421 FoundVad = (
PMMVAD)
MiLocateAddressInTree ( Vpn,
00422 (
PMMADDRESS_NODE *)&(CurrentProcess->
VadRoot));
00423
00424
if (FoundVad !=
NULL) {
00425 CurrentProcess->
VadHint = (PVOID)FoundVad;
00426 }
00427
return FoundVad;
00428 }
00429
00430 PVOID
00431 MiFindEmptyAddressRange (
00432 IN SIZE_T SizeOfRange,
00433 IN ULONG_PTR Alignment,
00434 IN ULONG QuickCheck
00435 )
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462 {
00463
PMMVAD NextVad;
00464
PMMVAD FreeHint;
00465
PEPROCESS CurrentProcess;
00466 PVOID StartingVa;
00467 PVOID EndingVa;
00468
00469 CurrentProcess =
PsGetCurrentProcess();
00470 FreeHint = CurrentProcess->
VadFreeHint;
00471
00472
if ((QuickCheck == 0) && (FreeHint !=
NULL)) {
00473
00474 EndingVa =
MI_VPN_TO_VA_ENDING (FreeHint->
EndingVpn);
00475 NextVad =
MiGetNextVad (FreeHint);
00476
if (NextVad ==
NULL) {
00477
00478
if (SizeOfRange <
00479 (((ULONG_PTR)MM_HIGHEST_USER_ADDRESS + 1) -
00480
MI_ROUND_TO_SIZE((ULONG_PTR)EndingVa, Alignment))) {
00481
return (
PMMADDRESS_NODE)
MI_ROUND_TO_SIZE((ULONG_PTR)EndingVa,
00482 Alignment);
00483 }
00484 }
else {
00485 StartingVa =
MI_VPN_TO_VA (NextVad->
StartingVpn);
00486
00487
if (SizeOfRange <
00488 ((ULONG_PTR)StartingVa -
00489
MI_ROUND_TO_SIZE((ULONG_PTR)EndingVa, Alignment))) {
00490
00491
00492
00493
00494
00495
00496
if ((ULONG_PTR)StartingVa >
00497
MI_ROUND_TO_SIZE((ULONG_PTR)EndingVa,Alignment)) {
00498
return (
PMMADDRESS_NODE)
MI_ROUND_TO_SIZE((ULONG_PTR)EndingVa,
00499 Alignment);
00500 }
00501 }
00502 }
00503 }
00504
00505
return (
PMMVAD)
MiFindEmptyAddressRangeInTree (
00506 SizeOfRange,
00507 Alignment,
00508 (
PMMADDRESS_NODE)(CurrentProcess->
VadRoot),
00509 (
PMMADDRESS_NODE *)&CurrentProcess->
VadFreeHint);
00510
00511 }
00512
00513
#if DBG
00514
VOID
00515
VadTreeWalk (
00516
PMMVAD Start
00517 )
00518
00519 {
00520 UNREFERENCED_PARAMETER (Start);
00521
00522
NodeTreeWalk ( (
PMMADDRESS_NODE)(
PsGetCurrentProcess()->VadRoot));
00523
00524
return;
00525 }
00526
#endif //DBG