Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
177 views
in Technique[技术] by (71.8m points)

C++ winapi VirtualQueryEx function gives me "000000"

I am trying to display information about the virtual memory of each process on the system:

#include <windows.h>
#include <conio.h>
#include <tlhelp32.h>
#include <iostream>
using namespace std;


void main() {
HANDLE CONST hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
PROCESSENTRY32 proc;
TCHAR Buffer[1024];
TCHAR Buffer2[1024];
DWORD temp;


HANDLE CONST hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

if (INVALID_HANDLE_VALUE == hSnap)
{
    return;
}

proc.dwSize = sizeof(PROCESSENTRY32);

Process32First(hSnap, &proc);

do {
    MEMORY_BASIC_INFORMATION    mbi = {};
    wsprintf(Buffer, L" %s %d 
 ", proc.szExeFile, proc.th32ProcessID);
    WriteConsole(hStdOut, Buffer, lstrlen(Buffer), &temp, NULL);
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, proc.th32ProcessID);
    VirtualQueryEx(hProcess, 0, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
    printf("Alloc = %p, base = %p , size = %d, type = %d, state = %p
", mbi.AllocationBase, mbi.BaseAddress, mbi.RegionSize, mbi.Type,mbi.State);

} while (Process32Next(hSnap, &proc));

CloseHandle(hSnap);


}

Output looks like this:

output

I get base address and alloc equal to 0000000 and type 0 How do I get normal values? I mean size and state seem to be ok but the rest is "0000000" I do not know what's the problem

question from:https://stackoverflow.com/questions/65897402/c-winapi-virtualqueryex-function-gives-me-000000

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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 << ")";

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

    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 << "guard page";
    if (nocache)
        std::cout << "non-cacheable";
    std::cout << "
";
    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>
";
        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
";
}

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).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...