update for HEAD-2003091401
[reactos.git] / ntoskrnl / mm / section.c
index d4b5f53..a62e54c 100644 (file)
@@ -29,7 +29,8 @@
 /* INCLUDES *****************************************************************/
 
 #include <limits.h>
-#include <ddk/ntddk.h>
+#define NTOS_MODE_KERNEL
+#include <ntos.h>
 #include <internal/mm.h>
 #include <internal/io.h>
 #include <internal/ps.h>
@@ -47,7 +48,7 @@ typedef struct
 {
   PSECTION_OBJECT Section;
   PMM_SECTION_SEGMENT Segment;
-  LARGE_INTEGER Offset;
+  ULONG Offset;
   BOOLEAN WasDirty;
   BOOLEAN Private;
 } MM_SECTION_PAGEOUT_CONTEXT;
@@ -79,90 +80,72 @@ VOID
 MmFreePageTablesSectionSegment(PMM_SECTION_SEGMENT Segment)
 {
   ULONG i;
-
-  for (i = 0; i < NR_SECTION_PAGE_TABLES; i++)
+  if (Segment->Length > NR_SECTION_PAGE_TABLES * PAGE_SIZE)
     {
-      if (Segment->PageDirectory.PageTables[i] != NULL)
-       {
-         ExFreePool(Segment->PageDirectory.PageTables[i]);
-       }
+      for (i = 0; i < NR_SECTION_PAGE_TABLES; i++)
+        {
+          if (Segment->PageDirectory.PageTables[i] != NULL)
+           {
+             ExFreePool(Segment->PageDirectory.PageTables[i]);
+           }
+        }
     }
 }
 
 VOID
 MmFreeSectionSegments(PFILE_OBJECT FileObject)
 {
-  if (FileObject->SectionObjectPointers->ImageSectionObject != NULL)
+  if (FileObject->SectionObjectPointer->ImageSectionObject != NULL)
     {
       PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
-
+      PMM_SECTION_SEGMENT SectionSegments;
+      ULONG NrSegments;
       ULONG i;
 
-      ImageSectionObject = 
-       (PMM_IMAGE_SECTION_OBJECT)FileObject->SectionObjectPointers->
-       ImageSectionObject;
-      
-      for (i = 0; i < ImageSectionObject->NrSegments; i++)
+      ImageSectionObject = (PMM_IMAGE_SECTION_OBJECT)FileObject->SectionObjectPointer->ImageSectionObject;
+      NrSegments = ImageSectionObject->NrSegments;
+      SectionSegments = ImageSectionObject->Segments;
+      for (i = 0; i < NrSegments; i++)
        {
-         if (ImageSectionObject->Segments[i].ReferenceCount != 0)
+         if (SectionSegments[i].ReferenceCount != 0)
            {
              DPRINT1("Image segment %d still referenced (was %d)\n", i,
-                     ImageSectionObject->Segments[i].ReferenceCount);
-             KeBugCheck(0);
+                     SectionSegments[i].ReferenceCount);
+             KEBUGCHECK(0);
            }
-         MmFreePageTablesSectionSegment(&ImageSectionObject->Segments[i]);
+         MmFreePageTablesSectionSegment(&SectionSegments[i]);
        }
       ExFreePool(ImageSectionObject);
-      FileObject->SectionObjectPointers->ImageSectionObject = NULL;
+      FileObject->SectionObjectPointer->ImageSectionObject = NULL;
     }
-  if (FileObject->SectionObjectPointers->DataSectionObject != NULL)
+  if (FileObject->SectionObjectPointer->DataSectionObject != NULL)
     {
       PMM_SECTION_SEGMENT Segment;
 
-      Segment = (PMM_SECTION_SEGMENT)FileObject->SectionObjectPointers->
+      Segment = (PMM_SECTION_SEGMENT)FileObject->SectionObjectPointer->
        DataSectionObject;
 
       if (Segment->ReferenceCount != 0)
        {
          DPRINT1("Data segment still referenced\n");
-         KeBugCheck(0);
+         KEBUGCHECK(0);
        }
       MmFreePageTablesSectionSegment(Segment);
       ExFreePool(Segment);
-      FileObject->SectionObjectPointers->DataSectionObject = NULL;
+      FileObject->SectionObjectPointer->DataSectionObject = NULL;
     }
 }
 
 VOID 
-MmLockSection(PSECTION_OBJECT Section)
-{
-  KeWaitForSingleObject(&Section->Lock,
-                       UserRequest,
-                       KernelMode,
-                       FALSE,
-                       NULL);
-}
-
-VOID 
-MmUnlockSection(PSECTION_OBJECT Section)
-{
-   KeReleaseMutex(&Section->Lock, FALSE);
-}
-
-VOID
 MmLockSectionSegment(PMM_SECTION_SEGMENT Segment)
 {
-  KeWaitForSingleObject(&Segment->Lock,
-                       UserRequest,
-                       KernelMode,
-                       FALSE,
-                       NULL);
+   ExAcquireFastMutex(&Segment->Lock);
 }
 
 VOID
 MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment)
 {
-  KeReleaseMutex(&Segment->Lock, FALSE);
+   ExReleaseFastMutex(&Segment->Lock);
 }
 
 VOID 
@@ -173,17 +156,28 @@ MmSetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
    PSECTION_PAGE_TABLE Table;
    ULONG DirectoryOffset;
    ULONG TableOffset;
-   
-   DirectoryOffset = PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(Offset);
-   Table = Segment->PageDirectory.PageTables[DirectoryOffset];
-   if (Table == NULL)
+
+   if (Segment->Length <= NR_SECTION_PAGE_TABLES * PAGE_SIZE)
      {
-       Table = 
-         Segment->PageDirectory.PageTables[DirectoryOffset] =
-         ExAllocatePoolWithTag(NonPagedPool, sizeof(SECTION_PAGE_TABLE),
-                               TAG_SECTION_PAGE_TABLE);
-       memset(Table, 0, sizeof(SECTION_PAGE_TABLE));
-       DPRINT("Table %x\n", Table);
+       Table = (PSECTION_PAGE_TABLE)&Segment->PageDirectory;
+     }
+   else
+     {
+       DirectoryOffset = PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(Offset);
+       Table = Segment->PageDirectory.PageTables[DirectoryOffset];
+       if (Table == NULL)
+         {
+          Table = 
+           Segment->PageDirectory.PageTables[DirectoryOffset] =
+            ExAllocatePoolWithTag(NonPagedPool, sizeof(SECTION_PAGE_TABLE),
+                                  TAG_SECTION_PAGE_TABLE);
+          if (Table == NULL)
+            {
+               KEBUGCHECK(0);
+            }
+          memset(Table, 0, sizeof(SECTION_PAGE_TABLE));
+          DPRINT("Table %x\n", Table);
+        }
      }
    TableOffset = PAGE_TO_SECTION_PAGE_TABLE_OFFSET(Offset);
    Table->Entry[TableOffset] = Entry;
@@ -201,12 +195,19 @@ MmGetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
    
    DPRINT("MmGetPageEntrySection(Offset %x)\n", Offset);
    
-   DirectoryOffset = PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(Offset);
-   Table = Segment->PageDirectory.PageTables[DirectoryOffset];
-   DPRINT("Table %x\n", Table);
-   if (Table == NULL)
+   if (Segment->Length <= NR_SECTION_PAGE_TABLES * PAGE_SIZE)
      {
-       return(0);
+       Table = (PSECTION_PAGE_TABLE)&Segment->PageDirectory;
+     }
+   else
+     {
+       DirectoryOffset = PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(Offset);
+       Table = Segment->PageDirectory.PageTables[DirectoryOffset];
+       DPRINT("Table %x\n", Table);
+       if (Table == NULL)
+         {
+          return(0);
+         }
      }
    TableOffset = PAGE_TO_SECTION_PAGE_TABLE_OFFSET(Offset);
    Entry = Table->Entry[TableOffset];
@@ -223,16 +224,16 @@ MmSharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
   if (Entry == 0)
     {
       DPRINT1("Entry == 0 for MmSharePageEntrySectionSegment\n");
-      KeBugCheck(0);
+      KEBUGCHECK(0);
     }
   if (SHARE_COUNT_FROM_SSE(Entry) == MAX_SHARE_COUNT)
     {
       DPRINT1("Maximum share count reached\n");
-      KeBugCheck(0);
+      KEBUGCHECK(0);
     }
   if (IS_SWAP_FROM_SSE(Entry))
     {
-      KeBugCheck(0);
+      KEBUGCHECK(0);
     }
   Entry = MAKE_SSE(PAGE_FROM_SSE(Entry), SHARE_COUNT_FROM_SSE(Entry) + 1);
   MmSetPageEntrySectionSegment(Segment, Offset, Entry);
@@ -241,7 +242,7 @@ MmSharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
 BOOLEAN
 MmUnsharePageEntrySectionSegment(PSECTION_OBJECT Section,
                                 PMM_SECTION_SEGMENT Segment,
-                                ULONG Offset,
+                                ULONG Offset,
                                 BOOLEAN Dirty)
 {
   ULONG Entry;
@@ -250,16 +251,16 @@ MmUnsharePageEntrySectionSegment(PSECTION_OBJECT Section,
   if (Entry == 0)
     {
       DPRINT1("Entry == 0 for MmSharePageEntrySectionSegment\n");
-      KeBugCheck(0);
+      KEBUGCHECK(0);
     }
   if (SHARE_COUNT_FROM_SSE(Entry) == 0)
     {
       DPRINT1("Zero share count for unshare\n");
-      KeBugCheck(0);
+      KEBUGCHECK(0);
     }
   if (IS_SWAP_FROM_SSE(Entry))
     {
-      KeBugCheck(0);
+      KEBUGCHECK(0);
     }
   Entry = MAKE_SSE(PAGE_FROM_SSE(Entry), SHARE_COUNT_FROM_SSE(Entry) - 1);
   /*
@@ -269,46 +270,96 @@ MmUnsharePageEntrySectionSegment(PSECTION_OBJECT Section,
   if (SHARE_COUNT_FROM_SSE(Entry) == 0)
     {
       PFILE_OBJECT FileObject;
-      PREACTOS_COMMON_FCB_HEADER Fcb;
+      PBCB Bcb;
       SWAPENTRY SavedSwapEntry;
       PHYSICAL_ADDRESS Page;
-      
-      MmSetPageEntrySectionSegment(Segment, Offset, 0);
+      BOOLEAN IsImageSection;
+      ULONG FileOffset;
+
+      FileOffset = Offset + Segment->FileOffset;
+   
+      IsImageSection = Section->AllocationAttributes & SEC_IMAGE ? TRUE : FALSE;
+    
+      Page = (PHYSICAL_ADDRESS)(LONGLONG)PAGE_FROM_SSE(Entry);
       FileObject = Section->FileObject;
       if (FileObject != NULL)
        {
-         Fcb = (PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext;
-      
+
          if (FileObject->Flags & FO_DIRECT_CACHE_PAGING_READ &&
-             (Offset % PAGE_SIZE) == 0)
+             (FileOffset % PAGE_SIZE) == 0 &&
+              (Offset + PAGE_SIZE <= Segment->RawLength || !IsImageSection))
            {
              NTSTATUS Status;
-             Status = CcRosUnmapCacheSegment(Fcb->Bcb, Offset, Dirty);
+              Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
+             Status = CcRosUnmapCacheSegment(Bcb, FileOffset, Dirty);
              if (!NT_SUCCESS(Status))
                {
-                 KeBugCheck(0);
+                 DPRINT1("CcRosUnmapCacheSegment failed, status = %x\n", Status);
+                 KEBUGCHECK(0);
                }
            }
        }
 
-      Page = (PHYSICAL_ADDRESS)(LONGLONG)PAGE_FROM_SSE(Entry);
       SavedSwapEntry = MmGetSavedSwapEntryPage(Page);
-      if (SavedSwapEntry != 0)
+      if (SavedSwapEntry == 0)
+        {
+         if (Segment->Flags & MM_PAGEFILE_SEGMENT)
+            {
+             /* 
+              * FIXME:
+              *   Try to page out this page and set the swap entry 
+              *   within the section segment. There exist no rmap entry
+              *   for this page. The pager thread can't page out a 
+              *   page without a rmap entry.
+              */
+             MmSetPageEntrySectionSegment(Segment, Offset, Entry);
+             MmReferencePage(Page);
+           }
+         else
+           {
+             MmSetPageEntrySectionSegment(Segment, Offset, 0);
+           }
+       }
+      else
        {
-         MmFreeSwapPage(SavedSwapEntry);
          MmSetSavedSwapEntryPage(Page, 0);
+         if (Segment->Flags & MM_PAGEFILE_SEGMENT)
+           {
+             MmSetPageEntrySectionSegment(Segment, Offset, MAKE_SWAP_SSE(SavedSwapEntry));
+           }
+         else
+           {
+             MmSetPageEntrySectionSegment(Segment, Offset, 0);
+             MmFreeSwapPage(SavedSwapEntry);
+           }
        }
     }
   else
     {
       MmSetPageEntrySectionSegment(Segment, Offset, Entry);
     }
-  return(SHARE_COUNT_FROM_SSE(Entry) > 1);
+  return(SHARE_COUNT_FROM_SSE(Entry) > 0);
+}
+
+BOOL MiIsPageFromCache(PMEMORY_AREA MemoryArea,
+                      ULONG SegOffset)
+{
+  PBCB Bcb;
+  PCACHE_SEGMENT CacheSeg;
+
+  Bcb = MemoryArea->Data.SectionData.Section->FileObject->SectionObjectPointer->SharedCacheMap;
+  CacheSeg = CcRosLookupCacheSegment(Bcb, SegOffset + MemoryArea->Data.SectionData.Segment->FileOffset);
+  if (CacheSeg)
+  {
+     CcRosReleaseCacheSegment(Bcb, CacheSeg, CacheSeg->Valid, FALSE, TRUE);
+     return TRUE;
+  }
+  return FALSE;
 }
 
 NTSTATUS
 MiReadPage(PMEMORY_AREA MemoryArea,
-          PLARGE_INTEGER Offset,
+          ULONG SegOffset,
           PHYSICAL_ADDRESS* Page)
      /*
       * FUNCTION: Read a page for a section backed memory area.
@@ -318,28 +369,37 @@ MiReadPage(PMEMORY_AREA MemoryArea,
       *       Page - Variable that receives a page contains the read data.
       */
 {
-  IO_STATUS_BLOCK IoStatus;
+  ULONG BaseOffset;
+  ULONG FileOffset;
+  PVOID BaseAddress;
+  BOOLEAN UptoDate;
+  PCACHE_SEGMENT CacheSeg;
   PFILE_OBJECT FileObject;
-  PMDL Mdl;
   NTSTATUS Status;
-  PREACTOS_COMMON_FCB_HEADER Fcb;
-  KEVENT Event;
-
+  ULONG RawLength;
+  PBCB Bcb;
+  BOOLEAN IsImageSection;
+  ULONG Length;
   FileObject = MemoryArea->Data.SectionData.Section->FileObject;
-  Fcb = (PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext;
+  Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
+  RawLength = MemoryArea->Data.SectionData.Segment->RawLength;
+  FileOffset = SegOffset + MemoryArea->Data.SectionData.Segment->FileOffset;
+  IsImageSection = MemoryArea->Data.SectionData.Section->AllocationAttributes & SEC_IMAGE ? TRUE : FALSE;
   
+  assert(Bcb);
+
+  DPRINT("%S %x\n", FileObject->FileName.Buffer, FileOffset);
+
   /*
    * If the file system is letting us go directly to the cache and the
    * memory area was mapped at an offset in the file which is page aligned
    * then get the related cache segment.
    */
   if (FileObject->Flags & FO_DIRECT_CACHE_PAGING_READ &&
-      (Offset->QuadPart % PAGE_SIZE) == 0)
+      (FileOffset % PAGE_SIZE) == 0 &&
+      (SegOffset + PAGE_SIZE <= RawLength || !IsImageSection))
     {
-      ULONG BaseOffset;
-      PVOID BaseAddress;
-      BOOLEAN UptoDate;
-      PCACHE_SEGMENT CacheSeg;
       PHYSICAL_ADDRESS Addr;
 
       /*
@@ -347,12 +407,12 @@ MiReadPage(PMEMORY_AREA MemoryArea,
        * filesystems do because it is safe for us to use an offset with a
        * alignment less than the file system block size.
        */
-      Status = CcRosGetCacheSegment(Fcb->Bcb,
-                                (ULONG)Offset->QuadPart,
-                                &BaseOffset,
-                                &BaseAddress,
-                                &UptoDate,
-                                &CacheSeg);
+      Status = CcRosGetCacheSegment(Bcb,
+                                   FileOffset,
+                                   &BaseOffset,
+                                   &BaseAddress,
+                                   &UptoDate,
+                                   &CacheSeg);
       if (!NT_SUCCESS(Status))
        {
          return(Status);
@@ -366,6 +426,7 @@ MiReadPage(PMEMORY_AREA MemoryArea,
           Status = ReadCacheSegment(CacheSeg);
          if (!NT_SUCCESS(Status))
          {
+             CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE);
              return Status;
          }
        }
@@ -373,15 +434,16 @@ MiReadPage(PMEMORY_AREA MemoryArea,
        * Retrieve the page from the cache segment that we actually want.
        */
       Addr = MmGetPhysicalAddress(BaseAddress +
-                                 Offset->QuadPart - BaseOffset);
+                                 FileOffset - BaseOffset);
       (*Page) = Addr;
       MmReferencePage((*Page));
 
-      CcRosReleaseCacheSegment(Fcb->Bcb, CacheSeg, TRUE, FALSE, TRUE);
-      return(STATUS_SUCCESS);
+      CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, TRUE);
     }
   else
     {
+      PVOID PageAddr;
+      ULONG CacheSegOffset;
       /*
        * Allocate a page, this is rather complicated by the possibility
        * we might have to move other things out of memory
@@ -391,29 +453,82 @@ MiReadPage(PMEMORY_AREA MemoryArea,
        {
          return(Status);
        }
-
-      /*
-       * Create an mdl to hold the page we are going to read data into.
-       */
-      Mdl = MmCreateMdl(NULL, NULL, PAGE_SIZE);
-      MmBuildMdlFromPages(Mdl, &Page->u.LowPart);
-      /*
-       * Call the FSD to read the page
-       */
-
-      KeInitializeEvent(&Event, NotificationEvent, FALSE);
-      Status = IoPageRead(FileObject,
-                         Mdl,
-                         Offset,
-                         &Event,
-                         &IoStatus);
-      if (Status == STATUS_PENDING)
+      Status = CcRosGetCacheSegment(Bcb,
+                                   FileOffset,
+                                   &BaseOffset,
+                                   &BaseAddress,
+                                   &UptoDate,
+                                   &CacheSeg);
+      if (!NT_SUCCESS(Status))
+       {
+         return(Status);
+       }
+      if (!UptoDate)
+       {
+         /*
+          * If the cache segment isn't up to date then call the file
+          * system to read in the data.
+          */
+          Status = ReadCacheSegment(CacheSeg);
+         if (!NT_SUCCESS(Status))
+         {
+             CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE);
+             return Status;
+         }
+       }
+      PageAddr = ExAllocatePageWithPhysPage(*Page);
+      CacheSegOffset = BaseOffset + CacheSeg->Bcb->CacheSegmentSize - FileOffset;
+      Length = RawLength - SegOffset;
+      if (Length <= CacheSegOffset && Length <= PAGE_SIZE)
       {
-        KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
-        return(IoStatus.Status);
+         memcpy(PageAddr, BaseAddress + FileOffset - BaseOffset, Length);
       }
