Fixed the check for the MEM_TOP_DOWN flag in MmMapViewOfSection.
[reactos.git] / reactos / ntoskrnl / mm / section.c
index 9040d97..584c9da 100644 (file)
@@ -1,29 +1,47 @@
-/*
- *  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$
  *
  * 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 *****************************************************************/
@@ -56,9 +74,6 @@ 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)
@@ -68,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". */
@@ -136,6 +157,7 @@ MmFreePageTablesSectionSegment(PMM_SECTION_SEGMENT Segment)
 }
 
 VOID
+NTAPI
 MmFreeSectionSegments(PFILE_OBJECT FileObject)
 {
    if (FileObject->SectionObjectPointer->ImageSectionObject != NULL)
@@ -181,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)
@@ -213,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)
          {
@@ -229,6 +254,7 @@ MmSetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
 
 
 ULONG
+NTAPI
 MmGetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
                              ULONG Offset)
 {
@@ -259,6 +285,7 @@ MmGetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
 }
 
 VOID
+NTAPI
 MmSharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
                                ULONG Offset)
 {
@@ -284,6 +311,7 @@ MmSharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
 }
 
 BOOLEAN
+NTAPI
 MmUnsharePageEntrySectionSegment(PSECTION_OBJECT Section,
                                  PMM_SECTION_SEGMENT Segment,
                                  ULONG Offset,
@@ -383,7 +411,7 @@ 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;
@@ -432,6 +460,7 @@ BOOL MiIsPageFromCache(PMEMORY_AREA MemoryArea,
 }
 
 NTSTATUS
+NTAPI
 MiReadPage(PMEMORY_AREA MemoryArea,
            ULONG SegOffset,
            PPFN_TYPE Page)
@@ -547,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)
@@ -570,7 +599,7 @@ MiReadPage(PMEMORY_AREA MemoryArea,
                                        &CacheSeg);
          if (!NT_SUCCESS(Status))
          {
-            ExUnmapPage(PageAddr);
+            MmDeleteHyperspaceMapping(PageAddr);
             return(Status);
          }
          if (!UptoDate)
@@ -583,7 +612,7 @@ MiReadPage(PMEMORY_AREA MemoryArea,
             if (!NT_SUCCESS(Status))
             {
                CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE);
-               ExUnmapPage(PageAddr);
+               MmDeleteHyperspaceMapping(PageAddr);
                return Status;
             }
          }
@@ -597,12 +626,13 @@ 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,
@@ -636,7 +666,8 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
    }
 
    PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
-   Offset = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress;
+   Offset = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress 
+            + MemoryArea->Data.SectionData.ViewOffset;
 
    Segment = MemoryArea->Data.SectionData.Segment;
    Section = MemoryArea->Data.SectionData.Section;
@@ -665,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");
@@ -728,7 +759,7 @@ 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);
@@ -739,7 +770,10 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
 
          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,
@@ -749,7 +783,7 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
             DbgPrint("Unable to create virtual mapping\n");
             KEBUGCHECK(0);
          }
-         MmInsertRmap(Page, MemoryArea->Process, (PVOID)PAddress);
+         MmInsertRmap(Page, AddressSpace->Process, (PVOID)PAddress);
       }
       if (Locked)
       {
@@ -840,15 +874,15 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
       /*
       * Just map the desired physical page
       */
-      Page = (Offset + MemoryArea->Data.SectionData.ViewOffset) >> PAGE_SHIFT;
-      Status = MmCreateVirtualMapping(AddressSpace->Process,
-                                      Address,
-                                      Region->Protect,
-                                      &Page,
-                                      1);
+      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);
       }
@@ -858,7 +892,7 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
       */
       if (Locked)
       {
-         MmLockPage(Page);
+         MmLockPageUnsafe(Page);
       }
 
       /*
@@ -873,7 +907,7 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
    /*
     * Map anonymous memory for BSS sections
     */
