Revert part of r20493. Created bug 1229 to keep track of the issue.
[reactos.git] / reactos / ntoskrnl / mm / pagefile.c
index 8e732ca..5cccff8 100644 (file)
@@ -16,8 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: pagefile.c,v 1.36 2003/08/29 21:22:24 dwelch Exp $
- *
+/*
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/mm/pagefile.c
  * PURPOSE:         Paging file functions
 
 /* INCLUDES *****************************************************************/
 
-#include <ddk/ntddk.h>
-#include <internal/io.h>
-#include <internal/mm.h>
-#include <napi/core.h>
-#include <internal/ps.h>
-#include <internal/ldr.h>
-
+#include <ntoskrnl.h>
 #define NDEBUG
 #include <internal/debug.h>
 
+#if defined (ALLOC_PRAGMA)
+#pragma alloc_text(INIT, MmInitPagingFile)
+#endif
+
+
 /* TYPES *********************************************************************/
 
 typedef struct _PAGINGFILE
@@ -51,11 +49,21 @@ typedef struct _PAGINGFILE
    PULONG AllocMap;
    KSPIN_LOCK AllocMapLock;
    ULONG AllocMapSize;
-   PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers;
-} PAGINGFILE, *PPAGINGFILE;
+   PRETRIEVAL_POINTERS_BUFFER RetrievalPointers;
+}
+PAGINGFILE, *PPAGINGFILE;
+
+typedef struct _RETRIEVEL_DESCRIPTOR_LIST
+{
+   struct _RETRIEVEL_DESCRIPTOR_LIST* Next;
+   RETRIEVAL_POINTERS_BUFFER RetrievalPointers;
+}
+RETRIEVEL_DESCRIPTOR_LIST, *PRETRIEVEL_DESCRIPTOR_LIST;
 
 /* GLOBALS *******************************************************************/
 
+#define PAIRS_PER_RUN (1024)
+
 #define MAX_PAGING_FILES  (32)
 
 /* List of paging files, both used and free */
@@ -68,17 +76,17 @@ static KSPIN_LOCK PagingFileListLock;
 static ULONG MiPagingFileCount;
 
 /* Number of pages that are available for swapping */
-static ULONG MiFreeSwapPages;
+ULONG MiFreeSwapPages;
 
 /* Number of pages that have been allocated for swapping */
-static ULONG MiUsedSwapPages;
+ULONG MiUsedSwapPages;
 
-/* 
- * Number of pages that have been reserved for swapping but not yet allocated 
+/*
+ * Number of pages that have been reserved for swapping but not yet allocated
  */
 static ULONG MiReservedSwapPages;
 
-/* 
+/*
  * Ratio between reserved and available swap pages, e.g. setting this to five
  * forces one swap page to be available for every five swap pages that are
  * reserved. Setting this to zero turns off commit checking altogether.
@@ -113,593 +121,660 @@ static BOOLEAN MmSwapSpaceMessage = FALSE;
 
 /* FUNCTIONS *****************************************************************/
 
+BOOLEAN
+STDCALL
+MmIsFileAPagingFile(PFILE_OBJECT FileObject)
+{
+    ULONG i;
+
+    /* Loop through all the paging files */
+    for (i = 0; i < MiPagingFileCount; i++)
+    {
+        /* Check if this is one of them */
+        if (PagingFileList[i]->FileObject == FileObject) return TRUE;
+    }
+
+    /* Nothing found */
+    return FALSE;
+}
+
 VOID
+NTAPI
 MmShowOutOfSpaceMessagePagingFile(VOID)
 {
-  if (!MmSwapSpaceMessage)
-    {
+   if (!MmSwapSpaceMessage)
+   {
       DPRINT1("MM: Out of swap space.\n");
       MmSwapSpaceMessage = TRUE;
-    }
+   }
+}
+
+LARGE_INTEGER STATIC
+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)
+         {
+            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[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(0);
+#if defined(__GNUC__)
+
+   return (LARGE_INTEGER)0LL;
+#else
+
+   {
+      const LARGE_INTEGER dummy =
+         {
+            0
+         };
+      return dummy;
+   }
+#endif
 }
 
-NTSTATUS MmWriteToSwapPage(SWAPENTRY SwapEntry, PMDL Mdl)
+NTSTATUS
+NTAPI
+MmWriteToSwapPage(SWAPENTRY SwapEntry, PFN_TYPE Page)
 {
-   ULONG i, offset, j;
+   ULONG i, offset;
    LARGE_INTEGER file_offset;
    IO_STATUS_BLOCK Iosb;
    NTSTATUS Status;
    KEVENT Event;
-   PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers;
+   UCHAR MdlBase[sizeof(MDL) + sizeof(ULONG)];
+   PMDL Mdl = (PMDL)MdlBase;
 
    DPRINT("MmWriteToSwapPage\n");
-   
+
    if (SwapEntry == 0)
-     {
-       KEBUGCHECK(0);
-       return(STATUS_UNSUCCESSFUL);
-     }
-   
+   {
+      KEBUGCHECK(0);
+      return(STATUS_UNSUCCESSFUL);
+   }
+
    i = FILE_FROM_ENTRY(SwapEntry);
    offset = OFFSET_FROM_ENTRY(SwapEntry);
 
    if (i >= MAX_PAGING_FILES)
-     {
-       DPRINT1("Bad swap entry 0x%.8X\n", SwapEntry);
-       KEBUGCHECK(0);
-     }
+   {
+      DPRINT1("Bad swap entry 0x%.8X\n", SwapEntry);
+      KEBUGCHECK(0);
+   }
    if (PagingFileList[i]->FileObject == NULL ||
-       PagingFileList[i]->FileObject->DeviceObject == NULL)
-     {
-       DPRINT1("Bad paging file 0x%.8X\n", SwapEntry);
-       KEBUGCHECK(0);
-     }
-   
-   file_offset.QuadPart = offset * PAGE_SIZE;
-   RetrievalPointers = PagingFileList[i]->RetrievalPointers;
+         PagingFileList[i]->FileObject->DeviceObject == NULL)
+   {
+      DPRINT1("Bad paging file 0x%.8X\n", SwapEntry);
+      KEBUGCHECK(0);
+   }
 
-   for (j = 0; j < RetrievalPointers->NumberOfPairs; j++)
-     {
-       if ((ULONGLONG) file_offset.QuadPart < RetrievalPointers->Pair[j].Vcn)
-         {
-           if (j == 0)
-            {
-              file_offset.QuadPart += RetrievalPointers->Pair[0].Lcn - RetrievalPointers->StartVcn;
-            }
-          else
-            {
-               file_offset.QuadPart += RetrievalPointers->Pair[j].Lcn  - RetrievalPointers->Pair[j-1].Vcn;
-            }
-          break;
-         }
-     }
-   if (j >= RetrievalPointers->NumberOfPairs)
-     {
-       CHECKPOINT1;
-       KEBUGCHECK(0);
-     }
+   MmInitializeMdl(Mdl, NULL, PAGE_SIZE);
+   MmBuildMdlFromPages(Mdl, &Page);
+
+   file_offset.QuadPart = offset * PAGE_SIZE;
+   file_offset = MmGetOffsetPageFile(PagingFileList[i]->RetrievalPointers, file_offset);
 
    KeInitializeEvent(&Event, NotificationEvent, FALSE);
-   Status = IoPageWrite(PagingFileList[i]->FileObject,
-                       Mdl,
-                       &file_offset,
-                       &Event,
-                       &Iosb);
+   Status = IoSynchronousPageWrite(PagingFileList[i]->FileObject,
+                                   Mdl,
+                                   &file_offset,
+                                   &Event,
+                                   &Iosb);
    if (Status == STATUS_PENDING)
    {
       KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
-      return(Iosb.Status);
+      Status = Iosb.Status;
    }
+   MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
    return(Status);
 }
 
