[NTOSKRNL]
[reactos.git] / reactos / ntoskrnl / mm / section.c
index ad43250..b7b6435 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 *****************************************************************/
 
@@ -241,13 +236,13 @@ NTSTATUS NTAPI PeFmtCreateSection(IN CONST VOID * FileHeader,
     if(pidhDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
         DIE(("No MZ signature found, e_magic is %hX\n", pidhDosHeader->e_magic));
 
+    /* NT HEADER */
+    nStatus = STATUS_INVALID_IMAGE_PROTECT;
+
     /* not a Windows executable */
     if(pidhDosHeader->e_lfanew <= 0)
         DIE(("Not a Windows executable, e_lfanew is %d\n", pidhDosHeader->e_lfanew));
 
-    /* NT HEADER */
-    nStatus = STATUS_INVALID_IMAGE_FORMAT;
-
     if(!Intsafe_AddULong32(&cbFileHeaderOffsetSize, pidhDosHeader->e_lfanew, RTL_SIZEOF_THROUGH_FIELD(IMAGE_NT_HEADERS32, FileHeader)))
         DIE(("The DOS stub is too large, e_lfanew is %X\n", pidhDosHeader->e_lfanew));
 
@@ -286,7 +281,7 @@ l_ReadHeaderFromFile:
             NTSTATUS ReturnedStatus = nStatus;
 
             /* If it attempted to read past the end of the file, it means e_lfanew is invalid */
-            if (ReturnedStatus == STATUS_END_OF_FILE) nStatus = STATUS_ROS_EXEFMT_UNKNOWN_FORMAT;
+            if (ReturnedStatus == STATUS_END_OF_FILE) nStatus = STATUS_INVALID_IMAGE_PROTECT;
 
             DIE(("ReadFile failed, status %08X\n", ReturnedStatus));
         }
@@ -336,11 +331,11 @@ l_ReadHeaderFromFile:
         if(pinhNtHeader->Signature != IMAGE_NT_SIGNATURE)
             DIE(("The file isn't a PE executable, Signature is %X\n", pinhNtHeader->Signature));
 
-        nStatus = STATUS_INVALID_IMAGE_FORMAT;
-
         if(!Intsafe_AddULong32(&cbOptHeaderOffsetSize, pidhDosHeader->e_lfanew, FIELD_OFFSET(IMAGE_NT_HEADERS32, OptionalHeader)))
             DIE(("The DOS stub is too large, e_lfanew is %X\n", pidhDosHeader->e_lfanew));
 
+        nStatus = STATUS_INVALID_IMAGE_FORMAT;
+
         if(!Intsafe_AddULong32(&cbOptHeaderOffsetSize, cbOptHeaderOffsetSize, pinhNtHeader->FileHeader.SizeOfOptionalHeader))
             DIE(("The NT header is too large, SizeOfOptionalHeader is %X\n", pinhNtHeader->FileHeader.SizeOfOptionalHeader));
 
@@ -363,7 +358,9 @@ l_ReadHeaderFromFile:
     switch(piohOptHeader->Magic)
     {
     case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
+#ifdef _WIN64
     case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
+#endif // _WIN64
         break;
 
     default:
@@ -2754,7 +2751,7 @@ MmCreatePhysicalMemorySection(VOID)
     SectionSize.QuadPart = 0xFFFFFFFF;
     InitializeObjectAttributes(&Obj,
                                &Name,
-                               OBJ_PERMANENT,
+                               OBJ_PERMANENT | OBJ_KERNEL_EXCLUSIVE,
                                NULL,
                                NULL);
     Status = MmCreateSection((PVOID)&PhysSection,
@@ -3234,6 +3231,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 +3248,7 @@ ExeFmtpReadFile(IN PVOID File,
                                    'rXmM');
     if (!Buffer)
     {
-        KeBugCheck(MEMORY_MANAGEMENT);
+        return STATUS_INSUFFICIENT_RESOURCES;
     }
 
     UsedSize = 0;
@@ -3610,7 +3613,7 @@ MmspPageAlignSegments
 }
 
 NTSTATUS
-ExeFmtpCreateImageSection(HANDLE FileHandle,
+ExeFmtpCreateImageSection(PFILE_OBJECT FileObject,
                           PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
 {
     LARGE_INTEGER Offset;
@@ -3628,8 +3631,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 +3655,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 +3777,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
      */
@@ -4184,7 +4193,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 +4219,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 +4232,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,12 +4288,14 @@ 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;
     KPROCESSOR_MODE PreviousMode;
@@ -4288,20 +4303,44 @@ NtQuerySection(IN HANDLE SectionHandle,
     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)
+        {
+            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,10 +4349,14 @@ 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;
+    }
+
+    switch (SectionInformationClass)
     {
-        switch (SectionInformationClass)
-        {
         case SectionBasicInformation:
         {
             PSECTION_BASIC_INFORMATION Sbi = (PSECTION_BASIC_INFORMATION)SectionInformation;
@@ -4375,11 +4418,10 @@ NtQuerySection(IN HANDLE SectionHandle,
 
             break;
         }
-        }
-
-        ObDereferenceObject(Section);
     }
 
+    ObDereferenceObject(Section);
+
     return(Status);
 }
 
@@ -4472,6 +4514,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 +4546,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 +4558,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 +4593,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 +4639,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 +4683,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;