-   if (Segment->Characteristics & IMAGE_SCN_LNK_OTHER)
+   if (Segment->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
    {
       MmUnlockSectionSegment(Segment);
       Status = MmRequestPageMemoryConsumer(MC_USER, FALSE, &Page);
@@ -916,7 +950,6 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
    /*
     * Get the entry corresponding to the offset within the section
     */
-   Offset += MemoryArea->Data.SectionData.ViewOffset;
    Entry = MmGetPageEntrySectionSegment(Segment, Offset);
 
    if (Entry == 0)
@@ -1118,6 +1151,7 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
 }
 
 NTSTATUS
+NTAPI
 MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
                          MEMORY_AREA* MemoryArea,
                          PVOID Address,
@@ -1127,7 +1161,6 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
    PSECTION_OBJECT Section;
    PFN_TYPE OldPage;
    PFN_TYPE NewPage;
-   PVOID NewAddress;
    NTSTATUS Status;
    PVOID PAddress;
    ULONG Offset;
@@ -1149,7 +1182,8 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
     * Find the offset of the page
     */
    PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
-   Offset = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress;
+   Offset = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress 
+            + MemoryArea->Data.SectionData.ViewOffset;
 
    Segment = MemoryArea->Data.SectionData.Segment;
    Section = MemoryArea->Data.SectionData.Section;
@@ -1188,7 +1222,7 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
    /*
     * 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)
    {
@@ -1242,11 +1276,9 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
    /*
     * Copy the old page
     */
+   MiCopyFromUserPage(NewPage, PAddress);
 
-   NewAddress = ExAllocatePageWithPhysPage(NewPage);
-   memcpy(NewAddress, PAddress, PAGE_SIZE);
-   ExUnmapPage(NewAddress);
-
+   MmLockAddressSpace(AddressSpace);
    /*
     * Delete the old entry.
     */
@@ -1255,7 +1287,6 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
    /*
     * Set the PTE to point to the new page
     */
-   MmLockAddressSpace(AddressSpace);
    Status = MmCreateVirtualMapping(AddressSpace->Process,
                                    Address,
                                    Region->Protect,
@@ -1267,7 +1298,6 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
       KEBUGCHECK(0);
       return(Status);
    }
-   MmInsertRmap(NewPage, AddressSpace->Process, PAddress);
    if (!NT_SUCCESS(Status))
    {
       DbgPrint("Unable to create virtual mapping\n");
@@ -1283,6 +1313,7 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
     * Unshare the old page.
     */
    MmDeleteRmap(OldPage, AddressSpace->Process, PAddress);
+   MmInsertRmap(NewPage, AddressSpace->Process, PAddress);
    MmLockSectionSegment(Segment);
    MmUnsharePageEntrySectionSegment(Section, Segment, Offset, FALSE, FALSE);
    MmUnlockSectionSegment(Segment);
@@ -1301,6 +1332,11 @@ MmPageOutDeleteMapping(PVOID Context, PEPROCESS Process, PVOID Address)
    PFN_TYPE Page;
 
    PageOutContext = (MM_SECTION_PAGEOUT_CONTEXT*)Context;
+   if (Process)
+   {
+      MmLockAddressSpace(&Process->AddressSpace);
+   }
+
    MmDeleteVirtualMapping(Process,
                           Address,
                           FALSE,
@@ -1312,21 +1348,29 @@ MmPageOutDeleteMapping(PVOID Context, PEPROCESS Process, PVOID Address)
    }
    if (!PageOutContext->Private)
    {
+      MmLockSectionSegment(PageOutContext->Segment);
       MmUnsharePageEntrySectionSegment(PageOutContext->Section,
                                        PageOutContext->Segment,
                                        PageOutContext->Offset,
                                        PageOutContext->WasDirty,
                                        TRUE);
+      MmUnlockSectionSegment(PageOutContext->Segment);
    }
-   else
+   if (Process)
+   {
+      MmUnlockAddressSpace(&Process->AddressSpace);
+   }
+   
+   if (PageOutContext->Private)
    {
       MmReleasePageMemoryConsumer(MC_USER, Page);
    }
 
-   DPRINT("PhysicalAddress %I64x, Address %x\n", Page, Address);
+   DPRINT("PhysicalAddress %x, Address %x\n", Page << PAGE_SHIFT, Address);
 }
 
 NTSTATUS
+NTAPI
 MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
                      MEMORY_AREA* MemoryArea,
                      PVOID Address,
@@ -1351,7 +1395,8 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
    Context.Segment = MemoryArea->Data.SectionData.Segment;
    Context.Section = MemoryArea->Data.SectionData.Section;
 
-   Context.Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress;
+   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;
@@ -1405,7 +1450,7 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
     * Prepare the context structure for the rmap delete call.
     */
    Context.WasDirty = FALSE;
-   if (Context.Segment->Characteristics & IMAGE_SCN_LNK_OTHER ||
+   if (Context.Segment->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ||
          IS_SWAP_FROM_SSE(Entry) ||
          PFN_FROM_SSE(Entry) != Page)
    {
@@ -1528,9 +1573,11 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
    else if (!Context.WasDirty && Context.Private && SwapEntry != 0)
    {
       MmSetSavedSwapEntryPage(Page, 0);
+      MmLockAddressSpace(AddressSpace);
       Status = MmCreatePageFileMapping(AddressSpace->Process,
                                        Address,
                                        SwapEntry);
+      MmUnlockAddressSpace(AddressSpace);
       if (!NT_SUCCESS(Status))
       {
          KEBUGCHECK(0);
@@ -1550,20 +1597,20 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
       if (SwapEntry == 0)
       {
          MmShowOutOfSpaceMessagePagingFile();
-
+         MmLockAddressSpace(AddressSpace);
          /*
           * For private pages restore the old mappings.
           */
          if (Context.Private)
          {
-            Status = MmCreateVirtualMapping(MemoryArea->Process,
+            Status = MmCreateVirtualMapping(AddressSpace->Process,
                                             Address,
                                             MemoryArea->Attributes,
                                             &Page,
                                             1);
-            MmSetDirtyPage(MemoryArea->Process, Address);
+            MmSetDirtyPage(AddressSpace->Process, Address);
             MmInsertRmap(Page,
-                         MemoryArea->Process,
+                         AddressSpace->Process,
                          Address);
          }
          else
@@ -1573,18 +1620,19 @@ 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,
                                             &Page,
                                             1);
-            MmSetDirtyPage(MemoryArea->Process, Address);
+            MmSetDirtyPage(AddressSpace->Process, Address);
             MmInsertRmap(Page,
-                         MemoryArea->Process,
+                         AddressSpace->Process,
                          Address);
             Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
             MmSetPageEntrySectionSegment(Context.Segment, Context.Offset, Entry);
          }
+         MmUnlockAddressSpace(AddressSpace);
          PageOp->Status = STATUS_UNSUCCESSFUL;
          MmspCompleteAndReleasePageOp(PageOp);
          return(STATUS_PAGEFILE_QUOTA);
@@ -1603,32 +1651,34 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
        * As above: undo our actions.
        * FIXME: Also free the swap page.
        */
+      MmLockAddressSpace(AddressSpace);
       if (Context.Private)
       {
-         Status = MmCreateVirtualMapping(MemoryArea->Process,
+         Status = MmCreateVirtualMapping(AddressSpace->Process,
                                          Address,
                                          MemoryArea->Attributes,
                                          &Page,
                                          1);
-         MmSetDirtyPage(MemoryArea->Process, Address);
+         MmSetDirtyPage(AddressSpace->Process, Address);
          MmInsertRmap(Page,
-                      MemoryArea->Process,
+                      AddressSpace->Process,
                       Address);
       }
       else
       {
-         Status = MmCreateVirtualMapping(MemoryArea->Process,
+         Status = MmCreateVirtualMapping(AddressSpace->Process,
                                          Address,
                                          MemoryArea->Attributes,
                                          &Page,
                                          1);
-         MmSetDirtyPage(MemoryArea->Process, Address);
+         MmSetDirtyPage(AddressSpace->Process, Address);
          MmInsertRmap(Page,
-                      MemoryArea->Process,
+                      AddressSpace->Process,
                       Address);
          Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
          MmSetPageEntrySectionSegment(Context.Segment, Context.Offset, Entry);
       }
+      MmUnlockAddressSpace(AddressSpace);
       PageOp->Status = STATUS_UNSUCCESSFUL;
       MmspCompleteAndReleasePageOp(PageOp);
       return(STATUS_UNSUCCESSFUL);
@@ -1651,9 +1701,11 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
 
    if (Context.Private)
    {
-      Status = MmCreatePageFileMapping(MemoryArea->Process,
+      MmLockAddressSpace(AddressSpace);
+      Status = MmCreatePageFileMapping(AddressSpace->Process,
                                        Address,
                                        SwapEntry);
+      MmUnlockAddressSpace(AddressSpace);
       if (!NT_SUCCESS(Status))
       {
          KEBUGCHECK(0);
@@ -1671,6 +1723,7 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
 }
 
 NTSTATUS
+NTAPI
 MmWritePageSectionView(PMADDRESS_SPACE AddressSpace,
                        PMEMORY_AREA MemoryArea,
                        PVOID Address,
@@ -1691,7 +1744,8 @@ MmWritePageSectionView(PMADDRESS_SPACE AddressSpace,
 
    Address = (PVOID)PAGE_ROUND_DOWN(Address);
 
-   Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress;
+   Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress 
+            + MemoryArea->Data.SectionData.ViewOffset;
 
    /*
     * Get the segment and section.
@@ -1712,7 +1766,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;
@@ -1747,7 +1801,7 @@ MmWritePageSectionView(PMADDRESS_SPACE AddressSpace,
    /*
     * Check for a private (COWed) page.
     */
-   if (Segment->Characteristics & IMAGE_SCN_LNK_OTHER ||
+   if (Segment->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ||
          IS_SWAP_FROM_SSE(Entry) ||
          PFN_FROM_SSE(Entry) != Page)
    {
@@ -1770,7 +1824,7 @@ MmWritePageSectionView(PMADDRESS_SPACE AddressSpace,
    if (DirectMapped && !Private)
    {
       ASSERT(SwapEntry == 0);
-      CcRosMarkDirtyCacheSegment(Bcb, Offset + MemoryArea->Data.SectionData.ViewOffset);
+      CcRosMarkDirtyCacheSegment(Bcb, Offset + Segment->FileOffset);
       PageOp->Status = STATUS_SUCCESS;
       MmspCompleteAndReleasePageOp(PageOp);
       return(STATUS_SUCCESS);
@@ -1855,12 +1909,13 @@ MmAlterViewAttributes(PMADDRESS_SPACE AddressSpace,
             ULONG Entry;
             PFN_TYPE Page;
 
-            Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress;
+            Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress 
+                     + MemoryArea->Data.SectionData.ViewOffset;
             Entry = MmGetPageEntrySectionSegment(Segment, Offset);
             Page = MmGetPfnForProcess(AddressSpace->Process, Address);
 
             Protect = PAGE_READONLY;
-            if (Segment->Characteristics & IMAGE_SCN_LNK_OTHER ||
+            if (Segment->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ||
                   IS_SWAP_FROM_SSE(Entry) ||
                   PFN_FROM_SSE(Entry) != Page)
             {
@@ -1878,6 +1933,7 @@ MmAlterViewAttributes(PMADDRESS_SPACE AddressSpace,
 }
 
 NTSTATUS
+NTAPI
 MmProtectSectionView(PMADDRESS_SPACE AddressSpace,
                      PMEMORY_AREA MemoryArea,
                      PVOID BaseAddress,
@@ -1914,9 +1970,7 @@ MmQuerySectionView(PMEMORY_AREA MemoryArea,
    PMM_REGION Region;
    PVOID RegionBaseAddress;
    PSECTION_OBJECT Section;
-   PLIST_ENTRY CurrentEntry;
-   PMEMORY_AREA CurrentMArea;
-   KIRQL oldIrql;
+   PMM_SECTION_SEGMENT Segment;
 
    Region = MmFindRegion((PVOID)MemoryArea->StartingAddress,
                          &MemoryArea->Data.SectionData.RegionListHead,
@@ -1925,39 +1979,22 @@ MmQuerySectionView(PMEMORY_AREA MemoryArea,
    {
       return STATUS_UNSUCCESSFUL;
    }
+
    Section = MemoryArea->Data.SectionData.Section;
    if (Section->AllocationAttributes & SEC_IMAGE)
    {
-      KeAcquireSpinLock(&Section->ViewListLock, &oldIrql);
-      CurrentEntry = Section->ViewListHead.Flink;
-      Info->AllocationBase = NULL;
-      while (CurrentEntry != &Section->ViewListHead)
-      {
-         CurrentMArea = CONTAINING_RECORD(CurrentEntry, MEMORY_AREA, Data.SectionData.ViewListEntry);
-         CurrentEntry = CurrentEntry->Flink;
-         if (Info->AllocationBase == NULL)
-         {
-            Info->AllocationBase = CurrentMArea->StartingAddress;
-         }
-         else if (CurrentMArea->StartingAddress < Info->AllocationBase)
-         {
-            Info->AllocationBase = CurrentMArea->StartingAddress;
-         }
-      }
-      KeReleaseSpinLock(&Section->ViewListLock, oldIrql);
-      Info->BaseAddress = RegionBaseAddress;
-      Info->AllocationProtect = MemoryArea->Attributes;
+      Segment = MemoryArea->Data.SectionData.Segment;
+      Info->AllocationBase = (PBYTE)MemoryArea->StartingAddress - Segment->VirtualAddress;
       Info->Type = MEM_IMAGE;
    }
    else
    {
-      Info->BaseAddress = RegionBaseAddress;
       Info->AllocationBase = MemoryArea->StartingAddress;
-      Info->AllocationProtect = MemoryArea->Attributes;
       Info->Type = MEM_MAPPED;
    }
-   Info->RegionSize = PAGE_ROUND_UP((ULONG_PTR)MemoryArea->EndingAddress -
-                                    (ULONG_PTR)MemoryArea->StartingAddress);
+   Info->BaseAddress = RegionBaseAddress;
+   Info->AllocationProtect = MemoryArea->Attributes;
+   Info->RegionSize = Region->Length;
    Info->State = MEM_COMMIT;
    Info->Protect = Region->Protect;
 
@@ -1966,6 +2003,7 @@ MmQuerySectionView(PMEMORY_AREA MemoryArea,
 }
 
 VOID
+NTAPI
 MmpFreePageFileSegment(PMM_SECTION_SEGMENT Segment)
 {
    ULONG Length;
@@ -2081,34 +2119,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)
 {
    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;
 
    /*
@@ -2117,7 +2136,7 @@ MmCreatePhysicalMemorySection(VOID)
    SectionSize.QuadPart = 0xFFFFFFFF;
    InitializeObjectAttributes(&Obj,
                               &Name,
-                              0,
+                              OBJ_PERMANENT,
                               NULL,
                               NULL);
    Status = MmCreateSection(&PhysSection,
@@ -2133,48 +2152,49 @@ MmCreatePhysicalMemorySection(VOID)
       DbgPrint("Failed to create PhysicalMemory section\n");
       KEBUGCHECK(0);
    }
+   Status = ObInsertObject(PhysSection,
+                           NULL,
+                           SECTION_ALL_ACCESS,
+                           0,
+                           NULL,
+                           NULL);
+   if (!NT_SUCCESS(Status))
+   {
+      ObDereferenceObject(PhysSection);
+   }
    PhysSection->AllocationAttributes |= SEC_PHYSICALMEMORY;
+   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;
+   OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
+   UNICODE_STRING Name;
 
-   /*
-    * 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);
+   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
+NTAPI
 MmCreatePageFileSection(PSECTION_OBJECT *SectionObject,
                         ACCESS_MASK DesiredAccess,
                         POBJECT_ATTRIBUTES ObjectAttributes,
@@ -2219,8 +2239,6 @@ MmCreatePageFileSection(PSECTION_OBJECT *SectionObject,
    Section->SectionPageProtection = SectionPageProtection;
    Section->AllocationAttributes = AllocationAttributes;
    Section->Segment = NULL;
-   InitializeListHead(&Section->ViewListHead);
-   KeInitializeSpinLock(&Section->ViewListLock);
    Section->FileObject = NULL;
    Section->MaximumSize = MaximumSize;
    Segment = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_SECTION_SEGMENT),
@@ -2248,6 +2266,7 @@ MmCreatePageFileSection(PSECTION_OBJECT *SectionObject,
 
 
 NTSTATUS
+NTAPI
 MmCreateDataFileSection(PSECTION_OBJECT *SectionObject,
                         ACCESS_MASK DesiredAccess,
                         POBJECT_ATTRIBUTES ObjectAttributes,
@@ -2286,15 +2305,12 @@ MmCreateDataFileSection(PSECTION_OBJECT *SectionObject,
    {
       return(Status);
    }
-
    /*
     * Initialize it
     */
    Section->SectionPageProtection = SectionPageProtection;
    Section->AllocationAttributes = AllocationAttributes;
    Section->Segment = NULL;
-   InitializeListHead(&Section->ViewListHead);
-   KeInitializeSpinLock(&Section->ViewListLock);
 
    /*
     * Check file access required
@@ -2330,11 +2346,11 @@ MmCreateDataFileSection(PSECTION_OBJECT *SectionObject,
     * (as in case of the EXT2FS driver by Manoj Paul Joseph where the
     * standard file information is filled on first request).
     */
-   Status = NtQueryInformationFile(FileHandle,
-                                   &Iosb,
-                                   &FileInfo,
+   Status = IoQueryFileInformation(FileObject,
+                                   FileStandardInformation,
                                    sizeof(FILE_STANDARD_INFORMATION),
-                                   FileStandardInformation);
+                                   &FileInfo,
+                                   &Iosb.Information);
    if (!NT_SUCCESS(Status))
    {
       ObDereferenceObject(Section);
@@ -2364,11 +2380,10 @@ MmCreateDataFileSection(PSECTION_OBJECT *SectionObject,
 
    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))
       {
          ObDereferenceObject(Section);
@@ -2583,7 +2598,6 @@ ExeFmtpReadFile(IN PVOID File,
       KEBUGCHECK(STATUS_INVALID_PARAMETER_5);
    }
 
-   ASSERT(PAGE_SIZE <= MAXULONG);
    AdjustOffset = PAGE_ROUND_DOWN(FileOffset.u.LowPart);
    OffsetAdjustment = FileOffset.u.LowPart - AdjustOffset;
    FileOffset.u.LowPart = AdjustOffset;
@@ -2628,7 +2642,7 @@ ExeFmtpReadFile(IN PVOID File,
                           BufferSize,
                           &FileOffset,
                           NULL);
-   
+
       if(NT_SUCCESS(Status))
       {
          UsedSize = Iosb.Information;
@@ -2786,7 +2800,7 @@ MmspCheckSegmentBounds
           * 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 
+          * (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 +
@@ -2817,6 +2831,7 @@ MmspPageAlignSegments
    ULONG i;
    ULONG LastSegment;
    BOOLEAN Initialized;
+   PMM_SECTION_SEGMENT EffectiveSegment;
 
    if (Flags & EXEFMT_LOAD_ASSUME_SEGMENTS_PAGE_ALIGNED)
    {
@@ -2826,11 +2841,10 @@ MmspPageAlignSegments
 
    Initialized = FALSE;
    LastSegment = 0;
+   EffectiveSegment = &ImageSectionObject->Segments[LastSegment];
 
    for ( i = 0; i < ImageSectionObject->NrSegments; ++ i )
    {
-      PMM_SECTION_SEGMENT EffectiveSegment = &ImageSectionObject->Segments[LastSegment];
-
       /*
        * The first segment requires special handling
        */
@@ -2840,25 +2854,25 @@ MmspPageAlignSegments
          ULONG_PTR VirtualOffset;
 
          VirtualAddress = EffectiveSegment->VirtualAddress;
-   
+
          /* 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)
          {
             return FALSE;
          }
-   
+
          /*
-          * Garbage in, garbage out: unaligned base addresses make the file 
-          * offset point in curious and odd places, but that's what we were 
+          * 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
           */
          EffectiveSegment->FileOffset -= VirtualOffset;
@@ -2871,7 +2885,7 @@ MmspPageAlignSegments
 
          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
@@ -2884,11 +2898,14 @@ MmspPageAlignSegments
 
             EffectiveSegment = &ImageSectionObject->Segments[LastSegment];
 
-            /*
-             * Copy the current segment. If necessary, the effective segment
-             * will be expanded later
-             */
-            *EffectiveSegment = *Segment;
+            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
@@ -2928,24 +2945,24 @@ MmspPageAlignSegments
             /*
              * 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);
-   
+            ASSERT(PAGE_ROUND_UP(Segment->VirtualAddress + Segment->Length) >= EndOfEffectiveSegment);
+
             EffectiveSegment->Length = PAGE_ROUND_UP(Segment->VirtualAddress + Segment->Length) -
                                        EffectiveSegment->VirtualAddress;
-   
+
             /*
              * Merge the protection
              */
@@ -2985,6 +3002,7 @@ MmspPageAlignSegments
          }
       }
    }
+   ImageSectionObject->NrSegments = LastSegment + 1;
 
    return TRUE;
 }
@@ -3062,7 +3080,7 @@ ExeFmtpCreateImageSection(HANDLE FileHandle,
     */
    if (Status == STATUS_ROS_EXEFMT_UNKNOWN_FORMAT)
    {
-      Status = STATUS_INVALID_IMAGE_FORMAT;
+      Status = STATUS_INVALID_IMAGE_NOT_MZ;
       ASSERT(!NT_SUCCESS(Status));
    }
 
@@ -3077,10 +3095,10 @@ ExeFmtpCreateImageSection(HANDLE FileHandle,
    /* 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)
@@ -3114,7 +3132,7 @@ ExeFmtpCreateImageSection(HANDLE FileHandle,
 
       SizeOfSegments = sizeof(MM_SECTION_SEGMENT) * ImageSectionObject->NrSegments;
 
-      Segments = ExAllocatePoolWithTag(NonPagedPool,
+      Segments = ExAllocatePoolWithTag(PagedPool,
                                        SizeOfSegments,
                                        TAG_MM_SECTION_SEGMENT);
 
@@ -3187,6 +3205,7 @@ MmCreateImageSection(PSECTION_OBJECT *SectionObject,
                                       UserMode,
                                       (PVOID*)(PVOID)&FileObject,
                                       NULL);
+
    if (!NT_SUCCESS(Status))
    {
       return Status;
@@ -3215,8 +3234,6 @@ MmCreateImageSection(PSECTION_OBJECT *SectionObject,
     */
    Section->SectionPageProtection = SectionPageProtection;
    Section->AllocationAttributes = AllocationAttributes;
-   InitializeListHead(&Section->ViewListHead);
-   KeInitializeSpinLock(&Section->ViewListLock);
 
    /*
     * Initialized caching for this file object if previously caching
@@ -3228,13 +3245,15 @@ MmCreateImageSection(PSECTION_OBJECT *SectionObject,
    {
       NTSTATUS StatusExeFmt;
 
-      ImageSectionObject = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_IMAGE_SECTION_OBJECT), TAG_MM_SECTION_SEGMENT);
+      ImageSectionObject = ExAllocatePoolWithTag(PagedPool, sizeof(MM_IMAGE_SECTION_OBJECT), TAG_MM_SECTION_SEGMENT);
       if (ImageSectionObject == NULL)
       {
          ObDereferenceObject(FileObject);
          ObDereferenceObject(Section);
          return(STATUS_NO_MEMORY);
       }
+      
+      RtlZeroMemory(ImageSectionObject, sizeof(MM_IMAGE_SECTION_OBJECT));
 
       StatusExeFmt = ExeFmtpCreateImageSection(FileHandle, ImageSectionObject);
 
@@ -3265,8 +3284,8 @@ MmCreateImageSection(PSECTION_OBJECT *SectionObject,
          return(Status);
       }
 
-      if (0 != InterlockedCompareExchangeUL(&FileObject->SectionObjectPointer->ImageSectionObject,
-                                            ImageSectionObject, 0))
+      if (NULL != InterlockedCompareExchangePointer(&FileObject->SectionObjectPointer->ImageSectionObject,
+                                                    ImageSectionObject, NULL))
       {
          /*
           * An other thread has initialized the some image in the background
@@ -3331,8 +3350,32 @@ NtCreateSection (OUT PHANDLE SectionHandle,
                  IN ULONG AllocationAttributes,
                  IN HANDLE FileHandle OPTIONAL)
 {
+   LARGE_INTEGER SafeMaximumSize;
    PSECTION_OBJECT SectionObject;
-   NTSTATUS Status;
+   KPROCESSOR_MODE PreviousMode;
+   NTSTATUS Status = STATUS_SUCCESS;
+
+   PreviousMode = ExGetPreviousMode();
+
+   if(MaximumSize != NULL && PreviousMode != KernelMode)
+   {
+     _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;
+     }
+   }
 
    /*
     * Check the protection
@@ -3389,17 +3432,50 @@ NtOpenSection(PHANDLE   SectionHandle,
               ACCESS_MASK  DesiredAccess,
               POBJECT_ATTRIBUTES ObjectAttributes)
 {
-   NTSTATUS Status;
+   HANDLE hSection;
+   KPROCESSOR_MODE PreviousMode;
+   NTSTATUS Status = STATUS_SUCCESS;
 
-   *SectionHandle = 0;
+   PreviousMode = ExGetPreviousMode();
+
+   if(PreviousMode != KernelMode)
+   {
+     _SEH_TRY
+     {
+       ProbeForWriteHandle(SectionHandle);
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
+
+     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);
 }
@@ -3417,7 +3493,6 @@ MmMapViewOfSegment(PEPROCESS Process,
 {
    PMEMORY_AREA MArea;
    NTSTATUS Status;
-   KIRQL oldIrql;
    PHYSICAL_ADDRESS BoundaryAddressMultiple;
 
    BoundaryAddressMultiple.QuadPart = 0;
@@ -3439,10 +3514,6 @@ MmMapViewOfSegment(PEPROCESS Process,
       return(Status);
    }
 
-   KeAcquireSpinLock(&Section->ViewListLock, &oldIrql);
-   InsertTailList(&Section->ViewListHead,
-                  &MArea->Data.SectionData.ViewListEntry);
-   KeReleaseSpinLock(&Section->ViewListLock, oldIrql);
 
    ObReferenceObjectByPointer((PVOID)Section,
                               SECTION_MAP_READ,
@@ -3509,26 +3580,71 @@ 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,
+                                      PreviousMode,
                                       (PVOID*)(PVOID)&Process,
                                       NULL);
    if (!NT_SUCCESS(Status))
@@ -3541,7 +3657,7 @@ NtMapViewOfSection(HANDLE SectionHandle,
    Status = ObReferenceObjectByHandle(SectionHandle,
                                       SECTION_MAP_READ,
                                       MmSectionObjectType,
-                                      UserMode,
+                                      PreviousMode,
                                       (PVOID*)(PVOID)&Section,
                                       NULL);
    if (!(NT_SUCCESS(Status)))
@@ -3553,11 +3669,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);
@@ -3565,6 +3681,31 @@ 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);
 }
 
@@ -3572,7 +3713,6 @@ VOID STATIC
 MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
                   PFN_TYPE Page, SWAPENTRY SwapEntry, BOOLEAN Dirty)
 {
-   PMEMORY_AREA MArea;
    ULONG Entry;
    PFILE_OBJECT FileObject;
    PBCB Bcb;
@@ -3582,23 +3722,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_PTR)Address - (ULONG_PTR)MArea->StartingAddress) +
+   Offset = ((ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress) +
             MemoryArea->Data.SectionData.ViewOffset;
 
-   Section = MArea->Data.SectionData.Section;
-   Segment = MArea->Data.SectionData.Segment;
+   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)
@@ -3607,10 +3748,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);
@@ -3625,7 +3766,7 @@ MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
       {
          FileObject = MemoryArea->Data.SectionData.Section->FileObject;
          Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
-         CcRosMarkDirtyCacheSegment(Bcb, Offset);
+         CcRosMarkDirtyCacheSegment(Bcb, Offset + Segment->FileOffset);
          ASSERT(SwapEntry == 0);
       }
    }
@@ -3664,18 +3805,18 @@ MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
             MmFreeSwapPage(SavedSwapEntry);
             MmSetSavedSwapEntryPage(Page, 0);
          }
-         MmDeleteRmap(Page, MArea->Process, Address);
+         MmDeleteRmap(Page, AddressSpace->Process, Address);
          MmReleasePageMemoryConsumer(MC_USER, Page);
       }
       else
       {
-         MmDeleteRmap(Page, MArea->Process, Address);
+         MmDeleteRmap(Page, AddressSpace->Process, Address);
          MmUnsharePageEntrySectionSegment(Section, Segment, Offset, Dirty, FALSE);
       }
    }
 }
 
-NTSTATUS
+STATIC NTSTATUS
 MmUnmapViewOfSegment(PMADDRESS_SPACE AddressSpace,
                      PVOID BaseAddress)
 {
@@ -3683,7 +3824,6 @@ 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;
@@ -3700,9 +3840,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))
@@ -3724,7 +3861,7 @@ MmUnmapViewOfSegment(PMADDRESS_SPACE AddressSpace,
       Status = MmFreeMemoryArea(AddressSpace,
                                 MemoryArea,
                                 MmFreeSectionPage,
-                                MemoryArea);
+                                AddressSpace);
    }
    MmUnlockSectionSegment(Segment);
    ObDereferenceObject(Section);
@@ -3742,6 +3879,8 @@ MmUnmapViewOfSection(PEPROCESS Process,
    PMEMORY_AREA MemoryArea;
    PMADDRESS_SPACE AddressSpace;
    PSECTION_OBJECT Section;
+   PMM_PAGEOP PageOp;
+   ULONG_PTR Offset;
 
    DPRINT("Opening memory area Process %x BaseAddress %x\n",
           Process, BaseAddress);
@@ -3749,15 +3888,53 @@ MmUnmapViewOfSection(PEPROCESS Process,
    ASSERT(Process);
 
    AddressSpace = &Process->AddressSpace;
+   
+   MmLockAddressSpace(AddressSpace);
    MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace,
                                             BaseAddress);
    if (MemoryArea == NULL ||
        MemoryArea->Type != MEMORY_AREA_SECTION_VIEW ||
        MemoryArea->DeleteInProgress)
    {
+      MmUnlockAddressSpace(AddressSpace);
       return STATUS_NOT_MAPPED_VIEW;
    }
 
+   MemoryArea->DeleteInProgress = TRUE;
+
+   while (MemoryArea->PageOpCount)
+   {
+      Offset = PAGE_ROUND_UP((ULONG_PTR)MemoryArea->EndingAddress - (ULONG_PTR)MemoryArea->StartingAddress);
+
+      while (Offset)
+      {
+         Offset -= PAGE_SIZE;
+         PageOp = MmCheckForPageOp(MemoryArea, NULL, NULL,
+                                   MemoryArea->Data.SectionData.Segment,
+                                   Offset + MemoryArea->Data.SectionData.ViewOffset);
+         if (PageOp)
+         {
+            MmUnlockAddressSpace(AddressSpace);
+            Status = MmspWaitForPageOpCompletionEvent(PageOp);
+            if (Status != STATUS_SUCCESS)
+            {
+               DPRINT1("Failed to wait for page op, status = %x\n", Status);
+               KEBUGCHECK(0);
+            }
+            MmLockAddressSpace(AddressSpace);
+            MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace,
+                                                     BaseAddress);
+            if (MemoryArea == NULL ||
+                MemoryArea->Type != MEMORY_AREA_SECTION_VIEW)
+            {
+               MmUnlockAddressSpace(AddressSpace);
+               return STATUS_NOT_MAPPED_VIEW;
+            }
+            break;
+         }
+      }
+   }
+
    Section = MemoryArea->Data.SectionData.Section;
 
    if (Section->AllocationAttributes & SEC_IMAGE)
@@ -3807,6 +3984,7 @@ MmUnmapViewOfSection(PEPROCESS Process,
    {
       Status = MmUnmapViewOfSegment(AddressSpace, BaseAddress);
    }
+   MmUnlockAddressSpace(AddressSpace);
    return(STATUS_SUCCESS);
 }
 
@@ -3831,16 +4009,19 @@ 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,
+                                      PreviousMode,
                                       (PVOID*)(PVOID)&Process,
                                       NULL);
    if (!NT_SUCCESS(Status))
@@ -3849,9 +4030,7 @@ NtUnmapViewOfSection (HANDLE ProcessHandle,
       return(Status);
    }
 
-   MmLockAddressSpace(&Process->AddressSpace);
    Status = MmUnmapViewOfSection(Process, BaseAddress);
-   MmUnlockAddressSpace(&Process->AddressSpace);
 
    ObDereferenceObject(Process);
 
@@ -3861,7 +4040,7 @@ NtUnmapViewOfSection (HANDLE ProcessHandle,
 
 /**
  * Queries the information of a section object.
- * 
+ *
  * @param SectionHandle
  *        Handle to the section object. It must be opened with SECTION_QUERY
  *        access.
@@ -3879,105 +4058,127 @@ NtUnmapViewOfSection (HANDLE ProcessHandle,
  *
  * @return Status.
  *
- * @todo Guard by SEH.
  * @implemented
  */
 NTSTATUS STDCALL
 NtQuerySection(IN HANDLE SectionHandle,
-               IN CINT SectionInformationClass,
+               IN SECTION_INFORMATION_CLASS SectionInformationClass,
                OUT PVOID SectionInformation,
-               IN ULONG Length,
-               OUT PULONG ResultLength)
+               IN ULONG SectionInformationLength,
+               OUT PULONG ResultLength  OPTIONAL)
 {
    PSECTION_OBJECT Section;
-   NTSTATUS Status;
+   KPROCESSOR_MODE PreviousMode;
+   NTSTATUS Status = STATUS_SUCCESS;
+
+   PreviousMode = ExGetPreviousMode();
+
+   Status = DefaultQueryInfoBufferCheck(SectionInformationClass,
+                                        ExSectionInfoClass,
+                                        sizeof(ExSectionInfoClass) / sizeof(ExSectionInfoClass[0]),
+                                        SectionInformation,
+                                        SectionInformationLength,
+                                        ResultLength,
+                                        PreviousMode);
+
+   if(!NT_SUCCESS(Status))
+   {
+     DPRINT1("NtQuerySection() failed, Status: 0x%x\n", Status);
+     return Status;
+   }
 
    Status = ObReferenceObjectByHandle(SectionHandle,
                                       SECTION_QUERY,
                                       MmSectionObjectType,
-                                      UserMode,
+                                      PreviousMode,
                                       (PVOID*)(PVOID)&Section,
                                       NULL);
-   if (!(NT_SUCCESS(Status)))
-   {
-      return(Status);
-   }
-
-   switch (SectionInformationClass)
+   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->Attributes = Section->AllocationAttributes;
-            if (Section->AllocationAttributes & SEC_IMAGE)
-            {
-               Sbi->BaseAddress = 0;
-               Sbi->Size.QuadPart = 0;
+               if (ResultLength != NULL)
+               {
+                  *ResultLength = sizeof(SECTION_BASIC_INFORMATION);
+               }
+               Status = STATUS_SUCCESS;
             }
-            else
+            _SEH_HANDLE
             {
-               Sbi->BaseAddress = (PVOID)Section->Segment->VirtualAddress;
-               Sbi->Size.QuadPart = Section->Segment->Length;
+               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 = ImageSectionObject->MinorSubsystemVersion;
-               Sii->MajorSubsystemVersion = 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.
@@ -3986,7 +4187,6 @@ NtQuerySection(IN HANDLE SectionHandle,
  *
  * @return Status.
  *
- * @todo Guard by SEH.
  * @todo Move the actual code to internal function MmExtendSection.
  * @unimplemented
  */
@@ -3994,13 +4194,37 @@ NTSTATUS STDCALL
 NtExtendSection(IN HANDLE SectionHandle,
                 IN PLARGE_INTEGER NewMaximumSize)
 {
+   LARGE_INTEGER SafeNewMaximumSize;
    PSECTION_OBJECT Section;
-   NTSTATUS Status;
+   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,
-                                      UserMode,
+                                      PreviousMode,
                                       (PVOID*)&Section,
                                       NULL);
    if (!NT_SUCCESS(Status))
@@ -4013,7 +4237,7 @@ NtExtendSection(IN HANDLE SectionHandle,
       ObfDereferenceObject(Section);
       return STATUS_INVALID_PARAMETER;
    }
-   
+
    /*
     * - Acquire file extneding resource.
     * - Check if we're not resizing the section below it's actual size!
@@ -4089,7 +4313,7 @@ MmAllocateSection (IN ULONG Length, PVOID BaseAddress)
          KEBUGCHECK(0);
       }
       Status = MmCreateVirtualMapping (NULL,
-                                       (PVOID)(Result + (i * PAGE_SIZE)),
+                                       (PVOID)((ULONG_PTR)Result + (i * PAGE_SIZE)),
                                        PAGE_READWRITE,
                                        &Page,
                                        1);
@@ -4201,9 +4425,9 @@ MmMapViewOfSection(IN PVOID SectionObject,
       {
          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);
          }
       }
@@ -4296,7 +4520,7 @@ MmMapViewOfSection(IN PVOID SectionObject,
                                   *ViewSize,
                                   Protect,
                                   ViewOffset,
-                                  (AllocationType & MEM_TOP_DOWN));
+                                  (AllocationType & MEM_TOP_DOWN) == MEM_TOP_DOWN);
       MmUnlockSectionSegment(Section->Segment);
       if (!NT_SUCCESS(Status))
       {