00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
#include "mi.h"
00025
00026
#ifdef ALLOC_PRAGMA
00027
#pragma alloc_text(INIT,MiSectionInitialization)
00028
#endif
00029
00030 MMEVENT_COUNT_LIST MmEventCountList;
00031
00032 ULONG
00033
FASTCALL
00034
MiCheckProtoPtePageState (
00035 IN
PMMPTE PrototypePte,
00036 IN ULONG PfnLockHeld
00037 );
00038
00039 ULONG
MmUnusedSegmentForceFree;
00040
00041 SIZE_T
MmSharedCommit = 0;
00042 extern ULONG
MMCONTROL;
00043
00044
00045
00046
00047
00048 typedef enum _SEGMENT_DEREFERENCE_OBJECT {
00049
SegmentDereference,
00050
UsedSegmentCleanup,
00051
SegMaximumObject
00052 }
BALANCE_OBJECT;
00053
00054 extern POBJECT_TYPE IoFileObjectType;
00055
00056 GENERIC_MAPPING
MiSectionMapping = {
00057 STANDARD_RIGHTS_READ |
00058 SECTION_QUERY | SECTION_MAP_READ,
00059 STANDARD_RIGHTS_WRITE |
00060 SECTION_MAP_WRITE,
00061 STANDARD_RIGHTS_EXECUTE |
00062 SECTION_MAP_EXECUTE,
00063 SECTION_ALL_ACCESS
00064 };
00065
00066
VOID
00067
VadTreeWalk (
00068
PMMVAD Start
00069 );
00070
00071
VOID
00072
MiRemoveUnusedSegments(
00073 VOID
00074 );
00075
00076
00077
VOID
00078
FASTCALL
00079 MiInsertBasedSection (
00080 IN PSECTION Section
00081 )
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 {
00105
PMMADDRESS_NODE *Root;
00106
00107
ASSERT (Section->Address.EndingVpn > Section->Address.StartingVpn);
00108
00109 Root = &
MmSectionBasedRoot;
00110
00111
MiInsertNode (&Section->Address, Root);
00112
return;
00113 }
00114
00115
00116
VOID
00117
FASTCALL
00118 MiRemoveBasedSection (
00119 IN PSECTION Section
00120 )
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142 {
00143
PMMADDRESS_NODE *Root;
00144
00145 Root = &
MmSectionBasedRoot;
00146
00147
MiRemoveNode (&Section->Address, Root);
00148
00149
return;
00150 }
00151
00152
00153 PVOID
00154 MiFindEmptySectionBaseDown (
00155 IN ULONG SizeOfRange,
00156 IN PVOID HighestAddressToEndAt
00157 )
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 {
00183
return MiFindEmptyAddressRangeDownTree (SizeOfRange,
00184 HighestAddressToEndAt,
00185
X64K,
00186
MmSectionBasedRoot);
00187 }
00188
00189
00190
VOID
00191 MiSegmentDelete (
00192
PSEGMENT Segment
00193 )
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
PMMPTE PointerPte;
00224
PMMPTE LastPte;
00225
PMMPFN Pfn1;
00226 KIRQL OldIrql;
00227 KIRQL OldIrql2;
00228
volatile PFILE_OBJECT File;
00229
volatile PCONTROL_AREA ControlArea;
00230
PEVENT_COUNTER Event;
00231
MMPTE PteContents;
00232
PSUBSECTION Subsection;
00233
PSUBSECTION NextSubsection;
00234 SIZE_T CommittedPages;
00235
00236 PointerPte = Segment->
PrototypePte;
00237 LastPte = PointerPte + Segment->
NonExtendedPtes;
00238
00239
#if DBG
00240
if (MmDebug &
MM_DBG_SECTIONS) {
00241
DbgPrint(
"MM:deleting segment %lx control %lx\n",Segment, Segment->
ControlArea);
00242 }
00243
#endif
00244
00245 ControlArea = Segment->
ControlArea;
00246
00247
ASSERT (ControlArea->
u.Flags.BeingDeleted == 1);
00248
00249
LOCK_PFN (OldIrql2);
00250
if (ControlArea->
DereferenceList.Flink !=
NULL) {
00251
00252
00253
00254
00255
00256 ExAcquireSpinLock (&
MmDereferenceSegmentHeader.
Lock, &OldIrql);
00257 RemoveEntryList (&ControlArea->
DereferenceList);
00258
00259
MI_UNUSED_SEGMENTS_REMOVE_CHARGE (ControlArea);
00260
00261 ExReleaseSpinLock (&
MmDereferenceSegmentHeader.
Lock, OldIrql);
00262 }
00263
UNLOCK_PFN (OldIrql2);
00264
00265
if (ControlArea->
u.Flags.Image ||
00266 ControlArea->
u.Flags.File ) {
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
if (ControlArea->
u.Flags.DebugSymbolsLoaded != 0) {
00279
00280
00281
00282
00283
00284 ANSI_STRING AnsiName;
00285
NTSTATUS Status;
00286
00287
Status =
RtlUnicodeStringToAnsiString( &AnsiName,
00288 (PUNICODE_STRING)&Segment->
ControlArea->
FilePointer->
FileName,
00289
TRUE );
00290
00291
if (
NT_SUCCESS(
Status)) {
00292 DbgUnLoadImageSymbols( &AnsiName,
00293 Segment->
BasedAddress,
00294 (ULONG_PTR)
PsGetCurrentProcess());
00295
RtlFreeAnsiString( &AnsiName );
00296 }
00297
LOCK_PFN (OldIrql);
00298 ControlArea->
u.Flags.DebugSymbolsLoaded = 0;
00299
UNLOCK_PFN (OldIrql);
00300 }
00301
00302
00303
00304
00305
00306
00307
if (ControlArea->
u.Flags.BeingCreated ==
FALSE) {
00308
00309
00310
00311
00312
00313
00314
LOCK_PFN (OldIrql);
00315
00316
MiMakeSystemAddressValidPfn (Segment);
00317
File = (
volatile PFILE_OBJECT)Segment->
ControlArea->
FilePointer;
00318 ControlArea = (
volatile PCONTROL_AREA)Segment->
ControlArea;
00319
00320
Event = ControlArea->
WaitingForDeletion;
00321 ControlArea->
WaitingForDeletion =
NULL;
00322
00323
UNLOCK_PFN (OldIrql);
00324
00325
if (
Event !=
NULL) {
00326
KeSetEvent (&
Event->Event, 0,
FALSE);
00327 }
00328
00329
#if DBG
00330
if (ControlArea->
u.Flags.Image == 1) {
00331
ASSERT (ControlArea->
FilePointer->
SectionObjectPointer->
ImageSectionObject != (PVOID)ControlArea);
00332 }
else {
00333
ASSERT (ControlArea->
FilePointer->
SectionObjectPointer->
DataSectionObject != (PVOID)ControlArea);
00334 }
00335
#endif //DBG
00336
00337
PERFINFO_SEGMENT_DELETE(ControlArea->
FilePointer);
00338
00339
ObDereferenceObject (ControlArea->
FilePointer);
00340 }
00341
00342
if (ControlArea->
u.Flags.Image == 0) {
00343
00344
00345
00346
00347
00348
00349
#if DBG
00350
while (PointerPte < LastPte) {
00351
00352
00353
00354
00355
00356
00357
ASSERT (PointerPte->
u.Hard.Valid == 0);
00358
ASSERT ((PointerPte->
u.Soft.Prototype == 1) ||
00359 (PointerPte->
u.Long == 0));
00360 PointerPte += 1;
00361 }
00362
#endif //DBG
00363
00364
00365
00366
00367
00368
ASSERT (ControlArea->
u.Flags.GlobalOnlyPerSession == 0);
00369
00370 Subsection = (
PSUBSECTION)(ControlArea + 1);
00371
00372 Subsection = Subsection->
NextSubsection;
00373
00374
while (Subsection !=
NULL) {
00375
ExFreePool (Subsection->
SubsectionBase);
00376 NextSubsection = Subsection->
NextSubsection;
00377
ExFreePool (Subsection);
00378 Subsection = NextSubsection;
00379 }
00380
00381
if (Segment->
NumberOfCommittedPages != 0) {
00382
MiReturnCommitment (Segment->
NumberOfCommittedPages);
00383
MM_TRACK_COMMIT (
MM_DBG_COMMIT_RETURN_SEGMENT_DELETE1,
00384 Segment->
NumberOfCommittedPages);
00385
00386 ExAcquireFastMutex (&
MmSectionCommitMutex);
00387
MmSharedCommit -= Segment->
NumberOfCommittedPages;
00388 ExReleaseFastMutex (&
MmSectionCommitMutex);
00389 }
00390
00391
ExFreePool (Segment->
ControlArea);
00392
ExFreePool (Segment);
00393
00394
00395
00396
00397
00398
return;
00399 }
00400 }
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
LOCK_PFN (OldIrql);
00413
00414
MiMakeSystemAddressValidPfn (PointerPte);
00415
00416
while (PointerPte < LastPte) {
00417
00418
if (
MiIsPteOnPdeBoundary(PointerPte)) {
00419
00420
00421
00422
00423
00424
if (
MmIsAddressValid (PointerPte) ==
FALSE) {
00425
00426
MiMakeSystemAddressValidPfn (PointerPte);
00427 }
00428 }
00429
00430 PteContents = *PointerPte;
00431
00432
00433
00434
00435
00436
00437
ASSERT (PteContents.
u.Hard.Valid == 0);
00438
00439
if (PteContents.
u.Soft.Prototype == 0) {
00440
00441
if (PteContents.
u.Soft.Transition == 1) {
00442
00443
00444
00445
00446
00447 Pfn1 =
MI_PFN_ELEMENT (PteContents.
u.Trans.PageFrameNumber);
00448
00449
MI_SET_PFN_DELETED (Pfn1);
00450
00451
MiDecrementShareCount (Pfn1->
PteFrame);
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
if (Pfn1->
u3.e2.ReferenceCount == 0) {
00463
MiUnlinkPageFromList (Pfn1);
00464
MiReleasePageFileSpace (Pfn1->
OriginalPte);
00465
MiInsertPageInList (
MmPageLocationList[
FreePageList],
00466
MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (&PteContents));
00467 }
00468
00469 }
else {
00470
00471
00472
00473
00474
00475
00476
if (
IS_PTE_NOT_DEMAND_ZERO (PteContents)) {
00477
MiReleasePageFileSpace (PteContents);
00478 }
00479 }
00480 }
00481
#if DBG
00482
MI_WRITE_INVALID_PTE (PointerPte,
ZeroPte);
00483
#endif
00484
PointerPte += 1;
00485 }
00486
00487
UNLOCK_PFN (OldIrql);
00488
00489
00490
00491
00492
00493
00494
if (Segment->
NumberOfCommittedPages != 0) {
00495
MiReturnCommitment (Segment->
NumberOfCommittedPages);
00496
MM_TRACK_COMMIT (
MM_DBG_COMMIT_RETURN_SEGMENT_DELETE2,
00497 Segment->
NumberOfCommittedPages);
00498
00499 ExAcquireFastMutex (&
MmSectionCommitMutex);
00500
MmSharedCommit -= Segment->
NumberOfCommittedPages;
00501 ExReleaseFastMutex (&
MmSectionCommitMutex);
00502 }
00503
00504
ExFreePool (Segment->
ControlArea);
00505
ExFreePool (Segment);
00506
00507
return;
00508 }
00509
00510
VOID
00511 MiSectionDelete (
00512 PVOID Object
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
PSECTION Section;
00538
volatile PCONTROL_AREA ControlArea;
00539 KIRQL OldIrql;
00540 ULONG UserRef;
00541
00542 Section = (
PSECTION)Object;
00543
00544
if (Section->Segment == (
PSEGMENT)
NULL) {
00545
00546
00547
00548
00549
00550
return;
00551 }
00552
00553 UserRef = Section->u.Flags.UserReference;
00554 ControlArea = (
volatile PCONTROL_AREA)Section->
Segment->
ControlArea;
00555
00556
#if DBG
00557
if (MmDebug &
MM_DBG_SECTIONS) {
00558
DbgPrint(
"MM:deleting section %lx control %lx\n",Section, ControlArea);
00559 }
00560
#endif
00561
00562
if (Section->Address.StartingVpn != 0) {
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573 ExAcquireFastMutex (&
MmSectionBasedMutex);
00574
00575
MiRemoveBasedSection (Section);
00576
00577 ExReleaseFastMutex (&
MmSectionBasedMutex);
00578
00579 }
00580
00581
00582
00583
00584
00585
00586
00587
LOCK_PFN (OldIrql);
00588
00589 ControlArea->
NumberOfSectionReferences -= 1;
00590 ControlArea->
NumberOfUserReferences -= UserRef;
00591
00592
00593
00594
00595
00596
MiCheckControlArea (ControlArea,
NULL, OldIrql);
00597
00598
return;
00599 }
00600
00601
00602
VOID
00603 MiDereferenceSegmentThread (
00604 IN PVOID StartContext
00605 )
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628 {
00629
PCONTROL_AREA ControlArea;
00630
PMMPAGE_FILE_EXPANSION PageExpand;
00631 PLIST_ENTRY NextEntry;
00632 KIRQL OldIrql;
00633
static KWAIT_BLOCK WaitBlockArray[
SegMaximumObject];
00634 PVOID WaitObjects[
SegMaximumObject];
00635
NTSTATUS Status;
00636
00637 UNREFERENCED_PARAMETER (StartContext);
00638
00639
00640
00641
00642
00643 (
VOID)
KeSetPriorityThread (&
PsGetCurrentThread()->Tcb,
00644 LOW_REALTIME_PRIORITY + 2);
00645
00646 WaitObjects[
SegmentDereference] = (PVOID)&
MmDereferenceSegmentHeader.
Semaphore;
00647 WaitObjects[
UsedSegmentCleanup] = (PVOID)&
MmUnusedSegmentCleanup;
00648
00649
for (;;) {
00650
00651
Status =
KeWaitForMultipleObjects(
SegMaximumObject,
00652 &WaitObjects[0],
00653 WaitAny,
00654
WrVirtualMemory,
00655
UserMode,
00656
FALSE,
00657
NULL,
00658 &WaitBlockArray[0]);
00659
00660
00661
00662
00663
00664
switch (
Status) {
00665
00666
case SegmentDereference:
00667
00668
00669
00670
00671
00672
00673 ExAcquireSpinLock (&
MmDereferenceSegmentHeader.
Lock, &OldIrql);
00674
00675
if (IsListEmpty(&
MmDereferenceSegmentHeader.
ListHead)) {
00676
00677
00678
00679
00680
00681 ExReleaseSpinLock (&
MmDereferenceSegmentHeader.
Lock, OldIrql);
00682
break;
00683 }
00684
00685 NextEntry = RemoveHeadList(&
MmDereferenceSegmentHeader.
ListHead);
00686
00687 ExReleaseSpinLock (&
MmDereferenceSegmentHeader.
Lock, OldIrql);
00688
00689
ASSERT (KeGetCurrentIrql() <
DISPATCH_LEVEL);
00690
00691 ControlArea = CONTAINING_RECORD( NextEntry,
00692
CONTROL_AREA,
00693 DereferenceList );
00694
00695
if (ControlArea->
Segment !=
NULL) {
00696
00697
00698
00699
00700
00701
#if DBG
00702
if (MmDebug &
MM_DBG_SECTIONS) {
00703
DbgPrint(
"MM:dereferencing segment %lx control %lx\n",
00704 ControlArea->
Segment, ControlArea);
00705 }
00706
#endif
00707
00708
00709
00710
00711
00712 ControlArea->
DereferenceList.Flink =
NULL;
00713
00714
ASSERT (ControlArea->
u.Flags.FilePointerNull == 1);
00715
MiSegmentDelete (ControlArea->
Segment);
00716
00717 }
else {
00718
00719
00720
00721
00722
00723 PageExpand = (
PMMPAGE_FILE_EXPANSION)ControlArea;
00724
00725
if (PageExpand->
RequestedExpansionSize == 0xFFFFFFFF) {
00726
00727
00728
00729
00730
00731
ExFreePool (PageExpand);
00732
00733
MiAttemptPageFileReduction ();
00734 }
else {
00735
00736
00737
00738
00739
00740
MiExtendPagingFiles (PageExpand);
00741
KeSetEvent (&PageExpand->
Event, 0,
FALSE);
00742
MiRemoveUnusedSegments();
00743 }
00744 }
00745
break;
00746
00747
case UsedSegmentCleanup:
00748
00749
MiRemoveUnusedSegments();
00750
00751
KeClearEvent (&
MmUnusedSegmentCleanup);
00752
00753
break;
00754
00755
default:
00756
00757 KdPrint((
"MMSegmentderef: Illegal wait status, %lx =\n",
Status));
00758
break;
00759 }
00760
00761 }
00762
00763
return;
00764 }
00765
00766
00767 ULONG
00768 MiSectionInitialization (
00769 )
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793 {
00794
OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
00795 UNICODE_STRING TypeName;
00796 HANDLE
ThreadHandle;
00797 OBJECT_ATTRIBUTES
ObjectAttributes;
00798 UNICODE_STRING SectionName;
00799
PSECTION Section;
00800 HANDLE
Handle;
00801
PSEGMENT Segment;
00802
PCONTROL_AREA ControlArea;
00803
NTSTATUS Status;
00804
00805
MmSectionBasedRoot = (
PMMADDRESS_NODE)
NULL;
00806
00807
00808
00809
00810
00811 RtlZeroMemory( &ObjectTypeInitializer,
sizeof( ObjectTypeInitializer ) );
00812 ObjectTypeInitializer.Length =
sizeof( ObjectTypeInitializer );
00813 ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
00814 ObjectTypeInitializer.GenericMapping =
MiSectionMapping;
00815 ObjectTypeInitializer.PoolType =
PagedPool;
00816 ObjectTypeInitializer.DefaultPagedPoolCharge =
sizeof(
SECTION);
00817
00818
00819
00820
00821
00822
RtlInitUnicodeString (&TypeName,
L"Section");
00823
00824
00825
00826
00827
00828 ObjectTypeInitializer.ValidAccessMask = SECTION_ALL_ACCESS;
00829 ObjectTypeInitializer.DeleteProcedure =
MiSectionDelete;
00830 ObjectTypeInitializer.GenericMapping =
MiSectionMapping;
00831 ObjectTypeInitializer.UseDefaultObject =
TRUE;
00832
if ( !
NT_SUCCESS(
ObCreateObjectType(&TypeName,
00833 &ObjectTypeInitializer,
00834 (PSECURITY_DESCRIPTOR)
NULL,
00835 &
MmSectionObjectType
00836 )) ) {
00837
return FALSE;
00838 }
00839
00840
00841
00842
00843
00844
00845
KeInitializeSpinLock (&
MmDereferenceSegmentHeader.
Lock);
00846 InitializeListHead (&
MmDereferenceSegmentHeader.
ListHead);
00847
KeInitializeSemaphore (&
MmDereferenceSegmentHeader.
Semaphore, 0, MAXLONG);
00848
00849 InitializeListHead (&
MmUnusedSegmentList);
00850
KeInitializeEvent (&
MmUnusedSegmentCleanup, NotificationEvent,
FALSE);
00851
00852
00853
00854
00855
00856 InitializeObjectAttributes( &
ObjectAttributes,
00857
NULL,
00858 0,
00859
NULL,
00860
NULL );
00861
00862
if ( !
NT_SUCCESS(
PsCreateSystemThread(
00863 &
ThreadHandle,
00864 THREAD_ALL_ACCESS,
00865 &
ObjectAttributes,
00866 0,
00867
NULL,
00868
MiDereferenceSegmentThread,
00869
NULL
00870 )) ) {
00871
return FALSE;
00872 }
00873 ZwClose (
ThreadHandle);
00874
00875
00876
00877
00878
00879 Segment = (
PSEGMENT)
ExAllocatePoolWithTag (
PagedPool,
00880
sizeof(
SEGMENT),
00881 'gSmM');
00882
if (Segment ==
NULL) {
00883
return FALSE;
00884 }
00885
00886 ControlArea =
ExAllocatePoolWithTag (
NonPagedPool,
00887 (ULONG)
sizeof(
CONTROL_AREA),
00888
MMCONTROL);
00889
if (ControlArea ==
NULL) {
00890
ExFreePool (Segment);
00891
return FALSE;
00892 }
00893
00894 RtlZeroMemory (Segment,
sizeof(
SEGMENT));
00895 RtlZeroMemory (ControlArea,
sizeof(
CONTROL_AREA));
00896
00897 ControlArea->
Segment = Segment;
00898 ControlArea->
NumberOfSectionReferences = 1;
00899 ControlArea->
u.Flags.PhysicalMemory = 1;
00900
00901 Segment->
ControlArea = ControlArea;
00902 Segment->
SegmentPteTemplate =
ZeroPte;
00903
00904
00905
00906
00907
00908
00909
RtlInitUnicodeString (&SectionName,
L"\\Device\\PhysicalMemory");
00910
00911 InitializeObjectAttributes( &
ObjectAttributes,
00912 &SectionName,
00913 OBJ_PERMANENT,
00914
NULL,
00915
NULL
00916 );
00917
00918
Status =
ObCreateObject (
KernelMode,
00919
MmSectionObjectType,
00920 &
ObjectAttributes,
00921
KernelMode,
00922
NULL,
00923
sizeof(
SECTION),
00924
sizeof(
SECTION),
00925 0,
00926 (PVOID *)&Section);
00927
if (!
NT_SUCCESS(
Status)) {
00928
ExFreePool (ControlArea);
00929
ExFreePool (Segment);
00930
return FALSE;
00931 }
00932
00933 Section->Segment = Segment;
00934 Section->SizeOfSection.QuadPart = ((LONGLONG)1 <<
PHYSICAL_ADDRESS_BITS) - 1;
00935 Section->u.LongFlags = 0;
00936 Section->InitialPageProtection = PAGE_READWRITE;
00937
00938
Status =
ObInsertObject ((PVOID)Section,
00939
NULL,
00940 SECTION_MAP_READ,
00941 0,
00942 (PVOID *)
NULL,
00943 &
Handle);
00944
00945
if (!
NT_SUCCESS(
Status )) {
00946
return FALSE;
00947 }
00948
00949
if ( !
NT_SUCCESS (
NtClose (
Handle))) {
00950
return FALSE;
00951 }
00952
00953
return TRUE;
00954 }
00955
00956 BOOLEAN
00957 MmForceSectionClosed (
00958 IN
PSECTION_OBJECT_POINTERS SectionObjectPointer,
00959 IN BOOLEAN DelayClose
00960 )
00961
00962
00963
00964
00965
00966
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
00993 {
00994
PCONTROL_AREA ControlArea;
00995 KIRQL OldIrql;
00996 BOOLEAN state;
00997
00998
00999
01000
01001
01002
01003 state =
MiCheckControlAreaStatus (
CheckBothSection,
01004 SectionObjectPointer,
01005 DelayClose,
01006 &ControlArea,
01007 &OldIrql);
01008
01009
if (ControlArea ==
NULL) {
01010
return state;
01011 }
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
do {
01025
01026
01027
01028
01029
01030
01031
01032
01033 ControlArea->
u.Flags.BeingDeleted = 1;
01034
ASSERT (ControlArea->
NumberOfMappedViews == 0);
01035 ControlArea->
NumberOfMappedViews = 1;
01036
01037
01038
01039
01040
01041
01042
UNLOCK_PFN (OldIrql);
01043
01044
01045
01046
01047
01048
01049
01050
MiCleanSection (ControlArea,
TRUE);
01051
01052
01053
01054
01055
01056
if (
MiHydra ==
TRUE) {
01057 state =
MiCheckControlAreaStatus (
CheckBothSection,
01058 SectionObjectPointer,
01059 DelayClose,
01060 &ControlArea,
01061 &OldIrql);
01062 }
01063
else {
01064 state =
TRUE;
01065
break;
01066 }
01067
01068 }
while (ControlArea);
01069
01070
return state;
01071 }
01072
01073
01074
VOID
01075 MiCleanSection (
01076 IN
PCONTROL_AREA ControlArea,
01077 IN LOGICAL DirtyDataPagesOk
01078 )
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116 {
01117
PMMPTE PointerPte;
01118
PMMPTE LastPte;
01119
PMMPTE LastWritten;
01120
MMPTE PteContents;
01121
PMMPFN Pfn1;
01122
PMMPFN Pfn2;
01123
PMMPTE WrittenPte;
01124
MMPTE WrittenContents;
01125 KIRQL OldIrql;
01126
PMDL Mdl;
01127
PSUBSECTION Subsection;
01128 PPFN_NUMBER Page;
01129 PPFN_NUMBER LastPage;
01130 LARGE_INTEGER StartingOffset;
01131 LARGE_INTEGER TempOffset;
01132
NTSTATUS Status;
01133 IO_STATUS_BLOCK IoStatus;
01134 ULONG WriteNow;
01135 ULONG ImageSection;
01136 ULONG DelayCount;
01137 ULONG First;
01138
KEVENT IoEvent;
01139 PFN_NUMBER MdlHack[(
sizeof(
MDL)/
sizeof(PFN_NUMBER)) +
MM_MAXIMUM_WRITE_CLUSTER];
01140
01141 WriteNow =
FALSE;
01142 ImageSection =
FALSE;
01143 DelayCount = 0;
01144
01145
if (ControlArea->u.Flags.Image) {
01146 ImageSection =
TRUE;
01147 }
01148
ASSERT (ControlArea->FilePointer);
01149
01150 PointerPte = ControlArea->Segment->PrototypePte;
01151 LastPte = PointerPte + ControlArea->Segment->NonExtendedPtes;
01152
01153 Mdl = (
PMDL)&MdlHack;
01154
01155
KeInitializeEvent (&IoEvent, NotificationEvent,
FALSE);
01156
01157 LastWritten =
NULL;
01158
ASSERT (
MmModifiedWriteClusterSize ==
MM_MAXIMUM_WRITE_CLUSTER);
01159 LastPage =
NULL;
01160
01161
if (ControlArea->u.Flags.GlobalOnlyPerSession == 0) {
01162 Subsection = (
PSUBSECTION)(ControlArea + 1);
01163 }
01164
else {
01165 Subsection = (
PSUBSECTION)((
PLARGE_CONTROL_AREA)ControlArea + 1);
01166 }
01167
01168
01169
01170
01171
01172
01173
LOCK_PFN (OldIrql);
01174
01175
01176
01177
01178
01179
01180
01181 ControlArea->u.Flags.NoModifiedWriting = 1;
01182
01183
while (ControlArea->ModifiedWriteCount != 0) {
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194 ControlArea->u.Flags.SetMappedFileIoComplete = 1;
01195
KeEnterCriticalRegion();
01196
UNLOCK_PFN_AND_THEN_WAIT(OldIrql);
01197
01198
KeWaitForSingleObject(&
MmMappedFileIoComplete,
01199
WrPageOut,
01200
KernelMode,
01201
FALSE,
01202 (PLARGE_INTEGER)
NULL);
01203
LOCK_PFN (OldIrql);
01204
KeLeaveCriticalRegion();
01205 }
01206
01207
for (;;) {
01208
01209 First =
TRUE;
01210
while (PointerPte < LastPte) {
01211
01212
if ((
MiIsPteOnPdeBoundary(PointerPte)) || (First)) {
01213
01214 First =
FALSE;
01215
01216
if ((ImageSection) ||
01217 (
MiCheckProtoPtePageState(PointerPte,
FALSE))) {
01218
MiMakeSystemAddressValidPfn (PointerPte);
01219 }
else {
01220
01221
01222
01223
01224
01225
01226 PointerPte = (
PMMPTE)((((ULONG_PTR)PointerPte |
PAGE_SIZE - 1)) + 1);
01227
if (LastWritten !=
NULL) {
01228 WriteNow =
TRUE;
01229 }
01230
goto WriteItOut;
01231 }
01232 }
01233
01234 PteContents = *PointerPte;
01235
01236
01237
01238
01239
01240
01241
if (PteContents.
u.Hard.Valid == 1) {
01242
KeBugCheckEx (POOL_CORRUPTION_IN_FILE_AREA,
01243 0x0,
01244 (ULONG_PTR)ControlArea,
01245 (ULONG_PTR)PointerPte,
01246 (ULONG_PTR)PteContents.
u.Long);
01247 }
01248
01249
if (PteContents.
u.Soft.Prototype == 1) {
01250
01251
01252
01253
01254
01255
if (LastWritten !=
NULL) {
01256 WriteNow =
TRUE;
01257 }
01258 }
01259
else if (PteContents.
u.Soft.Transition == 1) {
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272 Pfn1 =
MI_PFN_ELEMENT (PteContents.
u.Trans.PageFrameNumber);
01273
01274
if (Pfn1->
u3.e2.ReferenceCount != 0) {
01275
if (DelayCount < 20) {
01276
01277
01278
01279
01280
01281
01282
UNLOCK_PFN (OldIrql);
01283
01284
KeDelayExecutionThread (
KernelMode,
FALSE, (PLARGE_INTEGER)&
MmShortTime);
01285
01286 DelayCount += 1;
01287
01288
01289
01290
01291
01292
01293
01294
01295
LOCK_PFN (OldIrql);
01296
MiMakeSystemAddressValidPfn (PointerPte);
01297
continue;
01298 }
01299
#if DBG
01300
01301
01302
01303
01304
01305
01306 KdPrint((
"MM:CLEAN - page number %lx has i/o outstanding\n",
01307 PteContents.
u.Trans.PageFrameNumber));
01308
#endif
01309
}
01310
01311
if (Pfn1->
OriginalPte.
u.Soft.Prototype == 0) {
01312
01313
01314
01315
01316
01317
MI_SET_PFN_DELETED (Pfn1);
01318
01319
if (!ImageSection) {
01320
01321
01322
01323
01324
01325
01326
01327 ControlArea->NumberOfPfnReferences -= 1;
01328
ASSERT ((LONG)ControlArea->NumberOfPfnReferences >= 0);
01329 }
01330
#if DBG
01331
else {
01332
01333
01334
01335
01336 }
01337
#endif
01338
01339
MiDecrementShareCount (Pfn1->
PteFrame);
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
if ((Pfn1->
u3.e2.ReferenceCount == 0) &&
01350 (Pfn1->
u3.e1.PageLocation !=
FreePageList)) {
01351
01352
MiUnlinkPageFromList (Pfn1);
01353
MiReleasePageFileSpace (Pfn1->
OriginalPte);
01354
MiInsertPageInList (
MmPageLocationList[
FreePageList],
01355
MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (&PteContents));
01356
01357 }
01358 PointerPte->u.Long = 0;
01359
01360
01361
01362
01363
01364
01365
if (LastWritten !=
NULL) {
01366 WriteNow =
TRUE;
01367 }
01368
01369 }
else {
01370
01371
if ((Pfn1->
u3.e1.Modified == 0) || (ImageSection)) {
01372
01373
01374
01375
01376
01377
MI_SET_PFN_DELETED (Pfn1);
01378 ControlArea->NumberOfPfnReferences -= 1;
01379
ASSERT ((LONG)ControlArea->NumberOfPfnReferences >= 0);
01380
01381
MiDecrementShareCount (Pfn1->
PteFrame);
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
if ((Pfn1->
u3.e2.ReferenceCount == 0) &&
01393 (Pfn1->
u3.e1.PageLocation !=
FreePageList)) {
01394
01395
MiUnlinkPageFromList (Pfn1);
01396
MiReleasePageFileSpace (Pfn1->
OriginalPte);
01397
MiInsertPageInList (
MmPageLocationList[
FreePageList],
01398
MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (&PteContents));
01399 }
01400
01401 PointerPte->u.Long = 0;
01402
01403
01404
01405
01406
01407
01408
if (LastWritten !=
NULL) {
01409 WriteNow =
TRUE;
01410 }
01411
01412 }
else {
01413
01414
01415
01416
01417
01418
01419
01420
if (LastWritten ==
NULL) {
01421 LastPage = (PPFN_NUMBER)(Mdl + 1);
01422
ASSERT (
MiGetSubsectionAddress(&Pfn1->
OriginalPte) ==
01423 Subsection);
01424
01425
01426
01427
01428
01429
01430
ASSERT (Subsection->
ControlArea->
u.Flags.Image == 0);
01431 StartingOffset.QuadPart =
MiStartingOffset(
01432 Subsection,
01433 Pfn1->
PteAddress);
01434
01435
MI_INITIALIZE_ZERO_MDL (Mdl);
01436 Mdl->
MdlFlags |=
MDL_PAGES_LOCKED;
01437
01438 Mdl->
StartVa =
01439 (PVOID)ULongToPtr(Pfn1->
u3.e1.PageColor <<
PAGE_SHIFT);
01440 Mdl->
Size = (CSHORT)(
sizeof(
MDL) +
01441 (
sizeof(PFN_NUMBER) *
MmModifiedWriteClusterSize));
01442 }
01443
01444 LastWritten = PointerPte;
01445 Mdl->
ByteCount +=
PAGE_SIZE;
01446
01447
01448
01449
01450
01451
01452
if (Mdl->
ByteCount == (
PAGE_SIZE *
MmModifiedWriteClusterSize)) {
01453 WriteNow =
TRUE;
01454 }
01455
01456
MiUnlinkPageFromList (Pfn1);
01457 Pfn1->
u3.e1.Modified = 0;
01458
01459
01460
01461
01462
01463
01464
MI_ADD_LOCKED_PAGE_CHARGE_FOR_MODIFIED_PAGE(Pfn1, 22);
01465 Pfn1->
u3.e2.ReferenceCount += 1;
01466
01467
01468
01469
01470
01471
01472 *LastPage =
MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (&PteContents);
01473
01474 LastPage += 1;
01475 }
01476 }
01477 }
else {
01478
01479
if (
IS_PTE_NOT_DEMAND_ZERO (PteContents)) {
01480
MiReleasePageFileSpace (PteContents);
01481 }
01482 PointerPte->u.Long = 0;
01483
01484
01485
01486
01487
01488
01489
if (LastWritten !=
NULL) {
01490 WriteNow =
TRUE;
01491 }
01492 }
01493
01494
01495
01496
01497
01498
01499 PointerPte += 1;
01500 WriteItOut:
01501 DelayCount = 0;
01502
01503
if ((WriteNow) ||
01504 ((PointerPte == LastPte) && (LastWritten !=
NULL))) {
01505
01506
01507
01508
01509
01510
UNLOCK_PFN (OldIrql);
01511
01512
if (DirtyDataPagesOk ==
FALSE) {
01513
KeBugCheckEx (POOL_CORRUPTION_IN_FILE_AREA,
01514 0x1,
01515 (ULONG_PTR)ControlArea,
01516 (ULONG_PTR)Mdl,
01517 (ULONG_PTR)0);
01518 }
01519
01520 WriteNow =
FALSE;
01521
01522
KeClearEvent (&IoEvent);
01523
01524
01525
01526
01527
01528
01529
ASSERT (Subsection->
ControlArea->
u.Flags.Image == 0);
01530
01531 TempOffset =
MiEndingOffset(Subsection);
01532
01533
if (((UINT64)StartingOffset.QuadPart + Mdl->
ByteCount) >
01534 (UINT64)TempOffset.QuadPart) {
01535
01536
ASSERT ((ULONG)(TempOffset.QuadPart -
01537 StartingOffset.QuadPart) >
01538 (Mdl->
ByteCount -
PAGE_SIZE));
01539
01540 Mdl->
ByteCount = (ULONG)(TempOffset.QuadPart -
01541 StartingOffset.QuadPart);
01542 }
01543
01544
#if DBG
01545
if (MmDebug &
MM_DBG_FLUSH_SECTION) {
01546
DbgPrint(
"MM:flush page write begun %lx\n",
01547 Mdl->
ByteCount);
01548 }
01549
#endif //DBG
01550
01551
Status =
IoSynchronousPageWrite (ControlArea->FilePointer,
01552 Mdl,
01553 &StartingOffset,
01554 &IoEvent,
01555 &IoStatus );
01556
01557
if (
NT_SUCCESS(
Status)) {
01558
01559
KeWaitForSingleObject (&IoEvent,
01560
WrPageOut,
01561
KernelMode,
01562
FALSE,
01563 (PLARGE_INTEGER)
NULL);
01564 }
01565
01566
if (Mdl->
MdlFlags &
MDL_MAPPED_TO_SYSTEM_VA) {
01567
MmUnmapLockedPages (Mdl->
MappedSystemVa, Mdl);
01568 }
01569
01570 Page = (PPFN_NUMBER)(Mdl + 1);
01571
01572
LOCK_PFN (OldIrql);
01573
01574
if (
MiIsPteOnPdeBoundary(PointerPte) == 0) {
01575
01576
01577
01578
01579
01580
01581
01582
MiMakeSystemAddressValidPfn (PointerPte);
01583 }
01584
01585
01586
01587
01588
01589
01590
01591
while (Page < LastPage) {
01592
01593 Pfn2 =
MI_PFN_ELEMENT (*Page);
01594
01595
01596
01597
01598
01599 WrittenPte = Pfn2->
PteAddress;
01600
01601
MI_REMOVE_LOCKED_PAGE_CHARGE (Pfn2, 23);
01602
MiDecrementReferenceCount (*Page);
01603
01604
if (!
MI_IS_PFN_DELETED (Pfn2)) {
01605
01606
01607
01608
01609
01610
01611
MiMakeSystemAddressValidPfn (WrittenPte);
01612
01613
if (Pfn2->
PteAddress != WrittenPte) {
01614
01615
01616
01617
01618
01619
01620
01621
01622 Page += 1;
01623
continue;
01624 }
01625
01626 WrittenContents = *WrittenPte;
01627
01628
if ((WrittenContents.
u.Soft.Prototype == 0) &&
01629 (WrittenContents.
u.Soft.Transition == 1)) {
01630
01631
MI_SET_PFN_DELETED (Pfn2);
01632 ControlArea->NumberOfPfnReferences -= 1;
01633
ASSERT ((LONG)ControlArea->NumberOfPfnReferences >= 0);
01634
01635
MiDecrementShareCount (Pfn2->
PteFrame);
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
if ((Pfn2->
u3.e2.ReferenceCount == 0) &&
01648 (Pfn2->
u3.e1.PageLocation !=
FreePageList)) {
01649
01650
MiUnlinkPageFromList (Pfn2);
01651
MiReleasePageFileSpace (Pfn2->
OriginalPte);
01652
MiInsertPageInList (
01653
MmPageLocationList[
FreePageList],
01654 *Page);
01655 }
01656 }
01657 WrittenPte->u.Long = 0;
01658 }
01659 Page += 1;
01660 }
01661
01662
01663
01664
01665
01666 LastWritten =
NULL;
01667 }
01668
01669 }
01670
01671
01672
01673
01674
01675
if (Subsection->
NextSubsection == (
PSUBSECTION)
NULL) {
01676
break;
01677 }
01678
01679 Subsection = Subsection->
NextSubsection;
01680 PointerPte = Subsection->
SubsectionBase;
01681 LastPte = PointerPte + Subsection->
PtesInSubsection;
01682
01683 }
01684
01685 ControlArea->NumberOfMappedViews = 0;
01686
01687
ASSERT (ControlArea->NumberOfPfnReferences == 0);
01688
01689
if (ControlArea->u.Flags.FilePointerNull == 0) {
01690 ControlArea->u.Flags.FilePointerNull = 1;
01691
01692
if (ControlArea->u.Flags.Image) {
01693
01694
if (
MiHydra ==
TRUE) {
01695
MiRemoveImageSectionObject (ControlArea->FilePointer,
01696 ControlArea);
01697 }
01698
else {
01699 ControlArea->FilePointer->SectionObjectPointer->ImageSectionObject =
NULL;
01700 }
01701 }
01702
else {
01703
01704
ASSERT (((
PCONTROL_AREA)(ControlArea->FilePointer->SectionObjectPointer->DataSectionObject)) !=
NULL);
01705 ControlArea->FilePointer->SectionObjectPointer->DataSectionObject =
NULL;
01706
01707 }
01708 }
01709
UNLOCK_PFN (OldIrql);
01710
01711
01712
01713
01714
01715
MiSegmentDelete (ControlArea->Segment);
01716
01717
return;
01718 }
01719
01720
NTSTATUS
01721 MmGetFileNameForSection (
01722 IN HANDLE Section,
01723 OUT PSTRING FileName
01724 )
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748 {
01749
01750
PSECTION SectionObject;
01751 POBJECT_NAME_INFORMATION FileNameInfo;
01752 ULONG whocares;
01753
NTSTATUS Status;
01754 ULONG Dereference;
01755
01756 Dereference =
TRUE;
01757
01758
#define xMAX_NAME 1024
01759
01760
if ( (ULONG_PTR)Section & 1 ) {
01761 SectionObject = (
PSECTION)((ULONG_PTR)Section & ~1);
01762 Dereference =
FALSE;
01763 }
else {
01764
Status =
ObReferenceObjectByHandle ( Section,
01765 0,
01766
MmSectionObjectType,
01767
KernelMode,
01768 (PVOID *)&SectionObject,
01769
NULL );
01770
01771
if (!
NT_SUCCESS(
Status)) {
01772
return Status;
01773 }
01774 }
01775
01776
if (SectionObject->u.Flags.Image == 0) {
01777
if ( Dereference )
01778
ObDereferenceObject (SectionObject);
01779
return STATUS_SECTION_NOT_IMAGE;
01780 }
01781
01782 FileNameInfo =
ExAllocatePoolWithTag (
PagedPool,
xMAX_NAME, ' mM');
01783
01784
if ( !FileNameInfo ) {
01785
if ( Dereference )
01786
ObDereferenceObject (SectionObject);
01787
return STATUS_NO_MEMORY;
01788 }
01789
01790
Status =
ObQueryNameString(
01791 SectionObject->Segment->ControlArea->FilePointer,
01792 FileNameInfo,
01793
xMAX_NAME,
01794 &whocares
01795 );
01796
01797
if ( Dereference )
01798
ObDereferenceObject (SectionObject);
01799
01800
if ( !
NT_SUCCESS(
Status) ) {
01801
ExFreePool(FileNameInfo);
01802
return Status;
01803 }
01804
01805
FileName->Length = 0;
01806
FileName->MaximumLength = (FileNameInfo->Name.Length/
sizeof(WCHAR)) + 1;
01807
FileName->Buffer =
ExAllocatePoolWithTag (
PagedPool,
01808
FileName->MaximumLength,
01809 ' mM');
01810
if ( !
FileName->Buffer ) {
01811
ExFreePool(FileNameInfo);
01812
return STATUS_NO_MEMORY;
01813 }
01814
RtlUnicodeStringToAnsiString((PANSI_STRING)
FileName,&FileNameInfo->Name,
FALSE);
01815
FileName->Buffer[
FileName->Length] =
'\0';
01816
ExFreePool(FileNameInfo);
01817
01818
return STATUS_SUCCESS;
01819 }
01820
01821
01822
VOID
01823 MiCheckControlArea (
01824 IN
PCONTROL_AREA ControlArea,
01825 IN
PEPROCESS CurrentProcess,
01826 IN KIRQL PreviousIrql
01827 )
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860 {
01861
PEVENT_COUNTER PurgeEvent;
01862 ULONG DeleteOnClose;
01863 ULONG DereferenceSegment;
01864
01865 PurgeEvent =
NULL;
01866 DeleteOnClose =
FALSE;
01867 DereferenceSegment =
FALSE;
01868
01869
MM_PFN_LOCK_ASSERT();
01870
if ((ControlArea->NumberOfMappedViews == 0) &&
01871 (ControlArea->NumberOfSectionReferences == 0)) {
01872
01873
ASSERT (ControlArea->NumberOfUserReferences == 0);
01874
01875
if (ControlArea->FilePointer != (
PFILE_OBJECT)
NULL) {
01876
01877
if (ControlArea->NumberOfPfnReferences == 0) {
01878
01879
01880
01881
01882
01883
01884 ControlArea->u.Flags.BeingDeleted = 1;
01885 DereferenceSegment =
TRUE;
01886
01887
ASSERT (ControlArea->u.Flags.FilePointerNull == 0);
01888 ControlArea->u.Flags.FilePointerNull = 1;
01889
01890
if (ControlArea->u.Flags.Image) {
01891
01892
if (
MiHydra ==
TRUE) {
01893
MiRemoveImageSectionObject (ControlArea->FilePointer, ControlArea);
01894 }
01895
else {
01896 ((
PCONTROL_AREA)(ControlArea->FilePointer->SectionObjectPointer->ImageSectionObject)) =
NULL;
01897 }
01898
01899 }
01900
else {
01901
01902
ASSERT (((
PCONTROL_AREA)(ControlArea->FilePointer->SectionObjectPointer->DataSectionObject)) !=
NULL);
01903 ((
PCONTROL_AREA)(ControlArea->FilePointer->SectionObjectPointer->DataSectionObject)) =
NULL;
01904
01905 }
01906 }
else {
01907
01908
01909
01910
01911
01912
01913
if (ControlArea->DereferenceList.Flink ==
NULL) {
01914 InsertTailList ( &
MmUnusedSegmentList,
01915 &ControlArea->DereferenceList);
01916
MI_UNUSED_SEGMENTS_INSERT_CHARGE (ControlArea);
01917 }
01918
01919
01920
01921
01922
01923
01924 DeleteOnClose = ControlArea->u.Flags.DeleteOnClose;
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935
if (ControlArea->u.Flags.GlobalMemory == 1) {
01936
ASSERT (ControlArea->u.Flags.Image == 1);
01937
01938 ControlArea->u.Flags.BeingPurged = 1;
01939 ControlArea->NumberOfMappedViews = 1;
01940
01941
MiPurgeImageSection (ControlArea, CurrentProcess);
01942
01943 ControlArea->u.Flags.BeingPurged = 0;
01944 ControlArea->NumberOfMappedViews -= 1;
01945
if ((ControlArea->NumberOfMappedViews == 0) &&
01946 (ControlArea->NumberOfSectionReferences == 0) &&
01947 (ControlArea->NumberOfPfnReferences == 0)) {
01948
01949 ControlArea->u.Flags.BeingDeleted = 1;
01950 DereferenceSegment =
TRUE;
01951 ControlArea->u.Flags.FilePointerNull = 1;
01952
01953
if (
MiHydra ==
TRUE) {
01954
MiRemoveImageSectionObject (ControlArea->FilePointer, ControlArea);
01955 }
01956
else {
01957 ((
PCONTROL_AREA)(ControlArea->FilePointer->SectionObjectPointer->ImageSectionObject)) =
NULL;
01958 }
01959
01960 }
else {
01961
01962 PurgeEvent = ControlArea->WaitingForDeletion;
01963 ControlArea->WaitingForDeletion =
NULL;
01964 }
01965 }
01966
01967
01968
01969
01970
01971
01972
01973
01974
if (DeleteOnClose && !DereferenceSegment) {
01975 ControlArea->NumberOfMappedViews = 1;
01976 ControlArea->u.Flags.BeingDeleted = 1;
01977 }
01978 }
01979
01980 }
else {
01981
01982
01983
01984
01985
01986
01987
01988 ControlArea->u.Flags.BeingDeleted = 1;
01989 DereferenceSegment =
TRUE;
01990 }
01991 }
01992
else if (ControlArea->WaitingForDeletion !=
NULL) {
01993 PurgeEvent = ControlArea->WaitingForDeletion;
01994 ControlArea->WaitingForDeletion =
NULL;
01995 }
01996
01997
UNLOCK_PFN (PreviousIrql);
01998
01999
if (DereferenceSegment || DeleteOnClose) {
02000
02001
02002
02003
02004
02005
02006
if (CurrentProcess) {
02007
UNLOCK_WS_UNSAFE (CurrentProcess);
02008 }
02009
02010
if (DereferenceSegment) {
02011
02012
02013
02014
02015
02016
MiSegmentDelete (ControlArea->Segment);
02017
02018 }
else {
02019
02020
02021
02022
02023
02024
MiCleanSection (ControlArea,
TRUE);
02025 }
02026
02027
ASSERT (PurgeEvent ==
NULL);
02028
02029
02030
02031
02032
02033
if (CurrentProcess) {
02034
LOCK_WS_UNSAFE (CurrentProcess);
02035 }
02036
02037 }
else {
02038
02039
02040
02041
02042
02043
02044
if (PurgeEvent !=
NULL) {
02045
KeSetEvent (&PurgeEvent->
Event, 0,
FALSE);
02046 }
02047
02048
if (
MmUnusedSegmentPagedPoolUsage >
MmMaxUnusedSegmentPagedPoolUsage ||
02049
MmUnusedSegmentNonPagedPoolUsage >
MmMaxUnusedSegmentNonPagedPoolUsage) {
02050
KeSetEvent (&
MmUnusedSegmentCleanup, 0,
FALSE);
02051 }
02052 }
02053
02054
return;
02055 }
02056
02057
02058
VOID
02059 MiCheckForControlAreaDeletion (
02060 IN
PCONTROL_AREA ControlArea
02061 )
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084
02085 {
02086 KIRQL OldIrql;
02087
02088
MM_PFN_LOCK_ASSERT();
02089
if ((ControlArea->NumberOfPfnReferences == 0) &&
02090 (ControlArea->NumberOfMappedViews == 0) &&
02091 (ControlArea->NumberOfSectionReferences == 0 )) {
02092
02093
02094
02095
02096
02097
02098
02099
02100
02101
02102 ControlArea->u.Flags.BeingDeleted = 1;
02103
ASSERT (ControlArea->u.Flags.FilePointerNull == 0);
02104 ControlArea->u.Flags.FilePointerNull = 1;
02105
02106
if (ControlArea->u.Flags.Image) {
02107
02108
if (
MiHydra ==
TRUE) {
02109
MiRemoveImageSectionObject (ControlArea->FilePointer,
02110 ControlArea);
02111 }
02112
else {
02113 ((
PCONTROL_AREA)(ControlArea->FilePointer->SectionObjectPointer->ImageSectionObject)) =
NULL;
02114 }
02115
02116 }
02117
else {
02118 ((
PCONTROL_AREA)(ControlArea->FilePointer->SectionObjectPointer->DataSectionObject)) =
02119
NULL;
02120 }
02121
02122 ExAcquireSpinLock (&
MmDereferenceSegmentHeader.
Lock, &OldIrql);
02123
02124
ASSERT (ControlArea->DereferenceList.Flink !=
NULL);
02125
02126
02127
02128
02129
02130
02131 RemoveEntryList (&ControlArea->DereferenceList);
02132
02133
MI_UNUSED_SEGMENTS_REMOVE_CHARGE (ControlArea);
02134
02135 InsertTailList (&
MmDereferenceSegmentHeader.
ListHead,
02136 &ControlArea->DereferenceList);
02137 ExReleaseSpinLock (&
MmDereferenceSegmentHeader.
Lock, OldIrql);
02138
02139
KeReleaseSemaphore (&
MmDereferenceSegmentHeader.
Semaphore,
02140 0
L,
02141 1
L,
02142
FALSE);
02143 }
02144
return;
02145 }
02146
02147
02148 BOOLEAN
02149 MiCheckControlAreaStatus (
02150 IN SECTION_CHECK_TYPE SectionCheckType,
02151 IN
PSECTION_OBJECT_POINTERS SectionObjectPointers,
02152 IN ULONG DelayClose,
02153 OUT
PCONTROL_AREA *ControlAreaOut,
02154 OUT PKIRQL PreviousIrql
02155 )
02156
02157
02158
02159
02160
02161
02162
02163
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195
02196
02197
02198
02199
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210 {
02211
PEVENT_COUNTER IoEvent;
02212
PEVENT_COUNTER SegmentEvent;
02213 ULONG DeallocateSegmentEvent =
TRUE;
02214
PCONTROL_AREA ControlArea;
02215 ULONG SectRef;
02216 KIRQL OldIrql;
02217
02218
02219
02220
02221
02222
02223
02224 *ControlAreaOut =
NULL;
02225
02226
02227
02228
02229
02230
02231
02232
02233
02234
02235
LOCK_PFN (OldIrql);
02236
02237 SegmentEvent =
MiGetEventCounter ();
02238
02239
while (SegmentEvent ==
NULL) {
02240
UNLOCK_PFN (OldIrql);
02241
KeDelayExecutionThread (
KernelMode,
FALSE, (PLARGE_INTEGER)&
MmShortTime);
02242
LOCK_PFN (OldIrql);
02243 SegmentEvent =
MiGetEventCounter ();
02244 }
02245
02246
if (SectionCheckType !=
CheckImageSection) {
02247 ControlArea = ((
PCONTROL_AREA)(SectionObjectPointers->DataSectionObject));
02248 }
else {
02249 ControlArea = ((
PCONTROL_AREA)(SectionObjectPointers->ImageSectionObject));
02250 }
02251
02252
if (ControlArea ==
NULL) {
02253
02254
if (SectionCheckType !=
CheckBothSection) {
02255
02256
02257
02258
02259
02260
MiFreeEventCounter (SegmentEvent,
TRUE);
02261
UNLOCK_PFN (OldIrql);
02262
return TRUE;
02263 }
else {
02264 ControlArea = ((
PCONTROL_AREA)(SectionObjectPointers->ImageSectionObject));
02265
if (ControlArea ==
NULL) {
02266
02267
02268
02269
02270
02271
MiFreeEventCounter (SegmentEvent,
TRUE);
02272
UNLOCK_PFN (OldIrql);
02273
return TRUE;
02274 }
02275 }
02276 }
02277
02278
02279
02280
02281
02282
02283
if (SectionCheckType !=
CheckUserDataSection) {
02284 SectRef = ControlArea->
NumberOfSectionReferences;
02285 }
else {
02286 SectRef = ControlArea->
NumberOfUserReferences;
02287 }
02288
02289
if ((SectRef != 0) ||
02290 (ControlArea->
NumberOfMappedViews != 0) ||
02291 (ControlArea->
u.Flags.BeingCreated)) {
02292
02293
02294
02295
02296
02297
02298
if (DelayClose) {
02299
02300
02301
02302
02303
02304
02305 ControlArea->
u.Flags.DeleteOnClose = 1;
02306 }
02307
02308
MiFreeEventCounter (SegmentEvent,
TRUE);
02309
UNLOCK_PFN (OldIrql);
02310
return FALSE;
02311 }
02312
02313
02314
02315
02316
02317
02318
02319
if (ControlArea->
u.Flags.BeingDeleted) {
02320
02321
02322
02323
02324
02325
02326
02327
if (ControlArea->
WaitingForDeletion ==
NULL) {
02328
02329
02330
02331
02332
02333 DeallocateSegmentEvent =
FALSE;
02334 ControlArea->
WaitingForDeletion = SegmentEvent;
02335 IoEvent = SegmentEvent;
02336 }
else {
02337 IoEvent = ControlArea->
WaitingForDeletion;
02338 IoEvent->
RefCount += 1;
02339 }
02340
02341
02342
02343
02344
02345
KeEnterCriticalRegion();
02346
UNLOCK_PFN_AND_THEN_WAIT(OldIrql);
02347
02348
KeWaitForSingleObject(&IoEvent->
Event,
02349
WrPageOut,
02350
KernelMode,
02351
FALSE,
02352 (PLARGE_INTEGER)
NULL);
02353
02354
LOCK_PFN (OldIrql);
02355
KeLeaveCriticalRegion();
02356
02357
MiFreeEventCounter (IoEvent,
TRUE);
02358
if (DeallocateSegmentEvent) {
02359
MiFreeEventCounter (SegmentEvent,
TRUE);
02360 }
02361
UNLOCK_PFN (OldIrql);
02362
return TRUE;
02363 }
02364
02365
02366
02367
02368
02369
MiFreeEventCounter (SegmentEvent,
FALSE);
02370 *ControlAreaOut = ControlArea;
02371 *PreviousIrql = OldIrql;
02372
return FALSE;
02373 }
02374
02375
02376
PEVENT_COUNTER
02377 MiGetEventCounter (
02378 )
02379
02380
02381
02382
02383
02384
02385
02386
02387
02388
02389
02390
02391
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402 {
02403 KIRQL OldIrql;
02404
PEVENT_COUNTER Support;
02405 PLIST_ENTRY NextEntry;
02406
02407
MM_PFN_LOCK_ASSERT();
02408
02409
if (
MmEventCountList.
Count == 0) {
02410
ASSERT (IsListEmpty(&
MmEventCountList.
ListHead));
02411 OldIrql =
APC_LEVEL;
02412
UNLOCK_PFN (OldIrql);
02413 Support =
ExAllocatePoolWithTag (
NonPagedPool,
02414
sizeof(
EVENT_COUNTER),
02415 'xEmM');
02416
if (Support ==
NULL) {
02417
LOCK_PFN (OldIrql);
02418
return NULL;
02419 }
02420
KeInitializeEvent (&Support->
Event, NotificationEvent,
FALSE);
02421
LOCK_PFN (OldIrql);
02422 }
else {
02423
ASSERT (!IsListEmpty(&
MmEventCountList.
ListHead));
02424
MmEventCountList.
Count -= 1;
02425 NextEntry = RemoveHeadList (&
MmEventCountList.
ListHead);
02426 Support = CONTAINING_RECORD (NextEntry,
02427
EVENT_COUNTER,
02428 ListEntry );
02429
02430
KeClearEvent (&Support->
Event);
02431 }
02432 Support->
RefCount = 1;
02433 Support->
ListEntry.Flink =
NULL;
02434
return Support;
02435 }
02436
02437
VOID
02438 MiFreeEventCounter (
02439 IN
PEVENT_COUNTER Support,
02440 IN ULONG Flush
02441 )
02442
02443
02444
02445
02446
02447
02448
02449
02450
02451
02452
02453
02454
02455
02456
02457
02458
02459
02460
02461
02462
02463
02464
02465
02466
02467 {
02468
02469
MM_PFN_LOCK_ASSERT();
02470
02471
ASSERT (Support->RefCount != 0);
02472
ASSERT (Support->ListEntry.Flink ==
NULL);
02473 Support->RefCount -= 1;
02474
if (Support->RefCount == 0) {
02475 InsertTailList (&
MmEventCountList.
ListHead,
02476 &Support->ListEntry);
02477
MmEventCountList.
Count += 1;
02478 }
02479
if ((Flush) && (
MmEventCountList.
Count > 4)) {
02480
MiFlushEventCounter();
02481 }
02482
return;
02483 }
02484
02485
02486
VOID
02487 MiFlushEventCounter (
02488 )
02489
02490
02491
02492
02493
02494
02495
02496
02497
02498
02499
02500
02501
02502
02503
02504
02505
02506
02507
02508
02509
02510
02511
02512
02513
02514
02515 {
02516 KIRQL OldIrql;
02517
PEVENT_COUNTER Support[10];
02518 ULONG i = 0;
02519 PLIST_ENTRY NextEntry;
02520
02521
MM_PFN_LOCK_ASSERT();
02522
02523
while ((
MmEventCountList.
Count > 4) && (i < 10)) {
02524 NextEntry = RemoveHeadList (&
MmEventCountList.
ListHead);
02525 Support[i] = CONTAINING_RECORD (NextEntry,
02526
EVENT_COUNTER,
02527 ListEntry );
02528 Support[i]->
ListEntry.Flink =
NULL;
02529 i += 1;
02530
MmEventCountList.
Count -= 1;
02531 }
02532
02533
if (i == 0) {
02534
return;
02535 }
02536
02537 OldIrql =
APC_LEVEL;
02538
UNLOCK_PFN (OldIrql);
02539
02540
do {
02541 i -= 1;
02542
ExFreePool(Support[i]);
02543 }
while (i > 0);
02544
02545
LOCK_PFN (OldIrql);
02546
02547
return;
02548 }
02549
02550
02551 BOOLEAN
02552 MmCanFileBeTruncated (
02553 IN
PSECTION_OBJECT_POINTERS SectionPointer,
02554 IN PLARGE_INTEGER NewFileSize
02555 )
02556
02557
02558
02559
02560
02561
02562
02563
02564
02565
02566
02567
02568
02569
02570
02571
02572
02573
02574
02575
02576
02577
02578
02579
02580
02581
02582
02583
02584
02585
02586
02587
02588
02589
02590 {
02591 LARGE_INTEGER LocalOffset;
02592 KIRQL OldIrql;
02593
02594
02595
02596
02597
02598
if (ARGUMENT_PRESENT(NewFileSize)) {
02599
02600 LocalOffset = *NewFileSize;
02601 NewFileSize = &LocalOffset;
02602 }
02603
02604
if (
MiCanFileBeTruncatedInternal( SectionPointer, NewFileSize,
FALSE, &OldIrql )) {
02605
02606
UNLOCK_PFN (OldIrql);
02607
return TRUE;
02608 }
02609
02610
return FALSE;
02611 }
02612
02613 ULONG
02614 MiCanFileBeTruncatedInternal (
02615 IN
PSECTION_OBJECT_POINTERS SectionPointer,
02616 IN PLARGE_INTEGER NewFileSize OPTIONAL,
02617 IN LOGICAL BlockNewViews,
02618 OUT PKIRQL PreviousIrql
02619 )
02620
02621
02622
02623
02624
02625
02626
02627
02628
02629
02630
02631
02632
02633
02634
02635
02636
02637
02638
02639
02640
02641
02642
02643
02644
02645
02646
02647
02648
02649
02650
02651
02652
02653
02654
02655
02656
02657
02658
02659
02660
02661
02662
02663 {
02664 KIRQL OldIrql;
02665 LARGE_INTEGER SegmentSize;
02666
PCONTROL_AREA ControlArea;
02667
PSUBSECTION Subsection;
02668
02669
if (!
MmFlushImageSection (SectionPointer,
MmFlushForWrite)) {
02670
return FALSE;
02671 }
02672
02673
LOCK_PFN (OldIrql);
02674
02675 ControlArea = (
PCONTROL_AREA)(SectionPointer->DataSectionObject);
02676
02677
if (ControlArea !=
NULL) {
02678
02679
if (ControlArea->
u.Flags.BeingCreated ||
02680 ControlArea->
u.Flags.BeingDeleted) {
02681
goto UnlockAndReturn;
02682 }
02683
02684
02685
02686
02687
02688
02689
if ((ControlArea->
NumberOfUserReferences != 0) &&
02690 ((BlockNewViews ==
FALSE) || (ControlArea->
NumberOfMappedViews != 0))) {
02691
02692
02693
02694
02695
02696
02697
if (!ARGUMENT_PRESENT(NewFileSize)) {
02698
goto UnlockAndReturn;
02699 }
02700
02701
02702
02703
02704
02705
if (ControlArea->
u.Flags.GlobalOnlyPerSession == 0) {
02706 Subsection = (
PSUBSECTION)(ControlArea + 1);
02707 }
02708
else {
02709 Subsection = (
PSUBSECTION)((
PLARGE_CONTROL_AREA)ControlArea + 1);
02710 }
02711
02712
while (Subsection->
NextSubsection !=
NULL) {
02713 Subsection = Subsection->
NextSubsection;
02714 }
02715
02716
ASSERT (Subsection->
ControlArea->
u.Flags.Image == 0);
02717
02718 SegmentSize =
MiEndingOffset(Subsection);
02719
02720
if ((UINT64)NewFileSize->QuadPart < (UINT64)SegmentSize.QuadPart) {
02721
goto UnlockAndReturn;
02722 }
02723
02724
02725
02726
02727
02728
02729
02730 SegmentSize.QuadPart +=
PAGE_SIZE - 1;
02731 SegmentSize.LowPart &= ~(
PAGE_SIZE - 1);
02732
if ((UINT64)NewFileSize->QuadPart < (UINT64)SegmentSize.QuadPart) {
02733 *NewFileSize = SegmentSize;
02734 }
02735 }
02736 }
02737
02738 *PreviousIrql = OldIrql;
02739
return TRUE;
02740
02741 UnlockAndReturn:
02742
UNLOCK_PFN (OldIrql);
02743
return FALSE;
02744 }
02745
02746
02747
VOID
02748 MiRemoveUnusedSegments (
02749 VOID
02750 )
02751
02752
02753
02754
02755
02756
02757
02758
02759
02760
02761
02762
02763
02764
02765
02766
02767
02768
02769
02770
02771
02772
02773 {
02774 KIRQL OldIrql;
02775 PLIST_ENTRY NextEntry;
02776
PCONTROL_AREA ControlArea;
02777
NTSTATUS Status;
02778 ULONG ConsecutiveFileLockFailures;
02779 ULONG ConsecutivePagingIOs;
02780
PSUBSECTION Subsection;
02781
PSUBSECTION LastSubsection;
02782
PMMPTE PointerPte;
02783
PMMPTE LastPte;
02784 IO_STATUS_BLOCK IoStatus;
02785 LOGICAL DirtyPagesOk;
02786
02787 ConsecutivePagingIOs = 0;
02788 ConsecutiveFileLockFailures = 0;
02789
02790
while ((
MmUnusedSegmentPagedPoolUsage > (
MmMaxUnusedSegmentPagedPoolUsage -
MmUnusedSegmentPagedPoolReduction)) ||
02791 (
MmUnusedSegmentNonPagedPoolUsage >
MmMaxUnusedSegmentNonPagedPoolUsage -
MmUnusedSegmentNonPagedPoolReduction) ||
02792 (
MmUnusedSegmentForceFree != 0)) {
02793
02794
02795
02796
02797
02798
02799
Status = STATUS_SUCCESS;
02800
02801
LOCK_PFN (OldIrql);
02802
02803
if (IsListEmpty(&
MmUnusedSegmentList)) {
02804
02805
02806
02807
02808
02809
MmUnusedSegmentForceFree = 0;
02810
ASSERT (
MmUnusedSegmentCount == 0);
02811
ASSERT (
MmUnusedSegmentPagedPoolUsage == 0);
02812
ASSERT (
MmUnusedSegmentNonPagedPoolUsage == 0);
02813
UNLOCK_PFN (OldIrql);
02814
break;
02815 }
02816
02817 NextEntry = RemoveHeadList(&
MmUnusedSegmentList);
02818
02819 ControlArea = CONTAINING_RECORD( NextEntry,
02820
CONTROL_AREA,
02821 DereferenceList );
02822
#if DBG
02823
if (MmDebug &
MM_DBG_SECTIONS) {
02824
DbgPrint(
"MM: cleaning segment %lx control %lx\n",
02825 ControlArea->
Segment, ControlArea);
02826 }
02827
#endif
02828
02829
MI_UNUSED_SEGMENTS_REMOVE_CHARGE (ControlArea);
02830
02831
if (
MmUnusedSegmentForceFree != 0) {
02832
MmUnusedSegmentForceFree -= 1;
02833 }
02834
02835
02836
02837
02838
02839
#if DBG
02840
if (ControlArea->
u.Flags.BeingDeleted == 0) {
02841
if (ControlArea->
u.Flags.Image) {
02842
ASSERT (((
PCONTROL_AREA)(ControlArea->
FilePointer->
SectionObjectPointer->
ImageSectionObject)) !=
NULL);
02843 }
else {
02844
ASSERT (((
PCONTROL_AREA)(ControlArea->
FilePointer->
SectionObjectPointer->
DataSectionObject)) !=
NULL);
02845 }
02846 }
02847
#endif //DBG
02848
02849
02850
02851
02852
02853
02854 ControlArea->
DereferenceList.Flink =
NULL;
02855
02856
if ((ControlArea->
NumberOfMappedViews == 0) &&
02857 (ControlArea->
NumberOfSectionReferences == 0) &&
02858 (ControlArea->
u.Flags.BeingDeleted == 0)) {
02859
02860
02861
02862
02863
02864
02865
02866
02867
02868
02869
02870
if (ControlArea->
ModifiedWriteCount > 0) {
02871
02872 InsertTailList ( &
MmUnusedSegmentList,
02873 &ControlArea->
DereferenceList);
02874
02875
MI_UNUSED_SEGMENTS_INSERT_CHARGE (ControlArea);
02876
02877
UNLOCK_PFN (OldIrql);
02878
02879 ConsecutivePagingIOs += 1;
02880
if (ConsecutivePagingIOs > 10) {
02881
KeDelayExecutionThread (
KernelMode,
FALSE, &
MmShortTime);
02882 ConsecutivePagingIOs = 0;
02883 }
02884
continue;
02885 }
02886 ConsecutivePagingIOs = 0;
02887
02888
02889
02890
02891
02892
02893
02894
02895
02896
02897
02898 ControlArea->
NumberOfMappedViews = 1;
02899 ControlArea->
u.Flags.Accessed = 0;
02900
02901
if (ControlArea->
u.Flags.Image == 0) {
02902
02903
UNLOCK_PFN (OldIrql);
02904
02905
if (ControlArea->
u.Flags.GlobalOnlyPerSession == 0) {
02906 Subsection = (
PSUBSECTION)(ControlArea + 1);
02907 }
02908
else {
02909 Subsection = (
PSUBSECTION)((
PLARGE_CONTROL_AREA)ControlArea + 1);
02910 }
02911
02912 PointerPte = &Subsection->
SubsectionBase[0];
02913 LastSubsection = Subsection;
02914
while (LastSubsection->
NextSubsection !=
NULL) {
02915 LastSubsection = LastSubsection->
NextSubsection;
02916 }
02917 LastPte = &LastSubsection->
SubsectionBase
02918 [LastSubsection->
PtesInSubsection - 1];
02919
02920
02921
02922
02923
02924
02925
02926
02927
02928
FsRtlAcquireFileForCcFlush (ControlArea->
FilePointer);
02929
02930
IoSetTopLevelIrp((
PIRP)
FSRTL_FSP_TOP_LEVEL_IRP);
02931
02932
Status =
MiFlushSectionInternal (PointerPte,
02933 LastPte,
02934 Subsection,
02935 LastSubsection,
02936
FALSE,
02937
FALSE,
02938 &IoStatus);
02939
02940
IoSetTopLevelIrp((
PIRP)
NULL);
02941
02942
02943
02944
02945
02946
FsRtlReleaseFileForCcFlush (ControlArea->
FilePointer);
02947
02948
LOCK_PFN (OldIrql);
02949 }
02950
02951
02952
02953
02954
02955
02956
02957
02958
02959
02960
02961
02962
02963
02964
02965
if (!((ControlArea->
NumberOfMappedViews == 1) &&
02966 (ControlArea->
u.Flags.Accessed == 0) &&
02967 (ControlArea->
NumberOfSectionReferences == 0) &&
02968 (ControlArea->
u.Flags.BeingDeleted == 0))) {
02969
02970 ControlArea->
NumberOfMappedViews -= 1;
02971
02972
02973
02974
02975
02976
02977
02978
02979
02980
02981
02982
02983
02984
02985
02986
02987
02988
02989
if ((ControlArea->
NumberOfMappedViews == 0) &&
02990 (ControlArea->
NumberOfSectionReferences == 0) &&
02991 (ControlArea->
u.Flags.BeingDeleted == 0)) {
02992
02993
ASSERT (ControlArea->
u.Flags.Accessed == 1);
02994
ASSERT(ControlArea->
DereferenceList.Flink ==
NULL);
02995
02996 InsertTailList ( &
MmUnusedSegmentList,
02997 &ControlArea->
DereferenceList);
02998
MI_UNUSED_SEGMENTS_INSERT_CHARGE (ControlArea);
02999 }
03000
03001
UNLOCK_PFN (OldIrql);
03002
continue;
03003 }
03004
03005
if (!
NT_SUCCESS(
Status)) {
03006
03007
03008
03009
03010
03011
03012
03013
03014
03015
03016
03017
03018
03019
if ((
Status == STATUS_FILE_LOCK_CONFLICT) ||
03020 (
Status ==
STATUS_MAPPED_WRITER_COLLISION) ||
03021 (ControlArea->
u.Flags.Networked == 0)) {
03022
03023
ASSERT(ControlArea->
DereferenceList.Flink ==
NULL);
03024
03025 ControlArea->
NumberOfMappedViews -= 1;
03026
03027
if (
Status == STATUS_FILE_LOCK_CONFLICT) {
03028 ConsecutiveFileLockFailures += 1;
03029 }
03030
else {
03031 ConsecutiveFileLockFailures = 0;
03032 }
03033
03034 InsertTailList ( &
MmUnusedSegmentList,
03035 &ControlArea->
DereferenceList);
03036
MI_UNUSED_SEGMENTS_INSERT_CHARGE (ControlArea);
03037
03038
UNLOCK_PFN (OldIrql);
03039
03040
03041
03042
03043
03044
03045
03046
03047
if (ConsecutiveFileLockFailures >= 10) {
03048
KeDelayExecutionThread (
KernelMode,
FALSE, &
MmShortTime);
03049 ConsecutiveFileLockFailures = 0;
03050 }
03051
continue;
03052 }
03053 DirtyPagesOk =
TRUE;
03054 }
03055
else {
03056 ConsecutiveFileLockFailures = 0;
03057 DirtyPagesOk =
FALSE;
03058 }
03059
03060 ControlArea->
u.Flags.BeingDeleted = 1;
03061
03062
03063
03064
03065
03066
03067 ControlArea->
u.Flags.NoModifiedWriting = 1;
03068
ASSERT (ControlArea->
u.Flags.FilePointerNull == 0);
03069
UNLOCK_PFN (OldIrql);
03070
03071
MiCleanSection (ControlArea, DirtyPagesOk);
03072
03073 }
else {
03074
03075
03076
03077
03078
03079
03080
UNLOCK_PFN (OldIrql);
03081 ConsecutivePagingIOs = 0;
03082 }
03083
03084 }
03085 }