00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
#include "mi.h"
00023
00024 typedef enum _MODIFIED_WRITER_OBJECT {
00025
NormalCase,
00026
MappedPagesNeedWriting,
00027
ModifiedWriterMaximumObject
00028 }
MODIFIED_WRITER_OBJECT;
00029
00030 typedef struct _MMWORK_CONTEXT {
00031 LARGE_INTEGER
Size;
00032 NTSTATUS Status;
00033 KEVENT Event;
00034 }
MMWORK_CONTEXT, *
PMMWORK_CONTEXT;
00035
00036 typedef struct _MM_WRITE_CLUSTER {
00037 ULONG
Count;
00038 ULONG
StartIndex;
00039 ULONG
Cluster[2 * (
MM_MAXIMUM_DISK_IO_SIZE /
PAGE_SIZE) + 1];
00040 }
MM_WRITE_CLUSTER, *
PMM_WRITE_CLUSTER;
00041
00042 ULONG
MmWriteAllModifiedPages;
00043 LOGICAL
MiFirstPageFileCreatedAndReady =
FALSE;
00044
00045 #define ONEMB_IN_PAGES ((1024 * 1024) / PAGE_SIZE)
00046
00047
NTSTATUS
00048
MiCheckForCrashDump (
00049
PFILE_OBJECT File,
00050 IN ULONG FileNumber
00051 );
00052
00053
VOID
00054
MiCrashDumpWorker (
00055 IN PVOID Context
00056 );
00057
00058
VOID
00059
MiClusterWritePages (
00060 IN
PMMPFN Pfn1,
00061 IN PFN_NUMBER PageFrameIndex,
00062 IN PMM_WRITE_CLUSTER WriteCluster,
00063 IN ULONG Size
00064 );
00065
00066
VOID
00067
MiExtendPagingFileMaximum (
00068 IN ULONG PageFileNumber,
00069 IN PRTL_BITMAP NewBitmap
00070 );
00071
00072
#ifdef ALLOC_PRAGMA
00073
#pragma alloc_text(PAGE,NtCreatePagingFile)
00074
#pragma alloc_text(PAGE,MmGetPageFileInformation)
00075
#pragma alloc_text(PAGE,MiModifiedPageWriter)
00076
#pragma alloc_text(PAGE,MiCheckForCrashDump)
00077
#pragma alloc_text(PAGE,MmGetCrashDumpInformation)
00078
#pragma alloc_text(PAGE,MiCrashDumpWorker)
00079
#pragma alloc_text(PAGELK,MiFlushAllPages)
00080
#endif
00081
00082
00083 PSECTION MmCrashDumpSection;
00084
00085 extern POBJECT_TYPE IoFileObjectType;
00086 extern HANDLE
PspInitialSystemProcessHandle;
00087
00088 LIST_ENTRY
MmMappedPageWriterList;
00089
00090 KEVENT MmMappedPageWriterEvent;
00091
00092 KEVENT MmMappedFileIoComplete;
00093
00094 ULONG
MmSystemShutdown;
00095
00096 SIZE_T
MmOverCommit2;
00097
00098 SIZE_T
MmPageFileFullExtendPages;
00099
00100 ULONG
MmPageFileFullExtendCount;
00101
00102 #define MI_PAGEFILE_FULL_CHARGE 100
00103
00104 SIZE_T
MiPageFileFullCharge;
00105
00106 LOGICAL
MmPageFileFullPopupShown =
FALSE;
00107
00108 ULONG
MmModNoWriteInsert;
00109
00110 BOOLEAN
MmSystemPageFileLocated;
00111
00112
NTSTATUS
00113
MiCheckPageFileMapping (
00114 IN
PFILE_OBJECT File
00115 );
00116
00117
VOID
00118
MiInsertPageFileInList (
00119 VOID
00120 );
00121
00122
VOID
00123
MiGatherMappedPages (
00124 IN
PMMPFN Pfn1,
00125 IN PFN_NUMBER PageFrameIndex
00126 );
00127
00128
VOID
00129
MiGatherPagefilePages (
00130 IN
PMMPFN Pfn1,
00131 IN PFN_NUMBER PageFrameIndex
00132 );
00133
00134
VOID
00135
MiPageFileFull (
00136 VOID
00137 );
00138
00139 LOGICAL
00140
MiCauseOverCommitPopup(
00141 IN SIZE_T NumberOfPages,
00142 IN ULONG Extension
00143 );
00144
00145
#if DBG
00146
ULONG_PTR
MmPagingFileDebug[8192];
00147
#endif
00148
00149 extern PFN_NUMBER
MmMoreThanEnoughFreePages;
00150
00151 #define MINIMUM_PAGE_FILE_SIZE ((ULONG)(256*PAGE_SIZE))
00152
00153
VOID
00154
MiModifiedPageWriterWorker (
00155 VOID
00156 );
00157
00158 SIZE_T
00159
MiAttemptPageFileExtension (
00160 IN ULONG PageFileNumber,
00161 IN SIZE_T ExtendSize,
00162 IN SIZE_T Maximum
00163 );
00164
00165
NTSTATUS
00166 MiCheckPageFilePath (
00167
PFILE_OBJECT FileObject
00168 )
00169 {
00170
PIRP irp;
00171
NTSTATUS status;
00172
PDEVICE_OBJECT deviceObject;
00173
KEVENT event;
00174
PIO_STACK_LOCATION irpSp;
00175 IO_STATUS_BLOCK localIoStatus;
00176
00177
PAGED_CODE();
00178
00179
00180
00181
00182
00183
00184
00185
ObReferenceObject( FileObject );
00186
00187
00188
00189
00190
00191
KeInitializeEvent( &event, SynchronizationEvent,
FALSE );
00192
00193
00194
00195
00196
00197 deviceObject =
IoGetRelatedDeviceObject( FileObject );
00198
00199
00200
00201
00202
00203 irp =
IoAllocateIrp( deviceObject->
StackSize,
FALSE );
00204
ASSERT( irp !=
NULL );
00205
00206
if (irp ==
NULL) {
00207
00208
00209
00210
00211
00212
return STATUS_NO_MEMORY;
00213 }
00214
00215 irp->
Tail.Overlay.OriginalFileObject = FileObject;
00216 irp->
Tail.Overlay.Thread =
PsGetCurrentThread();
00217 irp->
RequestorMode =
KernelMode;
00218
00219
00220
00221
00222
00223 irp->
UserEvent = &event;
00224 irp->
Flags =
IRP_SYNCHRONOUS_API;
00225 irp->
UserIosb = &localIoStatus;
00226 irp->
Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE)
NULL;
00227
00228
00229
00230
00231
00232
00233 irpSp =
IoGetNextIrpStackLocation( irp );
00234 irpSp->
MajorFunction =
IRP_MJ_PNP;
00235 irpSp->
MinorFunction =
IRP_MN_DEVICE_USAGE_NOTIFICATION;
00236 irpSp->
FileObject = FileObject;
00237 irp->
IoStatus.Status = STATUS_NOT_SUPPORTED;
00238 irp->
AssociatedIrp.SystemBuffer =
NULL;
00239
00240
00241 irpSp->
Parameters.UsageNotification.InPath =
TRUE;
00242 irpSp->
Parameters.UsageNotification.Type =
DeviceUsageTypePaging;
00243
00244
00245
00246
00247
00248
IoQueueThreadIrp( irp );
00249
00250
00251
00252
00253
00254 status =
IoCallDriver( deviceObject, irp );
00255
00256
00257
00258
00259
00260
00261
if (status == STATUS_PENDING) {
00262 (
VOID)
KeWaitForSingleObject( &event,
00263
Executive,
00264
KernelMode,
00265
FALSE,
00266 (PLARGE_INTEGER)
NULL );
00267 status = localIoStatus.Status;
00268 }
00269
00270
return status;
00271 }
00272
00273
00274
VOID
00275 MiReleaseModifiedWriter (
00276 VOID
00277 )
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288 {
00289 KIRQL OldIrql;
00290
LOCK_PFN (OldIrql);
00291
MiFirstPageFileCreatedAndReady =
TRUE;
00292
UNLOCK_PFN (OldIrql);
00293 }
00294
00295
00296
NTSTATUS
00297 NtCreatePagingFile (
00298 IN PUNICODE_STRING PageFileName,
00299 IN PLARGE_INTEGER MinimumSize,
00300 IN PLARGE_INTEGER MaximumSize,
00301 IN ULONG Priority OPTIONAL
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
PFILE_OBJECT File;
00337
NTSTATUS Status;
00338 OBJECT_ATTRIBUTES PagingFileAttributes;
00339 HANDLE FileHandle;
00340 IO_STATUS_BLOCK IoStatus;
00341 UNICODE_STRING CapturedName;
00342 PWSTR CapturedBuffer;
00343 LARGE_INTEGER CapturedMaximumSize;
00344 LARGE_INTEGER CapturedMinimumSize;
00345 LARGE_INTEGER SpecifiedSize;
00346 FILE_END_OF_FILE_INFORMATION EndOfFileInformation;
00347
KPROCESSOR_MODE PreviousMode;
00348 BOOLEAN Attached =
FALSE;
00349 BOOLEAN HasPrivilege;
00350 HANDLE SystemProcess;
00351 FILE_FS_DEVICE_INFORMATION FileDeviceInfo;
00352 ULONG ReturnedLength;
00353 ULONG FinalStatus;
00354 ULONG PageFileNumber;
00355 ULONG NewMaxSizeInPages;
00356 ULONG NewMinSizeInPages;
00357
PMMPAGING_FILE FoundExisting;
00358 PRTL_BITMAP NewBitmap;
00359 PRTL_BITMAP OldBitmap;
00360
PDEVICE_OBJECT deviceObject;
00361
MMPAGE_FILE_EXPANSION PageExtend;
00362
00363 DBG_UNREFERENCED_PARAMETER (Priority);
00364
00365
PAGED_CODE();
00366
00367 CapturedBuffer =
NULL;
00368
00369
if (
MmNumberOfPagingFiles ==
MAX_PAGE_FILES) {
00370
00371
00372
00373
00374
00375
Status = STATUS_TOO_MANY_PAGING_FILES;
00376
goto ErrorReturn0;
00377 }
00378
00379 PreviousMode = KeGetPreviousMode();
00380
00381
try {
00382
00383
if (PreviousMode !=
KernelMode) {
00384
00385
00386
00387
00388
00389
00390 HasPrivilege =
SeSinglePrivilegeCheck (
SeCreatePagefilePrivilege,
00391 PreviousMode
00392 );
00393
00394
if (!HasPrivilege) {
00395
00396
Status = STATUS_PRIVILEGE_NOT_HELD;
00397
goto ErrorReturn0;
00398 }
00399
00400
00401
00402
00403
00404
ProbeForRead( PageFileName,
sizeof(*PageFileName),
sizeof(UCHAR));
00405
ProbeForRead( MaximumSize,
sizeof(LARGE_INTEGER), 4);
00406
ProbeForRead( MinimumSize,
sizeof(LARGE_INTEGER), 4);
00407 }
00408
00409
00410
00411
00412
00413 CapturedMinimumSize = *MinimumSize;
00414
00415
#if defined (_WIN64) || defined (_X86PAE_)
00416
if (CapturedMinimumSize.QuadPart <
MINIMUM_PAGE_FILE_SIZE) {
00417
Status = STATUS_INVALID_PARAMETER_2;
00418
goto ErrorReturn0;
00419 }
00420
00421 SpecifiedSize.QuadPart = (
ROUND_TO_PAGES (CapturedMinimumSize.QuadPart)) >>
PAGE_SHIFT;
00422
00423
if (SpecifiedSize.HighPart != 0) {
00424
Status = STATUS_INVALID_PARAMETER_2;
00425
goto ErrorReturn0;
00426 }
00427
#else
00428
if ((CapturedMinimumSize.HighPart != 0) ||
00429 (CapturedMinimumSize.LowPart <
MINIMUM_PAGE_FILE_SIZE)) {
00430
Status = STATUS_INVALID_PARAMETER_2;
00431
goto ErrorReturn0;
00432 }
00433
#endif
00434
00435 CapturedMaximumSize = *MaximumSize;
00436
00437
#if defined (_WIN64) || defined (_X86PAE_)
00438
SpecifiedSize.QuadPart = (
ROUND_TO_PAGES (CapturedMaximumSize.QuadPart)) >>
PAGE_SHIFT;
00439
00440
if (SpecifiedSize.HighPart != 0) {
00441
Status = STATUS_INVALID_PARAMETER_3;
00442
goto ErrorReturn0;
00443 }
00444
#else
00445
if (CapturedMaximumSize.HighPart != 0) {
00446
Status = STATUS_INVALID_PARAMETER_3;
00447
goto ErrorReturn0;
00448 }
00449
#endif
00450
00451
if (CapturedMinimumSize.QuadPart > CapturedMaximumSize.QuadPart) {
00452
Status = STATUS_INVALID_PARAMETER_3;
00453
goto ErrorReturn0;
00454 }
00455
00456 CapturedName = *PageFileName;
00457 CapturedName.MaximumLength = CapturedName.Length;
00458
00459
if ((CapturedName.Length == 0) ||
00460 (CapturedName.Length > MAXIMUM_FILENAME_LENGTH )) {
00461
Status = STATUS_OBJECT_NAME_INVALID;
00462
goto ErrorReturn0;
00463 }
00464
00465
if (PreviousMode !=
KernelMode) {
00466
ProbeForRead (CapturedName.Buffer,
00467 CapturedName.Length,
00468
sizeof( UCHAR ));
00469 }
00470
00471 CapturedBuffer =
ExAllocatePoolWithTag (
PagedPool,
00472 (ULONG)CapturedName.Length,
00473 ' mM');
00474
00475
if (CapturedBuffer ==
NULL) {
00476
Status = STATUS_INSUFFICIENT_RESOURCES;
00477
goto ErrorReturn0;
00478 }
00479
00480
00481
00482
00483
00484 RtlMoveMemory (CapturedBuffer,
00485 CapturedName.Buffer,
00486 CapturedName.Length);
00487
00488
00489
00490
00491
00492 CapturedName.Buffer = CapturedBuffer;
00493
00494 } except (
ExSystemExceptionFilter()) {
00495
00496
00497
00498
00499
00500
00501
00502
if (CapturedBuffer !=
NULL) {
00503
ExFreePool (CapturedBuffer);
00504 }
00505
00506
Status = GetExceptionCode();
00507
goto ErrorReturn0;
00508 }
00509
00510
00511
00512
00513
00514 InitializeObjectAttributes( &PagingFileAttributes,
00515 &CapturedName,
00516 OBJ_CASE_INSENSITIVE,
00517
NULL,
00518
NULL );
00519
00520
#if defined (_WIN64) || defined (_X86PAE_)
00521
EndOfFileInformation.EndOfFile.QuadPart =
00522
ROUND_TO_PAGES (CapturedMinimumSize.QuadPart);
00523
#else
00524
EndOfFileInformation.EndOfFile.HighPart = 0;
00525
#endif
00526
EndOfFileInformation.EndOfFile.LowPart = (ULONG)
00527
ROUND_TO_PAGES (CapturedMinimumSize.LowPart);
00528
00529
Status =
IoCreateFile( &FileHandle,
00530 FILE_READ_DATA | FILE_WRITE_DATA | SYNCHRONIZE,
00531 &PagingFileAttributes,
00532 &IoStatus,
00533 &CapturedMinimumSize,
00534 FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM,
00535 FILE_SHARE_WRITE,
00536 FILE_SUPERSEDE,
00537 FILE_NO_INTERMEDIATE_BUFFERING | FILE_NO_COMPRESSION,
00538 (PVOID)
NULL,
00539 0
L,
00540
CreateFileTypeNone,
00541 (PVOID)
NULL,
00542
IO_OPEN_PAGING_FILE |
IO_NO_PARAMETER_CHECKING );
00543
00544
if (!
NT_SUCCESS(
Status)) {
00545
00546
00547
00548
00549
00550
00551
Status =
IoCreateFile( &FileHandle,
00552 FILE_WRITE_DATA | SYNCHRONIZE,
00553 &PagingFileAttributes,
00554 &IoStatus,
00555 &CapturedMinimumSize,
00556 FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM,
00557 FILE_SHARE_READ | FILE_SHARE_WRITE,
00558 FILE_OPEN,
00559 FILE_NO_INTERMEDIATE_BUFFERING | FILE_NO_COMPRESSION,
00560 (PVOID)
NULL,
00561 0
L,
00562
CreateFileTypeNone,
00563 (PVOID)
NULL,
00564
IO_OPEN_PAGING_FILE |
IO_NO_PARAMETER_CHECKING );
00565
00566
if (!
NT_SUCCESS(
Status)) {
00567
00568
#if DBG
00569
if (
Status != STATUS_DISK_FULL) {
00570
DbgPrint(
"MM MODWRITE: unable to open paging file %wZ - status = %X \n", &CapturedName,
Status);
00571 }
00572
#endif
00573
00574
goto ErrorReturn1;
00575 }
00576
00577
Status =
ObReferenceObjectByHandle ( FileHandle,
00578 FILE_READ_DATA | FILE_WRITE_DATA,
00579
IoFileObjectType,
00580
KernelMode,
00581 (PVOID *)&
File,
00582
NULL );
00583
00584
if (!
NT_SUCCESS(
Status)) {
00585
goto ErrorReturn2;
00586 }
00587
00588 FoundExisting =
NULL;
00589
00590 ExAcquireFastMutex (&
MmPageFileCreationLock);
00591
00592
for (PageFileNumber = 0; PageFileNumber <
MmNumberOfPagingFiles; PageFileNumber += 1) {
00593
if (
MmPagingFile[PageFileNumber]->
File->
SectionObjectPointer ==
File->SectionObjectPointer) {
00594 FoundExisting =
MmPagingFile[PageFileNumber];
00595
break;
00596 }
00597 }
00598
00599
if (FoundExisting ==
NULL) {
00600
Status = STATUS_NOT_FOUND;
00601
goto ErrorReturn4;
00602 }
00603
00604
00605
00606
00607
00608
00609 NewMaxSizeInPages = (ULONG)(CapturedMaximumSize.QuadPart >>
PAGE_SHIFT);
00610 NewMinSizeInPages = (ULONG)(CapturedMinimumSize.QuadPart >>
PAGE_SHIFT);
00611
00612
if (FoundExisting->
MinimumSize > NewMinSizeInPages) {
00613
Status = STATUS_INVALID_PARAMETER_2;
00614
goto ErrorReturn4;
00615 }
00616
00617
if (FoundExisting->
MaximumSize > NewMaxSizeInPages) {
00618
Status = STATUS_INVALID_PARAMETER_3;
00619
goto ErrorReturn4;
00620 }
00621
00622
if (NewMaxSizeInPages > FoundExisting->
MaximumSize) {
00623
00624
00625
00626
00627
00628
00629
00630
00631
if (
MmTotalCommitLimitMaximum + (NewMaxSizeInPages - FoundExisting->
MaximumSize) <=
MmTotalCommitLimitMaximum) {
00632
Status = STATUS_INVALID_PARAMETER_3;
00633
goto ErrorReturn4;
00634 }
00635
00636
00637
00638
00639
00640
MiCreateBitMap (&NewBitmap, NewMaxSizeInPages,
NonPagedPool);
00641
00642
if (NewBitmap ==
NULL) {
00643
Status = STATUS_INSUFFICIENT_RESOURCES;
00644
goto ErrorReturn4;
00645 }
00646
00647 OldBitmap = FoundExisting->
Bitmap;
00648
00649
MiExtendPagingFileMaximum (PageFileNumber, NewBitmap);
00650
00651
MiRemoveBitMap (&OldBitmap);
00652
00653
00654
00655
00656
00657
00658
00659
if (
MmTotalCommittedPages + 100 >
MmTotalCommitLimit) {
00660
if (
MiChargeCommitment (200,
NULL) ==
TRUE) {
00661
MiReturnCommitment (200);
00662 }
00663 }
00664 }
00665
00666
if (NewMinSizeInPages > FoundExisting->
MinimumSize) {
00667
00668
00669
00670
00671
00672
if (NewMinSizeInPages > FoundExisting->
Size) {
00673
00674
00675
00676
00677
00678
00679 PageExtend.
RequestedExpansionSize = NewMinSizeInPages - FoundExisting->
Size;
00680 PageExtend.
Segment =
NULL;
00681 PageExtend.
PageFileNumber = PageFileNumber;
00682
KeInitializeEvent (&PageExtend.
Event, NotificationEvent,
FALSE);
00683
00684
MiIssuePageExtendRequest (&PageExtend);
00685 }
00686
00687
00688
00689
00690
00691
00692
if (FoundExisting->
Size >= NewMinSizeInPages) {
00693
ASSERT (FoundExisting->
Size >= FoundExisting->
MinimumSize);
00694
ASSERT (NewMinSizeInPages >= FoundExisting->
MinimumSize);
00695 FoundExisting->
MinimumSize = NewMinSizeInPages;
00696 }
00697
else {
00698
00699
00700
00701
00702
00703
00704
00705
00706
Status = STATUS_INSUFFICIENT_RESOURCES;
00707 }
00708 }
00709
00710
goto ErrorReturn4;
00711 }
00712
00713
if (!
NT_SUCCESS(IoStatus.Status)) {
00714 KdPrint((
"MM MODWRITE: unable to open paging file %wZ - iosb %lx\n", &CapturedName, IoStatus.Status));
00715
Status = IoStatus.Status;
00716
goto ErrorReturn1;
00717 }
00718
00719
00720
00721
00722
00723
00724
00725
00726
if (
MmTotalCommitLimitMaximum + (CapturedMaximumSize.QuadPart >>
PAGE_SHIFT)
00727 <=
MmTotalCommitLimitMaximum) {
00728
Status = STATUS_INVALID_PARAMETER_3;
00729
goto ErrorReturn2;
00730 }
00731
00732
Status =
ZwSetInformationFile (FileHandle,
00733 &IoStatus,
00734 &EndOfFileInformation,
00735
sizeof(EndOfFileInformation),
00736 FileEndOfFileInformation);
00737
00738
if (!
NT_SUCCESS(
Status)) {
00739 KdPrint((
"MM MODWRITE: unable to set length of paging file %wZ status = %X \n",
00740 &CapturedName,
Status));
00741
goto ErrorReturn2;
00742 }
00743
00744
if (!
NT_SUCCESS(IoStatus.Status)) {
00745 KdPrint((
"MM MODWRITE: unable to set length of paging file %wZ - iosb %lx\n",
00746 &CapturedName, IoStatus.Status));
00747
Status = IoStatus.Status;
00748
goto ErrorReturn2;
00749 }
00750
00751
Status =
ObReferenceObjectByHandle ( FileHandle,
00752 FILE_READ_DATA | FILE_WRITE_DATA,
00753
IoFileObjectType,
00754
KernelMode,
00755 (PVOID *)&
File,
00756
NULL );
00757
00758
if (!
NT_SUCCESS(
Status)) {
00759 KdPrint((
"MM MODWRITE: Unable to reference paging file - %wZ\n",
00760 &CapturedName));
00761
goto ErrorReturn2;
00762 }
00763
00764
00765
00766
00767
00768
00769 deviceObject =
IoGetRelatedDeviceObject (
File);
00770
00771
if ((deviceObject->
DeviceType != FILE_DEVICE_DISK_FILE_SYSTEM) &&
00772 (deviceObject->
DeviceType != FILE_DEVICE_NETWORK_FILE_SYSTEM) &&
00773 (deviceObject->
DeviceType != FILE_DEVICE_DFS_VOLUME) &&
00774 (deviceObject->
DeviceType != FILE_DEVICE_DFS_FILE_SYSTEM)) {
00775 KdPrint((
"MM MODWRITE: Invalid paging file type - %x\n",
00776 deviceObject->
DeviceType));
00777
Status = STATUS_UNRECOGNIZED_VOLUME;
00778
goto ErrorReturn3;
00779 }
00780
00781
00782
00783
00784
00785
00786
Status =
MiCheckPageFileMapping (
File);
00787
if (!
NT_SUCCESS(
Status)) {
00788
goto ErrorReturn3;
00789 }
00790
00791
00792
00793
00794
00795
Status =
IoQueryVolumeInformation (
File,
00796 FileFsDeviceInformation,
00797
sizeof(FILE_FS_DEVICE_INFORMATION),
00798 &FileDeviceInfo,
00799 &ReturnedLength
00800 );
00801
00802
if (FILE_FLOPPY_DISKETTE & FileDeviceInfo.Characteristics) {
00803
Status = STATUS_FLOPPY_VOLUME;
00804
goto ErrorReturn3;
00805 }
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
Status =
MiCheckPageFilePath (
File);
00819
if (!
NT_SUCCESS(
Status)) {
00820 KdPrint((
"MiCheckPageFilePath(%wZ) FAILED: %x\n", &CapturedName,
Status ));
00821
00822 }
00823
00824
00825
00826
00827
00828 ExAcquireFastMutex (&
MmPageFileCreationLock);
00829
00830
MmPagingFile[
MmNumberOfPagingFiles] =
ExAllocatePoolWithTag (
NonPagedPool,
00831
sizeof(
MMPAGING_FILE),
00832 ' mM');
00833
if (
MmPagingFile[
MmNumberOfPagingFiles] ==
NULL) {
00834
00835
00836
00837
00838
00839
Status = STATUS_INSUFFICIENT_RESOURCES;
00840
goto ErrorReturn4;
00841 }
00842
00843 RtlZeroMemory (
MmPagingFile[
MmNumberOfPagingFiles],
sizeof(
MMPAGING_FILE));
00844
MmPagingFile[
MmNumberOfPagingFiles]->
File =
File;
00845
MmPagingFile[
MmNumberOfPagingFiles]->
Size = (ULONG)(
00846 CapturedMinimumSize.QuadPart
00847 >>
PAGE_SHIFT);
00848
00849
MmPagingFile[
MmNumberOfPagingFiles]->
MinimumSize =
00850
MmPagingFile[
MmNumberOfPagingFiles]->
Size;
00851
MmPagingFile[
MmNumberOfPagingFiles]->
FreeSpace =
00852
MmPagingFile[
MmNumberOfPagingFiles]->
Size - 1;
00853
00854
MmPagingFile[
MmNumberOfPagingFiles]->
MaximumSize = (PFN_NUMBER)(
00855 CapturedMaximumSize.QuadPart >>
00856
PAGE_SHIFT);
00857
00858
MmPagingFile[
MmNumberOfPagingFiles]->
PageFileNumber =
MmNumberOfPagingFiles;
00859
00860
00861
00862
00863
00864
MmPagingFile[
MmNumberOfPagingFiles]->
Entry[0] =
ExAllocatePoolWithTag (
NonPagedPool,
00865
sizeof(
MMMOD_WRITER_MDL_ENTRY) +
00866
MmModifiedWriteClusterSize *
00867
sizeof(PFN_NUMBER),
00868 ' mM');
00869
00870
if (
MmPagingFile[
MmNumberOfPagingFiles]->
Entry[0] ==
NULL) {
00871
00872
00873
00874
00875
00876
Status = STATUS_INSUFFICIENT_RESOURCES;
00877
goto ErrorReturn5;
00878 }
00879
00880 RtlZeroMemory (
MmPagingFile[
MmNumberOfPagingFiles]->Entry[0],
00881
sizeof(
MMMOD_WRITER_MDL_ENTRY));
00882
00883
MmPagingFile[
MmNumberOfPagingFiles]->
Entry[0]->
PagingListHead =
00884 &
MmPagingFileHeader;
00885
MmPagingFile[
MmNumberOfPagingFiles]->
Entry[0]->
PagingFile =
00886
MmPagingFile[
MmNumberOfPagingFiles];
00887
00888
MmPagingFile[
MmNumberOfPagingFiles]->
Entry[1] =
ExAllocatePoolWithTag (
NonPagedPool,
00889
sizeof(
MMMOD_WRITER_MDL_ENTRY) +
00890
MmModifiedWriteClusterSize *
00891
sizeof(PFN_NUMBER),
00892 ' mM');
00893
00894
if (
MmPagingFile[
MmNumberOfPagingFiles]->
Entry[1] ==
NULL) {
00895
00896
00897
00898
00899
00900
Status = STATUS_INSUFFICIENT_RESOURCES;
00901
goto ErrorReturn6;
00902 }
00903
00904 RtlZeroMemory (
MmPagingFile[
MmNumberOfPagingFiles]->Entry[1],
00905
sizeof(
MMMOD_WRITER_MDL_ENTRY));
00906
00907
MmPagingFile[
MmNumberOfPagingFiles]->
Entry[1]->
PagingListHead =
00908 &
MmPagingFileHeader;
00909
MmPagingFile[
MmNumberOfPagingFiles]->
Entry[1]->
PagingFile =
00910
MmPagingFile[
MmNumberOfPagingFiles];
00911
00912
MmPagingFile[
MmNumberOfPagingFiles]->
PageFileName = CapturedName;
00913
00914
MiCreateBitMap (&
MmPagingFile[
MmNumberOfPagingFiles]->Bitmap,
00915
MmPagingFile[
MmNumberOfPagingFiles]->MaximumSize,
00916
NonPagedPool);
00917
00918
if (
MmPagingFile[
MmNumberOfPagingFiles]->
Bitmap ==
NULL) {
00919
00920
00921
00922
00923
00924
Status = STATUS_INSUFFICIENT_RESOURCES;
00925
goto ErrorReturn7;
00926 }
00927
00928
RtlSetAllBits (
MmPagingFile[
MmNumberOfPagingFiles]->Bitmap);
00929
00930
00931
00932
00933
00934
00935
RtlClearBits (
MmPagingFile[
MmNumberOfPagingFiles]->Bitmap,
00936 1,
00937 (ULONG)(
MmPagingFile[
MmNumberOfPagingFiles]->
Size - 1));
00938
00939 PageFileNumber =
MmNumberOfPagingFiles;
00940
MiInsertPageFileInList ();
00941
00942 FinalStatus =
MiCheckForCrashDump (
File, PageFileNumber);
00943
00944
if (PageFileNumber == 0) {
00945
00946
00947
00948
00949
00950
00951
00952
MiReleaseModifiedWriter ();
00953 }
00954
00955 ExReleaseFastMutex (&
MmPageFileCreationLock);
00956
00957
00958
00959
00960
00961
00962
00963
00964
Status =
ObOpenObjectByPointer(
00965
PsInitialSystemProcess,
00966 0,
00967
NULL,
00968 0,
00969
PsProcessType,
00970
KernelMode,
00971 &SystemProcess
00972 );
00973
00974
if ( !
NT_SUCCESS(
Status)) {
00975 ZwClose (FileHandle);
00976
return FinalStatus;
00977 }
00978
00979
Status = ZwDuplicateObject(
00980 NtCurrentProcess(),
00981 FileHandle,
00982 SystemProcess,
00983
NULL,
00984 0,
00985 0,
00986 DUPLICATE_SAME_ATTRIBUTES | DUPLICATE_SAME_ACCESS
00987 );
00988
00989
ASSERT(
NT_SUCCESS(
Status));
00990
00991
if (!
MmSystemPageFileLocated) {
00992
MmSystemPageFileLocated =
IoPageFileCreated(FileHandle);
00993 }
00994
00995 ZwClose (SystemProcess);
00996 ZwClose (FileHandle);
00997
00998
return FinalStatus;
00999
01000
01001
01002
01003
01004 ErrorReturn7:
01005
ExFreePool (
MmPagingFile[
MmNumberOfPagingFiles]->Entry[0]);
01006
01007 ErrorReturn6:
01008
ExFreePool (
MmPagingFile[
MmNumberOfPagingFiles]->Entry[1]);
01009
01010 ErrorReturn5:
01011
ExFreePool (
MmPagingFile[
MmNumberOfPagingFiles]);
01012
01013 ErrorReturn4:
01014 ExReleaseFastMutex (&
MmPageFileCreationLock);
01015
01016 ErrorReturn3:
01017
ObDereferenceObject (
File);
01018
01019 ErrorReturn2:
01020 ZwClose (FileHandle);
01021
01022 ErrorReturn1:
01023
ExFreePool (CapturedBuffer);
01024
01025 ErrorReturn0:
01026
return Status;
01027 }
01028
01029
01030
VOID
01031 MiExtendPagingFileMaximum (
01032 IN ULONG PageFileNumber,
01033 IN PRTL_BITMAP NewBitmap
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 KIRQL OldIrql;
01060 PRTL_BITMAP OldBitmap;
01061
01062 OldBitmap =
MmPagingFile[PageFileNumber]->
Bitmap;
01063
01064
RtlSetAllBits (NewBitmap);
01065
01066
LOCK_PFN (OldIrql);
01067
01068
01069
01070
01071
01072 RtlCopyMemory (NewBitmap->Buffer,
01073 OldBitmap->Buffer,
01074 ((OldBitmap->SizeOfBitMap + 31) / 32) * sizeof (ULONG));
01075
01076
MmTotalCommitLimitMaximum += (NewBitmap->SizeOfBitMap - OldBitmap->SizeOfBitMap);
01077
01078
MmPagingFile[PageFileNumber]->
MaximumSize = NewBitmap->SizeOfBitMap;
01079
01080
MmPagingFile[PageFileNumber]->
Bitmap = NewBitmap;
01081
01082
01083
01084
01085
01086
if (!IsListEmpty (&
MmFreePagingSpaceLow)) {
01087
MiUpdateModifiedWriterMdls (PageFileNumber);
01088 }
01089
01090
UNLOCK_PFN (OldIrql);
01091 }
01092
01093
01094
NTSTATUS
01095 MiCheckForCrashDump (
01096
PFILE_OBJECT File,
01097 IN ULONG FileNumber
01098 )
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122 {
01123
PMDL Mdl;
01124 LARGE_INTEGER
Offset = {0,0};
01125 LARGE_INTEGER DumpSpaceUsed;
01126 PFN_NUMBER DumpSpaceUsedInPages;
01127 PULONG Block;
01128 IO_STATUS_BLOCK IoStatus;
01129
NTSTATUS Status;
01130 PFN_NUMBER j;
01131 PPFN_NUMBER Page;
01132
NTSTATUS FinalStatus;
01133
PMMPTE PointerPte;
01134
PMMPFN Pfn;
01135 PFN_NUMBER MdlHack[(
sizeof(
MDL)/
sizeof(PFN_NUMBER)) + 1];
01136
WORK_QUEUE_ITEM WorkItem;
01137
MMWORK_CONTEXT Context;
01138
01139 FinalStatus = STATUS_SUCCESS;
01140
01141 Mdl = (
PMDL)&MdlHack[0];
01142
MmCreateMdl( Mdl,
NULL,
PAGE_SIZE);
01143 Mdl->
MdlFlags |=
MDL_PAGES_LOCKED;
01144
01145 Page = (PPFN_NUMBER)(Mdl + 1);
01146 *Page =
MiGetPageForHeader ();
01147 Block =
MmGetSystemAddressForMdlSafe (Mdl,
HighPagePriority);
01148
01149
if (Block ==
NULL) {
01150
MiRemoveImageHeaderPage(*Page);
01151
return STATUS_INSUFFICIENT_RESOURCES;
01152 }
01153
01154
KeInitializeEvent (&Context.
Event, NotificationEvent,
FALSE);
01155
01156
Status =
IoPageRead (
File,
01157 Mdl,
01158 &
Offset,
01159 &Context.
Event,
01160 &IoStatus);
01161
01162
if (
Status == STATUS_PENDING) {
01163
KeWaitForSingleObject( &Context.
Event,
01164
WrPageIn,
01165
KernelMode,
01166
FALSE,
01167 (PLARGE_INTEGER)
NULL);
01168 }
01169
01170
KeClearEvent (&Context.
Event);
01171
01172 DumpSpaceUsed.LowPart = Block[DH_REQUIRED_DUMP_SPACE];
01173 DumpSpaceUsed.HighPart = Block[DH_REQUIRED_DUMP_SPACE + 1];
01174
01175 DumpSpaceUsedInPages = (PFN_NUMBER)(DumpSpaceUsed.QuadPart >>
PAGE_SHIFT);
01176
01177
if ((Block[0] == 'EGAP') &&
01178 (Block[1] == 'PMUD') &&
01179 (DumpSpaceUsedInPages <=
MmPagingFile[FileNumber]->
Size)) {
01180
01181
01182
01183
01184
01185
01186 Context.
Size.QuadPart = DumpSpaceUsed.QuadPart;
01187
01188
ExInitializeWorkItem(&WorkItem,
01189
MiCrashDumpWorker,
01190 (PVOID)&Context);
01191
01192
ExQueueWorkItem( &WorkItem,
DelayedWorkQueue );
01193
01194
KeWaitForSingleObject( &Context.Event,
01195
WrPageIn,
01196
KernelMode,
01197
FALSE,
01198 (PLARGE_INTEGER)
NULL);
01199
01200
KeClearEvent (&Context.Event);
01201
01202
if (!
NT_SUCCESS(Context.Status)) {
01203
goto Failed;
01204 }
01205
01206
01207
01208
01209
01210 PointerPte =
MmCrashDumpSection->Segment->PrototypePte;
01211
MI_WRITE_INVALID_PTE (PointerPte,
MmCrashDumpSection->Segment->SegmentPteTemplate);
01212
01213 Pfn =
MI_PFN_ELEMENT (*Page);
01214
#if PFN_CONSISTENCY
01215
MiSetModified (Pfn, 1);
01216
#else
01217
Pfn->
u3.e1.Modified = 1;
01218
#endif
01219
01220 PointerPte += 1;
01221
01222
for (j = 1; j < DumpSpaceUsedInPages; j += 1) {
01223
01224
MI_SET_PAGING_FILE_INFO (*PointerPte,
01225
MmCrashDumpSection->Segment->SegmentPteTemplate,
01226 FileNumber,
01227 j);
01228
01229
#if DBG
01230
if ((j < 8192) && (FileNumber == 0)) {
01231
ASSERT ((
MmPagingFileDebug[j] & 1) == 0);
01232
MmPagingFileDebug[j] = (((ULONG_PTR)PointerPte << 3) | 1);
01233 }
01234
#endif //DBG
01235
PointerPte += 1;
01236 }
01237
01238
01239
01240
01241
01242
01243
RtlSetBits (
MmPagingFile[FileNumber]->Bitmap,
01244 1,
01245 (ULONG)DumpSpaceUsedInPages - 1);
01246
01247
MmPagingFile[FileNumber]->
FreeSpace -= DumpSpaceUsedInPages;
01248
MmPagingFile[FileNumber]->
CurrentUsage += DumpSpaceUsedInPages;
01249 FinalStatus = STATUS_CRASH_DUMP;
01250
01251 Failed:
01252
01253
01254
01255
01256
01257
01258 Block[1] = 'EGAP';
01259 }
else {
01260
01261
01262
01263
01264
01265 RtlFillMemoryUlong (Block,
01266
PAGE_SIZE,
01267 'EGAP');
01268
01269
#if !defined(_WIN64)
01270
01271
01272
01273
01274
01275
01276
01277 *(PULONG_PTR)(&Block[4]) =
PsInitialSystemProcess->
Pcb.
DirectoryTableBase[0];
01278 *(PULONG *)(&Block[5]) = (PULONG)
MmPfnDatabase;
01279 *(PLIST_ENTRY *)(&Block[6]) = (PLIST_ENTRY)&
PsLoadedModuleList;
01280 *(PLIST_ENTRY *)(&Block[7]) = (PLIST_ENTRY)&
PsActiveProcessHead;
01281
#endif
01282
Block[8] =
01283
#ifdef _X86_
01284
IMAGE_FILE_MACHINE_I386;
01285
#endif //_X86_
01286
01287
#ifdef _ALPHA_
01288
IMAGE_FILE_MACHINE_ALPHA;
01289
#endif //_ALPHA_
01290
01291
#ifdef _IA64_
01292
IMAGE_FILE_MACHINE_IA64;
01293
#endif //_IA64_
01294
01295 ExAcquireFastMutex (&
MmDynamicMemoryMutex);
01296
01297 RtlCopyMemory (&Block[DH_PHYSICAL_MEMORY_BLOCK],
01298
MmPhysicalMemoryBlock,
01299 (
sizeof(
PHYSICAL_MEMORY_DESCRIPTOR) +
01300 (
sizeof(
PHYSICAL_MEMORY_RUN) *
01301 (
MmPhysicalMemoryBlock->
NumberOfRuns - 1))));
01302
01303 ExReleaseFastMutex (&
MmDynamicMemoryMutex);
01304 }
01305
01306
Status =
IoSynchronousPageWrite (
01307
File,
01308 Mdl,
01309 &
Offset,
01310 &Context.
Event,
01311 &IoStatus );
01312
01313
KeWaitForSingleObject (&Context.
Event,
01314
WrVirtualMemory,
01315
KernelMode,
01316
FALSE,
01317 (PLARGE_INTEGER)
NULL);
01318
01319
MmUnmapLockedPages (Mdl->
MappedSystemVa, Mdl);
01320
if (FinalStatus == STATUS_CRASH_DUMP) {
01321
01322
01323
01324
01325
01326
01327
MiUpdateImageHeaderPage (
MmCrashDumpSection->Segment->PrototypePte,
01328 *Page,
01329
MmCrashDumpSection->Segment->ControlArea);
01330 }
else {
01331
MiRemoveImageHeaderPage(*Page);
01332 }
01333
return FinalStatus;
01334 }
01335
01336
01337
VOID
01338 MiCrashDumpWorker (
01339 IN PVOID Context
01340 )
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362 {
01363
PMMWORK_CONTEXT Work;
01364 OBJECT_ATTRIBUTES
ObjectAttributes;
01365
01366
PAGED_CODE();
01367
01368 Work = (
PMMWORK_CONTEXT)Context;
01369
01370 InitializeObjectAttributes( &
ObjectAttributes,
01371
NULL,
01372 0,
01373
NULL,
01374
NULL );
01375
01376
01377 Work->
Status =
MmCreateSection ( &
MmCrashDumpSection,
01378 SECTION_MAP_READ,
01379 &
ObjectAttributes,
01380 &Work->
Size,
01381 PAGE_READONLY,
01382 SEC_COMMIT,
01383
NULL,
01384
NULL );
01385
01386
KeSetEvent (&Work->
Event, 0,
FALSE);
01387
return;
01388 }
01389
01390
01391
NTSTATUS
01392 MmGetCrashDumpInformation (
01393 IN PSYSTEM_CRASH_DUMP_INFORMATION CrashInfo
01394 )
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420 {
01421
NTSTATUS Status;
01422 HANDLE
Handle;
01423
01424
PAGED_CODE();
01425
01426
if (
MmCrashDumpSection ==
NULL) {
01427
Handle = 0;
01428
Status = STATUS_SUCCESS;
01429 }
else {
01430
Status =
ObInsertObject (
MmCrashDumpSection,
01431
NULL,
01432 SECTION_MAP_READ,
01433 0,
01434 (PVOID *)
NULL,
01435 &
Handle);
01436
if (
NT_SUCCESS(
Status)) {
01437
01438
01439
01440
01441
01442
MmCrashDumpSection =
NULL;
01443 }
01444 }
01445
01446 CrashInfo->CrashDumpSection =
Handle;
01447
return Status;
01448 }
01449
01450
01451
NTSTATUS
01452 MmGetCrashDumpStateInformation (
01453 IN PSYSTEM_CRASH_STATE_INFORMATION CrashInfo
01454 )
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476 {
01477
PAGED_CODE();
01478
01479 CrashInfo->ValidCrashDump = (
MmCrashDumpSection !=
NULL);
01480
return STATUS_SUCCESS;
01481 }
01482
01483
01484 SIZE_T
01485 MiAttemptPageFileExtension (
01486 IN ULONG PageFileNumber,
01487 IN SIZE_T ExtendSize,
01488 IN SIZE_T Maximum
01489 )
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515 {
01516
01517
NTSTATUS status;
01518 FILE_FS_SIZE_INFORMATION FileInfo;
01519 FILE_END_OF_FILE_INFORMATION EndOfFileInformation;
01520 KIRQL OldIrql;
01521 ULONG AllocSize;
01522 PFN_NUMBER AdditionalAllocation;
01523 ULONG ReturnedLength;
01524 PFN_NUMBER PagesAvailable;
01525 SIZE_T SizeToExtend;
01526 LARGE_INTEGER BytesAvailable;
01527
01528
01529
01530
01531
01532
if (
MmPagingFile[PageFileNumber]->
Size ==
01533
MmPagingFile[PageFileNumber]->
MaximumSize) {
01534
return 0;
01535 }
01536
01537
01538
01539
01540
01541 status =
IoQueryVolumeInformation (
MmPagingFile[PageFileNumber]->
File,
01542 FileFsSizeInformation,
01543
sizeof(FileInfo),
01544 &FileInfo,
01545 &ReturnedLength
01546 );
01547
01548
if (!
NT_SUCCESS (status)) {
01549
01550
01551
01552
01553
01554
01555
return 0;
01556 }
01557
01558
01559
01560
01561
01562 SizeToExtend = ExtendSize;
01563
if (ExtendSize <
MmPageFileExtension) {
01564 SizeToExtend =
MmPageFileExtension;
01565 }
01566
01567
01568
01569
01570
01571
if ((SizeToExtend +
MmPagingFile[PageFileNumber]->
Size) >
01572
MmPagingFile[PageFileNumber]->
MaximumSize) {
01573 SizeToExtend = (
MmPagingFile[PageFileNumber]->
MaximumSize -
01574
MmPagingFile[PageFileNumber]->
Size);
01575 }
01576
01577
if ((Maximum ==
FALSE) && (SizeToExtend < ExtendSize)) {
01578
01579
01580
01581
01582
01583
return 0;
01584 }
01585
01586
01587
01588
01589 AllocSize = FileInfo.SectorsPerAllocationUnit * FileInfo.BytesPerSector;
01590
01591 BytesAvailable =
RtlExtendedIntegerMultiply (
01592 FileInfo.AvailableAllocationUnits,
01593 AllocSize);
01594
01595
if ((UINT64)BytesAvailable.QuadPart > (UINT64)
MmMinimumFreeDiskSpace) {
01596
01597 BytesAvailable.QuadPart = BytesAvailable.QuadPart -
01598 (LONGLONG)
MmMinimumFreeDiskSpace;
01599
01600
if ((UINT64)BytesAvailable.QuadPart > (UINT64)(SizeToExtend <<
PAGE_SHIFT)) {
01601 BytesAvailable.QuadPart = (LONGLONG)(SizeToExtend <<
PAGE_SHIFT);
01602 }
01603
01604 PagesAvailable = (PFN_NUMBER)(BytesAvailable.QuadPart >>
PAGE_SHIFT);
01605
01606
if ((Maximum ==
FALSE) && (PagesAvailable < ExtendSize)) {
01607
01608
01609
01610
01611
01612
return 0;
01613 }
01614
01615 }
else {
01616
01617
01618
01619
01620
01621
return 0;
01622 }
01623
01624
#if defined (_WIN64) || defined (_X86PAE_)
01625
EndOfFileInformation.EndOfFile.QuadPart =
01626 ((ULONG64)
MmPagingFile[PageFileNumber]->
Size + PagesAvailable) *
PAGE_SIZE;
01627
#else
01628
EndOfFileInformation.EndOfFile.LowPart =
01629 (
MmPagingFile[PageFileNumber]->
Size + PagesAvailable) *
PAGE_SIZE;
01630
01631
01632
01633
01634
01635 EndOfFileInformation.EndOfFile.HighPart = 0;
01636
#endif
01637
01638
01639
01640
01641
01642
ASSERT (KeGetCurrentIrql() <
DISPATCH_LEVEL);
01643 status =
IoSetInformation (
MmPagingFile[PageFileNumber]->
File,
01644 FileEndOfFileInformation,
01645
sizeof(FILE_END_OF_FILE_INFORMATION),
01646 &EndOfFileInformation
01647 );
01648
01649
if (status != STATUS_SUCCESS) {
01650 KdPrint((
"MM MODWRITE: page file extension failed %lx %lx\n",status));
01651
return 0;
01652 }
01653
01654
01655
01656
01657
01658
01659
LOCK_PFN (OldIrql);
01660
01661
ASSERT (RtlCheckBit (
MmPagingFile[PageFileNumber]->Bitmap,
01662
MmPagingFile[PageFileNumber]->
Size) == 1);
01663
01664 AdditionalAllocation = PagesAvailable;
01665
01666
RtlClearBits (
MmPagingFile[PageFileNumber]->Bitmap,
01667 (ULONG)
MmPagingFile[PageFileNumber]->
Size,
01668 (ULONG)AdditionalAllocation );
01669
01670
MmPagingFile[PageFileNumber]->
Size += AdditionalAllocation;
01671
MmPagingFile[PageFileNumber]->
FreeSpace += AdditionalAllocation;
01672
01673
MiUpdateModifiedWriterMdls (PageFileNumber);
01674
01675
UNLOCK_PFN (OldIrql);
01676
01677
return AdditionalAllocation;
01678 }
01679
01680 SIZE_T
01681 MiExtendPagingFiles (
01682 IN
PMMPAGE_FILE_EXPANSION PageExpand
01683 )
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711 {
01712 SIZE_T DesiredQuota;
01713 ULONG PageFileNumber;
01714 SIZE_T ExtendedSize;
01715 SIZE_T ExtendSize;
01716 ULONG i;
01717 KIRQL OldIrql;
01718 LOGICAL LockHeld;
01719 LOGICAL RealExpansion;
01720
01721 RealExpansion =
TRUE;
01722 LockHeld =
FALSE;
01723 ExtendedSize = 0;
01724 DesiredQuota = PageExpand->RequestedExpansionSize;
01725 PageFileNumber = PageExpand->PageFileNumber;
01726
01727 PageExpand->ActualExpansion = 0;
01728
01729
ASSERT (PageFileNumber <
MmNumberOfPagingFiles || PageFileNumber ==
MI_EXTEND_ANY_PAGEFILE);
01730
01731
if (
MmNumberOfPagingFiles == 0) {
01732
goto alldone;
01733 }
01734
01735
if (PageFileNumber <
MmNumberOfPagingFiles) {
01736 i = PageFileNumber;
01737 ExtendedSize =
MmPagingFile[i]->
MaximumSize -
MmPagingFile[i]->
Size;
01738
if (ExtendedSize < DesiredQuota) {
01739 ExtendedSize = 0;
01740 }
01741
else {
01742 ExtendedSize =
MiAttemptPageFileExtension (i, DesiredQuota,
FALSE);
01743 }
01744
goto alldone;
01745 }
01746
01747 LockHeld =
TRUE;
01748 ExAcquireSpinLock (&
MmChargeCommitmentLock, &OldIrql);
01749
01750
01751
01752
01753
01754
01755 ExtendSize = DesiredQuota +
MmTotalCommittedPages;
01756
01757
if (
MmTotalCommitLimit >= ExtendSize) {
01758 ExtendedSize = 1;
01759 RealExpansion =
FALSE;
01760
goto alldone;
01761 }
01762
01763
01764
01765
01766
01767 ExtendSize -=
MmTotalCommitLimit;
01768
01769 ExReleaseSpinLock (&
MmChargeCommitmentLock, OldIrql);
01770 LockHeld =
FALSE;
01771
01772
01773
01774
01775
01776 i = 0;
01777
01778
do {
01779 ExtendedSize +=
MmPagingFile[i]->
MaximumSize -
MmPagingFile[i]->
Size;
01780 i += 1;
01781 }
while (i <
MmNumberOfPagingFiles);
01782
01783
if (ExtendedSize < ExtendSize) {
01784 ExtendedSize = 0;
01785
goto alldone;
01786 }
01787
01788
01789
01790
01791
01792 i = 0;
01793
do {
01794 ExtendedSize =
MiAttemptPageFileExtension (i, ExtendSize,
FALSE);
01795
if (ExtendedSize != 0) {
01796
goto alldone;
01797 }
01798 i += 1;
01799 }
while (i <
MmNumberOfPagingFiles);
01800
01801
ASSERT (ExtendedSize == 0);
01802
01803
if (
MmNumberOfPagingFiles == 1) {
01804
01805
01806
01807
01808
01809
01810
goto alldone;
01811 }
01812
01813
01814
01815
01816
01817 i = 0;
01818
do {
01819
ASSERT (ExtendSize > ExtendedSize);
01820 ExtendedSize +=
MiAttemptPageFileExtension (i,
01821 ExtendSize - ExtendedSize,
01822
TRUE);
01823
if (ExtendedSize >= ExtendSize) {
01824
goto alldone;
01825 }
01826 i += 1;
01827 }
while (i <
MmNumberOfPagingFiles);
01828
01829
01830
01831
01832
01833 ExtendedSize = 0;
01834
01835 alldone:
01836
01837
if (LockHeld ==
FALSE) {
01838 ExAcquireSpinLock (&
MmChargeCommitmentLock, &OldIrql);
01839 }
01840
01841
if ((ExtendedSize != 0) && (RealExpansion ==
TRUE)) {
01842
MmTotalCommitLimit += ExtendedSize;
01843 }
01844
01845
01846
01847
01848
01849
if (
MmPageFileFullExtendPages) {
01850
ASSERT (
MmTotalCommittedPages >=
MmPageFileFullExtendPages);
01851
MmTotalCommittedPages -=
MmPageFileFullExtendPages;
01852
MmPageFileFullExtendPages = 0;
01853 }
01854
01855 PageExpand->InProgress =
FALSE;
01856 PageExpand->ActualExpansion = ExtendedSize;
01857
01858 ExReleaseSpinLock (&
MmChargeCommitmentLock, OldIrql);
01859
01860
return ExtendedSize;
01861 }
01862
01863
VOID
01864 MiContractPagingFiles (
01865 VOID
01866 )
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887 {
01888 BOOLEAN Reduce;
01889
PMMPAGE_FILE_EXPANSION PageReduce;
01890 KIRQL OldIrql;
01891 ULONG i;
01892
01893 Reduce =
FALSE;
01894
01895 ExAcquireSpinLock (&
MmChargeCommitmentLock, &OldIrql);
01896
01897
if ((
MmTotalCommitLimit -
MmMinimumPageFileReduction) >
01898
MmTotalCommittedPages) {
01899
01900
for (i = 0;i <
MmNumberOfPagingFiles; i += 1) {
01901
if (
MmPagingFile[i]->
Size !=
MmPagingFile[i]->
MinimumSize) {
01902
if (
MmPagingFile[i]->
FreeSpace >
MmMinimumPageFileReduction) {
01903 Reduce =
TRUE;
01904
break;
01905 }
01906 }
01907 }
01908
01909 ExReleaseSpinLock (&
MmChargeCommitmentLock, OldIrql);
01910
01911
if (!Reduce) {
01912
return;
01913 }
01914
01915 PageReduce =
ExAllocatePoolWithTag (
NonPagedPool,
01916
sizeof(
MMPAGE_FILE_EXPANSION),
01917 ' mM');
01918
01919
if (PageReduce ==
NULL) {
01920
return;
01921 }
01922
01923 PageReduce->
Segment =
NULL;
01924 PageReduce->
RequestedExpansionSize = 0xFFFFFFFF;
01925
01926 ExAcquireSpinLock (&
MmDereferenceSegmentHeader.
Lock, &OldIrql);
01927 InsertTailList ( &
MmDereferenceSegmentHeader.
ListHead,
01928 &PageReduce->
DereferenceList);
01929 ExReleaseSpinLock (&
MmDereferenceSegmentHeader.
Lock, OldIrql);
01930
01931
KeReleaseSemaphore (&
MmDereferenceSegmentHeader.
Semaphore, 0
L, 1
L,
FALSE);
01932
return;
01933 }
01934
01935 ExReleaseSpinLock (&
MmChargeCommitmentLock, OldIrql);
01936
return;
01937 }
01938
01939
VOID
01940 MiAttemptPageFileReduction (
01941 VOID
01942 )
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966 {
01967 BOOLEAN Reduce;
01968 KIRQL OldIrql;
01969 ULONG i;
01970 PFN_NUMBER StartReduction;
01971 PFN_NUMBER ReductionSize;
01972 PFN_NUMBER TryBit;
01973 PFN_NUMBER TryReduction;
01974 SIZE_T MaxReduce;
01975 FILE_ALLOCATION_INFORMATION FileAllocationInfo;
01976
NTSTATUS status;
01977
01978 Reduce =
FALSE;
01979
01980 ExAcquireSpinLock (&
MmChargeCommitmentLock, &OldIrql);
01981
01982
01983
01984
01985
01986
01987
01988
if ((
MmTotalCommittedPages + (2 *
MmMinimumPageFileReduction)) <
01989
MmTotalCommitLimit) {
01990
01991 MaxReduce =
MmTotalCommitLimit -
01992 (
MmMinimumPageFileReduction +
MmTotalCommittedPages);
01993
ASSERT ((LONG)MaxReduce >= 0);
01994
01995 i = 0;
01996
do {
01997
01998
if (MaxReduce <
MmMinimumPageFileReduction) {
01999
02000
02001
02002
02003
02004
break;
02005 }
02006
02007
if (
MmPagingFile[i]->
MinimumSize !=
MmPagingFile[i]->
Size) {
02008
02009
if (
MmPagingFile[i]->
FreeSpace >
MmMinimumPageFileReduction) {
02010
02011
02012
02013
02014
02015 ExReleaseSpinLock (&
MmChargeCommitmentLock, OldIrql);
02016
02017
02018
02019
02020
02021
02022 TryBit =
MmPagingFile[i]->
Size -
MmMinimumPageFileReduction;
02023 TryReduction =
MmMinimumPageFileReduction;
02024
02025
if (TryBit <=
MmPagingFile[i]->
MinimumSize) {
02026 TryBit =
MmPagingFile[i]->
MinimumSize;
02027 TryReduction =
MmPagingFile[i]->
Size -
02028
MmPagingFile[i]->
MinimumSize;
02029 }
02030
02031 StartReduction = 0;
02032 ReductionSize = 0;
02033
02034
LOCK_PFN (OldIrql);
02035
02036
while (
TRUE) {
02037
02038
02039
02040
02041
02042
if ((ReductionSize + TryReduction) > MaxReduce) {
02043
02044
02045
02046
02047
02048
02049
break;
02050 }
02051
02052
if (
RtlAreBitsClear (
MmPagingFile[i]->Bitmap,
02053 (ULONG)TryBit,
02054 (ULONG)TryReduction)) {
02055
02056
02057
02058
02059
02060
02061 StartReduction = TryBit;
02062 ReductionSize += TryReduction;
02063
02064
if (StartReduction ==
MmPagingFile[i]->
MinimumSize) {
02065
break;
02066 }
02067
02068 TryBit = StartReduction -
MmMinimumPageFileReduction;
02069
02070
if (TryBit <=
MmPagingFile[i]->
MinimumSize) {
02071 TryReduction -=
02072
MmPagingFile[i]->
MinimumSize - TryBit;
02073 TryBit =
MmPagingFile[i]->
MinimumSize;
02074 }
else {
02075 TryReduction =
MmMinimumPageFileReduction;
02076 }
02077 }
else {
02078
02079
02080
02081
02082
02083
break;
02084 }
02085 }
02086
02087
02088
02089
02090
02091
02092
if (StartReduction != 0) {
02093
02094
02095
02096
02097
02098
02099
02100
02101
if ((
MmPagingFile[i]->
Entry[0]->
LastPageToWrite >
02102 StartReduction) ||
02103 (
MmPagingFile[i]->
Entry[1]->
LastPageToWrite >
02104 StartReduction)) {
02105 StartReduction = 0;
02106 }
02107 }
02108
02109
02110
02111
02112
02113
if (StartReduction != 0) {
02114
02115
02116
02117
02118
02119
ASSERT (ReductionSize == (
MmPagingFile[i]->
Size - StartReduction));
02120
02121
MmPagingFile[i]->
Size = StartReduction;
02122
MmPagingFile[i]->
FreeSpace -= ReductionSize;
02123 MaxReduce -= ReductionSize;
02124
ASSERT ((LONG)MaxReduce >= 0);
02125
02126
RtlSetBits (
MmPagingFile[i]->Bitmap,
02127 (ULONG)StartReduction,
02128 (ULONG)ReductionSize );
02129
02130
02131
02132
02133
02134
02135
UNLOCK_PFN (OldIrql);
02136
02137
02138
02139
02140
02141
02142 ExAcquireSpinLock (&
MmChargeCommitmentLock, &OldIrql);
02143
02144
02145
02146
02147
02148
02149
02150
if ((
MmTotalCommittedPages + (2 *
MmMinimumPageFileReduction)) >=
02151
MmTotalCommitLimit) {
02152
02153 ExReleaseSpinLock (&
MmChargeCommitmentLock, OldIrql);
02154
LOCK_PFN (OldIrql);
02155
02156
MmPagingFile[i]->
Size = StartReduction + ReductionSize;
02157
MmPagingFile[i]->
FreeSpace += ReductionSize;
02158 MaxReduce += ReductionSize;
02159
ASSERT ((LONG)MaxReduce >= 0);
02160
02161
RtlClearBits (
MmPagingFile[i]->Bitmap,
02162 (ULONG)StartReduction,
02163 (ULONG)ReductionSize );
02164
02165
UNLOCK_PFN (OldIrql);
02166
02167 ExAcquireSpinLock (&
MmChargeCommitmentLock, &OldIrql);
02168
break;
02169 }
02170
02171
MmTotalCommitLimit -= ReductionSize;
02172
02173 ExReleaseSpinLock (&
MmChargeCommitmentLock, OldIrql);
02174
02175
#if defined (_WIN64) || defined (_X86PAE_)
02176
FileAllocationInfo.AllocationSize.QuadPart =
02177 ((ULONG64)StartReduction <<
PAGE_SHIFT);
02178
02179
#else
02180
FileAllocationInfo.AllocationSize.LowPart =
02181 StartReduction *
PAGE_SIZE;
02182
02183
02184
02185
02186
02187
02188 FileAllocationInfo.AllocationSize.HighPart = 0;
02189
#endif
02190
02191
02192
02193
02194
02195
02196
02197
02198
ASSERT (KeGetCurrentIrql() <
DISPATCH_LEVEL);
02199 status =
IoSetInformation (
02200
MmPagingFile[i]->
File,
02201 FileAllocationInformation,
02202
sizeof(FILE_ALLOCATION_INFORMATION),
02203 &FileAllocationInfo
02204 );
02205
#if DBG
02206
02207
02208
02209
02210
02211
02212
02213
if (status != STATUS_SUCCESS) {
02214
DbgPrint (
"MM: pagefile truncate status %lx\n",
02215 status);
02216 }
02217
#endif
02218
}
else {
02219
UNLOCK_PFN (OldIrql);
02220 }
02221
02222 ExAcquireSpinLock (&
MmChargeCommitmentLock, &OldIrql);
02223 }
02224 }
02225 i += 1;
02226 }
while (i <
MmNumberOfPagingFiles);
02227 }
02228
02229 ExReleaseSpinLock (&
MmChargeCommitmentLock, OldIrql);
02230
return;
02231 }
02232
02233
VOID
02234 MiWriteComplete (
02235 IN PVOID Context,
02236 IN PIO_STATUS_BLOCK IoStatus,
02237 IN ULONG Reserved
02238 )
02239
02240
02241
02242
02243
02244
02245
02246
02247
02248
02249
02250
02251
02252
02253
02254
02255
02256
02257
02258
02259
02260
02261
02262
02263
02264
02265 {
02266
02267
PMMMOD_WRITER_MDL_ENTRY WriterEntry;
02268
PMMMOD_WRITER_MDL_ENTRY NextWriterEntry;
02269 PPFN_NUMBER Page;
02270
PMMPFN Pfn1;
02271 KIRQL OldIrql;
02272 LONG ByteCount;
02273
NTSTATUS status;
02274
PCONTROL_AREA ControlArea;
02275 ULONG FailAllIo;
02276
PFILE_OBJECT FileObject;
02277
PERESOURCE FileResource;
02278
02279 UNREFERENCED_PARAMETER (Reserved);
02280
02281 FailAllIo =
FALSE;
02282
02283
#if DBG
02284
if (MmDebug &
MM_DBG_MOD_WRITE) {
02285
DbgPrint(
"MM MODWRITE: modified page write completed\n");
02286 }
02287
#endif
02288
02289
02290
02291
02292
02293
02294
02295 WriterEntry = (
PMMMOD_WRITER_MDL_ENTRY)Context;
02296 ByteCount = (LONG)WriterEntry->
Mdl.
ByteCount;
02297 Page = &WriterEntry->
Page[0];
02298
02299
if (WriterEntry->
Mdl.
MdlFlags &
MDL_MAPPED_TO_SYSTEM_VA) {
02300
MmUnmapLockedPages (WriterEntry->
Mdl.
MappedSystemVa,
02301 &WriterEntry->
Mdl);
02302 }
02303
02304
02305
02306
02307
02308 status = IoStatus->Status;
02309 ControlArea = WriterEntry->
ControlArea;
02310
02311
LOCK_PFN (OldIrql);
02312
02313
02314
02315
02316
02317 WriterEntry->
LastPageToWrite = 0;
02318
02319
02320
while (ByteCount > 0) {
02321
02322 Pfn1 =
MI_PFN_ELEMENT (*Page);
02323
ASSERT (Pfn1->
u3.e1.WriteInProgress == 1);
02324
#if DBG
02325
02326
if (Pfn1->
OriginalPte.
u.Soft.Prototype == 0) {
02327
02328 ULONG
Offset;
02329
Offset =
GET_PAGING_FILE_OFFSET(Pfn1->
OriginalPte);
02330
if ((
Offset < 8192) &&
02331 (
GET_PAGING_FILE_NUMBER(Pfn1->
OriginalPte) == 0)) {
02332
ASSERT ((
MmPagingFileDebug[
Offset] & 1) != 0);
02333
if (!
MI_IS_PFN_DELETED(Pfn1)) {
02334
if ((
GET_PAGING_FILE_NUMBER (Pfn1->
OriginalPte)) == 0) {
02335
if ((
MmPagingFileDebug[
Offset] & ~0x1f) !=
02336 ((ULONG_PTR)Pfn1->
PteAddress << 3)) {
02337
if (Pfn1->
PteAddress !=
MiGetPteAddress(PDE_BASE)) {
02338
02339
02340
02341
02342
02343
02344
if ((Pfn1->
PteAddress < (
PMMPTE)
PDE_TOP) ||
02345 ((Pfn1->
OriginalPte.
u.Soft.Protection &
02346
MM_COPY_ON_WRITE_MASK) ==
02347
MM_PROTECTION_WRITE_MASK)) {
02348
DbgPrint(
"MMWRITE: Mismatch Pfn1 %p Offset %lx info %p\n",
02349 Pfn1,
02350
Offset,
02351
MmPagingFileDebug[
Offset]);
02352
02353 DbgBreakPoint();
02354
02355 }
else {
02356
MmPagingFileDebug[
Offset] &= 0x1f;
02357
MmPagingFileDebug[
Offset] |=
02358 ((ULONG_PTR)Pfn1->
PteAddress << 3);
02359 }
02360 }
02361
02362 }
02363 }
02364 }
02365 }
02366 }
02367
#endif //DBG
02368
02369 Pfn1->
u3.e1.WriteInProgress = 0;
02370
02371
if (
NT_ERROR(status)) {
02372
02373
02374
02375
02376
02377
02378
02379
02380
if (((status != STATUS_FILE_LOCK_CONFLICT) &&
02381 (ControlArea !=
NULL) &&
02382 (ControlArea->
u.Flags.Networked == 1))
02383 ||
02384 (status == STATUS_FILE_INVALID)) {
02385
02386
if (ControlArea->
u.Flags.FailAllIo == 0) {
02387 ControlArea->
u.Flags.FailAllIo = 1;
02388 FailAllIo =
TRUE;
02389
02390 KdPrint((
"MM MODWRITE: failing all io, controlarea %lx status %lx\n",
02391 ControlArea, status));
02392 }
02393 }
else {
02394
02395
02396
02397
02398
02399
02400
02401
#if DBG
02402
if ((status != STATUS_FILE_LOCK_CONFLICT) &&
02403 ((MmDebug &
MM_DBG_PRINTS_MODWRITES) == 0)) {
02404 KdPrint((
"MM MODWRITE: modified page write iosb failed - status 0x%lx\n",
02405 status));
02406 }
02407
#endif
02408
02409 Pfn1->
u3.e1.Modified = 1;
02410 }
02411 }
02412
02413
if ((Pfn1->
u3.e1.Modified == 1) &&
02414 (Pfn1->
OriginalPte.
u.Soft.Prototype == 0)) {
02415
02416
02417
02418
02419
02420
02421
MiReleasePageFileSpace (Pfn1->
OriginalPte);
02422 Pfn1->
OriginalPte.
u.Soft.PageFileHigh = 0;
02423 }
02424
02425
MI_REMOVE_LOCKED_PAGE_CHARGE (Pfn1, 15);
02426
MiDecrementReferenceCount (*Page);
02427
#if DBG
02428
*Page = 0xF0FFFFFF;
02429
#endif //DBG
02430
02431 Page += 1;
02432 ByteCount -= (LONG)
PAGE_SIZE;
02433 }
02434
02435
02436
02437
02438
02439
02440 FileObject = WriterEntry->
File;
02441 FileResource = WriterEntry->
FileResource;
02442
02443
if ((WriterEntry->
PagingFile !=
NULL) &&
02444 (WriterEntry->
PagingFile->
FreeSpace <
MM_USABLE_PAGES_FREE)) {
02445
02446
if (
MmNumberOfActiveMdlEntries == 1) {
02447
02448
02449
02450
02451
02452
02453
02454 InsertTailList (&
MmFreePagingSpaceLow, &WriterEntry->
Links);
02455 WriterEntry->
CurrentList = &
MmFreePagingSpaceLow;
02456
02457
MmNumberOfActiveMdlEntries -= 1;
02458
02459
02460
02461
02462
02463 WriterEntry = (
PMMMOD_WRITER_MDL_ENTRY)
MmFreePagingSpaceLow.Flink;
02464
02465
while ((PLIST_ENTRY)WriterEntry != &
MmFreePagingSpaceLow) {
02466
02467 NextWriterEntry =
02468 (
PMMMOD_WRITER_MDL_ENTRY)WriterEntry->
Links.Flink;
02469
02470
if (WriterEntry->
PagingFile->
FreeSpace != 0) {
02471
02472 RemoveEntryList (&WriterEntry->
Links);
02473
02474
02475
02476
02477
02478
if (IsListEmpty (&WriterEntry->
PagingListHead->
ListHead)) {
02479
KeSetEvent (&WriterEntry->
PagingListHead->
Event,
02480 0,
02481
FALSE);
02482 }
02483
02484 InsertTailList (&WriterEntry->
PagingListHead->
ListHead,
02485 &WriterEntry->
Links);
02486 WriterEntry->
CurrentList = &
MmPagingFileHeader.
ListHead;
02487
MmNumberOfActiveMdlEntries += 1;
02488 }
02489
02490 WriterEntry = NextWriterEntry;
02491 }
02492
02493 }
else {
02494
02495 InsertTailList (&
MmFreePagingSpaceLow, &WriterEntry->
Links);
02496 WriterEntry->
CurrentList = &
MmFreePagingSpaceLow;
02497
MmNumberOfActiveMdlEntries -= 1;
02498 }
02499 }
else {
02500
02501
02502
02503
02504
02505
if (IsListEmpty (&WriterEntry->
PagingListHead->
ListHead)) {
02506
KeSetEvent (&WriterEntry->
PagingListHead->
Event, 0,
FALSE);
02507 }
02508
02509 InsertTailList (&WriterEntry->
PagingListHead->
ListHead,
02510 &WriterEntry->
Links);
02511 }
02512
02513
ASSERT (((ULONG_PTR)WriterEntry->
Links.Flink & 1) == 0);
02514
02515
UNLOCK_PFN (OldIrql);
02516
02517
if (FileResource !=
NULL) {
02518
FsRtlReleaseFileForModWrite (FileObject, FileResource);
02519 }
02520
02521
if (FailAllIo) {
02522
02523
if (ControlArea->
FilePointer->
FileName.Length &&
02524 ControlArea->
FilePointer->
FileName.MaximumLength &&
02525 ControlArea->
FilePointer->
FileName.Buffer) {
02526
02527
IoRaiseInformationalHardError(
02528 STATUS_LOST_WRITEBEHIND_DATA,
02529 &ControlArea->
FilePointer->
FileName,
02530
NULL
02531 );
02532 }
02533 }
02534
02535
if (ControlArea !=
NULL) {
02536
02537
LOCK_PFN (OldIrql);
02538
02539
02540
02541
02542
02543
02544 ControlArea->
ModifiedWriteCount -= 1;
02545
ASSERT ((
SHORT)ControlArea->
ModifiedWriteCount >= 0);
02546
if (ControlArea->
u.Flags.SetMappedFileIoComplete != 0) {
02547
KePulseEvent (&
MmMappedFileIoComplete,
02548 0,
02549
FALSE);
02550 }
02551
02552 ControlArea->
NumberOfPfnReferences -= 1;
02553
02554
if (ControlArea->
NumberOfPfnReferences == 0) {
02555
02556
02557
02558
02559
02560
MiCheckControlArea (ControlArea,
NULL, OldIrql);
02561 }
else {
02562
UNLOCK_PFN (OldIrql);
02563 }
02564 }
02565
02566
if (
NT_ERROR(status)) {
02567
02568
02569
02570
02571
02572
KeDelayExecutionThread (
KernelMode,
FALSE, &
Mm30Milliseconds);
02573 }
02574
02575
return;
02576 }
02577
02578 LOGICAL
02579 MiCancelWriteOfMappedPfn (
02580 IN PFN_NUMBER PageToStop
02581 )
02582
02583
02584
02585
02586
02587
02588
02589
02590
02591
02592
02593
02594
02595
02596
02597
02598
02599
02600
02601
02602
02603
02604
02605
02606
02607
02608 {
02609 ULONG i;
02610 ULONG PageCount;
02611 KIRQL OldIrql;
02612 PPFN_NUMBER Page;
02613 PLIST_ENTRY NextEntry;
02614
PMDL MemoryDescriptorList;
02615
PMMMOD_WRITER_MDL_ENTRY ModWriterEntry;
02616
02617
02618
02619
02620
02621
02622 NextEntry =
MmMappedPageWriterList.Flink;
02623
while (NextEntry != &
MmMappedPageWriterList) {
02624
02625 ModWriterEntry = CONTAINING_RECORD(NextEntry,
02626
MMMOD_WRITER_MDL_ENTRY,
02627 Links);
02628
02629 MemoryDescriptorList = &ModWriterEntry->
Mdl;
02630 PageCount = (MemoryDescriptorList->
ByteCount >>
PAGE_SHIFT);
02631 Page = (PPFN_NUMBER)(MemoryDescriptorList + 1);
02632
02633
for (i = 0; i < PageCount; i += 1) {
02634
if (*Page == PageToStop) {
02635 RemoveEntryList (NextEntry);
02636
goto CancelWrite;
02637 }
02638 Page += 1;
02639 }
02640
02641 NextEntry = NextEntry->Flink;
02642 }
02643
02644
return FALSE;
02645
02646 CancelWrite:
02647
02648
UNLOCK_PFN (
APC_LEVEL);
02649
02650
02651
02652
02653
02654
02655
02656 ModWriterEntry->
u.IoStatus.Status = STATUS_FILE_LOCK_CONFLICT;
02657 ModWriterEntry->
u.IoStatus.Information = 0;
02658
02659
MiWriteComplete ((PVOID)ModWriterEntry,
02660 &ModWriterEntry->
u.IoStatus,
02661 0 );
02662
02663
LOCK_PFN (OldIrql);
02664
02665
return TRUE;
02666 }
02667
02668
VOID
02669 MiModifiedPageWriter (
02670 IN PVOID StartContext
02671 )
02672
02673
02674
02675
02676
02677
02678
02679
02680
02681
02682
02683
02684
02685
02686
02687
02688
02689
02690
02691
02692
02693
02694
02695 {
02696 HANDLE
ThreadHandle;
02697 OBJECT_ATTRIBUTES
ObjectAttributes;
02698 ULONG i;
02699
02700
PAGED_CODE();
02701
02702 StartContext;
02703
02704
02705
02706
02707
02708
MmSystemShutdown = 0;
02709
KeInitializeEvent (&
MmPagingFileHeader.
Event, NotificationEvent,
FALSE);
02710
KeInitializeEvent (&
MmMappedFileHeader.
Event, NotificationEvent,
FALSE);
02711
02712 InitializeListHead(&
MmPagingFileHeader.
ListHead);
02713 InitializeListHead(&
MmMappedFileHeader.
ListHead);
02714 InitializeListHead(&
MmFreePagingSpaceLow);
02715
02716
for (i = 0; i <
MM_MAPPED_FILE_MDLS; i += 1) {
02717
MmMappedFileMdl[i] =
ExAllocatePoolWithTag (
NonPagedPoolMustSucceed,
02718
sizeof(
MMMOD_WRITER_MDL_ENTRY) +
02719
MmModifiedWriteClusterSize *
02720
sizeof(PFN_NUMBER),
02721 ' mM');
02722
02723
MmMappedFileMdl[i]->
PagingFile =
NULL;
02724
MmMappedFileMdl[i]->
PagingListHead = &
MmMappedFileHeader;
02725
02726 InsertTailList (&
MmMappedFileHeader.
ListHead,
02727 &
MmMappedFileMdl[i]->
Links);
02728 }
02729
02730
02731
02732
02733
02734 (
VOID)
KeSetPriorityThread (&
PsGetCurrentThread()->Tcb,
02735 LOW_REALTIME_PRIORITY + 1);
02736
02737
02738
02739
02740
02741
02742
02743
02744
02745
02746
02747
KeInitializeEvent (&
MmMappedPageWriterEvent, NotificationEvent,
FALSE);
02748 InitializeListHead(&
MmMappedPageWriterList);
02749 InitializeObjectAttributes( &
ObjectAttributes,
NULL, 0,
NULL,
NULL );
02750
02751
PsCreateSystemThread (&
ThreadHandle,
02752 THREAD_ALL_ACCESS,
02753 &
ObjectAttributes,
02754 0
L,
02755
NULL,
02756
MiMappedPageWriter,
02757
NULL );
02758 ZwClose (
ThreadHandle);
02759
MiModifiedPageWriterWorker();
02760
02761
02762
02763
02764
02765 {
02766 LARGE_INTEGER Forever;
02767
02768
02769
02770
02771
02772 Forever.LowPart = 0;
02773 Forever.HighPart = 0xF000000;
02774
KeDelayExecutionThread (
KernelMode,
FALSE, &Forever);
02775 }
02776
02777
return;
02778 }
02779
02780
02781
VOID
02782 MiModifiedPageWriterTimerDispatch (
02783 IN
PKDPC Dpc,
02784 IN PVOID DeferredContext,
02785 IN PVOID SystemArgument1,
02786 IN PVOID SystemArgument2
02787 )
02788
02789
02790
02791
02792
02793
02794
02795
02796
02797
02798
02799
02800
02801
02802
02803
02804
02805
02806
02807
02808
02809
02810
02811
02812
02813 {
02814 KIRQL OldIrql;
02815
02816 UNREFERENCED_PARAMETER (Dpc);
02817 UNREFERENCED_PARAMETER (DeferredContext);
02818 UNREFERENCED_PARAMETER (SystemArgument1);
02819 UNREFERENCED_PARAMETER (SystemArgument2);
02820
02821
LOCK_PFN2 (OldIrql);
02822
02823
MiTimerPending =
TRUE;
02824
KeSetEvent (&
MiMappedPagesTooOldEvent, 0,
FALSE);
02825
02826
UNLOCK_PFN2 (OldIrql);
02827 }
02828
02829
02830
VOID
02831 MiModifiedPageWriterWorker (
02832 VOID
02833 )
02834
02835
02836
02837
02838
02839
02840
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850
02851
02852
02853
02854
02855
02856
02857 {
02858
PMMPFN Pfn1;
02859 PFN_NUMBER PageFrameIndex;
02860 KIRQL OldIrql;
02861 ULONG NextColor;
02862 ULONG i;
02863
static KWAIT_BLOCK WaitBlockArray[
ModifiedWriterMaximumObject];
02864 PVOID WaitObjects[
ModifiedWriterMaximumObject];
02865
NTSTATUS WakeupStatus;
02866
02867
02868
02869
02870
02871 WaitObjects[
NormalCase] = (PVOID)&
MmModifiedPageWriterEvent;
02872 WaitObjects[
MappedPagesNeedWriting] = (PVOID)&
MiMappedPagesTooOldEvent;
02873
02874
for (;;) {
02875
02876 WakeupStatus =
KeWaitForMultipleObjects(
ModifiedWriterMaximumObject,
02877 &WaitObjects[0],
02878 WaitAny,
02879
WrFreePage,
02880
KernelMode,
02881
FALSE,
02882
NULL,
02883 &WaitBlockArray[0]);
02884
02885
02886
02887
02888
02889
switch (WakeupStatus) {
02890
02891
case NormalCase:
02892
break;
02893
02894
case MappedPagesNeedWriting:
02895
02896
02897
02898
02899
02900
02901
02902
break;
02903
02904
default:
02905
break;
02906
02907 }
02908
02909
02910
02911
02912
02913
02914
if (
MmNumberOfPagingFiles != 0) {
02915 i = 0;
02916
do {
02917
MmPagingFile[i]->
HintSetToZero =
FALSE;
02918 i += 1;
02919 }
while (i <
MmNumberOfPagingFiles);
02920 }
02921
02922 NextColor = 0;
02923
02924
LOCK_PFN (OldIrql);
02925
02926
for (;;) {
02927
02928
02929
02930
02931
02932
if ((
MmAvailablePages <
MmFreeGoal) &&
02933 (
MmModNoWriteInsert)) {
02934
02935
02936
02937
02938
02939
02940 i = 0;
02941
while ((
MmModifiedNoWritePageListHead.
Total != 0) &&
02942 (i < 32)) {
02943
PSUBSECTION Subsection;
02944
PCONTROL_AREA ControlArea;
02945
02946 PageFrameIndex =
MmModifiedNoWritePageListHead.
Flink;
02947 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
02948 Subsection =
MiGetSubsectionAddress (&Pfn1->
OriginalPte);
02949 ControlArea = Subsection->
ControlArea;
02950
if (ControlArea->
u.Flags.NoModifiedWriting) {
02951
MmModNoWriteInsert =
FALSE;
02952
break;
02953 }
02954
MiUnlinkPageFromList (Pfn1);
02955
MiInsertPageInList (&
MmModifiedPageListHead,
02956 PageFrameIndex);
02957 i += 1;
02958 }
02959 }
02960
02961
if (
MmModifiedPageListHead.
Total == 0) {
02962
02963
02964
02965
02966
02967
02968
02969
if (
MiTimerPending ==
TRUE) {
02970
MiTimerPending =
FALSE;
02971
KeClearEvent (&
MiMappedPagesTooOldEvent);
02972 }
02973
02974
UNLOCK_PFN (OldIrql);
02975
02976
KeClearEvent (&
MmModifiedPageWriterEvent);
02977
02978
break;
02979 }
02980
02981
02982
02983
02984
02985
02986
02987
if (WakeupStatus ==
MappedPagesNeedWriting) {
02988 PageFrameIndex =
MmModifiedPageListHead.
Flink;
02989
if (PageFrameIndex ==
MM_EMPTY_LIST) {
02990
02991
02992
02993
02994
02995
02996
02997
02998
MiTimerPending =
FALSE;
02999
KeClearEvent (&
MiMappedPagesTooOldEvent);
03000
03001
UNLOCK_PFN (OldIrql);
03002
03003
break;
03004 }
03005 }
03006
else if (
MmTotalPagesForPagingFile >=
03007 (
MmModifiedPageListHead.
Total -
MmTotalPagesForPagingFile)) {
03008
03009
03010
03011
03012
03013
MI_GET_MODIFIED_PAGE_ANY_COLOR (PageFrameIndex, NextColor);
03014
03015 }
else {
03016
03017
03018
03019
03020
03021 PageFrameIndex =
MmModifiedPageListHead.
Flink;
03022 }
03023
03024
03025
03026
03027
03028
03029
03030
03031
03032
03033
03034 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
03035
03036
if (Pfn1->
OriginalPte.
u.Soft.Prototype == 1) {
03037
if (IsListEmpty (&
MmMappedFileHeader.
ListHead)) {
03038
03039
03040
03041
03042
03043
03044
if (WakeupStatus !=
MappedPagesNeedWriting) {
03045
03046
MI_GET_MODIFIED_PAGE_ANY_COLOR (PageFrameIndex, NextColor);
03047
03048
03049
03050
03051
03052
03053
if (PageFrameIndex ==
MM_EMPTY_LIST) {
03054
03055
03056
03057
03058
03059 PageFrameIndex =
MmModifiedPageListHead.
Flink;
03060 }
03061
03062 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
03063 }
03064 }
03065 }
else if ((IsListEmpty(&
MmPagingFileHeader.
ListHead)) ||
03066 (
MiFirstPageFileCreatedAndReady ==
FALSE)) {
03067
03068
03069
03070
03071
03072
03073
if (
MmModifiedPageListHead.
Flink !=
MM_EMPTY_LIST) {
03074
ASSERT (
MmTotalPagesForPagingFile !=
MmModifiedPageListHead.
Total);
03075 PageFrameIndex =
MmModifiedPageListHead.
Flink;
03076 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
03077 }
03078
else {
03079
ASSERT (
MmTotalPagesForPagingFile ==
MmModifiedPageListHead.
Total);
03080
if ((
MiFirstPageFileCreatedAndReady ==
FALSE) &&
03081 (
MmNumberOfPagingFiles != 0)) {
03082
03083
03084
03085
03086
03087
03088
03089
UNLOCK_PFN (OldIrql);
03090
KeDelayExecutionThread (
KernelMode,
FALSE, &
MmShortTime);
03091
LOCK_PFN (OldIrql);
03092
continue;
03093 }
03094 }
03095 }
03096
03097
if (Pfn1->
OriginalPte.
u.Soft.Prototype == 1) {
03098
03099
if (IsListEmpty(&
MmMappedFileHeader.
ListHead)) {
03100
03101
if (WakeupStatus ==
MappedPagesNeedWriting) {
03102
03103
03104
03105
03106
03107
03108
03109
03110
03111
if (
MiTimerPending ==
TRUE) {
03112
03113
03114
03115
03116
03117
03118
03119
03120
03121
03122
03123
MiTimerPending =
FALSE;
03124
KeClearEvent (&
MiMappedPagesTooOldEvent);
03125 }
03126
03127
MiTimerPending =
TRUE;
03128
03129 (
VOID)
KeSetTimerEx( &
MiModifiedPageWriterTimer,
MiModifiedPageLife, 0, &
MiModifiedPageWriterTimerDpc );
03130
UNLOCK_PFN (OldIrql);
03131
break;
03132 }
03133
03134
03135
03136
03137
03138
03139
03140
03141
KeClearEvent (&
MmMappedFileHeader.
Event);
03142
03143
UNLOCK_PFN (OldIrql);
03144
KeWaitForSingleObject( &
MmMappedFileHeader.
Event,
03145
WrPageOut,
03146
KernelMode,
03147
FALSE,
03148 &
Mm30Milliseconds);
03149
LOCK_PFN (OldIrql);
03150
03151
03152
03153
03154
03155
03156
continue;
03157 }
03158
03159
MiGatherMappedPages (Pfn1, PageFrameIndex);
03160
03161 }
else {
03162
03163
MiGatherPagefilePages (Pfn1, PageFrameIndex);
03164 }
03165
03166
if (
MmSystemShutdown) {
03167
03168
03169
03170
03171
03172
UNLOCK_PFN (OldIrql);
03173
return;
03174 }
03175
03176
if (WakeupStatus !=
MappedPagesNeedWriting && !
MmWriteAllModifiedPages) {
03177
if (((
MmAvailablePages >
MmFreeGoal) &&
03178 (
MmModifiedPageListHead.
Total <
MmFreeGoal))
03179 ||
03180 (
MmAvailablePages >
MmMoreThanEnoughFreePages)) {
03181
03182
03183
03184
03185
03186
UNLOCK_PFN (OldIrql);
03187
03188
KeClearEvent (&
MmModifiedPageWriterEvent);
03189
break;
03190 }
03191 }
03192 }
03193
03194 }
03195 }
03196
03197
VOID
03198 MiGatherMappedPages (
03199 IN
PMMPFN Pfn1,
03200 IN PFN_NUMBER PageFrameIndex
03201 )
03202
03203
03204
03205
03206
03207
03208
03209
03210
03211
03212
03213
03214
03215
03216
03217
03218
03219
03220
03221
03222
03223
03224
03225
03226
03227
03228
03229
03230 {
03231
PMMPFN Pfn2;
03232
PMMMOD_WRITER_MDL_ENTRY ModWriterEntry;
03233
PSUBSECTION Subsection;
03234
PCONTROL_AREA ControlArea;
03235 PPFN_NUMBER Page;
03236
PMMPTE LastPte;
03237
PMMPTE BasePte;
03238
PMMPTE NextPte;
03239
PMMPTE PointerPte;
03240
PMMPTE StartingPte;
03241
MMPTE PteContents;
03242 KIRQL OldIrql = 0;
03243 KIRQL OldIrql2;
03244
03245
03246
03247
03248
03249
03250
03251 Subsection =
MiGetSubsectionAddress (&Pfn1->OriginalPte);
03252 ControlArea = Subsection->
ControlArea;
03253
03254
if (ControlArea->
u.Flags.NoModifiedWriting) {
03255
03256
03257
03258
03259
03260
03261
MiUnlinkPageFromList (Pfn1);
03262
MiInsertPageInList (
MmPageLocationList[
ModifiedNoWritePageList],
03263 PageFrameIndex);
03264
return;
03265 }
03266
03267
if (ControlArea->
u.Flags.Image) {
03268
03269
#if 0
03270
03271
03272
03273
03274
03275
03276
03277
03278
03279
ASSERT ((ControlArea->
NumberOfMappedViews != 0) ||
03280 (ControlArea->
NumberOfSectionReferences != 0) ||
03281 (ControlArea->
u.Flags.FloppyMedia != 0));
03282
#endif
03283
03284
03285
03286
03287
03288
03289
03290
03291
03292
03293
03294
03295
03296
03297
03298
03299
03300 ControlArea->
NumberOfPfnReferences -= 1;
03301
ASSERT ((LONG)ControlArea->
NumberOfPfnReferences >= 0);
03302
MiUnlinkPageFromList (Pfn1);
03303
03304 Pfn1->OriginalPte.u.Soft.PageFileHigh = 0;
03305 Pfn1->OriginalPte.u.Soft.Prototype = 0;
03306 Pfn1->OriginalPte.u.Soft.Transition = 0;
03307
03308
03309
03310
03311
03312
03313
MiInsertPageInList (
MmPageLocationList[
ModifiedPageList],
03314 PageFrameIndex);
03315
return;
03316 }
03317
03318
if ((ControlArea->
u.Flags.HadUserReference == 0) &&
03319 (
MmAvailablePages > (
MmFreeGoal + 40)) &&
03320 (
MmEnoughMemoryForWrite())) {
03321
03322
03323
03324
03325
03326
03327
MiUnlinkPageFromList (Pfn1);
03328
MiInsertFrontModifiedNoWrite (PageFrameIndex);
03329
MmModNoWriteInsert =
TRUE;
03330
return;
03331 }
03332
03333
03334
03335
03336
03337
03338 PointerPte = Pfn1->PteAddress;
03339 NextPte = PointerPte - (
MmModifiedWriteClusterSize - 1);
03340
03341
03342
03343
03344
03345
if (NextPte < (
PMMPTE)
PAGE_ALIGN (PointerPte)) {
03346 NextPte = (
PMMPTE)
PAGE_ALIGN (PointerPte);
03347 }
03348
03349
03350
03351
03352
03353
if (NextPte < Subsection->
SubsectionBase) {
03354 NextPte = Subsection->
SubsectionBase;
03355 }
03356
03357
03358
03359
03360
03361
03362
03363 OldIrql2 = 99;
03364
if (
MmIsAddressValid (PointerPte)) {
03365 BasePte = PointerPte;
03366 }
else {
03367 BasePte =
MiMapPageInHyperSpace (Pfn1->PteFrame, &OldIrql2);
03368 BasePte = (
PMMPTE)((PCHAR)BasePte +
03369
BYTE_OFFSET (PointerPte));
03370 }
03371
03372
ASSERT (
MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (BasePte) == PageFrameIndex);
03373
03374 PointerPte -= 1;
03375 BasePte -= 1;
03376
03377
03378
03379
03380
03381
03382
while (PointerPte >= NextPte) {
03383
03384 PteContents = *BasePte;
03385
03386
03387
03388
03389
03390
if ((PteContents.
u.Hard.Valid == 1) ||
03391 (PteContents.
u.Soft.Transition == 0) ||
03392 (PteContents.
u.Soft.Prototype == 1)) {
03393
03394
break;
03395 }
03396
03397 Pfn2 =
MI_PFN_ELEMENT (PteContents.
u.Trans.PageFrameNumber);
03398
03399
03400
03401
03402
03403
if ((Pfn2->
u3.e1.Modified == 0 ) ||
03404 (Pfn2->
u3.e2.ReferenceCount != 0)) {
03405
break;
03406 }
03407 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (&PteContents);
03408 PointerPte -= 1;
03409 BasePte -= 1;
03410 }
03411
03412 StartingPte = PointerPte + 1;
03413 BasePte = BasePte + 1;
03414
03415 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
03416
ASSERT (StartingPte == Pfn1->PteAddress);
03417
MiUnlinkPageFromList (Pfn1);
03418
03419
03420
03421
03422
03423 ModWriterEntry = (
PMMMOD_WRITER_MDL_ENTRY)RemoveHeadList (
03424 &
MmMappedFileHeader.
ListHead);
03425
03426 ModWriterEntry->
File = ControlArea->
FilePointer;
03427 ModWriterEntry->
ControlArea = ControlArea;
03428
03429
03430
03431
03432
03433
03434 ModWriterEntry->
WriteOffset.QuadPart =
MiStartingOffset (Subsection,
03435 Pfn1->PteAddress);
03436
03437
MmInitializeMdl(&ModWriterEntry->
Mdl,
03438 (PVOID)ULongToPtr(Pfn1->u3.e1.PageColor <<
PAGE_SHIFT),
03439
PAGE_SIZE);
03440
03441 ModWriterEntry->
Mdl.
MdlFlags |=
MDL_PAGES_LOCKED;
03442
03443 ModWriterEntry->
Mdl.
Size = (CSHORT)(
sizeof(
MDL) +
03444 (
sizeof(PFN_NUMBER) *
MmModifiedWriteClusterSize));
03445
03446 Page = &ModWriterEntry->
Page[0];
03447
03448
03449
03450
03451
03452
03453
MI_ADD_LOCKED_PAGE_CHARGE_FOR_MODIFIED_PAGE (Pfn1, 14);
03454 Pfn1->u3.e2.ReferenceCount += 1;
03455
03456
03457
03458
03459
03460
03461 Pfn1->u3.e1.Modified = 0;
03462 Pfn1->u3.e1.WriteInProgress = 1;
03463
03464
03465
03466
03467
03468 *Page = PageFrameIndex;
03469
03470
03471
03472
03473
03474
03475
03476
03477
03478
03479
03480
03481
03482 LastPte = StartingPte +
MmModifiedWriteClusterSize;
03483
03484
03485
03486
03487
03488
03489
if (StartingPte < (
PMMPTE)
PAGE_ALIGN(LastPte)) {
03490 LastPte = ((
PMMPTE)
PAGE_ALIGN(LastPte)) - 1;
03491 }
03492
03493
03494
03495
03496
03497
if (LastPte > &Subsection->
SubsectionBase[
03498 Subsection->
PtesInSubsection]) {
03499 LastPte = &Subsection->
SubsectionBase[
03500 Subsection->
PtesInSubsection];
03501 }
03502
03503
03504
03505
03506
03507 NextPte = BasePte + 1;
03508 PointerPte = StartingPte + 1;
03509
03510
03511
03512
03513
03514
03515
03516
03517
while (PointerPte < LastPte) {
03518
03519 PteContents = *NextPte;
03520
03521
03522
03523
03524
03525
if ((PteContents.
u.Hard.Valid == 1) ||
03526 (PteContents.
u.Soft.Transition == 0) ||
03527 (PteContents.
u.Soft.Prototype == 1)) {
03528
03529
break;
03530 }
03531
03532 Pfn2 =
MI_PFN_ELEMENT (PteContents.
u.Trans.PageFrameNumber);
03533
03534
if ((Pfn2->
u3.e1.Modified == 0 ) ||
03535 (Pfn2->
u3.e2.ReferenceCount != 0)) {
03536
03537
03538
03539
03540
03541
03542
break;
03543 }
03544 Page += 1;
03545
03546
03547
03548
03549
03550 *Page =
MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (&PteContents);
03551
ASSERT (PointerPte == Pfn2->
PteAddress);
03552
MiUnlinkPageFromList (Pfn2);
03553
03554
03555
03556
03557
03558
03559
MI_ADD_LOCKED_PAGE_CHARGE_FOR_MODIFIED_PAGE (Pfn2, 14);
03560 Pfn2->
u3.e2.ReferenceCount += 1;
03561
03562
03563
03564
03565
03566
03567 Pfn2->
u3.e1.Modified = 0;
03568 Pfn2->
u3.e1.WriteInProgress = 1;
03569
03570 ModWriterEntry->
Mdl.
ByteCount +=
PAGE_SIZE;
03571
03572 NextPte += 1;
03573 PointerPte += 1;
03574
03575 }
03576
03577
if (OldIrql2 != 99) {
03578
MiUnmapPageInHyperSpace (OldIrql2);
03579 }
03580
03581
ASSERT (
BYTES_TO_PAGES (ModWriterEntry->
Mdl.
ByteCount) <=
MmModifiedWriteClusterSize);
03582
03583 ModWriterEntry->
u.LastByte.QuadPart = ModWriterEntry->
WriteOffset.QuadPart +
03584 ModWriterEntry->
Mdl.
ByteCount;
03585
03586
ASSERT (Subsection->
ControlArea->
u.Flags.Image == 0);
03587
03588
#if DBG
03589
if ((ULONG)ModWriterEntry->
Mdl.
ByteCount >
03590 ((1+
MmModifiedWriteClusterSize)*
PAGE_SIZE)) {
03591
DbgPrint(
"Mdl %p, MDL End Offset %lx %lx Subsection %p\n",
03592 ModWriterEntry->
Mdl,
03593 ModWriterEntry->
u.LastByte.LowPart,
03594 ModWriterEntry->
u.LastByte.HighPart,
03595 Subsection);
03596 DbgBreakPoint();
03597 }
03598
#endif //DBG
03599
03600
MmInfoCounters.
MappedWriteIoCount += 1;
03601
MmInfoCounters.
MappedPagesWriteCount +=
03602 (ModWriterEntry->
Mdl.
ByteCount >>
PAGE_SHIFT);
03603
03604
03605
03606
03607
03608
03609 ControlArea->
ModifiedWriteCount += 1;
03610
03611
03612
03613
03614
03615
03616 ControlArea->
NumberOfPfnReferences += 1;
03617
03618 ModWriterEntry->
FileResource =
NULL;
03619
03620
if (ControlArea->
u.Flags.BeingPurged == 1) {
03621
UNLOCK_PFN (OldIrql);
03622 ModWriterEntry->
u.IoStatus.Status = STATUS_FILE_LOCK_CONFLICT;
03623 ModWriterEntry->
u.IoStatus.Information = 0;
03624
KeRaiseIrql (
APC_LEVEL, &OldIrql);
03625
MiWriteComplete ((PVOID)ModWriterEntry,
03626 &ModWriterEntry->
u.IoStatus,
03627 0 );
03628
KeLowerIrql (OldIrql);
03629
LOCK_PFN (OldIrql);
03630
return;
03631 }
03632
03633
03634
03635
03636
03637 InsertTailList (&
MmMappedPageWriterList,
03638 &ModWriterEntry->
Links);
03639
03640
KeSetEvent (&
MmMappedPageWriterEvent, 0,
FALSE);
03641
03642
03643
#if 0
03644
03645
UNLOCK_PFN (OldIrql);
03646
03647 ModWriterEntry->
FileResource =
NULL;
03648
03649
if (ModWriterEntry->
ControlArea->
u.Flags.FailAllIo == 1) {
03650
Status = STATUS_UNSUCCESSFUL;
03651
03652 }
else if (
FsRtlAcquireFileForModWrite (ModWriterEntry->
File,
03653 &ModWriterEntry->
u.LastByte,
03654 &ModWriterEntry->
FileResource)) {
03655
03656
03657
03658
03659
03660
Status =
IoAsynchronousPageWrite (
03661 ModWriterEntry->
File,
03662 &ModWriterEntry->
Mdl,
03663 &ModWriterEntry->
WriteOffset,
03664
MiWriteComplete,
03665 (PVOID)ModWriterEntry,
03666 &ModWriterEntry->
IoStatus,
03667 &ModWriterEntry->Irp );
03668 }
else {
03669
03670
03671
03672
03673
03674
03675
03676
Status = STATUS_FILE_LOCK_CONFLICT;
03677 }
03678
03679
if (
NT_ERROR(
Status)) {
03680
03681
03682
03683
03684
03685
03686 ModWriterEntry->
IoStatus.Status =
Status;
03687 ModWriterEntry->
IoStatus.Information = 0;
03688
KeRaiseIrql (
APC_LEVEL, &OldIrql);
03689
MiWriteComplete ((PVOID)ModWriterEntry,
03690 &ModWriterEntry->
IoStatus,
03691 0 );
03692
KeLowerIrql (OldIrql);
03693 }
03694
03695
LOCK_PFN (OldIrql);
03696
#endif //0
03697
return;
03698 }
03699
03700
VOID
03701 MiGatherPagefilePages (
03702 IN
PMMPFN Pfn1,
03703 IN PFN_NUMBER PageFrameIndex
03704 )
03705
03706
03707
03708
03709
03710
03711
03712
03713
03714
03715
03716
03717
03718
03719
03720
03721
03722
03723
03724
03725
03726
03727
03728
03729
03730
03731 {
03732
PFILE_OBJECT File;
03733
PMMMOD_WRITER_MDL_ENTRY ModWriterEntry;
03734
PMMPAGING_FILE CurrentPagingFile;
03735
NTSTATUS Status;
03736 PPFN_NUMBER Page;
03737 ULONG StartBit;
03738 LARGE_INTEGER StartingOffset;
03739 PFN_NUMBER ClusterSize;
03740 PFN_NUMBER ThisCluster;
03741
MMPTE LongPte;
03742 KIRQL OldIrql;
03743 ULONG NextColor;
03744 LOGICAL PageFileFull;
03745
03746
03747 OldIrql = 0;
03748
03749
if (IsListEmpty(&
MmPagingFileHeader.
ListHead)) {
03750
03751
03752
03753
03754
03755
03756
03757
KeClearEvent (&
MmPagingFileHeader.
Event);
03758
UNLOCK_PFN (OldIrql);
03759
KeWaitForSingleObject( &
MmPagingFileHeader.
Event,
03760
WrPageOut,
03761
KernelMode,
03762
FALSE,
03763 &
Mm30Milliseconds);
03764
LOCK_PFN (OldIrql);
03765
03766
03767
03768
03769
03770
03771
return;
03772 }
03773
03774
03775
03776
03777
03778
03779 NextColor = Pfn1->u3.e1.PageColor;
03780
03781 ModWriterEntry = (
PMMMOD_WRITER_MDL_ENTRY)RemoveHeadList (
03782 &
MmPagingFileHeader.
ListHead);
03783
#if DBG
03784
ModWriterEntry->
Links.Flink =
MM_IO_IN_PROGRESS;
03785
#endif
03786
CurrentPagingFile = ModWriterEntry->
PagingFile;
03787
03788
File = ModWriterEntry->
PagingFile->
File;
03789 ThisCluster =
MmModifiedWriteClusterSize;
03790
03791 PageFileFull =
FALSE;
03792
03793
do {
03794
03795
03796
03797
03798
03799
03800
if (((CurrentPagingFile->
Hint +
MmModifiedWriteClusterSize) >
03801 CurrentPagingFile->
MinimumSize)
03802 &&
03803 (CurrentPagingFile->
HintSetToZero ==
FALSE)) {
03804
03805 CurrentPagingFile->
HintSetToZero =
TRUE;
03806 CurrentPagingFile->
Hint = 0;
03807 }
03808
03809 StartBit =
RtlFindClearBitsAndSet (CurrentPagingFile->
Bitmap,
03810 (ULONG)ThisCluster,
03811 (ULONG)CurrentPagingFile->
Hint);
03812
03813
if (StartBit != 0xFFFFFFFF) {
03814
break;
03815 }
03816
if (CurrentPagingFile->
Hint != 0) {
03817
03818
03819
03820
03821
03822 CurrentPagingFile->
Hint = 0;
03823 }
else {
03824 ThisCluster = ThisCluster >> 1;
03825 PageFileFull =
TRUE;
03826 }
03827
03828 }
while (ThisCluster != 0);
03829
03830
if (StartBit == 0xFFFFFFFF) {
03831
03832
03833
03834
03835
03836 KdPrint((
"MM MODWRITE: page file full\n"));
03837
ASSERT(CurrentPagingFile->
FreeSpace == 0);
03838
03839
03840
03841
03842
03843
03844 InsertTailList (&
MmFreePagingSpaceLow,
03845 &ModWriterEntry->
Links);
03846 ModWriterEntry->
CurrentList = &
MmFreePagingSpaceLow;
03847
MmNumberOfActiveMdlEntries -= 1;
03848
MiPageFileFull ();
03849
return;
03850 }
03851
03852 CurrentPagingFile->
FreeSpace -= ThisCluster;
03853 CurrentPagingFile->
CurrentUsage += ThisCluster;
03854
if (CurrentPagingFile->
FreeSpace < 32) {
03855 PageFileFull =
TRUE;
03856 }
03857
03858 StartingOffset.QuadPart = (UINT64)StartBit <<
PAGE_SHIFT;
03859
03860
MmInitializeMdl(&ModWriterEntry->
Mdl,
03861 (PVOID)ULongToPtr(Pfn1->u3.e1.PageColor <<
PAGE_SHIFT),
03862
PAGE_SIZE);
03863
03864 ModWriterEntry->
Mdl.
MdlFlags |=
MDL_PAGES_LOCKED;
03865
03866 ModWriterEntry->
Mdl.
Size = (CSHORT)(
sizeof(
MDL) +
03867
sizeof(PFN_NUMBER) *
MmModifiedWriteClusterSize);
03868
03869 Page = &ModWriterEntry->
Page[0];
03870
03871 ClusterSize = 0;
03872
03873
03874
03875
03876
03877
03878
while (ClusterSize != ThisCluster) {
03879
03880
03881
03882
03883
03884
if (Pfn1->OriginalPte.u.Soft.Prototype == 0) {
03885
03886
#if 0 //********* commented out
03887
03888
MiClusterWritePages (Pfn1,
03889 PageFrameIndex,
03890 &WriteCluster,
03891 ThisCluster - ClusterSize);
03892
do {
03893
03894 PageFrameIndex = WriteCluster.Cluster[WriteCluster.StartIndex];
03895 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
03896
#endif //0
03897
*Page = PageFrameIndex;
03898
03899
03900
03901
03902
03903
03904
03905
03906
03907
03908
03909
MiUnlinkPageFromList (Pfn1);
03910 NextColor =
MI_GET_NEXT_COLOR(NextColor);
03911
03912
MI_GET_MODIFIED_PAGE_BY_COLOR (PageFrameIndex,
03913 NextColor);
03914
03915
03916
03917
03918
03919
03920
MI_ADD_LOCKED_PAGE_CHARGE_FOR_MODIFIED_PAGE (Pfn1, 16);
03921 Pfn1->u3.e2.ReferenceCount += 1;
03922
03923
03924
03925
03926
03927
03928 Pfn1->u3.e1.Modified = 0;
03929 Pfn1->u3.e1.WriteInProgress = 1;
03930
ASSERT (Pfn1->OriginalPte.u.Soft.PageFileHigh == 0);
03931
03932
MI_SET_PAGING_FILE_INFO (LongPte,
03933 Pfn1->OriginalPte,
03934 CurrentPagingFile->
PageFileNumber,
03935 StartBit);
03936
03937
#if DBG
03938
if ((StartBit < 8192) &&
03939 (CurrentPagingFile->
PageFileNumber == 0)) {
03940
ASSERT ((
MmPagingFileDebug[StartBit] & 1) == 0);
03941
MmPagingFileDebug[StartBit] =
03942 (((ULONG_PTR)Pfn1->PteAddress << 3) |
03943 ((ClusterSize & 0xf) << 1) | 1);
03944 }
03945
#endif //DBG
03946
03947
03948
03949
03950
03951
03952 Pfn1->OriginalPte = LongPte;
03953
03954 ClusterSize += 1;
03955 Page += 1;
03956 StartBit += 1;
03957
#if 0 // COMMENTED OUT
03958
WriteCluster.Count -= 1;
03959 WriteCluster.StartIndex += 1;
03960
03961 }
while (WriteCluster.Count != 0);
03962
#endif //0
03963
}
else {
03964
03965
03966
03967
03968
03969
03970
03971
03972
03973
MI_GET_MODIFIED_PAGE_BY_COLOR (PageFrameIndex,
03974 NextColor);
03975 }
03976
03977
if (PageFrameIndex ==
MM_EMPTY_LIST) {
03978
break;
03979 }
03980
03981 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
03982
03983 }
03984
03985
if (ClusterSize != ThisCluster) {
03986
03987
03988
03989
03990
03991
03992
03993
RtlClearBits (CurrentPagingFile->
Bitmap,
03994 StartBit,
03995 (ULONG)(ThisCluster - ClusterSize));
03996
03997 CurrentPagingFile->
FreeSpace += ThisCluster - ClusterSize;
03998 CurrentPagingFile->
CurrentUsage -= ThisCluster - ClusterSize;
03999
04000
04001
04002
04003
04004
04005
if (ClusterSize == 0) {
04006
04007
04008
04009
04010
04011
04012
if (IsListEmpty (&ModWriterEntry->
PagingListHead->
ListHead)) {
04013
KeSetEvent (&ModWriterEntry->
PagingListHead->
Event,
04014 0,
04015
FALSE);
04016 }
04017
04018 InsertTailList (&ModWriterEntry->
PagingListHead->
ListHead,
04019 &ModWriterEntry->
Links);
04020
04021
return;
04022 }
04023 }
04024
04025
if (CurrentPagingFile->
PeakUsage <
04026 CurrentPagingFile->
CurrentUsage) {
04027 CurrentPagingFile->
PeakUsage =
04028 CurrentPagingFile->
CurrentUsage;
04029 }
04030
04031 ModWriterEntry->
Mdl.
ByteCount = (ULONG)(ClusterSize *
PAGE_SIZE);
04032 ModWriterEntry->
LastPageToWrite = StartBit - 1;
04033
04034
MmInfoCounters.
DirtyWriteIoCount += 1;
04035
MmInfoCounters.
DirtyPagesWriteCount += (ULONG)ClusterSize;
04036
04037
04038
04039
04040
04041
UNLOCK_PFN (OldIrql);
04042
04043
#if DBG
04044
if (MmDebug &
MM_DBG_MOD_WRITE) {
04045
DbgPrint(
"MM MODWRITE: modified page write begun @ %08lx by %08lx\n",
04046 StartingOffset.LowPart, ModWriterEntry->
Mdl.
ByteCount);
04047 }
04048
#endif
04049
04050
04051
04052
04053
04054
Status =
IoAsynchronousPageWrite (
File,
04055 &ModWriterEntry->
Mdl,
04056 &StartingOffset,
04057
MiWriteComplete,
04058 (PVOID)ModWriterEntry,
04059 &ModWriterEntry->
u.IoStatus,
04060 &ModWriterEntry->Irp );
04061
04062
if (
NT_ERROR(
Status)) {
04063 KdPrint((
"MM MODWRITE: modified page write failed %lx\n",
Status));
04064
04065
04066
04067
04068
04069
04070 ModWriterEntry->u.IoStatus.Status =
Status;
04071 ModWriterEntry->u.IoStatus.Information = 0;
04072
KeRaiseIrql (
APC_LEVEL, &OldIrql);
04073
MiWriteComplete ((PVOID)ModWriterEntry,
04074 &ModWriterEntry->u.IoStatus,
04075 0 );
04076
KeLowerIrql (OldIrql);
04077 }
04078
04079
LOCK_PFN (OldIrql);
04080
04081
if (PageFileFull ==
TRUE) {
04082
MiPageFileFull ();
04083 }
04084
04085
return;
04086 }
04087
04088
04089
#if 0 // COMMENTED OUT **************************************************
04090
ULONG ClusterCounts[20];
04091 ULONG ClusterSizes[20];
04092
VOID
04093
MiClusterWritePages (
04094 IN
PMMPFN Pfn1,
04095 IN PFN_NUMBER PageFrameIndex,
04096 IN PMM_WRITE_CLUSTER WriteCluster,
04097 IN ULONG Size
04098 )
04099
04100 {
04101
PMMPTE PointerClusterPte;
04102
PMMPTE OriginalPte;
04103
PMMPTE StopPte;
04104
PMMPTE ThisPage;
04105
PMMPTE BasePage;
04106 ULONG
Start;
04107
PMMPFN Pfn2;
04108 KIRQL OldIrql = 99;
04109
04110
Start =
MM_MAXIMUM_DISK_IO_SIZE /
PAGE_SIZE;
04111 WriteCluster->Cluster[
Start] = PageFrameIndex;
04112 WriteCluster->Count = 1;
04113 ClusterSizes[
Size] += 1;
04114
if (
Size == 1) {
04115 WriteCluster->StartIndex =
Start;
04116
return;
04117 }
04118
04119
04120
04121
04122
04123
04124
04125 PointerClusterPte = Pfn1->PteAddress;
04126 BasePage = (
PMMPTE)((ULONG_PTR)PointerClusterPte & ~(
PAGE_SIZE - 1));
04127 ThisPage = BasePage;
04128
04129
if ((PointerClusterPte < (
PMMPTE)
PDE_TOP) ||
04130 (!
MmIsAddressValid (PointerClusterPte))) {
04131
04132
04133
04134
04135
04136
04137 PointerClusterPte = (
PMMPTE)((PCHAR)
MiMapPageInHyperSpace (
04138 Pfn1->PteFrame, &OldIrql)
04139 +
04140
BYTE_OFFSET (PointerClusterPte));
04141 ThisPage = (
PMMPTE)((ULONG_PTR)PointerClusterPte & ~(
PAGE_SIZE - 1));
04142 }
04143
04144 OriginalPte = PointerClusterPte;
04145
ASSERT (MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (PointerClusterPte) == PageFrameIndex);
04146
04147
04148
04149
04150
04151
04152 StopPte = PointerClusterPte - (
Size - 1);
04153
if (StopPte < ThisPage) {
04154 StopPte = ThisPage;
04155 }
04156
04157
while (PointerClusterPte > StopPte) {
04158 PointerClusterPte -= 1;
04159
04160
04161
04162
04163
04164
04165
if (BasePage != (
PMMPTE)
04166 (ULONG_PTR)(PointerClusterPte->u.Long & ~(
PAGE_SIZE - 1))) {
04167
04168
if ((PointerClusterPte->u.Hard.Valid == 0) &&
04169 (PointerClusterPte->u.Soft.Prototype == 0) &&
04170 (PointerClusterPte->u.Soft.Transition == 1)) {
04171
04172
04173
04174
04175
04176 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (PointerClusterPte);
04177 Pfn2 =
MI_PFN_ELEMENT(PageFrameIndex);
04178
ASSERT (Pfn2->
OriginalPte.
u.Soft.Prototype == 0);
04179
if ((Pfn2->
u3.e1.Modified != 0 ) &&
04180 (Pfn2->
u3.e2.ReferenceCount == 0)) {
04181
04182
Start -= 1;
04183 WriteCluster->Count += 1;
04184 WriteCluster->Cluster[
Start] = PageFrameIndex;
04185 }
04186 }
04187 }
04188
break;
04189 }
04190
04191 WriteCluster->StartIndex =
Start;
04192 PointerClusterPte = OriginalPte + 1;
04193
Start =
MM_MAXIMUM_DISK_IO_SIZE /
PAGE_SIZE;
04194
04195
04196
04197
04198
04199
04200 ThisPage = (
PMMPTE)((PCHAR)ThisPage +
PAGE_SIZE);
04201
04202
while ((WriteCluster->Count <
Size) &&
04203 (PointerClusterPte < ThisPage)) {
04204
04205
if ((PointerClusterPte->u.Hard.Valid == 0) &&
04206 (PointerClusterPte->u.Soft.Prototype == 0) &&
04207 (PointerClusterPte->u.Soft.Transition == 1)) {
04208
04209
04210
04211
04212
04213 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (PointerClusterPte);
04214 Pfn2 =
MI_PFN_ELEMENT(PageFrameIndex);
04215
ASSERT (Pfn2->
OriginalPte.
u.Soft.Prototype == 0);
04216
if ((Pfn2->
u3.e1.Modified != 0 ) &&
04217 (Pfn2->
u3.e2.ReferenceCount == 0)) {
04218
04219
Start += 1;
04220 WriteCluster->Count += 1;
04221 WriteCluster->Cluster[
Start] = PageFrameIndex;
04222 PointerClusterPte += 1;
04223
continue;
04224 }
04225 }
04226
break;
04227 }
04228
04229
if (OldIrql != 99) {
04230
MiUnmapPageInHyperSpace (OldIrql);
04231 }
04232 ClusterCounts[WriteCluster->Count] += 1;
04233
return;
04234 }
04235
#endif // COMMENTED OUT **************************************************
04236
04237
04238
VOID
04239 MiMappedPageWriter (
04240 IN PVOID StartContext
04241 )
04242
04243
04244
04245
04246
04247
04248
04249
04250
04251
04252
04253
04254
04255
04256
04257
04258
04259
04260
04261
04262
04263
04264
04265
04266
04267
04268
04269
04270 {
04271
PMMMOD_WRITER_MDL_ENTRY ModWriterEntry;
04272 KIRQL OldIrql = 0;
04273
NTSTATUS Status;
04274
KEVENT TempEvent;
04275
04276 UNREFERENCED_PARAMETER (StartContext);
04277
04278
04279
04280
04281
04282 (
VOID)
KeSetPriorityThread (&
PsGetCurrentThread()->Tcb,
04283 LOW_REALTIME_PRIORITY + 1);
04284
04285
04286
04287
04288
04289
FsRtlSetTopLevelIrpForModWriter();
04290
04291
KeInitializeEvent (&TempEvent, NotificationEvent,
FALSE);
04292
04293
while (
TRUE) {
04294
KeWaitForSingleObject (&
MmMappedPageWriterEvent,
04295
WrVirtualMemory,
04296
KernelMode,
04297
FALSE,
04298 (PLARGE_INTEGER)
NULL);
04299
04300
LOCK_PFN (OldIrql);
04301
if (IsListEmpty (&
MmMappedPageWriterList)) {
04302
KeClearEvent (&
MmMappedPageWriterEvent);
04303
UNLOCK_PFN (OldIrql);
04304 }
else {
04305
04306 ModWriterEntry = (
PMMMOD_WRITER_MDL_ENTRY)RemoveHeadList (
04307 &
MmMappedPageWriterList);
04308
04309
UNLOCK_PFN (OldIrql);
04310
04311
04312
if (ModWriterEntry->
ControlArea->
u.Flags.FailAllIo == 1) {
04313
Status = STATUS_UNSUCCESSFUL;
04314
04315 }
else if (
FsRtlAcquireFileForModWrite (ModWriterEntry->
File,
04316 &ModWriterEntry->
u.LastByte,
04317 &ModWriterEntry->
FileResource)) {
04318
04319
04320
04321
04322
04323
Status =
IoAsynchronousPageWrite (
04324 ModWriterEntry->
File,
04325 &ModWriterEntry->
Mdl,
04326 &ModWriterEntry->
WriteOffset,
04327
MiWriteComplete,
04328 (PVOID)ModWriterEntry,
04329 &ModWriterEntry->
u.IoStatus,
04330 &ModWriterEntry->Irp );
04331 }
else {
04332
04333
04334
04335
04336
04337
04338
04339
Status = STATUS_FILE_LOCK_CONFLICT;
04340 }
04341
04342
if (
NT_ERROR(
Status)) {
04343
04344
04345
04346
04347
04348
04349 ModWriterEntry->
u.IoStatus.Status =
Status;
04350 ModWriterEntry->
u.IoStatus.Information = 0;
04351
KeRaiseIrql (
APC_LEVEL, &OldIrql);
04352
MiWriteComplete ((PVOID)ModWriterEntry,
04353 &ModWriterEntry->
u.IoStatus,
04354 0 );
04355
KeLowerIrql (OldIrql);
04356 }
04357
#if 0
04358
04359
04360
04361
04362
04363
04364
Status =
IoSynchronousPageWrite (
04365 ModWriterEntry->
File,
04366 &ModWriterEntry->
Mdl,
04367 &ModWriterEntry->
WriteOffset,
04368 &TempEvent,
04369 &ModWriterEntry->
u.IoStatus );
04370
04371
if (
NT_ERROR(
Status)) {
04372 ModWriterEntry->
u.IoStatus.Status =
Status;
04373 ModWriterEntry->
u.IoStatus.Information = 0;
04374 }
04375
04376
if (
NT_ERROR(ModWriterEntry->
u.IoStatus.Status)) {
04377 KdPrint((
"MM MODWRITE: modified page write failed %lx\n",
Status));
04378 }
04379
04380
04381
04382
04383
04384
KeRaiseIrql (
APC_LEVEL, &OldIrql);
04385
MiWriteComplete ((PVOID)ModWriterEntry,
04386 &ModWriterEntry->
IoStatus,
04387 0 );
04388
KeLowerIrql (OldIrql);
04389
#endif //0
04390
04391 }
04392
04393 }
04394 }
04395
04396 BOOLEAN
04397 MmDisableModifiedWriteOfSection (
04398 IN
PSECTION_OBJECT_POINTERS SectionObjectPointer
04399 )
04400
04401
04402
04403
04404
04405
04406
04407
04408
04409
04410
04411
04412
04413
04414
04415
04416
04417
04418
04419
04420
04421
04422
04423 {
04424
PCONTROL_AREA ControlArea;
04425 KIRQL OldIrql;
04426 BOOLEAN state = 1;
04427
04428
LOCK_PFN (OldIrql);
04429
04430 ControlArea = ((
PCONTROL_AREA)(SectionObjectPointer->DataSectionObject));
04431
04432
if (ControlArea !=
NULL) {
04433
if (ControlArea->
NumberOfMappedViews == 0) {
04434
04435
04436
04437
04438
04439
04440 ControlArea->
u.Flags.NoModifiedWriting = 1;
04441 }
else {
04442
04443
04444
04445
04446
04447 state = (BOOLEAN)ControlArea->
u.Flags.NoModifiedWriting;
04448 }
04449 }
else {
04450
04451
04452
04453
04454
04455 state = 0;
04456 }
04457
04458
UNLOCK_PFN (OldIrql);
04459
return state;
04460 }
04461
04462
04463 #define ROUND_UP(VALUE,ROUND) ((ULONG)(((ULONG)VALUE + \
04464
((ULONG)ROUND - 1L)) & (~((ULONG)ROUND - 1L))))
04465
NTSTATUS
04466 MmGetPageFileInformation (
04467 OUT PVOID SystemInformation,
04468 IN ULONG SystemInformationLength,
04469 OUT PULONG Length
04470 )
04471
04472
04473
04474
04475
04476
04477
04478
04479
04480
04481
04482
04483
04484
04485
04486
04487
04488
04489
04490
04491
04492
04493
04494
04495 {
04496 PSYSTEM_PAGEFILE_INFORMATION PageFileInfo;
04497 ULONG NextEntryOffset = 0;
04498 ULONG TotalSize = 0;
04499 ULONG i;
04500 UNICODE_STRING UserBufferPageFileName;
04501
04502
PAGED_CODE();
04503
04504 *Length = 0;
04505 PageFileInfo = (PSYSTEM_PAGEFILE_INFORMATION)SystemInformation;
04506
04507 PageFileInfo->TotalSize = 0;
04508
04509
for (i = 0; i <
MmNumberOfPagingFiles; i += 1) {
04510 PageFileInfo = (PSYSTEM_PAGEFILE_INFORMATION)(
04511 (PUCHAR)PageFileInfo + NextEntryOffset);
04512 NextEntryOffset =
sizeof(SYSTEM_PAGEFILE_INFORMATION);
04513 TotalSize +=
sizeof(SYSTEM_PAGEFILE_INFORMATION);
04514
04515
if (TotalSize > SystemInformationLength) {
04516
return STATUS_INFO_LENGTH_MISMATCH;
04517 }
04518
04519 PageFileInfo->TotalSize = (ULONG)
MmPagingFile[i]->
Size;
04520 PageFileInfo->TotalInUse = (ULONG)
MmPagingFile[i]->
CurrentUsage;
04521 PageFileInfo->PeakUsage = (ULONG)
MmPagingFile[i]->
PeakUsage;
04522
04523
04524
04525
04526
04527
04528
04529
04530 UserBufferPageFileName.Length =
MmPagingFile[i]->
PageFileName.Length;
04531 UserBufferPageFileName.MaximumLength =
MmPagingFile[i]->
PageFileName.Length +
sizeof(WCHAR);
04532 UserBufferPageFileName.Buffer = (PWCHAR)(PageFileInfo + 1);
04533
04534 PageFileInfo->PageFileName = UserBufferPageFileName;
04535
04536 TotalSize +=
ROUND_UP (UserBufferPageFileName.MaximumLength,
04537
sizeof(ULONG));
04538 NextEntryOffset +=
ROUND_UP (UserBufferPageFileName.MaximumLength,
04539
sizeof(ULONG));
04540
04541
if (TotalSize > SystemInformationLength) {
04542
return STATUS_INFO_LENGTH_MISMATCH;
04543 }
04544
04545
04546
04547
04548
04549 RtlMoveMemory(UserBufferPageFileName.Buffer,
04550
MmPagingFile[i]->
PageFileName.Buffer,
04551
MmPagingFile[i]->
PageFileName.Length);
04552 UserBufferPageFileName.Buffer[
04553
MmPagingFile[i]->
PageFileName.Length/
sizeof(WCHAR)] = UNICODE_NULL;
04554 PageFileInfo->NextEntryOffset = NextEntryOffset;
04555 }
04556 PageFileInfo->NextEntryOffset = 0;
04557 *Length = TotalSize;
04558
return STATUS_SUCCESS;
04559 }
04560
04561
04562
NTSTATUS
04563 MiCheckPageFileMapping (
04564 IN
PFILE_OBJECT File
04565 )
04566
04567
04568
04569
04570
04571
04572
04573
04574
04575
04576
04577
04578
04579
04580
04581
04582
04583
04584 {
04585 KIRQL OldIrql;
04586
04587
LOCK_PFN (OldIrql);
04588
04589
if (
File->SectionObjectPointer ==
NULL) {
04590
UNLOCK_PFN (OldIrql);
04591
return STATUS_SUCCESS;
04592 }
04593
04594
if ((
File->SectionObjectPointer->DataSectionObject !=
NULL) ||
04595 (
File->SectionObjectPointer->ImageSectionObject !=
NULL)) {
04596
04597
UNLOCK_PFN (OldIrql);
04598
return STATUS_INCOMPATIBLE_FILE_MAP;
04599 }
04600
UNLOCK_PFN (OldIrql);
04601
return STATUS_SUCCESS;
04602
04603 }
04604
04605
04606
VOID
04607 MiInsertPageFileInList (
04608 VOID
04609 )
04610
04611
04612
04613
04614
04615
04616
04617
04618
04619
04620
04621
04622
04623
04624
04625
04626
04627
04628 {
04629 KIRQL OldIrql;
04630 ULONG
Count;
04631
04632
LOCK_PFN (OldIrql);
04633
04634
MmNumberOfPagingFiles += 1;
04635
Count =
MmNumberOfPagingFiles;
04636
04637
if (IsListEmpty (&
MmPagingFileHeader.
ListHead)) {
04638
KeSetEvent (&
MmPagingFileHeader.
Event, 0,
FALSE);
04639 }
04640
04641 InsertTailList (&
MmPagingFileHeader.
ListHead,
04642 &
MmPagingFile[
MmNumberOfPagingFiles - 1]->Entry[0]->Links);
04643
04644
MmPagingFile[
MmNumberOfPagingFiles - 1]->
Entry[0]->
CurrentList =
04645 &
MmPagingFileHeader.
ListHead;
04646
04647 InsertTailList (&
MmPagingFileHeader.
ListHead,
04648 &
MmPagingFile[
MmNumberOfPagingFiles - 1]->Entry[1]->Links);
04649
04650
MmPagingFile[
MmNumberOfPagingFiles - 1]->
Entry[1]->
CurrentList =
04651 &
MmPagingFileHeader.
ListHead;
04652
04653
MmNumberOfActiveMdlEntries += 2;
04654
04655
UNLOCK_PFN (OldIrql);
04656
04657
04658 ExAcquireSpinLock (&
MmChargeCommitmentLock, &OldIrql);
04659
04660
if (
Count == 1) {
04661
04662
04663
04664
04665
04666
04667
MmTotalCommitLimit =
04668
MmPagingFile[
MmNumberOfPagingFiles - 1]->
FreeSpace +
MmOverCommit;
04669
04670
MmTotalCommitLimitMaximum =
04671
MmPagingFile[
MmNumberOfPagingFiles - 1]->
MaximumSize +
MmOverCommit;
04672
04673
04674
04675
04676
04677
04678
if (
MmTotalCommitLimit < 5500) {
04679
MmOverCommit2 = 5500 -
MmTotalCommitLimit;
04680
MmTotalCommitLimit = 5500;
04681 }
04682
04683
if (
MmTotalCommitLimitMaximum < 5500) {
04684
MmTotalCommitLimitMaximum =
MmTotalCommitLimit;
04685 }
04686
04687 }
else {
04688
04689
04690
04691
04692
04693
if (
MmOverCommit2 >
MmPagingFile[
MmNumberOfPagingFiles - 1]->
FreeSpace) {
04694
MmOverCommit2 -=
MmPagingFile[
MmNumberOfPagingFiles - 1]->
FreeSpace;
04695 }
else {
04696
MmTotalCommitLimit +=
04697
MmPagingFile[
MmNumberOfPagingFiles - 1]->
FreeSpace -
MmOverCommit2;
04698
MmTotalCommitLimitMaximum +=
04699
MmPagingFile[
MmNumberOfPagingFiles - 1]->
MaximumSize -
MmOverCommit2;
04700
MmOverCommit2 = 0;
04701 }
04702 }
04703
04704 ExReleaseSpinLock (&
MmChargeCommitmentLock, OldIrql);
04705
return;
04706 }
04707
04708
VOID
04709 MiPageFileFull (
04710 )
04711
04712
04713
04714
04715
04716
04717
04718
04719
04720
04721
04722
04723
04724
04725
04726
04727
04728
04729
04730
04731
04732
04733 {
04734 ULONG i;
04735 PFN_NUMBER Total;
04736 PFN_NUMBER Free;
04737 KIRQL OldIrql;
04738 SIZE_T SizeToExpand;
04739
04740
MM_PFN_LOCK_ASSERT();
04741
04742 Total = 0;
04743 Free = 0;
04744 OldIrql = 0;
04745
04746 i = 0;
04747
do {
04748 Total +=
MmPagingFile[i]->
Size;
04749 Free +=
MmPagingFile[i]->
FreeSpace;
04750 i += 1;
04751 }
while (i <
MmNumberOfPagingFiles);
04752
04753
04754
04755
04756
04757
if (((Total >> 5) + (Total >> 4)) >= Free) {
04758
04759
04760
04761
04762
04763
UNLOCK_PFN (OldIrql);
04764
04765
04766
04767
04768
04769
04770
04771
04772
04773 SizeToExpand = 0;
04774 i = 0;
04775
04776 ExAcquireSpinLock (&
MmChargeCommitmentLock, &OldIrql);
04777
04778
do {
04779 SizeToExpand +=
MmPagingFile[i]->
MaximumSize -
MmPagingFile[i]->
Size;
04780 i += 1;
04781 }
while (i <
MmNumberOfPagingFiles);
04782
04783
if (SizeToExpand == 0) {
04784 ExReleaseSpinLock (&
MmChargeCommitmentLock, OldIrql);
04785
04786
04787
04788
04789
04790
if (
MmPageFileFullPopupShown ==
FALSE) {
04791
MmPageFileFullPopupShown =
TRUE;
04792
MiCauseOverCommitPopup (1, 0);
04793 }
04794
04795
LOCK_PFN (OldIrql);
04796
return;
04797 }
04798
04799
if (
MmTotalCommittedPages <=
MmTotalCommitLimit + 50) {
04800
04801
04802
04803
04804
04805
04806
if (
MmTotalCommittedPages <
MmTotalCommitLimit) {
04807
04808
if (
MmPageFileFullExtendPages) {
04809
ASSERT (
MmTotalCommittedPages >=
MmPageFileFullExtendPages);
04810
MmTotalCommittedPages -=
MmPageFileFullExtendPages;
04811
MmPageFileFullExtendPages = 0;
04812 }
04813
04814
MmPageFileFullExtendPages =
MmTotalCommitLimit -
MmTotalCommittedPages;
04815
MmPageFileFullExtendCount += 1;
04816
04817
MmTotalCommittedPages =
MmTotalCommitLimit;
04818 }
04819
04820
04821
04822
04823
04824
MiPageFileFullCharge +=
MI_PAGEFILE_FULL_CHARGE;
04825
04826 ExReleaseSpinLock (&
MmChargeCommitmentLock, OldIrql);
04827
04828
MiChargeCommitmentCantExpand (
MI_PAGEFILE_FULL_CHARGE,
TRUE);
04829
04830
MM_TRACK_COMMIT (
MM_DBG_COMMIT_PAGEFILE_FULL, 100);
04831
04832
04833
04834
04835
04836
if (
MmPageFileFullPopupShown ==
FALSE) {
04837
MmPageFileFullPopupShown =
TRUE;
04838
MiCauseOverCommitPopup (1, 0);
04839 }
04840
04841
04842
04843
04844
04845
04846
if (
MiPageFileFullCharge >= 5 *
MI_PAGEFILE_FULL_CHARGE) {
04847 ExAcquireSpinLock (&
MmChargeCommitmentLock, &OldIrql);
04848 SizeToExpand =
MiPageFileFullCharge;
04849
MiPageFileFullCharge = 0;
04850 ExReleaseSpinLock (&
MmChargeCommitmentLock, OldIrql);
04851
MiReturnCommitment (SizeToExpand);
04852 }
04853
04854 }
04855
else {
04856
04857
04858
04859
04860
04861 ExReleaseSpinLock (&
MmChargeCommitmentLock, OldIrql);
04862 }
04863
04864
LOCK_PFN (OldIrql);
04865 }
04866
return;
04867 }
04868
04869
VOID
04870 MiFlushAllPages (
04871 VOID
04872 )
04873
04874
04875
04876
04877
04878
04879
04880
04881
04882
04883
04884
04885
04886
04887
04888
04889
04890
04891
04892
04893
04894 {
04895 ULONG j = 0xff;
04896
04897
MmWriteAllModifiedPages =
TRUE;
04898
KeSetEvent (&
MmModifiedPageWriterEvent, 0,
FALSE);
04899
04900
do {
04901
KeDelayExecutionThread (
KernelMode,
FALSE, &
Mm30Milliseconds);
04902 j -= 1;
04903 }
while ((
MmModifiedPageListHead.
Total > 50) && (j > 0));
04904
04905
MmWriteAllModifiedPages =
FALSE;
04906
return;
04907 }
04908
04909
04910 LOGICAL
04911 MiIssuePageExtendRequest (
04912 IN
PMMPAGE_FILE_EXPANSION PageExtend
04913 )
04914
04915
04916
04917
04918
04919
04920
04921
04922
04923
04924
04925
04926
04927
04928
04929
04930
04931
04932
04933
04934
04935
04936
04937
04938
04939 {
04940 KIRQL OldIrql;
04941
NTSTATUS status;
04942 PLIST_ENTRY NextEntry;
04943
04944 ExAcquireFastLock (&
MmDereferenceSegmentHeader.
Lock, &OldIrql);
04945 InsertTailList ( &
MmDereferenceSegmentHeader.
ListHead,
04946 &PageExtend->DereferenceList);
04947 ExReleaseFastLock (&
MmDereferenceSegmentHeader.
Lock, OldIrql);
04948
04949
KeReleaseSemaphore (&
MmDereferenceSegmentHeader.
Semaphore,
04950 0
L,
04951 1
L,
04952
TRUE);
04953
04954
04955
04956
04957
04958 status =
KeWaitForSingleObject (&PageExtend->Event,
04959
Executive,
04960
KernelMode,
04961
FALSE,
04962 (PageExtend->RequestedExpansionSize < 10) ?
04963 &
MmOneSecond : &
MmTwentySeconds);
04964
04965
if (status == STATUS_TIMEOUT) {
04966
04967
04968
04969
04970
04971
04972
04973
04974
04975
04976
04977 KdPrint((
"MiIssuePageExtendRequest: wait timed out, page-extend= %lx, quota = %lx\n",
04978 PageExtend, PageExtend->RequestedExpansionSize));
04979
04980 ExAcquireFastLock (&
MmDereferenceSegmentHeader.
Lock, &OldIrql);
04981
04982 NextEntry =
MmDereferenceSegmentHeader.
ListHead.Flink;
04983
04984
while (NextEntry != &
MmDereferenceSegmentHeader.
ListHead) {
04985
04986
04987
04988
04989
04990
if (NextEntry == &PageExtend->DereferenceList) {
04991
04992
04993
04994
04995
04996 RemoveEntryList (&PageExtend->DereferenceList);
04997 ExReleaseFastLock (&
MmDereferenceSegmentHeader.
Lock, OldIrql);
04998
return FALSE;
04999 }
05000 NextEntry = NextEntry->Flink;
05001 }
05002
05003 ExReleaseFastLock (&
MmDereferenceSegmentHeader.
Lock, OldIrql);
05004
05005
05006
05007
05008
05009 KdPrint ((
"MiIssuePageExtendRequest: rewaiting...\n"));
05010
05011
KeWaitForSingleObject (&PageExtend->Event,
05012
Executive,
05013
KernelMode,
05014
FALSE,
05015
NULL);
05016 }
05017
05018
return TRUE;
05019 }
05020
05021
05022
VOID
05023 MiIssuePageExtendRequestNoWait (
05024 IN PFN_NUMBER SizeInPages
05025 )
05026
05027
05028
05029
05030
05031
05032
05033
05034
05035
05036
05037
05038
05039
05040
05041
05042
05043
05044
05045
05046
05047
05048
05049
05050
05051
05052
05053
05054
05055 {
05056 KIRQL OldIrql;
05057
NTSTATUS status;
05058 PLIST_ENTRY NextEntry;
05059
05060
ASSERT (KeGetCurrentIrql() <
DISPATCH_LEVEL);
05061
05062 ExAcquireFastLock (&
MmChargeCommitmentLock, &OldIrql);
05063
05064
if (
MmAttemptForCantExtend.
InProgress !=
FALSE) {
05065
05066
05067
05068
05069
05070
05071
05072 ExReleaseFastLock (&
MmChargeCommitmentLock, OldIrql);
05073
return;
05074 }
05075
05076
MmAttemptForCantExtend.
InProgress =
TRUE;
05077 ExReleaseFastLock (&
MmChargeCommitmentLock, OldIrql);
05078
05079 SizeInPages = (SizeInPages +
ONEMB_IN_PAGES - 1) & ~(
ONEMB_IN_PAGES - 1);
05080
05081
MmAttemptForCantExtend.
RequestedExpansionSize = SizeInPages;
05082
05083 ExAcquireFastLock (&
MmDereferenceSegmentHeader.
Lock, &OldIrql);
05084
05085 InsertTailList ( &
MmDereferenceSegmentHeader.
ListHead,
05086 &
MmAttemptForCantExtend.
DereferenceList);
05087
05088 ExReleaseFastLock (&
MmDereferenceSegmentHeader.
Lock, OldIrql);
05089
05090
KeReleaseSemaphore (&
MmDereferenceSegmentHeader.
Semaphore,
05091 0
L,
05092 1
L,
05093
FALSE);
05094
05095
return;
05096 }