-NTSTATUS MmReadFromSwapPage(SWAPENTRY SwapEntry, PMDL Mdl)
+NTSTATUS
+NTAPI
+MmReadFromSwapPage(SWAPENTRY SwapEntry, PFN_TYPE Page)
 {
-   ULONG i, offset, j;
+   ULONG i, offset;
    LARGE_INTEGER file_offset;
    IO_STATUS_BLOCK Iosb;
    NTSTATUS Status;
    KEVENT Event;
-   PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers;
+   UCHAR MdlBase[sizeof(MDL) + sizeof(ULONG)];
+   PMDL Mdl = (PMDL)MdlBase;
 
    DPRINT("MmReadFromSwapPage\n");
-   
+
    if (SwapEntry == 0)
-     {
-       KEBUGCHECK(0);
-       return(STATUS_UNSUCCESSFUL);
-     }
-   
+   {
+      KEBUGCHECK(0);
+      return(STATUS_UNSUCCESSFUL);
+   }
+
    i = FILE_FROM_ENTRY(SwapEntry);
    offset = OFFSET_FROM_ENTRY(SwapEntry);
 
    if (i >= MAX_PAGING_FILES)
-     {
-       DPRINT1("Bad swap entry 0x%.8X\n", SwapEntry);
-       KEBUGCHECK(0);
-     }
+   {
+      DPRINT1("Bad swap entry 0x%.8X\n", SwapEntry);
+      KEBUGCHECK(0);
+   }
    if (PagingFileList[i]->FileObject == NULL ||
-       PagingFileList[i]->FileObject->DeviceObject == NULL)
-     {
-       DPRINT1("Bad paging file 0x%.8X\n", SwapEntry);
-       KEBUGCHECK(0);
-     }
-   
+         PagingFileList[i]->FileObject->DeviceObject == NULL)
+   {
+      DPRINT1("Bad paging file 0x%.8X\n", SwapEntry);
+      KEBUGCHECK(0);
+   }
+
+   MmInitializeMdl(Mdl, NULL, PAGE_SIZE);
+   MmBuildMdlFromPages(Mdl, &Page);
+
    file_offset.QuadPart = offset * PAGE_SIZE;
-   RetrievalPointers = PagingFileList[i]->RetrievalPointers;
+   file_offset = MmGetOffsetPageFile(PagingFileList[i]->RetrievalPointers, file_offset);
 
-   for (j = 0; j < RetrievalPointers->NumberOfPairs; j++)
-     {
-       if ((ULONGLONG) file_offset.QuadPart < RetrievalPointers->Pair[j].Vcn)
-         {
-           if (j == 0)
-            {
-              file_offset.QuadPart += RetrievalPointers->Pair[0].Lcn - RetrievalPointers->StartVcn;
-            }
-          else
-            {
-               file_offset.QuadPart += RetrievalPointers->Pair[j].Lcn  - RetrievalPointers->Pair[j-1].Vcn;
-            }
-          break;
-         }
-     }
-   if (j >= RetrievalPointers->NumberOfPairs)
-     {
-       CHECKPOINT1;
-       KEBUGCHECK(0);
-     }
    KeInitializeEvent(&Event, NotificationEvent, FALSE);
    Status = IoPageRead(PagingFileList[i]->FileObject,
-                      Mdl,
-                      &file_offset,
-                      &Event,
-                      &Iosb);
+                       Mdl,
+                       &file_offset,
+                       &Event,
+                       &Iosb);
    if (Status == STATUS_PENDING)
    {
       KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
-      return(Iosb.Status);
+      Status = Iosb.Status;
    }
+   MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
    return(Status);
 }
 
-VOID 
+VOID
+INIT_FUNCTION
+NTAPI
 MmInitPagingFile(VOID)
 {
    ULONG i;
-   
+
    KeInitializeSpinLock(&PagingFileListLock);
-   
+
    MiFreeSwapPages = 0;
    MiUsedSwapPages = 0;
    MiReservedSwapPages = 0;
-   
+
    for (i = 0; i < MAX_PAGING_FILES; i++)
-     {
-       PagingFileList[i] = NULL;
-     }
+   {
+      PagingFileList[i] = NULL;
+   }
    MiPagingFileCount = 0;
 
    /*
     * Initialize the crash dump support.
     */
    if (MmCoreDumpType != MM_CORE_DUMP_TYPE_NONE)
-     {
-       MmCoreDumpPageFrame = MmAllocateSection(PAGE_SIZE);
-       if (MmCoreDumpType == MM_CORE_DUMP_TYPE_FULL)
-        {
-          MmCoreDumpSize = MmStats.NrTotalPages * 4096 + 1024 * 1024;
-        }
-       else
-        {
-          MmCoreDumpSize = 1024 * 1024;
-        }
-     }
+   {
+      MmCoreDumpPageFrame = MmAllocateSection(PAGE_SIZE, NULL);
+      if (MmCoreDumpType == MM_CORE_DUMP_TYPE_FULL)
+      {
+         MmCoreDumpSize = MmStats.NrTotalPages * 4096 + 1024 * 1024;
+      }
+      else
+      {
+         MmCoreDumpSize = 1024 * 1024;
+      }
+   }
 }
 
 BOOLEAN
