use crate::cpu::ArchInfo;
use crate::report::CpuReport;
use std::process::Command;
pub struct WindowsCpuInfo {
model: String,
vendor: String,
physical_cores: u32,
logical_cores: u32,
base_mhz: Option<f32>,
l2_size: Option<u32>,
l3_size: Option<u32>,
arch_info: ArchInfo,
}
fn wmi_property(property: &str) -> Option<String> {
let output = Command::new("powershell")
.args([
"-NoProfile",
"-Command",
&format!("(Get-CimInstance Win32_Processor | Select-Object -First 1 -ExpandProperty {}).ToString()", property),
])
.output()
.ok()?;
if !output.status.success() {
return None;
}
let s = String::from_utf8_lossy(&output.stdout).trim().to_string();
if s.is_empty() { None } else { Some(s) }
}
impl WindowsCpuInfo {
pub fn new() -> Result<Self, String> {
let model = wmi_property("Name").unwrap_or_else(|| "Unknown".to_string());
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
let arch_info = crate::cpu::x86::detect();
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
let arch_info = ArchInfo::default();
let vendor = arch_info.vendor.clone().unwrap_or_else(|| {
if model.to_lowercase().contains("intel") {
"Intel".to_string()
} else if model.to_lowercase().contains("amd") {
"AMD".to_string()
} else {
"Unknown".to_string()
}
});
let logical_cores = std::thread::available_parallelism()
.map(|n| n.get() as u32)
.unwrap_or(0);
let physical_cores = wmi_property("NumberOfCores")
.and_then(|s| s.parse().ok())
.unwrap_or(logical_cores);
let base_mhz = wmi_property("MaxClockSpeed").and_then(|s| s.parse::<f32>().ok());
let l2_size = wmi_property("L2CacheSize").and_then(|s| s.parse().ok());
let l3_size = wmi_property("L3CacheSize").and_then(|s| s.parse().ok());
Ok(Self {
model,
vendor,
physical_cores,
logical_cores,
base_mhz,
l2_size,
l3_size,
arch_info,
})
}
pub fn to_report(&self) -> CpuReport {
let info = &self.arch_info;
CpuReport {
model: self.model.clone(),
vendor: info.vendor.clone().unwrap_or_else(|| self.vendor.clone()),
uarch: info.uarch.clone(),
soc: None,
technology_nm: info.process_nm,
architecture: std::env::consts::ARCH.to_string(),
physical_cores: self.physical_cores,
logical_cores: self.logical_cores,
max_ghz: self.base_mhz.map(|mhz| mhz / 1000.0),
base_ghz: None,
l1i_kb: None,
l1d_kb: None,
l2_kb: self.l2_size.map(|kb| (0, kb)),
l3_kb: self.l3_size.map(|kb| (0, kb)),
flags: info.features.clone(),
}
}
}