-      return(Status);
+      else if (CacheSegOffset >= PAGE_SIZE)
+      {
+         memcpy(PageAddr, BaseAddress + FileOffset - BaseOffset, PAGE_SIZE);
+      }
+      else
+      {
+        memcpy(PageAddr, BaseAddress + FileOffset - BaseOffset, CacheSegOffset);
+         CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, FALSE);
+        Status = CcRosGetCacheSegment(Bcb,
+                                      FileOffset + CacheSegOffset,
+                                      &BaseOffset,
+                                      &BaseAddress,
+                                      &UptoDate,
+                                      &CacheSeg);
+         if (!NT_SUCCESS(Status))
+          {
+            ExUnmapPage(PageAddr);
+            return(Status);
+          }
+         if (!UptoDate)
+          {
+            /*
+             * If the cache segment isn't up to date then call the file
+             * system to read in the data.
+             */
+             Status = ReadCacheSegment(CacheSeg);
+            if (!NT_SUCCESS(Status))
+              {
+                CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE);
+                ExUnmapPage(PageAddr);
+                return Status;
+              }
+          }
+         if (Length < PAGE_SIZE)
+        {
+           memcpy(PageAddr + CacheSegOffset, BaseAddress, Length - CacheSegOffset);
+        }
+        else
+        {
+            memcpy(PageAddr + CacheSegOffset, BaseAddress, PAGE_SIZE - CacheSegOffset);
+        }
+      }
+      CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, FALSE);
+      ExUnmapPage(PageAddr);
     }
+  return(STATUS_SUCCESS);
 }
 
 NTSTATUS
@@ -422,7 +537,7 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
                             PVOID Address,
                             BOOLEAN Locked)
 {
-   LARGE_INTEGER Offset;
+   ULONG Offset;
    LARGE_INTEGER Page;
    NTSTATUS Status;
    ULONG PAddress;
@@ -433,34 +548,33 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
    ULONG Attributes;
    PMM_PAGEOP PageOp;
    PMM_REGION Region;
+   LARGE_INTEGER Timeout;
 
    /*
     * There is a window between taking the page fault and locking the
     * address space when another thread could load the page so we check
     * that.
     */
-   if (MmIsPagePresent(NULL, Address))
+   if (MmIsPagePresent(AddressSpace->Process, Address))
      {
        if (Locked)
          {
-           MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
+           MmLockPage(MmGetPhysicalAddressForProcess(AddressSpace->Process, Address));
          }  
        return(STATUS_SUCCESS);
      }
    
    PAddress = (ULONG)PAGE_ROUND_DOWN(((ULONG)Address));
-   Offset.QuadPart = (PAddress - (ULONG)MemoryArea->BaseAddress) +
-     MemoryArea->Data.SectionData.ViewOffset;
+   Offset = PAddress - (ULONG)MemoryArea->BaseAddress;
    
-   /*
-    * Lock the segment
-    */
    Segment = MemoryArea->Data.SectionData.Segment;
    Section = MemoryArea->Data.SectionData.Section;
    Region = MmFindRegion(MemoryArea->BaseAddress,
                         &MemoryArea->Data.SectionData.RegionListHead, 
                         Address, NULL);
-   MmLockSection(Section);
+   /*
+    * Lock the segment
+    */
    MmLockSectionSegment(Segment);
 
    /*
@@ -470,7 +584,7 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
        (Region->Protect == PAGE_READWRITE ||
        Region->Protect == PAGE_EXECUTE_READWRITE))
      {
-       Attributes = PAGE_READONLY;
+       Attributes = Region->Protect == PAGE_READWRITE ? PAGE_READONLY : PAGE_EXECUTE_READ;
      }
    else
      {
@@ -480,12 +594,11 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
    /*
     * Get or create a page operation descriptor
     */
-   PageOp = MmGetPageOp(MemoryArea, 0, 0, Segment, Offset.u.LowPart,
-                       MM_PAGEOP_PAGEIN);
+   PageOp = MmGetPageOp(MemoryArea, 0, 0, Segment, Offset, MM_PAGEOP_PAGEIN);
    if (PageOp == NULL)
      {
        DPRINT1("MmGetPageOp failed\n");
-       KeBugCheck(0);
+       KEBUGCHECK(0);
      }
 
    /*
@@ -495,86 +608,100 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
    if (PageOp->Thread != PsGetCurrentThread())
      {
        MmUnlockSectionSegment(Segment);
-       MmUnlockSection(Section);
        MmUnlockAddressSpace(AddressSpace);
+       Timeout.QuadPart = -100000000LL;        // 10 sec
        Status = KeWaitForSingleObject(&PageOp->CompletionEvent,
                                      0,
                                      KernelMode,
                                      FALSE,
-                                     NULL);
+                                     &Timeout);
+
        /*
        * Check for various strange conditions
        */
        if (Status != STATUS_SUCCESS)
         {
-          DPRINT1("Failed to wait for page op\n");
-          KeBugCheck(0);
+          DPRINT1("Failed to wait for page op, status = %x\n", Status);
+          KEBUGCHECK(0);
         }
        if (PageOp->Status == STATUS_PENDING)
         {
           DPRINT1("Woke for page op before completion\n");
-          KeBugCheck(0);
+          KEBUGCHECK(0);
         }
+       MmLockAddressSpace(AddressSpace);
        /*
        * If this wasn't a pagein then restart the operation
        */
        if (PageOp->OpType != MM_PAGEOP_PAGEIN)
         {
-          MmLockAddressSpace(AddressSpace);
+           KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
           MmReleasePageOp(PageOp);
           DPRINT("Address 0x%.8X\n", Address);
           return(STATUS_MM_RESTART_OPERATION);
         }
+       
        /*
        * If the thread handling this fault has failed then we don't retry
        */
        if (!NT_SUCCESS(PageOp->Status))
         {
-          MmLockAddressSpace(AddressSpace);
+          Status = PageOp->Status;
+          KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
+          MmReleasePageOp(PageOp);
           DPRINT("Address 0x%.8X\n", Address);
-          return(PageOp->Status);
+          return(Status);
         }
-       MmLockAddressSpace(AddressSpace);
-       MmLockSection(Section);
        MmLockSectionSegment(Segment);
        /*
        * If the completed fault was for another address space then set the 
        * page in this one.
        */
-       if (!MmIsPagePresent(NULL, Address))
+       if (!MmIsPagePresent(AddressSpace->Process, Address))
         {
-          Entry = MmGetPageEntrySectionSegment(Segment, Offset.u.LowPart);
+          Entry = MmGetPageEntrySectionSegment(Segment, Offset);
           if (Entry == 0)
           {
-               MmUnlockSectionSegment(Segment);
-               MmUnlockSection(Section);
+               MmUnlockSectionSegment(Segment);
+                KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
                MmReleasePageOp(PageOp);
                return(STATUS_MM_RESTART_OPERATION);
           } 
 
           Page = (LARGE_INTEGER)(LONGLONG)(PAGE_FROM_SSE(Entry));
           MmReferencePage(Page);       
-          MmSharePageEntrySectionSegment(Segment, Offset.u.LowPart);
+          MmSharePageEntrySectionSegment(Segment, Offset);
 
-          Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
+          Status = MmCreateVirtualMapping(MemoryArea->Process,
                                           Address,
                                           Attributes,
                                           Page,
                                           FALSE);
+          if (Status == STATUS_NO_MEMORY)
+            {
+              MmUnlockAddressSpace(AddressSpace);
+              Status = MmCreateVirtualMapping(MemoryArea->Process,
+                                              Address,
+                                              Attributes,
+                                              Page,
+                                              TRUE);
+              MmLockAddressSpace(AddressSpace);
+            }
+
           if (!NT_SUCCESS(Status))
             {
               DbgPrint("Unable to create virtual mapping\n");
-              KeBugCheck(0);
+              KEBUGCHECK(0);
             }
-          MmInsertRmap(Page, PsGetCurrentProcess(), 
-                       (PVOID)PAGE_ROUND_DOWN(Address));
+          MmInsertRmap(Page, MemoryArea->Process, (PVOID)PAddress);
         }
        if (Locked)
         {
-          MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
+          MmLockPage(Page);
         }
        MmUnlockSectionSegment(Segment);
-       MmUnlockSection(Section);
+       PageOp->Status = STATUS_SUCCESS;
+       KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
        MmReleasePageOp(PageOp);
        DPRINT("Address 0x%.8X\n", Address);
        return(STATUS_SUCCESS);
@@ -583,20 +710,28 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
    /*
     * Must be private page we have swapped out.
     */
-   if (MmIsPageSwapEntry(NULL, (PVOID)PAddress))
+   if (MmIsPageSwapEntry(AddressSpace->Process, (PVOID)PAddress))
      {
        SWAPENTRY SwapEntry;
        PMDL Mdl;
 
+       /*
+        * Sanity check
+       */
+       if (Segment->Flags & MM_PAGEFILE_SEGMENT)
+         {
+          DPRINT1("Found a swaped out private page in a pagefile section.\n");
+          KEBUGCHECK(0);
+        }
+
        MmUnlockSectionSegment(Segment);
-       MmUnlockSection(Section);
-       
-       MmDeletePageFileMapping(NULL, (PVOID)PAddress, &SwapEntry);
+       MmDeletePageFileMapping(AddressSpace->Process, (PVOID)PAddress, &SwapEntry);
 
+       MmUnlockAddressSpace(AddressSpace);
        Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
        if (!NT_SUCCESS(Status))
         {
-          KeBugCheck(0);
+          KEBUGCHECK(0);
         }
 
        Mdl = MmCreateMdl(NULL, NULL, PAGE_SIZE);
@@ -604,18 +739,19 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
        Status = MmReadFromSwapPage(SwapEntry, Mdl);
        if (!NT_SUCCESS(Status))
         {
-          KeBugCheck(0);
+          DPRINT1("MmReadFromSwapPage failed, status = %x\n", Status);
+          KEBUGCHECK(0);
         }
-       
-       Status = MmCreateVirtualMapping(PsGetCurrentProcess(),                
+       MmLockAddressSpace(AddressSpace);
+       Status = MmCreateVirtualMapping(AddressSpace->Process,                
                                       Address,
                                       Region->Protect,
                                       Page,
                                       FALSE);
-       while (Status == STATUS_NO_MEMORY)
+       if (Status == STATUS_NO_MEMORY)
         {
           MmUnlockAddressSpace(AddressSpace);     
-          Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
+          Status = MmCreateVirtualMapping(AddressSpace->Process,
                                           Address,
                                           Region->Protect,
                                           Page,
@@ -624,8 +760,8 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
         }  
        if (!NT_SUCCESS(Status))
         {
-          DPRINT1("MmCreateVirtualMapping failed, not out of memory\n");
-          KeBugCheck(0);
+          DPRINT("MmCreateVirtualMapping failed, not out of memory\n");
+          KEBUGCHECK(0);
           return(Status);
         }
 
@@ -637,8 +773,7 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
        /*
        * Add the page to the process's working set
        */
-       MmInsertRmap(Page, PsGetCurrentProcess(), 
-                   (PVOID)PAGE_ROUND_DOWN(Address));       
+       MmInsertRmap(Page, AddressSpace->Process, (PVOID)PAddress);
        
        /*
        * Finish the operation
@@ -659,21 +794,39 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
     */
    if (Section->AllocationAttributes & SEC_PHYSICALMEMORY)
      {
+       MmUnlockSectionSegment(Segment);
        /*
        * Just map the desired physical page 
        */
-       Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
+       Page.QuadPart = Offset + MemoryArea->Data.SectionData.ViewOffset;
+       Status = MmCreateVirtualMapping(AddressSpace->Process,
                                       Address,
                                       Region->Protect,
-                                      Offset,
+                                      Page,
                                       FALSE);
+       if (Status == STATUS_NO_MEMORY)
+        {
+          MmUnlockAddressSpace(AddressSpace);     
+          Status = MmCreateVirtualMapping(AddressSpace->Process,
+                                          Address,
+                                          Region->Protect,
+                                          Page,
+                                          TRUE);
+          MmLockAddressSpace(AddressSpace);
+        }  
+       if (!NT_SUCCESS(Status))
+        {
+          DPRINT("MmCreateVirtualMapping failed, not out of memory\n");
+          KEBUGCHECK(0);
+          return(Status);
+        }
        /* 
         * Don't add an rmap entry since the page mapped could be for 
        * anything. 
        */
        if (Locked)
         {
-          MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
+          MmLockPage(Page);
         }  
 
        /*
@@ -682,8 +835,6 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
        PageOp->Status = STATUS_SUCCESS;
        KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
        MmReleasePageOp(PageOp);
-       MmUnlockSectionSegment(Segment);
-       MmUnlockSection(Section);
        DPRINT("Address 0x%.8X\n", Address);
        return(STATUS_SUCCESS);
      }
@@ -693,28 +844,44 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
     */
    if (Segment->Characteristics & IMAGE_SECTION_CHAR_BSS)
      {
+       MmUnlockSectionSegment(Segment);
        Status = MmRequestPageMemoryConsumer(MC_USER, FALSE, &Page);
        if (!NT_SUCCESS(Status))
         {
-           MmUnlockSectionSegment(Segment);
-           MmUnlockSection(Section);
-           MmUnlockAddressSpace(AddressSpace);    
-           MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
-           MmLockAddressSpace(AddressSpace);
-           MmLockSection(Section);
-           MmLockSectionSegment(Segment);
+          MmUnlockAddressSpace(AddressSpace);     
+          Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
+          MmLockAddressSpace(AddressSpace);
         }
-
-       Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
+       if (!NT_SUCCESS(Status))
+         {
+           KEBUGCHECK(0);
+         }
+       Status = MmCreateVirtualMapping(AddressSpace->Process,
                                       Address,
                                       Region->Protect,
                                       Page,
                                       FALSE);
-       MmInsertRmap(Page, PsGetCurrentProcess(), 
-                   (PVOID)PAGE_ROUND_DOWN(Address));
+       if (Status == STATUS_NO_MEMORY)
+        {
+          MmUnlockAddressSpace(AddressSpace);     
+          Status = MmCreateVirtualMapping(AddressSpace->Process,
+                                          Address,
+                                          Region->Protect,
+                                          Page,
+                                          TRUE);
+          MmLockAddressSpace(AddressSpace);
+        }  
+
+       if (!NT_SUCCESS(Status))
+        {
+          DPRINT("MmCreateVirtualMapping failed, not out of memory\n");
+          KEBUGCHECK(0);
+          return(Status);
+        }
+       MmInsertRmap(Page, AddressSpace->Process, (PVOID)PAddress);
        if (Locked)
         {
-          MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
+          MmLockPage(Page);
         }  
 
        /*
@@ -723,8 +890,6 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
        PageOp->Status = STATUS_SUCCESS;
        KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
        MmReleasePageOp(PageOp);
-       MmUnlockSectionSegment(Segment);
-       MmUnlockSection(Section);
        DPRINT("Address 0x%.8X\n", Address);
        return(STATUS_SUCCESS);
      }
@@ -732,7 +897,7 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
    /*
     * Get the entry corresponding to the offset within the section
     */
-   Entry = MmGetPageEntrySectionSegment(Segment, Offset.u.LowPart);
+   Entry = MmGetPageEntrySectionSegment(Segment, Offset);
    
    if (Entry == 0)
      {   
@@ -740,105 +905,100 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
        * If the entry is zero (and it can't change because we have
        * locked the segment) then we need to load the page.
        */
-       
+
        /*
        * Release all our locks and read in the page from disk
        */
        MmUnlockSectionSegment(Segment);
-       MmUnlockSection(Section);
        MmUnlockAddressSpace(AddressSpace);
-       
-       if (Segment->Flags & MM_PAGEFILE_SEGMENT)
+
+       if ((Segment->Flags & MM_PAGEFILE_SEGMENT) || 
+          (Offset >= PAGE_ROUND_UP(Segment->RawLength) && Section->AllocationAttributes & SEC_IMAGE))
         {
-           Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
+          Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
+          if (!NT_SUCCESS(Status))
+            {
+              DPRINT1("MmRequestPageMemoryConsumer failed (Status %x)\n", Status);
+            }
         }
        else
-        {
-          Status = MiReadPage(MemoryArea, &Offset, &Page);
+         {
+           Status = MiReadPage(MemoryArea, Offset, &Page);
+          if (!NT_SUCCESS(Status))
+            {
+              DPRINT1("MiReadPage failed (Status %x)\n", Status);
+            }
         }
-       if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE)
+       if (!NT_SUCCESS(Status))
         {
           /*
            * FIXME: What do we know in this case?
            */
-          DPRINT1("IoPageRead failed (Status %x)\n", Status);
-          
           /*
            * Cleanup and release locks
            */
+          MmLockAddressSpace(AddressSpace);
           PageOp->Status = Status;
           KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
           MmReleasePageOp(PageOp);
-          MmLockAddressSpace(AddressSpace);
+           DPRINT("Address 0x%.8X\n", Address);
           return(Status);
         }
-       
        /*
-       * Relock the address space, section and segment
+       * Relock the address space and segment
        */
        MmLockAddressSpace(AddressSpace);
-       MmLockSection(Section);
        MmLockSectionSegment(Segment);
        
        /*
        * Check the entry. No one should change the status of a page
        * that has a pending page-in.
        */
-       Entry1 = MmGetPageEntrySectionSegment(Segment, Offset.QuadPart);
+       Entry1 = MmGetPageEntrySectionSegment(Segment, Offset);
        if (Entry != Entry1)
         {
           DbgPrint("Someone changed ppte entry while we slept\n");
-          KeBugCheck(0);
+          KEBUGCHECK(0);
         }
        
        /*
        * Mark the offset within the section as having valid, in-memory
        * data
        */
-       Entry = Page.u.LowPart;
-       MmSetPageEntrySectionSegment(Segment, Offset.QuadPart, Entry);
-       MmSharePageEntrySectionSegment(Segment, Offset.QuadPart);
-       
-       Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
+       Entry = MAKE_SSE(Page.u.LowPart, 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);
+         }
        if (!NT_SUCCESS(Status))
-        {
-          MmUnlockSectionSegment(Segment);
-          MmUnlockSection(Section);
-          MmUnlockAddressSpace(AddressSpace);
-          Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
-                                          Address,
-                                          Attributes,
-                                          Page,
-                                          TRUE);
-          if (!NT_SUCCESS(Status))
-            {
-              KeBugCheck(0);
-            }
-          MmLockAddressSpace(AddressSpace);
-          MmLockSection(Section);
-          MmLockSectionSegment(Segment);
-        }
-       MmInsertRmap(Page, PsGetCurrentProcess(), 
-                   (PVOID)PAGE_ROUND_DOWN(Address));     
-       if (!NT_SUCCESS(Status))
-        {
-          DbgPrint("Unable to create virtual mapping\n");
-          KeBugCheck(0);
-        }
+         {
+           DbgPrint("Unable to create virtual mapping\n");
+           KEBUGCHECK(0);
+         }
+       MmInsertRmap(Page, AddressSpace->Process, (PVOID)PAddress);
+
        if (Locked)
         {
-          MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
+          MmLockPage(Page);
         }  
        PageOp->Status = STATUS_SUCCESS;
        KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
        MmReleasePageOp(PageOp);
-       MmUnlockSectionSegment(Segment);
-       MmUnlockSection(Section);
-       DPRINT("MmNotPresentFaultSectionView succeeded\n");
+       DPRINT("Address 0x%.8X\n", Address);
        return(STATUS_SUCCESS);
      }
    else if (IS_SWAP_FROM_SSE(Entry))
@@ -852,13 +1012,13 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
        * Release all our locks and read in the page from disk
        */
        MmUnlockSectionSegment(Segment);
-       MmUnlockSection(Section);
+
        MmUnlockAddressSpace(AddressSpace);
        
        Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
        if (!NT_SUCCESS(Status))
         {
-          KeBugCheck(0);
+          KEBUGCHECK(0);
         }
 
        Mdl = MmCreateMdl(NULL, NULL, PAGE_SIZE);
@@ -866,96 +1026,110 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
        Status = MmReadFromSwapPage(SwapEntry, Mdl);
        if (!NT_SUCCESS(Status))
         {
-          KeBugCheck(0);
+          KEBUGCHECK(0);
         }
 
        /*
-       * Relock the address space, section and segment
+       * Relock the address space and segment
        */
        MmLockAddressSpace(AddressSpace);
-       MmLockSection(Section);
        MmLockSectionSegment(Segment);
        
        /*
        * Check the entry. No one should change the status of a page
        * that has a pending page-in.
        */
-       Entry1 = MmGetPageEntrySectionSegment(Segment, Offset.QuadPart);
+       Entry1 = MmGetPageEntrySectionSegment(Segment, Offset);
        if (Entry != Entry1)
         {
           DbgPrint("Someone changed ppte entry while we slept\n");
-          KeBugCheck(0);
+          KEBUGCHECK(0);
         }
        
        /*
        * Mark the offset within the section as having valid, in-memory
        * data
        */
-       Entry = Page.u.LowPart;
-       MmSetPageEntrySectionSegment(Segment, Offset.QuadPart, Entry);
-       MmSharePageEntrySectionSegment(Segment, Offset.QuadPart);
+       Entry = MAKE_SSE(Page.u.LowPart, 1);
+       MmSetPageEntrySectionSegment(Segment, Offset, Entry);
+       MmUnlockSectionSegment(Segment);
 
        /*
        * Save the swap entry.
        */
        MmSetSavedSwapEntryPage(Page, SwapEntry);
-       
-       Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
+       Status = MmCreateVirtualMapping(AddressSpace->Process,
                                       Address,
-                                      Attributes,
+                                      Region->Protect,
                                       Page,
                                       FALSE);
-       MmInsertRmap(Page, PsGetCurrentProcess(), 
-                   (PVOID)PAGE_ROUND_DOWN(Address));
+       if (Status == STATUS_NO_MEMORY)
+         {
+           MmUnlockAddressSpace(AddressSpace);
+           Status = MmCreateVirtualMapping(AddressSpace->Process,
+                                          Address,
+                                          Region->Protect,
+                                          Page,
+                                          TRUE);
+           MmLockAddressSpace(AddressSpace);
+         }
        if (!NT_SUCCESS(Status))
-        {
-          DbgPrint("Unable to create virtual mapping\n");
-          KeBugCheck(0);
-        }
+         {
+           DbgPrint("Unable to create virtual mapping\n");
+           KEBUGCHECK(0);
+         }
+       MmInsertRmap(Page, AddressSpace->Process, (PVOID)PAddress);
        if (Locked)
         {
-          MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
+          MmLockPage(Page);
         }  
        PageOp->Status = STATUS_SUCCESS;
        KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
        MmReleasePageOp(PageOp);
-       MmUnlockSectionSegment(Segment);
-       MmUnlockSection(Section);
-       DPRINT("MmNotPresentFaultSectionView succeeded\n");
+       DPRINT("Address 0x%.8X\n", Address);
        return(STATUS_SUCCESS);
      }
    else
      {
-       /*
-        * If the section offset is already in-memory and valid then just
-        * take another reference to the page 
-        */
-       
-       Page = (LARGE_INTEGER)(LONGLONG)PAGE_FROM_SSE(Entry);
-       MmReferencePage(Page);  
-       MmSharePageEntrySectionSegment(Segment, Offset.QuadPart);
+       /*
+        * If the section offset is already in-memory and valid then just
+       * take another reference to the page 
+       */
        
-       Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
-                                       Address,
-                                       Attributes,
-                                       Page,
-                                       FALSE);
-       MmInsertRmap(Page, PsGetCurrentProcess(), 
-                    (PVOID)PAGE_ROUND_DOWN(Address));
-       if (!NT_SUCCESS(Status))
-         {
-            DbgPrint("Unable to create virtual mapping\n");
-            KeBugCheck(0);
-         }
+       Page = (LARGE_INTEGER)(LONGLONG)PAGE_FROM_SSE(Entry);
+       MmReferencePage(Page);  
+       MmSharePageEntrySectionSegment(Segment, Offset);
+       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);
+         }
+       if (!NT_SUCCESS(Status))
+         {
+           DbgPrint("Unable to create virtual mapping\n");
+           KEBUGCHECK(0);
+         }
+       MmInsertRmap(Page, AddressSpace->Process, (PVOID)PAddress);
        if (Locked)
-        {
-          MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
-        }  
+         {
+           MmLockPage(Page);
+         }  
        PageOp->Status = STATUS_SUCCESS;
        KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
        MmReleasePageOp(PageOp);
-       MmUnlockSectionSegment(Segment);
-       MmUnlockSection(Section);       
+       DPRINT("Address 0x%.8X\n", Address);
        return(STATUS_SUCCESS);
      }
 }
