Author: jgardou
Date: Thu Jan 28 21:17:28 2016
New Revision: 70649

URL: http://svn.reactos.org/svn/reactos?rev=70649&view=rev
Log:
[BRANCHES/TRANSITIONPTE]
 - Make the thing build

Modified:
    branches/TransitionPte/ntoskrnl/mm/balance.c
    branches/TransitionPte/ntoskrnl/mm/pagefile.c

Modified: branches/TransitionPte/ntoskrnl/mm/balance.c
URL: 
http://svn.reactos.org/svn/reactos/branches/TransitionPte/ntoskrnl/mm/balance.c?rev=70649&r1=70648&r2=70649&view=diff
==============================================================================
--- branches/TransitionPte/ntoskrnl/mm/balance.c        [iso-8859-1] (original)
+++ branches/TransitionPte/ntoskrnl/mm/balance.c        [iso-8859-1] Thu Jan 28 
21:17:28 2016
@@ -24,14 +24,7 @@
 
 #define TEST_PAGING
 
-/* TYPES ********************************************************************/
-typedef struct _MM_ALLOCATION_REQUEST
-{
-    PFN_NUMBER Page;
-    LIST_ENTRY ListEntry;
-    KEVENT Event;
-}
-MM_ALLOCATION_REQUEST, *PMM_ALLOCATION_REQUEST;
+
 /* GLOBALS ******************************************************************/
 
 MM_MEMORY_CONSUMER MiMemoryConsumers[MC_MAXIMUM];
