在VirtualLock的documentation page上有以下注释:
typedef enum {
MGL_TRIANGLES,
MGL_QUADS
} MGLpoly_mode;
MGLpoly_mode mode; //mode 1
void mglBegin(MGLpoly_mode mode)
{
mode = mode; //mode 1 = input parameter mode
}
有什么方法可以解决这个问题吗?这个专长可以在unix系统上实现,但是在windows上存在这种限制。目标是防止将内存分页到磁盘,同时防止对它进行任何访问。
答案 0 :(得分:1)
当我们使用PAGE_NOACCESS
或PAGE_GUARD|*
在锁定的内存区域调用ZwProtectVirtualMemory
时,返回的状态为STATUS_WAS_UNLOCKED
:
{页面已解锁}
锁定页面的页面保护已更改为 “无权访问”,并且该页面已从内存和 过程。
此处重要的调用恰好是ZwProtectVirtualMemory
而不是VirtualProtect[Ex]
,因为此win32 api不能区分不同的NT_SUCCESS
值,只需对其中的任何一个返回 true 并删除原始状态。但是STATUS_WAS_UNLOCKED
也被定义为0x40000017L
和NT_SUCCESS
的值-因此,VirtualProtect[Ex]
在这种情况下丢失了重要信息。
因此将PAGE_NOACCESS
或PAGE_GUARD|*
设置为从内存中解锁页的副作用
但是在页面上设置PAGE_NOACCESS
有什么意义?为防止外部有人从页面读取数据?但是如果此代理有权访问您的进程-他也可以并删除此PAGE_NOACCESS
,如果没有访问权-则不需要执行保护。在两种情况下-无意义的集PAGE_NOACCESS
-是否需要或可以将其删除。
防止页面交换到页面文件是有道理的,因为从理论上讲,可以在系统关闭后(如果此时在此位置)从其中读取它,但设置为No Access(从 PTE中删除有效位) 进入此页面)
只需测试代码
void PrintNtStatus(PCSTR prefix, NTSTATUS status)
{
static HMODULE hmod = 0;
if (!hmod)
{
hmod = GetModuleHandle(L"ntdll");
}
PWSTR msg;
if (FormatMessageW(FORMAT_MESSAGE_FROM_HMODULE|FORMAT_MESSAGE_ALLOCATE_BUFFER, hmod, status, 0, (PWSTR)&msg, 0, 0))
{
DbgPrint("%s = %x(%S)\n", prefix, status, msg);
LocalFree(msg);
}
}
void LockTest()
{
if (PVOID pv = VirtualAlloc(0, 1, MEM_COMMIT, PAGE_READWRITE))
{
if (VirtualLock(pv, 1))
{
ULONG op;
SIZE_T size = 1;
PVOID BaseAddress = pv;
//STATUS_WAS_UNLOCKED
PrintNtStatus("ProtectVirtualMemory",
ZwProtectVirtualMemory(NtCurrentProcess(), &BaseAddress, &size, PAGE_NOACCESS, &op));
PrintNtStatus("ProtectVirtualMemory",
ZwProtectVirtualMemory(NtCurrentProcess(), &BaseAddress, &size, op, &op));
PrintNtStatus("VirtualUnlock", VirtualUnlock(pv, 1) ? STATUS_SUCCESS : RtlGetLastNtStatus());
}
VirtualFree(pv, 0, MEM_RELEASE);
}
}