Commit in reactos on MAIN
include/ddk/ntdef.h+101.5 -> 1.6
include/ntos/zw.h+2-21.39 -> 1.40
lib/kernel32/process/create.c+4-31.91 -> 1.92
lib/rtl/random.c+1-31.3 -> 1.4
ntoskrnl/Makefile+31.159 -> 1.160
ntoskrnl/include/internal/mm.h+31-141.94 -> 1.95
ntoskrnl/mm/i386/page.c+4-41.79 -> 1.80
ntoskrnl/mm/section.c+718-3111.168 -> 1.169
w32api/include/ddk/ntifs.h+13-131.9 -> 1.10
+786-350
9 modified files
ELF_support, welcome to HEAD! (just in time for the freeze, too!)

reactos/include/ddk
ntdef.h 1.5 -> 1.6
diff -u -r1.5 -r1.6
--- ntdef.h	27 Nov 2002 20:46:44 -0000	1.5
+++ ntdef.h	30 Dec 2004 08:05:09 -0000	1.6
@@ -17,4 +17,14 @@
 #define NTAPI STDCALL
 #endif
 
+#define MINCHAR   (0x80)
+#define MAXCHAR   (0x7F)
+#define MINSHORT  (0x8000)
+#define MAXSHORT  (0x7FFF)
+#define MINLONG   (0x80000000)
+#define MAXLONG   (0x7FFFFFFF)
+#define MAXUCHAR  (0xFF)
+#define MAXUSHORT (0xFFFF)
+#define MAXULONG  (0xFFFFFFFF)
+
 #endif

reactos/include/ntos
zw.h 1.39 -> 1.40
diff -u -r1.39 -r1.40
--- zw.h	23 Dec 2004 20:12:51 -0000	1.39
+++ zw.h	30 Dec 2004 08:05:10 -0000	1.40
@@ -1,4 +1,4 @@
-/* $Id: zw.h,v 1.39 2004/12/23 20:12:51 ekohl Exp $
+/* $Id: zw.h,v 1.40 2004/12/30 08:05:10 hyperion Exp $
  *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
@@ -6479,7 +6479,7 @@
 
 typedef struct _SECTION_IMAGE_INFORMATION
 {
-  PVOID EntryPoint;
+  ULONG EntryPoint;
   ULONG Unknown1;
   ULONG StackReserve;
   ULONG StackCommit;

reactos/lib/kernel32/process
create.c 1.91 -> 1.92
diff -u -r1.91 -r1.92
--- create.c	18 Dec 2004 13:26:57 -0000	1.91
+++ create.c	30 Dec 2004 08:05:11 -0000	1.92
@@ -1,4 +1,4 @@
-/* $Id: create.c,v 1.91 2004/12/18 13:26:57 weiden Exp $
+/* $Id: create.c,v 1.92 2004/12/30 08:05:11 hyperion Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
@@ -12,6 +12,7 @@
 /* INCLUDES ****************************************************************/
 
 #include <k32.h>
+#include <pseh/framebased.h>
 
 #define NDEBUG
 #include "../include/debug.h"
@@ -1385,11 +1386,11 @@
     * Create the thread for the kernel
     */
    DPRINT("Creating thread for process (EntryPoint = 0x%.08x)\n",
-    ImageBaseAddress + (ULONG)Sii.EntryPoint);
+    (PVOID)((ULONG_PTR)ImageBaseAddress + Sii.EntryPoint));
    hThread =  KlCreateFirstThread(hProcess,
 				  lpThreadAttributes,
           &Sii,
-          ImageBaseAddress + (ULONG)Sii.EntryPoint,
+          (PVOID)((ULONG_PTR)ImageBaseAddress + Sii.EntryPoint),
 				  dwCreationFlags,
 				  &lpProcessInformation->dwThreadId);
    if (hThread == INVALID_HANDLE_VALUE)

reactos/lib/rtl
random.c 1.3 -> 1.4
diff -u -r1.3 -r1.4
--- random.c	7 Aug 2004 19:13:25 -0000	1.3
+++ random.c	30 Dec 2004 08:05:11 -0000	1.4
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: random.c,v 1.3 2004/08/07 19:13:25 ion Exp $
+/* $Id: random.c,v 1.4 2004/12/30 08:05:11 hyperion Exp $
  *
  * COPYRIGHT:         See COPYING in the top level directory
  * PROJECT:           ReactOS kernel
@@ -31,8 +31,6 @@
 #define NDEBUG
 #include <debug.h>
 
-#define MAXLONG (0x7fffffff)
-
 static ULONG SavedValue[128] =
    {
       0x4c8bc0aa, 0x4c022957, 0x2232827a, 0x2f1e7626,  /*   0 */

reactos/ntoskrnl
Makefile 1.159 -> 1.160
diff -u -r1.159 -r1.160
--- Makefile	17 Dec 2004 07:31:11 -0000	1.159
+++ Makefile	30 Dec 2004 08:05:11 -0000	1.160
@@ -144,6 +144,8 @@
 	mm/balance.o \
 	mm/cont.o \
 	mm/drvlck.o \
+	mm/elf32.o \
+	mm/elf64.o \
 	mm/freelist.o \
 	mm/iospace.o \
 	mm/kmap.o \
@@ -159,6 +161,7 @@
 	mm/pageop.o \
 	mm/pager.o \
 	mm/paging.o \
