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)
{
....//此处是支持Pae情况暂且不考虑
}
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))//((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));//此处如果是0号页面仍然增加mappingcount和refcount吗
if (PAGE_MASK((Pte)) != 0 && !((Pte) & PA_PRESENT))//此处如果是0号页面就不会错误
{
KEBUGCHECK(0);
}
if (PAGE_MASK((Pte)) != 0)
{
MmMarkPageUnmapped(PTE_TO_PFN((Pte)));//此处如果是0号页面就不会减少
//mapcount和refcount与上面的Pages(i)的情况是否矛盾
}
(void)InterlockedExchangeUL(Pt, PFN_TO_PTE(Pages(i)) | Attributes);//0号页面可以被替换映射或者替换已有映射吗
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语句块貌似没有我写的下面这个(/*...*/)注释括起来的if语句块合理些
/*if((Address<MmSystemRangeStart)&&(((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable!=NULL))
{
PUSHORT ptrc=((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable;
if((Attributes&PA_PRESENT)&&(!(pte & PA_PRESENT)))
{
ptrc[ADDR_TO_PAGE_TABLE(Addr)]++;
}
else if((!(Attributes&PA_PRESENT))&&(pte & PA_PRESENT))
{
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);
}
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!