+NTAPI
 MmReserveSwapPages(ULONG Nr)
 {
    KIRQL oldIrql;
    ULONG MiAvailSwapPages;
-   
+
    KeAcquireSpinLock(&PagingFileListLock, &oldIrql);
    MiAvailSwapPages =
-     (MiFreeSwapPages * MM_PAGEFILE_COMMIT_RATIO) + MM_PAGEFILE_COMMIT_GRACE;
+      (MiFreeSwapPages * MM_PAGEFILE_COMMIT_RATIO) + MM_PAGEFILE_COMMIT_GRACE;
    MiReservedSwapPages = MiReservedSwapPages + Nr;
    if (MM_PAGEFILE_COMMIT_RATIO != 0 && MiAvailSwapPages < MiReservedSwapPages)
-     {
-       KeReleaseSpinLock(&PagingFileListLock, oldIrql);
-       return(FALSE);
-     }   
+   {
+      KeReleaseSpinLock(&PagingFileListLock, oldIrql);
+      return(FALSE);
+   }
    KeReleaseSpinLock(&PagingFileListLock, oldIrql);
    return(TRUE);
 }
 
-VOID 
+VOID
+NTAPI
 MmDereserveSwapPages(ULONG Nr)
 {
    KIRQL oldIrql;
-   
+
    KeAcquireSpinLock(&PagingFileListLock, &oldIrql);
    MiReservedSwapPages = MiReservedSwapPages - Nr;
    KeReleaseSpinLock(&PagingFileListLock, oldIrql);
 }
 
-static ULONG 
+static ULONG
 MiAllocPageFromPagingFile(PPAGINGFILE PagingFile)
 {
    KIRQL oldIrql;
    ULONG i, j;
-   
+
    KeAcquireSpinLock(&PagingFile->AllocMapLock, &oldIrql);
-   
+
    for (i = 0; i < PagingFile->AllocMapSize; i++)
-     {
-       for (j = 0; j < 32; j++)
-        {
-          if (!(PagingFile->AllocMap[i] & (1 << j)))
-            {
-              break;
-            }
-        }
-       if (j == 32)
-        {
-          continue;
-        }
-       PagingFile->AllocMap[i] |= (1 << j);
-       PagingFile->UsedPages++;
-       PagingFile->FreePages--;
-       KeReleaseSpinLock(&PagingFile->AllocMapLock, oldIrql);
-       return((i * 32) + j);
-     }
-   
+   {
+      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);
+         }
+      }
+   }
+
    KeReleaseSpinLock(&PagingFile->AllocMapLock, oldIrql);
    return(0xFFFFFFFF);
 }
 
-VOID 
+VOID
+NTAPI
 MmFreeSwapPage(SWAPENTRY Entry)
 {
    ULONG i;
    ULONG off;
    KIRQL oldIrql;
-   
+
    i = FILE_FROM_ENTRY(Entry);
    off = OFFSET_FROM_ENTRY(Entry);
-   
+
+   if (i >= MAX_PAGING_FILES)
+   {
+       DPRINT1("Bad swap entry 0x%.8X\n", Entry);
+       KEBUGCHECK(0);
+   }
+
    KeAcquireSpinLock(&PagingFileListLock, &oldIrql);
    if (PagingFileList[i] == NULL)
-     {
-       KEBUGCHECK(0);
-     }
+   {
+      KEBUGCHECK(0);
+   }
    KeAcquireSpinLockAtDpcLevel(&PagingFileList[i]->AllocMapLock);
-   
-   PagingFileList[i]->AllocMap[off / 32] &= (~(1 << (off % 32)));
-   
+
+   PagingFileList[i]->AllocMap[off >> 5] &= (~(1 << (off % 32)));
+
    PagingFileList[i]->FreePages++;
    PagingFileList[i]->UsedPages--;
-   
+
    MiFreeSwapPages++;
    MiUsedSwapPages--;
-   
+
    KeReleaseSpinLockFromDpcLevel(&PagingFileList[i]->AllocMapLock);
    KeReleaseSpinLock(&PagingFileListLock, oldIrql);
 }
 
 BOOLEAN
+NTAPI
 MmIsAvailableSwapPage(VOID)
 {
-  return(MiFreeSwapPages > 0);
+   return(MiFreeSwapPages > 0);
 }
 
-SWAPENTRY 
+SWAPENTRY
+NTAPI
 MmAllocSwapPage(VOID)
 {
    KIRQL oldIrql;
    ULONG i;
    ULONG off;
-   SWAPENTRY entry;   
-   
+   SWAPENTRY entry;
+
    KeAcquireSpinLock(&PagingFileListLock, &oldIrql);
-   
+
    if (MiFreeSwapPages == 0)
-     {
-       KeReleaseSpinLock(&PagingFileListLock, oldIrql);        
-       return(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(0);
-                 KeReleaseSpinLock(&PagingFileListLock, oldIrql);
-                 return(STATUS_UNSUCCESSFUL);
-              }
-            MiUsedSwapPages++;
-            MiFreeSwapPages--;
-            KeReleaseSpinLock(&PagingFileListLock, oldIrql);
-            
-            entry = ENTRY_FROM_FILE_OFFSET(i, off);
-            return(entry);
-         }
-     }
-   
-   KeReleaseSpinLock(&PagingFileListLock, oldIrql); 
+   {
+      if (PagingFileList[i] != NULL &&
+            PagingFileList[i]->FreePages >= 1)
+      {
+         off = MiAllocPageFromPagingFile(PagingFileList[i]);
+         if (off == 0xFFFFFFFF)
+         {
+            KEBUGCHECK(0);
+            KeReleaseSpinLock(&PagingFileListLock, oldIrql);
+            return(STATUS_UNSUCCESSFUL);
+         }
+         MiUsedSwapPages++;
+         MiFreeSwapPages--;
+         KeReleaseSpinLock(&PagingFileListLock, oldIrql);
+
+         entry = ENTRY_FROM_FILE_OFFSET(i, off);
+         return(entry);
+      }
+   }
+
+   KeReleaseSpinLock(&PagingFileListLock, oldIrql);
    KEBUGCHECK(0);
    return(0);
 }
 
