⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 page.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 5 页
字号:
      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 + -