📄 page.c
字号:
BOOLEAN
NTAPI
MmIsPageSwapEntry(PEPROCESS Process, PVOID Address)
{
if (Ke386Pae)
{
ULONGLONG Entry;
Entry = MmGetPageEntryForProcessForPAE(Process, Address);
return !(Entry & PA_PRESENT) && Entry != 0 ? TRUE : FALSE;
}
else
{
ULONG Entry;
Entry = MmGetPageEntryForProcess(Process, Address);
return !(Entry & PA_PRESENT) && Entry != 0 ? TRUE : FALSE;
}
}
NTSTATUS
NTAPI
MmCreateVirtualMappingForKernel(PVOID Address,
ULONG flProtect,
PPFN_TYPE Pages,
ULONG PageCount)
{
ULONG Attributes;
ULONG i;
PVOID Addr;
ULONG PdeOffset, oldPdeOffset;
BOOLEAN NoExecute = FALSE;
DPRINT("MmCreateVirtualMappingForKernel(%x, %x, %x, %d)\n",
Address, flProtect, Pages, PageCount);
if (Address < MmSystemRangeStart)
{
DPRINT1("MmCreateVirtualMappingForKernel is called for user space\n");
KEBUGCHECK(0);
}
Attributes = ProtectToPTE(flProtect);
if (Attributes & 0x80000000)
{
NoExecute = TRUE;
}
Attributes &= 0xfff;
if (Ke386GlobalPagesEnabled)
{
Attributes |= PA_GLOBAL;
}
Addr = Address;
if (Ke386Pae)
{
PULONGLONG Pt = NULL;
ULONGLONG Pte;
oldPdeOffset = PAE_ADDR_TO_PDE_OFFSET(Addr) + 1;
for (i = 0; i < PageCount; i++, Addr = (PVOID)((ULONG_PTR)Addr + PAGE_SIZE))
{
if (!(Attributes & PA_PRESENT) && Pages[i] != 0)
{
DPRINT1("Setting physical address but not allowing access at address "
"0x%.8X with attributes %x/%x.\n",
Addr, Attributes, flProtect);
KEBUGCHECK(0);
}
PdeOffset = PAE_ADDR_TO_PDE_OFFSET(Addr);
if (oldPdeOffset != PdeOffset)
{
Pt = MmGetPageTableForProcessForPAE(NULL, Addr, TRUE);
if (Pt == NULL)
{
KEBUGCHECK(0);
}
}
else
{
Pt++;
}
oldPdeOffset = PdeOffset;
Pte = PFN_TO_PTE(Pages[i]) | Attributes;
if (NoExecute)
{
Pte |= 0x8000000000000000LL;
}
Pte = ExfpInterlockedExchange64UL(Pt, &Pte);
if (Pte != 0LL)
{
KEBUGCHECK(0);
}
}
}
else
{
PULONG Pt;
ULONG Pte;
oldPdeOffset = ADDR_TO_PDE_OFFSET(Addr);
Pt = MmGetPageTableForProcess(NULL, Addr, TRUE);
if (Pt == NULL)
{
KEBUGCHECK(0);
}
Pt--;
for (i = 0; i < PageCount; i++, Addr = (PVOID)((ULONG_PTR)Addr + PAGE_SIZE))
{
if (!(Attributes & PA_PRESENT) && Pages[i] != 0)
{
DPRINT1("Setting physical address but not allowing access at address "
"0x%.8X with attributes %x/%x.\n",
Addr, Attributes, flProtect);
KEBUGCHECK(0);
}
PdeOffset = ADDR_TO_PDE_OFFSET(Addr);
if (oldPdeOffset != PdeOffset)
{
Pt = MmGetPageTableForProcess(NULL, Addr, TRUE);
if (Pt == NULL)
{
KEBUGCHECK(0);
}
}
else
{
Pt++;
}
oldPdeOffset = PdeOffset;
Pte = *Pt;
if (Pte != 0)
{
KEBUGCHECK(0);
}
(void)InterlockedExchangeUL(Pt, PFN_TO_PTE(Pages[i]) | Attributes);
}
}
return(STATUS_SUCCESS);
}
NTSTATUS
NTAPI
MmCreatePageFileMapping(PEPROCESS Process,
PVOID Address,
SWAPENTRY SwapEntry)
{
if (Process == NULL && Address < MmSystemRangeStart)
{
DPRINT1("No process\n");
KEBUGCHECK(0);
}
if (Process != NULL && Address >= MmSystemRangeStart)
{
DPRINT1("Setting kernel address with process context\n");
KEBUGCHECK(0);
}
if (SwapEntry & (1 << 31))
{
KEBUGCHECK(0);
}
if (Ke386Pae)
{
PULONGLONG Pt;
ULONGLONG Pte;
ULONGLONG tmpPte;
Pt = MmGetPageTableForProcessForPAE(Process, Address, TRUE);
if (Pt == NULL)
{
KEBUGCHECK(0);
}
tmpPte = SwapEntry << 1;
Pte = ExfpInterlockedExchange64UL(Pt, &tmpPte);
if (PAE_PAGE_MASK((Pte)) != 0)
{
MmMarkPageUnmapped(PAE_PTE_TO_PFN((Pte)));
}
if (Pte != 0)
{
MiFlushTlb((PULONG)Pt, Address);
}
else
{
MmUnmapPageTable((PULONG)Pt);
}
}
else
{
PULONG Pt;
ULONG Pte;
Pt = MmGetPageTableForProcess(Process, Address, TRUE);
if (Pt == NULL)
{
KEBUGCHECK(0);
}
Pte = *Pt;
if (PAGE_MASK((Pte)) != 0)
{
MmMarkPageUnmapped(PTE_TO_PFN((Pte)));
}
(void)InterlockedExchangeUL(Pt, SwapEntry << 1);
if (Pte != 0)
{
MiFlushTlb(Pt, Address);
}
else
{
MmUnmapPageTable(Pt);
}
}
if (Process != NULL &&
((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable != NULL &&
Address < MmSystemRangeStart)
{
PUSHORT Ptrc;
ULONG Idx;
Ptrc = ((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable;
Idx = Ke386Pae ? PAE_ADDR_TO_PAGE_TABLE(Address) : ADDR_TO_PAGE_TABLE(Address);
Ptrc[Idx]++;
}
return(STATUS_SUCCESS);
}
NTSTATUS
NTAPI
MmCreateVirtualMappingUnsafe(PEPROCESS Process,
PVOID Address,
ULONG flProtect,
PPFN_TYPE Pages,
ULONG PageCount)
{
ULONG Attributes;
PVOID Addr;
ULONG i;
ULONG oldPdeOffset, PdeOffset;
BOOLEAN NoExecute = FALSE;
DPRINT("MmCreateVirtualMappingUnsafe(%x, %x, %x, %x (%x), %d)\n",
Process, Address, flProtect, Pages, *Pages, PageCount);
if (Process == NULL)
{
if (Address < MmSystemRangeStart)
{
DPRINT1("No process\n");
KEBUGCHECK(0);
}
if (PageCount > 0x10000 ||
(ULONG_PTR) Address / PAGE_SIZE + PageCount > 0x100000)
{
DPRINT1("Page count to large\n");
KEBUGCHECK(0);
}
}
else
{
if (Address >= MmSystemRangeStart)
{
DPRINT1("Setting kernel address with process context\n");
KEBUGCHECK(0);
}
if (PageCount > (ULONG_PTR)MmSystemRangeStart / PAGE_SIZE ||
(ULONG_PTR) Address / PAGE_SIZE + PageCount >
(ULONG_PTR)MmSystemRangeStart / PAGE_SIZE)
{
DPRINT1("Page Count to large\n");
KEBUGCHECK(0);
}
}
Attributes = ProtectToPTE(flProtect);
if (Attributes & 0x80000000)
{
NoExecute = TRUE;
}
Attributes &= 0xfff;
if (Address >= MmSystemRangeStart)
{
Attributes &= ~PA_USER;
if (Ke386GlobalPagesEnabled)
{
Attributes |= PA_GLOBAL;
}
}
else
{
Attributes |= PA_USER;
}
Addr = Address;
if (Ke386Pae)
{
ULONGLONG Pte, tmpPte;
PULONGLONG Pt = NULL;
oldPdeOffset = PAE_ADDR_TO_PDE_OFFSET(Addr) + 1;
for (i = 0; i < PageCount; i++, Addr = (PVOID)((ULONG_PTR)Addr + PAGE_SIZE))
{
if (!(Attributes & PA_PRESENT) && Pages[i] != 0)
{
DPRINT1("Setting physical address but not allowing access at address "
"0x%.8X with attributes %x/%x.\n",
Addr, Attributes, flProtect);
KEBUGCHECK(0);
}
PdeOffset = PAE_ADDR_TO_PDE_OFFSET(Addr);
if (oldPdeOffset != PdeOffset)
{
MmUnmapPageTable((PULONG)Pt);
Pt = MmGetPageTableForProcessForPAE(Process, Addr, TRUE);
if (Pt == NULL)
{
KEBUGCHECK(0);
}
}
else
{
Pt++;
}
oldPdeOffset = PdeOffset;
MmMarkPageMapped(Pages[i]);
tmpPte = PAE_PFN_TO_PTE(Pages[i]) | Attributes;
if (NoExecute)
{
tmpPte |= 0x8000000000000000LL;
}
Pte = ExfpInterlockedExchange64UL(Pt, &tmpPte);
if (PAE_PAGE_MASK((Pte)) != 0LL && !((Pte) & PA_PRESENT))
{
KEBUGCHECK(0);
}
if (PAE_PAGE_MASK((Pte)) != 0LL)
{
MmMarkPageUnmapped(PAE_PTE_TO_PFN((Pte)));
}
if (Address < MmSystemRangeStart &&
((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable != NULL &&
Attributes & PA_PRESENT)
{
PUSHORT Ptrc;
Ptrc = ((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable;
Ptrc[PAE_ADDR_TO_PAGE_TABLE(Addr)]++;
}
if (Pte != 0LL)
{
if (Address > MmSystemRangeStart ||
(Pt >= (PULONGLONG)PAGETABLE_MAP && Pt < (PULONGLONG)PAGETABLE_MAP + 4*512*512))
{
MiFlushTlb((PULONG)Pt, Address);
}
}
}
if (Addr > Address)
{
MmUnmapPageTable((PULONG)Pt);
}
}
else
{
PULONG Pt = NULL;
ULONG Pte;
oldPdeOffset = ADDR_TO_PDE_OFFSET(Addr) + 1;
for (i = 0; i < PageCount; i++, Addr = (PVOID)((ULONG_PTR)Addr + PAGE_SIZE))
{
if (!(Attributes & PA_PRESENT) && Pages[i] != 0)
{
DPRINT1("Setting physical address but not allowing access at address "
"0x%.8X with attributes %x/%x.\n",
Addr, Attributes, flProtect);
KEBUGCHECK(0);
}
PdeOffset = ADDR_TO_PDE_OFFSET(Addr);
if (oldPdeOffset != PdeOffset)
{
MmUnmapPageTable(Pt);
Pt = MmGetPageTableForProcess(Process, Addr, TRUE);
if (Pt == NULL)
{
KEBUGCHECK(0);
}
}
else
{
Pt++;
}
oldPdeOffset = PdeOffset;
Pte = *Pt;
MmMarkPageMapped(Pages[i]);
if (PAGE_MASK((Pte)) != 0 && !((Pte) & PA_PRESENT))
{
KEBUGCHECK(0);
}
if (PAGE_MASK((Pte)) != 0)
{
MmMarkPageUnmapped(PTE_TO_PFN((Pte)));
}
(void)InterlockedExchangeUL(Pt, PFN_TO_PTE(Pages[i]) | Attributes);
if (Address < MmSystemRangeStart &&
((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable != NULL &&
Attributes & PA_PRESENT)
{
PUSHORT Ptrc;
Ptrc = ((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable;
Ptrc[ADDR_TO_PAGE_TABLE(Addr)]++;
}
if (Pte != 0)
{
if (Address > MmSystemRangeStart ||
(Pt >= (PULONG)PAGETABLE_MAP && Pt < (PULONG)PAGETABLE_MAP + 1024*1024))
{
MiFlushTlb(Pt, Address);
}
}
}
if (Addr > Address)
{
MmUnmapPageTable(Pt);
}
}
return(STATUS_SUCCESS);
}
NTSTATUS
NTAPI
MmCreateVirtualMapping(PEPROCESS Process,
PVOID Address,
ULONG flProtect,
PPFN_TYPE Pages,
ULONG PageCount)
{
ULONG i;
for (i = 0; i < PageCount; i++)
{
if (!MmIsUsablePage(Pages[i]))
{
DPRINT1("Page at address %x not usable\n", PFN_TO_PTE(Pages[i]));
KEBUGCHECK(0);
}
}
return(MmCreateVirtualMappingUnsafe(Process,
Address,
flProtect,
Pages,
PageCount));
}
ULONG
NTAPI
MmGetPageProtect(PEPROCESS Process, PVOID Address)
{
ULONG Entry;
ULONG Protect;
if (Ke386Pae)
{
Entry = MmGetPageEntryForProcessForPAE(Process, Address);
}
else
{
Entry = MmGetPageEntryForProcess(Process, Address);
}
if (!(Entry & PA_PRESENT))
{
Protect = PAGE_NOACCESS;
}
else
{
if (Entry & PA_READWRITE)
{
Protect = PAGE_READWRITE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -