Search code examples
c++memoryprobe

Enumerate the pages in a memory range


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.


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;
    }