说,如果在某个时刻,我的进程中的一系列虚拟内存被锁定:
//Memory was reserved & committed as such
void* pMem = ::VirtualAlloc(NULL, 4096, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
//...
//And then
::VirtualLock(pMem, 4096);
因此,在我的过程中在虚拟内存中有一个页面的任意地址,我可以判断它是locked
吗?
答案 0 :(得分:3)
by using win32 api this is impossible. but if use ZwQueryVirtualMemory
with undocumented MEMORY_INFORMATION_CLASS
values - this is possible. for data structures definition - see ntmmapi.h
we need use MemoryWorkingSetExInformation
with MEMORY_WORKING_SET_EX_BLOCK
and use ULONG_PTR Locked : 1;
member
demo test:
NTSTATUS IsPageLocked(PVOID BaseAddress, BOOLEAN& Locked)
{
MEMORY_WORKING_SET_EX_INFORMATION mwsei = { BaseAddress };
NTSTATUS status = ZwQueryVirtualMemory(NtCurrentProcess(), 0, MemoryWorkingSetExInformation, &mwsei, sizeof(mwsei), 0);
if (0 <= status)
{
if (mwsei.VirtualAttributes.Valid)
{
Locked = mwsei.VirtualAttributes.Locked;
}
else
{
status = STATUS_INVALID_ADDRESS;
}
}
return status;
}
NTSTATUS IsPageLockedEx(PVOID BaseAddress, BOOLEAN& Locked)
{
NTSTATUS status = IsPageLocked(BaseAddress, Locked);
if (0 > status)
{
DbgPrint("IsPageLocked - error %x\n", status);
}
else
{
DbgPrint("IsPageLocked = %x\n", Locked);
}
return status;
}
void CheckVA()
{
if (PVOID pv = VirtualAlloc(NULL, PAGE_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE))
{
BOOLEAN Locked;
NTSTATUS status = IsPageLockedEx(pv, Locked);
if (status == STATUS_INVALID_ADDRESS)
{
// at this point physical memory for pv not yet committed. reference memory for commit physical page
if (*(PBYTE)pv) __nop();
status = IsPageLockedEx(pv, Locked);
}
if (VirtualLock(pv, PAGE_SIZE))
{
IsPageLockedEx(pv, Locked);
if (VirtualUnlock(pv, PAGE_SIZE))
{
IsPageLockedEx(pv, Locked);
}
else
{
__debugbreak();
}
}
VirtualFree(pv, 0, MEM_RELEASE);
}
}
and DbgPrint output
IsPageLocked - error c0000141
IsPageLocked = 0
IsPageLocked = 1
IsPageLocked = 0