+	mm/pe.o \
 	mm/pool.o \
 	mm/ppool.o \
 	mm/physical.o \

reactos/ntoskrnl/include/internal
mm.h 1.94 -> 1.95
diff -u -r1.94 -r1.95
--- mm.h	19 Dec 2004 16:16:56 -0000	1.94
+++ mm.h	30 Dec 2004 08:05:11 -0000	1.95
@@ -71,6 +71,26 @@
 						 PAGE_NOACCESS | \
 						 PAGE_NOCACHE)
 
+#define PAGE_IS_READABLE (PAGE_READONLY | \
+                          PAGE_READWRITE | \
+                          PAGE_WRITECOPY | \
+                          PAGE_EXECUTE_READ | \
+                          PAGE_EXECUTE_READWRITE | \
+                          PAGE_EXECUTE_WRITECOPY)
+
+#define PAGE_IS_WRITABLE (PAGE_READWRITE | \
+                          PAGE_WRITECOPY | \
+                          PAGE_EXECUTE_READWRITE | \
+                          PAGE_EXECUTE_WRITECOPY)
+
+#define PAGE_IS_EXECUTABLE (PAGE_EXECUTE | \
+                            PAGE_EXECUTE_READ | \
+                            PAGE_EXECUTE_READWRITE | \
+                            PAGE_EXECUTE_WRITECOPY)
+
+#define PAGE_IS_WRITECOPY (PAGE_WRITECOPY | \
+                           PAGE_EXECUTE_WRITECOPY)
+
 typedef struct
 {
   ULONG Entry[NR_SECTION_PAGE_ENTRIES];
@@ -86,38 +106,35 @@
 #define MM_PAGEFILE_SEGMENT    (0x1)
 #define MM_DATAFILE_SEGMENT    (0x2)
 
-#define MM_SECTION_SEGMENT_BSS (0x1)
-
 typedef struct _MM_SECTION_SEGMENT
 {
-  ULONG FileOffset;
-  ULONG Protection;
-  ULONG Attributes;
-  ULONG Length;
+  LONGLONG FileOffset;
+  ULONG_PTR VirtualAddress;
   ULONG RawLength;
+  ULONG Length;
+  ULONG Protection;
   FAST_MUTEX Lock;
   ULONG ReferenceCount;
   SECTION_PAGE_DIRECTORY PageDirectory;
   ULONG Flags;
-  PVOID VirtualAddress;
   ULONG Characteristics;
   BOOLEAN WriteCopy;
 } MM_SECTION_SEGMENT, *PMM_SECTION_SEGMENT;
 
 typedef struct _MM_IMAGE_SECTION_OBJECT
 {
-  PVOID ImageBase;
-  PVOID EntryPoint;
-  ULONG StackReserve;
-  ULONG StackCommit;
+  ULONG_PTR ImageBase;
+  ULONG_PTR StackReserve;
+  ULONG_PTR StackCommit;
+  ULONG EntryPoint;
   ULONG Subsystem;
-  ULONG MinorSubsystemVersion;
-  ULONG MajorSubsystemVersion;
   ULONG ImageCharacteristics;
+  USHORT MinorSubsystemVersion;
+  USHORT MajorSubsystemVersion;
   USHORT Machine;
   BOOLEAN Executable;
   ULONG NrSegments;
-  MM_SECTION_SEGMENT Segments[0];
+  PMM_SECTION_SEGMENT Segments;
 } MM_IMAGE_SECTION_OBJECT, *PMM_IMAGE_SECTION_OBJECT;
 
 typedef struct _SECTION_OBJECT

reactos/ntoskrnl/mm/i386
page.c 1.79 -> 1.80
diff -u -r1.79 -r1.80
--- page.c	24 Dec 2004 17:07:00 -0000	1.79
+++ page.c	30 Dec 2004 08:05:11 -0000	1.80
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: page.c,v 1.79 2004/12/24 17:07:00 navaraf Exp $
+/* $Id: page.c,v 1.80 2004/12/30 08:05:11 hyperion Exp $
  *
  * PROJECT:     ReactOS kernel
  * FILE:        ntoskrnl/mm/i386/page.c
@@ -146,11 +146,11 @@
    {
       Attributes = 0;
    }
-   else if (flProtect & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE))
+   else if (flProtect & PAGE_IS_WRITABLE)
    {
       Attributes = PA_PRESENT | PA_READWRITE;
    }
-   else if (flProtect & (PAGE_READONLY|PAGE_EXECUTE|PAGE_EXECUTE_READ))
+   else if (flProtect & (PAGE_IS_READABLE | PAGE_IS_EXECUTABLE))
    {
       Attributes = PA_PRESENT;
    }
@@ -160,7 +160,7 @@
       KEBUGCHECK(0);
    }
    if (Ke386NoExecute && 
-       !(flProtect & (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE)))
+       !(flProtect & PAGE_IS_EXECUTABLE))
    {
       Attributes = Attributes | 0x80000000;
    }

reactos/ntoskrnl/mm
section.c 1.168 -> 1.169
diff -u -r1.168 -r1.169
--- section.c	24 Dec 2004 17:06:59 -0000	1.168
+++ section.c	30 Dec 2004 08:05:11 -0000	1.169
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: section.c,v 1.168 2004/12/24 17:06:59 navaraf Exp $
+/* $Id: section.c,v 1.169 2004/12/30 08:05:11 hyperion Exp $
  *
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/mm/section.c
@@ -32,6 +32,8 @@
 #define NDEBUG
 #include <internal/debug.h>
 
+#include <reactos/exeformat.h>
+
 /* TYPES *********************************************************************/
 
 typedef struct
@@ -156,6 +158,7 @@
          }
          MmFreePageTablesSectionSegment(&SectionSegments[i]);
       }
