use std::{mem::zeroed, num::NonZeroU64};
use sysinfo::System;
use windows::{
Win32::{
Foundation::ERROR_SUCCESS,
System::Performance::{
PDH_FMT_COUNTERVALUE, PDH_FMT_DOUBLE, PDH_HCOUNTER, PDH_HQUERY, PdhAddEnglishCounterW,
PdhCloseQuery, PdhCollectQueryData, PdhGetFormattedCounterValue, PdhOpenQueryW,
PdhRemoveCounter,
},
},
core::w,
};
use crate::collection::memory::MemData;
pub(crate) fn get_swap_usage(sys: &System) -> Option<MemData> {
let total_bytes = NonZeroU64::new(sys.total_swap())?;
let query = w!("\\Paging File(_Total)\\% Usage");
unsafe {
let mut query_handle: PDH_HQUERY = zeroed();
let mut counter_handle: PDH_HCOUNTER = zeroed();
let mut counter_value: PDH_FMT_COUNTERVALUE = zeroed();
if PdhOpenQueryW(None, 0, &mut query_handle) != ERROR_SUCCESS.0 {
return None;
}
if PdhAddEnglishCounterW(query_handle, query, 0, &mut counter_handle) != ERROR_SUCCESS.0 {
return None;
}
if PdhCollectQueryData(query_handle) != ERROR_SUCCESS.0 {
return None;
}
if PdhGetFormattedCounterValue(counter_handle, PDH_FMT_DOUBLE, None, &mut counter_value)
!= ERROR_SUCCESS.0
{
PdhCloseQuery(query_handle);
return None;
}
let use_percentage = counter_value.Anonymous.doubleValue;
PdhRemoveCounter(counter_handle);
PdhCloseQuery(query_handle);
let used_bytes = (total_bytes.get() as f64 / 100.0 * use_percentage) as u64;
Some(MemData {
used_bytes,
total_bytes,
})
}
}
#[cfg(all(target_os = "windows", test))]
mod tests {
use sysinfo::{MemoryRefreshKind, RefreshKind};
use super::*;
#[test]
fn test_windows_get_swap_usage() {
let sys = System::new_with_specifics(
RefreshKind::nothing().with_memory(MemoryRefreshKind::nothing().with_swap()),
);
let swap_usage = get_swap_usage(&sys);
if sys.total_swap() > 0 {
println!("swap: {swap_usage:?}");
} else {
println!("No swap, skipping.");
}
}
}