Question

I'm using C++ on Windows under Visual Studio 2012.

I have a start and end memory address and need to generate a list of page base addresses/handles between the two addresses. I considered the possibility of probing the pages manually but thought there must be a better way to enumerate them.

Does such a way exist?

Disclaimer; The final page handles must be the base address such that when the size of a windows page is added to them the resulting address does not overlap into the next page. The preferred solution would not be platform specific and be compatible with 32-bit with/without WOW64.

Was it helpful?

Solution

VirtualQuery is pretty much your only option. It should be fairly efficient:

The function determines the attributes of the first page in the region and then scans subsequent pages until it scans the entire range of pages or until it encounters a page with a nonmatching set of attributes.

So you'd start by calling it at the beginning of the range that you care about, and you'd get back a single chunk of pages. The next call would start right after that chunk, and the next one after that, and so on.

Here's a completely untested function that would populate an array of MEMORY_BASIC_INFORMATION structures:

int EnumVirtualAllocations(const void* ptr, size_t length, MEMORY_BASIC_INFORMATION* info, int size)
{
    const void* end = (const void*)((const char*)ptr + length);
    int index = 0;
    while (index < size && ptr < end &&
        VirtualQuery(ptr, &info[index], sizeof(*info)) == sizeof(*info))
    {
        MEMORY_BASIC_INFORMATION* i = &info[index];
        if (i->State != MEM_FREE) index++;
        ptr = (const void*)((const char*)(i->BaseAddress) + i->RegionSize);
    }
    return index;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top