#include <debug.h>
#define MODULE_INVOLVED_IN_ARM3
-#include "../ARM3/miarm.h"
+#include <mm/ARM3/miarm.h>
/* GLOBALS ********************************************************************/
}
/* This actually turns on guard page in this scenario! */
- ProtectMask |= MM_DECOMMIT;
+ ProtectMask |= MM_GUARDPAGE;
}
/* Check for nocache option */
SEGMENT_FLAGS SegmentFlags;
PSUBSECTION Subsection;
PMMPTE PointerPte, LastPte, PteForProto;
+ PMMPFN Pfn1;
+ PFN_NUMBER PageFrameIndex;
MMPTE TempPte;
KIRQL OldIrql;
/* These things are not supported yet */
ASSERT(ControlArea->DereferenceList.Flink == NULL);
- ASSERT(!(ControlArea->u.Flags.Image) & !(ControlArea->u.Flags.File));
+ ASSERT(!(ControlArea->u.Flags.Image) && !(ControlArea->u.Flags.File));
ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
ASSERT(ControlArea->u.Flags.Rom == 0);
TempPte = *PointerPte;
ASSERT(SegmentFlags.LargePages == 0);
ASSERT(TempPte.u.Hard.Valid == 0);
- ASSERT(TempPte.u.Soft.Prototype == 1);
+
+ /* See if we should clean things up */
+ if (!(ControlArea->u.Flags.Image) && !(ControlArea->u.Flags.File))
+ {
+ /*
+ * This is a section backed by the pagefile. Now that it doesn't exist anymore,
+ * we can give everything back to the system.
+ */
+ ASSERT(TempPte.u.Soft.Prototype == 0);
+
+ if (TempPte.u.Soft.Transition == 1)
+ {
+ /* We can give the page back for other use */
+ DPRINT("Releasing page for transition PTE %p\n", PointerPte);
+ PageFrameIndex = PFN_FROM_PTE(&TempPte);
+ Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
+
+ /* As this is a paged-backed section, nobody should reference it anymore (no cache or whatever) */
+ ASSERT(Pfn1->u3.ReferenceCount == 0);
+
+ /* And it should be in standby or modified list */
+ ASSERT((Pfn1->u3.e1.PageLocation == ModifiedPageList) || (Pfn1->u3.e1.PageLocation == StandbyPageList));
+
+ /* Unlink it and put it back in free list */
+ MiUnlinkPageFromList(Pfn1);
+
+ /* Temporarily mark this as active and make it free again */
+ Pfn1->u3.e1.PageLocation = ActiveAndValid;
+ MI_SET_PFN_DELETED(Pfn1);
+
+ MiInsertPageInFreeList(PageFrameIndex);
+ }
+ else if (TempPte.u.Soft.PageFileHigh != 0)
+ {
+ /* Should not happen for now */
+ ASSERT(FALSE);
+ }
+ }
+ else
+ {
+ /* unsupported for now */
+ ASSERT(FALSE);
+
+ /* File-backed section must have prototype PTEs */
+ ASSERT(TempPte.u.Soft.Prototype == 1);
+ }
/* Zero the PTE and keep going */
PointerPte->u.Long = 0;
{
KIRQL OldIrql;
ULONG Color, Index;
- PMMPTE StartPde, EndPde;
- MMPTE TempPte = ValidKernelPdeLocal;
+ PMMPDE StartPde, EndPde;
+ MMPDE TempPde = ValidKernelPdeLocal;
PMMPFN Pfn1;
PFN_NUMBER PageCount = 0, ActualPages = 0, PageFrameNumber;
/* Loop each PDE while holding the working set lock */
// MiLockWorkingSet(PsGetCurrentThread(),
// &MmSessionSpace->GlobalVirtualAddress->Vm);
-#ifndef _M_AMD64
+#ifdef _M_AMD64
+_WARN("MiSessionCommitPageTables halfplemented for amd64")
+ DBG_UNREFERENCED_LOCAL_VARIABLE(OldIrql);
+ DBG_UNREFERENCED_LOCAL_VARIABLE(Color);
+ DBG_UNREFERENCED_LOCAL_VARIABLE(TempPde);
+ DBG_UNREFERENCED_LOCAL_VARIABLE(Pfn1);
+ DBG_UNREFERENCED_LOCAL_VARIABLE(PageFrameNumber);
+ ASSERT(FALSE);
+#else
while (StartPde <= EndPde)
{
/* Check if we already have a page table */
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
Color = (++MmSessionSpace->Color) & MmSecondaryColorMask;
PageFrameNumber = MiRemoveZeroPage(Color);
- TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
- MI_WRITE_VALID_PTE(StartPde, TempPte);
+ TempPde.u.Hard.PageFrameNumber = PageFrameNumber;
+ MI_WRITE_VALID_PDE(StartPde, TempPde);
/* Write the page table in session space structure */
ASSERT(MmSessionSpace->PageTables[Index].u.Long == 0);
- MmSessionSpace->PageTables[Index] = TempPte;
+ MmSessionSpace->PageTables[Index] = TempPde;
/* Initialize the PFN */
MiInitializePfnForOtherProcess(PageFrameNumber,
Status = MiSessionCommitPageTables(Base,
(PVOID)((ULONG_PTR)Base +
Buckets * MI_SYSTEM_VIEW_BUCKET_SIZE));
- NT_ASSERT(NT_SUCCESS(Status));
+ ASSERT(NT_SUCCESS(Status));
}
/* Create the actual prototype PTEs for this mapping */
Status = RtlUnicodeStringToAnsiString(&FileNameA, FileName, TRUE);
if (NT_SUCCESS(Status))
{
- DbgLoadImageSymbols(&FileNameA, BaseAddress, (ULONG_PTR)Process);
+ DbgLoadImageSymbols(&FileNameA, BaseAddress, (ULONG_PTR)Process->UniqueProcessId);
RtlFreeAnsiString(&FileNameA);
}
}
IN ULONG AllocationType)
{
PMMVAD_LONG Vad;
- PETHREAD Thread = PsGetCurrentThread();
- ULONG_PTR StartAddress, EndingAddress;
+ ULONG_PTR StartAddress;
+ ULONG_PTR ViewSizeInPages;
PSUBSECTION Subsection;
PSEGMENT Segment;
PFN_NUMBER PteOffset;
ULONG QuotaCharge = 0, QuotaExcess = 0;
PMMPTE PointerPte, LastPte;
MMPTE TempPte;
+ ULONG Granularity = MM_VIRTMEM_GRANULARITY;
+
+ DPRINT("Mapping ARM3 data section\n");
/* Get the segment for this section */
Segment = ControlArea->Segment;
+#ifdef _M_IX86
+ /* ALlow being less restrictive on x86. */
+ if (AllocationType & MEM_DOS_LIM)
+ Granularity = PAGE_SIZE;
+#endif
+
/* One can only reserve a file-based mapping, not shared memory! */
if ((AllocationType & MEM_RESERVE) && !(ControlArea->FilePointer))
{
return STATUS_INVALID_PARAMETER_9;
}
- /* This flag determines alignment, but ARM3 does not yet support it */
- ASSERT((AllocationType & MEM_DOS_LIM) == 0);
-
/* First, increase the map count. No purging is supported yet */
Status = MiCheckPurgeAndUpMapCount(ControlArea, FALSE);
if (!NT_SUCCESS(Status)) return Status;
/* We must be dealing with a 64KB aligned offset. This is a Windows ASSERT */
ASSERT((SectionOffset->LowPart & ((ULONG)_64K - 1)) == 0);
- /* It's illegal to try to map more than 2GB */
- /* FIXME: Should dereference the control area */
- if (*ViewSize >= 0x80000000) return STATUS_INVALID_VIEW_SIZE;
+ /* It's illegal to try to map more than overflows a LONG_PTR */
+ if (*ViewSize >= MAXLONG_PTR)
+ {
+ MiDereferenceControlArea(ControlArea);
+ return STATUS_INVALID_VIEW_SIZE;
+ }
/* Windows ASSERTs for this flag */
ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
/* Compute how much commit space the segment will take */
if ((CommitSize) && (Segment->NumberOfCommittedPages < Segment->TotalNumberOfPtes))
{
- PointerPte = &Subsection->SubsectionBase[PteOffset];
- LastPte = PointerPte + BYTES_TO_PAGES(CommitSize);
- QuotaCharge = (ULONG)(LastPte - PointerPte);
+ /* Charge for the maximum pages */
+ QuotaCharge = BYTES_TO_PAGES(CommitSize);
}
/* ARM3 does not currently support large pages */
ASSERT(Segment->SegmentFlags.LargePages == 0);
- /* Did the caller specify an address? */
- if (!(*BaseAddress) && !(Section->Address.StartingVpn))
- {
- /* ARM3 does not support these flags yet */
- ASSERT(Process->VmTopDown == 0);
- ASSERT(ZeroBits == 0);
-
- /* Which way should we search? */
- if (AllocationType & MEM_TOP_DOWN)
- {
- /* No, find an address top-down */
- Status = MiFindEmptyAddressRangeDownTree(*ViewSize,
- (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS,
- _64K,
- &Process->VadRoot,
- &StartAddress,
- (PMMADDRESS_NODE*)&Process->VadFreeHint);
- ASSERT(NT_SUCCESS(Status));
- }
- else
- {
- /* No, find an address bottom-up */
- Status = MiFindEmptyAddressRangeInTree(*ViewSize,
- _64K,
- &Process->VadRoot,
- (PMMADDRESS_NODE*)&Process->VadFreeHint,
- &StartAddress);
- ASSERT(NT_SUCCESS(Status));
- }
-
- /* Get the ending address, which is the last piece we need for the VAD */
- EndingAddress = (StartAddress + *ViewSize - 1) | (PAGE_SIZE - 1);
- }
- else
- {
- /* Is it SEC_BASED, or did the caller manually specify an address? */
- if (!(*BaseAddress))
- {
- /* It is a SEC_BASED mapping, use the address that was generated */
- StartAddress = Section->Address.StartingVpn + SectionOffset->LowPart;
- DPRINT("BASED: 0x%p\n", StartAddress);
- }
- else
- {
- /* Just align what the caller gave us */
- StartAddress = ROUND_UP((ULONG_PTR)*BaseAddress, _64K);
- }
-
- /* Get the ending address, which is the last piece we need for the VAD */
- EndingAddress = (StartAddress + *ViewSize - 1) | (PAGE_SIZE - 1);
-
- /* Make sure it doesn't conflict with an existing allocation */
- if (MiCheckForConflictingNode(StartAddress >> PAGE_SHIFT,
- EndingAddress >> PAGE_SHIFT,
- &Process->VadRoot))
- {
- DPRINT1("Conflict with SEC_BASED or manually based section!\n");
- MiDereferenceControlArea(ControlArea);
- return STATUS_CONFLICTING_ADDRESSES;
- }
- }
+ /* Calculate how many pages the region spans */
+ ViewSizeInPages = BYTES_TO_PAGES(*ViewSize);
/* A VAD can now be allocated. Do so and zero it out */
/* FIXME: we are allocating a LONG VAD for ReactOS compatibility only */
MiDereferenceControlArea(ControlArea);
return STATUS_INSUFFICIENT_RESOURCES;
}
+
RtlZeroMemory(Vad, sizeof(MMVAD_LONG));
Vad->u4.Banked = (PVOID)0xDEADBABE;
/* Write all the data required in the VAD for handling a fault */
- Vad->StartingVpn = StartAddress >> PAGE_SHIFT;
- Vad->EndingVpn = EndingAddress >> PAGE_SHIFT;
Vad->ControlArea = ControlArea;
+ Vad->u.VadFlags.CommitCharge = 0;
Vad->u.VadFlags.Protection = ProtectionMask;
Vad->u2.VadFlags2.FileOffset = (ULONG)(SectionOffset->QuadPart >> 16);
Vad->u2.VadFlags2.Inherit = (InheritDisposition == ViewShare);
/* Finally, write down the first and last prototype PTE */
Vad->FirstPrototypePte = &Subsection->SubsectionBase[PteOffset];
- PteOffset += (Vad->EndingVpn - Vad->StartingVpn);
+ PteOffset += ViewSizeInPages - 1;
ASSERT(PteOffset < Subsection->PtesInSubsection);
Vad->LastContiguousPte = &Subsection->SubsectionBase[PteOffset];
/* FIXME: Should setup VAD bitmap */
Status = STATUS_SUCCESS;
- /* Pretend as if we own the working set */
- MiLockProcessWorkingSetUnsafe(Process, Thread);
-
- /* Insert the VAD */
- MiInsertVad((PMMVAD)Vad, Process);
-
- /* Release the working set */
- MiUnlockProcessWorkingSetUnsafe(Process, Thread);
-
- /* Windows stores this for accounting purposes, do so as well */
- if (!Segment->u2.FirstMappedVa) Segment->u2.FirstMappedVa = (PVOID)StartAddress;
-
/* Check if anything was committed */
if (QuotaCharge)
{
TempPte = Segment->SegmentPteTemplate;
/* Acquire the commit lock and loop all prototype PTEs to be committed */
- KeAcquireGuardedMutexUnsafe(&MmSectionCommitMutex);
+ KeAcquireGuardedMutex(&MmSectionCommitMutex);
while (PointerPte < LastPte)
{
/* Make sure the PTE is already invalid */
ASSERT(Segment->NumberOfCommittedPages <= Segment->TotalNumberOfPtes);
/* Now that we're done, release the lock */
- KeReleaseGuardedMutexUnsafe(&MmSectionCommitMutex);
+ KeReleaseGuardedMutex(&MmSectionCommitMutex);
}
+ /* Is it SEC_BASED, or did the caller manually specify an address? */
+ if (*BaseAddress != NULL)
+ {
+ /* Just align what the caller gave us */
+ StartAddress = ALIGN_DOWN_BY((ULONG_PTR)*BaseAddress, Granularity);
+ }
+ else if (Section->Address.StartingVpn != 0)
+ {
+ /* It is a SEC_BASED mapping, use the address that was generated */
+ StartAddress = Section->Address.StartingVpn + SectionOffset->LowPart;
+ }
+ else
+ {
+ StartAddress = 0;
+ }
+
+ /* Insert the VAD */
+ Status = MiInsertVadEx((PMMVAD)Vad,
+ &StartAddress,
+ ViewSizeInPages * PAGE_SIZE,
+ MAXULONG_PTR >> ZeroBits,
+ Granularity,
+ AllocationType);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ /* Windows stores this for accounting purposes, do so as well */
+ if (!Segment->u2.FirstMappedVa) Segment->u2.FirstMappedVa = (PVOID)StartAddress;
+
/* Finally, let the caller know where, and for what size, the view was mapped */
- *ViewSize = (ULONG_PTR)EndingAddress - (ULONG_PTR)StartAddress + 1;
+ *ViewSize = ViewSizeInPages * PAGE_SIZE;
*BaseAddress = (PVOID)StartAddress;
DPRINT("Start and region: 0x%p, 0x%p\n", *BaseAddress, *ViewSize);
return STATUS_SUCCESS;
if (AllocationAttributes & SEC_RESERVE) ControlArea->u.Flags.Reserve = 1;
if (AllocationAttributes & SEC_COMMIT) ControlArea->u.Flags.Commit = 1;
+ /* We just allocated it */
+ ControlArea->u.Flags.BeingCreated = 1;
+
/* The subsection follows, write the mask, PTE count and point back to the CA */
Subsection = (PSUBSECTION)(ControlArea + 1);
Subsection->ControlArea = ControlArea;
return STATUS_SUCCESS;
}
+NTSTATUS
+NTAPI
+MiGetFileObjectForSectionAddress(
+ IN PVOID Address,
+ OUT PFILE_OBJECT *FileObject)
+{
+ PMMVAD Vad;
+ PCONTROL_AREA ControlArea;
+
+ /* Get the VAD */
+ Vad = MiLocateAddress(Address);
+ if (Vad == NULL)
+ {
+ /* Fail, the address does not exist */
+ DPRINT1("Invalid address\n");
+ return STATUS_INVALID_ADDRESS;
+ }
+
+ /* Check if this is a RosMm memory area */
+ if (Vad->u.VadFlags.Spare != 0)
+ {
+ PMEMORY_AREA MemoryArea = (PMEMORY_AREA)Vad;
+ PROS_SECTION_OBJECT Section;
+
+ /* Check if it's a section view (RosMm section) */
+ if (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW)
+ {
+ /* Get the section pointer to the SECTION_OBJECT */
+ Section = MemoryArea->Data.SectionData.Section;
+ *FileObject = Section->FileObject;
+ }
+ else
+ {
+ ASSERT(MemoryArea->Type == MEMORY_AREA_CACHE);
+ DPRINT1("Address is a cache section!\n");
+ return STATUS_SECTION_NOT_IMAGE;
+ }
+ }
+ else
+ {
+ /* Make sure it's not a VM VAD */
+ if (Vad->u.VadFlags.PrivateMemory == 1)
+ {
+ DPRINT1("Address is not a section\n");
+ return STATUS_SECTION_NOT_IMAGE;
+ }
+
+ /* Get the control area */
+ ControlArea = Vad->ControlArea;
+ if (!(ControlArea) || !(ControlArea->u.Flags.Image))
+ {
+ DPRINT1("Address is not a section\n");
+ return STATUS_SECTION_NOT_IMAGE;
+ }
+
+ /* Get the file object */
+ *FileObject = ControlArea->FilePointer;
+ }
+
+ /* Return success */
+ return STATUS_SUCCESS;
+}
+
PFILE_OBJECT
NTAPI
MmGetFileObjectForSection(IN PVOID SectionObject)
return ((PROS_SECTION_OBJECT)SectionObject)->FileObject;
}
+static
+PFILE_OBJECT
+MiGetFileObjectForVad(
+ _In_ PMMVAD Vad)
+{
+ PCONTROL_AREA ControlArea;
+ PFILE_OBJECT FileObject;
+
+ /* Check if this is a RosMm memory area */
+ if (Vad->u.VadFlags.Spare != 0)
+ {
+ PMEMORY_AREA MemoryArea = (PMEMORY_AREA)Vad;
+ PROS_SECTION_OBJECT Section;
+
+ /* Check if it's a section view (RosMm section) */
+ if (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW)
+ {
+ /* Get the section pointer to the SECTION_OBJECT */
+ Section = MemoryArea->Data.SectionData.Section;
+ FileObject = Section->FileObject;
+ }
+ else
+ {
+ ASSERT(MemoryArea->Type == MEMORY_AREA_CACHE);
+ DPRINT1("VAD is a cache section!\n");
+ return NULL;
+ }
+ }
+ else
+ {
+ /* Make sure it's not a VM VAD */
+ if (Vad->u.VadFlags.PrivateMemory == 1)
+ {
+ DPRINT1("VAD is not a section\n");
+ return NULL;
+ }
+
+ /* Get the control area */
+ ControlArea = Vad->ControlArea;
+ if ((ControlArea == NULL) || !ControlArea->u.Flags.Image)
+ {
+ DPRINT1("Address is not a section\n");
+ return NULL;
+ }
+
+ /* Get the file object */
+ FileObject = ControlArea->FilePointer;
+ }
+
+ /* Return the file object */
+ return FileObject;
+}
+
VOID
NTAPI
MmGetImageInformation (OUT PSECTION_IMAGE_INFORMATION ImageInformation)
ASSERT(MiIsRosSectionObject(SectionObject) == TRUE);
/* Return the image information */
- DPRINT1("HERE!\n");
*ImageInformation = ((PROS_SECTION_OBJECT)SectionObject)->ImageSection->ImageInformation;
}
MmGetFileNameForAddress(IN PVOID Address,
OUT PUNICODE_STRING ModuleName)
{
- PVOID Section;
- PMEMORY_AREA MemoryArea;
- POBJECT_NAME_INFORMATION ModuleNameInformation;
- PVOID AddressSpace;
- NTSTATUS Status;
- PFILE_OBJECT FileObject = NULL;
- PMMVAD Vad;
- PCONTROL_AREA ControlArea;
-
- /* Lock address space */
- AddressSpace = MmGetCurrentAddressSpace();
- MmLockAddressSpace(AddressSpace);
-
- /* Locate the memory area for the process by address */
- MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, Address);
- if (!MemoryArea)
- {
- /* Fail, the address does not exist */
-InvalidAddress:
- DPRINT1("Invalid address\n");
- MmUnlockAddressSpace(AddressSpace);
- return STATUS_INVALID_ADDRESS;
- }
-
- /* Check if it's a section view (RosMm section) or ARM3 section */
- if (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW)
- {
- /* Get the section pointer to the SECTION_OBJECT */
- Section = MemoryArea->Data.SectionData.Section;
-
- /* Unlock address space */
- MmUnlockAddressSpace(AddressSpace);
-
- /* Get the filename of the section */
- Status = MmGetFileNameForSection(Section, &ModuleNameInformation);
- }
- else if (MemoryArea->Type == MEMORY_AREA_OWNED_BY_ARM3)
- {
- /* Get the VAD */
- Vad = MiLocateAddress(Address);
- if (!Vad) goto InvalidAddress;
-
- /* Make sure it's not a VM VAD */
- if (Vad->u.VadFlags.PrivateMemory == 1)
- {
-NotSection:
- DPRINT1("Address is not a section\n");
- MmUnlockAddressSpace(AddressSpace);
- return STATUS_SECTION_NOT_IMAGE;
- }
-
- /* Get the control area */
- ControlArea = Vad->ControlArea;
- if (!(ControlArea) || !(ControlArea->u.Flags.Image)) goto NotSection;
-
- /* Get the file object */
- FileObject = ControlArea->FilePointer;
- ASSERT(FileObject != NULL);
- ObReferenceObject(FileObject);
-
- /* Unlock address space */
- MmUnlockAddressSpace(AddressSpace);
-
- /* Get the filename of the file object */
- Status = MmGetFileNameForFileObject(FileObject, &ModuleNameInformation);
-
- /* Dereference it */
- ObDereferenceObject(FileObject);
- }
- else
- {
- /* Trying to access virtual memory or something */
- goto InvalidAddress;
- }
-
- /* Check if we were able to get the file object name */
- if (NT_SUCCESS(Status))
- {
+ POBJECT_NAME_INFORMATION ModuleNameInformation;
+ PVOID AddressSpace;
+ NTSTATUS Status;
+ PMMVAD Vad;
+ PFILE_OBJECT FileObject = NULL;
+
+ /* Lock address space */
+ AddressSpace = MmGetCurrentAddressSpace();
+ MmLockAddressSpace(AddressSpace);
+
+ /* Get the VAD */
+ Vad = MiLocateAddress(Address);
+ if (Vad == NULL)
+ {
+ /* Fail, the address does not exist */
+ DPRINT1("No VAD at address %p\n", Address);
+ MmUnlockAddressSpace(AddressSpace);
+ return STATUS_INVALID_ADDRESS;
+ }
+
+ /* Get the file object pointer for the VAD */
+ FileObject = MiGetFileObjectForVad(Vad);
+ if (FileObject == NULL)
+ {
+ DPRINT1("Failed to get file object for Address %p\n", Address);
+ MmUnlockAddressSpace(AddressSpace);
+ return STATUS_SECTION_NOT_IMAGE;
+ }
+
+ /* Reference the file object */
+ ObReferenceObject(FileObject);
+
+ /* Unlock address space */
+ MmUnlockAddressSpace(AddressSpace);
+
+ /* Get the filename of the file object */
+ Status = MmGetFileNameForFileObject(FileObject, &ModuleNameInformation);
+
+ /* Dereference the file object */
+ ObDereferenceObject(FileObject);
+
+ /* Check if we were able to get the file object name */
+ if (NT_SUCCESS(Status))
+ {
/* Init modulename */
- RtlCreateUnicodeString(ModuleName,
- ModuleNameInformation->Name.Buffer);
+ RtlCreateUnicodeString(ModuleName, ModuleNameInformation->Name.Buffer);
- /* Free temp taged buffer from MmGetFileNameForFileObject() */
- ExFreePoolWithTag(ModuleNameInformation, TAG_MM);
- DPRINT("Found ModuleName %S by address %p\n", ModuleName->Buffer, Address);
- }
+ /* Free temp taged buffer from MmGetFileNameForFileObject() */
+ ExFreePoolWithTag(ModuleNameInformation, TAG_MM);
+ DPRINT("Found ModuleName %S by address %p\n", ModuleName->Buffer, Address);
+ }
/* Return status */
return Status;
IN PMMPTE PointerPte,
IN ULONG ProtectionMask,
IN PMMPFN Pfn1,
- IN BOOLEAN CaptureDirtyBit)
+ IN BOOLEAN UpdateDirty)
{
MMPTE TempPte, PreviousPte;
KIRQL OldIrql;
//
// Write the new PTE, making sure we are only changing the bits
//
- ASSERT(PointerPte->u.Hard.Valid == 1);
- ASSERT(TempPte.u.Hard.Valid == 1);
- ASSERT(PointerPte->u.Hard.PageFrameNumber == TempPte.u.Hard.PageFrameNumber);
- MI_WRITE_VALID_PTE(PointerPte, TempPte);
+ MI_UPDATE_VALID_PTE(PointerPte, TempPte);
//
// Flush the TLB
//
// Windows updates the relevant PFN1 information, we currently don't.
//
- if (CaptureDirtyBit) DPRINT1("Warning, not handling dirty bit\n");
+ if (UpdateDirty && PreviousPte.u.Hard.Dirty)
+ {
+ if (!Pfn1->u3.e1.Modified)
+ {
+ DPRINT1("FIXME: Mark PFN as dirty\n");
+ }
+ }
//
// Not supported in ARM3
//
if ((((ULONG_PTR)PointerPte) & (SYSTEM_PD_SIZE - 1)) == 0)
{
- PointerPde = MiAddressToPte(PointerPte);
+ PointerPde = MiPteToPde(PointerPte);
MiMakePdeExistAndMakeValid(PointerPde, Process, MM_NOIRQL);
}
IN PCONTROL_AREA ControlArea,
IN PMMSUPPORT Ws)
{
- PMMPTE PointerPte;//, FirstPte;
+ PMMPTE PointerPte, ProtoPte;//, FirstPte;
PMMPDE PointerPde, SystemMapPde;
PMMPFN Pfn1, Pfn2;
MMPTE PteContents;
KIRQL OldIrql;
DPRINT("Removing mapped view at: 0x%p\n", BaseAddress);
+ ASSERT(Ws == NULL);
+
/* Get the PTE and loop each one */
PointerPte = MiAddressToPte(BaseAddress);
//FirstPte = PointerPte;
Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(&PteContents));
/* Get the PTE */
- PointerPde = MiAddressToPte(PointerPte);
+ PointerPde = MiPteToPde(PointerPte);
/* Lock the PFN database and make sure this isn't a mapped file */
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
ASSERT(((Pfn1->u3.e1.PrototypePte) && (Pfn1->OriginalPte.u.Soft.Prototype)) == 0);
- /* FIXME: Dirty bit management */
+ /* Mark the page as modified accordingly */
+ if (MI_IS_PAGE_DIRTY(&PteContents))
+ Pfn1->u3.e1.Modified = 1;
/* Was the PDE invalid */
if (PointerPde->u.Long == 0)
ASSERT(SystemMapPde->u.Hard.Valid == 1);
MI_WRITE_VALID_PDE(PointerPde, *SystemMapPde);
#else
+ DBG_UNREFERENCED_LOCAL_VARIABLE(SystemMapPde);
ASSERT(FALSE);
#endif
}
/* Dereference the PDE and the PTE */
Pfn2 = MiGetPfnEntry(PFN_FROM_PTE(PointerPde));
- //MiDecrementShareCount(Pfn2, PFN_FROM_PTE(PointerPde));
+ MiDecrementShareCount(Pfn2, PFN_FROM_PTE(PointerPde));
DBG_UNREFERENCED_LOCAL_VARIABLE(Pfn2);
MiDecrementShareCount(Pfn1, PFN_FROM_PTE(&PteContents));
/* Windows ASSERT */
ASSERT((PteContents.u.Long == 0) || (PteContents.u.Soft.Prototype == 1));
- /* But not handled in ARM3 */
- ASSERT(PteContents.u.Soft.Prototype == 0);
+ /* Check if this is a prototype pointer PTE */
+ if (PteContents.u.Soft.Prototype == 1)
+ {
+ /* Get the prototype PTE */
+ ProtoPte = MiProtoPteToPte(&PteContents);
+
+ /* We don't support anything else atm */
+ ASSERT(ProtoPte->u.Long == 0);
+ }
}
/* Make the PTE into a zero PTE */
BOOLEAN FileLock = FALSE, KernelCall = FALSE;
KIRQL OldIrql;
PFILE_OBJECT File;
+ BOOLEAN UserRefIncremented = FALSE;
PVOID PreviousSectionPointer;
/* Make the same sanity checks that the Nt interface should've validated */
/* Write down that this CA is being created, and set it */
ControlArea->u.Flags.BeingCreated = TRUE;
+ ASSERT((AllocationAttributes & SEC_IMAGE) == 0);
PreviousSectionPointer = File->SectionObjectPointer;
File->SectionObjectPointer->DataSectionObject = ControlArea;
SectionPageProtection,
AllocationAttributes,
KernelCall);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Lock the PFN database while we play with the section pointers */
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+
+ /* Reset the waiting-for-deletion event */
+ ASSERT(ControlArea->WaitingForDeletion == NULL);
+ ControlArea->WaitingForDeletion = NULL;
+
+ /* Set the file pointer NULL flag */
+ ASSERT(ControlArea->u.Flags.FilePointerNull == 0);
+ ControlArea->u.Flags.FilePointerNull = TRUE;
+
+ /* Delete the data section object */
+ ASSERT((AllocationAttributes & SEC_IMAGE) == 0);
+ File->SectionObjectPointer->DataSectionObject = NULL;
+
+ /* No longer being created */
+ ControlArea->u.Flags.BeingCreated = FALSE;
+
+ /* We can release the PFN lock now */
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+
+ /* Check if we locked and set the IRP */
+ if (FileLock)
+ {
+ /* Undo */
+ IoSetTopLevelIrp(NULL);
+ //FsRtlReleaseFile(File);
+ }
+
+ /* Free the control area and de-ref the file object */
+ ExFreePool(ControlArea);
+ ObDereferenceObject(File);
+
+ /* All done */
+ return Status;
+ }
+
+ /* On success, we expect this */
ASSERT(PreviousSectionPointer == File->SectionObjectPointer);
- ASSERT(NT_SUCCESS(Status));
/* Check if a maximum size was specified */
if (!InputMaximumSize->QuadPart)
/* Set the size here, and read the control area */
Section.SizeOfSection.QuadPart = NewSegment->SizeOfSegment;
ControlArea = NewSegment->ControlArea;
+
+ /* MiCreatePagingFileMap increments user references */
+ UserRefIncremented = TRUE;
}
/* Did we already have a segment? */
/* Check if this is a user-mode read-write non-image file mapping */
if (!(FileObject) &&
(SectionPageProtection & (PAGE_READWRITE | PAGE_EXECUTE_READWRITE)) &&
- (ControlArea->u.Flags.Image == 0) &&
- (ControlArea->FilePointer != NULL))
+ !(ControlArea->u.Flags.Image) &&
+ (ControlArea->FilePointer))
{
/* Add a reference and set the flag */
- Section.u.Flags.UserWritable = 1;
- InterlockedIncrement((PLONG)&ControlArea->WritableUserReferences);
+ Section.u.Flags.UserWritable = TRUE;
+ InterlockedIncrement((volatile LONG*)&ControlArea->WritableUserReferences);
}
/* Check for image mappings or page file mappings */
- if ((ControlArea->u.Flags.Image == 1) || !(ControlArea->FilePointer))
+ if ((ControlArea->u.Flags.Image) || !(ControlArea->FilePointer))
{
/* Charge the segment size, and allocate a subsection */
PagedCharge = sizeof(SECTION) + NewSegment->TotalNumberOfPtes * sizeof(MMPTE);
PagedCharge,
NonPagedCharge,
(PVOID*)&NewSection);
- ASSERT(NT_SUCCESS(Status));
+ if (!NT_SUCCESS(Status))
+ {
+ /* Check if this is a user-mode read-write non-image file mapping */
+ if (!(FileObject) &&
+ (SectionPageProtection & (PAGE_READWRITE | PAGE_EXECUTE_READWRITE)) &&
+ !(ControlArea->u.Flags.Image) &&
+ (ControlArea->FilePointer))
+ {
+ /* Remove a reference and check the flag */
+ ASSERT(Section.u.Flags.UserWritable == 1);
+ InterlockedDecrement((volatile LONG*)&ControlArea->WritableUserReferences);
+ }
+
+ /* Check if a user reference was added */
+ if (UserRefIncremented)
+ {
+ /* Acquire the PFN lock while we change counters */
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+
+ /* Decrement the accounting counters */
+ ControlArea->NumberOfSectionReferences--;
+ ASSERT((LONG)ControlArea->NumberOfUserReferences > 0);
+ ControlArea->NumberOfUserReferences--;
+
+ /* Check if we should destroy the CA and release the lock */
+ MiCheckControlArea(ControlArea, OldIrql);
+ }
+
+ /* Return the failure code */
+ return Status;
+ }
+
+ /* NOTE: Past this point, all failures will be handled by Ob upon ref->0 */
/* Now copy the local section object from the stack into this new object */
RtlCopyMemory(NewSection, &Section, sizeof(SECTION));
ASSERT(KernelCall == FALSE);
NewSection->u.Flags.UserReference = TRUE;
- /* Migrate the attribute into a flag */
- if (AllocationAttributes & SEC_NO_CHANGE) NewSection->u.Flags.NoChange = TRUE;
-
- /* If R/W access is not requested, this might eventually become a CoW mapping */
- if (!(SectionPageProtection & (PAGE_READWRITE | PAGE_EXECUTE_READWRITE)))
- {
- NewSection->u.Flags.CopyOnWrite = TRUE;
- }
-
/* Is this a "based" allocation, in which all mappings are identical? */
if (AllocationAttributes & SEC_BASED)
{
- /* Convert the flag, and make sure the section isn't too big */
- NewSection->u.Flags.Based = TRUE;
- if ((ULONGLONG)NewSection->SizeOfSection.QuadPart >
- (ULONG_PTR)MmHighSectionBase)
- {
- DPRINT1("BASED section is too large\n");
- ObDereferenceObject(NewSection);
- return STATUS_NO_MEMORY;
- }
-
/* Lock the VAD tree during the search */
KeAcquireGuardedMutex(&MmSectionBasedMutex);
- /* Find an address top-down */
- Status = MiFindEmptyAddressRangeDownBasedTree(NewSection->SizeOfSection.LowPart,
- (ULONG_PTR)MmHighSectionBase,
- _64K,
- &MmSectionBasedRoot,
- &NewSection->Address.StartingVpn);
- ASSERT(NT_SUCCESS(Status));
+ /* Is it a brand new ControArea ? */
+ if (ControlArea->u.Flags.BeingCreated == 1)
+ {
+ ASSERT(ControlArea->u.Flags.Based == 1);
+ /* Then we must find a global address, top-down */
+ Status = MiFindEmptyAddressRangeDownBasedTree((SIZE_T)ControlArea->Segment->SizeOfSegment,
+ (ULONG_PTR)MmHighSectionBase,
+ _64K,
+ &MmSectionBasedRoot,
+ (ULONG_PTR*)&ControlArea->Segment->BasedAddress);
- /* Compute the ending address and insert it into the VAD tree */
- NewSection->Address.EndingVpn = NewSection->Address.StartingVpn +
- NewSection->SizeOfSection.LowPart -
- 1;
- MiInsertBasedSection(NewSection);
+ if (!NT_SUCCESS(Status))
+ {
+ /* No way to find a valid range. */
+ KeReleaseGuardedMutex(&MmSectionBasedMutex);
+ ControlArea->u.Flags.Based = 0;
+ NewSection->u.Flags.Based = 0;
+ ObDereferenceObject(NewSection);
+ return Status;
+ }
+
+ /* Compute the ending address and insert it into the VAD tree */
+ NewSection->Address.StartingVpn = (ULONG_PTR)ControlArea->Segment->BasedAddress;
+ NewSection->Address.EndingVpn = NewSection->Address.StartingVpn + NewSection->SizeOfSection.LowPart - 1;
+ MiInsertBasedSection(NewSection);
+ }
+ else
+ {
+ /* FIXME : Should we deny section creation if SEC_BASED is not set ? Can we have two different section objects on the same based address ? Investigate !*/
+ ASSERT(FALSE);
+ }
- /* Finally release the lock */
KeReleaseGuardedMutex(&MmSectionBasedMutex);
}
+ /* The control area is not being created anymore */
+ if (ControlArea->u.Flags.BeingCreated == 1)
+ {
+ /* Acquire the PFN lock while we set control area flags */
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+
+ /* Take off the being created flag, and then release the lock */
+ ControlArea->u.Flags.BeingCreated = 0;
+ NewSection->u.Flags.BeingCreated = 0;
+
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+ }
+
+ /* Migrate the attribute into a flag */
+ if (AllocationAttributes & SEC_NO_CHANGE) NewSection->u.Flags.NoChange = TRUE;
+
+ /* If R/W access is not requested, this might eventually become a CoW mapping */
+ if (!(SectionPageProtection & (PAGE_READWRITE | PAGE_EXECUTE_READWRITE)))
+ {
+ NewSection->u.Flags.CopyOnWrite = TRUE;
+ }
+
/* Write down if this was a kernel call */
ControlArea->u.Flags.WasPurged |= KernelCall;
ASSERT(ControlArea->u.Flags.WasPurged == FALSE);
ASSERT(Section->u.Flags.Image == 0);
ASSERT(Section->u.Flags.NoCache == 0);
ASSERT(Section->u.Flags.WriteCombined == 0);
- ASSERT((AllocationType & MEM_RESERVE) == 0);
ASSERT(ControlArea->u.Flags.PhysicalMemory == 0);
+ /* FIXME */
+ if ((AllocationType & MEM_RESERVE) != 0)
+ {
+ DPRINT1("MmMapViewOfArm3Section called with MEM_RESERVE, this is not implemented yet!!!\n");
+ return STATUS_NOT_IMPLEMENTED;
+ }
+
/* Check if the mapping protection is compatible with the create */
if (!MiIsProtectionCompatible(Section->InitialPageProtection, Protect))
{
Attached = TRUE;
}
- /* Lock the address space and make sure the process is alive */
- MmLockAddressSpace(&Process->Vm);
- if (!Process->VmDeleted)
- {
- /* Do the actual mapping */
- DPRINT("Mapping ARM3 data section\n");
- Status = MiMapViewOfDataSection(ControlArea,
- Process,
- BaseAddress,
- SectionOffset,
- ViewSize,
- Section,
- InheritDisposition,
- ProtectionMask,
- CommitSize,
- ZeroBits,
- AllocationType);
- }
- else
- {
- /* The process is being terminated, fail */
- DPRINT1("The process is dying\n");
- Status = STATUS_PROCESS_IS_TERMINATING;
- }
-
- /* Unlock the address space and detatch if needed, then return status */
- MmUnlockAddressSpace(&Process->Vm);
+ /* Do the actual mapping */
+ Status = MiMapViewOfDataSection(ControlArea,
+ Process,
+ BaseAddress,
+ SectionOffset,
+ ViewSize,
+ Section,
+ InheritDisposition,
+ ProtectionMask,
+ CommitSize,
+ ZeroBits,
+ AllocationType);
+
+ /* Detach if needed, then return status */
if (Attached) KeUnstackDetachProcess(&ApcState);
return Status;
}
return STATUS_SUCCESS;
}
+VOID
+NTAPI
+MiDeleteARM3Section(PVOID ObjectBody)
+{
+ PSECTION SectionObject;
+ PCONTROL_AREA ControlArea;
+ KIRQL OldIrql;
+
+ SectionObject = (PSECTION)ObjectBody;
+
+ if (SectionObject->u.Flags.Based == 1)
+ {
+ /* Remove the node from the global section address tree */
+ KeAcquireGuardedMutex(&MmSectionBasedMutex);
+ MiRemoveNode(&SectionObject->Address, &MmSectionBasedRoot);
+ KeReleaseGuardedMutex(&MmSectionBasedMutex);
+ }
+
+ /* Lock the PFN database */
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+
+ ASSERT(SectionObject->Segment);
+ ASSERT(SectionObject->Segment->ControlArea);
+
+ ControlArea = SectionObject->Segment->ControlArea;
+
+ /* Dereference */
+ ControlArea->NumberOfSectionReferences--;
+ ControlArea->NumberOfUserReferences--;
+
+ ASSERT(ControlArea->u.Flags.BeingDeleted == 0);
+
+ /* Check it. It will delete it if there is no more reference to it */
+ MiCheckControlArea(ControlArea, OldIrql);
+}
+
+ULONG
+NTAPI
+MmDoesFileHaveUserWritableReferences(IN PSECTION_OBJECT_POINTERS SectionPointer)
+{
+ UNIMPLEMENTED;
+ return 0;
+}
+
/* SYSTEM CALLS ***************************************************************/
NTSTATUS
IN PVOID File2MappedAsFile)
{
PVOID AddressSpace;
- PMEMORY_AREA MemoryArea1, MemoryArea2;
- PROS_SECTION_OBJECT Section1, Section2;
+ PMMVAD Vad1, Vad2;
+ PFILE_OBJECT FileObject1, FileObject2;
+ NTSTATUS Status;
/* Lock address space */
AddressSpace = MmGetCurrentAddressSpace();
MmLockAddressSpace(AddressSpace);
- /* Locate the memory area for the process by address */
- MemoryArea1 = MmLocateMemoryAreaByAddress(AddressSpace, File1MappedAsAnImage);
- if (!MemoryArea1)
+ /* Get the VAD for Address 1 */
+ Vad1 = MiLocateAddress(File1MappedAsAnImage);
+ if (Vad1 == NULL)
{
/* Fail, the address does not exist */
- MmUnlockAddressSpace(AddressSpace);
- return STATUS_INVALID_ADDRESS;
+ DPRINT1("No VAD at address 1 %p\n", File1MappedAsAnImage);
+ Status = STATUS_INVALID_ADDRESS;
+ goto Exit;
}
- /* Check if it's a section view (RosMm section) or ARM3 section */
- if (MemoryArea1->Type != MEMORY_AREA_SECTION_VIEW)
+ /* Get the VAD for Address 2 */
+ Vad2 = MiLocateAddress(File2MappedAsFile);
+ if (Vad2 == NULL)
{
- /* Fail, the address is not a section */
- MmUnlockAddressSpace(AddressSpace);
- return STATUS_CONFLICTING_ADDRESSES;
+ /* Fail, the address does not exist */
+ DPRINT1("No VAD at address 2 %p\n", File2MappedAsFile);
+ Status = STATUS_INVALID_ADDRESS;
+ goto Exit;
}
- /* Get the section pointer to the SECTION_OBJECT */
- Section1 = MemoryArea1->Data.SectionData.Section;
- if (Section1->FileObject == NULL)
+ /* Get the file object pointer for VAD 1 */
+ FileObject1 = MiGetFileObjectForVad(Vad1);
+ if (FileObject1 == NULL)
{
- MmUnlockAddressSpace(AddressSpace);
- return STATUS_CONFLICTING_ADDRESSES;
+ DPRINT1("Failed to get file object for Address 1 %p\n", File1MappedAsAnImage);
+ Status = STATUS_CONFLICTING_ADDRESSES;
+ goto Exit;
}
- /* Locate the memory area for the process by address */
- MemoryArea2 = MmLocateMemoryAreaByAddress(AddressSpace, File2MappedAsFile);
- if (!MemoryArea2)
+ /* Get the file object pointer for VAD 2 */
+ FileObject2 = MiGetFileObjectForVad(Vad2);
+ if (FileObject2 == NULL)
{
- /* Fail, the address does not exist */
- MmUnlockAddressSpace(AddressSpace);
- return STATUS_INVALID_ADDRESS;
+ DPRINT1("Failed to get file object for Address 2 %p\n", File2MappedAsFile);
+ Status = STATUS_CONFLICTING_ADDRESSES;
+ goto Exit;
}
- /* Check if it's a section view (RosMm section) or ARM3 section */
- if (MemoryArea2->Type != MEMORY_AREA_SECTION_VIEW)
+ /* Make sure Vad1 is an image mapping */
+ if (Vad1->u.VadFlags.VadType != VadImageMap)
{
- /* Fail, the address is not a section */
- MmUnlockAddressSpace(AddressSpace);
- return STATUS_CONFLICTING_ADDRESSES;
+ DPRINT1("Address 1 (%p) is not an image mapping\n", File1MappedAsAnImage);
+ Status = STATUS_NOT_SAME_DEVICE;
+ goto Exit;
}
- /* Get the section pointer to the SECTION_OBJECT */
- Section2 = MemoryArea2->Data.SectionData.Section;
- if (Section2->FileObject == NULL)
+ /* SectionObjectPointer is equal if the files are equal */
+ if (FileObject1->SectionObjectPointer == FileObject2->SectionObjectPointer)
{
- MmUnlockAddressSpace(AddressSpace);
- return STATUS_CONFLICTING_ADDRESSES;
+ Status = STATUS_SUCCESS;
}
-
- /* The shared cache map seems to be the same if both of these are equal */
- if (Section1->FileObject->SectionObjectPointer->SharedCacheMap ==
- Section2->FileObject->SectionObjectPointer->SharedCacheMap)
+ else
{
- MmUnlockAddressSpace(AddressSpace);
- return STATUS_SUCCESS;
+ Status = STATUS_NOT_SAME_DEVICE;
}
+Exit:
/* Unlock address space */
MmUnlockAddressSpace(AddressSpace);
- return STATUS_NOT_SAME_DEVICE;
+ return Status;
}
/*
ACCESS_MASK DesiredAccess;
ULONG ProtectionMask;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-
- /* Check for invalid zero bits */
- if (ZeroBits > 21) // per-arch?
- {
- DPRINT1("Invalid zero bits\n");
- return STATUS_INVALID_PARAMETER_4;
- }
+#ifdef _M_IX86
+ static const ULONG ValidAllocationType = (MEM_TOP_DOWN | MEM_LARGE_PAGES |
+ MEM_DOS_LIM | SEC_NO_CHANGE | MEM_RESERVE);
+#else
+ static const ULONG ValidAllocationType = (MEM_TOP_DOWN | MEM_LARGE_PAGES |
+ SEC_NO_CHANGE | MEM_RESERVE);
+#endif
/* Check for invalid inherit disposition */
if ((InheritDisposition > ViewUnmap) || (InheritDisposition < ViewShare))
}
/* Allow only valid allocation types */
- if ((AllocationType & ~(MEM_TOP_DOWN | MEM_LARGE_PAGES | MEM_DOS_LIM |
- SEC_NO_CHANGE | MEM_RESERVE)))
+ if (AllocationType & ~ValidAllocationType)
{
DPRINT1("Invalid allocation type\n");
return STATUS_INVALID_PARAMETER_9;
return STATUS_INVALID_PAGE_PROTECTION;
}
- /* Check for non-allocation-granularity-aligned BaseAddress */
- if (BaseAddress && (*BaseAddress != ALIGN_DOWN_POINTER_BY(*BaseAddress, MM_VIRTMEM_GRANULARITY)))
- {
- DPRINT("BaseAddress is not at 64-kilobyte address boundary.");
- return STATUS_MAPPED_ALIGNMENT;
- }
-
/* Now convert the protection mask into desired section access mask */
DesiredAccess = MmMakeSectionAccess[ProtectionMask & 0x7];
}
/* Check for invalid zero bits */
- if (((ULONG_PTR)SafeBaseAddress + SafeViewSize) > (0xFFFFFFFF >> ZeroBits)) // arch?
+ if (ZeroBits)
{
- DPRINT1("Invalid zero bits\n");
- return STATUS_INVALID_PARAMETER_4;
+ if (ZeroBits > MI_MAX_ZERO_BITS)
+ {
+ DPRINT1("Invalid zero bits\n");
+ return STATUS_INVALID_PARAMETER_4;
+ }
+
+ if ((((ULONG_PTR)SafeBaseAddress << ZeroBits) >> ZeroBits) != (ULONG_PTR)SafeBaseAddress)
+ {
+ DPRINT1("Invalid zero bits\n");
+ return STATUS_INVALID_PARAMETER_4;
+ }
+
+ if (((((ULONG_PTR)SafeBaseAddress + SafeViewSize) << ZeroBits) >> ZeroBits) != ((ULONG_PTR)SafeBaseAddress + SafeViewSize))
+ {
+ DPRINT1("Invalid zero bits\n");
+ return STATUS_INVALID_PARAMETER_4;
+ }
}
/* Reference the process */
return Status;
}
+ if (MiIsRosSectionObject(Section) &&
+ (Section->AllocationAttributes & SEC_PHYSICALMEMORY))
+ {
+ if (PreviousMode == UserMode &&
+ SafeSectionOffset.QuadPart + SafeViewSize > MmHighestPhysicalPage << PAGE_SHIFT)
+ {
+ DPRINT1("Denying map past highest physical page.\n");
+ ObDereferenceObject(Section);
+ ObDereferenceObject(Process);
+ return STATUS_INVALID_PARAMETER_6;
+ }
+ }
+ else if (!(AllocationType & MEM_DOS_LIM))
+ {
+ /* Check for non-allocation-granularity-aligned BaseAddress */
+ if (SafeBaseAddress != ALIGN_DOWN_POINTER_BY(SafeBaseAddress, MM_VIRTMEM_GRANULARITY))
+ {
+ DPRINT("BaseAddress is not at 64-kilobyte address boundary.\n");
+ ObDereferenceObject(Section);
+ ObDereferenceObject(Process);
+ return STATUS_MAPPED_ALIGNMENT;
+ }
+
+ /* Do the same for the section offset */
+ if (SafeSectionOffset.LowPart != ALIGN_DOWN_BY(SafeSectionOffset.LowPart, MM_VIRTMEM_GRANULARITY))
+ {
+ DPRINT("SectionOffset is not at 64-kilobyte address boundary.\n");
+ ObDereferenceObject(Section);
+ ObDereferenceObject(Process);
+ return STATUS_MAPPED_ALIGNMENT;
+ }
+ }
+
/* Now do the actual mapping */
Status = MmMapViewOfSection(Section,
Process,
if (NT_SUCCESS(Status))
{
/* Check if this is an image for the current process */
- if ((Section->AllocationAttributes & SEC_IMAGE) &&
+ if (MiIsRosSectionObject(Section) &&
+ (Section->AllocationAttributes & SEC_IMAGE) &&
(Process == PsGetCurrentProcess()) &&
(Status != STATUS_IMAGE_NOT_AT_BASE))
{