mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 20:05:41 +00:00
[NTOS]: Attempt to hackfix MiGetPageProtection to support the case seen in OllyDBG.
[NTOS]: Implement Case C of NtFreeVirtualMemory, which is sometimes seen in some heap logs. The hard part is figuring out the right amount of committed/decommitted pages. Only supports 2-level paging for now as the algorithm is already messy enough. svn path=/trunk/; revision=56515
This commit is contained in:
parent
f067d3a67c
commit
747ae40486
1 changed files with 176 additions and 11 deletions
|
@ -28,6 +28,168 @@ MiProtectVirtualMemory(IN PEPROCESS Process,
|
||||||
|
|
||||||
/* PRIVATE FUNCTIONS **********************************************************/
|
/* PRIVATE FUNCTIONS **********************************************************/
|
||||||
|
|
||||||
|
ULONG
|
||||||
|
NTAPI
|
||||||
|
MiCalculatePageCommitment(IN ULONG_PTR StartingAddress,
|
||||||
|
IN ULONG_PTR EndingAddress,
|
||||||
|
IN PMMVAD Vad,
|
||||||
|
IN PEPROCESS Process)
|
||||||
|
{
|
||||||
|
PMMPTE PointerPte, LastPte, PointerPde;
|
||||||
|
ULONG CommittedPages;
|
||||||
|
|
||||||
|
/* Compute starting and ending PTE and PDE addresses */
|
||||||
|
PointerPde = MiAddressToPde(StartingAddress);
|
||||||
|
PointerPte = MiAddressToPte(StartingAddress);
|
||||||
|
LastPte = MiAddressToPte(EndingAddress);
|
||||||
|
|
||||||
|
/* Handle commited pages first */
|
||||||
|
if (Vad->u.VadFlags.MemCommit == 1)
|
||||||
|
{
|
||||||
|
/* This is a committed VAD, so Assume the whole range is committed */
|
||||||
|
CommittedPages = BYTES_TO_PAGES(EndingAddress - StartingAddress);
|
||||||
|
|
||||||
|
/* Is the PDE demand-zero? */
|
||||||
|
PointerPde = MiAddressToPte(PointerPte);
|
||||||
|
if (PointerPde->u.Long != 0)
|
||||||
|
{
|
||||||
|
/* It is not. Is it valid? */
|
||||||
|
if (PointerPde->u.Hard.Valid == 0)
|
||||||
|
{
|
||||||
|
/* Fault it in */
|
||||||
|
PointerPte = MiPteToAddress(PointerPde);
|
||||||
|
MiMakeSystemAddressValid(PointerPte, Process);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* It is, skip it and move to the next PDE, unless we're done */
|
||||||
|
PointerPde++;
|
||||||
|
PointerPte = MiPteToAddress(PointerPde);
|
||||||
|
if (PointerPte > LastPte) return CommittedPages;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now loop all the PTEs in the range */
|
||||||
|
while (PointerPte <= LastPte)
|
||||||
|
{
|
||||||
|
/* Have we crossed a PDE boundary? */
|
||||||
|
if (MiIsPteOnPdeBoundary(PointerPte))
|
||||||
|
{
|
||||||
|
/* Is this PDE demand zero? */
|
||||||
|
PointerPde = MiAddressToPte(PointerPte);
|
||||||
|
if (PointerPde->u.Long != 0)
|
||||||
|
{
|
||||||
|
/* It isn't -- is it valid? */
|
||||||
|
if (PointerPde->u.Hard.Valid == 0)
|
||||||
|
{
|
||||||
|
/* Nope, fault it in */
|
||||||
|
PointerPte = MiPteToAddress(PointerPde);
|
||||||
|
MiMakeSystemAddressValid(PointerPte, Process);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* It is, skip it and move to the next PDE */
|
||||||
|
PointerPde++;
|
||||||
|
PointerPte = MiPteToAddress(PointerPde);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Is this PTE demand zero? */
|
||||||
|
if (PointerPte->u.Long != 0)
|
||||||
|
{
|
||||||
|
/* It isn't -- is it a decommited, invalid, or faulted PTE? */
|
||||||
|
if ((PointerPte->u.Soft.Protection == MM_DECOMMIT) &&
|
||||||
|
(PointerPte->u.Hard.Valid == 0) &&
|
||||||
|
((PointerPte->u.Soft.Prototype == 0) ||
|
||||||
|
(PointerPte->u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED)))
|
||||||
|
{
|
||||||
|
/* It is, so remove it from the count of commited pages */
|
||||||
|
CommittedPages--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move to the next PTE */
|
||||||
|
PointerPte++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return how many committed pages there still are */
|
||||||
|
return CommittedPages;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is a non-commited VAD, so assume none of it is committed */
|
||||||
|
CommittedPages = 0;
|
||||||
|
|
||||||
|
/* Is the PDE demand-zero? */
|
||||||
|
PointerPde = MiAddressToPte(PointerPte);
|
||||||
|
if (PointerPde->u.Long != 0)
|
||||||
|
{
|
||||||
|
/* It isn't -- is it invalid? */
|
||||||
|
if (PointerPde->u.Hard.Valid == 0)
|
||||||
|
{
|
||||||
|
/* It is, so page it in */
|
||||||
|
PointerPte = MiPteToAddress(PointerPde);
|
||||||
|
MiMakeSystemAddressValid(PointerPte, Process);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* It is, so skip it and move to the next PDE */
|
||||||
|
PointerPde++;
|
||||||
|
PointerPte = MiPteToAddress(PointerPde);
|
||||||
|
if (PointerPte > LastPte) return CommittedPages;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loop all the PTEs in this PDE */
|
||||||
|
while (PointerPte <= LastPte)
|
||||||
|
{
|
||||||
|
/* Have we crossed a PDE boundary? */
|
||||||
|
if (MiIsPteOnPdeBoundary(PointerPte))
|
||||||
|
{
|
||||||
|
/* Is this new PDE demand-zero? */
|
||||||
|
PointerPde = MiAddressToPte(PointerPte);
|
||||||
|
if (PointerPde->u.Long != 0)
|
||||||
|
{
|
||||||
|
/* It isn't. Is it valid? */
|
||||||
|
if (PointerPde->u.Hard.Valid == 0)
|
||||||
|
{
|
||||||
|
/* It isn't, so make it valid */
|
||||||
|
PointerPte = MiPteToAddress(PointerPde);
|
||||||
|
MiMakeSystemAddressValid(PointerPte, Process);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* It is, so skip it and move to the next one */
|
||||||
|
PointerPde++;
|
||||||
|
PointerPte = MiPteToAddress(PointerPde);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Is this PTE demand-zero? */
|
||||||
|
if (PointerPte->u.Long != 0)
|
||||||
|
{
|
||||||
|
/* Nope. Is it a valid, non-decommited, non-paged out PTE? */
|
||||||
|
if ((PointerPte->u.Soft.Protection != MM_DECOMMIT) ||
|
||||||
|
(PointerPte->u.Hard.Valid == 1) ||
|
||||||
|
((PointerPte->u.Soft.Prototype == 1) &&
|
||||||
|
(PointerPte->u.Soft.PageFileHigh != MI_PTE_LOOKUP_NEEDED)))
|
||||||
|
{
|
||||||
|
/* It is! So we'll treat this as a committed page */
|
||||||
|
CommittedPages++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move to the next PTE */
|
||||||
|
PointerPte++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return how many committed pages we found in this VAD */
|
||||||
|
return CommittedPages;
|
||||||
|
}
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
NTAPI
|
NTAPI
|
||||||
MiMakeSystemAddressValid(IN PVOID PageTableVirtualAddress,
|
MiMakeSystemAddressValid(IN PVOID PageTableVirtualAddress,
|
||||||
|
@ -1118,18 +1280,19 @@ MiGetPageProtection(IN PMMPTE PointerPte)
|
||||||
|
|
||||||
/* If we get here, the PTE is valid, so look up the page in PFN database */
|
/* If we get here, the PTE is valid, so look up the page in PFN database */
|
||||||
Pfn = MiGetPfnEntry(TempPte.u.Hard.PageFrameNumber);
|
Pfn = MiGetPfnEntry(TempPte.u.Hard.PageFrameNumber);
|
||||||
|
|
||||||
if (!Pfn->u3.e1.PrototypePte)
|
if (!Pfn->u3.e1.PrototypePte)
|
||||||
{
|
{
|
||||||
/* Return protection of the original pte */
|
/* Return protection of the original pte */
|
||||||
|
ASSERT(Pfn->u4.AweAllocation == 0);
|
||||||
return MmProtectToValue[Pfn->OriginalPte.u.Soft.Protection];
|
return MmProtectToValue[Pfn->OriginalPte.u.Soft.Protection];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is hardware PTE */
|
/* This is software PTE */
|
||||||
UNIMPLEMENTED;
|
DPRINT1("Prototype PTE: %lx %p\n", TempPte.u.Hard.PageFrameNumber, Pfn);
|
||||||
ASSERT(FALSE);
|
DPRINT1("VA: %p\n", MiPteToAddress(&TempPte));
|
||||||
|
DPRINT1("Mask: %lx\n", TempPte.u.Soft.Protection);
|
||||||
return PAGE_NOACCESS;
|
DPRINT1("Mask2: %lx\n", Pfn->OriginalPte.u.Soft.Protection);
|
||||||
|
return MmProtectToValue[TempPte.u.Soft.Protection];
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
|
@ -4049,11 +4212,13 @@ NtFreeVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
// and then change the ending address of the VAD to be a bit
|
// and then change the ending address of the VAD to be a bit
|
||||||
// smaller.
|
// smaller.
|
||||||
//
|
//
|
||||||
// NOT YET IMPLEMENTED IN ARM3.
|
MiLockWorkingSet(CurrentThread, AddressSpace);
|
||||||
//
|
CommitReduction = MiCalculatePageCommitment(StartingAddress,
|
||||||
DPRINT1("Case C not handled\n");
|
EndingAddress,
|
||||||
Status = STATUS_FREE_VM_NOT_AT_BASE;
|
Vad,
|
||||||
goto FailPath;
|
Process);
|
||||||
|
Vad->u.VadFlags.CommitCharge -= CommitReduction;
|
||||||
|
Vad->EndingVpn = ((ULONG_PTR)StartingAddress - 1) >> PAGE_SHIFT;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue