Author: ion
Date: Sun Jul 10 21:55:55 2011
New Revision: 52618
URL: 
http://svn.reactos.org/svn/reactos?rev=52618&view=rev
Log:
[NDK]: Add missing RtlImageNtHeaderEx flags.
[RTL]: Implement RtlImageNtHeaderEx and make RtlImageNtHeader call it. This will result in
much stricter (and correct) PE loading by default, and enable a flag which can do even
stricter checks.
[NTDLL]: Export RtlImageNtHeaderEx (maybe NTOS should export it too, not sure).
Modified:
    trunk/reactos/dll/ntdll/def/ntdll.pspec
    trunk/reactos/include/ndk/rtltypes.h
    trunk/reactos/lib/rtl/image.c
Modified: trunk/reactos/dll/ntdll/def/ntdll.pspec
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/ntdll/def/ntdll.pspec?…
==============================================================================
--- trunk/reactos/dll/ntdll/def/ntdll.pspec [iso-8859-1] (original)
+++ trunk/reactos/dll/ntdll/def/ntdll.pspec [iso-8859-1] Sun Jul 10 21:55:55 2011
@@ -691,7 +691,7 @@
 @ stdcall RtlIdentifierAuthoritySid(ptr)
 @ stdcall RtlImageDirectoryEntryToData(long long long ptr)
 @ stdcall RtlImageNtHeader(long)
-//@ stdcall RtlImageNtHeaderEx
+@ stdcall RtlImageNtHeaderEx(long ptr double ptr)
 @ stdcall RtlImageRvaToSection(ptr long long)
 @ stdcall RtlImageRvaToVa(ptr long long ptr)
 @ stdcall RtlImpersonateSelf(long)
Modified: trunk/reactos/include/ndk/rtltypes.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/rtltypes.h?rev…
==============================================================================
--- trunk/reactos/include/ndk/rtltypes.h [iso-8859-1] (original)
+++ trunk/reactos/include/ndk/rtltypes.h [iso-8859-1] Sun Jul 10 21:55:55 2011
@@ -243,6 +243,11 @@
 // RtlFindCharInUnicodeString Flags
 //
 #define RTL_FIND_CHAR_IN_UNICODE_STRING_CASE_INSENSITIVE    4
+
+//
+// RtlImageNtHeaderEx Flags
+//
+#define RTL_IMAGE_NT_HEADER_EX_FLAG_NO_RANGE_CHECK          0x00000001
 //
 // Codepages
Modified: trunk/reactos/lib/rtl/image.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/image.c?rev=52618&…
==============================================================================
--- trunk/reactos/lib/rtl/image.c [iso-8859-1] (original)
+++ trunk/reactos/lib/rtl/image.c [iso-8859-1] Sun Jul 10 21:55:55 2011
@@ -120,6 +120,13 @@
     return (BOOLEAN)(CalcSum == HeaderSum);
 #else
+    /*
+     * FIXME: Warning, this violates the PE standard and makes ReactOS drivers
+     * and other system code when normally on Windows they would not, since
+     * we do not write the checksum in them.
+     * Our compilers should be made to write out the checksum and this function
+     * should be enabled as to reject badly checksummed code.
+     */
     return TRUE;
 #endif
 }
@@ -127,28 +134,122 @@
 /*
  * @implemented
  */