@@ -973,46 +1147,46 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
   PVOID NewAddress;
   NTSTATUS Status;
   ULONG PAddress;
-  LARGE_INTEGER Offset;
+  ULONG Offset;
   PMM_PAGEOP PageOp;
   PMM_REGION Region;
+  LARGE_INTEGER Timeout;
 
   /*
    * Check if the page has been paged out or has already been set readwrite
    */
-   if (!MmIsPagePresent(NULL, Address) ||
-       MmGetPageProtect(NULL, Address) & PAGE_READWRITE)
+   if (!MmIsPagePresent(AddressSpace->Process, Address) ||
+       MmGetPageProtect(AddressSpace->Process, Address) & PAGE_READWRITE)
      {
-       return(STATUS_SUCCESS);
+       DPRINT("Address 0x%.8X\n", Address);
+       return(STATUS_SUCCESS);
      }  
 
    /*
     * Find the offset of the page
     */
    PAddress = (ULONG)PAGE_ROUND_DOWN(((ULONG)Address));
-   Offset.QuadPart = (PAddress - (ULONG)MemoryArea->BaseAddress) +
-     MemoryArea->Data.SectionData.ViewOffset;
+   Offset = PAddress - (ULONG)MemoryArea->BaseAddress;
 
-   /*
-    * Lock the segment
-    */
    Segment = MemoryArea->Data.SectionData.Segment;
    Section = MemoryArea->Data.SectionData.Section;
    Region = MmFindRegion(MemoryArea->BaseAddress,
                         &MemoryArea->Data.SectionData.RegionListHead,
                         Address, NULL);
-   MmLockSection(Section);
+   /*
+    * Lock the segment
+    */
    MmLockSectionSegment(Segment);
 
    /*
     * Sanity check.
     */
-   if (MmGetPageEntrySectionSegment(Segment, Offset.QuadPart) == 0)
+   if (MmGetPageEntrySectionSegment(Segment, Offset) == 0)
      {
        DPRINT1("COW fault for page with PESS 0. Address was 0x%.8X\n",
               Address);
      }
-
+   MmUnlockSectionSegment(Segment);
    /*
     * Check if we are doing COW
     */
@@ -1020,20 +1194,19 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
         (Region->Protect == PAGE_READWRITE ||
          Region->Protect == PAGE_EXECUTE_READWRITE)))
      {
-       MmUnlockSection(Section);
-       MmUnlockSectionSegment(Segment);
+       DPRINT("Address 0x%.8X\n", Address);
        return(STATUS_UNSUCCESSFUL);
      }
 
    /*
     * Get or create a pageop
     */
-   PageOp = MmGetPageOp(MemoryArea, 0, 0, Segment, Offset.u.LowPart,
+   PageOp = MmGetPageOp(MemoryArea, 0, 0, Segment, Offset,
                        MM_PAGEOP_ACCESSFAULT);
    if (PageOp == NULL)
      {
        DPRINT1("MmGetPageOp failed\n");
-       KeBugCheck(0);
+       KEBUGCHECK(0);
      }
 
    /*
@@ -1041,46 +1214,49 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
     */
    if (PageOp->Thread != PsGetCurrentThread())
      {
-       MmUnlockSectionSegment(Segment);
-       MmUnlockSection(Section);
        MmUnlockAddressSpace(AddressSpace);
+       Timeout.QuadPart = -100000000LL;        // 10 sec
        Status = KeWaitForSingleObject(&PageOp->CompletionEvent,
                                      0,
                                      KernelMode,
                                      FALSE,
-                                     NULL);
+                                     &Timeout);
        /*
        * Check for various strange conditions
        */
-       if (Status != STATUS_SUCCESS)
+       if (Status == STATUS_TIMEOUT)
         {
-          DPRINT1("Failed to wait for page op\n");
-          KeBugCheck(0);
+          DPRINT1("Failed to wait for page op, status = %x\n", Status);
+          KEBUGCHECK(0);
         }
        if (PageOp->Status == STATUS_PENDING)
         {
           DPRINT1("Woke for page op before completion\n");
-          KeBugCheck(0);
+          KEBUGCHECK(0);
         }
        /*
        * Restart the operation
        */
        MmLockAddressSpace(AddressSpace);
+       KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
        MmReleasePageOp(PageOp);
+       DPRINT("Address 0x%.8X\n", Address);
        return(STATUS_MM_RESTART_OPERATION);
      }
 
    /*
     * Release locks now we have the pageop
     */
-   MmUnlockSectionSegment(Segment);
-   MmUnlockSection(Section);
    MmUnlockAddressSpace(AddressSpace);
 
    /*
     * Allocate a page
     */
    Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &NewPage);
+   if (!NT_SUCCESS(Status))
+   {
+     KEBUGCHECK(0);
+   }
 
    /*
     * Copy the old page
@@ -1088,46 +1264,63 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
    OldPage = MmGetPhysicalAddressForProcess(NULL, Address);
  
    NewAddress = ExAllocatePageWithPhysPage(NewPage);
-   memcpy(NewAddress, (PVOID)PAGE_ROUND_DOWN(Address), PAGE_SIZE);
+   memcpy(NewAddress, (PVOID)PAddress, PAGE_SIZE);
    ExUnmapPage(NewAddress);
 
    /*
     * Delete the old entry.
     */
-   MmDeleteVirtualMapping(PsGetCurrentProcess(), Address, FALSE, NULL, NULL);
+   MmDeleteVirtualMapping(AddressSpace->Process, Address, FALSE, NULL, NULL);
 
    /*
     * Set the PTE to point to the new page
     */
    MmLockAddressSpace(AddressSpace);
