3 modified files
reactos/ntoskrnl/mm/i386
diff -u -r1.77.2.3 -r1.77.2.4
--- page.c 13 Dec 2004 16:18:13 -0000 1.77.2.3
+++ page.c 18 Dec 2004 02:36:08 -0000 1.77.2.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: page.c,v 1.77.2.3 2004/12/13 16:18:13 hyperion Exp $
+/* $Id: page.c,v 1.77.2.4 2004/12/18 02:36:08 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
diff -u -r1.1.2.3 -r1.1.2.4
--- pe.c 13 Dec 2004 05:55:32 -0000 1.1.2.3
+++ pe.c 18 Dec 2004 02:36:09 -0000 1.1.2.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: pe.c,v 1.1.2.3 2004/12/13 05:55:32 hyperion Exp $
+/* $Id: pe.c,v 1.1.2.4 2004/12/18 02:36:09 hyperion Exp $
*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/mm/pe.c
@@ -31,7 +31,7 @@
#include <ntoskrnl.h>
-#define NDEBUG
+/*#define NDEBUG*/
#include <internal/debug.h>
#include <reactos/exeformat.h>
@@ -188,7 +188,7 @@
ULONG FASTCALL GetExcess(IN ULONG Address, IN ULONG Alignment)
{
ASSERT(IsPowerOf2(Alignment));
- return Address & ~(Alignment - 1);
+ return Address & (Alignment - 1);
}
BOOLEAN FASTCALL IsAligned(IN ULONG Address, IN ULONG Alignment)
@@ -203,12 +203,15 @@
IN ULONG Alignment
)
{
- return Intsafe_AddULong32
- (
- AlignedAddress,
- Address,
- Alignment - GetExcess(Address, Alignment)
- );
+ ULONG nExcess = GetExcess(Address, Alignment);
+
+ if(nExcess == 0)
+ {
+ *AlignedAddress = Address;
+ return nExcess == 0;
+ }
+ else
+ return Intsafe_AddULong32(AlignedAddress, Address, Alignment - nExcess);
}
/*
@@ -259,6 +262,8 @@
ASSERT(FileHeaderSize >= sizeof(IMAGE_DOS_HEADER));
ASSERT(((UINT_PTR)FileHeader % TYPE_ALIGNMENT(IMAGE_DOS_HEADER)) == 0);
+#define DIE(ARGS_) { DPRINT ARGS_; goto l_Return; }
+
pBuffer = NULL;
pidhDosHeader = FileHeader;
@@ -267,17 +272,17 @@
/* no MZ signature */
if(pidhDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
- goto l_Return;
+ DIE(("No MZ signature found, e_magic is %hX\n", pidhDosHeader->e_magic));
/* not a Windows executable */
if(pidhDosHeader->e_lfanew <= 0)
- goto l_Return;
+ 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)))
- goto l_Return;
+ DIE(("The DOS stub is too large, e_lfanew is %X\n", pidhDosHeader->e_lfanew));
if(FileHeaderSize < cbFileHeaderOffsetSize)
pinhNtHeader = NULL;
@@ -307,63 +312,58 @@
)
{
SIZE_T cbNtHeaderSize;
- SIZE_T cbReadSize;
+ ULONG cbReadSize;
+ PVOID pData;
l_ReadHeaderFromFile:
-
- nStatus = STATUS_INSUFFICIENT_RESOURCES;
-
- /* allocate the buffer. We use the largest size (IMAGE_NT_HEADERS64) */
- pBuffer = ExAllocatePoolWithTag
- (
- NonPagedPool,
- sizeof(IMAGE_NT_HEADERS64),
- TAG('P', 'e', 'F', 'm')
- );
-
- if(pBuffer == NULL)
- goto l_Return;
-
lnOffset.QuadPart = pidhDosHeader->e_lfanew;
/* read the header from the file */
nStatus = ReadFileCb
(
File,
- pBuffer,
- sizeof(IMAGE_NT_HEADERS64),
&lnOffset,
+ sizeof(IMAGE_NT_HEADERS64),
+ &pData,
+ &pBuffer,
&cbReadSize
);
if(!NT_SUCCESS(nStatus))
- goto l_Return;
-
- nStatus = STATUS_UNSUCCESSFUL;
+ DIE(("ReadFile failed, status %08X\n", nStatus));
- if(cbReadSize == 0)
- goto l_Return;
+ ASSERT(pData);
+ ASSERT(pBuffer);
+ ASSERT(cbReadSize > 0);
nStatus = STATUS_INVALID_IMAGE_FORMAT;
/* the buffer doesn't contain the file header */
if(cbReadSize < RTL_SIZEOF_THROUGH_FIELD(IMAGE_NT_HEADERS32, FileHeader))
- goto l_Return;
+ DIE(("The file doesn't contain the PE file header"));
+
+ pinhNtHeader = pData;
- pinhNtHeader = pBuffer;
+ /* object still not aligned: copy it to the beginning of the buffer */
+ if((UINT_PTR)pinhNtHeader % TYPE_ALIGNMENT(IMAGE_SECTION_HEADER) != 0)
+ {
+ ASSERT((UINT_PTR)pBuffer % TYPE_ALIGNMENT(IMAGE_SECTION_HEADER) == 0);
+ RtlMoveMemory(pBuffer, pData, cbReadSize);
+ pinhNtHeader = pBuffer;
+ }
/* invalid NT header */
if(pinhNtHeader->Signature != IMAGE_NT_SIGNATURE)
- goto l_Return;
+ DIE(("The file isn't a PE executable, Signature is %X\n", pinhNtHeader->Signature));
if(!Intsafe_AddULong32(&cbNtHeaderSize, pinhNtHeader->FileHeader.SizeOfOptionalHeader, FIELD_OFFSET(IMAGE_NT_HEADERS32, OptionalHeader)))
- goto l_Return;
+ DIE(("The full NT header is too large\n"));
nStatus = STATUS_UNSUCCESSFUL;
/* the buffer doesn't contain the whole NT header */
if(cbReadSize < cbNtHeaderSize)
- goto l_Return;
+ DIE(("The file doesn't contain the full NT header\n"));
}
else
{
@@ -373,13 +373,13 @@
/* don't trust an invalid NT header */
if(pinhNtHeader->Signature != IMAGE_NT_SIGNATURE)
- goto l_Return;
+ DIE(("The file isn't a PE executable, Signature is %X\n", pinhNtHeader->Signature));
if(!Intsafe_AddULong32(&cbOptHeaderOffsetSize, pidhDosHeader->e_lfanew, FIELD_OFFSET(IMAGE_NT_HEADERS32, OptionalHeader)))
- goto l_Return;
+ DIE(("The DOS stub is too large, e_lfanew is %X\n", pidhDosHeader->e_lfanew));
if(!Intsafe_AddULong32(&cbOptHeaderOffsetSize, cbOptHeaderOffsetSize, pinhNtHeader->FileHeader.SizeOfOptionalHeader))
- goto l_Return;
+ DIE(("The NT header is too large, SizeOfOptionalHeader is %X\n", pinhNtHeader->FileHeader.SizeOfOptionalHeader));
/* the buffer doesn't contain the whole NT header: read it from the file */
if(cbOptHeaderOffsetSize > FileHeaderSize)
@@ -393,7 +393,7 @@
nStatus = STATUS_INVALID_IMAGE_FORMAT;
if(!RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, Magic))
- goto l_Return;
+ DIE(("The optional header doesn't contain the Magic field, SizeOfOptionalHeader is %X\n", cbOptHeaderSize));
/* ASSUME: RtlZeroMemory(ImageSectionObject, sizeof(*ImageSectionObject)); */
@@ -404,7 +404,7 @@
break;
default:
- goto l_Return;
+ DIE(("Unrecognized optional header, Magic is %X\n", piohOptHeader->Magic));
}
if
@@ -417,16 +417,16 @@
if(piohOptHeader->SectionAlignment < PAGE_SIZE)
{
if(piohOptHeader->FileAlignment != piohOptHeader->SectionAlignment)
- goto l_Return;
+ DIE(("Sections aren't page-aligned and the file alignment isn't the same\n"));
}
else if(piohOptHeader->SectionAlignment < piohOptHeader->FileAlignment)
- goto l_Return;
+ DIE(("The section alignment is smaller than the file alignment\n"));
nSectionAlignment = piohOptHeader->SectionAlignment;
nFileAlignment = piohOptHeader->FileAlignment;
if(!IsPowerOf2(nSectionAlignment) || !IsPowerOf2(nFileAlignment))
- goto l_Return;
+ DIE(("The section alignment (%u) and file alignment (%u) aren't both powers of 2\n", nSectionAlignment, nFileAlignment));
}
else
{
@@ -442,9 +442,6 @@
/* PE32 */
case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
{
- if(cbOptHeaderSize > sizeof(IMAGE_OPTIONAL_HEADER32))
- goto l_Return;
-
if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, ImageBase))
ImageSectionObject->ImageBase = piohOptHeader->ImageBase;
@@ -462,15 +459,12 @@
{
PIMAGE_OPTIONAL_HEADER64 pioh64OptHeader;
- if(cbOptHeaderSize > sizeof(IMAGE_OPTIONAL_HEADER64))
- goto l_Return;
-
pioh64OptHeader = (PIMAGE_OPTIONAL_HEADER64)piohOptHeader;
if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, ImageBase))
{
if(pioh64OptHeader->ImageBase > MAXULONG_PTR)
- goto l_Return;
+ DIE(("ImageBase exceeds the address space\n"));
ImageSectionObject->ImageBase = pioh64OptHeader->ImageBase;
}
@@ -478,7 +472,7 @@
if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfStackReserve))
{
if(pioh64OptHeader->SizeOfStackReserve > MAXULONG_PTR)
- goto l_Return;
+ DIE(("SizeOfStackReserve exceeds the address space\n"));
ImageSectionObject->StackReserve = pioh64OptHeader->SizeOfStackReserve;
}
@@ -486,7 +480,7 @@
if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfStackCommit))
{
if(pioh64OptHeader->SizeOfStackCommit > MAXULONG_PTR)
- goto l_Return;
+ DIE(("SizeOfStackCommit exceeds the address space\n"));
ImageSectionObject->StackCommit = pioh64OptHeader->SizeOfStackCommit;
}
@@ -495,26 +489,9 @@
}
}
-#if 0
- /* some defaults */
- if(ImageSectionObject->StackReserve == 0)
- ImageSectionObject->StackReserve = 0x40000;
-
- if(ImageSectionObject->StackCommit == 0)
- ImageSectionObject->StackCommit = 0x1000;
-
- if(ImageSectionObject->ImageBase == NULL)
- {
- if(pinhNtHeader->FileHeader.Characteristics & IMAGE_FILE_DLL)
- ImageSectionObject->ImageBase = (PVOID)0x10000000;
- else
- ImageSectionObject->ImageBase = (PVOID)0x00400000;
- }
-#endif
-
/* [1], section 3.4.2 */
if((ULONG_PTR)ImageSectionObject->ImageBase % 0x10000)
- goto l_Return;
+ DIE(("ImageBase is not aligned on a 64KB boundary"));
/*
ASSUME: all the fields used here have the same offset and size in both
@@ -551,7 +528,7 @@
/* see [1], section 3.3 */
if(pinhNtHeader->FileHeader.NumberOfSections > 96)
- goto l_Return;
+ DIE(("Too many sections, NumberOfSections is %u\n", pinhNtHeader->FileHeader.NumberOfSections));
/*
the additional segment is for the file's headers. They need to be present for
@@ -562,31 +539,31 @@
/* file offset for the section headers */
if(!Intsafe_AddULong32(&cbSectionHeadersOffset, pidhDosHeader->e_lfanew, FIELD_OFFSET(IMAGE_NT_HEADERS32, OptionalHeader)))
- goto l_Return;
+ DIE(("Offset overflow\n"));
if(!Intsafe_AddULong32(&cbSectionHeadersOffset, cbSectionHeadersOffset, pinhNtHeader->FileHeader.SizeOfOptionalHeader))
- goto l_Return;
+ DIE(("Offset overflow\n"));
/* size of the section headers */
ASSERT(Intsafe_CanMulULong32(pinhNtHeader->FileHeader.NumberOfSections, sizeof(IMAGE_SECTION_HEADER)));
cbSectionHeadersSize = pinhNtHeader->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
if(!Intsafe_AddULong32(&cbSectionHeadersOffsetSize, cbSectionHeadersOffset, cbSectionHeadersSize))
- goto l_Return;
+ DIE(("Section headers too large\n"));
/* size of the executable's headers */
if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfHeaders))
{
if(!IsAligned(piohOptHeader->SizeOfHeaders, nFileAlignment))
- goto l_Return;
+ DIE(("SizeOfHeaders is not aligned\n"));
if(cbSectionHeadersSize > piohOptHeader->SizeOfHeaders)
- goto l_Return;
+ DIE(("The section headers overflow SizeOfHeaders\n"));
cbHeadersSize = piohOptHeader->SizeOfHeaders;
}
else if(!AlignUp(&cbHeadersSize, cbSectionHeadersOffsetSize, nFileAlignment))
- goto l_Return;
+ DIE(("Overflow aligning the size of headers\n"));
if(pBuffer)
{
@@ -619,20 +596,8 @@
(UINT_PTR)pishSectionHeaders % TYPE_ALIGNMENT(IMAGE_SECTION_HEADER) != 0
)
{
- SIZE_T cbReadSize;
-
- nStatus = STATUS_INSUFFICIENT_RESOURCES;
-
- /* allocate the buffer */
- pBuffer = ExAllocatePoolWithTag
- (
- NonPagedPool,
- cbSectionHeadersSize,
- TAG('P', 'e', 'F', 'm')
- );
-
- if(pBuffer == NULL)
- goto l_Return;
+ PVOID pData;
+ ULONG cbReadSize;
lnOffset.QuadPart = cbSectionHeadersOffset;
@@ -640,20 +605,35 @@
nStatus = ReadFileCb
(
File,
- pBuffer,
- cbSectionHeadersSize,
&lnOffset,
+ cbSectionHeadersSize,
+ &pData,
+ &pBuffer,
&cbReadSize
);
if(!NT_SUCCESS(nStatus))
- goto l_Return;
+ DIE(("ReadFile failed with status %08X\n", nStatus));
- nStatus = STATUS_UNSUCCESSFUL;
+ ASSERT(pData);
+ ASSERT(pBuffer);
+ ASSERT(cbReadSize > 0);
+
+ nStatus = STATUS_INVALID_IMAGE_FORMAT;
/* the buffer doesn't contain all the section headers */
if(cbReadSize < cbSectionHeadersSize)
- goto l_Return;
+ DIE(("The file doesn't contain all of the section headers\n"));
+
+ pishSectionHeaders = pData;
+
+ /* object still not aligned: copy it to the beginning of the buffer */
+ if((UINT_PTR)pishSectionHeaders % TYPE_ALIGNMENT(IMAGE_SECTION_HEADER) != 0)
+ {
+ ASSERT((UINT_PTR)pBuffer % TYPE_ALIGNMENT(IMAGE_SECTION_HEADER) == 0);
+ RtlMoveMemory(pBuffer, pData, cbReadSize);
+ pishSectionHeaders = pBuffer;
+ }
}
/* SEGMENTS */
@@ -662,15 +642,18 @@
ImageSectionObject->Segments = AllocateSegmentsCb(ImageSectionObject->NrSegments);
if(ImageSectionObject->Segments == NULL)
- goto l_Return;
+ DIE(("AllocateSegments failed\n"));
/* initialize the headers segment */
pssSegments = ImageSectionObject->Segments;
ASSERT(IsAligned(cbHeadersSize, nFileAlignment));
+ if(!AlignUp(&nPrevFileEndOfSegment, cbHeadersSize, nFileAlignment))
+ DIE(("Cannot align the size of the section headers\n"));
+
if(!AlignUp(&nPrevVirtualEndOfSegment, cbHeadersSize, nSectionAlignment))
- goto l_Return;
+ DIE(("Cannot align the size of the section headers\n"));
pssSegments[0].FileOffset = 0;
pssSegments[0].Protection = PAGE_READONLY;
@@ -690,27 +673,36 @@
ULONG nCharacteristics;
/* validate the alignment */
- if(!IsAligned(pishSectionHeaders[i].SizeOfRawData, nFileAlignment))
- goto l_Return;
-
- if(!IsAligned(pishSectionHeaders[i].PointerToRawData, nFileAlignment))
- goto l_Return;
-
- if(!IsAligned(pishSectionHeaders[i].Misc.VirtualSize, nSectionAlignment))
- goto l_Return;
-
if(!IsAligned(pishSectionHeaders[i].VirtualAddress, nSectionAlignment))
- goto l_Return;
+ DIE(("VirtualAddress[%u] is not aligned\n", i));
/* sections must be contiguous, ordered by base address and non-overlapping */
- if(pishSectionHeaders[i].PointerToRawData != nPrevFileEndOfSegment)
- goto l_Return;
-
if(pishSectionHeaders[i].VirtualAddress != nPrevVirtualEndOfSegment)
- goto l_Return;
+ DIE(("Memory gap between section %u and the previous\n", i));
- /* conversion */
- pssSegments[i].FileOffset = pishSectionHeaders[i].PointerToRawData;
+ /* ignore explicit BSS sections */
+ if(pishSectionHeaders[i].SizeOfRawData != 0)
+ {
+ /* validate the alignment */
+ if(!IsAligned(pishSectionHeaders[i].SizeOfRawData, nFileAlignment))
+ DIE(("SizeOfRawData[%u] is not aligned\n", i));
+
+ if(!IsAligned(pishSectionHeaders[i].PointerToRawData, nFileAlignment))
+ DIE(("PointerToRawData[%u] is not aligned\n", i));
+
+ /* sections must be contiguous, ordered by base address and non-overlapping */
+ if(pishSectionHeaders[i].PointerToRawData != nPrevFileEndOfSegment)
+ DIE(("File gap between section %u and the previous\n", i));
+
+ /* conversion */
+ pssSegments[i].FileOffset = pishSectionHeaders[i].PointerToRawData;
+ pssSegments[i].RawLength = pishSectionHeaders[i].SizeOfRawData;
+ }
+ else
+ {
+ ASSERT(pssSegments[i].FileOffset == 0);
+ ASSERT(pssSegments[i].RawLength == 0);
+ }
nCharacteristics = pishSectionHeaders[i].Characteristics;
@@ -730,12 +722,16 @@
/* see table above */
pssSegments[i].Protection = SectionCharacteristicsToProtect[nCharacteristics >> 28];
- pssSegments[i].RawLength = pishSectionHeaders[i].SizeOfRawData;
-
- if(pishSectionHeaders[i].Misc.VirtualSize != 0)
- pssSegments[i].Length = pishSectionHeaders[i].Misc.VirtualSize;
- else
+ if(pishSectionHeaders[i].Misc.VirtualSize == 0 || pishSectionHeaders[i].Misc.VirtualSize < pishSectionHeaders[i].SizeOfRawData)
pssSegments[i].Length = pishSectionHeaders[i].SizeOfRawData;
+ else
+ pssSegments[i].Length = pishSectionHeaders[i].Misc.VirtualSize;
+
+ if(!AlignUp(&pssSegments[i].Length, pssSegments[i].Length, nSectionAlignment))
+ DIE(("Cannot align the virtual size of section %u\n", i));
+
+ if(pssSegments[i].Length == 0)
+ DIE(("Virtual size of section %u is null\n", i));
/* ExInitializeFastMutex(&pssSegments[i].Lock); */
/* pssSegments[i].ReferenceCount = 1; */
@@ -743,12 +739,21 @@
pssSegments[i].VirtualAddress = pishSectionHeaders[i].VirtualAddress;
pssSegments[i].Characteristics = pishSectionHeaders[i].Characteristics;
- /* ensure the image is no larger than 4GB */
- if(!Intsafe_AddULong32(&nPrevFileEndOfSegment, pssSegments[i].FileOffset, pssSegments[i].RawLength))
- goto l_Return;
+ /* ensure the executable is no larger than 4GB */
+ if(pssSegments[i].RawLength != 0)
+ {
+ if(!Intsafe_AddULong32(&nPrevFileEndOfSegment, pssSegments[i].FileOffset, pssSegments[i].RawLength))
+ DIE(("The executable is larger than 4GB\n"));
+ }
+ /* ensure the memory image is no larger than 4GB */
if(!Intsafe_AddULong32(&nPrevVirtualEndOfSegment, pssSegments[i].VirtualAddress, pssSegments[i].Length))
- goto l_Return;
+ DIE(("The image is larger than 4GB\n"));
+
+ DPRINT("FileOffset [%u] = %lX\n", i, (ULONG)pssSegments[i].FileOffset);
+ DPRINT("RawLength [%u] = %lX\n", i, pssSegments[i].RawLength);
+ DPRINT("VirtualAddress[%u] = %lX\n", i, pssSegments[i].VirtualAddress);
+ DPRINT("Length [%u] = %lX\n", i, pssSegments[i].Length);
}
/* spare our caller some work in validating the segments */
reactos/ntoskrnl/mm
diff -u -r1.166.2.3 -r1.166.2.4
--- section.c 13 Dec 2004 05:55:32 -0000 1.166.2.3
+++ section.c 18 Dec 2004 02:36:09 -0000 1.166.2.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: section.c,v 1.166.2.3 2004/12/13 05:55:32 hyperion Exp $
+/* $Id: section.c,v 1.166.2.4 2004/12/18 02:36:09 hyperion Exp $
*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/mm/section.c
@@ -137,15 +137,19 @@
{
NTSTATUS Status;
KEVENT Event;
- MDL Mdl;
+ PMDL Mdl;
IO_STATUS_BLOCK Iosb;
+ Mdl = IoAllocateMdl(Buffer, BufferSize, FALSE, FALSE, NULL);
+
+ if(Mdl == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ MmBuildMdlForNonPagedPool(Mdl);
KeInitializeEvent(&Event, NotificationEvent, FALSE);
- MmInitializeMdl(&Mdl, Buffer, BufferSize);
- MmBuildMdlForNonPagedPool(&Mdl);
Status = IoPageRead(FileObject,
- &Mdl,
+ Mdl,
Offset,
&Event,
&Iosb);
@@ -157,6 +161,65 @@
return Iosb.Status;
}
+extern
+NTSTATUS
+NTAPI
+IopReadFile(IN PFILE_OBJECT FileObject,
+ IN KPROCESSOR_MODE AccessMode,
+ IN PKEVENT EventObject OPTIONAL,
+ IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+ IN PVOID ApcContext OPTIONAL,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ OUT PVOID Buffer,
+ IN ULONG Length,
+ IN PLARGE_INTEGER ByteOffset OPTIONAL,
+ IN PULONG Key OPTIONAL);
+
+/*
+ * This is, basically, a hack. We "touch" the file with an 1-byte read so
+ * caching is enabled for the file. This is wrong, wrong, WRONG: it moves the
+ * file pointer (and I'm NOT hiding the bug by moving it back), it's subject to
+ * whatever mode the file was opened in (synchronous vs asynchronous, cached vs
+ * non-cached, etc.) and in real Windows this is never necessary, but we get
+ * caching and memory mapping TOTALLY WRONG and BACKWARDS, with Mm calling Cc
+ * instead of the other way around. But it isn't "more wrong" than the previous
+ * implementation, so I'm leaving it this way. You're in for one hell of a ride,
+ * should this break something and should you need to fix it...
+ * [KJK::Hyperion - 2004-12-17]
+ */
+static
+NTSTATUS
+NTAPI
+MmspInitializeFileCache(IN PFILE_OBJECT FileObject)
+{
+ /*
+ * FIXME HACK HACK HORRIBLE HACK PLEASE LET ME DIE:
+ * Since the function can return too soon in case the file was opened for
+ * asyncronous I/O (this is the same behavior as before, when ZwReadFile was
+ * used), we at least limit the damage and pass static buffers. PLEASE, if
+ * you come across this comment, FIX THIS, because it means I still haven't.
+ * IopReadFile itself is a HACK, in kernel mode we should use completion
+ * routines, because any other notification mechanism is tailored towards
+ * consumption from user mode (e.g. EventObject can't be a bare KEVENT)
+ */
+ static UCHAR Buffer[1];
+ static IO_STATUS_BLOCK Iosb;
+ static LARGE_INTEGER FileOffset;
+
+ FileOffset.QuadPart = 0;
+
+ return IopReadFile(FileObject,
+ KernelMode,
+ NULL,
+ NULL,
+ NULL,
+ &Iosb,
+ Buffer,
+ 1,
+ &FileOffset,
+ NULL);
+}
+
VOID
MmFreePageTablesSectionSegment(PMM_SECTION_SEGMENT Segment)
{
@@ -176,14 +239,14 @@
VOID
MmFreeSectionSegments(PFILE_OBJECT FileObject)
{
- if (FileObject->SectionObjectPointer->ImageSectionObject != NULL)
+ if(FileObject->SectionObjectPointer == (PVOID)0xCCCCCCCC) KEBUGCHECK(0);if (FileObject->SectionObjectPointer->ImageSectionObject != NULL)
{
PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
PMM_SECTION_SEGMENT SectionSegments;
ULONG NrSegments;
ULONG i;
- ImageSectionObject = (PMM_IMAGE_SECTION_OBJECT)FileObject->SectionObjectPointer->ImageSectionObject;
+ if(FileObject->SectionObjectPointer == (PVOID)0xCCCCCCCC) KEBUGCHECK(0);ImageSectionObject = (PMM_IMAGE_SECTION_OBJECT)FileObject->SectionObjectPointer->ImageSectionObject;
NrSegments = ImageSectionObject->NrSegments;
SectionSegments = ImageSectionObject->Segments;
for (i = 0; i < NrSegments; i++)
@@ -198,13 +261,13 @@
}
ExFreePool(ImageSectionObject->Segments);
ExFreePool(ImageSectionObject);
- FileObject->SectionObjectPointer->ImageSectionObject = NULL;
+ if(FileObject->SectionObjectPointer == (PVOID)0xCCCCCCCC) KEBUGCHECK(0);FileObject->SectionObjectPointer->ImageSectionObject = NULL;
}
- if (FileObject->SectionObjectPointer->DataSectionObject != NULL)
+ if(FileObject->SectionObjectPointer == (PVOID)0xCCCCCCCC) KEBUGCHECK(0);if (FileObject->SectionObjectPointer->DataSectionObject != NULL)
{
PMM_SECTION_SEGMENT Segment;
- Segment = (PMM_SECTION_SEGMENT)FileObject->SectionObjectPointer->
+ if(FileObject->SectionObjectPointer == (PVOID)0xCCCCCCCC) KEBUGCHECK(0);Segment = (PMM_SECTION_SEGMENT)FileObject->SectionObjectPointer->
DataSectionObject;
if (Segment->ReferenceCount != 0)
@@ -214,7 +277,7 @@
}
MmFreePageTablesSectionSegment(Segment);
ExFreePool(Segment);
- FileObject->SectionObjectPointer->DataSectionObject = NULL;
+ if(FileObject->SectionObjectPointer == (PVOID)0xCCCCCCCC) KEBUGCHECK(0);FileObject->SectionObjectPointer->DataSectionObject = NULL;
}
}
@@ -374,7 +437,7 @@
(Offset + PAGE_SIZE <= Segment->RawLength || !IsImageSection))
{
NTSTATUS Status;
- Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
+ if(FileObject->SectionObjectPointer == (PVOID)0xCCCCCCCC) KEBUGCHECK(0);Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
IsDirectMapped = TRUE;
Status = CcRosUnmapCacheSegment(Bcb, FileOffset, Dirty);
if (!NT_SUCCESS(Status))
@@ -494,7 +557,7 @@
ULONG Length;
FileObject = MemoryArea->Data.SectionData.Section->FileObject;
- Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
+ if(FileObject->SectionObjectPointer == (PVOID)0xCCCCCCCC) KEBUGCHECK(0);Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
RawLength = MemoryArea->Data.SectionData.Segment->RawLength;
FileOffset = SegOffset + MemoryArea->Data.SectionData.Segment->FileOffset;
IsImageSection = MemoryArea->Data.SectionData.Section->AllocationAttributes & SEC_IMAGE ? TRUE : FALSE;
@@ -1399,7 +1462,7 @@
if (FileObject != NULL &&
!(Context.Segment->Characteristics & IMAGE_SECTION_CHAR_SHARED))
{
- Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
+ if(FileObject->SectionObjectPointer == (PVOID)0xCCCCCCCC) KEBUGCHECK(0);Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
/*
* If the file system is letting us go directly to the cache and the
@@ -1743,7 +1806,7 @@
if (FileObject != NULL &&
!(Segment->Characteristics & IMAGE_SECTION_CHAR_SHARED))
{
- Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
+ if(FileObject->SectionObjectPointer == (PVOID)0xCCCCCCCC) KEBUGCHECK(0);Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
/*
* If the file system is letting us go directly to the cache and the
@@ -2059,22 +2122,26 @@
return;
SectionSegments = Section->ImageSection->Segments;
- NrSegments = Section->ImageSection->NrSegments;
-
- for (i = 0; i < NrSegments; i++)
+
+ if (SectionSegments)
{
- if (SectionSegments[i].Characteristics & IMAGE_SECTION_CHAR_SHARED)
- {
- MmLockSectionSegment(&SectionSegments[i]);
- }
- RefCount = InterlockedDecrement(&SectionSegments[i].ReferenceCount);
- if (SectionSegments[i].Characteristics & IMAGE_SECTION_CHAR_SHARED)
+ NrSegments = Section->ImageSection->NrSegments;
+
+ for (i = 0; i < NrSegments; i++)
{
- if (RefCount == 0)
+ if (SectionSegments[i].Characteristics & IMAGE_SECTION_CHAR_SHARED)
{
- MmpFreePageFileSegment(&SectionSegments[i]);
+ MmLockSectionSegment(&SectionSegments[i]);
+ }
+ RefCount = InterlockedDecrement(&SectionSegments[i].ReferenceCount);
+ if (SectionSegments[i].Characteristics & IMAGE_SECTION_CHAR_SHARED)
+ {
+ if (RefCount == 0)
+ {
+ MmpFreePageFileSegment(&SectionSegments[i]);
+ }
+ MmUnlockSectionSegment(&SectionSegments[i]);
}
- MmUnlockSectionSegment(&SectionSegments[i]);
}
}
}
@@ -2410,7 +2477,7 @@
}
}
- if (FileObject->SectionObjectPointer == NULL ||
+ if(FileObject->SectionObjectPointer == (PVOID)0xCCCCCCCC) KEBUGCHECK(0);if (FileObject->SectionObjectPointer == NULL ||
FileObject->SectionObjectPointer->SharedCacheMap == NULL)
{
/*
@@ -2434,7 +2501,7 @@
ObDereferenceObject(FileObject);
return(Status);
}
- if (FileObject->SectionObjectPointer == NULL ||
+ if(FileObject->SectionObjectPointer == (PVOID)0xCCCCCCCC) KEBUGCHECK(0);if (FileObject->SectionObjectPointer == NULL ||
FileObject->SectionObjectPointer->SharedCacheMap == NULL)
{
/* FIXME: handle this situation */
@@ -2459,7 +2526,7 @@
* If this file hasn't been mapped as a data file before then allocate a
* section segment to describe the data file mapping
*/
- if (FileObject->SectionObjectPointer->DataSectionObject == NULL)
+ if(FileObject->SectionObjectPointer == (PVOID)0xCCCCCCCC) KEBUGCHECK(0);if (FileObject->SectionObjectPointer->DataSectionObject == NULL)
{
Segment = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_SECTION_SEGMENT),
TAG_MM_SECTION_SEGMENT);
@@ -2477,7 +2544,7 @@
* Set the lock before assigning the segment to the file object
*/
ExAcquireFastMutex(&Segment->Lock);
- FileObject->SectionObjectPointer->DataSectionObject = (PVOID)Segment;
+ if(FileObject->SectionObjectPointer == (PVOID)0xCCCCCCCC) KEBUGCHECK(0);FileObject->SectionObjectPointer->DataSectionObject = (PVOID)Segment;
Segment->FileOffset = 0;
Segment->Protection = SectionPageProtection;
@@ -2501,7 +2568,7 @@
* If the file is already mapped as a data file then we may need
* to extend it
*/
- Segment =
+ if(FileObject->SectionObjectPointer == (PVOID)0xCCCCCCCC) KEBUGCHECK(0);Segment =
(PMM_SECTION_SEGMENT)FileObject->SectionObjectPointer->
DataSectionObject;
Section->Segment = Segment;
@@ -2549,11 +2616,437 @@
PeFmtCreateSection
};
-static PMM_SECTION_SEGMENT NTAPI MmspAllocateSegments(IN ULONG NrSegments)
+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 PFILE_OBJECT FileObject,
+ 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;
+
+ Status = MmspPageRead(FileObject,
+ Buffer,
+ BufferSize,
+ &FileOffset,
+ &UsedSize);
+
+ if(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
+)
{
- return ExAllocatePoolWithTag(NonPagedPool,
- sizeof(MM_SECTION_SEGMENT) * NrSegments,
- TAG_MM_SECTION_SEGMENT);
+ 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
@@ -2597,9 +3090,9 @@
*/
Section->SectionPageProtection = SectionPageProtection;
Section->AllocationAttributes = AllocationAttributes;
+ Section->ImageSection = NULL;
InitializeListHead(&Section->ViewListHead);
KeInitializeSpinLock(&Section->ViewListLock);
- Section->FileObject = FileObject;
/*
* Initialized caching for this file object if previously caching
@@ -2607,12 +3100,21 @@
*/
Status = CcTryToInitializeFileCache(FileObject);
- if (!NT_SUCCESS(Status) || FileObject->SectionObjectPointer->ImageSectionObject == NULL)
+ if(FileObject->SectionObjectPointer == (PVOID)0xCCCCCCCC) KEBUGCHECK(0);if (!NT_SUCCESS(Status) || FileObject->SectionObjectPointer->ImageSectionObject == NULL)
{
LARGE_INTEGER Offset;
PVOID FileHeader;
ULONG FileHeaderSize;
ULONG Flags;
+ ULONG OldNrSegments;
+ NTSTATUS StatusExeFmt;
+
+ Status = MmspInitializeFileCache(FileObject);
+
+ if (!NT_SUCCESS(Status))
+ {
+ goto l_DereferenceSection;
+ }
/*
* Allocate the image section object
@@ -2675,43 +3177,100 @@
{
ImageSectionObject->Segments = NULL;
- Status = ExeFmtpLoaders[i](FileHeader,
- FileHeaderSize,
- FileObject,
- ImageSectionObject,
- &Flags,
- MmspPageRead,
- MmspAllocateSegments);
+ StatusExeFmt = ExeFmtpLoaders[i](FileHeader,
+ FileHeaderSize,
+ FileObject,
+ ImageSectionObject,
+ &Flags,
+ ExeFmtpReadFile,
+ ExeFmtpAllocateSegments);
- if (!NT_SUCCESS(Status))
+ if (!NT_SUCCESS(StatusExeFmt))
{
if (ImageSectionObject->Segments)
+ {
ExFreePool(ImageSectionObject->Segments);
+ ImageSectionObject->Segments = NULL;
+ }
}
- if (Status != STATUS_ROS_EXEFMT_UNKNOWN_FORMAT)
+ if (StatusExeFmt != STATUS_ROS_EXEFMT_UNKNOWN_FORMAT)
break;
}
/*
* No loader handled the format
*/
- if (Status == STATUS_ROS_EXEFMT_UNKNOWN_FORMAT)
+ if (StatusExeFmt == STATUS_ROS_EXEFMT_UNKNOWN_FORMAT)
+ {
Status = STATUS_INVALID_IMAGE_FORMAT;
+ ASSERT(!NT_SUCCESS(Status));
+ }
+ else
+ {
+ Status = StatusExeFmt;
+ }
ExFreePool(FileHeader);
if (!NT_SUCCESS(Status))
+ {
goto l_UnlockFile;
+ }
/*
* And now the fun part: fixing the segments
*/
- if (!(Flags & EXEFMT_LOAD_ASSUME_SEGMENTS_OK))
+
+ /* Sort them by virtual address */
+ MmspSortSegments(ImageSectionObject, Flags);
+
+ Status = STATUS_INVALID_IMAGE_FORMAT;
+
+ /* Ensure they don't overlap in memory */
+ if (!MmspCheckSegmentBounds(ImageSectionObject, Flags))
+ {
+ goto l_UnlockFile;
+ }
+
+ /* Ensure they are aligned */
+ OldNrSegments = ImageSectionObject->NrSegments;
+
+ if (!MmspPageAlignSegments(ImageSectionObject, Flags))
+ {
+ goto l_UnlockFile;
+ }
+
+ /* 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;
+
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+
+ Segments = ExAllocatePoolWithTag(NonPagedPool,
+ SizeOfSegments,
+ TAG_MM_SECTION_SEGMENT);
+
+ if (Segments == NULL)
+ goto l_UnlockFile;
+
+ 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;
}
- if (0 != InterlockedCompareExchange((PLONG)&FileObject->SectionObjectPointer->ImageSectionObject,
+ if(FileObject->SectionObjectPointer == (PVOID)0xCCCCCCCC) KEBUGCHECK(0);if (0 != InterlockedCompareExchange((PLONG)&FileObject->SectionObjectPointer->ImageSectionObject,
(LONG)ImageSectionObject, 0))
{
/*
@@ -2719,7 +3278,7 @@
*/
ExFreePool(ImageSectionObject->Segments);
ExFreePool(ImageSectionObject);
- ImageSectionObject = FileObject->SectionObjectPointer->ImageSectionObject;
+ if(FileObject->SectionObjectPointer == (PVOID)0xCCCCCCCC) KEBUGCHECK(0);ImageSectionObject = FileObject->SectionObjectPointer->ImageSectionObject;
Section->ImageSection = ImageSectionObject;
for (i = 0; i < ImageSectionObject->NrSegments; i++)
@@ -2728,12 +3287,24 @@
}
}
+ ASSERT(NT_SUCCESS(StatusExeFmt));
+ Status = StatusExeFmt;
goto l_Success;
-l_UnlockFile: MmspReleaseFileLock(FileObject);
-l_FreeImageSection: ExFreePool(ImageSectionObject);
-l_DereferenceSection: ObDereferenceObject(Section);
- return Status;
+l_UnlockFile:
+ MmspReleaseFileLock(FileObject);
+
+l_FreeImageSection:
+ if (ImageSectionObject->Segments)
+ ExFreePool(ImageSectionObject->Segments);
+
+ ExFreePool(ImageSectionObject);
+ Section->ImageSection = NULL;
+
+l_DereferenceSection:
+ ObDereferenceObject(Section);
+
+ return Status;
l_Success:
(void)0;
@@ -2750,7 +3321,7 @@
return(Status);
}
- ImageSectionObject = FileObject->SectionObjectPointer->ImageSectionObject;
+ if(FileObject->SectionObjectPointer == (PVOID)0xCCCCCCCC) KEBUGCHECK(0);ImageSectionObject = FileObject->SectionObjectPointer->ImageSectionObject;
Section->ImageSection = ImageSectionObject;
/*
@@ -2764,6 +3335,7 @@
Status = STATUS_SUCCESS;
}
+ Section->FileObject = FileObject;
CcRosReferenceCache(FileObject);
MmspReleaseFileLock(FileObject);
*SectionObject = Section;
@@ -3080,7 +3652,7 @@
if (Page == PFN_FROM_SSE(Entry) && Dirty)
{
FileObject = MemoryArea->Data.SectionData.Section->FileObject;
- Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
+ if(FileObject->SectionObjectPointer == (PVOID)0xCCCCCCCC) KEBUGCHECK(0);Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
CcRosMarkDirtyCacheSegment(Bcb, Offset);
ASSERT(SwapEntry == 0);
}
@@ -3999,36 +4571,83 @@
IN ULONG SectionPageProtection,
IN ULONG AllocationAttributes,
IN HANDLE FileHandle OPTIONAL,
- IN PFILE_OBJECT File OPTIONAL)
+ IN PFILE_OBJECT FileObject OPTIONAL)
{
- if (AllocationAttributes & SEC_IMAGE)
+ NTSTATUS Status;
+ ACCESS_MASK DesiredFileAccess = 0;
+
+ /*
+ * If both are NULL, we create a paging file section. Otherwise, FileObject
+ * takes precedence
+ */
+ if(FileObject == NULL && FileHandle != NULL)
{
- return(MmCreateImageSection(SectionObject,
- DesiredAccess,
- ObjectAttributes,
- MaximumSize,
- SectionPageProtection,
- AllocationAttributes,
- FileHandle));
+ if(SectionPageProtection & PAGE_IS_READABLE)
+ DesiredFileAccess |= FILE_READ_DATA;
+
+ if(SectionPageProtection & PAGE_IS_WRITABLE)
+ {
+ if(SectionPageProtection & PAGE_IS_WRITECOPY)
+ DesiredFileAccess |= FILE_READ_DATA;
+ else
+ DesiredFileAccess |= FILE_READ_DATA | FILE_WRITE_DATA;
+ }
+
+ if(SectionPageProtection & PAGE_IS_EXECUTABLE)
+ DesiredFileAccess |= FILE_EXECUTE;
+
+ Status = ObReferenceObjectByHandle(FileHandle,
+ DesiredFileAccess,
+ IoFileObjectType,
+ ExGetPreviousMode(),
+ (PVOID *)&FileObject,
+ NULL);
+
+ if(!NT_SUCCESS(Status))
+ return Status;
+
+ ASSERT(FileObject);
}
- if (FileHandle != NULL)
+ if (AllocationAttributes & SEC_IMAGE)
{
- return(MmCreateDataFileSection(SectionObject,
+ Status = MmCreateImageSection(SectionObject,
+ DesiredAccess,
+ ObjectAttributes,
+ MaximumSize,
+ SectionPageProtection,
+ AllocationAttributes,
+ FileObject);
+ }
+ /*
+ * TODO: MmCreateDataFileSection is too tied to the use of a handle to change
+ * it now. Note to self: change it later
+ */
+ else if (FileHandle != NULL)
+ /* else if (FileObject != NULL) */
+ {
+ Status = MmCreateDataFileSection(SectionObject,
+ DesiredAccess,
+ ObjectAttributes,
+ MaximumSize,
+ SectionPageProtection,
+ AllocationAttributes,
+ FileHandle);
+ }
+ else
+ {
+ return MmCreatePageFileSection(SectionObject,
DesiredAccess,
[truncated at 1000 lines; 21 more skipped]
CVSspam 0.2.8