static VOID MmDeletePageTablePfn(PFN_NUMBER PageFrameNumber, ULONG Level) { PMMPTE PageTable; KIRQL OldIrql; PMMPFN PfnEntry; ULONG i, NumberEntries; /* Check if this is a page table */ if (Level > 0) { NumberEntries = (Level == 4) ? MiAddressToPxi(MmHighestUserAddress)+1 : 512; /* Map the page table in hyperspace */ PageTable = (PMMPTE)MmCreateHyperspaceMapping(PageFrameNumber); /* Loop all page table entries */ for (i = 0; i < NumberEntries; i++) { /* Check if the entry is valid */ if (PageTable[i].u.Hard.Valid) { /* Recursively free the page that backs it */ MmDeletePageTablePfn(PageTable[i].u.Hard.PageFrameNumber, Level - 1); } } /* Delete the hyperspace mapping */ MmDeleteHyperspaceMapping(PageTable); } /* Check if this is a legacy allocation */ PfnEntry = MiGetPfnEntry(PageFrameNumber); if (MI_IS_ROS_PFN(PfnEntry)) { /* Free it using the legacy API */ MmReleasePageMemoryConsumer(MC_SYSTEM, PageFrameNumber); } else { OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); /* Free it using the ARM3 API */ MI_SET_PFN_DELETED(PfnEntry); MiDecrementShareCount(PfnEntry, PageFrameNumber); KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql); } }
NTSTATUS NTAPI _MiWriteBackPage (PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, PFN_NUMBER Page, const char *File, int Line) { NTSTATUS Status; PVOID Hyperspace; IO_STATUS_BLOCK Iosb; KIRQL OldIrql; PVOID PageBuffer = ExAllocatePool(NonPagedPool, PAGE_SIZE); if (!PageBuffer) return STATUS_NO_MEMORY; KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); Hyperspace = MmCreateHyperspaceMapping(Page); RtlCopyMemory(PageBuffer, Hyperspace, PAGE_SIZE); MmDeleteHyperspaceMapping(Hyperspace); KeLowerIrql(OldIrql); DPRINT1("MiWriteBackPage(%wZ,%08x%08x,%s:%d)\n", &FileObject->FileName, FileOffset->u.HighPart, FileOffset->u.LowPart, File, Line); Status = MiSimpleWrite (FileObject, FileOffset, PageBuffer, Length, &Iosb); ExFreePool(PageBuffer); if (!NT_SUCCESS(Status)) { DPRINT1("MiSimpleWrite failed (%x)\n", Status); } return Status; }