-   Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
+   Status = MmCreateVirtualMapping(AddressSpace->Process,
                                   Address,
                                   Region->Protect,
                                   NewPage,
                                   FALSE);   
-   MmInsertRmap(NewPage, PsGetCurrentProcess(), 
-               (PVOID)PAGE_ROUND_DOWN(Address));
+   if (Status == STATUS_NO_MEMORY)
+     {
+       MmUnlockAddressSpace(AddressSpace);        
+       Status = MmCreateVirtualMapping(AddressSpace->Process,
+                                      Address,
+                                      Region->Protect,
+                                      NewPage,
+                                      TRUE);
+       MmLockAddressSpace(AddressSpace);
+     }  
+   if (!NT_SUCCESS(Status))
+     {
+       DPRINT("MmCreateVirtualMapping failed, not out of memory\n");
+       KEBUGCHECK(0);
+       return(Status);
+     }
+   MmInsertRmap(NewPage, AddressSpace->Process, (PVOID)PAddress);
    if (!NT_SUCCESS(Status))
      {
        DbgPrint("Unable to create virtual mapping\n");
-       KeBugCheck(0);
+       KEBUGCHECK(0);
      }
    if (Locked)
      {
-       MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
+       MmLockPage(NewPage);
      }  
 
    /*
     * Unshare the old page.
     */
-   MmUnsharePageEntrySectionSegment(Section, Segment, Offset.QuadPart, FALSE);
-   MmDeleteRmap(OldPage, PsGetCurrentProcess(),
-               (PVOID)PAGE_ROUND_DOWN(Address));
+   MmDeleteRmap(OldPage, AddressSpace->Process, (PVOID)PAddress);
+   MmLockSectionSegment(Segment);
+   MmUnsharePageEntrySectionSegment(Section, Segment, Offset, FALSE);
+   MmUnlockSectionSegment(Segment);
    MmReleasePageMemoryConsumer(MC_USER, OldPage);
 
    PageOp->Status = STATUS_SUCCESS;
    KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
    MmReleasePageOp(PageOp);
+   DPRINT("Address 0x%.8X\n", Address);
    return(STATUS_SUCCESS);
 }
 
@@ -1136,14 +1329,14 @@ MmPageOutDeleteMapping(PVOID Context, PEPROCESS Process, PVOID Address)
 {
   MM_SECTION_PAGEOUT_CONTEXT* PageOutContext;
   BOOL WasDirty;
-  PHYSICAL_ADDRESS PhysicalAddress;
+  PHYSICAL_ADDRESS Page;
 
   PageOutContext = (MM_SECTION_PAGEOUT_CONTEXT*)Context;
   MmDeleteVirtualMapping(Process,
                         Address,
                         FALSE,
                         &WasDirty,
-                        &PhysicalAddress);
+                        &Page);
   if (WasDirty)
     {
       PageOutContext->WasDirty = TRUE;
@@ -1152,10 +1345,11 @@ MmPageOutDeleteMapping(PVOID Context, PEPROCESS Process, PVOID Address)
     {
       MmUnsharePageEntrySectionSegment(PageOutContext->Section,
                                       PageOutContext->Segment,
-                                      PageOutContext->Offset.u.LowPart,
+                                      PageOutContext->Offset,
                                       PageOutContext->WasDirty);
     }
-  MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
+  MmReleasePageMemoryConsumer(MC_USER, Page);
+  DPRINT("PhysicalAddress %I64x, Address %x\n", Page, Address);
 }
 
 NTSTATUS
@@ -1164,30 +1358,36 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
                     PVOID Address,
                     PMM_PAGEOP PageOp)
 {
-  LARGE_INTEGER Offset;
-  PSECTION_OBJECT Section;
-  PMM_SECTION_SEGMENT Segment;
   PHYSICAL_ADDRESS PhysicalAddress;
   MM_SECTION_PAGEOUT_CONTEXT Context;
   SWAPENTRY SwapEntry;
   PMDL Mdl;
   ULONG Entry;
-  BOOLEAN Private;
+  ULONG FileOffset;
   NTSTATUS Status;
   PFILE_OBJECT FileObject;
-  PREACTOS_COMMON_FCB_HEADER Fcb;
+  PBCB Bcb = NULL;
   BOOLEAN DirectMapped;
+  BOOLEAN IsImageSection;
 
   Address = (PVOID)PAGE_ROUND_DOWN(Address);
 
-  Offset.QuadPart = (ULONG)(Address - (ULONG)MemoryArea->BaseAddress) +
-     MemoryArea->Data.SectionData.ViewOffset;
+  /*
+   * Get the segment and section.
+   */
+  Context.Segment = MemoryArea->Data.SectionData.Segment;
+  Context.Section = MemoryArea->Data.SectionData.Section;
 
-  FileObject = MemoryArea->Data.SectionData.Section->FileObject;
+  Context.Offset = (ULONG)(Address - (ULONG)MemoryArea->BaseAddress);
+  FileOffset = Context.Offset + Context.Segment->FileOffset;
+
+  IsImageSection = Context.Section->AllocationAttributes & SEC_IMAGE ? TRUE : FALSE;
+
+  FileObject = Context.Section->FileObject;
   DirectMapped = FALSE;
   if (FileObject != NULL)
     {
-      Fcb = (PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext;
+      Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
   
       /*
        * If the file system is letting us go directly to the cache and the
@@ -1195,38 +1395,35 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
        * then note this is a direct mapped page.
        */
       if (FileObject->Flags & FO_DIRECT_CACHE_PAGING_READ &&
-         (Offset.QuadPart % PAGE_SIZE) == 0)
+         (FileOffset % PAGE_SIZE) == 0 &&
+         (Context.Offset + PAGE_SIZE <= Context.Segment->RawLength || !IsImageSection))
        {
          DirectMapped = TRUE;
        }
     }
    
-  /*
-   * Get the segment and section.
-   */
-  Segment = MemoryArea->Data.SectionData.Segment;
-  Section = MemoryArea->Data.SectionData.Section;
 
   /*
    * This should never happen since mappings of physical memory are never
    * placed in the rmap lists.
    */
-  if (Section->AllocationAttributes & SEC_PHYSICALMEMORY)
+  if (Context.Section->AllocationAttributes & SEC_PHYSICALMEMORY)
     {
       DPRINT1("Trying to page out from physical memory section address 0x%X "
-             "process %d\n", Address, AddressSpace->Process->UniqueProcessId);
-      KeBugCheck(0);
+             "process %d\n", Address, 
+             AddressSpace->Process ? AddressSpace->Process->UniqueProcessId : 0);
+      KEBUGCHECK(0);
     }
 
   /*
    * Get the section segment entry and the physical address.
    */
-  Entry = MmGetPageEntrySectionSegment(Segment, Offset.QuadPart);
+  Entry = MmGetPageEntrySectionSegment(Context.Segment, Context.Offset);
   if (!MmIsPagePresent(AddressSpace->Process, Address))
     {
       DPRINT1("Trying to page out not-present page at (%d,0x%.8X).\n",
-             AddressSpace->Process->UniqueProcessId, Address);
-      KeBugCheck(0);
+         AddressSpace->Process ? AddressSpace->Process->UniqueProcessId : 0, Address);
+      KEBUGCHECK(0);
     }
   PhysicalAddress = 
     MmGetPhysicalAddressForProcess(AddressSpace->Process, Address);
@@ -1235,31 +1432,22 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
   /*
    * Prepare the context structure for the rmap delete call.
    */
-  Context.Section = Section;
-  Context.Segment = Segment;
-  Context.Offset = Offset;
   Context.WasDirty = FALSE;
