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
PSUBSECTION
00026
MiGetSystemCacheSubsection (
00027 IN PVOID BaseAddress,
00028 IN
PEPROCESS Process,
00029 OUT
PMMPTE *ProtoPte
00030 );
00031
00032
VOID
00033
MiFlushDirtyBitsToPfn (
00034 IN
PMMPTE PointerPte,
00035 IN
PMMPTE LastPte,
00036 IN
PEPROCESS Process,
00037 IN BOOLEAN SystemCache
00038 );
00039
00040 ULONG
00041
FASTCALL
00042
MiCheckProtoPtePageState (
00043 IN
PMMPTE PrototypePte,
00044 IN ULONG PfnLockHeld
00045 );
00046
00047
#ifdef ALLOC_PRAGMA
00048
#pragma alloc_text(PAGE,NtFlushVirtualMemory)
00049
#pragma alloc_text(PAGE,MmFlushVirtualMemory)
00050
#endif
00051
00052 extern POBJECT_TYPE IoFileObjectType;
00053
00054
NTSTATUS
00055 NtFlushVirtualMemory (
00056 IN HANDLE ProcessHandle,
00057 IN OUT PVOID *BaseAddress,
00058 IN OUT PSIZE_T RegionSize,
00059 OUT PIO_STATUS_BLOCK IoStatus
00060 )
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
00091
00092
00093
00094
00095
00096
00097
00098 {
00099
PEPROCESS Process;
00100
KPROCESSOR_MODE PreviousMode;
00101
NTSTATUS Status;
00102 PVOID CapturedBase;
00103 SIZE_T CapturedRegionSize;
00104 IO_STATUS_BLOCK TemporaryIoStatus;
00105
00106
PAGED_CODE();
00107
00108 PreviousMode = KeGetPreviousMode();
00109
if (PreviousMode !=
KernelMode) {
00110
00111
00112
00113
00114
00115
00116
try {
00117
00118
ProbeForWritePointer (BaseAddress);
00119
ProbeForWriteUlong_ptr (RegionSize);
00120
ProbeForWriteIoStatus (IoStatus);
00121
00122
00123
00124
00125
00126 CapturedBase = *BaseAddress;
00127
00128
00129
00130
00131
00132 CapturedRegionSize = *RegionSize;
00133
00134 } except (
EXCEPTION_EXECUTE_HANDLER) {
00135
00136
00137
00138
00139
00140
00141
00142
return GetExceptionCode();
00143 }
00144
00145 }
else {
00146
00147
00148
00149
00150
00151 CapturedBase = *BaseAddress;
00152
00153
00154
00155
00156
00157 CapturedRegionSize = *RegionSize;
00158
00159 }
00160
00161
00162
00163
00164
00165
00166
if (CapturedBase > MM_HIGHEST_USER_ADDRESS) {
00167
00168
00169
00170
00171
00172
return STATUS_INVALID_PARAMETER_2;
00173 }
00174
00175
if (((ULONG_PTR)MM_HIGHEST_USER_ADDRESS - (ULONG_PTR)CapturedBase) <
00176 CapturedRegionSize) {
00177
00178
00179
00180
00181
00182
return STATUS_INVALID_PARAMETER_2;
00183
00184 }
00185
00186
Status =
ObReferenceObjectByHandle ( ProcessHandle,
00187 PROCESS_VM_OPERATION,
00188
PsProcessType,
00189 PreviousMode,
00190 (PVOID *)&Process,
00191
NULL );
00192
if (!
NT_SUCCESS(
Status)) {
00193
return Status;
00194 }
00195
00196
Status =
MmFlushVirtualMemory (Process,
00197 &CapturedBase,
00198 &CapturedRegionSize,
00199 &TemporaryIoStatus);
00200
00201
ObDereferenceObject (Process);
00202
00203
00204
00205
00206
00207
00208
try {
00209
00210 *RegionSize = CapturedRegionSize;
00211 *BaseAddress =
PAGE_ALIGN (CapturedBase);
00212 *IoStatus = TemporaryIoStatus;
00213
00214 } except (
EXCEPTION_EXECUTE_HANDLER) {
00215 }
00216
00217
return Status;
00218
00219 }
00220
00221
00222
VOID
00223 MiFlushAcquire (
00224 IN
PCONTROL_AREA ControlArea
00225 )
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245 {
00246 KIRQL OldIrql;
00247
00248
LOCK_PFN (OldIrql);
00249
00250
ASSERT ((LONG)ControlArea->NumberOfMappedViews >= 1);
00251 ControlArea->NumberOfMappedViews += 1;
00252
00253
UNLOCK_PFN (OldIrql);
00254 }
00255
00256
00257
VOID
00258 MiFlushRelease (
00259 IN
PCONTROL_AREA ControlArea
00260 )
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 {
00280 KIRQL OldIrql;
00281
00282
LOCK_PFN (OldIrql);
00283
00284
ASSERT ((LONG)ControlArea->NumberOfMappedViews >= 1);
00285 ControlArea->NumberOfMappedViews -= 1;
00286
00287
00288
00289
00290
00291
00292
MiCheckControlArea (ControlArea,
NULL, OldIrql);
00293 }
00294
00295
00296
NTSTATUS
00297 MmFlushVirtualMemory (
00298 IN
PEPROCESS Process,
00299 IN OUT PVOID *BaseAddress,
00300 IN OUT PSIZE_T RegionSize,
00301 OUT PIO_STATUS_BLOCK IoStatus
00302 )
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344 {
00345
PMMVAD Vad;
00346 PVOID EndingAddress;
00347 PVOID Va;
00348
PEPROCESS CurrentProcess;
00349 BOOLEAN SystemCache;
00350
PCONTROL_AREA ControlArea;
00351
PMMPTE PointerPte;
00352
PMMPTE PointerPde;
00353
PMMPTE PointerPpe;
00354
PMMPTE LastPte;
00355
PMMPTE FinalPte;
00356
PSUBSECTION Subsection;
00357
PSUBSECTION LastSubsection;
00358
NTSTATUS Status;
00359 ULONG ConsecutiveFileLockFailures;
00360 ULONG Waited;
00361 LOGICAL EntireRestOfVad;
00362 LOGICAL Attached;
00363
00364
PAGED_CODE();
00365
00366 Attached =
FALSE;
00367
00368
00369
00370
00371
00372
00373
00374
00375 EndingAddress = (PVOID)(((ULONG_PTR)*BaseAddress + *RegionSize - 1) |
00376 (
PAGE_SIZE - 1));
00377 *BaseAddress =
PAGE_ALIGN (*BaseAddress);
00378
00379
if (
MI_IS_SESSION_ADDRESS (*BaseAddress)) {
00380
00381
00382
00383
00384
00385
return STATUS_NOT_MAPPED_VIEW;
00386 }
00387
00388 CurrentProcess =
PsGetCurrentProcess ();
00389
00390
if (!
MI_IS_SYSTEM_CACHE_ADDRESS(*BaseAddress)) {
00391
00392 SystemCache =
FALSE;
00393
00394
00395
00396
00397
00398
if (
PsGetCurrentProcess() != Process) {
00399
KeAttachProcess (&Process->Pcb);
00400 Attached =
TRUE;
00401 }
00402
00403
LOCK_WS_AND_ADDRESS_SPACE (Process);
00404
00405
00406
00407
00408
00409
if (Process->AddressSpaceDeleted != 0) {
00410
Status = STATUS_PROCESS_IS_TERMINATING;
00411
goto ErrorReturn;
00412 }
00413
00414 Vad =
MiLocateAddress (*BaseAddress);
00415
00416
if (Vad == (
PMMVAD)
NULL) {
00417
00418
00419
00420
00421
00422
Status = STATUS_NOT_MAPPED_VIEW;
00423
goto ErrorReturn;
00424 }
00425
00426
if (*RegionSize == 0) {
00427 EndingAddress =
MI_VPN_TO_VA_ENDING (Vad->
EndingVpn);
00428 EntireRestOfVad =
TRUE;
00429 }
00430
else {
00431 EntireRestOfVad =
FALSE;
00432 }
00433
00434
if ((Vad->
u.VadFlags.PrivateMemory == 1) ||
00435 (
MI_VA_TO_VPN (EndingAddress) > Vad->
EndingVpn)) {
00436
00437
00438
00439
00440
00441
00442
Status = STATUS_NOT_MAPPED_VIEW;
00443
goto ErrorReturn;
00444 }
00445
00446
00447
00448
00449
00450 ControlArea = Vad->
ControlArea;
00451
00452
if ((ControlArea->
FilePointer ==
NULL) ||
00453 (Vad->
u.VadFlags.ImageMap == 1)) {
00454
00455
00456
00457
00458
00459
00460
Status = STATUS_NOT_MAPPED_DATA;
00461
goto ErrorReturn;
00462 }
00463
00464 }
else {
00465
00466 SystemCache =
TRUE;
00467 Process = CurrentProcess;
00468
LOCK_WS (Process);
00469 }
00470
00471 PointerPpe =
MiGetPpeAddress (*BaseAddress);
00472 PointerPde =
MiGetPdeAddress (*BaseAddress);
00473 PointerPte =
MiGetPteAddress (*BaseAddress);
00474 LastPte =
MiGetPteAddress (EndingAddress);
00475 *RegionSize = (PCHAR)EndingAddress - (PCHAR)*BaseAddress + 1;
00476
00477 retry:
00478
00479
while (!
MiDoesPpeExistAndMakeValid (PointerPpe, Process,
FALSE, &Waited)) {
00480
00481
00482
00483
00484
00485 PointerPpe += 1;
00486 PointerPde =
MiGetVirtualAddressMappedByPte (PointerPpe);
00487 PointerPte =
MiGetVirtualAddressMappedByPte (PointerPde);
00488 Va =
MiGetVirtualAddressMappedByPte (PointerPte);
00489
00490
if (PointerPte > LastPte) {
00491
break;
00492 }
00493 }
00494
00495 Waited = 0;
00496
00497
if (PointerPte <= LastPte) {
00498
while (!
MiDoesPdeExistAndMakeValid(PointerPde, Process,
FALSE, &Waited)) {
00499
00500
00501
00502
00503
00504 PointerPde += 1;
00505
00506 PointerPte =
MiGetVirtualAddressMappedByPte (PointerPde);
00507
00508
if (PointerPte > LastPte) {
00509
break;
00510 }
00511
00512
#if defined (_WIN64)
00513
if (
MiIsPteOnPdeBoundary (PointerPde)) {
00514 PointerPpe =
MiGetPteAddress (PointerPde);
00515
goto retry;
00516 }
00517
#endif
00518
00519 Va =
MiGetVirtualAddressMappedByPte (PointerPte);
00520 }
00521
00522
00523
00524
00525
00526
00527
if (PointerPte <= LastPte && Waited != 0) {
00528
goto retry;
00529 }
00530 }
00531
00532
MiFlushDirtyBitsToPfn (PointerPte, LastPte, Process, SystemCache);
00533
00534
if (SystemCache) {
00535
00536
00537
00538
00539
00540 Subsection =
MiGetSystemCacheSubsection (*BaseAddress,
00541 Process,
00542 &PointerPte);
00543 LastSubsection =
MiGetSystemCacheSubsection (EndingAddress,
00544 Process,
00545 &FinalPte);
00546
UNLOCK_WS (Process);
00547
00548
00549
00550
00551
00552
Status =
MiFlushSectionInternal (PointerPte,
00553 FinalPte,
00554 Subsection,
00555 LastSubsection,
00556
FALSE,
00557
TRUE,
00558 IoStatus);
00559 }
00560
else {
00561
00562
00563
00564
00565
00566
MiFlushAcquire (ControlArea);
00567
00568 PointerPte =
MiGetProtoPteAddress (Vad,
MI_VA_TO_VPN (*BaseAddress));
00569 Subsection =
MiLocateSubsection (Vad,
MI_VA_TO_VPN(*BaseAddress));
00570 LastSubsection =
MiLocateSubsection (Vad,
MI_VA_TO_VPN(EndingAddress));
00571
00572
00573
00574
00575
00576
00577
00578
if (LastSubsection ==
NULL) {
00579
00580
if (EntireRestOfVad ==
FALSE) {
00581
00582
00583
00584
00585
00586
00587
UNLOCK_WS_AND_ADDRESS_SPACE (Process);
00588
if (Attached ==
TRUE) {
00589
KeDetachProcess();
00590 }
00591
MiFlushRelease (ControlArea);
00592
return STATUS_NOT_MAPPED_VIEW;
00593 }
00594
00595 LastSubsection = Subsection;
00596
while (LastSubsection->
NextSubsection) {
00597 LastSubsection = LastSubsection->
NextSubsection;
00598 }
00599 FinalPte = LastSubsection->
SubsectionBase + LastSubsection->
PtesInSubsection - 1;
00600 }
00601
else {
00602 FinalPte =
MiGetProtoPteAddress (Vad,
MI_VA_TO_VPN (EndingAddress));
00603 }
00604
00605
UNLOCK_WS_AND_ADDRESS_SPACE (Process);
00606
if (Attached ==
TRUE) {
00607
KeDetachProcess();
00608 }
00609
00610
00611
00612
00613
00614 ConsecutiveFileLockFailures = 0;
00615
00616
do {
00617
00618
FsRtlAcquireFileForCcFlush (ControlArea->
FilePointer);
00619
00620
00621
00622
00623
00624
Status =
MiFlushSectionInternal (PointerPte,
00625 FinalPte,
00626 Subsection,
00627 LastSubsection,
00628
TRUE,
00629
TRUE,
00630 IoStatus);
00631
00632
00633
00634
00635
00636
FsRtlReleaseFileForCcFlush (ControlArea->
FilePointer);
00637
00638
00639
00640
00641
00642
00643
if (
Status != STATUS_FILE_LOCK_CONFLICT) {
00644
break;
00645 }
00646
00647 ConsecutiveFileLockFailures += 1;
00648
KeDelayExecutionThread (
KernelMode,
FALSE, &
MmShortTime);
00649
00650 }
while (ConsecutiveFileLockFailures < 5);
00651
00652
MiFlushRelease (ControlArea);
00653 }
00654
00655
return Status;
00656
00657 ErrorReturn:
00658
ASSERT (SystemCache ==
FALSE);
00659
UNLOCK_WS_AND_ADDRESS_SPACE (Process);
00660
if (Attached ==
TRUE) {
00661
KeDetachProcess();
00662 }
00663
return Status;
00664
00665 }
00666
00667
NTSTATUS
00668 MmFlushSection (
00669 IN
PSECTION_OBJECT_POINTERS SectionObjectPointer,
00670 IN PLARGE_INTEGER Offset,
00671 IN SIZE_T RegionSize,
00672 OUT PIO_STATUS_BLOCK IoStatus,
00673 IN ULONG AcquireFile
00674 )
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706 {
00707
PCONTROL_AREA ControlArea;
00708
PMMPTE PointerPte;
00709
PMMPTE LastPte;
00710 KIRQL OldIrql;
00711 ULONG PteOffset;
00712
PSUBSECTION Subsection;
00713
PSUBSECTION LastSubsection;
00714 BOOLEAN DeleteSegment =
FALSE;
00715
PETHREAD CurrentThread;
00716
NTSTATUS status;
00717 BOOLEAN OldClusterState;
00718 ULONG ConsecutiveFileLockFailures;
00719
00720
00721
00722
00723
00724 IoStatus->Status = STATUS_SUCCESS;
00725 IoStatus->Information = RegionSize;
00726
00727
LOCK_PFN (OldIrql);
00728
00729 ControlArea = ((
PCONTROL_AREA)(SectionObjectPointer->DataSectionObject));
00730
00731
ASSERT ((ControlArea ==
NULL) || (ControlArea->
u.Flags.Image == 0));
00732
00733
if ((ControlArea ==
NULL) ||
00734 (ControlArea->
u.Flags.BeingDeleted) ||
00735 (ControlArea->
u.Flags.BeingCreated) ||
00736 (ControlArea->
NumberOfPfnReferences == 0)) {
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
UNLOCK_PFN (OldIrql);
00747
return STATUS_SUCCESS;
00748 }
00749
00750
00751
00752
00753
00754
ASSERT (ControlArea->
u.Flags.GlobalOnlyPerSession == 0);
00755
00756 Subsection = (
PSUBSECTION)(ControlArea + 1);
00757
00758
if (!ARGUMENT_PRESENT (
Offset)) {
00759
00760
00761
00762
00763
00764
00765 PointerPte = &Subsection->
SubsectionBase[0];
00766 LastSubsection = Subsection;
00767
while (LastSubsection->
NextSubsection !=
NULL) {
00768 LastSubsection = LastSubsection->
NextSubsection;
00769 }
00770 LastPte = &LastSubsection->
SubsectionBase
00771 [LastSubsection->
PtesInSubsection - 1];
00772 }
else {
00773
00774 PteOffset = (ULONG)(
Offset->QuadPart >>
PAGE_SHIFT);
00775
00776
00777
00778
00779
00780
00781
while (PteOffset >= Subsection->
PtesInSubsection) {
00782 PteOffset -= Subsection->
PtesInSubsection;
00783
if (Subsection->
NextSubsection ==
NULL) {
00784
00785
00786
00787
00788
00789
UNLOCK_PFN (OldIrql);
00790
return STATUS_SUCCESS;
00791 }
00792 Subsection = Subsection->
NextSubsection;
00793 }
00794
00795
ASSERT (PteOffset < Subsection->PtesInSubsection);
00796 PointerPte = &Subsection->
SubsectionBase[PteOffset];
00797
00798
00799
00800
00801
00802 PteOffset += (ULONG)(((RegionSize +
BYTE_OFFSET(
Offset->LowPart)) - 1) >>
PAGE_SHIFT);
00803
00804 LastSubsection = Subsection;
00805
00806
while (PteOffset >= LastSubsection->
PtesInSubsection) {
00807 PteOffset -= LastSubsection->
PtesInSubsection;
00808
if (LastSubsection->
NextSubsection ==
NULL) {
00809 PteOffset = LastSubsection->
PtesInSubsection - 1;
00810
break;
00811 }
00812 LastSubsection = LastSubsection->
NextSubsection;
00813 }
00814
00815
ASSERT (PteOffset < LastSubsection->PtesInSubsection);
00816 LastPte = &LastSubsection->
SubsectionBase[PteOffset];
00817 }
00818
00819
00820
00821
00822
00823
00824 ControlArea->
NumberOfMappedViews += 1;
00825
00826
UNLOCK_PFN (OldIrql);
00827
00828 CurrentThread =
PsGetCurrentThread();
00829
00830
00831
00832
00833
00834 OldClusterState = CurrentThread->
ForwardClusterOnly;
00835 CurrentThread->
ForwardClusterOnly =
TRUE;
00836
00837
00838
00839
00840
00841
if (AcquireFile == 0) {
00842
00843
00844
00845
00846
00847 status =
MiFlushSectionInternal (PointerPte,
00848 LastPte,
00849 Subsection,
00850 LastSubsection,
00851
TRUE,
00852
TRUE,
00853 IoStatus);
00854 }
00855
else {
00856
00857 ConsecutiveFileLockFailures = 0;
00858
00859
do {
00860
00861
FsRtlAcquireFileForCcFlush (ControlArea->
FilePointer);
00862
00863
00864
00865
00866
00867 status =
MiFlushSectionInternal (PointerPte,
00868 LastPte,
00869 Subsection,
00870 LastSubsection,
00871
TRUE,
00872
TRUE,
00873 IoStatus);
00874
00875
00876
00877
00878
00879
FsRtlReleaseFileForCcFlush (ControlArea->
FilePointer);
00880
00881
00882
00883
00884
00885
00886
if (status != STATUS_FILE_LOCK_CONFLICT) {
00887
break;
00888 }
00889
00890 ConsecutiveFileLockFailures += 1;
00891
KeDelayExecutionThread (
KernelMode,
FALSE, &
MmShortTime);
00892
00893 }
while (ConsecutiveFileLockFailures < 5);
00894 }
00895
00896 CurrentThread->
ForwardClusterOnly = OldClusterState;
00897
00898
LOCK_PFN (OldIrql);
00899
00900
ASSERT ((LONG)ControlArea->
NumberOfMappedViews >= 1);
00901 ControlArea->
NumberOfMappedViews -= 1;
00902
00903
00904
00905
00906
00907
00908
MiCheckControlArea (ControlArea,
NULL, OldIrql);
00909
00910
return status;
00911
00912 }
00913
00914
00915 LONGLONG
00916 MiStartingOffset(
00917 IN
PSUBSECTION Subsection,
00918 IN
PMMPTE PteAddress
00919 )
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943 {
00944 LONGLONG PteByteOffset;
00945 LARGE_INTEGER StartAddress;
00946
00947
if (Subsection->ControlArea->u.Flags.Image == 1) {
00948
return MI_STARTING_OFFSET ( Subsection,
00949 PteAddress);
00950 }
00951
00952 PteByteOffset = (LONGLONG)((PteAddress - Subsection->SubsectionBase))
00953 <<
PAGE_SHIFT;
00954
00955
Mi4KStartFromSubsection (&StartAddress, Subsection);
00956
00957 StartAddress.QuadPart = StartAddress.QuadPart <<
MM4K_SHIFT;
00958
00959 PteByteOffset += StartAddress.QuadPart;
00960
00961
return PteByteOffset;
00962 }
00963
00964 LARGE_INTEGER
00965 MiEndingOffset(
00966 IN
PSUBSECTION Subsection
00967 )
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991 {
00992 LARGE_INTEGER FileByteOffset;
00993
00994
if (Subsection->ControlArea->u.Flags.Image == 1) {
00995 FileByteOffset.QuadPart =
00996 (Subsection->StartingSector + Subsection->NumberOfFullSectors) <<
00997
MMSECTOR_SHIFT;
00998 }
00999
else {
01000
Mi4KStartFromSubsection (&FileByteOffset, Subsection);
01001
01002 FileByteOffset.QuadPart += Subsection->NumberOfFullSectors;
01003
01004 FileByteOffset.QuadPart = FileByteOffset.QuadPart <<
MM4K_SHIFT;
01005 }
01006
01007 FileByteOffset.QuadPart += Subsection->u.SubsectionFlags.SectorEndOffset;
01008
01009
return FileByteOffset;
01010 }
01011
01012
01013
NTSTATUS
01014 MiFlushSectionInternal (
01015 IN
PMMPTE StartingPte,
01016 IN
PMMPTE FinalPte,
01017 IN
PSUBSECTION FirstSubsection,
01018 IN
PSUBSECTION LastSubsection,
01019 IN ULONG Synchronize,
01020 IN LOGICAL WriteInProgressOk,
01021 OUT PIO_STATUS_BLOCK IoStatus
01022 )
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067 {
01068
PCONTROL_AREA ControlArea;
01069
PMMPTE PointerPte;
01070
PMMPTE LastPte;
01071
PMMPTE LastWritten;
01072
MMPTE PteContents;
01073
PMMPFN Pfn1;
01074
PMMPFN Pfn2;
01075 KIRQL OldIrql;
01076
PMDL Mdl;
01077
KEVENT IoEvent;
01078
PSUBSECTION Subsection;
01079 PPFN_NUMBER Page;
01080 PFN_NUMBER PageFrameIndex;
01081 PPFN_NUMBER LastPage;
01082
NTSTATUS Status;
01083 UINT64 StartingOffset;
01084 UINT64 TempOffset;
01085 BOOLEAN WriteNow;
01086 LOGICAL Bail;
01087 PFN_NUMBER MdlHack[(
sizeof(
MDL)/
sizeof(PFN_NUMBER)) + (
MM_MAXIMUM_DISK_IO_SIZE /
PAGE_SIZE) + 1];
01088 ULONG ReflushCount;
01089
01090 WriteNow =
FALSE;
01091 Bail =
FALSE;
01092
01093 IoStatus->Status = STATUS_SUCCESS;
01094 IoStatus->Information = 0;
01095 Mdl = (
PMDL)&MdlHack[0];
01096
01097
KeInitializeEvent (&IoEvent, NotificationEvent,
FALSE);
01098
01099 FinalPte += 1;
01100
01101 LastWritten =
NULL;
01102 LastPage = 0;
01103 Subsection = FirstSubsection;
01104 PointerPte = StartingPte;
01105 ControlArea = FirstSubsection->ControlArea;
01106
01107
LOCK_PFN (OldIrql);
01108
01109
ASSERT (ControlArea->
u.Flags.Image == 0);
01110
01111
if (ControlArea->
NumberOfPfnReferences == 0) {
01112
01113
01114
01115
01116
01117
01118
UNLOCK_PFN (OldIrql);
01119
return STATUS_SUCCESS;
01120 }
01121
01122
while ((Synchronize) && (ControlArea->
FlushInProgressCount != 0)) {
01123
01124
01125
01126
01127
01128
01129
KeEnterCriticalRegion();
01130 ControlArea->
u.Flags.CollidedFlush = 1;
01131
UNLOCK_PFN_AND_THEN_WAIT(OldIrql);
01132
01133
KeWaitForSingleObject (&
MmCollidedFlushEvent,
01134
WrPageOut,
01135
KernelMode,
01136
FALSE,
01137 &
MmOneSecond);
01138
LOCK_PFN (OldIrql);
01139
KeLeaveCriticalRegion();
01140 }
01141
01142 ControlArea->
FlushInProgressCount += 1;
01143
01144
for (;;) {
01145
01146
if (LastSubsection != Subsection) {
01147
01148
01149
01150
01151
01152 LastPte = &Subsection->
SubsectionBase[Subsection->
PtesInSubsection];
01153 }
else {
01154
01155
01156
01157
01158
01159 LastPte = FinalPte;
01160 }
01161
01162
01163
01164
01165
01166
01167
if (!
MiCheckProtoPtePageState(PointerPte,
TRUE)) {
01168 PointerPte = (
PMMPTE)(((ULONG_PTR)PointerPte | (
PAGE_SIZE - 1)) + 1);
01169 }
01170
01171
while (PointerPte < LastPte) {
01172
01173
if (
MiIsPteOnPdeBoundary(PointerPte)) {
01174
01175
01176
01177
01178
01179
if (!
MiCheckProtoPtePageState(PointerPte,
TRUE)) {
01180 PointerPte = (
PMMPTE)((PCHAR)PointerPte +
PAGE_SIZE);
01181
01182
01183
01184
01185
01186
01187
if (LastWritten !=
NULL) {
01188 WriteNow =
TRUE;
01189
goto CheckForWrite;
01190 }
01191
continue;
01192 }
01193 }
01194
01195 PteContents = *PointerPte;
01196
01197
if ((PteContents.
u.Hard.Valid == 1) ||
01198 ((PteContents.
u.Soft.Prototype == 0) &&
01199 (PteContents.
u.Soft.Transition == 1))) {
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
if (PteContents.
u.Hard.Valid == 1) {
01213 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (&PteContents);
01214 }
else {
01215 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (&PteContents);
01216 }
01217
01218 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
01219
ASSERT (Pfn1->
OriginalPte.
u.Soft.Prototype == 1);
01220
ASSERT (Pfn1->
OriginalPte.
u.Hard.Valid == 0);
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
if ((Pfn1->
u3.e1.Modified == 1) ||
01232 (Pfn1->
u3.e1.WriteInProgress)) {
01233
01234
if ((WriteInProgressOk ==
FALSE) &&
01235 (Pfn1->
u3.e1.WriteInProgress)) {
01236
01237 PointerPte = LastPte;
01238 Bail =
TRUE;
01239
01240
if (LastWritten !=
NULL) {
01241 WriteNow =
TRUE;
01242 }
01243
goto CheckForWrite;
01244 }
01245
01246
if (LastWritten ==
NULL) {
01247
01248
01249
01250
01251
01252
01253 LastPage = (PPFN_NUMBER)(Mdl + 1);
01254
01255
01256
01257
01258
01259
01260 StartingOffset = (UINT64)
MiStartingOffset (
01261 Subsection,
01262 Pfn1->
PteAddress);
01263
01264
MI_INITIALIZE_ZERO_MDL (Mdl);
01265
01266 Mdl->
MdlFlags |=
MDL_PAGES_LOCKED;
01267 Mdl->
StartVa =
01268 (PVOID)ULongToPtr(Pfn1->
u3.e1.PageColor <<
PAGE_SHIFT);
01269 Mdl->
Size = (CSHORT)(
sizeof(
MDL) +
01270 (
sizeof(PFN_NUMBER) *
MmModifiedWriteClusterSize));
01271 }
01272
01273 LastWritten = PointerPte;
01274 Mdl->
ByteCount +=
PAGE_SIZE;
01275
if (Mdl->
ByteCount == (
PAGE_SIZE *
MmModifiedWriteClusterSize)) {
01276 WriteNow =
TRUE;
01277 }
01278
01279
if (PteContents.
u.Hard.Valid == 0) {
01280
01281
01282
01283
01284
01285
MiUnlinkPageFromList (Pfn1);
01286
MI_ADD_LOCKED_PAGE_CHARGE_FOR_MODIFIED_PAGE(Pfn1, 18);
01287 }
01288
else {
01289
MI_ADD_LOCKED_PAGE_CHARGE(Pfn1, 20);
01290 }
01291
01292
01293
01294
01295
01296 Pfn1->
u3.e1.Modified = 0;
01297
01298
01299
01300
01301
01302
01303 Pfn1->
u3.e2.ReferenceCount += 1;
01304
01305 *LastPage = PageFrameIndex;
01306 LastPage += 1;
01307 }
else {
01308
01309
01310
01311
01312
01313
01314
01315
if (LastWritten !=
NULL) {
01316 WriteNow =
TRUE;
01317 }
01318 }
01319 }
else {
01320
01321
01322
01323
01324
01325
01326
01327
if (LastWritten !=
NULL) {
01328 WriteNow =
TRUE;
01329 }
01330 }
01331
01332 PointerPte += 1;
01333
01334 CheckForWrite:
01335
01336
01337
01338
01339
01340
01341
if ((WriteNow) ||
01342 ((PointerPte == LastPte) && (LastWritten !=
NULL))) {
01343
01344 LARGE_INTEGER EndOfFile;
01345
01346
01347
01348
01349
01350
UNLOCK_PFN (OldIrql);
01351
01352 WriteNow =
FALSE;
01353
01354
01355
01356
01357
01358
01359 EndOfFile =
MiEndingOffset(Subsection);
01360 TempOffset = (UINT64) EndOfFile.QuadPart;
01361
01362
if (StartingOffset + Mdl->
ByteCount > TempOffset) {
01363
01364
ASSERT ((ULONG_PTR)(TempOffset - StartingOffset) >
01365 (Mdl->
ByteCount -
PAGE_SIZE));
01366
01367 Mdl->
ByteCount = (ULONG)(TempOffset-
01368 StartingOffset);
01369 }
01370
01371 ReflushCount =
MiIoRetryLevel;
01372
01373
while (
TRUE ) {
01374
01375
KeClearEvent (&IoEvent);
01376
01377
#if DBG
01378
if (MmDebug &
MM_DBG_FLUSH_SECTION) {
01379
DbgPrint(
"flush page write begun %lx\n",
01380 Mdl->
ByteCount);
01381 }
01382
#endif //DBG
01383
01384
Status =
IoSynchronousPageWrite (ControlArea->
FilePointer,
01385 Mdl,
01386 (PLARGE_INTEGER)&StartingOffset,
01387 &IoEvent,
01388 IoStatus );
01389
01390
01391
01392
01393
01394
if (
NT_SUCCESS(
Status)) {
01395
KeWaitForSingleObject( &IoEvent,
01396
WrPageOut,
01397
KernelMode,
01398
FALSE,
01399 (PLARGE_INTEGER)
NULL);
01400
01401
01402
01403
01404
01405 }
else {
01406 IoStatus->Status =
Status;
01407 }
01408
01409
if (Mdl->
MdlFlags &
MDL_MAPPED_TO_SYSTEM_VA) {
01410
MmUnmapLockedPages (Mdl->
MappedSystemVa, Mdl);
01411 }
01412
01413 Page = (PPFN_NUMBER)(Mdl + 1);
01414
01415
if (
MmIsRetryIoStatus(IoStatus->Status)) {
01416
01417 ReflushCount -= 1;
01418
if (ReflushCount != 0) {
01419
KeDelayExecutionThread (
KernelMode,
FALSE, &
Mm30Milliseconds);
01420
continue;
01421 }
01422 }
01423
01424
break;
01425 }
01426
01427
LOCK_PFN (OldIrql);
01428
01429
if (
MiIsPteOnPdeBoundary(PointerPte) == 0) {
01430
01431
01432
01433
01434
01435
01436
01437
MiMakeSystemAddressValidPfn (PointerPte);
01438 }
01439
01440
if (
NT_SUCCESS(IoStatus->Status)) {
01441
01442
01443
01444
01445
01446
while (Page < LastPage) {
01447
01448 Pfn2 =
MI_PFN_ELEMENT (*Page);
01449
MI_REMOVE_LOCKED_PAGE_CHARGE(Pfn2, 19);
01450
MiDecrementReferenceCount (*Page);
01451 Page += 1;
01452 }
01453 }
else {
01454
01455
01456
01457
01458
01459
01460 IoStatus->Information = 0;
01461
01462
01463
01464
01465
01466
01467
while (Page < LastPage) {
01468
01469 Pfn2 =
MI_PFN_ELEMENT (*Page);
01470
01471
01472
01473
01474
01475 Pfn2->
u3.e1.Modified = 1;
01476
01477
MI_REMOVE_LOCKED_PAGE_CHARGE(Pfn2, 21);
01478
MiDecrementReferenceCount (*Page);
01479 Page += 1;
01480 }
01481
01482
01483
01484
01485
01486
01487
01488 IoStatus->Information +=
01489 (((LastWritten - StartingPte) <<
PAGE_SHIFT) -
01490 Mdl->
ByteCount);
01491
01492
goto ErrorReturn;
01493 }
01494
01495
01496
01497
01498
01499
01500
01501 LastWritten =
NULL;
01502 }
01503
01504 }
01505
01506
if ((Bail ==
TRUE) || (Subsection == LastSubsection)) {
01507
01508
01509
01510
01511
01512
01513
01514
break;
01515 }
01516
01517 Subsection = Subsection->
NextSubsection;
01518 PointerPte = Subsection->
SubsectionBase;
01519
01520 }
01521
01522
ASSERT (LastWritten ==
NULL);
01523
01524 ErrorReturn:
01525
01526 ControlArea->
FlushInProgressCount -= 1;
01527
if ((ControlArea->
u.Flags.CollidedFlush == 1) &&
01528 (ControlArea->
FlushInProgressCount == 0)) {
01529 ControlArea->
u.Flags.CollidedFlush = 0;
01530
KePulseEvent (&
MmCollidedFlushEvent, 0,
FALSE);
01531 }
01532
UNLOCK_PFN (OldIrql);
01533
01534
if (Bail ==
TRUE) {
01535
01536
01537
01538
01539
01540
01541
return STATUS_MAPPED_WRITER_COLLISION;
01542 }
01543
01544
return IoStatus->Status;
01545 }
01546
01547 BOOLEAN
01548 MmPurgeSection (
01549 IN
PSECTION_OBJECT_POINTERS SectionObjectPointer,
01550 IN PLARGE_INTEGER Offset,
01551 IN SIZE_T RegionSize,
01552 IN ULONG IgnoreCacheViews
01553 )
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610 {
01611
PCONTROL_AREA ControlArea;
01612
PMMPTE PointerPte;
01613
PMMPTE LastPte;
01614
PMMPTE FinalPte;
01615
MMPTE PteContents;
01616
PMMPFN Pfn1;
01617 KIRQL OldIrql;
01618 ULONG PteOffset;
01619
PSUBSECTION Subsection;
01620
PSUBSECTION LastSubsection;
01621 LARGE_INTEGER LocalOffset;
01622 BOOLEAN DeleteSegment =
FALSE;
01623 BOOLEAN LockHeld;
01624 BOOLEAN ReturnValue;
01625 PFN_NUMBER PageFrameIndex;
01626
#if DBG
01627
PFN_NUMBER LastLocked = 0;
01628
#endif //DBG
01629
01630
01631
01632
01633
01634
01635
ASSERT (KeGetCurrentIrql() <
DISPATCH_LEVEL);
01636
01637
01638
01639
01640
01641
if (ARGUMENT_PRESENT(
Offset)) {
01642
01643 LocalOffset = *
Offset;
01644
Offset = &LocalOffset;
01645 }
01646
01647
01648
01649
01650
01651
01652
if (!
MiCanFileBeTruncatedInternal(SectionObjectPointer,
Offset,
TRUE, &OldIrql)) {
01653
return FALSE;
01654 }
01655
01656
01657
01658
01659
01660 ControlArea = (
PCONTROL_AREA)(SectionObjectPointer->DataSectionObject);
01661
if (ControlArea ==
NULL) {
01662
UNLOCK_PFN (OldIrql);
01663
return TRUE;
01664
01665
01666
01667
01668
01669
01670
01671 }
else if ((IgnoreCacheViews ==
FALSE) &&
01672 (ControlArea->
NumberOfSystemCacheViews != 0)) {
01673
UNLOCK_PFN (OldIrql);
01674
return FALSE;
01675 }
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
if (ControlArea->
u.Flags.BeingDeleted == 1) {
01691
UNLOCK_PFN (OldIrql);
01692
return FALSE;
01693 }
01694
01695
01696
01697
01698
01699
01700
ASSERT (ControlArea->
u.Flags.GlobalOnlyPerSession == 0);
01701
01702 Subsection = (
PSUBSECTION)(ControlArea + 1);
01703
01704
if (!ARGUMENT_PRESENT (
Offset)) {
01705
01706
01707
01708
01709
01710
01711 PointerPte = &Subsection->
SubsectionBase[0];
01712 RegionSize = 0;
01713
01714 }
else {
01715
01716 PteOffset = (ULONG)(
Offset->QuadPart >>
PAGE_SHIFT);
01717
01718
01719
01720
01721
01722
01723
while (PteOffset >= Subsection->
PtesInSubsection) {
01724 PteOffset -= Subsection->
PtesInSubsection;
01725 Subsection = Subsection->
NextSubsection;
01726
if (Subsection ==
NULL) {
01727
01728
01729
01730
01731
01732
01733
01734
UNLOCK_PFN (OldIrql);
01735
return TRUE;
01736 }
01737 }
01738
01739
ASSERT (PteOffset < Subsection->PtesInSubsection);
01740 PointerPte = &Subsection->
SubsectionBase[PteOffset];
01741 }
01742
01743
01744
01745
01746
01747
01748
if (RegionSize == 0) {
01749
01750
01751
01752
01753
01754 LastSubsection = Subsection;
01755
while (LastSubsection->
NextSubsection !=
NULL) {
01756 LastSubsection = LastSubsection->
NextSubsection;
01757 }
01758
01759
01760
01761
01762
01763 FinalPte = &LastSubsection->
SubsectionBase
01764 [LastSubsection->
PtesInSubsection];
01765 }
else {
01766
01767
01768
01769
01770
01771 PteOffset +=
01772 (ULONG) (((RegionSize +
BYTE_OFFSET(
Offset->LowPart)) - 1) >>
PAGE_SHIFT);
01773
01774 LastSubsection = Subsection;
01775
01776
while (PteOffset >= LastSubsection->
PtesInSubsection) {
01777 PteOffset -= LastSubsection->
PtesInSubsection;
01778
if (LastSubsection->
NextSubsection ==
NULL) {
01779 PteOffset = LastSubsection->
PtesInSubsection - 1;
01780
break;
01781 }
01782 LastSubsection = LastSubsection->
NextSubsection;
01783 }
01784
01785
ASSERT (PteOffset < LastSubsection->PtesInSubsection);
01786
01787
01788
01789
01790
01791 FinalPte = &LastSubsection->
SubsectionBase[PteOffset + 1];
01792 }
01793
01794
01795
01796
01797
01798
01799
01800 ControlArea->
NumberOfMappedViews += 1;
01801
01802
01803
01804
01805
01806
01807 ControlArea->
u.Flags.BeingPurged = 1;
01808 ControlArea->
u.Flags.WasPurged = 1;
01809
01810
UNLOCK_PFN (OldIrql);
01811 LockHeld =
FALSE;
01812 ReturnValue =
TRUE;
01813
01814
for (;;) {
01815
01816
if (LastSubsection != Subsection) {
01817
01818
01819
01820
01821
01822 LastPte = &Subsection->
SubsectionBase[Subsection->
PtesInSubsection];
01823 }
else {
01824
01825
01826
01827
01828
01829 LastPte = FinalPte;
01830 }
01831
01832
01833
01834
01835
01836
01837
01838
if (!
MiCheckProtoPtePageState(PointerPte, LockHeld)) {
01839 PointerPte = (
PMMPTE)(((ULONG_PTR)PointerPte | (
PAGE_SIZE - 1)) + 1);
01840 }
01841
01842
while (PointerPte < LastPte) {
01843
01844
01845
01846
01847
01848
01849
01850
if (
MiIsPteOnPdeBoundary(PointerPte)) {
01851
if (!
MiCheckProtoPtePageState(PointerPte, LockHeld)) {
01852 PointerPte = (
PMMPTE)((PCHAR)PointerPte +
PAGE_SIZE);
01853
continue;
01854 }
01855 }
01856
01857 PteContents = *PointerPte;
01858
01859
if (PteContents.
u.Hard.Valid == 1) {
01860
01861
01862
01863
01864
01865
01866
01867 ReturnValue =
FALSE;
01868
break;
01869 }
01870
01871
if ((PteContents.
u.Soft.Prototype == 0) &&
01872 (PteContents.
u.Soft.Transition == 1)) {
01873
01874
if (!LockHeld) {
01875 LockHeld =
TRUE;
01876
LOCK_PFN (OldIrql);
01877
MiMakeSystemAddressValidPfn (PointerPte);
01878
continue;
01879 }
01880
01881 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE(&PteContents);
01882 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
01883
01884
if ((Pfn1->
OriginalPte.
u.Soft.Prototype != 1) ||
01885 (Pfn1->
OriginalPte.
u.Hard.Valid != 0) ||
01886 (Pfn1->
PteAddress != PointerPte)) {
01887
01888
01889
01890
01891
01892
01893
KeBugCheckEx (POOL_CORRUPTION_IN_FILE_AREA,
01894 0x2,
01895 (ULONG_PTR)PointerPte,
01896 (ULONG_PTR)Pfn1->
PteAddress,
01897 (ULONG_PTR)PteContents.
u.Long);
01898 }
01899
01900
#if DBG
01901
if ((Pfn1->
u3.e2.ReferenceCount != 0) &&
01902 (Pfn1->
u3.e1.WriteInProgress == 0)) {
01903
01904
01905
01906
01907
01908
01909
if (
MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE(&PteContents) != LastLocked) {
01910
UNLOCK_PFN (OldIrql);
01911
01912
#if DBG
01913
if (MmDebug &
MM_DBG_FLUSH_SECTION) {
01914
DbgPrint(
"MM:PURGE - page %lx locked, file:%Z\n",
01915 PageFrameIndex,
01916 &ControlArea->
FilePointer->
FileName
01917 );
01918 }
01919
#endif
01920
LastLocked =
MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (&PteContents);
01921
01922
LOCK_PFN (OldIrql);
01923
MiMakeSystemAddressValidPfn (PointerPte);
01924
continue;
01925 }
01926 }
01927
#endif //DBG
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
if (Pfn1->
u3.e1.WriteInProgress == 1) {
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963
if (
MiCancelWriteOfMappedPfn (PageFrameIndex) ==
TRUE) {
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973
MiMakeSystemAddressValidPfn (PointerPte);
01974
continue;
01975 }
01976
01977
ASSERT (ControlArea->
ModifiedWriteCount != 0);
01978
ASSERT (Pfn1->
u3.e2.ReferenceCount != 0);
01979
01980 ControlArea->
u.Flags.SetMappedFileIoComplete = 1;
01981
01982
KeEnterCriticalRegion();
01983
UNLOCK_PFN_AND_THEN_WAIT(OldIrql);
01984
01985
KeWaitForSingleObject(&
MmMappedFileIoComplete,
01986
WrPageOut,
01987
KernelMode,
01988
FALSE,
01989 (PLARGE_INTEGER)
NULL);
01990
LOCK_PFN (OldIrql);
01991
KeLeaveCriticalRegion();
01992
MiMakeSystemAddressValidPfn (PointerPte);
01993
continue;
01994 }
01995
01996
if (Pfn1->
u3.e1.ReadInProgress == 1) {
01997
01998
01999
02000
02001
02002
02003
02004 ReturnValue =
FALSE;
02005
break;
02006 }
02007
02008
ASSERT (!((Pfn1->
OriginalPte.
u.Soft.Prototype == 0) &&
02009 (Pfn1->
OriginalPte.
u.Soft.Transition == 1)));
02010
02011
MI_WRITE_INVALID_PTE (PointerPte, Pfn1->
OriginalPte);
02012
02013
ASSERT (Pfn1->
OriginalPte.
u.Hard.Valid == 0);
02014
02015 ControlArea->
NumberOfPfnReferences -= 1;
02016
ASSERT ((LONG)ControlArea->
NumberOfPfnReferences >= 0);
02017
02018
MiUnlinkPageFromList (Pfn1);
02019
02020
MI_SET_PFN_DELETED (Pfn1);
02021
02022
MiDecrementShareCount (Pfn1->
PteFrame);
02023
02024
02025
02026
02027
02028
02029
02030
02031
if (Pfn1->
u3.e2.ReferenceCount == 0) {
02032
MiReleasePageFileSpace (Pfn1->
OriginalPte);
02033
MiInsertPageInList (
MmPageLocationList[
FreePageList],
02034
MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (&PteContents));
02035 }
02036 }
02037 PointerPte += 1;
02038
02039
if ((
MiIsPteOnPdeBoundary(PointerPte)) && (LockHeld)) {
02040
02041
02042
02043
02044
02045
02046
UNLOCK_PFN (OldIrql);
02047 LockHeld =
FALSE;
02048 }
02049
02050 }
02051
02052
if (LockHeld) {
02053
UNLOCK_PFN (OldIrql);
02054 LockHeld =
FALSE;
02055 }
02056
02057
if ((LastSubsection != Subsection) && (ReturnValue)) {
02058
02059
02060
02061
02062
02063 Subsection = Subsection->
NextSubsection;
02064 PointerPte = Subsection->
SubsectionBase;
02065
02066 }
else {
02067
02068
02069
02070
02071
02072
02073
break;
02074 }
02075 }
02076
02077
LOCK_PFN (OldIrql);
02078
02079
ASSERT ((LONG)ControlArea->
NumberOfMappedViews >= 1);
02080 ControlArea->
NumberOfMappedViews -= 1;
02081
02082 ControlArea->
u.Flags.BeingPurged = 0;
02083
02084
02085
02086
02087
02088
02089
MiCheckControlArea (ControlArea,
NULL, OldIrql);
02090
return ReturnValue;
02091 }
02092
02093 BOOLEAN
02094 MmFlushImageSection (
02095 IN
PSECTION_OBJECT_POINTERS SectionPointer,
02096 IN
MMFLUSH_TYPE FlushType
02097 )
02098
02099
02100
02101
02102
02103
02104
02105
02106
02107
02108
02109
02110
02111
02112
02113
02114
02115
02116
02117
02118
02119
02120
02121
02122
02123
02124
02125
02126
02127 {
02128 PLIST_ENTRY Next;
02129
PCONTROL_AREA ControlArea;
02130
PLARGE_CONTROL_AREA LargeControlArea;
02131 KIRQL OldIrql;
02132 BOOLEAN state;
02133 BOOLEAN FinalControlArea;
02134
02135
02136
if (FlushType ==
MmFlushForDelete) {
02137
02138
02139
02140
02141
02142
02143
LOCK_PFN (OldIrql);
02144 ControlArea = (
PCONTROL_AREA)(SectionPointer->DataSectionObject);
02145
if (ControlArea !=
NULL) {
02146
if ((ControlArea->
NumberOfUserReferences != 0) ||
02147 (ControlArea->
u.Flags.BeingCreated)) {
02148
UNLOCK_PFN (OldIrql);
02149
return FALSE;
02150 }
02151 }
02152
UNLOCK_PFN (OldIrql);
02153 }
02154
02155
02156
02157
02158
02159
02160 state =
MiCheckControlAreaStatus (
CheckImageSection,
02161 SectionPointer,
02162
FALSE,
02163 &ControlArea,
02164 &OldIrql);
02165
02166
if (ControlArea ==
NULL) {
02167
return state;
02168 }
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
do {
02182
02183
02184
02185
02186
02187
02188
02189
02190 ControlArea->
u.Flags.BeingDeleted = 1;
02191 ControlArea->
NumberOfMappedViews = 1;
02192 FinalControlArea =
TRUE;
02193
02194
if (
MiHydra ==
FALSE) {
02195
ASSERT (ControlArea ==
02196 (
PCONTROL_AREA)SectionPointer->ImageSectionObject);
02197 }
02198
02199
else if (ControlArea->
u.Flags.GlobalOnlyPerSession == 0) {
02200 }
02201
else if (IsListEmpty(&((
PLARGE_CONTROL_AREA)ControlArea)->UserGlobalList)) {
02202
ASSERT (ControlArea ==
02203 (
PCONTROL_AREA)SectionPointer->ImageSectionObject);
02204 }
02205
else {
02206
02207
02208
02209
02210
02211
02212
02213 FinalControlArea =
FALSE;
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223
ASSERT (ControlArea->
u.Flags.GlobalOnlyPerSession == 1);
02224
02225 Next = ((
PLARGE_CONTROL_AREA)ControlArea)->UserGlobalList.Flink;
02226
02227 LargeControlArea = CONTAINING_RECORD (Next,
02228
LARGE_CONTROL_AREA,
02229 UserGlobalList);
02230
02231
ASSERT (LargeControlArea->
u.Flags.GlobalOnlyPerSession == 1);
02232
02233 LargeControlArea->
NumberOfSectionReferences += 1;
02234 }
02235
02236
02237
02238
02239
02240
02241
02242
UNLOCK_PFN (OldIrql);
02243
02244
MiCleanSection (ControlArea,
TRUE);
02245
02246
02247
02248
02249
02250
if (FinalControlArea ==
FALSE) {
02251 state =
MiCheckControlAreaStatus (
CheckImageSection,
02252 SectionPointer,
02253
FALSE,
02254 &ControlArea,
02255 &OldIrql);
02256
if (!ControlArea) {
02257
LOCK_PFN (OldIrql);
02258 LargeControlArea->
NumberOfSectionReferences -= 1;
02259
MiCheckControlArea ((
PCONTROL_AREA)LargeControlArea,
02260
NULL,
02261 OldIrql);
02262 }
02263
else {
02264 LargeControlArea->
NumberOfSectionReferences -= 1;
02265
MiCheckControlArea ((
PCONTROL_AREA)LargeControlArea,
02266
NULL,
02267 OldIrql);
02268
LOCK_PFN (OldIrql);
02269 }
02270 }
else {
02271 state =
TRUE;
02272
break;
02273 }
02274
02275 }
while (ControlArea);
02276
02277
return state;
02278 }
02279
02280
VOID
02281 MiFlushDirtyBitsToPfn (
02282 IN
PMMPTE PointerPte,
02283 IN
PMMPTE LastPte,
02284 IN
PEPROCESS Process,
02285 IN BOOLEAN SystemCache
02286 )
02287
02288 {
02289 KIRQL OldIrql;
02290
MMPTE PteContents;
02291
PMMPFN Pfn1;
02292 PVOID Va;
02293
PMMPTE PointerPde;
02294
PMMPTE PointerPpe;
02295 ULONG Waited;
02296
02297 Va =
MiGetVirtualAddressMappedByPte (PointerPte);
02298
LOCK_PFN (OldIrql);
02299
02300
while (PointerPte <= LastPte) {
02301
02302 PteContents = *PointerPte;
02303
02304
if ((PteContents.
u.Hard.Valid == 1) &&
02305 (
MI_IS_PTE_DIRTY (PteContents))) {
02306
02307
02308
02309
02310
02311 Pfn1 =
MI_PFN_ELEMENT (PteContents.
u.Hard.PageFrameNumber);
02312 Pfn1->
u3.e1.Modified = 1;
02313
02314
MI_SET_PTE_CLEAN (PteContents);
02315
02316
02317
02318
02319
02320
02321
02322 (
VOID)
KeFlushSingleTb (Va,
02323
FALSE,
02324 SystemCache,
02325 (PHARDWARE_PTE)PointerPte,
02326 PteContents.
u.Flush);
02327 }
02328
02329 Va = (PVOID)((PCHAR)Va +
PAGE_SIZE);
02330 PointerPte += 1;
02331
02332
if (
MiIsPteOnPdeBoundary (PointerPte)) {
02333
02334 PointerPde =
MiGetPteAddress (PointerPte);
02335
02336
while (PointerPte <= LastPte) {
02337
02338 PointerPpe =
MiGetPteAddress (PointerPde);
02339
02340
if (!
MiDoesPpeExistAndMakeValid (PointerPpe,
02341 Process,
02342
TRUE,
02343 &Waited)) {
02344
02345
02346
02347
02348
02349 PointerPpe += 1;
02350
02351 PointerPde =
MiGetVirtualAddressMappedByPte (PointerPpe);
02352 PointerPte =
MiGetVirtualAddressMappedByPte (PointerPde);
02353 }
02354
else {
02355
02356 Waited = 0;
02357
02358
if (!
MiDoesPdeExistAndMakeValid (PointerPde,
02359 Process,
02360
TRUE,
02361 &Waited)) {
02362
02363
02364
02365
02366
02367 PointerPde += 1;
02368
02369 PointerPte =
MiGetVirtualAddressMappedByPte (PointerPde);
02370 }
02371
else {
02372
02373
02374
02375
02376
02377
02378
if (Waited != 0) {
02379
continue;
02380 }
02381
02382
02383
02384
02385
02386
02387
02388
break;
02389 }
02390 }
02391 }
02392
02393 Va =
MiGetVirtualAddressMappedByPte (PointerPte);
02394 }
02395 }
02396
02397
UNLOCK_PFN (OldIrql);
02398
return;
02399 }
02400
02401
PSUBSECTION
02402 MiGetSystemCacheSubsection (
02403 IN PVOID BaseAddress,
02404 IN
PEPROCESS Process,
02405 OUT
PMMPTE *ProtoPte
02406 )
02407
02408 {
02409 KIRQL OldIrql;
02410
PMMPTE PointerPte;
02411
PSUBSECTION Subsection;
02412
02413
LOCK_PFN (OldIrql);
02414
02415 PointerPte =
MiGetPteAddress (BaseAddress);
02416
02417 Subsection =
MiGetSubsectionAndProtoFromPte (PointerPte,
02418 ProtoPte,
02419 Process);
02420
UNLOCK_PFN (OldIrql);
02421
return Subsection;
02422 }
02423
02424
02425 ULONG
02426
FASTCALL
02427 MiCheckProtoPtePageState (
02428 IN
PMMPTE PrototypePte,
02429 IN ULONG PfnLockHeld
02430 )
02431
02432
02433
02434
02435
02436
02437
02438
02439
02440
02441
02442
02443
02444
02445
02446
02447
02448
02449
02450
02451
02452
02453
02454
02455 {
02456
PMMPTE PointerPte;
02457
MMPTE PteContents;
02458 PFN_NUMBER PageFrameIndex;
02459
PMMPFN Pfn;
02460
02461
#if defined (_WIN64)
02462
02463
02464
02465
02466
02467 PointerPte =
MiGetPdeAddress(
PrototypePte);
02468 PteContents = *PointerPte;
02469
02470
if (PteContents.
u.Hard.Valid == 0) {
02471
return FALSE;
02472 }
02473
#endif
02474
02475 PointerPte =
MiGetPteAddress(
PrototypePte);
02476
#if !defined (_WIN64)
02477
if (PointerPte->u.Hard.Valid == 0) {
02478
MiCheckPdeForPagedPool (
PrototypePte);
02479 }
02480
#endif
02481
PteContents = *PointerPte;
02482
02483
if (PteContents.
u.Hard.Valid == 1) {
02484 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (&PteContents);
02485 Pfn =
MI_PFN_ELEMENT (PageFrameIndex);
02486
if (Pfn->
u2.ShareCount != 1) {
02487
return TRUE;
02488 }
02489 }
else if ((PteContents.
u.Soft.Prototype == 0) &&
02490 (PteContents.
u.Soft.Transition == 1)) {
02491
02492
02493
02494
02495
02496 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (&PteContents);
02497 Pfn =
MI_PFN_ELEMENT (PageFrameIndex);
02498
if (Pfn->
u3.e1.PageLocation >=
ActiveAndValid) {
02499
if (PfnLockHeld) {
02500
MiMakeSystemAddressValidPfn (
PrototypePte);
02501 }
02502
return TRUE;
02503 }
02504 }
02505
02506
02507
02508
02509
02510
return FALSE;
02511 }