NTSTATUS NTAPI _MmSetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER Offset, ULONG_PTR Entry, const char *file, int line) { ULONG_PTR PageIndex, OldEntry; PCACHE_SECTION_PAGE_TABLE PageTable; ASSERT(Segment->Locked); ASSERT(!IS_SWAP_FROM_SSE(Entry) || !IS_DIRTY_SSE(Entry)); if (Entry && !IS_SWAP_FROM_SSE(Entry)) MmGetRmapListHeadPage(PFN_FROM_SSE(Entry)); PageTable = MiSectionPageTableGetOrAllocate(&Segment->PageTable, Offset); if (!PageTable) return STATUS_NO_MEMORY; ASSERT(MiSectionPageTableGet(&Segment->PageTable, Offset)); PageTable->Segment = Segment; PageIndex = (ULONG_PTR)((Offset->QuadPart - PageTable->FileOffset.QuadPart) / PAGE_SIZE); OldEntry = PageTable->PageEntries[PageIndex]; DPRINT("MiSetPageEntrySectionSegment(%p,%08x%08x,%x=>%x)\n", Segment, Offset->u.HighPart, Offset->u.LowPart, OldEntry, Entry); if (PFN_FROM_SSE(Entry) == PFN_FROM_SSE(OldEntry)) { /* Nothing */ } else if (Entry && !IS_SWAP_FROM_SSE(Entry)) { ASSERT(!OldEntry || IS_SWAP_FROM_SSE(OldEntry)); MmSetSectionAssociation(PFN_FROM_SSE(Entry), Segment, Offset); } else if (OldEntry && !IS_SWAP_FROM_SSE(OldEntry)) { ASSERT(!Entry || IS_SWAP_FROM_SSE(Entry)); MmDeleteSectionAssociation(PFN_FROM_SSE(OldEntry)); } else if (IS_SWAP_FROM_SSE(Entry)) { ASSERT(!IS_SWAP_FROM_SSE(OldEntry) || SWAPENTRY_FROM_SSE(OldEntry) == MM_WAIT_ENTRY); if (OldEntry && SWAPENTRY_FROM_SSE(OldEntry) != MM_WAIT_ENTRY) MmDeleteSectionAssociation(PFN_FROM_SSE(OldEntry)); } else if (IS_SWAP_FROM_SSE(OldEntry)) { ASSERT(!IS_SWAP_FROM_SSE(Entry)); if (Entry) MmSetSectionAssociation(PFN_FROM_SSE(OldEntry), Segment, Offset); } else { /* We should not be replacing a page like this */ ASSERT(FALSE); } PageTable->PageEntries[PageIndex] = Entry; return STATUS_SUCCESS; }
/* MmWithdrawSectionPage removes a page entry from the section segment, replacing it with a wait entry. The caller must replace the wait entry with a 0, when any required writing is done. The wait entry must remain until the page is written to protect against cases where a fault brings a stale copy of the page back before writing is complete. */ PFN_NUMBER NTAPI MmWithdrawSectionPage(PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER FileOffset, BOOLEAN *Dirty) { ULONG_PTR Entry; DPRINT("MmWithdrawSectionPage(%p,%08x%08x,%p)\n", Segment, FileOffset->HighPart, FileOffset->LowPart, Dirty); MmLockSectionSegment(Segment); Entry = MmGetPageEntrySectionSegment(Segment, FileOffset); *Dirty = !!IS_DIRTY_SSE(Entry); DPRINT("Withdraw %x (%x) of %wZ\n", FileOffset->LowPart, Entry, Segment->FileObject ? &Segment->FileObject->FileName : NULL); if (!Entry) { DPRINT("Stoeled!\n"); MmUnlockSectionSegment(Segment); return 0; } else if (MM_IS_WAIT_PTE(Entry)) { DPRINT("WAIT\n"); MmUnlockSectionSegment(Segment); return MM_WAIT_ENTRY; } else if (Entry && !IS_SWAP_FROM_SSE(Entry)) { DPRINT("Page %x\n", PFN_FROM_SSE(Entry)); *Dirty |= (Entry & 2); MmSetPageEntrySectionSegment(Segment, FileOffset, MAKE_SWAP_SSE(MM_WAIT_ENTRY)); MmUnlockSectionSegment(Segment); return PFN_FROM_SSE(Entry); } else { DPRINT1("SWAP ENTRY?! (%p:%08x%08x)\n", Segment, FileOffset->HighPart, FileOffset->LowPart); ASSERT(FALSE); MmUnlockSectionSegment(Segment); return 0; } }