首页 > 解决方案 > Virtual Protect 的 64 位声明是否正确?

问题描述

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,所以在第二次调用中我得到 87 的 LastDllError -“参数不正确。”。我很确定内存最初受到保护,因为删除对 VirtualProtect 的调用会使我的程序崩溃,而包含它是成功的。但我无法重置保护。


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

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

标签: vbawinapi64-bit

解决方案


是的,声明是正确的。

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

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

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


推荐阅读