00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
#include "mi.h"
00024
00025 #define MM_MAXIMUM_QUOTA_OVERCHARGE 9
00026
00027 #define MM_DONT_EXTEND_SIZE 512
00028
00029 #define MM_COMMIT_POPUP_MAX ((512*1024)/PAGE_SIZE)
00030
00031 #define MM_EXTEND_COMMIT ((1024*1024)/PAGE_SIZE)
00032
00033 SIZE_T
MmPeakCommitment;
00034
00035 SIZE_T
MmExtendedCommit;
00036
00037 SIZE_T
MmExtendedCommitLimit;
00038
00039 LOGICAL
MiCommitExtensionActive =
FALSE;
00040
00041 extern ULONG_PTR
MmAllocatedPagedPool;
00042
00043 extern SIZE_T
MmPageFileFullExtendPages;
00044
00045 ULONG
MiOverCommitCallCount;
00046 extern EPROCESS_QUOTA_BLOCK PspDefaultQuotaBlock;
00047
00048
00049 LOGICAL
00050
MiCauseOverCommitPopup(
00051 IN SIZE_T NumberOfPages,
00052 IN ULONG Extension
00053 );
00054
00055
00056 ULONG
00057
FASTCALL
00058 MiChargePageFileQuota (
00059 IN SIZE_T QuotaCharge,
00060 IN
PEPROCESS CurrentProcess
00061 )
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 {
00090 SIZE_T NewPagefileValue;
00091
PEPROCESS_QUOTA_BLOCK QuotaBlock;
00092 KIRQL OldIrql;
00093
00094 QuotaBlock = CurrentProcess->QuotaBlock;
00095
00096 retry_charge:
00097
if ( QuotaBlock != &
PspDefaultQuotaBlock) {
00098 ExAcquireFastLock (&QuotaBlock->
QuotaLock,&OldIrql);
00099 do_charge:
00100 NewPagefileValue = QuotaBlock->
PagefileUsage + QuotaCharge;
00101
00102
if (NewPagefileValue > QuotaBlock->
PagefileLimit) {
00103 ExReleaseFastLock (&QuotaBlock->
QuotaLock,OldIrql);
00104
ExRaiseStatus (STATUS_PAGEFILE_QUOTA_EXCEEDED);
00105 }
00106
00107 QuotaBlock->
PagefileUsage = NewPagefileValue;
00108
00109
if (NewPagefileValue > QuotaBlock->
PeakPagefileUsage) {
00110 QuotaBlock->
PeakPagefileUsage = NewPagefileValue;
00111 }
00112
00113 NewPagefileValue = CurrentProcess->PagefileUsage + QuotaCharge;
00114 CurrentProcess->PagefileUsage = NewPagefileValue;
00115
00116
if (NewPagefileValue > CurrentProcess->PeakPagefileUsage) {
00117 CurrentProcess->PeakPagefileUsage = NewPagefileValue;
00118 }
00119 ExReleaseFastLock (&QuotaBlock->
QuotaLock,OldIrql);
00120 }
else {
00121 ExAcquireFastLock (&
PspDefaultQuotaBlock.
QuotaLock,&OldIrql);
00122
00123
if ( (QuotaBlock = CurrentProcess->QuotaBlock) != &
PspDefaultQuotaBlock) {
00124 ExReleaseFastLock(&
PspDefaultQuotaBlock.
QuotaLock,OldIrql);
00125
goto retry_charge;
00126 }
00127
goto do_charge;
00128 }
00129
return TRUE;
00130 }
00131
00132
VOID
00133 MiReturnPageFileQuota (
00134 IN SIZE_T QuotaCharge,
00135 IN
PEPROCESS CurrentProcess
00136 )
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 {
00162
00163
PEPROCESS_QUOTA_BLOCK QuotaBlock;
00164 KIRQL OldIrql;
00165
00166 QuotaBlock = CurrentProcess->QuotaBlock;
00167
00168 retry_return:
00169
if ( QuotaBlock != &
PspDefaultQuotaBlock) {
00170 ExAcquireFastLock (&QuotaBlock->
QuotaLock, &OldIrql);
00171 do_return:
00172
ASSERT (CurrentProcess->PagefileUsage >= QuotaCharge);
00173 CurrentProcess->PagefileUsage -= QuotaCharge;
00174
00175
ASSERT (QuotaBlock->
PagefileUsage >= QuotaCharge);
00176 QuotaBlock->
PagefileUsage -= QuotaCharge;
00177 ExReleaseFastLock(&QuotaBlock->
QuotaLock,OldIrql);
00178 }
else {
00179 ExAcquireFastLock (&
PspDefaultQuotaBlock.
QuotaLock, &OldIrql);
00180
if ( (QuotaBlock = CurrentProcess->QuotaBlock) != &
PspDefaultQuotaBlock ) {
00181 ExReleaseFastLock(&
PspDefaultQuotaBlock.
QuotaLock,OldIrql);
00182
goto retry_return;
00183 }
00184
goto do_return;
00185 }
00186
return;
00187 }
00188
00189 LOGICAL
00190
FASTCALL
00191 MiChargeCommitment (
00192 IN SIZE_T QuotaCharge,
00193 IN
PEPROCESS Process OPTIONAL
00194 )
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 {
00224 KIRQL OldIrql;
00225 SIZE_T NewCommitValue;
00226
MMPAGE_FILE_EXPANSION PageExtend;
00227 LOGICAL WsHeldSafe;
00228
00229
#if !defined (_WIN64)
00230
ASSERT (QuotaCharge < 0x100000);
00231
#endif
00232
00233 ExAcquireFastLock (&
MmChargeCommitmentLock, &OldIrql);
00234
00235 NewCommitValue =
MmTotalCommittedPages + QuotaCharge;
00236
00237
while (NewCommitValue >
MmTotalCommitLimit) {
00238
00239 ExReleaseFastLock (&
MmChargeCommitmentLock, OldIrql);
00240
00241
if (Process !=
NULL) {
00242
00243
00244
00245
00246
00247
00248
UNLOCK_WS_REGARDLESS(Process, WsHeldSafe);
00249 }
00250
00251
00252
00253
00254
00255
00256
00257
00258 PageExtend.
RequestedExpansionSize = QuotaCharge;
00259 PageExtend.
Segment =
NULL;
00260 PageExtend.
PageFileNumber =
MI_EXTEND_ANY_PAGEFILE;
00261
KeInitializeEvent (&PageExtend.
Event, NotificationEvent,
FALSE);
00262
00263
if (
MiIssuePageExtendRequest (&PageExtend) ==
FALSE) {
00264
00265
if (Process !=
NULL) {
00266
LOCK_WS_REGARDLESS(Process, WsHeldSafe);
00267 }
00268
00269
00270
00271
00272
00273
00274
if (QuotaCharge <
MM_MAXIMUM_QUOTA_OVERCHARGE) {
00275
00276
00277
00278
00279
00280
if (
MiChargeCommitmentCantExpand (QuotaCharge,
FALSE) ==
FALSE) {
00281
return FALSE;
00282 }
00283 }
else {
00284
00285
00286
00287
00288
00289
if (
MiCauseOverCommitPopup (QuotaCharge,
MM_EXTEND_COMMIT) ==
FALSE) {
00290
return FALSE;
00291 }
00292 }
00293
return TRUE;
00294 }
00295
00296
if (Process !=
NULL) {
00297
if (WsHeldSafe ==
TRUE) {
00298
LOCK_WS (Process);
00299 }
00300
else {
00301
LOCK_WS_UNSAFE (Process);
00302 }
00303 }
00304
00305
if (PageExtend.
ActualExpansion == 0) {
00306
if (
MiCauseOverCommitPopup (QuotaCharge,
MM_EXTEND_COMMIT) ==
FALSE) {
00307
return FALSE;
00308 }
00309
return TRUE;
00310 }
00311
00312 ExAcquireFastLock (&
MmChargeCommitmentLock, &OldIrql);
00313 NewCommitValue =
MmTotalCommittedPages + QuotaCharge;
00314 }
00315
00316
MmTotalCommittedPages = NewCommitValue;
00317
if ((
MmTotalCommittedPages >
MmPeakCommitment) &&
00318 (
MmPageFileFullExtendPages == 0)) {
00319
MmPeakCommitment =
MmTotalCommittedPages;
00320 }
00321
00322 ExReleaseFastLock (&
MmChargeCommitmentLock, OldIrql);
00323
00324
return TRUE;
00325 }
00326
00327 LOGICAL
00328
FASTCALL
00329 MiChargeCommitmentCantExpand (
00330 IN SIZE_T QuotaCharge,
00331 IN ULONG MustSucceed
00332 )
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359 {
00360 KIRQL OldIrql;
00361 SIZE_T NewCommitValue;
00362 SIZE_T ExtendAmount;
00363
00364 ExAcquireFastLock (&
MmChargeCommitmentLock, &OldIrql);
00365
00366
00367
00368
00369
00370 NewCommitValue =
MmTotalCommittedPages + QuotaCharge;
00371
00372
if (!MustSucceed) {
00373
00374
if (NewCommitValue >
MmTotalCommitLimit) {
00375
00376
if ((NewCommitValue -
MmTotalCommitLimit >
MM_DONT_EXTEND_SIZE) ||
00377 (NewCommitValue <
MmTotalCommittedPages) ||
00378 (NewCommitValue >
MmTotalCommitLimitMaximum)) {
00379
00380 ExReleaseFastLock (&
MmChargeCommitmentLock, OldIrql);
00381
return FALSE;
00382 }
00383 }
00384
else if (NewCommitValue >
MmTotalCommitLimitMaximum) {
00385 ExReleaseFastLock (&
MmChargeCommitmentLock, OldIrql);
00386
return FALSE;
00387 }
00388 }
00389
00390 ExtendAmount = NewCommitValue -
MmTotalCommitLimit;
00391
MmTotalCommittedPages = NewCommitValue;
00392
00393
if (NewCommitValue > (
MmTotalCommitLimit + 20)) {
00394
00395
00396
00397
00398
00399
00400
if (
MmAttemptForCantExtend.
InProgress !=
FALSE) {
00401
00402
00403
00404
00405
00406
00407 ExReleaseFastLock (&
MmChargeCommitmentLock, OldIrql);
00408
return TRUE;
00409 }
00410
00411
MmAttemptForCantExtend.
InProgress =
TRUE;
00412 ExReleaseFastLock (&
MmChargeCommitmentLock, OldIrql);
00413
00414
00415
00416
00417
00418
00419
00420
00421
if (QuotaCharge > ExtendAmount) {
00422 ExtendAmount = QuotaCharge;
00423 }
00424
00425
MmAttemptForCantExtend.
RequestedExpansionSize = ExtendAmount;
00426 ExAcquireFastLock (&
MmDereferenceSegmentHeader.
Lock, &OldIrql);
00427 InsertTailList ( &
MmDereferenceSegmentHeader.
ListHead,
00428 &
MmAttemptForCantExtend.
DereferenceList);
00429 ExReleaseFastLock (&
MmDereferenceSegmentHeader.
Lock, OldIrql);
00430
00431
KeReleaseSemaphore (&
MmDereferenceSegmentHeader.
Semaphore, 0
L, 1
L,
FALSE);
00432 }
00433
else {
00434 ExReleaseFastLock (&
MmChargeCommitmentLock, OldIrql);
00435 }
00436
00437
return TRUE;
00438 }
00439
00440
VOID
00441
FASTCALL
00442 MiReturnCommitment (
00443 IN SIZE_T QuotaCharge
00444 )
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 {
00470 KIRQL OldIrql;
00471
00472 ExAcquireFastLock (&
MmChargeCommitmentLock, &OldIrql);
00473
00474
ASSERT (
MmTotalCommittedPages >= QuotaCharge);
00475
00476
MmTotalCommittedPages -= QuotaCharge;
00477
00478
00479
00480
00481
00482
00483
00484
if (
MmPageFileFullExtendPages) {
00485
ASSERT (
MmTotalCommittedPages >=
MmPageFileFullExtendPages);
00486
MmTotalCommittedPages -=
MmPageFileFullExtendPages;
00487
MmPageFileFullExtendPages = 0;
00488 }
00489
00490
00491
00492
00493
00494
00495
if (
MiCommitExtensionActive ==
TRUE) {
00496
00497
if ((
MmExtendedCommitLimit != 0) &&
00498 (
MmTotalCommitLimit >
MmTotalCommittedPages) &&
00499 (
MmTotalCommitLimit -
MmTotalCommittedPages >
MmExtendedCommitLimit)) {
00500
MmTotalCommitLimit -=
MmExtendedCommitLimit;
00501
MmExtendedCommitLimit = 0;
00502 }
00503
00504
if (
MmExtendedCommit != 0) {
00505
MmTotalCommittedPages -=
MmExtendedCommit;
00506
MmExtendedCommit = 0;
00507 }
00508
00509
if ((
MmExtendedCommitLimit == 0) && (
MmExtendedCommit == 0)) {
00510
MiCommitExtensionActive =
FALSE;
00511 }
00512 }
00513
00514 ExReleaseFastLock (&
MmChargeCommitmentLock, OldIrql);
00515
return;
00516 }
00517
00518 SIZE_T
00519 MiCalculatePageCommitment (
00520 IN PVOID StartingAddress,
00521 IN PVOID EndingAddress,
00522 IN
PMMVAD Vad,
00523 IN
PEPROCESS Process
00524 )
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555 {
00556
PMMPTE PointerPte;
00557
PMMPTE LastPte;
00558
PMMPTE PointerPde;
00559
PMMPTE PointerPpe;
00560
PMMPTE TempEnd;
00561 SIZE_T NumberOfCommittedPages;
00562 ULONG Waited;
00563
00564 NumberOfCommittedPages = 0;
00565
00566 PointerPpe =
MiGetPpeAddress (StartingAddress);
00567 PointerPde =
MiGetPdeAddress (StartingAddress);
00568 PointerPte =
MiGetPteAddress (StartingAddress);
00569
00570
if (Vad->u.VadFlags.MemCommit == 1) {
00571
00572 TempEnd = EndingAddress;
00573
00574
00575
00576
00577
00578 NumberOfCommittedPages =
BYTES_TO_PAGES ((PCHAR)TempEnd -
00579 (PCHAR)StartingAddress);
00580
00581
00582
00583
00584
00585
00586 LastPte =
MiGetPteAddress (TempEnd);
00587
00588
do {
00589
00590
while (!
MiDoesPpeExistAndMakeValid (PointerPpe,
00591 Process,
00592
FALSE,
00593 &Waited)) {
00594
00595
00596
00597
00598
00599
00600 PointerPpe += 1;
00601 PointerPde =
MiGetVirtualAddressMappedByPte (PointerPpe);
00602 PointerPte =
MiGetVirtualAddressMappedByPte (PointerPde);
00603
if (PointerPte > LastPte) {
00604
goto DoneCommit;
00605 }
00606 }
00607
00608 Waited = 0;
00609
00610
while (!
MiDoesPdeExistAndMakeValid (PointerPde,
00611 Process,
00612
FALSE,
00613 &Waited)) {
00614
00615
00616
00617
00618
00619
00620 PointerPde += 1;
00621 PointerPpe =
MiGetPteAddress (PointerPde);
00622 PointerPte =
MiGetVirtualAddressMappedByPte (PointerPde);
00623
if (PointerPte > LastPte) {
00624
goto DoneCommit;
00625 }
00626
#if defined (_WIN64)
00627
if (
MiIsPteOnPdeBoundary (PointerPde)) {
00628 Waited = 1;
00629
break;
00630 }
00631
#endif
00632
}
00633
00634 }
while (Waited != 0);
00635
00636 restart:
00637
00638
while (PointerPte <= LastPte) {
00639
00640
if (
MiIsPteOnPdeBoundary (PointerPte)) {
00641
00642
00643
00644
00645
00646
00647 PointerPde =
MiGetPteAddress (PointerPte);
00648 PointerPpe =
MiGetPteAddress (PointerPde);
00649
00650
do {
00651
00652
if (!
MiDoesPpeExistAndMakeValid (PointerPpe,
00653 Process,
00654
FALSE,
00655 &Waited)) {
00656
00657
00658
00659
00660
00661
00662 PointerPpe += 1;
00663 PointerPde =
MiGetVirtualAddressMappedByPte (PointerPpe);
00664 PointerPte =
MiGetVirtualAddressMappedByPte (PointerPde);
00665
00666
00667
00668
00669
00670
goto restart;
00671 }
00672
00673 Waited = 0;
00674
00675
if (!
MiDoesPdeExistAndMakeValid (PointerPde,
00676 Process,
00677
FALSE,
00678 &Waited)) {
00679
00680
00681
00682
00683
00684
00685 PointerPde += 1;
00686 PointerPpe =
MiGetPteAddress (PointerPde);
00687 PointerPte =
MiGetVirtualAddressMappedByPte (PointerPde);
00688
00689
00690
00691
00692
00693
goto restart;
00694 }
00695 }
while (Waited != 0);
00696 }
00697
00698
00699
00700
00701
00702
if (PointerPte->
u.Long != 0) {
00703
00704
00705
00706
00707
00708
if (
MiIsPteDecommittedPage (PointerPte)) {
00709
00710
00711
00712
00713
00714 NumberOfCommittedPages -= 1;
00715
00716 }
00717 }
00718
00719 PointerPte += 1;
00720 }
00721
00722 DoneCommit:
00723
00724
if (TempEnd == EndingAddress) {
00725
return NumberOfCommittedPages;
00726 }
00727
00728 }
00729
00730
00731
00732
00733
00734 LastPte =
MiGetPteAddress (EndingAddress);
00735
00736
do {
00737
00738
while (!
MiDoesPpeExistAndMakeValid (PointerPpe,
00739 Process,
00740
FALSE,
00741 &Waited)) {
00742
00743
00744
00745
00746
00747
00748
00749 PointerPpe += 1;
00750 PointerPde =
MiGetVirtualAddressMappedByPte (PointerPpe);
00751 PointerPte =
MiGetVirtualAddressMappedByPte (PointerPde);
00752
if (PointerPte > LastPte) {
00753
return NumberOfCommittedPages;
00754 }
00755 }
00756
00757 Waited = 0;
00758
00759
while (!
MiDoesPdeExistAndMakeValid (PointerPde,
00760 Process,
00761
FALSE,
00762 &Waited)) {
00763
00764
00765
00766
00767
00768
00769 PointerPde += 1;
00770 PointerPte =
MiGetVirtualAddressMappedByPte (PointerPde);
00771
if (PointerPte > LastPte) {
00772
return NumberOfCommittedPages;
00773 }
00774
#if defined (_WIN64)
00775
if (
MiIsPteOnPdeBoundary (PointerPde)) {
00776 PointerPpe =
MiGetPteAddress (PointerPde);
00777 Waited = 1;
00778
break;
00779 }
00780
#endif
00781
}
00782
00783 }
while (Waited != 0);
00784
00785 restart2:
00786
00787
while (PointerPte <= LastPte) {
00788
00789
if (
MiIsPteOnPdeBoundary (PointerPte)) {
00790
00791
00792
00793
00794
00795
00796 PointerPde =
MiGetPteAddress (PointerPte);
00797 PointerPpe =
MiGetPteAddress (PointerPde);
00798
00799
do {
00800
00801
if (!
MiDoesPpeExistAndMakeValid (PointerPpe,
00802 Process,
00803
FALSE,
00804 &Waited)) {
00805
00806
00807
00808
00809
00810
00811 PointerPpe += 1;
00812 PointerPde =
MiGetVirtualAddressMappedByPte (PointerPpe);
00813 PointerPte =
MiGetVirtualAddressMappedByPte (PointerPde);
00814
00815
00816
00817
00818
00819
goto restart2;
00820 }
00821
00822 Waited = 0;
00823
00824
if (!
MiDoesPdeExistAndMakeValid (PointerPde,
00825 Process,
00826
FALSE,
00827 &Waited)) {
00828
00829
00830
00831
00832
00833
00834 PointerPde += 1;
00835 PointerPpe =
MiGetPteAddress (PointerPde);
00836 PointerPte =
MiGetVirtualAddressMappedByPte (PointerPde);
00837
00838
00839
00840
00841
00842
goto restart2;
00843 }
00844
00845 }
while (Waited != 0);
00846 }
00847
00848
00849
00850
00851
00852
if ((PointerPte->
u.Long != 0) &&
00853 (!
MiIsPteDecommittedPage (PointerPte))) {
00854
00855
00856
00857
00858
00859 NumberOfCommittedPages += 1;
00860 }
00861
00862 PointerPte += 1;
00863 }
00864
00865
return NumberOfCommittedPages;
00866 }
00867
00868
VOID
00869 MiReturnPageTablePageCommitment (
00870 IN PVOID StartingAddress,
00871 IN PVOID EndingAddress,
00872 IN
PEPROCESS CurrentProcess,
00873 IN
PMMVAD PreviousVad,
00874 IN
PMMVAD NextVad
00875 )
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911 {
00912
#ifdef _WIN64
00913
DBG_UNREFERENCED_PARAMETER (StartingAddress);
00914 DBG_UNREFERENCED_PARAMETER (EndingAddress);
00915 DBG_UNREFERENCED_PARAMETER (CurrentProcess);
00916 DBG_UNREFERENCED_PARAMETER (PreviousVad);
00917 DBG_UNREFERENCED_PARAMETER (NextVad);
00918
#else
00919
ULONG NumberToClear;
00920 LONG FirstPage;
00921 LONG LastPage;
00922 LONG PreviousPage;
00923 LONG NextPage;
00924
00925
00926
00927
00928
00929
ASSERT (StartingAddress != EndingAddress);
00930
00931
if (PreviousVad ==
NULL) {
00932 PreviousPage = -1;
00933 }
else {
00934 PreviousPage =
MiGetPpePdeOffset (
MI_VPN_TO_VA (PreviousVad->EndingVpn));
00935 }
00936
00937
if (NextVad ==
NULL) {
00938 NextPage =
MiGetPpePdeOffset (MM_HIGHEST_USER_ADDRESS) + 1;
00939 }
else {
00940 NextPage =
MiGetPpePdeOffset (
MI_VPN_TO_VA (NextVad->StartingVpn));
00941 }
00942
00943
ASSERT (PreviousPage <= NextPage);
00944
00945 FirstPage =
MiGetPpePdeOffset (StartingAddress);
00946
00947 LastPage =
MiGetPpePdeOffset (EndingAddress);
00948
00949
if (PreviousPage == FirstPage) {
00950
00951
00952
00953
00954
00955 FirstPage += 1;
00956 }
00957
00958
if (NextPage == LastPage) {
00959
00960
00961
00962
00963
00964 LastPage -= 1;
00965 }
00966
00967
00968
00969
00970
00971
if (FirstPage > LastPage) {
00972
return;
00973 }
00974
00975 NumberToClear = 1 + LastPage - FirstPage;
00976
00977
while (FirstPage <= LastPage) {
00978
ASSERT (
MI_CHECK_BIT (
MmWorkingSetList->
CommittedPageTables,
00979 FirstPage));
00980
00981
MI_CLEAR_BIT (
MmWorkingSetList->
CommittedPageTables, FirstPage);
00982 FirstPage += 1;
00983 }
00984
00985
MmWorkingSetList->
NumberOfCommittedPageTables -= NumberToClear;
00986
MiReturnCommitment (NumberToClear);
00987
MM_TRACK_COMMIT (
MM_DBG_COMMIT_RETURN_PAGETABLES, NumberToClear);
00988
MiReturnPageFileQuota (NumberToClear, CurrentProcess);
00989
00990
if (CurrentProcess->JobStatus &
PS_JOB_STATUS_REPORT_COMMIT_CHANGES) {
00991
PsChangeJobMemoryUsage(-(SSIZE_T)NumberToClear);
00992 }
00993 CurrentProcess->CommitCharge -= NumberToClear;
00994
00995
return;
00996
#endif
00997
}
00998
00999
01000 LOGICAL
01001 MiCauseOverCommitPopup(
01002 SIZE_T NumberOfPages,
01003 IN ULONG Extension
01004 )
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028 {
01029 KIRQL OldIrql;
01030 BOOLEAN RaisedPopup;
01031 ULONG PopupNumber;
01032
01033
if (NumberOfPages >
MM_COMMIT_POPUP_MAX ||
01034
MmTotalCommittedPages + NumberOfPages >
MmTotalCommitLimitMaximum) {
01035
return FALSE;
01036 }
01037
01038
01039
01040
01041
01042
01043
if (
MmTotalCommittedPages >
MmTotalCommitLimitMaximum - 100) {
01044 PopupNumber = STATUS_COMMITMENT_LIMIT;
01045 }
01046
else {
01047 PopupNumber = STATUS_COMMITMENT_MINIMUM;
01048 }
01049
01050 RaisedPopup =
IoRaiseInformationalHardError (PopupNumber,
NULL,
NULL);
01051
01052 ExAcquireFastLock (&
MmChargeCommitmentLock, &OldIrql);
01053
01054
if ((RaisedPopup ==
FALSE) && (
MiOverCommitCallCount > 0)) {
01055
01056
01057
01058
01059
01060
01061 ExReleaseFastLock (&
MmChargeCommitmentLock, OldIrql);
01062
return FALSE;
01063 }
01064
01065
01066
01067
01068
01069
01070
if (
MmTotalCommittedPages + NumberOfPages >
MmTotalCommitLimitMaximum) {
01071 ExReleaseFastLock (&
MmChargeCommitmentLock, OldIrql);
01072
return FALSE;
01073 }
01074
01075
01076
01077
01078
01079
01080
if (
MmExtendedCommit > 1024) {
01081 ExReleaseFastLock (&
MmChargeCommitmentLock, OldIrql);
01082
return FALSE;
01083 }
01084
01085
MiOverCommitCallCount += 1;
01086
01087
MiCommitExtensionActive =
TRUE;
01088
01089
MmTotalCommitLimit += Extension;
01090
MmExtendedCommitLimit += Extension;
01091
01092
MmTotalCommittedPages += NumberOfPages;
01093
01094
01095
01096
01097
01098
01099
if (Extension == 0) {
01100
MmExtendedCommit += NumberOfPages;
01101 }
01102
01103
if ((
MmTotalCommittedPages >
MmPeakCommitment) &&
01104 (
MmPageFileFullExtendPages == 0)) {
01105
MmPeakCommitment =
MmTotalCommittedPages;
01106 }
01107
01108 ExReleaseFastLock (&
MmChargeCommitmentLock, OldIrql);
01109
01110
return TRUE;
01111 }
01112
01113
01114 SIZE_T
MmTotalPagedPoolQuota;
01115 SIZE_T
MmTotalNonPagedPoolQuota;
01116
01117 BOOLEAN
01118 MmRaisePoolQuota(
01119 IN POOL_TYPE PoolType,
01120 IN SIZE_T OldQuotaLimit,
01121 OUT PSIZE_T NewQuotaLimit
01122 )
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152 {
01153 SIZE_T Limit;
01154
PMM_PAGED_POOL_INFO PagedPoolInfo;
01155
01156
if (PoolType ==
PagedPool) {
01157
01158
01159
01160
01161
01162
01163 PagedPoolInfo = &
MmPagedPoolInfo;
01164
01165
if ((
MmSizeOfPagedPoolInBytes >>
PAGE_SHIFT) <
01166 (PagedPoolInfo->
AllocatedPagedPool + ((
MMPAGED_QUOTA_CHECK) >>
PAGE_SHIFT))) {
01167
01168
return FALSE;
01169 }
01170
01171
MmTotalPagedPoolQuota += (
MMPAGED_QUOTA_INCREASE);
01172 *NewQuotaLimit = OldQuotaLimit + (
MMPAGED_QUOTA_INCREASE);
01173
return TRUE;
01174
01175 }
else {
01176
01177
if ( (ULONG_PTR)(
MmAllocatedNonPagedPool + ((1*1024*1024) >>
PAGE_SHIFT)) < (
MmMaximumNonPagedPoolInBytes >>
PAGE_SHIFT)) {
01178
goto aok;
01179 }
01180
01181
01182
01183
01184
01185
01186
if ((
MmAvailablePages < 200) ||
01187 (MmResidentAvailablePages < ((MMNONPAGED_QUOTA_CHECK) >>
PAGE_SHIFT))) {
01188
01189
return FALSE;
01190 }
01191
01192
if (
MmAvailablePages > ((4*1024*1024) >>
PAGE_SHIFT)) {
01193 Limit = (1*1024*1024) >>
PAGE_SHIFT;
01194 }
else {
01195 Limit = (4*1024*1024) >>
PAGE_SHIFT;
01196 }
01197
01198
if ((ULONG_PTR)((
MmMaximumNonPagedPoolInBytes >>
PAGE_SHIFT)) <
01199 (
MmAllocatedNonPagedPool + Limit)) {
01200
01201
return FALSE;
01202 }
01203 aok:
01204
MmTotalNonPagedPoolQuota += (
MMNONPAGED_QUOTA_INCREASE);
01205 *NewQuotaLimit = OldQuotaLimit + (
MMNONPAGED_QUOTA_INCREASE);
01206
return TRUE;
01207 }
01208 }
01209
01210
01211
VOID
01212 MmReturnPoolQuota(
01213 IN POOL_TYPE PoolType,
01214 IN SIZE_T ReturnedQuota
01215 )
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239 {
01240
01241
if (PoolType ==
PagedPool) {
01242
MmTotalPagedPoolQuota -= ReturnedQuota;
01243 }
else {
01244
MmTotalNonPagedPoolQuota -= ReturnedQuota;
01245 }
01246
01247
return;
01248 }