-/*
- * ReactOS kernel
- * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
+/* $Id$
*
- * 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.
+ * Copyright (C) 1998-2005 ReactOS Team (and the authors from the programmers section)
*
- * 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.
+ * 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.
*
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-/* $Id$
*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/mm/section.c
* PURPOSE: Implements section objects
- * PROGRAMMER: David Welch (welch@mcmail.com)
- * UPDATE HISTORY:
- * Created 22/05/98
+ *
+ * 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)
#define SWAPENTRY_FROM_SSE(E) ((E) >> 1)
#define MAKE_SWAP_SSE(S) (((S) << 1) | 0x1)
+static const INFORMATION_CLASS_INFO ExSectionInfoClass[] =
+{
+ ICI_SQ_SAME( sizeof(SECTION_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* SectionBasicInformation */
+ ICI_SQ_SAME( sizeof(SECTION_IMAGE_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* SectionImageInformation */
+};
+
/* FUNCTIONS *****************************************************************/
/* Note: Mmsp prefix denotes "Memory Manager Section Private". */
}
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,
{
/*
* FIXME:
- * We hold all locks. Nobody can do something with the current
+ * We hold all locks. Nobody can do something with the current
* process and the current segment (also not within an other process).
*/
NTSTATUS Status;
}
NTSTATUS
+NTAPI
MiReadPage(PMEMORY_AREA MemoryArea,
ULONG SegOffset,
PPFN_TYPE Page)
return Status;
}
}
- PageAddr = ExAllocatePageWithPhysPage(*Page);
+ PageAddr = MmCreateHyperspaceMapping(*Page);
CacheSegOffset = BaseOffset + CacheSeg->Bcb->CacheSegmentSize - FileOffset;
Length = RawLength - SegOffset;
if (Length <= CacheSegOffset && Length <= PAGE_SIZE)
&CacheSeg);
if (!NT_SUCCESS(Status))
{
- ExUnmapPage(PageAddr);
+ MmDeleteHyperspaceMapping(PageAddr);
return(Status);
}
if (!UptoDate)
if (!NT_SUCCESS(Status))
{
CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE);
- ExUnmapPage(PageAddr);
+ MmDeleteHyperspaceMapping(PageAddr);
return Status;
}
}
}
}
CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, FALSE);
- ExUnmapPage(PageAddr);
+ MmDeleteHyperspaceMapping(PageAddr);
}
return(STATUS_SUCCESS);
}
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;
/*
* Get or create a page operation descriptor
*/
- PageOp = MmGetPageOp(MemoryArea, 0, 0, Segment, Offset, MM_PAGEOP_PAGEIN, FALSE);
+ PageOp = MmGetPageOp(MemoryArea, NULL, 0, Segment, Offset, MM_PAGEOP_PAGEIN, FALSE);
if (PageOp == NULL)
{
DPRINT1("MmGetPageOp failed\n");
if (PAGE_FROM_SSE(Entry) == 0 || HasSwapEntry)
{
/*
- * The page was a private page in another or in our address space
+ * The page was a private page in another or in our address space
*/
MmUnlockSectionSegment(Segment);
MmspCompleteAndReleasePageOp(PageOp);
MmSharePageEntrySectionSegment(Segment, Offset);
- Status = MmCreateVirtualMapping(MemoryArea->Process,
+ /* FIXME: Should we call MmCreateVirtualMappingUnsafe if
+ * (Section->AllocationAttributes & SEC_PHYSICALMEMORY) is true?
+ */
+ 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;
- Status = MmCreateVirtualMapping(AddressSpace->Process,
- Address,
- Region->Protect,
- &Page,
- 1);
+ Page = Offset >> PAGE_SHIFT;
+ Status = MmCreateVirtualMappingUnsafe(AddressSpace->Process,
+ Address,
+ Region->Protect,
+ &Page,
+ 1);
if (!NT_SUCCESS(Status))
{
- DPRINT("MmCreateVirtualMapping failed, not out of memory\n");
+ DPRINT("MmCreateVirtualMappingUnsafe failed, not out of memory\n");
KEBUGCHECK(0);
return(Status);
}
*/
if (Locked)
{
- MmLockPage(Page);
+ MmLockPageUnsafe(Page);
}
/*
/*
* 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,
PSECTION_OBJECT Section;
PFN_TYPE OldPage;
PFN_TYPE NewPage;
- PVOID NewAddress;
NTSTATUS Status;
PVOID PAddress;
ULONG Offset;
* 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;
/*
* Get or create a pageop
*/
- PageOp = MmGetPageOp(MemoryArea, 0, 0, Segment, Offset,
+ PageOp = MmGetPageOp(MemoryArea, NULL, 0, Segment, Offset,
MM_PAGEOP_ACCESSFAULT, FALSE);
if (PageOp == NULL)
{
/*
* Copy the old page
*/
-
- NewAddress = ExAllocatePageWithPhysPage(NewPage);
- memcpy(NewAddress, PAddress, PAGE_SIZE);
- ExUnmapPage(NewAddress);
+ MiCopyFromUserPage(NewPage, PAddress);
/*
* Delete the old entry.
}
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)
{
*/
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);
*/
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);
if (Context.Private)
{
- Status = MmCreatePageFileMapping(MemoryArea->Process,
+ Status = MmCreatePageFileMapping(AddressSpace->Process,
Address,
SwapEntry);
if (!NT_SUCCESS(Status))
}
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->BaseAddress = RegionBaseAddress;
+ Info->AllocationProtect = MemoryArea->Attributes;
Info->RegionSize = PAGE_ROUND_UP((ULONG_PTR)MemoryArea->EndingAddress -
(ULONG_PTR)MemoryArea->StartingAddress);
Info->State = MEM_COMMIT;
}
VOID
+NTAPI
MmpFreePageFileSegment(PMM_SECTION_SEGMENT Segment)
{
ULONG Length;
ObjectBody, HandleCount, ObGetObjectPointerCount(ObjectBody));
}
-NTSTATUS STDCALL
-MmpCreateSection(PVOID ObjectBody,
- PVOID Parent,
- PWSTR RemainingPath,
- POBJECT_ATTRIBUTES ObjectAttributes)
-{
- DPRINT("MmpCreateSection(ObjectBody %x, Parent %x, RemainingPath %S)\n",
- ObjectBody, Parent, RemainingPath);
-
- if (RemainingPath == NULL)
- {
- return(STATUS_SUCCESS);
- }
-
- if (wcschr(RemainingPath+1, L'\\') != NULL)
- {
- return(STATUS_UNSUCCESSFUL);
- }
- return(STATUS_SUCCESS);
-}
-
-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;
/*
SectionSize.QuadPart = 0xFFFFFFFF;
InitializeObjectAttributes(&Obj,
&Name,
- 0,
+ OBJ_PERMANENT,
NULL,
NULL);
Status = MmCreateSection(&PhysSection,
DbgPrint("Failed to create PhysicalMemory section\n");
KEBUGCHECK(0);
}
+ Status = ObInsertObject(PhysSection,
+ NULL,
+ SECTION_ALL_ACCESS,
+ 0,
+ NULL,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(PhysSection);
+ }
PhysSection->AllocationAttributes |= SEC_PHYSICALMEMORY;
+ PhysSection->Segment->Flags &= ~MM_PAGEFILE_SEGMENT;
return(STATUS_SUCCESS);
}
-NTSTATUS INIT_FUNCTION
+NTSTATUS
+INIT_FUNCTION
+NTAPI
MmInitSectionImplementation(VOID)
{
- MmSectionObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
-
- RtlRosInitUnicodeStringFromLiteral(&MmSectionObjectType->TypeName, L"Section");
-
- MmSectionObjectType->Tag = TAG('S', 'E', 'C', 'T');
- MmSectionObjectType->TotalObjects = 0;
- MmSectionObjectType->TotalHandles = 0;
- MmSectionObjectType->PeakObjects = 0;
- MmSectionObjectType->PeakHandles = 0;
- MmSectionObjectType->PagedPoolCharge = 0;
- MmSectionObjectType->NonpagedPoolCharge = sizeof(SECTION_OBJECT);
- MmSectionObjectType->Mapping = &MmpSectionMapping;
- MmSectionObjectType->Dump = NULL;
- MmSectionObjectType->Open = NULL;
- MmSectionObjectType->Close = MmpCloseSection;
- MmSectionObjectType->Delete = MmpDeleteSection;
- MmSectionObjectType->Parse = NULL;
- MmSectionObjectType->Security = NULL;
- MmSectionObjectType->QueryName = NULL;
- MmSectionObjectType->OkayToClose = NULL;
- MmSectionObjectType->Create = MmpCreateSection;
- MmSectionObjectType->DuplicationNotify = NULL;
+ OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
+ UNICODE_STRING Name;
- /*
- * NOTE: Do not register the section object type here because
- * the object manager it not initialized yet!
- * The section object type will be created in ObInit().
- */
- ObpCreateTypeObject(MmSectionObjectType);
+ DPRINT("Creating Section Object Type\n");
+
+ /* Initialize the Section object type */
+ RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
+ RtlInitUnicodeString(&Name, L"Section");
+ ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
+ ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(SECTION_OBJECT);
+ ObjectTypeInitializer.PoolType = PagedPool;
+ ObjectTypeInitializer.UseDefaultObject = TRUE;
+ ObjectTypeInitializer.GenericMapping = MmpSectionMapping;
+ ObjectTypeInitializer.DeleteProcedure = MmpDeleteSection;
+ ObjectTypeInitializer.CloseProcedure = MmpCloseSection;
+ ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &MmSectionObjectType);
return(STATUS_SUCCESS);
}
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,
{
return(Status);
}
-
/*
* Initialize it
*/
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;
BufferSize,
&FileOffset,
NULL);
-
+
if(NT_SUCCESS(Status))
{
UsedSize = Iosb.Information;
* 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
+ * (NtMapViewOfSection could then refuse to map them, and they could
* e.g. only be allowed as parameters to NtCreateProcess, like on UNIX)
*/
if ((ImageSectionObject->Segments[i - 1].VirtualAddress +
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
*/
ULONG_PTR VirtualOffset;
VirtualAddress = EffectiveSegment->VirtualAddress;
-
+
/* Round down the virtual address to the nearest page */
EffectiveSegment->VirtualAddress = PAGE_ROUND_DOWN(VirtualAddress);
-
+
/* Round up the virtual size to the nearest page */
EffectiveSegment->Length = PAGE_ROUND_UP(VirtualAddress + EffectiveSegment->Length) -
EffectiveSegment->VirtualAddress;
-
+
/* Adjust the raw address and size */
VirtualOffset = VirtualAddress - EffectiveSegment->VirtualAddress;
-
+
if (EffectiveSegment->FileOffset < VirtualOffset)
{
return FALSE;
}
-
+
/*
- * Garbage in, garbage out: unaligned base addresses make the file
- * offset point in curious and odd places, but that's what we were
+ * Garbage in, garbage out: unaligned base addresses make the file
+ * offset point in curious and odd places, but that's what we were
* asked for
*/
EffectiveSegment->FileOffset -= VirtualOffset;
EndOfEffectiveSegment = EffectiveSegment->VirtualAddress + EffectiveSegment->Length;
ASSERT((EndOfEffectiveSegment % PAGE_SIZE) == 0);
-
+
/*
* The current segment begins exactly where the current effective
* segment ended, therefore beginning a new effective segment
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 file size
*/
-
+
/* Unaligned segments must be contiguous within the file */
if (Segment->FileOffset != (EffectiveSegment->FileOffset +
EffectiveSegment->RawLength))
{
return FALSE;
}
-
+
EffectiveSegment->RawLength += Segment->RawLength;
-
+
/*
* Extend the virtual size
*/
- ASSERT(PAGE_ROUND_UP(Segment->VirtualAddress + Segment->Length) > EndOfEffectiveSegment);
-
+ ASSERT(PAGE_ROUND_UP(Segment->VirtualAddress + Segment->Length) >= EndOfEffectiveSegment);
+
EffectiveSegment->Length = PAGE_ROUND_UP(Segment->VirtualAddress + Segment->Length) -
EffectiveSegment->VirtualAddress;
-
+
/*
* Merge the protection
*/
}
}
}
+ 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));
}
/* 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)
SizeOfSegments = sizeof(MM_SECTION_SEGMENT) * ImageSectionObject->NrSegments;
- Segments = ExAllocatePoolWithTag(NonPagedPool,
+ Segments = ExAllocatePoolWithTag(PagedPool,
SizeOfSegments,
TAG_MM_SECTION_SEGMENT);
UserMode,
(PVOID*)(PVOID)&FileObject,
NULL);
+
if (!NT_SUCCESS(Status))
{
return Status;
*/
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);
return(Status);
}
- if (0 != InterlockedCompareExchangeUL(&FileObject->SectionObjectPointer->ImageSectionObject,
- ImageSectionObject, 0))
+ if (NULL != InterlockedCompareExchangePointer(&FileObject->SectionObjectPointer->ImageSectionObject,
+ ImageSectionObject, NULL))
{
/*
* An other thread has initialized the some image in the background
IN ULONG AllocationAttributes,
IN HANDLE FileHandle OPTIONAL)
{
+ LARGE_INTEGER SafeMaximumSize;
PSECTION_OBJECT SectionObject;
- NTSTATUS Status;
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PreviousMode = ExGetPreviousMode();
+
+ if(MaximumSize != NULL && PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ /* make a copy on the stack */
+ SafeMaximumSize = ProbeForReadLargeInteger(MaximumSize);
+ MaximumSize = &SafeMaximumSize;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if(!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
/*
* Check the protection
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes)
{
- NTSTATUS Status;
+ HANDLE hSection;
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PreviousMode = ExGetPreviousMode();
+
+ if(PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForWriteHandle(SectionHandle);
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
- *SectionHandle = 0;
+ if(!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
Status = ObOpenObjectByName(ObjectAttributes,
MmSectionObjectType,
NULL,
- UserMode,
+ PreviousMode,
DesiredAccess,
NULL,
- SectionHandle);
+ &hSection);
+
+ if(NT_SUCCESS(Status))
+ {
+ _SEH_TRY
+ {
+ *SectionHandle = hSection;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
return(Status);
}
{
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,
* @implemented
*/
NTSTATUS STDCALL
-NtMapViewOfSection(HANDLE SectionHandle,
- HANDLE ProcessHandle,
- PVOID* BaseAddress,
- ULONG ZeroBits,
- ULONG CommitSize,
- PLARGE_INTEGER SectionOffset,
- PULONG ViewSize,
- SECTION_INHERIT InheritDisposition,
- ULONG AllocationType,
- ULONG Protect)
+NtMapViewOfSection(IN HANDLE SectionHandle,
+ IN HANDLE ProcessHandle,
+ IN OUT PVOID* BaseAddress OPTIONAL,
+ IN ULONG ZeroBits OPTIONAL,
+ IN ULONG CommitSize,
+ IN OUT PLARGE_INTEGER SectionOffset OPTIONAL,
+ IN OUT PULONG ViewSize,
+ IN SECTION_INHERIT InheritDisposition,
+ IN ULONG AllocationType OPTIONAL,
+ IN ULONG Protect)
{
+ PVOID SafeBaseAddress;
+ LARGE_INTEGER SafeSectionOffset;
+ ULONG SafeViewSize;
PSECTION_OBJECT Section;
PEPROCESS Process;
- NTSTATUS Status;
+ KPROCESSOR_MODE PreviousMode;
PMADDRESS_SPACE AddressSpace;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PreviousMode = ExGetPreviousMode();
+
+ if(PreviousMode != KernelMode)
+ {
+ SafeBaseAddress = NULL;
+ SafeSectionOffset.QuadPart = 0;
+ SafeViewSize = 0;
+
+ _SEH_TRY
+ {
+ if(BaseAddress != NULL)
+ {
+ ProbeForWritePointer(BaseAddress);
+ SafeBaseAddress = *BaseAddress;
+ }
+ if(SectionOffset != NULL)
+ {
+ ProbeForWriteLargeInteger(SectionOffset);
+ SafeSectionOffset = *SectionOffset;
+ }
+ ProbeForWriteUlong(ViewSize);
+ SafeViewSize = *ViewSize;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if(!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+ else
+ {
+ SafeBaseAddress = (BaseAddress != NULL ? *BaseAddress : NULL);
+ SafeSectionOffset.QuadPart = (SectionOffset != NULL ? SectionOffset->QuadPart : 0);
+ SafeViewSize = (ViewSize != NULL ? *ViewSize : 0);
+ }
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_VM_OPERATION,
PsProcessType,
- UserMode,
+ PreviousMode,
(PVOID*)(PVOID)&Process,
NULL);
if (!NT_SUCCESS(Status))
Status = ObReferenceObjectByHandle(SectionHandle,
SECTION_MAP_READ,
MmSectionObjectType,
- UserMode,
+ PreviousMode,
(PVOID*)(PVOID)&Section,
NULL);
if (!(NT_SUCCESS(Status)))
Status = MmMapViewOfSection(Section,
Process,
- BaseAddress,
+ (BaseAddress != NULL ? &SafeBaseAddress : NULL),
ZeroBits,
CommitSize,
- SectionOffset,
- ViewSize,
+ (SectionOffset != NULL ? &SafeSectionOffset : NULL),
+ (ViewSize != NULL ? &SafeViewSize : NULL),
InheritDisposition,
AllocationType,
Protect);
ObDereferenceObject(Section);
ObDereferenceObject(Process);
+ if(NT_SUCCESS(Status))
+ {
+ /* copy parameters back to the caller */
+ _SEH_TRY
+ {
+ if(BaseAddress != NULL)
+ {
+ *BaseAddress = SafeBaseAddress;
+ }
+ if(SectionOffset != NULL)
+ {
+ *SectionOffset = SafeSectionOffset;
+ }
+ if(ViewSize != NULL)
+ {
+ *ViewSize = SafeViewSize;
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
+
return(Status);
}
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, 0, 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, 0, 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);
}
}
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);
PVOID BaseAddress)
{
PEPROCESS Process;
+ KPROCESSOR_MODE PreviousMode;
NTSTATUS Status;
DPRINT("NtUnmapViewOfSection(ProcessHandle %x, BaseAddress %x)\n",
ProcessHandle, BaseAddress);
+ PreviousMode = ExGetPreviousMode();
+
DPRINT("Referencing process\n");
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_VM_OPERATION,
PsProcessType,
- UserMode,
+ PreviousMode,
(PVOID*)(PVOID)&Process,
NULL);
if (!NT_SUCCESS(Status))
/**
* Queries the information of a section object.
- *
+ *
* @param SectionHandle
* Handle to the section object. It must be opened with SECTION_QUERY
* access.
*
* @return Status.
*
- * @todo Guard by SEH.
* @implemented
*/
NTSTATUS STDCALL
NtQuerySection(IN HANDLE SectionHandle,
- IN CINT SectionInformationClass,
+ IN SECTION_INFORMATION_CLASS SectionInformationClass,
OUT PVOID SectionInformation,
- IN ULONG Length,
- OUT PULONG ResultLength)
+ IN ULONG SectionInformationLength,
+ OUT PULONG ResultLength OPTIONAL)
{
PSECTION_OBJECT Section;
- NTSTATUS Status;
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PreviousMode = ExGetPreviousMode();
+
+ Status = DefaultQueryInfoBufferCheck(SectionInformationClass,
+ ExSectionInfoClass,
+ sizeof(ExSectionInfoClass) / sizeof(ExSectionInfoClass[0]),
+ SectionInformation,
+ SectionInformationLength,
+ ResultLength,
+ PreviousMode);
+
+ if(!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtQuerySection() failed, Status: 0x%x\n", Status);
+ return Status;
+ }
Status = ObReferenceObjectByHandle(SectionHandle,
SECTION_QUERY,
MmSectionObjectType,
- UserMode,
+ PreviousMode,
(PVOID*)(PVOID)&Section,
NULL);
- if (!(NT_SUCCESS(Status)))
- {
- return(Status);
- }
-
- switch (SectionInformationClass)
+ if (NT_SUCCESS(Status))
{
- case SectionBasicInformation:
+ switch (SectionInformationClass)
+ {
+ case SectionBasicInformation:
{
- PSECTION_BASIC_INFORMATION Sbi;
+ PSECTION_BASIC_INFORMATION Sbi = (PSECTION_BASIC_INFORMATION)SectionInformation;
- if (Length != sizeof(SECTION_BASIC_INFORMATION))
+ _SEH_TRY
{
- ObDereferenceObject(Section);
- return(STATUS_INFO_LENGTH_MISMATCH);
- }
-
- Sbi = (PSECTION_BASIC_INFORMATION)SectionInformation;
+ Sbi->Attributes = Section->AllocationAttributes;
+ if (Section->AllocationAttributes & SEC_IMAGE)
+ {
+ Sbi->BaseAddress = 0;
+ Sbi->Size.QuadPart = 0;
+ }
+ else
+ {
+ Sbi->BaseAddress = (PVOID)Section->Segment->VirtualAddress;
+ Sbi->Size.QuadPart = Section->Segment->Length;
+ }
- Sbi->Attributes = Section->AllocationAttributes;
- if (Section->AllocationAttributes & SEC_IMAGE)
- {
- Sbi->BaseAddress = 0;
- Sbi->Size.QuadPart = 0;
+ if (ResultLength != NULL)
+ {
+ *ResultLength = sizeof(SECTION_BASIC_INFORMATION);
+ }
+ Status = STATUS_SUCCESS;
}
- else
+ _SEH_HANDLE
{
- Sbi->BaseAddress = (PVOID)Section->Segment->VirtualAddress;
- Sbi->Size.QuadPart = Section->Segment->Length;
+ Status = _SEH_GetExceptionCode();
}
+ _SEH_END;
- *ResultLength = sizeof(SECTION_BASIC_INFORMATION);
- Status = STATUS_SUCCESS;
break;
}
- case SectionImageInformation:
+ case SectionImageInformation:
{
- PSECTION_IMAGE_INFORMATION Sii;
+ PSECTION_IMAGE_INFORMATION Sii = (PSECTION_IMAGE_INFORMATION)SectionInformation;
- if (Length != sizeof(SECTION_IMAGE_INFORMATION))
+ _SEH_TRY
{
- ObDereferenceObject(Section);
- return(STATUS_INFO_LENGTH_MISMATCH);
- }
+ 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;
+ }
- Sii = (PSECTION_IMAGE_INFORMATION)SectionInformation;
- memset(Sii, 0, sizeof(SECTION_IMAGE_INFORMATION));
- if (Section->AllocationAttributes & SEC_IMAGE)
+ if (ResultLength != NULL)
+ {
+ *ResultLength = sizeof(SECTION_IMAGE_INFORMATION);
+ }
+ Status = STATUS_SUCCESS;
+ }
+ _SEH_HANDLE
{
- 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;
+ Status = _SEH_GetExceptionCode();
}
- *ResultLength = sizeof(SECTION_IMAGE_INFORMATION);
- Status = STATUS_SUCCESS;
+ _SEH_END;
+
break;
}
+ }
- default:
- *ResultLength = 0;
- Status = STATUS_INVALID_INFO_CLASS;
+ ObDereferenceObject(Section);
}
- ObDereferenceObject(Section);
+
return(Status);
}
/**
* Extends size of file backed section.
- *
+ *
* @param SectionHandle
* Handle to the section object. It must be opened with
* SECTION_EXTEND_SIZE access.
*
* @return Status.
*
- * @todo Guard by SEH.
* @todo Move the actual code to internal function MmExtendSection.
* @unimplemented
*/
NtExtendSection(IN HANDLE SectionHandle,
IN PLARGE_INTEGER NewMaximumSize)
{
+ LARGE_INTEGER SafeNewMaximumSize;
PSECTION_OBJECT Section;
- NTSTATUS Status;
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PreviousMode = ExGetPreviousMode();
+
+ if(PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ /* make a copy on the stack */
+ SafeNewMaximumSize = ProbeForReadLargeInteger(NewMaximumSize);
+ NewMaximumSize = &SafeNewMaximumSize;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if(!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
Status = ObReferenceObjectByHandle(SectionHandle,
SECTION_EXTEND_SIZE,
MmSectionObjectType,
- UserMode,
+ PreviousMode,
(PVOID*)&Section,
NULL);
if (!NT_SUCCESS(Status))
ObfDereferenceObject(Section);
return STATUS_INVALID_PARAMETER;
}
-
+
/*
* - Acquire file extneding resource.
* - Check if we're not resizing the section below it's actual size!
KEBUGCHECK(0);
}
Status = MmCreateVirtualMapping (NULL,
- (PVOID)(Result + (i * PAGE_SIZE)),
+ (PVOID)((ULONG_PTR)Result + (i * PAGE_SIZE)),
PAGE_READWRITE,
&Page,
1);
{
if (!(SectionSegments[i].Characteristics & IMAGE_SCN_TYPE_NOLOAD))
{
- ULONG MaxExtent;
- MaxExtent = (ULONG)((char*)SectionSegments[i].VirtualAddress +
- SectionSegments[i].Length);
+ ULONG_PTR MaxExtent;
+ MaxExtent = (ULONG_PTR)SectionSegments[i].VirtualAddress +
+ SectionSegments[i].Length;
ImageSize = max(ImageSize, MaxExtent);
}
}