-LARGE_INTEGER STATIC
-MmGetOffsetPageFile(PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers, LARGE_INTEGER Offset)
+STATIC PRETRIEVEL_DESCRIPTOR_LIST FASTCALL
+MmAllocRetrievelDescriptorList(ULONG Pairs)
 {
-  ULONG j;
-  for (j = 0; j < RetrievalPointers->NumberOfPairs; j++)
-    {
-      if (Offset.QuadPart < RetrievalPointers->Pair[j].Vcn)
-       {
-         if (j == 0)
-           {
-             Offset.QuadPart += RetrievalPointers->Pair[0].Lcn - RetrievalPointers->StartVcn;
-           }
-         else
-           {
-             Offset.QuadPart += RetrievalPointers->Pair[j].Lcn  - RetrievalPointers->Pair[j-1].Vcn;
-           }
-         break;
-       }
-    }
-  if (j >= RetrievalPointers->NumberOfPairs)
-    {
-      CHECKPOINT1;
-      KEBUGCHECK(0);
-    }
-  return(Offset);
+   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 STDCALL 
+NTSTATUS STDCALL
 MmDumpToPagingFile(ULONG BugCode,
-                  ULONG BugCodeParameter1,
-                  ULONG BugCodeParameter2,
-                  ULONG BugCodeParameter3,
-                  ULONG BugCodeParameter4,
-                  PKTRAP_FRAME TrapFrame)
+                   ULONG BugCodeParameter1,
+                   ULONG BugCodeParameter2,
+                   ULONG BugCodeParameter3,
+                   ULONG BugCodeParameter4,
+                   PKTRAP_FRAME TrapFrame)
 {
-  PMM_CORE_DUMP_HEADER Headers;
-  NTSTATUS Status;
-  UCHAR MdlBase[sizeof(MDL) + sizeof(PVOID)];
-  PMDL Mdl = (PMDL)MdlBase;
-  PETHREAD Thread = PsGetCurrentThread();
-  ULONG StackSize;
-  PULONG MdlMap;
-  LONGLONG NextOffset = 0;
-  ULONG i;
-  PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers;
-  LARGE_INTEGER DiskOffset;
-
-  if (MmCoreDumpPageFile == 0xFFFFFFFF)
-    {
+   PMM_CORE_DUMP_HEADER Headers;
+   NTSTATUS Status;
+   UCHAR MdlBase[sizeof(MDL) + sizeof(ULONG)];
+   PMDL Mdl = (PMDL)MdlBase;
+   PETHREAD Thread = PsGetCurrentThread();
+   ULONG_PTR StackSize;
+   PULONG MdlMap;
+   LONGLONG NextOffset = 0;
+   ULONG i;
+   PRETRIEVAL_POINTERS_BUFFER RetrievalPointers;
+   LARGE_INTEGER DiskOffset;
+
+   if (MmCoreDumpPageFile == 0xFFFFFFFF)
+   {
       return(STATUS_UNSUCCESSFUL);
-    }
+   }
 
-  DbgPrint("\nMM: Dumping core: ");
+   DbgPrint("\nMM: Dumping core: ");
 
-  /* Prepare the dump headers. */
-  Headers = (PMM_CORE_DUMP_HEADER)MmCoreDumpPageFrame;
-  Headers->Magic = MM_CORE_DUMP_HEADER_MAGIC;
-  Headers->Version = MM_CORE_DUMP_HEADER_VERSION;
-  Headers->Type = MmCoreDumpType;
-  if (TrapFrame != NULL)
-    {
-      if (!(TrapFrame->Eflags & (1 << 17)))
-       {
-         memcpy(&Headers->TrapFrame, TrapFrame, 
-                sizeof(KTRAP_FRAME) - (4 * sizeof(DWORD)));
-       }
+   /* Prepare the dump headers. */
+   Headers = (PMM_CORE_DUMP_HEADER)MmCoreDumpPageFrame;
+   Headers->Magic = MM_CORE_DUMP_HEADER_MAGIC;
+   Headers->Version = MM_CORE_DUMP_HEADER_VERSION;
+   Headers->Type = MmCoreDumpType;
+   if (TrapFrame != NULL)
+   {
+      if (!(TrapFrame->EFlags & (1 << 17)))
+      {
+         memcpy(&Headers->TrapFrame, TrapFrame,
+                sizeof(KTRAP_FRAME) - (4 * sizeof(DWORD)));
+      }
       else
-       {
-         memcpy(&Headers->TrapFrame, TrapFrame, sizeof(KTRAP_FRAME));
-       }
-    }
-  Headers->BugCheckCode = BugCode;
-  Headers->BugCheckParameters[0] = BugCodeParameter1;
-  Headers->BugCheckParameters[1] = BugCodeParameter2;
-  Headers->BugCheckParameters[2] = BugCodeParameter3;
-  Headers->BugCheckParameters[3] = BugCodeParameter4;
-  Headers->FaultingStackBase = (PVOID)Thread->Tcb.StackLimit;
-  Headers->FaultingStackSize = StackSize =
-    (ULONG)(Thread->Tcb.StackBase - Thread->Tcb.StackLimit);
-  Headers->PhysicalMemorySize = MmStats.NrTotalPages * PAGE_SIZE;
-
-  /* Initialize the dump device. */
-  MmCoreDumpFunctions->DumpInit();
-  if (!NT_SUCCESS(Status))
-    {
+      {
+         memcpy(&Headers->TrapFrame, TrapFrame, sizeof(KTRAP_FRAME));
+      }
+   }
+   Headers->BugCheckCode = BugCode;
+   Headers->BugCheckParameters[0] = BugCodeParameter1;
+   Headers->BugCheckParameters[1] = BugCodeParameter2;
+   Headers->BugCheckParameters[2] = BugCodeParameter3;
+   Headers->BugCheckParameters[3] = BugCodeParameter4;
+   Headers->FaultingStackBase = (PVOID)Thread->Tcb.StackLimit;
+   Headers->FaultingStackSize =
+   StackSize = (ULONG_PTR)Thread->Tcb.StackBase - (ULONG_PTR)Thread->Tcb.StackLimit;
+   Headers->PhysicalMemorySize = MmStats.NrTotalPages * PAGE_SIZE;
+
+   /* Initialize the dump device. */
+   Status = MmCoreDumpFunctions->DumpInit();
+   if (!NT_SUCCESS(Status))
+   {
       DPRINT1("MM: Failed to initialize core dump device.\n");
       return(Status);
-    }
+   }
 
-  /* Initialize the MDL. */
-  Mdl->Next = NULL;
-  Mdl->Size = sizeof(MDL) + sizeof(PVOID);
-  Mdl->MdlFlags = MDL_SOURCE_IS_NONPAGED_POOL;
-  Mdl->Process = NULL;
-  Mdl->MappedSystemVa = MmCoreDumpPageFrame;
-  Mdl->StartVa = NULL;
-  Mdl->ByteCount = PAGE_SIZE;
-  Mdl->ByteOffset = 0;
-  MdlMap = (PULONG)(Mdl + 1);
-
-  
-  /* Initialize the retrieval offsets. */
-  RetrievalPointers = PagingFileList[MmCoreDumpPageFile]->RetrievalPointers;
-
-  /* Dump the header. */
-  MdlMap[0] = MmGetPhysicalAddress(MmCoreDumpPageFrame).u.LowPart;
-  DiskOffset = MmGetOffsetPageFile(RetrievalPointers, (LARGE_INTEGER)0LL);
-  DiskOffset.QuadPart += MmCoreDumpLcnMapping.LcnDiskOffset.QuadPart;
-  Status = MmCoreDumpFunctions->DumpWrite(DiskOffset, Mdl);
-  if (!NT_SUCCESS(Status))
-    {
+   /* Initialize the MDL. */
+   MmInitializeMdl(Mdl, MmCoreDumpPageFrame, PAGE_SIZE);
+   Mdl->MdlFlags = MDL_PAGES_LOCKED|MDL_IO_PAGE_READ|MDL_SOURCE_IS_NONPAGED_POOL;
+   MdlMap = (PULONG)(Mdl + 1);
+
+
+   /* Initialize the retrieval offsets. */
+   RetrievalPointers = PagingFileList[MmCoreDumpPageFile]->RetrievalPointers;
+
+   /* Dump the header. */
+   MdlMap[0] = MmGetPhysicalAddress(MmCoreDumpPageFrame).QuadPart >> PAGE_SHIFT;
+#if defined(__GNUC__)
+
+   DiskOffset = MmGetOffsetPageFile(RetrievalPointers, (LARGE_INTEGER)0LL);
+#else
+
+   {
+      const LARGE_INTEGER dummy =
+         {
+            0
+         };
+      DiskOffset = MmGetOffsetPageFile(RetrievalPointers, dummy);
+   }
+#endif
+   DiskOffset.QuadPart += MmCoreDumpLcnMapping.LcnDiskOffset.QuadPart;
+   Status = MmCoreDumpFunctions->DumpWrite(DiskOffset, Mdl);
+   if (!NT_SUCCESS(Status))
+   {
       DPRINT1("MM: Failed to write core dump header\n.");
       return(Status);
-    }
-  NextOffset += PAGE_SIZE;;
-  DbgPrint("00");
+   }
+   NextOffset += PAGE_SIZE;
+   ;
+   DbgPrint("00");
 
-  
-  /* Write out the contents of physical memory. */
-  if (MmCoreDumpType == MM_CORE_DUMP_TYPE_FULL)
-    {
+
+   /* Write out the contents of physical memory. */
+   if (MmCoreDumpType == MM_CORE_DUMP_TYPE_FULL)
+   {
       for (i = 0; i < MmStats.NrTotalPages; i++)
-       {
-         LARGE_INTEGER PhysicalAddress;
-         PhysicalAddress.QuadPart = i * PAGE_SIZE;
-         MdlMap[0] = i * PAGE_SIZE;
-         MmCreateVirtualMappingDump(MmCoreDumpPageFrame,
-                                    PAGE_READWRITE,
-                                    PhysicalAddress);
-         DiskOffset = MmGetOffsetPageFile(RetrievalPointers, 
-                                          (LARGE_INTEGER)NextOffset);
-         DiskOffset.QuadPart += MmCoreDumpLcnMapping.LcnDiskOffset.QuadPart;
-         Status = MmCoreDumpFunctions->DumpWrite(DiskOffset, Mdl);
-         if (!NT_SUCCESS(Status))
-           {
-             DPRINT1("MM: Failed to write page to core dump.\n");
-             return(Status);
-           }
-         if ((i % ((1024*1024) / PAGE_SIZE)) == 0)
-           {
-             DbgPrint("\b\b%.2d", i / ((1024*1024)/PAGE_SIZE));
-           }
-         NextOffset += PAGE_SIZE;
-       }
-    }
+      {
+         MdlMap[0] = i;
+         MmCreateVirtualMappingForKernel(MmCoreDumpPageFrame,
+                                        PAGE_READWRITE,
+                                         MdlMap,
+                                        1);
+#if defined(__GNUC__)
+
+         DiskOffset = MmGetOffsetPageFile(RetrievalPointers,
+                                          (LARGE_INTEGER)NextOffset);
+#else
 
-  DbgPrint("\n");
-  MmCoreDumpFunctions->DumpFinish();
-  return(STATUS_SUCCESS);
+         {
+            LARGE_INTEGER dummy;
+            dummy.QuadPart = NextOffset;
+            DiskOffset = MmGetOffsetPageFile(RetrievalPointers, dummy);
+         }
+#endif
+         DiskOffset.QuadPart += MmCoreDumpLcnMapping.LcnDiskOffset.QuadPart;
+         Status = MmCoreDumpFunctions->DumpWrite(DiskOffset, Mdl);
+        MmRawDeleteVirtualMapping(MmCoreDumpPageFrame);
+         if (!NT_SUCCESS(Status))
+         {
+            DPRINT1("MM: Failed to write page to core dump.\n");
+            return(Status);
+         }
+         if ((i % ((1024*1024) / PAGE_SIZE)) == 0)
+         {
+            DbgPrint("\b\b%.2d", i / ((1024*1024)/PAGE_SIZE));
+         }
+         NextOffset += PAGE_SIZE;
+      }
+   }
+
+   DbgPrint("\n");
+   MmCoreDumpFunctions->DumpFinish();
+   return(STATUS_SUCCESS);
 }
 
 NTSTATUS STDCALL
 MmInitializeCrashDump(HANDLE PageFileHandle, ULONG PageFileNum)
 {
-  PFILE_OBJECT PageFile;
-  PDEVICE_OBJECT PageFileDevice;
-  NTSTATUS Status;
-  PIRP Irp;
-  KEVENT Event;
-  IO_STATUS_BLOCK Iosb;
-  UNICODE_STRING DiskDumpName;
-  ANSI_STRING ProcName;
-  PIO_STACK_LOCATION StackPtr;
-  PMODULE_OBJECT ModuleObject;  
-
-  Status = ZwFsControlFile(PageFileHandle,
-                          0,
-                          NULL,
-                          NULL,
-                          &Iosb,
-                          FSCTL_ROS_QUERY_LCN_MAPPING,
-                          NULL,
-                          0,
-                          &MmCoreDumpLcnMapping,
-                          sizeof(ROS_QUERY_LCN_MAPPING));
-  if (!NT_SUCCESS(Status) ||
-      Iosb.Information != sizeof(ROS_QUERY_LCN_MAPPING))
-    {
+   PFILE_OBJECT PageFile;
+   PDEVICE_OBJECT PageFileDevice;
+   NTSTATUS Status;
+   PIRP Irp;
+   KEVENT Event;
+   IO_STATUS_BLOCK Iosb;
+   UNICODE_STRING DiskDumpName = RTL_CONSTANT_STRING(L"DiskDump");
+   ANSI_STRING ProcName;
+   PIO_STACK_LOCATION StackPtr;
+   PLDR_DATA_TABLE_ENTRY ModuleObject;
+
+   Status = ZwFsControlFile(PageFileHandle,
+                            0,
+                            NULL,
+                            NULL,
+                            &Iosb,
+                            FSCTL_ROS_QUERY_LCN_MAPPING,
+                            NULL,
+                            0,
+                            &MmCoreDumpLcnMapping,
+                            sizeof(ROS_QUERY_LCN_MAPPING));
+   if (!NT_SUCCESS(Status) ||
+         Iosb.Information != sizeof(ROS_QUERY_LCN_MAPPING))
+   {
       return(Status);
-    }
+   }
 
-  /* Get the underlying storage device. */
-  Status = 
-    ObReferenceObjectByHandle(PageFileHandle,
-                             FILE_ALL_ACCESS,
-                             NULL,
-                             KernelMode,
-                             (PVOID*)&PageFile,
-                             NULL);
-  if (!NT_SUCCESS(Status))
-    {
+   /* Get the underlying storage device. */
+   Status =
+      ObReferenceObjectByHandle(PageFileHandle,
+                                FILE_ALL_ACCESS,
+                                NULL,
+                                KernelMode,
+                                (PVOID*)&PageFile,
+                                NULL);
+   if (!NT_SUCCESS(Status))
+   {
       return(Status);
-    }
+   }
 
-  PageFileDevice = PageFile->Vpb->RealDevice;
-
-  /* Get the dump pointers. */
-  KeInitializeEvent(&Event, NotificationEvent, FALSE);
-  Irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_DUMP_POINTERS,
-                                     PageFileDevice,
-                                     NULL,
-                                     0,
-                                     &MmCoreDumpPointers,
-                                     sizeof(MmCoreDumpPointers),
-                                     FALSE,
-                                     &Event,
-                                     &Iosb);
-  StackPtr = IoGetNextIrpStackLocation(Irp);
-  StackPtr->FileObject = PageFile;
-  StackPtr->DeviceObject = PageFileDevice;
-  StackPtr->Parameters.DeviceIoControl.InputBufferLength = 0;
-  StackPtr->Parameters.DeviceIoControl.OutputBufferLength = sizeof(MmCoreDumpPointers);
-  
-  Status = IoCallDriver(PageFileDevice,Irp);
-  if (Status == STATUS_PENDING)
-    {
+   PageFileDevice = PageFile->Vpb->RealDevice;
+
+   /* Get the dump pointers. */
+   KeInitializeEvent(&Event, NotificationEvent, FALSE);
+   Irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_DUMP_POINTERS,
+                                       PageFileDevice,
+                                       NULL,
+                                       0,
+                                       &MmCoreDumpPointers,
+                                       sizeof(MmCoreDumpPointers),
+                                       FALSE,
+                                       &Event,
+                                       &Iosb);
+   if(Irp == NULL)
+   {
+      ObDereferenceObject(PageFile);
+      return(STATUS_NO_MEMORY);// tMk - is this correct return code ???
+   }
+
+   StackPtr = IoGetNextIrpStackLocation(Irp);
+   StackPtr->FileObject = PageFile;
+   StackPtr->DeviceObject = PageFileDevice;
+   StackPtr->Parameters.DeviceIoControl.InputBufferLength = 0;
+   StackPtr->Parameters.DeviceIoControl.OutputBufferLength = sizeof(MmCoreDumpPointers);
+
+   Status = IoCallDriver(PageFileDevice,Irp);
+   if (Status == STATUS_PENDING)
+   {
       Status = KeWaitForSingleObject(&Event,
-                                    Executive,
-                                    KernelMode,
-                                    FALSE,
-                                    NULL);
-    }
-  if (Status != STATUS_SUCCESS || 
-      Iosb.Information != sizeof(MmCoreDumpPointers))
-    {
+                                     Executive,
+                                     KernelMode,
+                                     FALSE,
+                                     NULL);
+   }
+   if (Status != STATUS_SUCCESS ||
+         Iosb.Information != sizeof(MmCoreDumpPointers))
+   {
       ObDereferenceObject(PageFile);
       return(Status);
-    }
+   }
 
-  /* Load the diskdump driver. */
-  RtlInitUnicodeStringFromLiteral(&DiskDumpName, L"DiskDump");
-  ModuleObject = LdrGetModuleObject(&DiskDumpName);
-  if (ModuleObject == NULL)
-    {
+   /* Load the diskdump driver. */
+   ModuleObject = LdrGetModuleObject(&DiskDumpName);
+   if (ModuleObject == NULL)
+   {
       return(STATUS_OBJECT_NAME_NOT_FOUND);
-    }
-  RtlInitAnsiString(&ProcName, "DiskDumpFunctions");
-  Status = LdrGetProcedureAddress(ModuleObject->Base,
-                                 &ProcName,
-                                 0,
-                                 (PVOID*)&MmCoreDumpFunctions);
-  if (!NT_SUCCESS(Status))
-    {
+   }
+   RtlInitAnsiString(&ProcName, "DiskDumpFunctions");
+   Status = LdrGetProcedureAddress(ModuleObject->DllBase,
+                                   &ProcName,
+                                   0,
+                                   (PVOID*)&MmCoreDumpFunctions);
+   if (!NT_SUCCESS(Status))
+   {
       ObDereferenceObject(PageFile);
       return(Status);
-    }
+   }
 
-  /* Prepare for disk dumping. */
-  Status = MmCoreDumpFunctions->DumpPrepare(PageFileDevice,
-                                           &MmCoreDumpPointers);
-  if (!NT_SUCCESS(Status))
-    {
+   /* Prepare for disk dumping. */
+   Status = MmCoreDumpFunctions->DumpPrepare(PageFileDevice,
+            &MmCoreDumpPointers);
+   if (!NT_SUCCESS(Status))
+   {
       ObDereferenceObject(PageFile);
       return(Status);
-    }
+   }
 
-  MmCoreDumpPageFile = PageFileNum;
-  ObDereferenceObject(PageFile);
-  return(STATUS_SUCCESS);
+   MmCoreDumpPageFile = PageFileNum;
+   ObDereferenceObject(PageFile);
+   return(STATUS_SUCCESS);
 }
 
 NTSTATUS STDCALL
 NtCreatePagingFile(IN PUNICODE_STRING FileName,
-                  IN PLARGE_INTEGER InitialSize,
-                  IN PLARGE_INTEGER MaximumSize,
-                  IN ULONG Reserved)
+                   IN PLARGE_INTEGER InitialSize,
+                   IN PLARGE_INTEGER MaximumSize,
+                   IN ULONG Reserved)
 {
    NTSTATUS Status;
    OBJECT_ATTRIBUTES ObjectAttributes;
@@ -709,234 +784,340 @@ NtCreatePagingFile(IN PUNICODE_STRING FileName,
    PPAGINGFILE PagingFile;
    KIRQL oldIrql;
    ULONG AllocMapSize;
-   ULONG Size;
    FILE_FS_SIZE_INFORMATION FsSizeInformation;
-   PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers;
+   PRETRIEVEL_DESCRIPTOR_LIST RetDescList;
+   PRETRIEVEL_DESCRIPTOR_LIST CurrentRetDescList;
    ULONG i;
    ULONG BytesPerAllocationUnit;
    LARGE_INTEGER Vcn;
    ULONG ExtentCount;
-   ULONG MaxVcn;
+   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);
-   
+          FileName, InitialSize->QuadPart);
+
    if (MiPagingFileCount >= MAX_PAGING_FILES)
-     {
-       return(STATUS_TOO_MANY_PAGING_FILES);
-     }
-   
+   {
+      return(STATUS_TOO_MANY_PAGING_FILES);
+   }
+
+   PreviousMode = ExGetPreviousMode();
+
+   if (PreviousMode != KernelMode)
+   {
+      _SEH_TRY
+      {
+         SafeInitialSize = ProbeForReadLargeInteger(InitialSize);
+         SafeMaximumSize = ProbeForReadLargeInteger(MaximumSize);
+      }
+      _SEH_HANDLE
+      {
+         Status = _SEH_GetExceptionCode();
+      }
+      _SEH_END;
+
+      if (!NT_SUCCESS(Status))
+      {
+         return Status;
+      }
+   }
+   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,
-                             FileName,
-                             0,
-                             NULL,
-                             NULL);
-   
+                              &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);
+                         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 = NtQueryVolumeInformationFile(FileHandle,
+   {
+      return(Status);
+   }
+
+   Status = ZwQueryVolumeInformationFile(FileHandle,
                                          &IoStatus,
-                                        &FsSizeInformation,
-                                        sizeof(FILE_FS_SIZE_INFORMATION),
-                                        FileFsSizeInformation);
+                                         &FsSizeInformation,
+                                         sizeof(FILE_FS_SIZE_INFORMATION),
+                                         FileFsSizeInformation);
    if (!NT_SUCCESS(Status))
-     {
-       NtClose(FileHandle);
-       return Status;
-     }
-   
-   BytesPerAllocationUnit = FsSizeInformation.SectorsPerAllocationUnit * FsSizeInformation.BytesPerSector;
+   {
+      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)
-     {
-       NtClose(FileHandle);
-       return STATUS_UNSUCCESSFUL;
-     }
-
-   Status = NtSetInformationFile(FileHandle,
-                                &IoStatus,
-                                InitialSize,
-                                sizeof(LARGE_INTEGER),
-                                FileAllocationInformation);
+   {
+      DPRINT1("BytesPerAllocationUnit %d 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))
-     {
-       NtClose(FileHandle);
-       return(Status);
-     }
+   {
+      ZwClose(FileHandle);
+      return(Status);
+   }
 
    Status = ObReferenceObjectByHandle(FileHandle,
-                                     FILE_ALL_ACCESS,
-                                     IoFileObjectType,
-                                     UserMode,
-                                     (PVOID*)&FileObject,
-                                     NULL);
+                                      FILE_ALL_ACCESS,
+                                      IoFileObjectType,
+                                      PreviousMode,
+                                      (PVOID*)&FileObject,
+                                      NULL);
    if (!NT_SUCCESS(Status))
-     {
-       NtClose(FileHandle);
-       return(Status);
-     }
+   {
+      ZwClose(FileHandle);
+      return(Status);
+   }
 
-   RetrievalPointers = ExAllocatePool(NonPagedPool, sizeof(GET_RETRIEVAL_DESCRIPTOR) + sizeof(MAPPING_PAIR));
+   CurrentRetDescList = RetDescList = MmAllocRetrievelDescriptorList(PAIRS_PER_RUN);
 
-   if (RetrievalPointers == NULL)
-     {
-       ObDereferenceObject(FileObject);
-       NtClose(FileHandle);
-       return(STATUS_NO_MEMORY);
-     }
+   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 = (InitialSize->QuadPart + BytesPerAllocationUnit - 1) / BytesPerAllocationUnit;
+   MaxVcn.QuadPart = (SafeInitialSize.QuadPart + BytesPerAllocationUnit - 1) / BytesPerAllocationUnit;
    while(1)
-     {
-       Status = NtFsControlFile(FileHandle,
-                               0,
-                               NULL,
-                               NULL,
-                               &IoStatus,
-                               FSCTL_GET_RETRIEVAL_POINTERS,
-                               &Vcn,
-                               sizeof(LARGE_INTEGER),
-                               RetrievalPointers,
-                               sizeof(GET_RETRIEVAL_DESCRIPTOR) + sizeof(MAPPING_PAIR));
-       if (!NT_SUCCESS(Status))
-         {
-           ExFreePool(RetrievalPointers);
-           ObDereferenceObject(FileObject);
-           NtClose(FileHandle);
-           return(Status);
-         }
-       ExtentCount += RetrievalPointers->NumberOfPairs;
-       if ((ULONG)RetrievalPointers->Pair[0].Vcn < MaxVcn)
+   {
+      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))
+      {
+         while (RetDescList)
          {
-           Vcn.QuadPart = RetrievalPointers->Pair[0].Vcn;
+            CurrentRetDescList = RetDescList;
+            RetDescList = RetDescList->Next;
+            ExFreePool(CurrentRetDescList);
          }
-       else
+         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)
          {
-           break;
+            while (RetDescList)
+            {
+               CurrentRetDescList = RetDescList;
+               RetDescList = RetDescList->Next;
+               ExFreePool(CurrentRetDescList);
+            }
+            ObDereferenceObject(FileObject);
+            ZwClose(FileHandle);
+            return(STATUS_NO_MEMORY);
          }
-     }
-   ExFreePool(RetrievalPointers);
+         Vcn = CurrentRetDescList->RetrievalPointers.Extents[CurrentRetDescList->RetrievalPointers.ExtentCount-1].NextVcn;
+         CurrentRetDescList = CurrentRetDescList->Next;
+      }
+      else
+      {
+         break;
+      }
+   }
 
    PagingFile = ExAllocatePool(NonPagedPool, sizeof(*PagingFile));
    if (PagingFile == NULL)
-     {
-       ObDereferenceObject(FileObject);
-       NtClose(FileHandle);
-       return(STATUS_NO_MEMORY);
-     }
-   
+   {
+      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 = MaximumSize->QuadPart;
-   PagingFile->CurrentSize.QuadPart = InitialSize->QuadPart;
-   PagingFile->FreePages = InitialSize->QuadPart / PAGE_SIZE;
+   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->AllocMap = ExAllocatePool(NonPagedPool,
+                                         AllocMapSize * sizeof(ULONG));
    PagingFile->AllocMapSize = AllocMapSize;
-   
+
    if (PagingFile->AllocMap == NULL)
-     {
-       ExFreePool(PagingFile);
-       ObDereferenceObject(FileObject);
-       ZwClose(FileHandle);
-       return(STATUS_NO_MEMORY);
-     }
-
-   Size = sizeof(GET_RETRIEVAL_DESCRIPTOR) + ExtentCount * sizeof(MAPPING_PAIR);
+   {
+      while (RetDescList)
+      {
+         CurrentRetDescList = RetDescList;
+         RetDescList = RetDescList->Next;
+         ExFreePool(CurrentRetDescList);
+      }
+      ExFreePool(PagingFile);
+      ObDereferenceObject(FileObject);
+      ZwClose(FileHandle);
+      return(STATUS_NO_MEMORY);
+   }
+   DPRINT("ExtentCount: %d\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);
-      NtClose(FileHandle);
+      ZwClose(FileHandle);
       return(STATUS_NO_MEMORY);
    }
-   
-   Vcn.QuadPart = 0LL;
-   Status = NtFsControlFile(FileHandle,
-                           0,
-                           NULL,
-                           NULL,
-                           &IoStatus,
-                           FSCTL_GET_RETRIEVAL_POINTERS,
-                           &Vcn,
-                           sizeof(LARGE_INTEGER),
-                           PagingFile->RetrievalPointers,
-                           Size);
-   if (!NT_SUCCESS(Status))
-     {
-       ExFreePool(PagingFile->RetrievalPointers);
-       ExFreePool(PagingFile->AllocMap);
-       ExFreePool(PagingFile);
-       ObDereferenceObject(FileObject);
-       NtClose(FileHandle);
-       return(STATUS_NO_MEMORY);
-     }
-
-   if (PagingFile->RetrievalPointers->NumberOfPairs != ExtentCount || 
-       (ULONG)PagingFile->RetrievalPointers->Pair[ExtentCount - 1].Vcn != MaxVcn)
-     {
-       ExFreePool(PagingFile->RetrievalPointers);
-       ExFreePool(PagingFile->AllocMap);
-       ExFreePool(PagingFile);
-       ObDereferenceObject(FileObject);
-       NtClose(FileHandle);
-       return(STATUS_UNSUCCESSFUL);
-     }
-
-   /* 
+
+   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->StartVcn *= BytesPerAllocationUnit;
+   PagingFile->RetrievalPointers->StartingVcn.QuadPart *= BytesPerAllocationUnit;
    for (i = 0; i < ExtentCount; i++)
-     {
-       PagingFile->RetrievalPointers->Pair[i].Lcn *= BytesPerAllocationUnit;
-       PagingFile->RetrievalPointers->Pair[i].Vcn *= BytesPerAllocationUnit;
-     }
+   {
+      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;
-         }
-     }
+   {
+      if (PagingFileList[i] == NULL)
+      {
+         PagingFileList[i] = PagingFile;
+         break;
+      }
+   }
    MiFreeSwapPages = MiFreeSwapPages + PagingFile->FreePages;
    MiPagingFileCount++;
    KeReleaseSpinLock(&PagingFileListLock, oldIrql);
-   
+
    /* Check whether this pagefile can be a crash dump target. */
    if (MmCoreDumpType != MM_CORE_DUMP_TYPE_NONE &&
-       PagingFile->CurrentSize.QuadPart >= MmCoreDumpSize &&
-       MmCoreDumpPageFile == 0xFFFFFFFF)
-     {
-       MmInitializeCrashDump(FileHandle, i);       
-     }
-   NtClose(FileHandle);
+         PagingFile->CurrentSize.QuadPart >= MmCoreDumpSize &&
+         MmCoreDumpPageFile == 0xFFFFFFFF)
+   {
+      MmInitializeCrashDump(FileHandle, i);
+   }
+   ZwClose(FileHandle);
 
    MmSwapSpaceMessage = FALSE;