From 6948c64efbd638954ac39dbd59171e9440590bef Mon Sep 17 00:00:00 2001 From: "KJK::Hyperion" Date: Thu, 30 Dec 2004 08:05:12 +0000 Subject: [PATCH] ELF_support, welcome to HEAD! (just in time for the freeze, too!) svn path=/trunk/; revision=12400 --- reactos/include/ddk/ntdef.h | 10 + reactos/include/ntos/zw.h | 4 +- reactos/lib/kernel32/process/create.c | 7 +- reactos/lib/rtl/random.c | 4 +- reactos/ntoskrnl/Makefile | 3 + reactos/ntoskrnl/include/internal/mm.h | 45 +- reactos/ntoskrnl/mm/i386/page.c | 8 +- reactos/ntoskrnl/mm/section.c | 1031 +++++++++++++++++------- reactos/w32api/include/ddk/ntifs.h | 26 +- 9 files changed, 787 insertions(+), 351 deletions(-) diff --git a/reactos/include/ddk/ntdef.h b/reactos/include/ddk/ntdef.h index e56b777a118..f3d2c575347 100644 --- a/reactos/include/ddk/ntdef.h +++ b/reactos/include/ddk/ntdef.h @@ -17,4 +17,14 @@ struct _EPROCESS; #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 diff --git a/reactos/include/ntos/zw.h b/reactos/include/ntos/zw.h index cc5fa0ce0c6..9d75ed7464e 100755 --- a/reactos/include/ntos/zw.h +++ b/reactos/include/ntos/zw.h @@ -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 @@ ZwQuerySection( typedef struct _SECTION_IMAGE_INFORMATION { - PVOID EntryPoint; + ULONG EntryPoint; ULONG Unknown1; ULONG StackReserve; ULONG StackCommit; diff --git a/reactos/lib/kernel32/process/create.c b/reactos/lib/kernel32/process/create.c index 0fdef2dea88..5ad85550ec7 100644 --- a/reactos/lib/kernel32/process/create.c +++ b/reactos/lib/kernel32/process/create.c @@ -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 +#include #define NDEBUG #include "../include/debug.h" @@ -1385,11 +1386,11 @@ CreateProcessW * 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) diff --git a/reactos/lib/rtl/random.c b/reactos/lib/rtl/random.c index a6c70d96586..25193a2e1d9 100644 --- a/reactos/lib/rtl/random.c +++ b/reactos/lib/rtl/random.c @@ -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 -#define MAXLONG (0x7fffffff) - static ULONG SavedValue[128] = { 0x4c8bc0aa, 0x4c022957, 0x2232827a, 0x2f1e7626, /* 0 */ diff --git a/reactos/ntoskrnl/Makefile b/reactos/ntoskrnl/Makefile index 515976d9ebe..37b0a992c6a 100644 --- a/reactos/ntoskrnl/Makefile +++ b/reactos/ntoskrnl/Makefile @@ -144,6 +144,8 @@ OBJECTS_MM = \ 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 @@ OBJECTS_MM = \ mm/pageop.o \ mm/pager.o \ mm/paging.o \ + mm/pe.o \ mm/pool.o \ mm/ppool.o \ mm/physical.o \ diff --git a/reactos/ntoskrnl/include/internal/mm.h b/reactos/ntoskrnl/include/internal/mm.h index fbe8d7d6dd9..ae052e45b96 100644 --- a/reactos/ntoskrnl/include/internal/mm.h +++ b/reactos/ntoskrnl/include/internal/mm.h @@ -71,6 +71,26 @@ typedef ULONG PFN_TYPE, *PPFN_TYPE; 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 @@ typedef struct #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 diff --git a/reactos/ntoskrnl/mm/i386/page.c b/reactos/ntoskrnl/mm/i386/page.c index 7cc2ffd9989..916d576f204 100644 --- a/reactos/ntoskrnl/mm/i386/page.c +++ b/reactos/ntoskrnl/mm/i386/page.c @@ -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 @@ ProtectToPTE(ULONG flProtect) { 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 @@ ProtectToPTE(ULONG flProtect) KEBUGCHECK(0); } if (Ke386NoExecute && - !(flProtect & (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE))) + !(flProtect & PAGE_IS_EXECUTABLE)) { Attributes = Attributes | 0x80000000; } diff --git a/reactos/ntoskrnl/mm/section.c b/reactos/ntoskrnl/mm/section.c index 05148de1701..e635257910d 100644 --- a/reactos/ntoskrnl/mm/section.c +++ b/reactos/ntoskrnl/mm/section.c @@ -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 +#include + /* TYPES *********************************************************************/ typedef struct @@ -156,6 +158,7 @@ MmFreeSectionSegments(PFILE_OBJECT FileObject) } MmFreePageTablesSectionSegment(&SectionSegments[i]); } + ExFreePool(ImageSectionObject->Segments); ExFreePool(ImageSectionObject); FileObject->SectionObjectPointer->ImageSectionObject = NULL; } @@ -2228,7 +2231,6 @@ MmCreatePageFileSection(PSECTION_OBJECT *SectionObject, 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 @@ MmCreateDataFileSection(PSECTION_OBJECT *SectionObject, Segment->FileOffset = 0; Segment->Protection = SectionPageProtection; - Segment->Attributes = 0; Segment->Flags = MM_DATAFILE_SEGMENT; Segment->Characteristics = 0; Segment->WriteCopy = FALSE; @@ -2455,7 +2456,7 @@ MmCreateDataFileSection(PSECTION_OBJECT *SectionObject, 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 @@ MmCreateDataFileSection(PSECTION_OBJECT *SectionObject, 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) { - 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 - }; + 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 ) + { + 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 @@ MmCreateImageSection(PSECTION_OBJECT *SectionObject, 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; /* @@ -2539,6 +3161,19 @@ MmCreateImageSection(PSECTION_OBJECT *SectionObject, return(STATUS_INVALID_PARAMETER_4); } + /* + * 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 */ @@ -2553,6 +3188,32 @@ MmCreateImageSection(PSECTION_OBJECT *SectionObject, return Status; } + /* + * 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,321 +3222,67 @@ MmCreateImageSection(PSECTION_OBJECT *SectionObject, 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); - } + NTSTATUS StatusExeFmt; - /* - * 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); - } - - /* - * 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)) + StatusExeFmt = ExeFmtpCreateImageSection(FileHandle, ImageSectionObject); + + if (!NT_SUCCESS(StatusExeFmt)) { + if(ImageSectionObject->Segments != NULL) + ExFreePool(ImageSectionObject->Segments); + + ExFreePool(ImageSectionObject); + ObDereferenceObject(Section); 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); + return(StatusExeFmt); } - /* - * Create the section - */ - Status = ObCreateObject (ExGetPreviousMode(), - MmSectionObjectType, - ObjectAttributes, - ExGetPreviousMode(), - NULL, - sizeof(SECTION_OBJECT), - 0, - 0, - (PVOID*)(PVOID)&Section); - if (!NT_SUCCESS(Status)) - { - ObDereferenceObject(FileObject); - ExFreePool(ImageSections); - return(Status); - } - - /* - * 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; - SectionSegments[0].WriteCopy = TRUE; - SectionSegments[0].Attributes = 0; - ExInitializeFastMutex(&SectionSegments[0].Lock); - RtlZeroMemory(&SectionSegments[0].PageDirectory, sizeof(SECTION_PAGE_DIRECTORY)); - for (i = 1; i < NrSegments; i++) - { - SectionSegments[i].FileOffset = ImageSections[i-1].PointerToRawData; - SectionSegments[i].Characteristics = ImageSections[i-1].Characteristics; - - /* - * Set up the protection and write copy variables. - */ - Characteristics = ImageSections[i - 1].Characteristics; - if (Characteristics & (IMAGE_SECTION_CHAR_READABLE|IMAGE_SECTION_CHAR_WRITABLE|IMAGE_SECTION_CHAR_EXECUTABLE)) - { - SectionSegments[i].Protection = SectionCharacteristicsToProtect[Characteristics >> 28]; - SectionSegments[i].WriteCopy = !(Characteristics & IMAGE_SECTION_CHAR_SHARED); - } - else if (Characteristics & IMAGE_SECTION_CHAR_CODE) - { - SectionSegments[i].Protection = PAGE_EXECUTE_READ; - SectionSegments[i].WriteCopy = TRUE; - } - else if (Characteristics & IMAGE_SECTION_CHAR_DATA) - { - SectionSegments[i].Protection = PAGE_READWRITE; - SectionSegments[i].WriteCopy = TRUE; - } - else if (Characteristics & IMAGE_SECTION_CHAR_BSS) - { - SectionSegments[i].Protection = PAGE_READWRITE; - SectionSegments[i].WriteCopy = TRUE; - } - else - { - SectionSegments[i].Protection = PAGE_NOACCESS; - SectionSegments[i].WriteCopy = TRUE; - } - - /* - * Set up the attributes. - */ - if (Characteristics & IMAGE_SECTION_CHAR_CODE) - { - SectionSegments[i].Attributes = 0; - } - else if (Characteristics & IMAGE_SECTION_CHAR_DATA) - { - SectionSegments[i].Attributes = 0; - } - else if (Characteristics & IMAGE_SECTION_CHAR_BSS) - { - SectionSegments[i].Attributes = MM_SECTION_SEGMENT_BSS; - } - else - { - SectionSegments[i].Attributes = 0; - } - - SectionSegments[i].RawLength = ImageSections[i-1].SizeOfRawData; - if (ImageSections[i-1].Misc.VirtualSize != 0) - { - SectionSegments[i].Length = ImageSections[i-1].Misc.VirtualSize; - } - else - { - SectionSegments[i].Length = ImageSections[i-1].SizeOfRawData; - } - SectionSegments[i].Flags = 0; - SectionSegments[i].ReferenceCount = 1; - SectionSegments[i].VirtualAddress = (PVOID)ImageSections[i-1].VirtualAddress; - ExInitializeFastMutex(&SectionSegments[i].Lock); - RtlZeroMemory(&SectionSegments[i].PageDirectory, sizeof(SECTION_PAGE_DIRECTORY)); - } if (0 != InterlockedCompareExchangeUL(&FileObject->SectionObjectPointer->ImageSectionObject, ImageSectionObject, 0)) { /* * An other thread has initialized the some image in the background */ + ExFreePool(ImageSectionObject->Segments); ExFreePool(ImageSectionObject); ImageSectionObject = FileObject->SectionObjectPointer->ImageSectionObject; Section->ImageSection = ImageSectionObject; SectionSegments = ImageSectionObject->Segments; - for (i = 0; i < NrSegments; i++) + for (i = 0; i < ImageSectionObject->NrSegments; i++) { InterlockedIncrementUL(&SectionSegments[i].ReferenceCount); } } - ExFreePool(ImageSections); + + Status = StatusExeFmt; } else { - /* - * 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); - - /* - * Check file access required - */ - if (SectionPageProtection & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE)) - { - FileAccess = FILE_READ_DATA | FILE_WRITE_DATA; - } - else - { - FileAccess = FILE_READ_DATA; - } - /* * Lock the file */ @@ -2890,22 +3297,22 @@ MmCreateImageSection(PSECTION_OBJECT *SectionObject, ImageSectionObject = FileObject->SectionObjectPointer->ImageSectionObject; Section->ImageSection = ImageSectionObject; SectionSegments = ImageSectionObject->Segments; - NrSegments = ImageSectionObject->NrSegments; /* * Otherwise just reference all the section segments */ - for (i = 0; i < NrSegments; i++) + for (i = 0; i < ImageSectionObject->NrSegments; i++) { InterlockedIncrementUL(&SectionSegments[i].ReferenceCount); } + Status = STATUS_SUCCESS; } Section->FileObject = FileObject; CcRosReferenceCache(FileObject); KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE); *SectionObject = Section; - return(STATUS_SUCCESS); + return(Status); } /* @@ -3516,7 +3923,7 @@ NtQuerySection(IN HANDLE SectionHandle, } else { - Sbi->BaseAddress = Section->Segment->VirtualAddress; + Sbi->BaseAddress = (PVOID)Section->Segment->VirtualAddress; Sbi->Size.QuadPart = Section->Segment->Length; } @@ -3546,8 +3953,8 @@ NtQuerySection(IN HANDLE SectionHandle, Sii->StackReserve = ImageSectionObject->StackReserve; Sii->StackCommit = ImageSectionObject->StackCommit; Sii->Subsystem = ImageSectionObject->Subsystem; - Sii->MinorSubsystemVersion = (USHORT)ImageSectionObject->MinorSubsystemVersion; - Sii->MajorSubsystemVersion = (USHORT)ImageSectionObject->MajorSubsystemVersion; + Sii->MinorSubsystemVersion = ImageSectionObject->MinorSubsystemVersion; + Sii->MajorSubsystemVersion = ImageSectionObject->MajorSubsystemVersion; Sii->Characteristics = ImageSectionObject->ImageCharacteristics; Sii->ImageNumber = ImageSectionObject->Machine; Sii->Executable = ImageSectionObject->Executable; @@ -3784,7 +4191,7 @@ MmMapViewOfSection(IN PVOID SectionObject, ImageBase = *BaseAddress; if (ImageBase == NULL) { - ImageBase = ImageSectionObject->ImageBase; + ImageBase = (PVOID)ImageSectionObject->ImageBase; } ImageSize = 0; diff --git a/reactos/w32api/include/ddk/ntifs.h b/reactos/w32api/include/ddk/ntifs.h index d1895316701..d6922bcddb2 100644 --- a/reactos/w32api/include/ddk/ntifs.h +++ b/reactos/w32api/include/ddk/ntifs.h @@ -1486,19 +1486,19 @@ typedef struct _SECTION_BASIC_INFORMATION { } 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)