📄 page.c
字号:
else
{
Protect = PAGE_EXECUTE_READ;
}
if (Entry & PA_CD)
{
Protect |= PAGE_NOCACHE;
}
if (Entry & PA_WT)
{
Protect |= PAGE_WRITETHROUGH;
}
if (!(Entry & PA_USER))
{
Protect |= PAGE_SYSTEM;
}
}
return(Protect);
}
VOID
NTAPI
MmSetPageProtect(PEPROCESS Process, PVOID Address, ULONG flProtect)
{
ULONG Attributes = 0;
BOOLEAN NoExecute = FALSE;
DPRINT("MmSetPageProtect(Process %x Address %x flProtect %x)\n",
Process, Address, flProtect);
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;
}
if (Ke386Pae)
{
PULONGLONG Pt;
ULONGLONG tmpPte, Pte;
Pt = MmGetPageTableForProcessForPAE(Process, Address, FALSE);
if (Pt == NULL)
{
DPRINT1("Address %x\n", Address);
KEBUGCHECK(0);
}
do
{
Pte = *Pt;
tmpPte = PAE_PAGE_MASK(Pte) | Attributes | (Pte & (PA_ACCESSED|PA_DIRTY));
if (NoExecute)
{
tmpPte |= 0x8000000000000000LL;
}
else
{
tmpPte &= ~0x8000000000000000LL;
}
} while (Pte != ExfInterlockedCompareExchange64UL(Pt, &tmpPte, &Pte));
MiFlushTlb((PULONG)Pt, Address);
}
else
{
PULONG Pt;
Pt = MmGetPageTableForProcess(Process, Address, FALSE);
if (Pt == NULL)
{
KEBUGCHECK(0);
}
InterlockedExchange((PLONG)Pt, PAGE_MASK(*Pt) | Attributes | (*Pt & (PA_ACCESSED|PA_DIRTY)));
MiFlushTlb(Pt, Address);
}
}
/*
* @implemented
*/
PHYSICAL_ADDRESS STDCALL
MmGetPhysicalAddress(PVOID vaddr)
/*
* FUNCTION: Returns the physical address corresponding to a virtual address
*/
{
PHYSICAL_ADDRESS p;
DPRINT("MmGetPhysicalAddress(vaddr %x)\n", vaddr);
if (Ke386Pae)
{
ULONGLONG Pte;
Pte = MmGetPageEntryForProcessForPAE(NULL, vaddr);
if (Pte != 0 && Pte & PA_PRESENT)
{
p.QuadPart = PAE_PAGE_MASK(Pte);
p.u.LowPart |= (ULONG_PTR)vaddr & (PAGE_SIZE - 1);
}
else
{
p.QuadPart = 0;
}
}
else
{
ULONG Pte;
Pte = MmGetPageEntryForProcess(NULL, vaddr);
if (Pte != 0 && Pte & PA_PRESENT)
{
p.QuadPart = PAGE_MASK(Pte);
p.u.LowPart |= (ULONG_PTR)vaddr & (PAGE_SIZE - 1);
}
else
{
p.QuadPart = 0;
}
}
return p;
}
PVOID
NTAPI
MmCreateHyperspaceMapping(PFN_TYPE Page)
{
PVOID Address;
ULONG i;
if (Ke386Pae)
{
ULONGLONG Entry;
ULONGLONG ZeroEntry = 0LL;
PULONGLONG Pte;
Entry = PFN_TO_PTE(Page) | PA_PRESENT | PA_READWRITE;
Pte = PAE_ADDR_TO_PTE(HYPERSPACE) + Page % 1024;
if (Page & 1024)
{
for (i = Page %1024; i < 1024; i++, Pte++)
{
if (0LL == ExfInterlockedCompareExchange64UL(Pte, &Entry, &ZeroEntry))
{
break;
}
}
if (i >= 1024)
{
Pte = PAE_ADDR_TO_PTE(HYPERSPACE);
for (i = 0; i < Page % 1024; i++, Pte++)
{
if (0LL == ExfInterlockedCompareExchange64UL(Pte, &Entry, &ZeroEntry))
{
break;
}
}
if (i >= Page % 1024)
{
KEBUGCHECK(0);
}
}
}
else
{
for (i = Page %1024; (LONG)i >= 0; i--, Pte--)
{
if (0LL == ExfInterlockedCompareExchange64UL(Pte, &Entry, &ZeroEntry))
{
break;
}
}
if ((LONG)i < 0)
{
Pte = PAE_ADDR_TO_PTE(HYPERSPACE) + 1023;
for (i = 1023; i > Page % 1024; i--, Pte--)
{
if (0LL == ExfInterlockedCompareExchange64UL(Pte, &Entry, &ZeroEntry))
{
break;
}
}
if (i <= Page % 1024)
{
KEBUGCHECK(0);
}
}
}
}
else
{
ULONG Entry;
PULONG Pte;
Entry = PFN_TO_PTE(Page) | PA_PRESENT | PA_READWRITE;
Pte = ADDR_TO_PTE(HYPERSPACE) + Page % 1024;
if (Page & 1024)
{
for (i = Page % 1024; i < 1024; i++, Pte++)
{
if (0 == InterlockedCompareExchange((PLONG)Pte, (LONG)Entry, 0))
{
break;
}
}
if (i >= 1024)
{
Pte = ADDR_TO_PTE(HYPERSPACE);
for (i = 0; i < Page % 1024; i++, Pte++)
{
if (0 == InterlockedCompareExchange((PLONG)Pte, (LONG)Entry, 0))
{
break;
}
}
if (i >= Page % 1024)
{
KEBUGCHECK(0);
}
}
}
else
{
for (i = Page % 1024; (LONG)i >= 0; i--, Pte--)
{
if (0 == InterlockedCompareExchange((PLONG)Pte, (LONG)Entry, 0))
{
break;
}
}
if ((LONG)i < 0)
{
Pte = ADDR_TO_PTE(HYPERSPACE) + 1023;
for (i = 1023; i > Page % 1024; i--, Pte--)
{
if (0 == InterlockedCompareExchange((PLONG)Pte, (LONG)Entry, 0))
{
break;
}
}
if (i <= Page % 1024)
{
KEBUGCHECK(0);
}
}
}
}
Address = (PVOID)((ULONG_PTR)HYPERSPACE + i * PAGE_SIZE);
__invlpg(Address);
return Address;
}
PFN_TYPE
NTAPI
MmChangeHyperspaceMapping(PVOID Address, PFN_TYPE NewPage)
{
PFN_TYPE Pfn;
ASSERT (IS_HYPERSPACE(Address));
if (Ke386Pae)
{
ULONGLONG Entry = PAE_PFN_TO_PTE(NewPage) | PA_PRESENT | PA_READWRITE;
Entry = (ULONG)ExfpInterlockedExchange64UL(PAE_ADDR_TO_PTE(Address), &Entry);
Pfn = PAE_PTE_TO_PFN(Entry);
}
else
{
ULONG Entry;
Entry = InterlockedExchange((PLONG)ADDR_TO_PTE(Address), PFN_TO_PTE(NewPage) | PA_PRESENT | PA_READWRITE);
Pfn = PTE_TO_PFN(Entry);
}
__invlpg(Address);
return Pfn;
}
PFN_TYPE
NTAPI
MmDeleteHyperspaceMapping(PVOID Address)
{
PFN_TYPE Pfn;
ASSERT (IS_HYPERSPACE(Address));
if (Ke386Pae)
{
ULONGLONG Entry = 0LL;
Entry = (ULONG)ExfpInterlockedExchange64UL(PAE_ADDR_TO_PTE(Address), &Entry);
Pfn = PAE_PTE_TO_PFN(Entry);
}
else
{
ULONG Entry;
Entry = InterlockedExchange((PLONG)ADDR_TO_PTE(Address), 0);
Pfn = PTE_TO_PFN(Entry);
}
__invlpg(Address);
return Pfn;
}
VOID
NTAPI
MmUpdatePageDir(PEPROCESS Process, PVOID Address, ULONG Size)
{
ULONG StartOffset, EndOffset, Offset;
if (Address < MmSystemRangeStart)
{
KEBUGCHECK(0);
}
if (Ke386Pae)
{
PULONGLONG PageDirTable;
PULONGLONG Pde;
ULONGLONG ZeroPde = 0LL;
ULONG i;
for (i = PAE_ADDR_TO_PDTE_OFFSET(Address); i <= PAE_ADDR_TO_PDTE_OFFSET((PVOID)((ULONG_PTR)Address + Size)); i++)
{
if (i == PAE_ADDR_TO_PDTE_OFFSET(Address))
{
StartOffset = PAE_ADDR_TO_PDE_PAGE_OFFSET(Address);
}
else
{
StartOffset = 0;
}
if (i == PAE_ADDR_TO_PDTE_OFFSET((PVOID)((ULONG_PTR)Address + Size)))
{
EndOffset = PAE_ADDR_TO_PDE_PAGE_OFFSET((PVOID)((ULONG_PTR)Address + Size));
}
else
{
EndOffset = 511;
}
if (Process != NULL && Process != PsGetCurrentProcess())
{
PageDirTable = MmCreateHyperspaceMapping(PAE_PTE_TO_PFN(Process->Pcb.DirectoryTableBase.QuadPart));
Pde = (PULONGLONG)MmCreateHyperspaceMapping(PTE_TO_PFN(PageDirTable[i]));
MmDeleteHyperspaceMapping(PageDirTable);
}
else
{
Pde = (PULONGLONG)PAE_PAGEDIRECTORY_MAP + i*512;
}
for (Offset = StartOffset; Offset <= EndOffset; Offset++)
{
if (i * 512 + Offset < PAE_ADDR_TO_PDE_OFFSET(PAGETABLE_MAP) || i * 512 + Offset >= PAE_ADDR_TO_PDE_OFFSET(PAGETABLE_MAP)+4)
{
(void)ExfInterlockedCompareExchange64UL(&Pde[Offset], &MmGlobalKernelPageDirectoryForPAE[i*512 + Offset], &ZeroPde);
}
}
MmUnmapPageTable((PULONG)Pde);
}
}
else
{
PULONG Pde;
StartOffset = ADDR_TO_PDE_OFFSET(Address);
EndOffset = ADDR_TO_PDE_OFFSET((PVOID)((ULONG_PTR)Address + Size));
if (Process != NULL && Process != PsGetCurrentProcess())
{
Pde = MmCreateHyperspaceMapping(PTE_TO_PFN(Process->Pcb.DirectoryTableBase.u.LowPart));
}
else
{
Pde = (PULONG)PAGEDIRECTORY_MAP;
}
for (Offset = StartOffset; Offset <= EndOffset; Offset++)
{
if (Offset != ADDR_TO_PDE_OFFSET(PAGETABLE_MAP))
{
(void)InterlockedCompareExchangeUL(&Pde[Offset], MmGlobalKernelPageDirectory[Offset], 0);
}
}
if (Pde != (PULONG)PAGEDIRECTORY_MAP)
{
MmDeleteHyperspaceMapping(Pde);
}
}
}
VOID
INIT_FUNCTION
NTAPI
MmInitGlobalKernelPageDirectory(VOID)
{
ULONG i;
DPRINT("MmInitGlobalKernelPageDirectory()\n");
if (Ke386Pae)
{
PULONGLONG CurrentPageDirectory = (PULONGLONG)PAE_PAGEDIRECTORY_MAP;
for (i = PAE_ADDR_TO_PDE_OFFSET(MmSystemRangeStart); i < 4 * 512; i++)
{
if (!(i >= PAE_ADDR_TO_PDE_OFFSET(PAGETABLE_MAP) && i < PAE_ADDR_TO_PDE_OFFSET(PAGETABLE_MAP) + 4) &&
!(i >= PAE_ADDR_TO_PDE_OFFSET(HYPERSPACE) && i < PAE_ADDR_TO_PDE_OFFSET(HYPERSPACE) + 2) &&
0LL == MmGlobalKernelPageDirectoryForPAE[i] && 0LL != CurrentPageDirectory[i])
{
(void)ExfpInterlockedExchange64UL(&MmGlobalKernelPageDirectoryForPAE[i], &CurrentPageDirectory[i]);
if (Ke386GlobalPagesEnabled)
{
MmGlobalKernelPageDirectoryForPAE[i] |= PA_GLOBAL;
CurrentPageDirectory[i] |= PA_GLOBAL;
}
}
}
}
else
{
PULONG CurrentPageDirectory = (PULONG)PAGEDIRECTORY_MAP;
for (i = ADDR_TO_PDE_OFFSET(MmSystemRangeStart); i < 1024; i++)
{
if (i != ADDR_TO_PDE_OFFSET(PAGETABLE_MAP) &&
i != ADDR_TO_PDE_OFFSET(HYPERSPACE) &&
0 == MmGlobalKernelPageDirectory[i] && 0 != CurrentPageDirectory[i])
{
MmGlobalKernelPageDirectory[i] = CurrentPageDirectory[i];
if (Ke386GlobalPagesEnabled)
{
MmGlobalKernelPageDirectory[i] |= PA_GLOBAL;
CurrentPageDirectory[i] |= PA_GLOBAL;
}
}
}
}
}
ULONG
NTAPI
MiGetUserPageDirectoryCount(VOID)
{
return Ke386Pae ? PAE_ADDR_TO_PDE_OFFSET(MmSystemRangeStart) : ADDR_TO_PDE_OFFSET(MmSystemRangeStart);
}
VOID
INIT_FUNCTION
NTAPI
MiInitPageDirectoryMap(VOID)
{
MEMORY_AREA* kernel_map_desc = NULL;
MEMORY_AREA* hyperspace_desc = NULL;
PHYSICAL_ADDRESS BoundaryAddressMultiple;
PVOID BaseAddress;
NTSTATUS Status;
DPRINT("MiInitPageDirectoryMap()\n");
BoundaryAddressMultiple.QuadPart = 0;
BaseAddress = (PVOID)PAGETABLE_MAP;
Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
MEMORY_AREA_SYSTEM,
&BaseAddress,
Ke386Pae ? 0x800000 : 0x400000,
PAGE_READWRITE,
&kernel_map_desc,
TRUE,
0,
BoundaryAddressMultiple);
if (!NT_SUCCESS(Status))
{
KEBUGCHECK(0);
}
BaseAddress = (PVOID)HYPERSPACE;
Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
MEMORY_AREA_SYSTEM,
&BaseAddress,
0x400000,
PAGE_READWRITE,
&hyperspace_desc,
TRUE,
0,
BoundaryAddressMultiple);
if (!NT_SUCCESS(Status))
{
KEBUGCHECK(0);
}
}
/* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -