Fixed the mapping for low alignment images.
[reactos.git] / reactos / ntoskrnl / mm / section.c
index 070147e..c541a41 100644 (file)
@@ -1,50 +1,57 @@
-/*
- *  ReactOS kernel
- *  Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
+/* $Id$
  *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
+ * Copyright (C) 1998-2005 ReactOS Team (and the authors from the programmers section)
  *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-/* $Id: section.c,v 1.148 2004/05/01 00:25:41 tamlin Exp $
  *
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/mm/section.c
  * PURPOSE:         Implements section objects
- * PROGRAMMER:      David Welch (welch@mcmail.com)
- * UPDATE HISTORY:
- *                  Created 22/05/98
+ *
+ * PROGRAMMERS:     Rex Jolliff
+ *                  David Welch
+ *                  Eric Kohl
+ *                  Emanuele Aliberti
+ *                  Eugene Ingerman
+ *                  Hartmut Birr
+ *                  Casper Hornstrup
+ *                  KJK::Hyperion
+ *                  Guido de Jong
+ *                  Ge van Geldorp
+ *                  Royce Mitchell III
+ *                  Filip Navara
+ *                  Aleksey Bragin 
+ *                  Jason Filby
+ *                  Thomas Weidenmueller
+ *                  Gunnar Andre' Dalsnes
+ *                  Mike Nordell
+ *                  Alex Ionescu
+ *                  Gregor Anich
+ *                  Steven Edwards
+ *                  Herve Poussineau
  */
 
 /* INCLUDES *****************************************************************/
 
-#include <limits.h>
-#define NTOS_MODE_KERNEL
-#include <ntos.h>
-#include <internal/mm.h>
-#include <internal/io.h>
-#include <internal/ob.h>
-#include <internal/ps.h>
-#include <internal/pool.h>
-#include <internal/cc.h>
-#include <ddk/ntifs.h>
-#include <ntos/minmax.h>
-#include <rosrtl/string.h>
-#include <reactos/bugcodes.h>
-
+#include <ntoskrnl.h>
 #define NDEBUG
 #include <internal/debug.h>
 
+#include <reactos/exeformat.h>
+
 /* TYPES *********************************************************************/
 
 typedef struct
@@ -67,10 +74,8 @@ static GENERIC_MAPPING MmpSectionMapping = {
          STANDARD_RIGHTS_EXECUTE | SECTION_MAP_EXECUTE,
          SECTION_ALL_ACCESS};
 
-#define TAG_MM_SECTION_SEGMENT   TAG('M', 'M', 'S', 'S')
-#define TAG_SECTION_PAGE_TABLE   TAG('M', 'S', 'P', 'T')
-
 #define PAGE_FROM_SSE(E)         ((E) & 0xFFFFF000)
+#define PFN_FROM_SSE(E)          ((E) >> PAGE_SHIFT)
 #define SHARE_COUNT_FROM_SSE(E)  (((E) & 0x00000FFE) >> 1)
 #define IS_SWAP_FROM_SSE(E)      ((E) & 0x00000001)
 #define MAX_SHARE_COUNT          0x7FF
@@ -78,6 +83,12 @@ static GENERIC_MAPPING MmpSectionMapping = {
 #define SWAPENTRY_FROM_SSE(E)    ((E) >> 1)
 #define MAKE_SWAP_SSE(S)         (((S) << 1) | 0x1)
 
+static const INFORMATION_CLASS_INFO ExSectionInfoClass[] =
+{
+  ICI_SQ_SAME( sizeof(SECTION_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* SectionBasicInformation */
+  ICI_SQ_SAME( sizeof(SECTION_IMAGE_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* SectionImageInformation */
+};
+
 /* FUNCTIONS *****************************************************************/
 
 /* Note: Mmsp prefix denotes "Memory Manager Section Private". */
@@ -146,6 +157,7 @@ MmFreePageTablesSectionSegment(PMM_SECTION_SEGMENT Segment)
 }
 
 VOID
+NTAPI
 MmFreeSectionSegments(PFILE_OBJECT FileObject)
 {
    if (FileObject->SectionObjectPointer->ImageSectionObject != NULL)
@@ -168,6 +180,7 @@ MmFreeSectionSegments(PFILE_OBJECT FileObject)
          }
          MmFreePageTablesSectionSegment(&SectionSegments[i]);
       }
+      ExFreePool(ImageSectionObject->Segments);
       ExFreePool(ImageSectionObject);
       FileObject->SectionObjectPointer->ImageSectionObject = NULL;
    }
@@ -190,18 +203,21 @@ MmFreeSectionSegments(PFILE_OBJECT FileObject)
 }
 
 VOID
+NTAPI
 MmLockSectionSegment(PMM_SECTION_SEGMENT Segment)
 {
    ExAcquireFastMutex(&Segment->Lock);
 }
 
 VOID
+NTAPI
 MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment)
 {
    ExReleaseFastMutex(&Segment->Lock);
 }
 
 VOID
+NTAPI
 MmSetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
                              ULONG Offset,
                              ULONG Entry)
@@ -222,7 +238,7 @@ MmSetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
       {
          Table =
             Segment->PageDirectory.PageTables[DirectoryOffset] =
-               ExAllocatePoolWithTag(NonPagedPool, sizeof(SECTION_PAGE_TABLE),
+               ExAllocatePoolWithTag(PagedPool, sizeof(SECTION_PAGE_TABLE),
                                      TAG_SECTION_PAGE_TABLE);
          if (Table == NULL)
          {
@@ -238,6 +254,7 @@ MmSetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
 
 
 ULONG
+NTAPI
 MmGetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
                              ULONG Offset)
 {
@@ -268,6 +285,7 @@ MmGetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
 }
 
 VOID
+NTAPI
 MmSharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
                                ULONG Offset)
 {
@@ -293,6 +311,7 @@ MmSharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
 }
 
 BOOLEAN
+NTAPI
 MmUnsharePageEntrySectionSegment(PSECTION_OBJECT Section,
                                  PMM_SECTION_SEGMENT Segment,
                                  ULONG Offset,
@@ -327,7 +346,7 @@ MmUnsharePageEntrySectionSegment(PSECTION_OBJECT Section,
       PFILE_OBJECT FileObject;
       PBCB Bcb;
       SWAPENTRY SavedSwapEntry;
-      PHYSICAL_ADDRESS Page;
+      PFN_TYPE Page;
       BOOLEAN IsImageSection;
       ULONG FileOffset;
 
@@ -335,10 +354,10 @@ MmUnsharePageEntrySectionSegment(PSECTION_OBJECT Section,
 
       IsImageSection = Section->AllocationAttributes & SEC_IMAGE ? TRUE : FALSE;
 
-      Page.QuadPart = (LONGLONG)PAGE_FROM_SSE(Entry);
+      Page = PFN_FROM_SSE(Entry);
       FileObject = Section->FileObject;
       if (FileObject != NULL &&
-            !(Segment->Characteristics & IMAGE_SECTION_CHAR_SHARED))
+            !(Segment->Characteristics & IMAGE_SCN_MEM_SHARED))
       {
 
          if ((FileOffset % PAGE_SIZE) == 0 &&
@@ -361,7 +380,7 @@ MmUnsharePageEntrySectionSegment(PSECTION_OBJECT Section,
       {
          if (!PageOut &&
                ((Segment->Flags & MM_PAGEFILE_SEGMENT) ||
-                (Segment->Characteristics & IMAGE_SECTION_CHAR_SHARED)))
+                (Segment->Characteristics & IMAGE_SCN_MEM_SHARED)))
          {
             /*
              * FIXME:
@@ -384,7 +403,7 @@ MmUnsharePageEntrySectionSegment(PSECTION_OBJECT Section,
       else
       {
          if ((Segment->Flags & MM_PAGEFILE_SEGMENT) ||
-               (Segment->Characteristics & IMAGE_SECTION_CHAR_SHARED))
+               (Segment->Characteristics & IMAGE_SCN_MEM_SHARED))
          {
             if (!PageOut)
             {
@@ -392,14 +411,11 @@ MmUnsharePageEntrySectionSegment(PSECTION_OBJECT Section,
                {
                   /*
                    * FIXME:
-                   *   We hold all locks. Nobody can do something with the current 
+                   *   We hold all locks. Nobody can do something with the current
                    *   process and the current segment (also not within an other process).
                    */
                   NTSTATUS Status;
-                  PMDL Mdl;
-                  Mdl = MmCreateMdl(NULL, NULL, PAGE_SIZE);
-                  MmBuildMdlFromPages(Mdl, (PULONG)&Page);
-                  Status = MmWriteToSwapPage(SavedSwapEntry, Mdl);
+                  Status = MmWriteToSwapPage(SavedSwapEntry, Page);
                   if (!NT_SUCCESS(Status))
                   {
                      DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n", Status);
@@ -428,7 +444,7 @@ MmUnsharePageEntrySectionSegment(PSECTION_OBJECT Section,
 BOOL MiIsPageFromCache(PMEMORY_AREA MemoryArea,
                        ULONG SegOffset)
 {
-   if (!(MemoryArea->Data.SectionData.Segment->Characteristics & IMAGE_SECTION_CHAR_SHARED))
+   if (!(MemoryArea->Data.SectionData.Segment->Characteristics & IMAGE_SCN_MEM_SHARED))
    {
       PBCB Bcb;
       PCACHE_SEGMENT CacheSeg;
@@ -444,9 +460,10 @@ BOOL MiIsPageFromCache(PMEMORY_AREA MemoryArea,
 }
 
 NTSTATUS
+NTAPI
 MiReadPage(PMEMORY_AREA MemoryArea,
            ULONG SegOffset,
-           PHYSICAL_ADDRESS* Page)
+           PPFN_TYPE Page)
 /*
  * FUNCTION: Read a page for a section backed memory area.
  * PARAMETERS:
@@ -473,7 +490,7 @@ MiReadPage(PMEMORY_AREA MemoryArea,
    FileOffset = SegOffset + MemoryArea->Data.SectionData.Segment->FileOffset;
    IsImageSection = MemoryArea->Data.SectionData.Section->AllocationAttributes & SEC_IMAGE ? TRUE : FALSE;
 
-   assert(Bcb);
+   ASSERT(Bcb);
 
    DPRINT("%S %x\n", FileObject->FileName.Buffer, FileOffset);
 
@@ -483,8 +500,8 @@ MiReadPage(PMEMORY_AREA MemoryArea,
     * then get the related cache segment.
     */
    if ((FileOffset % PAGE_SIZE) == 0 &&
-         (SegOffset + PAGE_SIZE <= RawLength || !IsImageSection) &&
-         !(MemoryArea->Data.SectionData.Segment->Characteristics & IMAGE_SECTION_CHAR_SHARED))
+       (SegOffset + PAGE_SIZE <= RawLength || !IsImageSection) &&
+       !(MemoryArea->Data.SectionData.Segment->Characteristics & IMAGE_SCN_MEM_SHARED))
    {
 
       /*
@@ -519,7 +536,7 @@ MiReadPage(PMEMORY_AREA MemoryArea,
        * Retrieve the page from the cache segment that we actually want.
        */
       (*Page) = MmGetPhysicalAddress((char*)BaseAddress +
-                                     FileOffset - BaseOffset);
+                                     FileOffset - BaseOffset).QuadPart >> PAGE_SHIFT;
 
       CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, TRUE);
    }
@@ -559,7 +576,7 @@ MiReadPage(PMEMORY_AREA MemoryArea,
             return Status;
          }
       }
-      PageAddr = ExAllocatePageWithPhysPage(*Page);
+      PageAddr = MmCreateHyperspaceMapping(*Page);
       CacheSegOffset = BaseOffset + CacheSeg->Bcb->CacheSegmentSize - FileOffset;
       Length = RawLength - SegOffset;
       if (Length <= CacheSegOffset && Length <= PAGE_SIZE)
@@ -582,7 +599,7 @@ MiReadPage(PMEMORY_AREA MemoryArea,
                                        &CacheSeg);
          if (!NT_SUCCESS(Status))
          {
-            ExUnmapPage(PageAddr);
+            MmDeleteHyperspaceMapping(PageAddr);
             return(Status);
          }
          if (!UptoDate)
@@ -595,7 +612,7 @@ MiReadPage(PMEMORY_AREA MemoryArea,
             if (!NT_SUCCESS(Status))
             {
                CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE);
-               ExUnmapPage(PageAddr);
+               MmDeleteHyperspaceMapping(PageAddr);
                return Status;
             }
          }
@@ -609,21 +626,22 @@ MiReadPage(PMEMORY_AREA MemoryArea,
          }
       }
       CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, FALSE);
-      ExUnmapPage(PageAddr);
+      MmDeleteHyperspaceMapping(PageAddr);
    }
    return(STATUS_SUCCESS);
 }
 
 NTSTATUS
+NTAPI
 MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
                              MEMORY_AREA* MemoryArea,
                              PVOID Address,
                              BOOLEAN Locked)
 {
    ULONG Offset;
-   LARGE_INTEGER Page;
+   PFN_TYPE Page;
    NTSTATUS Status;
-   ULONG PAddress;
+   PVOID PAddress;
    PSECTION_OBJECT Section;
    PMM_SECTION_SEGMENT Segment;
    ULONG Entry;
@@ -642,17 +660,18 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
    {
       if (Locked)
       {
-         MmLockPage(MmGetPhysicalAddressForProcess(AddressSpace->Process, Address));
+         MmLockPage(MmGetPfnForProcess(AddressSpace->Process, Address));
       }
       return(STATUS_SUCCESS);
    }
 
-   PAddress = (ULONG)PAGE_ROUND_DOWN(((ULONG)Address));
-   Offset = PAddress - (ULONG)MemoryArea->BaseAddress;
+   PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
+   Offset = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress 
+            + MemoryArea->Data.SectionData.ViewOffset;
 
    Segment = MemoryArea->Data.SectionData.Segment;
    Section = MemoryArea->Data.SectionData.Section;
-   Region = MmFindRegion(MemoryArea->BaseAddress,
+   Region = MmFindRegion(MemoryArea->StartingAddress,
                          &MemoryArea->Data.SectionData.RegionListHead,
                          Address, NULL);
    /*
@@ -664,8 +683,8 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
     * Check if this page needs to be mapped COW
     */
    if ((Segment->WriteCopy || MemoryArea->Data.SectionData.WriteCopyView) &&
-         (Region->Protect == PAGE_READWRITE ||
-          Region->Protect == PAGE_EXECUTE_READWRITE))
+       (Region->Protect == PAGE_READWRITE ||
+       Region->Protect == PAGE_EXECUTE_READWRITE))
    {
       Attributes = Region->Protect == PAGE_READWRITE ? PAGE_READONLY : PAGE_EXECUTE_READ;
    }
@@ -677,7 +696,7 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
    /*
     * Get or create a page operation descriptor
     */
-   PageOp = MmGetPageOp(MemoryArea, 0, 0, Segment, Offset, MM_PAGEOP_PAGEIN, FALSE);
+   PageOp = MmGetPageOp(MemoryArea, NULL, 0, Segment, Offset, MM_PAGEOP_PAGEIN, FALSE);
    if (PageOp == NULL)
    {
       DPRINT1("MmGetPageOp failed\n");
@@ -740,39 +759,31 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
          if (PAGE_FROM_SSE(Entry) == 0 || HasSwapEntry)
          {
             /*
-             * The page was a private page in another or in our address space 
+             * The page was a private page in another or in our address space
             */
             MmUnlockSectionSegment(Segment);
             MmspCompleteAndReleasePageOp(PageOp);
             return(STATUS_MM_RESTART_OPERATION);
          }
 
-         Page.QuadPart = (LONGLONG)(PAGE_FROM_SSE(Entry));
+         Page = PFN_FROM_SSE(Entry);
 
          MmSharePageEntrySectionSegment(Segment, Offset);
 
-         Status = MmCreateVirtualMapping(MemoryArea->Process,
+         /* FIXME: Should we call MmCreateVirtualMappingUnsafe if
+          * (Section->AllocationAttributes & SEC_PHYSICALMEMORY) is true?
+          */
+         Status = MmCreateVirtualMapping(AddressSpace->Process,
                                          Address,
                                          Attributes,
-                                         Page,
-                                         FALSE);
-         if (Status == STATUS_NO_MEMORY)
-         {
-            MmUnlockAddressSpace(AddressSpace);
-            Status = MmCreateVirtualMapping(MemoryArea->Process,
-                                            Address,
-                                            Attributes,
-                                            Page,
-                                            TRUE);
-            MmLockAddressSpace(AddressSpace);
-         }
-
+                                         &Page,
+                                         1);
          if (!NT_SUCCESS(Status))
          {
             DbgPrint("Unable to create virtual mapping\n");
             KEBUGCHECK(0);
          }
-         MmInsertRmap(Page, MemoryArea->Process, (PVOID)PAddress);
+         MmInsertRmap(Page, AddressSpace->Process, (PVOID)PAddress);
       }
       if (Locked)
       {
@@ -792,7 +803,6 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
        * Must be private page we have swapped out.
        */
       SWAPENTRY SwapEntry;
-      PMDL Mdl;
 
       /*
        * Sanity check
@@ -813,9 +823,7 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
          KEBUGCHECK(0);
       }
 
-      Mdl = MmCreateMdl(NULL, NULL, PAGE_SIZE);
-      MmBuildMdlFromPages(Mdl, (PULONG)&Page);
-      Status = MmReadFromSwapPage(SwapEntry, Mdl);
+      Status = MmReadFromSwapPage(SwapEntry, Page);
       if (!NT_SUCCESS(Status))
       {
          DPRINT1("MmReadFromSwapPage failed, status = %x\n", Status);
@@ -825,18 +833,8 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
       Status = MmCreateVirtualMapping(AddressSpace->Process,
                                       Address,
                                       Region->Protect,
-                                      Page,
-                                      FALSE);
-      if (Status == STATUS_NO_MEMORY)
-      {
-         MmUnlockAddressSpace(AddressSpace);
-         Status = MmCreateVirtualMapping(AddressSpace->Process,
-                                         Address,
-                                         Region->Protect,
-                                         Page,
-                                         TRUE);
-         MmLockAddressSpace(AddressSpace);
-      }
+                                      &Page,
+                                      1);
       if (!NT_SUCCESS(Status))
       {
          DPRINT("MmCreateVirtualMapping failed, not out of memory\n");
@@ -845,8 +843,8 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
       }
 
       /*
-      * Store the swap entry for later use.
-      */
+       * Store the swap entry for later use.
+       */
       MmSetSavedSwapEntryPage(Page, SwapEntry);
 
       /*
@@ -859,7 +857,7 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
       */
       if (Locked)
       {
-         MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
+         MmLockPage(Page);
       }
       PageOp->Status = STATUS_SUCCESS;
       MmspCompleteAndReleasePageOp(PageOp);
@@ -876,25 +874,15 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
       /*
       * Just map the desired physical page
       */
-      Page.QuadPart = Offset + MemoryArea->Data.SectionData.ViewOffset;
-      Status = MmCreateVirtualMapping(AddressSpace->Process,
-                                      Address,
-                                      Region->Protect,
-                                      Page,
-                                      FALSE);
-      if (Status == STATUS_NO_MEMORY)
-      {
-         MmUnlockAddressSpace(AddressSpace);
-         Status = MmCreateVirtualMapping(AddressSpace->Process,
-                                         Address,
-                                         Region->Protect,
-                                         Page,
-                                         TRUE);
-         MmLockAddressSpace(AddressSpace);
-      }
+      Page = Offset >> PAGE_SHIFT;
+      Status = MmCreateVirtualMappingUnsafe(AddressSpace->Process,
+                                            Address,
+                                            Region->Protect,
+                                            &Page,
+                                            1);
       if (!NT_SUCCESS(Status))
       {
-         DPRINT("MmCreateVirtualMapping failed, not out of memory\n");
+         DPRINT("MmCreateVirtualMappingUnsafe failed, not out of memory\n");
          KEBUGCHECK(0);
          return(Status);
       }
@@ -904,7 +892,7 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
       */
       if (Locked)
       {
-         MmLockPage(Page);
+         MmLockPageUnsafe(Page);
       }
 
       /*
@@ -919,7 +907,7 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
    /*
     * Map anonymous memory for BSS sections
     */
-   if (Segment->Characteristics & IMAGE_SECTION_CHAR_BSS)
+   if (Segment->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
    {
       MmUnlockSectionSegment(Segment);
       Status = MmRequestPageMemoryConsumer(MC_USER, FALSE, &Page);
@@ -936,19 +924,8 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
       Status = MmCreateVirtualMapping(AddressSpace->Process,
                                       Address,
                                       Region->Protect,
-                                      Page,
-                                      FALSE);
-      if (Status == STATUS_NO_MEMORY)
-      {
-         MmUnlockAddressSpace(AddressSpace);
-         Status = MmCreateVirtualMapping(AddressSpace->Process,
-                                         Address,
-                                         Region->Protect,
-                                         Page,
-                                         TRUE);
-         MmLockAddressSpace(AddressSpace);
-      }
-
+                                      &Page,
+                                      1);
       if (!NT_SUCCESS(Status))
       {
          DPRINT("MmCreateVirtualMapping failed, not out of memory\n");
@@ -989,7 +966,7 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
       MmUnlockAddressSpace(AddressSpace);
 
       if ((Segment->Flags & MM_PAGEFILE_SEGMENT) ||
-            (Offset >= PAGE_ROUND_UP(Segment->RawLength) && Section->AllocationAttributes & SEC_IMAGE))
+          (Offset >= PAGE_ROUND_UP(Segment->RawLength) && Section->AllocationAttributes & SEC_IMAGE))
       {
          Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
          if (!NT_SUCCESS(Status))
@@ -1040,25 +1017,15 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
       * Mark the offset within the section as having valid, in-memory
       * data
       */
-      Entry = MAKE_SSE(Page.u.LowPart, 1);
+      Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
       MmSetPageEntrySectionSegment(Segment, Offset, Entry);
       MmUnlockSectionSegment(Segment);
 
       Status = MmCreateVirtualMapping(AddressSpace->Process,
                                       Address,
                                       Attributes,
-                                      Page,
-                                      FALSE);
-      if (Status == STATUS_NO_MEMORY)
-      {
-         MmUnlockAddressSpace(AddressSpace);
-         Status = MmCreateVirtualMapping(AddressSpace->Process,
-                                         Address,
-                                         Attributes,
-                                         Page,
-                                         TRUE);
-         MmLockAddressSpace(AddressSpace);
-      }
+                                      &Page,
+                                      1);
       if (!NT_SUCCESS(Status))
       {
          DbgPrint("Unable to create virtual mapping\n");
@@ -1078,7 +1045,6 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
    else if (IS_SWAP_FROM_SSE(Entry))
    {
       SWAPENTRY SwapEntry;
-      PMDL Mdl;
 
       SwapEntry = SWAPENTRY_FROM_SSE(Entry);
 
@@ -1095,9 +1061,7 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
          KEBUGCHECK(0);
       }
 
-      Mdl = MmCreateMdl(NULL, NULL, PAGE_SIZE);
-      MmBuildMdlFromPages(Mdl, (PULONG)&Page);
-      Status = MmReadFromSwapPage(SwapEntry, Mdl);
+      Status = MmReadFromSwapPage(SwapEntry, Page);
       if (!NT_SUCCESS(Status))
       {
          KEBUGCHECK(0);
@@ -1124,7 +1088,7 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
       * Mark the offset within the section as having valid, in-memory
       * data
       */
-      Entry = MAKE_SSE(Page.u.LowPart, 1);
+      Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
       MmSetPageEntrySectionSegment(Segment, Offset, Entry);
       MmUnlockSectionSegment(Segment);
 
@@ -1135,18 +1099,8 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
       Status = MmCreateVirtualMapping(AddressSpace->Process,
                                       Address,
                                       Region->Protect,
-                                      Page,
-                                      FALSE);
-      if (Status == STATUS_NO_MEMORY)
-      {
-         MmUnlockAddressSpace(AddressSpace);
-         Status = MmCreateVirtualMapping(AddressSpace->Process,
-                                         Address,
-                                         Region->Protect,
-                                         Page,
-                                         TRUE);
-         MmLockAddressSpace(AddressSpace);
-      }
+                                      &Page,
+                                      1);
       if (!NT_SUCCESS(Status))
       {
          DbgPrint("Unable to create virtual mapping\n");
@@ -1169,7 +1123,7 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
       * take another reference to the page
       */
 
-      Page.QuadPart = (LONGLONG)PAGE_FROM_SSE(Entry);
+      Page = PFN_FROM_SSE(Entry);
 
       MmSharePageEntrySectionSegment(Segment, Offset);
       MmUnlockSectionSegment(Segment);
@@ -1177,18 +1131,8 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
       Status = MmCreateVirtualMapping(AddressSpace->Process,
                                       Address,
                                       Attributes,
-                                      Page,
-                                      FALSE);
-      if (Status == STATUS_NO_MEMORY)
-      {
-         MmUnlockAddressSpace(AddressSpace);
-         Status = MmCreateVirtualMapping(AddressSpace->Process,
-                                         Address,
-                                         Attributes,
-                                         Page,
-                                         TRUE);
-         MmLockAddressSpace(AddressSpace);
-      }
+                                      &Page,
+                                      1);
       if (!NT_SUCCESS(Status))
       {
          DbgPrint("Unable to create virtual mapping\n");
@@ -1207,6 +1151,7 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
 }
 
 NTSTATUS
+NTAPI
 MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
                          MEMORY_AREA* MemoryArea,
                          PVOID Address,
@@ -1214,11 +1159,10 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
 {
    PMM_SECTION_SEGMENT Segment;
    PSECTION_OBJECT Section;
-   PHYSICAL_ADDRESS OldPage;
-   PHYSICAL_ADDRESS NewPage;
-   PVOID NewAddress;
+   PFN_TYPE OldPage;
+   PFN_TYPE NewPage;
    NTSTATUS Status;
-   ULONG PAddress;
+   PVOID PAddress;
    ULONG Offset;
    PMM_PAGEOP PageOp;
    PMM_REGION Region;
@@ -1237,12 +1181,13 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
    /*
     * Find the offset of the page
     */
-   PAddress = (ULONG)PAGE_ROUND_DOWN(((ULONG)Address));
-   Offset = PAddress - (ULONG)MemoryArea->BaseAddress;
+   PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
+   Offset = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress 
+            + MemoryArea->Data.SectionData.ViewOffset;
 
    Segment = MemoryArea->Data.SectionData.Segment;
    Section = MemoryArea->Data.SectionData.Section;
-   Region = MmFindRegion(MemoryArea->BaseAddress,
+   Region = MmFindRegion(MemoryArea->StartingAddress,
                          &MemoryArea->Data.SectionData.RegionListHead,
                          Address, NULL);
    /*
@@ -1250,7 +1195,7 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
     */
    MmLockSectionSegment(Segment);
 
-   OldPage = MmGetPhysicalAddressForProcess(NULL, Address);
+   OldPage = MmGetPfnForProcess(NULL, Address);
    Entry = MmGetPageEntrySectionSegment(Segment, Offset);
 
    MmUnlockSectionSegment(Segment);
@@ -1267,17 +1212,17 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
    }
 
    if (IS_SWAP_FROM_SSE(Entry) ||
-         PAGE_FROM_SSE(Entry) != OldPage.u.LowPart)
+       PFN_FROM_SSE(Entry) != OldPage)
    {
       /* This is a private page. We must only change the page protection. */
-      MmSetPageProtect(AddressSpace->Process, (PVOID)PAddress, Region->Protect);
+      MmSetPageProtect(AddressSpace->Process, PAddress, Region->Protect);
       return(STATUS_SUCCESS);
    }
 
    /*
     * Get or create a pageop
     */
-   PageOp = MmGetPageOp(MemoryArea, 0, 0, Segment, Offset,
+   PageOp = MmGetPageOp(MemoryArea, NULL, 0, Segment, Offset,
                         MM_PAGEOP_ACCESSFAULT, FALSE);
    if (PageOp == NULL)
    {
@@ -1331,10 +1276,7 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
    /*
     * Copy the old page
     */
-
-   NewAddress = ExAllocatePageWithPhysPage(NewPage);
-   memcpy(NewAddress, (PVOID)PAddress, PAGE_SIZE);
-   ExUnmapPage(NewAddress);
+   MiCopyFromUserPage(NewPage, PAddress);
 
    /*
     * Delete the old entry.
@@ -1348,25 +1290,15 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
    Status = MmCreateVirtualMapping(AddressSpace->Process,
                                    Address,
                                    Region->Protect,
-                                   NewPage,
-                                   FALSE);
-   if (Status == STATUS_NO_MEMORY)
-   {
-      MmUnlockAddressSpace(AddressSpace);
-      Status = MmCreateVirtualMapping(AddressSpace->Process,
-                                      Address,
-                                      Region->Protect,
-                                      NewPage,
-                                      TRUE);
-      MmLockAddressSpace(AddressSpace);
-   }
+                                   &NewPage,
+                                   1);
    if (!NT_SUCCESS(Status))
    {
       DPRINT("MmCreateVirtualMapping failed, not out of memory\n");
       KEBUGCHECK(0);
       return(Status);
    }
-   MmInsertRmap(NewPage, AddressSpace->Process, (PVOID)PAddress);
+   MmInsertRmap(NewPage, AddressSpace->Process, PAddress);
    if (!NT_SUCCESS(Status))
    {
       DbgPrint("Unable to create virtual mapping\n");
@@ -1381,7 +1313,7 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
    /*
     * Unshare the old page.
     */
-   MmDeleteRmap(OldPage, AddressSpace->Process, (PVOID)PAddress);
+   MmDeleteRmap(OldPage, AddressSpace->Process, PAddress);
    MmLockSectionSegment(Segment);
    MmUnsharePageEntrySectionSegment(Section, Segment, Offset, FALSE, FALSE);
    MmUnlockSectionSegment(Segment);
@@ -1397,7 +1329,7 @@ MmPageOutDeleteMapping(PVOID Context, PEPROCESS Process, PVOID Address)
 {
    MM_SECTION_PAGEOUT_CONTEXT* PageOutContext;
    BOOL WasDirty;
-   PHYSICAL_ADDRESS Page;
+   PFN_TYPE Page;
 
    PageOutContext = (MM_SECTION_PAGEOUT_CONTEXT*)Context;
    MmDeleteVirtualMapping(Process,
@@ -1426,15 +1358,15 @@ MmPageOutDeleteMapping(PVOID Context, PEPROCESS Process, PVOID Address)
 }
 
 NTSTATUS
+NTAPI
 MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
                      MEMORY_AREA* MemoryArea,
                      PVOID Address,
                      PMM_PAGEOP PageOp)
 {
-   PHYSICAL_ADDRESS PhysicalAddress;
+   PFN_TYPE Page;
    MM_SECTION_PAGEOUT_CONTEXT Context;
    SWAPENTRY SwapEntry;
-   PMDL Mdl;
    ULONG Entry;
    ULONG FileOffset;
    NTSTATUS Status;
@@ -1451,7 +1383,8 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
    Context.Segment = MemoryArea->Data.SectionData.Segment;
    Context.Section = MemoryArea->Data.SectionData.Section;
 
-   Context.Offset = (ULONG)((char*)Address - (ULONG)MemoryArea->BaseAddress);
+   Context.Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress 
+                    + MemoryArea->Data.SectionData.ViewOffset;
    FileOffset = Context.Offset + Context.Segment->FileOffset;
 
    IsImageSection = Context.Section->AllocationAttributes & SEC_IMAGE ? TRUE : FALSE;
@@ -1459,7 +1392,7 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
    FileObject = Context.Section->FileObject;
    DirectMapped = FALSE;
    if (FileObject != NULL &&
-         !(Context.Segment->Characteristics & IMAGE_SECTION_CHAR_SHARED))
+       !(Context.Segment->Characteristics & IMAGE_SCN_MEM_SHARED))
    {
       Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
 
@@ -1498,17 +1431,16 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
               AddressSpace->Process ? AddressSpace->Process->UniqueProcessId : 0, Address);
       KEBUGCHECK(0);
    }
-   PhysicalAddress =
-      MmGetPhysicalAddressForProcess(AddressSpace->Process, Address);
-   SwapEntry = MmGetSavedSwapEntryPage(PhysicalAddress);
+   Page = MmGetPfnForProcess(AddressSpace->Process, Address);
+   SwapEntry = MmGetSavedSwapEntryPage(Page);
 
    /*
     * Prepare the context structure for the rmap delete call.
     */
    Context.WasDirty = FALSE;
-   if (Context.Segment->Characteristics & IMAGE_SECTION_CHAR_BSS ||
+   if (Context.Segment->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ||
          IS_SWAP_FROM_SSE(Entry) ||
-         (LONGLONG)PAGE_FROM_SSE(Entry) != PhysicalAddress.QuadPart)
+         PFN_FROM_SSE(Entry) != Page)
    {
       Context.Private = TRUE;
    }
@@ -1530,10 +1462,10 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
    }
    else
    {
-      MmReferencePage(PhysicalAddress);
+      MmReferencePage(Page);
    }
 
-   MmDeleteAllRmaps(PhysicalAddress, (PVOID)&Context, MmPageOutDeleteMapping);
+   MmDeleteAllRmaps(Page, (PVOID)&Context, MmPageOutDeleteMapping);
 
    /*
     * If this wasn't a private page then we should have reduced the entry to
@@ -1542,7 +1474,7 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
    if (!Context.Private && MmGetPageEntrySectionSegment(Context.Segment, Context.Offset) != 0)
    {
       if (!(Context.Segment->Flags & MM_PAGEFILE_SEGMENT) &&
-            !(Context.Segment->Characteristics & IMAGE_SECTION_CHAR_SHARED))
+            !(Context.Segment->Characteristics & IMAGE_SCN_MEM_SHARED))
       {
          KEBUGCHECK(0);
       }
@@ -1555,7 +1487,7 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
     * If the page is from a pagefile section and has no swap entry,
     * we can't free the page at this point.
     */
-   SwapEntry = MmGetSavedSwapEntryPage(PhysicalAddress);
+   SwapEntry = MmGetSavedSwapEntryPage(Page);
    if (Context.Segment->Flags & MM_PAGEFILE_SEGMENT)
    {
       if (Context.Private)
@@ -1566,15 +1498,15 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
       }
       if (!Context.WasDirty && SwapEntry != 0)
       {
-         MmSetSavedSwapEntryPage(PhysicalAddress, 0);
+         MmSetSavedSwapEntryPage(Page, 0);
          MmSetPageEntrySectionSegment(Context.Segment, Context.Offset, MAKE_SWAP_SSE(SwapEntry));
-         MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
+         MmReleasePageMemoryConsumer(MC_USER, Page);
          PageOp->Status = STATUS_SUCCESS;
          MmspCompleteAndReleasePageOp(PageOp);
          return(STATUS_SUCCESS);
       }
    }
-   else if (Context.Segment->Characteristics & IMAGE_SECTION_CHAR_SHARED)
+   else if (Context.Segment->Characteristics & IMAGE_SCN_MEM_SHARED)
    {
       if (Context.Private)
       {
@@ -1584,12 +1516,12 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
       }
       if (!Context.WasDirty || SwapEntry != 0)
       {
-         MmSetSavedSwapEntryPage(PhysicalAddress, 0);
+         MmSetSavedSwapEntryPage(Page, 0);
          if (SwapEntry != 0)
          {
             MmSetPageEntrySectionSegment(Context.Segment, Context.Offset, MAKE_SWAP_SSE(SwapEntry));
          }
-         MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
+         MmReleasePageMemoryConsumer(MC_USER, Page);
          PageOp->Status = STATUS_SUCCESS;
          MmspCompleteAndReleasePageOp(PageOp);
          return(STATUS_SUCCESS);
@@ -1621,14 +1553,14 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
                  Address);
          KEBUGCHECK(0);
       }
-      MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
+      MmReleasePageMemoryConsumer(MC_USER, Page);
       PageOp->Status = STATUS_SUCCESS;
       MmspCompleteAndReleasePageOp(PageOp);
       return(STATUS_SUCCESS);
    }
    else if (!Context.WasDirty && Context.Private && SwapEntry != 0)
    {
-      MmSetSavedSwapEntryPage(PhysicalAddress, 0);
+      MmSetSavedSwapEntryPage(Page, 0);
       Status = MmCreatePageFileMapping(AddressSpace->Process,
                                        Address,
                                        SwapEntry);
@@ -1636,7 +1568,7 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
       {
          KEBUGCHECK(0);
       }
-      MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
+      MmReleasePageMemoryConsumer(MC_USER, Page);
       PageOp->Status = STATUS_SUCCESS;
       MmspCompleteAndReleasePageOp(PageOp);
       return(STATUS_SUCCESS);
@@ -1657,14 +1589,14 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
           */
          if (Context.Private)
          {
-            Status = MmCreateVirtualMapping(MemoryArea->Process,
+            Status = MmCreateVirtualMapping(AddressSpace->Process,
                                             Address,
                                             MemoryArea->Attributes,
-                                            PhysicalAddress,
-                                            FALSE);
-            MmSetDirtyPage(MemoryArea->Process, Address);
-            MmInsertRmap(PhysicalAddress,
-                         MemoryArea->Process,
+                                            &Page,
+                                            1);
+            MmSetDirtyPage(AddressSpace->Process, Address);
+            MmInsertRmap(Page,
+                         AddressSpace->Process,
                          Address);
          }
          else
@@ -1674,16 +1606,16 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
              * set it back into the section segment entry so we don't loose
              * our copy. Otherwise it will be handled by the cache manager.
              */
-            Status = MmCreateVirtualMapping(MemoryArea->Process,
+            Status = MmCreateVirtualMapping(AddressSpace->Process,
                                             Address,
                                             MemoryArea->Attributes,
-                                            PhysicalAddress,
-                                            FALSE);
-            MmSetDirtyPage(MemoryArea->Process, Address);
-            MmInsertRmap(PhysicalAddress,
-                         MemoryArea->Process,
+                                            &Page,
+                                            1);
+            MmSetDirtyPage(AddressSpace->Process, Address);
+            MmInsertRmap(Page,
+                         AddressSpace->Process,
                          Address);
-            Entry = MAKE_SSE(PhysicalAddress.u.LowPart, 1);
+            Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
             MmSetPageEntrySectionSegment(Context.Segment, Context.Offset, Entry);
          }
          PageOp->Status = STATUS_UNSUCCESSFUL;
@@ -1695,9 +1627,7 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
    /*
     * Write the page to the pagefile
     */
-   Mdl = MmCreateMdl(NULL, NULL, PAGE_SIZE);
-   MmBuildMdlFromPages(Mdl, (PULONG)&PhysicalAddress);
-   Status = MmWriteToSwapPage(SwapEntry, Mdl);
+   Status = MmWriteToSwapPage(SwapEntry, Page);
    if (!NT_SUCCESS(Status))
    {
       DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n",
@@ -1708,28 +1638,28 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
        */
       if (Context.Private)
       {
-         Status = MmCreateVirtualMapping(MemoryArea->Process,
+         Status = MmCreateVirtualMapping(AddressSpace->Process,
                                          Address,
                                          MemoryArea->Attributes,
-                                         PhysicalAddress,
-                                         FALSE);
-         MmSetDirtyPage(MemoryArea->Process, Address);
-         MmInsertRmap(PhysicalAddress,
-                      MemoryArea->Process,
+                                         &Page,
+                                         1);
+         MmSetDirtyPage(AddressSpace->Process, Address);
+         MmInsertRmap(Page,
+                      AddressSpace->Process,
                       Address);
       }
       else
       {
-         Status = MmCreateVirtualMapping(MemoryArea->Process,
+         Status = MmCreateVirtualMapping(AddressSpace->Process,
                                          Address,
                                          MemoryArea->Attributes,
-                                         PhysicalAddress,
-                                         FALSE);
-         MmSetDirtyPage(MemoryArea->Process, Address);
-         MmInsertRmap(PhysicalAddress,
-                      MemoryArea->Process,
+                                         &Page,
+                                         1);
+         MmSetDirtyPage(AddressSpace->Process, Address);
+         MmInsertRmap(Page,
+                      AddressSpace->Process,
                       Address);
-         Entry = MAKE_SSE(PhysicalAddress.u.LowPart, 1);
+         Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
          MmSetPageEntrySectionSegment(Context.Segment, Context.Offset, Entry);
       }
       PageOp->Status = STATUS_UNSUCCESSFUL;
@@ -1740,21 +1670,21 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
    /*
     * Otherwise we have succeeded.
     */
-   DPRINT("MM: Wrote section page 0x%.8X to swap!\n", PhysicalAddress);
-   MmSetSavedSwapEntryPage(PhysicalAddress, 0);
+   DPRINT("MM: Wrote section page 0x%.8X to swap!\n", Page << PAGE_SHIFT);
+   MmSetSavedSwapEntryPage(Page, 0);
    if (Context.Segment->Flags & MM_PAGEFILE_SEGMENT ||
-         Context.Segment->Characteristics & IMAGE_SECTION_CHAR_SHARED)
+         Context.Segment->Characteristics & IMAGE_SCN_MEM_SHARED)
    {
       MmSetPageEntrySectionSegment(Context.Segment, Context.Offset, MAKE_SWAP_SSE(SwapEntry));
    }
    else
    {
-      MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
+      MmReleasePageMemoryConsumer(MC_USER, Page);
    }
 
    if (Context.Private)
    {
-      Status = MmCreatePageFileMapping(MemoryArea->Process,
+      Status = MmCreatePageFileMapping(AddressSpace->Process,
                                        Address,
                                        SwapEntry);
       if (!NT_SUCCESS(Status))
@@ -1774,6 +1704,7 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
 }
 
 NTSTATUS
+NTAPI
 MmWritePageSectionView(PMADDRESS_SPACE AddressSpace,
                        PMEMORY_AREA MemoryArea,
                        PVOID Address,
@@ -1782,9 +1713,8 @@ MmWritePageSectionView(PMADDRESS_SPACE AddressSpace,
    ULONG Offset;
    PSECTION_OBJECT Section;
    PMM_SECTION_SEGMENT Segment;
-   PHYSICAL_ADDRESS PhysicalAddress;
+   PFN_TYPE Page;
    SWAPENTRY SwapEntry;
-   PMDL Mdl;
    ULONG Entry;
    BOOLEAN Private;
    NTSTATUS Status;
@@ -1795,7 +1725,8 @@ MmWritePageSectionView(PMADDRESS_SPACE AddressSpace,
 
    Address = (PVOID)PAGE_ROUND_DOWN(Address);
 
-   Offset = (ULONG)((char*)Address - (ULONG)MemoryArea->BaseAddress);
+   Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress 
+            + MemoryArea->Data.SectionData.ViewOffset;
 
    /*
     * Get the segment and section.
@@ -1807,7 +1738,7 @@ MmWritePageSectionView(PMADDRESS_SPACE AddressSpace,
    FileObject = Section->FileObject;
    DirectMapped = FALSE;
    if (FileObject != NULL &&
-         !(Segment->Characteristics & IMAGE_SECTION_CHAR_SHARED))
+         !(Segment->Characteristics & IMAGE_SCN_MEM_SHARED))
    {
       Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
 
@@ -1816,7 +1747,7 @@ MmWritePageSectionView(PMADDRESS_SPACE AddressSpace,
        * memory area was mapped at an offset in the file which is page aligned
        * then note this is a direct mapped page.
        */
-      if ((Offset + MemoryArea->Data.SectionData.ViewOffset % PAGE_SIZE) == 0 &&
+      if (((Offset + Segment->FileOffset) % PAGE_SIZE) == 0 &&
             (Offset + PAGE_SIZE <= Segment->RawLength || !IsImageSection))
       {
          DirectMapped = TRUE;
@@ -1845,16 +1776,15 @@ MmWritePageSectionView(PMADDRESS_SPACE AddressSpace,
               AddressSpace->Process ? AddressSpace->Process->UniqueProcessId : 0, Address);
       KEBUGCHECK(0);
    }
-   PhysicalAddress =
-      MmGetPhysicalAddressForProcess(AddressSpace->Process, Address);
-   SwapEntry = MmGetSavedSwapEntryPage(PhysicalAddress);
+   Page = MmGetPfnForProcess(AddressSpace->Process, Address);
+   SwapEntry = MmGetSavedSwapEntryPage(Page);
 
    /*
     * Check for a private (COWed) page.
     */
-   if (Segment->Characteristics & IMAGE_SECTION_CHAR_BSS ||
+   if (Segment->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ||
          IS_SWAP_FROM_SSE(Entry) ||
-         (LONGLONG)PAGE_FROM_SSE(Entry) != PhysicalAddress.QuadPart)
+         PFN_FROM_SSE(Entry) != Page)
    {
       Private = TRUE;
    }
@@ -1866,7 +1796,7 @@ MmWritePageSectionView(PMADDRESS_SPACE AddressSpace,
    /*
     * Speculatively set all mappings of the page to clean.
     */
-   MmSetCleanAllRmaps(PhysicalAddress);
+   MmSetCleanAllRmaps(Page);
 
    /*
     * If this page was direct mapped from the cache then the cache manager
@@ -1874,8 +1804,8 @@ MmWritePageSectionView(PMADDRESS_SPACE AddressSpace,
     */
    if (DirectMapped && !Private)
    {
-      assert(SwapEntry == 0);
-      CcRosMarkDirtyCacheSegment(Bcb, Offset + MemoryArea->Data.SectionData.ViewOffset);
+      ASSERT(SwapEntry == 0);
+      CcRosMarkDirtyCacheSegment(Bcb, Offset + Segment->FileOffset);
       PageOp->Status = STATUS_SUCCESS;
       MmspCompleteAndReleasePageOp(PageOp);
       return(STATUS_SUCCESS);
@@ -1889,25 +1819,23 @@ MmWritePageSectionView(PMADDRESS_SPACE AddressSpace,
       SwapEntry = MmAllocSwapPage();
       if (SwapEntry == 0)
       {
-         MmSetDirtyAllRmaps(PhysicalAddress);
+         MmSetDirtyAllRmaps(Page);
          PageOp->Status = STATUS_UNSUCCESSFUL;
          MmspCompleteAndReleasePageOp(PageOp);
          return(STATUS_PAGEFILE_QUOTA);
       }
-      MmSetSavedSwapEntryPage(PhysicalAddress, SwapEntry);
+      MmSetSavedSwapEntryPage(Page, SwapEntry);
    }
 
    /*
     * Write the page to the pagefile
     */
-   Mdl = MmCreateMdl(NULL, NULL, PAGE_SIZE);
-   MmBuildMdlFromPages(Mdl, (PULONG)&PhysicalAddress);
-   Status = MmWriteToSwapPage(SwapEntry, Mdl);
+   Status = MmWriteToSwapPage(SwapEntry, Page);
    if (!NT_SUCCESS(Status))
    {
       DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n",
               Status);
-      MmSetDirtyAllRmaps(PhysicalAddress);
+      MmSetDirtyAllRmaps(Page);
       PageOp->Status = STATUS_UNSUCCESSFUL;
       MmspCompleteAndReleasePageOp(PageOp);
       return(STATUS_UNSUCCESSFUL);
@@ -1916,7 +1844,7 @@ MmWritePageSectionView(PMADDRESS_SPACE AddressSpace,
    /*
     * Otherwise we have succeeded.
     */
-   DPRINT("MM: Wrote section page 0x%.8X to swap!\n", PhysicalAddress);
+   DPRINT("MM: Wrote section page 0x%.8X to swap!\n", Page << PAGE_SHIFT);
    PageOp->Status = STATUS_SUCCESS;
    MmspCompleteAndReleasePageOp(PageOp);
    return(STATUS_SUCCESS);
@@ -1936,7 +1864,7 @@ MmAlterViewAttributes(PMADDRESS_SPACE AddressSpace,
    BOOL DoCOW = FALSE;
    ULONG i;
 
-   MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, BaseAddress);
+   MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, BaseAddress);
    Segment = MemoryArea->Data.SectionData.Segment;
 
    if ((Segment->WriteCopy || MemoryArea->Data.SectionData.WriteCopyView) &&
@@ -1960,17 +1888,17 @@ MmAlterViewAttributes(PMADDRESS_SPACE AddressSpace,
          {
             ULONG Offset;
             ULONG Entry;
-            LARGE_INTEGER PhysicalAddress;
+            PFN_TYPE Page;
 
-            Offset =  (ULONG)Address - (ULONG)MemoryArea->BaseAddress;
+            Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress 
+                     + MemoryArea->Data.SectionData.ViewOffset;
             Entry = MmGetPageEntrySectionSegment(Segment, Offset);
-            PhysicalAddress =
-               MmGetPhysicalAddressForProcess(AddressSpace->Process, Address);
+            Page = MmGetPfnForProcess(AddressSpace->Process, Address);
 
             Protect = PAGE_READONLY;
-            if ((Segment->Characteristics & IMAGE_SECTION_CHAR_BSS ||
+            if (Segment->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ||
                   IS_SWAP_FROM_SSE(Entry) ||
-                  (LONGLONG)PAGE_FROM_SSE(Entry) != PhysicalAddress.QuadPart))
+                  PFN_FROM_SSE(Entry) != Page)
             {
                Protect = NewProtect;
             }
@@ -1978,7 +1906,7 @@ MmAlterViewAttributes(PMADDRESS_SPACE AddressSpace,
 
          if (MmIsPagePresent(AddressSpace->Process, Address))
          {
-            MmSetPageProtect(AddressSpace->Process, BaseAddress,
+            MmSetPageProtect(AddressSpace->Process, Address,
                              Protect);
          }
       }
@@ -1986,6 +1914,7 @@ MmAlterViewAttributes(PMADDRESS_SPACE AddressSpace,
 }
 
 NTSTATUS
+NTAPI
 MmProtectSectionView(PMADDRESS_SPACE AddressSpace,
                      PMEMORY_AREA MemoryArea,
                      PVOID BaseAddress,
@@ -1995,14 +1924,17 @@ MmProtectSectionView(PMADDRESS_SPACE AddressSpace,
 {
    PMM_REGION Region;
    NTSTATUS Status;
+   ULONG_PTR MaxLength;
+
+   MaxLength = (ULONG_PTR)MemoryArea->EndingAddress - (ULONG_PTR)BaseAddress;
+   if (Length > MaxLength)
+      Length = MaxLength;
 
-   Length =
-      min(Length, (ULONG) ((char*)MemoryArea->BaseAddress + MemoryArea->Length - (char*)BaseAddress));
-   Region = MmFindRegion(MemoryArea->BaseAddress,
+   Region = MmFindRegion(MemoryArea->StartingAddress,
                          &MemoryArea->Data.SectionData.RegionListHead,
                          BaseAddress, NULL);
    *OldProtect = Region->Protect;
-   Status = MmAlterRegion(AddressSpace, MemoryArea->BaseAddress,
+   Status = MmAlterRegion(AddressSpace, MemoryArea->StartingAddress,
                           &MemoryArea->Data.SectionData.RegionListHead,
                           BaseAddress, Length, Region->Type, Protect,
                           MmAlterViewAttributes);
@@ -2018,43 +1950,51 @@ MmQuerySectionView(PMEMORY_AREA MemoryArea,
 {
    PMM_REGION Region;
    PVOID RegionBaseAddress;
+   PSECTION_OBJECT Section;
+   PMM_SECTION_SEGMENT Segment;
 
-   Region = MmFindRegion(MemoryArea->BaseAddress,
+   Region = MmFindRegion((PVOID)MemoryArea->StartingAddress,
                          &MemoryArea->Data.SectionData.RegionListHead,
                          Address, &RegionBaseAddress);
    if (Region == NULL)
    {
       return STATUS_UNSUCCESSFUL;
    }
-   Info->BaseAddress = (PVOID)PAGE_ROUND_DOWN(Address);
-   Info->AllocationBase = MemoryArea->BaseAddress;
-   Info->AllocationProtect = MemoryArea->Attributes;
-   Info->RegionSize = MemoryArea->Length;
-   Info->State = MEM_COMMIT;
-   Info->Protect = Region->Protect;
-   if (MemoryArea->Data.SectionData.Section->AllocationAttributes & SEC_IMAGE)
+
+   Section = MemoryArea->Data.SectionData.Section;
+   if (Section->AllocationAttributes & SEC_IMAGE)
    {
+      Segment = MemoryArea->Data.SectionData.Segment;
+      Info->AllocationBase = (PBYTE)MemoryArea->StartingAddress - Segment->VirtualAddress;
       Info->Type = MEM_IMAGE;
    }
    else
    {
+      Info->AllocationBase = MemoryArea->StartingAddress;
       Info->Type = MEM_MAPPED;
    }
+   Info->BaseAddress = RegionBaseAddress;
+   Info->AllocationProtect = MemoryArea->Attributes;
+   Info->RegionSize = PAGE_ROUND_UP((ULONG_PTR)MemoryArea->EndingAddress -
+                                    (ULONG_PTR)MemoryArea->StartingAddress);
+   Info->State = MEM_COMMIT;
+   Info->Protect = Region->Protect;
 
    *ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
    return(STATUS_SUCCESS);
 }
 
 VOID
+NTAPI
 MmpFreePageFileSegment(PMM_SECTION_SEGMENT Segment)
 {
    ULONG Length;
    ULONG Offset;
    ULONG Entry;
    ULONG SavedSwapEntry;
-   PHYSICAL_ADDRESS Page;
+   PFN_TYPE Page;
 
-   Page.u.HighPart = 0;
+   Page = 0;
 
    Length = PAGE_ROUND_UP(Segment->Length);
    for (Offset = 0; Offset < Length; Offset += PAGE_SIZE)
@@ -2068,7 +2008,7 @@ MmpFreePageFileSegment(PMM_SECTION_SEGMENT Segment)
          }
          else
          {
-            Page.u.LowPart = PAGE_FROM_SSE(Entry);
+            Page = PFN_FROM_SSE(Entry);
             SavedSwapEntry = MmGetSavedSwapEntryPage(Page);
             if (SavedSwapEntry != 0)
             {
@@ -2095,17 +2035,26 @@ MmpDeleteSection(PVOID ObjectBody)
       ULONG RefCount;
       PMM_SECTION_SEGMENT SectionSegments;
 
+      /*
+       * NOTE: Section->ImageSection can be NULL for short time
+       * during the section creating. If we fail for some reason
+       * until the image section is properly initialized we shouldn't
+       * process further here.
+       */
+      if (Section->ImageSection == NULL)
+         return;
+
       SectionSegments = Section->ImageSection->Segments;
       NrSegments = Section->ImageSection->NrSegments;
 
       for (i = 0; i < NrSegments; i++)
       {
-         if (SectionSegments[i].Characteristics & IMAGE_SECTION_CHAR_SHARED)
+         if (SectionSegments[i].Characteristics & IMAGE_SCN_MEM_SHARED)
          {
             MmLockSectionSegment(&SectionSegments[i]);
          }
-         RefCount = InterlockedDecrement((LONG *)&SectionSegments[i].ReferenceCount);
-         if (SectionSegments[i].Characteristics & IMAGE_SECTION_CHAR_SHARED)
+         RefCount = InterlockedDecrementUL(&SectionSegments[i].ReferenceCount);
+         if (SectionSegments[i].Characteristics & IMAGE_SCN_MEM_SHARED)
          {
             if (RefCount == 0)
             {
@@ -2117,6 +2066,13 @@ MmpDeleteSection(PVOID ObjectBody)
    }
    else
    {
+      /*
+       * NOTE: Section->Segment can be NULL for short time
+       * during the section creating.
+       */
+      if (Section->Segment == NULL)
+         return;
+
       if (Section->Segment->Flags & MM_PAGEFILE_SEGMENT)
       {
          MmpFreePageFileSegment(Section->Segment);
@@ -2126,7 +2082,7 @@ MmpDeleteSection(PVOID ObjectBody)
       }
       else
       {
-         InterlockedDecrement((LONG *)&Section->Segment->ReferenceCount);
+         InterlockedDecrementUL(&Section->Segment->ReferenceCount);
       }
    }
    if (Section->FileObject != NULL)
@@ -2145,35 +2101,15 @@ MmpCloseSection(PVOID ObjectBody,
           ObjectBody, HandleCount, ObGetObjectPointerCount(ObjectBody));
 }
 
-NTSTATUS STDCALL
-MmpCreateSection(PVOID ObjectBody,
-                 PVOID Parent,
-                 PWSTR RemainingPath,
-                 POBJECT_ATTRIBUTES ObjectAttributes)
-{
-   DPRINT("MmpCreateSection(ObjectBody %x, Parent %x, RemainingPath %S)\n",
-          ObjectBody, Parent, RemainingPath);
-
-   if (RemainingPath == NULL)
-   {
-      return(STATUS_SUCCESS);
-   }
-
-   if (wcschr(RemainingPath+1, L'\\') != NULL)
-   {
-      return(STATUS_UNSUCCESSFUL);
-   }
-   return(STATUS_SUCCESS);
-}
-
-NTSTATUS INIT_FUNCTION
+NTSTATUS
+INIT_FUNCTION
+NTAPI
 MmCreatePhysicalMemorySection(VOID)
 {
-   HANDLE PhysSectionH;
    PSECTION_OBJECT PhysSection;
    NTSTATUS Status;
    OBJECT_ATTRIBUTES Obj;
-   UNICODE_STRING Name = ROS_STRING_INITIALIZER(L"\\Device\\PhysicalMemory");
+   UNICODE_STRING Name = RTL_CONSTANT_STRING(L"\\Device\\PhysicalMemory");
    LARGE_INTEGER SectionSize;
 
    /*
@@ -2182,76 +2118,66 @@ MmCreatePhysicalMemorySection(VOID)
    SectionSize.QuadPart = 0xFFFFFFFF;
    InitializeObjectAttributes(&Obj,
                               &Name,
-                              0,
+                              OBJ_PERMANENT,
                               NULL,
                               NULL);
-   Status = NtCreateSection(&PhysSectionH,
+   Status = MmCreateSection(&PhysSection,
                             SECTION_ALL_ACCESS,
                             &Obj,
                             &SectionSize,
                             PAGE_EXECUTE_READWRITE,
                             0,
+                            NULL,
                             NULL);
    if (!NT_SUCCESS(Status))
    {
       DbgPrint("Failed to create PhysicalMemory section\n");
       KEBUGCHECK(0);
    }
-   Status = ObReferenceObjectByHandle(PhysSectionH,
-                                      SECTION_ALL_ACCESS,
-                                      NULL,
-                                      KernelMode,
-                                      (PVOID*)&PhysSection,
-                                      NULL);
+   Status = ObInsertObject(PhysSection,
+                           NULL,
+                           SECTION_ALL_ACCESS,
+                           0,
+                           NULL,
+                           NULL);
    if (!NT_SUCCESS(Status))
    {
-      DbgPrint("Failed to reference PhysicalMemory section\n");
-      KEBUGCHECK(0);
+      ObDereferenceObject(PhysSection);
    }
    PhysSection->AllocationAttributes |= SEC_PHYSICALMEMORY;
-   ObDereferenceObject((PVOID)PhysSection);
+   PhysSection->Segment->Flags &= ~MM_PAGEFILE_SEGMENT;
 
    return(STATUS_SUCCESS);
 }
 
-NTSTATUS INIT_FUNCTION
+NTSTATUS
+INIT_FUNCTION
+NTAPI
 MmInitSectionImplementation(VOID)
 {
-   MmSectionObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
-
-   RtlRosInitUnicodeStringFromLiteral(&MmSectionObjectType->TypeName, L"Section");
-
-   MmSectionObjectType->Tag = TAG('S', 'E', 'C', 'T');
-   MmSectionObjectType->TotalObjects = 0;
-   MmSectionObjectType->TotalHandles = 0;
-   MmSectionObjectType->MaxObjects = ULONG_MAX;
-   MmSectionObjectType->MaxHandles = ULONG_MAX;
-   MmSectionObjectType->PagedPoolCharge = 0;
-   MmSectionObjectType->NonpagedPoolCharge = sizeof(SECTION_OBJECT);
-   MmSectionObjectType->Mapping = &MmpSectionMapping;
-   MmSectionObjectType->Dump = NULL;
-   MmSectionObjectType->Open = NULL;
-   MmSectionObjectType->Close = MmpCloseSection;
-   MmSectionObjectType->Delete = MmpDeleteSection;
-   MmSectionObjectType->Parse = NULL;
-   MmSectionObjectType->Security = NULL;
-   MmSectionObjectType->QueryName = NULL;
-   MmSectionObjectType->OkayToClose = NULL;
-   MmSectionObjectType->Create = MmpCreateSection;
-   MmSectionObjectType->DuplicationNotify = NULL;
-
-   /*
-    * NOTE: Do not register the section object type here because
-    * the object manager it not initialized yet!
-    * The section object type will be created in ObInit().
-    */
-   ObpCreateTypeObject(MmSectionObjectType);
+   OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
+   UNICODE_STRING Name;
+
+   DPRINT("Creating Section Object Type\n");
+  
+   /* Initialize the Section object type  */
+   RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
+   RtlInitUnicodeString(&Name, L"Section");
+   ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
+   ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(SECTION_OBJECT);
+   ObjectTypeInitializer.PoolType = PagedPool;
+   ObjectTypeInitializer.UseDefaultObject = TRUE;
+   ObjectTypeInitializer.GenericMapping = MmpSectionMapping;
+   ObjectTypeInitializer.DeleteProcedure = MmpDeleteSection;
+   ObjectTypeInitializer.CloseProcedure = MmpCloseSection;
+   ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &MmSectionObjectType);
 
    return(STATUS_SUCCESS);
 }
 
 NTSTATUS
-MmCreatePageFileSection(PHANDLE SectionHandle,
+NTAPI
+MmCreatePageFileSection(PSECTION_OBJECT *SectionObject,
                         ACCESS_MASK DesiredAccess,
                         POBJECT_ATTRIBUTES ObjectAttributes,
                         PLARGE_INTEGER UMaximumSize,
@@ -2272,15 +2198,6 @@ MmCreatePageFileSection(PHANDLE SectionHandle,
    }
    MaximumSize = *UMaximumSize;
 
-   /*
-    * Check the protection
-    */
-   if ((SectionPageProtection & PAGE_FLAGS_VALID_FROM_USER_MODE) !=
-         SectionPageProtection)
-   {
-      return(STATUS_INVALID_PAGE_PROTECTION);
-   }
-
    /*
     * Create the section
     */
@@ -2292,21 +2209,9 @@ MmCreatePageFileSection(PHANDLE SectionHandle,
                            sizeof(SECTION_OBJECT),
                            0,
                            0,
-                           (PVOID*)&Section);
-   if (!NT_SUCCESS(Status))
-   {
-      return(Status);
-   }
-
-   Status = ObInsertObject ((PVOID)Section,
-                            NULL,
-                            DesiredAccess,
-                            0,
-                            NULL,
-                            SectionHandle);
+                           (PVOID*)(PVOID)&Section);
    if (!NT_SUCCESS(Status))
    {
-      ObDereferenceObject(Section);
       return(Status);
    }
 
@@ -2315,15 +2220,13 @@ MmCreatePageFileSection(PHANDLE SectionHandle,
     */
    Section->SectionPageProtection = SectionPageProtection;
    Section->AllocationAttributes = AllocationAttributes;
-   InitializeListHead(&Section->ViewListHead);
-   KeInitializeSpinLock(&Section->ViewListLock);
+   Section->Segment = NULL;
    Section->FileObject = NULL;
    Section->MaximumSize = MaximumSize;
    Segment = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_SECTION_SEGMENT),
                                    TAG_MM_SECTION_SEGMENT);
    if (Segment == NULL)
    {
-      ZwClose(*SectionHandle);
       ObDereferenceObject(Section);
       return(STATUS_NO_MEMORY);
    }
@@ -2332,7 +2235,6 @@ MmCreatePageFileSection(PHANDLE SectionHandle,
    ExInitializeFastMutex(&Segment->Lock);
    Segment->FileOffset = 0;
    Segment->Protection = SectionPageProtection;
-   Segment->Attributes = AllocationAttributes;
    Segment->RawLength = MaximumSize.u.LowPart;
    Segment->Length = PAGE_ROUND_UP(MaximumSize.u.LowPart);
    Segment->Flags = MM_PAGEFILE_SEGMENT;
@@ -2340,13 +2242,14 @@ MmCreatePageFileSection(PHANDLE SectionHandle,
    RtlZeroMemory(&Segment->PageDirectory, sizeof(SECTION_PAGE_DIRECTORY));
    Segment->VirtualAddress = 0;
    Segment->Characteristics = 0;
-   ObDereferenceObject(Section);
+   *SectionObject = Section;
    return(STATUS_SUCCESS);
 }
 
 
 NTSTATUS
-MmCreateDataFileSection(PHANDLE SectionHandle,
+NTAPI
+MmCreateDataFileSection(PSECTION_OBJECT *SectionObject,
                         ACCESS_MASK DesiredAccess,
                         POBJECT_ATTRIBUTES ObjectAttributes,
                         PLARGE_INTEGER UMaximumSize,
@@ -2366,15 +2269,8 @@ MmCreateDataFileSection(PHANDLE SectionHandle,
    IO_STATUS_BLOCK Iosb;
    LARGE_INTEGER Offset;
    CHAR Buffer;
+   FILE_STANDARD_INFORMATION FileInfo;
 
-   /*
-    * Check the protection
-    */
-   if ((SectionPageProtection & PAGE_FLAGS_VALID_FROM_USER_MODE) !=
-         SectionPageProtection)
-   {
-      return(STATUS_INVALID_PAGE_PROTECTION);
-   }
    /*
     * Create the section
     */
@@ -2386,31 +2282,17 @@ MmCreateDataFileSection(PHANDLE SectionHandle,
                            sizeof(SECTION_OBJECT),
                            0,
                            0,
-                           (PVOID*)&Section);
-   if (!NT_SUCCESS(Status))
-   {
-      return(Status);
-   }
-
-   Status = ObInsertObject ((PVOID)Section,
-                            NULL,
-                            DesiredAccess,
-                            0,
-                            NULL,
-                            SectionHandle);
+                           (PVOID*)(PVOID)&Section);
    if (!NT_SUCCESS(Status))
    {
-      ObDereferenceObject(Section);
       return(Status);
    }
-
    /*
     * Initialize it
     */
    Section->SectionPageProtection = SectionPageProtection;
    Section->AllocationAttributes = AllocationAttributes;
-   InitializeListHead(&Section->ViewListHead);
-   KeInitializeSpinLock(&Section->ViewListLock);
+   Section->Segment = NULL;
 
    /*
     * Check file access required
@@ -2432,25 +2314,30 @@ MmCreateDataFileSection(PHANDLE SectionHandle,
                                       FileAccess,
                                       IoFileObjectType,
                                       UserMode,
-                                      (PVOID*)&FileObject,
+                                      (PVOID*)(PVOID)&FileObject,
                                       NULL);
    if (!NT_SUCCESS(Status))
    {
-      ZwClose(*SectionHandle);
       ObDereferenceObject(Section);
       return(Status);
    }
 
    /*
-    * We can't do memory mappings if the file system doesn't support the
-    * standard FCB
+    * FIXME: This is propably not entirely correct. We can't look into
+    * the standard FCB header because it might not be initialized yet
+    * (as in case of the EXT2FS driver by Manoj Paul Joseph where the
+    * standard file information is filled on first request).
     */
-   if (!(FileObject->Flags & FO_FCB_IS_VALID))
+   Status = IoQueryFileInformation(FileObject,
+                                   FileStandardInformation,
+                                   sizeof(FILE_STANDARD_INFORMATION),
+                                   &FileInfo,
+                                   &Iosb.Information);
+   if (!NT_SUCCESS(Status))
    {
-      ZwClose(*SectionHandle);
       ObDereferenceObject(Section);
       ObDereferenceObject(FileObject);
-      return(STATUS_INVALID_FILE_FOR_SECTION);
+      return Status;
    }
 
    /*
@@ -2463,21 +2350,24 @@ MmCreateDataFileSection(PHANDLE SectionHandle,
    }
    else
    {
-      MaximumSize =
-         ((PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext)->FileSize;
+      MaximumSize = FileInfo.EndOfFile;
+      /* Mapping zero-sized files isn't allowed. */
+      if (MaximumSize.QuadPart == 0)
+      {
+         ObDereferenceObject(Section);
+         ObDereferenceObject(FileObject);
+         return STATUS_FILE_INVALID;
+      }
    }
 
-   if (MaximumSize.QuadPart >
-         ((PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext)->FileSize.QuadPart)
+   if (MaximumSize.QuadPart > FileInfo.EndOfFile.QuadPart)
    {
-      Status = NtSetInformationFile(FileHandle,
-                                    &Iosb,
-                                    &MaximumSize,
-                                    sizeof(LARGE_INTEGER),
-                                    FileAllocationInformation);
+      Status = IoSetInformation(FileObject,
+                                FileAllocationInformation,
+                                sizeof(LARGE_INTEGER),
+                                &MaximumSize);
       if (!NT_SUCCESS(Status))
       {
-         ZwClose(*SectionHandle);
          ObDereferenceObject(Section);
          ObDereferenceObject(FileObject);
          return(STATUS_SECTION_NOT_EXTENDED);
@@ -2504,7 +2394,6 @@ MmCreateDataFileSection(PHANDLE SectionHandle,
                           0);
       if (!NT_SUCCESS(Status) && (Status != STATUS_END_OF_FILE))
       {
-         ZwClose(*SectionHandle);
          ObDereferenceObject(Section);
          ObDereferenceObject(FileObject);
          return(Status);
@@ -2513,7 +2402,6 @@ MmCreateDataFileSection(PHANDLE SectionHandle,
             FileObject->SectionObjectPointer->SharedCacheMap == NULL)
       {
          /* FIXME: handle this situation */
-         ZwClose(*SectionHandle);
          ObDereferenceObject(Section);
          ObDereferenceObject(FileObject);
          return STATUS_INVALID_PARAMETER;
@@ -2526,7 +2414,6 @@ MmCreateDataFileSection(PHANDLE SectionHandle,
    Status = MmspWaitForFileLock(FileObject);
    if (Status != STATUS_SUCCESS)
    {
-      ZwClose(*SectionHandle);
       ObDereferenceObject(Section);
       ObDereferenceObject(FileObject);
       return(Status);
@@ -2543,7 +2430,6 @@ MmCreateDataFileSection(PHANDLE SectionHandle,
       if (Segment == NULL)
       {
          KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
-         ZwClose(*SectionHandle);
          ObDereferenceObject(Section);
          ObDereferenceObject(FileObject);
          return(STATUS_NO_MEMORY);
@@ -2559,7 +2445,6 @@ MmCreateDataFileSection(PHANDLE SectionHandle,
 
       Segment->FileOffset = 0;
       Segment->Protection = SectionPageProtection;
-      Segment->Attributes = 0;
       Segment->Flags = MM_DATAFILE_SEGMENT;
       Segment->Characteristics = 0;
       Segment->WriteCopy = FALSE;
@@ -2572,7 +2457,7 @@ MmCreateDataFileSection(PHANDLE SectionHandle,
          Segment->RawLength = MaximumSize.u.LowPart;
          Segment->Length = PAGE_ROUND_UP(Segment->RawLength);
       }
-      Segment->VirtualAddress = NULL;
+      Segment->VirtualAddress = 0;
       RtlZeroMemory(&Segment->PageDirectory, sizeof(SECTION_PAGE_DIRECTORY));
    }
    else
@@ -2585,7 +2470,7 @@ MmCreateDataFileSection(PHANDLE SectionHandle,
          (PMM_SECTION_SEGMENT)FileObject->SectionObjectPointer->
          DataSectionObject;
       Section->Segment = Segment;
-      InterlockedIncrement((PLONG)&Segment->ReferenceCount);
+      InterlockedIncrementUL(&Segment->ReferenceCount);
       MmLockSectionSegment(Segment);
 
       if (MaximumSize.u.LowPart > Segment->RawLength &&
@@ -2600,448 +2485,815 @@ MmCreateDataFileSection(PHANDLE SectionHandle,
    Section->MaximumSize = MaximumSize;
    CcRosReferenceCache(FileObject);
    KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
-   ObDereferenceObject(Section);
+   *SectionObject = Section;
    return(STATUS_SUCCESS);
 }
 
-static ULONG SectionCharacteristicsToProtect[16] =
-   {
-      PAGE_NOACCESS,               // 0 = NONE
-      PAGE_NOACCESS,               // 1 = SHARED
-      PAGE_EXECUTE,                // 2 = EXECUTABLE
-      PAGE_EXECUTE,                // 3 = EXECUTABLE, SHARED
-      PAGE_READONLY,               // 4 = READABLE
-      PAGE_READONLY,               // 5 = READABLE, SHARED
-      PAGE_EXECUTE_READ,           // 6 = READABLE, EXECUTABLE
-      PAGE_EXECUTE_READ,           // 7 = READABLE, EXECUTABLE, SHARED
-      PAGE_READWRITE,              // 8 = WRITABLE
-      PAGE_READWRITE,              // 9 = WRITABLE, SHARED
-      PAGE_EXECUTE_READWRITE,      // 10 = WRITABLE, EXECUTABLE
-      PAGE_EXECUTE_READWRITE,      // 11 = WRITABLE, EXECUTABLE, SHARED
-      PAGE_READWRITE,              // 12 = WRITABLE, READABLE
-      PAGE_READWRITE,              // 13 = WRITABLE, READABLE, SHARED
-      PAGE_EXECUTE_READWRITE,      // 14 = WRITABLE, READABLE, EXECUTABLE,
-      PAGE_EXECUTE_READWRITE,      // 15 = WRITABLE, READABLE, EXECUTABLE, SHARED
-   };
+/*
+ TODO: not that great (declaring loaders statically, having to declare all of
+ them, having to keep them extern, etc.), will fix in the future
+*/
+extern NTSTATUS NTAPI PeFmtCreateSection
+(
+ IN CONST VOID * FileHeader,
+ IN SIZE_T FileHeaderSize,
+ IN PVOID File,
+ OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
+ OUT PULONG Flags,
+ IN PEXEFMT_CB_READ_FILE ReadFileCb,
+ IN PEXEFMT_CB_ALLOCATE_SEGMENTS AllocateSegmentsCb
+);
+
+extern NTSTATUS NTAPI ElfFmtCreateSection
+(
+ IN CONST VOID * FileHeader,
+ IN SIZE_T FileHeaderSize,
+ IN PVOID File,
+ OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
+ OUT PULONG Flags,
+ IN PEXEFMT_CB_READ_FILE ReadFileCb,
+ IN PEXEFMT_CB_ALLOCATE_SEGMENTS AllocateSegmentsCb
+);
+
+/* TODO: this is a standard DDK/PSDK macro */
+#ifndef RTL_NUMBER_OF
+#define RTL_NUMBER_OF(ARR_) (sizeof(ARR_) / sizeof((ARR_)[0]))
+#endif
+
+static PEXEFMT_LOADER ExeFmtpLoaders[] =
+{
+ PeFmtCreateSection,
+ ElfFmtCreateSection
+};
+
+static
+PMM_SECTION_SEGMENT
+NTAPI
+ExeFmtpAllocateSegments(IN ULONG NrSegments)
+{
+ SIZE_T SizeOfSegments;
+ PMM_SECTION_SEGMENT Segments;
+
+ /* TODO: check for integer overflow */
+ SizeOfSegments = sizeof(MM_SECTION_SEGMENT) * NrSegments;
 
+ Segments = ExAllocatePoolWithTag(NonPagedPool,
+                                  SizeOfSegments,
+                                  TAG_MM_SECTION_SEGMENT);
+
+ if(Segments)
+  RtlZeroMemory(Segments, SizeOfSegments);
+
+ return Segments;
+}
+
+static
 NTSTATUS
-MmCreateImageSection(PHANDLE SectionHandle,
-                     ACCESS_MASK DesiredAccess,
-                     POBJECT_ATTRIBUTES ObjectAttributes,
-                     PLARGE_INTEGER UMaximumSize,
-                     ULONG SectionPageProtection,
-                     ULONG AllocationAttributes,
-                     HANDLE FileHandle)
+NTAPI
+ExeFmtpReadFile(IN PVOID File,
+                IN PLARGE_INTEGER Offset,
+                IN ULONG Length,
+                OUT PVOID * Data,
+                OUT PVOID * AllocBase,
+                OUT PULONG ReadSize)
 {
-   PSECTION_OBJECT Section;
    NTSTATUS Status;
-   PFILE_OBJECT FileObject;
-   IMAGE_DOS_HEADER DosHeader;
-   IO_STATUS_BLOCK Iosb;
-   LARGE_INTEGER Offset;
-   IMAGE_NT_HEADERS PEHeader;
-   PMM_SECTION_SEGMENT SectionSegments;
-   ULONG NrSegments;
-   PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
-   ULONG i;
-   ULONG Size;
-   ULONG Characteristics;
-   ULONG FileAccess = 0;
-   /*
-    * Check the protection
-    */
-   if ((SectionPageProtection & PAGE_FLAGS_VALID_FROM_USER_MODE) !=
-         SectionPageProtection)
-   {
-      return(STATUS_INVALID_PAGE_PROTECTION);
-   }
+   LARGE_INTEGER FileOffset;
+   ULONG AdjustOffset;
+   ULONG OffsetAdjustment;
+   ULONG BufferSize;
+   ULONG UsedSize;
+   PVOID Buffer;
 
-   /*
-    * Specifying a maximum size is meaningless for an image section
-    */
-   if (UMaximumSize != NULL)
+   ASSERT_IRQL_LESS(DISPATCH_LEVEL);
+
+   if(Length == 0)
    {
-      return(STATUS_INVALID_PARAMETER_4);
+      KEBUGCHECK(STATUS_INVALID_PARAMETER_4);
    }
 
-   /*
-    * Reference the file handle
-    */
-   Status = ObReferenceObjectByHandle(FileHandle,
-                                      FileAccess,
-                                      IoFileObjectType,
-                                      UserMode,
-                                      (PVOID*)&FileObject,
-                                      NULL);
-   if (!NT_SUCCESS(Status))
+   FileOffset = *Offset;
+
+   /* Negative/special offset: it cannot be used in this context */
+   if(FileOffset.u.HighPart < 0)
    {
-      return Status;
+      KEBUGCHECK(STATUS_INVALID_PARAMETER_5);
    }
 
+   AdjustOffset = PAGE_ROUND_DOWN(FileOffset.u.LowPart);
+   OffsetAdjustment = FileOffset.u.LowPart - AdjustOffset;
+   FileOffset.u.LowPart = AdjustOffset;
+
+   BufferSize = Length + OffsetAdjustment;
+   BufferSize = PAGE_ROUND_UP(BufferSize);
+
    /*
-    * Initialized caching for this file object if previously caching
-    * was initialized for the same on disk file
+    * It's ok to use paged pool, because this is a temporary buffer only used in
+    * the loading of executables. The assumption is that MmCreateSection is
+    * always called at low IRQLs and that these buffers don't survive a brief
+    * initialization phase
     */
-   Status = CcTryToInitializeFileCache(FileObject);
-
-   if (!NT_SUCCESS(Status) || FileObject->SectionObjectPointer->ImageSectionObject == NULL)
+   Buffer = ExAllocatePoolWithTag(PagedPool,
+                                  BufferSize,
+                                  TAG('M', 'm', 'X', 'r'));
+
+   UsedSize = 0;
+
+#if 0
+   Status = MmspPageRead(File,
+                         Buffer,
+                         BufferSize,
+                         &FileOffset,
+                         &UsedSize);
+#else
+/*
+ * FIXME: if we don't use ZwReadFile, caching is not enabled for the file and
+ * nothing will work. But using ZwReadFile is wrong, and using its side effects
+ * to initialize internal state is even worse. Our cache manager is in need of
+ * professional help
+ */
    {
-      PIMAGE_SECTION_HEADER ImageSections;
-      /*
-       * Read the dos header and check the DOS signature
-       */
-      Offset.QuadPart = 0;
-      Status = ZwReadFile(FileHandle,
+      IO_STATUS_BLOCK Iosb;
+
+      Status = ZwReadFile(File,
                           NULL,
                           NULL,
                           NULL,
                           &Iosb,
-                          &DosHeader,
-                          sizeof(DosHeader),
-                          &Offset,
+                          Buffer,
+                          BufferSize,
+                          &FileOffset,
                           NULL);
-      if (!NT_SUCCESS(Status))
-      {
-         ObDereferenceObject(FileObject);
-         return(Status);
-      }
 
-      /*
-       * Check the DOS signature
-       */
-      if (Iosb.Information != sizeof(DosHeader) ||
-            DosHeader.e_magic != IMAGE_DOS_SIGNATURE)
+      if(NT_SUCCESS(Status))
       {
-         ObDereferenceObject(FileObject);
-         return(STATUS_INVALID_IMAGE_FORMAT);
+         UsedSize = Iosb.Information;
       }
+   }
+#endif
 
-      /*
-       * Read the PE header
-       */
-      Offset.QuadPart = DosHeader.e_lfanew;
-      Status = ZwReadFile(FileHandle,
-                          NULL,
-                          NULL,
-                          NULL,
-                          &Iosb,
-                          &PEHeader,
-                          sizeof(PEHeader),
-                          &Offset,
-                          NULL);
-      if (!NT_SUCCESS(Status))
-      {
-         ObDereferenceObject(FileObject);
-         return(Status);
-      }
+   if(NT_SUCCESS(Status) && UsedSize < OffsetAdjustment)
+   {
+      Status = STATUS_IN_PAGE_ERROR;
+      ASSERT(!NT_SUCCESS(Status));
+   }
 
-      /*
-       * Check the signature
-       */
-      if (Iosb.Information != sizeof(PEHeader) ||
-            PEHeader.Signature != IMAGE_NT_SIGNATURE)
-      {
-         ObDereferenceObject(FileObject);
-         return(STATUS_INVALID_IMAGE_FORMAT);
-      }
+   if(NT_SUCCESS(Status))
+   {
+      *Data = (PVOID)((ULONG_PTR)Buffer + OffsetAdjustment);
+      *AllocBase = Buffer;
+      *ReadSize = UsedSize - OffsetAdjustment;
+   }
+   else
+   {
+      ExFreePool(Buffer);
+   }
 
-      /*
-       * Read in the section headers
-       */
-      Offset.QuadPart = DosHeader.e_lfanew + sizeof(PEHeader);
-      ImageSections = ExAllocatePool(NonPagedPool,
-                                     PEHeader.FileHeader.NumberOfSections *
-                                     sizeof(IMAGE_SECTION_HEADER));
-      if (ImageSections == NULL)
-      {
-         ObDereferenceObject(FileObject);
-         return(STATUS_NO_MEMORY);
-      }
+   return Status;
+}
 
-      Status = ZwReadFile(FileHandle,
-                          NULL,
-                          NULL,
-                          NULL,
-                          &Iosb,
-                          ImageSections,
-                          PEHeader.FileHeader.NumberOfSections *
-                          sizeof(IMAGE_SECTION_HEADER),
-                          &Offset,
-                          0);
-      if (!NT_SUCCESS(Status))
-      {
-         ObDereferenceObject(FileObject);
-         ExFreePool(ImageSections);
-         return(Status);
-      }
-      if (Iosb.Information != (PEHeader.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER)))
-      {
-         ObDereferenceObject(FileObject);
-         ExFreePool(ImageSections);
-         return(STATUS_INVALID_IMAGE_FORMAT);
-      }
+#ifdef NASSERT
+# define MmspAssertSegmentsSorted(OBJ_) ((void)0)
+# define MmspAssertSegmentsNoOverlap(OBJ_) ((void)0)
+# define MmspAssertSegmentsPageAligned(OBJ_) ((void)0)
+#else
+static
+VOID
+NTAPI
+MmspAssertSegmentsSorted(IN PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
+{
+   ULONG i;
 
-      /*
-       * Create the section
-       */
-      Status = ObCreateObject (ExGetPreviousMode(),
-                               MmSectionObjectType,
-                               ObjectAttributes,
-                               ExGetPreviousMode(),
-                               NULL,
-                               sizeof(SECTION_OBJECT),
-                               0,
-                               0,
-                               (PVOID*)&Section);
-      if (!NT_SUCCESS(Status))
-      {
-         ObDereferenceObject(FileObject);
-         ExFreePool(ImageSections);
-         return(Status);
-      }
+   for( i = 1; i < ImageSectionObject->NrSegments; ++ i )
+   {
+      ASSERT(ImageSectionObject->Segments[i].VirtualAddress >=
+             ImageSectionObject->Segments[i - 1].VirtualAddress);
+   }
+}
 
-      Status = ObInsertObject ((PVOID)Section,
-                               NULL,
-                               DesiredAccess,
-                               0,
-                               NULL,
-                               SectionHandle);
-      if (!NT_SUCCESS(Status))
-      {
-         ObDereferenceObject(Section);
-         ObDereferenceObject(FileObject);
-         ExFreePool(ImageSections);
-         return(Status);
-      }
+static
+VOID
+NTAPI
+MmspAssertSegmentsNoOverlap(IN PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
+{
+   ULONG i;
 
-      /*
-       * Initialize it
-       */
-      Section->SectionPageProtection = SectionPageProtection;
-      Section->AllocationAttributes = AllocationAttributes;
-      InitializeListHead(&Section->ViewListHead);
-      KeInitializeSpinLock(&Section->ViewListLock);
+   MmspAssertSegmentsSorted(ImageSectionObject);
 
-      /*
-              * Check file access required
-              */
-      if (SectionPageProtection & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE))
-      {
-         FileAccess = FILE_READ_DATA | FILE_WRITE_DATA;
-      }
-      else
+   for( i = 0; i < ImageSectionObject->NrSegments; ++ i )
+   {
+      ASSERT(ImageSectionObject->Segments[i].Length > 0);
+
+      if(i > 0)
       {
-         FileAccess = FILE_READ_DATA;
+         ASSERT(ImageSectionObject->Segments[i].VirtualAddress >=
+                (ImageSectionObject->Segments[i - 1].VirtualAddress +
+                 ImageSectionObject->Segments[i - 1].Length));
       }
+   }
+}
 
-      /*
-       * We can't do memory mappings if the file system doesn't support the
-       * standard FCB
-       */
-      if (!(FileObject->Flags & FO_FCB_IS_VALID))
+static
+VOID
+NTAPI
+MmspAssertSegmentsPageAligned(IN PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
+{
+   ULONG i;
+
+   for( i = 0; i < ImageSectionObject->NrSegments; ++ i )
+   {
+      ASSERT((ImageSectionObject->Segments[i].VirtualAddress % PAGE_SIZE) == 0);
+      ASSERT((ImageSectionObject->Segments[i].Length % PAGE_SIZE) == 0);
+   }
+}
+#endif
+
+static
+int
+__cdecl
+MmspCompareSegments(const void * x,
+                    const void * y)
+{
+   PMM_SECTION_SEGMENT Segment1 = (PMM_SECTION_SEGMENT)x;
+   PMM_SECTION_SEGMENT Segment2 = (PMM_SECTION_SEGMENT)y;
+
+   return
+      (Segment1->VirtualAddress - Segment2->VirtualAddress) >>
+      ((sizeof(ULONG_PTR) - sizeof(int)) * 8);
+}
+
+/*
+ * Ensures an image section's segments are sorted in memory
+ */
+static
+VOID
+NTAPI
+MmspSortSegments(IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
+                 IN ULONG Flags)
+{
+   if (Flags & EXEFMT_LOAD_ASSUME_SEGMENTS_SORTED)
+   {
+      MmspAssertSegmentsSorted(ImageSectionObject);
+   }
+   else
+   {
+      qsort(ImageSectionObject->Segments,
+            ImageSectionObject->NrSegments,
+            sizeof(ImageSectionObject->Segments[0]),
+            MmspCompareSegments);
+   }
+}
+
+
+/*
+ * Ensures an image section's segments don't overlap in memory and don't have
+ * gaps and don't have a null size. We let them map to overlapping file regions,
+ * though - that's not necessarily an error
+ */
+static
+BOOLEAN
+NTAPI
+MmspCheckSegmentBounds
+(
+ IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
+ IN ULONG Flags
+)
+{
+   ULONG i;
+
+   if (Flags & EXEFMT_LOAD_ASSUME_SEGMENTS_NO_OVERLAP)
+   {
+      MmspAssertSegmentsNoOverlap(ImageSectionObject);
+      return TRUE;
+   }
+
+   ASSERT(ImageSectionObject->NrSegments >= 1);
+
+   for ( i = 0; i < ImageSectionObject->NrSegments; ++ i )
+   {
+      if(ImageSectionObject->Segments[i].Length == 0)
       {
-         ZwClose(*SectionHandle);
-         ObDereferenceObject(Section);
-         ObDereferenceObject(FileObject);
-         ExFreePool(ImageSections);
-         return(STATUS_INVALID_FILE_FOR_SECTION);
+         return FALSE;
       }
 
-      /*
-       * Lock the file
-       */
-      Status = MmspWaitForFileLock(FileObject);
-      if (Status != STATUS_SUCCESS)
+      if(i > 0)
       {
-         ZwClose(*SectionHandle);
-         ObDereferenceObject(Section);
-         ObDereferenceObject(FileObject);
-         ExFreePool(ImageSections);
-         return(Status);
+         /*
+          * TODO: relax the limitation on gaps. For example, gaps smaller than a
+          * page could be OK (Windows seems to be OK with them), and larger gaps
+          * could lead to image sections spanning several discontiguous regions
+          * (NtMapViewOfSection could then refuse to map them, and they could
+          * e.g. only be allowed as parameters to NtCreateProcess, like on UNIX)
+          */
+         if ((ImageSectionObject->Segments[i - 1].VirtualAddress +
+              ImageSectionObject->Segments[i - 1].Length) !=
+              ImageSectionObject->Segments[i].VirtualAddress)
+         {
+            return FALSE;
+         }
       }
+   }
 
+   return TRUE;
+}
+
+/*
+ * Merges and pads an image section's segments until they all are page-aligned
+ * and have a size that is a multiple of the page size
+ */
+static
+BOOLEAN
+NTAPI
+MmspPageAlignSegments
+(
+ IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
+ IN ULONG Flags
+)
+{
+   ULONG i;
+   ULONG LastSegment;
+   BOOLEAN Initialized;
+   PMM_SECTION_SEGMENT EffectiveSegment;
+
+   if (Flags & EXEFMT_LOAD_ASSUME_SEGMENTS_PAGE_ALIGNED)
+   {
+      MmspAssertSegmentsPageAligned(ImageSectionObject);
+      return TRUE;
+   }
+
+   Initialized = FALSE;
+   LastSegment = 0;
+   EffectiveSegment = &ImageSectionObject->Segments[LastSegment];
+
+   for ( i = 0; i < ImageSectionObject->NrSegments; ++ i )
+   {
       /*
-       * allocate the section segments to describe the mapping
+       * The first segment requires special handling
        */
-      NrSegments = PEHeader.FileHeader.NumberOfSections + 1;
-      Size = sizeof(MM_IMAGE_SECTION_OBJECT) + sizeof(MM_SECTION_SEGMENT) * NrSegments;
-      ImageSectionObject = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_MM_SECTION_SEGMENT);
-      if (ImageSectionObject == NULL)
+      if (i == 0)
       {
-         KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
-         ZwClose(*SectionHandle);
-         ObDereferenceObject(Section);
-         ObDereferenceObject(FileObject);
-         ExFreePool(ImageSections);
-         return(STATUS_NO_MEMORY);
-      }
-      Section->ImageSection = ImageSectionObject;
-      ImageSectionObject->NrSegments = NrSegments;
-      ImageSectionObject->ImageBase = (PVOID)PEHeader.OptionalHeader.ImageBase;
-      ImageSectionObject->EntryPoint = (PVOID)PEHeader.OptionalHeader.AddressOfEntryPoint;
-      ImageSectionObject->StackReserve = PEHeader.OptionalHeader.SizeOfStackReserve;
-      ImageSectionObject->StackCommit = PEHeader.OptionalHeader.SizeOfStackCommit;
-      ImageSectionObject->Subsystem = PEHeader.OptionalHeader.Subsystem;
-      ImageSectionObject->MinorSubsystemVersion = PEHeader.OptionalHeader.MinorSubsystemVersion;
-      ImageSectionObject->MajorSubsystemVersion = PEHeader.OptionalHeader.MajorSubsystemVersion;
-      ImageSectionObject->ImageCharacteristics = PEHeader.FileHeader.Characteristics;
-      ImageSectionObject->Machine = PEHeader.FileHeader.Machine;
-      ImageSectionObject->Executable = (PEHeader.OptionalHeader.SizeOfCode != 0);
+         ULONG_PTR VirtualAddress;
+         ULONG_PTR VirtualOffset;
 
-      SectionSegments = ImageSectionObject->Segments;
-      SectionSegments[0].FileOffset = 0;
-      SectionSegments[0].Characteristics = IMAGE_SECTION_CHAR_DATA;
-      SectionSegments[0].Protection = PAGE_READONLY;
-      SectionSegments[0].RawLength = PAGE_SIZE;
-      SectionSegments[0].Length = PAGE_SIZE;
-      SectionSegments[0].Flags = 0;
-      SectionSegments[0].ReferenceCount = 1;
-      SectionSegments[0].VirtualAddress = 0;
-      SectionSegments[0].WriteCopy = TRUE;
-      SectionSegments[0].Attributes = 0;
-      ExInitializeFastMutex(&SectionSegments[0].Lock);
-      RtlZeroMemory(&SectionSegments[0].PageDirectory, sizeof(SECTION_PAGE_DIRECTORY));
-      for (i = 1; i < NrSegments; i++)
-      {
-         SectionSegments[i].FileOffset = ImageSections[i-1].PointerToRawData;
-         SectionSegments[i].Characteristics = ImageSections[i-1].Characteristics;
+         VirtualAddress = EffectiveSegment->VirtualAddress;
 
-         /*
-          * Set up the protection and write copy variables.
-          */
-         Characteristics = ImageSections[i - 1].Characteristics;
-         if (Characteristics & (IMAGE_SECTION_CHAR_READABLE|IMAGE_SECTION_CHAR_WRITABLE|IMAGE_SECTION_CHAR_EXECUTABLE))
-         {
-            SectionSegments[i].Protection = SectionCharacteristicsToProtect[Characteristics >> 28];
-            SectionSegments[i].WriteCopy = !(Characteristics & IMAGE_SECTION_CHAR_SHARED);
-         }
-         else if (Characteristics & IMAGE_SECTION_CHAR_CODE)
-         {
-            SectionSegments[i].Protection = PAGE_EXECUTE_READ;
-            SectionSegments[i].WriteCopy = TRUE;
-         }
-         else if (Characteristics & IMAGE_SECTION_CHAR_DATA)
-         {
-            SectionSegments[i].Protection = PAGE_READWRITE;
-            SectionSegments[i].WriteCopy = TRUE;
-         }
-         else if (Characteristics & IMAGE_SECTION_CHAR_BSS)
-         {
-            SectionSegments[i].Protection = PAGE_READWRITE;
-            SectionSegments[i].WriteCopy = TRUE;
-         }
-         else
+         /* Round down the virtual address to the nearest page */
+         EffectiveSegment->VirtualAddress = PAGE_ROUND_DOWN(VirtualAddress);
+
+         /* Round up the virtual size to the nearest page */
+         EffectiveSegment->Length = PAGE_ROUND_UP(VirtualAddress + EffectiveSegment->Length) -
+                                    EffectiveSegment->VirtualAddress;
+
+         /* Adjust the raw address and size */
+         VirtualOffset = VirtualAddress - EffectiveSegment->VirtualAddress;
+
+         if (EffectiveSegment->FileOffset < VirtualOffset)
          {
-            SectionSegments[i].Protection = PAGE_NOACCESS;
-            SectionSegments[i].WriteCopy = TRUE;
+            return FALSE;
          }
 
          /*
-          * Set up the attributes.
+          * Garbage in, garbage out: unaligned base addresses make the file
+          * offset point in curious and odd places, but that's what we were
+          * asked for
           */
-         if (Characteristics & IMAGE_SECTION_CHAR_CODE)
-         {
-            SectionSegments[i].Attributes = 0;
-         }
-         else if (Characteristics & IMAGE_SECTION_CHAR_DATA)
+         EffectiveSegment->FileOffset -= VirtualOffset;
+         EffectiveSegment->RawLength += VirtualOffset;
+      }
+      else
+      {
+         PMM_SECTION_SEGMENT Segment = &ImageSectionObject->Segments[i];
+         ULONG_PTR EndOfEffectiveSegment;
+
+         EndOfEffectiveSegment = EffectiveSegment->VirtualAddress + EffectiveSegment->Length;
+         ASSERT((EndOfEffectiveSegment % PAGE_SIZE) == 0);
+
+         /*
+          * The current segment begins exactly where the current effective
+          * segment ended, therefore beginning a new effective segment
+          */
+         if (EndOfEffectiveSegment == Segment->VirtualAddress)
          {
-            SectionSegments[i].Attributes = 0;
+            LastSegment ++;
+            ASSERT(LastSegment <= i);
+            ASSERT(LastSegment < ImageSectionObject->NrSegments);
+
+            EffectiveSegment = &ImageSectionObject->Segments[LastSegment];
+
+            if (LastSegment != i)
+            {
+               /*
+                * Copy the current segment. If necessary, the effective segment
+                * will be expanded later
+                */
+               *EffectiveSegment = *Segment;
+            }
+
+            /*
+             * Page-align the virtual size. We know for sure the virtual address
+             * already is
+             */
+            ASSERT((EffectiveSegment->VirtualAddress % PAGE_SIZE) == 0);
+            EffectiveSegment->Length = PAGE_ROUND_UP(EffectiveSegment->Length);
          }
-         else if (Characteristics & IMAGE_SECTION_CHAR_BSS)
+         /*
+          * The current segment is still part of the current effective segment:
+          * extend the effective segment to reflect this
+          */
+         else if (EndOfEffectiveSegment > Segment->VirtualAddress)
          {
-            SectionSegments[i].Attributes = MM_SECTION_SEGMENT_BSS;
+            static const ULONG FlagsToProtection[16] =
+            {
+               PAGE_NOACCESS,
+               PAGE_READONLY,
+               PAGE_READWRITE,
+               PAGE_READWRITE,
+               PAGE_EXECUTE_READ,
+               PAGE_EXECUTE_READ,
+               PAGE_EXECUTE_READWRITE,
+               PAGE_EXECUTE_READWRITE,
+               PAGE_WRITECOPY,
+               PAGE_WRITECOPY,
+               PAGE_WRITECOPY,
+               PAGE_WRITECOPY,
+               PAGE_EXECUTE_WRITECOPY,
+               PAGE_EXECUTE_WRITECOPY,
+               PAGE_EXECUTE_WRITECOPY,
+               PAGE_EXECUTE_WRITECOPY
+            };
+
+            unsigned ProtectionFlags;
+
+            /*
+             * Extend the file size
+             */
+
+            /* Unaligned segments must be contiguous within the file */
+            if (Segment->FileOffset != (EffectiveSegment->FileOffset +
+                                        EffectiveSegment->RawLength))
+            {
+               return FALSE;
+            }
+
+            EffectiveSegment->RawLength += Segment->RawLength;
+
+            /*
+             * Extend the virtual size
+             */
+            ASSERT(PAGE_ROUND_UP(Segment->VirtualAddress + Segment->Length) >= EndOfEffectiveSegment);
+
+            EffectiveSegment->Length = PAGE_ROUND_UP(Segment->VirtualAddress + Segment->Length) -
+                                       EffectiveSegment->VirtualAddress;
+
+            /*
+             * Merge the protection
+             */
+            EffectiveSegment->Protection |= Segment->Protection;
+
+            /* Clean up redundance */
+            ProtectionFlags = 0;
+
+            if(EffectiveSegment->Protection & PAGE_IS_READABLE)
+               ProtectionFlags |= 1 << 0;
+
+            if(EffectiveSegment->Protection & PAGE_IS_WRITABLE)
+               ProtectionFlags |= 1 << 1;
+
+            if(EffectiveSegment->Protection & PAGE_IS_EXECUTABLE)
+               ProtectionFlags |= 1 << 2;
+
+            if(EffectiveSegment->Protection & PAGE_IS_WRITECOPY)
+               ProtectionFlags |= 1 << 3;
+
+            ASSERT(ProtectionFlags < 16);
+            EffectiveSegment->Protection = FlagsToProtection[ProtectionFlags];
+
+            /* If a segment was required to be shared and cannot, fail */
+            if(!(Segment->Protection & PAGE_IS_WRITECOPY) &&
+               EffectiveSegment->Protection & PAGE_IS_WRITECOPY)
+            {
+               return FALSE;
+            }
          }
+         /*
+          * We assume no holes between segments at this point
+          */
          else
          {
-            SectionSegments[i].Attributes = 0;
+            ASSERT(FALSE);
          }
-
-         SectionSegments[i].RawLength = ImageSections[i-1].SizeOfRawData;
-         SectionSegments[i].Length = ImageSections[i-1].Misc.VirtualSize;
-         SectionSegments[i].Flags = 0;
-         SectionSegments[i].ReferenceCount = 1;
-         SectionSegments[i].VirtualAddress = (PVOID)ImageSections[i-1].VirtualAddress;
-         ExInitializeFastMutex(&SectionSegments[i].Lock);
-         RtlZeroMemory(&SectionSegments[i].PageDirectory, sizeof(SECTION_PAGE_DIRECTORY));
       }
-      if (0 != InterlockedCompareExchange((PLONG)&FileObject->SectionObjectPointer->ImageSectionObject,
-                                          (LONG)ImageSectionObject, 0))
-      {
-         /*
-          * An other thread has initialized the some image in the background
-          */
-         ExFreePool(ImageSectionObject);
-         ImageSectionObject = FileObject->SectionObjectPointer->ImageSectionObject;
-         Section->ImageSection = ImageSectionObject;
-         SectionSegments = ImageSectionObject->Segments;
+   }
+   ImageSectionObject->NrSegments = LastSegment + 1;
+
+   return TRUE;
+}
+
+NTSTATUS
+ExeFmtpCreateImageSection(HANDLE FileHandle,
+                          PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
+{
+   LARGE_INTEGER Offset;
+   PVOID FileHeader;
+   PVOID FileHeaderBuffer;
+   ULONG FileHeaderSize;
+   ULONG Flags;
+   ULONG OldNrSegments;
+   NTSTATUS Status;
+   ULONG i;
+
+   /*
+    * Read the beginning of the file (2 pages). Should be enough to contain
+    * all (or most) of the headers
+    */
+   Offset.QuadPart = 0;
+
+   /* FIXME: use FileObject instead of FileHandle */
+   Status = ExeFmtpReadFile (FileHandle,
+                             &Offset,
+                             PAGE_SIZE * 2,
+                             &FileHeader,
+                             &FileHeaderBuffer,
+                             &FileHeaderSize);
+
+   if (!NT_SUCCESS(Status))
+      return Status;
 
-         for (i = 0; i < NrSegments; i++)
+   if (FileHeaderSize == 0)
+   {
+      ExFreePool(FileHeaderBuffer);
+      return STATUS_UNSUCCESSFUL;
+   }
+
+   /*
+    * Look for a loader that can handle this executable
+    */
+   for (i = 0; i < RTL_NUMBER_OF(ExeFmtpLoaders); ++ i)
+   {
+      RtlZeroMemory(ImageSectionObject, sizeof(*ImageSectionObject));
+      Flags = 0;
+
+      /* FIXME: use FileObject instead of FileHandle */
+      Status = ExeFmtpLoaders[i](FileHeader,
+                                 FileHeaderSize,
+                                 FileHandle,
+                                 ImageSectionObject,
+                                 &Flags,
+                                 ExeFmtpReadFile,
+                                 ExeFmtpAllocateSegments);
+
+      if (!NT_SUCCESS(Status))
+      {
+         if (ImageSectionObject->Segments)
          {
-            InterlockedIncrement((LONG *)&SectionSegments[i].ReferenceCount);
+            ExFreePool(ImageSectionObject->Segments);
+            ImageSectionObject->Segments = NULL;
          }
       }
-      ExFreePool(ImageSections);
+
+      if (Status != STATUS_ROS_EXEFMT_UNKNOWN_FORMAT)
+         break;
+   }
+
+   ExFreePool(FileHeaderBuffer);
+
+   /*
+    * No loader handled the format
+    */
+   if (Status == STATUS_ROS_EXEFMT_UNKNOWN_FORMAT)
+   {
+      Status = STATUS_INVALID_IMAGE_NOT_MZ;
+      ASSERT(!NT_SUCCESS(Status));
+   }
+
+   if (!NT_SUCCESS(Status))
+      return Status;
+
+   ASSERT(ImageSectionObject->Segments != NULL);
+
+   /*
+    * Some defaults
+    */
+   /* FIXME? are these values platform-dependent? */
+   if(ImageSectionObject->StackReserve == 0)
+      ImageSectionObject->StackReserve = 0x40000;
+
+   if(ImageSectionObject->StackCommit == 0)
+      ImageSectionObject->StackCommit = 0x1000;
+
+   if(ImageSectionObject->ImageBase == 0)
+   {
+      if(ImageSectionObject->ImageCharacteristics & IMAGE_FILE_DLL)
+         ImageSectionObject->ImageBase = 0x10000000;
+      else
+         ImageSectionObject->ImageBase = 0x00400000;
+   }
+
+   /*
+    * And now the fun part: fixing the segments
+    */
+
+   /* Sort them by virtual address */
+   MmspSortSegments(ImageSectionObject, Flags);
+
+   /* Ensure they don't overlap in memory */
+   if (!MmspCheckSegmentBounds(ImageSectionObject, Flags))
+      return STATUS_INVALID_IMAGE_FORMAT;
+
+   /* Ensure they are aligned */
+   OldNrSegments = ImageSectionObject->NrSegments;
+
+   if (!MmspPageAlignSegments(ImageSectionObject, Flags))
+      return STATUS_INVALID_IMAGE_FORMAT;
+
+   /* Trim them if the alignment phase merged some of them */
+   if (ImageSectionObject->NrSegments < OldNrSegments)
+   {
+      PMM_SECTION_SEGMENT Segments;
+      SIZE_T SizeOfSegments;
+
+      SizeOfSegments = sizeof(MM_SECTION_SEGMENT) * ImageSectionObject->NrSegments;
+
+      Segments = ExAllocatePoolWithTag(PagedPool,
+                                       SizeOfSegments,
+                                       TAG_MM_SECTION_SEGMENT);
+
+      if (Segments == NULL)
+         return STATUS_INSUFFICIENT_RESOURCES;
+
+      RtlCopyMemory(Segments, ImageSectionObject->Segments, SizeOfSegments);
+      ExFreePool(ImageSectionObject->Segments);
+      ImageSectionObject->Segments = Segments;
+   }
+
+   /* And finish their initialization */
+   for ( i = 0; i < ImageSectionObject->NrSegments; ++ i )
+   {
+      ExInitializeFastMutex(&ImageSectionObject->Segments[i].Lock);
+      ImageSectionObject->Segments[i].ReferenceCount = 1;
+
+      RtlZeroMemory(&ImageSectionObject->Segments[i].PageDirectory,
+                    sizeof(ImageSectionObject->Segments[i].PageDirectory));
+   }
+
+   ASSERT(NT_SUCCESS(Status));
+   return Status;
+}
+
+NTSTATUS
+MmCreateImageSection(PSECTION_OBJECT *SectionObject,
+                     ACCESS_MASK DesiredAccess,
+                     POBJECT_ATTRIBUTES ObjectAttributes,
+                     PLARGE_INTEGER UMaximumSize,
+                     ULONG SectionPageProtection,
+                     ULONG AllocationAttributes,
+                     HANDLE FileHandle)
+{
+   PSECTION_OBJECT Section;
+   NTSTATUS Status;
+   PFILE_OBJECT FileObject;
+   PMM_SECTION_SEGMENT SectionSegments;
+   PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
+   ULONG i;
+   ULONG FileAccess = 0;
+
+   /*
+    * Specifying a maximum size is meaningless for an image section
+    */
+   if (UMaximumSize != NULL)
+   {
+      return(STATUS_INVALID_PARAMETER_4);
+   }
+
+   /*
+    * Check file access required
+    */
+   if (SectionPageProtection & PAGE_READWRITE ||
+         SectionPageProtection & PAGE_EXECUTE_READWRITE)
+   {
+      FileAccess = FILE_READ_DATA | FILE_WRITE_DATA;
    }
    else
    {
-      /*
-       * Create the section
-       */
-      Status = ObCreateObject (ExGetPreviousMode(),
-                               MmSectionObjectType,
-                               ObjectAttributes,
-                               ExGetPreviousMode(),
-                               NULL,
-                               sizeof(SECTION_OBJECT),
-                               0,
-                               0,
-                               (PVOID*)&Section);
-      if (!NT_SUCCESS(Status))
+      FileAccess = FILE_READ_DATA;
+   }
+
+   /*
+    * Reference the file handle
+    */
+   Status = ObReferenceObjectByHandle(FileHandle,
+                                      FileAccess,
+                                      IoFileObjectType,
+                                      UserMode,
+                                      (PVOID*)(PVOID)&FileObject,
+                                      NULL);
+
+   if (!NT_SUCCESS(Status))
+   {
+      return Status;
+   }
+
+   /*
+    * Create the section
+    */
+   Status = ObCreateObject (ExGetPreviousMode(),
+                            MmSectionObjectType,
+                            ObjectAttributes,
+                            ExGetPreviousMode(),
+                            NULL,
+                            sizeof(SECTION_OBJECT),
+                            0,
+                            0,
+                            (PVOID*)(PVOID)&Section);
+   if (!NT_SUCCESS(Status))
+   {
+      ObDereferenceObject(FileObject);
+      return(Status);
+   }
+
+   /*
+    * Initialize it
+    */
+   Section->SectionPageProtection = SectionPageProtection;
+   Section->AllocationAttributes = AllocationAttributes;
+
+   /*
+    * Initialized caching for this file object if previously caching
+    * was initialized for the same on disk file
+    */
+   Status = CcTryToInitializeFileCache(FileObject);
+
+   if (!NT_SUCCESS(Status) || FileObject->SectionObjectPointer->ImageSectionObject == NULL)
+   {
+      NTSTATUS StatusExeFmt;
+
+      ImageSectionObject = ExAllocatePoolWithTag(PagedPool, sizeof(MM_IMAGE_SECTION_OBJECT), TAG_MM_SECTION_SEGMENT);
+      if (ImageSectionObject == NULL)
       {
          ObDereferenceObject(FileObject);
-         return(Status);
+         ObDereferenceObject(Section);
+         return(STATUS_NO_MEMORY);
       }
+      
+      RtlZeroMemory(ImageSectionObject, sizeof(MM_IMAGE_SECTION_OBJECT));
 
-      Status = ObInsertObject ((PVOID)Section,
-                               NULL,
-                               DesiredAccess,
-                               0,
-                               NULL,
-                               SectionHandle);
-      if (!NT_SUCCESS(Status))
+      StatusExeFmt = ExeFmtpCreateImageSection(FileHandle, ImageSectionObject);
+
+      if (!NT_SUCCESS(StatusExeFmt))
       {
+         if(ImageSectionObject->Segments != NULL)
+            ExFreePool(ImageSectionObject->Segments);
+
+         ExFreePool(ImageSectionObject);
          ObDereferenceObject(Section);
          ObDereferenceObject(FileObject);
-         return(Status);
+         return(StatusExeFmt);
       }
 
-      /*
-       * Initialize it
-       */
-      Section->SectionPageProtection = SectionPageProtection;
-      Section->AllocationAttributes = AllocationAttributes;
-      InitializeListHead(&Section->ViewListHead);
-      KeInitializeSpinLock(&Section->ViewListLock);
+      Section->ImageSection = ImageSectionObject;
+      ASSERT(ImageSectionObject->Segments);
 
       /*
-       * Check file access required
+       * Lock the file
        */
-      if (SectionPageProtection & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE))
+      Status = MmspWaitForFileLock(FileObject);
+      if (!NT_SUCCESS(Status))
       {
-         FileAccess = FILE_READ_DATA | FILE_WRITE_DATA;
+         ExFreePool(ImageSectionObject->Segments);
+         ExFreePool(ImageSectionObject);
+         ObDereferenceObject(Section);
+         ObDereferenceObject(FileObject);
+         return(Status);
       }
-      else
+
+      if (NULL != InterlockedCompareExchangePointer(&FileObject->SectionObjectPointer->ImageSectionObject,
+                                                    ImageSectionObject, NULL))
       {
-         FileAccess = FILE_READ_DATA;
+         /*
+          * An other thread has initialized the some image in the background
+          */
+         ExFreePool(ImageSectionObject->Segments);
+         ExFreePool(ImageSectionObject);
+         ImageSectionObject = FileObject->SectionObjectPointer->ImageSectionObject;
+         Section->ImageSection = ImageSectionObject;
+         SectionSegments = ImageSectionObject->Segments;
+
+         for (i = 0; i < ImageSectionObject->NrSegments; i++)
+         {
+            InterlockedIncrementUL(&SectionSegments[i].ReferenceCount);
+         }
       }
 
+      Status = StatusExeFmt;
+   }
+   else
+   {
       /*
        * Lock the file
        */
       Status = MmspWaitForFileLock(FileObject);
       if (Status != STATUS_SUCCESS)
       {
-         ZwClose(*SectionHandle);
          ObDereferenceObject(Section);
          ObDereferenceObject(FileObject);
          return(Status);
@@ -3050,22 +3302,22 @@ MmCreateImageSection(PHANDLE SectionHandle,
       ImageSectionObject = FileObject->SectionObjectPointer->ImageSectionObject;
       Section->ImageSection = ImageSectionObject;
       SectionSegments = ImageSectionObject->Segments;
-      NrSegments = ImageSectionObject->NrSegments;
 
       /*
        * Otherwise just reference all the section segments
        */
-      for (i = 0; i < NrSegments; i++)
+      for (i = 0; i < ImageSectionObject->NrSegments; i++)
       {
-         InterlockedIncrement((LONG *)&SectionSegments[i].ReferenceCount);
+         InterlockedIncrementUL(&SectionSegments[i].ReferenceCount);
       }
 
+      Status = STATUS_SUCCESS;
    }
    Section->FileObject = FileObject;
    CcRosReferenceCache(FileObject);
    KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
-   ObDereferenceObject(Section);
-   return(STATUS_SUCCESS);
+   *SectionObject = Section;
+   return(Status);
 }
 
 /*
@@ -3080,34 +3332,63 @@ NtCreateSection (OUT PHANDLE SectionHandle,
                  IN ULONG AllocationAttributes,
                  IN HANDLE FileHandle OPTIONAL)
 {
-   if (AllocationAttributes & SEC_IMAGE)
+   LARGE_INTEGER SafeMaximumSize;
+   PSECTION_OBJECT SectionObject;
+   KPROCESSOR_MODE PreviousMode;
+   NTSTATUS Status = STATUS_SUCCESS;
+
+   PreviousMode = ExGetPreviousMode();
+
+   if(MaximumSize != NULL && PreviousMode != KernelMode)
    {
-      return(MmCreateImageSection(SectionHandle,
-                                  DesiredAccess,
-                                  ObjectAttributes,
-                                  MaximumSize,
-                                  SectionPageProtection,
-                                  AllocationAttributes,
-                                  FileHandle));
+     _SEH_TRY
+     {
+       /* make a copy on the stack */
+       SafeMaximumSize = ProbeForReadLargeInteger(MaximumSize);
+       MaximumSize = &SafeMaximumSize;
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
+
+     if(!NT_SUCCESS(Status))
+     {
+       return Status;
+     }
    }
 
-   if (FileHandle != NULL)
+   /*
+    * Check the protection
+    */
+   if ((SectionPageProtection & PAGE_FLAGS_VALID_FROM_USER_MODE) !=
+         SectionPageProtection)
    {
-      return(MmCreateDataFileSection(SectionHandle,
-                                     DesiredAccess,
-                                     ObjectAttributes,
-                                     MaximumSize,
-                                     SectionPageProtection,
-                                     AllocationAttributes,
-                                     FileHandle));
+      return(STATUS_INVALID_PAGE_PROTECTION);
    }
 
-   return(MmCreatePageFileSection(SectionHandle,
-                                  DesiredAccess,
-                                  ObjectAttributes,
-                                  MaximumSize,
-                                  SectionPageProtection,
-                                  AllocationAttributes));
+   Status = MmCreateSection(&SectionObject,
+                            DesiredAccess,
+                            ObjectAttributes,
+                            MaximumSize,
+                            SectionPageProtection,
+                            AllocationAttributes,
+                            FileHandle,
+                            NULL);
+
+   if (NT_SUCCESS(Status))
+   {
+      Status = ObInsertObject ((PVOID)SectionObject,
+                               NULL,
+                               DesiredAccess,
+                               0,
+                               NULL,
+                               SectionHandle);
+      ObDereferenceObject(SectionObject);
+   }
+
+   return Status;
 }
 
 
@@ -3133,17 +3414,50 @@ NtOpenSection(PHANDLE   SectionHandle,
               ACCESS_MASK  DesiredAccess,
               POBJECT_ATTRIBUTES ObjectAttributes)
 {
-   NTSTATUS Status;
+   HANDLE hSection;
+   KPROCESSOR_MODE PreviousMode;
+   NTSTATUS Status = STATUS_SUCCESS;
+
+   PreviousMode = ExGetPreviousMode();
+
+   if(PreviousMode != KernelMode)
+   {
+     _SEH_TRY
+     {
+       ProbeForWriteHandle(SectionHandle);
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
 
-   *SectionHandle = 0;
+     if(!NT_SUCCESS(Status))
+     {
+       return Status;
+     }
+   }
 
    Status = ObOpenObjectByName(ObjectAttributes,
                                MmSectionObjectType,
                                NULL,
-                               UserMode,
+                               PreviousMode,
                                DesiredAccess,
                                NULL,
-                               SectionHandle);
+                               &hSection);
+
+   if(NT_SUCCESS(Status))
+   {
+     _SEH_TRY
+     {
+       *SectionHandle = hSection;
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
+   }
 
    return(Status);
 }
@@ -3161,7 +3475,6 @@ MmMapViewOfSegment(PEPROCESS Process,
 {
    PMEMORY_AREA MArea;
    NTSTATUS Status;
-   KIRQL oldIrql;
    PHYSICAL_ADDRESS BoundaryAddressMultiple;
 
    BoundaryAddressMultiple.QuadPart = 0;
@@ -3178,15 +3491,11 @@ MmMapViewOfSegment(PEPROCESS Process,
                                BoundaryAddressMultiple);
    if (!NT_SUCCESS(Status))
    {
-      DPRINT1("Mapping between 0x%.8X and 0x%.8X failed.\n",
-              (*BaseAddress), (char*)(*BaseAddress) + ViewSize);
+      DPRINT1("Mapping between 0x%.8X and 0x%.8X failed (%X).\n",
+              (*BaseAddress), (char*)(*BaseAddress) + ViewSize, Status);
       return(Status);
    }
 
-   KeAcquireSpinLock(&Section->ViewListLock, &oldIrql);
-   InsertTailList(&Section->ViewListHead,
-                  &MArea->Data.SectionData.ViewListEntry);
-   KeReleaseSpinLock(&Section->ViewListLock, oldIrql);
 
    ObReferenceObjectByPointer((PVOID)Section,
                               SECTION_MAP_READ,
@@ -3253,27 +3562,72 @@ MmMapViewOfSegment(PEPROCESS Process,
  * @implemented
  */
 NTSTATUS STDCALL
-NtMapViewOfSection(HANDLE SectionHandle,
-                   HANDLE ProcessHandle,
-                   PVOID* BaseAddress,
-                   ULONG ZeroBits,
-                   ULONG CommitSize,
-                   PLARGE_INTEGER SectionOffset,
-                   PULONG ViewSize,
-                   SECTION_INHERIT InheritDisposition,
-                   ULONG AllocationType,
-                   ULONG Protect)
+NtMapViewOfSection(IN HANDLE SectionHandle,
+                   IN HANDLE ProcessHandle,
+                   IN OUT PVOID* BaseAddress  OPTIONAL,
+                   IN ULONG ZeroBits  OPTIONAL,
+                   IN ULONG CommitSize,
+                   IN OUT PLARGE_INTEGER SectionOffset  OPTIONAL,
+                   IN OUT PULONG ViewSize,
+                   IN SECTION_INHERIT InheritDisposition,
+                   IN ULONG AllocationType  OPTIONAL,
+                   IN ULONG Protect)
 {
+   PVOID SafeBaseAddress;
+   LARGE_INTEGER SafeSectionOffset;
+   ULONG SafeViewSize;
    PSECTION_OBJECT Section;
    PEPROCESS Process;
-   NTSTATUS Status;
+   KPROCESSOR_MODE PreviousMode;
    PMADDRESS_SPACE AddressSpace;
+   NTSTATUS Status = STATUS_SUCCESS;
+
+   PreviousMode = ExGetPreviousMode();
+
+   if(PreviousMode != KernelMode)
+   {
+     SafeBaseAddress = NULL;
+     SafeSectionOffset.QuadPart = 0;
+     SafeViewSize = 0;
+
+     _SEH_TRY
+     {
+       if(BaseAddress != NULL)
+       {
+         ProbeForWritePointer(BaseAddress);
+         SafeBaseAddress = *BaseAddress;
+       }
+       if(SectionOffset != NULL)
+       {
+         ProbeForWriteLargeInteger(SectionOffset);
+         SafeSectionOffset = *SectionOffset;
+       }
+       ProbeForWriteUlong(ViewSize);
+       SafeViewSize = *ViewSize;
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
+
+     if(!NT_SUCCESS(Status))
+     {
+       return Status;
+     }
+   }
+   else
+   {
+     SafeBaseAddress = (BaseAddress != NULL ? *BaseAddress : NULL);
+     SafeSectionOffset.QuadPart = (SectionOffset != NULL ? SectionOffset->QuadPart : 0);
+     SafeViewSize = (ViewSize != NULL ? *ViewSize : 0);
+   }
 
    Status = ObReferenceObjectByHandle(ProcessHandle,
                                       PROCESS_VM_OPERATION,
                                       PsProcessType,
-                                      UserMode,
-                                      (PVOID*)&Process,
+                                      PreviousMode,
+                                      (PVOID*)(PVOID)&Process,
                                       NULL);
    if (!NT_SUCCESS(Status))
    {
@@ -3285,8 +3639,8 @@ NtMapViewOfSection(HANDLE SectionHandle,
    Status = ObReferenceObjectByHandle(SectionHandle,
                                       SECTION_MAP_READ,
                                       MmSectionObjectType,
-                                      UserMode,
-                                      (PVOID*)&Section,
+                                      PreviousMode,
+                                      (PVOID*)(PVOID)&Section,
                                       NULL);
    if (!(NT_SUCCESS(Status)))
    {
@@ -3297,11 +3651,11 @@ NtMapViewOfSection(HANDLE SectionHandle,
 
    Status = MmMapViewOfSection(Section,
                                Process,
-                               BaseAddress,
+                               (BaseAddress != NULL ? &SafeBaseAddress : NULL),
                                ZeroBits,
                                CommitSize,
-                               SectionOffset,
-                               ViewSize,
+                               (SectionOffset != NULL ? &SafeSectionOffset : NULL),
+                               (ViewSize != NULL ? &SafeViewSize : NULL),
                                InheritDisposition,
                                AllocationType,
                                Protect);
@@ -3309,15 +3663,38 @@ NtMapViewOfSection(HANDLE SectionHandle,
    ObDereferenceObject(Section);
    ObDereferenceObject(Process);
 
+   if(NT_SUCCESS(Status))
+   {
+     /* copy parameters back to the caller */
+     _SEH_TRY
+     {
+       if(BaseAddress != NULL)
+       {
+         *BaseAddress = SafeBaseAddress;
+       }
+       if(SectionOffset != NULL)
+       {
+         *SectionOffset = SafeSectionOffset;
+       }
+       if(ViewSize != NULL)
+       {
+         *ViewSize = SafeViewSize;
+       }
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
+   }
+
    return(Status);
 }
 
 VOID STATIC
 MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
-                  PHYSICAL_ADDRESS PhysAddr, SWAPENTRY SwapEntry,
-                  BOOLEAN Dirty)
+                  PFN_TYPE Page, SWAPENTRY SwapEntry, BOOLEAN Dirty)
 {
-   PMEMORY_AREA MArea;
    ULONG Entry;
    PFILE_OBJECT FileObject;
    PBCB Bcb;
@@ -3327,23 +3704,24 @@ MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
    NTSTATUS Status;
    PSECTION_OBJECT Section;
    PMM_SECTION_SEGMENT Segment;
+   PMADDRESS_SPACE AddressSpace;
 
-   MArea = (PMEMORY_AREA)Context;
+   AddressSpace = (PMADDRESS_SPACE)Context;
 
    Address = (PVOID)PAGE_ROUND_DOWN(Address);
 
-   Offset = ((ULONG)Address - (ULONG)MArea->BaseAddress);
-
-   Section = MArea->Data.SectionData.Section;
-   Segment = MArea->Data.SectionData.Segment;
+   Offset = ((ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress) +
+            MemoryArea->Data.SectionData.ViewOffset;
 
+   Section = MemoryArea->Data.SectionData.Section;
+   Segment = MemoryArea->Data.SectionData.Segment;
 
-   PageOp = MmCheckForPageOp(MArea, 0, NULL, Segment, Offset);
+   PageOp = MmCheckForPageOp(MemoryArea, NULL, NULL, Segment, Offset);
 
    while (PageOp)
    {
       MmUnlockSectionSegment(Segment);
-      MmUnlockAddressSpace(&MArea->Process->AddressSpace);
+      MmUnlockAddressSpace(AddressSpace);
 
       Status = MmspWaitForPageOpCompletionEvent(PageOp);
       if (Status != STATUS_SUCCESS)
@@ -3352,10 +3730,10 @@ MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
          KEBUGCHECK(0);
       }
 
-      MmLockAddressSpace(&MArea->Process->AddressSpace);
+      MmLockAddressSpace(AddressSpace);
       MmLockSectionSegment(Segment);
       MmspCompleteAndReleasePageOp(PageOp);
-      PageOp = MmCheckForPageOp(MArea, 0, NULL, Segment, Offset);
+      PageOp = MmCheckForPageOp(MemoryArea, NULL, NULL, Segment, Offset);
    }
 
    Entry = MmGetPageEntrySectionSegment(Segment, Offset);
@@ -3366,12 +3744,12 @@ MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
     */
    if (Segment->Flags & MM_DATAFILE_SEGMENT)
    {
-      if (PhysAddr.QuadPart == PAGE_FROM_SSE(Entry) && Dirty)
+      if (Page == PFN_FROM_SSE(Entry) && Dirty)
       {
          FileObject = MemoryArea->Data.SectionData.Section->FileObject;
          Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
-         CcRosMarkDirtyCacheSegment(Bcb, Offset);
-         assert(SwapEntry == 0);
+         CcRosMarkDirtyCacheSegment(Bcb, Offset + Segment->FileOffset);
+         ASSERT(SwapEntry == 0);
       }
    }
 
@@ -3387,10 +3765,10 @@ MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
       }
       MmFreeSwapPage(SwapEntry);
    }
-   else if (PhysAddr.QuadPart != 0)
+   else if (Page != 0)
    {
       if (IS_SWAP_FROM_SSE(Entry) ||
-            PhysAddr.QuadPart != (PAGE_FROM_SSE(Entry)))
+          Page != PFN_FROM_SSE(Entry))
       {
          /*
           * Sanity check
@@ -3403,18 +3781,18 @@ MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
          /*
           * Just dereference private pages
           */
-         SavedSwapEntry = MmGetSavedSwapEntryPage(PhysAddr);
+         SavedSwapEntry = MmGetSavedSwapEntryPage(Page);
          if (SavedSwapEntry != 0)
          {
             MmFreeSwapPage(SavedSwapEntry);
-            MmSetSavedSwapEntryPage(PhysAddr, 0);
+            MmSetSavedSwapEntryPage(Page, 0);
          }
-         MmDeleteRmap(PhysAddr, MArea->Process, Address);
-         MmReleasePageMemoryConsumer(MC_USER, PhysAddr);
+         MmDeleteRmap(Page, AddressSpace->Process, Address);
+         MmReleasePageMemoryConsumer(MC_USER, Page);
       }
       else
       {
-         MmDeleteRmap(PhysAddr, MArea->Process, Address);
+         MmDeleteRmap(Page, AddressSpace->Process, Address);
          MmUnsharePageEntrySectionSegment(Section, Segment, Offset, Dirty, FALSE);
       }
    }
@@ -3428,13 +3806,12 @@ MmUnmapViewOfSegment(PMADDRESS_SPACE AddressSpace,
    PMEMORY_AREA MemoryArea;
    PSECTION_OBJECT Section;
    PMM_SECTION_SEGMENT Segment;
-   KIRQL oldIrql;
    PLIST_ENTRY CurrentEntry;
    PMM_REGION CurrentRegion;
    PLIST_ENTRY RegionListHead;
 
-   MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
-                                          BaseAddress);
+   MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace,
+                                            BaseAddress);
    if (MemoryArea == NULL)
    {
       return(STATUS_UNSUCCESSFUL);
@@ -3445,9 +3822,6 @@ MmUnmapViewOfSegment(PMADDRESS_SPACE AddressSpace,
    Segment = MemoryArea->Data.SectionData.Segment;
 
    MmLockSectionSegment(Segment);
-   KeAcquireSpinLock(&Section->ViewListLock, &oldIrql);
-   RemoveEntryList(&MemoryArea->Data.SectionData.ViewListEntry);
-   KeReleaseSpinLock(&Section->ViewListLock, oldIrql);
 
    RegionListHead = &MemoryArea->Data.SectionData.RegionListHead;
    while (!IsListEmpty(RegionListHead))
@@ -3460,18 +3834,16 @@ MmUnmapViewOfSegment(PMADDRESS_SPACE AddressSpace,
    if (Section->AllocationAttributes & SEC_PHYSICALMEMORY)
    {
       Status = MmFreeMemoryArea(AddressSpace,
-                                BaseAddress,
-                                0,
+                                MemoryArea,
                                 NULL,
                                 NULL);
    }
    else
    {
       Status = MmFreeMemoryArea(AddressSpace,
-                                BaseAddress,
-                                0,
+                                MemoryArea,
                                 MmFreeSectionPage,
-                                MemoryArea);
+                                AddressSpace);
    }
    MmUnlockSectionSegment(Segment);
    ObDereferenceObject(Section);
@@ -3493,14 +3865,16 @@ MmUnmapViewOfSection(PEPROCESS Process,
    DPRINT("Opening memory area Process %x BaseAddress %x\n",
           Process, BaseAddress);
 
-   assert(Process);
+   ASSERT(Process);
 
    AddressSpace = &Process->AddressSpace;
-   MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
-                                          BaseAddress);
-   if (MemoryArea == NULL)
+   MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace,
+                                            BaseAddress);
+   if (MemoryArea == NULL ||
+       MemoryArea->Type != MEMORY_AREA_SECTION_VIEW ||
+       MemoryArea->DeleteInProgress)
    {
-      return(STATUS_UNSUCCESSFUL);
+      return STATUS_NOT_MAPPED_VIEW;
    }
 
    Section = MemoryArea->Data.SectionData.Section;
@@ -3523,7 +3897,7 @@ MmUnmapViewOfSection(PEPROCESS Process,
        * and calculate the image base address */
       for (i = 0; i < NrSegments; i++)
       {
-         if (!(SectionSegments[i].Characteristics & IMAGE_SECTION_NOLOAD))
+         if (!(SectionSegments[i].Characteristics & IMAGE_SCN_TYPE_NOLOAD))
          {
             if (Segment == &SectionSegments[i])
             {
@@ -3539,7 +3913,7 @@ MmUnmapViewOfSection(PEPROCESS Process,
 
       for (i = 0; i < NrSegments; i++)
       {
-         if (!(SectionSegments[i].Characteristics & IMAGE_SECTION_NOLOAD))
+         if (!(SectionSegments[i].Characteristics & IMAGE_SCN_TYPE_NOLOAD))
          {
             PVOID SBaseAddress = (PVOID)
                                  ((char*)ImageBaseAddress + (ULONG_PTR)SectionSegments[i].VirtualAddress);
@@ -3576,17 +3950,20 @@ NtUnmapViewOfSection (HANDLE ProcessHandle,
                       PVOID BaseAddress)
 {
    PEPROCESS Process;
+   KPROCESSOR_MODE PreviousMode;
    NTSTATUS Status;
 
    DPRINT("NtUnmapViewOfSection(ProcessHandle %x, BaseAddress %x)\n",
           ProcessHandle, BaseAddress);
 
+   PreviousMode = ExGetPreviousMode();
+
    DPRINT("Referencing process\n");
    Status = ObReferenceObjectByHandle(ProcessHandle,
                                       PROCESS_VM_OPERATION,
                                       PsProcessType,
-                                      UserMode,
-                                      (PVOID*)&Process,
+                                      PreviousMode,
+                                      (PVOID*)(PVOID)&Process,
                                       NULL);
    if (!NT_SUCCESS(Status))
    {
@@ -3604,109 +3981,217 @@ NtUnmapViewOfSection (HANDLE ProcessHandle,
 }
 
 
-NTSTATUS STDCALL
-NtQuerySection (IN HANDLE SectionHandle,
-                IN CINT SectionInformationClass,
-                OUT PVOID SectionInformation,
-                IN ULONG Length,
-                OUT PULONG ResultLength)
-/*
- * FUNCTION: Queries the information of a section object.
- * ARGUMENTS:
- *        SectionHandle = Handle to the section link object
- *   SectionInformationClass = Index to a certain information structure
- *        SectionInformation (OUT)= Caller supplies storage for resulting
- *                                  information
- *        Length =  Size of the supplied storage
- *        ResultLength = Data written
- * RETURNS: Status
+/**
+ * Queries the information of a section object.
+ *
+ * @param SectionHandle
+ *        Handle to the section object. It must be opened with SECTION_QUERY
+ *        access.
+ * @param SectionInformationClass
+ *        Index to a certain information structure. Can be either
+ *        SectionBasicInformation or SectionImageInformation. The latter
+ *        is valid only for sections that were created with the SEC_IMAGE
+ *        flag.
+ * @param SectionInformation
+ *        Caller supplies storage for resulting information.
+ * @param Length
+ *        Size of the supplied storage.
+ * @param ResultLength
+ *        Data written.
  *
+ * @return Status.
+ *
+ * @implemented
  */
+NTSTATUS STDCALL
+NtQuerySection(IN HANDLE SectionHandle,
+               IN SECTION_INFORMATION_CLASS SectionInformationClass,
+               OUT PVOID SectionInformation,
+               IN ULONG SectionInformationLength,
+               OUT PULONG ResultLength  OPTIONAL)
 {
    PSECTION_OBJECT Section;
-   NTSTATUS Status;
+   KPROCESSOR_MODE PreviousMode;
+   NTSTATUS Status = STATUS_SUCCESS;
 
-   Status = ObReferenceObjectByHandle(SectionHandle,
-                                      SECTION_MAP_READ,
-                                      MmSectionObjectType,
-                                      UserMode,
-                                      (PVOID*)&Section,
-                                      NULL);
-   if (!(NT_SUCCESS(Status)))
+   PreviousMode = ExGetPreviousMode();
+
+   Status = DefaultQueryInfoBufferCheck(SectionInformationClass,
+                                        ExSectionInfoClass,
+                                        sizeof(ExSectionInfoClass) / sizeof(ExSectionInfoClass[0]),
+                                        SectionInformation,
+                                        SectionInformationLength,
+                                        ResultLength,
+                                        PreviousMode);
+
+   if(!NT_SUCCESS(Status))
    {
-      return(Status);
+     DPRINT1("NtQuerySection() failed, Status: 0x%x\n", Status);
+     return Status;
    }
 
-   switch (SectionInformationClass)
+   Status = ObReferenceObjectByHandle(SectionHandle,
+                                      SECTION_QUERY,
+                                      MmSectionObjectType,
+                                      PreviousMode,
+                                      (PVOID*)(PVOID)&Section,
+                                      NULL);
+   if (NT_SUCCESS(Status))
    {
-      case SectionBasicInformation:
+      switch (SectionInformationClass)
+      {
+         case SectionBasicInformation:
          {
-            PSECTION_BASIC_INFORMATION Sbi;
+            PSECTION_BASIC_INFORMATION Sbi = (PSECTION_BASIC_INFORMATION)SectionInformation;
 
-            if (Length != sizeof(SECTION_BASIC_INFORMATION))
+            _SEH_TRY
             {
-               ObDereferenceObject(Section);
-               return(STATUS_INFO_LENGTH_MISMATCH);
-            }
-
-            Sbi = (PSECTION_BASIC_INFORMATION)SectionInformation;
+               Sbi->Attributes = Section->AllocationAttributes;
+               if (Section->AllocationAttributes & SEC_IMAGE)
+               {
+                  Sbi->BaseAddress = 0;
+                  Sbi->Size.QuadPart = 0;
+               }
+               else
+               {
+                  Sbi->BaseAddress = (PVOID)Section->Segment->VirtualAddress;
+                  Sbi->Size.QuadPart = Section->Segment->Length;
+               }
 
-            Sbi->BaseAddress = 0;
-            Sbi->Attributes = 0;
-            Sbi->Size.QuadPart = 0;
+               if (ResultLength != NULL)
+               {
+                  *ResultLength = sizeof(SECTION_BASIC_INFORMATION);
+               }
+               Status = STATUS_SUCCESS;
+            }
+            _SEH_HANDLE
+            {
+               Status = _SEH_GetExceptionCode();
+            }
+            _SEH_END;
 
-            *ResultLength = sizeof(SECTION_BASIC_INFORMATION);
-            Status = STATUS_SUCCESS;
             break;
          }
 
-      case SectionImageInformation:
+         case SectionImageInformation:
          {
-            PSECTION_IMAGE_INFORMATION Sii;
+            PSECTION_IMAGE_INFORMATION Sii = (PSECTION_IMAGE_INFORMATION)SectionInformation;
 
-            if (Length != sizeof(SECTION_IMAGE_INFORMATION))
+            _SEH_TRY
             {
-               ObDereferenceObject(Section);
-               return(STATUS_INFO_LENGTH_MISMATCH);
-            }
+               memset(Sii, 0, sizeof(SECTION_IMAGE_INFORMATION));
+               if (Section->AllocationAttributes & SEC_IMAGE)
+               {
+                  PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
+                  ImageSectionObject = Section->ImageSection;
+
+                  Sii->TransferAddress = (PVOID)ImageSectionObject->EntryPoint;
+                  Sii->MaximumStackSize = ImageSectionObject->StackReserve;
+                  Sii->CommittedStackSize = ImageSectionObject->StackCommit;
+                  Sii->SubsystemType = ImageSectionObject->Subsystem;
+                  Sii->SubSystemMinorVersion = ImageSectionObject->MinorSubsystemVersion;
+                  Sii->SubSystemMajorVersion = ImageSectionObject->MajorSubsystemVersion;
+                  Sii->ImageCharacteristics = ImageSectionObject->ImageCharacteristics;
+                  Sii->Machine = ImageSectionObject->Machine;
+                  Sii->ImageContainsCode = ImageSectionObject->Executable;
+               }
 
-            Sii = (PSECTION_IMAGE_INFORMATION)SectionInformation;
-            memset(Sii, 0, sizeof(SECTION_IMAGE_INFORMATION));
-            if (Section->AllocationAttributes & SEC_IMAGE)
+               if (ResultLength != NULL)
+               {
+                  *ResultLength = sizeof(SECTION_IMAGE_INFORMATION);
+               }
+               Status = STATUS_SUCCESS;
+            }
+            _SEH_HANDLE
             {
-               PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
-               ImageSectionObject = Section->ImageSection;
-
-               Sii->EntryPoint = ImageSectionObject->EntryPoint;
-               Sii->StackReserve = ImageSectionObject->StackReserve;
-               Sii->StackCommit = ImageSectionObject->StackCommit;
-               Sii->Subsystem = ImageSectionObject->Subsystem;
-               Sii->MinorSubsystemVersion = (USHORT)ImageSectionObject->MinorSubsystemVersion;
-               Sii->MajorSubsystemVersion = (USHORT)ImageSectionObject->MajorSubsystemVersion;
-               Sii->Characteristics = ImageSectionObject->ImageCharacteristics;
-               Sii->ImageNumber = ImageSectionObject->Machine;
-               Sii->Executable = ImageSectionObject->Executable;
+               Status = _SEH_GetExceptionCode();
             }
-            *ResultLength = sizeof(SECTION_IMAGE_INFORMATION);
-            Status = STATUS_SUCCESS;
+            _SEH_END;
+
             break;
          }
+      }
 
-      default:
-         *ResultLength = 0;
-         Status = STATUS_INVALID_INFO_CLASS;
+      ObDereferenceObject(Section);
    }
-   ObDereferenceObject(Section);
+
    return(Status);
 }
 
 
+/**
+ * Extends size of file backed section.
+ *
+ * @param SectionHandle
+ *        Handle to the section object. It must be opened with
+ *        SECTION_EXTEND_SIZE access.
+ * @param NewMaximumSize
+ *        New maximum size of the section in bytes.
+ *
+ * @return Status.
+ *
+ * @todo Move the actual code to internal function MmExtendSection.
+ * @unimplemented
+ */
 NTSTATUS STDCALL
 NtExtendSection(IN HANDLE SectionHandle,
-                IN ULONG NewMaximumSize)
+                IN PLARGE_INTEGER NewMaximumSize)
 {
-   UNIMPLEMENTED;
-   return(STATUS_NOT_IMPLEMENTED);
+   LARGE_INTEGER SafeNewMaximumSize;
+   PSECTION_OBJECT Section;
+   KPROCESSOR_MODE PreviousMode;
+   NTSTATUS Status = STATUS_SUCCESS;
+
+   PreviousMode = ExGetPreviousMode();
+
+   if(PreviousMode != KernelMode)
+   {
+     _SEH_TRY
+     {
+       /* make a copy on the stack */
+       SafeNewMaximumSize = ProbeForReadLargeInteger(NewMaximumSize);
+       NewMaximumSize = &SafeNewMaximumSize;
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
+
+     if(!NT_SUCCESS(Status))
+     {
+       return Status;
+     }
+   }
+
+   Status = ObReferenceObjectByHandle(SectionHandle,
+                                      SECTION_EXTEND_SIZE,
+                                      MmSectionObjectType,
+                                      PreviousMode,
+                                      (PVOID*)&Section,
+                                      NULL);
+   if (!NT_SUCCESS(Status))
+   {
+      return Status;
+   }
+
+   if (!(Section->AllocationAttributes & SEC_FILE))
+   {
+      ObfDereferenceObject(Section);
+      return STATUS_INVALID_PARAMETER;
+   }
+
+   /*
+    * - Acquire file extneding resource.
+    * - Check if we're not resizing the section below it's actual size!
+    * - Extend segments if needed.
+    * - Set file information (FileAllocationInformation) to the new size.
+    * - Release file extending resource.
+    */
+
+   ObDereferenceObject(Section);
+
+   return STATUS_NOT_IMPLEMENTED;
 }
 
 
@@ -3727,7 +4212,7 @@ NtExtendSection(IN HANDLE SectionHandle,
  * REVISIONS
  */
 PVOID STDCALL
-MmAllocateSection (IN ULONG Length)
+MmAllocateSection (IN ULONG Length, PVOID BaseAddress)
 {
    PVOID Result;
    MEMORY_AREA* marea;
@@ -3741,7 +4226,7 @@ MmAllocateSection (IN ULONG Length)
    BoundaryAddressMultiple.QuadPart = 0;
 
    AddressSpace = MmGetKernelAddressSpace();
-   Result = NULL;
+   Result = BaseAddress;
    MmLockAddressSpace(AddressSpace);
    Status = MmCreateMemoryArea (NULL,
                                 AddressSpace,
@@ -3762,7 +4247,7 @@ MmAllocateSection (IN ULONG Length)
    DPRINT("Result %p\n",Result);
    for (i = 0; i < PAGE_ROUND_UP(Length) / PAGE_SIZE; i++)
    {
-      PHYSICAL_ADDRESS Page;
+      PFN_TYPE Page;
 
       Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Page);
       if (!NT_SUCCESS(Status))
@@ -3771,10 +4256,10 @@ MmAllocateSection (IN ULONG Length)
          KEBUGCHECK(0);
       }
       Status = MmCreateVirtualMapping (NULL,
-                                       ((char*)Result + (i * PAGE_SIZE)),
+                                       (PVOID)((ULONG_PTR)Result + (i * PAGE_SIZE)),
                                        PAGE_READWRITE,
-                                       Page,
-                                       TRUE);
+                                       &Page,
+                                       1);
       if (!NT_SUCCESS(Status))
       {
          DbgPrint("Unable to create virtual mapping\n");
@@ -3851,7 +4336,7 @@ MmMapViewOfSection(IN PVOID SectionObject,
    ULONG ViewOffset;
    NTSTATUS Status = STATUS_SUCCESS;
 
-   assert(Process);
+   ASSERT(Process);
 
    Section = (PSECTION_OBJECT)SectionObject;
    AddressSpace = &Process->AddressSpace;
@@ -3862,7 +4347,7 @@ MmMapViewOfSection(IN PVOID SectionObject,
    {
       ULONG i;
       ULONG NrSegments;
-      PVOID ImageBase;
+      ULONG_PTR ImageBase;
       ULONG ImageSize;
       PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
       PMM_SECTION_SEGMENT SectionSegments;
@@ -3872,8 +4357,8 @@ MmMapViewOfSection(IN PVOID SectionObject,
       NrSegments = ImageSectionObject->NrSegments;
 
 
-      ImageBase = *BaseAddress;
-      if (ImageBase == NULL)
+      ImageBase = (ULONG_PTR)*BaseAddress;
+      if (ImageBase == 0)
       {
          ImageBase = ImageSectionObject->ImageBase;
       }
@@ -3881,18 +4366,18 @@ MmMapViewOfSection(IN PVOID SectionObject,
       ImageSize = 0;
       for (i = 0; i < NrSegments; i++)
       {
-         if (!(SectionSegments[i].Characteristics & IMAGE_SECTION_NOLOAD))
+         if (!(SectionSegments[i].Characteristics & IMAGE_SCN_TYPE_NOLOAD))
          {
-            ULONG MaxExtent;
-            MaxExtent = (ULONG)((char*)SectionSegments[i].VirtualAddress +
-                                SectionSegments[i].Length);
+            ULONG_PTR MaxExtent;
+            MaxExtent = (ULONG_PTR)SectionSegments[i].VirtualAddress +
+                        SectionSegments[i].Length;
             ImageSize = max(ImageSize, MaxExtent);
          }
       }
 
       /* Check there is enough space to map the section at that point. */
-      if (MmOpenMemoryAreaByRegion(AddressSpace, ImageBase,
-                                   PAGE_ROUND_UP(ImageSize)) != NULL)
+      if (MmLocateMemoryAreaByRegion(AddressSpace, (PVOID)ImageBase,
+                                     PAGE_ROUND_UP(ImageSize)) != NULL)
       {
          /* Fail if the user requested a fixed base address. */
          if ((*BaseAddress) != NULL)
@@ -3901,8 +4386,8 @@ MmMapViewOfSection(IN PVOID SectionObject,
             return(STATUS_UNSUCCESSFUL);
          }
          /* Otherwise find a gap to map the image. */
-         ImageBase = MmFindGap(AddressSpace, PAGE_ROUND_UP(ImageSize), FALSE);
-         if (ImageBase == NULL)
+         ImageBase = (ULONG_PTR)MmFindGap(AddressSpace, PAGE_ROUND_UP(ImageSize), PAGE_SIZE, FALSE);
+         if (ImageBase == 0)
          {
             MmUnlockAddressSpace(AddressSpace);
             return(STATUS_UNSUCCESSFUL);
@@ -3911,7 +4396,7 @@ MmMapViewOfSection(IN PVOID SectionObject,
 
       for (i = 0; i < NrSegments; i++)
       {
-         if (!(SectionSegments[i].Characteristics & IMAGE_SECTION_NOLOAD))
+         if (!(SectionSegments[i].Characteristics & IMAGE_SCN_TYPE_NOLOAD))
          {
             PVOID SBaseAddress = (PVOID)
                                  ((char*)ImageBase + (ULONG_PTR)SectionSegments[i].VirtualAddress);
@@ -3923,7 +4408,7 @@ MmMapViewOfSection(IN PVOID SectionObject,
                                         &SBaseAddress,
                                         SectionSegments[i].Length,
                                         SectionSegments[i].Protection,
-                                        (ULONG_PTR)SectionSegments[i].VirtualAddress,
+                                        0,
                                         FALSE);
             MmUnlockSectionSegment(&SectionSegments[i]);
             if (!NT_SUCCESS(Status))
@@ -3934,7 +4419,7 @@ MmMapViewOfSection(IN PVOID SectionObject,
          }
       }
 
-      *BaseAddress = ImageBase;
+      *BaseAddress = (PVOID)ImageBase;
    }
    else
    {
@@ -4041,8 +4526,9 @@ MmFlushImageSection (IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
  * @unimplemented
  */
 BOOLEAN STDCALL
-MmForceSectionClosed (DWORD Unknown0,
-                      DWORD Unknown1)
+MmForceSectionClosed (
+    IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
+    IN BOOLEAN                  DelayClose)
 {
    UNIMPLEMENTED;
    return (FALSE);
@@ -4097,6 +4583,21 @@ MmMapViewInSystemSpace (IN PVOID SectionObject,
    return Status;
 }
 
+/*
+ * @unimplemented
+ */
+NTSTATUS
+STDCALL
+MmMapViewInSessionSpace (
+    IN PVOID Section,
+    OUT PVOID *MappedBase,
+    IN OUT PSIZE_T ViewSize
+    )
+{
+       UNIMPLEMENTED;
+       return STATUS_NOT_IMPLEMENTED;
+}
+
 
 /*
  * @implemented
@@ -4116,6 +4617,18 @@ MmUnmapViewInSystemSpace (IN PVOID MappedBase)
    return Status;
 }
 
+/*
+ * @unimplemented
+ */
+NTSTATUS
+STDCALL
+MmUnmapViewInSessionSpace (
+    IN PVOID MappedBase
+    )
+{
+       UNIMPLEMENTED;
+       return STATUS_NOT_IMPLEMENTED;
+}
 
 /*
  * @unimplemented
@@ -4141,7 +4654,7 @@ MmSetBankedSection (DWORD Unknown0,
  *  Creates a section object.
  *
  * ARGUMENTS
- * SectionObjiect (OUT)
+ * SectionObject (OUT)
  *  Caller supplied storage for the resulting pointer
  *  to a SECTION_OBJECT instance;
  *
@@ -4186,7 +4699,7 @@ MmSetBankedSection (DWORD Unknown0,
  * RETURN VALUE
  *  Status.
  *
- * @unimplemented
+ * @implemented
  */
 NTSTATUS STDCALL
 MmCreateSection (OUT PSECTION_OBJECT  * SectionObject,
@@ -4198,7 +4711,34 @@ MmCreateSection (OUT PSECTION_OBJECT  * SectionObject,
                  IN HANDLE   FileHandle   OPTIONAL,
                  IN PFILE_OBJECT  File      OPTIONAL)
 {
-   return (STATUS_NOT_IMPLEMENTED);
+   if (AllocationAttributes & SEC_IMAGE)
+   {
+      return(MmCreateImageSection(SectionObject,
+                                  DesiredAccess,
+                                  ObjectAttributes,
+                                  MaximumSize,
+                                  SectionPageProtection,
+                                  AllocationAttributes,
+                                  FileHandle));
+   }
+
+   if (FileHandle != NULL)
+   {
+      return(MmCreateDataFileSection(SectionObject,
+                                     DesiredAccess,
+                                     ObjectAttributes,
+                                     MaximumSize,
+                                     SectionPageProtection,
+                                     AllocationAttributes,
+                                     FileHandle));
+   }
+
+   return(MmCreatePageFileSection(SectionObject,
+                                  DesiredAccess,
+                                  ObjectAttributes,
+                                  MaximumSize,
+                                  SectionPageProtection,
+                                  AllocationAttributes));
 }
 
 /* EOF */