diff --git a/WatcherAgent/src/main.rs b/WatcherAgent/src/main.rs index 4a99a3b..cb98d6d 100644 --- a/WatcherAgent/src/main.rs +++ b/WatcherAgent/src/main.rs @@ -472,23 +472,96 @@ fn get_cpu_temp() -> Option { #[cfg(target_os = "windows")] { - // Method 1: Try WMI first (for modern hardware) - if let Some(temp) = get_cpu_temp_wmi() { - return Some(temp); - } + use com::runtime::init_runtime; + use com::sys::{CLSCTX_INPROC_SERVER, COINIT_MULTITHREADED}; + use widestring::U16CString; + use winapi::shared::wtypes::VT_I4; + use winapi::um::oaidl::VARIANT; + use winapi::um::{combaseapi, wbemcli}; + init_runtime().ok()?; - // Method 2: Fallback to Open Hardware Monitor (HTTP API) - if let Some(temp) = get_cpu_temp_ohm() { - return Some(temp); - } + unsafe { + let mut locator: *mut wbemcli::IWbemLocator = std::ptr::null_mut(); + let hr = combaseapi::CoCreateInstance( + &wbemcli::CLSID_WbemLocator, + std::ptr::null_mut(), + CLSCTX_INPROC_SERVER, + &wbemcli::IID_IWbemLocator, + &mut locator as *mut _ as *mut _, + ); - // Method 3: Fallback to CoreTemp (shared memory) - if let Some(temp) = get_cpu_temp_coretemp() { - return Some(temp); - } + if hr != 0 { + eprintln!("Failed to create WbemLocator (HRESULT: {})", hr); + return None; + } - eprintln!("All methods failed to read CPU temperature."); - None + let mut services: *mut wbemcli::IWbemServices = std::ptr::null_mut(); + let namespace = U16CString::from_str("root\\wmi").unwrap(); + let hr = (*locator).ConnectServer( + namespace.as_ptr().cast_mut(), + std::ptr::null_mut(), + std::ptr::null_mut(), + std::ptr::null_mut(), + 0, + std::ptr::null_mut(), + std::ptr::null_mut(), + &mut services, + ); + + if hr != 0 { + eprintln!("Failed to connect to WMI (HRESULT: {})", hr); + return None; + } + + let query = + U16CString::from_str("SELECT * FROM MSAcpi_ThermalZoneTemperature").unwrap(); + let mut enumerator: *mut wbemcli::IEnumWbemClassObject = std::ptr::null_mut(); + let hr = (*services).ExecQuery( + U16CString::from_str("WQL").unwrap().as_ptr().cast_mut(), + query.as_ptr().cast_mut(), + wbemcli::WBEM_FLAG_FORWARD_ONLY as i32, + std::ptr::null_mut(), + &mut enumerator, + ); + + if hr != 0 { + eprintln!("Failed to execute WMI query (HRESULT: {})", hr); + return None; + } + + loop { + let mut obj: *mut wbemcli::IWbemClassObject = std::ptr::null_mut(); + let mut returned = 0; + let hr = (*enumerator).Next( + wbemcli::WBEM_INFINITE.try_into().unwrap(), + 1, + &mut obj, + &mut returned, + ); + + if hr != 0 || returned == 0 { + break; + } + + let mut variant = std::mem::zeroed::(); + let hr = (*obj).Get( + U16CString::from_str("CurrentTemperature").unwrap().as_ptr(), + 0, + &mut variant, + std::ptr::null_mut(), + std::ptr::null_mut(), + ); + + if hr == 0 && variant.n1.n2().vt as u32 == VT_I4 { + let temp_kelvin = *variant.n1.n2().n3.intVal() as f32 / 10.0; + Some(temp_kelvin - 273.15); + } else { + return None; + } + } + + None + } } #[cfg(not(any(target_os = "linux", target_os = "windows")))] @@ -498,128 +571,6 @@ fn get_cpu_temp() -> Option { } } -#[cfg(target_os = "windows")] -use com::runtime::init_runtime; -use com::sys::{CLSCTX_INPROC_SERVER, COINIT_MULTITHREADED}; -use widestring::U16CString; -use winapi::shared::wtypes::VT_I4; -use winapi::um::oaidl::VARIANT; -use winapi::um::{combaseapi, wbemcli}; -fn get_cpu_temp_wmi() -> Option { - init_runtime().ok()?; - - unsafe { - let mut locator: *mut wbemcli::IWbemLocator = std::ptr::null_mut(); - let hr = combaseapi::CoCreateInstance( - &wbemcli::CLSID_WbemLocator, - std::ptr::null_mut(), - CLSCTX_INPROC_SERVER, - &wbemcli::IID_IWbemLocator, - &mut locator as *mut _ as *mut _, - ); - - if hr != 0 { - eprintln!("Failed to create WbemLocator (HRESULT: {})", hr); - return None; - } - - let mut services: *mut wbemcli::IWbemServices = std::ptr::null_mut(); - let namespace = U16CString::from_str("root\\wmi").unwrap(); - let hr = (*locator).ConnectServer( - namespace.as_ptr().cast_mut(), - std::ptr::null_mut(), - std::ptr::null_mut(), - std::ptr::null_mut(), - 0, - std::ptr::null_mut(), - std::ptr::null_mut(), - &mut services, - ); - - if hr != 0 { - eprintln!("Failed to connect to WMI (HRESULT: {})", hr); - return None; - } - - let query = U16CString::from_str("SELECT * FROM MSAcpi_ThermalZoneTemperature").unwrap(); - let mut enumerator: *mut wbemcli::IEnumWbemClassObject = std::ptr::null_mut(); - let hr = (*services).ExecQuery( - U16CString::from_str("WQL").unwrap().as_ptr().cast_mut(), - query.as_ptr().cast_mut(), - wbemcli::WBEM_FLAG_FORWARD_ONLY as i32, - std::ptr::null_mut(), - &mut enumerator, - ); - - if hr != 0 { - eprintln!("Failed to execute WMI query (HRESULT: {})", hr); - return None; - } - - loop { - let mut obj: *mut wbemcli::IWbemClassObject = std::ptr::null_mut(); - let mut returned = 0; - let hr = (*enumerator).Next( - wbemcli::WBEM_INFINITE.try_into().unwrap(), - 1, - &mut obj, - &mut returned, - ); - - if hr != 0 || returned == 0 { - break; - } - - let mut variant = std::mem::zeroed::(); - let hr = (*obj).Get( - U16CString::from_str("CurrentTemperature").unwrap().as_ptr(), - 0, - &mut variant, - std::ptr::null_mut(), - std::ptr::null_mut(), - ); - - if hr == 0 && variant.n1.n2().vt as u32 == VT_I4 { - let temp_kelvin = *variant.n1.n2().n3.intVal() as f32 / 10.0; - Some(temp_kelvin - 273.15); - } else { - return None; - } - } - - None - } -} - -#[cfg(target_os = "windows")] -fn get_cpu_temp_ohm() -> Option { - // Open Hardware Monitor HTTP API fallback - let output = Command::new("curl") - .args(&["-s", "http://localhost:5000/data.json"]) - .output() - .ok()?; - - let json: serde_json::Value = serde_json::from_slice(&output.stdout).ok()?; - json["Children"][0]["Children"][0]["Children"] - .as_array()? - .iter() - .find(|s| s["Text"].as_str() == Some("CPU Package")) - .and_then(|s| s["Value"].as_f64()) - .map(|t| t as f32) -} - -#[cfg(target_os = "windows")] -fn get_cpu_temp_coretemp() -> Option { - // CoreTemp shared memory fallback - let output = Command::new("CoreTemp.exe").arg("/S").output().ok()?; - - String::from_utf8_lossy(&output.stdout) - .lines() - .find(|line| line.contains("Core 0")) - .and_then(|line| line.split_whitespace().last()) - .and_then(|s| s.replace("°C", "").parse::().ok()) -} - fn get_disk_info() -> (f64, f64, f64) { let mut sys = System::new(); sys.refresh_all();