+      ExFreePool(ImageSectionObject->Segments);
       ExFreePool(ImageSectionObject);
       FileObject->SectionObjectPointer->ImageSectionObject = NULL;
    }
@@ -2228,7 +2231,6 @@
    ExInitializeFastMutex(&Segment->Lock);
    Segment->FileOffset = 0;
    Segment->Protection = SectionPageProtection;
-   Segment->Attributes = AllocationAttributes;
    Segment->RawLength = MaximumSize.u.LowPart;
    Segment->Length = PAGE_ROUND_UP(MaximumSize.u.LowPart);
    Segment->Flags = MM_PAGEFILE_SEGMENT;
@@ -2442,7 +2444,6 @@
 
       Segment->FileOffset = 0;
       Segment->Protection = SectionPageProtection;
-      Segment->Attributes = 0;
       Segment->Flags = MM_DATAFILE_SEGMENT;
       Segment->Characteristics = 0;
       Segment->WriteCopy = FALSE;
@@ -2455,7 +2456,7 @@
          Segment->RawLength = MaximumSize.u.LowPart;
          Segment->Length = PAGE_ROUND_UP(Segment->RawLength);
       }
-      Segment->VirtualAddress = NULL;
+      Segment->VirtualAddress = 0;
       RtlZeroMemory(&Segment->PageDirectory, sizeof(SECTION_PAGE_DIRECTORY));
    }
    else
@@ -2487,25 +2488,653 @@
    return(STATUS_SUCCESS);
 }
 
-static ULONG SectionCharacteristicsToProtect[16] =
+/*
+ TODO: not that great (declaring loaders statically, having to declare all of
+ them, having to keep them extern, etc.), will fix in the future
+*/
+extern NTSTATUS NTAPI PeFmtCreateSection
+(
+ IN CONST VOID * FileHeader,
+ IN SIZE_T FileHeaderSize,
+ IN PVOID File,
+ OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
+ OUT PULONG Flags,
+ IN PEXEFMT_CB_READ_FILE ReadFileCb,
+ IN PEXEFMT_CB_ALLOCATE_SEGMENTS AllocateSegmentsCb
+);
+
+extern NTSTATUS NTAPI ElfFmtCreateSection
+(
+ IN CONST VOID * FileHeader,
+ IN SIZE_T FileHeaderSize,
+ IN PVOID File,
+ OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
+ OUT PULONG Flags,
+ IN PEXEFMT_CB_READ_FILE ReadFileCb,
+ 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,
+ ElfFmtCreateSection
+};
+
+static
+PMM_SECTION_SEGMENT
+NTAPI
+ExeFmtpAllocateSegments(IN ULONG NrSegments)
+{
+ SIZE_T SizeOfSegments;
+ PMM_SECTION_SEGMENT Segments;
+
+ /* TODO: check for integer overflow */
+ SizeOfSegments = sizeof(MM_SECTION_SEGMENT) * NrSegments;
+
+ Segments = ExAllocatePoolWithTag(NonPagedPool,
+                                  SizeOfSegments,
+                                  TAG_MM_SECTION_SEGMENT);
+
+ if(Segments)
+  RtlZeroMemory(Segments, SizeOfSegments);
+
+ return Segments;
+}
+
+static
+NTSTATUS
+NTAPI
+ExeFmtpReadFile(IN PVOID File,
+                IN PLARGE_INTEGER Offset,
+                IN ULONG Length,
+                OUT PVOID * Data,
+                OUT PVOID * AllocBase,
+                OUT PULONG ReadSize)
+{
+   NTSTATUS Status;
+   LARGE_INTEGER FileOffset;
+   ULONG AdjustOffset;
+   ULONG OffsetAdjustment;
+   ULONG BufferSize;
+   ULONG UsedSize;
+   PVOID Buffer;
+
+   ASSERT_IRQL_LESS(DISPATCH_LEVEL);
+
+   if(Length == 0)
+   {
+      KEBUGCHECK(STATUS_INVALID_PARAMETER_4);
+   }
+
+   FileOffset = *Offset;
+
+   /* Negative/special offset: it cannot be used in this context */
+   if(FileOffset.u.HighPart < 0)
+   {
+      KEBUGCHECK(STATUS_INVALID_PARAMETER_5);
+   }
+
+   ASSERT(PAGE_SIZE <= MAXULONG);
+   AdjustOffset = PAGE_ROUND_DOWN(FileOffset.u.LowPart);
+   OffsetAdjustment = FileOffset.u.LowPart - AdjustOffset;
+   FileOffset.u.LowPart = AdjustOffset;
+
+   BufferSize = Length + OffsetAdjustment;
+   BufferSize = PAGE_ROUND_UP(BufferSize);
+
+   /*
+    * 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
+    * always called at low IRQLs and that these buffers don't survive a brief
+    * initialization phase
+    */
+   Buffer = ExAllocatePoolWithTag(PagedPool,
+                                  BufferSize,
+                                  TAG('M', 'm', 'X', 'r'));
+
+   UsedSize = 0;
+
+#if 0
+   Status = MmspPageRead(File,
+                         Buffer,
+                         BufferSize,
+                         &FileOffset,
+                         &UsedSize);
+#else
+/*
+ * FIXME: if we don't use ZwReadFile, caching is not enabled for the file and
+ * nothing will work. But using ZwReadFile is wrong, and using its side effects
+ * to initialize internal state is even worse. Our cache manager is in need of
+ * professional help
+ */
+   {
+      IO_STATUS_BLOCK Iosb;
+
+      Status = ZwReadFile(File,
+                          NULL,
+                          NULL,
+                          NULL,
+                          &Iosb,
+                          Buffer,
+                          BufferSize,
+                          &FileOffset,
+                          NULL);
+   
+      if(NT_SUCCESS(Status))
+      {
+         UsedSize = Iosb.Information;
+      }
+   }
+#endif
+
+   if(NT_SUCCESS(Status) && UsedSize < OffsetAdjustment)
+   {
+      Status = STATUS_IN_PAGE_ERROR;
+      ASSERT(!NT_SUCCESS(Status));
+   }
+
+   if(NT_SUCCESS(Status))
+   {
+      *Data = (PVOID)((ULONG_PTR)Buffer + OffsetAdjustment);
+      *AllocBase = Buffer;
+      *ReadSize = UsedSize - OffsetAdjustment;
+   }
+   else
+   {
+      ExFreePool(Buffer);
+   }
+
+   return Status;
+}
+
+#ifdef NASSERT
+# define MmspAssertSegmentsSorted(OBJ_) ((void)0)
+# define MmspAssertSegmentsNoOverlap(OBJ_) ((void)0)
+# define MmspAssertSegmentsPageAligned(OBJ_) ((void)0)
+#else
+static
+VOID
+NTAPI
+MmspAssertSegmentsSorted(IN PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
+{
+   ULONG i;
+
+   for( i = 1; i < ImageSectionObject->NrSegments; ++ i )
+   {
+      ASSERT(ImageSectionObject->Segments[i].VirtualAddress >=
+             ImageSectionObject->Segments[i - 1].VirtualAddress);
+   }
+}
+
+static
+VOID
+NTAPI
+MmspAssertSegmentsNoOverlap(IN PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
+{
+   ULONG i;
+
+   MmspAssertSegmentsSorted(ImageSectionObject);
+
+   for( i = 0; i < ImageSectionObject->NrSegments; ++ i )
+   {
+      ASSERT(ImageSectionObject->Segments[i].Length > 0);
+
+      if(i > 0)
+      {
+         ASSERT(ImageSectionObject->Segments[i].VirtualAddress >=
+                (ImageSectionObject->Segments[i - 1].VirtualAddress +
+                 ImageSectionObject->Segments[i - 1].Length));
+      }
+   }
+}
+
+static
+VOID
+NTAPI
+MmspAssertSegmentsPageAligned(IN PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
+{
+   ULONG i;
+
+   for( i = 0; i < ImageSectionObject->NrSegments; ++ i )
    {
-      PAGE_NOACCESS,               // 0 = NONE
-      PAGE_NOACCESS,               // 1 = SHARED
-      PAGE_EXECUTE,                // 2 = EXECUTABLE
-      PAGE_EXECUTE,                // 3 = EXECUTABLE, SHARED
-      PAGE_READONLY,               // 4 = READABLE
-      PAGE_READONLY,               // 5 = READABLE, SHARED
-      PAGE_EXECUTE_READ,           // 6 = READABLE, EXECUTABLE
-      PAGE_EXECUTE_READ,           // 7 = READABLE, EXECUTABLE, SHARED
-      PAGE_READWRITE,              // 8 = WRITABLE
-      PAGE_READWRITE,              // 9 = WRITABLE, SHARED
-      PAGE_EXECUTE_READWRITE,      // 10 = WRITABLE, EXECUTABLE
-      PAGE_EXECUTE_READWRITE,      // 11 = WRITABLE, EXECUTABLE, SHARED
-      PAGE_READWRITE,              // 12 = WRITABLE, READABLE
-      PAGE_READWRITE,              // 13 = WRITABLE, READABLE, SHARED
-      PAGE_EXECUTE_READWRITE,      // 14 = WRITABLE, READABLE, EXECUTABLE,
-      PAGE_EXECUTE_READWRITE,      // 15 = WRITABLE, READABLE, EXECUTABLE, SHARED
-   };
+      ASSERT((ImageSectionObject->Segments[i].VirtualAddress % PAGE_SIZE) == 0);
+      ASSERT((ImageSectionObject->Segments[i].Length % PAGE_SIZE) == 0);
+   }
+}
+#endif
+
+static
+int
+__cdecl
+MmspCompareSegments(const void * x,
+                    const void * y)
+{
+   PMM_SECTION_SEGMENT Segment1 = (PMM_SECTION_SEGMENT)x;
+   PMM_SECTION_SEGMENT Segment2 = (PMM_SECTION_SEGMENT)y;
+
+   return
+      (Segment1->VirtualAddress - Segment2->VirtualAddress) >>
+      ((sizeof(ULONG_PTR) - sizeof(int)) * 8);
+}
+
+/*
+ * Ensures an image section's segments are sorted in memory
+ */
+static
+VOID
+NTAPI
+MmspSortSegments(IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
+                 IN ULONG Flags)
+{
+   if (Flags & EXEFMT_LOAD_ASSUME_SEGMENTS_SORTED)
+   {
+      MmspAssertSegmentsSorted(ImageSectionObject);
+   }
+   else
+   {
+      qsort(ImageSectionObject->Segments,
+            ImageSectionObject->NrSegments,
+            sizeof(ImageSectionObject->Segments[0]),
+            MmspCompareSegments);
+   }
+}
+
+
+/*
+ * Ensures an image section's segments don't overlap in memory and don't have
+ * gaps and don't have a null size. We let them map to overlapping file regions,
+ * though - that's not necessarily an error
+ */
+static
+BOOLEAN
+NTAPI
+MmspCheckSegmentBounds
+(
+ IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
+ IN ULONG Flags
+)
+{
+   ULONG i;
+
+   if (Flags & EXEFMT_LOAD_ASSUME_SEGMENTS_NO_OVERLAP)
+   {
+      MmspAssertSegmentsNoOverlap(ImageSectionObject);
+      return TRUE;
+   }
+
+   ASSERT(ImageSectionObject->NrSegments >= 1);
+
+   for ( i = 0; i < ImageSectionObject->NrSegments; ++ i )
+   {
+      if(ImageSectionObject->Segments[i].Length == 0)
+      {
+         return FALSE;
+      }
+
+      if(i > 0)
+      {
+         /*
+          * TODO: relax the limitation on gaps. For example, gaps smaller than a
+          * page could be OK (Windows seems to be OK with them), and larger gaps
+          * could lead to image sections spanning several discontiguous regions
+          * (NtMapViewOfSection could then refuse to map them, and they could 
+          * e.g. only be allowed as parameters to NtCreateProcess, like on UNIX)
+          */
+         if ((ImageSectionObject->Segments[i - 1].VirtualAddress +
+              ImageSectionObject->Segments[i - 1].Length) !=
+              ImageSectionObject->Segments[i].VirtualAddress)
+         {
+            return FALSE;
+         }
+      }
+   }
+
+   return TRUE;
+}
+
+/*
+ * Merges and pads an image section's segments until they all are page-aligned
+ * and have a size that is a multiple of the page size
+ */
+static
+BOOLEAN
+NTAPI
+MmspPageAlignSegments
+(
+ IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
+ IN ULONG Flags
+)
+{
+   ULONG i;
+   ULONG LastSegment;
+   BOOLEAN Initialized;
+
+   if (Flags & EXEFMT_LOAD_ASSUME_SEGMENTS_PAGE_ALIGNED)
+   {
+      MmspAssertSegmentsPageAligned(ImageSectionObject);
+      return TRUE;
+   }
+
+   Initialized = FALSE;
+   LastSegment = 0;
+
+   for ( i = 0; i < ImageSectionObject->NrSegments; ++ i )
+   {
+      PMM_SECTION_SEGMENT EffectiveSegment = &ImageSectionObject->Segments[LastSegment];
+
+      /*
+       * The first segment requires special handling
+       */
+      if (i == 0)
+      {
+         ULONG_PTR VirtualAddress;
+         ULONG_PTR VirtualOffset;
+
+         VirtualAddress = EffectiveSegment->VirtualAddress;
+   
+         /* Round down the virtual address to the nearest page */
+         EffectiveSegment->VirtualAddress = PAGE_ROUND_DOWN(VirtualAddress);
+   
+         /* Round up the virtual size to the nearest page */
+         EffectiveSegment->Length = PAGE_ROUND_UP(VirtualAddress + EffectiveSegment->Length) -
+                                    EffectiveSegment->VirtualAddress;
+   
+         /* Adjust the raw address and size */
+         VirtualOffset = VirtualAddress - EffectiveSegment->VirtualAddress;
+   
+         if (EffectiveSegment->FileOffset < VirtualOffset)
+         {
+            return FALSE;
+         }
+   
+         /*
+          * Garbage in, garbage out: unaligned base addresses make the file 
+          * offset point in curious and odd places, but that's what we were 
+          * asked for
+          */
+         EffectiveSegment->FileOffset -= VirtualOffset;
+         EffectiveSegment->RawLength += VirtualOffset;
+      }
+      else
+      {
+         PMM_SECTION_SEGMENT Segment = &ImageSectionObject->Segments[i];
+         ULONG_PTR EndOfEffectiveSegment;
+
+         EndOfEffectiveSegment = EffectiveSegment->VirtualAddress + EffectiveSegment->Length;
+         ASSERT((EndOfEffectiveSegment % PAGE_SIZE) == 0);
+   
+         /*
+          * The current segment begins exactly where the current effective
+          * segment ended, therefore beginning a new effective segment
+          */
+         if (EndOfEffectiveSegment == Segment->VirtualAddress)
+         {
+            LastSegment ++;
+            ASSERT(LastSegment <= i);
+            ASSERT(LastSegment < ImageSectionObject->NrSegments);
+
+            EffectiveSegment = &ImageSectionObject->Segments[LastSegment];
+
+            /*
+             * Copy the current segment. If necessary, the effective segment
+             * will be expanded later
+             */
+            *EffectiveSegment = *Segment;
+
+            /*
+             * Page-align the virtual size. We know for sure the virtual address
+             * already is
+             */
+            ASSERT((EffectiveSegment->VirtualAddress % PAGE_SIZE) == 0);
+            EffectiveSegment->Length = PAGE_ROUND_UP(EffectiveSegment->Length);
+         }
+         /*
+          * The current segment is still part of the current effective segment:
+          * extend the effective segment to reflect this
+          */
+         else if (EndOfEffectiveSegment > Segment->VirtualAddress)
+         {
+            static const ULONG FlagsToProtection[16] =
+            {
+               PAGE_NOACCESS,
+               PAGE_READONLY,
+               PAGE_READWRITE,
+               PAGE_READWRITE,
+               PAGE_EXECUTE_READ,
+               PAGE_EXECUTE_READ,
+               PAGE_EXECUTE_READWRITE,
+               PAGE_EXECUTE_READWRITE,
+               PAGE_WRITECOPY,
+               PAGE_WRITECOPY,
+               PAGE_WRITECOPY,
+               PAGE_WRITECOPY,
+               PAGE_EXECUTE_WRITECOPY,
+               PAGE_EXECUTE_WRITECOPY,
+               PAGE_EXECUTE_WRITECOPY,
+               PAGE_EXECUTE_WRITECOPY
+            };
+
+            unsigned ProtectionFlags;
+
+            /*
+             * Extend the file size
+             */
+   
+            /* Unaligned segments must be contiguous within the file */
+            if (Segment->FileOffset != (EffectiveSegment->FileOffset +
+                                        EffectiveSegment->RawLength))
+            {
+               return FALSE;
+            }
+            
+            EffectiveSegment->RawLength += Segment->RawLength;
+   
+            /*
+             * Extend the virtual size
+             */
+            ASSERT(PAGE_ROUND_UP(Segment->VirtualAddress + Segment->Length) > EndOfEffectiveSegment);
+   
+            EffectiveSegment->Length = PAGE_ROUND_UP(Segment->VirtualAddress + Segment->Length) -
+                                       EffectiveSegment->VirtualAddress;
+   
+            /*
+             * Merge the protection
+             */
+            EffectiveSegment->Protection |= Segment->Protection;
+
+            /* Clean up redundance */
+            ProtectionFlags = 0;
+
+            if(EffectiveSegment->Protection & PAGE_IS_READABLE)
+               ProtectionFlags |= 1 << 0;
+
+            if(EffectiveSegment->Protection & PAGE_IS_WRITABLE)
+               ProtectionFlags |= 1 << 1;
+
+            if(EffectiveSegment->Protection & PAGE_IS_EXECUTABLE)
+               ProtectionFlags |= 1 << 2;
+
+            if(EffectiveSegment->Protection & PAGE_IS_WRITECOPY)
+               ProtectionFlags |= 1 << 3;
+
+            ASSERT(ProtectionFlags < 16);
+            EffectiveSegment->Protection = FlagsToProtection[ProtectionFlags];
+
+            /* If a segment was required to be shared and cannot, fail */
+            if(!(Segment->Protection & PAGE_IS_WRITECOPY) &&
+               EffectiveSegment->Protection & PAGE_IS_WRITECOPY)
+            {
+               return FALSE;
+            }
+         }
+         /*
+          * We assume no holes between segments at this point
+          */
+         else
+         {
+            ASSERT(FALSE);
+         }
+      }
+   }
+
+   return TRUE;
+}
+
+NTSTATUS
+ExeFmtpCreateImageSection(HANDLE FileHandle,
+                          PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
+{
+   LARGE_INTEGER Offset;
+   PVOID FileHeader;
+   PVOID FileHeaderBuffer;
+   ULONG FileHeaderSize;
+   ULONG Flags;
+   ULONG OldNrSegments;
+   NTSTATUS Status;
+   ULONG i;
+
+   /*
+    * Read the beginning of the file (2 pages). Should be enough to contain
+    * all (or most) of the headers
+    */
+   Offset.QuadPart = 0;
+
+   /* FIXME: use FileObject instead of FileHandle */
+   Status = ExeFmtpReadFile (FileHandle,
+                             &Offset,
+                             PAGE_SIZE * 2,
+                             &FileHeader,
+                             &FileHeaderBuffer,
+                             &FileHeaderSize);
+
+   if (!NT_SUCCESS(Status))
+      return Status;
+
+   if (FileHeaderSize == 0)
+   {
+      ExFreePool(FileHeaderBuffer);
+      return STATUS_UNSUCCESSFUL;
+   }
+
+   /*
+    * Look for a loader that can handle this executable
+    */
+   for (i = 0; i < RTL_NUMBER_OF(ExeFmtpLoaders); ++ i)
+   {
+      RtlZeroMemory(ImageSectionObject, sizeof(*ImageSectionObject));
+      Flags = 0;
+
+      /* FIXME: use FileObject instead of FileHandle */
+      Status = ExeFmtpLoaders[i](FileHeader,
+                                 FileHeaderSize,
+                                 FileHandle,
+                                 ImageSectionObject,
+                                 &Flags,
+                                 ExeFmtpReadFile,
+                                 ExeFmtpAllocateSegments);
+
+      if (!NT_SUCCESS(Status))
+      {
+         if (ImageSectionObject->Segments)
+         {
+            ExFreePool(ImageSectionObject->Segments);
+            ImageSectionObject->Segments = NULL;
+         }
+      }
+
+      if (Status != STATUS_ROS_EXEFMT_UNKNOWN_FORMAT)
+         break;
+   }
+
+   ExFreePool(FileHeaderBuffer);
+
+   /*
+    * No loader handled the format
+    */
+   if (Status == STATUS_ROS_EXEFMT_UNKNOWN_FORMAT)
+   {
+      Status = STATUS_INVALID_IMAGE_FORMAT;
+      ASSERT(!NT_SUCCESS(Status));
+   }
+
+   if (!NT_SUCCESS(Status))
+      return Status;
+
+   ASSERT(ImageSectionObject->Segments != NULL);
+
+   /*
+    * Some defaults
+    */
+   /* FIXME? are these values platform-dependent? */
+   if(ImageSectionObject->StackReserve == 0)
+      ImageSectionObject->StackReserve = 0x40000;
+  
+   if(ImageSectionObject->StackCommit == 0)
+      ImageSectionObject->StackCommit = 0x1000;
+  
+   if(ImageSectionObject->ImageBase == 0)
+   {
+      if(ImageSectionObject->ImageCharacteristics & IMAGE_FILE_DLL)
+         ImageSectionObject->ImageBase = 0x10000000;
+      else
+         ImageSectionObject->ImageBase = 0x00400000;
+   }
+
+   /*
+    * And now the fun part: fixing the segments
+    */
+
+   /* Sort them by virtual address */
+   MmspSortSegments(ImageSectionObject, Flags);
+
+   /* Ensure they don't overlap in memory */
+   if (!MmspCheckSegmentBounds(ImageSectionObject, Flags))
+      return STATUS_INVALID_IMAGE_FORMAT;
+
+   /* Ensure they are aligned */
+   OldNrSegments = ImageSectionObject->NrSegments;
+
+   if (!MmspPageAlignSegments(ImageSectionObject, Flags))
+      return STATUS_INVALID_IMAGE_FORMAT;
+
+   /* Trim them if the alignment phase merged some of them */
+   if (ImageSectionObject->NrSegments < OldNrSegments)
+   {
+      PMM_SECTION_SEGMENT Segments;
+      SIZE_T SizeOfSegments;
+
+      SizeOfSegments = sizeof(MM_SECTION_SEGMENT) * ImageSectionObject->NrSegments;
+
+      Segments = ExAllocatePoolWithTag(NonPagedPool,
+                                       SizeOfSegments,
+                                       TAG_MM_SECTION_SEGMENT);
+
+      if (Segments == NULL)
+         return STATUS_INSUFFICIENT_RESOURCES;
+
+      RtlCopyMemory(Segments, ImageSectionObject->Segments, SizeOfSegments);
+      ExFreePool(ImageSectionObject->Segments);
+      ImageSectionObject->Segments = Segments;
+   }
+
+   /* And finish their initialization */
+   for ( i = 0; i < ImageSectionObject->NrSegments; ++ i )
+   {
+      ExInitializeFastMutex(&ImageSectionObject->Segments[i].Lock);
+      ImageSectionObject->Segments[i].ReferenceCount = 1;
+
+      RtlZeroMemory(&ImageSectionObject->Segments[i].PageDirectory,
+                    sizeof(ImageSectionObject->Segments[i].PageDirectory));
+   }
+
+   ASSERT(NT_SUCCESS(Status));
+   return Status;
+}
 
 NTSTATUS
 MmCreateImageSection(PSECTION_OBJECT *SectionObject,
@@ -2519,16 +3148,9 @@
    PSECTION_OBJECT Section;
    NTSTATUS Status;
    PFILE_OBJECT FileObject;
-   IMAGE_DOS_HEADER DosHeader;
-   IO_STATUS_BLOCK Iosb;
-   LARGE_INTEGER Offset;
-   IMAGE_NT_HEADERS PEHeader;
    PMM_SECTION_SEGMENT SectionSegments;
-   ULONG NrSegments;
    PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
    ULONG i;
-   ULONG Size;
-   ULONG Characteristics;
    ULONG FileAccess = 0;
 
    /*
@@ -2540,6 +3162,19 @@
    }
 
    /*
+    * 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,
@@ -2554,6 +3189,32 @@
    }
 
    /*
+    * Create the section
+    */
+   Status = ObCreateObject (ExGetPreviousMode(),
+                            MmSectionObjectType,
+                            ObjectAttributes,
+                            ExGetPreviousMode(),
+                            NULL,
+                            sizeof(SECTION_OBJECT),
+                            0,
+                            0,
+                            (PVOID*)(PVOID)&Section);
+   if (!NT_SUCCESS(Status))
+   {
+      ObDereferenceObject(FileObject);
+      return(Status);
+   }
+
+   /*
+    * Initialize it
+    */
+   Section->SectionPageProtection = SectionPageProtection;
+   Section->AllocationAttributes = AllocationAttributes;
+   InitializeListHead(&Section->ViewListHead);
+   KeInitializeSpinLock(&Section->ViewListLock);
+
+   /*
     * Initialized caching for this file object if previously caching
     * was initialized for the same on disk file
     */
@@ -2561,322 +3222,68 @@
 
    if (!NT_SUCCESS(Status) || FileObject->SectionObjectPointer->ImageSectionObject == NULL)
    {
-      PIMAGE_SECTION_HEADER ImageSections;
-      /*
-       * Read the dos header and check the DOS signature
-       */
-      Offset.QuadPart = 0;
-      Status = ZwReadFile(FileHandle,
-                          NULL,
-                          NULL,
-                          NULL,
-                          &Iosb,
-                          &DosHeader,
-                          sizeof(DosHeader),
-                          &Offset,
-                          NULL);
-      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,
-                          NULL);
-      if (!NT_SUCCESS(Status))
-      {
-         ObDereferenceObject(FileObject);
-         return(Status);
-      }
-
-      /*
-       * Check the signature
-       */
-      if (Iosb.Information != sizeof(PEHeader) ||
-            PEHeader.Signature != IMAGE_NT_SIGNATURE)
-      {
-         ObDereferenceObject(FileObject);
-         return(STATUS_INVALID_IMAGE_FORMAT);
-      }
+      NTSTATUS StatusExeFmt;
 
-      /*
-       * 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)
+      ImageSectionObject = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_IMAGE_SECTION_OBJECT), TAG_MM_SECTION_SEGMENT);
+      if (ImageSectionObject == NULL)
       {
          ObDereferenceObject(FileObject);
+         ObDereferenceObject(Section);
          return(STATUS_NO_MEMORY);
       }
 
-      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);
-      }
+      StatusExeFmt = ExeFmtpCreateImageSection(FileHandle, ImageSectionObject);
 
-      /*
-       * Create the section
-       */
-      Status = ObCreateObject (ExGetPreviousMode(),
-                               MmSectionObjectType,
-                               ObjectAttributes,
-                               ExGetPreviousMode(),
-                               NULL,
-                               sizeof(SECTION_OBJECT),
-                               0,
-                               0,
-                               (PVOID*)(PVOID)&Section);
-      if (!NT_SUCCESS(Status))
+      if (!NT_SUCCESS(StatusExeFmt))
       {
+         if(ImageSectionObject->Segments != NULL)
+            ExFreePool(ImageSectionObject->Segments);
+
+         ExFreePool(ImageSectionObject);
+         ObDereferenceObject(Section);
          ObDereferenceObject(FileObject);
-         ExFreePool(ImageSections);
-         return(Status);
+         return(StatusExeFmt);
       }
 
-      /*
-       * Initialize it
-       */
-      Section->SectionPageProtection = SectionPageProtection;
-      Section->AllocationAttributes = AllocationAttributes;
-      Section->ImageSection = NULL;
-      InitializeListHead(&Section->ViewListHead);
-      KeInitializeSpinLock(&Section->ViewListLock);
-
-      /*
-              * Check file access required
-              */
-      if (SectionPageProtection & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE))
-      {
-         FileAccess = FILE_READ_DATA | FILE_WRITE_DATA;
-      }
-      else
-      {
-         FileAccess = FILE_READ_DATA;
-      }
+      Section->ImageSection = ImageSectionObject;
+      ASSERT(ImageSectionObject->Segments);
 
       /*
        * Lock the file
        */
       Status = MmspWaitForFileLock(FileObject);
-      if (Status != STATUS_SUCCESS)
+      if (!NT_SUCCESS(Status))
       {
+         ExFreePool(ImageSectionObject->Segments);
+         ExFreePool(ImageSectionObject);
          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);
-         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;
[truncated at 1000 lines; 195 more skipped]

reactos/w32api/include/ddk
ntifs.h 1.9 -> 1.10
diff -u -r1.9 -r1.10
--- ntifs.h	23 Dec 2004 12:30:03 -0000	1.9
+++ ntifs.h	30 Dec 2004 08:05:12 -0000	1.10
@@ -1486,19 +1486,19 @@
 } SECTION_BASIC_INFORMATION, *PSECTION_BASIC_INFORMATION;
 
 typedef struct _SECTION_IMAGE_INFORMATION {
-    PVOID   EntryPoint;
-    ULONG   Unknown1;
-    ULONG   StackReserve;
-    ULONG   StackCommit;
-    ULONG   Subsystem;
-    USHORT  MinorSubsystemVersion;
-    USHORT  MajorSubsystemVersion;
-    ULONG   Unknown2;
-    ULONG   Characteristics;
-    USHORT  ImageNumber;
-    BOOLEAN Executable;
-    UCHAR   Unknown3;
-    ULONG   Unknown4[3];
+    ULONG     EntryPoint;
+    ULONG     Unknown1;
+    ULONG_PTR StackReserve;
+    ULONG_PTR StackCommit;
+    ULONG     Subsystem;
+    USHORT    MinorSubsystemVersion;
+    USHORT    MajorSubsystemVersion;
+    ULONG     Unknown2;
+    ULONG     Characteristics;
+    USHORT    ImageNumber;
+    BOOLEAN   Executable;
+    UCHAR     Unknown3;
+    ULONG     Unknown4[3];
 } SECTION_IMAGE_INFORMATION, *PSECTION_IMAGE_INFORMATION;
 
 #if (VER_PRODUCTBUILD >= 2600)
CVSspam 0.2.8