+VOID
+NTAPI
+MiCopyPfn(
+ _In_ PFN_NUMBER DestPage,
+ _In_ PFN_NUMBER SrcPage)
+{
+ PMMPTE SysPtes;
+ MMPTE TempPte;
+ PMMPFN DestPfn, SrcPfn;
+ PVOID DestAddress;
+ const VOID* SrcAddress;
+
+ /* Get the PFNs */
+ DestPfn = MiGetPfnEntry(DestPage);
+ ASSERT(DestPfn);
+ SrcPfn = MiGetPfnEntry(SrcPage);
+ ASSERT(SrcPfn);
+
+ /* Grab 2 system PTEs */
+ SysPtes = MiReserveSystemPtes(2, SystemPteSpace);
+ ASSERT(SysPtes);
+
+ /* Initialize the destination PTE */
+ TempPte = ValidKernelPte;
+ TempPte.u.Hard.PageFrameNumber = DestPage;
+
+ /* Setup caching */
+ if (DestPfn->u3.e1.CacheAttribute == MiWriteCombined)
+ {
+ /* Write combining, no caching */
+ MI_PAGE_DISABLE_CACHE(&TempPte);
+ MI_PAGE_WRITE_COMBINED(&TempPte);
+ }
+ else if (DestPfn->u3.e1.CacheAttribute == MiNonCached)
+ {
+ /* Write through, no caching */
+ MI_PAGE_DISABLE_CACHE(&TempPte);
+ MI_PAGE_WRITE_THROUGH(&TempPte);
+ }
+
+ /* Make the system PTE valid with our PFN */
+ MI_WRITE_VALID_PTE(&SysPtes[0], TempPte);
+
+ /* Initialize the source PTE */
+ TempPte = ValidKernelPte;
+ TempPte.u.Hard.PageFrameNumber = SrcPage;
+
+ /* Setup caching */
+ if (SrcPfn->u3.e1.CacheAttribute == MiNonCached)
+ {
+ MI_PAGE_DISABLE_CACHE(&TempPte);
+ }
+
+ /* Make the system PTE valid with our PFN */
+ MI_WRITE_VALID_PTE(&SysPtes[1], TempPte);
+
+ /* Get the addresses and perform the copy */
+ DestAddress = MiPteToAddress(&SysPtes[0]);
+ SrcAddress = MiPteToAddress(&SysPtes[1]);
+ RtlCopyMemory(DestAddress, SrcAddress, PAGE_SIZE);
+
+ /* Now get rid of it */
+ MiReleaseSystemPtes(SysPtes, 2, SystemPteSpace);
+}
+