mirror of
https://github.com/reactos/reactos.git
synced 2025-08-07 00:43:09 +00:00
[NTOS]: Implement ARM3 version of MmMapViewOfSection, only for ARM3 pagefile-backed sections, and without any special flag support. Tested and works great, with the new pagefault code correctly finding the Prototype PTE for the VAD.
[NTOS]: Make every VAD insert also create a MEMORY_AREA. Now the two address space views should be completely synchronized and we can try removing the hack that was done for PEB/TEB support (which will remove the 200 thread regression). [NTOS]: Implement MiGetNextNode and MiFindEmptyAddressRangeInTree. svn path=/trunk/; revision=48997
This commit is contained in:
parent
faa70e3d70
commit
29764be430
3 changed files with 450 additions and 3 deletions
|
@ -463,6 +463,159 @@ MiMapViewInSystemSpace(IN PVOID Section,
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
MiMapViewOfDataSection(IN PCONTROL_AREA ControlArea,
|
||||||
|
IN PEPROCESS Process,
|
||||||
|
IN PVOID *BaseAddress,
|
||||||
|
IN PLARGE_INTEGER SectionOffset,
|
||||||
|
IN PSIZE_T ViewSize,
|
||||||
|
IN PSECTION Section,
|
||||||
|
IN SECTION_INHERIT InheritDisposition,
|
||||||
|
IN ULONG ProtectionMask,
|
||||||
|
IN ULONG CommitSize,
|
||||||
|
IN ULONG_PTR ZeroBits,
|
||||||
|
IN ULONG AllocationType)
|
||||||
|
{
|
||||||
|
PMMVAD Vad;
|
||||||
|
PETHREAD Thread = PsGetCurrentThread();
|
||||||
|
ULONG_PTR StartAddress, EndingAddress;
|
||||||
|
PSUBSECTION Subsection;
|
||||||
|
PSEGMENT Segment;
|
||||||
|
PFN_NUMBER PteOffset;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
/* Get the segment and subection for this section */
|
||||||
|
Segment = ControlArea->Segment;
|
||||||
|
Subsection = (PSUBSECTION)(ControlArea + 1);
|
||||||
|
|
||||||
|
/* Non-pagefile-backed sections not supported */
|
||||||
|
ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
|
||||||
|
ASSERT(ControlArea->u.Flags.Rom == 0);
|
||||||
|
ASSERT(ControlArea->FilePointer == NULL);
|
||||||
|
ASSERT(Segment->SegmentFlags.TotalNumberOfPtes4132 == 0);
|
||||||
|
|
||||||
|
/* Based sections not supported */
|
||||||
|
ASSERT(Section->Address.StartingVpn == 0);
|
||||||
|
|
||||||
|
/* These flags/parameters are not supported */
|
||||||
|
ASSERT((AllocationType & MEM_DOS_LIM) == 0);
|
||||||
|
ASSERT((AllocationType & MEM_RESERVE) == 0);
|
||||||
|
ASSERT((AllocationType & MEM_TOP_DOWN) == 0);
|
||||||
|
ASSERT(Process->VmTopDown == 0);
|
||||||
|
ASSERT(Section->u.Flags.CopyOnWrite == FALSE);
|
||||||
|
ASSERT(ZeroBits == 0);
|
||||||
|
|
||||||
|
/* First, increase the map count. No purging is supported yet */
|
||||||
|
Status = MiCheckPurgeAndUpMapCount(ControlArea, FALSE);
|
||||||
|
ASSERT(NT_SUCCESS(Status));
|
||||||
|
|
||||||
|
/* Check if the caller specified the view size */
|
||||||
|
if (!(*ViewSize))
|
||||||
|
{
|
||||||
|
/* The caller did not, so pick a 64K aligned view size based on the offset */
|
||||||
|
SectionOffset->LowPart &= ~(_64K - 1);
|
||||||
|
*ViewSize = Section->SizeOfSection.QuadPart - SectionOffset->QuadPart;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* A size was specified, align it to a 64K boundary */
|
||||||
|
*ViewSize += SectionOffset->LowPart & (_64K - 1);
|
||||||
|
|
||||||
|
/* Align the offset as well to make this an aligned map */
|
||||||
|
SectionOffset->LowPart &= ~((ULONG)_64K - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We must be dealing with a 64KB aligned offset */
|
||||||
|
ASSERT((SectionOffset->LowPart & ((ULONG)_64K - 1)) == 0);
|
||||||
|
|
||||||
|
/* It's illegal to try to map more than 2GB */
|
||||||
|
if (*ViewSize >= 0x80000000) return STATUS_INVALID_VIEW_SIZE;
|
||||||
|
|
||||||
|
/* Within this section, figure out which PTEs will describe the view */
|
||||||
|
PteOffset = SectionOffset->QuadPart >> PAGE_SHIFT;
|
||||||
|
|
||||||
|
/* The offset must be in this segment's PTE chunk and it must be valid */
|
||||||
|
ASSERT(PteOffset < Segment->TotalNumberOfPtes);
|
||||||
|
ASSERT(((SectionOffset->QuadPart + *ViewSize + PAGE_SIZE - 1) >> PAGE_SHIFT) >= PteOffset);
|
||||||
|
|
||||||
|
/* In ARM3, only one subsection is used for now. It must contain these PTEs */
|
||||||
|
ASSERT(PteOffset < Subsection->PtesInSubsection);
|
||||||
|
ASSERT(Subsection->SubsectionBase != NULL);
|
||||||
|
|
||||||
|
/* In ARM3, only MEM_COMMIT is supported for now. The PTEs must've been committed */
|
||||||
|
ASSERT(Segment->NumberOfCommittedPages >= Segment->TotalNumberOfPtes);
|
||||||
|
|
||||||
|
/* Did the caller specify an address? */
|
||||||
|
if (!(*BaseAddress))
|
||||||
|
{
|
||||||
|
/* No, find an address bottom-up */
|
||||||
|
Status = MiFindEmptyAddressRangeInTree(*ViewSize,
|
||||||
|
_64K,
|
||||||
|
&Process->VadRoot,
|
||||||
|
(PMMADDRESS_NODE*)&Process->VadFreeHint,
|
||||||
|
&StartAddress);
|
||||||
|
ASSERT(NT_SUCCESS(Status));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* This (rather easy) code path is not yet implemented */
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
while (TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the ending address, which is the last piece we need for the VAD */
|
||||||
|
EndingAddress = (StartAddress + *ViewSize - 1) | (PAGE_SIZE - 1);
|
||||||
|
|
||||||
|
/* A VAD can now be allocated. Do so and zero it out */
|
||||||
|
Vad = ExAllocatePoolWithTag(NonPagedPool, sizeof(MMVAD), 'ldaV');
|
||||||
|
ASSERT(Vad);
|
||||||
|
RtlZeroMemory(Vad, sizeof(MMVAD));
|
||||||
|
|
||||||
|
/* 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.Protection = ProtectionMask;
|
||||||
|
Vad->u2.VadFlags2.FileOffset = SectionOffset->QuadPart >> 16;
|
||||||
|
Vad->u2.VadFlags2.Inherit = (InheritDisposition == ViewShare);
|
||||||
|
if ((AllocationType & SEC_NO_CHANGE) || (Section->u.Flags.NoChange))
|
||||||
|
{
|
||||||
|
/* This isn't really implemented yet, but handle setting the flag */
|
||||||
|
Vad->u.VadFlags.NoChange = 1;
|
||||||
|
Vad->u2.VadFlags2.SecNoChange = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finally, write down the first and last prototype PTE */
|
||||||
|
Vad->FirstPrototypePte = &Subsection->SubsectionBase[PteOffset];
|
||||||
|
PteOffset += (Vad->EndingVpn - Vad->StartingVpn);
|
||||||
|
Vad->LastContiguousPte = &Subsection->SubsectionBase[PteOffset];
|
||||||
|
|
||||||
|
/* Make sure the last PTE is valid and still within the subsection */
|
||||||
|
ASSERT(PteOffset < Subsection->PtesInSubsection);
|
||||||
|
ASSERT(Vad->FirstPrototypePte <= Vad->LastContiguousPte);
|
||||||
|
|
||||||
|
/* FIXME: Should setup VAD bitmap */
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
/* Pretend as if we own the working set */
|
||||||
|
MiLockProcessWorkingSet(Process, Thread);
|
||||||
|
|
||||||
|
/* Insert the VAD */
|
||||||
|
MiInsertVad(Vad, Process);
|
||||||
|
|
||||||
|
/* Release the working set */
|
||||||
|
MiUnlockProcessWorkingSet(Process, Thread);
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
*BaseAddress = (PVOID)StartAddress;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
MiCreatePagingFileMap(OUT PSEGMENT *Segment,
|
MiCreatePagingFileMap(OUT PSEGMENT *Segment,
|
||||||
|
@ -668,6 +821,146 @@ MmCreateArm3Section(OUT PVOID *SectionObject,
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
MmMapViewOfArm3Section(IN PVOID SectionObject,
|
||||||
|
IN PEPROCESS Process,
|
||||||
|
IN OUT PVOID *BaseAddress,
|
||||||
|
IN ULONG_PTR ZeroBits,
|
||||||
|
IN SIZE_T CommitSize,
|
||||||
|
IN OUT PLARGE_INTEGER SectionOffset OPTIONAL,
|
||||||
|
IN OUT PSIZE_T ViewSize,
|
||||||
|
IN SECTION_INHERIT InheritDisposition,
|
||||||
|
IN ULONG AllocationType,
|
||||||
|
IN ULONG Protect)
|
||||||
|
{
|
||||||
|
KAPC_STATE ApcState;
|
||||||
|
BOOLEAN Attached = FALSE;
|
||||||
|
PSECTION Section;
|
||||||
|
PCONTROL_AREA ControlArea;
|
||||||
|
ULONG ProtectionMask;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
/* Get the segment and control area */
|
||||||
|
Section = (PSECTION)SectionObject;
|
||||||
|
ControlArea = Section->Segment->ControlArea;
|
||||||
|
|
||||||
|
/* These flags/states are not yet supported by ARM3 */
|
||||||
|
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);
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* FIXME: Check if the mapping protection is compatible with the create */
|
||||||
|
if (!MiIsProtectionCompatible(Section->InitialPageProtection, Protect))
|
||||||
|
{
|
||||||
|
DPRINT1("Mapping protection is incompatible\n");
|
||||||
|
return STATUS_SECTION_PROTECTION;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Check if the offset and size would cause an overflow */
|
||||||
|
if ((SectionOffset->QuadPart + *ViewSize) < SectionOffset->QuadPart)
|
||||||
|
{
|
||||||
|
DPRINT1("Section offset overflows\n");
|
||||||
|
return STATUS_INVALID_VIEW_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the offset and size are bigger than the section itself */
|
||||||
|
if ((SectionOffset->QuadPart + *ViewSize) > Section->SizeOfSection.QuadPart)
|
||||||
|
{
|
||||||
|
DPRINT1("Section offset is larger than section\n");
|
||||||
|
return STATUS_INVALID_VIEW_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the caller did not specify a view size */
|
||||||
|
if (!(*ViewSize))
|
||||||
|
{
|
||||||
|
/* Compute it for the caller */
|
||||||
|
*ViewSize = Section->SizeOfSection.QuadPart - SectionOffset->QuadPart;
|
||||||
|
|
||||||
|
/* Check if it's larger than 4GB or overflows into kernel-mode */
|
||||||
|
if ((*ViewSize > 0xFFFFFFFF) ||
|
||||||
|
(((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS - (ULONG_PTR)*BaseAddress) < *ViewSize))
|
||||||
|
{
|
||||||
|
DPRINT1("Section view won't fit\n");
|
||||||
|
return STATUS_INVALID_VIEW_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the commit size is larger than the view size */
|
||||||
|
if (CommitSize > *ViewSize)
|
||||||
|
{
|
||||||
|
DPRINT1("Attempting to commit more than the view itself\n");
|
||||||
|
return STATUS_INVALID_PARAMETER_5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the view size is larger than the section */
|
||||||
|
if (*ViewSize > Section->SizeOfSection.QuadPart)
|
||||||
|
{
|
||||||
|
DPRINT1("The view is larger than the section\n");
|
||||||
|
return STATUS_INVALID_VIEW_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute and validate the protection mask */
|
||||||
|
ProtectionMask = MiMakeProtectionMask(Protect);
|
||||||
|
if (ProtectionMask == MM_INVALID_PROTECTION)
|
||||||
|
{
|
||||||
|
DPRINT1("The protection is invalid\n");
|
||||||
|
return STATUS_INVALID_PAGE_PROTECTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We only handle pagefile-backed sections, which cannot be writecombined */
|
||||||
|
if (Protect & PAGE_WRITECOMBINE)
|
||||||
|
{
|
||||||
|
DPRINT1("Cannot write combine a pagefile-backed section\n");
|
||||||
|
return STATUS_INVALID_PARAMETER_10;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Start by attaching to the current process if needed */
|
||||||
|
if (PsGetCurrentProcess() != Process)
|
||||||
|
{
|
||||||
|
KeStackAttachProcess(&Process->Pcb, &ApcState);
|
||||||
|
Attached = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lock the address space and make sure the process is alive */
|
||||||
|
MmLockAddressSpace(&Process->Vm);
|
||||||
|
if (!Process->VmDeleted)
|
||||||
|
{
|
||||||
|
/* Do the actual mapping */
|
||||||
|
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);
|
||||||
|
if (Attached) KeUnstackDetachProcess(&ApcState);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
/* SYSTEM CALLS ***************************************************************/
|
/* SYSTEM CALLS ***************************************************************/
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
|
|
@ -121,6 +121,28 @@ MiInsertVad(IN PMMVAD Vad,
|
||||||
|
|
||||||
/* Do the actual insert operation */
|
/* Do the actual insert operation */
|
||||||
MiInsertNode(&Process->VadRoot, (PVOID)Vad, Parent, Result);
|
MiInsertNode(&Process->VadRoot, (PVOID)Vad, Parent, Result);
|
||||||
|
|
||||||
|
/* Now insert an ARM3 MEMORY_AREA for this node, unless the insert was already from the MEMORY_AREA code */
|
||||||
|
if (Vad->u.VadFlags.Spare == 0)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PMEMORY_AREA MemoryArea;
|
||||||
|
PHYSICAL_ADDRESS BoundaryAddressMultiple;
|
||||||
|
SIZE_T Size;
|
||||||
|
PVOID AllocatedBase = (PVOID)(Vad->StartingVpn << PAGE_SHIFT);
|
||||||
|
BoundaryAddressMultiple.QuadPart = 0;
|
||||||
|
Size = ((Vad->EndingVpn + 1) - Vad->StartingVpn) << PAGE_SHIFT;
|
||||||
|
Status = MmCreateMemoryArea(&Process->Vm,
|
||||||
|
MEMORY_AREA_OWNED_BY_ARM3,
|
||||||
|
&AllocatedBase,
|
||||||
|
Size,
|
||||||
|
PAGE_READWRITE,
|
||||||
|
&MemoryArea,
|
||||||
|
TRUE,
|
||||||
|
0,
|
||||||
|
BoundaryAddressMultiple);
|
||||||
|
ASSERT(NT_SUCCESS(Status));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
@ -181,6 +203,112 @@ MiGetPreviousNode(IN PMMADDRESS_NODE Node)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PMMADDRESS_NODE
|
||||||
|
NTAPI
|
||||||
|
MiGetNextNode(IN PMMADDRESS_NODE Node)
|
||||||
|
{
|
||||||
|
PMMADDRESS_NODE Parent;
|
||||||
|
|
||||||
|
/* Get the right child */
|
||||||
|
if (RtlRightChildAvl(Node))
|
||||||
|
{
|
||||||
|
/* Get left-most child */
|
||||||
|
Node = RtlRightChildAvl(Node);
|
||||||
|
while (RtlLeftChildAvl(Node)) Node = RtlLeftChildAvl(Node);
|
||||||
|
return Node;
|
||||||
|
}
|
||||||
|
|
||||||
|
Parent = RtlParentAvl(Node);
|
||||||
|
ASSERT(Parent != NULL);
|
||||||
|
while (Parent != Node)
|
||||||
|
{
|
||||||
|
/* The parent should be a left child, return the real predecessor */
|
||||||
|
if (RtlIsLeftChildAvl(Node))
|
||||||
|
{
|
||||||
|
/* Return it */
|
||||||
|
return Parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Keep lopping until we find our parent */
|
||||||
|
Node = Parent;
|
||||||
|
Parent = RtlParentAvl(Node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nothing found */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
MiFindEmptyAddressRangeInTree(IN SIZE_T Length,
|
||||||
|
IN ULONG_PTR Alignment,
|
||||||
|
IN PMM_AVL_TABLE Table,
|
||||||
|
OUT PMMADDRESS_NODE *PreviousVad,
|
||||||
|
OUT PULONG_PTR Base)
|
||||||
|
{
|
||||||
|
PMMADDRESS_NODE Node;
|
||||||
|
PMMADDRESS_NODE NextNode;
|
||||||
|
ULONG_PTR StartingVpn, HighestVpn, AlignmentVpn, LengthVpn, LowVpn;
|
||||||
|
ASSERT(Length != 0);
|
||||||
|
|
||||||
|
/* Precompute page numbers for the length, alignment, and starting address */
|
||||||
|
LengthVpn = (Length + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
|
||||||
|
AlignmentVpn = Alignment >> PAGE_SHIFT;
|
||||||
|
StartingVpn = ROUND_DOWN((ULONG_PTR)MM_LOWEST_USER_ADDRESS >> PAGE_SHIFT,
|
||||||
|
AlignmentVpn);
|
||||||
|
|
||||||
|
/* Check if the table is free, so the lowest possible address is available */
|
||||||
|
if (!Table->NumberGenericTableElements) goto FoundAtBottom;
|
||||||
|
|
||||||
|
/* Otherwise, follow the leftmost child of the right root node's child */
|
||||||
|
Node = RtlRightChildAvl(&Table->BalancedRoot);
|
||||||
|
while (RtlLeftChildAvl(Node)) Node = RtlLeftChildAvl(Node);
|
||||||
|
|
||||||
|
/* This is the node for the remaining gap at the bottom, can it be used? */
|
||||||
|
if ((Node->StartingVpn > StartingVpn) &&
|
||||||
|
(LengthVpn < Node->StartingVpn - StartingVpn))
|
||||||
|
{
|
||||||
|
FoundAtBottom:
|
||||||
|
/* Use this VAD to store the allocation */
|
||||||
|
*PreviousVad = NULL;
|
||||||
|
*Base = StartingVpn << PAGE_SHIFT;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Otherwise, we start a search to find a gap */
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
/* The last aligned page number in this entry */
|
||||||
|
LowVpn = ROUND_DOWN(Node->EndingVpn + 1, AlignmentVpn);
|
||||||
|
|
||||||
|
/* Keep going as long as there's still a next node */
|
||||||
|
NextNode = MiGetNextNode(Node);
|
||||||
|
if (!NextNode) break;
|
||||||
|
|
||||||
|
/* Can this allocation fit in this node? */
|
||||||
|
if ((LengthVpn <= (NextNode->StartingVpn - LowVpn)) &&
|
||||||
|
(NextNode->StartingVpn > LowVpn))
|
||||||
|
{
|
||||||
|
Found:
|
||||||
|
/* Yes! Use this VAD to store the allocation */
|
||||||
|
*PreviousVad = Node;
|
||||||
|
*Base = ROUND_DOWN((Node->EndingVpn << PAGE_SHIFT) | (PAGE_SIZE - 1),
|
||||||
|
Alignment);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try the next node */
|
||||||
|
Node = NextNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We're down to the last (top) VAD, will this allocation fit inside it? */
|
||||||
|
HighestVpn = ((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1) >> PAGE_SHIFT;
|
||||||
|
if ((HighestVpn > LowVpn) && (LengthVpn <= HighestVpn - LowVpn)) goto Found;
|
||||||
|
|
||||||
|
/* Nyet, there's no free address space for this allocation, so we'll fail */
|
||||||
|
return STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
TABLE_SEARCH_RESULT
|
TABLE_SEARCH_RESULT
|
||||||
NTAPI
|
NTAPI
|
||||||
MiFindEmptyAddressRangeDownTree(IN SIZE_T Length,
|
MiFindEmptyAddressRangeDownTree(IN SIZE_T Length,
|
||||||
|
|
|
@ -3956,6 +3956,18 @@ NtQuerySection(IN HANDLE SectionHandle,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
MmMapViewOfArm3Section(IN PVOID SectionObject,
|
||||||
|
IN PEPROCESS Process,
|
||||||
|
IN OUT PVOID *BaseAddress,
|
||||||
|
IN ULONG_PTR ZeroBits,
|
||||||
|
IN SIZE_T CommitSize,
|
||||||
|
IN OUT PLARGE_INTEGER SectionOffset OPTIONAL,
|
||||||
|
IN OUT PSIZE_T ViewSize,
|
||||||
|
IN SECTION_INHERIT InheritDisposition,
|
||||||
|
IN ULONG AllocationType,
|
||||||
|
IN ULONG Protect);
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* NAME EXPORTED
|
* NAME EXPORTED
|
||||||
|
@ -4023,6 +4035,20 @@ MmMapViewOfSection(IN PVOID SectionObject,
|
||||||
ULONG ViewOffset;
|
ULONG ViewOffset;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
if ((ULONG_PTR)SectionObject & 1)
|
||||||
|
{
|
||||||
|
return MmMapViewOfArm3Section((PVOID)((ULONG_PTR)SectionObject & ~1),
|
||||||
|
Process,
|
||||||
|
BaseAddress,
|
||||||
|
ZeroBits,
|
||||||
|
CommitSize,
|
||||||
|
SectionOffset,
|
||||||
|
ViewSize,
|
||||||
|
InheritDisposition,
|
||||||
|
AllocationType,
|
||||||
|
Protect);
|
||||||
|
}
|
||||||
|
|
||||||
ASSERT(Process);
|
ASSERT(Process);
|
||||||
|
|
||||||
if (!Protect || Protect & ~PAGE_FLAGS_VALID_FOR_SECTION)
|
if (!Protect || Protect & ~PAGE_FLAGS_VALID_FOR_SECTION)
|
||||||
|
@ -4280,10 +4306,10 @@ MmMapViewInSystemSpace (IN PVOID SectionObject,
|
||||||
PROS_SECTION_OBJECT Section;
|
PROS_SECTION_OBJECT Section;
|
||||||
PMMSUPPORT AddressSpace;
|
PMMSUPPORT AddressSpace;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
if ((ULONG_PTR)SectionObject & 1)
|
if ((ULONG_PTR)SectionObject & 1)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
|
||||||
extern PVOID MmSession;
|
extern PVOID MmSession;
|
||||||
return MiMapViewInSystemSpace((PVOID)((ULONG_PTR)SectionObject & ~1),
|
return MiMapViewInSystemSpace((PVOID)((ULONG_PTR)SectionObject & ~1),
|
||||||
&MmSession,
|
&MmSession,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue