这个64位的Virtual Protect声明正确吗?


Private Declare PtrSafe Function VirtualProtect Lib "kernel32" ( _
ByVal memAddress As LongPtr, _
ByVal lengthInBytes As LongPtr, _
ByVal newProtect As protectFlags, _
ByRef outOldProtect As protectFlags _
) As Long
Public Enum protectFlags 'an enum is a Long in VBA which is 32-bit so can be used in place of DWORD
PAGE_NOACCESS = &H1
PAGE_READONLY = &H2
PAGE_READWRITE = &H4
PAGE_WRITECOPY = &H8
PAGE_EXECUTE = &H10
PAGE_EXECUTE_READ = &H20
PAGE_EXECUTE_READWRITE = &H40
PAGE_EXECUTE_WRITECOPY = &H80
PAGE_GUARD = &H100
PAGE_NOCACHE = &H200
PAGE_WRITECOMBINE = &H400
End Enum

我这样调用它:

Dim memoryAddress As LongPtr
memoryAddress = ... 'some protected memory
Dim originalProtection As protectFlags
If CBool(VirtualProtect(memoryAddress, 8, PAGE_EXECUTE_READWRITE, originalProtection)) Then
Debug.Print "Previous protection cached: &H"; Hex(originalProtection)
Else
Err.Raise 5, Description:="Memory address cannot be unprotected with PAGE_EXECUTE_READWRITE"
End If

…然后恢复保护

VirtualProtect(memoryAddress, 8, originalProtection, temp) 

问题是,originalProtection在第一次调用后仍然是&H0,因此在第二次调用中,我得到LastDllError为87 - "参数不正确。"。我很确定内存最初是受保护的,因为删除对VirtualProtect的调用会使我的程序崩溃,而包括它是成功的。但是我不能重置保护。


作为参考,这是我翻译的内容:

BOOL VirtualProtect(
LPVOID lpAddress,
SIZE_T dwSize,
DWORD  flNewProtect,
PDWORD lpflOldProtect
);

是,声明是正确的。

问题是,在我的实际代码中,originalProtection是一个公共类变量。

公共类变量不能通过ref传递给函数,因为它们实际上是作为带有隐藏私有变量的Property Get/Let过程实现的,因此只有一个临时值被传递给VirtualProtect,而不是要写入的底层变量。

解决方案是用Dim声明一个局部变量来接收值,然后将其写入我的类变量。

最新更新