You're currently only retrieving information about the first block of memory for each process. A process will typically have a lot of memory blocks, not just one (thousands to tens of thousands would be pretty typical).
Here's some code that retrieves and prints out the status of each block of data in a specified process.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <iostream>
#include <string>
unsigned long show_module(MEMORY_BASIC_INFORMATION info) {
unsigned long usage = 0;
std::cout << info.BaseAddress << "(" << info.RegionSize / 1024 << ")\t";
switch (info.State) {
case MEM_COMMIT:
std::cout << "Committed";
break;
case MEM_RESERVE:
std::cout << "Reserved";
break;
case MEM_FREE:
std::cout << "Free";
break;
}
std::cout << "\t";
switch (info.Type) {
case MEM_IMAGE:
std::cout << "Code Module";
break;
case MEM_MAPPED:
std::cout << "Mapped ";
break;
case MEM_PRIVATE:
std::cout << "Private ";
}
std::cout << "\t";
int guard = 0, nocache = 0;
if ( info.AllocationProtect & PAGE_NOCACHE)
nocache = 1;
if ( info.AllocationProtect & PAGE_GUARD )
guard = 1;
info.AllocationProtect &= ~(PAGE_GUARD | PAGE_NOCACHE);
if ((info.State == MEM_COMMIT) && (info.AllocationProtect == PAGE_READWRITE || info.AllocationProtect == PAGE_READONLY))
usage += info.RegionSize;
switch (info.AllocationProtect) {
case PAGE_READONLY:
std::cout << "Read Only";
break;
case PAGE_READWRITE:
std::cout << "Read/Write";
break;
case PAGE_WRITECOPY:
std::cout << "Copy on Write";
break;
case PAGE_EXECUTE:
std::cout << "Execute only";
break;
case PAGE_EXECUTE_READ:
std::cout << "Execute/Read";
break;
case PAGE_EXECUTE_READWRITE:
std::cout << "Execute/Read/Write";
break;
case PAGE_EXECUTE_WRITECOPY:
std::cout << "COW Executable";
break;
}
if (guard)
std::cout << "\tguard page";
if (nocache)
std::cout << "\tnon-cacheable";
std::cout << "\n";
return usage;
}
unsigned long show_modules(HANDLE process) {
unsigned long usage = 0;
unsigned char* p = NULL;
MEMORY_BASIC_INFORMATION info;
for ( p = NULL;
VirtualQueryEx(process, p, &info, sizeof(info)) == sizeof(info);
p += info.RegionSize )
{
usage += show_module(info);
}
return usage;
}
int main(int argc, char **argv) {
int pid;
if (argc != 2) {
std::cerr << "Usage: " << argv[0] << " <process ID>\n";
return EXIT_FAILURE;
}
pid = std::stoi(argv[1]);
HANDLE process = OpenProcess(
PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
false,
pid);
unsigned long mem_used = show_modules(process);
std::cout << "Total memory used: " << mem_used / 10224 << "KB\n";
}
To give an idea of the result, here are the first few lines of output from a process on my system:
0000000000000000(64) Free
0000000000010000(64) Committed Mapped Read/Write
0000000000020000(4) Committed Mapped Read Only
0000000000021000(60) Free
0000000000030000(4) Committed Private
0000000000031000(60) Reserved Private
But be aware: you're likely to get a lot more output than that for most typical processes. That particular process (Thunderbird) produced a total of 3,686 lines of output. A quick test with Chrome (using a couple gigabytes of memory) produces over 46,000 lines of output (i.e., over 46,000 separate memory blocks being tracked by the system for it).
If you're going to print something out for every process in the system, you'll probably want to summarize the data quite a bit (but without knowing why you want this, it's hard to guess what sort of result you're likely to want).