/* $Id$
*
- * COPYRIGHT: See COPYING in the top level directory
+ * Copyright (C) 1998-2005 ReactOS Team (and the authors from the programmers section)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/mm/section.c
* PURPOSE: Implements section objects
*
- * PROGRAMMERS: David Welch (welch@mcmail.com)
+ * PROGRAMMERS: Rex Jolliff
+ * David Welch
+ * Eric Kohl
+ * Emanuele Aliberti
+ * Eugene Ingerman
+ * Hartmut Birr
+ * Casper Hornstrup
+ * KJK::Hyperion
+ * Guido de Jong
+ * Ge van Geldorp
+ * Royce Mitchell III
+ * Filip Navara
+ * Aleksey Bragin
+ * Jason Filby
+ * Thomas Weidenmueller
+ * Gunnar Andre' Dalsnes
+ * Mike Nordell
+ * Alex Ionescu
+ * Gregor Anich
+ * Steven Edwards
+ * Herve Poussineau
*/
/* INCLUDES *****************************************************************/
STANDARD_RIGHTS_EXECUTE | SECTION_MAP_EXECUTE,
SECTION_ALL_ACCESS};
-#define TAG_MM_SECTION_SEGMENT TAG('M', 'M', 'S', 'S')
-#define TAG_SECTION_PAGE_TABLE TAG('M', 'S', 'P', 'T')
-
#define PAGE_FROM_SSE(E) ((E) & 0xFFFFF000)
#define PFN_FROM_SSE(E) ((E) >> PAGE_SHIFT)
#define SHARE_COUNT_FROM_SSE(E) (((E) & 0x00000FFE) >> 1)
}
VOID
+NTAPI
MmFreeSectionSegments(PFILE_OBJECT FileObject)
{
if (FileObject->SectionObjectPointer->ImageSectionObject != NULL)
}
VOID
+NTAPI
MmLockSectionSegment(PMM_SECTION_SEGMENT Segment)
{
ExAcquireFastMutex(&Segment->Lock);
}
VOID
+NTAPI
MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment)
{
ExReleaseFastMutex(&Segment->Lock);
}
VOID
+NTAPI
MmSetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
ULONG Offset,
ULONG Entry)
{
Table =
Segment->PageDirectory.PageTables[DirectoryOffset] =
- ExAllocatePoolWithTag(NonPagedPool, sizeof(SECTION_PAGE_TABLE),
+ ExAllocatePoolWithTag(PagedPool, sizeof(SECTION_PAGE_TABLE),
TAG_SECTION_PAGE_TABLE);
if (Table == NULL)
{
ULONG
+NTAPI
MmGetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
ULONG Offset)
{
}
VOID
+NTAPI
MmSharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
ULONG Offset)
{
}
BOOLEAN
+NTAPI
MmUnsharePageEntrySectionSegment(PSECTION_OBJECT Section,
PMM_SECTION_SEGMENT Segment,
ULONG Offset,
}
NTSTATUS
+NTAPI
MiReadPage(PMEMORY_AREA MemoryArea,
ULONG SegOffset,
PPFN_TYPE Page)
}
NTSTATUS
+NTAPI
MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
MEMORY_AREA* MemoryArea,
PVOID Address,
}
PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
- Offset = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress;
+ Offset = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress
+ + MemoryArea->Data.SectionData.ViewOffset;
Segment = MemoryArea->Data.SectionData.Segment;
Section = MemoryArea->Data.SectionData.Section;
/* FIXME: Should we call MmCreateVirtualMappingUnsafe if
* (Section->AllocationAttributes & SEC_PHYSICALMEMORY) is true?
*/
- Status = MmCreateVirtualMapping(MemoryArea->Process,
+ Status = MmCreateVirtualMapping(AddressSpace->Process,
Address,
Attributes,
&Page,
DbgPrint("Unable to create virtual mapping\n");
KEBUGCHECK(0);
}
- MmInsertRmap(Page, MemoryArea->Process, (PVOID)PAddress);
+ MmInsertRmap(Page, AddressSpace->Process, (PVOID)PAddress);
}
if (Locked)
{
/*
* Just map the desired physical page
*/
- Page = (Offset + MemoryArea->Data.SectionData.ViewOffset) >> PAGE_SHIFT;
+ Page = Offset >> PAGE_SHIFT;
Status = MmCreateVirtualMappingUnsafe(AddressSpace->Process,
Address,
Region->Protect,
/*
* Map anonymous memory for BSS sections
*/
- if (Segment->Characteristics & IMAGE_SCN_LNK_OTHER)
+ if (Segment->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
{
MmUnlockSectionSegment(Segment);
Status = MmRequestPageMemoryConsumer(MC_USER, FALSE, &Page);
/*
* Get the entry corresponding to the offset within the section
*/
- Offset += MemoryArea->Data.SectionData.ViewOffset;
Entry = MmGetPageEntrySectionSegment(Segment, Offset);
if (Entry == 0)
}
NTSTATUS
+NTAPI
MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
MEMORY_AREA* MemoryArea,
PVOID Address,
* Find the offset of the page
*/
PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
- Offset = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress;
+ Offset = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress
+ + MemoryArea->Data.SectionData.ViewOffset;
Segment = MemoryArea->Data.SectionData.Segment;
Section = MemoryArea->Data.SectionData.Section;
*/
MiCopyFromUserPage(NewPage, PAddress);
+ MmLockAddressSpace(AddressSpace);
/*
* Delete the old entry.
*/
/*
* Set the PTE to point to the new page
*/
- MmLockAddressSpace(AddressSpace);
Status = MmCreateVirtualMapping(AddressSpace->Process,
Address,
Region->Protect,
KEBUGCHECK(0);
return(Status);
}
- MmInsertRmap(NewPage, AddressSpace->Process, PAddress);
if (!NT_SUCCESS(Status))
{
DbgPrint("Unable to create virtual mapping\n");
* Unshare the old page.
*/
MmDeleteRmap(OldPage, AddressSpace->Process, PAddress);
+ MmInsertRmap(NewPage, AddressSpace->Process, PAddress);
MmLockSectionSegment(Segment);
MmUnsharePageEntrySectionSegment(Section, Segment, Offset, FALSE, FALSE);
MmUnlockSectionSegment(Segment);
PFN_TYPE Page;
PageOutContext = (MM_SECTION_PAGEOUT_CONTEXT*)Context;
+ if (Process)
+ {
+ MmLockAddressSpace(&Process->AddressSpace);
+ }
+
MmDeleteVirtualMapping(Process,
Address,
FALSE,
}
if (!PageOutContext->Private)
{
+ MmLockSectionSegment(PageOutContext->Segment);
MmUnsharePageEntrySectionSegment(PageOutContext->Section,
PageOutContext->Segment,
PageOutContext->Offset,
PageOutContext->WasDirty,
TRUE);
+ MmUnlockSectionSegment(PageOutContext->Segment);
}
- else
+ if (Process)
+ {
+ MmUnlockAddressSpace(&Process->AddressSpace);
+ }
+
+ if (PageOutContext->Private)
{
MmReleasePageMemoryConsumer(MC_USER, Page);
}
- DPRINT("PhysicalAddress %I64x, Address %x\n", Page, Address);
+ DPRINT("PhysicalAddress %x, Address %x\n", Page << PAGE_SHIFT, Address);
}
NTSTATUS
+NTAPI
MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
MEMORY_AREA* MemoryArea,
PVOID Address,
Context.Segment = MemoryArea->Data.SectionData.Segment;
Context.Section = MemoryArea->Data.SectionData.Section;
- Context.Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress;
+ Context.Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress
+ + MemoryArea->Data.SectionData.ViewOffset;
FileOffset = Context.Offset + Context.Segment->FileOffset;
IsImageSection = Context.Section->AllocationAttributes & SEC_IMAGE ? TRUE : FALSE;
* Prepare the context structure for the rmap delete call.
*/
Context.WasDirty = FALSE;
- if (Context.Segment->Characteristics & IMAGE_SCN_LNK_OTHER ||
+ if (Context.Segment->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ||
IS_SWAP_FROM_SSE(Entry) ||
PFN_FROM_SSE(Entry) != Page)
{
else if (!Context.WasDirty && Context.Private && SwapEntry != 0)
{
MmSetSavedSwapEntryPage(Page, 0);
+ MmLockAddressSpace(AddressSpace);
Status = MmCreatePageFileMapping(AddressSpace->Process,
Address,
SwapEntry);
+ MmUnlockAddressSpace(AddressSpace);
if (!NT_SUCCESS(Status))
{
KEBUGCHECK(0);
if (SwapEntry == 0)
{
MmShowOutOfSpaceMessagePagingFile();
-
+ MmLockAddressSpace(AddressSpace);
/*
* For private pages restore the old mappings.
*/
if (Context.Private)
{
- Status = MmCreateVirtualMapping(MemoryArea->Process,
+ Status = MmCreateVirtualMapping(AddressSpace->Process,
Address,
MemoryArea->Attributes,
&Page,
1);
- MmSetDirtyPage(MemoryArea->Process, Address);
+ MmSetDirtyPage(AddressSpace->Process, Address);
MmInsertRmap(Page,
- MemoryArea->Process,
+ AddressSpace->Process,
Address);
}
else
* 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(MemoryArea->Process,
+ Status = MmCreateVirtualMapping(AddressSpace->Process,
Address,
MemoryArea->Attributes,
&Page,
1);
- MmSetDirtyPage(MemoryArea->Process, Address);
+ MmSetDirtyPage(AddressSpace->Process, Address);
MmInsertRmap(Page,
- MemoryArea->Process,
+ AddressSpace->Process,
Address);
Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
MmSetPageEntrySectionSegment(Context.Segment, Context.Offset, Entry);
}
+ MmUnlockAddressSpace(AddressSpace);
PageOp->Status = STATUS_UNSUCCESSFUL;
MmspCompleteAndReleasePageOp(PageOp);
return(STATUS_PAGEFILE_QUOTA);
* As above: undo our actions.
* FIXME: Also free the swap page.
*/
+ MmLockAddressSpace(AddressSpace);
if (Context.Private)
{
- Status = MmCreateVirtualMapping(MemoryArea->Process,
+ Status = MmCreateVirtualMapping(AddressSpace->Process,
Address,
MemoryArea->Attributes,
&Page,
1);
- MmSetDirtyPage(MemoryArea->Process, Address);
+ MmSetDirtyPage(AddressSpace->Process, Address);
MmInsertRmap(Page,
- MemoryArea->Process,
+ AddressSpace->Process,
Address);
}
else
{
- Status = MmCreateVirtualMapping(MemoryArea->Process,
+ Status = MmCreateVirtualMapping(AddressSpace->Process,
Address,
MemoryArea->Attributes,
&Page,
1);
- MmSetDirtyPage(MemoryArea->Process, Address);
+ MmSetDirtyPage(AddressSpace->Process, Address);
MmInsertRmap(Page,
- MemoryArea->Process,
+ AddressSpace->Process,
Address);
Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
MmSetPageEntrySectionSegment(Context.Segment, Context.Offset, Entry);
}
+ MmUnlockAddressSpace(AddressSpace);
PageOp->Status = STATUS_UNSUCCESSFUL;
MmspCompleteAndReleasePageOp(PageOp);
return(STATUS_UNSUCCESSFUL);
if (Context.Private)
{
- Status = MmCreatePageFileMapping(MemoryArea->Process,
+ MmLockAddressSpace(AddressSpace);
+ Status = MmCreatePageFileMapping(AddressSpace->Process,
Address,
SwapEntry);
+ MmUnlockAddressSpace(AddressSpace);
if (!NT_SUCCESS(Status))
{
KEBUGCHECK(0);
}
NTSTATUS
+NTAPI
MmWritePageSectionView(PMADDRESS_SPACE AddressSpace,
PMEMORY_AREA MemoryArea,
PVOID Address,
Address = (PVOID)PAGE_ROUND_DOWN(Address);
- Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress;
+ Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress
+ + MemoryArea->Data.SectionData.ViewOffset;
/*
* Get the segment and section.
* memory area was mapped at an offset in the file which is page aligned
* then note this is a direct mapped page.
*/
- if ((Offset + MemoryArea->Data.SectionData.ViewOffset % PAGE_SIZE) == 0 &&
+ if (((Offset + Segment->FileOffset) % PAGE_SIZE) == 0 &&
(Offset + PAGE_SIZE <= Segment->RawLength || !IsImageSection))
{
DirectMapped = TRUE;
/*
* Check for a private (COWed) page.
*/
- if (Segment->Characteristics & IMAGE_SCN_LNK_OTHER ||
+ if (Segment->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ||
IS_SWAP_FROM_SSE(Entry) ||
PFN_FROM_SSE(Entry) != Page)
{
if (DirectMapped && !Private)
{
ASSERT(SwapEntry == 0);
- CcRosMarkDirtyCacheSegment(Bcb, Offset + MemoryArea->Data.SectionData.ViewOffset);
+ CcRosMarkDirtyCacheSegment(Bcb, Offset + Segment->FileOffset);
PageOp->Status = STATUS_SUCCESS;
MmspCompleteAndReleasePageOp(PageOp);
return(STATUS_SUCCESS);
ULONG Entry;
PFN_TYPE Page;
- Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress;
+ Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress
+ + MemoryArea->Data.SectionData.ViewOffset;
Entry = MmGetPageEntrySectionSegment(Segment, Offset);
Page = MmGetPfnForProcess(AddressSpace->Process, Address);
Protect = PAGE_READONLY;
- if (Segment->Characteristics & IMAGE_SCN_LNK_OTHER ||
+ if (Segment->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ||
IS_SWAP_FROM_SSE(Entry) ||
PFN_FROM_SSE(Entry) != Page)
{
}
NTSTATUS
+NTAPI
MmProtectSectionView(PMADDRESS_SPACE AddressSpace,
PMEMORY_AREA MemoryArea,
PVOID BaseAddress,
PMM_REGION Region;
PVOID RegionBaseAddress;
PSECTION_OBJECT Section;
- PLIST_ENTRY CurrentEntry;
- PMEMORY_AREA CurrentMArea;
- KIRQL oldIrql;
+ PMM_SECTION_SEGMENT Segment;
Region = MmFindRegion((PVOID)MemoryArea->StartingAddress,
&MemoryArea->Data.SectionData.RegionListHead,
{
return STATUS_UNSUCCESSFUL;
}
+
Section = MemoryArea->Data.SectionData.Section;
if (Section->AllocationAttributes & SEC_IMAGE)
{
- KeAcquireSpinLock(&Section->ViewListLock, &oldIrql);
- CurrentEntry = Section->ViewListHead.Flink;
- Info->AllocationBase = NULL;
- while (CurrentEntry != &Section->ViewListHead)
- {
- CurrentMArea = CONTAINING_RECORD(CurrentEntry, MEMORY_AREA, Data.SectionData.ViewListEntry);
- CurrentEntry = CurrentEntry->Flink;
- if (Info->AllocationBase == NULL)
- {
- Info->AllocationBase = CurrentMArea->StartingAddress;
- }
- else if (CurrentMArea->StartingAddress < Info->AllocationBase)
- {
- Info->AllocationBase = CurrentMArea->StartingAddress;
- }
- }
- KeReleaseSpinLock(&Section->ViewListLock, oldIrql);
- Info->BaseAddress = RegionBaseAddress;
- Info->AllocationProtect = MemoryArea->Attributes;
+ Segment = MemoryArea->Data.SectionData.Segment;
+ Info->AllocationBase = (PBYTE)MemoryArea->StartingAddress - Segment->VirtualAddress;
Info->Type = MEM_IMAGE;
}
else
{
- Info->BaseAddress = RegionBaseAddress;
Info->AllocationBase = MemoryArea->StartingAddress;
- Info->AllocationProtect = MemoryArea->Attributes;
Info->Type = MEM_MAPPED;
}
- Info->RegionSize = PAGE_ROUND_UP((ULONG_PTR)MemoryArea->EndingAddress -
- (ULONG_PTR)MemoryArea->StartingAddress);
+ Info->BaseAddress = RegionBaseAddress;
+ Info->AllocationProtect = MemoryArea->Attributes;
+ Info->RegionSize = Region->Length;
Info->State = MEM_COMMIT;
Info->Protect = Region->Protect;
}
VOID
+NTAPI
MmpFreePageFileSegment(PMM_SECTION_SEGMENT Segment)
{
ULONG Length;
ObjectBody, HandleCount, ObGetObjectPointerCount(ObjectBody));
}
-NTSTATUS INIT_FUNCTION
+NTSTATUS
+INIT_FUNCTION
+NTAPI
MmCreatePhysicalMemorySection(VOID)
{
PSECTION_OBJECT PhysSection;
NTSTATUS Status;
OBJECT_ATTRIBUTES Obj;
- UNICODE_STRING Name = ROS_STRING_INITIALIZER(L"\\Device\\PhysicalMemory");
+ UNICODE_STRING Name = RTL_CONSTANT_STRING(L"\\Device\\PhysicalMemory");
LARGE_INTEGER SectionSize;
/*
ObDereferenceObject(PhysSection);
}
PhysSection->AllocationAttributes |= SEC_PHYSICALMEMORY;
+ PhysSection->Segment->Flags &= ~MM_PAGEFILE_SEGMENT;
return(STATUS_SUCCESS);
}
-NTSTATUS INIT_FUNCTION
+NTSTATUS
+INIT_FUNCTION
+NTAPI
MmInitSectionImplementation(VOID)
{
OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
UNICODE_STRING Name;
- DPRINT1("Creating Section Object Type\n");
+ DPRINT("Creating Section Object Type\n");
/* Initialize the Section object type */
RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
RtlInitUnicodeString(&Name, L"Section");
ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
- ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(SECTION_OBJECT);
- ObjectTypeInitializer.PoolType = NonPagedPool;
+ ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(SECTION_OBJECT);
+ ObjectTypeInitializer.PoolType = PagedPool;
ObjectTypeInitializer.UseDefaultObject = TRUE;
ObjectTypeInitializer.GenericMapping = MmpSectionMapping;
ObjectTypeInitializer.DeleteProcedure = MmpDeleteSection;
}
NTSTATUS
+NTAPI
MmCreatePageFileSection(PSECTION_OBJECT *SectionObject,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
Section->SectionPageProtection = SectionPageProtection;
Section->AllocationAttributes = AllocationAttributes;
Section->Segment = NULL;
- InitializeListHead(&Section->ViewListHead);
- KeInitializeSpinLock(&Section->ViewListLock);
Section->FileObject = NULL;
Section->MaximumSize = MaximumSize;
Segment = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_SECTION_SEGMENT),
NTSTATUS
+NTAPI
MmCreateDataFileSection(PSECTION_OBJECT *SectionObject,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
Section->SectionPageProtection = SectionPageProtection;
Section->AllocationAttributes = AllocationAttributes;
Section->Segment = NULL;
- InitializeListHead(&Section->ViewListHead);
- KeInitializeSpinLock(&Section->ViewListLock);
/*
* Check file access required
* (as in case of the EXT2FS driver by Manoj Paul Joseph where the
* standard file information is filled on first request).
*/
- Status = NtQueryInformationFile(FileHandle,
- &Iosb,
- &FileInfo,
+ Status = IoQueryFileInformation(FileObject,
+ FileStandardInformation,
sizeof(FILE_STANDARD_INFORMATION),
- FileStandardInformation);
+ &FileInfo,
+ &Iosb.Information);
if (!NT_SUCCESS(Status))
{
ObDereferenceObject(Section);
if (MaximumSize.QuadPart > FileInfo.EndOfFile.QuadPart)
{
- Status = NtSetInformationFile(FileHandle,
- &Iosb,
- &MaximumSize,
- sizeof(LARGE_INTEGER),
- FileAllocationInformation);
+ Status = IoSetInformation(FileObject,
+ FileAllocationInformation,
+ sizeof(LARGE_INTEGER),
+ &MaximumSize);
if (!NT_SUCCESS(Status))
{
ObDereferenceObject(Section);
KEBUGCHECK(STATUS_INVALID_PARAMETER_5);
}
- ASSERT(PAGE_SIZE <= MAXULONG);
AdjustOffset = PAGE_ROUND_DOWN(FileOffset.u.LowPart);
OffsetAdjustment = FileOffset.u.LowPart - AdjustOffset;
FileOffset.u.LowPart = AdjustOffset;
ULONG i;
ULONG LastSegment;
BOOLEAN Initialized;
+ PMM_SECTION_SEGMENT EffectiveSegment;
if (Flags & EXEFMT_LOAD_ASSUME_SEGMENTS_PAGE_ALIGNED)
{
Initialized = FALSE;
LastSegment = 0;
+ EffectiveSegment = &ImageSectionObject->Segments[LastSegment];
for ( i = 0; i < ImageSectionObject->NrSegments; ++ i )
{
- PMM_SECTION_SEGMENT EffectiveSegment = &ImageSectionObject->Segments[LastSegment];
-
/*
* The first segment requires special handling
*/
EffectiveSegment = &ImageSectionObject->Segments[LastSegment];
- /*
- * Copy the current segment. If necessary, the effective segment
- * will be expanded later
- */
- *EffectiveSegment = *Segment;
+ 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
/*
* Extend the virtual size
*/
- ASSERT(PAGE_ROUND_UP(Segment->VirtualAddress + Segment->Length) > EndOfEffectiveSegment);
+ ASSERT(PAGE_ROUND_UP(Segment->VirtualAddress + Segment->Length) >= EndOfEffectiveSegment);
EffectiveSegment->Length = PAGE_ROUND_UP(Segment->VirtualAddress + Segment->Length) -
EffectiveSegment->VirtualAddress;
}
}
}
+ ImageSectionObject->NrSegments = LastSegment + 1;
return TRUE;
}
*/
if (Status == STATUS_ROS_EXEFMT_UNKNOWN_FORMAT)
{
- Status = STATUS_INVALID_IMAGE_FORMAT;
+ Status = STATUS_INVALID_IMAGE_NOT_MZ;
ASSERT(!NT_SUCCESS(Status));
}
SizeOfSegments = sizeof(MM_SECTION_SEGMENT) * ImageSectionObject->NrSegments;
- Segments = ExAllocatePoolWithTag(NonPagedPool,
+ Segments = ExAllocatePoolWithTag(PagedPool,
SizeOfSegments,
TAG_MM_SECTION_SEGMENT);
*/
Section->SectionPageProtection = SectionPageProtection;
Section->AllocationAttributes = AllocationAttributes;
- InitializeListHead(&Section->ViewListHead);
- KeInitializeSpinLock(&Section->ViewListLock);
/*
* Initialized caching for this file object if previously caching
{
NTSTATUS StatusExeFmt;
- ImageSectionObject = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_IMAGE_SECTION_OBJECT), TAG_MM_SECTION_SEGMENT);
+ 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(FileHandle, ImageSectionObject);
{
_SEH_TRY
{
- ProbeForRead(MaximumSize,
- sizeof(LARGE_INTEGER),
- sizeof(ULONG));
/* make a copy on the stack */
- SafeMaximumSize = *MaximumSize;
+ SafeMaximumSize = ProbeForReadLargeInteger(MaximumSize);
MaximumSize = &SafeMaximumSize;
}
_SEH_HANDLE
{
_SEH_TRY
{
- ProbeForWrite(SectionHandle,
- sizeof(HANDLE),
- sizeof(ULONG));
+ ProbeForWriteHandle(SectionHandle);
}
_SEH_HANDLE
{
{
PMEMORY_AREA MArea;
NTSTATUS Status;
- KIRQL oldIrql;
PHYSICAL_ADDRESS BoundaryAddressMultiple;
BoundaryAddressMultiple.QuadPart = 0;
return(Status);
}
- KeAcquireSpinLock(&Section->ViewListLock, &oldIrql);
- InsertTailList(&Section->ViewListHead,
- &MArea->Data.SectionData.ViewListEntry);
- KeReleaseSpinLock(&Section->ViewListLock, oldIrql);
ObReferenceObjectByPointer((PVOID)Section,
SECTION_MAP_READ,
{
if(BaseAddress != NULL)
{
- ProbeForWrite(BaseAddress,
- sizeof(PVOID),
- sizeof(ULONG));
+ ProbeForWritePointer(BaseAddress);
SafeBaseAddress = *BaseAddress;
}
if(SectionOffset != NULL)
{
- ProbeForWrite(SectionOffset,
- sizeof(LARGE_INTEGER),
- sizeof(ULONG));
+ ProbeForWriteLargeInteger(SectionOffset);
SafeSectionOffset = *SectionOffset;
}
- ProbeForWrite(ViewSize,
- sizeof(ULONG),
- sizeof(ULONG));
+ ProbeForWriteUlong(ViewSize);
SafeViewSize = *ViewSize;
}
_SEH_HANDLE
MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
PFN_TYPE Page, SWAPENTRY SwapEntry, BOOLEAN Dirty)
{
- PMEMORY_AREA MArea;
ULONG Entry;
PFILE_OBJECT FileObject;
PBCB Bcb;
NTSTATUS Status;
PSECTION_OBJECT Section;
PMM_SECTION_SEGMENT Segment;
+ PMADDRESS_SPACE AddressSpace;
- MArea = (PMEMORY_AREA)Context;
+ AddressSpace = (PMADDRESS_SPACE)Context;
Address = (PVOID)PAGE_ROUND_DOWN(Address);
- Offset = ((ULONG_PTR)Address - (ULONG_PTR)MArea->StartingAddress) +
+ Offset = ((ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress) +
MemoryArea->Data.SectionData.ViewOffset;
- Section = MArea->Data.SectionData.Section;
- Segment = MArea->Data.SectionData.Segment;
+ Section = MemoryArea->Data.SectionData.Section;
+ Segment = MemoryArea->Data.SectionData.Segment;
- PageOp = MmCheckForPageOp(MArea, NULL, NULL, Segment, Offset);
+ PageOp = MmCheckForPageOp(MemoryArea, NULL, NULL, Segment, Offset);
while (PageOp)
{
MmUnlockSectionSegment(Segment);
- MmUnlockAddressSpace(&MArea->Process->AddressSpace);
+ MmUnlockAddressSpace(AddressSpace);
Status = MmspWaitForPageOpCompletionEvent(PageOp);
if (Status != STATUS_SUCCESS)
KEBUGCHECK(0);
}
- MmLockAddressSpace(&MArea->Process->AddressSpace);
+ MmLockAddressSpace(AddressSpace);
MmLockSectionSegment(Segment);
MmspCompleteAndReleasePageOp(PageOp);
- PageOp = MmCheckForPageOp(MArea, NULL, NULL, Segment, Offset);
+ PageOp = MmCheckForPageOp(MemoryArea, NULL, NULL, Segment, Offset);
}
Entry = MmGetPageEntrySectionSegment(Segment, Offset);
{
FileObject = MemoryArea->Data.SectionData.Section->FileObject;
Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
- CcRosMarkDirtyCacheSegment(Bcb, Offset);
+ CcRosMarkDirtyCacheSegment(Bcb, Offset + Segment->FileOffset);
ASSERT(SwapEntry == 0);
}
}
MmFreeSwapPage(SavedSwapEntry);
MmSetSavedSwapEntryPage(Page, 0);
}
- MmDeleteRmap(Page, MArea->Process, Address);
+ MmDeleteRmap(Page, AddressSpace->Process, Address);
MmReleasePageMemoryConsumer(MC_USER, Page);
}
else
{
- MmDeleteRmap(Page, MArea->Process, Address);
+ MmDeleteRmap(Page, AddressSpace->Process, Address);
MmUnsharePageEntrySectionSegment(Section, Segment, Offset, Dirty, FALSE);
}
}
}
-NTSTATUS
+STATIC NTSTATUS
MmUnmapViewOfSegment(PMADDRESS_SPACE AddressSpace,
PVOID BaseAddress)
{
PMEMORY_AREA MemoryArea;
PSECTION_OBJECT Section;
PMM_SECTION_SEGMENT Segment;
- KIRQL oldIrql;
PLIST_ENTRY CurrentEntry;
PMM_REGION CurrentRegion;
PLIST_ENTRY RegionListHead;
Segment = MemoryArea->Data.SectionData.Segment;
MmLockSectionSegment(Segment);
- KeAcquireSpinLock(&Section->ViewListLock, &oldIrql);
- RemoveEntryList(&MemoryArea->Data.SectionData.ViewListEntry);
- KeReleaseSpinLock(&Section->ViewListLock, oldIrql);
RegionListHead = &MemoryArea->Data.SectionData.RegionListHead;
while (!IsListEmpty(RegionListHead))
Status = MmFreeMemoryArea(AddressSpace,
MemoryArea,
MmFreeSectionPage,
- MemoryArea);
+ AddressSpace);
}
MmUnlockSectionSegment(Segment);
ObDereferenceObject(Section);
PMEMORY_AREA MemoryArea;
PMADDRESS_SPACE AddressSpace;
PSECTION_OBJECT Section;
+ PMM_PAGEOP PageOp;
+ ULONG_PTR Offset;
DPRINT("Opening memory area Process %x BaseAddress %x\n",
Process, BaseAddress);
ASSERT(Process);
AddressSpace = &Process->AddressSpace;
+
+ MmLockAddressSpace(AddressSpace);
MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace,
BaseAddress);
if (MemoryArea == NULL ||
MemoryArea->Type != MEMORY_AREA_SECTION_VIEW ||
MemoryArea->DeleteInProgress)
{
+ MmUnlockAddressSpace(AddressSpace);
return STATUS_NOT_MAPPED_VIEW;
}
+ MemoryArea->DeleteInProgress = TRUE;
+
+ while (MemoryArea->PageOpCount)
+ {
+ Offset = PAGE_ROUND_UP((ULONG_PTR)MemoryArea->EndingAddress - (ULONG_PTR)MemoryArea->StartingAddress);
+
+ while (Offset)
+ {
+ Offset -= PAGE_SIZE;
+ PageOp = MmCheckForPageOp(MemoryArea, NULL, NULL,
+ MemoryArea->Data.SectionData.Segment,
+ Offset + MemoryArea->Data.SectionData.ViewOffset);
+ if (PageOp)
+ {
+ MmUnlockAddressSpace(AddressSpace);
+ Status = MmspWaitForPageOpCompletionEvent(PageOp);
+ if (Status != STATUS_SUCCESS)
+ {
+ DPRINT1("Failed to wait for page op, status = %x\n", Status);
+ KEBUGCHECK(0);
+ }
+ MmLockAddressSpace(AddressSpace);
+ MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace,
+ BaseAddress);
+ if (MemoryArea == NULL ||
+ MemoryArea->Type != MEMORY_AREA_SECTION_VIEW)
+ {
+ MmUnlockAddressSpace(AddressSpace);
+ return STATUS_NOT_MAPPED_VIEW;
+ }
+ break;
+ }
+ }
+ }
+
Section = MemoryArea->Data.SectionData.Section;
if (Section->AllocationAttributes & SEC_IMAGE)
{
Status = MmUnmapViewOfSegment(AddressSpace, BaseAddress);
}
+ MmUnlockAddressSpace(AddressSpace);
return(STATUS_SUCCESS);
}
return(Status);
}
- MmLockAddressSpace(&Process->AddressSpace);
Status = MmUnmapViewOfSection(Process, BaseAddress);
- MmUnlockAddressSpace(&Process->AddressSpace);
ObDereferenceObject(Process);
PreviousMode = ExGetPreviousMode();
- DefaultQueryInfoBufferCheck(SectionInformationClass,
- ExSectionInfoClass,
- SectionInformation,
- SectionInformationLength,
- ResultLength,
- PreviousMode,
- &Status);
+ Status = DefaultQueryInfoBufferCheck(SectionInformationClass,
+ ExSectionInfoClass,
+ sizeof(ExSectionInfoClass) / sizeof(ExSectionInfoClass[0]),
+ SectionInformation,
+ SectionInformationLength,
+ ResultLength,
+ PreviousMode);
if(!NT_SUCCESS(Status))
{
PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
ImageSectionObject = Section->ImageSection;
- Sii->EntryPoint = ImageSectionObject->EntryPoint;
- Sii->StackReserve = ImageSectionObject->StackReserve;
- Sii->StackCommit = ImageSectionObject->StackCommit;
- Sii->Subsystem = ImageSectionObject->Subsystem;
- Sii->MinorSubsystemVersion = ImageSectionObject->MinorSubsystemVersion;
- Sii->MajorSubsystemVersion = ImageSectionObject->MajorSubsystemVersion;
- Sii->Characteristics = ImageSectionObject->ImageCharacteristics;
- Sii->ImageNumber = ImageSectionObject->Machine;
- Sii->Executable = ImageSectionObject->Executable;
+ 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)
{
_SEH_TRY
{
- ProbeForRead(NewMaximumSize,
- sizeof(LARGE_INTEGER),
- sizeof(ULONG));
/* make a copy on the stack */
- SafeNewMaximumSize = *NewMaximumSize;
+ SafeNewMaximumSize = ProbeForReadLargeInteger(NewMaximumSize);
NewMaximumSize = &SafeNewMaximumSize;
}
_SEH_HANDLE
*ViewSize,
Protect,
ViewOffset,
- (AllocationType & MEM_TOP_DOWN));
+ (AllocationType & MEM_TOP_DOWN) == MEM_TOP_DOWN);
MmUnlockSectionSegment(Section->Segment);
if (!NT_SUCCESS(Status))
{