00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
#include "mi.h"
00024
00025 extern ULONG
MmSystemShutdown;
00026
00027
VOID
00028
MmReleaseAllMemory (
00029 VOID
00030 );
00031
00032
#ifdef ALLOC_PRAGMA
00033
#pragma alloc_text(PAGELK,MmShutdownSystem)
00034
#pragma alloc_text(PAGEVRFY,MmReleaseAllMemory)
00035
#endif
00036
00037 ULONG
MmZeroPageFile;
00038
00039
00040 BOOLEAN
00041 MmShutdownSystem (
00042 VOID
00043 )
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 {
00064 PFN_NUMBER ModifiedPage;
00065
PMMPFN Pfn1;
00066
PSUBSECTION Subsection;
00067
PCONTROL_AREA ControlArea;
00068 PPFN_NUMBER Page;
00069 PFN_NUMBER MdlHack[(
sizeof(
MDL)/
sizeof(PFN_NUMBER)) +
MM_MAXIMUM_WRITE_CLUSTER];
00070
PMDL Mdl;
00071
NTSTATUS Status;
00072
KEVENT IoEvent;
00073 IO_STATUS_BLOCK IoStatus;
00074 KIRQL OldIrql;
00075 LARGE_INTEGER StartingOffset;
00076 ULONG count;
00077 PFN_NUMBER j;
00078 ULONG k;
00079 PFN_NUMBER first;
00080 ULONG write;
00081
PMMPAGING_FILE PagingFile;
00082
00083
00084
00085
00086
00087
if (!
MmSystemShutdown) {
00088
00089
MmLockPagableSectionByHandle(
ExPageLockHandle);
00090
00091 Mdl = (
PMDL)&MdlHack;
00092 Page = (PPFN_NUMBER)(Mdl + 1);
00093
00094
KeInitializeEvent (&IoEvent, NotificationEvent,
FALSE);
00095
00096
MmInitializeMdl(Mdl,
00097
NULL,
00098
PAGE_SIZE);
00099
00100 Mdl->
MdlFlags |=
MDL_PAGES_LOCKED;
00101
00102
LOCK_PFN (OldIrql);
00103
00104 ModifiedPage =
MmModifiedPageListHead.
Flink;
00105
while (ModifiedPage !=
MM_EMPTY_LIST) {
00106
00107
00108
00109
00110
00111 Pfn1 =
MI_PFN_ELEMENT (ModifiedPage);
00112
00113
if (Pfn1->
OriginalPte.
u.Soft.Prototype == 1) {
00114
00115
00116
00117
00118
00119 Subsection =
MiGetSubsectionAddress (&Pfn1->
OriginalPte);
00120 ControlArea = Subsection->
ControlArea;
00121
if ((!ControlArea->
u.Flags.Image) &&
00122 (!ControlArea->
u.Flags.NoModifiedWriting)) {
00123
00124
MiUnlinkPageFromList (Pfn1);
00125
00126
00127
00128
00129
00130 Pfn1->
u3.e1.Modified = 0;
00131
00132
00133
00134
00135
00136
00137
MI_ADD_LOCKED_PAGE_CHARGE_FOR_MODIFIED_PAGE (Pfn1, 26);
00138 Pfn1->
u3.e2.ReferenceCount += 1;
00139
00140 *Page = ModifiedPage;
00141 ControlArea->
NumberOfMappedViews += 1;
00142 ControlArea->
NumberOfPfnReferences += 1;
00143
00144
UNLOCK_PFN (OldIrql);
00145
00146 StartingOffset.QuadPart =
MiStartingOffset (Subsection,
00147 Pfn1->
PteAddress);
00148
00149 Mdl->
StartVa = (PVOID)ULongToPtr(Pfn1->
u3.e1.PageColor <<
PAGE_SHIFT);
00150
KeClearEvent (&IoEvent);
00151
Status =
IoSynchronousPageWrite (
00152 ControlArea->
FilePointer,
00153 Mdl,
00154 &StartingOffset,
00155 &IoEvent,
00156 &IoStatus );
00157
00158
00159
00160
00161
00162
00163
if (!
NT_SUCCESS(
Status)) {
00164
KeSetEvent (&IoEvent, 0,
FALSE);
00165 }
00166
00167
Status =
KeWaitForSingleObject (&IoEvent,
00168
WrPageOut,
00169
KernelMode,
00170
FALSE,
00171 (PLARGE_INTEGER)&
MmTwentySeconds);
00172
00173
if (Mdl->
MdlFlags &
MDL_MAPPED_TO_SYSTEM_VA) {
00174
MmUnmapLockedPages (Mdl->
MappedSystemVa, Mdl);
00175 }
00176
00177
if (
Status == STATUS_TIMEOUT) {
00178
00179
00180
00181
00182
00183
00184
00185
LOCK_PFN (OldIrql);
00186 Pfn1->
u3.e1.Modified = 1;
00187
MI_REMOVE_LOCKED_PAGE_CHARGE (Pfn1, 27);
00188
MiDecrementReferenceCount (ModifiedPage);
00189 ControlArea->
NumberOfMappedViews -= 1;
00190 ControlArea->
NumberOfPfnReferences -= 1;
00191
00192
00193
00194
00195
00196
MiCheckControlArea (ControlArea,
NULL, OldIrql);
00197
00198
MmUnlockPagableImageSection(
ExPageLockHandle);
00199
00200
return FALSE;
00201 }
00202
00203
LOCK_PFN (OldIrql);
00204
MI_REMOVE_LOCKED_PAGE_CHARGE (Pfn1, 27);
00205
MiDecrementReferenceCount (ModifiedPage);
00206 ControlArea->
NumberOfMappedViews -= 1;
00207 ControlArea->
NumberOfPfnReferences -= 1;
00208
00209
00210
00211
00212
00213
MiCheckControlArea (ControlArea,
NULL, OldIrql);
00214
LOCK_PFN (OldIrql);
00215
00216
00217
00218
00219
00220 ModifiedPage =
MmModifiedPageListHead.
Flink;
00221
continue;
00222 }
00223 }
00224 ModifiedPage = Pfn1->
u1.Flink;
00225 }
00226
00227
UNLOCK_PFN (OldIrql);
00228
00229
00230
00231
00232
00233
00234
if (
MmAvailablePages < (
MmFreeGoal * 2)) {
00235 LARGE_INTEGER FiveSeconds = {(ULONG)(-5 * 1000 * 1000 * 10), -1};
00236
00237
KeSetEvent (&
MmModifiedPageWriterEvent, 0,
FALSE);
00238
KeDelayExecutionThread (
KernelMode,
00239
FALSE,
00240 (PLARGE_INTEGER)&FiveSeconds);
00241 }
00242
00243
00244
00245
00246
00247
00248
MmSystemShutdown = 1;
00249
00250
00251
00252
00253
00254
00255
if (
MmZeroPageFile) {
00256
00257
00258
00259
00260
00261 Mdl->
StartVa =
NULL;
00262 j = 0;
00263 k = 0;
00264 Page = (PPFN_NUMBER)(Mdl + 1);
00265
00266
LOCK_PFN (OldIrql);
00267
00268
if (
MmAvailablePages < (
MmModifiedWriteClusterSize + 20)) {
00269
UNLOCK_PFN(OldIrql);
00270
MmUnlockPagableImageSection(
ExPageLockHandle);
00271
return TRUE;
00272 }
00273
00274
do {
00275 *Page =
MiRemoveZeroPage ((ULONG)j);
00276 Pfn1 =
MI_PFN_ELEMENT (*Page);
00277 Pfn1->
u3.e2.ReferenceCount = 1;
00278
ASSERT (Pfn1->
u2.ShareCount == 0);
00279 Pfn1->
OriginalPte.
u.Long = 0;
00280
MI_SET_PFN_DELETED (Pfn1);
00281 Page += 1;
00282 j += 1;
00283 }
while (j <
MmModifiedWriteClusterSize);
00284
00285
while (k <
MmNumberOfPagingFiles) {
00286
00287 PagingFile =
MmPagingFile[k];
00288
00289 count = 0;
00290 write =
FALSE;
00291
00292
for (j = 1; j < PagingFile->
Size; j += 1) {
00293
00294
if (RtlCheckBit (PagingFile->
Bitmap, j) == 0) {
00295
00296
if (count == 0) {
00297 first = j;
00298 }
00299 count += 1;
00300
if (count ==
MmModifiedWriteClusterSize) {
00301 write =
TRUE;
00302 }
00303 }
else {
00304
if (count != 0) {
00305
00306
00307
00308
00309
00310 write =
TRUE;
00311 }
00312 }
00313
00314
if ((j == (PagingFile->
Size - 1)) &&
00315 (count != 0)) {
00316 write =
TRUE;
00317 }
00318
00319
if (write) {
00320
00321
UNLOCK_PFN (OldIrql);
00322
00323 StartingOffset.QuadPart = (LONGLONG)first <<
PAGE_SHIFT;
00324 Mdl->
ByteCount = count <<
PAGE_SHIFT;
00325
KeClearEvent (&IoEvent);
00326
00327
Status =
IoSynchronousPageWrite (PagingFile->
File,
00328 Mdl,
00329 &StartingOffset,
00330 &IoEvent,
00331 &IoStatus);
00332
00333
00334
00335
00336
00337
00338
if (!
NT_SUCCESS(
Status)) {
00339
KeSetEvent (&IoEvent, 0,
FALSE);
00340 }
00341
00342
Status =
KeWaitForSingleObject (&IoEvent,
00343
WrPageOut,
00344
KernelMode,
00345
FALSE,
00346 (PLARGE_INTEGER)&
MmTwentySeconds);
00347
00348
if (Mdl->
MdlFlags &
MDL_MAPPED_TO_SYSTEM_VA) {
00349
MmUnmapLockedPages (Mdl->
MappedSystemVa, Mdl);
00350 }
00351
00352
if (
Status == STATUS_TIMEOUT) {
00353
00354
00355
00356
00357
00358
00359
00360 j = 0;
00361 Page = (PPFN_NUMBER)(Mdl + 1);
00362
LOCK_PFN (OldIrql);
00363
do {
00364
MiDecrementReferenceCount (*Page);
00365 Page += 1;
00366 j += 1;
00367 }
while (j <
MmModifiedWriteClusterSize);
00368
UNLOCK_PFN (OldIrql);
00369
00370
MmUnlockPagableImageSection(
ExPageLockHandle);
00371
return FALSE;
00372 }
00373
00374 count = 0;
00375 write =
FALSE;
00376
LOCK_PFN (OldIrql);
00377 }
00378 }
00379 k += 1;
00380 }
00381 j = 0;
00382 Page = (PPFN_NUMBER)(Mdl + 1);
00383
do {
00384
MiDecrementReferenceCount (*Page);
00385 Page += 1;
00386 j += 1;
00387 }
while (j <
MmModifiedWriteClusterSize);
00388
UNLOCK_PFN (OldIrql);
00389 }
00390
MmUnlockPagableImageSection(
ExPageLockHandle);
00391 }
00392
return TRUE;
00393 }