use crate::doctor::types::{Check, CheckCtx, CheckResult, Severity};
static CHECKS: &[&Check] = &[&WMI, &GPU_PERF_COUNTERS, &RYZEN_MASTER, &INTEL_WMI, &LHM];
pub fn checks() -> &'static [&'static Check] {
CHECKS
}
static WMI: Check = Check {
id: "windows.wmi",
title: "WMI thermal-zone access",
severity_on_fail: Severity::Warn,
run: check_wmi,
};
static GPU_PERF_COUNTERS: Check = Check {
id: "windows.gpu.perf_counters",
title: "GPU performance counters (DXGI / PDH)",
severity_on_fail: Severity::Info,
run: check_gpu_perf_counters,
};
static RYZEN_MASTER: Check = Check {
id: "windows.amd_ryzen_master",
title: "AMD Ryzen Master SDK",
severity_on_fail: Severity::Info,
run: check_ryzen_master,
};
static INTEL_WMI: Check = Check {
id: "windows.intel_wmi",
title: "Intel WMI temperature provider",
severity_on_fail: Severity::Info,
run: check_intel_wmi,
};
static LHM: Check = Check {
id: "windows.libre_hardware_monitor",
title: "LibreHardwareMonitor service",
severity_on_fail: Severity::Info,
run: check_lhm,
};
fn check_wmi(_ctx: &CheckCtx) -> CheckResult {
#[cfg(target_os = "windows")]
{
match wmi::WMIConnection::with_namespace_path("root\\WMI") {
Ok(_conn) => CheckResult::Pass("root\\WMI reachable".to_string()),
Err(e) => CheckResult::Warn(
format!("WMI connection failed: {e}"),
Some("ensure the WinMgmt service is running".to_string()),
),
}
}
#[cfg(not(target_os = "windows"))]
{
CheckResult::Skip("not Windows".to_string())
}
}
fn check_gpu_perf_counters(_ctx: &CheckCtx) -> CheckResult {
#[cfg(target_os = "windows")]
{
use crate::device::readers::windows_gpu_perf;
let snapshot = windows_gpu_perf::snapshot();
let pdh_open = windows_gpu_perf::pdh_query_available();
if snapshot.adapters.is_empty() {
return CheckResult::Warn(
"DXGI reported no hardware adapters".to_string(),
Some(
"expected on a session with no display driver (headless VM, some RDP \
configurations); GPU memory and utilization fall back to the WMI baseline"
.to_string(),
),
);
}
let described: Vec<String> = snapshot
.adapters
.iter()
.map(|adapter| {
let total_gib =
adapter.total_memory.unwrap_or(0) as f64 / (1024.0 * 1024.0 * 1024.0);
let description = &adapter.identity.description;
let utilization = match adapter.utilization {
Some(value) => format!("{value:.1}%"),
None => "unavailable".to_string(),
};
let pool = if adapter.memory_is_shared {
"shared aperture"
} else {
"dedicated"
};
format!("{description} ({total_gib:.1} GiB {pool}, utilization {utilization})")
})
.collect();
if !pdh_open {
return CheckResult::Warn(
format!(
"DXGI sees {} adapter(s) but the PDH GPU counter query could not be opened: {}",
snapshot.adapters.len(),
described.join("; ")
),
Some(
"VRAM size still comes from DXGI; utilization and per-process memory need \
the GPU performance counters. Check that the Performance Logs and Alerts \
service is enabled."
.to_string(),
),
);
}
let has_utilization = snapshot
.adapters
.iter()
.any(|adapter| adapter.utilization.is_some());
let processes = snapshot.processes.len();
let adapters = snapshot.adapters.len();
let summary = described.join("; ");
let utilization_note = if has_utilization {
""
} else {
" (utilization needs a second poll; absent here is normal)"
};
CheckResult::Pass(format!(
"{adapters} adapter(s): {summary}; PDH query open, \
{processes} per-process row(s){utilization_note}"
))
}
#[cfg(not(target_os = "windows"))]
{
CheckResult::Skip("not Windows".to_string())
}
}
fn check_ryzen_master(_ctx: &CheckCtx) -> CheckResult {
#[cfg(target_os = "windows")]
{
let paths = [
"C:\\Program Files\\AMD\\RyzenMaster\\Platform\\bin\\AMDRyzenMasterDriver.sys",
"C:\\Program Files\\AMD\\RyzenMaster\\bin\\AMDRyzenMasterDriver.sys",
];
for p in &paths {
if std::path::Path::new(p).exists() {
return CheckResult::Pass(format!("SDK driver at {p}"));
}
}
CheckResult::Skip("AMD Ryzen Master SDK not installed".to_string())
}
#[cfg(not(target_os = "windows"))]
{
CheckResult::Skip("not Windows".to_string())
}
}
fn check_intel_wmi(_ctx: &CheckCtx) -> CheckResult {
#[cfg(target_os = "windows")]
{
CheckResult::Pass(
"Intel thermal probe uses the same root\\WMI namespace as windows.wmi".to_string(),
)
}
#[cfg(not(target_os = "windows"))]
{
CheckResult::Skip("not Windows".to_string())
}
}
fn check_lhm(_ctx: &CheckCtx) -> CheckResult {
#[cfg(target_os = "windows")]
{
match wmi::WMIConnection::with_namespace_path("root\\LibreHardwareMonitor") {
Ok(_) => CheckResult::Pass("LibreHardwareMonitor WMI provider available".to_string()),
Err(_) => {
CheckResult::Skip("LibreHardwareMonitor not installed or not running".to_string())
}
}
}
#[cfg(not(target_os = "windows"))]
{
CheckResult::Skip("not Windows".to_string())
}
}