2010-12-16 20 views
16

ReadProcessMemory in MSDN:爲什麼ReadProcessMemory有`lpNumberOfBytesRead`?

lpBaseAddress [IN]
的指針在指定過程中的基地址從中讀取。在發生任何數據傳輸之前,系統會驗證指定大小的基址和內存中的所有數據是否可以讀取訪問,如果不可訪問,則該功能將失敗。

nSize [in]
要從指定進程讀取的字節數。

lpNumberOfBytesRead [OUT]
的指針,該接收傳送到指定緩衝區的字節數的變量。如果lpNumberOfBytesRead爲NULL,則該參數將被忽略。

因此.. ReadProcessMemory只能完全成功或完全失敗。而呼叫者顯然知道這個尺寸 - 必須通過它才能撥打電話。爲什麼有lpNumberOfBytesRead

+5

這是一個很好的問題。 – paxdiablo 2010-12-16 03:30:38

+0

@paxdiablo:謝謝:) – 2010-12-16 03:32:30

+0

黑暗魔法在這裏。有一個特定的錯誤ERROR_PARTIAL_COPY,其中指出「只有部分ReadProcessMemory或WriteProcessMemory請求已完成」。這似乎是在「完全成功或失敗」的情況下飛行,但我不知道哪個是正確的。 – paxdiablo 2010-12-16 03:49:54

回答

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),但他們仍然希望儘可能地複製到垃圾場。

+0

所以你說ReadProcessMemory可以失敗,但仍然複製一些內存? – 2010-12-16 06:10:20

+2

是的。想象一下,你將如何實現一個原子化的ReadProcessMemory(或者複製一切,或者什麼都不)。你必須或者*回滾*拷貝(意味着你保存了之前寫入的內容),或者你必須通過兩遍(一個驗證請求區域中的每個頁面,一個拷貝)拷貝並且希望目標進程執行不改變通行證之間的頁面保護。 – 2010-12-16 06:14:17

3

也許在以前的某些API版本中,該函數並未完全失敗,但可能會返回部分結果。所以out參數保持兼容性,但新的程序可以傳遞一個NULL並忽略它。

+1

但是,這意味着現在有人跟隨文檔將他們的程序在較舊的操作系統上隨機失敗....我沒有看到,至少沒有記錄在MSDN上... – 2010-12-16 03:34:05

+2

@Billy ONeal:如果您使用在MSDN上記錄的API版本,您的應用程序很可能無法在這些較舊的操作系統上運行,因爲某些API函數從舊版本的API中只是簡單*丟失*。如果您打算爲Windows 95進行開發,則應該將代碼放在Windows 95文檔中。如果您沒有爲Windows 95開發,那麼額外的信息就是噪音。 – 2010-12-16 03:39:27

+0

@Anon:我不知道Win95上的ReadProcessMemory存在。以爲這只是一個新臺幣。 (我不在乎任何東西,但NT ...無論如何... – 2010-12-16 03:41:01

0

9000's answer之外的另一種可能性是該參數用於將來的擴展目的。也許在某一時刻(甚至現在)有計劃提供可能部分失敗的ReadProcessMemory實現,所以out參數就是出於這個原因。這將是一種(並非特別好)的方法來避免整個API/APIEx/APIEx2/Win32的API多年來一直苦苦掙扎的問題。

1

我猜測該區域可能是權限方面可訪問的,但頁面錯誤中的錯誤可能只允許讀取其中的一部分。這只是一個猜測。

編輯:看到這個頁面:ReactOS - STATUS_PARTIAL_COPY

> // Otherwise, we failed probably during the move 

好像那是出了功能的控制可能會返回該錯誤代碼的任何問題。

0

存在固有的競爭條件。副本不是即時的。當然,該功能會檢查它是否可能成功,但可能在複製期間內存範圍變爲未映射。這是你正在看的另一個運行過程,畢竟,很可能不知道你正在進行的ReadProcessMemory()

(Remus Rusanu也暗示了這樣一個部分副本,但提出了一個損壞的過程作爲根本原因,而不是一個種族。)