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
VOID
00026 MiDeleteVirtualAddresses (
00027 IN PUCHAR StartingAddress,
00028 IN PUCHAR EndingAddress,
00029 IN ULONG AddressSpaceDeletion,
00030 IN
PMMVAD Vad
00031 )
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 {
00070 PUCHAR Va;
00071 PUCHAR FirstValidVa;
00072 PVOID TempVa;
00073
PMMPTE PointerPte;
00074
PMMPTE PointerPde;
00075
PMMPTE PointerPpe;
00076
PMMPTE OriginalPointerPte;
00077
PMMPTE ProtoPte;
00078
PMMPTE ProtoPte2;
00079
PMMPTE LastProtoPte;
00080
PMMPTE LastProtoPte2;
00081
PEPROCESS CurrentProcess;
00082
PSUBSECTION Subsection;
00083 PVOID UsedPageTableHandle;
00084 PVOID UsedPageDirectoryHandle;
00085 KIRQL OldIrql;
00086
MMPTE_FLUSH_LIST FlushList;
00087 ULONG Waited;
00088 LOGICAL Skipped;
00089
00090 OldIrql =
APC_LEVEL;
00091 FlushList.
Count = 0;
00092
00093
MM_PFN_LOCK_ASSERT();
00094 CurrentProcess =
PsGetCurrentProcess();
00095
00096 Va = StartingAddress;
00097 PointerPpe =
MiGetPpeAddress (Va);
00098 PointerPde =
MiGetPdeAddress (Va);
00099 PointerPte =
MiGetPteAddress (Va);
00100 OriginalPointerPte = PointerPte;
00101
00102
do {
00103
00104
while (
MiDoesPpeExistAndMakeValid (PointerPpe,
00105 CurrentProcess,
00106
TRUE,
00107 &Waited) ==
FALSE) {
00108
00109
00110
00111
00112
00113 PointerPpe += 1;
00114 PointerPde =
MiGetVirtualAddressMappedByPte (PointerPpe);
00115 PointerPte =
MiGetVirtualAddressMappedByPte (PointerPde);
00116 Va =
MiGetVirtualAddressMappedByPte (PointerPte);
00117
00118
if (Va > EndingAddress) {
00119
00120
00121
00122
00123
00124
return;
00125 }
00126 }
00127
00128 Waited = 0;
00129
00130
while (
MiDoesPdeExistAndMakeValid (PointerPde,
00131 CurrentProcess,
00132
TRUE,
00133 &Waited) ==
FALSE) {
00134
00135
00136
00137
00138
00139 PointerPde += 1;
00140 PointerPte =
MiGetVirtualAddressMappedByPte (PointerPde);
00141 Va =
MiGetVirtualAddressMappedByPte (PointerPte);
00142
00143
if (Va > EndingAddress) {
00144
00145
00146
00147
00148
00149
return;
00150 }
00151
#if defined (_WIN64)
00152
if (
MiIsPteOnPdeBoundary (PointerPde)) {
00153 PointerPpe =
MiGetPteAddress (PointerPde);
00154 Waited = 1;
00155
break;
00156 }
00157
#endif
00158
}
00159
00160 }
while (Waited != 0);
00161
00162 FirstValidVa = Va;
00163 UsedPageTableHandle =
MI_GET_USED_PTES_HANDLE (Va);
00164
00165
00166
00167
00168
00169
if ((Vad == (
PMMVAD)
NULL) ||
00170 (Vad->u.VadFlags.PrivateMemory) ||
00171 (Vad->FirstPrototypePte == (
PMMPTE)
NULL)) {
00172 ProtoPte = (
PMMPTE)
NULL;
00173 LastProtoPte = (
PMMPTE)
NULL;
00174 }
else {
00175 ProtoPte = Vad->FirstPrototypePte;
00176 LastProtoPte = (
PMMPTE)4;
00177 }
00178
00179
00180
00181
00182
00183
while (Va <= EndingAddress) {
00184
00185
00186
00187
00188
00189
00190
if (
MiIsVirtualAddressOnPdeBoundary(Va)) {
00191
00192
00193
00194
00195
00196
00197
00198
MiFlushPteList (&FlushList,
FALSE,
ZeroPte);
00199
00200
00201
00202
00203
00204
00205
if ((
MI_GET_USED_PTES_FROM_HANDLE (UsedPageTableHandle) == 0) &&
00206 (PointerPde->
u.Long != 0)) {
00207
00208 TempVa =
MiGetVirtualAddressMappedByPte(PointerPde);
00209
MiDeletePte (PointerPde,
00210 TempVa,
00211 AddressSpaceDeletion,
00212 CurrentProcess,
00213
NULL,
00214
NULL);
00215
00216
#if defined (_WIN64)
00217
if (Va == FirstValidVa) {
00218 UsedPageDirectoryHandle =
MI_GET_USED_PTES_HANDLE (PointerPte);
00219 }
00220
else {
00221 UsedPageDirectoryHandle =
MI_GET_USED_PTES_HANDLE (PointerPte - 1);
00222 }
00223
00224
MI_DECREMENT_USED_PTES_BY_HANDLE (UsedPageDirectoryHandle);
00225
#endif
00226
00227 }
00228
00229
if (
MiIsVirtualAddressOnPpeBoundary(Va)) {
00230
00231
if (Va == FirstValidVa) {
00232 UsedPageDirectoryHandle =
MI_GET_USED_PTES_HANDLE (PointerPte);
00233 }
00234
else {
00235 UsedPageDirectoryHandle =
MI_GET_USED_PTES_HANDLE (PointerPte - 1);
00236 }
00237
00238
if ((
MI_GET_USED_PTES_FROM_HANDLE (UsedPageDirectoryHandle) == 0) &&
00239 (PointerPpe->
u.Long != 0)) {
00240
00241 TempVa =
MiGetVirtualAddressMappedByPte(PointerPpe);
00242
MiDeletePte (PointerPpe,
00243 TempVa,
00244 AddressSpaceDeletion,
00245 CurrentProcess,
00246
NULL,
00247
NULL);
00248 }
00249 }
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
UNLOCK_PFN (OldIrql);
00260 PointerPde =
MiGetPdeAddress (Va);
00261 PointerPpe =
MiGetPpeAddress (Va);
00262 Skipped =
FALSE;
00263
LOCK_PFN (OldIrql);
00264
00265
do {
00266
while (
MiDoesPpeExistAndMakeValid (PointerPpe,
00267 CurrentProcess,
00268
TRUE,
00269 &Waited) ==
FALSE) {
00270
00271
00272
00273
00274
00275
00276 Skipped =
TRUE;
00277 PointerPpe += 1;
00278 PointerPde =
MiGetVirtualAddressMappedByPte (PointerPpe);
00279 PointerPte =
MiGetVirtualAddressMappedByPte (PointerPde);
00280 Va =
MiGetVirtualAddressMappedByPte (PointerPte);
00281
00282
if (Va > EndingAddress) {
00283
00284
00285
00286
00287
00288
return;
00289 }
00290 }
00291
00292 Waited = 0;
00293
00294
while (
MiDoesPdeExistAndMakeValid (PointerPde,
00295 CurrentProcess,
00296
TRUE,
00297 &Waited) ==
FALSE) {
00298
00299
00300
00301
00302
00303 Skipped =
TRUE;
00304 PointerPde += 1;
00305 PointerPte =
MiGetVirtualAddressMappedByPte (PointerPde);
00306 Va =
MiGetVirtualAddressMappedByPte (PointerPte);
00307
00308
if (Va > EndingAddress) {
00309
00310
00311
00312
00313
00314
00315
#if defined (_WIN64)
00316
00317 PointerPde -= 1;
00318 PointerPte =
MiGetVirtualAddressMappedByPte (PointerPde);
00319 UsedPageDirectoryHandle =
MI_GET_USED_PTES_HANDLE (PointerPte);
00320
00321
if ((
MI_GET_USED_PTES_FROM_HANDLE (UsedPageDirectoryHandle) == 0) &&
00322 (PointerPpe->
u.Long != 0)) {
00323
00324 TempVa =
MiGetVirtualAddressMappedByPte(PointerPpe);
00325
MiDeletePte (PointerPpe,
00326 TempVa,
00327 AddressSpaceDeletion,
00328 CurrentProcess,
00329
NULL,
00330
NULL);
00331 }
00332
#endif
00333
00334
return;
00335 }
00336
00337
#if defined (_WIN64)
00338
if (
MiIsPteOnPdeBoundary (PointerPde)) {
00339 PointerPpe =
MiGetPteAddress (PointerPde);
00340 Waited = 1;
00341
break;
00342 }
00343
#endif
00344
00345
#if DBG
00346
if ((LastProtoPte !=
NULL) &&
00347 (Vad->u2.VadFlags2.ExtendableFile == 0)) {
00348 ProtoPte2 =
MiGetProtoPteAddress(Vad,
MI_VA_TO_VPN (Va));
00349 Subsection =
MiLocateSubsection (Vad,
MI_VA_TO_VPN (Va));
00350 LastProtoPte2 = &Subsection->
SubsectionBase[Subsection->
PtesInSubsection];
00351
if (Vad->u.VadFlags.ImageMap != 1) {
00352
if ((ProtoPte2 < Subsection->
SubsectionBase) ||
00353 (ProtoPte2 >= LastProtoPte2)) {
00354
DbgPrint (
"bad proto pte %p va %p Vad %p sub %p\n",
00355 ProtoPte2,Va,Vad,Subsection);
00356 DbgBreakPoint();
00357 }
00358 }
00359 }
00360
#endif //DBG
00361
}
00362
00363 }
while (Waited != 0);
00364
00365
00366
00367
00368
00369 UsedPageTableHandle =
MI_GET_USED_PTES_HANDLE (Va);
00370
00371
00372
00373
00374
00375
00376
00377
if ((Skipped ==
TRUE) && (LastProtoPte !=
NULL)) {
00378
00379 ProtoPte =
MiGetProtoPteAddress(Vad,
MI_VA_TO_VPN(Va));
00380 Subsection =
MiLocateSubsection (Vad,
MI_VA_TO_VPN(Va));
00381
00382
if (Subsection !=
NULL) {
00383 LastProtoPte = &Subsection->
SubsectionBase[Subsection->
PtesInSubsection];
00384
#if DBG
00385
if (Vad->u.VadFlags.ImageMap != 1) {
00386
if ((ProtoPte < Subsection->
SubsectionBase) ||
00387 (ProtoPte >= LastProtoPte)) {
00388
DbgPrint (
"bad proto pte %p va %p Vad %p sub %p\n",
00389 ProtoPte,Va,Vad,Subsection);
00390 DbgBreakPoint();
00391 }
00392 }
00393
#endif //DBG
00394
}
00395
else {
00396
00397
00398
00399
00400
00401
00402
00403 LastProtoPte = (
PMMPTE)
NULL;
00404 }
00405 }
00406 }
00407
00408
00409
00410
00411
00412
if (PointerPte->u.Long != 0) {
00413
00414
00415
00416
00417
00418
MI_DECREMENT_USED_PTES_BY_HANDLE (UsedPageTableHandle);
00419
00420
if (
IS_PTE_NOT_DEMAND_ZERO (*PointerPte)) {
00421
00422
if (LastProtoPte !=
NULL) {
00423
if (ProtoPte >= LastProtoPte) {
00424 ProtoPte =
MiGetProtoPteAddress(Vad,
MI_VA_TO_VPN(Va));
00425 Subsection =
MiLocateSubsection (Vad,
MI_VA_TO_VPN(Va));
00426 LastProtoPte = &Subsection->
SubsectionBase[Subsection->
PtesInSubsection];
00427 }
00428
#if DBG
00429
if (Vad->u.VadFlags.ImageMap != 1) {
00430
if ((ProtoPte < Subsection->
SubsectionBase) ||
00431 (ProtoPte >= LastProtoPte)) {
00432
DbgPrint (
"bad proto pte %p va %p Vad %p sub %p\n",
00433 ProtoPte,Va,Vad,Subsection);
00434 DbgBreakPoint();
00435 }
00436 }
00437
#endif //DBG
00438
}
00439
00440
MiDeletePte (PointerPte,
00441 (PVOID)Va,
00442 AddressSpaceDeletion,
00443 CurrentProcess,
00444 ProtoPte,
00445 &FlushList);
00446 }
else {
00447
MI_WRITE_INVALID_PTE (PointerPte,
ZeroPte);
00448 }
00449 }
00450
00451 Va +=
PAGE_SIZE;
00452 PointerPte += 1;
00453 ProtoPte += 1;
00454 }
00455
00456
00457
00458
00459
00460
MiFlushPteList (&FlushList,
FALSE,
ZeroPte);
00461
00462
00463
00464
00465
00466
00467
if ((
MI_GET_USED_PTES_FROM_HANDLE (UsedPageTableHandle) == 0) &&
00468 (PointerPde->
u.Long != 0)) {
00469
00470 TempVa =
MiGetVirtualAddressMappedByPte(PointerPde);
00471
MiDeletePte (PointerPde,
00472 TempVa,
00473 AddressSpaceDeletion,
00474 CurrentProcess,
00475
NULL,
00476
NULL);
00477
00478
#if defined (_WIN64)
00479
UsedPageDirectoryHandle =
MI_GET_USED_PTES_HANDLE (PointerPte - 1);
00480
00481
MI_DECREMENT_USED_PTES_BY_HANDLE (UsedPageDirectoryHandle);
00482
00483
if ((
MI_GET_USED_PTES_FROM_HANDLE (UsedPageDirectoryHandle) == 0) &&
00484 (PointerPpe->
u.Long != 0)) {
00485
00486 TempVa =
MiGetVirtualAddressMappedByPte(PointerPpe);
00487
MiDeletePte (PointerPpe,
00488 TempVa,
00489 AddressSpaceDeletion,
00490 CurrentProcess,
00491
NULL,
00492
NULL);
00493 }
00494
#endif
00495
}
00496
00497
00498
00499
00500
00501
return;
00502 }
00503
00504
00505
VOID
00506 MiDeletePte (
00507 IN
PMMPTE PointerPte,
00508 IN PVOID VirtualAddress,
00509 IN ULONG AddressSpaceDeletion,
00510 IN
PEPROCESS CurrentProcess,
00511 IN
PMMPTE PrototypePte,
00512 IN
PMMPTE_FLUSH_LIST PteFlushList OPTIONAL
00513 )
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
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
00557
00558 {
00559
PMMPTE PointerPde;
00560
PMMPTE PointerPpe;
00561
PMMPFN Pfn1;
00562
PMMPFN Pfn2;
00563
MMPTE PteContents;
00564 ULONG WorkingSetIndex;
00565 ULONG Entry;
00566 PVOID SwapVa;
00567
MMWSLENTRY Locked;
00568 ULONG WsPfnIndex;
00569
PMMCLONE_BLOCK CloneBlock;
00570
PMMCLONE_DESCRIPTOR CloneDescriptor;
00571 ULONG Waited;
00572
00573
MM_PFN_LOCK_ASSERT();
00574
00575
#if DBG
00576
if (MmDebug &
MM_DBG_PTE_UPDATE) {
00577
DbgPrint(
"deleting PTE\n");
00578
MiFormatPte(PointerPte);
00579 }
00580
#endif //DBG
00581
00582 PteContents = *PointerPte;
00583
00584
if (PteContents.
u.Hard.Valid == 1) {
00585
00586
#ifdef _X86_
00587
#if DBG
00588
#if !defined(NT_UP)
00589
00590
if (PteContents.
u.Hard.Writable == 1) {
00591
ASSERT (PteContents.
u.Hard.Dirty == 1);
00592 }
00593
ASSERT (PteContents.
u.Hard.Accessed == 1);
00594
#endif //NTUP
00595
#endif //DBG
00596
#endif //X86
00597
00598
00599
00600
00601
00602 Pfn1 =
MI_PFN_ELEMENT (PteContents.
u.Hard.PageFrameNumber);
00603 WsPfnIndex = Pfn1->
u1.WsIndex;
00604
00605
#if DBG
00606
if (MmDebug &
MM_DBG_PTE_UPDATE) {
00607
MiFormatPfn(Pfn1);
00608 }
00609
#endif //DBG
00610
00611 CloneDescriptor =
NULL;
00612
00613
if (Pfn1->
u3.e1.PrototypePte == 1) {
00614
00615 CloneBlock = (
PMMCLONE_BLOCK)Pfn1->
PteAddress;
00616
00617
00618
00619
00620
00621
MI_CAPTURE_DIRTY_BIT_TO_PFN (PointerPte, Pfn1);
00622
00623
00624
00625
00626
00627
00628 PointerPde =
MiGetPteAddress (PointerPte);
00629
if (PointerPde->
u.Hard.Valid == 0) {
00630
#if !defined (_WIN64)
00631
if (!
NT_SUCCESS(
MiCheckPdeForPagedPool (PointerPte))) {
00632
#endif
00633
KeBugCheckEx (MEMORY_MANAGEMENT,
00634 0x61940,
00635 (ULONG_PTR)PointerPte,
00636 (ULONG_PTR)PointerPde->
u.Long,
00637 (ULONG_PTR)
MiGetVirtualAddressMappedByPte(PointerPte));
00638
#if !defined (_WIN64)
00639
}
00640
#endif
00641
}
00642
MiDecrementShareAndValidCount (
MI_GET_PAGE_FRAME_FROM_PTE (PointerPde));
00643
00644
00645
00646
00647
00648
MiDecrementShareCount (
MI_GET_PAGE_FRAME_FROM_PTE (&PteContents));
00649
00650
00651
00652
00653
00654
00655
if (PointerPte <=
MiHighestUserPte) {
00656
00657
if (
PrototypePte != Pfn1->
PteAddress) {
00658
00659
00660
00661
00662
00663 CloneDescriptor =
MiLocateCloneAddress ((PVOID)CloneBlock);
00664
00665
#if DBG
00666
if (CloneDescriptor ==
NULL) {
00667
DbgPrint(
"1PrototypePte %p Clone desc %p pfn pte addr %p\n",
00668
PrototypePte, CloneDescriptor, Pfn1->
PteAddress);
00669
MiFormatPte(PointerPte);
00670
ASSERT (
FALSE);
00671 }
00672
#endif // DBG
00673
00674 }
00675 }
00676 }
else {
00677
00678
ASSERT (Pfn1->
u2.ShareCount == 1);
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
MiDecrementShareAndValidCount (Pfn1->
PteFrame);
00690
00691
MI_SET_PFN_DELETED (Pfn1);
00692
00693
00694
00695
00696
00697
00698
MiDecrementShareCountOnly (
MI_GET_PAGE_FRAME_FROM_PTE (&PteContents));
00699
00700
00701
00702
00703
00704 CurrentProcess->NumberOfPrivatePages -= 1;
00705 }
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
if (AddressSpaceDeletion ==
FALSE) {
00718
00719 WorkingSetIndex =
MiLocateWsle (VirtualAddress,
00720
MmWorkingSetList,
00721 WsPfnIndex );
00722
00723
ASSERT (WorkingSetIndex !=
WSLE_NULL_INDEX);
00724
00725
00726
00727
00728
00729
00730 Locked =
MmWsle[WorkingSetIndex].
u1.e1;
00731
00732
MiRemoveWsle (WorkingSetIndex,
MmWorkingSetList);
00733
00734
00735
00736
00737
00738
00739
MiReleaseWsle (WorkingSetIndex, &CurrentProcess->Vm);
00740
00741
if ((Locked.
LockedInWs == 1) || (Locked.
LockedInMemory == 1)) {
00742
00743
00744
00745
00746
00747
ASSERT (WorkingSetIndex < MmWorkingSetList->FirstDynamic);
00748
MmWorkingSetList->
FirstDynamic -= 1;
00749
00750
if (WorkingSetIndex !=
MmWorkingSetList->
FirstDynamic) {
00751
00752 Entry =
MmWorkingSetList->
FirstDynamic;
00753
ASSERT (
MmWsle[Entry].u1.
e1.
Valid);
00754 SwapVa =
MmWsle[Entry].
u1.VirtualAddress;
00755 SwapVa =
PAGE_ALIGN (SwapVa);
00756 Pfn2 =
MI_PFN_ELEMENT (
00757
MiGetPteAddress (SwapVa)->u.Hard.PageFrameNumber);
00758
#if 0
00759
Entry = MiLocateWsleAndParent (SwapVa,
00760 &Parent,
00761
MmWorkingSetList,
00762 Pfn2->
u1.WsIndex);
00763
00764
00765
00766
00767
00768
00769
MiSwapWslEntries (Entry,
00770 Parent,
00771 WorkingSetIndex,
00772
MmWorkingSetList);
00773
#endif //0
00774
00775
MiSwapWslEntries (Entry,
00776 WorkingSetIndex,
00777 &CurrentProcess->Vm);
00778 }
00779 }
else {
00780
ASSERT (WorkingSetIndex >=
MmWorkingSetList->
FirstDynamic);
00781 }
00782
00783
00784
00785
00786
00787
if (!ARGUMENT_PRESENT (PteFlushList)) {
00788
KeFlushSingleTb (VirtualAddress,
00789
TRUE,
00790
FALSE,
00791 (PHARDWARE_PTE)PointerPte,
00792
ZeroPte.
u.Flush);
00793 }
else {
00794
if (PteFlushList->Count !=
MM_MAXIMUM_FLUSH_COUNT) {
00795 PteFlushList->FlushPte[PteFlushList->Count] = PointerPte;
00796 PteFlushList->FlushVa[PteFlushList->Count] = VirtualAddress;
00797 PteFlushList->Count += 1;
00798 }
00799
MI_WRITE_INVALID_PTE (PointerPte,
ZeroPte);
00800 }
00801
00802
if (CloneDescriptor !=
NULL) {
00803
00804
00805
00806
00807
00808
if (ARGUMENT_PRESENT (PteFlushList)) {
00809
MiFlushPteList (PteFlushList,
FALSE,
ZeroPte);
00810 }
00811
00812
00813
00814
00815
00816
00817
00818
00819
if (
MiDecrementCloneBlockReference ( CloneDescriptor,
00820 CloneBlock,
00821 CurrentProcess )) {
00822
00823
00824
00825
00826
00827
00828 PointerPpe =
MiGetPteAddress (PointerPde);
00829
00830
do {
00831
00832
MiDoesPpeExistAndMakeValid (PointerPpe,
00833 CurrentProcess,
00834
TRUE,
00835 &Waited);
00836
00837 Waited = 0;
00838
00839
00840
00841
00842
00843
00844
MiDoesPdeExistAndMakeValid (PointerPde,
00845 CurrentProcess,
00846
TRUE,
00847 &Waited);
00848
00849 }
while (Waited != 0);
00850 }
00851 }
00852 }
00853
00854 }
else if (PteContents.
u.Soft.Prototype == 1) {
00855
00856
00857
00858
00859
00860
00861
if (PteContents.
u.Soft.PageFileHigh !=
MI_PTE_LOOKUP_NEEDED) {
00862
00863
00864
00865
00866
00867
if (PointerPte <=
MiHighestUserPte) {
00868
00869
if (
PrototypePte !=
MiPteToProto (PointerPte)) {
00870
00871 CloneBlock = (
PMMCLONE_BLOCK)
MiPteToProto (PointerPte);
00872 CloneDescriptor =
MiLocateCloneAddress ((PVOID)CloneBlock);
00873
00874
00875
#if DBG
00876
if (CloneDescriptor ==
NULL) {
00877
DbgPrint(
"1PrototypePte %p Clone desc %p \n",
00878
PrototypePte, CloneDescriptor);
00879
MiFormatPte(PointerPte);
00880
ASSERT (
FALSE);
00881 }
00882
#endif //DBG
00883
00884
00885
00886
00887
00888
00889
00890
MI_WRITE_INVALID_PTE (PointerPte,
ZeroPte);
00891
00892
if (ARGUMENT_PRESENT (PteFlushList)) {
00893
MiFlushPteList (PteFlushList,
FALSE,
ZeroPte);
00894 }
00895
00896
if (
MiDecrementCloneBlockReference ( CloneDescriptor,
00897 CloneBlock,
00898 CurrentProcess )) {
00899
00900
00901
00902
00903
00904
00905 PointerPde =
MiGetPteAddress (PointerPte);
00906 PointerPpe =
MiGetPteAddress (PointerPde);
00907
00908
00909
00910
00911
00912
00913
do {
00914
00915
if (
MiDoesPpeExistAndMakeValid (PointerPpe,
00916 CurrentProcess,
00917
TRUE,
00918 &Waited) ==
FALSE) {
00919
00920
00921
00922
00923
00924
00925
00926
return;
00927 }
00928
00929 Waited = 0;
00930
00931
00932
00933
00934
00935
00936
00937
00938
if (
MiDoesPdeExistAndMakeValid (PointerPde,
00939 CurrentProcess,
00940
TRUE,
00941 &Waited) ==
FALSE) {
00942
return;
00943 }
00944
00945 }
while (Waited != 0);
00946 }
00947 }
00948 }
00949 }
00950
00951 }
else if (PteContents.
u.Soft.Transition == 1) {
00952
00953
00954
00955
00956
00957 Pfn1 =
MI_PFN_ELEMENT (PteContents.
u.Trans.PageFrameNumber);
00958
00959
MI_SET_PFN_DELETED (Pfn1);
00960
00961
MiDecrementShareCount (Pfn1->
PteFrame);
00962
00963
00964
00965
00966
00967
00968
00969
00970
if (Pfn1->
u3.e2.ReferenceCount == 0) {
00971
MiUnlinkPageFromList (Pfn1);
00972
MiReleasePageFileSpace (Pfn1->
OriginalPte);
00973
MiInsertPageInList (
MmPageLocationList[
FreePageList],
00974
MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE(&PteContents));
00975 }
00976
00977
00978
00979
00980
00981 CurrentProcess->NumberOfPrivatePages -= 1;
00982
00983 }
else {
00984
00985
00986
00987
00988
00989
if (PteContents.
u.Soft.PageFileHigh !=
MI_PTE_LOOKUP_NEEDED) {
00990
00991
if (
MiReleasePageFileSpace (*PointerPte)) {
00992
00993
00994
00995
00996
00997 CurrentProcess->NumberOfPrivatePages -= 1;
00998 }
00999 }
01000 }
01001
01002
01003
01004
01005
01006
MI_WRITE_INVALID_PTE (PointerPte,
ZeroPte);
01007
01008
return;
01009 }
01010
01011
01012 ULONG
01013
FASTCALL
01014 MiReleasePageFileSpace (
01015 IN
MMPTE PteContents
01016 )
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039 {
01040 ULONG FreeBit;
01041 ULONG PageFileNumber;
01042
01043
MM_PFN_LOCK_ASSERT();
01044
01045
if (PteContents.u.Soft.Prototype == 1) {
01046
01047
01048
01049
01050
01051
return FALSE;
01052 }
01053
01054 FreeBit =
GET_PAGING_FILE_OFFSET (PteContents);
01055
01056
if ((FreeBit == 0) || (FreeBit == 0xFFFFF)) {
01057
01058
01059
01060
01061
01062
return FALSE;
01063 }
01064
01065 PageFileNumber =
GET_PAGING_FILE_NUMBER (PteContents);
01066
01067
ASSERT (RtlCheckBit(
MmPagingFile[PageFileNumber]->Bitmap, FreeBit) == 1);
01068
01069
#if DBG
01070
if ((FreeBit < 8192) && (PageFileNumber == 0)) {
01071
ASSERT ((
MmPagingFileDebug[FreeBit] & 1) != 0);
01072
MmPagingFileDebug[FreeBit] ^= 1;
01073 }
01074
#endif //DBG
01075
01076
RtlClearBits (
MmPagingFile[PageFileNumber]->Bitmap, FreeBit, 1);
01077
01078
MmPagingFile[PageFileNumber]->
FreeSpace += 1;
01079
MmPagingFile[PageFileNumber]->
CurrentUsage -= 1;
01080
01081
01082
01083
01084
01085
01086
if ((
MmNumberOfActiveMdlEntries == 0) ||
01087 (
MmPagingFile[PageFileNumber]->
FreeSpace ==
MM_USABLE_PAGES_FREE)) {
01088
01089
MiUpdateModifiedWriterMdls (PageFileNumber);
01090 }
01091
01092
return TRUE;
01093 }
01094
01095
01096
VOID
01097
FASTCALL
01098 MiUpdateModifiedWriterMdls (
01099 IN ULONG PageFileNumber
01100 )
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123 {
01124 ULONG i;
01125
PMMMOD_WRITER_MDL_ENTRY WriterEntry;
01126
01127
01128
01129
01130
01131
for (i = 0; i <
MM_PAGING_FILE_MDLS; i += 1) {
01132
01133
if ((
MmPagingFile[PageFileNumber]->
Entry[i]->
Links.Flink !=
01134
MM_IO_IN_PROGRESS)
01135 &&
01136 (
MmPagingFile[PageFileNumber]->
Entry[i]->
CurrentList ==
01137 &
MmFreePagingSpaceLow)) {
01138
01139
01140
01141
01142
01143 WriterEntry =
MmPagingFile[PageFileNumber]->
Entry[i];
01144 RemoveEntryList (&WriterEntry->
Links);
01145 WriterEntry->
CurrentList = &
MmPagingFileHeader.
ListHead;
01146
01147
KeSetEvent (&WriterEntry->
PagingListHead->
Event, 0,
FALSE);
01148
01149 InsertTailList (&WriterEntry->
PagingListHead->
ListHead,
01150 &WriterEntry->
Links);
01151
MmNumberOfActiveMdlEntries += 1;
01152 }
01153 }
01154
01155
return;
01156 }
01157
01158
01159
VOID
01160 MiFlushPteList (
01161 IN
PMMPTE_FLUSH_LIST PteFlushList,
01162 IN ULONG AllProcessors,
01163 IN
MMPTE FillPte
01164 )
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191 {
01192 ULONG count;
01193
01194
ASSERT (ARGUMENT_PRESENT (PteFlushList));
01195
MM_PFN_LOCK_ASSERT ();
01196
01197 count = PteFlushList->Count;
01198
01199
if (count != 0) {
01200
if (count != 1) {
01201
if (count <
MM_MAXIMUM_FLUSH_COUNT) {
01202
KeFlushMultipleTb (count,
01203 &PteFlushList->FlushVa[0],
01204
TRUE,
01205 (BOOLEAN)AllProcessors,
01206 &((PHARDWARE_PTE)PteFlushList->FlushPte[0]),
01207 FillPte.u.Flush);
01208 }
else {
01209
01210
01211
01212
01213
01214
if (AllProcessors ==
TRUE) {
01215
MiLockSystemSpaceAtDpcLevel();
01216
KeFlushEntireTb (
TRUE,
TRUE);
01217
MmFlushCounter = (
MmFlushCounter + 1) &
MM_FLUSH_COUNTER_MASK;
01218
MiUnlockSystemSpaceFromDpcLevel();
01219 }
else {
01220
KeFlushEntireTb (
TRUE,
FALSE);
01221 }
01222 }
01223 }
else {
01224
KeFlushSingleTb (PteFlushList->FlushVa[0],
01225
TRUE,
01226 (BOOLEAN)AllProcessors,
01227 (PHARDWARE_PTE)PteFlushList->FlushPte[0],
01228 FillPte.u.Flush);
01229 }
01230 PteFlushList->Count = 0;
01231 }
01232
return;
01233 }