2010-12-16 3 views
16

De ReadProcessMemory in MSDN:Pourquoi ReadProcessMemory a-t-il `lpNumberOfBytesRead`?

lpBaseAddress [in]:
Un pointeur sur l'adresse de base dans le processus spécifié à partir de laquelle la lecture. Avant tout transfert de données, le système vérifie que toutes les données dans l'adresse de base et la mémoire de la taille spécifiée sont accessibles pour l'accès en lecture, et si elle n'est pas accessible, la fonction échoue.

nSize [in]:
Le nombre d'octets à lire dans le processus spécifié.

lpNumberOfBytesRead [out]
Un pointeur sur une variable qui reçoit le nombre d'octets transférés dans la mémoire tampon spécifiée. Si lpNumberOfBytesRead est NULL, le paramètre est ignoré.

Donc, ReadProcessMemory ne peut réussir complètement ou échouer complètement. Et la taille est évidemment connue de l'appelant - a dû le passer pour faire l'appel. Pourquoi avoir le lpNumberOfBytesRead?

+5

C'est une bonne question. – paxdiablo

+0

@paxdiablo: Merci :) –

+0

La magie noire se passe ici. Il existe une erreur spécifique ERROR_PARTIAL_COPY qui stipule "Seule une partie d'une demande ReadProcessMemory ou WriteProcessMemory a été terminée". Cela semble aller à l'encontre de «réussir ou échouer complètement», mais je n'ai aucune idée de ce qui est juste. – paxdiablo

Répondre

10

De winerror.h:

// 
// MessageId: ERROR_PARTIAL_COPY 
// 
// MessageText: 
// 
// Only part of a ReadProcessMemory or WriteProcessMemory request was completed. 
// 
#define ERROR_PARTIAL_COPY    299L 

ReadProcessMemory retournerait FAUX et GetLastError retournerait ERROR_PARTIAL_COPY lorsque la copie frappe une faute de page. C'est un scénario courant dans les dumpers, qui doivent travailler sur un processus potentiellement corrompu, donc ils ne peuvent pas être sûrs que la zone demandée est valide ou non (le pointeur qu'ils ont chassé pour obtenir l'adresse de départ pourrait être corrompu la-land), mais ils aimeraient toujours copier autant que possible dans la décharge.

+0

Donc vous dites que ReadProcessMemory peut échouer mais toujours copier de la mémoire? –

+2

Oui. Imaginez * comment * implémenteriez-vous un ReadProcessMemory atomique (soit tout copie, soit rien). Vous devez soit * annuler * la copie (ce qui signifie que vous avez sauvegardé le contenu précédent), soit effectuer la copie en deux fois (une copie valide chaque page dans la zone demandée, une copie) et espérer que le processus cible ne pas changer une protection de page entre les passes. –

3

Peut-être que dans certaines versions précédentes de l'API, cette fonction n'échouait pas complètement, mais pouvait renvoyer des résultats partiels. Ainsi, le paramètre out est conservé pour des raisons de compatibilité, mais les nouveaux programmes peuvent passer une valeur NULL et l'ignorer.

+1

Mais cela signifierait que quelqu'un suivant les docs aurait maintenant leurs programmes échouer aléatoirement sur les anciens systèmes d'exploitation .... Je ne vois pas cela au moins être documenté sur MSDN ... –

+2

@Billy ONeal: Si vous utilisez le version de l'API documentée sur MSDN, votre application échouera probablement à fonctionner sur ces anciens systèmes d'exploitation, car certaines fonctions de l'API sont tout simplement * manquantes * dans les anciennes versions de l'API. Si vous avez l'intention de développer pour Windows 95, vous devez baser votre code sur la documentation de Windows 95. Si vous ne développez pas pour Windows 95, les informations supplémentaires ne sont que du bruit. –

+0

@Anon: Je n'étais pas au courant que ReadProcessMemory existait du tout sur Win95. Pensé que c'était un bit NT seulement. (Je me fous de tout sauf de NT de toute façon ...) –

0

Une autre possibilité, mis à part 9000's answer, est que le paramètre est là pour des extensions futures. Peut-être qu'à un moment donné (et peut-être même maintenant) il était prévu de fournir des implémentations de ReadProcessMemory qui pourraient partiellement échouer, de sorte que le paramètre out a été mis là pour cette raison. Ce serait une manière (pas particulièrement bonne) d'éviter tout le problème API/APIEx/APIEx2/quel que soit le problème que les API de Win32 ont connu depuis des années.

1

Je suppose que la zone peut être accessible en termes d'autorisations, mais une erreur dans une erreur de page peut seulement permettre à une partie d'être lue. C'est juste une supposition cependant.

Edit: Voir cette page: ReactOS - STATUS_PARTIAL_COPY

> // Otherwise, we failed probably during the move 

Il semble que tout problème qui est hors du contrôle de la fonction peut renvoyer ce code d'erreur.

0

Il existe une condition de concurrence inhérente. Les copies ne sont pas instantanées. Bien sûr, la fonction vérifie à l'avance si elle est susceptible de réussir, mais il est possible que la plage de mémoire devienne non mappée pendant la copie. C'est un autre processus en cours que vous regardez, après tout, probablement pas au courant de votre ReadProcessMemory() en cours. (Remus Rusanu a également fait allusion à une telle copie partielle, mais a suggéré un processus corrompu comme cause profonde, pas une course.