+NTSTATUS
+NTAPI
+RtlImageNtHeaderEx(IN ULONG Flags,
+                   IN PVOID Base,
+                   IN ULONG64 Size,
+                   OUT PIMAGE_NT_HEADERS *OutHeaders)
+{
+    PIMAGE_NT_HEADERS NtHeaders;
+    PIMAGE_DOS_HEADER DosHeader;
+
+    /* You must want NT Headers, no? */
+    if (!OutHeaders) return STATUS_INVALID_PARAMETER;
+
+    /* Assume failure */
+    *OutHeaders = NULL;
+
+    /* Validate Flags */
+    if (Flags &~ RTL_IMAGE_NT_HEADER_EX_FLAG_NO_RANGE_CHECK)
+    {
+        DPRINT1("Invalid flag combination... check for new API flags?\n");
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Validate base */
+    if (!(Base) || (Base == (PVOID)-1)) return STATUS_INVALID_PARAMETER;
+
+    /* Check if the caller wants validation */
+    if (Flags & RTL_IMAGE_NT_HEADER_EX_FLAG_NO_RANGE_CHECK)
+    {
+        /* Make sure the image size is at least big enough for the DOS header */
+        if (Size < sizeof(IMAGE_DOS_HEADER))
+        {
+            DPRINT1("Size too small\n");
+            return STATUS_INVALID_IMAGE_FORMAT;
+        }
+    }
+
+    /* Check if the DOS Signature matches */
+    DosHeader = Base;
+    if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE)
+    {
+        /* Not a valid COFF */
+        DPRINT1("Not an MZ file\n");
+        return STATUS_INVALID_IMAGE_FORMAT;
+    }
+
+    /* Check if the caller wants validation */
+    if (Flags & RTL_IMAGE_NT_HEADER_EX_FLAG_NO_RANGE_CHECK)
+    {
+        /* The offset should fit in the passsed-in size */
+        if (DosHeader->e_lfanew >= Size)
+        {
+            /* Fail */
+            DPRINT1("e_lfanew is larger than PE file\n");
+            return STATUS_INVALID_IMAGE_FORMAT;
+        }
+
+        /* It shouldn't be past 4GB either */
+        if (DosHeader->e_lfanew >=
+            (MAXULONG - sizeof(IMAGE_DOS_SIGNATURE) - sizeof(IMAGE_FILE_HEADER)))
+        {
+            /* Fail */
+            DPRINT1("e_lfanew is larger than 4GB\n");
+            return STATUS_INVALID_IMAGE_FORMAT;
+        }
+
+        /* And the whole file shouldn't overflow past 4GB */
+        if ((DosHeader->e_lfanew +
+            sizeof(IMAGE_DOS_SIGNATURE) - sizeof(IMAGE_FILE_HEADER)) >= Size)
+        {
+            /* Fail */
+            DPRINT1("PE is larger than 4GB\n");
+            return STATUS_INVALID_IMAGE_FORMAT;
+        }
+    }
+
+    /* The offset also can't be larger than 256MB, as a hard-coded check */
+    if (DosHeader->e_lfanew >= (256 * 1024 * 1024))
+    {
+        /* Fail */
+        DPRINT1("PE offset is larger than 256MB\n");
+        return STATUS_INVALID_IMAGE_FORMAT;
+    }
+
+    /* Now it's safe to get the NT Headers */
+    NtHeaders = (PIMAGE_NT_HEADERS)((ULONG_PTR)Base + DosHeader->e_lfanew);
+
+    /* Verify the PE Signature */
+    if (NtHeaders->Signature != IMAGE_NT_SIGNATURE)
+    {
+        /* Fail */
+        DPRINT1("PE signature missing\n");
+        return STATUS_INVALID_IMAGE_FORMAT;
+    }
+
+    /* Now return success and the NT header */
+    *OutHeaders = NtHeaders;
+    return STATUS_SUCCESS;
+}
+
+/*
+ * @implemented
+ */
 PIMAGE_NT_HEADERS
 NTAPI
-RtlImageNtHeader(IN PVOID BaseAddress)
+RtlImageNtHeader(IN PVOID Base)
 {
     PIMAGE_NT_HEADERS NtHeader;
-    PIMAGE_DOS_HEADER DosHeader = (PIMAGE_DOS_HEADER)BaseAddress;
-
-    if (DosHeader && SWAPW(DosHeader->e_magic) != IMAGE_DOS_SIGNATURE)
-    {
-        DPRINT1("DosHeader->e_magic %x\n", SWAPW(DosHeader->e_magic));
-        DPRINT1("NtHeader 0x%lx\n", ((ULONG_PTR)BaseAddress +
SWAPD(DosHeader->e_lfanew)));
-    }
-    else
-    {
-        NtHeader = (PIMAGE_NT_HEADERS)((ULONG_PTR)BaseAddress +
SWAPD(DosHeader->e_lfanew));
-        if (SWAPD(NtHeader->Signature) == IMAGE_NT_SIGNATURE)
-            return NtHeader;
-    }
-
-    return NULL;
-}
-
+
+    /* Call the new API */
+    RtlImageNtHeaderEx(RTL_IMAGE_NT_HEADER_EX_FLAG_NO_RANGE_CHECK,
+                       Base,
+                       0,
+                       &NtHeader);
+    return NtHeader;
+}
 /*
  * @implemented