2010-12-16 29 views
16

De ReadProcessMemory in MSDN:¿Por qué ReadProcessMemory tiene `lpNumberOfBytesRead`?

lpBaseAddress [en]:
Un puntero a la dirección de base en el proceso especificado desde la que leer. Antes de que se produzca cualquier transferencia de datos, el sistema verifica que todos los datos en la dirección base y la memoria del tamaño especificado sean accesibles para el acceso de lectura, y si no es accesible, la función falla.

nTamaño [en]:
El número de bytes que se lee desde el proceso especificado.

lpNumberOfBytesRead [out]
Un puntero a una variable que recibe el número de bytes transferidos en el tampón especificado. Si lpNumberOfBytesRead es NULL, el parámetro se ignora.

Así que .. ReadProcessMemory solo puede tener éxito completo o puede fallar por completo. Y el tamaño obviamente es conocido por la persona que llama, tuvo que pasarlo para hacer la llamada. ¿Por qué tener el lpNumberOfBytesRead?

+5

Esa es una buena pregunta. – paxdiablo

+0

@paxdiablo: Gracias :) –

+0

Magia oscura pasando aquí. Hay un error específico ERROR_PARTIAL_COPY que dice "Solo se completó una parte de una solicitud ReadProcessMemory o WriteProcessMemory". Esto parece ir en contra de "tener éxito o fracasar por completo", pero no tengo idea de cuál es la correcta. – paxdiablo

Respuesta

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 volvería FALSO y GetLastError volvería ERROR_PARTIAL_COPY cuando la copia realiza un error de página. Este es un escenario común en los volcadores, que tienen que trabajar en un proceso potencialmente dañado, por lo que no pueden estar seguros de si el área solicitada es válida o no (el puntero que persiguieron para obtener la dirección de inicio podría estar dañado y señalar a la la-land), pero aún así les gustaría copiar tanto como sea posible en el vertedero.

+0

¿Entonces está diciendo que ReadProcessMemory puede fallar pero aún copiar algo de memoria? –

+2

Sí. Imagine * cómo * implementaría una ReadProcessMemory que es atómica (copia todo o nada). Tendría que * retrotraer * la copia (lo que significa que ha guardado el contenido anterior al que escribió) o tendría que hacer la copia en dos pasos (uno valida cada página en el área solicitada, una copia) y esperar que el proceso objetivo lo haga no cambie una protección de página entre los pases. –

3

Tal vez en algunas versiones de API anteriores, esta función no falló completamente, pero podría devolver resultados parciales. Entonces el parámetro out se mantiene para compatibilidad, pero los programas más nuevos pueden pasar un NULL e ignorarlo.

+1

Pero esto significaría que alguien que sigue los documentos ahora tendría sus programas fallarían aleatoriamente en sistemas operativos más antiguos ... No veo que al menos no esté documentado en MSDN ... –

+2

@Billy ONeal: Si está usando el versión de la API documentada en MSDN, su aplicación probablemente no se ejecutará en esos sistemas operativos más antiguos de todos modos, porque algunas de las funciones de la API simplemente faltan * de versiones anteriores de la API. Si pretende desarrollar para Windows 95, debe basar su código en la documentación de Windows 95. Si no está desarrollando para Windows 95, entonces la información adicional es solo ruido. –

+0

@Anon: no sabía que existiera ReadProcessMemory en Win95. Pensé que era un NT solo un poco. (No me importa nada más que NT de todos modos ...) –

0

Otra posibilidad, aparte de 9000's answer es que el parámetro está ahí para futuras expansiones. Quizás en algún momento (y tal vez incluso ahora) hubo planes para proporcionar implementaciones de ReadProcessMemory que podrían fallar parcialmente, por lo que el parámetro out se puso allí por ese motivo. Esta sería una forma (no particularmente buena) de evitar todo el problema API/APIEx/APIEx2/cualquier problema con el que las API de Win32 han trabajado durante años.

1

Supongo que el área podría ser accesible en términos de permisos, pero un error en una página podría permitir que se lea solo una parte. Sin embargo, eso solo es una suposición.

Editar: Ver esta página: ReactOS - STATUS_PARTIAL_COPY

> // Otherwise, we failed probably during the move 

Parece que cualquier problema que está fuera del control de la función puede devolver el código de error.

0

Hay una condición de carrera inherente. Las copias no son instantáneas. Claro, la función comprueba desde el principio si es probable que tenga éxito, pero es posible que el rango de memoria quede sin asignar durante la copia. Después de todo, es otro proceso en ejecución que está viendo, muy probablemente desconoce su actual ReadProcessMemory().

(Remus Rusanu también insinuó una copia parcial, pero sugirió un proceso dañado como causa principal, no como una carrera.)

Cuestiones relacionadas