mirror of
https://github.com/reactos/reactos.git
synced 2025-06-12 10:38:29 +00:00
[NTOSKRNL]: Implement correct locking and unlocking of the working set, one of the biggest blunders in ARM3 so far.
[NTOSKRNL]: Implement MiDereferenceControlArea to avoid leaking CAs in failure cases. svn path=/trunk/; revision=57228
This commit is contained in:
parent
5b9e315fb7
commit
5547667b67
5 changed files with 239 additions and 64 deletions
|
@ -1718,17 +1718,13 @@ VOID
|
||||||
MmLockAddressSpace(PMMSUPPORT AddressSpace)
|
MmLockAddressSpace(PMMSUPPORT AddressSpace)
|
||||||
{
|
{
|
||||||
KeAcquireGuardedMutex(&CONTAINING_RECORD(AddressSpace, EPROCESS, Vm)->AddressCreationLock);
|
KeAcquireGuardedMutex(&CONTAINING_RECORD(AddressSpace, EPROCESS, Vm)->AddressCreationLock);
|
||||||
//ASSERT(Thread->OwnsProcessAddressSpaceExclusive == 0);
|
|
||||||
//Thread->OwnsProcessAddressSpaceExclusive = TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCEINLINE
|
FORCEINLINE
|
||||||
VOID
|
VOID
|
||||||
MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
|
MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
|
||||||
{
|
{
|
||||||
//ASSERT(Thread->OwnsProcessAddressSpaceExclusive == 1);
|
|
||||||
KeReleaseGuardedMutex(&CONTAINING_RECORD(AddressSpace, EPROCESS, Vm)->AddressCreationLock);
|
KeReleaseGuardedMutex(&CONTAINING_RECORD(AddressSpace, EPROCESS, Vm)->AddressCreationLock);
|
||||||
//Thread->OwnsProcessAddressSpaceExclusive = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCEINLINE
|
FORCEINLINE
|
||||||
|
|
|
@ -1041,6 +1041,14 @@ BOOLEAN
|
||||||
MI_WS_OWNER(IN PEPROCESS Process)
|
MI_WS_OWNER(IN PEPROCESS Process)
|
||||||
{
|
{
|
||||||
/* Check if this process is the owner, and that the thread owns the WS */
|
/* Check if this process is the owner, and that the thread owns the WS */
|
||||||
|
if (PsGetCurrentThread()->OwnsProcessWorkingSetExclusive == 0)
|
||||||
|
{
|
||||||
|
DPRINT1("Thread: %p is not an owner\n", PsGetCurrentThread());
|
||||||
|
}
|
||||||
|
if (KeGetCurrentThread()->ApcState.Process != &Process->Pcb)
|
||||||
|
{
|
||||||
|
DPRINT1("Current thread %p is attached to another process %p\n", PsGetCurrentThread(), Process);
|
||||||
|
}
|
||||||
return ((KeGetCurrentThread()->ApcState.Process == &Process->Pcb) &&
|
return ((KeGetCurrentThread()->ApcState.Process == &Process->Pcb) &&
|
||||||
((PsGetCurrentThread()->OwnsProcessWorkingSetExclusive) ||
|
((PsGetCurrentThread()->OwnsProcessWorkingSetExclusive) ||
|
||||||
(PsGetCurrentThread()->OwnsProcessWorkingSetShared)));
|
(PsGetCurrentThread()->OwnsProcessWorkingSetShared)));
|
||||||
|
@ -1083,6 +1091,13 @@ MiDecrementReferenceCount(
|
||||||
IN PFN_NUMBER PageFrameIndex
|
IN PFN_NUMBER PageFrameIndex
|
||||||
);
|
);
|
||||||
|
|
||||||
|
FORCEINLINE
|
||||||
|
BOOLEAN
|
||||||
|
MI_IS_WS_UNSAFE(IN PEPROCESS Process)
|
||||||
|
{
|
||||||
|
return (Process->Vm.Flags.AcquiredUnsafe == TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Locks the working set for the given process
|
// Locks the working set for the given process
|
||||||
//
|
//
|
||||||
|
@ -1099,12 +1114,57 @@ MiLockProcessWorkingSet(IN PEPROCESS Process,
|
||||||
KeEnterGuardedRegion();
|
KeEnterGuardedRegion();
|
||||||
ASSERT(!MM_ANY_WS_LOCK_HELD(Thread));
|
ASSERT(!MM_ANY_WS_LOCK_HELD(Thread));
|
||||||
|
|
||||||
/* FIXME: Actually lock it (we can't because Vm is used by MAREAs) */
|
/* Lock the working set */
|
||||||
|
ExAcquirePushLockExclusive(&Process->Vm.WorkingSetMutex);
|
||||||
|
|
||||||
/* FIXME: This also can't be checked because Vm is used by MAREAs) */
|
/* Now claim that we own the lock */
|
||||||
//ASSERT(Process->Vm.Flags.AcquiredUnsafe == 0);
|
ASSERT(!MI_IS_WS_UNSAFE(Process));
|
||||||
|
ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE);
|
||||||
|
Thread->OwnsProcessWorkingSetExclusive = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Okay, now we can own it exclusively */
|
FORCEINLINE
|
||||||
|
VOID
|
||||||
|
MiLockProcessWorkingSetShared(IN PEPROCESS Process,
|
||||||
|
IN PETHREAD Thread)
|
||||||
|
{
|
||||||
|
/* Shouldn't already be owning the process working set */
|
||||||
|
ASSERT(Thread->OwnsProcessWorkingSetShared == FALSE);
|
||||||
|
ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE);
|
||||||
|
|
||||||
|
/* Block APCs, make sure that still nothing is already held */
|
||||||
|
KeEnterGuardedRegion();
|
||||||
|
ASSERT(!MM_ANY_WS_LOCK_HELD(Thread));
|
||||||
|
|
||||||
|
/* Lock the working set */
|
||||||
|
ExAcquirePushLockShared(&Process->Vm.WorkingSetMutex);
|
||||||
|
|
||||||
|
/* Now claim that we own the lock */
|
||||||
|
ASSERT(!MI_IS_WS_UNSAFE(Process));
|
||||||
|
ASSERT(Thread->OwnsProcessWorkingSetShared == FALSE);
|
||||||
|
ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE);
|
||||||
|
Thread->OwnsProcessWorkingSetShared = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE
|
||||||
|
VOID
|
||||||
|
MiLockProcessWorkingSetUnsafe(IN PEPROCESS Process,
|
||||||
|
IN PETHREAD Thread)
|
||||||
|
{
|
||||||
|
/* Shouldn't already be owning the process working set */
|
||||||
|
ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE);
|
||||||
|
|
||||||
|
/* APCs must be blocked, make sure that still nothing is already held */
|
||||||
|
ASSERT(KeAreAllApcsDisabled() == TRUE);
|
||||||
|
ASSERT(!MM_ANY_WS_LOCK_HELD(Thread));
|
||||||
|
|
||||||
|
/* Lock the working set */
|
||||||
|
ExAcquirePushLockExclusive(&Process->Vm.WorkingSetMutex);
|
||||||
|
|
||||||
|
/* Now claim that we own the lock */
|
||||||
|
ASSERT(!MI_IS_WS_UNSAFE(Process));
|
||||||
|
Process->Vm.Flags.AcquiredUnsafe = 1;
|
||||||
|
ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE);
|
||||||
Thread->OwnsProcessWorkingSetExclusive = TRUE;
|
Thread->OwnsProcessWorkingSetExclusive = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1116,21 +1176,45 @@ VOID
|
||||||
MiUnlockProcessWorkingSet(IN PEPROCESS Process,
|
MiUnlockProcessWorkingSet(IN PEPROCESS Process,
|
||||||
IN PETHREAD Thread)
|
IN PETHREAD Thread)
|
||||||
{
|
{
|
||||||
/* Make sure this process really is owner, and it was a safe acquisition */
|
/* Make sure we are the owner of a safe acquisition */
|
||||||
ASSERT(MI_WS_OWNER(Process));
|
ASSERT(MI_WS_OWNER(Process));
|
||||||
/* This can't be checked because Vm is used by MAREAs) */
|
ASSERT(!MI_IS_WS_UNSAFE(Process));
|
||||||
//ASSERT(Process->Vm.Flags.AcquiredUnsafe == 0);
|
|
||||||
|
|
||||||
/* The thread doesn't own it anymore */
|
/* The thread doesn't own it anymore */
|
||||||
ASSERT(Thread->OwnsProcessWorkingSetExclusive == TRUE);
|
ASSERT(Thread->OwnsProcessWorkingSetExclusive == TRUE);
|
||||||
Thread->OwnsProcessWorkingSetExclusive = FALSE;
|
Thread->OwnsProcessWorkingSetExclusive = FALSE;
|
||||||
|
|
||||||
/* FIXME: Actually release it (we can't because Vm is used by MAREAs) */
|
/* Release the lock and re-enable APCs */
|
||||||
|
ExReleasePushLockExclusive(&Process->Vm.WorkingSetMutex);
|
||||||
/* Unblock APCs */
|
|
||||||
KeLeaveGuardedRegion();
|
KeLeaveGuardedRegion();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Unlocks the working set for the given process
|
||||||
|
//
|
||||||
|
FORCEINLINE
|
||||||
|
VOID
|
||||||
|
MiUnlockProcessWorkingSetUnsafe(IN PEPROCESS Process,
|
||||||
|
IN PETHREAD Thread)
|
||||||
|
{
|
||||||
|
/* Make sure we are the owner of an unsafe acquisition */
|
||||||
|
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
|
||||||
|
ASSERT(KeAreAllApcsDisabled() == TRUE);
|
||||||
|
ASSERT(MI_WS_OWNER(Process));
|
||||||
|
ASSERT(MI_IS_WS_UNSAFE(Process));
|
||||||
|
|
||||||
|
/* No longer unsafe */
|
||||||
|
Process->Vm.Flags.AcquiredUnsafe = 0;
|
||||||
|
|
||||||
|
/* The thread doesn't own it anymore */
|
||||||
|
ASSERT(Thread->OwnsProcessWorkingSetExclusive == TRUE);
|
||||||
|
Thread->OwnsProcessWorkingSetExclusive = FALSE;
|
||||||
|
|
||||||
|
/* Release the lock but don't touch APC state */
|
||||||
|
ExReleasePushLockExclusive(&Process->Vm.WorkingSetMutex);
|
||||||
|
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Locks the working set
|
// Locks the working set
|
||||||
//
|
//
|
||||||
|
@ -1148,7 +1232,8 @@ MiLockWorkingSet(IN PETHREAD Thread,
|
||||||
/* Thread shouldn't already be owning something */
|
/* Thread shouldn't already be owning something */
|
||||||
ASSERT(!MM_ANY_WS_LOCK_HELD(Thread));
|
ASSERT(!MM_ANY_WS_LOCK_HELD(Thread));
|
||||||
|
|
||||||
/* FIXME: Actually lock it (we can't because Vm is used by MAREAs) */
|
/* Lock this working set */
|
||||||
|
ExAcquirePushLockExclusive(&WorkingSet->WorkingSetMutex);
|
||||||
|
|
||||||
/* Which working set is this? */
|
/* Which working set is this? */
|
||||||
if (WorkingSet == &MmSystemCacheWs)
|
if (WorkingSet == &MmSystemCacheWs)
|
||||||
|
@ -1208,12 +1293,68 @@ MiUnlockWorkingSet(IN PETHREAD Thread,
|
||||||
Thread->OwnsProcessWorkingSetExclusive = FALSE;
|
Thread->OwnsProcessWorkingSetExclusive = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: Actually release it (we can't because Vm is used by MAREAs) */
|
/* Release the working set lock */
|
||||||
|
ExReleasePushLockExclusive(&WorkingSet->WorkingSetMutex);
|
||||||
|
|
||||||
/* Unblock APCs */
|
/* Unblock APCs */
|
||||||
KeLeaveGuardedRegion();
|
KeLeaveGuardedRegion();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FORCEINLINE
|
||||||
|
VOID
|
||||||
|
MiUnlockProcessWorkingSetForFault(IN PEPROCESS Process,
|
||||||
|
IN PETHREAD Thread,
|
||||||
|
IN BOOLEAN Safe,
|
||||||
|
IN BOOLEAN Shared)
|
||||||
|
{
|
||||||
|
ASSERT(MI_WS_OWNER(Process));
|
||||||
|
|
||||||
|
/* Check if the current owner is unsafe */
|
||||||
|
if (MI_IS_WS_UNSAFE(Process))
|
||||||
|
{
|
||||||
|
/* Release unsafely */
|
||||||
|
MiUnlockProcessWorkingSetUnsafe(Process, Thread);
|
||||||
|
Safe = FALSE;
|
||||||
|
Shared = FALSE;
|
||||||
|
}
|
||||||
|
else if (Thread->OwnsProcessWorkingSetExclusive == 1)
|
||||||
|
{
|
||||||
|
/* Owner is safe and exclusive, release normally */
|
||||||
|
MiUnlockProcessWorkingSet(Process, Thread);
|
||||||
|
Safe = TRUE;
|
||||||
|
Shared = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Owner is shared (implies safe), release normally */
|
||||||
|
ASSERT(FALSE);
|
||||||
|
Safe = TRUE;
|
||||||
|
Shared = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE
|
||||||
|
VOID
|
||||||
|
MiLockProcessWorkingSetForFault(IN PEPROCESS Process,
|
||||||
|
IN PETHREAD Thread,
|
||||||
|
IN BOOLEAN Safe,
|
||||||
|
IN BOOLEAN Shared)
|
||||||
|
{
|
||||||
|
ASSERT(Shared == FALSE);
|
||||||
|
|
||||||
|
/* Check if this was a safe lock or not */
|
||||||
|
if (Safe)
|
||||||
|
{
|
||||||
|
/* Reacquire safely */
|
||||||
|
MiLockProcessWorkingSet(Process, Thread);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Reacquire unsafely */
|
||||||
|
MiLockProcessWorkingSetUnsafe(Process, Thread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Returns the ProtoPTE inside a VAD for the given VPN
|
// Returns the ProtoPTE inside a VAD for the given VPN
|
||||||
//
|
//
|
||||||
|
|
|
@ -135,7 +135,7 @@ MiCreatePebOrTeb(IN PEPROCESS Process,
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
/* Pretend as if we own the working set */
|
/* Pretend as if we own the working set */
|
||||||
MiLockProcessWorkingSet(Process, Thread);
|
MiLockProcessWorkingSetUnsafe(Process, Thread);
|
||||||
|
|
||||||
/* Insert the VAD */
|
/* Insert the VAD */
|
||||||
ASSERT(Vad->EndingVpn >= Vad->StartingVpn);
|
ASSERT(Vad->EndingVpn >= Vad->StartingVpn);
|
||||||
|
@ -147,7 +147,7 @@ MiCreatePebOrTeb(IN PEPROCESS Process,
|
||||||
MiInsertNode(&Process->VadRoot, (PVOID)Vad, Parent, Result);
|
MiInsertNode(&Process->VadRoot, (PVOID)Vad, Parent, Result);
|
||||||
|
|
||||||
/* Release the working set */
|
/* Release the working set */
|
||||||
MiUnlockProcessWorkingSet(Process, Thread);
|
MiUnlockProcessWorkingSetUnsafe(Process, Thread);
|
||||||
|
|
||||||
/* Release the address space lock */
|
/* Release the address space lock */
|
||||||
KeReleaseGuardedMutex(&Process->AddressCreationLock);
|
KeReleaseGuardedMutex(&Process->AddressCreationLock);
|
||||||
|
@ -195,7 +195,7 @@ MmDeleteTeb(IN PEPROCESS Process,
|
||||||
ASSERT(Vad->u2.VadFlags2.MultipleSecured == FALSE);
|
ASSERT(Vad->u2.VadFlags2.MultipleSecured == FALSE);
|
||||||
|
|
||||||
/* Lock the working set */
|
/* Lock the working set */
|
||||||
MiLockProcessWorkingSet(Process, Thread);
|
MiLockProcessWorkingSetUnsafe(Process, Thread);
|
||||||
|
|
||||||
/* Remove this VAD from the tree */
|
/* Remove this VAD from the tree */
|
||||||
ASSERT(VadTree->NumberGenericTableElements >= 1);
|
ASSERT(VadTree->NumberGenericTableElements >= 1);
|
||||||
|
@ -205,7 +205,7 @@ MmDeleteTeb(IN PEPROCESS Process,
|
||||||
MiDeleteVirtualAddresses((ULONG_PTR)Teb, TebEnd, NULL);
|
MiDeleteVirtualAddresses((ULONG_PTR)Teb, TebEnd, NULL);
|
||||||
|
|
||||||
/* Release the working set */
|
/* Release the working set */
|
||||||
MiUnlockProcessWorkingSet(Process, Thread);
|
MiUnlockProcessWorkingSetUnsafe(Process, Thread);
|
||||||
|
|
||||||
/* Remove the VAD */
|
/* Remove the VAD */
|
||||||
ExFreePool(Vad);
|
ExFreePool(Vad);
|
||||||
|
@ -1338,9 +1338,11 @@ MmCleanProcessAddressSpace(IN PEPROCESS Process)
|
||||||
|
|
||||||
/* Lock the process address space from changes */
|
/* Lock the process address space from changes */
|
||||||
MmLockAddressSpace(&Process->Vm);
|
MmLockAddressSpace(&Process->Vm);
|
||||||
|
MiLockProcessWorkingSetUnsafe(Process, Thread);
|
||||||
|
|
||||||
/* VM is deleted now */
|
/* VM is deleted now */
|
||||||
Process->VmDeleted = TRUE;
|
Process->VmDeleted = TRUE;
|
||||||
|
MiUnlockProcessWorkingSetUnsafe(Process, Thread);
|
||||||
|
|
||||||
/* Enumerate the VADs */
|
/* Enumerate the VADs */
|
||||||
VadTree = &Process->VadRoot;
|
VadTree = &Process->VadRoot;
|
||||||
|
@ -1350,7 +1352,7 @@ MmCleanProcessAddressSpace(IN PEPROCESS Process)
|
||||||
Vad = (PMMVAD)VadTree->BalancedRoot.RightChild;
|
Vad = (PMMVAD)VadTree->BalancedRoot.RightChild;
|
||||||
|
|
||||||
/* Lock the working set */
|
/* Lock the working set */
|
||||||
MiLockProcessWorkingSet(Process, Thread);
|
MiLockProcessWorkingSetUnsafe(Process, Thread);
|
||||||
|
|
||||||
/* Remove this VAD from the tree */
|
/* Remove this VAD from the tree */
|
||||||
ASSERT(VadTree->NumberGenericTableElements >= 1);
|
ASSERT(VadTree->NumberGenericTableElements >= 1);
|
||||||
|
@ -1373,7 +1375,7 @@ MmCleanProcessAddressSpace(IN PEPROCESS Process)
|
||||||
Vad);
|
Vad);
|
||||||
|
|
||||||
/* Release the working set */
|
/* Release the working set */
|
||||||
MiUnlockProcessWorkingSet(Process, Thread);
|
MiUnlockProcessWorkingSetUnsafe(Process, Thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip ARM3 fake VADs, they'll be freed by MmDeleteProcessAddresSpace */
|
/* Skip ARM3 fake VADs, they'll be freed by MmDeleteProcessAddresSpace */
|
||||||
|
@ -1388,9 +1390,17 @@ MmCleanProcessAddressSpace(IN PEPROCESS Process)
|
||||||
ExFreePool(Vad);
|
ExFreePool(Vad);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Lock the working set */
|
||||||
|
MiLockProcessWorkingSetUnsafe(Process, Thread);
|
||||||
|
ASSERT(Process->CloneRoot == NULL);
|
||||||
|
ASSERT(Process->PhysicalVadRoot == NULL);
|
||||||
|
|
||||||
/* Delete the shared user data section */
|
/* Delete the shared user data section */
|
||||||
MiDeleteVirtualAddresses(USER_SHARED_DATA, USER_SHARED_DATA, NULL);
|
MiDeleteVirtualAddresses(USER_SHARED_DATA, USER_SHARED_DATA, NULL);
|
||||||
|
|
||||||
|
/* Release the working set */
|
||||||
|
MiUnlockProcessWorkingSetUnsafe(Process, Thread);
|
||||||
|
|
||||||
/* Release the address space */
|
/* Release the address space */
|
||||||
MmUnlockAddressSpace(&Process->Vm);
|
MmUnlockAddressSpace(&Process->Vm);
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,22 +84,22 @@ CHAR MmUserProtectionToMask2[16] =
|
||||||
ULONG MmCompatibleProtectionMask[8] =
|
ULONG MmCompatibleProtectionMask[8] =
|
||||||
{
|
{
|
||||||
PAGE_NOACCESS,
|
PAGE_NOACCESS,
|
||||||
|
|
||||||
PAGE_NOACCESS | PAGE_READONLY | PAGE_WRITECOPY,
|
PAGE_NOACCESS | PAGE_READONLY | PAGE_WRITECOPY,
|
||||||
|
|
||||||
PAGE_NOACCESS | PAGE_EXECUTE,
|
PAGE_NOACCESS | PAGE_EXECUTE,
|
||||||
|
|
||||||
PAGE_NOACCESS | PAGE_READONLY | PAGE_WRITECOPY | PAGE_EXECUTE |
|
PAGE_NOACCESS | PAGE_READONLY | PAGE_WRITECOPY | PAGE_EXECUTE |
|
||||||
PAGE_EXECUTE_READ,
|
PAGE_EXECUTE_READ,
|
||||||
|
|
||||||
PAGE_NOACCESS | PAGE_READONLY | PAGE_WRITECOPY | PAGE_READWRITE,
|
PAGE_NOACCESS | PAGE_READONLY | PAGE_WRITECOPY | PAGE_READWRITE,
|
||||||
|
|
||||||
PAGE_NOACCESS | PAGE_READONLY | PAGE_WRITECOPY,
|
PAGE_NOACCESS | PAGE_READONLY | PAGE_WRITECOPY,
|
||||||
|
|
||||||
PAGE_NOACCESS | PAGE_READONLY | PAGE_WRITECOPY | PAGE_READWRITE |
|
PAGE_NOACCESS | PAGE_READONLY | PAGE_WRITECOPY | PAGE_READWRITE |
|
||||||
PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE |
|
PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE |
|
||||||
PAGE_EXECUTE_WRITECOPY,
|
PAGE_EXECUTE_WRITECOPY,
|
||||||
|
|
||||||
PAGE_NOACCESS | PAGE_READONLY | PAGE_WRITECOPY | PAGE_EXECUTE |
|
PAGE_NOACCESS | PAGE_READONLY | PAGE_WRITECOPY | PAGE_EXECUTE |
|
||||||
PAGE_EXECUTE_READ | PAGE_EXECUTE_WRITECOPY
|
PAGE_EXECUTE_READ | PAGE_EXECUTE_WRITECOPY
|
||||||
};
|
};
|
||||||
|
@ -711,6 +711,23 @@ MiCheckControlArea(IN PCONTROL_AREA ControlArea,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
MiDereferenceControlArea(IN PCONTROL_AREA ControlArea)
|
||||||
|
{
|
||||||
|
KIRQL OldIrql;
|
||||||
|
|
||||||
|
/* Lock the PFN database */
|
||||||
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
|
|
||||||
|
/* Drop reference counts */
|
||||||
|
ControlArea->NumberOfMappedViews--;
|
||||||
|
ControlArea->NumberOfUserReferences--;
|
||||||
|
|
||||||
|
/* Check if it's time to delete the CA. This releases the lock */
|
||||||
|
MiCheckControlArea(ControlArea, OldIrql);
|
||||||
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
MiRemoveMappedView(IN PEPROCESS CurrentProcess,
|
MiRemoveMappedView(IN PEPROCESS CurrentProcess,
|
||||||
|
@ -718,6 +735,7 @@ MiRemoveMappedView(IN PEPROCESS CurrentProcess,
|
||||||
{
|
{
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
PCONTROL_AREA ControlArea;
|
PCONTROL_AREA ControlArea;
|
||||||
|
PETHREAD CurrentThread = PsGetCurrentThread();
|
||||||
|
|
||||||
/* Get the control area */
|
/* Get the control area */
|
||||||
ControlArea = Vad->ControlArea;
|
ControlArea = Vad->ControlArea;
|
||||||
|
@ -734,7 +752,7 @@ MiRemoveMappedView(IN PEPROCESS CurrentProcess,
|
||||||
Vad);
|
Vad);
|
||||||
|
|
||||||
/* Release the working set */
|
/* Release the working set */
|
||||||
MiUnlockProcessWorkingSet(CurrentProcess, PsGetCurrentThread());
|
MiUnlockProcessWorkingSetUnsafe(CurrentProcess, CurrentThread);
|
||||||
|
|
||||||
/* Lock the PFN database */
|
/* Lock the PFN database */
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
|
@ -760,6 +778,8 @@ MiUnmapViewOfSection(IN PEPROCESS Process,
|
||||||
PVOID DbgBase = NULL;
|
PVOID DbgBase = NULL;
|
||||||
SIZE_T RegionSize;
|
SIZE_T RegionSize;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
PETHREAD CurrentThread = PsGetCurrentThread();
|
||||||
|
PEPROCESS CurrentProcess = PsGetCurrentProcess();
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
/* Check for Mm Region */
|
/* Check for Mm Region */
|
||||||
|
@ -771,7 +791,7 @@ MiUnmapViewOfSection(IN PEPROCESS Process,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if we should attach to the process */
|
/* Check if we should attach to the process */
|
||||||
if (PsGetCurrentProcess() != Process)
|
if (CurrentProcess != Process)
|
||||||
{
|
{
|
||||||
/* The process is different, do an attach */
|
/* The process is different, do an attach */
|
||||||
KeStackAttachProcess(&Process->Pcb, &ApcState);
|
KeStackAttachProcess(&Process->Pcb, &ApcState);
|
||||||
|
@ -837,13 +857,13 @@ MiUnmapViewOfSection(IN PEPROCESS Process,
|
||||||
/* FIXME: Remove VAD charges */
|
/* FIXME: Remove VAD charges */
|
||||||
|
|
||||||
/* Lock the working set */
|
/* Lock the working set */
|
||||||
MiLockWorkingSet(PsGetCurrentThread(), &Process->Vm);
|
MiLockProcessWorkingSetUnsafe(Process, CurrentThread);
|
||||||
|
|
||||||
/* Remove the VAD */
|
/* Remove the VAD */
|
||||||
ASSERT(Process->VadRoot.NumberGenericTableElements >= 1);
|
ASSERT(Process->VadRoot.NumberGenericTableElements >= 1);
|
||||||
MiRemoveNode((PMMADDRESS_NODE)Vad, &Process->VadRoot);
|
MiRemoveNode((PMMADDRESS_NODE)Vad, &Process->VadRoot);
|
||||||
|
|
||||||
/* Remove the PTEs for this view */
|
/* Remove the PTEs for this view, which also releases the working set lock */
|
||||||
MiRemoveMappedView(Process, Vad);
|
MiRemoveMappedView(Process, Vad);
|
||||||
|
|
||||||
/* FIXME: Remove commitment */
|
/* FIXME: Remove commitment */
|
||||||
|
@ -1205,7 +1225,8 @@ MiMapViewOfDataSection(IN PCONTROL_AREA ControlArea,
|
||||||
&Process->VadRoot))
|
&Process->VadRoot))
|
||||||
{
|
{
|
||||||
DPRINT1("Conflict with SEC_BASED or manually based section!\n");
|
DPRINT1("Conflict with SEC_BASED or manually based section!\n");
|
||||||
return STATUS_CONFLICTING_ADDRESSES; // FIXME: CA Leak
|
MiDereferenceControlArea(ControlArea);
|
||||||
|
return STATUS_CONFLICTING_ADDRESSES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1213,7 +1234,11 @@ MiMapViewOfDataSection(IN PCONTROL_AREA ControlArea,
|
||||||
/* FIXME: we are allocating a LONG VAD for ReactOS compatibility only */
|
/* FIXME: we are allocating a LONG VAD for ReactOS compatibility only */
|
||||||
ASSERT((AllocationType & MEM_RESERVE) == 0); /* ARM3 does not support this */
|
ASSERT((AllocationType & MEM_RESERVE) == 0); /* ARM3 does not support this */
|
||||||
Vad = ExAllocatePoolWithTag(NonPagedPool, sizeof(MMVAD_LONG), 'ldaV');
|
Vad = ExAllocatePoolWithTag(NonPagedPool, sizeof(MMVAD_LONG), 'ldaV');
|
||||||
if (!Vad) return STATUS_INSUFFICIENT_RESOURCES; /* FIXME: CA Leak */
|
if (!Vad)
|
||||||
|
{
|
||||||
|
MiDereferenceControlArea(ControlArea);
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
RtlZeroMemory(Vad, sizeof(MMVAD_LONG));
|
RtlZeroMemory(Vad, sizeof(MMVAD_LONG));
|
||||||
Vad->u4.Banked = (PVOID)0xDEADBABE;
|
Vad->u4.Banked = (PVOID)0xDEADBABE;
|
||||||
|
|
||||||
|
@ -1244,13 +1269,13 @@ MiMapViewOfDataSection(IN PCONTROL_AREA ControlArea,
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
/* Pretend as if we own the working set */
|
/* Pretend as if we own the working set */
|
||||||
MiLockProcessWorkingSet(Process, Thread);
|
MiLockProcessWorkingSetUnsafe(Process, Thread);
|
||||||
|
|
||||||
/* Insert the VAD */
|
/* Insert the VAD */
|
||||||
MiInsertVad((PMMVAD)Vad, Process);
|
MiInsertVad((PMMVAD)Vad, Process);
|
||||||
|
|
||||||
/* Release the working set */
|
/* Release the working set */
|
||||||
MiUnlockProcessWorkingSet(Process, Thread);
|
MiUnlockProcessWorkingSetUnsafe(Process, Thread);
|
||||||
|
|
||||||
/* Windows stores this for accounting purposes, do so as well */
|
/* Windows stores this for accounting purposes, do so as well */
|
||||||
if (!Segment->u2.FirstMappedVa) Segment->u2.FirstMappedVa = (PVOID)StartAddress;
|
if (!Segment->u2.FirstMappedVa) Segment->u2.FirstMappedVa = (PVOID)StartAddress;
|
||||||
|
@ -1797,7 +1822,7 @@ MiSetProtectionOnSection(IN PEPROCESS Process,
|
||||||
PMMPFN Pfn1;
|
PMMPFN Pfn1;
|
||||||
ULONG ProtectionMask, QuotaCharge = 0;
|
ULONG ProtectionMask, QuotaCharge = 0;
|
||||||
PUSHORT UsedPageTableEntries;
|
PUSHORT UsedPageTableEntries;
|
||||||
//PETHREAD Thread = PsGetCurrentThread();
|
PETHREAD Thread = PsGetCurrentThread();
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -1829,7 +1854,7 @@ MiSetProtectionOnSection(IN PEPROCESS Process,
|
||||||
//
|
//
|
||||||
// Get the PTE and PDE for the address, as well as the final PTE
|
// Get the PTE and PDE for the address, as well as the final PTE
|
||||||
//
|
//
|
||||||
//MiLockProcessWorkingSet(Thread, Process);
|
MiLockProcessWorkingSetUnsafe(Process, Thread);
|
||||||
PointerPde = MiAddressToPde(StartingAddress);
|
PointerPde = MiAddressToPde(StartingAddress);
|
||||||
PointerPte = MiAddressToPte(StartingAddress);
|
PointerPte = MiAddressToPte(StartingAddress);
|
||||||
LastPte = MiAddressToPte(EndingAddress);
|
LastPte = MiAddressToPte(EndingAddress);
|
||||||
|
@ -1943,7 +1968,7 @@ MiSetProtectionOnSection(IN PEPROCESS Process,
|
||||||
//
|
//
|
||||||
// Unlock the working set and update quota charges if needed, then return
|
// Unlock the working set and update quota charges if needed, then return
|
||||||
//
|
//
|
||||||
//MiUnlockProcessWorkingSet(Thread, Process);
|
MiUnlockProcessWorkingSetUnsafe(Process, Thread);
|
||||||
if ((QuotaCharge > 0) && (!DontCharge))
|
if ((QuotaCharge > 0) && (!DontCharge))
|
||||||
{
|
{
|
||||||
FoundVad->u.VadFlags.CommitCharge -= QuotaCharge;
|
FoundVad->u.VadFlags.CommitCharge -= QuotaCharge;
|
||||||
|
|
|
@ -205,7 +205,7 @@ MiMakeSystemAddressValid(IN PVOID PageTableVirtualAddress,
|
||||||
IN PEPROCESS CurrentProcess)
|
IN PEPROCESS CurrentProcess)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
BOOLEAN WsWasLocked = FALSE, LockChange = FALSE;
|
BOOLEAN WsShared = FALSE, WsSafe = FALSE, LockChange = FALSE;
|
||||||
PETHREAD CurrentThread = PsGetCurrentThread();
|
PETHREAD CurrentThread = PsGetCurrentThread();
|
||||||
|
|
||||||
/* Must be a non-pool page table, since those are double-mapped already */
|
/* Must be a non-pool page table, since those are double-mapped already */
|
||||||
|
@ -219,13 +219,11 @@ MiMakeSystemAddressValid(IN PVOID PageTableVirtualAddress,
|
||||||
/* Check if the page table is valid */
|
/* Check if the page table is valid */
|
||||||
while (!MmIsAddressValid(PageTableVirtualAddress))
|
while (!MmIsAddressValid(PageTableVirtualAddress))
|
||||||
{
|
{
|
||||||
/* Check if the WS is locked */
|
/* Release the working set lock */
|
||||||
if (CurrentThread->OwnsProcessWorkingSetExclusive)
|
MiUnlockProcessWorkingSetForFault(CurrentProcess,
|
||||||
{
|
CurrentThread,
|
||||||
/* Unlock the working set and remember it was locked */
|
WsSafe,
|
||||||
MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
|
WsShared);
|
||||||
WsWasLocked = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fault it in */
|
/* Fault it in */
|
||||||
Status = MmAccessFault(FALSE, PageTableVirtualAddress, KernelMode, NULL);
|
Status = MmAccessFault(FALSE, PageTableVirtualAddress, KernelMode, NULL);
|
||||||
|
@ -240,7 +238,10 @@ MiMakeSystemAddressValid(IN PVOID PageTableVirtualAddress,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lock the working set again */
|
/* Lock the working set again */
|
||||||
if (WsWasLocked) MiLockProcessWorkingSet(CurrentProcess, CurrentThread);
|
MiLockProcessWorkingSetForFault(CurrentProcess,
|
||||||
|
CurrentThread,
|
||||||
|
WsSafe,
|
||||||
|
WsShared);
|
||||||
|
|
||||||
/* This flag will be useful later when we do better locking */
|
/* This flag will be useful later when we do better locking */
|
||||||
LockChange = TRUE;
|
LockChange = TRUE;
|
||||||
|
@ -1884,8 +1885,9 @@ MiProtectVirtualMemory(IN PEPROCESS Process,
|
||||||
ULONG ProtectionMask, OldProtect;
|
ULONG ProtectionMask, OldProtect;
|
||||||
BOOLEAN Committed;
|
BOOLEAN Committed;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
PETHREAD Thread = PsGetCurrentThread();
|
||||||
|
|
||||||
/* Calcualte base address for the VAD */
|
/* Calculate base address for the VAD */
|
||||||
StartingAddress = (ULONG_PTR)PAGE_ALIGN((*BaseAddress));
|
StartingAddress = (ULONG_PTR)PAGE_ALIGN((*BaseAddress));
|
||||||
EndingAddress = (((ULONG_PTR)*BaseAddress + *NumberOfBytesToProtect - 1) | (PAGE_SIZE - 1));
|
EndingAddress = (((ULONG_PTR)*BaseAddress + *NumberOfBytesToProtect - 1) | (PAGE_SIZE - 1));
|
||||||
|
|
||||||
|
@ -1896,7 +1898,7 @@ MiProtectVirtualMemory(IN PEPROCESS Process,
|
||||||
DPRINT1("Invalid protection mask\n");
|
DPRINT1("Invalid protection mask\n");
|
||||||
return STATUS_INVALID_PAGE_PROTECTION;
|
return STATUS_INVALID_PAGE_PROTECTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for ROS specific memory area */
|
/* Check for ROS specific memory area */
|
||||||
MemoryArea = MmLocateMemoryAreaByAddress(&Process->Vm, *BaseAddress);
|
MemoryArea = MmLocateMemoryAreaByAddress(&Process->Vm, *BaseAddress);
|
||||||
if ((MemoryArea) && (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW))
|
if ((MemoryArea) && (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW))
|
||||||
|
@ -2006,7 +2008,8 @@ MiProtectVirtualMemory(IN PEPROCESS Process,
|
||||||
goto FailPath;
|
goto FailPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
//MiLockProcessWorkingSet(Thread, Process);
|
/* Lock the working set */
|
||||||
|
MiLockProcessWorkingSetUnsafe(Process, Thread);
|
||||||
|
|
||||||
/* Check if all pages in this range are committed */
|
/* Check if all pages in this range are committed */
|
||||||
Committed = MiIsEntireRangeCommitted(StartingAddress,
|
Committed = MiIsEntireRangeCommitted(StartingAddress,
|
||||||
|
@ -2018,7 +2021,7 @@ MiProtectVirtualMemory(IN PEPROCESS Process,
|
||||||
/* Fail */
|
/* Fail */
|
||||||
DPRINT1("The entire range is not committed\n");
|
DPRINT1("The entire range is not committed\n");
|
||||||
Status = STATUS_NOT_COMMITTED;
|
Status = STATUS_NOT_COMMITTED;
|
||||||
//MiUnlockProcessWorkingSet(Thread, Process);
|
MiUnlockProcessWorkingSetUnsafe(Process, Thread);
|
||||||
goto FailPath;
|
goto FailPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2105,7 +2108,7 @@ MiProtectVirtualMemory(IN PEPROCESS Process,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unlock the working set */
|
/* Unlock the working set */
|
||||||
//MiUnlockProcessWorkingSet(Thread, Process);
|
MiUnlockProcessWorkingSetUnsafe(Process, Thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unlock the address space */
|
/* Unlock the address space */
|
||||||
|
@ -2278,7 +2281,7 @@ MiDecommitPages(IN PVOID StartingAddress,
|
||||||
PointerPde = MiAddressToPde(StartingAddress);
|
PointerPde = MiAddressToPde(StartingAddress);
|
||||||
PointerPte = MiAddressToPte(StartingAddress);
|
PointerPte = MiAddressToPte(StartingAddress);
|
||||||
if (Vad->u.VadFlags.MemCommit) CommitPte = MiAddressToPte(Vad->EndingVpn << PAGE_SHIFT);
|
if (Vad->u.VadFlags.MemCommit) CommitPte = MiAddressToPte(Vad->EndingVpn << PAGE_SHIFT);
|
||||||
MiLockWorkingSet(CurrentThread, &Process->Vm);
|
MiLockProcessWorkingSetUnsafe(Process, CurrentThread);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Make the PDE valid, and now loop through each page's worth of data
|
// Make the PDE valid, and now loop through each page's worth of data
|
||||||
|
@ -2403,7 +2406,7 @@ MiDecommitPages(IN PVOID StartingAddress,
|
||||||
// release the working set and return the commit reduction accounting.
|
// release the working set and return the commit reduction accounting.
|
||||||
//
|
//
|
||||||
if (PteCount) MiProcessValidPteList(ValidPteList, PteCount);
|
if (PteCount) MiProcessValidPteList(ValidPteList, PteCount);
|
||||||
MiUnlockWorkingSet(CurrentThread, &Process->Vm);
|
MiUnlockProcessWorkingSetUnsafe(Process, CurrentThread);
|
||||||
return CommitReduction;
|
return CommitReduction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3992,10 +3995,10 @@ NtAllocateVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
//
|
//
|
||||||
// Lock the working set and insert the VAD into the process VAD tree
|
// Lock the working set and insert the VAD into the process VAD tree
|
||||||
//
|
//
|
||||||
MiLockProcessWorkingSet(Process, CurrentThread);
|
MiLockProcessWorkingSetUnsafe(Process, CurrentThread);
|
||||||
Vad->ControlArea = NULL; // For Memory-Area hack
|
Vad->ControlArea = NULL; // For Memory-Area hack
|
||||||
MiInsertVad(Vad, Process);
|
MiInsertVad(Vad, Process);
|
||||||
MiUnlockProcessWorkingSet(Process, CurrentThread);
|
MiUnlockProcessWorkingSetUnsafe(Process, CurrentThread);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Update the virtual size of the process, and if this is now the highest
|
// Update the virtual size of the process, and if this is now the highest
|
||||||
|
@ -4254,7 +4257,7 @@ NtAllocateVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
//
|
//
|
||||||
// Lock the working set while we play with user pages and page tables
|
// Lock the working set while we play with user pages and page tables
|
||||||
//
|
//
|
||||||
//MiLockWorkingSet(CurrentThread, AddressSpace);
|
MiLockProcessWorkingSetUnsafe(Process, CurrentThread);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Make the current page table valid, and then loop each page within it
|
// Make the current page table valid, and then loop each page within it
|
||||||
|
@ -4335,7 +4338,7 @@ NtAllocateVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
// the target process if it was not the current process. Also dereference the
|
// the target process if it was not the current process. Also dereference the
|
||||||
// target process if this wasn't the case.
|
// target process if this wasn't the case.
|
||||||
//
|
//
|
||||||
//MiUnlockProcessWorkingSet(Process, CurrentThread);
|
MiUnlockProcessWorkingSetUnsafe(Process, CurrentThread);
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
FailPath:
|
FailPath:
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
MmUnlockAddressSpace(AddressSpace);
|
||||||
|
@ -4584,7 +4587,7 @@ NtFreeVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
//
|
//
|
||||||
// Finally lock the working set and remove the VAD from the VAD tree
|
// Finally lock the working set and remove the VAD from the VAD tree
|
||||||
//
|
//
|
||||||
MiLockWorkingSet(CurrentThread, AddressSpace);
|
MiLockProcessWorkingSetUnsafe(Process, CurrentThread);
|
||||||
ASSERT(Process->VadRoot.NumberGenericTableElements >= 1);
|
ASSERT(Process->VadRoot.NumberGenericTableElements >= 1);
|
||||||
MiRemoveNode((PMMADDRESS_NODE)Vad, &Process->VadRoot);
|
MiRemoveNode((PMMADDRESS_NODE)Vad, &Process->VadRoot);
|
||||||
}
|
}
|
||||||
|
@ -4614,7 +4617,7 @@ NtFreeVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
// the code path above when the caller sets a zero region size
|
// the code path above when the caller sets a zero region size
|
||||||
// and the whole VAD is destroyed
|
// and the whole VAD is destroyed
|
||||||
//
|
//
|
||||||
MiLockWorkingSet(CurrentThread, AddressSpace);
|
MiLockProcessWorkingSetUnsafe(Process, CurrentThread);
|
||||||
ASSERT(Process->VadRoot.NumberGenericTableElements >= 1);
|
ASSERT(Process->VadRoot.NumberGenericTableElements >= 1);
|
||||||
MiRemoveNode((PMMADDRESS_NODE)Vad, &Process->VadRoot);
|
MiRemoveNode((PMMADDRESS_NODE)Vad, &Process->VadRoot);
|
||||||
}
|
}
|
||||||
|
@ -4653,7 +4656,7 @@ 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.
|
||||||
//
|
//
|
||||||
MiLockWorkingSet(CurrentThread, AddressSpace);
|
MiLockProcessWorkingSetUnsafe(Process, CurrentThread);
|
||||||
CommitReduction = MiCalculatePageCommitment(StartingAddress,
|
CommitReduction = MiCalculatePageCommitment(StartingAddress,
|
||||||
EndingAddress,
|
EndingAddress,
|
||||||
Vad,
|
Vad,
|
||||||
|
@ -4695,7 +4698,7 @@ NtFreeVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
// around with process pages.
|
// around with process pages.
|
||||||
//
|
//
|
||||||
MiDeleteVirtualAddresses(StartingAddress, EndingAddress, NULL);
|
MiDeleteVirtualAddresses(StartingAddress, EndingAddress, NULL);
|
||||||
MiUnlockWorkingSet(CurrentThread, AddressSpace);
|
MiUnlockProcessWorkingSetUnsafe(Process, CurrentThread);
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
FinalPath:
|
FinalPath:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue