[NTOS]: Add support for unmapping ARM3 sections, destroying segments and control areas, and clearing out subsection PTEs.

[NTOS]: Add support to MiDeletePte/MiDeleteVirtualAddresses to handle Section VADs.
[NTOS]: Add support to MiDeletePte to handle valid, prototype PTEs.
[NTOS]: Add MEM_TOP_DOWN support to ARM3 section code.
[NTOS]: Add support for unmapping currently mapped ARM3 section views at process termination.
[NTOS]: Use the new ARM3 section code for mapping the NLS section in the system (tests the system-view mapping code) and in each new process (tests the data-mapping code). Section is correctly unmapped at process termination time!

svn path=/trunk/; revision=49206
This commit is contained in:
Sir Richard 2010-10-19 17:07:11 +00:00
parent 20d602d71f
commit 3e8034d4a5
5 changed files with 444 additions and 61 deletions

View file

@ -296,7 +296,7 @@ ExpInitNls(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
NULL,
&SectionSize,
PAGE_READWRITE,
SEC_COMMIT,
SEC_COMMIT | 0x1,
NULL);
if (!NT_SUCCESS(Status))
{
@ -319,7 +319,7 @@ ExpInitNls(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
}
/* Map the NLS Section in system space */
Status = MmMapViewInSystemSpace(ExpNlsSectionPointer,
Status = MmMapViewInSystemSpace((PVOID)((ULONG_PTR)ExpNlsSectionPointer | 0x1),
&SectionBase,
&ExpNlsTableSize);
if (!NT_SUCCESS(Status))
@ -349,7 +349,7 @@ ExpInitNls(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
SectionBase = NULL;
/* Map the section in the system process */
Status = MmMapViewOfSection(ExpNlsSectionPointer,
Status = MmMapViewOfSection((PVOID)((ULONG_PTR)ExpNlsSectionPointer | 0x1),
PsGetCurrentProcess(),
&SectionBase,
0L,

View file

@ -832,6 +832,22 @@ MiUnlockWorkingSet(IN PETHREAD Thread,
KeLeaveGuardedRegion();
}
//
// Returns the ProtoPTE inside a VAD for the given VPN
//
FORCEINLINE
PMMPTE
MI_GET_PROTOTYPE_PTE_FOR_VPN(IN PMMVAD Vad,
IN ULONG_PTR Vpn)
{
PMMPTE ProtoPte;
/* Find the offset within the VAD's prototype PTEs */
ProtoPte = Vad->FirstPrototypePte + ((Vpn - Vad->StartingVpn) * sizeof(MMPTE));
ASSERT(ProtoPte <= Vad->LastContiguousPte);
return ProtoPte;
}
BOOLEAN
NTAPI
MmArmInitSystem(
@ -1224,6 +1240,27 @@ MiMakeSystemAddressValid(
IN PVOID PageTableVirtualAddress,
IN PEPROCESS CurrentProcess
);
ULONG
NTAPI
MiMakeSystemAddressValidPfn(
IN PVOID VirtualAddress,
IN KIRQL OldIrql
);
VOID
NTAPI
MiRemoveMappedView(
IN PEPROCESS CurrentProcess,
IN PMMVAD Vad
);
PSUBSECTION
NTAPI
MiLocateSubsection(
IN PMMVAD Vad,
IN ULONG_PTR Vpn
);
//
// MiRemoveZeroPage will use inline code to zero out the page manually if only

View file

@ -581,7 +581,7 @@ MmCreatePeb(IN PEPROCESS Process,
//
// Map NLS Tables
//
Status = MmMapViewOfSection(ExpNlsSectionPointer,
Status = MmMapViewOfSection((PVOID)((ULONG_PTR)ExpNlsSectionPointer | 0x1),
(PEPROCESS)Process,
&TableBase,
0,
@ -1186,17 +1186,25 @@ MmCleanProcessAddressSpace(IN PEPROCESS Process)
ASSERT(VadTree->NumberGenericTableElements >= 1);
MiRemoveNode((PMMADDRESS_NODE)Vad, VadTree);
/* Only PEB/TEB VADs supported for now */
ASSERT(Vad->u.VadFlags.PrivateMemory == 1);
/* Only regular VADs supported for now */
ASSERT(Vad->u.VadFlags.VadType == VadNone);
/* Delete the addresses */
MiDeleteVirtualAddresses(Vad->StartingVpn << PAGE_SHIFT,
(Vad->EndingVpn << PAGE_SHIFT) | (PAGE_SIZE - 1),
Vad);
/* Check if this is a section VAD */
if (!(Vad->u.VadFlags.PrivateMemory) && (Vad->ControlArea))
{
/* Remove the view */
MiRemoveMappedView(Process, Vad);
}
else
{
/* Delete the addresses */
MiDeleteVirtualAddresses(Vad->StartingVpn << PAGE_SHIFT,
(Vad->EndingVpn << PAGE_SHIFT) | (PAGE_SIZE - 1),
Vad);
/* Release the working set */
MiUnlockProcessWorkingSet(Process, Thread);
/* Release the working set */
MiUnlockProcessWorkingSet(Process, Thread);
}
/* Skip ARM3 fake VADs, they'll be freed by MmDeleteProcessAddresSpace */
if (Vad->u.VadFlags.Spare == 1)

View file

@ -393,6 +393,188 @@ MiCheckPurgeAndUpMapCount(IN PCONTROL_AREA ControlArea,
return STATUS_SUCCESS;
}
PSUBSECTION
NTAPI
MiLocateSubsection(IN PMMVAD Vad,
IN ULONG_PTR Vpn)
{
PSUBSECTION Subsection;
PCONTROL_AREA ControlArea;
ULONG PteOffset;
/* Get the control area */
ControlArea = Vad->ControlArea;
ASSERT(ControlArea->u.Flags.Rom == 0);
ASSERT(ControlArea->u.Flags.Image == 0);
ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
/* Get the subsection */
Subsection = (PSUBSECTION)(ControlArea + 1);
/* We only support single-subsection segments */
ASSERT(Subsection->SubsectionBase != NULL);
ASSERT(Vad->FirstPrototypePte >= Subsection->SubsectionBase);
ASSERT(Vad->FirstPrototypePte < &Subsection->SubsectionBase[Subsection->PtesInSubsection]);
/* Compute the PTE offset */
PteOffset = (ULONG_PTR)Vpn - Vad->StartingVpn;
PteOffset += Vad->FirstPrototypePte - Subsection->SubsectionBase;
/* Again, we only support single-subsection segments */
ASSERT(PteOffset < 0xF0000000);
ASSERT(PteOffset < Subsection->PtesInSubsection);
/* Return the subsection */
return Subsection;
}
VOID
NTAPI
MiSegmentDelete(IN PSEGMENT Segment)
{
PCONTROL_AREA ControlArea;
SEGMENT_FLAGS SegmentFlags;
PSUBSECTION Subsection;
PMMPTE PointerPte, LastPte, PteForProto;
MMPTE TempPte;
KIRQL OldIrql;
/* Capture data */
SegmentFlags = Segment->SegmentFlags;
ControlArea = Segment->ControlArea;
/* Make sure control area is on the right delete path */
ASSERT(ControlArea->u.Flags.BeingDeleted == 1);
ASSERT(ControlArea->WritableUserReferences == 0);
/* These things are not supported yet */
ASSERT(ControlArea->DereferenceList.Flink == NULL);
ASSERT(!(ControlArea->u.Flags.Image) & !(ControlArea->u.Flags.File));
ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
ASSERT(ControlArea->u.Flags.Rom == 0);
/* Get the subsection and PTEs for this segment */
Subsection = (PSUBSECTION)(ControlArea + 1);
PointerPte = Subsection->SubsectionBase;
LastPte = PointerPte + Segment->NonExtendedPtes;
/* Lock the PFN database */
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
/* Check if the master PTE is invalid */
PteForProto = MiAddressToPte(PointerPte);
if (!PteForProto->u.Hard.Valid)
{
/* Fault it in */
MiMakeSystemAddressValidPfn(PointerPte, OldIrql);
}
/* Loop all the segment PTEs */
while (PointerPte < LastPte)
{
/* Check if it's time to switch master PTEs if we passed a PDE boundary */
if (!((ULONG_PTR)PointerPte & (PD_SIZE - 1)) &&
(PointerPte != Subsection->SubsectionBase))
{
/* Check if the master PTE is invalid */
PteForProto = MiAddressToPte(PointerPte);
if (!PteForProto->u.Hard.Valid)
{
/* Fault it in */
MiMakeSystemAddressValidPfn(PointerPte, OldIrql);
}
}
/* This should be a prototype PTE */
TempPte = *PointerPte;
ASSERT(SegmentFlags.LargePages == 0);
ASSERT(TempPte.u.Hard.Valid == 0);
ASSERT(TempPte.u.Soft.Prototype == 1);
/* Zero the PTE and keep going */
PointerPte->u.Long = 0;
PointerPte++;
}
/* Release the PFN lock */
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
/* Free the structures */
ExFreePool(ControlArea);
ExFreePool(Segment);
}
VOID
NTAPI
MiCheckControlArea(IN PCONTROL_AREA ControlArea,
IN KIRQL OldIrql)
{
BOOLEAN DeleteSegment = FALSE;
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
/* Check if this is the last reference or view */
if (!(ControlArea->NumberOfMappedViews) &&
!(ControlArea->NumberOfSectionReferences))
{
/* There should be no more user references either */
ASSERT(ControlArea->NumberOfUserReferences == 0);
/* Not yet supported */
ASSERT(ControlArea->FilePointer == NULL);
/* The control area is being destroyed */
ControlArea->u.Flags.BeingDeleted = TRUE;
DeleteSegment = TRUE;
}
/* Release the PFN lock */
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
/* Delete the segment if needed */
if (DeleteSegment)
{
/* No more user write references at all */
ASSERT(ControlArea->WritableUserReferences == 0);
MiSegmentDelete(ControlArea->Segment);
}
}
VOID
NTAPI
MiRemoveMappedView(IN PEPROCESS CurrentProcess,
IN PMMVAD Vad)
{
KIRQL OldIrql;
PCONTROL_AREA ControlArea;
/* Get the control area */
ControlArea = Vad->ControlArea;
/* We only support non-extendable, non-image, pagefile-backed regular sections */
ASSERT(Vad->u.VadFlags.VadType == VadNone);
ASSERT(Vad->u2.VadFlags2.ExtendableFile == FALSE);
ASSERT(ControlArea);
ASSERT(ControlArea->FilePointer == NULL);
/* Delete the actual virtual memory pages */
MiDeleteVirtualAddresses(Vad->StartingVpn << PAGE_SHIFT,
(Vad->EndingVpn << PAGE_SHIFT) | (PAGE_SIZE - 1),
Vad);
/* Release the working set */
MiUnlockProcessWorkingSet(CurrentProcess, PsGetCurrentThread());
/* Lock the PFN database */
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
/* Remove references */
ControlArea->NumberOfMappedViews--;
ControlArea->NumberOfUserReferences--;
/* Check if it should be destroyed */
MiCheckControlArea(ControlArea, OldIrql);
}
NTSTATUS
NTAPI
MiMapViewInSystemSpace(IN PVOID Section,
@ -505,7 +687,6 @@ MiMapViewOfDataSection(IN PCONTROL_AREA ControlArea,
/* 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);
@ -553,13 +734,28 @@ MiMapViewOfDataSection(IN PCONTROL_AREA ControlArea,
/* 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));
/* 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));
}
}
else
{
@ -1179,8 +1375,11 @@ NtCreateSection(OUT PHANDLE SectionHandle,
SEC_LARGE_PAGES | SEC_IMAGE | SEC_NOCACHE |
SEC_NO_CHANGE)))
{
DPRINT1("Bogus allocation attribute: %lx\n", AllocationAttributes);
return STATUS_INVALID_PARAMETER_6;
if (!(AllocationAttributes & 1))
{
DPRINT1("Bogus allocation attribute: %lx\n", AllocationAttributes);
return STATUS_INVALID_PARAMETER_6;
}
}
/* Check for no allocation type */

View file

@ -68,6 +68,46 @@ MiMakeSystemAddressValid(IN PVOID PageTableVirtualAddress,
return LockChange;
}
ULONG
NTAPI
MiMakeSystemAddressValidPfn(IN PVOID VirtualAddress,
IN KIRQL OldIrql)
{
NTSTATUS Status;
BOOLEAN LockChange = FALSE;
/* Must be e kernel address */
ASSERT(VirtualAddress > MM_HIGHEST_USER_ADDRESS);
/* Check if the page is valid */
while (!MmIsAddressValid(VirtualAddress))
{
/* Release the PFN database */
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
/* Fault it in */
Status = MmAccessFault(FALSE, VirtualAddress, KernelMode, NULL);
if (!NT_SUCCESS(Status))
{
/* This should not fail */
KeBugCheckEx(KERNEL_DATA_INPAGE_ERROR,
3,
Status,
0,
(ULONG_PTR)VirtualAddress);
}
/* This flag will be useful later when we do better locking */
LockChange = TRUE;
/* Lock the PFN database */
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
}
/* Let caller know what the lock state is */
return LockChange;
}
PFN_NUMBER
NTAPI
MiDeleteSystemPageableVm(IN PMMPTE PointerPte,
@ -169,11 +209,13 @@ VOID
NTAPI
MiDeletePte(IN PMMPTE PointerPte,
IN PVOID VirtualAddress,
IN PEPROCESS CurrentProcess)
IN PEPROCESS CurrentProcess,
IN PMMPTE PrototypePte)
{
PMMPFN Pfn1;
MMPTE TempPte;
PFN_NUMBER PageFrameIndex;
PMMPDE PointerPde;
/* PFN lock must be held */
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
@ -183,39 +225,74 @@ MiDeletePte(IN PMMPTE PointerPte,
/* We only support valid PTEs for now */
ASSERT(TempPte.u.Hard.Valid == 1);
ASSERT(TempPte.u.Soft.Prototype == 0);
ASSERT(TempPte.u.Soft.Transition == 0);
if (TempPte.u.Hard.Valid == 0)
{
/* Invalid PTEs not supported yet */
ASSERT(TempPte.u.Soft.Prototype == 0);
ASSERT(TempPte.u.Soft.Transition == 0);
}
/* Get the PFN entry */
PageFrameIndex = PFN_FROM_PTE(&TempPte);
Pfn1 = MiGetPfnEntry(PageFrameIndex);
/* We don't support deleting prototype PTEs for now */
ASSERT(Pfn1->u3.e1.PrototypePte == 0);
/* Make sure the saved PTE address is valid */
if ((PMMPTE)((ULONG_PTR)Pfn1->PteAddress & ~0x1) != PointerPte)
/* Check if this is a valid, prototype PTE */
if (Pfn1->u3.e1.PrototypePte == 1)
{
/* The PFN entry is illegal, or invalid */
KeBugCheckEx(MEMORY_MANAGEMENT,
0x401,
(ULONG_PTR)PointerPte,
PointerPte->u.Long,
(ULONG_PTR)Pfn1->PteAddress);
/* Get the PDE and make sure it's faulted in */
PointerPde = MiAddressToPde(PointerPte);
if (PointerPde->u.Hard.Valid == 0)
{
#if (_MI_PAGING_LEVELS == 2)
/* Could be paged pool access from a new process -- synchronize the page directories */
if (!NT_SUCCESS(MiCheckPdeForPagedPool(VirtualAddress)))
{
#endif
/* The PDE must be valid at this point */
KeBugCheckEx(MEMORY_MANAGEMENT,
0x61940,
(ULONG_PTR)PointerPte,
PointerPte->u.Long,
(ULONG_PTR)VirtualAddress);
}
#if (_MI_PAGING_LEVELS == 2)
}
#endif
/* FIXME: Drop the reference on the page table. For now, leak it until RosMM is gone */
//MiDecrementShareCount(MiGetPfnEntry(PFN_FROM_PTE(PointerPde)), PFN_FROM_PDE(PointerPde));
/* Drop the share count */
MiDecrementShareCount(Pfn1, PageFrameIndex);
/* No fork yet */
if (PointerPte <= MiHighestUserPte) ASSERT(PrototypePte == Pfn1->PteAddress);
}
else
{
/* Make sure the saved PTE address is valid */
if ((PMMPTE)((ULONG_PTR)Pfn1->PteAddress & ~0x1) != PointerPte)
{
/* The PFN entry is illegal, or invalid */
KeBugCheckEx(MEMORY_MANAGEMENT,
0x401,
(ULONG_PTR)PointerPte,
PointerPte->u.Long,
(ULONG_PTR)Pfn1->PteAddress);
}
/* There should only be 1 shared reference count */
ASSERT(Pfn1->u2.ShareCount == 1);
/* There should only be 1 shared reference count */
ASSERT(Pfn1->u2.ShareCount == 1);
/* FIXME: Drop the reference on the page table. For now, leak it until RosMM is gone */
//MiDecrementShareCount(MiGetPfnEntry(Pfn1->u4.PteFrame), Pfn1->u4.PteFrame);
/* FIXME: Drop the reference on the page table. For now, leak it until RosMM is gone */
//MiDecrementShareCount(MiGetPfnEntry(Pfn1->u4.PteFrame), Pfn1->u4.PteFrame);
/* Mark the PFN for deletion and dereference what should be the last ref */
MI_SET_PFN_DELETED(Pfn1);
MiDecrementShareCount(Pfn1, PageFrameIndex);
/* Mark the PFN for deletion and dereference what should be the last ref */
MI_SET_PFN_DELETED(Pfn1);
MiDecrementShareCount(Pfn1, PageFrameIndex);
/* We should eventually do this */
//CurrentProcess->NumberOfPrivatePages--;
/* We should eventually do this */
//CurrentProcess->NumberOfPrivatePages--;
}
/* Destroy the PTE and flush the TLB */
PointerPte->u.Long = 0;
@ -228,27 +305,34 @@ MiDeleteVirtualAddresses(IN ULONG_PTR Va,
IN ULONG_PTR EndingAddress,
IN PMMVAD Vad)
{
PMMPTE PointerPte, PointerPde;
PMMPTE PointerPte, PointerPde, PrototypePte, LastPrototypePte;
MMPTE TempPte;
PEPROCESS CurrentProcess;
KIRQL OldIrql;
BOOLEAN AddressGap = FALSE;
PSUBSECTION Subsection;
/* Get out if this is a fake VAD, RosMm will free the marea pages */
if ((Vad) && (Vad->u.VadFlags.Spare == 1)) return;
/* Grab the process and PTE/PDE for the address being deleted */
CurrentProcess = PsGetCurrentProcess();
PointerPde = MiAddressToPde(Va);
PointerPte = MiAddressToPte(Va);
/* We usually only get a VAD when it's not a VM address */
if (Vad)
/* Check if this is a section VAD or a VM VAD */
if (!(Vad) || (Vad->u.VadFlags.PrivateMemory) || !(Vad->FirstPrototypePte))
{
/* Get out if this is a fake VAD, RosMm will free the marea pages */
if (Vad->u.VadFlags.Spare == 1) return;
/* At process deletion, we may get a VAD, but it should be a VM VAD */
ASSERT(Vad->u.VadFlags.PrivateMemory);
//ASSERT(Vad->FirstPrototypePte == NULL); memory_area fuckers
/* Don't worry about prototypes */
PrototypePte = LastPrototypePte = NULL;
}
else
{
/* Get the prototype PTE */
PrototypePte = Vad->FirstPrototypePte;
LastPrototypePte = Vad->FirstPrototypePte + 1;
}
/* In all cases, we don't support fork() yet */
ASSERT(CurrentProcess->CloneRoot == NULL);
@ -256,8 +340,11 @@ MiDeleteVirtualAddresses(IN ULONG_PTR Va,
while (TRUE)
{
/* First keep going until we find a valid PDE */
while (PointerPde->u.Long == 0)
while (!PointerPde->u.Long)
{
/* There are gaps in the address space */
AddressGap = TRUE;
/* Still no valid PDE, try the next 4MB (or whatever) */
PointerPde++;
@ -270,7 +357,7 @@ MiDeleteVirtualAddresses(IN ULONG_PTR Va,
}
/* Now check if the PDE is mapped in */
if (PointerPde->u.Hard.Valid == 0)
if (!PointerPde->u.Hard.Valid)
{
/* It isn't, so map it in */
PointerPte = MiPteToAddress(PointerPde);
@ -281,6 +368,26 @@ MiDeleteVirtualAddresses(IN ULONG_PTR Va,
ASSERT(PointerPde->u.Hard.Valid == 1);
ASSERT(Va <= EndingAddress);
/* Check if this is a section VAD with gaps in it */
if ((AddressGap) && (LastPrototypePte))
{
/* We need to skip to the next correct prototype PTE */
PrototypePte = MI_GET_PROTOTYPE_PTE_FOR_VPN(Vad, Va >> PAGE_SHIFT);
/* And we need the subsection to skip to the next last prototype PTE */
Subsection = MiLocateSubsection(Vad, Va >> PAGE_SHIFT);
if (Subsection)
{
/* Found it! */
LastPrototypePte = &Subsection->SubsectionBase[Subsection->PtesInSubsection];
}
else
{
/* No more subsections, we are done with prototype PTEs */
PrototypePte = NULL;
}
}
/* Lock the PFN Database while we delete the PTEs */
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
do
@ -292,11 +399,41 @@ MiDeleteVirtualAddresses(IN ULONG_PTR Va,
/* Check if the PTE is actually mapped in */
if (TempPte.u.Long & 0xFFFFFC01)
{
/* It is, we don't support prototype PTEs for now though */
ASSERT(TempPte.u.Soft.Prototype == 0);
/* Are we dealing with section VAD? */
if ((LastPrototypePte) && (PrototypePte > LastPrototypePte))
{
/* We need to skip to the next correct prototype PTE */
PrototypePte = MI_GET_PROTOTYPE_PTE_FOR_VPN(Vad, Va >> PAGE_SHIFT);
/* And we need the subsection to skip to the next last prototype PTE */
Subsection = MiLocateSubsection(Vad, Va >> PAGE_SHIFT);
if (Subsection)
{
/* Found it! */
LastPrototypePte = &Subsection->SubsectionBase[Subsection->PtesInSubsection];
}
else
{
/* No more subsections, we are done with prototype PTEs */
PrototypePte = NULL;
}
}
/* Delete the PTE proper */
MiDeletePte(PointerPte, (PVOID)Va, CurrentProcess);
/* Check for prototype PTE */
if ((TempPte.u.Hard.Valid == 0) &&
(TempPte.u.Soft.Prototype == 1))
{
/* Just nuke it */
PointerPte->u.Long = 0;
}
else
{
/* Delete the PTE proper */
MiDeletePte(PointerPte,
(PVOID)Va,
CurrentProcess,
PrototypePte);
}
}
else
{
@ -308,6 +445,7 @@ MiDeleteVirtualAddresses(IN ULONG_PTR Va,
/* Update the address and PTE for it */
Va += PAGE_SIZE;
PointerPte++;
PrototypePte++;
/* Making sure the PDE is still valid */
ASSERT(PointerPde->u.Hard.Valid == 1);
@ -323,6 +461,7 @@ MiDeleteVirtualAddresses(IN ULONG_PTR Va,
/* Otherwise, we exited because we hit a new PDE boundary, so start over */
PointerPde = MiAddressToPde(Va);
AddressGap = FALSE;
}
}