Cannot get memory information via VirtualQueryEx

I'm learning Rust by writing a small program that reads through a process' memory via VirtualQueryEx.

Something ain't working, because VirtualQueryEx(...) returns only 0 and does not write to mbi. I don't know why and need help.

use itertools::Itertools;
use std::ffi::c_void;
use std::mem::size_of;
use sysinfo::System;
//use windows::Win32::System::Diagnostics::Debug::ReadProcessMemory;
use windows::Win32::System::Memory::{VirtualQueryEx, MEMORY_BASIC_INFORMATION};
use windows::Win32::System::Threading::{OpenProcess, PROCESS_READ_CONTROL};

fn main() {
    let process_name = "cmd.exe";
    let system = System::new_all();
    let noita_pid = match system.processes_by_exact_name(process_name).at_most_one() {
        Ok(Some(process)) => process.pid().as_u32(),
        Ok(None) => {
            println!("No process '{}' was found. 🙁", process_name);
            std::process::exit(1);
        }
        Err(_) => {
            println!("More than one process '{}' was found. 😵‍💫", process_name);
            std::process::exit(1);
        }
    };

    let process_handle = unsafe { OpenProcess(PROCESS_READ_CONTROL, false, noita_pid).unwrap() };

    println!("---------- Init Memory Search ----------");

    let mut mbi = MEMORY_BASIC_INFORMATION::default();
    let base_address: *const c_void = std::ptr::null_mut();
    println!("    Memory Information: {:?}", mbi);
    println!("    Base Address:       {:?}", base_address);

    println!("\n---------- Begin Memory Search ----------");

    while unsafe {
        VirtualQueryEx(
            process_handle,
            Some(base_address),
            &mut mbi,
            size_of::<MEMORY_BASIC_INFORMATION>(),
        )
    } != 0
    {
        let base_address = base_address.wrapping_add(mbi.RegionSize);
        println!("    Memory Information: {:?}", mbi);
        println!("    Base Address:       {:?}", base_address);
    }

    println!("\n---------- End Memory Search ----------");
    println!("    Memory Information: {:?}", mbi);
    println!("    Base Address:       {:?}", base_address);

}

The output of above code is always:

---------- Init Memory Search ----------
    Memory Information: MEMORY_BASIC_INFORMATION { BaseAddress: 0x0, AllocationBase: 0x0, AllocationProtect: PAGE_PROTECTION_FLAGS(0), PartitionId: 0, RegionSize: 0, State: VIRTUAL_ALLOCATION_TYPE(0), Protect: PAGE_PROTECTION_FLAGS(0), Type: PAGE_TYPE(0) }
    Base Address:       0x0

---------- Begin Memory Search ----------

---------- End Memory Search ----------
    Memory Information: MEMORY_BASIC_INFORMATION { BaseAddress: 0x0, AllocationBase: 0x0, AllocationProtect: PAGE_PROTECTION_FLAGS(0), PartitionId: 0, RegionSize: 0, State: VIRTUAL_ALLOCATION_TYPE(0), Protect: PAGE_PROTECTION_FLAGS(0), Type: PAGE_TYPE(0) }
    Base Address:       0x0

To test the code, you need to start a single cmd.exe process, or set process_name to any unique process that is currently running on your system.

I discovered GetLastError(), which told me that the code runs fine. The issue was that the program requires admin rights :slight_smile: