📄 page.c
字号:
}
else
{
MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
}
if (Process != NULL && Process != CurrentProcess)
{
KeDetachProcess();
}
}
static PULONGLONG
MmGetPageTableForProcessForPAE(PEPROCESS Process, PVOID Address, BOOLEAN Create)
{
NTSTATUS Status;
PFN_TYPE Pfn;
ULONGLONG Entry;
ULONGLONG ZeroEntry = 0LL;
PULONGLONG Pt;
PULONGLONG PageDir;
PULONGLONG PageDirTable;
DPRINT("MmGetPageTableForProcessForPAE(%x %x %d)\n",
Process, Address, Create);
if (Address >= (PVOID)PAGETABLE_MAP && Address < (PVOID)((ULONG_PTR)PAGETABLE_MAP + 0x800000))
{
KEBUGCHECK(0);
}
if (Address < MmSystemRangeStart && Process && Process != PsGetCurrentProcess())
{
PageDirTable = MmCreateHyperspaceMapping(PAE_PTE_TO_PFN(Process->Pcb.DirectoryTableBase.QuadPart));
if (PageDirTable == NULL)
{
KEBUGCHECK(0);
}
PageDir = MmCreateHyperspaceMapping(PAE_PTE_TO_PFN(PageDirTable[PAE_ADDR_TO_PDTE_OFFSET(Address)]));
MmDeleteHyperspaceMapping(PageDirTable);
if (PageDir == NULL)
{
KEBUGCHECK(0);
}
PageDir += PAE_ADDR_TO_PDE_PAGE_OFFSET(Address);
Entry = ExfInterlockedCompareExchange64UL(PageDir, &ZeroEntry, &ZeroEntry);
if (Entry == 0LL)
{
if (Create == FALSE)
{
MmDeleteHyperspaceMapping(PageDir);
return NULL;
}
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn);
if (!NT_SUCCESS(Status))
{
KEBUGCHECK(0);
}
Entry = PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE | PA_USER;
Entry = ExfInterlockedCompareExchange64UL(PageDir, &Entry, &ZeroEntry);
if (Entry != 0LL)
{
MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
Pfn = PAE_PTE_TO_PFN(Entry);
}
}
else
{
Pfn = PAE_PTE_TO_PFN(Entry);
}
MmDeleteHyperspaceMapping(PageDir);
Pt = MmCreateHyperspaceMapping(Pfn);
if (Pt == NULL)
{
KEBUGCHECK(0);
}
return Pt + PAE_ADDR_TO_PTE_OFFSET(Address);
}
PageDir = PAE_ADDR_TO_PDE(Address);
if (0LL == ExfInterlockedCompareExchange64UL(PageDir, &ZeroEntry, &ZeroEntry))
{
if (Address >= MmSystemRangeStart)
{
if (MmGlobalKernelPageDirectoryForPAE[PAE_ADDR_TO_PDE_OFFSET(Address)] == 0LL)
{
if (Create == FALSE)
{
return NULL;
}
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn);
if (!NT_SUCCESS(Status))
{
KEBUGCHECK(0);
}
Entry = PAE_PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE;
if (Ke386GlobalPagesEnabled)
{
Entry |= PA_GLOBAL;
}
if (0LL != ExfInterlockedCompareExchange64UL(&MmGlobalKernelPageDirectoryForPAE[PAE_ADDR_TO_PDE_OFFSET(Address)], &Entry, &ZeroEntry))
{
MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
}
}
(void)ExfInterlockedCompareExchange64UL(PageDir, &MmGlobalKernelPageDirectoryForPAE[PAE_ADDR_TO_PDE_OFFSET(Address)], &ZeroEntry);
}
else
{
if (Create == FALSE)
{
return NULL;
}
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn);
if (!NT_SUCCESS(Status))
{
KEBUGCHECK(0);
}
Entry = PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE | PA_USER;
Entry = ExfInterlockedCompareExchange64UL(PageDir, &Entry, &ZeroEntry);
if (Entry != 0LL)
{
MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
}
}
}
return (PULONGLONG)PAE_ADDR_TO_PTE(Address);
}
static PULONG
MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create)
{
ULONG PdeOffset = ADDR_TO_PDE_OFFSET(Address);
NTSTATUS Status;
PFN_TYPE Pfn;
ULONG Entry;
PULONG Pt, PageDir;
if (Address < MmSystemRangeStart && Process && Process != PsGetCurrentProcess())
{
PageDir = MmCreateHyperspaceMapping(PTE_TO_PFN(Process->Pcb.DirectoryTableBase.LowPart));
if (PageDir == NULL)
{
KEBUGCHECK(0);
}
if (0 == InterlockedCompareExchangeUL(&PageDir[PdeOffset], 0, 0))
{
if (Create == FALSE)
{
MmDeleteHyperspaceMapping(PageDir);
return NULL;
}
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn);
if (!NT_SUCCESS(Status) || Pfn == 0)
{
KEBUGCHECK(0);
}
Entry = InterlockedCompareExchangeUL(&PageDir[PdeOffset], PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE | PA_USER, 0);
if (Entry != 0)
{
MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
Pfn = PTE_TO_PFN(Entry);
}
}
else
{
Pfn = PTE_TO_PFN(PageDir[PdeOffset]);
}
MmDeleteHyperspaceMapping(PageDir);
Pt = MmCreateHyperspaceMapping(Pfn);
if (Pt == NULL)
{
KEBUGCHECK(0);
}
return Pt + ADDR_TO_PTE_OFFSET(Address);
}
PageDir = ADDR_TO_PDE(Address);
if (0 == InterlockedCompareExchangeUL(PageDir, 0, 0))
{
if (Address >= MmSystemRangeStart)
{
if (0 == InterlockedCompareExchangeUL(&MmGlobalKernelPageDirectory[PdeOffset], 0, 0))
{
if (Create == FALSE)
{
return NULL;
}
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn);
if (!NT_SUCCESS(Status) || Pfn == 0)
{
KEBUGCHECK(0);
}
Entry = PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE;
if (Ke386GlobalPagesEnabled)
{
Entry |= PA_GLOBAL;
}
if(0 != InterlockedCompareExchangeUL(&MmGlobalKernelPageDirectory[PdeOffset], Entry, 0))
{
MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
}
}
(void)InterlockedExchangeUL(PageDir, MmGlobalKernelPageDirectory[PdeOffset]);
}
else
{
if (Create == FALSE)
{
return NULL;
}
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn);
if (!NT_SUCCESS(Status) || Pfn == 0)
{
KEBUGCHECK(0);
}
Entry = InterlockedCompareExchangeUL(PageDir, PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE | PA_USER, 0);
if (Entry != 0)
{
MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
}
}
}
return (PULONG)ADDR_TO_PTE(Address);
}
BOOLEAN MmUnmapPageTable(PULONG Pt)
{
if (Ke386Pae)
{
if ((PULONGLONG)Pt >= (PULONGLONG)PAGETABLE_MAP && (PULONGLONG)Pt < (PULONGLONG)PAGETABLE_MAP + 4*512*512)
{
return TRUE;
}
}
else
{
if (Pt >= (PULONG)PAGETABLE_MAP && Pt < (PULONG)PAGETABLE_MAP + 1024*1024)
{
return TRUE;
}
}
if (Pt)
{
MmDeleteHyperspaceMapping((PVOID)PAGE_ROUND_DOWN(Pt));
}
return FALSE;
}
static ULONGLONG MmGetPageEntryForProcessForPAE(PEPROCESS Process, PVOID Address)
{
ULONGLONG Pte;
PULONGLONG Pt;
Pt = MmGetPageTableForProcessForPAE(Process, Address, FALSE);
if (Pt)
{
Pte = *Pt;
MmUnmapPageTable((PULONG)Pt);
return Pte;
}
return 0;
}
static ULONG MmGetPageEntryForProcess(PEPROCESS Process, PVOID Address)
{
ULONG Pte;
PULONG Pt;
Pt = MmGetPageTableForProcess(Process, Address, FALSE);
if (Pt)
{
Pte = *Pt;
MmUnmapPageTable(Pt);
return Pte;
}
return 0;
}
PFN_TYPE
NTAPI
MmGetPfnForProcess(PEPROCESS Process,
PVOID Address)
{
if (Ke386Pae)
{
ULONGLONG Entry;
Entry = MmGetPageEntryForProcessForPAE(Process, Address);
if (!(Entry & PA_PRESENT))
{
return 0;
}
return(PAE_PTE_TO_PFN(Entry));
}
else
{
ULONG Entry;
Entry = MmGetPageEntryForProcess(Process, Address);
if (!(Entry & PA_PRESENT))
{
return 0;
}
return(PTE_TO_PFN(Entry));
}
}
VOID
NTAPI
MmDisableVirtualMapping(PEPROCESS Process, PVOID Address, BOOLEAN* WasDirty, PPFN_TYPE Page)
/*
* FUNCTION: Delete a virtual mapping
*/
{
BOOLEAN WasValid;
if (Ke386Pae)
{
ULONGLONG Pte;
ULONGLONG tmpPte;
PULONGLONG Pt;
Pt = MmGetPageTableForProcessForPAE(Process, Address, FALSE);
if (Pt == NULL)
{
KEBUGCHECK(0);
}
/*
* Atomically disable the present bit and get the old value.
*/
do
{
Pte = *Pt;
tmpPte = Pte & ~PA_PRESENT;
} while (Pte != ExfInterlockedCompareExchange64UL(Pt, &tmpPte, &Pte));
MiFlushTlb((PULONG)Pt, Address);
WasValid = PAE_PAGE_MASK(Pte) != 0LL ? TRUE : FALSE;
if (!WasValid)
{
KEBUGCHECK(0);
}
/*
* Return some information to the caller
*/
if (WasDirty != NULL)
{
*WasDirty = Pte & PA_DIRTY ? TRUE : FALSE;
}
if (Page != NULL)
{
*Page = PAE_PTE_TO_PFN(Pte);
}
}
else
{
ULONG Pte;
PULONG Pt;
Pt = MmGetPageTableForProcess(Process, Address, FALSE);
if (Pt == NULL)
{
KEBUGCHECK(0);
}
/*
* Atomically disable the present bit and get the old value.
*/
do
{
Pte = *Pt;
} while (Pte != InterlockedCompareExchangeUL(Pt, Pte & ~PA_PRESENT, Pte));
MiFlushTlb(Pt, Address);
WasValid = (PAGE_MASK(Pte) != 0);
if (!WasValid)
{
KEBUGCHECK(0);
}
/*
* Return some information to the caller
*/
if (WasDirty != NULL)
{
*WasDirty = Pte & PA_DIRTY;
}
if (Page != NULL)
{
*Page = PTE_TO_PFN(Pte);
}
}
}
VOID
NTAPI
MmRawDeleteVirtualMapping(PVOID Address)
{
if (Ke386Pae)
{
PULONGLONG Pt;
ULONGLONG ZeroPte = 0LL;
Pt = MmGetPageTableForProcessForPAE(NULL, Address, FALSE);
if (Pt)
{
/*
* Set the entry to zero
*/
(void)ExfpInterlockedExchange64UL(Pt, &ZeroPte);
MiFlushTlb((PULONG)Pt, Address);
}
}
else
{
PULONG Pt;
Pt = MmGetPageTableForProcess(NULL, Address, FALSE);
if (Pt && *Pt)
{
/*
* Set the entry to zero
*/
(void)InterlockedExchangeUL(Pt, 0);
MiFlushTlb(Pt, Address);
}
}
}
VOID
NTAPI
MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOLEAN FreePage,
BOOLEAN* WasDirty, PPFN_TYPE Page)
/*
* FUNCTION: Delete a virtual mapping
*/
{
BOOLEAN WasValid = FALSE;
PFN_TYPE Pfn;
DPRINT("MmDeleteVirtualMapping(%x, %x, %d, %x, %x)\n",
Process, Address, FreePage, WasDirty, Page);
if (Ke386Pae)
{
ULONGLONG Pte;
PULONGLONG Pt;
Pt = MmGetPageTableForProcessForPAE(Process, Address, FALSE);
if (Pt == NULL)
{
if (WasDirty != NULL)
{
*WasDirty = FALSE;
}
if (Page != NULL)
{
*Page = 0;
}
return;
}
/*
* Atomically set the entry to zero and get the old value.
*/
Pte = 0LL;
Pte = ExfpInterlockedExchange64UL(Pt, &Pte);
MiFlushTlb((PULONG)Pt, Address);
WasValid = PAE_PAGE_MASK(Pte) != 0 ? TRUE : FALSE;
if (WasValid)
{
Pfn = PAE_PTE_TO_PFN(Pte);
MmMarkPageUnmapped(Pfn);
}
else
{
Pfn = 0;
}
if (FreePage && WasValid)
{
MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
}
/*
* Return some information to the caller
*/
if (WasDirty != NULL)
{
*WasDirty = Pte & PA_DIRTY ? TRUE : FALSE;
}
if (Page != NULL)
{
*Page = Pfn;
}
}
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -