/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
-#include "../cache/newcc.h"
-#include "../cache/section/newmm.h"
+#include <cache/newcc.h>
+#include <cache/section/newmm.h>
#define NDEBUG
#include <debug.h>
#include <reactos/exeformat.h>
#undef MmSetPageEntrySectionSegment
#define MmSetPageEntrySectionSegment(S,O,E) do { \
- DPRINT("SetPageEntrySectionSegment(old,%x,%x,%x)\n",(S),(O)->LowPart,E); \
+ DPRINT("SetPageEntrySectionSegment(old,%p,%x,%x)\n",(S),(O)->LowPart,E); \
_MmSetPageEntrySectionSegment((S),(O),(E),__FILE__,__LINE__); \
} while (0)
NTSTATUS
NTAPI
MiMapViewInSystemSpace(IN PVOID Section,
-IN PVOID Session,
-OUT PVOID *MappedBase,
-IN OUT PSIZE_T ViewSize);
+ IN PVOID Session,
+ OUT PVOID *MappedBase,
+ IN OUT PSIZE_T ViewSize);
NTSTATUS
NTAPI
MmCreateArm3Section(OUT PVOID *SectionObject,
-IN ACCESS_MASK DesiredAccess,
-IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
-IN PLARGE_INTEGER InputMaximumSize,
-IN ULONG SectionPageProtection,
-IN ULONG AllocationAttributes,
-IN HANDLE FileHandle OPTIONAL,
-IN PFILE_OBJECT FileObject OPTIONAL);
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
+ IN PLARGE_INTEGER InputMaximumSize,
+ IN ULONG SectionPageProtection,
+ IN ULONG AllocationAttributes,
+ IN HANDLE FileHandle OPTIONAL,
+ IN PFILE_OBJECT FileObject OPTIONAL);
NTSTATUS
NTAPI
typedef struct
{
- PROS_SECTION_OBJECT Section;
- PMM_SECTION_SEGMENT Segment;
- LARGE_INTEGER Offset;
- BOOLEAN WasDirty;
- BOOLEAN Private;
- PEPROCESS CallingProcess;
- ULONG_PTR SectionEntry;
+ PROS_SECTION_OBJECT Section;
+ PMM_SECTION_SEGMENT Segment;
+ LARGE_INTEGER Offset;
+ BOOLEAN WasDirty;
+ BOOLEAN Private;
+ PEPROCESS CallingProcess;
+ ULONG_PTR SectionEntry;
}
MM_SECTION_PAGEOUT_CONTEXT;
PAGE_EXECUTE_READWRITE, /* 15 = WRITABLE, READABLE, EXECUTABLE, SHARED */
};
+extern ULONG MmMakeFileAccess [];
ACCESS_MASK NTAPI MiArm3GetCorrectFileAccessMask(IN ACCESS_MASK SectionPageProtection);
-static GENERIC_MAPPING MmpSectionMapping = {
- STANDARD_RIGHTS_READ | SECTION_MAP_READ | SECTION_QUERY,
- STANDARD_RIGHTS_WRITE | SECTION_MAP_WRITE,
- STANDARD_RIGHTS_EXECUTE | SECTION_MAP_EXECUTE,
- SECTION_ALL_ACCESS};
-
-static const INFORMATION_CLASS_INFO ExSectionInfoClass[] =
+static GENERIC_MAPPING MmpSectionMapping =
{
- ICI_SQ_SAME( sizeof(SECTION_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* SectionBasicInformation */
- ICI_SQ_SAME( sizeof(SECTION_IMAGE_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* SectionImageInformation */
+ STANDARD_RIGHTS_READ | SECTION_MAP_READ | SECTION_QUERY,
+ STANDARD_RIGHTS_WRITE | SECTION_MAP_WRITE,
+ STANDARD_RIGHTS_EXECUTE | SECTION_MAP_EXECUTE,
+ SECTION_ALL_ACCESS
};
+
/* FUNCTIONS *****************************************************************/
ULONG cbHeadersSize = 0;
ULONG nSectionAlignment;
ULONG nFileAlignment;
+ ULONG_PTR ImageBase = 0;
const IMAGE_DOS_HEADER * pidhDosHeader;
const IMAGE_NT_HEADERS32 * pinhNtHeader;
const IMAGE_OPTIONAL_HEADER32 * piohOptHeader;
SIZE_T nPrevVirtualEndOfSegment = 0;
ULONG nFileSizeOfHeaders = 0;
ULONG i;
+ ULONG AlignedLength;
ASSERT(FileHeader);
ASSERT(FileHeaderSize > 0);
if(pidhDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
DIE(("No MZ signature found, e_magic is %hX\n", pidhDosHeader->e_magic));
+ /* NT HEADER */
+ nStatus = STATUS_INVALID_IMAGE_PROTECT;
+
/* not a Windows executable */
if(pidhDosHeader->e_lfanew <= 0)
DIE(("Not a Windows executable, e_lfanew is %d\n", pidhDosHeader->e_lfanew));
- /* NT HEADER */
- nStatus = STATUS_INVALID_IMAGE_FORMAT;
-
if(!Intsafe_AddULong32(&cbFileHeaderOffsetSize, pidhDosHeader->e_lfanew, RTL_SIZEOF_THROUGH_FIELD(IMAGE_NT_HEADERS32, FileHeader)))
DIE(("The DOS stub is too large, e_lfanew is %X\n", pidhDosHeader->e_lfanew));
* need to read the header from the file
*/
if(FileHeaderSize < cbFileHeaderOffsetSize ||
- (UINT_PTR)pinhNtHeader % TYPE_ALIGNMENT(IMAGE_NT_HEADERS32) != 0)
+ (UINT_PTR)pinhNtHeader % TYPE_ALIGNMENT(IMAGE_NT_HEADERS32) != 0)
{
ULONG cbNtHeaderSize;
ULONG cbReadSize;
nStatus = ReadFileCb(File, &lnOffset, sizeof(IMAGE_NT_HEADERS64), &pData, &pBuffer, &cbReadSize);
if(!NT_SUCCESS(nStatus))
- DIE(("ReadFile failed, status %08X\n", nStatus));
+ {
+ NTSTATUS ReturnedStatus = nStatus;
+
+ /* If it attempted to read past the end of the file, it means e_lfanew is invalid */
+ if (ReturnedStatus == STATUS_END_OF_FILE) nStatus = STATUS_INVALID_IMAGE_PROTECT;
+
+ DIE(("ReadFile failed, status %08X\n", ReturnedStatus));
+ }
ASSERT(pData);
ASSERT(pBuffer);
{
ULONG cbOptHeaderOffsetSize = 0;
- nStatus = STATUS_INVALID_IMAGE_FORMAT;
+ nStatus = STATUS_INVALID_IMAGE_PROTECT;
/* don't trust an invalid NT header */
if(pinhNtHeader->Signature != IMAGE_NT_SIGNATURE)
if(!Intsafe_AddULong32(&cbOptHeaderOffsetSize, pidhDosHeader->e_lfanew, FIELD_OFFSET(IMAGE_NT_HEADERS32, OptionalHeader)))
DIE(("The DOS stub is too large, e_lfanew is %X\n", pidhDosHeader->e_lfanew));
+ nStatus = STATUS_INVALID_IMAGE_FORMAT;
+
if(!Intsafe_AddULong32(&cbOptHeaderOffsetSize, cbOptHeaderOffsetSize, pinhNtHeader->FileHeader.SizeOfOptionalHeader))
DIE(("The NT header is too large, SizeOfOptionalHeader is %X\n", pinhNtHeader->FileHeader.SizeOfOptionalHeader));
switch(piohOptHeader->Magic)
{
- case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
- case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
- break;
-
- default:
- DIE(("Unrecognized optional header, Magic is %X\n", piohOptHeader->Magic));
+ case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
+#ifdef _WIN64
+ case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
+#endif // _WIN64
+ break;
+
+#ifndef _WIN64
+ case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
+ nStatus = STATUS_INVALID_IMAGE_WIN_64;
+#endif
+ default:
+ DIE(("Unrecognized optional header, Magic is %X\n", piohOptHeader->Magic));
}
if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SectionAlignment) &&
- RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, FileAlignment))
+ RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, FileAlignment))
{
/* See [1], section 3.4.2 */
if(piohOptHeader->SectionAlignment < PAGE_SIZE)
switch(piohOptHeader->Magic)
{
- /* PE32 */
- case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
- {
- if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, ImageBase))
- ImageSectionObject->ImageBase = piohOptHeader->ImageBase;
+ /* PE32 */
+ case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
+ {
+ if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, ImageBase))
+ ImageBase = piohOptHeader->ImageBase;
- if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfImage))
- ImageSectionObject->ImageSize = piohOptHeader->SizeOfImage;
+ if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfImage))
+ ImageSectionObject->ImageInformation.ImageFileSize = piohOptHeader->SizeOfImage;
- if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfStackReserve))
- ImageSectionObject->StackReserve = piohOptHeader->SizeOfStackReserve;
+ if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfStackReserve))
+ ImageSectionObject->ImageInformation.MaximumStackSize = piohOptHeader->SizeOfStackReserve;
- if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfStackCommit))
- ImageSectionObject->StackCommit = piohOptHeader->SizeOfStackCommit;
+ if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfStackCommit))
+ ImageSectionObject->ImageInformation.CommittedStackSize = piohOptHeader->SizeOfStackCommit;
- break;
+ if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, Subsystem))
+ {
+ ImageSectionObject->ImageInformation.SubSystemType = piohOptHeader->Subsystem;
+
+ if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, MinorSubsystemVersion) &&
+ RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, MajorSubsystemVersion))
+ {
+ ImageSectionObject->ImageInformation.SubSystemMinorVersion = piohOptHeader->MinorSubsystemVersion;
+ ImageSectionObject->ImageInformation.SubSystemMajorVersion = piohOptHeader->MajorSubsystemVersion;
+ }
}
- /* PE64 */
- case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
+ if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, AddressOfEntryPoint))
{
- const IMAGE_OPTIONAL_HEADER64 * pioh64OptHeader;
+ ImageSectionObject->ImageInformation.TransferAddress = (PVOID) (ImageBase +
+ piohOptHeader->AddressOfEntryPoint);
+ }
- pioh64OptHeader = (const IMAGE_OPTIONAL_HEADER64 *)piohOptHeader;
+ if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfCode))
+ ImageSectionObject->ImageInformation.ImageContainsCode = piohOptHeader->SizeOfCode != 0;
+ else
+ ImageSectionObject->ImageInformation.ImageContainsCode = TRUE;
- if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, ImageBase))
+ if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, AddressOfEntryPoint))
+ {
+ if (piohOptHeader->AddressOfEntryPoint == 0)
{
- if(pioh64OptHeader->ImageBase > MAXULONG_PTR)
- DIE(("ImageBase exceeds the address space\n"));
-
- ImageSectionObject->ImageBase = (ULONG_PTR)pioh64OptHeader->ImageBase;
+ ImageSectionObject->ImageInformation.ImageContainsCode = FALSE;
}
+ }
- if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfImage))
- {
- if(pioh64OptHeader->SizeOfImage > MAXULONG_PTR)
- DIE(("SizeOfImage exceeds the address space\n"));
+ if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, LoaderFlags))
+ ImageSectionObject->ImageInformation.LoaderFlags = piohOptHeader->LoaderFlags;
- ImageSectionObject->ImageSize = pioh64OptHeader->SizeOfImage;
- }
+ if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, DllCharacteristics))
+ {
+ ImageSectionObject->ImageInformation.DllCharacteristics = piohOptHeader->DllCharacteristics;
- if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfStackReserve))
- {
- if(pioh64OptHeader->SizeOfStackReserve > MAXULONG_PTR)
- DIE(("SizeOfStackReserve exceeds the address space\n"));
+ /*
+ * Since we don't really implement SxS yet and LD doesn't supoprt /ALLOWISOLATION:NO, hard-code
+ * this flag here, which will prevent the loader and other code from doing any .manifest or SxS
+ * magic to any binary.
+ *
+ * This will break applications that depend on SxS when running with real Windows Kernel32/SxS/etc
+ * but honestly that's not tested. It will also break them when running no ReactOS once we implement
+ * the SxS support -- at which point, duh, this should be removed.
+ *
+ * But right now, any app depending on SxS is already broken anyway, so this flag only helps.
+ */
+ ImageSectionObject->ImageInformation.DllCharacteristics |= IMAGE_DLLCHARACTERISTICS_NO_ISOLATION;
+ }
- ImageSectionObject->StackReserve = (ULONG_PTR)pioh64OptHeader->SizeOfStackReserve;
- }
+ break;
+ }
+#ifdef _WIN64
+ /* PE64 */
+ case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
+ {
+ const IMAGE_OPTIONAL_HEADER64 * pioh64OptHeader;
- if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfStackCommit))
- {
- if(pioh64OptHeader->SizeOfStackCommit > MAXULONG_PTR)
- DIE(("SizeOfStackCommit exceeds the address space\n"));
+ pioh64OptHeader = (const IMAGE_OPTIONAL_HEADER64 *)piohOptHeader;
- ImageSectionObject->StackCommit = (ULONG_PTR)pioh64OptHeader->SizeOfStackCommit;
- }
+ if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, ImageBase))
+ {
+ ImageBase = pioh64OptHeader->ImageBase;
+ if(pioh64OptHeader->ImageBase > MAXULONG_PTR)
+ DIE(("ImageBase exceeds the address space\n"));
+ }
- break;
+ if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfImage))
+ {
+ if(pioh64OptHeader->SizeOfImage > MAXULONG_PTR)
+ DIE(("SizeOfImage exceeds the address space\n"));
+
+ ImageSectionObject->ImageInformation.ImageFileSize = pioh64OptHeader->SizeOfImage;
}
- }
- /* [1], section 3.4.2 */
- if((ULONG_PTR)ImageSectionObject->ImageBase % 0x10000)
- DIE(("ImageBase is not aligned on a 64KB boundary"));
+ if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfStackReserve))
+ {
+ if(pioh64OptHeader->SizeOfStackReserve > MAXULONG_PTR)
+ DIE(("SizeOfStackReserve exceeds the address space\n"));
- if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, Subsystem))
- {
- ImageSectionObject->Subsystem = piohOptHeader->Subsystem;
+ ImageSectionObject->ImageInformation.MaximumStackSize = (ULONG_PTR) pioh64OptHeader->SizeOfStackReserve;
+ }
- if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, MinorSubsystemVersion) &&
- RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, MajorSubsystemVersion))
+ if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfStackCommit))
{
- ImageSectionObject->MinorSubsystemVersion = piohOptHeader->MinorSubsystemVersion;
- ImageSectionObject->MajorSubsystemVersion = piohOptHeader->MajorSubsystemVersion;
+ if(pioh64OptHeader->SizeOfStackCommit > MAXULONG_PTR)
+ DIE(("SizeOfStackCommit exceeds the address space\n"));
+
+ ImageSectionObject->ImageInformation.CommittedStackSize = (ULONG_PTR) pioh64OptHeader->SizeOfStackCommit;
}
- }
- if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, AddressOfEntryPoint))
- {
- ImageSectionObject->EntryPoint = ImageSectionObject->ImageBase +
- piohOptHeader->AddressOfEntryPoint;
+ if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, Subsystem))
+ {
+ ImageSectionObject->ImageInformation.SubSystemType = pioh64OptHeader->Subsystem;
+
+ if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, MinorSubsystemVersion) &&
+ RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, MajorSubsystemVersion))
+ {
+ ImageSectionObject->ImageInformation.SubSystemMinorVersion = pioh64OptHeader->MinorSubsystemVersion;
+ ImageSectionObject->ImageInformation.SubSystemMajorVersion = pioh64OptHeader->MajorSubsystemVersion;
+ }
+ }
+
+ if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, AddressOfEntryPoint))
+ {
+ ImageSectionObject->ImageInformation.TransferAddress = (PVOID) (ImageBase +
+ pioh64OptHeader->AddressOfEntryPoint);
+ }
+
+ if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfCode))
+ ImageSectionObject->ImageInformation.ImageContainsCode = pioh64OptHeader->SizeOfCode != 0;
+ else
+ ImageSectionObject->ImageInformation.ImageContainsCode = TRUE;
+
+ if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, AddressOfEntryPoint))
+ {
+ if (pioh64OptHeader->AddressOfEntryPoint == 0)
+ {
+ ImageSectionObject->ImageInformation.ImageContainsCode = FALSE;
+ }
+ }
+
+ if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, LoaderFlags))
+ ImageSectionObject->ImageInformation.LoaderFlags = pioh64OptHeader->LoaderFlags;
+
+ if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, DllCharacteristics))
+ ImageSectionObject->ImageInformation.DllCharacteristics = pioh64OptHeader->DllCharacteristics;
+
+ break;
+ }
+#endif // _WIN64
}
- if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfCode))
- ImageSectionObject->Executable = piohOptHeader->SizeOfCode != 0;
- else
- ImageSectionObject->Executable = TRUE;
+ /* [1], section 3.4.2 */
+ if((ULONG_PTR)ImageBase % 0x10000)
+ DIE(("ImageBase is not aligned on a 64KB boundary"));
- ImageSectionObject->ImageCharacteristics = pinhNtHeader->FileHeader.Characteristics;
- ImageSectionObject->Machine = pinhNtHeader->FileHeader.Machine;
+ ImageSectionObject->ImageInformation.ImageCharacteristics = pinhNtHeader->FileHeader.Characteristics;
+ ImageSectionObject->ImageInformation.Machine = pinhNtHeader->FileHeader.Machine;
+ ImageSectionObject->ImageInformation.GpValue = 0;
+ ImageSectionObject->ImageInformation.ZeroBits = 0;
+ ImageSectionObject->BasedAddress = (PVOID)ImageBase;
/* SECTION HEADERS */
nStatus = STATUS_INVALID_IMAGE_FORMAT;
* read the headers from the file
*/
if(FileHeaderSize < cbSectionHeadersOffsetSize ||
- (UINT_PTR)pishSectionHeaders % TYPE_ALIGNMENT(IMAGE_SECTION_HEADER) != 0)
+ (UINT_PTR)pishSectionHeaders % TYPE_ALIGNMENT(IMAGE_SECTION_HEADER) != 0)
{
PVOID pData;
ULONG cbReadSize;
pssSegments[0].Length.QuadPart = nPrevVirtualEndOfSegment;
pssSegments[0].RawLength.QuadPart = nFileSizeOfHeaders;
pssSegments[0].Image.VirtualAddress = 0;
- pssSegments[0].Image.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA;
+ pssSegments[0].Image.Characteristics = 0;
pssSegments[0].WriteCopy = TRUE;
/* skip the headers segment */
else
pssSegments[i].Length.QuadPart = pishSectionHeaders[i].Misc.VirtualSize;
- pssSegments[i].Length.LowPart = ALIGN_UP_BY(pssSegments[i].Length.LowPart, nSectionAlignment);
- /* FIXME: always false */
- if (pssSegments[i].Length.QuadPart < pssSegments[i].Length.QuadPart)
+ AlignedLength = ALIGN_UP_BY(pssSegments[i].Length.LowPart, nSectionAlignment);
+ if(AlignedLength < pssSegments[i].Length.LowPart)
DIE(("Cannot align the virtual size of section %u\n", i));
+ pssSegments[i].Length.LowPart = AlignedLength;
+
if(pssSegments[i].Length.QuadPart == 0)
DIE(("Virtual size of section %u is null\n", i));
*Flags |= EXEFMT_LOAD_ASSUME_SEGMENTS_PAGE_ALIGNED;
/* Success */
- nStatus = STATUS_ROS_EXEFMT_LOADED_FORMAT | EXEFMT_LOADED_PE32;
+ nStatus = STATUS_SUCCESS;// STATUS_ROS_EXEFMT_LOADED_FORMAT | EXEFMT_LOADED_PE32;
l_Return:
if(pBuffer)
MmspWaitForFileLock(PFILE_OBJECT File)
{
return STATUS_SUCCESS;
- //return KeWaitForSingleObject(&File->Lock, 0, KernelMode, FALSE, NULL);
+ //return KeWaitForSingleObject(&File->Lock, 0, KernelMode, FALSE, NULL);
}
VOID
NTAPI
MmFreeSectionSegments(PFILE_OBJECT FileObject)
{
- 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;
- NrSegments = ImageSectionObject->NrSegments;
- SectionSegments = ImageSectionObject->Segments;
- for (i = 0; i < NrSegments; i++)
- {
- if (SectionSegments[i].ReferenceCount != 0)
- {
- DPRINT1("Image segment %d still referenced (was %d)\n", i,
- SectionSegments[i].ReferenceCount);
+ 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;
+ NrSegments = ImageSectionObject->NrSegments;
+ SectionSegments = ImageSectionObject->Segments;
+ for (i = 0; i < NrSegments; i++)
+ {
+ if (SectionSegments[i].ReferenceCount != 0)
+ {
+ DPRINT1("Image segment %lu still referenced (was %lu)\n", i,
+ SectionSegments[i].ReferenceCount);
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+ MmFreePageTablesSectionSegment(&SectionSegments[i], NULL);
+ }
+ ExFreePool(ImageSectionObject->Segments);
+ ExFreePool(ImageSectionObject);
+ FileObject->SectionObjectPointer->ImageSectionObject = NULL;
+ }
+ if (FileObject->SectionObjectPointer->DataSectionObject != NULL)
+ {
+ PMM_SECTION_SEGMENT Segment;
+
+ Segment = (PMM_SECTION_SEGMENT)FileObject->SectionObjectPointer->
+ DataSectionObject;
+
+ if (Segment->ReferenceCount != 0)
+ {
+ DPRINT1("Data segment still referenced\n");
KeBugCheck(MEMORY_MANAGEMENT);
- }
- MmFreePageTablesSectionSegment(&SectionSegments[i], NULL);
- }
- ExFreePool(ImageSectionObject->Segments);
- ExFreePool(ImageSectionObject);
- FileObject->SectionObjectPointer->ImageSectionObject = NULL;
- }
- if (FileObject->SectionObjectPointer->DataSectionObject != NULL)
- {
- PMM_SECTION_SEGMENT Segment;
-
- Segment = (PMM_SECTION_SEGMENT)FileObject->SectionObjectPointer->
- DataSectionObject;
-
- if (Segment->ReferenceCount != 0)
- {
- DPRINT1("Data segment still referenced\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- MmFreePageTablesSectionSegment(Segment, NULL);
- ExFreePool(Segment);
- FileObject->SectionObjectPointer->DataSectionObject = NULL;
- }
+ }
+ MmFreePageTablesSectionSegment(Segment, NULL);
+ ExFreePool(Segment);
+ FileObject->SectionObjectPointer->DataSectionObject = NULL;
+ }
}
VOID
MmSharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
PLARGE_INTEGER Offset)
{
- ULONG_PTR Entry;
-
- Entry = MmGetPageEntrySectionSegment(Segment, Offset);
- if (Entry == 0)
- {
- DPRINT1("Entry == 0 for MmSharePageEntrySectionSegment\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- if (SHARE_COUNT_FROM_SSE(Entry) == MAX_SHARE_COUNT)
- {
- DPRINT1("Maximum share count reached\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- if (IS_SWAP_FROM_SSE(Entry))
- {
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- Entry = MAKE_SSE(PAGE_FROM_SSE(Entry), SHARE_COUNT_FROM_SSE(Entry) + 1);
- MmSetPageEntrySectionSegment(Segment, Offset, Entry);
+ ULONG_PTR Entry;
+
+ Entry = MmGetPageEntrySectionSegment(Segment, Offset);
+ if (Entry == 0)
+ {
+ DPRINT1("Entry == 0 for MmSharePageEntrySectionSegment\n");
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+ if (SHARE_COUNT_FROM_SSE(Entry) == MAX_SHARE_COUNT)
+ {
+ DPRINT1("Maximum share count reached\n");
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+ if (IS_SWAP_FROM_SSE(Entry))
+ {
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+ Entry = MAKE_SSE(PAGE_FROM_SSE(Entry), SHARE_COUNT_FROM_SSE(Entry) + 1);
+ MmSetPageEntrySectionSegment(Segment, Offset, Entry);
}
BOOLEAN
BOOLEAN PageOut,
ULONG_PTR *InEntry)
{
- ULONG_PTR Entry = InEntry ? *InEntry : MmGetPageEntrySectionSegment(Segment, Offset);
- BOOLEAN IsDirectMapped = FALSE;
-
- if (Entry == 0)
- {
- DPRINT1("Entry == 0 for MmUnsharePageEntrySectionSegment\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- if (SHARE_COUNT_FROM_SSE(Entry) == 0)
- {
- DPRINT1("Zero share count for unshare (Seg %p Offset %x Page %x)\n", Segment, Offset->LowPart, PFN_FROM_SSE(Entry));
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- if (IS_SWAP_FROM_SSE(Entry))
- {
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- Entry = MAKE_SSE(PAGE_FROM_SSE(Entry), SHARE_COUNT_FROM_SSE(Entry) - 1);
- /*
- * If we reducing the share count of this entry to zero then set the entry
- * to zero and tell the cache the page is no longer mapped.
- */
- if (SHARE_COUNT_FROM_SSE(Entry) == 0)
- {
- PFILE_OBJECT FileObject;
-#ifndef NEWCC
- PBCB Bcb;
-#endif
- SWAPENTRY SavedSwapEntry;
- PFN_NUMBER Page;
- BOOLEAN IsImageSection;
- LARGE_INTEGER FileOffset;
+ ULONG_PTR Entry = InEntry ? *InEntry : MmGetPageEntrySectionSegment(Segment, Offset);
+ BOOLEAN IsDirectMapped = FALSE;
- FileOffset.QuadPart = Offset->QuadPart + Segment->Image.FileOffset;
+ if (Entry == 0)
+ {
+ DPRINT1("Entry == 0 for MmUnsharePageEntrySectionSegment\n");
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+ if (SHARE_COUNT_FROM_SSE(Entry) == 0)
+ {
+ DPRINT1("Zero share count for unshare (Seg %p Offset %x Page %x)\n", Segment, Offset->LowPart, PFN_FROM_SSE(Entry));
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+ if (IS_SWAP_FROM_SSE(Entry))
+ {
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+ Entry = MAKE_SSE(PAGE_FROM_SSE(Entry), SHARE_COUNT_FROM_SSE(Entry) - 1);
+ /*
+ * If we reducing the share count of this entry to zero then set the entry
+ * to zero and tell the cache the page is no longer mapped.
+ */
+ if (SHARE_COUNT_FROM_SSE(Entry) == 0)
+ {
+ PFILE_OBJECT FileObject;
+ SWAPENTRY SavedSwapEntry;
+ PFN_NUMBER Page;
+#ifndef NEWCC
+ PROS_SHARED_CACHE_MAP SharedCacheMap;
+ BOOLEAN IsImageSection;
+ LARGE_INTEGER FileOffset;
- IsImageSection = Section->AllocationAttributes & SEC_IMAGE ? TRUE : FALSE;
+ FileOffset.QuadPart = Offset->QuadPart + Segment->Image.FileOffset;
+ IsImageSection = Section->AllocationAttributes & SEC_IMAGE ? TRUE : FALSE;
+#endif
- Page = PFN_FROM_SSE(Entry);
- FileObject = Section->FileObject;
- if (FileObject != NULL &&
- !(Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED))
- {
+ Page = PFN_FROM_SSE(Entry);
+ FileObject = Section->FileObject;
+ if (FileObject != NULL &&
+ !(Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED))
+ {
#ifndef NEWCC
- if ((FileOffset.QuadPart % PAGE_SIZE) == 0 &&
- (Offset->QuadPart + PAGE_SIZE <= Segment->RawLength.QuadPart || !IsImageSection))
- {
- NTSTATUS Status;
- Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
- IsDirectMapped = TRUE;
+ if ((FileOffset.QuadPart % PAGE_SIZE) == 0 &&
+ (Offset->QuadPart + PAGE_SIZE <= Segment->RawLength.QuadPart || !IsImageSection))
+ {
+ NTSTATUS Status;
+ SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
+ IsDirectMapped = TRUE;
#ifndef NEWCC
- Status = CcRosUnmapCacheSegment(Bcb, FileOffset.LowPart, Dirty);
+ Status = CcRosUnmapVacb(SharedCacheMap, FileOffset.QuadPart, Dirty);
#else
- Status = STATUS_SUCCESS;
+ Status = STATUS_SUCCESS;
#endif
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("CcRosUnmapCacheSegment failed, status = %x\n", Status);
- KeBugCheck(MEMORY_MANAGEMENT);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("CcRosUnmapVacb failed, status = %x\n", Status);
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
}
- }
#endif
- }
-
- SavedSwapEntry = MmGetSavedSwapEntryPage(Page);
- if (SavedSwapEntry == 0)
- {
- if (!PageOut &&
- ((Segment->Flags & MM_PAGEFILE_SEGMENT) ||
- (Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED)))
- {
- /*
- * FIXME:
- * Try to page out this page and set the swap entry
- * within the section segment. There exist no rmap entry
- * for this page. The pager thread can't page out a
- * page without a rmap entry.
- */
- MmSetPageEntrySectionSegment(Segment, Offset, Entry);
- if (InEntry) *InEntry = Entry;
- MiSetPageEvent(NULL, NULL);
- }
- else
- {
- MmSetPageEntrySectionSegment(Segment, Offset, 0);
- if (InEntry) *InEntry = 0;
- MiSetPageEvent(NULL, NULL);
- if (!IsDirectMapped)
+ }
+
+ SavedSwapEntry = MmGetSavedSwapEntryPage(Page);
+ if (SavedSwapEntry == 0)
+ {
+ if (!PageOut &&
+ ((Segment->Flags & MM_PAGEFILE_SEGMENT) ||
+ (Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED)))
{
- MmReleasePageMemoryConsumer(MC_USER, Page);
+ /*
+ * FIXME:
+ * Try to page out this page and set the swap entry
+ * within the section segment. There exist no rmap entry
+ * for this page. The pager thread can't page out a
+ * page without a rmap entry.
+ */
+ MmSetPageEntrySectionSegment(Segment, Offset, Entry);
+ if (InEntry) *InEntry = Entry;
+ MiSetPageEvent(NULL, NULL);
}
- }
- }
- else
- {
- if ((Segment->Flags & MM_PAGEFILE_SEGMENT) ||
- (Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED))
- {
- if (!PageOut)
+ else
{
- if (Dirty)
- {
- /*
- * FIXME:
- * We hold all locks. Nobody can do something with the current
- * process and the current segment (also not within an other process).
- */
- NTSTATUS Status;
- Status = MmWriteToSwapPage(SavedSwapEntry, Page);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n", Status);
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- }
- MmSetPageEntrySectionSegment(Segment, Offset, MAKE_SWAP_SSE(SavedSwapEntry));
- if (InEntry) *InEntry = MAKE_SWAP_SSE(SavedSwapEntry);
- MmSetSavedSwapEntryPage(Page, 0);
- MiSetPageEvent(NULL, NULL);
+ MmSetPageEntrySectionSegment(Segment, Offset, 0);
+ if (InEntry) *InEntry = 0;
+ MiSetPageEvent(NULL, NULL);
+ if (!IsDirectMapped)
+ {
+ MmReleasePageMemoryConsumer(MC_USER, Page);
+ }
}
- MmReleasePageMemoryConsumer(MC_USER, Page);
- }
- else
- {
- DPRINT1("Found a swapentry for a non private page in an image or data file sgment\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- }
- }
- else
- {
- if (InEntry)
- *InEntry = Entry;
- else
- MmSetPageEntrySectionSegment(Segment, Offset, Entry);
- }
- return(SHARE_COUNT_FROM_SSE(Entry) > 0);
+ }
+ else
+ {
+ if ((Segment->Flags & MM_PAGEFILE_SEGMENT) ||
+ (Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED))
+ {
+ if (!PageOut)
+ {
+ if (Dirty)
+ {
+ /*
+ * FIXME:
+ * We hold all locks. Nobody can do something with the current
+ * process and the current segment (also not within an other process).
+ */
+ NTSTATUS Status;
+ Status = MmWriteToSwapPage(SavedSwapEntry, Page);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n", Status);
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+ }
+ MmSetPageEntrySectionSegment(Segment, Offset, MAKE_SWAP_SSE(SavedSwapEntry));
+ if (InEntry) *InEntry = MAKE_SWAP_SSE(SavedSwapEntry);
+ MmSetSavedSwapEntryPage(Page, 0);
+ MiSetPageEvent(NULL, NULL);
+ }
+ MmReleasePageMemoryConsumer(MC_USER, Page);
+ }
+ else
+ {
+ DPRINT1("Found a swapentry for a non private page in an image or data file sgment\n");
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+ }
+ }
+ else
+ {
+ if (InEntry)
+ *InEntry = Entry;
+ else
+ MmSetPageEntrySectionSegment(Segment, Offset, Entry);
+ }
+ return(SHARE_COUNT_FROM_SSE(Entry) > 0);
}
BOOLEAN MiIsPageFromCache(PMEMORY_AREA MemoryArea,
- ULONG SegOffset)
+ LONGLONG SegOffset)
{
#ifndef NEWCC
- if (!(MemoryArea->Data.SectionData.Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED))
- {
- PBCB Bcb;
- PCACHE_SEGMENT CacheSeg;
- Bcb = MemoryArea->Data.SectionData.Section->FileObject->SectionObjectPointer->SharedCacheMap;
- CacheSeg = CcRosLookupCacheSegment(Bcb, (ULONG)(SegOffset + MemoryArea->Data.SectionData.Segment->Image.FileOffset));
- if (CacheSeg)
- {
- CcRosReleaseCacheSegment(Bcb, CacheSeg, CacheSeg->Valid, FALSE, TRUE);
- return TRUE;
- }
- }
+ if (!(MemoryArea->Data.SectionData.Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED))
+ {
+ PROS_SHARED_CACHE_MAP SharedCacheMap;
+ PROS_VACB Vacb;
+ SharedCacheMap = MemoryArea->Data.SectionData.Section->FileObject->SectionObjectPointer->SharedCacheMap;
+ Vacb = CcRosLookupVacb(SharedCacheMap, SegOffset + MemoryArea->Data.SectionData.Segment->Image.FileOffset);
+ if (Vacb)
+ {
+ CcRosReleaseVacb(SharedCacheMap, Vacb, Vacb->Valid, FALSE, TRUE);
+ return TRUE;
+ }
+ }
#endif
- return FALSE;
+ return FALSE;
}
NTSTATUS
NTAPI
-MiCopyFromUserPage(PFN_NUMBER DestPage, PFN_NUMBER SrcPage)
+MiCopyFromUserPage(PFN_NUMBER DestPage, const VOID *SrcAddress)
{
PEPROCESS Process;
- KIRQL Irql, Irql2;
- PVOID DestAddress, SrcAddress;
+ KIRQL Irql;
+ PVOID DestAddress;
Process = PsGetCurrentProcess();
DestAddress = MiMapPageInHyperSpace(Process, DestPage, &Irql);
- SrcAddress = MiMapPageInHyperSpace(Process, SrcPage, &Irql2);
- if (DestAddress == NULL || SrcAddress == NULL)
+ if (DestAddress == NULL)
{
return(STATUS_NO_MEMORY);
}
ASSERT((ULONG_PTR)DestAddress % PAGE_SIZE == 0);
ASSERT((ULONG_PTR)SrcAddress % PAGE_SIZE == 0);
RtlCopyMemory(DestAddress, SrcAddress, PAGE_SIZE);
- MiUnmapPageInHyperSpace(Process, SrcAddress, Irql2);
MiUnmapPageInHyperSpace(Process, DestAddress, Irql);
return(STATUS_SUCCESS);
}
NTSTATUS
NTAPI
MiReadPage(PMEMORY_AREA MemoryArea,
- ULONG_PTR SegOffset,
+ LONGLONG SegOffset,
PPFN_NUMBER Page)
/*
* FUNCTION: Read a page for a section backed memory area.
* Page - Variable that receives a page contains the read data.
*/
{
- ULONG BaseOffset;
- ULONGLONG FileOffset;
- PVOID BaseAddress;
- BOOLEAN UptoDate;
- PCACHE_SEGMENT CacheSeg;
- PFILE_OBJECT FileObject;
- NTSTATUS Status;
- ULONG_PTR RawLength;
- PBCB Bcb;
- BOOLEAN IsImageSection;
- ULONG_PTR Length;
-
- FileObject = MemoryArea->Data.SectionData.Section->FileObject;
- Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
- RawLength = (ULONG_PTR)(MemoryArea->Data.SectionData.Segment->RawLength.QuadPart);
- FileOffset = SegOffset + MemoryArea->Data.SectionData.Segment->Image.FileOffset;
- IsImageSection = MemoryArea->Data.SectionData.Section->AllocationAttributes & SEC_IMAGE ? TRUE : FALSE;
-
- ASSERT(Bcb);
-
- DPRINT("%S %x\n", FileObject->FileName.Buffer, FileOffset);
-
- /*
- * If the file system is letting us go directly to the cache and the
- * memory area was mapped at an offset in the file which is page aligned
- * then get the related cache segment.
- */
- if (((FileOffset % PAGE_SIZE) == 0) &&
- ((SegOffset + PAGE_SIZE <= RawLength) || !IsImageSection) &&
- !(MemoryArea->Data.SectionData.Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED))
- {
-
- /*
- * Get the related cache segment; we use a lower level interface than
- * filesystems do because it is safe for us to use an offset with a
- * alignment less than the file system block size.
- */
- Status = CcRosGetCacheSegment(Bcb,
- (ULONG)FileOffset,
- &BaseOffset,
- &BaseAddress,
- &UptoDate,
- &CacheSeg);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
- if (!UptoDate)
- {
- /*
- * If the cache segment isn't up to date then call the file
- * system to read in the data.
- */
- Status = ReadCacheSegment(CacheSeg);
- if (!NT_SUCCESS(Status))
- {
- CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE);
- return Status;
- }
- }
- /*
- * Retrieve the page from the cache segment that we actually want.
- */
- (*Page) = MmGetPhysicalAddress((char*)BaseAddress +
- FileOffset - BaseOffset).LowPart >> PAGE_SHIFT;
-
- CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, TRUE);
- }
- else
- {
- PEPROCESS Process;
- KIRQL Irql;
- PVOID PageAddr;
- ULONG_PTR CacheSegOffset;
-
- /*
- * Allocate a page, this is rather complicated by the possibility
- * we might have to move other things out of memory
- */
- MI_SET_USAGE(MI_USAGE_SECTION);
- MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName);
- Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, Page);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
- Status = CcRosGetCacheSegment(Bcb,
- (ULONG)FileOffset,
- &BaseOffset,
- &BaseAddress,
- &UptoDate,
- &CacheSeg);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
- if (!UptoDate)
- {
- /*
- * If the cache segment isn't up to date then call the file
- * system to read in the data.
- */
- Status = ReadCacheSegment(CacheSeg);
- if (!NT_SUCCESS(Status))
- {
- CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE);
- return Status;
- }
- }
-
- Process = PsGetCurrentProcess();
- PageAddr = MiMapPageInHyperSpace(Process, *Page, &Irql);
- CacheSegOffset = (ULONG_PTR)(BaseOffset + CacheSeg->Bcb->CacheSegmentSize - FileOffset);
- Length = RawLength - SegOffset;
- if (Length <= CacheSegOffset && Length <= PAGE_SIZE)
- {
- memcpy(PageAddr, (char*)BaseAddress + FileOffset - BaseOffset, Length);
- }
- else if (CacheSegOffset >= PAGE_SIZE)
- {
- memcpy(PageAddr, (char*)BaseAddress + FileOffset - BaseOffset, PAGE_SIZE);
- }
- else
- {
- memcpy(PageAddr, (char*)BaseAddress + FileOffset - BaseOffset, CacheSegOffset);
- MiUnmapPageInHyperSpace(Process, PageAddr, Irql);
- CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, FALSE);
- Status = CcRosGetCacheSegment(Bcb,
- (ULONG)(FileOffset + CacheSegOffset),
- &BaseOffset,
- &BaseAddress,
- &UptoDate,
- &CacheSeg);
- if (!NT_SUCCESS(Status))
- {
+ LONGLONG BaseOffset;
+ LONGLONG FileOffset;
+ PVOID BaseAddress;
+ BOOLEAN UptoDate;
+ PROS_VACB Vacb;
+ PFILE_OBJECT FileObject;
+ NTSTATUS Status;
+ LONGLONG RawLength;
+ PROS_SHARED_CACHE_MAP SharedCacheMap;
+ BOOLEAN IsImageSection;
+ LONGLONG Length;
+
+ FileObject = MemoryArea->Data.SectionData.Section->FileObject;
+ SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
+ RawLength = MemoryArea->Data.SectionData.Segment->RawLength.QuadPart;
+ FileOffset = SegOffset + MemoryArea->Data.SectionData.Segment->Image.FileOffset;
+ IsImageSection = MemoryArea->Data.SectionData.Section->AllocationAttributes & SEC_IMAGE ? TRUE : FALSE;
+
+ ASSERT(SharedCacheMap);
+
+ DPRINT("%S %I64x\n", FileObject->FileName.Buffer, FileOffset);
+
+ /*
+ * If the file system is letting us go directly to the cache and the
+ * memory area was mapped at an offset in the file which is page aligned
+ * then get the related VACB.
+ */
+ if (((FileOffset % PAGE_SIZE) == 0) &&
+ ((SegOffset + PAGE_SIZE <= RawLength) || !IsImageSection) &&
+ !(MemoryArea->Data.SectionData.Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED))
+ {
+
+ /*
+ * Get the related VACB; we use a lower level interface than
+ * filesystems do because it is safe for us to use an offset with an
+ * alignment less than the file system block size.
+ */
+ Status = CcRosGetVacb(SharedCacheMap,
+ FileOffset,
+ &BaseOffset,
+ &BaseAddress,
+ &UptoDate,
+ &Vacb);
+ if (!NT_SUCCESS(Status))
+ {
+ return(Status);
+ }
+ if (!UptoDate)
+ {
+ /*
+ * If the VACB isn't up to date then call the file
+ * system to read in the data.
+ */
+ Status = CcReadVirtualAddress(Vacb);
+ if (!NT_SUCCESS(Status))
+ {
+ CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE, FALSE);
+ return Status;
+ }
+ }
+
+ /* Probe the page, since it's PDE might not be synced */
+ (void)*((volatile char*)BaseAddress + FileOffset - BaseOffset);
+
+ /*
+ * Retrieve the page from the view that we actually want.
+ */
+ (*Page) = MmGetPhysicalAddress((char*)BaseAddress +
+ FileOffset - BaseOffset).LowPart >> PAGE_SHIFT;
+
+ CcRosReleaseVacb(SharedCacheMap, Vacb, TRUE, FALSE, TRUE);
+ }
+ else
+ {
+ PEPROCESS Process;
+ KIRQL Irql;
+ PVOID PageAddr;
+ LONGLONG VacbOffset;
+
+ /*
+ * Allocate a page, this is rather complicated by the possibility
+ * we might have to move other things out of memory
+ */
+ MI_SET_USAGE(MI_USAGE_SECTION);
+ MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName);
+ Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, Page);
+ if (!NT_SUCCESS(Status))
+ {
+ return(Status);
+ }
+ Status = CcRosGetVacb(SharedCacheMap,
+ FileOffset,
+ &BaseOffset,
+ &BaseAddress,
+ &UptoDate,
+ &Vacb);
+ if (!NT_SUCCESS(Status))
+ {
return(Status);
- }
- if (!UptoDate)
- {
+ }
+ if (!UptoDate)
+ {
/*
- * If the cache segment isn't up to date then call the file
+ * If the VACB isn't up to date then call the file
* system to read in the data.
*/
- Status = ReadCacheSegment(CacheSeg);
+ Status = CcReadVirtualAddress(Vacb);
+ if (!NT_SUCCESS(Status))
+ {
+ CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE, FALSE);
+ return Status;
+ }
+ }
+
+ Process = PsGetCurrentProcess();
+ PageAddr = MiMapPageInHyperSpace(Process, *Page, &Irql);
+ VacbOffset = BaseOffset + VACB_MAPPING_GRANULARITY - FileOffset;
+ Length = RawLength - SegOffset;
+ if (Length <= VacbOffset && Length <= PAGE_SIZE)
+ {
+ memcpy(PageAddr, (char*)BaseAddress + FileOffset - BaseOffset, Length);
+ }
+ else if (VacbOffset >= PAGE_SIZE)
+ {
+ memcpy(PageAddr, (char*)BaseAddress + FileOffset - BaseOffset, PAGE_SIZE);
+ }
+ else
+ {
+ memcpy(PageAddr, (char*)BaseAddress + FileOffset - BaseOffset, VacbOffset);
+ MiUnmapPageInHyperSpace(Process, PageAddr, Irql);
+ CcRosReleaseVacb(SharedCacheMap, Vacb, TRUE, FALSE, FALSE);
+ Status = CcRosGetVacb(SharedCacheMap,
+ FileOffset + VacbOffset,
+ &BaseOffset,
+ &BaseAddress,
+ &UptoDate,
+ &Vacb);
if (!NT_SUCCESS(Status))
{
- CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE);
- return Status;
+ return(Status);
+ }
+ if (!UptoDate)
+ {
+ /*
+ * If the VACB isn't up to date then call the file
+ * system to read in the data.
+ */
+ Status = CcReadVirtualAddress(Vacb);
+ if (!NT_SUCCESS(Status))
+ {
+ CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE, FALSE);
+ return Status;
+ }
+ }
+ PageAddr = MiMapPageInHyperSpace(Process, *Page, &Irql);
+ if (Length < PAGE_SIZE)
+ {
+ memcpy((char*)PageAddr + VacbOffset, BaseAddress, Length - VacbOffset);
+ }
+ else
+ {
+ memcpy((char*)PageAddr + VacbOffset, BaseAddress, PAGE_SIZE - VacbOffset);
}
- }
- PageAddr = MiMapPageInHyperSpace(Process, *Page, &Irql);
- if (Length < PAGE_SIZE)
- {
- memcpy((char*)PageAddr + CacheSegOffset, BaseAddress, Length - CacheSegOffset);
- }
- else
- {
- memcpy((char*)PageAddr + CacheSegOffset, BaseAddress, PAGE_SIZE - CacheSegOffset);
- }
- }
- MiUnmapPageInHyperSpace(Process, PageAddr, Irql);
- CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, FALSE);
- }
- return(STATUS_SUCCESS);
+ }
+ MiUnmapPageInHyperSpace(Process, PageAddr, Irql);
+ CcRosReleaseVacb(SharedCacheMap, Vacb, TRUE, FALSE, FALSE);
+ }
+ return(STATUS_SUCCESS);
}
#else
NTSTATUS
NTAPI
MiReadPage(PMEMORY_AREA MemoryArea,
- ULONG_PTR SegOffset,
+ LONGLONG SegOffset,
PPFN_NUMBER Page)
/*
* FUNCTION: Read a page for a section backed memory area.
* Page - Variable that receives a page contains the read data.
*/
{
- MM_REQUIRED_RESOURCES Resources;
- NTSTATUS Status;
+ MM_REQUIRED_RESOURCES Resources;
+ NTSTATUS Status;
- RtlZeroMemory(&Resources, sizeof(MM_REQUIRED_RESOURCES));
+ RtlZeroMemory(&Resources, sizeof(MM_REQUIRED_RESOURCES));
- Resources.Context = MemoryArea->Data.SectionData.Section->FileObject;
- Resources.FileOffset.QuadPart = SegOffset +
- MemoryArea->Data.SectionData.Segment->Image.FileOffset;
- Resources.Consumer = MC_USER;
- Resources.Amount = PAGE_SIZE;
+ Resources.Context = MemoryArea->Data.SectionData.Section->FileObject;
+ Resources.FileOffset.QuadPart = SegOffset +
+ MemoryArea->Data.SectionData.Segment->Image.FileOffset;
+ Resources.Consumer = MC_USER;
+ Resources.Amount = PAGE_SIZE;
- DPRINT("%S, offset 0x%x, len 0x%x, page 0x%x\n", ((PFILE_OBJECT)Resources.Context)->FileName.Buffer, Resources.FileOffset.LowPart, Resources.Amount, Resources.Page[0]);
+ DPRINT("%S, offset 0x%x, len 0x%x, page 0x%x\n", ((PFILE_OBJECT)Resources.Context)->FileName.Buffer, Resources.FileOffset.LowPart, Resources.Amount, Resources.Page[0]);
- Status = MiReadFilePage(MmGetKernelAddressSpace(), MemoryArea, &Resources);
- *Page = Resources.Page[0];
- return Status;
+ Status = MiReadFilePage(MmGetKernelAddressSpace(), MemoryArea, &Resources);
+ *Page = Resources.Page[0];
+ return Status;
}
#endif
+static VOID
+MmAlterViewAttributes(PMMSUPPORT AddressSpace,
+ PVOID BaseAddress,
+ SIZE_T RegionSize,
+ ULONG OldType,
+ ULONG OldProtect,
+ ULONG NewType,
+ ULONG NewProtect)
+{
+ PMEMORY_AREA MemoryArea;
+ PMM_SECTION_SEGMENT Segment;
+ BOOLEAN DoCOW = FALSE;
+ ULONG i;
+ PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
+
+ MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, BaseAddress);
+ ASSERT(MemoryArea != NULL);
+ Segment = MemoryArea->Data.SectionData.Segment;
+ MmLockSectionSegment(Segment);
+
+ if ((Segment->WriteCopy) &&
+ (NewProtect == PAGE_READWRITE || NewProtect == PAGE_EXECUTE_READWRITE))
+ {
+ DoCOW = TRUE;
+ }
+
+ if (OldProtect != NewProtect)
+ {
+ for (i = 0; i < PAGE_ROUND_UP(RegionSize) / PAGE_SIZE; i++)
+ {
+ SWAPENTRY SwapEntry;
+ PVOID Address = (char*)BaseAddress + (i * PAGE_SIZE);
+ ULONG Protect = NewProtect;
+
+ /* Wait for a wait entry to disappear */
+ do
+ {
+ MmGetPageFileMapping(Process, Address, &SwapEntry);
+ if (SwapEntry != MM_WAIT_ENTRY)
+ break;
+ MiWaitForPageEvent(Process, Address);
+ }
+ while (TRUE);
+
+ /*
+ * If we doing COW for this segment then check if the page is
+ * already private.
+ */
+ if (DoCOW && MmIsPagePresent(Process, Address))
+ {
+ LARGE_INTEGER Offset;
+ ULONG_PTR Entry;
+ PFN_NUMBER Page;
+
+ Offset.QuadPart = (ULONG_PTR)Address - MA_GetStartingAddress(MemoryArea)
+ + MemoryArea->Data.SectionData.ViewOffset.QuadPart;
+ Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
+ /*
+ * An MM_WAIT_ENTRY is ok in this case... It'll just count as
+ * IS_SWAP_FROM_SSE and we'll do the right thing.
+ */
+ Page = MmGetPfnForProcess(Process, Address);
+
+ Protect = PAGE_READONLY;
+ if (IS_SWAP_FROM_SSE(Entry) || PFN_FROM_SSE(Entry) != Page)
+ {
+ Protect = NewProtect;
+ }
+ }
+
+ if (MmIsPagePresent(Process, Address) || MmIsDisabledPage(Process, Address))
+ {
+ MmSetPageProtect(Process, Address,
+ Protect);
+ }
+ }
+ }
+
+ MmUnlockSectionSegment(Segment);
+}
+
NTSTATUS
NTAPI
MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
PVOID Address,
BOOLEAN Locked)
{
- LARGE_INTEGER Offset;
- PFN_NUMBER Page;
- NTSTATUS Status;
- PROS_SECTION_OBJECT Section;
- PMM_SECTION_SEGMENT Segment;
- ULONG_PTR Entry;
- ULONG_PTR Entry1;
- ULONG Attributes;
- PMM_REGION Region;
- BOOLEAN HasSwapEntry;
- PVOID PAddress;
- PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
- SWAPENTRY SwapEntry;
-
- /*
- * There is a window between taking the page fault and locking the
- * address space when another thread could load the page so we check
- * that.
- */
- if (MmIsPagePresent(Process, Address))
- {
- return(STATUS_SUCCESS);
- }
-
- if (MmIsDisabledPage(Process, Address))
- {
- return(STATUS_ACCESS_VIOLATION);
- }
-
- /*
- * Check for the virtual memory area being deleted.
- */
- if (MemoryArea->DeleteInProgress)
- {
- return(STATUS_UNSUCCESSFUL);
- }
-
- PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
- Offset.QuadPart = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress
- + MemoryArea->Data.SectionData.ViewOffset.QuadPart;
-
- Segment = MemoryArea->Data.SectionData.Segment;
- Section = MemoryArea->Data.SectionData.Section;
- Region = MmFindRegion(MemoryArea->StartingAddress,
- &MemoryArea->Data.SectionData.RegionListHead,
- Address, NULL);
- ASSERT(Region != NULL);
- /*
- * Lock the segment
- */
- MmLockSectionSegment(Segment);
- Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
- /*
- * Check if this page needs to be mapped COW
- */
- if ((Segment->WriteCopy) &&
- (Region->Protect == PAGE_READWRITE ||
- Region->Protect == PAGE_EXECUTE_READWRITE))
- {
- Attributes = Region->Protect == PAGE_READWRITE ? PAGE_READONLY : PAGE_EXECUTE_READ;
- }
- else
- {
- Attributes = Region->Protect;
- }
-
- /*
- * Check if someone else is already handling this fault, if so wait
- * for them
- */
- if (Entry && IS_SWAP_FROM_SSE(Entry) && SWAPENTRY_FROM_SSE(Entry) == MM_WAIT_ENTRY)
- {
- MmUnlockSectionSegment(Segment);
- MmUnlockAddressSpace(AddressSpace);
- MiWaitForPageEvent(NULL, NULL);
- MmLockAddressSpace(AddressSpace);
- DPRINT("Address 0x%.8X\n", Address);
- return(STATUS_MM_RESTART_OPERATION);
- }
-
- HasSwapEntry = MmIsPageSwapEntry(Process, Address);
-
- if (HasSwapEntry)
- {
- SWAPENTRY DummyEntry;
-
- /*
- * Is it a wait entry?
- */
- MmGetPageFileMapping(Process, Address, &SwapEntry);
-
- if (SwapEntry == MM_WAIT_ENTRY)
- {
- MmUnlockSectionSegment(Segment);
- MmUnlockAddressSpace(AddressSpace);
- MiWaitForPageEvent(NULL, NULL);
- MmLockAddressSpace(AddressSpace);
- return STATUS_MM_RESTART_OPERATION;
- }
-
- /*
- * Must be private page we have swapped out.
- */
-
- /*
- * Sanity check
- */
- if (Segment->Flags & MM_PAGEFILE_SEGMENT)
- {
- DPRINT1("Found a swaped out private page in a pagefile section.\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- }
-
- MmUnlockSectionSegment(Segment);
- MmDeletePageFileMapping(Process, Address, &SwapEntry);
- MmCreatePageFileMapping(Process, Address, MM_WAIT_ENTRY);
-
- MmUnlockAddressSpace(AddressSpace);
- MI_SET_USAGE(MI_USAGE_SECTION);
- if (Process) MI_SET_PROCESS2(Process->ImageFileName);
- if (!Process) MI_SET_PROCESS2("Kernel Section");
- Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
- if (!NT_SUCCESS(Status))
- {
- KeBugCheck(MEMORY_MANAGEMENT);
- }
-
- Status = MmReadFromSwapPage(SwapEntry, Page);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("MmReadFromSwapPage failed, status = %x\n", Status);
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- MmLockAddressSpace(AddressSpace);
- MmDeletePageFileMapping(Process, PAddress, &DummyEntry);
- Status = MmCreateVirtualMapping(Process,
- PAddress,
- Region->Protect,
- &Page,
- 1);
- if (!NT_SUCCESS(Status))
- {
- DPRINT("MmCreateVirtualMapping failed, not out of memory\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- return(Status);
- }
-
- /*
- * Store the swap entry for later use.
- */
- MmSetSavedSwapEntryPage(Page, SwapEntry);
-
- /*
- * Add the page to the process's working set
- */
- MmInsertRmap(Page, Process, Address);
- /*
- * Finish the operation
- */
- MiSetPageEvent(Process, Address);
- DPRINT("Address 0x%.8X\n", Address);
- return(STATUS_SUCCESS);
- }
-
- /*
- * Satisfying a page fault on a map of /Device/PhysicalMemory is easy
- */
- if (Section->AllocationAttributes & SEC_PHYSICALMEMORY)
- {
- MmUnlockSectionSegment(Segment);
- /*
- * Just map the desired physical page
- */
- Page = (PFN_NUMBER)(Offset.QuadPart >> PAGE_SHIFT);
- Status = MmCreateVirtualMappingUnsafe(Process,
- PAddress,
- Region->Protect,
- &Page,
- 1);
- if (!NT_SUCCESS(Status))
- {
- DPRINT("MmCreateVirtualMappingUnsafe failed, not out of memory\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- return(Status);
- }
-
- /*
- * Cleanup and release locks
- */
- MiSetPageEvent(Process, Address);
- DPRINT("Address 0x%.8X\n", Address);
- return(STATUS_SUCCESS);
- }
-
- /*
- * Get the entry corresponding to the offset within the section
- */
- Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
-
- if (Entry == 0)
- {
- SWAPENTRY FakeSwapEntry;
-
- /*
- * If the entry is zero (and it can't change because we have
- * locked the segment) then we need to load the page.
- */
-
- /*
- * Release all our locks and read in the page from disk
- */
- MmSetPageEntrySectionSegment(Segment, &Offset, MAKE_SWAP_SSE(MM_WAIT_ENTRY));
- MmUnlockSectionSegment(Segment);
- MmCreatePageFileMapping(Process, PAddress, MM_WAIT_ENTRY);
- MmUnlockAddressSpace(AddressSpace);
-
- if ((Segment->Flags & MM_PAGEFILE_SEGMENT) ||
- ((Offset.QuadPart >= (LONGLONG)PAGE_ROUND_UP(Segment->RawLength.QuadPart) &&
- (Section->AllocationAttributes & SEC_IMAGE))))
- {
- MI_SET_USAGE(MI_USAGE_SECTION);
- if (Process) MI_SET_PROCESS2(Process->ImageFileName);
- if (!Process) MI_SET_PROCESS2("Kernel Section");
- Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("MmRequestPageMemoryConsumer failed (Status %x)\n", Status);
- }
-
- }
- else
- {
- Status = MiReadPage(MemoryArea, (ULONG_PTR)Offset.QuadPart, &Page);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("MiReadPage failed (Status %x)\n", Status);
- }
- }
- if (!NT_SUCCESS(Status))
- {
- /*
- * FIXME: What do we know in this case?
- */
- /*
- * Cleanup and release locks
- */
- MmLockAddressSpace(AddressSpace);
- MiSetPageEvent(Process, Address);
- DPRINT("Address 0x%.8X\n", Address);
- return(Status);
- }
-
- /*
- * Mark the offset within the section as having valid, in-memory
- * data
- */
- MmLockAddressSpace(AddressSpace);
- MmLockSectionSegment(Segment);
- Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
- MmSetPageEntrySectionSegment(Segment, &Offset, Entry);
- MmUnlockSectionSegment(Segment);
-
- MmDeletePageFileMapping(Process, PAddress, &FakeSwapEntry);
- DPRINT("CreateVirtualMapping Page %x Process %p PAddress %p Attributes %x\n",
- Page, Process, PAddress, Attributes);
- Status = MmCreateVirtualMapping(Process,
- PAddress,
- Attributes,
- &Page,
- 1);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Unable to create virtual mapping\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- ASSERT(MmIsPagePresent(Process, PAddress));
- MmInsertRmap(Page, Process, Address);
-
- MiSetPageEvent(Process, Address);
- DPRINT("Address 0x%.8X\n", Address);
- return(STATUS_SUCCESS);
- }
- else if (IS_SWAP_FROM_SSE(Entry))
- {
- SWAPENTRY SwapEntry;
-
- SwapEntry = SWAPENTRY_FROM_SSE(Entry);
-
- /*
- * Release all our locks and read in the page from disk
- */
- MmUnlockSectionSegment(Segment);
-
- MmUnlockAddressSpace(AddressSpace);
- MI_SET_USAGE(MI_USAGE_SECTION);
- if (Process) MI_SET_PROCESS2(Process->ImageFileName);
- if (!Process) MI_SET_PROCESS2("Kernel Section");
- Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
- if (!NT_SUCCESS(Status))
- {
- KeBugCheck(MEMORY_MANAGEMENT);
- }
-
- Status = MmReadFromSwapPage(SwapEntry, Page);
- if (!NT_SUCCESS(Status))
- {
- KeBugCheck(MEMORY_MANAGEMENT);
- }
-
- /*
- * Relock the address space and segment
- */
- MmLockAddressSpace(AddressSpace);
- MmLockSectionSegment(Segment);
-
- /*
- * Check the entry. No one should change the status of a page
- * that has a pending page-in.
- */
- Entry1 = MmGetPageEntrySectionSegment(Segment, &Offset);
- if (Entry != Entry1)
- {
- DPRINT1("Someone changed ppte entry while we slept (%x vs %x)\n", Entry, Entry1);
- KeBugCheck(MEMORY_MANAGEMENT);
- }
-
- /*
- * Mark the offset within the section as having valid, in-memory
- * data
- */
- Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
- MmSetPageEntrySectionSegment(Segment, &Offset, Entry);
- MmUnlockSectionSegment(Segment);
-
- /*
- * Save the swap entry.
- */
- MmSetSavedSwapEntryPage(Page, SwapEntry);
- Status = MmCreateVirtualMapping(Process,
- PAddress,
- Region->Protect,
- &Page,
- 1);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Unable to create virtual mapping\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- MmInsertRmap(Page, Process, Address);
- MiSetPageEvent(Process, Address);
- DPRINT("Address 0x%.8X\n", Address);
- return(STATUS_SUCCESS);
- }
- else
- {
- /*
- * If the section offset is already in-memory and valid then just
- * take another reference to the page
- */
-
- Page = PFN_FROM_SSE(Entry);
-
- MmSharePageEntrySectionSegment(Segment, &Offset);
- MmUnlockSectionSegment(Segment);
-
- Status = MmCreateVirtualMapping(Process,
- PAddress,
- Attributes,
- &Page,
- 1);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Unable to create virtual mapping\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- MmInsertRmap(Page, Process, Address);
- MiSetPageEvent(Process, Address);
- DPRINT("Address 0x%.8X\n", Address);
- return(STATUS_SUCCESS);
- }
-}
+ LARGE_INTEGER Offset;
+ PFN_NUMBER Page;
+ NTSTATUS Status;
+ PROS_SECTION_OBJECT Section;
+ PMM_SECTION_SEGMENT Segment;
+ ULONG_PTR Entry;
+ ULONG_PTR Entry1;
+ ULONG Attributes;
+ PMM_REGION Region;
+ BOOLEAN HasSwapEntry;
+ PVOID PAddress;
+ PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
+ SWAPENTRY SwapEntry;
-NTSTATUS
-NTAPI
-MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
+ /*
+ * There is a window between taking the page fault and locking the
+ * address space when another thread could load the page so we check
+ * that.
+ */
+ if (MmIsPagePresent(Process, Address))
+ {
+ return(STATUS_SUCCESS);
+ }
+
+ if (MmIsDisabledPage(Process, Address))
+ {
+ return(STATUS_ACCESS_VIOLATION);
+ }
+
+ /*
+ * Check for the virtual memory area being deleted.
+ */
+ if (MemoryArea->DeleteInProgress)
+ {
+ return(STATUS_UNSUCCESSFUL);
+ }
+
+ PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
+ Offset.QuadPart = (ULONG_PTR)PAddress - MA_GetStartingAddress(MemoryArea)
+ + MemoryArea->Data.SectionData.ViewOffset.QuadPart;
+
+ Segment = MemoryArea->Data.SectionData.Segment;
+ Section = MemoryArea->Data.SectionData.Section;
+ Region = MmFindRegion((PVOID)MA_GetStartingAddress(MemoryArea),
+ &MemoryArea->Data.SectionData.RegionListHead,
+ Address, NULL);
+ ASSERT(Region != NULL);
+
+ /* Check for a NOACCESS mapping */
+ if (Region->Protect & PAGE_NOACCESS)
+ {
+ return STATUS_ACCESS_VIOLATION;
+ }
+
+ if (Region->Protect & PAGE_GUARD)
+ {
+ /* Remove it */
+ Status = MmAlterRegion(AddressSpace, (PVOID)MA_GetStartingAddress(MemoryArea),
+ &MemoryArea->Data.SectionData.RegionListHead,
+ Address, PAGE_SIZE, Region->Type, Region->Protect & ~PAGE_GUARD,
+ MmAlterViewAttributes);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Removing PAGE_GUARD protection failed : 0x%08x.\n", Status);
+ }
+
+ return STATUS_GUARD_PAGE_VIOLATION;
+ }
+
+ /*
+ * Lock the segment
+ */
+ MmLockSectionSegment(Segment);
+ Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
+ /*
+ * Check if this page needs to be mapped COW
+ */
+ if ((Segment->WriteCopy) &&
+ (Region->Protect == PAGE_READWRITE ||
+ Region->Protect == PAGE_EXECUTE_READWRITE))
+ {
+ Attributes = Region->Protect == PAGE_READWRITE ? PAGE_READONLY : PAGE_EXECUTE_READ;
+ }
+ else
+ {
+ Attributes = Region->Protect;
+ }
+
+ /*
+ * Check if someone else is already handling this fault, if so wait
+ * for them
+ */
+ if (Entry && MM_IS_WAIT_PTE(Entry))
+ {
+ MmUnlockSectionSegment(Segment);
+ MmUnlockAddressSpace(AddressSpace);
+ MiWaitForPageEvent(NULL, NULL);
+ MmLockAddressSpace(AddressSpace);
+ DPRINT("Address 0x%p\n", Address);
+ return(STATUS_MM_RESTART_OPERATION);
+ }
+
+ HasSwapEntry = MmIsPageSwapEntry(Process, Address);
+
+ /* See if we should use a private page */
+ if (HasSwapEntry)
+ {
+ SWAPENTRY DummyEntry;
+
+ /*
+ * Is it a wait entry?
+ */
+ if (HasSwapEntry)
+ {
+ MmGetPageFileMapping(Process, Address, &SwapEntry);
+
+ if (SwapEntry == MM_WAIT_ENTRY)
+ {
+ MmUnlockSectionSegment(Segment);
+ MmUnlockAddressSpace(AddressSpace);
+ MiWaitForPageEvent(NULL, NULL);
+ MmLockAddressSpace(AddressSpace);
+ return STATUS_MM_RESTART_OPERATION;
+ }
+
+ /*
+ * Must be private page we have swapped out.
+ */
+
+ /*
+ * Sanity check
+ */
+ if (Segment->Flags & MM_PAGEFILE_SEGMENT)
+ {
+ DPRINT1("Found a swaped out private page in a pagefile section.\n");
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+ MmDeletePageFileMapping(Process, Address, &SwapEntry);
+ }
+
+ MmUnlockSectionSegment(Segment);
+
+ /* Tell everyone else we are serving the fault. */
+ MmCreatePageFileMapping(Process, Address, MM_WAIT_ENTRY);
+
+ MmUnlockAddressSpace(AddressSpace);
+ MI_SET_USAGE(MI_USAGE_SECTION);
+ if (Process) MI_SET_PROCESS2(Process->ImageFileName);
+ if (!Process) MI_SET_PROCESS2("Kernel Section");
+ Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
+ if (!NT_SUCCESS(Status))
+ {
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+
+ if (HasSwapEntry)
+ {
+ Status = MmReadFromSwapPage(SwapEntry, Page);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("MmReadFromSwapPage failed, status = %x\n", Status);
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+ }
+
+ MmLockAddressSpace(AddressSpace);
+ MmDeletePageFileMapping(Process, PAddress, &DummyEntry);
+ Status = MmCreateVirtualMapping(Process,
+ PAddress,
+ Region->Protect,
+ &Page,
+ 1);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("MmCreateVirtualMapping failed, not out of memory\n");
+ KeBugCheck(MEMORY_MANAGEMENT);
+ return(Status);
+ }
+
+ /*
+ * Store the swap entry for later use.
+ */
+ if (HasSwapEntry)
+ MmSetSavedSwapEntryPage(Page, SwapEntry);
+
+ /*
+ * Add the page to the process's working set
+ */
+ MmInsertRmap(Page, Process, Address);
+ /*
+ * Finish the operation
+ */
+ MiSetPageEvent(Process, Address);
+ DPRINT("Address 0x%p\n", Address);
+ return(STATUS_SUCCESS);
+ }
+
+ /*
+ * Satisfying a page fault on a map of /Device/PhysicalMemory is easy
+ */
+ if (Section->AllocationAttributes & SEC_PHYSICALMEMORY)
+ {
+ MmUnlockSectionSegment(Segment);
+ /*
+ * Just map the desired physical page
+ */
+ Page = (PFN_NUMBER)(Offset.QuadPart >> PAGE_SHIFT);
+ Status = MmCreateVirtualMappingUnsafe(Process,
+ PAddress,
+ Region->Protect,
+ &Page,
+ 1);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("MmCreateVirtualMappingUnsafe failed, not out of memory\n");
+ KeBugCheck(MEMORY_MANAGEMENT);
+ return(Status);
+ }
+
+ /*
+ * Cleanup and release locks
+ */
+ MiSetPageEvent(Process, Address);
+ DPRINT("Address 0x%p\n", Address);
+ return(STATUS_SUCCESS);
+ }
+
+ /*
+ * Get the entry corresponding to the offset within the section
+ */
+ Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
+
+ if (Entry == 0)
+ {
+ SWAPENTRY FakeSwapEntry;
+
+ /*
+ * If the entry is zero (and it can't change because we have
+ * locked the segment) then we need to load the page.
+ */
+
+ /*
+ * Release all our locks and read in the page from disk
+ */
+ MmSetPageEntrySectionSegment(Segment, &Offset, MAKE_SWAP_SSE(MM_WAIT_ENTRY));
+ MmUnlockSectionSegment(Segment);
+ MmCreatePageFileMapping(Process, PAddress, MM_WAIT_ENTRY);
+ MmUnlockAddressSpace(AddressSpace);
+
+ if ((Segment->Flags & MM_PAGEFILE_SEGMENT) ||
+ ((Offset.QuadPart >= (LONGLONG)PAGE_ROUND_UP(Segment->RawLength.QuadPart) &&
+ (Section->AllocationAttributes & SEC_IMAGE))))
+ {
+ MI_SET_USAGE(MI_USAGE_SECTION);
+ if (Process) MI_SET_PROCESS2(Process->ImageFileName);
+ if (!Process) MI_SET_PROCESS2("Kernel Section");
+ Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("MmRequestPageMemoryConsumer failed (Status %x)\n", Status);
+ }
+
+ }
+ else
+ {
+ Status = MiReadPage(MemoryArea, Offset.QuadPart, &Page);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("MiReadPage failed (Status %x)\n", Status);
+ }
+ }
+ if (!NT_SUCCESS(Status))
+ {
+ /*
+ * FIXME: What do we know in this case?
+ */
+ /*
+ * Cleanup and release locks
+ */
+ MmLockAddressSpace(AddressSpace);
+ MiSetPageEvent(Process, Address);
+ DPRINT("Address 0x%p\n", Address);
+ return(Status);
+ }
+
+ /* Lock both segment and process address space while we proceed. */
+ MmLockAddressSpace(AddressSpace);
+ MmLockSectionSegment(Segment);
+
+ MmDeletePageFileMapping(Process, PAddress, &FakeSwapEntry);
+ DPRINT("CreateVirtualMapping Page %x Process %p PAddress %p Attributes %x\n",
+ Page, Process, PAddress, Attributes);
+ Status = MmCreateVirtualMapping(Process,
+ PAddress,
+ Attributes,
+ &Page,
+ 1);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Unable to create virtual mapping\n");
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+ ASSERT(MmIsPagePresent(Process, PAddress));
+ MmInsertRmap(Page, Process, Address);
+
+ /* Set this section offset has being backed by our new page. */
+ Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
+ MmSetPageEntrySectionSegment(Segment, &Offset, Entry);
+ MmUnlockSectionSegment(Segment);
+
+ MiSetPageEvent(Process, Address);
+ DPRINT("Address 0x%p\n", Address);
+ return(STATUS_SUCCESS);
+ }
+ else if (IS_SWAP_FROM_SSE(Entry))
+ {
+ SWAPENTRY SwapEntry;
+
+ SwapEntry = SWAPENTRY_FROM_SSE(Entry);
+
+ /* See if a page op is running on this segment. */
+ if (SwapEntry == MM_WAIT_ENTRY)
+ {
+ MmUnlockSectionSegment(Segment);
+ MmUnlockAddressSpace(AddressSpace);
+ MiWaitForPageEvent(NULL, NULL);
+ MmLockAddressSpace(AddressSpace);
+ return STATUS_MM_RESTART_OPERATION;
+ }
+
+ /*
+ * Release all our locks and read in the page from disk
+ */
+ MmUnlockSectionSegment(Segment);
+
+ MmUnlockAddressSpace(AddressSpace);
+ MI_SET_USAGE(MI_USAGE_SECTION);
+ if (Process) MI_SET_PROCESS2(Process->ImageFileName);
+ if (!Process) MI_SET_PROCESS2("Kernel Section");
+ Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
+ if (!NT_SUCCESS(Status))
+ {
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+
+ Status = MmReadFromSwapPage(SwapEntry, Page);
+ if (!NT_SUCCESS(Status))
+ {
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+
+ /*
+ * Relock the address space and segment
+ */
+ MmLockAddressSpace(AddressSpace);
+ MmLockSectionSegment(Segment);
+
+ /*
+ * Check the entry. No one should change the status of a page
+ * that has a pending page-in.
+ */
+ Entry1 = MmGetPageEntrySectionSegment(Segment, &Offset);
+ if (Entry != Entry1)
+ {
+ DPRINT1("Someone changed ppte entry while we slept (%x vs %x)\n", Entry, Entry1);
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+
+ /*
+ * Save the swap entry.
+ */
+ MmSetSavedSwapEntryPage(Page, SwapEntry);
+
+ /* Map the page into the process address space */
+ Status = MmCreateVirtualMapping(Process,
+ PAddress,
+ Region->Protect,
+ &Page,
+ 1);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Unable to create virtual mapping\n");
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+ MmInsertRmap(Page, Process, Address);
+
+ /*
+ * Mark the offset within the section as having valid, in-memory
+ * data
+ */
+ Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
+ MmSetPageEntrySectionSegment(Segment, &Offset, Entry);
+ MmUnlockSectionSegment(Segment);
+
+ MiSetPageEvent(Process, Address);
+ DPRINT("Address 0x%p\n", Address);
+ return(STATUS_SUCCESS);
+ }
+ else
+ {
+ /* We already have a page on this section offset. Map it into the process address space. */
+ Page = PFN_FROM_SSE(Entry);
+
+ Status = MmCreateVirtualMapping(Process,
+ PAddress,
+ Attributes,
+ &Page,
+ 1);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Unable to create virtual mapping\n");
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+ MmInsertRmap(Page, Process, Address);
+
+ /* Take a reference on it */
+ MmSharePageEntrySectionSegment(Segment, &Offset);
+ MmUnlockSectionSegment(Segment);
+
+ MiSetPageEvent(Process, Address);
+ DPRINT("Address 0x%p\n", Address);
+ return(STATUS_SUCCESS);
+ }
+}
+
+NTSTATUS
+NTAPI
+MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
MEMORY_AREA* MemoryArea,
PVOID Address)
{
- PMM_SECTION_SEGMENT Segment;
- PROS_SECTION_OBJECT Section;
- PFN_NUMBER OldPage;
- PFN_NUMBER NewPage;
- NTSTATUS Status;
- PVOID PAddress;
- LARGE_INTEGER Offset;
- PMM_REGION Region;
- ULONG_PTR Entry;
- PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
- SWAPENTRY SwapEntry;
-
- DPRINT("MmAccessFaultSectionView(%x, %x, %x, %x)\n", AddressSpace, MemoryArea, Address);
-
- /*
- * Check if the page has already been set readwrite
- */
- if (MmGetPageProtect(Process, Address) & PAGE_READWRITE)
- {
- DPRINT("Address 0x%.8X\n", Address);
- return(STATUS_SUCCESS);
- }
-
- /*
- * Find the offset of the page
- */
- PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
- Offset.QuadPart = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress
- + MemoryArea->Data.SectionData.ViewOffset.QuadPart;
-
- Segment = MemoryArea->Data.SectionData.Segment;
- Section = MemoryArea->Data.SectionData.Section;
- Region = MmFindRegion(MemoryArea->StartingAddress,
- &MemoryArea->Data.SectionData.RegionListHead,
- Address, NULL);
- ASSERT(Region != NULL);
- /*
- * Lock the segment
- */
- MmLockSectionSegment(Segment);
-
- OldPage = MmGetPfnForProcess(Process, Address);
- Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
-
- MmUnlockSectionSegment(Segment);
-
- /*
- * Check if we are doing COW
- */
- if (!((Segment->WriteCopy) &&
- (Region->Protect == PAGE_READWRITE ||
- Region->Protect == PAGE_EXECUTE_READWRITE)))
- {
- DPRINT("Address 0x%.8X\n", Address);
- return(STATUS_ACCESS_VIOLATION);
- }
-
- if (IS_SWAP_FROM_SSE(Entry) ||
- PFN_FROM_SSE(Entry) != OldPage)
- {
- /* This is a private page. We must only change the page protection. */
- MmSetPageProtect(Process, Address, Region->Protect);
- return(STATUS_SUCCESS);
- }
-
- if(OldPage == 0)
- DPRINT("OldPage == 0!\n");
-
- /*
- * Get or create a pageop
- */
- MmLockSectionSegment(Segment);
- Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
-
- /*
- * Wait for any other operations to complete
- */
- if (Entry == SWAPENTRY_FROM_SSE(MM_WAIT_ENTRY))
- {
- MmUnlockSectionSegment(Segment);
- MmUnlockAddressSpace(AddressSpace);
- MiWaitForPageEvent(NULL, NULL);
- /*
- * Restart the operation
- */
- MmLockAddressSpace(AddressSpace);
- DPRINT("Address 0x%.8X\n", Address);
- return(STATUS_MM_RESTART_OPERATION);
- }
-
- MmDeleteRmap(OldPage, Process, PAddress);
- MmDeleteVirtualMapping(Process, PAddress, FALSE, NULL, NULL);
- MmCreatePageFileMapping(Process, PAddress, MM_WAIT_ENTRY);
-
- /*
- * Release locks now we have the pageop
- */
- MmUnlockSectionSegment(Segment);
- MmUnlockAddressSpace(AddressSpace);
-
- /*
- * Allocate a page
- */
- MI_SET_USAGE(MI_USAGE_SECTION);
- if (Process) MI_SET_PROCESS2(Process->ImageFileName);
- if (!Process) MI_SET_PROCESS2("Kernel Section");
- Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &NewPage);
- if (!NT_SUCCESS(Status))
- {
- KeBugCheck(MEMORY_MANAGEMENT);
- }
-
- /*
- * Copy the old page
- */
- MiCopyFromUserPage(NewPage, OldPage);
-
- MmLockAddressSpace(AddressSpace);
-
- /*
- * Set the PTE to point to the new page
- */
- MmDeletePageFileMapping(Process, PAddress, &SwapEntry);
- Status = MmCreateVirtualMapping(Process,
- PAddress,
- Region->Protect,
- &NewPage,
- 1);
+ PMM_SECTION_SEGMENT Segment;
+ PROS_SECTION_OBJECT Section;
+ PFN_NUMBER OldPage;
+ PFN_NUMBER NewPage;
+ NTSTATUS Status;
+ PVOID PAddress;
+ LARGE_INTEGER Offset;
+ PMM_REGION Region;
+ ULONG_PTR Entry;
+ PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
+
+ DPRINT("MmAccessFaultSectionView(%p, %p, %p)\n", AddressSpace, MemoryArea, Address);
+
+ /* Make sure we have a page mapping for this address. */
+ Status = MmNotPresentFaultSectionView(AddressSpace, MemoryArea, Address, TRUE);
+ if (!NT_SUCCESS(Status))
+ {
+ /* This is invalid access ! */
+ return Status;
+ }
+
+ /*
+ * Check if the page has already been set readwrite
+ */
+ if (MmGetPageProtect(Process, Address) & PAGE_READWRITE)
+ {
+ DPRINT("Address 0x%p\n", Address);
+ return(STATUS_SUCCESS);
+ }
+
+ /*
+ * Find the offset of the page
+ */
+ PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
+ Offset.QuadPart = (ULONG_PTR)PAddress - MA_GetStartingAddress(MemoryArea)
+ + MemoryArea->Data.SectionData.ViewOffset.QuadPart;
+
+ Segment = MemoryArea->Data.SectionData.Segment;
+ Section = MemoryArea->Data.SectionData.Section;
+ Region = MmFindRegion((PVOID)MA_GetStartingAddress(MemoryArea),
+ &MemoryArea->Data.SectionData.RegionListHead,
+ Address, NULL);
+ ASSERT(Region != NULL);
+
+ /*
+ * Check if we are doing COW
+ */
+ if (!((Segment->WriteCopy) &&
+ (Region->Protect == PAGE_READWRITE ||
+ Region->Protect == PAGE_EXECUTE_READWRITE)))
+ {
+ DPRINT("Address 0x%p\n", Address);
+ return(STATUS_ACCESS_VIOLATION);
+ }
+
+ /* Get the page mapping this section offset. */
+ MmLockSectionSegment(Segment);
+ Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
+
+ /* Get the current page mapping for the process */
+ ASSERT(MmIsPagePresent(Process, PAddress));
+ OldPage = MmGetPfnForProcess(Process, PAddress);
+ ASSERT(OldPage != 0);
+
+ if (IS_SWAP_FROM_SSE(Entry) ||
+ PFN_FROM_SSE(Entry) != OldPage)
+ {
+ MmUnlockSectionSegment(Segment);
+ /* This is a private page. We must only change the page protection. */
+ MmSetPageProtect(Process, PAddress, Region->Protect);
+ return(STATUS_SUCCESS);
+ }
+
+ /*
+ * Allocate a page
+ */
+ MI_SET_USAGE(MI_USAGE_SECTION);
+ if (Process) MI_SET_PROCESS2(Process->ImageFileName);
+ if (!Process) MI_SET_PROCESS2("Kernel Section");
+ Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &NewPage);
+ if (!NT_SUCCESS(Status))
+ {
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+
+ /*
+ * Copy the old page
+ */
+ NT_VERIFY(NT_SUCCESS(MiCopyFromUserPage(NewPage, PAddress)));
+
+ /*
+ * Unshare the old page.
+ */
+ DPRINT("Swapping page (Old %x New %x)\n", OldPage, NewPage);
+ MmDeleteVirtualMapping(Process, PAddress, NULL, NULL);
+ MmDeleteRmap(OldPage, Process, PAddress);
+ MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, FALSE, FALSE, NULL);
+ MmUnlockSectionSegment(Segment);
+
+ /*
+ * Set the PTE to point to the new page
+ */
+ Status = MmCreateVirtualMapping(Process,
+ PAddress,
+ Region->Protect,
+ &NewPage,
+ 1);
if (!NT_SUCCESS(Status))
{
DPRINT1("MmCreateVirtualMapping failed, unable to create virtual mapping, not out of memory\n");
KeBugCheck(MEMORY_MANAGEMENT);
return(Status);
}
+ MmInsertRmap(NewPage, Process, PAddress);
- /*
- * Unshare the old page.
- */
- DPRINT("Swapping page (Old %x New %x)\n", OldPage, NewPage);
- MmInsertRmap(NewPage, Process, PAddress);
- MmLockSectionSegment(Segment);
- MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, FALSE, FALSE, NULL);
- MmUnlockSectionSegment(Segment);
-
- MiSetPageEvent(Process, Address);
- DPRINT("Address 0x%.8X\n", Address);
- return(STATUS_SUCCESS);
+ MiSetPageEvent(Process, Address);
+ DPRINT("Address 0x%p\n", Address);
+ return(STATUS_SUCCESS);
}
VOID
MmPageOutDeleteMapping(PVOID Context, PEPROCESS Process, PVOID Address)
{
- MM_SECTION_PAGEOUT_CONTEXT* PageOutContext;
- BOOLEAN WasDirty;
- PFN_NUMBER Page = 0;
-
- PageOutContext = (MM_SECTION_PAGEOUT_CONTEXT*)Context;
- if (Process)
- {
- MmLockAddressSpace(&Process->Vm);
- }
-
- MmDeleteVirtualMapping(Process,
- Address,
- FALSE,
- &WasDirty,
- &Page);
- if (WasDirty)
- {
- PageOutContext->WasDirty = TRUE;
- }
- if (!PageOutContext->Private)
- {
- MmLockSectionSegment(PageOutContext->Segment);
- MmUnsharePageEntrySectionSegment((PROS_SECTION_OBJECT)PageOutContext->Section,
- PageOutContext->Segment,
- &PageOutContext->Offset,
- PageOutContext->WasDirty,
- TRUE,
- &PageOutContext->SectionEntry);
- MmUnlockSectionSegment(PageOutContext->Segment);
- }
- if (Process)
- {
- MmUnlockAddressSpace(&Process->Vm);
- }
-
- if (PageOutContext->Private)
- {
- MmReleasePageMemoryConsumer(MC_USER, Page);
- }
+ MM_SECTION_PAGEOUT_CONTEXT* PageOutContext;
+ BOOLEAN WasDirty;
+ PFN_NUMBER Page = 0;
+
+ PageOutContext = (MM_SECTION_PAGEOUT_CONTEXT*)Context;
+ if (Process)
+ {
+ MmLockAddressSpace(&Process->Vm);
+ }
+
+ MmDeleteVirtualMapping(Process,
+ Address,
+ &WasDirty,
+ &Page);
+ if (WasDirty)
+ {
+ PageOutContext->WasDirty = TRUE;
+ }
+ if (!PageOutContext->Private)
+ {
+ MmLockSectionSegment(PageOutContext->Segment);
+ MmUnsharePageEntrySectionSegment((PROS_SECTION_OBJECT)PageOutContext->Section,
+ PageOutContext->Segment,
+ &PageOutContext->Offset,
+ PageOutContext->WasDirty,
+ TRUE,
+ &PageOutContext->SectionEntry);
+ MmUnlockSectionSegment(PageOutContext->Segment);
+ }
+ if (Process)
+ {
+ MmUnlockAddressSpace(&Process->Vm);
+ }
+
+ if (PageOutContext->Private)
+ {
+ MmReleasePageMemoryConsumer(MC_USER, Page);
+ }
}
NTSTATUS
MEMORY_AREA* MemoryArea,
PVOID Address, ULONG_PTR Entry)
{
- PFN_NUMBER Page;
- MM_SECTION_PAGEOUT_CONTEXT Context;
- SWAPENTRY SwapEntry;
- ULONGLONG FileOffset;
- NTSTATUS Status;
- PFILE_OBJECT FileObject;
+ PFN_NUMBER Page;
+ MM_SECTION_PAGEOUT_CONTEXT Context;
+ SWAPENTRY SwapEntry;
+ NTSTATUS Status;
#ifndef NEWCC
- PBCB Bcb = NULL;
+ ULONGLONG FileOffset;
+ PFILE_OBJECT FileObject;
+ PROS_SHARED_CACHE_MAP SharedCacheMap = NULL;
+ BOOLEAN IsImageSection;
#endif
- BOOLEAN DirectMapped;
- BOOLEAN IsImageSection;
- PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
- KIRQL OldIrql;
-
- Address = (PVOID)PAGE_ROUND_DOWN(Address);
+ BOOLEAN DirectMapped;
+ PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
+ KIRQL OldIrql;
- /*
- * Get the segment and section.
- */
- Context.Segment = MemoryArea->Data.SectionData.Segment;
- Context.Section = MemoryArea->Data.SectionData.Section;
- Context.SectionEntry = Entry;
- Context.CallingProcess = Process;
+ Address = (PVOID)PAGE_ROUND_DOWN(Address);
- Context.Offset.QuadPart = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress
- + MemoryArea->Data.SectionData.ViewOffset.QuadPart;
- FileOffset = Context.Offset.QuadPart + Context.Segment->Image.FileOffset;
+ /*
+ * Get the segment and section.
+ */
+ Context.Segment = MemoryArea->Data.SectionData.Segment;
+ Context.Section = MemoryArea->Data.SectionData.Section;
+ Context.SectionEntry = Entry;
+ Context.CallingProcess = Process;
- IsImageSection = Context.Section->AllocationAttributes & SEC_IMAGE ? TRUE : FALSE;
+ Context.Offset.QuadPart = (ULONG_PTR)Address - MA_GetStartingAddress(MemoryArea)
+ + MemoryArea->Data.SectionData.ViewOffset.QuadPart;
- FileObject = Context.Section->FileObject;
- DirectMapped = FALSE;
+ DirectMapped = FALSE;
- MmLockSectionSegment(Context.Segment);
+ MmLockSectionSegment(Context.Segment);
#ifndef NEWCC
- if (FileObject != NULL &&
- !(Context.Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED))
- {
- Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
-
- /*
- * If the file system is letting us go directly to the cache and the
- * memory area was mapped at an offset in the file which is page aligned
- * then note this is a direct mapped page.
- */
- if ((FileOffset % PAGE_SIZE) == 0 &&
- (Context.Offset.QuadPart + PAGE_SIZE <= Context.Segment->RawLength.QuadPart || !IsImageSection))
- {
- DirectMapped = TRUE;
- }
- }
+ FileOffset = Context.Offset.QuadPart + Context.Segment->Image.FileOffset;
+ IsImageSection = Context.Section->AllocationAttributes & SEC_IMAGE ? TRUE : FALSE;
+ FileObject = Context.Section->FileObject;
+
+ if (FileObject != NULL &&
+ !(Context.Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED))
+ {
+ SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
+
+ /*
+ * If the file system is letting us go directly to the cache and the
+ * memory area was mapped at an offset in the file which is page aligned
+ * then note this is a direct mapped page.
+ */
+ if ((FileOffset % PAGE_SIZE) == 0 &&
+ (Context.Offset.QuadPart + PAGE_SIZE <= Context.Segment->RawLength.QuadPart || !IsImageSection))
+ {
+ DirectMapped = TRUE;
+ }
+ }
#endif
- /*
- * This should never happen since mappings of physical memory are never
- * placed in the rmap lists.
- */
- if (Context.Section->AllocationAttributes & SEC_PHYSICALMEMORY)
- {
- DPRINT1("Trying to page out from physical memory section address 0x%X "
- "process %d\n", Address,
- Process ? Process->UniqueProcessId : 0);
- KeBugCheck(MEMORY_MANAGEMENT);
- }
-
- /*
- * Get the section segment entry and the physical address.
- */
- if (!MmIsPagePresent(Process, Address))
- {
- DPRINT1("Trying to page out not-present page at (%d,0x%.8X).\n",
- Process ? Process->UniqueProcessId : 0, Address);
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- Page = MmGetPfnForProcess(Process, Address);
- SwapEntry = MmGetSavedSwapEntryPage(Page);
-
- /*
- * Check the reference count to ensure this page can be paged out
- */
- if (MmGetReferenceCountPage(Page) != 1)
- {
- DPRINT("Cannot page out locked section page: 0x%p (RefCount: %d)\n",
+ /*
+ * This should never happen since mappings of physical memory are never
+ * placed in the rmap lists.
+ */
+ if (Context.Section->AllocationAttributes & SEC_PHYSICALMEMORY)
+ {
+ DPRINT1("Trying to page out from physical memory section address 0x%p "
+ "process %p\n", Address,
+ Process ? Process->UniqueProcessId : 0);
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+
+ /*
+ * Get the section segment entry and the physical address.
+ */
+ if (!MmIsPagePresent(Process, Address))
+ {
+ DPRINT1("Trying to page out not-present page at (%p,0x%p).\n",
+ Process ? Process->UniqueProcessId : 0, Address);
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+ Page = MmGetPfnForProcess(Process, Address);
+ SwapEntry = MmGetSavedSwapEntryPage(Page);
+
+ /*
+ * Check the reference count to ensure this page can be paged out
+ */
+ if (MmGetReferenceCountPage(Page) != 1)
+ {
+ DPRINT("Cannot page out locked section page: 0x%lu (RefCount: %lu)\n",
Page, MmGetReferenceCountPage(Page));
- MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
- MmUnlockSectionSegment(Context.Segment);
- return STATUS_UNSUCCESSFUL;
- }
-
- /*
- * Prepare the context structure for the rmap delete call.
- */
- MmUnlockSectionSegment(Context.Segment);
- Context.WasDirty = FALSE;
- if (Context.Segment->Image.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ||
- IS_SWAP_FROM_SSE(Entry) ||
- PFN_FROM_SSE(Entry) != Page)
- {
- Context.Private = TRUE;
- }
- else
- {
- Context.Private = FALSE;
- }
-
- /*
- * Take an additional reference to the page or the cache segment.
- */
- if (DirectMapped && !Context.Private)
- {
- if(!MiIsPageFromCache(MemoryArea, Context.Offset.LowPart))
- {
- DPRINT1("Direct mapped non private page is not associated with the cache.\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- }
- else
- {
- OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
- MmReferencePage(Page);
- KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
- }
-
- MmDeleteAllRmaps(Page, (PVOID)&Context, MmPageOutDeleteMapping);
-
- /* Since we passed in a surrogate, we'll get back the page entry
- * state in our context. This is intended to make intermediate
- * decrements of share count not release the wait entry.
- */
- Entry = Context.SectionEntry;
-
- /*
- * If this wasn't a private page then we should have reduced the entry to
- * zero by deleting all the rmaps.
- */
- if (!Context.Private && Entry != 0)
- {
- if (!(Context.Segment->Flags & MM_PAGEFILE_SEGMENT) &&
- !(Context.Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED))
- {
- KeBugCheckEx(MEMORY_MANAGEMENT, Entry, (ULONG_PTR)Process, (ULONG_PTR)Address, 0);
- }
- }
-
- /*
- * If the page wasn't dirty then we can just free it as for a readonly page.
- * Since we unmapped all the mappings above we know it will not suddenly
- * become dirty.
- * If the page is from a pagefile section and has no swap entry,
- * we can't free the page at this point.
- */
- SwapEntry = MmGetSavedSwapEntryPage(Page);
- if (Context.Segment->Flags & MM_PAGEFILE_SEGMENT)
- {
- if (Context.Private)
- {
- DPRINT1("Found a %s private page (address %x) in a pagefile segment.\n",
- Context.WasDirty ? "dirty" : "clean", Address);
- KeBugCheckEx(MEMORY_MANAGEMENT, SwapEntry, (ULONG_PTR)Process, (ULONG_PTR)Address, 0);
- }
- if (!Context.WasDirty && SwapEntry != 0)
- {
- MmSetSavedSwapEntryPage(Page, 0);
- MmLockSectionSegment(Context.Segment);
- MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, MAKE_SWAP_SSE(SwapEntry));
- MmUnlockSectionSegment(Context.Segment);
- MmReleasePageMemoryConsumer(MC_USER, Page);
- MiSetPageEvent(NULL, NULL);
- return(STATUS_SUCCESS);
- }
- }
- else if (Context.Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED)
- {
- if (Context.Private)
- {
- DPRINT1("Found a %s private page (address %x) in a shared section segment.\n",
- Context.WasDirty ? "dirty" : "clean", Address);
- KeBugCheckEx(MEMORY_MANAGEMENT, Page, (ULONG_PTR)Process, (ULONG_PTR)Address, 0);
- }
- if (!Context.WasDirty || SwapEntry != 0)
- {
- MmSetSavedSwapEntryPage(Page, 0);
- if (SwapEntry != 0)
- {
+ MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
+ MmUnlockSectionSegment(Context.Segment);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ /*
+ * Prepare the context structure for the rmap delete call.
+ */
+ MmUnlockSectionSegment(Context.Segment);
+ Context.WasDirty = FALSE;
+ if (IS_SWAP_FROM_SSE(Entry) || PFN_FROM_SSE(Entry) != Page)
+ {
+ Context.Private = TRUE;
+ }
+ else
+ {
+ Context.Private = FALSE;
+ }
+
+ /*
+ * Take an additional reference to the page or the VACB.
+ */
+ if (DirectMapped && !Context.Private)
+ {
+ if(!MiIsPageFromCache(MemoryArea, Context.Offset.QuadPart))
+ {
+ DPRINT1("Direct mapped non private page is not associated with the cache.\n");
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+ }
+ else
+ {
+ OldIrql = MiAcquirePfnLock();
+ MmReferencePage(Page);
+ MiReleasePfnLock(OldIrql);
+ }
+
+ MmDeleteAllRmaps(Page, (PVOID)&Context, MmPageOutDeleteMapping);
+
+ /* Since we passed in a surrogate, we'll get back the page entry
+ * state in our context. This is intended to make intermediate
+ * decrements of share count not release the wait entry.
+ */
+ Entry = Context.SectionEntry;
+
+ /*
+ * If this wasn't a private page then we should have reduced the entry to
+ * zero by deleting all the rmaps.
+ */
+ if (!Context.Private && Entry != 0)
+ {
+ if (!(Context.Segment->Flags & MM_PAGEFILE_SEGMENT) &&
+ !(Context.Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED))
+ {
+ KeBugCheckEx(MEMORY_MANAGEMENT, Entry, (ULONG_PTR)Process, (ULONG_PTR)Address, 0);
+ }
+ }
+
+ /*
+ * If the page wasn't dirty then we can just free it as for a readonly page.
+ * Since we unmapped all the mappings above we know it will not suddenly
+ * become dirty.
+ * If the page is from a pagefile section and has no swap entry,
+ * we can't free the page at this point.
+ */
+ SwapEntry = MmGetSavedSwapEntryPage(Page);
+ if (Context.Segment->Flags & MM_PAGEFILE_SEGMENT)
+ {
+ if (Context.Private)
+ {
+ DPRINT1("Found a %s private page (address %p) in a pagefile segment.\n",
+ Context.WasDirty ? "dirty" : "clean", Address);
+ KeBugCheckEx(MEMORY_MANAGEMENT, SwapEntry, (ULONG_PTR)Process, (ULONG_PTR)Address, 0);
+ }
+ if (!Context.WasDirty && SwapEntry != 0)
+ {
+ MmSetSavedSwapEntryPage(Page, 0);
MmLockSectionSegment(Context.Segment);
MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, MAKE_SWAP_SSE(SwapEntry));
MmUnlockSectionSegment(Context.Segment);
- }
- MmReleasePageMemoryConsumer(MC_USER, Page);
- MiSetPageEvent(NULL, NULL);
- return(STATUS_SUCCESS);
- }
- }
- else if (!Context.Private && DirectMapped)
- {
- if (SwapEntry != 0)
- {
- DPRINT1("Found a swapentry for a non private and direct mapped page (address %x)\n",
- Address);
- KeBugCheckEx(MEMORY_MANAGEMENT, STATUS_UNSUCCESSFUL, SwapEntry, (ULONG_PTR)Process, (ULONG_PTR)Address);
- }
+ MmReleasePageMemoryConsumer(MC_USER, Page);
+ MiSetPageEvent(NULL, NULL);
+ return(STATUS_SUCCESS);
+ }
+ }
+ else if (Context.Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED)
+ {
+ if (Context.Private)
+ {
+ DPRINT1("Found a %s private page (address %p) in a shared section segment.\n",
+ Context.WasDirty ? "dirty" : "clean", Address);
+ KeBugCheckEx(MEMORY_MANAGEMENT, Page, (ULONG_PTR)Process, (ULONG_PTR)Address, 0);
+ }
+ if (!Context.WasDirty || SwapEntry != 0)
+ {
+ MmSetSavedSwapEntryPage(Page, 0);
+ if (SwapEntry != 0)
+ {
+ MmLockSectionSegment(Context.Segment);
+ MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, MAKE_SWAP_SSE(SwapEntry));
+ MmUnlockSectionSegment(Context.Segment);
+ }
+ MmReleasePageMemoryConsumer(MC_USER, Page);
+ MiSetPageEvent(NULL, NULL);
+ return(STATUS_SUCCESS);
+ }
+ }
+ else if (!Context.Private && DirectMapped)
+ {
+ if (SwapEntry != 0)
+ {
+ DPRINT1("Found a swapentry for a non private and direct mapped page (address %p)\n",
+ Address);
+ KeBugCheckEx(MEMORY_MANAGEMENT, STATUS_UNSUCCESSFUL, SwapEntry, (ULONG_PTR)Process, (ULONG_PTR)Address);
+ }
#ifndef NEWCC
- Status = CcRosUnmapCacheSegment(Bcb, (ULONG)FileOffset, FALSE);
+ Status = CcRosUnmapVacb(SharedCacheMap, FileOffset, FALSE);
#else
- Status = STATUS_SUCCESS;
+ Status = STATUS_SUCCESS;
#endif
#ifndef NEWCC
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("CCRosUnmapCacheSegment failed, status = %x\n", Status);
- KeBugCheckEx(MEMORY_MANAGEMENT, Status, (ULONG_PTR)Bcb, (ULONG_PTR)FileOffset, (ULONG_PTR)Address);
- }
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("CcRosUnmapVacb failed, status = %x\n", Status);
+ KeBugCheckEx(MEMORY_MANAGEMENT, Status, (ULONG_PTR)SharedCacheMap, (ULONG_PTR)FileOffset, (ULONG_PTR)Address);
+ }
#endif
- MiSetPageEvent(NULL, NULL);
- return(STATUS_SUCCESS);
- }
- else if (!Context.WasDirty && !DirectMapped && !Context.Private)
- {
- if (SwapEntry != 0)
- {
- DPRINT1("Found a swap entry for a non dirty, non private and not direct mapped page (address %x)\n",
- Address);
- KeBugCheckEx(MEMORY_MANAGEMENT, SwapEntry, Page, (ULONG_PTR)Process, (ULONG_PTR)Address);
- }
- MmReleasePageMemoryConsumer(MC_USER, Page);
- MiSetPageEvent(NULL, NULL);
- return(STATUS_SUCCESS);
- }
- else if (!Context.WasDirty && Context.Private && SwapEntry != 0)
- {
- DPRINT("Not dirty and private and not swapped (%p:%p)\n", Process, Address);
- MmSetSavedSwapEntryPage(Page, 0);
- MmLockAddressSpace(AddressSpace);
- Status = MmCreatePageFileMapping(Process,
- Address,
- SwapEntry);
- MmUnlockAddressSpace(AddressSpace);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Status %x Swapping out %p:%p\n", Status, Process, Address);
- KeBugCheckEx(MEMORY_MANAGEMENT, Status, (ULONG_PTR)Process, (ULONG_PTR)Address, SwapEntry);
- }
- MmReleasePageMemoryConsumer(MC_USER, Page);
- MiSetPageEvent(NULL, NULL);
- return(STATUS_SUCCESS);
- }
-
- /*
- * If necessary, allocate an entry in the paging file for this page
- */
- if (SwapEntry == 0)
- {
- SwapEntry = MmAllocSwapPage();
- if (SwapEntry == 0)
- {
- MmShowOutOfSpaceMessagePagingFile();
- MmLockAddressSpace(AddressSpace);
- /*
- * For private pages restore the old mappings.
- */
- if (Context.Private)
- {
+ MiSetPageEvent(NULL, NULL);
+ return(STATUS_SUCCESS);
+ }
+ else if (!Context.WasDirty && !DirectMapped && !Context.Private)
+ {
+ if (SwapEntry != 0)
+ {
+ DPRINT1("Found a swap entry for a non dirty, non private and not direct mapped page (address %p)\n",
+ Address);
+ KeBugCheckEx(MEMORY_MANAGEMENT, SwapEntry, Page, (ULONG_PTR)Process, (ULONG_PTR)Address);
+ }
+ MmReleasePageMemoryConsumer(MC_USER, Page);
+ MiSetPageEvent(NULL, NULL);
+ return(STATUS_SUCCESS);
+ }
+ else if (!Context.WasDirty && Context.Private && SwapEntry != 0)
+ {
+ DPRINT("Not dirty and private and not swapped (%p:%p)\n", Process, Address);
+ MmSetSavedSwapEntryPage(Page, 0);
+ MmLockAddressSpace(AddressSpace);
+ Status = MmCreatePageFileMapping(Process,
+ Address,
+ SwapEntry);
+ MmUnlockAddressSpace(AddressSpace);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Status %x Swapping out %p:%p\n", Status, Process, Address);
+ KeBugCheckEx(MEMORY_MANAGEMENT, Status, (ULONG_PTR)Process, (ULONG_PTR)Address, SwapEntry);
+ }
+ MmReleasePageMemoryConsumer(MC_USER, Page);
+ MiSetPageEvent(NULL, NULL);
+ return(STATUS_SUCCESS);
+ }
+
+ /*
+ * If necessary, allocate an entry in the paging file for this page
+ */
+ if (SwapEntry == 0)
+ {
+ SwapEntry = MmAllocSwapPage();
+ if (SwapEntry == 0)
+ {
+ MmShowOutOfSpaceMessagePagingFile();
+ MmLockAddressSpace(AddressSpace);
+ /*
+ * For private pages restore the old mappings.
+ */
+ if (Context.Private)
+ {
+ Status = MmCreateVirtualMapping(Process,
+ Address,
+ MemoryArea->Protect,
+ &Page,
+ 1);
+ MmSetDirtyPage(Process, Address);
+ MmInsertRmap(Page,
+ Process,
+ Address);
+ }
+ else
+ {
+ ULONG_PTR OldEntry;
+
+ MmLockSectionSegment(Context.Segment);
+
+ /*
+ * For non-private pages if the page wasn't direct mapped then
+ * set it back into the section segment entry so we don't loose
+ * our copy. Otherwise it will be handled by the cache manager.
+ */
+ Status = MmCreateVirtualMapping(Process,
+ Address,
+ MemoryArea->Protect,
+ &Page,
+ 1);
+ MmSetDirtyPage(Process, Address);
+ MmInsertRmap(Page,
+ Process,
+ Address);
+ // If we got here, the previous entry should have been a wait
+ Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
+ OldEntry = MmGetPageEntrySectionSegment(Context.Segment, &Context.Offset);
+ ASSERT(OldEntry == 0 || OldEntry == MAKE_SWAP_SSE(MM_WAIT_ENTRY));
+ MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
+ MmUnlockSectionSegment(Context.Segment);
+ }
+ MmUnlockAddressSpace(AddressSpace);
+ MiSetPageEvent(NULL, NULL);
+ return(STATUS_PAGEFILE_QUOTA);
+ }
+ }
+
+ /*
+ * Write the page to the pagefile
+ */
+ Status = MmWriteToSwapPage(SwapEntry, Page);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n",
+ Status);
+ /*
+ * As above: undo our actions.
+ * FIXME: Also free the swap page.
+ */
+ MmLockAddressSpace(AddressSpace);
+ if (Context.Private)
+ {
Status = MmCreateVirtualMapping(Process,
Address,
MemoryArea->Protect,
MmInsertRmap(Page,
Process,
Address);
- }
- else
- {
- ULONG_PTR OldEntry;
- /*
- * For non-private pages if the page wasn't direct mapped then
- * set it back into the section segment entry so we don't loose
- * our copy. Otherwise it will be handled by the cache manager.
- */
+ }
+ else
+ {
+ MmLockSectionSegment(Context.Segment);
Status = MmCreateVirtualMapping(Process,
Address,
MemoryArea->Protect,
MmInsertRmap(Page,
Process,
Address);
- // If we got here, the previous entry should have been a wait
Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
- MmLockSectionSegment(Context.Segment);
- OldEntry = MmGetPageEntrySectionSegment(Context.Segment, &Context.Offset);
- ASSERT(OldEntry == 0 || OldEntry == MAKE_SWAP_SSE(MM_WAIT_ENTRY));
MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
MmUnlockSectionSegment(Context.Segment);
- }
- MmUnlockAddressSpace(AddressSpace);
- MiSetPageEvent(NULL, NULL);
- return(STATUS_PAGEFILE_QUOTA);
- }
- }
-
- /*
- * Write the page to the pagefile
- */
- Status = MmWriteToSwapPage(SwapEntry, Page);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n",
- Status);
- /*
- * As above: undo our actions.
- * FIXME: Also free the swap page.
- */
- MmLockAddressSpace(AddressSpace);
- if (Context.Private)
- {
- Status = MmCreateVirtualMapping(Process,
- Address,
- MemoryArea->Protect,
- &Page,
- 1);
- MmSetDirtyPage(Process, Address);
- MmInsertRmap(Page,
- Process,
- Address);
- }
- else
- {
- Status = MmCreateVirtualMapping(Process,
+ }
+ MmUnlockAddressSpace(AddressSpace);
+ MiSetPageEvent(NULL, NULL);
+ return(STATUS_UNSUCCESSFUL);
+ }
+
+ /*
+ * Otherwise we have succeeded.
+ */
+ DPRINT("MM: Wrote section page 0x%.8X to swap!\n", Page << PAGE_SHIFT);
+ MmSetSavedSwapEntryPage(Page, 0);
+ if (Context.Segment->Flags & MM_PAGEFILE_SEGMENT ||
+ Context.Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED)
+ {
+ MmLockSectionSegment(Context.Segment);
+ MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, MAKE_SWAP_SSE(SwapEntry));
+ MmUnlockSectionSegment(Context.Segment);
+ }
+ else
+ {
+ MmReleasePageMemoryConsumer(MC_USER, Page);
+ }
+
+ if (Context.Private)
+ {
+ MmLockAddressSpace(AddressSpace);
+ MmLockSectionSegment(Context.Segment);
+ Status = MmCreatePageFileMapping(Process,
Address,
- MemoryArea->Protect,
- &Page,
- 1);
- MmSetDirtyPage(Process, Address);
- MmInsertRmap(Page,
- Process,
- Address);
- Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
- MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
- }
- MmUnlockAddressSpace(AddressSpace);
- MiSetPageEvent(NULL, NULL);
- return(STATUS_UNSUCCESSFUL);
- }
-
- /*
- * Otherwise we have succeeded.
- */
- DPRINT("MM: Wrote section page 0x%.8X to swap!\n", Page << PAGE_SHIFT);
- MmSetSavedSwapEntryPage(Page, 0);
- if (Context.Segment->Flags & MM_PAGEFILE_SEGMENT ||
- Context.Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED)
- {
- MmLockSectionSegment(Context.Segment);
- MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, MAKE_SWAP_SSE(SwapEntry));
- MmUnlockSectionSegment(Context.Segment);
- }
- else
- {
- MmReleasePageMemoryConsumer(MC_USER, Page);
- }
-
- if (Context.Private)
- {
- MmLockAddressSpace(AddressSpace);
- MmLockSectionSegment(Context.Segment);
- Status = MmCreatePageFileMapping(Process,
- Address,
- SwapEntry);
- /* We had placed a wait entry upon entry ... replace it before leaving */
- MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
- MmUnlockSectionSegment(Context.Segment);
- MmUnlockAddressSpace(AddressSpace);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Status %x Creating page file mapping for %p:%p\n", Status, Process, Address);
- KeBugCheckEx(MEMORY_MANAGEMENT, Status, (ULONG_PTR)Process, (ULONG_PTR)Address, SwapEntry);
- }
- }
- else
- {
- MmLockAddressSpace(AddressSpace);
- MmLockSectionSegment(Context.Segment);
- Entry = MAKE_SWAP_SSE(SwapEntry);
- /* We had placed a wait entry upon entry ... replace it before leaving */
- MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
- MmUnlockSectionSegment(Context.Segment);
- MmUnlockAddressSpace(AddressSpace);
- }
-
- MiSetPageEvent(NULL, NULL);
- return(STATUS_SUCCESS);
+ SwapEntry);
+ /* We had placed a wait entry upon entry ... replace it before leaving */
+ MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
+ MmUnlockSectionSegment(Context.Segment);
+ MmUnlockAddressSpace(AddressSpace);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Status %x Creating page file mapping for %p:%p\n", Status, Process, Address);
+ KeBugCheckEx(MEMORY_MANAGEMENT, Status, (ULONG_PTR)Process, (ULONG_PTR)Address, SwapEntry);
+ }
+ }
+ else
+ {
+ MmLockAddressSpace(AddressSpace);
+ MmLockSectionSegment(Context.Segment);
+ Entry = MAKE_SWAP_SSE(SwapEntry);
+ /* We had placed a wait entry upon entry ... replace it before leaving */
+ MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
+ MmUnlockSectionSegment(Context.Segment);
+ MmUnlockAddressSpace(AddressSpace);
+ }
+
+ MiSetPageEvent(NULL, NULL);
+ return(STATUS_SUCCESS);
}
NTSTATUS
PVOID Address,
ULONG PageEntry)
{
- LARGE_INTEGER Offset;
- PROS_SECTION_OBJECT Section;
- PMM_SECTION_SEGMENT Segment;
- PFN_NUMBER Page;
- SWAPENTRY SwapEntry;
- ULONG_PTR Entry;
- BOOLEAN Private;
- NTSTATUS Status;
- PFILE_OBJECT FileObject;
- PBCB Bcb = NULL;
- BOOLEAN DirectMapped;
- BOOLEAN IsImageSection;
- PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
-
- Address = (PVOID)PAGE_ROUND_DOWN(Address);
-
- Offset.QuadPart = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress
- + MemoryArea->Data.SectionData.ViewOffset.QuadPart;
-
- /*
- * Get the segment and section.
- */
- Segment = MemoryArea->Data.SectionData.Segment;
- Section = MemoryArea->Data.SectionData.Section;
- IsImageSection = Section->AllocationAttributes & SEC_IMAGE ? TRUE : FALSE;
-
- FileObject = Section->FileObject;
- DirectMapped = FALSE;
- if (FileObject != NULL &&
- !(Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED))
- {
- Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
-
- /*
- * If the file system is letting us go directly to the cache and the
- * memory area was mapped at an offset in the file which is page aligned
- * then note this is a direct mapped page.
- */
- if (((Offset.QuadPart + Segment->Image.FileOffset) % PAGE_SIZE) == 0 &&
- (Offset.QuadPart + PAGE_SIZE <= Segment->RawLength.QuadPart || !IsImageSection))
- {
- DirectMapped = TRUE;
- }
- }
-
- /*
- * This should never happen since mappings of physical memory are never
- * placed in the rmap lists.
- */
- if (Section->AllocationAttributes & SEC_PHYSICALMEMORY)
- {
- DPRINT1("Trying to write back page from physical memory mapped at %X "
- "process %d\n", Address,
- Process ? Process->UniqueProcessId : 0);
- KeBugCheck(MEMORY_MANAGEMENT);
- }
-
- /*
- * Get the section segment entry and the physical address.
- */
- Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
- if (!MmIsPagePresent(Process, Address))
- {
- DPRINT1("Trying to page out not-present page at (%d,0x%.8X).\n",
- Process ? Process->UniqueProcessId : 0, Address);
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- Page = MmGetPfnForProcess(Process, Address);
- SwapEntry = MmGetSavedSwapEntryPage(Page);
-
- /*
- * Check for a private (COWed) page.
- */
- if (Segment->Image.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ||
- IS_SWAP_FROM_SSE(Entry) ||
- PFN_FROM_SSE(Entry) != Page)
- {
- Private = TRUE;
- }
- else
- {
- Private = FALSE;
- }
-
- /*
- * Speculatively set all mappings of the page to clean.
- */
- MmSetCleanAllRmaps(Page);
-
- /*
- * If this page was direct mapped from the cache then the cache manager
- * will take care of writing it back to disk.
- */
- if (DirectMapped && !Private)
- {
- //LARGE_INTEGER SOffset;
- ASSERT(SwapEntry == 0);
- //SOffset.QuadPart = Offset.QuadPart + Segment->Image.FileOffset;
+ LARGE_INTEGER Offset;
+ PROS_SECTION_OBJECT Section;
+ PMM_SECTION_SEGMENT Segment;
+ PFN_NUMBER Page;
+ SWAPENTRY SwapEntry;
+ ULONG_PTR Entry;
+ BOOLEAN Private;
+ NTSTATUS Status;
+ PFILE_OBJECT FileObject;
+#ifndef NEWCC
+ PROS_SHARED_CACHE_MAP SharedCacheMap = NULL;
+#endif
+ BOOLEAN DirectMapped;
+ BOOLEAN IsImageSection;
+ PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
+
+ Address = (PVOID)PAGE_ROUND_DOWN(Address);
+
+ Offset.QuadPart = (ULONG_PTR)Address - MA_GetStartingAddress(MemoryArea)
+ + MemoryArea->Data.SectionData.ViewOffset.QuadPart;
+
+ /*
+ * Get the segment and section.
+ */
+ Segment = MemoryArea->Data.SectionData.Segment;
+ Section = MemoryArea->Data.SectionData.Section;
+ IsImageSection = Section->AllocationAttributes & SEC_IMAGE ? TRUE : FALSE;
+
+ FileObject = Section->FileObject;
+ DirectMapped = FALSE;
+ if (FileObject != NULL &&
+ !(Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED))
+ {
+#ifndef NEWCC
+ SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
+#endif
+
+ /*
+ * If the file system is letting us go directly to the cache and the
+ * memory area was mapped at an offset in the file which is page aligned
+ * then note this is a direct mapped page.
+ */
+ if (((Offset.QuadPart + Segment->Image.FileOffset) % PAGE_SIZE) == 0 &&
+ (Offset.QuadPart + PAGE_SIZE <= Segment->RawLength.QuadPart || !IsImageSection))
+ {
+ DirectMapped = TRUE;
+ }
+ }
+
+ /*
+ * This should never happen since mappings of physical memory are never
+ * placed in the rmap lists.
+ */
+ if (Section->AllocationAttributes & SEC_PHYSICALMEMORY)
+ {
+ DPRINT1("Trying to write back page from physical memory mapped at %p "
+ "process %p\n", Address,
+ Process ? Process->UniqueProcessId : 0);
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+
+ /*
+ * Get the section segment entry and the physical address.
+ */
+ Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
+ if (!MmIsPagePresent(Process, Address))
+ {
+ DPRINT1("Trying to page out not-present page at (%p,0x%p).\n",
+ Process ? Process->UniqueProcessId : 0, Address);
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+ Page = MmGetPfnForProcess(Process, Address);
+ SwapEntry = MmGetSavedSwapEntryPage(Page);
+
+ /*
+ * Check for a private (COWed) page.
+ */
+ if (IS_SWAP_FROM_SSE(Entry) || PFN_FROM_SSE(Entry) != Page)
+ {
+ Private = TRUE;
+ }
+ else
+ {
+ Private = FALSE;
+ }
+
+ /*
+ * Speculatively set all mappings of the page to clean.
+ */
+ MmSetCleanAllRmaps(Page);
+
+ /*
+ * If this page was direct mapped from the cache then the cache manager
+ * will take care of writing it back to disk.
+ */
+ if (DirectMapped && !Private)
+ {
+ //LARGE_INTEGER SOffset;
+ ASSERT(SwapEntry == 0);
+ //SOffset.QuadPart = Offset.QuadPart + Segment->Image.FileOffset;
#ifndef NEWCC
- CcRosMarkDirtyCacheSegment(Bcb, Offset.LowPart);
+ CcRosMarkDirtyFile(SharedCacheMap, Offset.QuadPart);
#endif
- MmLockSectionSegment(Segment);
- MmSetPageEntrySectionSegment(Segment, &Offset, PageEntry);
- MmUnlockSectionSegment(Segment);
- MiSetPageEvent(NULL, NULL);
- return(STATUS_SUCCESS);
- }
-
- /*
- * If necessary, allocate an entry in the paging file for this page
- */
- if (SwapEntry == 0)
- {
- SwapEntry = MmAllocSwapPage();
- if (SwapEntry == 0)
- {
- MmSetDirtyAllRmaps(Page);
- MiSetPageEvent(NULL, NULL);
- return(STATUS_PAGEFILE_QUOTA);
- }
- MmSetSavedSwapEntryPage(Page, SwapEntry);
- }
-
- /*
- * Write the page to the pagefile
- */
- Status = MmWriteToSwapPage(SwapEntry, Page);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n",
- Status);
- MmSetDirtyAllRmaps(Page);
- MiSetPageEvent(NULL, NULL);
- return(STATUS_UNSUCCESSFUL);
- }
-
- /*
- * Otherwise we have succeeded.
- */
- DPRINT("MM: Wrote section page 0x%.8X to swap!\n", Page << PAGE_SHIFT);
- MiSetPageEvent(NULL, NULL);
- return(STATUS_SUCCESS);
-}
-
-static VOID
-MmAlterViewAttributes(PMMSUPPORT AddressSpace,
- PVOID BaseAddress,
- SIZE_T RegionSize,
- ULONG OldType,
- ULONG OldProtect,
- ULONG NewType,
- ULONG NewProtect)
-{
- PMEMORY_AREA MemoryArea;
- PMM_SECTION_SEGMENT Segment;
- BOOLEAN DoCOW = FALSE;
- ULONG i;
- PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
-
- MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, BaseAddress);
- ASSERT(MemoryArea != NULL);
- Segment = MemoryArea->Data.SectionData.Segment;
- MmLockSectionSegment(Segment);
-
- if ((Segment->WriteCopy) &&
- (NewProtect == PAGE_READWRITE || NewProtect == PAGE_EXECUTE_READWRITE))
- {
- DoCOW = TRUE;
- }
-
- if (OldProtect != NewProtect)
- {
- for (i = 0; i < PAGE_ROUND_UP(RegionSize) / PAGE_SIZE; i++)
- {
- SWAPENTRY SwapEntry;
- PVOID Address = (char*)BaseAddress + (i * PAGE_SIZE);
- ULONG Protect = NewProtect;
-
- /* Wait for a wait entry to disappear */
- do {
- MmGetPageFileMapping(Process, Address, &SwapEntry);
- if (SwapEntry != MM_WAIT_ENTRY)
- break;
- MiWaitForPageEvent(Process, Address);
- } while (TRUE);
-
- /*
- * If we doing COW for this segment then check if the page is
- * already private.
- */
- if (DoCOW && MmIsPagePresent(Process, Address))
- {
- LARGE_INTEGER Offset;
- ULONG_PTR Entry;
- PFN_NUMBER Page;
-
- Offset.QuadPart = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress
- + MemoryArea->Data.SectionData.ViewOffset.QuadPart;
- Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
- /*
- * An MM_WAIT_ENTRY is ok in this case... It'll just count as
- * IS_SWAP_FROM_SSE and we'll do the right thing.
- */
- Page = MmGetPfnForProcess(Process, Address);
+ MmLockSectionSegment(Segment);
+ MmSetPageEntrySectionSegment(Segment, &Offset, PageEntry);
+ MmUnlockSectionSegment(Segment);
+ MiSetPageEvent(NULL, NULL);
+ return(STATUS_SUCCESS);
+ }
- Protect = PAGE_READONLY;
- if (Segment->Image.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ||
- IS_SWAP_FROM_SSE(Entry) ||
- PFN_FROM_SSE(Entry) != Page)
- {
- Protect = NewProtect;
- }
- }
+ /*
+ * If necessary, allocate an entry in the paging file for this page
+ */
+ if (SwapEntry == 0)
+ {
+ SwapEntry = MmAllocSwapPage();
+ if (SwapEntry == 0)
+ {
+ MmSetDirtyAllRmaps(Page);
+ MiSetPageEvent(NULL, NULL);
+ return(STATUS_PAGEFILE_QUOTA);
+ }
+ MmSetSavedSwapEntryPage(Page, SwapEntry);
+ }
- if (MmIsPagePresent(Process, Address) || MmIsDisabledPage(Process, Address))
- {
- MmSetPageProtect(Process, Address,
- Protect);
- }
- }
- }
+ /*
+ * Write the page to the pagefile
+ */
+ Status = MmWriteToSwapPage(SwapEntry, Page);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n",
+ Status);
+ MmSetDirtyAllRmaps(Page);
+ MiSetPageEvent(NULL, NULL);
+ return(STATUS_UNSUCCESSFUL);
+ }
- MmUnlockSectionSegment(Segment);
+ /*
+ * Otherwise we have succeeded.
+ */
+ DPRINT("MM: Wrote section page 0x%.8X to swap!\n", Page << PAGE_SHIFT);
+ MiSetPageEvent(NULL, NULL);
+ return(STATUS_SUCCESS);
}
NTSTATUS
ULONG Protect,
PULONG OldProtect)
{
- PMM_REGION Region;
- NTSTATUS Status;
- ULONG_PTR MaxLength;
-
- MaxLength = (ULONG_PTR)MemoryArea->EndingAddress - (ULONG_PTR)BaseAddress;
- if (Length > MaxLength)
- Length = (ULONG)MaxLength;
-
- Region = MmFindRegion(MemoryArea->StartingAddress,
- &MemoryArea->Data.SectionData.RegionListHead,
- BaseAddress, NULL);
- ASSERT(Region != NULL);
-
- if ((MemoryArea->Flags & SEC_NO_CHANGE) &&
- Region->Protect != Protect)
- {
- return STATUS_INVALID_PAGE_PROTECTION;
- }
-
- *OldProtect = Region->Protect;
- Status = MmAlterRegion(AddressSpace, MemoryArea->StartingAddress,
+ PMM_REGION Region;
+ NTSTATUS Status;
+ ULONG_PTR MaxLength;
+
+ MaxLength = MA_GetEndingAddress(MemoryArea) - (ULONG_PTR)BaseAddress;
+ if (Length > MaxLength)
+ Length = (ULONG)MaxLength;
+
+ Region = MmFindRegion((PVOID)MA_GetStartingAddress(MemoryArea),
&MemoryArea->Data.SectionData.RegionListHead,
- BaseAddress, Length, Region->Type, Protect,
- MmAlterViewAttributes);
+ BaseAddress, NULL);
+ ASSERT(Region != NULL);
+
+ if ((MemoryArea->Flags & SEC_NO_CHANGE) &&
+ Region->Protect != Protect)
+ {
+ return STATUS_INVALID_PAGE_PROTECTION;
+ }
- return(Status);
+ *OldProtect = Region->Protect;
+ Status = MmAlterRegion(AddressSpace, (PVOID)MA_GetStartingAddress(MemoryArea),
+ &MemoryArea->Data.SectionData.RegionListHead,
+ BaseAddress, Length, Region->Type, Protect,
+ MmAlterViewAttributes);
+
+ return(Status);
}
NTSTATUS NTAPI
PMEMORY_BASIC_INFORMATION Info,
PSIZE_T ResultLength)
{
- PMM_REGION Region;
- PVOID RegionBaseAddress;
- PROS_SECTION_OBJECT Section;
- PMM_SECTION_SEGMENT Segment;
-
- Region = MmFindRegion((PVOID)MemoryArea->StartingAddress,
- &MemoryArea->Data.SectionData.RegionListHead,
- Address, &RegionBaseAddress);
- if (Region == NULL)
- {
- return STATUS_UNSUCCESSFUL;
- }
-
- Section = MemoryArea->Data.SectionData.Section;
- if (Section->AllocationAttributes & SEC_IMAGE)
- {
- Segment = MemoryArea->Data.SectionData.Segment;
- Info->AllocationBase = (PUCHAR)MemoryArea->StartingAddress - Segment->Image.VirtualAddress;
- Info->Type = MEM_IMAGE;
- }
- else
- {
- Info->AllocationBase = MemoryArea->StartingAddress;
- Info->Type = MEM_MAPPED;
- }
- Info->BaseAddress = RegionBaseAddress;
- Info->AllocationProtect = MemoryArea->Protect;
- Info->RegionSize = Region->Length;
- Info->State = MEM_COMMIT;
- Info->Protect = Region->Protect;
-
- *ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
- return(STATUS_SUCCESS);
+ PMM_REGION Region;
+ PVOID RegionBaseAddress;
+ PROS_SECTION_OBJECT Section;
+ PMM_SECTION_SEGMENT Segment;
+
+ Region = MmFindRegion((PVOID)MA_GetStartingAddress(MemoryArea),
+ &MemoryArea->Data.SectionData.RegionListHead,
+ Address, &RegionBaseAddress);
+ if (Region == NULL)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ Section = MemoryArea->Data.SectionData.Section;
+ if (Section->AllocationAttributes & SEC_IMAGE)
+ {
+ Segment = MemoryArea->Data.SectionData.Segment;
+ Info->AllocationBase = (PUCHAR)MA_GetStartingAddress(MemoryArea) - Segment->Image.VirtualAddress;
+ Info->Type = MEM_IMAGE;
+ }
+ else
+ {
+ Info->AllocationBase = (PVOID)MA_GetStartingAddress(MemoryArea);
+ Info->Type = MEM_MAPPED;
+ }
+ Info->BaseAddress = RegionBaseAddress;
+ Info->AllocationProtect = MemoryArea->Protect;
+ Info->RegionSize = Region->Length;
+ Info->State = MEM_COMMIT;
+ Info->Protect = Region->Protect;
+
+ *ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
+ return(STATUS_SUCCESS);
}
VOID
NTAPI
MmpFreePageFileSegment(PMM_SECTION_SEGMENT Segment)
{
- ULONG Length;
- LARGE_INTEGER Offset;
- ULONG_PTR Entry;
- SWAPENTRY SavedSwapEntry;
- PFN_NUMBER Page;
-
- Page = 0;
-
- MmLockSectionSegment(Segment);
-
- Length = PAGE_ROUND_UP(Segment->Length.QuadPart);
- for (Offset.QuadPart = 0; Offset.QuadPart < Length; Offset.QuadPart += PAGE_SIZE)
- {
- Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
- if (Entry)
- {
- MmSetPageEntrySectionSegment(Segment, &Offset, 0);
- if (IS_SWAP_FROM_SSE(Entry))
- {
- MmFreeSwapPage(SWAPENTRY_FROM_SSE(Entry));
- }
- else
- {
- Page = PFN_FROM_SSE(Entry);
- SavedSwapEntry = MmGetSavedSwapEntryPage(Page);
- if (SavedSwapEntry != 0)
+ ULONG Length;
+ LARGE_INTEGER Offset;
+ ULONG_PTR Entry;
+ SWAPENTRY SavedSwapEntry;
+ PFN_NUMBER Page;
+
+ Page = 0;
+
+ MmLockSectionSegment(Segment);
+
+ Length = PAGE_ROUND_UP(Segment->Length.QuadPart);
+ for (Offset.QuadPart = 0; Offset.QuadPart < Length; Offset.QuadPart += PAGE_SIZE)
+ {
+ Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
+ if (Entry)
+ {
+ MmSetPageEntrySectionSegment(Segment, &Offset, 0);
+ if (IS_SWAP_FROM_SSE(Entry))
{
- MmSetSavedSwapEntryPage(Page, 0);
- MmFreeSwapPage(SavedSwapEntry);
+ MmFreeSwapPage(SWAPENTRY_FROM_SSE(Entry));
}
- MmReleasePageMemoryConsumer(MC_USER, Page);
- }
- }
- }
+ else
+ {
+ Page = PFN_FROM_SSE(Entry);
+ SavedSwapEntry = MmGetSavedSwapEntryPage(Page);
+ if (SavedSwapEntry != 0)
+ {
+ MmSetSavedSwapEntryPage(Page, 0);
+ MmFreeSwapPage(SavedSwapEntry);
+ }
+ MmReleasePageMemoryConsumer(MC_USER, Page);
+ }
+ }
+ }
- MmUnlockSectionSegment(Segment);
+ MmUnlockSectionSegment(Segment);
}
VOID NTAPI
MmpDeleteSection(PVOID ObjectBody)
{
- PROS_SECTION_OBJECT Section = (PROS_SECTION_OBJECT)ObjectBody;
-
- DPRINT("MmpDeleteSection(ObjectBody %p)\n", ObjectBody);
- if (Section->AllocationAttributes & SEC_IMAGE)
- {
- ULONG i;
- ULONG NrSegments;
- ULONG RefCount;
- PMM_SECTION_SEGMENT SectionSegments;
-
- /*
- * NOTE: Section->ImageSection can be NULL for short time
- * during the section creating. If we fail for some reason
- * until the image section is properly initialized we shouldn't
- * process further here.
- */
- if (Section->ImageSection == NULL)
- return;
-
- SectionSegments = Section->ImageSection->Segments;
- NrSegments = Section->ImageSection->NrSegments;
-
- for (i = 0; i < NrSegments; i++)
- {
- if (SectionSegments[i].Image.Characteristics & IMAGE_SCN_MEM_SHARED)
- {
- MmLockSectionSegment(&SectionSegments[i]);
- }
- RefCount = InterlockedDecrementUL(&SectionSegments[i].ReferenceCount);
- if (SectionSegments[i].Image.Characteristics & IMAGE_SCN_MEM_SHARED)
- {
- MmUnlockSectionSegment(&SectionSegments[i]);
- if (RefCount == 0)
+ PROS_SECTION_OBJECT Section = (PROS_SECTION_OBJECT)ObjectBody;
+
+ /* Check if it's an ARM3, or ReactOS section */
+ if (!MiIsRosSectionObject(Section))
+ {
+ MiDeleteARM3Section(ObjectBody);
+ return;
+ }
+
+ DPRINT("MmpDeleteSection(ObjectBody %p)\n", ObjectBody);
+ if (Section->AllocationAttributes & SEC_IMAGE)
+ {
+ ULONG i;
+ ULONG NrSegments;
+ ULONG RefCount;
+ PMM_SECTION_SEGMENT SectionSegments;
+
+ /*
+ * NOTE: Section->ImageSection can be NULL for short time
+ * during the section creating. If we fail for some reason
+ * until the image section is properly initialized we shouldn't
+ * process further here.
+ */
+ if (Section->ImageSection == NULL)
+ return;
+
+ SectionSegments = Section->ImageSection->Segments;
+ NrSegments = Section->ImageSection->NrSegments;
+
+ for (i = 0; i < NrSegments; i++)
+ {
+ if (SectionSegments[i].Image.Characteristics & IMAGE_SCN_MEM_SHARED)
{
- MmpFreePageFileSegment(&SectionSegments[i]);
+ MmLockSectionSegment(&SectionSegments[i]);
}
- }
- }
- }
+ RefCount = InterlockedDecrementUL(&SectionSegments[i].ReferenceCount);
+ if (SectionSegments[i].Image.Characteristics & IMAGE_SCN_MEM_SHARED)
+ {
+ MmUnlockSectionSegment(&SectionSegments[i]);
+ if (RefCount == 0)
+ {
+ MmpFreePageFileSegment(&SectionSegments[i]);
+ }
+ }
+ }
+ }
#ifdef NEWCC
- else if (Section->Segment && Section->Segment->Flags & MM_DATAFILE_SEGMENT)
- {
- ULONG RefCount = 0;
- PMM_SECTION_SEGMENT Segment = Section->Segment;
-
- if (Segment &&
- (RefCount = InterlockedDecrementUL(&Segment->ReferenceCount)) == 0)
- {
- DPRINT("Freeing section segment\n");
- Section->Segment = NULL;
- MmFinalizeSegment(Segment);
- }
- else
- {
- DPRINT("RefCount %d\n", RefCount);
- }
- }
+ else if (Section->Segment && Section->Segment->Flags & MM_DATAFILE_SEGMENT)
+ {
+ ULONG RefCount = 0;
+ PMM_SECTION_SEGMENT Segment = Section->Segment;
+
+ if (Segment &&
+ (RefCount = InterlockedDecrementUL(&Segment->ReferenceCount)) == 0)
+ {
+ DPRINT("Freeing section segment\n");
+ Section->Segment = NULL;
+ MmFinalizeSegment(Segment);
+ }
+ else
+ {
+ DPRINT("RefCount %d\n", RefCount);
+ }
+ }
#endif
- else
- {
- /*
- * NOTE: Section->Segment can be NULL for short time
- * during the section creating.
- */
- if (Section->Segment == NULL)
- return;
-
- if (Section->Segment->Flags & MM_PAGEFILE_SEGMENT)
- {
- MmpFreePageFileSegment(Section->Segment);
- MmFreePageTablesSectionSegment(Section->Segment, NULL);
- ExFreePool(Section->Segment);
- Section->Segment = NULL;
- }
- else
- {
- (void)InterlockedDecrementUL(&Section->Segment->ReferenceCount);
- }
- }
- if (Section->FileObject != NULL)
- {
+ else
+ {
+ /*
+ * NOTE: Section->Segment can be NULL for short time
+ * during the section creating.
+ */
+ if (Section->Segment == NULL)
+ return;
+
+ if (Section->Segment->Flags & MM_PAGEFILE_SEGMENT)
+ {
+ MmpFreePageFileSegment(Section->Segment);
+ MmFreePageTablesSectionSegment(Section->Segment, NULL);
+ ExFreePool(Section->Segment);
+ Section->Segment = NULL;
+ }
+ else
+ {
+ (void)InterlockedDecrementUL(&Section->Segment->ReferenceCount);
+ }
+ }
+ if (Section->FileObject != NULL)
+ {
#ifndef NEWCC
- CcRosDereferenceCache(Section->FileObject);
+ CcRosDereferenceCache(Section->FileObject);
#endif
- ObDereferenceObject(Section->FileObject);
- Section->FileObject = NULL;
- }
+ ObDereferenceObject(Section->FileObject);
+ Section->FileObject = NULL;
+ }
}
VOID NTAPI
IN ULONG ProcessHandleCount,
IN ULONG SystemHandleCount)
{
- DPRINT("MmpCloseSection(OB %x, HC %d)\n",
- Object, ProcessHandleCount);
+ DPRINT("MmpCloseSection(OB %p, HC %lu)\n", Object, ProcessHandleCount);
}
NTSTATUS
NTAPI
MmCreatePhysicalMemorySection(VOID)
{
- PROS_SECTION_OBJECT PhysSection;
- NTSTATUS Status;
- OBJECT_ATTRIBUTES Obj;
- UNICODE_STRING Name = RTL_CONSTANT_STRING(L"\\Device\\PhysicalMemory");
- LARGE_INTEGER SectionSize;
- HANDLE Handle;
-
- /*
- * Create the section mapping physical memory
- */
- SectionSize.QuadPart = 0xFFFFFFFF;
- InitializeObjectAttributes(&Obj,
- &Name,
- OBJ_PERMANENT,
- NULL,
- NULL);
- Status = MmCreateSection((PVOID)&PhysSection,
+ PROS_SECTION_OBJECT PhysSection;
+ NTSTATUS Status;
+ OBJECT_ATTRIBUTES Obj;
+ UNICODE_STRING Name = RTL_CONSTANT_STRING(L"\\Device\\PhysicalMemory");
+ LARGE_INTEGER SectionSize;
+ HANDLE Handle;
+
+ /*
+ * Create the section mapping physical memory
+ */
+ SectionSize.QuadPart = 0xFFFFFFFF;
+ InitializeObjectAttributes(&Obj,
+ &Name,
+ OBJ_PERMANENT | OBJ_KERNEL_EXCLUSIVE,
+ NULL,
+ NULL);
+ Status = MmCreateSection((PVOID)&PhysSection,
+ SECTION_ALL_ACCESS,
+ &Obj,
+ &SectionSize,
+ PAGE_EXECUTE_READWRITE,
+ SEC_PHYSICALMEMORY,
+ NULL,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to create PhysicalMemory section\n");
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+ Status = ObInsertObject(PhysSection,
+ NULL,
SECTION_ALL_ACCESS,
- &Obj,
- &SectionSize,
- PAGE_EXECUTE_READWRITE,
- SEC_PHYSICALMEMORY,
+ 0,
NULL,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Failed to create PhysicalMemory section\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- Status = ObInsertObject(PhysSection,
- NULL,
- SECTION_ALL_ACCESS,
- 0,
- NULL,
- &Handle);
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject(PhysSection);
- }
- ObCloseHandle(Handle, KernelMode);
- PhysSection->AllocationAttributes |= SEC_PHYSICALMEMORY;
- PhysSection->Segment->Flags &= ~MM_PAGEFILE_SEGMENT;
-
- return(STATUS_SUCCESS);
+ &Handle);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(PhysSection);
+ }
+ ObCloseHandle(Handle, KernelMode);
+ PhysSection->AllocationAttributes |= SEC_PHYSICALMEMORY;
+ PhysSection->Segment->Flags &= ~MM_PAGEFILE_SEGMENT;
+
+ return(STATUS_SUCCESS);
}
NTSTATUS
NTAPI
MmInitSectionImplementation(VOID)
{
- OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
- UNICODE_STRING Name;
-
- DPRINT("Creating Section Object Type\n");
-
- /* Initialize the section based root */
- ASSERT(MmSectionBasedRoot.NumberGenericTableElements == 0);
- MmSectionBasedRoot.BalancedRoot.u1.Parent = &MmSectionBasedRoot.BalancedRoot;
-
- /* Initialize the Section object type */
- RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
- RtlInitUnicodeString(&Name, L"Section");
- ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
- ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(ROS_SECTION_OBJECT);
- ObjectTypeInitializer.PoolType = PagedPool;
- ObjectTypeInitializer.UseDefaultObject = TRUE;
- ObjectTypeInitializer.GenericMapping = MmpSectionMapping;
- ObjectTypeInitializer.DeleteProcedure = MmpDeleteSection;
- ObjectTypeInitializer.CloseProcedure = MmpCloseSection;
- ObjectTypeInitializer.ValidAccessMask = SECTION_ALL_ACCESS;
- ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
- ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &MmSectionObjectType);
-
- MmCreatePhysicalMemorySection();
-
- return(STATUS_SUCCESS);
+ OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
+ UNICODE_STRING Name;
+
+ DPRINT("Creating Section Object Type\n");
+
+ /* Initialize the section based root */
+ ASSERT(MmSectionBasedRoot.NumberGenericTableElements == 0);
+ MmSectionBasedRoot.BalancedRoot.u1.Parent = &MmSectionBasedRoot.BalancedRoot;
+
+ /* Initialize the Section object type */
+ RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
+ RtlInitUnicodeString(&Name, L"Section");
+ ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
+ ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(ROS_SECTION_OBJECT);
+ ObjectTypeInitializer.PoolType = PagedPool;
+ ObjectTypeInitializer.UseDefaultObject = TRUE;
+ ObjectTypeInitializer.GenericMapping = MmpSectionMapping;
+ ObjectTypeInitializer.DeleteProcedure = MmpDeleteSection;
+ ObjectTypeInitializer.CloseProcedure = MmpCloseSection;
+ ObjectTypeInitializer.ValidAccessMask = SECTION_ALL_ACCESS;
+ ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
+ ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &MmSectionObjectType);
+
+ MmCreatePhysicalMemorySection();
+
+ return(STATUS_SUCCESS);
}
NTSTATUS
* Create a section which is backed by the pagefile
*/
{
- LARGE_INTEGER MaximumSize;
- PROS_SECTION_OBJECT Section;
- PMM_SECTION_SEGMENT Segment;
- NTSTATUS Status;
-
- if (UMaximumSize == NULL)
- {
- return(STATUS_UNSUCCESSFUL);
- }
- MaximumSize = *UMaximumSize;
-
- /*
- * Create the section
- */
- Status = ObCreateObject(ExGetPreviousMode(),
- MmSectionObjectType,
- ObjectAttributes,
- ExGetPreviousMode(),
- NULL,
- sizeof(ROS_SECTION_OBJECT),
- 0,
- 0,
- (PVOID*)(PVOID)&Section);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
-
- /*
- * Initialize it
- */
- RtlZeroMemory(Section, sizeof(ROS_SECTION_OBJECT));
- Section->Type = 'SC';
- Section->Size = 'TN';
- Section->SectionPageProtection = SectionPageProtection;
- Section->AllocationAttributes = AllocationAttributes;
- Section->MaximumSize = MaximumSize;
- Segment = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_SECTION_SEGMENT),
- TAG_MM_SECTION_SEGMENT);
- if (Segment == NULL)
- {
- ObDereferenceObject(Section);
- return(STATUS_NO_MEMORY);
- }
- RtlZeroMemory(Segment, sizeof(MM_SECTION_SEGMENT));
- Section->Segment = Segment;
- Segment->ReferenceCount = 1;
- ExInitializeFastMutex(&Segment->Lock);
- Segment->Image.FileOffset = 0;
- Segment->Protection = SectionPageProtection;
- Segment->RawLength.QuadPart = MaximumSize.u.LowPart;
- Segment->Length.QuadPart = PAGE_ROUND_UP(MaximumSize.u.LowPart);
- Segment->Flags = MM_PAGEFILE_SEGMENT;
- Segment->WriteCopy = FALSE;
- Segment->Image.VirtualAddress = 0;
- Segment->Image.Characteristics = 0;
- *SectionObject = Section;
- MiInitializeSectionPageTable(Segment);
- return(STATUS_SUCCESS);
+ LARGE_INTEGER MaximumSize;
+ PROS_SECTION_OBJECT Section;
+ PMM_SECTION_SEGMENT Segment;
+ NTSTATUS Status;
+
+ if (UMaximumSize == NULL)
+ {
+ DPRINT1("MmCreatePageFileSection: (UMaximumSize == NULL)\n");
+ return(STATUS_INVALID_PARAMETER);
+ }
+ MaximumSize = *UMaximumSize;
+
+ /*
+ * Create the section
+ */
+ Status = ObCreateObject(ExGetPreviousMode(),
+ MmSectionObjectType,
+ ObjectAttributes,
+ ExGetPreviousMode(),
+ NULL,
+ sizeof(ROS_SECTION_OBJECT),
+ 0,
+ 0,
+ (PVOID*)(PVOID)&Section);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("MmCreatePageFileSection: failed to create object (0x%lx)\n", Status);
+ return(Status);
+ }
+
+ /*
+ * Initialize it
+ */
+ RtlZeroMemory(Section, sizeof(ROS_SECTION_OBJECT));
+ Section->Type = 'SC';
+ Section->Size = 'TN';
+ Section->SectionPageProtection = SectionPageProtection;
+ Section->AllocationAttributes = AllocationAttributes;
+ Section->MaximumSize = MaximumSize;
+ Segment = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_SECTION_SEGMENT),
+ TAG_MM_SECTION_SEGMENT);
+ if (Segment == NULL)
+ {
+ ObDereferenceObject(Section);
+ return(STATUS_NO_MEMORY);
+ }
+ RtlZeroMemory(Segment, sizeof(MM_SECTION_SEGMENT));
+ Section->Segment = Segment;
+ Segment->ReferenceCount = 1;
+ ExInitializeFastMutex(&Segment->Lock);
+ Segment->Image.FileOffset = 0;
+ Segment->Protection = SectionPageProtection;
+ Segment->RawLength.QuadPart = MaximumSize.u.LowPart;
+ Segment->Length.QuadPart = PAGE_ROUND_UP(MaximumSize.u.LowPart);
+ Segment->Flags = MM_PAGEFILE_SEGMENT;
+ Segment->WriteCopy = FALSE;
+ Segment->Image.VirtualAddress = 0;
+ Segment->Image.Characteristics = 0;
+ *SectionObject = Section;
+ MiInitializeSectionPageTable(Segment);
+ return(STATUS_SUCCESS);
}
NTSTATUS
PLARGE_INTEGER UMaximumSize,
ULONG SectionPageProtection,
ULONG AllocationAttributes,
- HANDLE FileHandle)
+ PFILE_OBJECT FileObject)
/*
* Create a section backed by a data file
*/
{
- PROS_SECTION_OBJECT Section;
- NTSTATUS Status;
- LARGE_INTEGER MaximumSize;
- PFILE_OBJECT FileObject;
- PMM_SECTION_SEGMENT Segment;
- ULONG FileAccess;
- IO_STATUS_BLOCK Iosb;
- LARGE_INTEGER Offset;
- CHAR Buffer;
- FILE_STANDARD_INFORMATION FileInfo;
- ULONG Length;
-
- /*
- * Create the section
- */
- Status = ObCreateObject(ExGetPreviousMode(),
- MmSectionObjectType,
- ObjectAttributes,
- ExGetPreviousMode(),
- NULL,
- sizeof(ROS_SECTION_OBJECT),
- 0,
- 0,
- (PVOID*)&Section);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
- /*
- * Initialize it
- */
- RtlZeroMemory(Section, sizeof(ROS_SECTION_OBJECT));
- Section->Type = 'SC';
- Section->Size = 'TN';
- Section->SectionPageProtection = SectionPageProtection;
- Section->AllocationAttributes = AllocationAttributes;
-
- /*
- * Reference the file handle
- */
- FileAccess = MiArm3GetCorrectFileAccessMask(SectionPageProtection);
- Status = ObReferenceObjectByHandle(FileHandle,
- FileAccess,
- IoFileObjectType,
- ExGetPreviousMode(),
- (PVOID*)(PVOID)&FileObject,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject(Section);
- return(Status);
- }
-
- /*
- * FIXME: This is propably not entirely correct. We can't look into
- * the standard FCB header because it might not be initialized yet
- * (as in case of the EXT2FS driver by Manoj Paul Joseph where the
- * standard file information is filled on first request).
- */
- Status = IoQueryFileInformation(FileObject,
- FileStandardInformation,
- sizeof(FILE_STANDARD_INFORMATION),
- &FileInfo,
- &Length);
- Iosb.Information = Length;
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject(Section);
- ObDereferenceObject(FileObject);
- return Status;
- }
-
- /*
- * FIXME: Revise this once a locking order for file size changes is
- * decided
- */
- if ((UMaximumSize != NULL) && (UMaximumSize->QuadPart != 0))
- {
- MaximumSize = *UMaximumSize;
- }
- else
- {
- MaximumSize = FileInfo.EndOfFile;
- /* Mapping zero-sized files isn't allowed. */
- if (MaximumSize.QuadPart == 0)
- {
- ObDereferenceObject(Section);
- ObDereferenceObject(FileObject);
- return STATUS_FILE_INVALID;
- }
- }
-
- if (MaximumSize.QuadPart > FileInfo.EndOfFile.QuadPart)
- {
- Status = IoSetInformation(FileObject,
- FileAllocationInformation,
- sizeof(LARGE_INTEGER),
- &MaximumSize);
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject(Section);
- ObDereferenceObject(FileObject);
- return(STATUS_SECTION_NOT_EXTENDED);
- }
- }
-
- if (FileObject->SectionObjectPointer == NULL ||
- FileObject->SectionObjectPointer->SharedCacheMap == NULL)
- {
- /*
- * Read a bit so caching is initiated for the file object.
- * This is only needed because MiReadPage currently cannot
- * handle non-cached streams.
- */
- Offset.QuadPart = 0;
- Status = ZwReadFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &Iosb,
- &Buffer,
- sizeof (Buffer),
- &Offset,
- 0);
- if (!NT_SUCCESS(Status) && (Status != STATUS_END_OF_FILE))
- {
- ObDereferenceObject(Section);
- ObDereferenceObject(FileObject);
- return(Status);
- }
- if (FileObject->SectionObjectPointer == NULL ||
+ PROS_SECTION_OBJECT Section;
+ NTSTATUS Status;
+ LARGE_INTEGER MaximumSize;
+ PMM_SECTION_SEGMENT Segment;
+ FILE_STANDARD_INFORMATION FileInfo;
+ ULONG Length;
+
+ /*
+ * Create the section
+ */
+ Status = ObCreateObject(ExGetPreviousMode(),
+ MmSectionObjectType,
+ ObjectAttributes,
+ ExGetPreviousMode(),
+ NULL,
+ sizeof(ROS_SECTION_OBJECT),
+ 0,
+ 0,
+ (PVOID*)&Section);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(FileObject);
+ return(Status);
+ }
+ /*
+ * Initialize it
+ */
+ RtlZeroMemory(Section, sizeof(ROS_SECTION_OBJECT));
+ Section->Type = 'SC';
+ Section->Size = 'TN';
+ Section->SectionPageProtection = SectionPageProtection;
+ Section->AllocationAttributes = AllocationAttributes;
+
+ /*
+ * FIXME: This is propably not entirely correct. We can't look into
+ * the standard FCB header because it might not be initialized yet
+ * (as in case of the EXT2FS driver by Manoj Paul Joseph where the
+ * standard file information is filled on first request).
+ */
+ Status = IoQueryFileInformation(FileObject,
+ FileStandardInformation,
+ sizeof(FILE_STANDARD_INFORMATION),
+ &FileInfo,
+ &Length);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(Section);
+ ObDereferenceObject(FileObject);
+ return Status;
+ }
+
+ /*
+ * FIXME: Revise this once a locking order for file size changes is
+ * decided
+ */
+ if ((UMaximumSize != NULL) && (UMaximumSize->QuadPart != 0))
+ {
+ MaximumSize = *UMaximumSize;
+ }
+ else
+ {
+ MaximumSize = FileInfo.EndOfFile;
+ /* Mapping zero-sized files isn't allowed. */
+ if (MaximumSize.QuadPart == 0)
+ {
+ ObDereferenceObject(Section);
+ ObDereferenceObject(FileObject);
+ return STATUS_MAPPED_FILE_SIZE_ZERO;
+ }
+ }
+
+ if (MaximumSize.QuadPart > FileInfo.EndOfFile.QuadPart)
+ {
+ Status = IoSetInformation(FileObject,
+ FileEndOfFileInformation,
+ sizeof(LARGE_INTEGER),
+ &MaximumSize);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(Section);
+ ObDereferenceObject(FileObject);
+ return(STATUS_SECTION_NOT_EXTENDED);
+ }
+ }
+
+ if (FileObject->SectionObjectPointer == NULL ||
FileObject->SectionObjectPointer->SharedCacheMap == NULL)
- {
- /* FIXME: handle this situation */
- ObDereferenceObject(Section);
- ObDereferenceObject(FileObject);
- return STATUS_INVALID_PARAMETER;
- }
- }
-
- /*
- * Lock the file
- */
- Status = MmspWaitForFileLock(FileObject);
- if (Status != STATUS_SUCCESS)
- {
- ObDereferenceObject(Section);
- ObDereferenceObject(FileObject);
- return(Status);
- }
-
- /*
- * 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)
- {
- Segment = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_SECTION_SEGMENT),
- TAG_MM_SECTION_SEGMENT);
- if (Segment == NULL)
- {
- //KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
- ObDereferenceObject(Section);
- ObDereferenceObject(FileObject);
- return(STATUS_NO_MEMORY);
- }
- Section->Segment = Segment;
- Segment->ReferenceCount = 1;
- ExInitializeFastMutex(&Segment->Lock);
- /*
- * Set the lock before assigning the segment to the file object
- */
- ExAcquireFastMutex(&Segment->Lock);
- FileObject->SectionObjectPointer->DataSectionObject = (PVOID)Segment;
-
- Segment->Image.FileOffset = 0;
- Segment->Protection = SectionPageProtection;
- Segment->Flags = MM_DATAFILE_SEGMENT;
- Segment->Image.Characteristics = 0;
- Segment->WriteCopy = (SectionPageProtection & (PAGE_WRITECOPY | PAGE_EXECUTE_WRITECOPY));
- if (AllocationAttributes & SEC_RESERVE)
- {
- Segment->Length.QuadPart = Segment->RawLength.QuadPart = 0;
- }
- else
- {
- Segment->RawLength.QuadPart = MaximumSize.QuadPart;
- Segment->Length.QuadPart = PAGE_ROUND_UP(Segment->RawLength.QuadPart);
- }
- Segment->Image.VirtualAddress = 0;
- Segment->Locked = TRUE;
- MiInitializeSectionPageTable(Segment);
- }
- else
- {
- /*
- * If the file is already mapped as a data file then we may need
- * to extend it
- */
- Segment =
- (PMM_SECTION_SEGMENT)FileObject->SectionObjectPointer->
- DataSectionObject;
- Section->Segment = Segment;
- (void)InterlockedIncrementUL(&Segment->ReferenceCount);
- MmLockSectionSegment(Segment);
-
- if (MaximumSize.QuadPart > Segment->RawLength.QuadPart &&
- !(AllocationAttributes & SEC_RESERVE))
- {
- Segment->RawLength.QuadPart = MaximumSize.QuadPart;
- Segment->Length.QuadPart = PAGE_ROUND_UP(Segment->RawLength.QuadPart);
- }
- }
- MmUnlockSectionSegment(Segment);
- Section->FileObject = FileObject;
- Section->MaximumSize = MaximumSize;
+ {
+ ObDereferenceObject(Section);
+ ObDereferenceObject(FileObject);
+ return STATUS_INVALID_FILE_FOR_SECTION;
+ }
+
+ /*
+ * Lock the file
+ */
+ Status = MmspWaitForFileLock(FileObject);
+ if (Status != STATUS_SUCCESS)
+ {
+ ObDereferenceObject(Section);
+ ObDereferenceObject(FileObject);
+ return(Status);
+ }
+
+ /*
+ * 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)
+ {
+ Segment = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_SECTION_SEGMENT),
+ TAG_MM_SECTION_SEGMENT);
+ if (Segment == NULL)
+ {
+ //KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
+ ObDereferenceObject(Section);
+ ObDereferenceObject(FileObject);
+ return(STATUS_NO_MEMORY);
+ }
+ Section->Segment = Segment;
+ Segment->ReferenceCount = 1;
+ ExInitializeFastMutex(&Segment->Lock);
+ /*
+ * Set the lock before assigning the segment to the file object
+ */
+ ExAcquireFastMutex(&Segment->Lock);
+ FileObject->SectionObjectPointer->DataSectionObject = (PVOID)Segment;
+
+ Segment->Image.FileOffset = 0;
+ Segment->Protection = SectionPageProtection;
+ Segment->Flags = MM_DATAFILE_SEGMENT;
+ Segment->Image.Characteristics = 0;
+ Segment->WriteCopy = (SectionPageProtection & (PAGE_WRITECOPY | PAGE_EXECUTE_WRITECOPY));
+ if (AllocationAttributes & SEC_RESERVE)
+ {
+ Segment->Length.QuadPart = Segment->RawLength.QuadPart = 0;
+ }
+ else
+ {
+ Segment->RawLength.QuadPart = MaximumSize.QuadPart;
+ Segment->Length.QuadPart = PAGE_ROUND_UP(Segment->RawLength.QuadPart);
+ }
+ Segment->Image.VirtualAddress = 0;
+ Segment->Locked = TRUE;
+ MiInitializeSectionPageTable(Segment);
+ }
+ else
+ {
+ /*
+ * If the file is already mapped as a data file then we may need
+ * to extend it
+ */
+ Segment =
+ (PMM_SECTION_SEGMENT)FileObject->SectionObjectPointer->
+ DataSectionObject;
+ Section->Segment = Segment;
+ (void)InterlockedIncrementUL(&Segment->ReferenceCount);
+ MmLockSectionSegment(Segment);
+
+ if (MaximumSize.QuadPart > Segment->RawLength.QuadPart &&
+ !(AllocationAttributes & SEC_RESERVE))
+ {
+ Segment->RawLength.QuadPart = MaximumSize.QuadPart;
+ Segment->Length.QuadPart = PAGE_ROUND_UP(Segment->RawLength.QuadPart);
+ }
+ }
+ MmUnlockSectionSegment(Segment);
+ Section->FileObject = FileObject;
+ Section->MaximumSize = MaximumSize;
#ifndef NEWCC
- CcRosReferenceCache(FileObject);
+ CcRosReferenceCache(FileObject);
#endif
- //KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
- *SectionObject = Section;
- return(STATUS_SUCCESS);
+ //KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
+ *SectionObject = Section;
+ return(STATUS_SUCCESS);
}
/*
*/
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
+ 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
+ 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,
+ PeFmtCreateSection,
#ifdef __ELF
- ElfFmtCreateSection
+ ElfFmtCreateSection
#endif
};
NTAPI
ExeFmtpAllocateSegments(IN ULONG NrSegments)
{
- SIZE_T SizeOfSegments;
- PMM_SECTION_SEGMENT Segments;
+ SIZE_T SizeOfSegments;
+ PMM_SECTION_SEGMENT Segments;
- /* TODO: check for integer overflow */
- SizeOfSegments = sizeof(MM_SECTION_SEGMENT) * NrSegments;
+ /* TODO: check for integer overflow */
+ SizeOfSegments = sizeof(MM_SECTION_SEGMENT) * NrSegments;
- Segments = ExAllocatePoolWithTag(NonPagedPool,
- SizeOfSegments,
- TAG_MM_SECTION_SEGMENT);
+ Segments = ExAllocatePoolWithTag(NonPagedPool,
+ SizeOfSegments,
+ TAG_MM_SECTION_SEGMENT);
- if(Segments)
- RtlZeroMemory(Segments, SizeOfSegments);
+ if(Segments)
+ RtlZeroMemory(Segments, SizeOfSegments);
- return Segments;
+ return Segments;
}
static
OUT PVOID * AllocBase,
OUT PULONG ReadSize)
{
- NTSTATUS Status;
- LARGE_INTEGER FileOffset;
- ULONG AdjustOffset;
- ULONG OffsetAdjustment;
- ULONG BufferSize;
- ULONG UsedSize;
- PVOID Buffer;
- PFILE_OBJECT FileObject = File;
- IO_STATUS_BLOCK Iosb;
-
- ASSERT_IRQL_LESS(DISPATCH_LEVEL);
-
- if(Length == 0)
- {
- KeBugCheck(MEMORY_MANAGEMENT);
- }
-
- FileOffset = *Offset;
-
- /* Negative/special offset: it cannot be used in this context */
- if(FileOffset.u.HighPart < 0)
- {
- KeBugCheck(MEMORY_MANAGEMENT);
- }
-
- 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,
- 'rXmM');
- if (!Buffer)
- {
- KeBugCheck(MEMORY_MANAGEMENT);
- }
-
- UsedSize = 0;
-
- Status = MiSimpleRead(FileObject, &FileOffset, Buffer, BufferSize, TRUE, &Iosb);
-
- UsedSize = (ULONG)Iosb.Information;
-
- 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
- {
- ExFreePoolWithTag(Buffer, 'rXmM');
- }
-
- return Status;
+ NTSTATUS Status;
+ LARGE_INTEGER FileOffset;
+ ULONG AdjustOffset;
+ ULONG OffsetAdjustment;
+ ULONG BufferSize;
+ ULONG UsedSize;
+ PVOID Buffer;
+ PFILE_OBJECT FileObject = File;
+ IO_STATUS_BLOCK Iosb;
+
+ ASSERT_IRQL_LESS(DISPATCH_LEVEL);
+
+ if(Length == 0)
+ {
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+
+ FileOffset = *Offset;
+
+ /* Negative/special offset: it cannot be used in this context */
+ if(FileOffset.u.HighPart < 0)
+ {
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+
+ AdjustOffset = PAGE_ROUND_DOWN(FileOffset.u.LowPart);
+ OffsetAdjustment = FileOffset.u.LowPart - AdjustOffset;
+ FileOffset.u.LowPart = AdjustOffset;
+
+ BufferSize = Length + OffsetAdjustment;
+ BufferSize = PAGE_ROUND_UP(BufferSize);
+
+ /* Flush data since we're about to perform a non-cached read */
+ CcFlushCache(FileObject->SectionObjectPointer,
+ &FileOffset,
+ BufferSize,
+ &Iosb);
+
+ /*
+ * It's ok to use paged pool, because this is a temporary buffer only used in
+ * the loading of executables. The assumption is that MmCreateSection is
+ * always called at low IRQLs and that these buffers don't survive a brief
+ * initialization phase
+ */
+ Buffer = ExAllocatePoolWithTag(PagedPool,
+ BufferSize,
+ 'rXmM');
+ if (!Buffer)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ UsedSize = 0;
+
+ Status = MiSimpleRead(FileObject, &FileOffset, Buffer, BufferSize, TRUE, &Iosb);
+
+ UsedSize = (ULONG)Iosb.Information;
+
+ 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
+ {
+ ExFreePoolWithTag(Buffer, 'rXmM');
+ }
+
+ return Status;
}
#ifdef NASSERT
NTAPI
MmspAssertSegmentsSorted(IN PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
{
- ULONG i;
+ ULONG i;
- for( i = 1; i < ImageSectionObject->NrSegments; ++ i )
- {
- ASSERT(ImageSectionObject->Segments[i].Image.VirtualAddress >=
- ImageSectionObject->Segments[i - 1].Image.VirtualAddress);
- }
+ for( i = 1; i < ImageSectionObject->NrSegments; ++ i )
+ {
+ ASSERT(ImageSectionObject->Segments[i].Image.VirtualAddress >=
+ ImageSectionObject->Segments[i - 1].Image.VirtualAddress);
+ }
}
static
NTAPI
MmspAssertSegmentsNoOverlap(IN PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
{
- ULONG i;
+ ULONG i;
- MmspAssertSegmentsSorted(ImageSectionObject);
+ MmspAssertSegmentsSorted(ImageSectionObject);
- for( i = 0; i < ImageSectionObject->NrSegments; ++ i )
- {
- ASSERT(ImageSectionObject->Segments[i].Length.QuadPart > 0);
+ for( i = 0; i < ImageSectionObject->NrSegments; ++ i )
+ {
+ ASSERT(ImageSectionObject->Segments[i].Length.QuadPart > 0);
- if(i > 0)
- {
- ASSERT(ImageSectionObject->Segments[i].Image.VirtualAddress >=
- (ImageSectionObject->Segments[i - 1].Image.VirtualAddress +
- ImageSectionObject->Segments[i - 1].Length.QuadPart));
- }
- }
+ if(i > 0)
+ {
+ ASSERT(ImageSectionObject->Segments[i].Image.VirtualAddress >=
+ (ImageSectionObject->Segments[i - 1].Image.VirtualAddress +
+ ImageSectionObject->Segments[i - 1].Length.QuadPart));
+ }
+ }
}
static
NTAPI
MmspAssertSegmentsPageAligned(IN PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
{
- ULONG i;
+ ULONG i;
- for( i = 0; i < ImageSectionObject->NrSegments; ++ i )
- {
- ASSERT((ImageSectionObject->Segments[i].Image.VirtualAddress % PAGE_SIZE) == 0);
- ASSERT((ImageSectionObject->Segments[i].Length.QuadPart % PAGE_SIZE) == 0);
- }
+ for( i = 0; i < ImageSectionObject->NrSegments; ++ i )
+ {
+ ASSERT((ImageSectionObject->Segments[i].Image.VirtualAddress % PAGE_SIZE) == 0);
+ ASSERT((ImageSectionObject->Segments[i].Length.QuadPart % PAGE_SIZE) == 0);
+ }
}
#endif
MmspCompareSegments(const void * x,
const void * y)
{
- const MM_SECTION_SEGMENT *Segment1 = (const MM_SECTION_SEGMENT *)x;
- const MM_SECTION_SEGMENT *Segment2 = (const MM_SECTION_SEGMENT *)y;
+ const MM_SECTION_SEGMENT *Segment1 = (const MM_SECTION_SEGMENT *)x;
+ const MM_SECTION_SEGMENT *Segment2 = (const MM_SECTION_SEGMENT *)y;
- return
- (Segment1->Image.VirtualAddress - Segment2->Image.VirtualAddress) >>
- ((sizeof(ULONG_PTR) - sizeof(int)) * 8);
+ return
+ (Segment1->Image.VirtualAddress - Segment2->Image.VirtualAddress) >>
+ ((sizeof(ULONG_PTR) - sizeof(int)) * 8);
}
/*
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);
- }
+ if (Flags & EXEFMT_LOAD_ASSUME_SEGMENTS_SORTED)
+ {
+ MmspAssertSegmentsSorted(ImageSectionObject);
+ }
+ else
+ {
+ qsort(ImageSectionObject->Segments,
+ ImageSectionObject->NrSegments,
+ sizeof(ImageSectionObject->Segments[0]),
+ MmspCompareSegments);
+ }
}
NTAPI
MmspCheckSegmentBounds
(
- IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
- IN ULONG Flags
+ 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.QuadPart == 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].Image.VirtualAddress +
- ImageSectionObject->Segments[i - 1].Length.QuadPart) !=
- ImageSectionObject->Segments[i].Image.VirtualAddress)
- {
+ 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.QuadPart == 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].Image.VirtualAddress +
+ ImageSectionObject->Segments[i - 1].Length.QuadPart) !=
+ ImageSectionObject->Segments[i].Image.VirtualAddress)
+ {
+ return FALSE;
+ }
+ }
+ }
- return TRUE;
+ return TRUE;
}
/*
NTAPI
MmspPageAlignSegments
(
- IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
- IN ULONG Flags
+ IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
+ IN ULONG Flags
)
{
- ULONG i;
- ULONG LastSegment;
- PMM_SECTION_SEGMENT EffectiveSegment;
-
- if (Flags & EXEFMT_LOAD_ASSUME_SEGMENTS_PAGE_ALIGNED)
- {
- MmspAssertSegmentsPageAligned(ImageSectionObject);
- return TRUE;
- }
-
- LastSegment = 0;
- EffectiveSegment = &ImageSectionObject->Segments[LastSegment];
-
- for ( i = 0; i < ImageSectionObject->NrSegments; ++ i )
- {
- /*
- * The first segment requires special handling
- */
- if (i == 0)
- {
- ULONG_PTR VirtualAddress;
- ULONG_PTR VirtualOffset;
-
- VirtualAddress = EffectiveSegment->Image.VirtualAddress;
-
- /* Round down the virtual address to the nearest page */
- EffectiveSegment->Image.VirtualAddress = PAGE_ROUND_DOWN(VirtualAddress);
-
- /* Round up the virtual size to the nearest page */
- EffectiveSegment->Length.QuadPart = PAGE_ROUND_UP(VirtualAddress + EffectiveSegment->Length.QuadPart) -
- EffectiveSegment->Image.VirtualAddress;
-
- /* Adjust the raw address and size */
- VirtualOffset = VirtualAddress - EffectiveSegment->Image.VirtualAddress;
-
- if (EffectiveSegment->Image.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->Image.FileOffset -= VirtualOffset;
- EffectiveSegment->RawLength.QuadPart += VirtualOffset;
- }
- else
- {
- PMM_SECTION_SEGMENT Segment = &ImageSectionObject->Segments[i];
- ULONG_PTR EndOfEffectiveSegment;
-
- EndOfEffectiveSegment = (ULONG_PTR)(EffectiveSegment->Image.VirtualAddress + EffectiveSegment->Length.QuadPart);
- 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->Image.VirtualAddress)
- {
- LastSegment ++;
- ASSERT(LastSegment <= i);
- ASSERT(LastSegment < ImageSectionObject->NrSegments);
-
- EffectiveSegment = &ImageSectionObject->Segments[LastSegment];
-
- if (LastSegment != i)
+ ULONG i;
+ ULONG LastSegment;
+ PMM_SECTION_SEGMENT EffectiveSegment;
+
+ if (Flags & EXEFMT_LOAD_ASSUME_SEGMENTS_PAGE_ALIGNED)
+ {
+ MmspAssertSegmentsPageAligned(ImageSectionObject);
+ return TRUE;
+ }
+
+ LastSegment = 0;
+ EffectiveSegment = &ImageSectionObject->Segments[LastSegment];
+
+ for ( i = 0; i < ImageSectionObject->NrSegments; ++ i )
+ {
+ /*
+ * The first segment requires special handling
+ */
+ if (i == 0)
+ {
+ ULONG_PTR VirtualAddress;
+ ULONG_PTR VirtualOffset;
+
+ VirtualAddress = EffectiveSegment->Image.VirtualAddress;
+
+ /* Round down the virtual address to the nearest page */
+ EffectiveSegment->Image.VirtualAddress = PAGE_ROUND_DOWN(VirtualAddress);
+
+ /* Round up the virtual size to the nearest page */
+ EffectiveSegment->Length.QuadPart = PAGE_ROUND_UP(VirtualAddress + EffectiveSegment->Length.QuadPart) -
+ EffectiveSegment->Image.VirtualAddress;
+
+ /* Adjust the raw address and size */
+ VirtualOffset = VirtualAddress - EffectiveSegment->Image.VirtualAddress;
+
+ if (EffectiveSegment->Image.FileOffset < VirtualOffset)
{
- /*
- * Copy the current segment. If necessary, the effective segment
- * will be expanded later
- */
- *EffectiveSegment = *Segment;
+ return FALSE;
}
/*
- * Page-align the virtual size. We know for sure the virtual address
- * already is
+ * 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
*/
- ASSERT((EffectiveSegment->Image.VirtualAddress % PAGE_SIZE) == 0);
- EffectiveSegment->Length.QuadPart = PAGE_ROUND_UP(EffectiveSegment->Length.QuadPart);
- }
- /*
- * The current segment is still part of the current effective segment:
- * extend the effective segment to reflect this
- */
- else if (EndOfEffectiveSegment > Segment->Image.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;
+ EffectiveSegment->Image.FileOffset -= VirtualOffset;
+ EffectiveSegment->RawLength.QuadPart += VirtualOffset;
+ }
+ else
+ {
+ PMM_SECTION_SEGMENT Segment = &ImageSectionObject->Segments[i];
+ ULONG_PTR EndOfEffectiveSegment;
+
+ EndOfEffectiveSegment = (ULONG_PTR)(EffectiveSegment->Image.VirtualAddress + EffectiveSegment->Length.QuadPart);
+ ASSERT((EndOfEffectiveSegment % PAGE_SIZE) == 0);
/*
- * Extend the file size
+ * The current segment begins exactly where the current effective
+ * segment ended, therefore beginning a new effective segment
*/
-
- /* Unaligned segments must be contiguous within the file */
- if (Segment->Image.FileOffset != (EffectiveSegment->Image.FileOffset +
- EffectiveSegment->RawLength.QuadPart))
+ if (EndOfEffectiveSegment == Segment->Image.VirtualAddress)
{
- return FALSE;
+ LastSegment ++;
+ ASSERT(LastSegment <= i);
+ ASSERT(LastSegment < ImageSectionObject->NrSegments);
+
+ EffectiveSegment = &ImageSectionObject->Segments[LastSegment];
+
+ if (LastSegment != i)
+ {
+ /*
+ * 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->Image.VirtualAddress % PAGE_SIZE) == 0);
+ EffectiveSegment->Length.QuadPart = PAGE_ROUND_UP(EffectiveSegment->Length.QuadPart);
}
-
- EffectiveSegment->RawLength.QuadPart += Segment->RawLength.QuadPart;
-
/*
- * Extend the virtual size
+ * The current segment is still part of the current effective segment:
+ * extend the effective segment to reflect this
*/
- ASSERT(PAGE_ROUND_UP(Segment->Image.VirtualAddress + Segment->Length.QuadPart) >= EndOfEffectiveSegment);
-
- EffectiveSegment->Length.QuadPart = PAGE_ROUND_UP(Segment->Image.VirtualAddress + Segment->Length.QuadPart) -
- EffectiveSegment->Image.VirtualAddress;
-
+ else if (EndOfEffectiveSegment > Segment->Image.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->Image.FileOffset != (EffectiveSegment->Image.FileOffset +
+ EffectiveSegment->RawLength.QuadPart))
+ {
+ return FALSE;
+ }
+
+ EffectiveSegment->RawLength.QuadPart += Segment->RawLength.QuadPart;
+
+ /*
+ * Extend the virtual size
+ */
+ ASSERT(PAGE_ROUND_UP(Segment->Image.VirtualAddress + Segment->Length.QuadPart) >= EndOfEffectiveSegment);
+
+ EffectiveSegment->Length.QuadPart = PAGE_ROUND_UP(Segment->Image.VirtualAddress + Segment->Length.QuadPart) -
+ EffectiveSegment->Image.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;
+ }
+ }
/*
- * Merge the protection
+ * We assume no holes between segments at this point
*/
- EffectiveSegment->Protection |= Segment->Protection;
+ else
+ {
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+ }
+ }
+ ImageSectionObject->NrSegments = LastSegment + 1;
+
+ return TRUE;
+}
- /* Clean up redundance */
- ProtectionFlags = 0;
+NTSTATUS
+ExeFmtpCreateImageSection(PFILE_OBJECT FileObject,
+ 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;
- if(EffectiveSegment->Protection & PAGE_IS_READABLE)
- ProtectionFlags |= 1 << 0;
+ Status = ExeFmtpReadFile (FileObject,
+ &Offset,
+ PAGE_SIZE * 2,
+ &FileHeader,
+ &FileHeaderBuffer,
+ &FileHeaderSize);
- if(EffectiveSegment->Protection & PAGE_IS_WRITABLE)
- ProtectionFlags |= 1 << 1;
+ if (!NT_SUCCESS(Status))
+ return Status;
- if(EffectiveSegment->Protection & PAGE_IS_EXECUTABLE)
- ProtectionFlags |= 1 << 2;
+ if (FileHeaderSize == 0)
+ {
+ ExFreePool(FileHeaderBuffer);
+ return STATUS_UNSUCCESSFUL;
+ }
- if(EffectiveSegment->Protection & PAGE_IS_WRITECOPY)
- ProtectionFlags |= 1 << 3;
+ /*
+ * Look for a loader that can handle this executable
+ */
+ for (i = 0; i < RTL_NUMBER_OF(ExeFmtpLoaders); ++ i)
+ {
+ RtlZeroMemory(ImageSectionObject, sizeof(*ImageSectionObject));
+ Flags = 0;
- ASSERT(ProtectionFlags < 16);
- EffectiveSegment->Protection = FlagsToProtection[ProtectionFlags];
+ Status = ExeFmtpLoaders[i](FileHeader,
+ FileHeaderSize,
+ FileObject,
+ ImageSectionObject,
+ &Flags,
+ ExeFmtpReadFile,
+ ExeFmtpAllocateSegments);
- /* If a segment was required to be shared and cannot, fail */
- if(!(Segment->Protection & PAGE_IS_WRITECOPY) &&
- EffectiveSegment->Protection & PAGE_IS_WRITECOPY)
+ if (!NT_SUCCESS(Status))
+ {
+ if (ImageSectionObject->Segments)
{
- return FALSE;
+ ExFreePool(ImageSectionObject->Segments);
+ ImageSectionObject->Segments = NULL;
}
- }
- /*
- * We assume no holes between segments at this point
- */
- else
- {
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- }
- }
- ImageSectionObject->NrSegments = LastSegment + 1;
+ }
- return TRUE;
-}
+ if (Status != STATUS_ROS_EXEFMT_UNKNOWN_FORMAT)
+ break;
+ }
-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;
- }
-
- ExFreePoolWithTag(FileHeaderBuffer, 'rXmM');
-
- /*
- * No loader handled the format
- */
- if (Status == STATUS_ROS_EXEFMT_UNKNOWN_FORMAT)
- {
- Status = STATUS_INVALID_IMAGE_NOT_MZ;
- 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(PagedPool,
- 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;
- MiInitializeSectionPageTable(&ImageSectionObject->Segments[i]);
- }
-
- ASSERT(NT_SUCCESS(Status));
- return Status;
+ ExFreePoolWithTag(FileHeaderBuffer, 'rXmM');
+
+ /*
+ * No loader handled the format
+ */
+ if (Status == STATUS_ROS_EXEFMT_UNKNOWN_FORMAT)
+ {
+ Status = STATUS_INVALID_IMAGE_NOT_MZ;
+ ASSERT(!NT_SUCCESS(Status));
+ }
+
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ ASSERT(ImageSectionObject->Segments != NULL);
+
+ /*
+ * Some defaults
+ */
+ /* FIXME? are these values platform-dependent? */
+ if (ImageSectionObject->ImageInformation.MaximumStackSize == 0)
+ ImageSectionObject->ImageInformation.MaximumStackSize = 0x40000;
+
+ if(ImageSectionObject->ImageInformation.CommittedStackSize == 0)
+ ImageSectionObject->ImageInformation.CommittedStackSize = 0x1000;
+
+ if(ImageSectionObject->BasedAddress == NULL)
+ {
+ if(ImageSectionObject->ImageInformation.ImageCharacteristics & IMAGE_FILE_DLL)
+ ImageSectionObject->BasedAddress = (PVOID)0x10000000;
+ else
+ ImageSectionObject->BasedAddress = (PVOID)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(PagedPool,
+ 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;
+ MiInitializeSectionPageTable(&ImageSectionObject->Segments[i]);
+ }
+
+ ASSERT(NT_SUCCESS(Status));
+ return Status;
}
NTSTATUS
ULONG AllocationAttributes,
PFILE_OBJECT FileObject)
{
- PROS_SECTION_OBJECT Section;
- NTSTATUS Status;
- PMM_SECTION_SEGMENT SectionSegments;
- PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
- ULONG i;
-
- if (FileObject == NULL)
- return STATUS_INVALID_FILE_FOR_SECTION;
-
- /*
- * Create the section
- */
- Status = ObCreateObject (ExGetPreviousMode(),
- MmSectionObjectType,
- ObjectAttributes,
- ExGetPreviousMode(),
- NULL,
- sizeof(ROS_SECTION_OBJECT),
- 0,
- 0,
- (PVOID*)(PVOID)&Section);
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject(FileObject);
- return(Status);
- }
-
- /*
- * Initialize it
- */
- RtlZeroMemory(Section, sizeof(ROS_SECTION_OBJECT));
- Section->Type = 'SC';
- Section->Size = 'TN';
- Section->SectionPageProtection = SectionPageProtection;
- Section->AllocationAttributes = AllocationAttributes;
+ PROS_SECTION_OBJECT Section;
+ NTSTATUS Status;
+ PMM_SECTION_SEGMENT SectionSegments;
+ PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
+ ULONG i;
+
+ if (FileObject == NULL)
+ return STATUS_INVALID_FILE_FOR_SECTION;
#ifndef NEWCC
- /*
- * Initialized caching for this file object if previously caching
- * was initialized for the same on disk file
- */
- Status = CcTryToInitializeFileCache(FileObject);
-#else
- Status = STATUS_SUCCESS;
+ if (!CcIsFileCached(FileObject))
+ {
+ DPRINT1("Denying section creation due to missing cache initialization\n");
+ return STATUS_INVALID_FILE_FOR_SECTION;
+ }
#endif
- if (!NT_SUCCESS(Status) || FileObject->SectionObjectPointer->ImageSectionObject == NULL)
- {
- NTSTATUS StatusExeFmt;
+ /*
+ * Create the section
+ */
+ Status = ObCreateObject (ExGetPreviousMode(),
+ MmSectionObjectType,
+ ObjectAttributes,
+ ExGetPreviousMode(),
+ NULL,
+ sizeof(ROS_SECTION_OBJECT),
+ 0,
+ 0,
+ (PVOID*)(PVOID)&Section);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(FileObject);
+ return(Status);
+ }
+
+ /*
+ * Initialize it
+ */
+ RtlZeroMemory(Section, sizeof(ROS_SECTION_OBJECT));
+ Section->Type = 'SC';
+ Section->Size = 'TN';
+ Section->SectionPageProtection = SectionPageProtection;
+ Section->AllocationAttributes = AllocationAttributes;
+
+ if (FileObject->SectionObjectPointer->ImageSectionObject == NULL)
+ {
+ NTSTATUS StatusExeFmt;
+
+ ImageSectionObject = ExAllocatePoolWithTag(PagedPool, sizeof(MM_IMAGE_SECTION_OBJECT), TAG_MM_SECTION_SEGMENT);
+ if (ImageSectionObject == NULL)
+ {
+ ObDereferenceObject(FileObject);
+ ObDereferenceObject(Section);
+ return(STATUS_NO_MEMORY);
+ }
+
+ RtlZeroMemory(ImageSectionObject, sizeof(MM_IMAGE_SECTION_OBJECT));
+
+ StatusExeFmt = ExeFmtpCreateImageSection(FileObject, ImageSectionObject);
+
+ if (!NT_SUCCESS(StatusExeFmt))
+ {
+ if(ImageSectionObject->Segments != NULL)
+ ExFreePool(ImageSectionObject->Segments);
+
+ /*
+ * If image file is empty, then return that the file is invalid for section
+ */
+ Status = StatusExeFmt;
+ if (StatusExeFmt == STATUS_END_OF_FILE)
+ {
+ Status = STATUS_INVALID_FILE_FOR_SECTION;
+ }
- ImageSectionObject = ExAllocatePoolWithTag(PagedPool, sizeof(MM_IMAGE_SECTION_OBJECT), TAG_MM_SECTION_SEGMENT);
- if (ImageSectionObject == NULL)
- {
- ObDereferenceObject(FileObject);
- ObDereferenceObject(Section);
- return(STATUS_NO_MEMORY);
- }
+ ExFreePoolWithTag(ImageSectionObject, TAG_MM_SECTION_SEGMENT);
+ ObDereferenceObject(Section);
+ ObDereferenceObject(FileObject);
+ return(Status);
+ }
- RtlZeroMemory(ImageSectionObject, sizeof(MM_IMAGE_SECTION_OBJECT));
+ Section->ImageSection = ImageSectionObject;
+ ASSERT(ImageSectionObject->Segments);
- StatusExeFmt = ExeFmtpCreateImageSection(FileObject, ImageSectionObject);
+ /*
+ * Lock the file
+ */
+ Status = MmspWaitForFileLock(FileObject);
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePool(ImageSectionObject->Segments);
+ ExFreePool(ImageSectionObject);
+ ObDereferenceObject(Section);
+ ObDereferenceObject(FileObject);
+ return(Status);
+ }
- if (!NT_SUCCESS(StatusExeFmt))
- {
- if(ImageSectionObject->Segments != NULL)
+ if (NULL != InterlockedCompareExchangePointer(&FileObject->SectionObjectPointer->ImageSectionObject,
+ ImageSectionObject, NULL))
+ {
+ /*
+ * An other thread has initialized the same image in the background
+ */
ExFreePool(ImageSectionObject->Segments);
+ ExFreePool(ImageSectionObject);
+ ImageSectionObject = FileObject->SectionObjectPointer->ImageSectionObject;
+ Section->ImageSection = ImageSectionObject;
+ SectionSegments = ImageSectionObject->Segments;
+
+ for (i = 0; i < ImageSectionObject->NrSegments; i++)
+ {
+ (void)InterlockedIncrementUL(&SectionSegments[i].ReferenceCount);
+ }
+ }
+
+ Status = StatusExeFmt;
+ }
+ else
+ {
+ /*
+ * Lock the file
+ */
+ Status = MmspWaitForFileLock(FileObject);
+ if (Status != STATUS_SUCCESS)
+ {
+ ObDereferenceObject(Section);
+ ObDereferenceObject(FileObject);
+ return(Status);
+ }
- ExFreePoolWithTag(ImageSectionObject, TAG_MM_SECTION_SEGMENT);
- ObDereferenceObject(Section);
- ObDereferenceObject(FileObject);
- return(StatusExeFmt);
- }
-
- Section->ImageSection = ImageSectionObject;
- ASSERT(ImageSectionObject->Segments);
-
- /*
- * Lock the file
- */
- Status = MmspWaitForFileLock(FileObject);
- if (!NT_SUCCESS(Status))
- {
- ExFreePool(ImageSectionObject->Segments);
- ExFreePool(ImageSectionObject);
- ObDereferenceObject(Section);
- ObDereferenceObject(FileObject);
- return(Status);
- }
-
- if (NULL != InterlockedCompareExchangePointer(&FileObject->SectionObjectPointer->ImageSectionObject,
- ImageSectionObject, NULL))
- {
- /*
- * An other thread has initialized the same image in the background
- */
- ExFreePool(ImageSectionObject->Segments);
- ExFreePool(ImageSectionObject);
- ImageSectionObject = FileObject->SectionObjectPointer->ImageSectionObject;
- Section->ImageSection = ImageSectionObject;
- SectionSegments = ImageSectionObject->Segments;
-
- for (i = 0; i < ImageSectionObject->NrSegments; i++)
- {
+ ImageSectionObject = FileObject->SectionObjectPointer->ImageSectionObject;
+ Section->ImageSection = ImageSectionObject;
+ SectionSegments = ImageSectionObject->Segments;
+
+ /*
+ * Otherwise just reference all the section segments
+ */
+ for (i = 0; i < ImageSectionObject->NrSegments; i++)
+ {
(void)InterlockedIncrementUL(&SectionSegments[i].ReferenceCount);
- }
- }
-
- Status = StatusExeFmt;
- }
- else
- {
- /*
- * Lock the file
- */
- Status = MmspWaitForFileLock(FileObject);
- if (Status != STATUS_SUCCESS)
- {
- ObDereferenceObject(Section);
- ObDereferenceObject(FileObject);
- return(Status);
- }
-
- ImageSectionObject = FileObject->SectionObjectPointer->ImageSectionObject;
- Section->ImageSection = ImageSectionObject;
- SectionSegments = ImageSectionObject->Segments;
-
- /*
- * Otherwise just reference all the section segments
- */
- for (i = 0; i < ImageSectionObject->NrSegments; i++)
- {
- (void)InterlockedIncrementUL(&SectionSegments[i].ReferenceCount);
- }
-
- Status = STATUS_SUCCESS;
- }
- Section->FileObject = FileObject;
+ }
+
+ Status = STATUS_SUCCESS;
+ }
+ Section->FileObject = FileObject;
#ifndef NEWCC
- CcRosReferenceCache(FileObject);
+ CcRosReferenceCache(FileObject);
#endif
- //KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
- *SectionObject = Section;
- return(Status);
+ //KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
+ *SectionObject = Section;
+ return(Status);
}
ULONG ViewOffset,
ULONG AllocationType)
{
- PMEMORY_AREA MArea;
- NTSTATUS Status;
- PHYSICAL_ADDRESS BoundaryAddressMultiple;
-
- if (Segment->WriteCopy)
- {
- /* We have to do this because the not present fault
- * and access fault handlers depend on the protection
- * that should be granted AFTER the COW fault takes
- * place to be in Region->Protect. The not present fault
- * handler changes this to the correct protection for COW when
- * mapping the pages into the process's address space. If a COW
- * fault takes place, the access fault handler sets the page protection
- * to these values for the newly copied pages
- */
- if (Protect == PAGE_WRITECOPY)
- Protect = PAGE_READWRITE;
- else if (Protect == PAGE_EXECUTE_WRITECOPY)
- Protect = PAGE_EXECUTE_READWRITE;
- }
+ PMEMORY_AREA MArea;
+ NTSTATUS Status;
+ ULONG Granularity;
+
+ if (Segment->WriteCopy)
+ {
+ /* We have to do this because the not present fault
+ * and access fault handlers depend on the protection
+ * that should be granted AFTER the COW fault takes
+ * place to be in Region->Protect. The not present fault
+ * handler changes this to the correct protection for COW when
+ * mapping the pages into the process's address space. If a COW
+ * fault takes place, the access fault handler sets the page protection
+ * to these values for the newly copied pages
+ */
+ if (Protect == PAGE_WRITECOPY)
+ Protect = PAGE_READWRITE;
+ else if (Protect == PAGE_EXECUTE_WRITECOPY)
+ Protect = PAGE_EXECUTE_READWRITE;
+ }
- BoundaryAddressMultiple.QuadPart = 0;
+ if (*BaseAddress == NULL)
+ Granularity = MM_ALLOCATION_GRANULARITY;
+ else
+ Granularity = PAGE_SIZE;
#ifdef NEWCC
- if (Segment->Flags & MM_DATAFILE_SEGMENT) {
- LARGE_INTEGER FileOffset;
- FileOffset.QuadPart = ViewOffset;
- ObReferenceObject(Section);
- return _MiMapViewOfSegment(AddressSpace, Segment, BaseAddress, ViewSize, Protect, &FileOffset, AllocationType, __FILE__, __LINE__);
- }
+ if (Segment->Flags & MM_DATAFILE_SEGMENT)
+ {
+ LARGE_INTEGER FileOffset;
+ FileOffset.QuadPart = ViewOffset;
+ ObReferenceObject(Section);
+ return _MiMapViewOfSegment(AddressSpace, Segment, BaseAddress, ViewSize, Protect, &FileOffset, AllocationType, __FILE__, __LINE__);
+ }
#endif
- Status = MmCreateMemoryArea(AddressSpace,
- MEMORY_AREA_SECTION_VIEW,
- BaseAddress,
- ViewSize,
- Protect,
- &MArea,
- FALSE,
- AllocationType,
- BoundaryAddressMultiple);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Mapping between 0x%.8X and 0x%.8X failed (%X).\n",
- (*BaseAddress), (char*)(*BaseAddress) + ViewSize, Status);
- return(Status);
- }
-
- ObReferenceObject((PVOID)Section);
-
- MArea->Data.SectionData.Segment = Segment;
- MArea->Data.SectionData.Section = Section;
- MArea->Data.SectionData.ViewOffset.QuadPart = ViewOffset;
- MmInitializeRegion(&MArea->Data.SectionData.RegionListHead,
- ViewSize, 0, Protect);
-
- return(STATUS_SUCCESS);
+ Status = MmCreateMemoryArea(AddressSpace,
+ MEMORY_AREA_SECTION_VIEW,
+ BaseAddress,
+ ViewSize,
+ Protect,
+ &MArea,
+ AllocationType,
+ Granularity);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Mapping between 0x%p and 0x%p failed (%X).\n",
+ (*BaseAddress), (char*)(*BaseAddress) + ViewSize, Status);
+ return(Status);
+ }
+
+ ObReferenceObject((PVOID)Section);
+
+ MArea->Data.SectionData.Segment = Segment;
+ MArea->Data.SectionData.Section = Section;
+ MArea->Data.SectionData.ViewOffset.QuadPart = ViewOffset;
+ if (Section->AllocationAttributes & SEC_IMAGE)
+ {
+ MArea->VadNode.u.VadFlags.VadType = VadImageMap;
+ }
+
+ MmInitializeRegion(&MArea->Data.SectionData.RegionListHead,
+ ViewSize, 0, Protect);
+
+ return(STATUS_SUCCESS);
}
MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
PFN_NUMBER Page, SWAPENTRY SwapEntry, BOOLEAN Dirty)
{
- ULONG_PTR Entry;
- PFILE_OBJECT FileObject;
- PBCB Bcb;
- LARGE_INTEGER Offset;
- SWAPENTRY SavedSwapEntry;
- PROS_SECTION_OBJECT Section;
- PMM_SECTION_SEGMENT Segment;
- PMMSUPPORT AddressSpace;
- PEPROCESS Process;
-
- AddressSpace = (PMMSUPPORT)Context;
- Process = MmGetAddressSpaceOwner(AddressSpace);
-
- Address = (PVOID)PAGE_ROUND_DOWN(Address);
-
- Offset.QuadPart = ((ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress) +
- MemoryArea->Data.SectionData.ViewOffset.QuadPart;
-
- Section = MemoryArea->Data.SectionData.Section;
- Segment = MemoryArea->Data.SectionData.Segment;
-
- Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
- while (Entry && IS_SWAP_FROM_SSE(Entry) && SWAPENTRY_FROM_SSE(Entry) == MM_WAIT_ENTRY)
- {
- MmUnlockSectionSegment(Segment);
- MmUnlockAddressSpace(AddressSpace);
-
- MiWaitForPageEvent(NULL, NULL);
-
- MmLockAddressSpace(AddressSpace);
- MmLockSectionSegment(Segment);
- Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
- }
-
- /*
- * For a dirty, datafile, non-private page mark it as dirty in the
- * cache manager.
- */
- if (Segment->Flags & MM_DATAFILE_SEGMENT)
- {
- if (Page == PFN_FROM_SSE(Entry) && Dirty)
- {
- FileObject = MemoryArea->Data.SectionData.Section->FileObject;
- Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
+ ULONG_PTR Entry;
+#ifndef NEWCC
+ PFILE_OBJECT FileObject;
+ PROS_SHARED_CACHE_MAP SharedCacheMap;
+#endif
+ LARGE_INTEGER Offset;
+ SWAPENTRY SavedSwapEntry;
+ PROS_SECTION_OBJECT Section;
+ PMM_SECTION_SEGMENT Segment;
+ PMMSUPPORT AddressSpace;
+ PEPROCESS Process;
+
+ AddressSpace = (PMMSUPPORT)Context;
+ Process = MmGetAddressSpaceOwner(AddressSpace);
+
+ Address = (PVOID)PAGE_ROUND_DOWN(Address);
+
+ Offset.QuadPart = ((ULONG_PTR)Address - MA_GetStartingAddress(MemoryArea)) +
+ MemoryArea->Data.SectionData.ViewOffset.QuadPart;
+
+ Section = MemoryArea->Data.SectionData.Section;
+ Segment = MemoryArea->Data.SectionData.Segment;
+
+ Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
+ while (Entry && MM_IS_WAIT_PTE(Entry))
+ {
+ MmUnlockSectionSegment(Segment);
+ MmUnlockAddressSpace(AddressSpace);
+
+ MiWaitForPageEvent(NULL, NULL);
+
+ MmLockAddressSpace(AddressSpace);
+ MmLockSectionSegment(Segment);
+ Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
+ }
+
+ /*
+ * For a dirty, datafile, non-private page mark it as dirty in the
+ * cache manager.
+ */
+ if (Segment->Flags & MM_DATAFILE_SEGMENT)
+ {
+ if (Page == PFN_FROM_SSE(Entry) && Dirty)
+ {
#ifndef NEWCC
- CcRosMarkDirtyCacheSegment(Bcb, (ULONG)(Offset.QuadPart + Segment->Image.FileOffset));
+ FileObject = MemoryArea->Data.SectionData.Section->FileObject;
+ SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
+ CcRosMarkDirtyFile(SharedCacheMap, Offset.QuadPart + Segment->Image.FileOffset);
#endif
- ASSERT(SwapEntry == 0);
- }
- }
-
- if (SwapEntry != 0)
- {
- /*
- * Sanity check
- */
- if (Segment->Flags & MM_PAGEFILE_SEGMENT)
- {
- DPRINT1("Found a swap entry for a page in a pagefile section.\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- MmFreeSwapPage(SwapEntry);
- }
- else if (Page != 0)
- {
- if (IS_SWAP_FROM_SSE(Entry) ||
- Page != PFN_FROM_SSE(Entry))
- {
- /*
- * Sanity check
- */
- if (Segment->Flags & MM_PAGEFILE_SEGMENT)
- {
- DPRINT1("Found a private page in a pagefile section.\n");
+ ASSERT(SwapEntry == 0);
+ }
+ }
+
+ if (SwapEntry != 0)
+ {
+ /*
+ * Sanity check
+ */
+ if (Segment->Flags & MM_PAGEFILE_SEGMENT)
+ {
+ DPRINT1("Found a swap entry for a page in a pagefile section.\n");
KeBugCheck(MEMORY_MANAGEMENT);
- }
- /*
- * Just dereference private pages
- */
- SavedSwapEntry = MmGetSavedSwapEntryPage(Page);
- if (SavedSwapEntry != 0)
- {
- MmFreeSwapPage(SavedSwapEntry);
- MmSetSavedSwapEntryPage(Page, 0);
- }
- MmDeleteRmap(Page, Process, Address);
- MmReleasePageMemoryConsumer(MC_USER, Page);
- }
- else
- {
- MmDeleteRmap(Page, Process, Address);
- MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, Dirty, FALSE, NULL);
- }
- }
+ }
+ MmFreeSwapPage(SwapEntry);
+ }
+ else if (Page != 0)
+ {
+ if (IS_SWAP_FROM_SSE(Entry) ||
+ Page != PFN_FROM_SSE(Entry))
+ {
+ /*
+ * Sanity check
+ */
+ if (Segment->Flags & MM_PAGEFILE_SEGMENT)
+ {
+ DPRINT1("Found a private page in a pagefile section.\n");
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+ /*
+ * Just dereference private pages
+ */
+ SavedSwapEntry = MmGetSavedSwapEntryPage(Page);
+ if (SavedSwapEntry != 0)
+ {
+ MmFreeSwapPage(SavedSwapEntry);
+ MmSetSavedSwapEntryPage(Page, 0);
+ }
+ MmDeleteRmap(Page, Process, Address);
+ MmReleasePageMemoryConsumer(MC_USER, Page);
+ }
+ else
+ {
+ MmDeleteRmap(Page, Process, Address);
+ MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, Dirty, FALSE, NULL);
+ }
+ }
}
static NTSTATUS
MmUnmapViewOfSegment(PMMSUPPORT AddressSpace,
PVOID BaseAddress)
{
- NTSTATUS Status;
- PMEMORY_AREA MemoryArea;
- PROS_SECTION_OBJECT Section;
- PMM_SECTION_SEGMENT Segment;
- PLIST_ENTRY CurrentEntry;
- PMM_REGION CurrentRegion;
- PLIST_ENTRY RegionListHead;
-
- MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace,
- BaseAddress);
- if (MemoryArea == NULL)
- {
- return(STATUS_UNSUCCESSFUL);
- }
-
- MemoryArea->DeleteInProgress = TRUE;
- Section = MemoryArea->Data.SectionData.Section;
- Segment = MemoryArea->Data.SectionData.Segment;
+ NTSTATUS Status;
+ PMEMORY_AREA MemoryArea;
+ PROS_SECTION_OBJECT Section;
+ PMM_SECTION_SEGMENT Segment;
+ PLIST_ENTRY CurrentEntry;
+ PMM_REGION CurrentRegion;
+ PLIST_ENTRY RegionListHead;
+
+ MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace,
+ BaseAddress);
+ if (MemoryArea == NULL)
+ {
+ return(STATUS_UNSUCCESSFUL);
+ }
+
+ Section = MemoryArea->Data.SectionData.Section;
+ Segment = MemoryArea->Data.SectionData.Segment;
#ifdef NEWCC
- if (Segment->Flags & MM_DATAFILE_SEGMENT)
- return MmUnmapViewOfCacheSegment(AddressSpace, BaseAddress);
+ if (Segment->Flags & MM_DATAFILE_SEGMENT)
+ {
+ MmUnlockAddressSpace(AddressSpace);
+ Status = MmUnmapViewOfCacheSegment(AddressSpace, BaseAddress);
+ MmLockAddressSpace(AddressSpace);
+
+ return Status;
+ }
#endif
- MmLockSectionSegment(Segment);
-
- RegionListHead = &MemoryArea->Data.SectionData.RegionListHead;
- while (!IsListEmpty(RegionListHead))
- {
- CurrentEntry = RemoveHeadList(RegionListHead);
- CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION, RegionListEntry);
- ExFreePoolWithTag(CurrentRegion, TAG_MM_REGION);
- }
-
- if (Section->AllocationAttributes & SEC_PHYSICALMEMORY)
- {
- Status = MmFreeMemoryArea(AddressSpace,
- MemoryArea,
- NULL,
- NULL);
- }
- else
- {
- Status = MmFreeMemoryArea(AddressSpace,
- MemoryArea,
- MmFreeSectionPage,
- AddressSpace);
- }
- MmUnlockSectionSegment(Segment);
- ObDereferenceObject(Section);
- return(Status);
+ MemoryArea->DeleteInProgress = TRUE;
+
+ MmLockSectionSegment(Segment);
+
+ RegionListHead = &MemoryArea->Data.SectionData.RegionListHead;
+ while (!IsListEmpty(RegionListHead))
+ {
+ CurrentEntry = RemoveHeadList(RegionListHead);
+ CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION, RegionListEntry);
+ ExFreePoolWithTag(CurrentRegion, TAG_MM_REGION);
+ }
+
+ if (Section->AllocationAttributes & SEC_PHYSICALMEMORY)
+ {
+ Status = MmFreeMemoryArea(AddressSpace,
+ MemoryArea,
+ NULL,
+ NULL);
+ }
+ else
+ {
+ Status = MmFreeMemoryArea(AddressSpace,
+ MemoryArea,
+ MmFreeSectionPage,
+ AddressSpace);
+ }
+ MmUnlockSectionSegment(Segment);
+ ObDereferenceObject(Section);
+ return(Status);
}
NTSTATUS
NTAPI
MiRosUnmapViewOfSection(IN PEPROCESS Process,
IN PVOID BaseAddress,
- IN ULONG Flags)
+ IN BOOLEAN SkipDebuggerNotify)
{
- NTSTATUS Status;
- PMEMORY_AREA MemoryArea;
- PMMSUPPORT AddressSpace;
- PROS_SECTION_OBJECT Section;
- PVOID ImageBaseAddress = 0;
-
- DPRINT("Opening memory area Process %x BaseAddress %x\n",
- Process, BaseAddress);
-
- ASSERT(Process);
-
- AddressSpace = Process ? &Process->Vm : MmGetKernelAddressSpace();
-
- MmLockAddressSpace(AddressSpace);
- MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace,
- BaseAddress);
- if (MemoryArea == NULL ||
- MemoryArea->Type != MEMORY_AREA_SECTION_VIEW ||
- MemoryArea->DeleteInProgress)
- {
- ASSERT(MemoryArea->Type != MEMORY_AREA_OWNED_BY_ARM3);
- MmUnlockAddressSpace(AddressSpace);
- return STATUS_NOT_MAPPED_VIEW;
- }
-
- MemoryArea->DeleteInProgress = TRUE;
-
- Section = MemoryArea->Data.SectionData.Section;
-
- if (Section->AllocationAttributes & SEC_IMAGE)
- {
- ULONG i;
- ULONG NrSegments;
- PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
- PMM_SECTION_SEGMENT SectionSegments;
- PMM_SECTION_SEGMENT Segment;
-
- Segment = MemoryArea->Data.SectionData.Segment;
- ImageSectionObject = Section->ImageSection;
- SectionSegments = ImageSectionObject->Segments;
- NrSegments = ImageSectionObject->NrSegments;
-
- /* Search for the current segment within the section segments
- * and calculate the image base address */
- for (i = 0; i < NrSegments; i++)
- {
- if (!(SectionSegments[i].Image.Characteristics & IMAGE_SCN_TYPE_NOLOAD))
- {
+ NTSTATUS Status;
+ PMEMORY_AREA MemoryArea;
+ PMMSUPPORT AddressSpace;
+ PROS_SECTION_OBJECT Section;
+ PVOID ImageBaseAddress = 0;
+
+ DPRINT("Opening memory area Process %p BaseAddress %p\n",
+ Process, BaseAddress);
+
+ ASSERT(Process);
+
+ AddressSpace = Process ? &Process->Vm : MmGetKernelAddressSpace();
+
+ MmLockAddressSpace(AddressSpace);
+ MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace,
+ BaseAddress);
+ if (MemoryArea == NULL ||
+ ((MemoryArea->Type != MEMORY_AREA_SECTION_VIEW) &&
+ (MemoryArea->Type != MEMORY_AREA_CACHE)) ||
+ MemoryArea->DeleteInProgress)
+ {
+ if (MemoryArea) ASSERT(MemoryArea->Type != MEMORY_AREA_OWNED_BY_ARM3);
+ MmUnlockAddressSpace(AddressSpace);
+ return STATUS_NOT_MAPPED_VIEW;
+ }
+
+ Section = MemoryArea->Data.SectionData.Section;
+
+ if ((Section != NULL) && (Section->AllocationAttributes & SEC_IMAGE))
+ {
+ ULONG i;
+ ULONG NrSegments;
+ PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
+ PMM_SECTION_SEGMENT SectionSegments;
+ PMM_SECTION_SEGMENT Segment;
+
+ Segment = MemoryArea->Data.SectionData.Segment;
+ ImageSectionObject = Section->ImageSection;
+ SectionSegments = ImageSectionObject->Segments;
+ NrSegments = ImageSectionObject->NrSegments;
+
+ MemoryArea->DeleteInProgress = TRUE;
+
+ /* Search for the current segment within the section segments
+ * and calculate the image base address */
+ for (i = 0; i < NrSegments; i++)
+ {
if (Segment == &SectionSegments[i])
{
- ImageBaseAddress = (char*)BaseAddress - (ULONG_PTR)SectionSegments[i].Image.VirtualAddress;
- break;
+ ImageBaseAddress = (char*)BaseAddress - (ULONG_PTR)SectionSegments[i].Image.VirtualAddress;
+ break;
}
- }
- }
- if (i >= NrSegments)
- {
- KeBugCheck(MEMORY_MANAGEMENT);
- }
-
- for (i = 0; i < NrSegments; i++)
- {
- if (!(SectionSegments[i].Image.Characteristics & IMAGE_SCN_TYPE_NOLOAD))
- {
+ }
+ if (i >= NrSegments)
+ {
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+
+ for (i = 0; i < NrSegments; i++)
+ {
PVOID SBaseAddress = (PVOID)
((char*)ImageBaseAddress + (ULONG_PTR)SectionSegments[i].Image.VirtualAddress);
Status = MmUnmapViewOfSegment(AddressSpace, SBaseAddress);
- NT_ASSERT(NT_SUCCESS(Status));
- }
- }
- }
- else
- {
- Status = MmUnmapViewOfSegment(AddressSpace, BaseAddress);
- NT_ASSERT(NT_SUCCESS(Status));
- }
-
- MmUnlockAddressSpace(AddressSpace);
-
- /* Notify debugger */
- if (ImageBaseAddress) DbgkUnMapViewOfSection(ImageBaseAddress);
-
- return(STATUS_SUCCESS);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("MmUnmapViewOfSegment failed for %p (Process %p) with %lx\n",
+ SBaseAddress, Process, Status);
+ ASSERT(NT_SUCCESS(Status));
+ }
+ }
+ }
+ else
+ {
+ Status = MmUnmapViewOfSegment(AddressSpace, BaseAddress);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("MmUnmapViewOfSegment failed for %p (Process %p) with %lx\n",
+ BaseAddress, Process, Status);
+ ASSERT(NT_SUCCESS(Status));
+ }
+ }
+
+ MmUnlockAddressSpace(AddressSpace);
+
+ /* Notify debugger */
+ if (ImageBaseAddress && !SkipDebuggerNotify) DbgkUnMapViewOfSection(ImageBaseAddress);
+
+ return(STATUS_SUCCESS);
}
*
* @implemented
*/
-NTSTATUS NTAPI
-NtQuerySection(IN HANDLE SectionHandle,
- IN SECTION_INFORMATION_CLASS SectionInformationClass,
- OUT PVOID SectionInformation,
- IN SIZE_T SectionInformationLength,
- OUT PSIZE_T ResultLength OPTIONAL)
+NTSTATUS
+NTAPI
+NtQuerySection(
+ _In_ HANDLE SectionHandle,
+ _In_ SECTION_INFORMATION_CLASS SectionInformationClass,
+ _Out_ PVOID SectionInformation,
+ _In_ SIZE_T SectionInformationLength,
+ _Out_opt_ PSIZE_T ResultLength)
{
- PROS_SECTION_OBJECT Section;
- KPROCESSOR_MODE PreviousMode;
- NTSTATUS Status;
- PAGED_CODE();
-
- PreviousMode = ExGetPreviousMode();
-
- Status = DefaultQueryInfoBufferCheck(SectionInformationClass,
- ExSectionInfoClass,
- sizeof(ExSectionInfoClass) / sizeof(ExSectionInfoClass[0]),
- SectionInformation,
- (ULONG)SectionInformationLength,
- NULL,
- ResultLength,
- PreviousMode);
-
- if(!NT_SUCCESS(Status))
- {
- DPRINT1("NtQuerySection() failed, Status: 0x%x\n", Status);
- return Status;
- }
-
- Status = ObReferenceObjectByHandle(SectionHandle,
- SECTION_QUERY,
- MmSectionObjectType,
- PreviousMode,
- (PVOID*)(PVOID)&Section,
- NULL);
- if (NT_SUCCESS(Status))
- {
- switch (SectionInformationClass)
- {
- case SectionBasicInformation:
- {
- PSECTION_BASIC_INFORMATION Sbi = (PSECTION_BASIC_INFORMATION)SectionInformation;
-
- _SEH2_TRY
- {
- Sbi->Attributes = Section->AllocationAttributes;
- if (Section->AllocationAttributes & SEC_IMAGE)
- {
- Sbi->BaseAddress = 0;
- Sbi->Size.QuadPart = 0;
- }
- else
- {
- Sbi->BaseAddress = (PVOID)Section->Segment->Image.VirtualAddress;
- Sbi->Size.QuadPart = Section->Segment->Length.QuadPart;
- }
-
- if (ResultLength != NULL)
- {
- *ResultLength = sizeof(SECTION_BASIC_INFORMATION);
- }
- Status = STATUS_SUCCESS;
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ PSECTION Section;
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status;
+ PAGED_CODE();
+
+ PreviousMode = ExGetPreviousMode();
+ if (PreviousMode != KernelMode)
+ {
+ _SEH2_TRY
+ {
+ ProbeForWrite(SectionInformation,
+ SectionInformationLength,
+ __alignof(ULONG));
+ if (ResultLength != NULL)
{
- Status = _SEH2_GetExceptionCode();
+ ProbeForWrite(ResultLength,
+ sizeof(*ResultLength),
+ __alignof(SIZE_T));
}
- _SEH2_END;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+ }
- break;
- }
+ if (SectionInformationClass == SectionBasicInformation)
+ {
+ if (SectionInformationLength < sizeof(SECTION_BASIC_INFORMATION))
+ {
+ return STATUS_INFO_LENGTH_MISMATCH;
+ }
+ }
+ else if (SectionInformationClass == SectionImageInformation)
+ {
+ if (SectionInformationLength < sizeof(SECTION_IMAGE_INFORMATION))
+ {
+ return STATUS_INFO_LENGTH_MISMATCH;
+ }
+ }
+ else
+ {
+ return STATUS_INVALID_INFO_CLASS;
+ }
- case SectionImageInformation:
- {
- PSECTION_IMAGE_INFORMATION Sii = (PSECTION_IMAGE_INFORMATION)SectionInformation;
+ Status = ObReferenceObjectByHandle(SectionHandle,
+ SECTION_QUERY,
+ MmSectionObjectType,
+ PreviousMode,
+ (PVOID*)(PVOID)&Section,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to reference section: 0x%lx\n", Status);
+ return Status;
+ }
+
+ if (MiIsRosSectionObject(Section))
+ {
+ PROS_SECTION_OBJECT RosSection = (PROS_SECTION_OBJECT)Section;
- _SEH2_TRY
+ switch (SectionInformationClass)
+ {
+ case SectionBasicInformation:
{
- memset(Sii, 0, sizeof(SECTION_IMAGE_INFORMATION));
- if (Section->AllocationAttributes & SEC_IMAGE)
- {
- PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
- ImageSectionObject = Section->ImageSection;
-
- Sii->TransferAddress = (PVOID)ImageSectionObject->EntryPoint;
- Sii->MaximumStackSize = ImageSectionObject->StackReserve;
- Sii->CommittedStackSize = ImageSectionObject->StackCommit;
- Sii->SubSystemType = ImageSectionObject->Subsystem;
- Sii->SubSystemMinorVersion = ImageSectionObject->MinorSubsystemVersion;
- Sii->SubSystemMajorVersion = ImageSectionObject->MajorSubsystemVersion;
- Sii->ImageCharacteristics = ImageSectionObject->ImageCharacteristics;
- Sii->Machine = ImageSectionObject->Machine;
- Sii->ImageContainsCode = ImageSectionObject->Executable;
- }
-
- if (ResultLength != NULL)
- {
- *ResultLength = sizeof(SECTION_IMAGE_INFORMATION);
- }
- Status = STATUS_SUCCESS;
+ PSECTION_BASIC_INFORMATION Sbi = (PSECTION_BASIC_INFORMATION)SectionInformation;
+
+ _SEH2_TRY
+ {
+ Sbi->Attributes = RosSection->AllocationAttributes;
+ if (RosSection->AllocationAttributes & SEC_IMAGE)
+ {
+ Sbi->BaseAddress = 0;
+ Sbi->Size.QuadPart = 0;
+ }
+ else
+ {
+ Sbi->BaseAddress = (PVOID)RosSection->Segment->Image.VirtualAddress;
+ Sbi->Size.QuadPart = RosSection->Segment->Length.QuadPart;
+ }
+
+ if (ResultLength != NULL)
+ {
+ *ResultLength = sizeof(SECTION_BASIC_INFORMATION);
+ }
+ Status = STATUS_SUCCESS;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ break;
}
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+
+ case SectionImageInformation:
{
- Status = _SEH2_GetExceptionCode();
+ PSECTION_IMAGE_INFORMATION Sii = (PSECTION_IMAGE_INFORMATION)SectionInformation;
+
+ _SEH2_TRY
+ {
+ if (RosSection->AllocationAttributes & SEC_IMAGE)
+ {
+ PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
+ ImageSectionObject = RosSection->ImageSection;
+
+ *Sii = ImageSectionObject->ImageInformation;
+ }
+
+ if (ResultLength != NULL)
+ {
+ *ResultLength = sizeof(SECTION_IMAGE_INFORMATION);
+ }
+ Status = STATUS_SUCCESS;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ break;
}
- _SEH2_END;
-
- break;
- }
- }
+ }
+ }
+ else
+ {
+ switch(SectionInformationClass)
+ {
+ case SectionBasicInformation:
+ {
+ SECTION_BASIC_INFORMATION Sbi;
+
+ Sbi.Size = Section->SizeOfSection;
+ Sbi.BaseAddress = (PVOID)Section->Address.StartingVpn;
+
+ Sbi.Attributes = 0;
+ if (Section->u.Flags.Image)
+ Sbi.Attributes |= SEC_IMAGE;
+ if (Section->u.Flags.Commit)
+ Sbi.Attributes |= SEC_COMMIT;
+ if (Section->u.Flags.Reserve)
+ Sbi.Attributes |= SEC_RESERVE;
+ if (Section->u.Flags.File)
+ Sbi.Attributes |= SEC_FILE;
+ if (Section->u.Flags.Image)
+ Sbi.Attributes |= SEC_IMAGE;
+
+ /* FIXME : Complete/test the list of flags passed back from NtCreateSection */
+
+ _SEH2_TRY
+ {
+ *((SECTION_BASIC_INFORMATION*)SectionInformation) = Sbi;
+ if (ResultLength)
+ *ResultLength = sizeof(Sbi);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+ break;
+ }
+ case SectionImageInformation:
+ {
+ if (!Section->u.Flags.Image)
+ {
+ Status = STATUS_SECTION_NOT_IMAGE;
+ }
+ else
+ {
+ /* Currently not supported */
+ ASSERT(FALSE);
+ }
+ break;
+ }
+ }
+ }
- ObDereferenceObject(Section);
- }
+ ObDereferenceObject(Section);
- return(Status);
+ return(Status);
}
/**********************************************************************
IN ULONG AllocationType,
IN ULONG Protect)
{
- PROS_SECTION_OBJECT Section;
- PMMSUPPORT AddressSpace;
- ULONG ViewOffset;
- NTSTATUS Status = STATUS_SUCCESS;
- BOOLEAN NotAtBase = FALSE;
-
- if (MiIsRosSectionObject(SectionObject) == FALSE)
- {
- DPRINT("Mapping ARM3 section into %s\n", Process->ImageFileName);
- return MmMapViewOfArm3Section(SectionObject,
- Process,
- BaseAddress,
- ZeroBits,
- CommitSize,
- SectionOffset,
- ViewSize,
- InheritDisposition,
- AllocationType,
- Protect);
- }
-
- ASSERT(Process);
-
- if (!Protect || Protect & ~PAGE_FLAGS_VALID_FOR_SECTION)
- {
- return STATUS_INVALID_PAGE_PROTECTION;
- }
-
-
- Section = (PROS_SECTION_OBJECT)SectionObject;
- AddressSpace = &Process->Vm;
-
- AllocationType |= (Section->AllocationAttributes & SEC_NO_CHANGE);
-
- MmLockAddressSpace(AddressSpace);
-
- if (Section->AllocationAttributes & SEC_IMAGE)
- {
- ULONG i;
- ULONG NrSegments;
- ULONG_PTR ImageBase;
- SIZE_T ImageSize;
- PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
- PMM_SECTION_SEGMENT SectionSegments;
-
- ImageSectionObject = Section->ImageSection;
- SectionSegments = ImageSectionObject->Segments;
- NrSegments = ImageSectionObject->NrSegments;
-
-
- ImageBase = (ULONG_PTR)*BaseAddress;
- if (ImageBase == 0)
- {
- ImageBase = ImageSectionObject->ImageBase;
- }
-
- ImageSize = 0;
- for (i = 0; i < NrSegments; i++)
- {
- if (!(SectionSegments[i].Image.Characteristics & IMAGE_SCN_TYPE_NOLOAD))
- {
+ PROS_SECTION_OBJECT Section;
+ PMMSUPPORT AddressSpace;
+ ULONG ViewOffset;
+ NTSTATUS Status = STATUS_SUCCESS;
+ BOOLEAN NotAtBase = FALSE;
+
+ if (MiIsRosSectionObject(SectionObject) == FALSE)
+ {
+ DPRINT("Mapping ARM3 section into %s\n", Process->ImageFileName);
+ return MmMapViewOfArm3Section(SectionObject,
+ Process,
+ BaseAddress,
+ ZeroBits,
+ CommitSize,
+ SectionOffset,
+ ViewSize,
+ InheritDisposition,
+ AllocationType,
+ Protect);
+ }
+
+ ASSERT(Process);
+
+ if (!Protect || Protect & ~PAGE_FLAGS_VALID_FOR_SECTION)
+ {
+ return STATUS_INVALID_PAGE_PROTECTION;
+ }
+
+ /* FIXME: We should keep this, but it would break code checking equality */
+ Protect &= ~PAGE_NOCACHE;
+
+ Section = (PROS_SECTION_OBJECT)SectionObject;
+ AddressSpace = &Process->Vm;
+
+ AllocationType |= (Section->AllocationAttributes & SEC_NO_CHANGE);
+
+ MmLockAddressSpace(AddressSpace);
+
+ if (Section->AllocationAttributes & SEC_IMAGE)
+ {
+ ULONG i;
+ ULONG NrSegments;
+ ULONG_PTR ImageBase;
+ SIZE_T ImageSize;
+ PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
+ PMM_SECTION_SEGMENT SectionSegments;
+
+ ImageSectionObject = Section->ImageSection;
+ SectionSegments = ImageSectionObject->Segments;
+ NrSegments = ImageSectionObject->NrSegments;
+
+ ImageBase = (ULONG_PTR)*BaseAddress;
+ if (ImageBase == 0)
+ {
+ ImageBase = (ULONG_PTR)ImageSectionObject->BasedAddress;
+ }
+
+ ImageSize = 0;
+ for (i = 0; i < NrSegments; i++)
+ {
ULONG_PTR MaxExtent;
MaxExtent = (ULONG_PTR)(SectionSegments[i].Image.VirtualAddress +
- SectionSegments[i].Length.QuadPart);
+ SectionSegments[i].Length.QuadPart);
ImageSize = max(ImageSize, MaxExtent);
- }
- }
-
- ImageSectionObject->ImageSize = (ULONG)ImageSize;
-
- /* Check for an illegal base address */
- if ((ImageBase + ImageSize) > (ULONG_PTR)MmHighestUserAddress)
- {
- ImageBase = PAGE_ROUND_DOWN((ULONG_PTR)MmHighestUserAddress - ImageSize);
- }
-
- /* Check there is enough space to map the section at that point. */
- if (MmLocateMemoryAreaByRegion(AddressSpace, (PVOID)ImageBase,
- PAGE_ROUND_UP(ImageSize)) != NULL)
- {
- /* Fail if the user requested a fixed base address. */
- if ((*BaseAddress) != NULL)
- {
- MmUnlockAddressSpace(AddressSpace);
- return(STATUS_UNSUCCESSFUL);
- }
- /* Otherwise find a gap to map the image. */
- ImageBase = (ULONG_PTR)MmFindGap(AddressSpace, PAGE_ROUND_UP(ImageSize), PAGE_SIZE, FALSE);
- if (ImageBase == 0)
- {
- MmUnlockAddressSpace(AddressSpace);
- return(STATUS_UNSUCCESSFUL);
- }
- /* Remember that we loaded image at a different base address */
- NotAtBase = TRUE;
- }
-
- for (i = 0; i < NrSegments; i++)
- {
- if (!(SectionSegments[i].Image.Characteristics & IMAGE_SCN_TYPE_NOLOAD))
- {
+ }
+
+ ImageSectionObject->ImageInformation.ImageFileSize = (ULONG)ImageSize;
+
+ /* Check for an illegal base address */
+ if (((ImageBase + ImageSize) > (ULONG_PTR)MmHighestUserAddress) ||
+ ((ImageBase + ImageSize) < ImageSize))
+ {
+ ASSERT(*BaseAddress == NULL);
+ ImageBase = ALIGN_DOWN_BY((ULONG_PTR)MmHighestUserAddress - ImageSize,
+ MM_VIRTMEM_GRANULARITY);
+ NotAtBase = TRUE;
+ }
+ else if (ImageBase != ALIGN_DOWN_BY(ImageBase, MM_VIRTMEM_GRANULARITY))
+ {
+ ASSERT(*BaseAddress == NULL);
+ ImageBase = ALIGN_DOWN_BY(ImageBase, MM_VIRTMEM_GRANULARITY);
+ NotAtBase = TRUE;
+ }
+
+ /* Check there is enough space to map the section at that point. */
+ if (MmLocateMemoryAreaByRegion(AddressSpace, (PVOID)ImageBase,
+ PAGE_ROUND_UP(ImageSize)) != NULL)
+ {
+ /* Fail if the user requested a fixed base address. */
+ if ((*BaseAddress) != NULL)
+ {
+ MmUnlockAddressSpace(AddressSpace);
+ return(STATUS_CONFLICTING_ADDRESSES);
+ }
+ /* Otherwise find a gap to map the image. */
+ ImageBase = (ULONG_PTR)MmFindGap(AddressSpace, PAGE_ROUND_UP(ImageSize), MM_VIRTMEM_GRANULARITY, FALSE);
+ if (ImageBase == 0)
+ {
+ MmUnlockAddressSpace(AddressSpace);
+ return(STATUS_CONFLICTING_ADDRESSES);
+ }
+ /* Remember that we loaded image at a different base address */
+ NotAtBase = TRUE;
+ }
+
+ for (i = 0; i < NrSegments; i++)
+ {
PVOID SBaseAddress = (PVOID)
((char*)ImageBase + (ULONG_PTR)SectionSegments[i].Image.VirtualAddress);
MmLockSectionSegment(&SectionSegments[i]);
MmUnlockSectionSegment(&SectionSegments[i]);
if (!NT_SUCCESS(Status))
{
- MmUnlockAddressSpace(AddressSpace);
- return(Status);
+ MmUnlockAddressSpace(AddressSpace);
+ return(Status);
}
- }
- }
-
- *BaseAddress = (PVOID)ImageBase;
- *ViewSize = ImageSize;
- }
- else
- {
- /* check for write access */
- if ((Protect & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE)) &&
- !(Section->SectionPageProtection & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE)))
- {
- MmUnlockAddressSpace(AddressSpace);
- return STATUS_SECTION_PROTECTION;
- }
- /* check for read access */
- if ((Protect & (PAGE_READONLY|PAGE_WRITECOPY|PAGE_EXECUTE_READ|PAGE_EXECUTE_WRITECOPY)) &&
- !(Section->SectionPageProtection & (PAGE_READONLY|PAGE_READWRITE|PAGE_WRITECOPY|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE|PAGE_EXECUTE_WRITECOPY)))
- {
- MmUnlockAddressSpace(AddressSpace);
- return STATUS_SECTION_PROTECTION;
- }
- /* check for execute access */
- if ((Protect & (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE|PAGE_EXECUTE_WRITECOPY)) &&
- !(Section->SectionPageProtection & (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE|PAGE_EXECUTE_WRITECOPY)))
- {
- MmUnlockAddressSpace(AddressSpace);
- return STATUS_SECTION_PROTECTION;
- }
-
- if (ViewSize == NULL)
- {
- /* Following this pointer would lead to us to the dark side */
- /* What to do? Bugcheck? Return status? Do the mambo? */
- KeBugCheck(MEMORY_MANAGEMENT);
- }
-
- if (SectionOffset == NULL)
- {
- ViewOffset = 0;
- }
- else
- {
- ViewOffset = SectionOffset->u.LowPart;
- }
-
- if ((ViewOffset % PAGE_SIZE) != 0)
- {
- MmUnlockAddressSpace(AddressSpace);
- return(STATUS_MAPPED_ALIGNMENT);
- }
-
- if ((*ViewSize) == 0)
- {
- (*ViewSize) = Section->MaximumSize.u.LowPart - ViewOffset;
- }
- else if (((*ViewSize)+ViewOffset) > Section->MaximumSize.u.LowPart)
- {
- (*ViewSize) = Section->MaximumSize.u.LowPart - ViewOffset;
- }
-
- *ViewSize = PAGE_ROUND_UP(*ViewSize);
-
- MmLockSectionSegment(Section->Segment);
- Status = MmMapViewOfSegment(AddressSpace,
- Section,
- Section->Segment,
- BaseAddress,
- *ViewSize,
- Protect,
- ViewOffset,
- AllocationType & (MEM_TOP_DOWN|SEC_NO_CHANGE));
- MmUnlockSectionSegment(Section->Segment);
- if (!NT_SUCCESS(Status))
- {
- MmUnlockAddressSpace(AddressSpace);
- return(Status);
- }
- }
-
- MmUnlockAddressSpace(AddressSpace);
-
- if (NotAtBase)
- Status = STATUS_IMAGE_NOT_AT_BASE;
- else
- Status = STATUS_SUCCESS;
-
- return Status;
+ }
+
+ *BaseAddress = (PVOID)ImageBase;
+ *ViewSize = ImageSize;
+ }
+ else
+ {
+ /* check for write access */
+ if ((Protect & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE)) &&
+ !(Section->SectionPageProtection & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE)))
+ {
+ MmUnlockAddressSpace(AddressSpace);
+ return STATUS_SECTION_PROTECTION;
+ }
+ /* check for read access */
+ if ((Protect & (PAGE_READONLY|PAGE_WRITECOPY|PAGE_EXECUTE_READ|PAGE_EXECUTE_WRITECOPY)) &&
+ !(Section->SectionPageProtection & (PAGE_READONLY|PAGE_READWRITE|PAGE_WRITECOPY|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE|PAGE_EXECUTE_WRITECOPY)))
+ {
+ MmUnlockAddressSpace(AddressSpace);
+ return STATUS_SECTION_PROTECTION;
+ }
+ /* check for execute access */
+ if ((Protect & (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE|PAGE_EXECUTE_WRITECOPY)) &&
+ !(Section->SectionPageProtection & (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE|PAGE_EXECUTE_WRITECOPY)))
+ {
+ MmUnlockAddressSpace(AddressSpace);
+ return STATUS_SECTION_PROTECTION;
+ }
+
+ if (SectionOffset == NULL)
+ {
+ ViewOffset = 0;
+ }
+ else
+ {
+ ViewOffset = SectionOffset->u.LowPart;
+ }
+
+ if ((ViewOffset % PAGE_SIZE) != 0)
+ {
+ MmUnlockAddressSpace(AddressSpace);
+ return(STATUS_MAPPED_ALIGNMENT);
+ }
+
+ if ((*ViewSize) == 0)
+ {
+ (*ViewSize) = Section->MaximumSize.u.LowPart - ViewOffset;
+ }
+ else if (((*ViewSize)+ViewOffset) > Section->MaximumSize.u.LowPart)
+ {
+ (*ViewSize) = Section->MaximumSize.u.LowPart - ViewOffset;
+ }
+
+ *ViewSize = PAGE_ROUND_UP(*ViewSize);
+
+ MmLockSectionSegment(Section->Segment);
+ Status = MmMapViewOfSegment(AddressSpace,
+ Section,
+ Section->Segment,
+ BaseAddress,
+ *ViewSize,
+ Protect,
+ ViewOffset,
+ AllocationType & (MEM_TOP_DOWN|SEC_NO_CHANGE));
+ MmUnlockSectionSegment(Section->Segment);
+ if (!NT_SUCCESS(Status))
+ {
+ MmUnlockAddressSpace(AddressSpace);
+ return(Status);
+ }
+ }
+
+ MmUnlockAddressSpace(AddressSpace);
+ ASSERT(*BaseAddress == ALIGN_DOWN_POINTER_BY(*BaseAddress, MM_VIRTMEM_GRANULARITY));
+
+ if (NotAtBase)
+ Status = STATUS_IMAGE_NOT_AT_BASE;
+ else
+ Status = STATUS_SUCCESS;
+
+ return Status;
}
/*
MmCanFileBeTruncated (IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
IN PLARGE_INTEGER NewFileSize)
{
- /* Check whether an ImageSectionObject exists */
- if (SectionObjectPointer->ImageSectionObject != NULL)
- {
- DPRINT1("ERROR: File can't be truncated because it has an image section\n");
- return FALSE;
- }
-
- if (SectionObjectPointer->DataSectionObject != NULL)
- {
- PMM_SECTION_SEGMENT Segment;
-
- Segment = (PMM_SECTION_SEGMENT)SectionObjectPointer->
- DataSectionObject;
-
- if (Segment->ReferenceCount != 0)
- {
+ /* Check whether an ImageSectionObject exists */
+ if (SectionObjectPointer->ImageSectionObject != NULL)
+ {
+ DPRINT1("ERROR: File can't be truncated because it has an image section\n");
+ return FALSE;
+ }
+
+ if (SectionObjectPointer->DataSectionObject != NULL)
+ {
+ PMM_SECTION_SEGMENT Segment;
+
+ Segment = (PMM_SECTION_SEGMENT)SectionObjectPointer->
+ DataSectionObject;
+
+ if (Segment->ReferenceCount != 0)
+ {
#ifdef NEWCC
- CC_FILE_SIZES FileSizes;
- CcpLock();
- if (SectionObjectPointer->SharedCacheMap && (Segment->ReferenceCount > CcpCountCacheSections((PNOCC_CACHE_MAP)SectionObjectPointer->SharedCacheMap)))
- {
- CcpUnlock();
+ CC_FILE_SIZES FileSizes;
+ CcpLock();
+ if (SectionObjectPointer->SharedCacheMap && (Segment->ReferenceCount > CcpCountCacheSections((PNOCC_CACHE_MAP)SectionObjectPointer->SharedCacheMap)))
+ {
+ CcpUnlock();
+ /* Check size of file */
+ if (SectionObjectPointer->SharedCacheMap)
+ {
+ if (!CcGetFileSizes(Segment->FileObject, &FileSizes))
+ {
+ return FALSE;
+ }
+
+ if (NewFileSize->QuadPart <= FileSizes.FileSize.QuadPart)
+ {
+ return FALSE;
+ }
+ }
+ }
+ else
+ CcpUnlock();
+#else
/* Check size of file */
if (SectionObjectPointer->SharedCacheMap)
{
- if (!CcGetFileSizes(Segment->FileObject, &FileSizes))
- {
- return FALSE;
- }
-
- if (NewFileSize->QuadPart <= FileSizes.FileSize.QuadPart)
- {
- return FALSE;
- }
+ PROS_SHARED_CACHE_MAP SharedCacheMap = SectionObjectPointer->SharedCacheMap;
+ if (NewFileSize->QuadPart <= SharedCacheMap->FileSize.QuadPart)
+ {
+ return FALSE;
+ }
}
- }
- else
- CcpUnlock();
-#else
- /* Check size of file */
- if (SectionObjectPointer->SharedCacheMap)
- {
- PBCB Bcb = SectionObjectPointer->SharedCacheMap;
- if (NewFileSize->QuadPart <= Bcb->FileSize.QuadPart)
- {
- return FALSE;
- }
- }
#endif
- }
- else
- {
- /* Something must gone wrong
- * how can we have a Section but no
- * reference? */
- DPRINT("ERROR: DataSectionObject without reference!\n");
- }
- }
-
- DPRINT("FIXME: didn't check for outstanding write probes\n");
-
- return TRUE;
+ }
+ else
+ {
+ /* Something must gone wrong
+ * how can we have a Section but no
+ * reference? */
+ DPRINT("ERROR: DataSectionObject without reference!\n");
+ }
+ }
+
+ DPRINT("FIXME: didn't check for outstanding write probes\n");
+
+ return TRUE;
}
MmFlushImageSection (IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
IN MMFLUSH_TYPE FlushType)
{
- BOOLEAN Result = TRUE;
+ BOOLEAN Result = TRUE;
#ifdef NEWCC
- PMM_SECTION_SEGMENT Segment;
+ PMM_SECTION_SEGMENT Segment;
#endif
- switch(FlushType)
- {
- case MmFlushForDelete:
- if (SectionObjectPointer->ImageSectionObject ||
- SectionObjectPointer->DataSectionObject)
- {
+ switch(FlushType)
+ {
+ case MmFlushForDelete:
+ if (SectionObjectPointer->ImageSectionObject ||
+ SectionObjectPointer->DataSectionObject)
+ {
return FALSE;
- }
+ }
#ifndef NEWCC
- CcRosSetRemoveOnClose(SectionObjectPointer);
+ CcRosRemoveIfClosed(SectionObjectPointer);
#endif
- return TRUE;
- case MmFlushForWrite:
- {
- DPRINT("MmFlushImageSection(%d)\n", FlushType);
+ return TRUE;
+ case MmFlushForWrite:
+ {
+ DPRINT("MmFlushImageSection(%d)\n", FlushType);
#ifdef NEWCC
- Segment = (PMM_SECTION_SEGMENT)SectionObjectPointer->DataSectionObject;
+ Segment = (PMM_SECTION_SEGMENT)SectionObjectPointer->DataSectionObject;
#endif
- if (SectionObjectPointer->ImageSectionObject) {
+ if (SectionObjectPointer->ImageSectionObject)
+ {
DPRINT1("SectionObject has ImageSection\n");
return FALSE;
- }
+ }
#ifdef NEWCC
- CcpLock();
- Result = !SectionObjectPointer->SharedCacheMap || (Segment->ReferenceCount == CcpCountCacheSections((PNOCC_CACHE_MAP)SectionObjectPointer->SharedCacheMap));
- CcpUnlock();
- DPRINT("Result %d\n", Result);
+ CcpLock();
+ Result = !SectionObjectPointer->SharedCacheMap || (Segment->ReferenceCount == CcpCountCacheSections((PNOCC_CACHE_MAP)SectionObjectPointer->SharedCacheMap));
+ CcpUnlock();
+ DPRINT("Result %d\n", Result);
#endif
- return Result;
- }
- }
- return FALSE;
+ return Result;
+ }
+ }
+ return FALSE;
}
/*
OUT PVOID * MappedBase,
IN OUT PSIZE_T ViewSize)
{
- PROS_SECTION_OBJECT Section;
- PMMSUPPORT AddressSpace;
- NTSTATUS Status;
- PAGED_CODE();
+ PROS_SECTION_OBJECT Section;
+ PMMSUPPORT AddressSpace;
+ NTSTATUS Status;
+ PAGED_CODE();
if (MiIsRosSectionObject(SectionObject) == FALSE)
{
ViewSize);
}
- DPRINT("MmMapViewInSystemSpace() called\n");
+ DPRINT("MmMapViewInSystemSpace() called\n");
- Section = (PROS_SECTION_OBJECT)SectionObject;
- AddressSpace = MmGetKernelAddressSpace();
+ Section = (PROS_SECTION_OBJECT)SectionObject;
+ AddressSpace = MmGetKernelAddressSpace();
- MmLockAddressSpace(AddressSpace);
+ MmLockAddressSpace(AddressSpace);
- if ((*ViewSize) == 0)
- {
- (*ViewSize) = Section->MaximumSize.u.LowPart;
- }
- else if ((*ViewSize) > Section->MaximumSize.u.LowPart)
- {
- (*ViewSize) = Section->MaximumSize.u.LowPart;
- }
+ if ((*ViewSize) == 0)
+ {
+ (*ViewSize) = Section->MaximumSize.u.LowPart;
+ }
+ else if ((*ViewSize) > Section->MaximumSize.u.LowPart)
+ {
+ (*ViewSize) = Section->MaximumSize.u.LowPart;
+ }
- MmLockSectionSegment(Section->Segment);
+ MmLockSectionSegment(Section->Segment);
- Status = MmMapViewOfSegment(AddressSpace,
- Section,
- Section->Segment,
- MappedBase,
- *ViewSize,
- PAGE_READWRITE,
- 0,
- 0);
+ Status = MmMapViewOfSegment(AddressSpace,
+ Section,
+ Section->Segment,
+ MappedBase,
+ *ViewSize,
+ PAGE_READWRITE,
+ 0,
+ 0);
- MmUnlockSectionSegment(Section->Segment);
- MmUnlockAddressSpace(AddressSpace);
+ MmUnlockSectionSegment(Section->Segment);
+ MmUnlockAddressSpace(AddressSpace);
- return Status;
+ return Status;
}
NTSTATUS
NTAPI
MiRosUnmapViewInSystemSpace(IN PVOID MappedBase)
{
- PMMSUPPORT AddressSpace;
- NTSTATUS Status;
+ PMMSUPPORT AddressSpace;
+ NTSTATUS Status;
- DPRINT("MmUnmapViewInSystemSpace() called\n");
+ DPRINT("MmUnmapViewInSystemSpace() called\n");
- AddressSpace = MmGetKernelAddressSpace();
+ AddressSpace = MmGetKernelAddressSpace();
- MmLockAddressSpace(AddressSpace);
+ MmLockAddressSpace(AddressSpace);
- Status = MmUnmapViewOfSegment(AddressSpace, MappedBase);
+ Status = MmUnmapViewOfSegment(AddressSpace, MappedBase);
- MmUnlockAddressSpace(AddressSpace);
+ MmUnlockAddressSpace(AddressSpace);
- return Status;
+ return Status;
}
/**********************************************************************
IN PFILE_OBJECT FileObject OPTIONAL)
{
NTSTATUS Status;
- ULONG Protection, FileAccess;
+ ULONG Protection;
PROS_SECTION_OBJECT *SectionObject = (PROS_SECTION_OBJECT *)Section;
/* Check if an ARM3 section is being created instead */
}
}
- /*
- * Check the protection
- */
- Protection = SectionPageProtection & ~(PAGE_GUARD | PAGE_NOCACHE);
- if (Protection != PAGE_READONLY &&
- Protection != PAGE_READWRITE &&
- Protection != PAGE_WRITECOPY &&
- Protection != PAGE_EXECUTE &&
- Protection != PAGE_EXECUTE_READ &&
- Protection != PAGE_EXECUTE_READWRITE &&
- Protection != PAGE_EXECUTE_WRITECOPY)
+ /* Convert section flag to page flag */
+ if (AllocationAttributes & SEC_NOCACHE) SectionPageProtection |= PAGE_NOCACHE;
+
+ /* Check to make sure the protection is correct. Nt* does this already */
+ Protection = MiMakeProtectionMask(SectionPageProtection);
+ if (Protection == MM_INVALID_PROTECTION)
{
+ DPRINT1("Page protection is invalid\n");
return STATUS_INVALID_PAGE_PROTECTION;
}
- if ((DesiredAccess & SECTION_MAP_WRITE) &&
- (Protection == PAGE_READWRITE ||
- Protection == PAGE_EXECUTE_READWRITE) &&
- !(AllocationAttributes & SEC_IMAGE))
+ /* Check if this is going to be a data or image backed file section */
+ if ((FileHandle) || (FileObject))
{
- DPRINT("Creating a section with WRITE access\n");
- FileAccess = FILE_READ_DATA | FILE_WRITE_DATA | SYNCHRONIZE;
- }
- else
- {
- DPRINT("Creating a section with READ access\n");
- FileAccess = FILE_READ_DATA | SYNCHRONIZE;
- }
-
- /* FIXME: somehow combine this with the above checks */
- if (AllocationAttributes & SEC_IMAGE)
- FileAccess = MiArm3GetCorrectFileAccessMask(SectionPageProtection);
+ /* These cannot be mapped with large pages */
+ if (AllocationAttributes & SEC_LARGE_PAGES)
+ {
+ DPRINT1("Large pages cannot be used with an image mapping\n");
+ return STATUS_INVALID_PARAMETER_6;
+ }
- if (!FileObject && FileHandle)
- {
- Status = ObReferenceObjectByHandle(FileHandle,
- FileAccess,
- IoFileObjectType,
- ExGetPreviousMode(),
- (PVOID *)&FileObject,
- NULL);
- if (!NT_SUCCESS(Status))
+ /* Did the caller pass an object? */
+ if (FileObject)
{
- DPRINT("Failed: 0x%08lx\n", Status);
- return Status;
+ /* Reference the object directly */
+ ObReferenceObject(FileObject);
+ }
+ else
+ {
+ /* Reference the file handle to get the object */
+ Status = ObReferenceObjectByHandle(FileHandle,
+ MmMakeFileAccess[Protection],
+ IoFileObjectType,
+ ExGetPreviousMode(),
+ (PVOID*)&FileObject,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to get a handle to the FO: %lx\n", Status);
+ return Status;
+ }
}
}
- else if (FileObject)
- ObReferenceObject(FileObject);
+ else
+ {
+ /* A handle must be supplied with SEC_IMAGE, as this is the no-handle path */
+ if (AllocationAttributes & SEC_IMAGE) return STATUS_INVALID_FILE_FOR_SECTION;
+ }
#ifndef NEWCC // A hack for initializing caching.
// This is needed only in the old case.
&ByteOffset,
NULL);
if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE)
+ {
+ DPRINT1("CC failure: %lx\n", Status);
+ if (FileObject)
+ ObDereferenceObject(FileObject);
return Status;
+ }
// Caching is initialized...
+
+ // Hack of the hack: actually, it might not be initialized if FSD init on effective right and if file is null-size
+ // In such case, force cache by initiating a write IRP
+ if (Status == STATUS_END_OF_FILE && !(AllocationAttributes & SEC_IMAGE) && FileObject != NULL &&
+ (FileObject->SectionObjectPointer == NULL || FileObject->SectionObjectPointer->SharedCacheMap == NULL))
+ {
+ Buffer = 0xdb;
+ Status = ZwWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &Iosb,
+ &Buffer,
+ sizeof(Buffer),
+ &ByteOffset,
+ NULL);
+ if (NT_SUCCESS(Status))
+ {
+ LARGE_INTEGER Zero;
+ Zero.QuadPart = 0LL;
+
+ Status = IoSetInformation(FileObject,
+ FileEndOfFileInformation,
+ sizeof(LARGE_INTEGER),
+ &Zero);
+ ASSERT(NT_SUCCESS(Status));
+ }
+ }
}
#endif
MaximumSize,
SectionPageProtection,
AllocationAttributes,
- FileHandle);
- if (FileObject)
- ObDereferenceObject(FileObject);
+ FileObject);
}
#else
else if (FileHandle != NULL || FileObject != NULL)
MaximumSize,
SectionPageProtection,
AllocationAttributes);
+ if (FileObject)
+ ObDereferenceObject(FileObject);
}
return Status;