[NTOSKRNL]
[reactos.git] / reactos / ntoskrnl / mm / section.c
index a97d668..22d3b99 100644 (file)
@@ -171,11 +171,6 @@ static GENERIC_MAPPING MmpSectionMapping =
     SECTION_ALL_ACCESS
 };
 
-static const INFORMATION_CLASS_INFO ExSectionInfoClass[] =
-{
-    ICI_SQ_SAME( sizeof(SECTION_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* SectionBasicInformation */
-    ICI_SQ_SAME( sizeof(SECTION_IMAGE_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* SectionImageInformation */
-};
 
 /* FUNCTIONS *****************************************************************/
 
@@ -213,6 +208,7 @@ NTSTATUS NTAPI PeFmtCreateSection(IN CONST VOID * FileHeader,
     SIZE_T nPrevVirtualEndOfSegment = 0;
     ULONG nFileSizeOfHeaders = 0;
     ULONG i;
+    ULONG AlignedLength;
 
     ASSERT(FileHeader);
     ASSERT(FileHeaderSize > 0);
@@ -363,7 +359,9 @@ l_ReadHeaderFromFile:
     switch(piohOptHeader->Magic)
     {
     case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
+#ifdef _WIN64
     case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
+#endif // _WIN64
         break;
 
     default:
@@ -758,11 +756,12 @@ l_ReadHeaderFromFile:
         else
             pssSegments[i].Length.QuadPart = pishSectionHeaders[i].Misc.VirtualSize;
 
-        pssSegments[i].Length.LowPart = ALIGN_UP_BY(pssSegments[i].Length.LowPart, nSectionAlignment);
-        /* FIXME: always false */
-        if (pssSegments[i].Length.QuadPart < pssSegments[i].Length.QuadPart)
+        AlignedLength = ALIGN_UP_BY(pssSegments[i].Length.LowPart, nSectionAlignment);
+        if(AlignedLength < pssSegments[i].Length.LowPart)
             DIE(("Cannot align the virtual size of section %u\n", i));
 
+        pssSegments[i].Length.LowPart = AlignedLength;
+
         if(pssSegments[i].Length.QuadPart == 0)
             DIE(("Virtual size of section %u is null\n", i));
 
@@ -1355,7 +1354,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
      * Check if someone else is already handling this fault, if so wait
      * for them
      */
-    if (Entry && IS_SWAP_FROM_SSE(Entry) && SWAPENTRY_FROM_SSE(Entry) == MM_WAIT_ENTRY)
+    if (Entry && MM_IS_WAIT_PTE(Entry))
     {
         MmUnlockSectionSegment(Segment);
         MmUnlockAddressSpace(AddressSpace);
@@ -1367,39 +1366,45 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
 
     HasSwapEntry = MmIsPageSwapEntry(Process, Address);
 
-    if (HasSwapEntry)
+    /* See if we should use a private page */
+    if ((HasSwapEntry) || (Segment->Image.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA))
     {
         SWAPENTRY DummyEntry;
 
         /*
          * Is it a wait entry?
          */
-        MmGetPageFileMapping(Process, Address, &SwapEntry);
-
-        if (SwapEntry == MM_WAIT_ENTRY)
+        if (HasSwapEntry)
         {
-            MmUnlockSectionSegment(Segment);
-            MmUnlockAddressSpace(AddressSpace);
-            MiWaitForPageEvent(NULL, NULL);
-            MmLockAddressSpace(AddressSpace);
-            return STATUS_MM_RESTART_OPERATION;
-        }
+            MmGetPageFileMapping(Process, Address, &SwapEntry);
 
-        /*
-         * Must be private page we have swapped out.
-         */
+            if (SwapEntry == MM_WAIT_ENTRY)
+            {
+                MmUnlockSectionSegment(Segment);
+                MmUnlockAddressSpace(AddressSpace);
+                MiWaitForPageEvent(NULL, NULL);
+                MmLockAddressSpace(AddressSpace);
+                return STATUS_MM_RESTART_OPERATION;
+            }
 
-        /*
-         * Sanity check
-         */
-        if (Segment->Flags & MM_PAGEFILE_SEGMENT)
-        {
-            DPRINT1("Found a swaped out private page in a pagefile section.\n");
-            KeBugCheck(MEMORY_MANAGEMENT);
+            /*
+             * Must be private page we have swapped out.
+             */
+
+            /*
+             * Sanity check
+             */
+            if (Segment->Flags & MM_PAGEFILE_SEGMENT)
+            {
+                DPRINT1("Found a swaped out private page in a pagefile section.\n");
+                KeBugCheck(MEMORY_MANAGEMENT);
+            }
+            MmDeletePageFileMapping(Process, Address, &SwapEntry);
         }
 
         MmUnlockSectionSegment(Segment);
-        MmDeletePageFileMapping(Process, Address, &SwapEntry);
+
+        /* Tell everyone else we are serving the fault. */
         MmCreatePageFileMapping(Process, Address, MM_WAIT_ENTRY);
 
         MmUnlockAddressSpace(AddressSpace);
@@ -1412,12 +1417,16 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
             KeBugCheck(MEMORY_MANAGEMENT);
         }
 
-        Status = MmReadFromSwapPage(SwapEntry, Page);
-        if (!NT_SUCCESS(Status))
+        if (HasSwapEntry)
         {
-            DPRINT1("MmReadFromSwapPage failed, status = %x\n", Status);
-            KeBugCheck(MEMORY_MANAGEMENT);
+            Status = MmReadFromSwapPage(SwapEntry, Page);
+            if (!NT_SUCCESS(Status))
+            {
+                DPRINT1("MmReadFromSwapPage failed, status = %x\n", Status);
+                KeBugCheck(MEMORY_MANAGEMENT);
+            }
         }
+
         MmLockAddressSpace(AddressSpace);
         MmDeletePageFileMapping(Process, PAddress, &DummyEntry);
         Status = MmCreateVirtualMapping(Process,
@@ -1435,7 +1444,8 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
         /*
          * Store the swap entry for later use.
          */
-        MmSetSavedSwapEntryPage(Page, SwapEntry);
+        if (HasSwapEntry)
+            MmSetSavedSwapEntryPage(Page, SwapEntry);
 
         /*
          * Add the page to the process's working set
@@ -1537,15 +1547,9 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
             return(Status);
         }
 
-        /*
-         * Mark the offset within the section as having valid, in-memory
-         * data
-         */
+        /* Lock both segment and process address space while we proceed. */
         MmLockAddressSpace(AddressSpace);
         MmLockSectionSegment(Segment);
-        Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
-        MmSetPageEntrySectionSegment(Segment, &Offset, Entry);
-        MmUnlockSectionSegment(Segment);
 
         MmDeletePageFileMapping(Process, PAddress, &FakeSwapEntry);
         DPRINT("CreateVirtualMapping Page %x Process %p PAddress %p Attributes %x\n",
@@ -1563,6 +1567,11 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
         ASSERT(MmIsPagePresent(Process, PAddress));
         MmInsertRmap(Page, Process, Address);
 
+        /* Set this section offset has being backed by our new page. */
+        Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
+        MmSetPageEntrySectionSegment(Segment, &Offset, Entry);
+        MmUnlockSectionSegment(Segment);
+
         MiSetPageEvent(Process, Address);
         DPRINT("Address 0x%p\n", Address);
         return(STATUS_SUCCESS);
@@ -1573,6 +1582,16 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
 
         SwapEntry = SWAPENTRY_FROM_SSE(Entry);
 
+        /* See if a page op is running on this segment. */
+        if (SwapEntry == MM_WAIT_ENTRY)
+        {
+            MmUnlockSectionSegment(Segment);
+            MmUnlockAddressSpace(AddressSpace);
+            MiWaitForPageEvent(NULL, NULL);
+            MmLockAddressSpace(AddressSpace);
+            return STATUS_MM_RESTART_OPERATION;
+        }
+
         /*
         * Release all our locks and read in the page from disk
         */
@@ -1611,18 +1630,12 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
             KeBugCheck(MEMORY_MANAGEMENT);
         }
 
-        /*
-         * Mark the offset within the section as having valid, in-memory
-         * data
-         */
-        Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
-        MmSetPageEntrySectionSegment(Segment, &Offset, Entry);
-        MmUnlockSectionSegment(Segment);
-
         /*
          * Save the swap entry.
          */
         MmSetSavedSwapEntryPage(Page, SwapEntry);
+
+        /* Map the page into the process address space */
         Status = MmCreateVirtualMapping(Process,
                                         PAddress,
                                         Region->Protect,
@@ -1634,22 +1647,24 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
             KeBugCheck(MEMORY_MANAGEMENT);
         }
         MmInsertRmap(Page, Process, Address);
+
+        /*
+         * Mark the offset within the section as having valid, in-memory
+         * data
+         */
+        Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
+        MmSetPageEntrySectionSegment(Segment, &Offset, Entry);
+        MmUnlockSectionSegment(Segment);
+
         MiSetPageEvent(Process, Address);
         DPRINT("Address 0x%p\n", Address);
         return(STATUS_SUCCESS);
     }
     else
     {
-        /*
-         * If the section offset is already in-memory and valid then just
-         * take another reference to the page
-         */
-
+        /* We already have a page on this section offset. Map it into the process address space. */
         Page = PFN_FROM_SSE(Entry);
 
-        MmSharePageEntrySectionSegment(Segment, &Offset);
-        MmUnlockSectionSegment(Segment);
-
         Status = MmCreateVirtualMapping(Process,
                                         PAddress,
                                         Attributes,
@@ -1661,6 +1676,11 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
             KeBugCheck(MEMORY_MANAGEMENT);
         }
         MmInsertRmap(Page, Process, Address);
+
+        /* Take a reference on it */
+        MmSharePageEntrySectionSegment(Segment, &Offset);
+        MmUnlockSectionSegment(Segment);
+
         MiSetPageEvent(Process, Address);
         DPRINT("Address 0x%p\n", Address);
         return(STATUS_SUCCESS);
@@ -1683,10 +1703,17 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
     PMM_REGION Region;
     ULONG_PTR Entry;
     PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
-    SWAPENTRY SwapEntry;
 
     DPRINT("MmAccessFaultSectionView(%p, %p, %p)\n", AddressSpace, MemoryArea, Address);
 
+    /* Make sure we have a page mapping for this address.  */
+    Status = MmNotPresentFaultSectionView(AddressSpace, MemoryArea, Address, TRUE);
+    if (!NT_SUCCESS(Status))
+    {
+        /* This is invalid access ! */
+        return Status;
+    }
+
     /*
      * Check if the page has already been set readwrite
      */
@@ -1709,15 +1736,6 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
                           &MemoryArea->Data.SectionData.RegionListHead,
                           Address, NULL);
     ASSERT(Region != NULL);
-    /*
-     * Lock the segment
-     */
-    MmLockSectionSegment(Segment);
-
-    OldPage = MmGetPfnForProcess(Process, Address);
-    Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
-
-    MmUnlockSectionSegment(Segment);
 
     /*
      * Check if we are doing COW
@@ -1730,49 +1748,24 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
         return(STATUS_ACCESS_VIOLATION);
     }
 
-    if (IS_SWAP_FROM_SSE(Entry) ||
-            PFN_FROM_SSE(Entry) != OldPage)
-    {
-        /* This is a private page. We must only change the page protection. */
-        MmSetPageProtect(Process, Address, Region->Protect);
-        return(STATUS_SUCCESS);
-    }
-
-    if(OldPage == 0)
-        DPRINT("OldPage == 0!\n");
-
-    /*
-     * Get or create a pageop
-     */
+    /* Get the page mapping this section offset. */
     MmLockSectionSegment(Segment);
     Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
 
-    /*
-     * Wait for any other operations to complete
-     */
-    if (Entry == SWAPENTRY_FROM_SSE(MM_WAIT_ENTRY))
+    /* Get the current page mapping for the process */
+    ASSERT(MmIsPagePresent(Process, PAddress));
+    OldPage = MmGetPfnForProcess(Process, PAddress);
+    ASSERT(OldPage != 0);
+
+    if (IS_SWAP_FROM_SSE(Entry) ||
+            PFN_FROM_SSE(Entry) != OldPage)
     {
         MmUnlockSectionSegment(Segment);
-        MmUnlockAddressSpace(AddressSpace);
-        MiWaitForPageEvent(NULL, NULL);
-        /*
-         * Restart the operation
-         */
-        MmLockAddressSpace(AddressSpace);
-        DPRINT("Address 0x%p\n", Address);
-        return(STATUS_MM_RESTART_OPERATION);
+        /* This is a private page. We must only change the page protection. */
+        MmSetPageProtect(Process, PAddress, Region->Protect);
+        return(STATUS_SUCCESS);
     }
 
-    MmDeleteRmap(OldPage, Process, PAddress);
-    MmDeleteVirtualMapping(Process, PAddress, NULL, NULL);
-    MmCreatePageFileMapping(Process, PAddress, MM_WAIT_ENTRY);
-
-    /*
-     * Release locks now we have the pageop
-     */
-    MmUnlockSectionSegment(Segment);
-    MmUnlockAddressSpace(AddressSpace);
-
     /*
      * Allocate a page
      */
@@ -1790,12 +1783,18 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
      */
     MiCopyFromUserPage(NewPage, OldPage);
 
-    MmLockAddressSpace(AddressSpace);
+    /*
+     * Unshare the old page.
+     */
+    DPRINT("Swapping page (Old %x New %x)\n", OldPage, NewPage);
+    MmDeleteVirtualMapping(Process, PAddress, NULL, NULL);
+    MmDeleteRmap(OldPage, Process, PAddress);
+    MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, FALSE, FALSE, NULL);
+    MmUnlockSectionSegment(Segment);
 
     /*
      * Set the PTE to point to the new page
      */
-    MmDeletePageFileMapping(Process, PAddress, &SwapEntry);
     Status = MmCreateVirtualMapping(Process,
                                     PAddress,
                                     Region->Protect,
@@ -1807,15 +1806,7 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
         KeBugCheck(MEMORY_MANAGEMENT);
         return(Status);
     }
-
-    /*
-     * Unshare the old page.
-     */
-    DPRINT("Swapping page (Old %x New %x)\n", OldPage, NewPage);
     MmInsertRmap(NewPage, Process, PAddress);
-    MmLockSectionSegment(Segment);
-    MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, FALSE, FALSE, NULL);
-    MmUnlockSectionSegment(Segment);
 
     MiSetPageEvent(Process, Address);
     DPRINT("Address 0x%p\n", Address);
@@ -2148,6 +2139,9 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
             else
             {
                 ULONG_PTR OldEntry;
+
+                MmLockSectionSegment(Context.Segment);
+
                 /*
                  * For non-private pages if the page wasn't direct mapped then
                  * set it back into the section segment entry so we don't loose
@@ -2164,7 +2158,6 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
                              Address);
                 // If we got here, the previous entry should have been a wait
                 Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
-                MmLockSectionSegment(Context.Segment);
                 OldEntry = MmGetPageEntrySectionSegment(Context.Segment, &Context.Offset);
                 ASSERT(OldEntry == 0 || OldEntry == MAKE_SWAP_SSE(MM_WAIT_ENTRY));
                 MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
@@ -2203,6 +2196,7 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
         }
         else
         {
+            MmLockSectionSegment(Context.Segment);
             Status = MmCreateVirtualMapping(Process,
                                             Address,
                                             MemoryArea->Protect,
@@ -2214,6 +2208,7 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
                          Address);
             Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
             MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
+            MmUnlockSectionSegment(Context.Segment);
         }
         MmUnlockAddressSpace(AddressSpace);
         MiSetPageEvent(NULL, NULL);
@@ -2754,7 +2749,7 @@ MmCreatePhysicalMemorySection(VOID)
     SectionSize.QuadPart = 0xFFFFFFFF;
     InitializeObjectAttributes(&Obj,
                                &Name,
-                               OBJ_PERMANENT,
+                               OBJ_PERMANENT | OBJ_KERNEL_EXCLUSIVE,
                                NULL,
                                NULL);
     Status = MmCreateSection((PVOID)&PhysSection,
@@ -2914,9 +2909,6 @@ MmCreateDataFileSection(PROS_SECTION_OBJECT *SectionObject,
     PFILE_OBJECT FileObject;
     PMM_SECTION_SEGMENT Segment;
     ULONG FileAccess;
-    IO_STATUS_BLOCK Iosb;
-    LARGE_INTEGER Offset;
-    CHAR Buffer;
     FILE_STANDARD_INFORMATION FileInfo;
     ULONG Length;
 
@@ -2972,7 +2964,6 @@ MmCreateDataFileSection(PROS_SECTION_OBJECT *SectionObject,
                                     sizeof(FILE_STANDARD_INFORMATION),
                                     &FileInfo,
                                     &Length);
-    Iosb.Information = Length;
     if (!NT_SUCCESS(Status))
     {
         ObDereferenceObject(Section);
@@ -2996,14 +2987,14 @@ MmCreateDataFileSection(PROS_SECTION_OBJECT *SectionObject,
         {
             ObDereferenceObject(Section);
             ObDereferenceObject(FileObject);
-            return STATUS_FILE_INVALID;
+            return STATUS_MAPPED_FILE_SIZE_ZERO;
         }
     }
 
     if (MaximumSize.QuadPart > FileInfo.EndOfFile.QuadPart)
     {
         Status = IoSetInformation(FileObject,
-                                  FileAllocationInformation,
+                                  FileEndOfFileInformation,
                                   sizeof(LARGE_INTEGER),
                                   &MaximumSize);
         if (!NT_SUCCESS(Status))
@@ -3017,35 +3008,9 @@ MmCreateDataFileSection(PROS_SECTION_OBJECT *SectionObject,
     if (FileObject->SectionObjectPointer == NULL ||
             FileObject->SectionObjectPointer->SharedCacheMap == NULL)
     {
-        /*
-         * 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))
-        {
-            ObDereferenceObject(Section);
-            ObDereferenceObject(FileObject);
-            return(Status);
-        }
-        if (FileObject->SectionObjectPointer == NULL ||
-                FileObject->SectionObjectPointer->SharedCacheMap == NULL)
-        {
-            /* FIXME: handle this situation */
-            ObDereferenceObject(Section);
-            ObDereferenceObject(FileObject);
-            return STATUS_INVALID_PARAMETER;
-        }
+        ObDereferenceObject(Section);
+        ObDereferenceObject(FileObject);
+        return STATUS_INVALID_FILE_FOR_SECTION;
     }
 
     /*
@@ -3158,11 +3123,6 @@ extern NTSTATUS NTAPI ElfFmtCreateSection
     IN PEXEFMT_CB_ALLOCATE_SEGMENTS AllocateSegmentsCb
 );
 
-/* TODO: this is a standard DDK/PSDK macro */
-#ifndef RTL_NUMBER_OF
-#define RTL_NUMBER_OF(ARR_) (sizeof(ARR_) / sizeof((ARR_)[0]))
-#endif
-
 static PEXEFMT_LOADER ExeFmtpLoaders[] =
 {
     PeFmtCreateSection,
@@ -3234,6 +3194,12 @@ ExeFmtpReadFile(IN PVOID File,
     BufferSize = Length + OffsetAdjustment;
     BufferSize = PAGE_ROUND_UP(BufferSize);
 
+    /* Flush data since we're about to perform a non-cached read */
+    CcFlushCache(FileObject->SectionObjectPointer,
+                 &FileOffset,
+                 BufferSize,
+                 &Iosb);
+
     /*
      * It's ok to use paged pool, because this is a temporary buffer only used in
      * the loading of executables. The assumption is that MmCreateSection is
@@ -3245,7 +3211,7 @@ ExeFmtpReadFile(IN PVOID File,
                                    'rXmM');
     if (!Buffer)
     {
-        KeBugCheck(MEMORY_MANAGEMENT);
+        return STATUS_INSUFFICIENT_RESOURCES;
     }
 
     UsedSize = 0;
@@ -3610,7 +3576,7 @@ MmspPageAlignSegments
 }
 
 NTSTATUS
-ExeFmtpCreateImageSection(HANDLE FileHandle,
+ExeFmtpCreateImageSection(PFILE_OBJECT FileObject,
                           PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
 {
     LARGE_INTEGER Offset;
@@ -3628,8 +3594,7 @@ ExeFmtpCreateImageSection(HANDLE FileHandle,
      */
     Offset.QuadPart = 0;
 
-    /* FIXME: use FileObject instead of FileHandle */
-    Status = ExeFmtpReadFile (FileHandle,
+    Status = ExeFmtpReadFile (FileObject,
                               &Offset,
                               PAGE_SIZE * 2,
                               &FileHeader,
@@ -3653,10 +3618,9 @@ ExeFmtpCreateImageSection(HANDLE FileHandle,
         RtlZeroMemory(ImageSectionObject, sizeof(*ImageSectionObject));
         Flags = 0;
 
-        /* FIXME: use FileObject instead of FileHandle */
         Status = ExeFmtpLoaders[i](FileHeader,
                                    FileHeaderSize,
-                                   FileHandle,
+                                   FileObject,
                                    ImageSectionObject,
                                    &Flags,
                                    ExeFmtpReadFile,
@@ -3776,6 +3740,14 @@ MmCreateImageSection(PROS_SECTION_OBJECT *SectionObject,
     if (FileObject == NULL)
         return STATUS_INVALID_FILE_FOR_SECTION;
 
+#ifndef NEWCC
+    if (FileObject->SectionObjectPointer->SharedCacheMap == NULL)
+    {
+        DPRINT1("Denying section creation due to missing cache initialization\n");
+        return STATUS_INVALID_FILE_FOR_SECTION;
+    }
+#endif
+
     /*
      * Create the section
      */
@@ -3834,10 +3806,19 @@ MmCreateImageSection(PROS_SECTION_OBJECT *SectionObject,
             if(ImageSectionObject->Segments != NULL)
                 ExFreePool(ImageSectionObject->Segments);
 
+            /*
+             * If image file is empty, then return that the file is invalid for section
+             */
+            Status = StatusExeFmt;
+            if (StatusExeFmt == STATUS_END_OF_FILE)
+            {
+                Status = STATUS_INVALID_FILE_FOR_SECTION;
+            }
+
             ExFreePoolWithTag(ImageSectionObject, TAG_MM_SECTION_SEGMENT);
             ObDereferenceObject(Section);
             ObDereferenceObject(FileObject);
-            return(StatusExeFmt);
+            return(Status);
         }
 
         Section->ImageSection = ImageSectionObject;
@@ -4019,7 +4000,7 @@ MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
     Segment = MemoryArea->Data.SectionData.Segment;
 
     Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
-    while (Entry && IS_SWAP_FROM_SSE(Entry) && SWAPENTRY_FROM_SSE(Entry) == MM_WAIT_ENTRY)
+    while (Entry && MM_IS_WAIT_PTE(Entry))
     {
         MmUnlockSectionSegment(Segment);
         MmUnlockAddressSpace(AddressSpace);
@@ -4184,7 +4165,7 @@ MiRosUnmapViewOfSection(IN PEPROCESS Process,
              (MemoryArea->Type != MEMORY_AREA_CACHE)) ||
             MemoryArea->DeleteInProgress)
     {
-        if (MemoryArea) NT_ASSERT(MemoryArea->Type != MEMORY_AREA_OWNED_BY_ARM3);
+        if (MemoryArea) ASSERT(MemoryArea->Type != MEMORY_AREA_OWNED_BY_ARM3);
         MmUnlockAddressSpace(AddressSpace);
         return STATUS_NOT_MAPPED_VIEW;
     }
@@ -4210,13 +4191,10 @@ MiRosUnmapViewOfSection(IN PEPROCESS Process,
          * and calculate the image base address */
         for (i = 0; i < NrSegments; i++)
         {
-            if (!(SectionSegments[i].Image.Characteristics & IMAGE_SCN_TYPE_NOLOAD))
+            if (Segment == &SectionSegments[i])
             {
-                if (Segment == &SectionSegments[i])
-                {
-                    ImageBaseAddress = (char*)BaseAddress - (ULONG_PTR)SectionSegments[i].Image.VirtualAddress;
-                    break;
-                }
+                ImageBaseAddress = (char*)BaseAddress - (ULONG_PTR)SectionSegments[i].Image.VirtualAddress;
+                break;
             }
         }
         if (i >= NrSegments)
@@ -4226,20 +4204,27 @@ MiRosUnmapViewOfSection(IN PEPROCESS Process,
 
         for (i = 0; i < NrSegments; i++)
         {
-            if (!(SectionSegments[i].Image.Characteristics & IMAGE_SCN_TYPE_NOLOAD))
-            {
-                PVOID SBaseAddress = (PVOID)
-                                     ((char*)ImageBaseAddress + (ULONG_PTR)SectionSegments[i].Image.VirtualAddress);
+            PVOID SBaseAddress = (PVOID)
+                                 ((char*)ImageBaseAddress + (ULONG_PTR)SectionSegments[i].Image.VirtualAddress);
 
-                Status = MmUnmapViewOfSegment(AddressSpace, SBaseAddress);
-                NT_ASSERT(NT_SUCCESS(Status));
+            Status = MmUnmapViewOfSegment(AddressSpace, SBaseAddress);
+            if (!NT_SUCCESS(Status))
+            {
+                DPRINT1("MmUnmapViewOfSegment failed for %p (Process %p) with %lx\n",
+                        SBaseAddress, Process, Status);
+                ASSERT(NT_SUCCESS(Status));
             }
         }
     }
     else
     {
         Status = MmUnmapViewOfSegment(AddressSpace, BaseAddress);
-        NT_ASSERT(NT_SUCCESS(Status));
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("MmUnmapViewOfSegment failed for %p (Process %p) with %lx\n",
+                    BaseAddress, Process, Status);
+            ASSERT(NT_SUCCESS(Status));
+        }
     }
 
     MmUnlockAddressSpace(AddressSpace);
@@ -4275,33 +4260,59 @@ MiRosUnmapViewOfSection(IN PEPROCESS Process,
  *
  * @implemented
  */
-NTSTATUS NTAPI
-NtQuerySection(IN HANDLE SectionHandle,
-               IN SECTION_INFORMATION_CLASS SectionInformationClass,
-               OUT PVOID SectionInformation,
-               IN SIZE_T SectionInformationLength,
-               OUT PSIZE_T ResultLength  OPTIONAL)
+NTSTATUS
+NTAPI
+NtQuerySection(
+    _In_ HANDLE SectionHandle,
+    _In_ SECTION_INFORMATION_CLASS SectionInformationClass,
+    _Out_ PVOID SectionInformation,
+    _In_ SIZE_T SectionInformationLength,
+    _Out_opt_ PSIZE_T ResultLength)
 {
-    PROS_SECTION_OBJECT Section;
+    PSECTION Section;
     KPROCESSOR_MODE PreviousMode;
     NTSTATUS Status;
     PAGED_CODE();
 
     PreviousMode = ExGetPreviousMode();
+    if (PreviousMode != KernelMode)
+    {
+        _SEH2_TRY
+        {
+            ProbeForWrite(SectionInformation,
+                          SectionInformationLength,
+                          __alignof(ULONG));
+            if (ResultLength != NULL)
+            {
+                ProbeForWrite(ResultLength,
+                              sizeof(*ResultLength),
+                              __alignof(SIZE_T));
+            }
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            _SEH2_YIELD(return _SEH2_GetExceptionCode());
+        }
+        _SEH2_END;
+    }
 
-    Status = DefaultQueryInfoBufferCheck(SectionInformationClass,
-                                         ExSectionInfoClass,
-                                         sizeof(ExSectionInfoClass) / sizeof(ExSectionInfoClass[0]),
-                                         SectionInformation,
-                                         (ULONG)SectionInformationLength,
-                                         NULL,
-                                         ResultLength,
-                                         PreviousMode);
-
-    if(!NT_SUCCESS(Status))
+    if (SectionInformationClass == SectionBasicInformation)
     {
-        DPRINT1("NtQuerySection() failed, Status: 0x%x\n", Status);
-        return Status;
+        if (SectionInformationLength < sizeof(SECTION_BASIC_INFORMATION))
+        {
+            return STATUS_INFO_LENGTH_MISMATCH;
+        }
+    }
+    else if (SectionInformationClass == SectionImageInformation)
+    {
+        if (SectionInformationLength < sizeof(SECTION_IMAGE_INFORMATION))
+        {
+            return STATUS_INFO_LENGTH_MISMATCH;
+        }
+    }
+    else
+    {
+        return STATUS_INVALID_INFO_CLASS;
     }
 
     Status = ObReferenceObjectByHandle(SectionHandle,
@@ -4310,76 +4321,137 @@ NtQuerySection(IN HANDLE SectionHandle,
                                        PreviousMode,
                                        (PVOID*)(PVOID)&Section,
                                        NULL);
-    if (NT_SUCCESS(Status))
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to reference section: 0x%lx\n", Status);
+        return Status;
+    }
+
+    if (MiIsRosSectionObject(Section))
     {
+        PROS_SECTION_OBJECT RosSection = (PROS_SECTION_OBJECT)Section;
+
         switch (SectionInformationClass)
         {
-        case SectionBasicInformation:
-        {
-            PSECTION_BASIC_INFORMATION Sbi = (PSECTION_BASIC_INFORMATION)SectionInformation;
-
-            _SEH2_TRY
+            case SectionBasicInformation:
             {
-                Sbi->Attributes = Section->AllocationAttributes;
-                if (Section->AllocationAttributes & SEC_IMAGE)
+                PSECTION_BASIC_INFORMATION Sbi = (PSECTION_BASIC_INFORMATION)SectionInformation;
+
+                _SEH2_TRY
                 {
-                    Sbi->BaseAddress = 0;
-                    Sbi->Size.QuadPart = 0;
+                    Sbi->Attributes = RosSection->AllocationAttributes;
+                    if (RosSection->AllocationAttributes & SEC_IMAGE)
+                    {
+                        Sbi->BaseAddress = 0;
+                        Sbi->Size.QuadPart = 0;
+                    }
+                    else
+                    {
+                        Sbi->BaseAddress = (PVOID)RosSection->Segment->Image.VirtualAddress;
+                        Sbi->Size.QuadPart = RosSection->Segment->Length.QuadPart;
+                    }
+
+                    if (ResultLength != NULL)
+                    {
+                        *ResultLength = sizeof(SECTION_BASIC_INFORMATION);
+                    }
+                    Status = STATUS_SUCCESS;
                 }
-                else
+                _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
                 {
-                    Sbi->BaseAddress = (PVOID)Section->Segment->Image.VirtualAddress;
-                    Sbi->Size.QuadPart = Section->Segment->Length.QuadPart;
+                    Status = _SEH2_GetExceptionCode();
                 }
+                _SEH2_END;
 
-                if (ResultLength != NULL)
-                {
-                    *ResultLength = sizeof(SECTION_BASIC_INFORMATION);
-                }
-                Status = STATUS_SUCCESS;
+                break;
             }
-            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+
+            case SectionImageInformation:
             {
-                Status = _SEH2_GetExceptionCode();
-            }
-            _SEH2_END;
+                PSECTION_IMAGE_INFORMATION Sii = (PSECTION_IMAGE_INFORMATION)SectionInformation;
 
-            break;
-        }
+                _SEH2_TRY
+                {
+                    if (RosSection->AllocationAttributes & SEC_IMAGE)
+                    {
+                        PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
+                        ImageSectionObject = RosSection->ImageSection;
 
-        case SectionImageInformation:
-        {
-            PSECTION_IMAGE_INFORMATION Sii = (PSECTION_IMAGE_INFORMATION)SectionInformation;
+                        *Sii = ImageSectionObject->ImageInformation;
+                    }
 
-            _SEH2_TRY
-            {
-                if (Section->AllocationAttributes & SEC_IMAGE)
+                    if (ResultLength != NULL)
+                    {
+                        *ResultLength = sizeof(SECTION_IMAGE_INFORMATION);
+                    }
+                    Status = STATUS_SUCCESS;
+                }
+                _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
                 {
-                    PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
-                    ImageSectionObject = Section->ImageSection;
-
-                    *Sii = ImageSectionObject->ImageInformation;
+                    Status = _SEH2_GetExceptionCode();
                 }
+                _SEH2_END;
 
-                if (ResultLength != NULL)
+                break;
+            }
+        }
+    }
+    else
+    {
+        switch(SectionInformationClass)
+        {
+            case SectionBasicInformation:
+            {
+                SECTION_BASIC_INFORMATION Sbi;
+
+                Sbi.Size = Section->SizeOfSection;
+                Sbi.BaseAddress = (PVOID)Section->Address.StartingVpn;
+
+                Sbi.Attributes = 0;
+                if (Section->u.Flags.Image)
+                    Sbi.Attributes |= SEC_IMAGE;
+                if (Section->u.Flags.Commit)
+                    Sbi.Attributes |= SEC_COMMIT;
+                if (Section->u.Flags.Reserve)
+                    Sbi.Attributes |= SEC_RESERVE;
+                if (Section->u.Flags.File)
+                    Sbi.Attributes |= SEC_FILE;
+                if (Section->u.Flags.Image)
+                    Sbi.Attributes |= SEC_IMAGE;
+
+                /* FIXME : Complete/test the list of flags passed back from NtCreateSection */
+
+                _SEH2_TRY
                 {
-                    *ResultLength = sizeof(SECTION_IMAGE_INFORMATION);
+                    *((SECTION_BASIC_INFORMATION*)SectionInformation) = Sbi;
+                    if (ResultLength)
+                        *ResultLength = sizeof(Sbi);
                 }
-                Status = STATUS_SUCCESS;
+                _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+                {
+                    Status = _SEH2_GetExceptionCode();
+                }
+                _SEH2_END;
+                break;
             }
-            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+            case SectionImageInformation:
             {
-                Status = _SEH2_GetExceptionCode();
+                if (!Section->u.Flags.Image)
+                {
+                    Status = STATUS_SECTION_NOT_IMAGE;
+                }
+                else
+                {
+                    /* Currently not supported */
+                    ASSERT(FALSE);
+                }
+                break;
             }
-            _SEH2_END;
-
-            break;
-        }
         }
-
-        ObDereferenceObject(Section);
     }
 
+    ObDereferenceObject(Section);
+
     return(Status);
 }
 
@@ -4472,6 +4544,8 @@ MmMapViewOfSection(IN PVOID SectionObject,
         return STATUS_INVALID_PAGE_PROTECTION;
     }
 
+    /* FIXME: We should keep this, but it would break code checking equality */
+    Protect &= ~PAGE_NOCACHE;
 
     Section = (PROS_SECTION_OBJECT)SectionObject;
     AddressSpace = &Process->Vm;
@@ -4502,13 +4576,10 @@ MmMapViewOfSection(IN PVOID SectionObject,
         ImageSize = 0;
         for (i = 0; i < NrSegments; i++)
         {
-            if (!(SectionSegments[i].Image.Characteristics & IMAGE_SCN_TYPE_NOLOAD))
-            {
-                ULONG_PTR MaxExtent;
-                MaxExtent = (ULONG_PTR)(SectionSegments[i].Image.VirtualAddress +
-                                        SectionSegments[i].Length.QuadPart);
-                ImageSize = max(ImageSize, MaxExtent);
-            }
+            ULONG_PTR MaxExtent;
+            MaxExtent = (ULONG_PTR)(SectionSegments[i].Image.VirtualAddress +
+                                    SectionSegments[i].Length.QuadPart);
+            ImageSize = max(ImageSize, MaxExtent);
         }
 
         ImageSectionObject->ImageInformation.ImageFileSize = (ULONG)ImageSize;
@@ -4517,14 +4588,14 @@ MmMapViewOfSection(IN PVOID SectionObject,
         if (((ImageBase + ImageSize) > (ULONG_PTR)MmHighestUserAddress) ||
                 ((ImageBase + ImageSize) < ImageSize))
         {
-            NT_ASSERT(*BaseAddress == NULL);
+            ASSERT(*BaseAddress == NULL);
             ImageBase = ALIGN_DOWN_BY((ULONG_PTR)MmHighestUserAddress - ImageSize,
                                       MM_VIRTMEM_GRANULARITY);
             NotAtBase = TRUE;
         }
         else if (ImageBase != ALIGN_DOWN_BY(ImageBase, MM_VIRTMEM_GRANULARITY))
         {
-            NT_ASSERT(*BaseAddress == NULL);
+            ASSERT(*BaseAddress == NULL);
             ImageBase = ALIGN_DOWN_BY(ImageBase, MM_VIRTMEM_GRANULARITY);
             NotAtBase = TRUE;
         }
@@ -4552,25 +4623,22 @@ MmMapViewOfSection(IN PVOID SectionObject,
 
         for (i = 0; i < NrSegments; i++)
         {
-            if (!(SectionSegments[i].Image.Characteristics & IMAGE_SCN_TYPE_NOLOAD))
+            PVOID SBaseAddress = (PVOID)
+                                 ((char*)ImageBase + (ULONG_PTR)SectionSegments[i].Image.VirtualAddress);
+            MmLockSectionSegment(&SectionSegments[i]);
+            Status = MmMapViewOfSegment(AddressSpace,
+                                        Section,
+                                        &SectionSegments[i],
+                                        &SBaseAddress,
+                                        SectionSegments[i].Length.LowPart,
+                                        SectionSegments[i].Protection,
+                                        0,
+                                        0);
+            MmUnlockSectionSegment(&SectionSegments[i]);
+            if (!NT_SUCCESS(Status))
             {
-                PVOID SBaseAddress = (PVOID)
-                                     ((char*)ImageBase + (ULONG_PTR)SectionSegments[i].Image.VirtualAddress);
-                MmLockSectionSegment(&SectionSegments[i]);
-                Status = MmMapViewOfSegment(AddressSpace,
-                                            Section,
-                                            &SectionSegments[i],
-                                            &SBaseAddress,
-                                            SectionSegments[i].Length.LowPart,
-                                            SectionSegments[i].Protection,
-                                            0,
-                                            0);
-                MmUnlockSectionSegment(&SectionSegments[i]);
-                if (!NT_SUCCESS(Status))
-                {
-                    MmUnlockAddressSpace(AddressSpace);
-                    return(Status);
-                }
+                MmUnlockAddressSpace(AddressSpace);
+                return(Status);
             }
         }
 
@@ -4601,13 +4669,6 @@ MmMapViewOfSection(IN PVOID SectionObject,
             return STATUS_SECTION_PROTECTION;
         }
 
-        if (ViewSize == NULL)
-        {
-            /* Following this pointer would lead to us to the dark side */
-            /* What to do? Bugcheck? Return status? Do the mambo? */
-            KeBugCheck(MEMORY_MANAGEMENT);
-        }
-
         if (SectionOffset == NULL)
         {
             ViewOffset = 0;
@@ -4652,7 +4713,7 @@ MmMapViewOfSection(IN PVOID SectionObject,
     }
 
     MmUnlockAddressSpace(AddressSpace);
-    NT_ASSERT(*BaseAddress == ALIGN_DOWN_POINTER_BY(*BaseAddress, MM_VIRTMEM_GRANULARITY));
+    ASSERT(*BaseAddress == ALIGN_DOWN_POINTER_BY(*BaseAddress, MM_VIRTMEM_GRANULARITY));
 
     if (NotAtBase)
         Status = STATUS_IMAGE_NOT_AT_BASE;
@@ -5016,9 +5077,39 @@ MmCreateSection (OUT PVOID  * Section,
         if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE)
         {
             DPRINT1("CC failure: %lx\n", Status);
+            if (FileObject)
+                ObDereferenceObject(FileObject);
             return Status;
         }
         // Caching is initialized...
+
+        // Hack of the hack: actually, it might not be initialized if FSD init on effective right and if file is null-size
+        // In such case, force cache by initiating a write IRP
+        if (Status == STATUS_END_OF_FILE && !(AllocationAttributes & SEC_IMAGE) && FileObject != NULL &&
+            (FileObject->SectionObjectPointer == NULL || FileObject->SectionObjectPointer->SharedCacheMap == NULL))
+        {
+            Buffer = 0xdb;
+            Status = ZwWriteFile(FileHandle,
+                                 NULL,
+                                 NULL,
+                                 NULL,
+                                 &Iosb,
+                                 &Buffer,
+                                 sizeof(Buffer),
+                                 &ByteOffset,
+                                 NULL);
+            if (NT_SUCCESS(Status))
+            {
+                LARGE_INTEGER Zero;
+                Zero.QuadPart = 0LL;
+
+                Status = IoSetInformation(FileObject,
+                                          FileEndOfFileInformation,
+                                          sizeof(LARGE_INTEGER),
+                                          &Zero);
+                ASSERT(NT_SUCCESS(Status));
+            }
+        }
     }
 #endif