@@ -51,15 +44,13 @@
 NTAPI
 MmInitializeBalancer(ULONG NrAvailablePages, ULONG NrSystemPages)
 {
-    memset(MiMemoryConsumers, 0, sizeof(MiMemoryConsumers));
-    InitializeListHead(&AllocationListHead);
-    KeInitializeSpinLock(&AllocationListLock);
-
-    MiNrTotalPages = NrAvailablePages;
-
-    /* Set up targets. */
-    MiMinimumAvailablePages = 128;
-    MiMinimumPagesPerRun = 256;
+   memset(MiMemoryConsumers, 0, sizeof(MiMemoryConsumers));
+
+   MiNrTotalPages = NrAvailablePages;
+
+   /* Set up targets. */
+   MiMinimumAvailablePages = 128;
+   MiMinimumPagesPerRun = 256;
     if ((NrAvailablePages + NrSystemPages) >= 8192)
     {
         MiMemoryConsumers[MC_CACHE].PagesTarget = NrAvailablePages / 4 * 3;
@@ -72,54 +63,42 @@
     {
         MiMemoryConsumers[MC_CACHE].PagesTarget = NrAvailablePages / 8;
     }
-    MiMemoryConsumers[MC_USER].PagesTarget = NrAvailablePages - 
MiMinimumAvailablePages;
+   MiMemoryConsumers[MC_USER].PagesTarget = NrAvailablePages - 
MiMinimumAvailablePages;
 }
 
 VOID
 INIT_FUNCTION
 NTAPI
-MmInitializeMemoryConsumer(
-    ULONG Consumer,
-    NTSTATUS (*Trim)(ULONG Target, ULONG Priority, PULONG NrFreed))
-{
-    MiMemoryConsumers[Consumer].Trim = Trim;
+MmInitializeMemoryConsumer(ULONG Consumer,
+                           NTSTATUS (*Trim)(ULONG Target, ULONG Priority,
+                                            PULONG NrFreed))
+{
+   MiMemoryConsumers[Consumer].Trim = Trim;
 }
 
 NTSTATUS
 NTAPI
 MmReleasePageMemoryConsumer(ULONG Consumer, PFN_NUMBER Page)
 {
-    PMM_ALLOCATION_REQUEST Request;
-    PLIST_ENTRY Entry;
-
-    if (Page == 0)
-    {
-        DPRINT1("Tried to release page zero.\n");
-        KeBugCheck(MEMORY_MANAGEMENT);
-    }
-
-    if (MmGetReferenceCountPage(Page) == 1)
-    {
-        if(Consumer == MC_USER) MmRemoveLRUUserPage(Page);
-        (void)InterlockedDecrementUL(&MiMemoryConsumers[Consumer].PagesUsed);
-        if ((Entry = ExInterlockedRemoveHeadList(&AllocationListHead, 
&AllocationListLock)) == NULL)
-        {
-            MmDereferencePage(Page);
-        }
-        else
-        {
-            Request = CONTAINING_RECORD(Entry, MM_ALLOCATION_REQUEST, 
ListEntry);
-            MiZeroPhysicalPage(Page);
-            Request->Page = Page;
-            KeSetEvent(&Request->Event, IO_NO_INCREMENT, FALSE);
-        }
-    }
-    else
-    {
-        MmDereferencePage(Page);
-    }
-
-    return(STATUS_SUCCESS);
+   KIRQL OldIrql;
+
+   if (Page == 0)
+   {
+      DPRINT1("Tried to release page zero.\n");
+      KeBugCheck(MEMORY_MANAGEMENT);
+   }
+
+   if (MmGetReferenceCountPage(Page) == 1)
+   {
+      if(Consumer == MC_USER) MmRemoveLRUUserPage(Page);
+      (void)InterlockedDecrementUL(&MiMemoryConsumers[Consumer].PagesUsed);
+   }
+
+   OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+   MmDereferencePage(Page);
+   KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+
+   return(STATUS_SUCCESS);
 }
 
 ULONG
@@ -214,8 +193,8 @@
 static BOOLEAN
 MiIsBalancerThread(VOID)
 {
-    return (MiBalancerThreadHandle != NULL) &&
-           (PsGetCurrentThreadId() == MiBalancerThreadId.UniqueThread);
+   return (MiBalancerThreadHandle != NULL) &&
+          (PsGetCurrentThreadId() == MiBalancerThreadId.UniqueThread);
 }
 
 VOID
@@ -234,97 +213,52 @@
 MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait,
                             PPFN_NUMBER AllocatedPage)
 {
-    ULONG PagesUsed;
-    PFN_NUMBER Page;
-
-    /*
-     * Make sure we don't exceed our individual target.
-     */
-    PagesUsed = InterlockedIncrementUL(&MiMemoryConsumers[Consumer].PagesUsed);
-    if (PagesUsed > MiMemoryConsumers[Consumer].PagesTarget &&
-            !MiIsBalancerThread())
-    {
-        MmRebalanceMemoryConsumers();
-    }
-
-    /*
-     * Allocate always memory for the non paged pool and for the pager thread.
-     */
-    if ((Consumer == MC_SYSTEM) || MiIsBalancerThread())
-    {
-        Page = MmAllocPage(Consumer);
-        if (Page == 0)
-        {
-            KeBugCheck(NO_PAGES_AVAILABLE);
-        }
-        if (Consumer == MC_USER) MmInsertLRULastUserPage(Page);
-        *AllocatedPage = Page;
-        if (MmAvailablePages < MiMinimumAvailablePages)
-            MmRebalanceMemoryConsumers();
-        return(STATUS_SUCCESS);
-    }
-
-    /*
-     * Make sure we don't exceed global targets.
-     */
-    if (MmAvailablePages < MiMinimumAvailablePages)
-    {
-        MM_ALLOCATION_REQUEST Request;
-
-        if (!CanWait)
-        {
-            
(void)InterlockedDecrementUL(&MiMemoryConsumers[Consumer].PagesUsed);
-            MmRebalanceMemoryConsumers();
-            return(STATUS_NO_MEMORY);
-        }
-
-        /* Insert an allocation request. */
-        Request.Page = 0;
-        KeInitializeEvent(&Request.Event, NotificationEvent, FALSE);
-
-        ExInterlockedInsertTailList(&AllocationListHead, &Request.ListEntry, 
&AllocationListLock);
-        MmRebalanceMemoryConsumers();
-
-        KeWaitForSingleObject(&Request.Event,
-                              0,
-                              KernelMode,
-                              FALSE,
-                              NULL);
-
-        Page = Request.Page;
-        if (Page == 0)
-        {
-            KeBugCheck(NO_PAGES_AVAILABLE);
-        }
-
-        if(Consumer == MC_USER) MmInsertLRULastUserPage(Page);
-        *AllocatedPage = Page;
-
-        if (MmAvailablePages < MiMinimumAvailablePages)
-        {
-            MmRebalanceMemoryConsumers();
-        }
-
-        return(STATUS_SUCCESS);
-    }
-
-    /*
-     * Actually allocate the page.
-     */
-    Page = MmAllocPage(Consumer);
-    if (Page == 0)
-    {
-        KeBugCheck(NO_PAGES_AVAILABLE);
-    }
-    if(Consumer == MC_USER) MmInsertLRULastUserPage(Page);
-    *AllocatedPage = Page;
-
-    if (MmAvailablePages < MiMinimumAvailablePages)
-    {
-        MmRebalanceMemoryConsumers();
-    }
-
-    return(STATUS_SUCCESS);
+   ULONG PagesUsed;
+   PFN_NUMBER Page;
+   KIRQL OldIrql;
+
+   /*
+    * Make sure we don't exceed our individual target.
+    */
+   PagesUsed = InterlockedIncrementUL(&MiMemoryConsumers[Consumer].PagesUsed);
+   if ((PagesUsed > MiMemoryConsumers[Consumer].PagesTarget) &&
+       !MiIsBalancerThread() &&
+       (MmNumberOfPagingFiles == 0))
+   {
+      MmRebalanceMemoryConsumers();
+   }
+
+   /*
+    * Allocate always memory for the non paged pool and for the pager thread.
+    */
+   if ((Consumer == MC_SYSTEM) || MiIsBalancerThread())
+   {
+      OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+      Page = MmAllocPage(Consumer);
+      KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+      if (Page == 0)
+      {
+         KeBugCheck(NO_PAGES_AVAILABLE);
+      }
+      if (Consumer == MC_USER) MmInsertLRULastUserPage(Page);
+      *AllocatedPage = Page;
+      return(STATUS_SUCCESS);
+   }
+
+   /*
+    * Actually allocate the page.
+    */
+   OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+   Page = MmAllocPage(Consumer);
+   KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+   if (Page == 0)
+   {
+      KeBugCheck(NO_PAGES_AVAILABLE);
+   }
+   if(Consumer == MC_USER) MmInsertLRULastUserPage(Page);
+   *AllocatedPage = Page;
+
+   return(STATUS_SUCCESS);
 }
 
 /* Old implementation of the balancer thread */
@@ -388,50 +322,146 @@
     PVOID WaitObjects[2];
     NTSTATUS Status;
     ULONG i;
-
-    WaitObjects[0] = &MiBalancerEvent;
-    WaitObjects[1] = &MiBalancerTimer;
+    PVOID LastPagedPoolAddress = MmPagedPoolStart;
+#ifdef TEST_PAGING
+    PULONG PagingTestBuffer;
+    BOOLEAN TestPage = FALSE;
+#endif
+
+    WaitObjects[0] = &MiBalancerTimer;
+    WaitObjects[1] = &MiBalancerEvent;
+
+#ifdef TEST_PAGING
+    PagingTestBuffer = ExAllocatePoolWithTag(PagedPool, PAGE_SIZE, 'tseT');
+    DPRINT1("PagingTestBuffer: %p, PTE %p\n", PagingTestBuffer, 
MiAddressToPte(PagingTestBuffer));
+    for (i = 0; i < (PAGE_SIZE / sizeof(ULONG)); i++)
+        PagingTestBuffer[i] = i;
+#endif
 
     while (1)
     {
-        Status = KeWaitForMultipleObjects(2,
-                                          WaitObjects,
-                                          WaitAny,
-                                          Executive,
-                                          KernelMode,
-                                          FALSE,
-                                          NULL,
-                                          NULL);
-
-        if (Status == STATUS_WAIT_0 || Status == STATUS_WAIT_1)
-        {
-            ULONG InitialTarget = 0;
-
-#if (_MI_PAGING_LEVELS == 2)
-            if (!MiIsBalancerThread())
-            {
-                /* Clean up the unused PDEs */
-                ULONG_PTR Address;
-                PEPROCESS Process = PsGetCurrentProcess();
-
-                /* Acquire PFN lock */
-                KIRQL OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
-                PMMPDE pointerPde;
-                for (Address = (ULONG_PTR)MI_LOWEST_VAD_ADDRESS;
-                        Address < (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS;
-                        Address += (PAGE_SIZE * PTE_COUNT))
+        /* For now, we only age the paged pool, with 100 pages per run. */
+        LONG Count = 100;
+        PVOID Address = LastPagedPoolAddress;
+        KIRQL OldIrql;
+        PMMPTE PointerPte;
+        PMMPDE PointerPde;
+        ULONG PdeIndex;
+        MMPTE TempPte;
+        PMMPFN Pfn1;
+        BOOLEAN Flush;
+
+        Status = KeWaitForMultipleObjects(
+            2,
+            WaitObjects,
+            WaitAny,
+            Executive,
+            KernelMode,
+            FALSE,
+            NULL,
+            NULL);
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("KeWaitForMultipleObjects failed, status = %x\n", Status);
+            KeBugCheck(MEMORY_MANAGEMENT);
+        }
+
+        DPRINT("MM Balancer: Starting to loop.\n");
+
+        while (Count-- > 0)
+        {
+            Address = (PVOID)((ULONG_PTR) Address + PAGE_SIZE);
+
+            /* Acquire PFN lock while we are cooking */
+            OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+
+            if (Address > MmPagedPoolEnd)
+            {
+                Address = MmPagedPoolStart;
+            }
+
+            PointerPde = MiAddressToPde(Address);
+            PointerPte = MiAddressToPte(Address);
+
+            PdeIndex = ((ULONG_PTR)PointerPde & (SYSTEM_PD_SIZE - 1)) / 
sizeof(MMPTE);
+
+            if (MmSystemPagePtes[PdeIndex].u.Hard.Valid == 0)
+                TempPte.u.Long = 0;
+            else
+                TempPte = *PointerPte;
+
+            if (TempPte.u.Hard.Valid == 0)
+            {
+                /* Bad luck, not a paged-in address */
+#ifdef TEST_PAGING
+                if (PointerPte == MiAddressToPte(PagingTestBuffer))
                 {
-                    if (MiQueryPageTableReferences((PVOID)Address) == 0)
+                    /* Of course it should not magically become a prototype 
pte */
+                    ASSERT(TempPte.u.Soft.Prototype == 0);
+                    if (TempPte.u.Soft.Transition == 0)
                     {
-                        pointerPde = MiAddressToPde(Address);
-                        if (pointerPde->u.Hard.Valid)
-                            MiDeletePte(pointerPde, MiPdeToPte(pointerPde), 
Process, NULL);
-                        ASSERT(pointerPde->u.Hard.Valid == 0);
+                        /* It was paged out! */
+                        ASSERT(TempPte.u.Soft.PageFileHigh != 0);
+                        TestPage = TRUE;
                     }
                 }
-                /* Release lock */
+#endif
                 KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
-            }
+                continue;
+            }
+
+            Flush = FALSE;
+
+            /* Get the Pfn */
+            Pfn1 = MI_PFN_ELEMENT(PFN_FROM_PTE(&TempPte));
+            ASSERT(Pfn1->PteAddress == PointerPte);
+            ASSERT(Pfn1->u3.e1.PrototypePte == 0);
+
+            /* First check if it was written to */
+            if (TempPte.u.Hard.Dirty)
+                Pfn1->u3.e1.Modified = 1;
+
+            /* See if it was accessed since the last time we looked */
+            if (TempPte.u.Hard.Accessed)
+            {
+                /* Yes! Mark the page as young and fresh again */
+                Pfn1->Wsle.u1.e1.Age = 0;
+                /* Tell the CPU we want to know for the next time */
+                TempPte.u.Hard.Accessed = 0;
+                MI_UPDATE_VALID_PTE(PointerPte, TempPte);
+                Flush = TRUE;
+            }
+            else if (Pfn1->Wsle.u1.e1.Age == 3)
+            {
+                /* Page is getting old: Mark the PTE as transition */
+                DPRINT1("MM Balancer: putting %p (page %x) as transition.\n", 
PointerPte,
+                    PFN_FROM_PTE(&TempPte));
+                TempPte.u.Hard.Valid = 0;
+                TempPte.u.Soft.Transition = 1;
+                TempPte.u.Trans.Protection = MM_READWRITE;
+                MiDecrementShareCount(Pfn1, PFN_FROM_PTE(&TempPte));
+                MI_WRITE_INVALID_PTE(PointerPte, TempPte);
+                Flush = TRUE;
+            }
+            else
+            {
+                /* The page is just getting older */
+                Pfn1->Wsle.u1.e1.Age++;
+            }
+
+            /* Flush the TLB entry if we have to */
+            if (Flush)
+            {
+#ifdef CONFIG_SMP
+                // FIXME: Should invalidate entry in every CPU TLB
+                ASSERT(FALSE);
+#endif
+                KeInvalidateTlbEntry(Address);
+            }
+
+            /* Unlock, we're done for this address */
+            KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+        }
 
         DPRINT("MM Balancer: End of the loop.\n");
 
@@ -452,30 +482,20 @@
             TestPage = FALSE;
         }
 #endif
-            do
-            {
-                ULONG OldTarget = InitialTarget;
-
-                /* Trim each consumer */
-                for (i = 0; i < MC_MAXIMUM; i++)
-                {
-                    InitialTarget = MiTrimMemoryConsumer(i, InitialTarget);
-                }
-
-                /* No pages left to swap! */
-                if (InitialTarget != 0 &&
-                        InitialTarget == OldTarget)
-                {
-                    /* Game over */
-                    KeBugCheck(NO_PAGES_AVAILABLE);
-                }
-            }
-            while (InitialTarget != 0);
-        }
-        else
-        {
-            DPRINT1("KeWaitForMultipleObjects failed, status = %x\n", Status);
-            KeBugCheck(MEMORY_MANAGEMENT);
+        /* Remember this for the next run */
+        LastPagedPoolAddress = Address;
+
+        if (Status == STATUS_WAIT_1)
+        {
+            /* Balancer thread was woken up by legacy MM
+             * This means we are really starving. Let's see if this still a 
problem */
+            if ((MmAvailablePages >= MmMinimumFreePages) && 
(MmNumberOfPagingFiles != 0))
+            {
+                /* Yay! No need to trust the old balancer */
+                continue;
+            }
+
+            MiRosBalancerThread();
         }
     }
 }