-  if (Segment->Characteristics & IMAGE_SECTION_CHAR_BSS ||
+  if (Context.Segment->Characteristics & IMAGE_SECTION_CHAR_BSS ||
       IS_SWAP_FROM_SSE(Entry) || 
       (LONGLONG)PAGE_FROM_SSE(Entry) != PhysicalAddress.QuadPart)
     {
-      Context.Private = Private = TRUE;
+      Context.Private = TRUE;
     }
   else
     {
-      Context.Private = Private = FALSE;
+      Context.Private = FALSE;
     }
 
   /*
-   * Take an additional reference to the page.
-   */
-  MmReferencePage(PhysicalAddress);
-
-  /*
    * Paging out data mapped read-only is easy.
    */
-  if (MemoryArea->Attributes & PAGE_READONLY ||
-      MemoryArea->Attributes & PAGE_EXECUTE_READ)
+  if (Context.Segment->Protection & (PAGE_READONLY|PAGE_EXECUTE_READ))
     {
       /*
        * Read-only data should never be in the swapfile.
@@ -1269,16 +1457,16 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
          DPRINT1("SwapEntry != 0 was 0x%.8X at address 0x%.8X, "
                  "paddress 0x%.8X\n", SwapEntry, Address, 
                  PhysicalAddress);
-         KeBugCheck(0);
+         KEBUGCHECK(0);
        }
 
       /*
        * Read-only data should never be COWed
        */
-      if (Private)
+      if (Context.Private)
        {
          DPRINT1("Had private copy of read-only page.\n");
-         KeBugCheck(0);
+         KEBUGCHECK(0);
        }
       
       /*
@@ -1288,18 +1476,10 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
                       MmPageOutDeleteMapping);
       if (Context.WasDirty)
        {
-         KeBugCheck(0);
-       }
-      /*
-       * If this page wasn't direct mapped then we have a private copy so 
-       * release back to the system; otherwise the cache manager will have 
-       * handled freeing the cache segment which we mapped from.
-       */
-      if (!DirectMapped)
-       {
-         MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
+         DPRINT1("Had a dirty page of a read-only page.\n");
+         KEBUGCHECK(0);
        }
-       
+
       PageOp->Status = STATUS_SUCCESS;
       KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
       MmReleasePageOp(PageOp);
@@ -1309,39 +1489,61 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
   /*
    * Otherwise we have read-write data.
    */
+
+  /*
+   * Take an additional reference to the page or the cache segment.
+   */
+  if (DirectMapped && !Context.Private)
+    {
+      if(!MiIsPageFromCache(MemoryArea, Context.Offset))
+        {
+         DPRINT1("Direct mapped non private page is not associated with the cache.\n")
+          KEBUGCHECK(0);
+        }
+    }
+  else
+    {
+      MmReferencePage(PhysicalAddress);
+    }
+
   MmDeleteAllRmaps(PhysicalAddress, (PVOID)&Context, MmPageOutDeleteMapping);
   
   /*
    * If this wasn't a private page then we should have reduced the entry to
    * zero by deleting all the rmaps.
    */
-  if (!Private && MmGetPageEntrySectionSegment(Segment, Offset.QuadPart) != 0)
+  if (!Context.Private && MmGetPageEntrySectionSegment(Context.Segment, Context.Offset) != 0)
     {
-      KeBugCheck(0);
+      if (!(Context.Segment->Flags & MM_PAGEFILE_SEGMENT))
+        {
+         CHECKPOINT1;
+          KEBUGCHECK(0);
+       }
     }
 
   /*
    * If the page wasn't dirty then we can just free it as for a readonly page.
    * Since we unmapped all the mappings above we know it will not suddenly
-   * become dirty.
+   * become dirty. 
+   * If the page is from a pagefile section and has no swap entry, 
+   * we can't free the page at this point.
    */
-  if (!Context.WasDirty)
+  SwapEntry = MmGetSavedSwapEntryPage(PhysicalAddress);
+  if (!Context.WasDirty && 
+      !(SwapEntry == 0 && Context.Segment->Flags & MM_PAGEFILE_SEGMENT))
+      
     {
-      if (!DirectMapped || Private)
+      if (Context.Private)
        {
          MmSetSavedSwapEntryPage(PhysicalAddress, 0);
-         MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
-       }
-      if (Private)
-       {
-         if (!(Segment->Characteristics & IMAGE_SECTION_CHAR_BSS) &&
+         if (!(Context.Segment->Characteristics & IMAGE_SECTION_CHAR_BSS) &&
              SwapEntry == 0)
            {
              DPRINT1("Private page, non-dirty but not swapped out "
                      "process %d address 0x%.8X\n",
-                     AddressSpace->Process->UniqueProcessId,
+                     AddressSpace->Process ? AddressSpace->Process->UniqueProcessId : 0,
                      Address);       
-             KeBugCheck(0);
+             KEBUGCHECK(0);
            }
          else
            {
@@ -1350,10 +1552,23 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
                                               SwapEntry);
              if (!NT_SUCCESS(Status))
                {
-                 KeBugCheck(0);
+                 KEBUGCHECK(0);
                }
            }
        }
+      if (DirectMapped && !Context.Private)
+        {
+          Status = CcRosUnmapCacheSegment(Bcb, FileOffset, FALSE);
+          if (!NT_SUCCESS(Status))
+            {
+              DPRINT1("CCRosUnmapCacheSegment failed, status = %x\n", Status);
+              KEBUGCHECK(0);
+           }
+       }
+      else
+        {
+          MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
+       }
       
       PageOp->Status = STATUS_SUCCESS;
       KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
@@ -1365,10 +1580,15 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
    * If this page was direct mapped from the cache then the cache manager
    * will already have taken care of writing it back.
    */
-  if (DirectMapped && !Private)
+  if (DirectMapped && !Context.Private)
     {
       assert(SwapEntry == 0);
-      MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
+      Status = CcRosUnmapCacheSegment(Bcb, FileOffset, FALSE);
+      if (!NT_SUCCESS(Status))
+        {
+          DPRINT1("CcRosUnmapCacheSegment failed, status = %x\n", Status);
+          KEBUGCHECK(0);
+       }
       PageOp->Status = STATUS_SUCCESS;
       KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
       MmReleasePageOp(PageOp);
@@ -1378,7 +1598,6 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
   /*
    * If necessary, allocate an entry in the paging file for this page
    */
-  SwapEntry = MmGetSavedSwapEntryPage(PhysicalAddress);
   if (SwapEntry == 0)
     {
       SwapEntry = MmAllocSwapPage();
@@ -1389,7 +1608,7 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
          /*
           * For private pages restore the old mappings.
           */
-         if (Private)
+         if (Context.Private)
            {
              Status = MmCreateVirtualMapping(MemoryArea->Process,   
                                              Address,
@@ -1417,14 +1636,13 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
              MmInsertRmap(PhysicalAddress, 
                           MemoryArea->Process,
                           Address);
-             MmSetPageEntrySectionSegment(Segment, Offset.QuadPart, 
-                                          PhysicalAddress.u.LowPart);
-             MmSharePageEntrySectionSegment(Segment, Offset.QuadPart);
+              Entry = MAKE_SSE(PhysicalAddress.u.LowPart, 1);
+             MmSetPageEntrySectionSegment(Context.Segment, Context.Offset, Entry);
            }
-          PageOp->Status = STATUS_UNSUCCESSFUL;
-          KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
-          MmReleasePageOp(PageOp);
-          return(STATUS_UNSUCCESSFUL);
+         PageOp->Status = STATUS_UNSUCCESSFUL;
+         KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
+         MmReleasePageOp(PageOp);
+         return(STATUS_PAGEFILE_QUOTA);
        }
     }
 
@@ -1442,7 +1660,7 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
        * As above: undo our actions.
        * FIXME: Also free the swap page.
        */
-      if (Private)
+      if (Context.Private)
        {
          Status = MmCreateVirtualMapping(MemoryArea->Process,   
                                          Address,
@@ -1465,9 +1683,8 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
          MmInsertRmap(PhysicalAddress, 
                           MemoryArea->Process,
                           Address);
-         MmSetPageEntrySectionSegment(Segment, Offset.QuadPart, 
-                                      PhysicalAddress.u.LowPart);
-         MmSharePageEntrySectionSegment(Segment, Offset.QuadPart);
+          Entry = MAKE_SSE(PhysicalAddress.u.LowPart, 1);
+         MmSetPageEntrySectionSegment(Context.Segment, Context.Offset, Entry);
        }
       PageOp->Status = STATUS_UNSUCCESSFUL;
       KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
@@ -1482,20 +1699,20 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
   MmSetSavedSwapEntryPage(PhysicalAddress, 0);
   MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
 
-  if (Private)
+  if (Context.Private)
     {
       Status = MmCreatePageFileMapping(MemoryArea->Process,   
                                       Address,
                                       SwapEntry);
       if (!NT_SUCCESS(Status))
        {
-         KeBugCheck(0);
+         KEBUGCHECK(0);
        }
     }
   else
     {
       Entry = MAKE_SWAP_SSE(SwapEntry);
-      MmSetPageEntrySectionSegment(Segment, Offset.QuadPart, Entry);
+      MmSetPageEntrySectionSegment(Context.Segment, Context.Offset, Entry);
     }
 
   PageOp->Status = STATUS_SUCCESS;
@@ -1510,7 +1727,7 @@ MmWritePageSectionView(PMADDRESS_SPACE AddressSpace,
                       PVOID Address,
                       PMM_PAGEOP PageOp)
 {
-  LARGE_INTEGER Offset;
+  ULONG Offset;
   PSECTION_OBJECT Section;
   PMM_SECTION_SEGMENT Segment;
   PHYSICAL_ADDRESS PhysicalAddress;
@@ -1520,19 +1737,26 @@ MmWritePageSectionView(PMADDRESS_SPACE AddressSpace,
   BOOLEAN Private;
   NTSTATUS Status;
   PFILE_OBJECT FileObject;
-  PREACTOS_COMMON_FCB_HEADER Fcb = NULL;
+  PBCB Bcb = NULL;
   BOOLEAN DirectMapped;
+  BOOLEAN IsImageSection;
 
   Address = (PVOID)PAGE_ROUND_DOWN(Address);
 
-  Offset.QuadPart = (ULONG)(Address - (ULONG)MemoryArea->BaseAddress) +
-     MemoryArea->Data.SectionData.ViewOffset;
+  Offset = (ULONG)(Address - (ULONG)MemoryArea->BaseAddress);
 
-  FileObject = MemoryArea->Data.SectionData.Section->FileObject;
+  /*
+   * Get the segment and section.
+   */
+  Segment = MemoryArea->Data.SectionData.Segment;
+  Section = MemoryArea->Data.SectionData.Section;
+  IsImageSection = Section->AllocationAttributes & SEC_IMAGE ? TRUE : FALSE;
+
+  FileObject = Section->FileObject;
   DirectMapped = FALSE;
   if (FileObject != NULL)
     {
-      Fcb = (PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext;
+      Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
   
       /*
        * If the file system is letting us go directly to the cache and the
@@ -1540,38 +1764,34 @@ MmWritePageSectionView(PMADDRESS_SPACE AddressSpace,
        * then note this is a direct mapped page.
        */
       if (FileObject->Flags & FO_DIRECT_CACHE_PAGING_READ &&
-         (Offset.QuadPart % PAGE_SIZE) == 0)
+         (Offset + MemoryArea->Data.SectionData.ViewOffset % PAGE_SIZE) == 0 &&
+         (Offset + PAGE_SIZE <= Segment->RawLength || !IsImageSection))
        {
          DirectMapped = TRUE;
        }
     }
    
   /*
-   * Get the segment and section.
-   */
-  Segment = MemoryArea->Data.SectionData.Segment;
-  Section = MemoryArea->Data.SectionData.Section;
-
-  /*
    * This should never happen since mappings of physical memory are never
    * placed in the rmap lists.
    */
   if (Section->AllocationAttributes & SEC_PHYSICALMEMORY)
     {
       DPRINT1("Trying to write back page from physical memory mapped at %X "
-             "process %d\n", Address, AddressSpace->Process->UniqueProcessId);
-      KeBugCheck(0);
+             "process %d\n", Address, 
+             AddressSpace->Process ? AddressSpace->Process->UniqueProcessId : 0);
+      KEBUGCHECK(0);
     }
 
   /*
    * Get the section segment entry and the physical address.
    */
-  Entry = MmGetPageEntrySectionSegment(Segment, Offset.QuadPart);
+  Entry = MmGetPageEntrySectionSegment(Segment, Offset);
   if (!MmIsPagePresent(AddressSpace->Process, Address))
     {
       DPRINT1("Trying to page out not-present page at (%d,0x%.8X).\n",
-             AddressSpace->Process->UniqueProcessId, Address);
-      KeBugCheck(0);
+         AddressSpace->Process ? AddressSpace->Process->UniqueProcessId : 0, Address);
+      KEBUGCHECK(0);
     }
   PhysicalAddress = 
     MmGetPhysicalAddressForProcess(AddressSpace->Process, Address);
@@ -1603,7 +1823,7 @@ MmWritePageSectionView(PMADDRESS_SPACE AddressSpace,
   if (DirectMapped && !Private)
     {
       assert(SwapEntry == 0);
-      CcRosMarkDirtyCacheSegment(Fcb->Bcb, Offset.u.LowPart);
+      CcRosMarkDirtyCacheSegment(Bcb, Offset + MemoryArea->Data.SectionData.ViewOffset);
       PageOp->Status = STATUS_SUCCESS;
       KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
       MmReleasePageOp(PageOp);
@@ -1613,7 +1833,6 @@ MmWritePageSectionView(PMADDRESS_SPACE AddressSpace,
   /*
    * If necessary, allocate an entry in the paging file for this page
    */
-  SwapEntry = MmGetSavedSwapEntryPage(PhysicalAddress);
   if (SwapEntry == 0)
     {
       SwapEntry = MmAllocSwapPage();
@@ -1623,7 +1842,7 @@ MmWritePageSectionView(PMADDRESS_SPACE AddressSpace,
          PageOp->Status = STATUS_UNSUCCESSFUL;
          KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
          MmReleasePageOp(PageOp);
-         return(STATUS_UNSUCCESSFUL);
+         return(STATUS_PAGEFILE_QUOTA);
        }
     }
 
@@ -1680,7 +1899,7 @@ MmAlterViewAttributes(PMADDRESS_SPACE AddressSpace,
 
   if (OldProtect != NewProtect)
     {
-      for (i = 0; i < (RegionSize / PAGE_SIZE); i++)
+      for (i = 0; i < PAGE_ROUND_UP(RegionSize) / PAGE_SIZE; i++)
        {
          PVOID Address = BaseAddress + (i * PAGE_SIZE);
          ULONG Protect = NewProtect;
@@ -1691,14 +1910,12 @@ MmAlterViewAttributes(PMADDRESS_SPACE AddressSpace,
           */
          if (DoCOW && MmIsPagePresent(AddressSpace->Process, Address))
            {
-             LARGE_INTEGER Offset;
+             ULONG Offset;
              ULONG Entry;
              LARGE_INTEGER PhysicalAddress;
 
-             Offset.QuadPart = 
-               (ULONG)(Address - (ULONG)MemoryArea->BaseAddress) +
-               MemoryArea->Data.SectionData.ViewOffset;
-             Entry = MmGetPageEntrySectionSegment(Segment, Offset.QuadPart);
+             Offset =  (ULONG)Address - (ULONG)MemoryArea->BaseAddress;
+             Entry = MmGetPageEntrySectionSegment(Segment, Offset);
              PhysicalAddress = 
                MmGetPhysicalAddressForProcess(AddressSpace->Process, Address);
 
@@ -1732,7 +1949,7 @@ MmProtectSectionView(PMADDRESS_SPACE AddressSpace,
   NTSTATUS Status;
 
   Length = 
-    min(Length, MemoryArea->BaseAddress + MemoryArea->Length - BaseAddress);
+    min(Length, (ULONG) (MemoryArea->BaseAddress + MemoryArea->Length - BaseAddress));
   Region = MmFindRegion(MemoryArea->BaseAddress,
                        &MemoryArea->Data.SectionData.RegionListHead,
                        BaseAddress, NULL);
@@ -1757,6 +1974,10 @@ MmQuerySectionView(PMEMORY_AREA MemoryArea,
   Region = MmFindRegion(MemoryArea->BaseAddress,
                        &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;
@@ -1784,22 +2005,60 @@ MmpDeleteSection(PVOID ObjectBody)
   if (Section->AllocationAttributes & SEC_IMAGE)
     {
       ULONG i;
-      
-      for (i = 0; i < Section->NrSegments; i++)
+      ULONG NrSegments;
+      PMM_SECTION_SEGMENT SectionSegments;
+
+      SectionSegments = Section->ImageSection->Segments;
+      NrSegments = Section->ImageSection->NrSegments;
+
+      for (i = 0; i < NrSegments; i++)
        {
-         InterlockedDecrement(&Section->Segments[i].ReferenceCount);
+         InterlockedDecrement((LONG *)&SectionSegments[i].ReferenceCount);
        }
     }
   else
     {
-      InterlockedDecrement(&Section->Segments->ReferenceCount);
+      if (Section->Segment->Flags & MM_PAGEFILE_SEGMENT)
+       {
+         ULONG Offset;
+         ULONG Length;
+         ULONG Entry;
+         PMM_SECTION_SEGMENT Segment;
+         
+         Segment = Section->Segment;
+         Length = PAGE_ROUND_UP(Segment->Length);
+         
+         for (Offset = 0; Offset < Length; Offset += PAGE_SIZE)
+           {
+             Entry = MmGetPageEntrySectionSegment(Segment, Offset);
+             if (Entry)
+               {
+                 if (IS_SWAP_FROM_SSE(Entry))
+                   {
+                     MmFreeSwapPage(SWAPENTRY_FROM_SSE(Entry));
+                   }
+                 else
+                   {
+                     PHYSICAL_ADDRESS Page = (PHYSICAL_ADDRESS)(LONGLONG)PAGE_FROM_SSE(Entry);
+                     MmReleasePageMemoryConsumer(MC_USER, Page);
+                   }
+               }
+           }
+         MmFreePageTablesSectionSegment(Section->Segment);
+         ExFreePool(Section->Segment);
+         Section->Segment = NULL;
+       }
+      else
+       {
+         InterlockedDecrement((LONG *)&Section->Segment->ReferenceCount);
+       }
     }
   if (Section->FileObject != NULL)
     {
       CcRosDereferenceCache(Section->FileObject);
       ObDereferenceObject(Section->FileObject);
       Section->FileObject = NULL;
-    }
+    }  
 }
 
 VOID STDCALL
@@ -1808,7 +2067,6 @@ MmpCloseSection(PVOID ObjectBody,
 {
    DPRINT("MmpCloseSection(OB %x, HC %d) RC %d\n",
           ObjectBody, HandleCount, ObGetObjectPointerCount(ObjectBody));
-   
 }
 
 NTSTATUS STDCALL
@@ -1818,18 +2076,17 @@ MmpCreateSection(PVOID ObjectBody,
                 POBJECT_ATTRIBUTES ObjectAttributes)
 {
    DPRINT("MmpCreateSection(ObjectBody %x, Parent %x, RemainingPath %S)\n",
-         ObjectBody, Parent, RemainingPath);
+          ObjectBody, Parent, RemainingPath);
    
    if (RemainingPath == NULL)
      {
-       return(STATUS_SUCCESS);
+        return(STATUS_SUCCESS);
      }
    
    if (wcschr(RemainingPath+1, L'\\') != NULL)
      {
        return(STATUS_UNSUCCESSFUL);
      }
-   
    return(STATUS_SUCCESS);
 }
 
@@ -1862,7 +2119,7 @@ MmCreatePhysicalMemorySection(VOID)
   if (!NT_SUCCESS(Status))
     {
       DbgPrint("Failed to create PhysicalMemory section\n");
-      KeBugCheck(0);
+      KEBUGCHECK(0);
     }
   Status = ObReferenceObjectByHandle(PhysSectionH,
                                     SECTION_ALL_ACCESS,
@@ -1873,7 +2130,7 @@ MmCreatePhysicalMemorySection(VOID)
   if (!NT_SUCCESS(Status))
     {
       DbgPrint("Failed to reference PhysicalMemory section\n");
-      KeBugCheck(0);
+      KEBUGCHECK(0);
     }
   PhysSection->AllocationAttributes |= SEC_PHYSICALMEMORY;
   ObDereferenceObject((PVOID)PhysSection);
@@ -1944,7 +2201,7 @@ MmCreatePageFileSection(PHANDLE SectionHandle,
   /*
    * Create the section
    */
-  Status = ObCreateObject(SectionHandle,
+  Status = ObRosCreateObject(SectionHandle,
                          DesiredAccess,
                          ObjectAttributes,
                          MmSectionObjectType,
@@ -1961,7 +2218,6 @@ MmCreatePageFileSection(PHANDLE SectionHandle,
   Section->AllocationAttributes = AllocationAttributes;
   InitializeListHead(&Section->ViewListHead);
   KeInitializeSpinLock(&Section->ViewListLock);
-  KeInitializeMutex(&Section->Lock, 0);
   Section->FileObject = NULL;
   Section->MaximumSize = MaximumSize;
   Segment = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_SECTION_SEGMENT),
@@ -1972,15 +2228,16 @@ MmCreatePageFileSection(PHANDLE SectionHandle,
       ObDereferenceObject(Section);
       return(STATUS_NO_MEMORY);
     }
-  Section->Segments = Segment;
+  Section->Segment = Segment;
   Segment->ReferenceCount = 1;
-  KeInitializeMutex(&Segment->Lock, 0);
+  ExInitializeFastMutex(&Segment->Lock);
   Segment->FileOffset = 0;
   Segment->Protection = SectionPageProtection;
   Segment->Attributes = AllocationAttributes;
   Segment->Length = MaximumSize.u.LowPart;
   Segment->Flags = MM_PAGEFILE_SEGMENT;
   Segment->WriteCopy = FALSE;
+  ObDereferenceObject(Section);
   return(STATUS_SUCCESS);
 }
 
@@ -2003,6 +2260,9 @@ MmCreateDataFileSection(PHANDLE SectionHandle,
   PFILE_OBJECT FileObject;
   PMM_SECTION_SEGMENT Segment;
   ULONG FileAccess;
+  IO_STATUS_BLOCK Iosb;
+  LARGE_INTEGER Offset;
+  CHAR Buffer;
   
   /*
    * Check the protection
@@ -2012,11 +2272,31 @@ MmCreateDataFileSection(PHANDLE SectionHandle,
     {
       return(STATUS_INVALID_PAGE_PROTECTION);
     }
-  
+
+  /*
+   * Read a bit so caching is initiated for the file object.
+   * This is only needed because MiReadPage currently cannot
+   * handle non-cached streams.
+   */
+  Offset.QuadPart = 0;
+  Status = ZwReadFile(FileHandle,
+                     NULL,
+                     NULL,
+                     NULL,
+                     &Iosb,
+                     &Buffer,
+                     sizeof (Buffer),
+                     &Offset,
+                     0);
+  if (!NT_SUCCESS(Status) && (Status != STATUS_END_OF_FILE))
+    {
+      return(Status);
+    }
+
   /*
    * Create the section
    */
-  Status = ObCreateObject(SectionHandle,
+  Status = ObRosCreateObject(SectionHandle,
                          DesiredAccess,
                          ObjectAttributes,
                          MmSectionObjectType,
@@ -2033,18 +2313,6 @@ MmCreateDataFileSection(PHANDLE SectionHandle,
   Section->AllocationAttributes = AllocationAttributes;
   InitializeListHead(&Section->ViewListHead);
   KeInitializeSpinLock(&Section->ViewListLock);
-  KeInitializeMutex(&Section->Lock, 0);
-  Section->NrSegments = 1;
-  Section->ImageBase = NULL;
-  Section->EntryPoint = NULL;
-  Section->StackReserve = 0;
-  Section->StackCommit = 0;
-  Section->Subsystem = 0;
-  Section->MinorSubsystemVersion = 0;
-  Section->MajorSubsystemVersion = 0;
-  Section->ImageCharacteristics = 0;
-  Section->Machine = 0;
-  Section->Executable = FALSE;
 
   /*
    * Check file access required
@@ -2098,11 +2366,11 @@ MmCreateDataFileSection(PHANDLE SectionHandle,
   else
     {
       MaximumSize = 
-       ((PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext)->FileSize;
+       ((PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext)->FileSize;
     }
 
   if (MaximumSize.QuadPart > 
-      ((PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext)->FileSize.QuadPart)
+      ((PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext)->FileSize.QuadPart)
     {
       IO_STATUS_BLOCK Iosb;
       Status = NtSetInformationFile(FileHandle,
@@ -2139,7 +2407,7 @@ MmCreateDataFileSection(PHANDLE SectionHandle,
    * If this file hasn't been mapped as a data file before then allocate a
    * section segment to describe the data file mapping
    */
-  if (FileObject->SectionObjectPointers->DataSectionObject == NULL)
+  if (FileObject->SectionObjectPointer->DataSectionObject == NULL)
     {
       Segment = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_SECTION_SEGMENT),
                                      TAG_MM_SECTION_SEGMENT);
@@ -2151,28 +2419,14 @@ MmCreateDataFileSection(PHANDLE SectionHandle,
          ObDereferenceObject(FileObject);
          return(STATUS_NO_MEMORY);
        }
-      Section->Segments = Segment;
+      Section->Segment = Segment;
       Segment->ReferenceCount = 1;
-      KeInitializeMutex(&Segment->Lock, 0);
-
+      ExInitializeFastMutex(&Segment->Lock);
       /*
        * Set the lock before assigning the segment to the file object
        */
-      Status = KeWaitForSingleObject((PVOID)&Segment->Lock,
-                                    0,
-                                    KernelMode,
-                                    FALSE,
-                                    NULL);
-      if (Status != STATUS_SUCCESS)
-       {
-         KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
-         ExFreePool(Segment);
-         ZwClose(*SectionHandle);
-         ObDereferenceObject(Section);
-         ObDereferenceObject(FileObject);
-         return(Status);
-       }
-      FileObject->SectionObjectPointers->DataSectionObject = (PVOID)Segment;
+      ExAcquireFastMutex(&Segment->Lock);
+      FileObject->SectionObjectPointer->DataSectionObject = (PVOID)Segment;
 
       Segment->FileOffset = 0;
       Segment->Protection = 0;
@@ -2182,11 +2436,12 @@ MmCreateDataFileSection(PHANDLE SectionHandle,
       Segment->WriteCopy = FALSE;
       if (AllocationAttributes & SEC_RESERVE)
        {
-         Segment->Length = 0;
+         Segment->Length = Segment->RawLength = 0;
        }
       else
        {
-         Segment->Length = MaximumSize.u.LowPart;
+         Segment->RawLength = MaximumSize.u.LowPart;
+         Segment->Length = PAGE_ROUND_UP(Segment->RawLength);
        }
       Segment->VirtualAddress = NULL;
     }
@@ -2197,36 +2452,24 @@ MmCreateDataFileSection(PHANDLE SectionHandle,
        * to extend it
        */      
       Segment = 
-       (PMM_SECTION_SEGMENT)FileObject->SectionObjectPointers->
+       (PMM_SECTION_SEGMENT)FileObject->SectionObjectPointer->
        DataSectionObject;
-      Section->Segments = Segment;
+      Section->Segment = Segment;
       InterlockedIncrement((PLONG)&Segment->ReferenceCount);
-      Status = KeWaitForSingleObject((PVOID)&Segment->Lock,
-                                    0,
-                                    KernelMode,
-                                    FALSE,
-                                    NULL);
-      if (Status != STATUS_SUCCESS)
-       {
-         InterlockedDecrement((PLONG)&Segment->ReferenceCount);
-         KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
-         ZwClose(*SectionHandle);
-         ObDereferenceObject(Section);
-         ObDereferenceObject(FileObject);
-         return(Status);
-       }
-      if (MaximumSize.u.LowPart > Segment->Length && 
+      MmLockSectionSegment(Segment);
+
+      if (MaximumSize.u.LowPart > Segment->RawLength && 
          !(AllocationAttributes & SEC_RESERVE))
        {
-         Segment->Length = MaximumSize.u.LowPart;
+         Segment->RawLength = MaximumSize.u.LowPart;
+         Segment->Length = PAGE_ROUND_UP(Segment->RawLength);
        }
     }
-  KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
-  CcRosReferenceCache(FileObject);
+  MmUnlockSectionSegment(Segment);
   Section->FileObject = FileObject; 
   Section->MaximumSize = MaximumSize;
-  KeReleaseMutex(&Segment->Lock, FALSE);
-
+  CcRosReferenceCache(FileObject);
+  KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
   ObDereferenceObject(Section);
   return(STATUS_SUCCESS);
 }
@@ -2263,7 +2506,6 @@ MmCreateImageSection(PHANDLE SectionHandle,
   PSECTION_OBJECT Section;
   NTSTATUS Status;
   PFILE_OBJECT FileObject;
-  ULONG FileAccess;
   IMAGE_DOS_HEADER DosHeader;
   IO_STATUS_BLOCK Iosb;
   LARGE_INTEGER Offset;
@@ -2272,7 +2514,10 @@ MmCreateImageSection(PHANDLE SectionHandle,
   PMM_SECTION_SEGMENT SectionSegments;
   ULONG NrSegments;
   PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
-
+  ULONG i;
+  ULONG Size;
+  ULONG Characteristics;
+  ULONG FileAccess = 0;
   /*
    * Check the protection
    */
@@ -2291,145 +2536,6 @@ MmCreateImageSection(PHANDLE SectionHandle,
     } 
 
   /*
-   * Read the dos header
-   */
-  Offset.QuadPart = 0;
-  Status = ZwReadFile(FileHandle,
-                     NULL,
-                     NULL,
-                     NULL,
-                     &Iosb,
-                     &DosHeader,
-                     sizeof(DosHeader),
-                     &Offset,
-                     0);
-  if (!NT_SUCCESS(Status))
-    {
-      return(Status);
-    }
-  if (Iosb.Information != sizeof(DosHeader))
-    {
-      return(STATUS_INVALID_IMAGE_FORMAT);
-    }
-
-  /*
-   * Check the DOS signature
-   */
-  if (DosHeader.e_magic != IMAGE_DOS_SIGNATURE)
-    {
-      return(STATUS_INVALID_IMAGE_FORMAT);
-    }
-
-  /*
-   * Read the PE header
-   */
-  Offset.QuadPart = DosHeader.e_lfanew;
-  Status = ZwReadFile(FileHandle,
-                     NULL,
-                     NULL,
-                     NULL,
-                     &Iosb,
-                     &PEHeader,
-                     sizeof(PEHeader),
-                     &Offset,
-                     0);
-  if (!NT_SUCCESS(Status))
-    {
-      return(Status);
-    }
-  if (Iosb.Information != sizeof(PEHeader))
-    {
-      return(STATUS_INVALID_IMAGE_FORMAT);
-    }
-
-  /*
-   * Check the signature
-   */
-  if (PEHeader.Signature != IMAGE_NT_SIGNATURE)
-    {
-      return(STATUS_INVALID_IMAGE_FORMAT);
-    }
-
-  /*
-   * Read in the section headers
-   */
-  Offset.QuadPart = DosHeader.e_lfanew + sizeof(PEHeader);  
-  ImageSections = 
-    ExAllocatePool(NonPagedPool,
-                  PEHeader.FileHeader.NumberOfSections * 
-                  sizeof(IMAGE_SECTION_HEADER));
-  Status = ZwReadFile(FileHandle,
-                     NULL,
-                     NULL,
-                     NULL,
-                     &Iosb,
-                     ImageSections,
-                     PEHeader.FileHeader.NumberOfSections * 
-                     sizeof(IMAGE_SECTION_HEADER),
-                     &Offset,
-                     0);
-  if (!NT_SUCCESS(Status))
-    {
-      ExFreePool(ImageSections);
-      return(Status);
-    }
-  if (Iosb.Information != 
-      (PEHeader.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER)))
-    {
-      ExFreePool(ImageSections);
-      return(STATUS_INVALID_IMAGE_FORMAT);
-    }
-
-  /*
-   * Create the section
-   */
-  Status = ObCreateObject(SectionHandle,
-                         DesiredAccess,
-                         ObjectAttributes,
-                         MmSectionObjectType,
-                         (PVOID*)&Section);
-  if (!NT_SUCCESS(Status))
-    {
-      ExFreePool(ImageSections);
-      return(Status);
-    }
-
-  /*
-   * Initialize it
-   */
-  Section->SectionPageProtection = SectionPageProtection;
-  Section->AllocationAttributes = AllocationAttributes;
-  InitializeListHead(&Section->ViewListHead);
-  KeInitializeSpinLock(&Section->ViewListLock);
-  KeInitializeMutex(&Section->Lock, 0);
-  Section->NrSegments = PEHeader.FileHeader.NumberOfSections + 1;
-  Section->ImageBase = (PVOID)PEHeader.OptionalHeader.ImageBase;
-  Section->EntryPoint = (PVOID)PEHeader.OptionalHeader.AddressOfEntryPoint;
-  Section->StackReserve = PEHeader.OptionalHeader.SizeOfStackReserve;
-  Section->StackCommit = PEHeader.OptionalHeader.SizeOfStackCommit;
-  Section->Subsystem = PEHeader.OptionalHeader.Subsystem;
-  Section->MinorSubsystemVersion = 
-    PEHeader.OptionalHeader.MinorSubsystemVersion;
-  Section->MajorSubsystemVersion = 
-    PEHeader.OptionalHeader.MajorSubsystemVersion;
-  Section->ImageCharacteristics = PEHeader.FileHeader.Characteristics;
-  Section->Machine = PEHeader.FileHeader.Machine;
-  Section->Executable = (PEHeader.OptionalHeader.SizeOfCode != 0); 
-
-  /*
-   * Check file access required
-   */
-  if (SectionPageProtection & PAGE_READWRITE ||
-      SectionPageProtection & PAGE_EXECUTE_READWRITE)
-    {
-      FileAccess = FILE_READ_DATA | FILE_WRITE_DATA;
-    }
-  else
-    {
-      FileAccess = FILE_READ_DATA;
-    }
-  
-  /*
    * Reference the file handle
    */
   Status = ObReferenceObjectByHandle(FileHandle,
@@ -2440,182 +2546,371 @@ MmCreateImageSection(PHANDLE SectionHandle,
                                     NULL);
   if (!NT_SUCCESS(Status))
     {
-      ZwClose(*SectionHandle);
-      ObDereferenceObject(Section);
-      ExFreePool(ImageSections);
-      return(Status);
+      return Status;
     }
 
   /*
-   * We can't do memory mappings if the file system doesn't support the
-   * standard FCB
+   * Initialized caching for this file object if previously caching 
+   * was initialized for the same on disk file
    */
-  if (!(FileObject->Flags & FO_FCB_IS_VALID))
-    {
-      ZwClose(*SectionHandle);
-      ObDereferenceObject(Section);
-      ObDereferenceObject(FileObject);
-      ExFreePool(ImageSections);
-      return(STATUS_INVALID_FILE_FOR_SECTION);
-    }
+  Status = CcTryToInitializeFileCache(FileObject);
   
-  /*
-   * Lock the file
-   */
-  Status = KeWaitForSingleObject((PVOID)&FileObject->Lock,
-                                0,
-                                KernelMode,
-                                FALSE,
-                                NULL);
-  if (Status != STATUS_SUCCESS)
+  if (!NT_SUCCESS(Status) || FileObject->SectionObjectPointer->ImageSectionObject == NULL)
     {
-      ZwClose(*SectionHandle);
-      ObDereferenceObject(Section);
-      ObDereferenceObject(FileObject);
-      ExFreePool(ImageSections);
-      return(Status);
-    }
+      /*
+       * Read the dos header and check the DOS signature
+       */
+      Offset.QuadPart = 0;
+      Status = ZwReadFile(FileHandle,
+                         NULL,
+                         NULL,
+                         NULL,
+                         &Iosb,
+                         &DosHeader,
+                         sizeof(DosHeader),
+                         &Offset,
+                         0);
+      if (!NT_SUCCESS(Status))
+        {
+          ObDereferenceObject(FileObject);
+          return(Status);
+       }
+    
+      /*
+       * Check the DOS signature
+       */
+      if (Iosb.Information != sizeof(DosHeader) ||
+         DosHeader.e_magic != IMAGE_DOS_SIGNATURE)
+        {
+          ObDereferenceObject(FileObject);
+          return(STATUS_INVALID_IMAGE_FORMAT);
+        }
+
+      /*
+       * Read the PE header
+       */
+      Offset.QuadPart = DosHeader.e_lfanew;
+      Status = ZwReadFile(FileHandle,
+                         NULL,
+                         NULL,
+                         NULL,
+                         &Iosb,
+                         &PEHeader,
+                         sizeof(PEHeader),
+                         &Offset,
+                         0);
+      if (!NT_SUCCESS(Status))
+        {
+          ObDereferenceObject(FileObject);
+          return(Status);
+        }
 
-  /*
-   * If this file hasn't been mapped as a image file before then allocate the
-   * section segments to describe the mapping
-   */
-  NrSegments = PEHeader.FileHeader.NumberOfSections + 1;
-  if (FileObject->SectionObjectPointers->ImageSectionObject == NULL)
-    {
-      ULONG i;
-      ULONG Size;
-      ULONG Characteristics;
-
-      Size = sizeof(MM_IMAGE_SECTION_OBJECT) + 
-       (sizeof(MM_SECTION_SEGMENT) * NrSegments);
-      ImageSectionObject = 
-       ExAllocatePoolWithTag(NonPagedPool, Size, TAG_MM_SECTION_SEGMENT);
-      if (ImageSectionObject == NULL)
-       {
-         KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
-         ZwClose(*SectionHandle);
-         ObDereferenceObject(Section);
+      /*
+       * Check the signature
+       */
+      if (Iosb.Information != sizeof(PEHeader) || 
+         PEHeader.Signature != IMAGE_NT_SIGNATURE)
+        {
+          ObDereferenceObject(FileObject);
+          return(STATUS_INVALID_IMAGE_FORMAT);
+        }
+
+      /*
+       * 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);
-         ExFreePool(ImageSections);
          return(STATUS_NO_MEMORY);
        }
-      ImageSectionObject->NrSegments = NrSegments;
-      SectionSegments = ImageSectionObject->Segments;
-      Section->Segments = SectionSegments;
-
-      SectionSegments[0].FileOffset = 0;
-      SectionSegments[0].Characteristics = IMAGE_SECTION_CHAR_DATA;
-      SectionSegments[0].Protection = PAGE_READWRITE;
-      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;
-      KeInitializeMutex(&SectionSegments[0].Lock, 0);
-
-      for (i = 1; i < NrSegments; i++)
-       {
-         SectionSegments[i].FileOffset = 
-           ImageSections[i-1].PointerToRawData;
-         SectionSegments[i].Characteristics = 
-           ImageSections[i-1].Characteristics;
 
-         /*
-          * Set up the protection and write copy variables.
-          */
-         Characteristics = ImageSections[i - 1].Characteristics;
-         if ((Characteristics & IMAGE_SECTION_CHAR_READABLE) ||
-             (Characteristics & IMAGE_SECTION_CHAR_WRITABLE) ||
-             (Characteristics & 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
-           {
-             SectionSegments[i].Protection = PAGE_NOACCESS;
-             SectionSegments[i].WriteCopy = TRUE;
-           }
-         
-         /*
-          * Set up the attributes.
-          */
-         if (Characteristics & IMAGE_SECTION_CHAR_CODE)            
-           {
-             SectionSegments[i].Attributes = 0;
-           }
-         else if (Characteristics & IMAGE_SECTION_CHAR_DATA)       
-           {
-             SectionSegments[i].Attributes = 0;
-           }
-         else if (Characteristics & IMAGE_SECTION_CHAR_BSS)
-           {
-             SectionSegments[i].Attributes = MM_SECTION_SEGMENT_BSS;
-           }
-         else
-           {
-             SectionSegments[i].Attributes = 0;
-           }
+      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);
+        }
 
-         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;
-         KeInitializeMutex(&SectionSegments[i].Lock, 0);
-       }
+      /*
+       * Create the section
+       */
+        Status = ObRosCreateObject(SectionHandle,
+                                  DesiredAccess,
+                                  ObjectAttributes,
+                                  MmSectionObjectType,
+                                  (PVOID*)&Section);
+        if (!NT_SUCCESS(Status))
+          {
+            ObDereferenceObject(FileObject);
+            ExFreePool(ImageSections);
+            return(Status);
+          }
+
+        /*
+         * Initialize it
+         */
+        Section->SectionPageProtection = SectionPageProtection;
+        Section->AllocationAttributes = AllocationAttributes;
+        InitializeListHead(&Section->ViewListHead);
+        KeInitializeSpinLock(&Section->ViewListLock);
 
-      FileObject->SectionObjectPointers->ImageSectionObject = 
-       (PVOID)ImageSectionObject;       
+       /*
+         * Check file access required
+         */
+        if (SectionPageProtection & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE))
+          {
+            FileAccess = FILE_READ_DATA | FILE_WRITE_DATA;
+          }
+        else
+          {
+            FileAccess = FILE_READ_DATA;
+          }
+  
+        /*
+         * We can't do memory mappings if the file system doesn't support the
+         * standard FCB
+         */
+        if (!(FileObject->Flags & FO_FCB_IS_VALID))
+          {
+            ZwClose(*SectionHandle);
+            ObDereferenceObject(Section);
+            ObDereferenceObject(FileObject);
+            ExFreePool(ImageSections);
+            return(STATUS_INVALID_FILE_FOR_SECTION);
+          }
+  
+        /*
+         * Lock the file
+         */
+        Status = KeWaitForSingleObject((PVOID)&FileObject->Lock,
+                                      0,
+                                      KernelMode,
+                                      FALSE,
+                                      NULL);
+        if (Status != STATUS_SUCCESS)
+          {
+            ZwClose(*SectionHandle);
+            ObDereferenceObject(Section);
+            ObDereferenceObject(FileObject);
+            ExFreePool(ImageSections);
+            return(Status);
+          }
+
+        /*
+         * allocate the section segments to describe the mapping
+         */
+        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)
+         {
+           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);
+
+       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 = FALSE;
+       ExInitializeFastMutex(&SectionSegments[0].Lock);
+        for (i = 1; i < NrSegments; i++)
+         {
+           SectionSegments[i].FileOffset = ImageSections[i-1].PointerToRawData;
+           SectionSegments[i].Characteristics = ImageSections[i-1].Characteristics;
+
+           /*
+            * 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
+             {
+               SectionSegments[i].Protection = PAGE_NOACCESS;
+               SectionSegments[i].WriteCopy = TRUE;
+             }
+         
+           /*
+            * Set up the attributes.
+            */
+           if (Characteristics & IMAGE_SECTION_CHAR_CODE)
+             {
+               SectionSegments[i].Attributes = 0;
+             }
+           else if (Characteristics & IMAGE_SECTION_CHAR_DATA)
+             {
+               SectionSegments[i].Attributes = 0;
+             }
+           else if (Characteristics & IMAGE_SECTION_CHAR_BSS)
+             {
+               SectionSegments[i].Attributes = MM_SECTION_SEGMENT_BSS;
+             }
+           else
+             {
+               SectionSegments[i].Attributes = 0;
+             }
+
+           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);
+         }
+        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;
+
+            for (i = 0; i < NrSegments; i++)
+            {
+               InterlockedIncrement((LONG *)&SectionSegments[i].ReferenceCount);
+            }
+         }
+        ExFreePool(ImageSections);
     }
   else
     {
-      ULONG i;
+      /*
+       * Create the section
+       */
+      Status = ObRosCreateObject(SectionHandle,
+                                DesiredAccess,
+                                ObjectAttributes,
+                                MmSectionObjectType,
+                                (PVOID*)&Section);
+      if (!NT_SUCCESS(Status))
+        {
+          ObDereferenceObject(FileObject);
+          return(Status);
+        }
+
+      /*
+       * Initialize it
+       */
+      Section->SectionPageProtection = SectionPageProtection;
+      Section->AllocationAttributes = AllocationAttributes;
+      InitializeListHead(&Section->ViewListHead);
+      KeInitializeSpinLock(&Section->ViewListLock);
 
-      ImageSectionObject = (PMM_IMAGE_SECTION_OBJECT)
-       FileObject->SectionObjectPointers->ImageSectionObject;
+      /*
+       * Check file access required
+       */
+      if (SectionPageProtection & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE))
+        {
+          FileAccess = FILE_READ_DATA | FILE_WRITE_DATA;
+        }
+      else
+        {
+          FileAccess = FILE_READ_DATA;
+        }
+  
+      /*
+       * Lock the file
+       */
+      Status = KeWaitForSingleObject((PVOID)&FileObject->Lock,
+                                    0,
+                                    KernelMode,
+                                    FALSE,
+                                    NULL);
+      if (Status != STATUS_SUCCESS)
+        {
+          ZwClose(*SectionHandle);
+          ObDereferenceObject(Section);
+          ObDereferenceObject(FileObject);
+          return(Status);
+        }
+
+      ImageSectionObject = FileObject->SectionObjectPointer->ImageSectionObject;
+      Section->ImageSection = ImageSectionObject;
       SectionSegments = ImageSectionObject->Segments;
-      Section->Segments = SectionSegments;
+      NrSegments = ImageSectionObject->NrSegments;
 
       /*
        * Otherwise just reference all the section segments
        */
       for (i = 0; i < NrSegments; i++)
        {
-         InterlockedIncrement(&SectionSegments[i].ReferenceCount);
+         InterlockedIncrement((LONG *)&SectionSegments[i].ReferenceCount);
        }
 
     }
-  ExFreePool(ImageSections);
-  KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
-  CcRosReferenceCache(FileObject);
   Section->FileObject = FileObject;
-
+  CcRosReferenceCache(FileObject);
+  KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
   ObDereferenceObject(Section);
   return(STATUS_SUCCESS);
 }
 
+/*
+ * @implemented
+ */
 NTSTATUS STDCALL
 NtCreateSection (OUT PHANDLE SectionHandle,
                 IN ACCESS_MASK DesiredAccess,
@@ -2673,26 +2968,25 @@ NtCreateSection (OUT PHANDLE SectionHandle,
  * RETURN VALUE
  *
  * REVISIONS
- *
  */
 NTSTATUS STDCALL
 NtOpenSection(PHANDLE                  SectionHandle,
              ACCESS_MASK               DesiredAccess,
              POBJECT_ATTRIBUTES        ObjectAttributes)
 {
-   NTSTATUS Status;
-   
-   *SectionHandle = 0;
+  NTSTATUS Status;
 
-   Status = ObOpenObjectByName(ObjectAttributes,
-                              MmSectionObjectType,
-                              NULL,
-                              UserMode,
-                              DesiredAccess,
-                              NULL,
-                              SectionHandle);
+  *SectionHandle = 0;
 
-   return(Status);
+  Status = ObOpenObjectByName(ObjectAttributes,
+                             MmSectionObjectType,
+                             NULL,
+                             UserMode,
+                             DesiredAccess,
+                             NULL,
+                             SectionHandle);
+
+  return(Status);
 }
 
 NTSTATUS STATIC
@@ -2703,32 +2997,34 @@ MmMapViewOfSegment(PEPROCESS Process,
                   PVOID* BaseAddress,
                   ULONG ViewSize,
                   ULONG Protect,
-                  ULONG ViewOffset)
+                  ULONG ViewOffset,
+                  BOOL TopDown)
 {
   PMEMORY_AREA MArea;
   NTSTATUS Status;
   KIRQL oldIrql;
 
   Status = MmCreateMemoryArea(Process,
-                             &Process->AddressSpace,
+                             AddressSpace,
                              MEMORY_AREA_SECTION_VIEW,
                              BaseAddress,
                              ViewSize,
                              Protect,
                              &MArea,
-                             FALSE);
+                             FALSE,
+                             TopDown);
   if (!NT_SUCCESS(Status))
     {
       DPRINT1("Mapping between 0x%.8X and 0x%.8X failed.\n",
              (*BaseAddress), (*BaseAddress) + ViewSize);
       return(Status);
     }
-  
+
   KeAcquireSpinLock(&Section->ViewListLock, &oldIrql);
-  InsertTailList(&Section->ViewListHead, 
+  InsertTailList(&Section->ViewListHead,
                 &MArea->Data.SectionData.ViewListEntry);
   KeReleaseSpinLock(&Section->ViewListLock, oldIrql);
-  
+
   ObReferenceObjectByPointer((PVOID)Section,
                             SECTION_MAP_READ,
                             NULL,
@@ -2739,7 +3035,7 @@ MmMapViewOfSegment(PEPROCESS Process,
   MArea->Data.SectionData.WriteCopyView = FALSE;
   MmInitialiseRegion(&MArea->Data.SectionData.RegionListHead,
                     ViewSize, 0, Protect);
-  
+
   return(STATUS_SUCCESS);
 }
 
@@ -2790,6 +3086,8 @@ MmMapViewOfSegment(PEPROCESS Process,
  *
  * RETURN VALUE
  *     Status.
+ *
+ * @implemented
  */
 NTSTATUS STDCALL
 NtMapViewOfSection(HANDLE SectionHandle,
@@ -2859,39 +3157,78 @@ MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
   PMEMORY_AREA MArea;
   ULONG Entry;
   PFILE_OBJECT FileObject;
-  PREACTOS_COMMON_FCB_HEADER Fcb;
+  PBCB Bcb;
   ULONG Offset;
   SWAPENTRY SavedSwapEntry;
   PMM_PAGEOP PageOp;
+  LARGE_INTEGER Timeout;
+  NTSTATUS Status;
+  PSECTION_OBJECT Section;
+  PMM_SECTION_SEGMENT Segment;
 
   MArea = (PMEMORY_AREA)Context;
 
-  Offset = ((ULONG)PAGE_ROUND_DOWN(Address) - (ULONG)MArea->BaseAddress) + 
-    MArea->Data.SectionData.ViewOffset;
-  Entry = MmGetPageEntrySectionSegment(MArea->Data.SectionData.Segment,
-                                      Offset);
+  Address = (PVOID)PAGE_ROUND_DOWN(Address);
+
+  Offset = ((ULONG)Address - (ULONG)MArea->BaseAddress);
+
+  Section = MArea->Data.SectionData.Section;
+  Segment = MArea->Data.SectionData.Segment;
+
 
-  PageOp = MmCheckForPageOp(MArea, 0, NULL, MArea->Data.SectionData.Segment,
-                           Offset);
-  assert(PageOp == NULL);
+  PageOp = MmCheckForPageOp(MArea, 0, NULL, Segment, Offset);
+  
+  while (PageOp)
+  {
+     MmUnlockSectionSegment(Segment);
+     MmUnlockAddressSpace(&MArea->Process->AddressSpace);
+
+     Timeout.QuadPart = -100000000LL;  // 10 sec
+     Status = KeWaitForSingleObject(&PageOp->CompletionEvent,
+                                   0,
+                                   KernelMode,
+                                   FALSE,
+                                   &Timeout);
+     if (Status != STATUS_SUCCESS)
+       {
+         DPRINT1("Failed to wait for page op, status = %x\n", Status);
+        KEBUGCHECK(0);
+       }
+
+     MmLockAddressSpace(&MArea->Process->AddressSpace);
+     MmLockSectionSegment(Segment);
+     KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
+     MmReleasePageOp(PageOp);
+     PageOp = MmCheckForPageOp(MArea, 0, NULL, Segment, Offset);
+  }
 
+  Entry = MmGetPageEntrySectionSegment(Segment, Offset);
+  
   /*
    * For a dirty, datafile, non-private page mark it as dirty in the
    * cache manager.
    */
-  if (MArea->Data.SectionData.Segment->Flags & MM_DATAFILE_SEGMENT)
+  if (Segment->Flags & MM_DATAFILE_SEGMENT)
     {
       if (PhysAddr.QuadPart == PAGE_FROM_SSE(Entry) && Dirty)
        {
          FileObject = MemoryArea->Data.SectionData.Section->FileObject;
-         Fcb = (PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext;
-         CcRosMarkDirtyCacheSegment(Fcb->Bcb, Offset);
+         Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
+         CcRosMarkDirtyCacheSegment(Bcb, Offset);
          assert(SwapEntry == 0);
        }
     }
 
   if (SwapEntry != 0)
     {
+      /*
+       * Sanity check
+       */
+      if (Segment->Flags & MM_PAGEFILE_SEGMENT)
+        {
+         DPRINT1("Found a swap entry for a page in a pagefile section.\n");
+         KEBUGCHECK(0);
+       }
       MmFreeSwapPage(SwapEntry);
     }
   else if (PhysAddr.QuadPart != 0)
@@ -2899,6 +3236,14 @@ MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
       if (IS_SWAP_FROM_SSE(Entry) || 
          PhysAddr.QuadPart != (PAGE_FROM_SSE(Entry)))
        {
+          /*
+           * Sanity check
+           */
+          if (Segment->Flags & MM_PAGEFILE_SEGMENT)
+            {
+             DPRINT1("Found a private page in a pagefile section.\n");
+             KEBUGCHECK(0);
+           }
          /*
           * Just dereference private pages
           */
@@ -2908,38 +3253,31 @@ MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
              MmFreeSwapPage(SavedSwapEntry);
              MmSetSavedSwapEntryPage(PhysAddr, 0);
            }
-         MmDeleteRmap(PhysAddr, MArea->Process, Address);
-         MmReleasePageMemoryConsumer(MC_USER, PhysAddr);
+          MmDeleteRmap(PhysAddr, MArea->Process, Address);
+          MmReleasePageMemoryConsumer(MC_USER, PhysAddr);
        }
       else
        {
-         MmUnsharePageEntrySectionSegment(MArea->Data.SectionData.Section,
-                                          MArea->Data.SectionData.Segment,
-                                          Offset,
-                                          Dirty);
-         MmDeleteRmap(PhysAddr, MArea->Process, Address);
-         MmReleasePageMemoryConsumer(MC_USER, PhysAddr);
+          MmDeleteRmap(PhysAddr, MArea->Process, Address);
+         MmUnsharePageEntrySectionSegment(Section, Segment, Offset, Dirty);
+          MmReleasePageMemoryConsumer(MC_USER, PhysAddr);
        }
     }
 }
 
-NTSTATUS STDCALL
-MmUnmapViewOfSection(PEPROCESS Process,
+NTSTATUS
+MmUnmapViewOfSegment(PMADDRESS_SPACE AddressSpace,
                     PVOID BaseAddress)
 {
-   NTSTATUS    Status;
+   NTSTATUS Status;
    PMEMORY_AREA MemoryArea;
-   PMADDRESS_SPACE AddressSpace;
    PSECTION_OBJECT Section;
    PMM_SECTION_SEGMENT Segment;
    KIRQL oldIrql;
    PLIST_ENTRY CurrentEntry;
    PMM_REGION CurrentRegion;
-   
-   AddressSpace = &Process->AddressSpace;
-   
-   DPRINT("Opening memory area Process %x BaseAddress %x\n",
-         Process, BaseAddress);
+   PLIST_ENTRY RegionListHead;
+
    MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
                                          BaseAddress);
    if (MemoryArea == NULL)
@@ -2948,47 +3286,120 @@ MmUnmapViewOfSection(PEPROCESS Process,
      }
 
    MemoryArea->DeleteInProgress = TRUE;
-   
-   MmLockSection(MemoryArea->Data.SectionData.Section);
-   MmLockSectionSegment(MemoryArea->Data.SectionData.Segment);
    Section = MemoryArea->Data.SectionData.Section;
    Segment = MemoryArea->Data.SectionData.Segment;
+   
+   MmLockSectionSegment(Segment);
    KeAcquireSpinLock(&Section->ViewListLock, &oldIrql);
    RemoveEntryList(&MemoryArea->Data.SectionData.ViewListEntry);
    KeReleaseSpinLock(&Section->ViewListLock, oldIrql);
 
-   CurrentEntry = MemoryArea->Data.SectionData.RegionListHead.Flink;
-   while (CurrentEntry != &MemoryArea->Data.SectionData.RegionListHead)
+   RegionListHead = &MemoryArea->Data.SectionData.RegionListHead;
+   while (!IsListEmpty(RegionListHead))
      {
-       CurrentRegion = 
-        CONTAINING_RECORD(CurrentEntry, MM_REGION, RegionListEntry);
-       CurrentEntry = CurrentEntry->Flink;
+       CurrentEntry = RemoveHeadList(RegionListHead);
+       CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION, RegionListEntry);
        ExFreePool(CurrentRegion);
      }
 
-   if (MemoryArea->Data.SectionData.Section->AllocationAttributes & 
-       SEC_PHYSICALMEMORY)
+   if (Section->AllocationAttributes & SEC_PHYSICALMEMORY)
      {
-       Status = MmFreeMemoryArea(&Process->AddressSpace,
-                                BaseAddress,
+       Status = MmFreeMemoryArea(AddressSpace,
+                                BaseAddress,
                                 0,
                                 NULL,
                                 NULL);
      }
    else
      {
-       Status = MmFreeMemoryArea(&Process->AddressSpace,
+       Status = MmFreeMemoryArea(AddressSpace,
                                 BaseAddress,
                                 0,
                                 MmFreeSectionPage,
                                 MemoryArea);
-      }
-   MmUnlockSection(Section);
+     }
    MmUnlockSectionSegment(Segment);
    ObDereferenceObject(Section);
    return(STATUS_SUCCESS);
 }
 
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+MmUnmapViewOfSection(PEPROCESS Process,
+                    PVOID BaseAddress)
+{
+   NTSTATUS    Status;
+   PMEMORY_AREA MemoryArea;
+   PMADDRESS_SPACE AddressSpace;
+   PSECTION_OBJECT Section;
+   
+   DPRINT("Opening memory area Process %x BaseAddress %x\n",
+         Process, BaseAddress);
+
+   assert(Process);
+   
+   AddressSpace = &Process->AddressSpace;
+   MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
+                                         BaseAddress);
+   if (MemoryArea == NULL)
+     {
+       return(STATUS_UNSUCCESSFUL);
+     }
+
+   Section = MemoryArea->Data.SectionData.Section;
+
+   if (Section->AllocationAttributes & SEC_IMAGE)
+     {
+       ULONG i;
+       ULONG NrSegments;
+       PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
+       PMM_SECTION_SEGMENT SectionSegments;
+       PVOID ImageBaseAddress;
+       PMM_SECTION_SEGMENT Segment;
+   
+       Segment = MemoryArea->Data.SectionData.Segment;
+       ImageSectionObject = Section->ImageSection;
+       SectionSegments = ImageSectionObject->Segments;
+       NrSegments = ImageSectionObject->NrSegments;
+
+       /* Search for the current segment within the section segments 
+        * and calculate the image base address */
+       for (i = 0; i < NrSegments; i++)
+         {
+          if (!(SectionSegments[i].Characteristics & IMAGE_SECTION_NOLOAD))
+            {
+              if (Segment == &SectionSegments[i])
+                {
+                  ImageBaseAddress = BaseAddress - (ULONG_PTR)SectionSegments[i].VirtualAddress;
+                  break;
+                }
+            }
+        }
+       if (i >= NrSegments)
+         {
+           KEBUGCHECK(0);
+        }
+
+       for (i = 0; i < NrSegments; i++)
+        {
+          if (!(SectionSegments[i].Characteristics & IMAGE_SECTION_NOLOAD))
+            {
+              PVOID SBaseAddress = (PVOID)
+                (ImageBaseAddress + (ULONG_PTR)SectionSegments[i].VirtualAddress);
+
+              Status = MmUnmapViewOfSegment(AddressSpace, SBaseAddress);
+            }
+        }
+     }
+   else
+     {
+       Status = MmUnmapViewOfSegment(AddressSpace, BaseAddress);
+     }
+   return(STATUS_SUCCESS);
+}
+
 /**********************************************************************
  * NAME                                                        EXPORTED
  *     NtUnmapViewOfSection
@@ -3004,7 +3415,6 @@ MmUnmapViewOfSection(PEPROCESS Process,
  *     Status.
  *
  * REVISIONS
- *
  */
 NTSTATUS STDCALL
 NtUnmapViewOfSection (HANDLE   ProcessHandle,
@@ -3104,23 +3514,24 @@ NtQuerySection (IN      HANDLE  SectionHandle,
              ObDereferenceObject(Section);
              return(STATUS_INFO_LENGTH_MISMATCH);
            }
+         
          Sii = (PSECTION_IMAGE_INFORMATION)SectionInformation; 
-         Sii->EntryPoint = Section->EntryPoint;
-         Sii->Unknown1 = 0;
-         Sii->StackReserve = Section->StackReserve;
-         Sii->StackCommit = Section->StackCommit;
-         Sii->Subsystem = Section->Subsystem;
-         Sii->MinorSubsystemVersion = Section->MinorSubsystemVersion;
-         Sii->MajorSubsystemVersion = Section->MajorSubsystemVersion;
-         Sii->Unknown2 = 0;
-         Sii->Characteristics = Section->ImageCharacteristics;
-         Sii->ImageNumber = Section->Machine;
-         Sii->Executable = Section->Executable;
-         Sii->Unknown3 = 0;
-         Sii->Unknown4[0] = 0;
-         Sii->Unknown4[1] = 0;
-         Sii->Unknown4[2] = 0;
-
+         memset(Sii, 0, sizeof(SECTION_IMAGE_INFORMATION));
+         if (Section->AllocationAttributes & SEC_IMAGE)
+           {
+             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;
+           }
          *ResultLength = sizeof(SECTION_IMAGE_INFORMATION);
          Status = STATUS_SUCCESS;
          break;
@@ -3140,6 +3551,7 @@ NtExtendSection(IN        HANDLE  SectionHandle,
                IN      ULONG   NewMaximumSize)
 {
    UNIMPLEMENTED;
+   return(STATUS_NOT_IMPLEMENTED);
 }
 
 
@@ -3158,7 +3570,6 @@ NtExtendSection(IN        HANDLE  SectionHandle,
  *     Code taken from ntoskrnl/mm/special.c.
  *
  * REVISIONS
- *
  */
 PVOID STDCALL 
 MmAllocateSection (IN ULONG Length)
@@ -3181,6 +3592,7 @@ MmAllocateSection (IN ULONG Length)
                                Length,
                                0,
                                &marea,
+                               FALSE,
                                FALSE);
    if (!NT_SUCCESS(Status))
      {
@@ -3189,7 +3601,7 @@ MmAllocateSection (IN ULONG Length)
      }
    MmUnlockAddressSpace(AddressSpace);
    DPRINT("Result %p\n",Result);
-   for (i = 0; (i <= (Length / PAGE_SIZE)); i++)
+   for (i = 0; i < PAGE_ROUND_UP(Length) / PAGE_SIZE; i++)
      {
        PHYSICAL_ADDRESS Page;
 
@@ -3197,7 +3609,7 @@ MmAllocateSection (IN ULONG Length)
        if (!NT_SUCCESS(Status))
         {
           DbgPrint("Unable to allocate page\n");
-          KeBugCheck(0);
+          KEBUGCHECK(0);
         }
        Status = MmCreateVirtualMapping (NULL,
                                        (Result + (i * PAGE_SIZE)),
@@ -3206,8 +3618,8 @@ MmAllocateSection (IN ULONG Length)
                                        TRUE);
        if (!NT_SUCCESS(Status))
         {
-          DbgPrint("Unable to create virtual mapping\n");        
-          KeBugCheck(0);
+          DbgPrint("Unable to create virtual mapping\n");
+          KEBUGCHECK(0);
         }
      }
    return ((PVOID)Result);
@@ -3260,6 +3672,8 @@ MmAllocateSection (IN ULONG Length)
  *
  * RETURN VALUE
  *     Status.
+ *
+ * @implemented
  */
 NTSTATUS STDCALL
 MmMapViewOfSection(IN PVOID SectionObject,
@@ -3278,84 +3692,91 @@ MmMapViewOfSection(IN PVOID SectionObject,
    ULONG ViewOffset;
    NTSTATUS Status = STATUS_SUCCESS;
 
+   assert(Process);
+
    Section = (PSECTION_OBJECT)SectionObject;
    AddressSpace = &Process->AddressSpace;
 
    MmLockAddressSpace(AddressSpace);
-   MmLockSection(SectionObject);
-   
+
    if (Section->AllocationAttributes & SEC_IMAGE)
      {
        ULONG i;
+       ULONG NrSegments;
        PVOID ImageBase;
-       ULONG ImageSize;           
-       
+       ULONG ImageSize;
+       PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
+       PMM_SECTION_SEGMENT SectionSegments;
+
+       ImageSectionObject = Section->ImageSection;
+       SectionSegments = ImageSectionObject->Segments;
+       NrSegments = ImageSectionObject->NrSegments;
+
+
        ImageBase = *BaseAddress;
        if (ImageBase == NULL)
         {
-          ImageBase = Section->ImageBase;
+          ImageBase = ImageSectionObject->ImageBase;
         }
-       
+
        ImageSize = 0;
-       for (i = 0; i < Section->NrSegments; i++)
+       for (i = 0; i < NrSegments; i++)
         {
-          if (!(Section->Segments[i].Characteristics & IMAGE_SECTION_NOLOAD))
+          if (!(SectionSegments[i].Characteristics & IMAGE_SECTION_NOLOAD))
             {
               ULONG MaxExtent;
-              MaxExtent = (ULONG)(Section->Segments[i].VirtualAddress +
-                                  Section->Segments[i].Length);
+              MaxExtent = (ULONG)(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, 
-                                   ImageSize) != NULL)
+                                   PAGE_ROUND_UP(ImageSize)) != NULL)
         {
           /* Fail if the user requested a fixed base address. */
           if ((*BaseAddress) != NULL)
             {
-              MmUnlockSection(Section);
               MmUnlockAddressSpace(AddressSpace);
-              return(Status);
+              return(STATUS_UNSUCCESSFUL);
             }
           /* Otherwise find a gap to map the image. */
-          ImageBase = MmFindGap(AddressSpace, ImageSize);
+          ImageBase = MmFindGap(AddressSpace, PAGE_ROUND_UP(ImageSize), FALSE);
           if (ImageBase == NULL)
             {
-              MmUnlockSection(Section);
               MmUnlockAddressSpace(AddressSpace);
-              return(Status);
+              return(STATUS_UNSUCCESSFUL);
             }
         }
-                                   
-       for (i = 0; i < Section->NrSegments; i++)
+
+       for (i = 0; i < NrSegments; i++)
         {
-          PVOID SBaseAddress;             
-          
-          if (!(Section->Segments[i].Characteristics & IMAGE_SECTION_NOLOAD))
+          PVOID SBaseAddress;
+
+          if (!(SectionSegments[i].Characteristics & IMAGE_SECTION_NOLOAD))
             {
               SBaseAddress = (PVOID)
-                (ImageBase + (ULONG_PTR)Section->Segments[i].VirtualAddress);
-
-              MmLockSectionSegment(&Section->Segments[i]);
+                (ImageBase + (ULONG_PTR)SectionSegments[i].VirtualAddress);
+              MmLockSectionSegment(&SectionSegments[i]);
               Status = MmMapViewOfSegment(Process,
-                                          &Process->AddressSpace,
+                                          AddressSpace,
                                           Section,
-                                          &Section->Segments[i],
+                                          &SectionSegments[i],
                                           &SBaseAddress,
-                                          Section->Segments[i].Length,
-                                          Section->Segments[i].Protection,
-                                          Section->Segments[i].FileOffset);
-              MmUnlockSectionSegment(&Section->Segments[i]);
+                                          SectionSegments[i].Length,
+                                          SectionSegments[i].Protection,
+                                          (ULONG_PTR)SectionSegments[i].VirtualAddress,
+                                          FALSE);
+              MmUnlockSectionSegment(&SectionSegments[i]);
               if (!NT_SUCCESS(Status))
                 {
-                  MmUnlockSection(Section);
                   MmUnlockAddressSpace(AddressSpace);
                   return(Status);
                 }
             }
         }
+
        *BaseAddress = ImageBase;
      }
    else
@@ -3368,10 +3789,9 @@ MmMapViewOfSection(IN PVOID SectionObject,
         {
           ViewOffset = SectionOffset->u.LowPart;
         }
-       
+
        if ((ViewOffset % PAGE_SIZE) != 0)
         {
-          MmUnlockSection(Section);
           MmUnlockAddressSpace(AddressSpace);
           return(STATUS_MAPPED_ALIGNMENT);
         }
@@ -3384,31 +3804,33 @@ MmMapViewOfSection(IN PVOID SectionObject,
         {
           (*ViewSize) = Section->MaximumSize.u.LowPart - ViewOffset;
         }
-       
-       MmLockSectionSegment(Section->Segments);
+
+       MmLockSectionSegment(Section->Segment);
        Status = MmMapViewOfSegment(Process,
-                                  &Process->AddressSpace,
+                                  AddressSpace,
                                   Section,
-                                  Section->Segments,
+                                  Section->Segment,
                                   BaseAddress,
                                   *ViewSize,
                                   Protect,
-                                  ViewOffset);
-       MmUnlockSectionSegment(Section->Segments);
+                                  ViewOffset,
+                                  (AllocationType & MEM_TOP_DOWN));
+       MmUnlockSectionSegment(Section->Segment);
        if (!NT_SUCCESS(Status))
         {
-          MmUnlockSection(Section);
-          MmUnlockAddressSpace(AddressSpace);
+           MmUnlockAddressSpace(AddressSpace);
           return(Status);
         }
      }
 
-   MmUnlockSection(Section);
    MmUnlockAddressSpace(AddressSpace);
 
    return(STATUS_SUCCESS);
 }
 
+/*
+ * @unimplemented
+ */
 BOOLEAN STDCALL
 MmCanFileBeTruncated (IN PSECTION_OBJECT_POINTERS      SectionObjectPointer,
                      IN PLARGE_INTEGER                 NewFileSize)
@@ -3418,6 +3840,9 @@ MmCanFileBeTruncated (IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
 }
 
 
+/*
+ * @unimplemented
+ */
 BOOLEAN STDCALL
 MmDisableModifiedWriteOfSection (DWORD Unknown0)
 {
@@ -3425,14 +3850,32 @@ MmDisableModifiedWriteOfSection (DWORD  Unknown0)
   return (FALSE);
 }
 
+/*
+ * @implemented
+ */
 BOOLEAN STDCALL
 MmFlushImageSection (IN        PSECTION_OBJECT_POINTERS        SectionObjectPointer,
                     IN MMFLUSH_TYPE                    FlushType)
 {
-  UNIMPLEMENTED;
-  return (FALSE);
+   switch(FlushType)
+   {
+      case MmFlushForDelete: 
+         if (SectionObjectPointer->ImageSectionObject || 
+            SectionObjectPointer->DataSectionObject)
+        {
+            return FALSE;
+        }
+        CcRosSetRemoveOnClose(SectionObjectPointer);
+         return TRUE;
+      case MmFlushForWrite:
+        break;
+   }
+   return FALSE;
 }
 
+/*
+ * @unimplemented
+ */
 BOOLEAN STDCALL
 MmForceSectionClosed (DWORD    Unknown0,
                      DWORD     Unknown1)
@@ -3442,23 +3885,77 @@ MmForceSectionClosed (DWORD     Unknown0,
 }
 
 
+/*
+ * @implemented
+ */
 NTSTATUS STDCALL
-MmMapViewInSystemSpace (IN     PVOID   Section,
+MmMapViewInSystemSpace (IN     PVOID   SectionObject,
                        OUT     PVOID   * MappedBase,
-                       IN      PULONG  ViewSize)
+                       IN OUT  PULONG  ViewSize)
 {
-  UNIMPLEMENTED;
-  return (STATUS_NOT_IMPLEMENTED);
+  PSECTION_OBJECT Section;
+  PMADDRESS_SPACE AddressSpace;
+  NTSTATUS Status;
+
+  DPRINT("MmMapViewInSystemSpace() called\n");
+
+  Section = (PSECTION_OBJECT)SectionObject;
+  AddressSpace = MmGetKernelAddressSpace();
+
+  MmLockAddressSpace(AddressSpace);
+
+  
+  if ((*ViewSize) == 0)
+    {
+      (*ViewSize) = Section->MaximumSize.u.LowPart;
+    }
+  else if ((*ViewSize) > Section->MaximumSize.u.LowPart)
+    {
+      (*ViewSize) = Section->MaximumSize.u.LowPart;
+    }
+
+  MmLockSectionSegment(Section->Segment);
+
+
+  Status = MmMapViewOfSegment(NULL,
+                             AddressSpace,
+                             Section,
+                             Section->Segment,
+                             MappedBase,
+                             *ViewSize,
+                             PAGE_READWRITE,
+                             0,
+                             FALSE);
+
+  MmUnlockSectionSegment(Section->Segment);
+  MmUnlockAddressSpace(AddressSpace);
+
+  return Status;
 }
 
+
+/*
+ * @implemented
+ */
 NTSTATUS STDCALL
-MmUnmapViewInSystemSpace (DWORD        Unknown0)
+MmUnmapViewInSystemSpace (IN   PVOID   MappedBase)
 {
-  UNIMPLEMENTED;
-  return (STATUS_NOT_IMPLEMENTED);
+  PMADDRESS_SPACE AddressSpace;
+  NTSTATUS Status;
+
+  DPRINT("MmUnmapViewInSystemSpace() called\n");
+
+  AddressSpace = MmGetKernelAddressSpace();
+
+  Status = MmUnmapViewOfSegment(AddressSpace, MappedBase);
+
+  return Status;
 }
 
 
+/*
+ * @unimplemented
+ */
 NTSTATUS STDCALL
 MmSetBankedSection (DWORD      Unknown0,
                    DWORD       Unknown1,
@@ -3482,7 +3979,7 @@ MmSetBankedSection (DWORD Unknown0,
  * ARGUMENTS
  *     SectionObjiect (OUT)
  *             Caller supplied storage for the resulting pointer
- *             to a SECTION_BOJECT instance;
+ *             to a SECTION_OBJECT instance;
  *             
  *     DesiredAccess
  *             Specifies the desired access to the section can be a
@@ -3524,6 +4021,8 @@ MmSetBankedSection (DWORD Unknown0,
  *     
  * RETURN VALUE
  *     Status.
+ *
+ * @unimplemented
  */
 NTSTATUS STDCALL
 MmCreateSection (OUT   PSECTION_OBJECT         * SectionObject,
@@ -3539,9 +4038,3 @@ MmCreateSection (OUT      PSECTION_OBJECT         * SectionObject,
 }
 
 /* EOF */
-
-
-
-
-
-