lpBaseAddress [in] :
指向要从中读取的指定进程中的基址的指针。在发生任何数据传输之前,系统会验证基本地址和指定大小的内存中的所有数据是否都可以进行读访问,如果无法访问,则该函数将失败。
nSize [in] :
要从指定进程读取的字节数。
lpNumberOfBytesRead [out]
指向变量的指针,该变量接收传输到指定缓冲区的字节数。如果lpNumberOfBytesRead为NULL,则忽略该参数。
所以.. ReadProcessMemory
只能完全成功或完全失败。并且呼叫者显然知道大小 - 必须将其传入以进行呼叫。为什么要lpNumberOfBytesRead
?
答案 0 :(得分:10)
来自winerror.h
:
//
// MessageId: ERROR_PARTIAL_COPY
//
// MessageText:
//
// Only part of a ReadProcessMemory or WriteProcessMemory request was completed.
//
#define ERROR_PARTIAL_COPY 299L
当副本遇到页面错误时, ReadProcessMemory
将返回FALSE并且GetLastError
将返回ERROR_PARTIAL_COPY
。这是转储器中的常见情况,它必须处理可能已损坏的进程,因此无法确定所请求的区域是否有效(他们追逐以获取起始地址的指针可能已损坏并指向la- la-land),但他们仍然希望尽可能多地复制到垃圾场。
答案 1 :(得分:3)
也许在以前的某些API版本中,此功能并未完全失败,但可能会返回部分结果。因此保留out参数以保持兼容性,但较新的程序可以传递NULL并忽略它。
答案 2 :(得分:1)
我猜这个区域可能在权限方面是可访问的,但是页面错误中的错误可能只允许读取其中的一部分。这只是一个猜测。
修改:请参阅此页:ReactOS - STATUS_PARTIAL_COPY
> // Otherwise, we failed probably during the move
似乎任何不受函数控制的问题都可能返回此错误代码。
答案 3 :(得分:1)
存在固有的竞争条件。副本不是即时的。当然,该函数会预先检查它是否可能成功,但是在复制期间内存范围可能会被取消映射。这是你正在看的另一个正在运行的过程,毕竟很可能不知道你正在进行的ReadProcessMemory()
。
(Remus Rusanu也暗示了这样的部分副本,但建议将一个损坏的过程作为根本原因,而不是种族。)
答案 4 :(得分:0)
除了9000's answer之外,另一种可能性是该参数用于将来的扩展目的。也许在某一时刻(甚至可能是现在)有计划提供可能部分失败的ReadProcessMemory实现,因此出于那个原因将out参数放在那里。这将是一种(不是特别好的)方法来避免整个API / APIEx / APIEx2 / Win32的API多年来一直在努力解决的问题。