@@ -485,44 +505,44 @@
 NTAPI
 MiInitBalancerThread(VOID)
 {
-    KPRIORITY Priority;
-    NTSTATUS Status;
+   KPRIORITY Priority;
+   NTSTATUS Status;
 #if !defined(__GNUC__)
 
-    LARGE_INTEGER dummyJunkNeeded;
-    dummyJunkNeeded.QuadPart = -20000000; /* 2 sec */
-    ;
-#endif
-
-
-    KeInitializeEvent(&MiBalancerEvent, SynchronizationEvent, FALSE);
-    KeInitializeTimerEx(&MiBalancerTimer, SynchronizationTimer);
-    KeSetTimerEx(&MiBalancerTimer,
+   LARGE_INTEGER dummyJunkNeeded;
+   dummyJunkNeeded.QuadPart = -20000000; /* 2 sec */
+   ;
+#endif
+
+
+   KeInitializeEvent(&MiBalancerEvent, SynchronizationEvent, FALSE);
+   KeInitializeTimerEx(&MiBalancerTimer, SynchronizationTimer);
+   KeSetTimerEx(&MiBalancerTimer,
 #if defined(__GNUC__)
-                 (LARGE_INTEGER)(LONGLONG)-20000000LL,     /* 2 sec */
+                (LARGE_INTEGER)(LONGLONG)-20000000LL,     /* 2 sec */
 #else
-                 dummyJunkNeeded,
-#endif
-                 2000,         /* 2 sec */
-                 NULL);
-
-    Status = PsCreateSystemThread(&MiBalancerThreadHandle,
-                                  THREAD_ALL_ACCESS,
-                                  NULL,
-                                  NULL,
-                                  &MiBalancerThreadId,
-                                  MiBalancerThread,
-                                  NULL);
-    if (!NT_SUCCESS(Status))
-    {
-        KeBugCheck(MEMORY_MANAGEMENT);
-    }
-
-    Priority = LOW_REALTIME_PRIORITY + 1;
-    NtSetInformationThread(MiBalancerThreadHandle,
-                           ThreadPriority,
-                           &Priority,
-                           sizeof(Priority));
+                dummyJunkNeeded,
+#endif
+                2000,         /* 2 sec */
+                NULL);
+
+   Status = PsCreateSystemThread(&MiBalancerThreadHandle,
+                                 THREAD_ALL_ACCESS,
+                                 NULL,
+                                 NULL,
+                                 &MiBalancerThreadId,
+                                 MiBalancerThread,
+                                 NULL);
+   if (!NT_SUCCESS(Status))
+   {
+      KeBugCheck(MEMORY_MANAGEMENT);
+   }
+
+   Priority = LOW_REALTIME_PRIORITY + 1;
+   NtSetInformationThread(MiBalancerThreadHandle,
+                          ThreadPriority,
+                          &Priority,
+                          sizeof(Priority));
 
 }
 

Modified: branches/TransitionPte/ntoskrnl/mm/pagefile.c
URL: 
http://svn.reactos.org/svn/reactos/branches/TransitionPte/ntoskrnl/mm/pagefile.c?rev=70649&r1=70648&r2=70649&view=diff
==============================================================================
--- branches/TransitionPte/ntoskrnl/mm/pagefile.c       [iso-8859-1] (original)
+++ branches/TransitionPte/ntoskrnl/mm/pagefile.c       [iso-8859-1] Thu Jan 28 
21:17:28 2016
@@ -44,23 +44,24 @@
 
 typedef struct _PAGINGFILE
 {
-    LIST_ENTRY PagingFileListEntry;
-    PFILE_OBJECT FileObject;
-    LARGE_INTEGER MaximumSize;
-    LARGE_INTEGER CurrentSize;
-    PFN_NUMBER FreePages;
-    PFN_NUMBER UsedPages;
-    PULONG AllocMap;
-    KSPIN_LOCK AllocMapLock;
-    ULONG AllocMapSize;
-    PRETRIEVAL_POINTERS_BUFFER RetrievalPointers;
+   LIST_ENTRY PagingFileListEntry;
+   PFILE_OBJECT FileObject;
+   ULONG_PTR MaximumSize;
+   ULONG_PTR CurrentSize;
+   PFN_NUMBER FreePages;
+   PFN_NUMBER UsedPages;
+   PVOID AllocMap;
+   RTL_BITMAP AllocBitMap;
+   ULONG_PTR AllocBitMapHint;
+   KSPIN_LOCK AllocMapLock;
+   PRETRIEVAL_POINTERS_BUFFER RetrievalPointers;
 }
 PAGINGFILE, *PPAGINGFILE;
 
 typedef struct _RETRIEVEL_DESCRIPTOR_LIST
 {
-    struct _RETRIEVEL_DESCRIPTOR_LIST* Next;
-    RETRIEVAL_POINTERS_BUFFER RetrievalPointers;
+   struct _RETRIEVEL_DESCRIPTOR_LIST* Next;
+   RETRIEVAL_POINTERS_BUFFER RetrievalPointers;
 }
 RETRIEVEL_DESCRIPTOR_LIST, *PRETRIEVEL_DESCRIPTOR_LIST;
 
@@ -150,67 +151,67 @@
 NTAPI
 MmShowOutOfSpaceMessagePagingFile(VOID)
 {
-    if (!MmSwapSpaceMessage)
-    {
-        DPRINT1("MM: Out of swap space.\n");
-        MmSwapSpaceMessage = TRUE;
-    }
+   if (!MmSwapSpaceMessage)
+   {
+      DPRINT1("MM: Out of swap space.\n");
+      MmSwapSpaceMessage = TRUE;
+   }
 }
 
 static LARGE_INTEGER
 MmGetOffsetPageFile(PRETRIEVAL_POINTERS_BUFFER RetrievalPointers, 
LARGE_INTEGER Offset)
 {
-    /* Simple binary search */
-    ULONG first, last, mid;
-    first = 0;
-    last = RetrievalPointers->ExtentCount - 1;
-    while (first <= last)
-    {
-        mid = (last - first) / 2 + first;
-        if (Offset.QuadPart < RetrievalPointers->Extents[mid].NextVcn.QuadPart)
-        {
-            if (mid == 0)
+   /* Simple binary search */
+   ULONG first, last, mid;
+   first = 0;
+   last = RetrievalPointers->ExtentCount - 1;
+   while (first <= last)
+   {
+      mid = (last - first) / 2 + first;
+      if (Offset.QuadPart < RetrievalPointers->Extents[mid].NextVcn.QuadPart)
+      {
+         if (mid == 0)
+         {
+            Offset.QuadPart += RetrievalPointers->Extents[0].Lcn.QuadPart - 
RetrievalPointers->StartingVcn.QuadPart;
+            return Offset;
+         }
+         else
+         {
+            if (Offset.QuadPart >= 
RetrievalPointers->Extents[mid-1].NextVcn.QuadPart)
             {
-                Offset.QuadPart += RetrievalPointers->Extents[0].Lcn.QuadPart 
- RetrievalPointers->StartingVcn.QuadPart;
-                return Offset;
+               Offset.QuadPart += RetrievalPointers->Extents[mid].Lcn.QuadPart 
- RetrievalPointers->Extents[mid-1].NextVcn.QuadPart;
+               return Offset;
             }
-            else
-            {
-                if (Offset.QuadPart >= 
RetrievalPointers->Extents[mid-1].NextVcn.QuadPart)
-                {
-                    Offset.QuadPart += 
RetrievalPointers->Extents[mid].Lcn.QuadPart - 
RetrievalPointers->Extents[mid-1].NextVcn.QuadPart;
-                    return Offset;
-                }
-                last = mid - 1;
-            }
-        }
-        else
-        {
-            if (mid == RetrievalPointers->ExtentCount - 1)
-            {
-                break;
-            }
-            if (Offset.QuadPart < 
RetrievalPointers->Extents[mid+1].NextVcn.QuadPart)
-            {
-                Offset.QuadPart += 
RetrievalPointers->Extents[mid+1].Lcn.QuadPart  - 
RetrievalPointers->Extents[mid].NextVcn.QuadPart;
-                return Offset;
-            }
-            first = mid + 1;
-        }
-    }
-    KeBugCheck(MEMORY_MANAGEMENT);
+            last = mid - 1;
+         }
+      }
+      else
+      {
+         if (mid == RetrievalPointers->ExtentCount - 1)
+         {
+            break;
+         }
+         if (Offset.QuadPart < 
RetrievalPointers->Extents[mid+1].NextVcn.QuadPart)
+         {
+            Offset.QuadPart += RetrievalPointers->Extents[mid+1].Lcn.QuadPart  
- RetrievalPointers->Extents[mid].NextVcn.QuadPart;
+            return Offset;
+         }
+         first = mid + 1;
+      }
+   }
+   KeBugCheck(MEMORY_MANAGEMENT);
 #if defined(__GNUC__)
 
-    return (LARGE_INTEGER)0LL;
+   return (LARGE_INTEGER)0LL;
 #else
 
-    {
-        const LARGE_INTEGER dummy =
-        {
+   {
+      const LARGE_INTEGER dummy =
+         {
             0
-        };
-        return dummy;
-    }
+         };
+      return dummy;
+   }
 #endif
 }
 
