From: Zach on
I have a situation where I'm using ReadProcessMemory() to read another
process's address space. I have an upper bound on how much memory the
structure I'm reading can occupy, but being that it's a variable length
structure, I can't know exactly how big it is until I've read it and
done some parsing on the fields in the structure. In some situations,
ReadProcessMemory() returns ERROR_PARTIAL_COPY, which according to
winerror.h means "Only part of a ReadProcessMemoty or
WriteProcessMemory request was completed."

The documentation for ReadProcessMemory() states that it should only
fail when I attempt to read an area of the process that is not
accessible. My question is, is this by a marvelous coincidence,
sometimes my structure is exactly at the end of a page of memory, and
the next page of memory contains different protection settings? If so,
how do I handle this? For reference, my "upper bound" on how much
memory I need to read is 250 bytes. Is code like the following
bulletproof enough?

const int nSizeUpperBound = 250;
BYTE* lpAddressToReadFrom = /*initialize*/;
MEMORY_BASIC_INFORMATION memInfo;
ZeroMemory(&memInfo, sizeof(MEMORY_BASIC_INFORMATION));

VirtualQueryEx(hProcess, lpAddressToReadFrom, &memInfo,
sizeof(MEMORY_BASIC_INFORMATION);

int nBytesIntoRegion = lpAddressToReadFrom - memInfo.BaseAddress;
int nBytesAwayFromEnd = memInfo.RegionSize - nBytesIntoRegion;

int ActualNumberOfBytesToRead = min(nSizeUpperBound,
nBytesAwayFromEnd);

If not, what is the correct way to handle this and what concept do I
need to understand in order to see why the above doesn't work?

For the record, I have actually tested this, but the problem only
arises every once in a blue moon. I've only ever had it happen once
with the ERROR_PARTIAL_COPY, so it's difficult to know if the above
code fixed it, or I'm just getting unlucky and can't reproduce it.

Thanks

From: Grzegorz Wróbel on
Zach wrote:
> I have a situation where I'm using ReadProcessMemory() to read another
> process's address space. I have an upper bound on how much memory the
> structure I'm reading can occupy, but being that it's a variable length
> structure, I can't know exactly how big it is until I've read it and
> done some parsing on the fields in the structure. In some situations,
> ReadProcessMemory() returns ERROR_PARTIAL_COPY, which according to
> winerror.h means "Only part of a ReadProcessMemoty or
> WriteProcessMemory request was completed."
>
> The documentation for ReadProcessMemory() states that it should only
> fail when I attempt to read an area of the process that is not
> accessible. My question is, is this by a marvelous coincidence,
> sometimes my structure is exactly at the end of a page of memory, and
> the next page of memory contains different protection settings? If so,
> how do I handle this? For reference, my "upper bound" on how much
> memory I need to read is 250 bytes. Is code like the following
> bulletproof enough?
>
> const int nSizeUpperBound = 250;
> BYTE* lpAddressToReadFrom = /*initialize*/;
> MEMORY_BASIC_INFORMATION memInfo;
> ZeroMemory(&memInfo, sizeof(MEMORY_BASIC_INFORMATION));
>
> VirtualQueryEx(hProcess, lpAddressToReadFrom, &memInfo,
> sizeof(MEMORY_BASIC_INFORMATION);
>
> int nBytesIntoRegion = lpAddressToReadFrom - memInfo.BaseAddress;
> int nBytesAwayFromEnd = memInfo.RegionSize - nBytesIntoRegion;
>
> int ActualNumberOfBytesToRead = min(nSizeUpperBound,
> nBytesAwayFromEnd);
>
> If not, what is the correct way to handle this and what concept do I
> need to understand in order to see why the above doesn't work?
>
> For the record, I have actually tested this, but the problem only
> arises every once in a blue moon. I've only ever had it happen once
> with the ERROR_PARTIAL_COPY, so it's difficult to know if the above
> code fixed it, or I'm just getting unlucky and can't reproduce it.

I think you shouldn't be worried about ERROR_PARTIAL_COPY in the first
place, since this would mean you have copied all the bytes you wanted
anyway. So you should just ignore this kind of error. The code above
looks like it does what you want (prevent returning ERROR_PARTIAL_COPY
by ReadProcessMemory) but what for? You just duplicated the
ERROR_PARTIAL_COPY mechanism.

If you want to test your code really works set the nSizeUpperBound to
some large value that will exceed memory address range allocated for the
process.

--
Grzegorz Wr�bel
http://www.4neurons.com/
677265676F727940346E6575726F6E732E636F6D