@@ -218,57 +219,12 @@
 NTAPI
 MmWriteToSwapPage(SWAPENTRY SwapEntry, PFN_NUMBER Page)
 {
-    ULONG i;
-    ULONG_PTR offset;
-    LARGE_INTEGER file_offset;
-    IO_STATUS_BLOCK Iosb;
-    NTSTATUS Status;
-    KEVENT Event;
-    UCHAR MdlBase[sizeof(MDL) + sizeof(ULONG)];
-    PMDL Mdl = (PMDL)MdlBase;
-
-    DPRINT("MmWriteToSwapPage\n");
-
-    if (SwapEntry == 0)
-    {
-        KeBugCheck(MEMORY_MANAGEMENT);
-        return(STATUS_UNSUCCESSFUL);
-    }
-
-    i = FILE_FROM_ENTRY(SwapEntry);
-    offset = OFFSET_FROM_ENTRY(SwapEntry);
-
-    if (PagingFileList[i]->FileObject == NULL ||
-            PagingFileList[i]->FileObject->DeviceObject == NULL)
-    {
-        DPRINT1("Bad paging file 0x%.8X\n", SwapEntry);
-        KeBugCheck(MEMORY_MANAGEMENT);
-    }
-
-    MmInitializeMdl(Mdl, NULL, PAGE_SIZE);
-    MmBuildMdlFromPages(Mdl, &Page);
-    Mdl->MdlFlags |= MDL_PAGES_LOCKED;
-
-    file_offset.QuadPart = offset * PAGE_SIZE;
-    file_offset = MmGetOffsetPageFile(PagingFileList[i]->RetrievalPointers, 
file_offset);
-
-    KeInitializeEvent(&Event, NotificationEvent, FALSE);
-    Status = IoSynchronousPageWrite(PagingFileList[i]->FileObject,
-                                    Mdl,
-                                    &file_offset,
-                                    &Event,
-                                    &Iosb);
-    if (Status == STATUS_PENDING)
-    {
-        KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
-        Status = Iosb.Status;
-    }
-
-    if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
-    {
-        MmUnmapLockedPages (Mdl->MappedSystemVa, Mdl);
-    }
-    return(Status);
+    MMPTE TempPte;
+
+    TempPte.u.Long = 0;
+    TempPte.u.Soft.PageFileHigh = OFFSET_FROM_ENTRY(SwapEntry);
+    TempPte.u.Soft.PageFileLow = FILE_FROM_ENTRY(SwapEntry);
+    return MiWritePageFile(Page, &TempPte);
 }
 
 
@@ -276,65 +232,75 @@
 NTAPI
 MmReadFromSwapPage(SWAPENTRY SwapEntry, PFN_NUMBER Page)
 {
-    return MiReadPageFile(Page, FILE_FROM_ENTRY(SwapEntry), 
OFFSET_FROM_ENTRY(SwapEntry));
+    MMPTE TempPte;
+
+    TempPte.u.Long = 0;
+    TempPte.u.Soft.PageFileHigh = OFFSET_FROM_ENTRY(SwapEntry);
+    TempPte.u.Soft.PageFileLow = FILE_FROM_ENTRY(SwapEntry);
+    return MiReadPageFile(Page, &TempPte);
 }
 
 NTSTATUS
 NTAPI
 MiReadPageFile(
-    _In_ PFN_NUMBER Page,
-    _In_ ULONG PageFileIndex,
-    _In_ ULONG_PTR PageFileOffset)
-{
-    LARGE_INTEGER file_offset;
-    IO_STATUS_BLOCK Iosb;
-    NTSTATUS Status;
-    KEVENT Event;
-    UCHAR MdlBase[sizeof(MDL) + sizeof(ULONG)];
-    PMDL Mdl = (PMDL)MdlBase;
-    PPAGINGFILE PagingFile;
-
-    DPRINT("MiReadSwapFile\n");
-
-    if (PageFileOffset == 0)
-    {
-        KeBugCheck(MEMORY_MANAGEMENT);
-        return(STATUS_UNSUCCESSFUL);
-    }
-
-    ASSERT(PageFileIndex < MAX_PAGING_FILES);
-
-    PagingFile = PagingFileList[PageFileIndex];
-
-    if (PagingFile->FileObject == NULL || PagingFile->FileObject->DeviceObject 
== NULL)
-    {
-        DPRINT1("Bad paging file %u\n", PageFileIndex);
-        KeBugCheck(MEMORY_MANAGEMENT);
-    }
-
-    MmInitializeMdl(Mdl, NULL, PAGE_SIZE);
-    MmBuildMdlFromPages(Mdl, &Page);
-    Mdl->MdlFlags |= MDL_PAGES_LOCKED;
-
-    file_offset.QuadPart = PageFileOffset * PAGE_SIZE;
-    file_offset = MmGetOffsetPageFile(PagingFile->RetrievalPointers, 
file_offset);
-
-    KeInitializeEvent(&Event, NotificationEvent, FALSE);
-    Status = IoPageRead(PagingFile->FileObject,
-                        Mdl,
-                        &file_offset,
-                        &Event,
-                        &Iosb);
-    if (Status == STATUS_PENDING)
-    {
-        KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
-        Status = Iosb.Status;
-    }
-    if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
-    {
-        MmUnmapLockedPages (Mdl->MappedSystemVa, Mdl);
-    }
-    return(Status);
+       _In_ PFN_NUMBER Page,
+       _In_ const MMPTE* PointerPte
+)
+{
+   LARGE_INTEGER FileOffset;
+   IO_STATUS_BLOCK Iosb;
+   ULONG PageFileIndex = PointerPte->u.Soft.PageFileLow;
+   ULONG_PTR PageFileOffset = PointerPte->u.Soft.PageFileHigh;
+   NTSTATUS Status;
+   KEVENT Event;
+   UCHAR MdlBase[sizeof(MDL) + sizeof(PFN_NUMBER)];
+   PMDL Mdl = (PMDL)MdlBase;
+   PPAGINGFILE PagingFile;
+
+   DPRINT("MiReadPageFile\n");
+
+   if (PageFileOffset == 0)
+   {
+      KeBugCheck(MEMORY_MANAGEMENT);
+      return(STATUS_UNSUCCESSFUL);
+   }
+
+   /* Normalize it */
+   PageFileOffset--;
+
+   ASSERT(PageFileIndex < MAX_PAGING_FILES);
+
+   PagingFile = PagingFileList[PageFileIndex];
+
+   if (PagingFile->FileObject == NULL || PagingFile->FileObject->DeviceObject 
== NULL)
+   {
+      DPRINT1("Bad paging file %u\n", PageFileIndex);
+      KeBugCheck(MEMORY_MANAGEMENT);
+   }
+
+   MmInitializeMdl(Mdl, NULL, PAGE_SIZE);
+   MmBuildMdlFromPages(Mdl, &Page);
+   Mdl->MdlFlags |= MDL_PAGES_LOCKED;
+
+   FileOffset.QuadPart = PageFileOffset * PAGE_SIZE;
+   FileOffset = MmGetOffsetPageFile(PagingFile->RetrievalPointers, FileOffset);
+
+   KeInitializeEvent(&Event, NotificationEvent, FALSE);
+   Status = IoPageRead(PagingFile->FileObject,
+                       Mdl,
+                       &FileOffset,
+                       &Event,
+                       &Iosb);
+   if (Status == STATUS_PENDING)
+   {
+      KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+      Status = Iosb.Status;
+   }
+   if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
+   {
+      MmUnmapLockedPages (Mdl->MappedSystemVa, Mdl);
+   }
+   return(Status);
 }
 
 NTSTATUS
@@ -411,19 +377,47 @@
     _In_ PMMPTE PointerPte
 )
 {
-    ULONG i;
-
-    KeInitializeSpinLock(&PagingFileListLock);
-
-    MiFreeSwapPages = 0;
-    MiUsedSwapPages = 0;
-    MiReservedSwapPages = 0;
-
-    for (i = 0; i < MAX_PAGING_FILES; i++)
-    {
-        PagingFileList[i] = NULL;
-    }
-    MmNumberOfPagingFiles = 0;
+    ULONG PageFileIndex;
+    ULONG_PTR PageFileOffset;
+    PPAGINGFILE PageFile;
+
+    /* Some sanity checks */
+    ASSERT(PointerPte->u.Hard.Valid == 0);
+    ASSERT(PointerPte->u.Soft.Transition == 0);
+    ASSERT(PointerPte->u.Soft.Prototype == 0);
+
+    /* We must hold the PFN lock */
+    ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+
+    PageFileIndex = PointerPte->u.Soft.PageFileLow;
+    PageFileOffset = PointerPte->u.Soft.PageFileHigh;
+
+    /* Fix up the value */
+    ASSERT(PageFileOffset != 0);
+    PageFileOffset--;
+
+    DPRINT1("Releasing page file entry %u, %lu\n", PageFileIndex, 
PageFileOffset);
+
+    ASSERT(PageFileIndex < MAX_PAGING_FILES);
+
+    PageFile = PagingFileList[PageFileIndex];
+
+    /* And also lock this pagefile */
+    KeAcquireSpinLockAtDpcLevel(&PageFile->AllocMapLock);
+
+    /* It must be already in use */
+    ASSERT(RtlTestBit(&PageFile->AllocBitMap, PageFileOffset));
+    RtlClearBit(&PageFile->AllocBitMap, PageFileOffset);
+
+    /* One more */
+    PageFile->FreePages++;
+    PageFile->UsedPages--;
+
+    MiFreeSwapPages++;
+    MiUsedSwapPages--;
+
+    /* Done */
+    KeReleaseSpinLockFromDpcLevel(&PageFile->AllocMapLock);
 }
 
 NTSTATUS
@@ -432,28 +426,51 @@
     _Out_ PMMPTE PointerPte
 )
 {
-    KIRQL oldIrql;
-    ULONG i, j;
-
-    KeAcquireSpinLock(&PagingFile->AllocMapLock, &oldIrql);
-
-    for (i = 0; i < PagingFile->AllocMapSize; i++)
+    ULONG PageFileIndex;
+    ULONG_PTR PageFileOffset;
+    PPAGINGFILE PageFile;
+
+    /* We must hold the PFN lock */
+    ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+
+    for (PageFileIndex = 0; PageFileIndex < MAX_PAGING_FILES; PageFileIndex++)
     {
-        for (j = 0; j < 32; j++)
-        {
-            if (!(PagingFile->AllocMap[i] & (1 << j)))
-            {
-                PagingFile->AllocMap[i] |= (1 << j);
-                PagingFile->UsedPages++;
-                PagingFile->FreePages--;
-                KeReleaseSpinLock(&PagingFile->AllocMapLock, oldIrql);
-                return((i * 32) + j);
-            }
-        }
+        if (PagingFileList[PageFileIndex] == NULL)
+            continue;
+        if (PagingFileList[PageFileIndex]->FreePages != 0)
+            break;
     }
 
-    KeReleaseSpinLock(&PagingFile->AllocMapLock, oldIrql);
-    return(0xFFFFFFFF);
+    if (PageFileIndex == MAX_PAGING_FILES)
+    {
+        DPRINT1("Pagefiles are full!\n");
+        return STATUS_PAGEFILE_QUOTA;
+    }
+
+    PointerPte->u.Long = 0;
+
+    PageFile = PagingFileList[PageFileIndex];
+
+    /* And also lock this page file */
+    KeAcquireSpinLockAtDpcLevel(&PageFile->AllocMapLock);
+
+    /* Find a free entry in this page file */
+    PageFileOffset = RtlFindClearBitsAndSet(&PageFile->AllocBitMap, 1, 
PageFile->AllocBitMapHint);
+
+    /* We must have found something as the file was marked as having free 
entries */
+    ASSERT(PageFileOffset != ~((ULONG_PTR)0));
+    PageFile->AllocBitMapHint = PageFileOffset & ~((PageFile->MaximumSize / 
PAGE_SIZE) - 1);
+
+    DPRINT1("Reserving page file entry %lu, %Iu\n", PageFileIndex, 
PageFileOffset);
+
+    /* Done */
+    KeReleaseSpinLockFromDpcLevel(&PageFile->AllocMapLock);
+
+    /* We rely on PageFileHigh being != 0 */
+    PointerPte->u.Soft.PageFileHigh = PageFileOffset + 1;
+    PointerPte->u.Soft.PageFileLow = PageFileIndex;
+
+    return STATUS_SUCCESS;
 }
 
 VOID
@@ -461,89 +478,70 @@
 NTAPI
 MmInitPagingFile(VOID)
 {
-    ULONG i;
-    ULONG_PTR off;
-    KIRQL oldIrql;
-
-    i = FILE_FROM_ENTRY(Entry);
-    off = OFFSET_FROM_ENTRY(Entry);
-
-    KeAcquireSpinLock(&PagingFileListLock, &oldIrql);
-    if (PagingFileList[i] == NULL)
-    {
-        KeBugCheck(MEMORY_MANAGEMENT);
-    }
-    KeAcquireSpinLockAtDpcLevel(&PagingFileList[i]->AllocMapLock);
-
-    PagingFileList[i]->AllocMap[off >> 5] &= (~(1 << (off % 32)));
-
-    PagingFileList[i]->FreePages++;
-    PagingFileList[i]->UsedPages--;
-
-    MiFreeSwapPages++;
-    MiUsedSwapPages--;
-
-    KeReleaseSpinLockFromDpcLevel(&PagingFileList[i]->AllocMapLock);
-    KeReleaseSpinLock(&PagingFileListLock, oldIrql);
+   ULONG i;
+
+   MiFreeSwapPages = 0;
+   MiUsedSwapPages = 0;
+   MiReservedSwapPages = 0;
+
+   for (i = 0; i < MAX_PAGING_FILES; i++)
+   {
+      PagingFileList[i] = NULL;
+   }
+   MmNumberOfPagingFiles = 0;
+}
+
+VOID
+NTAPI
+MmFreeSwapPage(SWAPENTRY Entry)
+{
+    MMPTE TempPte;
+    KIRQL OldIrql;
+
+    TempPte.u.Long = 0;
+    TempPte.u.Soft.PageFileLow = FILE_FROM_ENTRY(Entry);
+    TempPte.u.Soft.PageFileHigh = OFFSET_FROM_ENTRY(Entry);
+
+    OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+    MiFreePageFileEntry(&TempPte);
+    KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
 }
 
 SWAPENTRY
 NTAPI
 MmAllocSwapPage(VOID)
 {
-    KIRQL oldIrql;
-    ULONG i;
-    ULONG off;
+    MMPTE TempPte;
     SWAPENTRY entry;
-
-    KeAcquireSpinLock(&PagingFileListLock, &oldIrql);
-
-    if (MiFreeSwapPages == 0)
-    {
-        KeReleaseSpinLock(&PagingFileListLock, oldIrql);
-        return(0);
-    }
-
-    for (i = 0; i < MAX_PAGING_FILES; i++)
-    {
-        if (PagingFileList[i] != NULL &&
-                PagingFileList[i]->FreePages >= 1)
-        {
-            off = MiAllocPageFromPagingFile(PagingFileList[i]);
-            if (off == 0xFFFFFFFF)
-            {
-                KeBugCheck(MEMORY_MANAGEMENT);
-                KeReleaseSpinLock(&PagingFileListLock, oldIrql);
-                return(STATUS_UNSUCCESSFUL);
-            }
-            MiUsedSwapPages++;
-            MiFreeSwapPages--;
-            KeReleaseSpinLock(&PagingFileListLock, oldIrql);
-
-            entry = ENTRY_FROM_FILE_OFFSET(i, off);
-            return(entry);
-        }
-    }
-
-    KeReleaseSpinLock(&PagingFileListLock, oldIrql);
-    KeBugCheck(MEMORY_MANAGEMENT);
-    return(0);
+    NTSTATUS Status;
+    KIRQL OldIrql;
+
+    OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+    Status = MiReservePageFileEntry(&TempPte);
+    KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+
+    if (!NT_SUCCESS(Status))
+        return 0;
+
+    entry = ENTRY_FROM_FILE_OFFSET(TempPte.u.Soft.PageFileLow, 
TempPte.u.Soft.PageFileHigh);
+
+    return entry;
 }
 
 static PRETRIEVEL_DESCRIPTOR_LIST FASTCALL
 MmAllocRetrievelDescriptorList(ULONG Pairs)
 {
-    ULONG Size;
-    PRETRIEVEL_DESCRIPTOR_LIST RetDescList;
-
-    Size = sizeof(RETRIEVEL_DESCRIPTOR_LIST) + Pairs * 2 * 
sizeof(LARGE_INTEGER);
-    RetDescList = ExAllocatePool(NonPagedPool, Size);
-    if (RetDescList)
-    {
-        RtlZeroMemory(RetDescList, Size);
-    }
-
-    return RetDescList;
+   ULONG Size;
+   PRETRIEVEL_DESCRIPTOR_LIST RetDescList;
+
+   Size = sizeof(RETRIEVEL_DESCRIPTOR_LIST) + Pairs * 2 * 
sizeof(LARGE_INTEGER);
+   RetDescList = ExAllocatePool(NonPagedPool, Size);
+   if (RetDescList)
+   {
+      RtlZeroMemory(RetDescList, Size);
+   }
+
+   return RetDescList;
 }
 
 NTSTATUS NTAPI
@@ -552,340 +550,341 @@
                    IN PLARGE_INTEGER MaximumSize,
                    IN ULONG Reserved)
 {
-    NTSTATUS Status;
-    OBJECT_ATTRIBUTES ObjectAttributes;
-    HANDLE FileHandle;
-    IO_STATUS_BLOCK IoStatus;
-    PFILE_OBJECT FileObject;
-    PPAGINGFILE PagingFile;
-    KIRQL oldIrql;
-    ULONG AllocMapSize;
-    FILE_FS_SIZE_INFORMATION FsSizeInformation;
-    PRETRIEVEL_DESCRIPTOR_LIST RetDescList;
-    PRETRIEVEL_DESCRIPTOR_LIST CurrentRetDescList;
-    ULONG i;
-    ULONG BytesPerAllocationUnit;
-    LARGE_INTEGER Vcn;
-    ULONG ExtentCount;
-    LARGE_INTEGER MaxVcn;
-    ULONG Count;
-    ULONG Size;
-    KPROCESSOR_MODE PreviousMode;
-    UNICODE_STRING CapturedFileName;
-    LARGE_INTEGER SafeInitialSize, SafeMaximumSize;
-
-    DPRINT("NtCreatePagingFile(FileName %wZ, InitialSize %I64d)\n",
-           FileName, InitialSize->QuadPart);
-
-    if (MmNumberOfPagingFiles >= MAX_PAGING_FILES)
-    {
-        return(STATUS_TOO_MANY_PAGING_FILES);
-    }
-
-    PreviousMode = ExGetPreviousMode();
-
-    if (PreviousMode != KernelMode)
-    {
-        _SEH2_TRY
-        {
-            SafeInitialSize = ProbeForReadLargeInteger(InitialSize);
-            SafeMaximumSize = ProbeForReadLargeInteger(MaximumSize);
-        }
-        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-        {
-            /* Return the exception code */
-            _SEH2_YIELD(return _SEH2_GetExceptionCode());
-        }
-        _SEH2_END;
-    }
-    else
-    {
-        SafeInitialSize = *InitialSize;
-        SafeMaximumSize = *MaximumSize;
-    }
-
-    /* Pagefiles can't be larger than 4GB and ofcourse the minimum should be
-       smaller than the maximum */
-    if (0 != SafeInitialSize.u.HighPart)
-    {
-        return STATUS_INVALID_PARAMETER_2;
-    }
-    if (0 != SafeMaximumSize.u.HighPart)
-    {
-        return STATUS_INVALID_PARAMETER_3;
-    }
-    if (SafeMaximumSize.u.LowPart < SafeInitialSize.u.LowPart)
-    {
-        return STATUS_INVALID_PARAMETER_MIX;
-    }
-
-    Status = ProbeAndCaptureUnicodeString(&CapturedFileName,
-                                          PreviousMode,
-                                          FileName);
-    if (!NT_SUCCESS(Status))
-    {
-        return(Status);
-    }
-
-    InitializeObjectAttributes(&ObjectAttributes,
-                               &CapturedFileName,
-                               OBJ_KERNEL_HANDLE,
+   NTSTATUS Status;
+   OBJECT_ATTRIBUTES ObjectAttributes;
+   HANDLE FileHandle;
+   IO_STATUS_BLOCK IoStatus;
+   PFILE_OBJECT FileObject;
+   PPAGINGFILE PagingFile;
+   KIRQL OldIrql;
+   ULONG AllocMapSize;
+   FILE_FS_SIZE_INFORMATION FsSizeInformation;
+   PRETRIEVEL_DESCRIPTOR_LIST RetDescList;
+   PRETRIEVEL_DESCRIPTOR_LIST CurrentRetDescList;
+   ULONG i;
+   ULONG BytesPerAllocationUnit;
+   LARGE_INTEGER Vcn;
+   ULONG ExtentCount;
+   LARGE_INTEGER MaxVcn;
+   ULONG Count;
+   ULONG Size;
+   KPROCESSOR_MODE PreviousMode;
+   UNICODE_STRING CapturedFileName;
+   LARGE_INTEGER SafeInitialSize, SafeMaximumSize;
+
+   DPRINT("NtCreatePagingFile(FileName %wZ, InitialSize %I64d)\n",
+          FileName, InitialSize->QuadPart);
+
+   if (MmNumberOfPagingFiles >= MAX_PAGING_FILES)
+   {
+      return(STATUS_TOO_MANY_PAGING_FILES);
+   }
+
+   PreviousMode = ExGetPreviousMode();
+
+   if (PreviousMode != KernelMode)
+   {
+      _SEH2_TRY
+      {
+         SafeInitialSize = ProbeForReadLargeInteger(InitialSize);
+         SafeMaximumSize = ProbeForReadLargeInteger(MaximumSize);
+      }
+      _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+      {
+          /* Return the exception code */
+          _SEH2_YIELD(return _SEH2_GetExceptionCode());
+      }
+      _SEH2_END;
+   }
+   else
+   {
+      SafeInitialSize = *InitialSize;
+      SafeMaximumSize = *MaximumSize;
+   }
+
+   /* Pagefiles can't be larger than 4GB and ofcourse the minimum should be
+      smaller than the maximum */
+   if (0 != SafeInitialSize.u.HighPart)
+   {
+      return STATUS_INVALID_PARAMETER_2;
+   }
+   if (0 != SafeMaximumSize.u.HighPart)
+   {
+      return STATUS_INVALID_PARAMETER_3;
+   }
+   if (SafeMaximumSize.u.LowPart < SafeInitialSize.u.LowPart)
+   {
+      return STATUS_INVALID_PARAMETER_MIX;
+   }
+
+   Status = ProbeAndCaptureUnicodeString(&CapturedFileName,
+                                         PreviousMode,
+                                         FileName);
+   if (!NT_SUCCESS(Status))
+   {
+      return(Status);
+   }
+
+   InitializeObjectAttributes(&ObjectAttributes,
+                              &CapturedFileName,
+                              0,
+                              NULL,
+                              NULL);
+
+   Status = IoCreateFile(&FileHandle,
+                         FILE_ALL_ACCESS,
+                         &ObjectAttributes,
+                         &IoStatus,
+                         NULL,
+                         0,
+                         0,
+                         FILE_OPEN_IF,
+                         FILE_SYNCHRONOUS_IO_NONALERT,
+                         NULL,
+                         0,
+                         CreateFileTypeNone,
+                         NULL,
+                         SL_OPEN_PAGING_FILE | IO_NO_PARAMETER_CHECKING);
+
+   ReleaseCapturedUnicodeString(&CapturedFileName,
+                                PreviousMode);
+   if (!NT_SUCCESS(Status))
+   {
+      return(Status);
+   }
+
+   Status = ZwQueryVolumeInformationFile(FileHandle,
+                                         &IoStatus,
+                                         &FsSizeInformation,
+                                         sizeof(FILE_FS_SIZE_INFORMATION),
+                                         FileFsSizeInformation);
+   if (!NT_SUCCESS(Status))
+   {
+      ZwClose(FileHandle);
+      return Status;
+   }
+
+   BytesPerAllocationUnit = FsSizeInformation.SectorsPerAllocationUnit *
+                            FsSizeInformation.BytesPerSector;
+   /* FIXME: If we have 2048 BytesPerAllocationUnit (FAT16 < 128MB) there is
+    * a problem if the paging file is fragmented. Suppose the first cluster
+    * of the paging file is cluster 3042 but cluster 3043 is NOT part of the
+    * paging file but of another file. We can't write a complete page (4096
+    * bytes) to the physical location of cluster 3042 then. */
+   if (BytesPerAllocationUnit % PAGE_SIZE)
+   {
+      DPRINT1("BytesPerAllocationUnit %lu is not a multiple of PAGE_SIZE %d\n",
+              BytesPerAllocationUnit, PAGE_SIZE);
+      ZwClose(FileHandle);
+      return STATUS_UNSUCCESSFUL;
+   }
+
+   Status = ZwSetInformationFile(FileHandle,
+                                 &IoStatus,
+                                 &SafeInitialSize,
+                                 sizeof(LARGE_INTEGER),
+                                 FileAllocationInformation);
+   if (!NT_SUCCESS(Status))
+   {
+      ZwClose(FileHandle);
+      return(Status);
+   }
+
+   Status = ObReferenceObjectByHandle(FileHandle,
+                                      FILE_ALL_ACCESS,
+                                      IoFileObjectType,
+                                      PreviousMode,
+                                      (PVOID*)&FileObject,
+                                      NULL);
+   if (!NT_SUCCESS(Status))
+   {
+      ZwClose(FileHandle);
+      return(Status);
+   }
+
+   CurrentRetDescList = RetDescList = 
MmAllocRetrievelDescriptorList(PAIRS_PER_RUN);
+
+   if (CurrentRetDescList == NULL)
+   {
+      ObDereferenceObject(FileObject);
+      ZwClose(FileHandle);
+      return(STATUS_NO_MEMORY);
+   }
+
+#if defined(__GNUC__)
+   Vcn.QuadPart = 0LL;
+#else
+   Vcn.QuadPart = 0;
+#endif
+
+   ExtentCount = 0;
+   MaxVcn.QuadPart = (SafeInitialSize.QuadPart + BytesPerAllocationUnit - 1) / 
BytesPerAllocationUnit;
+   while(1)
+   {
+      Status = ZwFsControlFile(FileHandle,
+                               0,
                                NULL,
-                               NULL);
-
-    Status = IoCreateFile(&FileHandle,
-                          FILE_ALL_ACCESS,
-                          &ObjectAttributes,
-                          &IoStatus,
-                          NULL,
-                          0,
-                          0,
-                          FILE_OPEN_IF,
-                          FILE_SYNCHRONOUS_IO_NONALERT,
-                          NULL,
-                          0,
-                          CreateFileTypeNone,
-                          NULL,
-                          SL_OPEN_PAGING_FILE | IO_NO_PARAMETER_CHECKING);
-
-    ReleaseCapturedUnicodeString(&CapturedFileName,
-                                 PreviousMode);
-    if (!NT_SUCCESS(Status))
-    {
-        return(Status);
-    }
-
-    Status = ZwQueryVolumeInformationFile(FileHandle,
-                                          &IoStatus,
-                                          &FsSizeInformation,
-                                          sizeof(FILE_FS_SIZE_INFORMATION),
-                                          FileFsSizeInformation);
-    if (!NT_SUCCESS(Status))
-    {
-        ZwClose(FileHandle);
-        return Status;
-    }
-
-    BytesPerAllocationUnit = FsSizeInformation.SectorsPerAllocationUnit *
-                             FsSizeInformation.BytesPerSector;
-    /* FIXME: If we have 2048 BytesPerAllocationUnit (FAT16 < 128MB) there is
-     * a problem if the paging file is fragmented. Suppose the first cluster
-     * of the paging file is cluster 3042 but cluster 3043 is NOT part of the
-     * paging file but of another file. We can't write a complete page (4096
-     * bytes) to the physical location of cluster 3042 then. */
-    if (BytesPerAllocationUnit % PAGE_SIZE)
-    {
-        DPRINT1("BytesPerAllocationUnit %lu is not a multiple of PAGE_SIZE 
%d\n",
-                BytesPerAllocationUnit, PAGE_SIZE);
-        ZwClose(FileHandle);
-        return STATUS_UNSUCCESSFUL;
-    }
-
-    Status = ZwSetInformationFile(FileHandle,
-                                  &IoStatus,
-                                  &SafeInitialSize,
-                                  sizeof(LARGE_INTEGER),
-                                  FileAllocationInformation);
-    if (!NT_SUCCESS(Status))
-    {
-        ZwClose(FileHandle);
-        return(Status);
-    }
-
-    Status = ObReferenceObjectByHandle(FileHandle,
-                                       FILE_ALL_ACCESS,
-                                       IoFileObjectType,
-                                       KernelMode,
-                                       (PVOID*)&FileObject,
-                                       NULL);
-    if (!NT_SUCCESS(Status))
-    {
-        ZwClose(FileHandle);
-        return(Status);
-    }
-
-    CurrentRetDescList = RetDescList = 
MmAllocRetrievelDescriptorList(PAIRS_PER_RUN);
-
-    if (CurrentRetDescList == NULL)
-    {
-        ObDereferenceObject(FileObject);
-        ZwClose(FileHandle);
-        return(STATUS_NO_MEMORY);
-    }
-
-#if defined(__GNUC__)
-    Vcn.QuadPart = 0LL;
-#else
-    Vcn.QuadPart = 0;
-#endif
-
-    ExtentCount = 0;
-    MaxVcn.QuadPart = (SafeInitialSize.QuadPart + BytesPerAllocationUnit - 1) 
/ BytesPerAllocationUnit;
-    while(1)
-    {
-        Status = ZwFsControlFile(FileHandle,
-                                 0,
-                                 NULL,
-                                 NULL,
-                                 &IoStatus,
-                                 FSCTL_GET_RETRIEVAL_POINTERS,
-                                 &Vcn,
-                                 sizeof(LARGE_INTEGER),
-                                 &CurrentRetDescList->RetrievalPointers,
-                                 sizeof(RETRIEVAL_POINTERS_BUFFER) + 
PAIRS_PER_RUN * 2 * sizeof(LARGE_INTEGER));
-        if (!NT_SUCCESS(Status))
-        {
+                               NULL,
+                               &IoStatus,
+                               FSCTL_GET_RETRIEVAL_POINTERS,
+                               &Vcn,
+                               sizeof(LARGE_INTEGER),
+                               &CurrentRetDescList->RetrievalPointers,
+                               sizeof(RETRIEVAL_POINTERS_BUFFER) + 
PAIRS_PER_RUN * 2 * sizeof(LARGE_INTEGER));
+      if (!NT_SUCCESS(Status))
+      {
+         while (RetDescList)
+         {
+            CurrentRetDescList = RetDescList;
+            RetDescList = RetDescList->Next;
+            ExFreePool(CurrentRetDescList);
+         }
+         ObDereferenceObject(FileObject);
+         ZwClose(FileHandle);
+         return(Status);
+      }
+      ExtentCount += CurrentRetDescList->RetrievalPointers.ExtentCount;
+      if 
(CurrentRetDescList->RetrievalPointers.Extents[CurrentRetDescList->RetrievalPointers.ExtentCount-1].NextVcn.QuadPart
 < MaxVcn.QuadPart)
+      {
+         CurrentRetDescList->Next = 
MmAllocRetrievelDescriptorList(PAIRS_PER_RUN);
+         if (CurrentRetDescList->Next == NULL)
+         {
             while (RetDescList)
             {
-                CurrentRetDescList = RetDescList;
-                RetDescList = RetDescList->Next;
-                ExFreePool(CurrentRetDescList);
+               CurrentRetDescList = RetDescList;
+               RetDescList = RetDescList->Next;
+               ExFreePool(CurrentRetDescList);
             }
             ObDereferenceObject(FileObject);
             ZwClose(FileHandle);
-            return(Status);
-        }
-        ExtentCount += CurrentRetDescList->RetrievalPointers.ExtentCount;
-        if 
(CurrentRetDescList->RetrievalPointers.Extents[CurrentRetDescList->RetrievalPointers.ExtentCount-1].NextVcn.QuadPart
 < MaxVcn.QuadPart)
-        {
-            CurrentRetDescList->Next = 
MmAllocRetrievelDescriptorList(PAIRS_PER_RUN);
-            if (CurrentRetDescList->Next == NULL)
-            {
-                while (RetDescList)
-                {
-                    CurrentRetDescList = RetDescList;
-                    RetDescList = RetDescList->Next;
-                    ExFreePool(CurrentRetDescList);
-                }
-                ObDereferenceObject(FileObject);
-                ZwClose(FileHandle);
-                return(STATUS_NO_MEMORY);
-            }
-            Vcn = 
CurrentRetDescList->RetrievalPointers.Extents[CurrentRetDescList->RetrievalPointers.ExtentCount-1].NextVcn;
-            CurrentRetDescList = CurrentRetDescList->Next;
-        }
-        else
-        {
-            break;
-        }
-    }
-
-    PagingFile = ExAllocatePool(NonPagedPool, sizeof(*PagingFile));
-    if (PagingFile == NULL)
-    {
-        while (RetDescList)
-        {
-            CurrentRetDescList = RetDescList;
-            RetDescList = RetDescList->Next;
-            ExFreePool(CurrentRetDescList);
-        }
-        ObDereferenceObject(FileObject);
-        ZwClose(FileHandle);
-        return(STATUS_NO_MEMORY);
-    }
-
-    RtlZeroMemory(PagingFile, sizeof(*PagingFile));
-
-    PagingFile->FileObject = FileObject;
-    PagingFile->MaximumSize.QuadPart = SafeMaximumSize.QuadPart;
-    PagingFile->CurrentSize.QuadPart = SafeInitialSize.QuadPart;
-    PagingFile->FreePages = (ULONG)(SafeInitialSize.QuadPart / PAGE_SIZE);
-    PagingFile->UsedPages = 0;
-    KeInitializeSpinLock(&PagingFile->AllocMapLock);
-
-    AllocMapSize = (PagingFile->FreePages / 32) + 1;
-    PagingFile->AllocMap = ExAllocatePool(NonPagedPool,
-                                          AllocMapSize * sizeof(ULONG));
-    PagingFile->AllocMapSize = AllocMapSize;
-
-    if (PagingFile->AllocMap == NULL)
-    {
-        while (RetDescList)
-        {
-            CurrentRetDescList = RetDescList;
-            RetDescList = RetDescList->Next;
-            ExFreePool(CurrentRetDescList);
-        }
-        ExFreePool(PagingFile);
-        ObDereferenceObject(FileObject);
-        ZwClose(FileHandle);
-        return(STATUS_NO_MEMORY);
-    }
-    DPRINT("ExtentCount: %lu\n", ExtentCount);
-    Size = sizeof(RETRIEVAL_POINTERS_BUFFER) + ExtentCount * 2 * 
sizeof(LARGE_INTEGER);
-    PagingFile->RetrievalPointers = ExAllocatePool(NonPagedPool, Size);
-    if (PagingFile->RetrievalPointers == NULL)
-    {
-        while (RetDescList)
-        {
-            CurrentRetDescList = RetDescList;
-            RetDescList = RetDescList->Next;
-            ExFreePool(CurrentRetDescList);
-        }
-        ExFreePool(PagingFile->AllocMap);
-        ExFreePool(PagingFile);
-        ObDereferenceObject(FileObject);
-        ZwClose(FileHandle);
-        return(STATUS_NO_MEMORY);
-    }
-
-    RtlZeroMemory(PagingFile->AllocMap, AllocMapSize * sizeof(ULONG));
-    RtlZeroMemory(PagingFile->RetrievalPointers, Size);
-
-    Count = 0;
-    PagingFile->RetrievalPointers->ExtentCount = ExtentCount;
-    PagingFile->RetrievalPointers->StartingVcn = 
RetDescList->RetrievalPointers.StartingVcn;
-    CurrentRetDescList = RetDescList;
-    while (CurrentRetDescList)
-    {
-        memcpy(&PagingFile->RetrievalPointers->Extents[Count],
-               CurrentRetDescList->RetrievalPointers.Extents,
-               CurrentRetDescList->RetrievalPointers.ExtentCount * 2 * 
sizeof(LARGE_INTEGER));
-        Count += CurrentRetDescList->RetrievalPointers.ExtentCount;
-        RetDescList = CurrentRetDescList;
-        CurrentRetDescList = CurrentRetDescList->Next;
-        ExFreePool(RetDescList);
-    }
-
-    if (PagingFile->RetrievalPointers->ExtentCount != ExtentCount ||
-            PagingFile->RetrievalPointers->Extents[ExtentCount - 
1].NextVcn.QuadPart != MaxVcn.QuadPart)
-    {
-        ExFreePool(PagingFile->RetrievalPointers);
-        ExFreePool(PagingFile->AllocMap);
-        ExFreePool(PagingFile);
-        ObDereferenceObject(FileObject);
-        ZwClose(FileHandle);
-        return(STATUS_UNSUCCESSFUL);
-    }
-
-    /*
-     * Change the entries from lcn's to volume offset's.
-     */
-    PagingFile->RetrievalPointers->StartingVcn.QuadPart *= 
BytesPerAllocationUnit;
-    for (i = 0; i < ExtentCount; i++)
-    {
-        PagingFile->RetrievalPointers->Extents[i].Lcn.QuadPart *= 
BytesPerAllocationUnit;
-        PagingFile->RetrievalPointers->Extents[i].NextVcn.QuadPart *= 
BytesPerAllocationUnit;
-    }
-
-    KeAcquireSpinLock(&PagingFileListLock, &oldIrql);
-    for (i = 0; i < MAX_PAGING_FILES; i++)
-    {
-        if (PagingFileList[i] == NULL)
-        {
-            PagingFileList[i] = PagingFile;
-            break;
-        }
-    }
-    MiFreeSwapPages = MiFreeSwapPages + PagingFile->FreePages;
-    MmNumberOfPagingFiles++;
-    KeReleaseSpinLock(&PagingFileListLock, oldIrql);
-
-    ZwClose(FileHandle);
-
-    MmSwapSpaceMessage = FALSE;
-
-    return(STATUS_SUCCESS);
+            return(STATUS_NO_MEMORY);
+         }
+         Vcn = 
CurrentRetDescList->RetrievalPointers.Extents[CurrentRetDescList->RetrievalPointers.ExtentCount-1].NextVcn;
+         CurrentRetDescList = CurrentRetDescList->Next;
+      }
+      else
+      {
+         break;
+      }
+   }
+
+   PagingFile = ExAllocatePool(NonPagedPool, sizeof(*PagingFile));
+   if (PagingFile == NULL)
+   {
+      while (RetDescList)
+      {
+         CurrentRetDescList = RetDescList;
+         RetDescList = RetDescList->Next;
+         ExFreePool(CurrentRetDescList);
+      }
+      ObDereferenceObject(FileObject);
+      ZwClose(FileHandle);
+      return(STATUS_NO_MEMORY);
+   }
+
+   RtlZeroMemory(PagingFile, sizeof(*PagingFile));
+
+   PagingFile->FileObject = FileObject;
+   PagingFile->MaximumSize = SafeMaximumSize.LowPart;
+   PagingFile->CurrentSize = SafeInitialSize.LowPart;
+   PagingFile->FreePages = (ULONG)(SafeMaximumSize.LowPart / PAGE_SIZE);
+   PagingFile->UsedPages = 0;
+   KeInitializeSpinLock(&PagingFile->AllocMapLock);
+
+   AllocMapSize = (PagingFile->FreePages / 32) + 1;
+   PagingFile->AllocMap = ExAllocatePool(NonPagedPool,
+                                         AllocMapSize * sizeof(ULONG));
+
+   if (PagingFile->AllocMap == NULL)
+   {
+      while (RetDescList)
+      {
+         CurrentRetDescList = RetDescList;
+         RetDescList = RetDescList->Next;
+         ExFreePool(CurrentRetDescList);
+      }
+      ExFreePool(PagingFile);
+      ObDereferenceObject(FileObject);
+      ZwClose(FileHandle);
+      return(STATUS_NO_MEMORY);
+   }
+   DPRINT("ExtentCount: %lu\n", ExtentCount);
+   Size = sizeof(RETRIEVAL_POINTERS_BUFFER) + ExtentCount * 2 * 
sizeof(LARGE_INTEGER);
+   PagingFile->RetrievalPointers = ExAllocatePool(NonPagedPool, Size);
+   if (PagingFile->RetrievalPointers == NULL)
+   {
+      while (RetDescList)
+      {
+         CurrentRetDescList = RetDescList;
+         RetDescList = RetDescList->Next;
+         ExFreePool(CurrentRetDescList);
+      }
+      ExFreePool(PagingFile->AllocMap);
+      ExFreePool(PagingFile);
+      ObDereferenceObject(FileObject);
+      ZwClose(FileHandle);
+      return(STATUS_NO_MEMORY);
+   }
+
+   RtlZeroMemory(PagingFile->RetrievalPointers, Size);
+
+   RtlInitializeBitMap(&PagingFile->AllocBitMap, PagingFile->AllocMap, 
AllocMapSize * 32);
+   RtlClearAllBits(&PagingFile->AllocBitMap);
+
+   Count = 0;
+   PagingFile->RetrievalPointers->ExtentCount = ExtentCount;
+   PagingFile->RetrievalPointers->StartingVcn = 
RetDescList->RetrievalPointers.StartingVcn;
+   CurrentRetDescList = RetDescList;
+   while (CurrentRetDescList)
+   {
+      memcpy(&PagingFile->RetrievalPointers->Extents[Count],
+             CurrentRetDescList->RetrievalPointers.Extents,
+             CurrentRetDescList->RetrievalPointers.ExtentCount * 2 * 
sizeof(LARGE_INTEGER));
+      Count += CurrentRetDescList->RetrievalPointers.ExtentCount;
+      RetDescList = CurrentRetDescList;
+      CurrentRetDescList = CurrentRetDescList->Next;
+      ExFreePool(RetDescList);
+   }
+
+   if (PagingFile->RetrievalPointers->ExtentCount != ExtentCount ||
+         PagingFile->RetrievalPointers->Extents[ExtentCount - 
1].NextVcn.QuadPart != MaxVcn.QuadPart)
+   {
+      ExFreePool(PagingFile->RetrievalPointers);
+      ExFreePool(PagingFile->AllocMap);
+      ExFreePool(PagingFile);
+      ObDereferenceObject(FileObject);
+      ZwClose(FileHandle);
+      return(STATUS_UNSUCCESSFUL);
+   }
+
+   /*
+    * Change the entries from lcn's to volume offset's.
+    */
+   PagingFile->RetrievalPointers->StartingVcn.QuadPart *= 
BytesPerAllocationUnit;
+   for (i = 0; i < ExtentCount; i++)
+   {
+      PagingFile->RetrievalPointers->Extents[i].Lcn.QuadPart *= 
BytesPerAllocationUnit;
+      PagingFile->RetrievalPointers->Extents[i].NextVcn.QuadPart *= 
BytesPerAllocationUnit;
+   }
+
+   OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+   for (i = 0; i < MAX_PAGING_FILES; i++)
+   {
+      if (PagingFileList[i] == NULL)
+      {
+         PagingFileList[i] = PagingFile;
+         break;
+      }
+   }
+   MiFreeSwapPages = MiFreeSwapPages + PagingFile->FreePages;
+   MmNumberOfPagingFiles++;
+   KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+
+   ZwClose(FileHandle);
+
+   MmSwapSpaceMessage = FALSE;
+
+   return(STATUS_SUCCESS);
 }
 
 /* EOF */


Reply via email to